diff --git a/composer.lock b/composer.lock index 62c13899..8c6d3443 100644 --- a/composer.lock +++ b/composer.lock @@ -157,16 +157,16 @@ }, { "name": "composer/composer", - "version": "2.8.3", + "version": "2.8.4", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "2a7c71266b2545a3bed9f4860734081963f6e688" + "reference": "112e37d1dca22b3fdb81cf3524ab4994f47fdb8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/2a7c71266b2545a3bed9f4860734081963f6e688", - "reference": "2a7c71266b2545a3bed9f4860734081963f6e688", + "url": "https://api.github.com/repos/composer/composer/zipball/112e37d1dca22b3fdb81cf3524ab4994f47fdb8c", + "reference": "112e37d1dca22b3fdb81cf3524ab4994f47fdb8c", "shasum": "" }, "require": { @@ -251,7 +251,7 @@ "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", "security": "https://github.com/composer/composer/security/policy", - "source": "https://github.com/composer/composer/tree/2.8.3" + "source": "https://github.com/composer/composer/tree/2.8.4" }, "funding": [ { @@ -267,7 +267,7 @@ "type": "tidelift" } ], - "time": "2024-11-17T12:13:04+00:00" + "time": "2024-12-11T10:57:47+00:00" }, { "name": "composer/metadata-minifier", @@ -715,12 +715,12 @@ "source": { "type": "git", "url": "https://github.com/manticoresoftware/buddy-core.git", - "reference": "358c002cf30251cc258ba9d1a7e4839d957cbd81" + "reference": "60e85c4839ed2a5de017513816bbf155977ea5a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/manticoresoftware/buddy-core/zipball/358c002cf30251cc258ba9d1a7e4839d957cbd81", - "reference": "358c002cf30251cc258ba9d1a7e4839d957cbd81", + "url": "https://api.github.com/repos/manticoresoftware/buddy-core/zipball/60e85c4839ed2a5de017513816bbf155977ea5a2", + "reference": "60e85c4839ed2a5de017513816bbf155977ea5a2", "shasum": "" }, "require": { @@ -759,7 +759,7 @@ "issues": "https://github.com/manticoresoftware/buddy-core/issues", "source": "https://github.com/manticoresoftware/buddy-core/tree/main" }, - "time": "2024-11-13T11:49:20+00:00" + "time": "2024-12-12T08:00:26+00:00" }, { "name": "manticoresoftware/manticoresearch-backup", @@ -2072,8 +2072,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2148,8 +2148,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2226,8 +2226,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2310,8 +2310,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2384,8 +2384,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2460,8 +2460,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2540,8 +2540,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4884,16 +4884,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.11.1", + "version": "3.11.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "19473c30efe4f7b3cd42522d0b2e6e7f243c6f87" + "reference": "1368f4a58c3c52114b86b1abe8f4098869cb0079" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/19473c30efe4f7b3cd42522d0b2e6e7f243c6f87", - "reference": "19473c30efe4f7b3cd42522d0b2e6e7f243c6f87", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/1368f4a58c3c52114b86b1abe8f4098869cb0079", + "reference": "1368f4a58c3c52114b86b1abe8f4098869cb0079", "shasum": "" }, "require": { @@ -4960,7 +4960,7 @@ "type": "open_collective" } ], - "time": "2024-11-16T12:02:36+00:00" + "time": "2024-12-11T16:04:26+00:00" }, { "name": "swoole/ide-helper", @@ -5052,8 +5052,8 @@ }, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], + "platform": {}, + "platform-dev": {}, "platform-overrides": { "php": "8.1.0" }, diff --git a/src/Handler.php b/src/Handler.php index 6bbce3dc..7a4d0610 100644 --- a/src/Handler.php +++ b/src/Handler.php @@ -41,10 +41,9 @@ public function run(): Task { throw new RuntimeException('Failed to prepare query'); } - $queryResult = $manticoreClient - ->sendRequest($query, $payload->path) - ->getResult(); - return TaskResult::raw($queryResult); + $resp = $manticoreClient + ->sendRequest($query, $payload->path); + return TaskResult::fromResponse($resp); }; return Task::create( diff --git a/src/Lib/QueryProcessor.php b/src/Lib/QueryProcessor.php index b8a2adc3..dca89364 100644 --- a/src/Lib/QueryProcessor.php +++ b/src/Lib/QueryProcessor.php @@ -224,6 +224,7 @@ public static function detectPluginPrefixFromRequest(Request $request): string { foreach ($plugins as $plugin) { $pluginPrefix = $prefix . ucfirst(Strings::camelcaseBySeparator($plugin['short'], '-')); /** @var BasePayload $pluginPayloadClass */ + $pluginPayloadClass = "$pluginPrefix\\Payload"; $pluginPayloadClass::setParser(static::$sqlQueryParser); $hasMatch = $pluginPayloadClass::hasMatch($request); diff --git a/src/Network/EventHandler.php b/src/Network/EventHandler.php index 5cf9cee5..771348b2 100644 --- a/src/Network/EventHandler.php +++ b/src/Network/EventHandler.php @@ -16,6 +16,7 @@ use Manticoresearch\Buddy\Core\Error\GenericError; use Manticoresearch\Buddy\Core\Error\InvalidNetworkRequestError; use Manticoresearch\Buddy\Core\ManticoreSearch\RequestFormat; +use Manticoresearch\Buddy\Core\Network\OutputFormat; use Manticoresearch\Buddy\Core\Network\Request; use Manticoresearch\Buddy\Core\Network\Response; use Manticoresearch\Buddy\Core\Task\Column; @@ -87,6 +88,8 @@ static function () use ($requestId, $body, $channel, $startTime) { */ public static function process(string $id, string $payload): Response { try { + /** @var int $startTime */ + $startTime = hrtime(true); $request = Request::fromString($payload, $id); $handler = QueryProcessor::process($request)->run(); @@ -101,7 +104,18 @@ public static function process(string $id, string $payload): Response { $result = $handler->getResult(); } - $response = Response::fromResult($result, $request->format); + // Check if this is a cli and we need to activate Table Formatter + $outputFormat = $request->getOutputFormat(); + $message = match ($outputFormat) { + // TODO: Maybe later we can use meta for time, but not now cuz no time for non select + OutputFormat::Table => $result->getTableFormatted($startTime), + default => $result->getStruct(), + }; + $response = Response::fromMessageAndMeta( + $message, + $result->getMeta(), + $request->format, + ); } catch (Throwable $e) { if (isset($request)) { /** @var string $originalError */ diff --git a/src/Plugin/Alias/Handler.php b/src/Plugin/Alias/Handler.php index 6bbce3dc..2e28acf9 100644 --- a/src/Plugin/Alias/Handler.php +++ b/src/Plugin/Alias/Handler.php @@ -41,10 +41,9 @@ public function run(): Task { throw new RuntimeException('Failed to prepare query'); } - $queryResult = $manticoreClient - ->sendRequest($query, $payload->path) - ->getResult(); - return TaskResult::raw($queryResult); + $queryResponse = $manticoreClient + ->sendRequest($query, $payload->path); + return TaskResult::fromResponse($queryResponse); }; return Task::create( diff --git a/src/Plugin/AlterDistributedTable/Handler.php b/src/Plugin/AlterDistributedTable/Handler.php index 23e4c3c7..4dead6e0 100644 --- a/src/Plugin/AlterDistributedTable/Handler.php +++ b/src/Plugin/AlterDistributedTable/Handler.php @@ -96,12 +96,12 @@ private static function createTable(string $tableName, array $options, Client $m } } - $request = $manticoreClient->sendRequest($sql); - if ($request->hasError()) { - throw ManticoreSearchResponseError::create((string)$request->getError()); + $response = $manticoreClient->sendRequest($sql); + if ($response->hasError()) { + throw ManticoreSearchResponseError::create((string)$response->getError()); } - return TaskResult::raw($request->getResult()); + return TaskResult::fromResponse($response); } /** diff --git a/src/Plugin/AlterRenameTable/Handler.php b/src/Plugin/AlterRenameTable/Handler.php index e661bc6b..5836053a 100644 --- a/src/Plugin/AlterRenameTable/Handler.php +++ b/src/Plugin/AlterRenameTable/Handler.php @@ -14,6 +14,7 @@ use Manticoresearch\Buddy\Core\Error\ManticoreSearchClientError; use Manticoresearch\Buddy\Core\Error\ManticoreSearchResponseError; use Manticoresearch\Buddy\Core\ManticoreSearch\Client; +use Manticoresearch\Buddy\Core\ManticoreSearch\Response; use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskResult; @@ -60,11 +61,11 @@ public function run(): Task { } self::createTableLike($payload->sourceTableName, $payload->destinationTableName, $client); - $result = self::attachTable($payload->sourceTableName, $payload->destinationTableName, $client); + $resp = self::attachTable($payload->sourceTableName, $payload->destinationTableName, $client); self::dropTable($payload->sourceTableName, $client); - return TaskResult::raw($result); + return TaskResult::fromResponse($resp); }; return Task::create( @@ -103,7 +104,7 @@ private static function createTableLike( * @param string $sourceTableName * @param string $destinationTableName * @param Client $client - * @return mixed + * @return Response * @throws GenericError * @throws ManticoreSearchClientError */ @@ -111,7 +112,7 @@ private static function attachTable( string $sourceTableName, string $destinationTableName, Client $client - ): mixed { + ): Response { $sql = /** @lang ManticoreSearch */ "ATTACH TABLE $sourceTableName TO TABLE $destinationTableName"; @@ -122,7 +123,7 @@ private static function attachTable( 'Reason: ' . $result->getError() ); } - return $result->getResult(); + return $result; } diff --git a/src/Plugin/CliTable/Handler.php b/src/Plugin/CliTable/Handler.php index eac4a8f4..6159b8e9 100644 --- a/src/Plugin/CliTable/Handler.php +++ b/src/Plugin/CliTable/Handler.php @@ -12,8 +12,7 @@ namespace Manticoresearch\Buddy\Base\Plugin\CliTable; use Manticoresearch\Buddy\Core\ManticoreSearch\Client; -use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithTableFormatter; -use Manticoresearch\Buddy\Core\Plugin\TableFormatter; +use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskResult; use RuntimeException; @@ -21,7 +20,7 @@ /** * This is the class to return response to the '/cli' endpoint in table format */ -final class Handler extends BaseHandlerWithTableFormatter { +final class Handler extends BaseHandlerWithClient { /** * Initialize the executor @@ -44,42 +43,18 @@ public function run(): Task { $taskFn = static function ( Payload $payload, Client $manticoreClient, - ?TableFormatter $tableFormatter ): TaskResult { - $time0 = hrtime(true); $resp = $manticoreClient->sendRequest( $payload->query, $payload->path, disableAgentHeader: true ); - $data = null; - $total = -1; - $respBody = $resp->getBody(); - $result = (array)json_decode($respBody, true); - if ($tableFormatter === null - || (!isset($result['error']) && (!isset($result[0]) || !is_array($result[0]))) - ) { - return TaskResult::raw($result); - } - // Convert JSON response from Manticore to table format - if (isset($result['error'])) { - /** @var string $errorMsg */ - $errorMsg = $result['error']; - if ($errorMsg !== '') { - return TaskResult::raw($tableFormatter->getTable($time0, $data, $total, $errorMsg)); - } - } - - if (isset($result[0]) && is_array($result[0])) { - static::processResultInfo($result[0], $data, $total); - } - - return TaskResult::raw($tableFormatter->getTable($time0, $data, $total)); + return TaskResult::fromResponse($resp); }; return Task::create( $taskFn, - [$this->payload, $this->manticoreClient, $this->tableFormatter] + [$this->payload, $this->manticoreClient] )->run(); } diff --git a/src/Plugin/Insert/Handler.php b/src/Plugin/Insert/Handler.php index a1ff20ab..82a08fc3 100644 --- a/src/Plugin/Insert/Handler.php +++ b/src/Plugin/Insert/Handler.php @@ -15,7 +15,6 @@ use Manticoresearch\Buddy\Base\Plugin\Insert\Error\AutoSchemaDisabledError; use Manticoresearch\Buddy\Core\Error\GenericError; use Manticoresearch\Buddy\Core\ManticoreSearch\Client; -use Manticoresearch\Buddy\Core\Network\Struct; use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskResult; @@ -62,6 +61,7 @@ public function run(): Task { $taskFn = static function (Payload $payload, Client $manticoreClient): TaskResult { for ($i = 0, $maxI = sizeof($payload->queries) - 1; $i <= $maxI; $i++) { $query = $payload->queries[$i]; + $resp = $manticoreClient->sendRequest($query, $i === 0 ? null : $payload->path); } @@ -69,10 +69,7 @@ public function run(): Task { throw new Exception('Empty queries to process'); } - $struct = Struct::fromJson( - $resp->getBody() - ); - return TaskResult::raw($struct); + return TaskResult::fromResponse($resp); }; return Task::create( $taskFn, [$this->payload, $this->manticoreClient] diff --git a/src/Plugin/Knn/Handler.php b/src/Plugin/Knn/Handler.php index bab7ce95..9ea0e334 100644 --- a/src/Plugin/Knn/Handler.php +++ b/src/Plugin/Knn/Handler.php @@ -17,7 +17,7 @@ use Manticoresearch\Buddy\Core\Error\QueryParseError; use Manticoresearch\Buddy\Core\ManticoreSearch\Client; use Manticoresearch\Buddy\Core\ManticoreSearch\Endpoint; -use Manticoresearch\Buddy\Core\Network\Struct; +use Manticoresearch\Buddy\Core\ManticoreSearch\Response; use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskResult; @@ -46,7 +46,8 @@ public function run(): Task { if ($queryVector === false) { return TaskResult::none(); } - return TaskResult::raw(self::getKnnResult($manticoreClient, $payload, $queryVector)); + $resp = self::getKnnResult($manticoreClient, $payload, $queryVector); + return TaskResult::fromResponse($resp); }; return Task::create( @@ -93,10 +94,10 @@ private static function getQueryVectorValue(Client $client, Payload $payload): s * @param Client $manticoreClient * @param Payload $payload * @param string $queryVector - * @return Struct + * @return Response * @throws ManticoreSearchClientError|QueryParseError */ - private static function getKnnResult(Client $manticoreClient, Payload $payload, string $queryVector): Struct { + private static function getKnnResult(Client $manticoreClient, Payload $payload, string $queryVector): Response { if ($payload->endpointBundle === Endpoint::Search) { return self::knnHttpQuery($manticoreClient, $payload, $queryVector); } @@ -109,10 +110,10 @@ private static function getKnnResult(Client $manticoreClient, Payload $payload, * @param Payload $payload * @param string $queryVector * - * @return Struct + * @return Response * @throws ManticoreSearchClientError|GenericError */ - private static function knnHttpQuery(Client $manticoreClient, Payload $payload, string $queryVector): Struct { + private static function knnHttpQuery(Client $manticoreClient, Payload $payload, string $queryVector): Response { $query = [ 'table' => $payload->table, 'knn' => [ @@ -134,65 +135,67 @@ function ($val) { $query['knn']['filter'] = $payload->condition; } - $request = $manticoreClient + $resp = $manticoreClient ->sendRequest((string)json_encode($query), Endpoint::Search->value); - if ($request->hasError()) { - ManticoreSearchResponseError::throw((string)$request->getError()); + if ($resp->hasError()) { + ManticoreSearchResponseError::throw((string)$resp->getError()); } - $result = $request->getResult(); - if (is_array($result['hits']) && isset($result['hits']['hits'])) { + $docId = (int)$payload->docId; + $resp->apply( + static function ($result) use ($docId) { // Removing requested doc from result set - $resultHits = $result['hits']; - $filteredResults = []; - foreach ($resultHits['hits'] as $v) { - if ($v['_id'] === (int)$payload->docId) { - continue; - } + $filteredResults = []; + foreach ($result['hits']['hits'] as $v) { + if ($v['_id'] === $docId) { + continue; + } - $filteredResults[] = $v; + $filteredResults[] = $v; + } + return $filteredResults; } - $resultHits['hits'] = $filteredResults; - $result->offsetSet('hits', $resultHits); - } - - return $result; + ); + return $resp; } /** * @param Client $manticoreClient * @param Payload $payload * @param string $queryVector - * @return Struct + * @return Response * @throws QueryParseError|ManticoreSearchClientError|GenericError */ - private static function knnSqlQuery(Client $manticoreClient, Payload $payload, string $queryVector): Struct { + private static function knnSqlQuery(Client $manticoreClient, Payload $payload, string $queryVector): Response { self::substituteParsedQuery($payload, $queryVector); - $request = $manticoreClient + $resp = $manticoreClient ->sendRequest($payload::$sqlQueryParser::getCompletedPayload()); - if ($request->hasError()) { - ManticoreSearchResponseError::throw((string)$request->getError()); + if ($resp->hasError()) { + ManticoreSearchResponseError::throw((string)$resp->getError()); } - $result = $request->getResult(); + $result = $resp->getResult(); if (is_array($result[0])) { - $resultStruct = $result[0]; - foreach ($resultStruct['data'] as $k => $v) { - if (!isset($v['id']) || $v['id'] !== (int)$payload->docId) { - continue; + $docId = (int)$payload->docId; + $resp->apply( + static function ($result) use ($docId) { + foreach ($result[0]['data'] as $k => $v) { + if (!isset($v['id']) || $v['id'] !== $docId) { + continue; + } + + unset($result[0]['data'][$k]); + } + return $result; } - - unset($resultStruct['data'][$k]); - } - $result->offsetSet(0, $resultStruct); + ); } - - return $result; + return $resp; } /** diff --git a/src/Plugin/ModifyTable/Handler.php b/src/Plugin/ModifyTable/Handler.php index 432d9930..1c4febae 100644 --- a/src/Plugin/ModifyTable/Handler.php +++ b/src/Plugin/ModifyTable/Handler.php @@ -35,8 +35,8 @@ public function __construct(public Payload $payload) { public function run(): Task { $taskFn = static function (Payload $payload, Client $client): TaskResult { $q = "{$payload->type} table {$payload->table} {$payload->structure} {$payload->extra}"; - $result = $client->sendRequest($q, disableAgentHeader: true)->getResult(); - return TaskResult::raw([$result]); + $resp = $client->sendRequest($q, disableAgentHeader: true); + return TaskResult::fromResponse($resp); }; $task = Task::create( diff --git a/src/Plugin/Queue/Handlers/BaseViewHandler.php b/src/Plugin/Queue/Handlers/BaseViewHandler.php index 2b0c08fb..e6488ea8 100644 --- a/src/Plugin/Queue/Handlers/BaseViewHandler.php +++ b/src/Plugin/Queue/Handlers/BaseViewHandler.php @@ -56,12 +56,12 @@ public function run(): Task { $sql = /** @lang manticore */ "SELECT name FROM $tableName GROUP BY name"; - $result = $manticoreClient->sendRequest($sql); - if ($result->hasError()) { - throw ManticoreSearchClientError::create((string)$result->getError()); + $resp = $manticoreClient->sendRequest($sql); + if ($resp->hasError()) { + throw ManticoreSearchClientError::create((string)$resp->getError()); } - return TaskResult::raw($result->getResult()); + return TaskResult::fromResponse($resp); }; return Task::create( diff --git a/src/Plugin/Select/Handler.php b/src/Plugin/Select/Handler.php index a4cdeb12..11ffe382 100644 --- a/src/Plugin/Select/Handler.php +++ b/src/Plugin/Select/Handler.php @@ -538,7 +538,7 @@ function ($matches) { $response = $manticoreClient->sendRequest($selectQuery); if ($isLikeOp) { $filterFn = static::getFilterRegexFieldFn(); - $response->filterResult($filterFn); + $response->apply($filterFn); } return TaskResult::fromResponse($response); } diff --git a/src/Plugin/Sharding/CreateHandler.php b/src/Plugin/Sharding/CreateHandler.php index e7fcab7a..674ec997 100644 --- a/src/Plugin/Sharding/CreateHandler.php +++ b/src/Plugin/Sharding/CreateHandler.php @@ -12,6 +12,7 @@ use Closure; use Manticoresearch\Buddy\Core\ManticoreSearch\Client; +use Manticoresearch\Buddy\Core\ManticoreSearch\Response; use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskResult; @@ -161,7 +162,7 @@ protected static function getShardingFn(): Closure { $type = $value['type'] ?? 'unknown'; $status = $value['status'] ?? 'processing'; if ($type === 'create' && $status !== 'processing') { - return TaskResult::raw($value['result']); + return TaskResult::fromResponse(Response::fromBody($value['result'])); } if ((time() - $ts) > $timeout) { break; diff --git a/src/Plugin/Sharding/DropHandler.php b/src/Plugin/Sharding/DropHandler.php index e75d26aa..e9fe3c10 100644 --- a/src/Plugin/Sharding/DropHandler.php +++ b/src/Plugin/Sharding/DropHandler.php @@ -12,6 +12,7 @@ use Closure; use Manticoresearch\Buddy\Core\Error\ManticoreSearchClientError; +use Manticoresearch\Buddy\Core\ManticoreSearch\Response; use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskResult; @@ -160,7 +161,7 @@ protected function getShardingFn(): Closure { $type = $state['type'] ?? 'unknown'; $status = $state['status'] ?? 'processing'; if ($type === 'drop' && $status !== 'processing') { - return TaskResult::raw($state['result']); + return TaskResult::fromResponse(Response::fromBody($state['result'])); } } if ((time() - $ts) > $timeout) { diff --git a/src/Plugin/Sharding/Operator.php b/src/Plugin/Sharding/Operator.php index 8a08619b..ec3ad187 100644 --- a/src/Plugin/Sharding/Operator.php +++ b/src/Plugin/Sharding/Operator.php @@ -288,8 +288,8 @@ public function checkTableStatus(string $table): bool { if ($isProcessed) { $result['status'] = 'done'; $result['result'] = getenv('DEBUG') && $result['type'] === 'create' - ? $this->client->sendRequest("SHOW CREATE TABLE {$table}")->getResult() - : TaskResult::none()->getStruct(); + ? $this->client->sendRequest("SHOW CREATE TABLE {$table}")->getBody() + : TaskResult::none()->toString(); $this->state->set($stateKey, $result); } diff --git a/src/Plugin/Show/CreateTableHandler.php b/src/Plugin/Show/CreateTableHandler.php index d2221a48..77928c04 100644 --- a/src/Plugin/Show/CreateTableHandler.php +++ b/src/Plugin/Show/CreateTableHandler.php @@ -12,8 +12,7 @@ namespace Manticoresearch\Buddy\Base\Plugin\Show; use Manticoresearch\Buddy\Core\ManticoreSearch\Client; -use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithTableFormatter; -use Manticoresearch\Buddy\Core\Plugin\TableFormatter; +use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskResult; use RuntimeException; @@ -21,7 +20,7 @@ /** * This is the parent class to handle erroneous Manticore queries */ -class CreateTableHandler extends BaseHandlerWithTableFormatter { +class CreateTableHandler extends BaseHandlerWithClient { /** * Initialize the executor * @@ -42,42 +41,37 @@ public function run(): Task { // We just waiting for a thread to be done $taskFn = static function ( Payload $payload, - Client $manticoreClient, - TableFormatter $tableFormatter + Client $manticoreClient ): TaskResult { - $time0 = hrtime(true); // First, get response from the manticore $query = "SHOW CREATE TABLE {$payload->table}"; - $result = $manticoreClient->sendRequest($query, $payload->path)->getResult(); - /** @var array{data:array>} $resultStruct */ - $resultStruct = $result[0]; - if ($payload->hasCliEndpoint) { - $total = sizeof($resultStruct['data']); - return TaskResult::raw($tableFormatter->getTable($time0, $resultStruct['data'], $total)); - } + $resp = $manticoreClient->sendRequest($query); // It's important to have ` and 2 spaces for Apache Superset - foreach ($resultStruct['data'] as &$row) { + $resp->mapData( + static function (array $row): array { /** @var array{'Create Table':string} $row */ - $lines = explode("\n", $row['Create Table']); - $lastN = sizeof($lines) - 1; - foreach ($lines as $n => &$line) { - if ($n === 0 || $n === $lastN) { - continue; + $lines = explode("\n", $row['Create Table']); + $lastN = sizeof($lines) - 1; + foreach ($lines as $n => &$line) { + if ($n === 0 || $n === $lastN) { + continue; + } + $parts = explode(' ', $line); + $parts[0] = '`' . trim($parts[0], '`') . '`'; + $line = ' ' . trim(implode(' ', $parts)); } - $parts = explode(' ', $line); - $parts[0] = '`' . trim($parts[0], '`') . '`'; - $line = ' ' . trim(implode(' ', $parts)); + $row['Create Table'] = implode("\n", $lines); + return $row; } - $row['Create Table'] = implode("\n", $lines); - } - $result->offsetSet(0, $resultStruct); - return TaskResult::raw($result); + ); + + return TaskResult::fromResponse($resp); }; return Task::create( $taskFn, - [$this->payload, $this->manticoreClient, $this->tableFormatter] + [$this->payload, $this->manticoreClient] )->run(); } } diff --git a/src/Plugin/Show/ExpandedTablesHandler.php b/src/Plugin/Show/ExpandedTablesHandler.php index b33e670a..57dafded 100644 --- a/src/Plugin/Show/ExpandedTablesHandler.php +++ b/src/Plugin/Show/ExpandedTablesHandler.php @@ -12,8 +12,7 @@ namespace Manticoresearch\Buddy\Base\Plugin\Show; use Manticoresearch\Buddy\Core\ManticoreSearch\Client; -use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithTableFormatter; -use Manticoresearch\Buddy\Core\Plugin\TableFormatter; +use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; use Manticoresearch\Buddy\Core\Task\Column; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskResult; @@ -22,7 +21,7 @@ /** * This is a class to handle SHOW TABLES-like queries where MySQL syntax is used */ -class ExpandedTablesHandler extends BaseHandlerWithTableFormatter { +class ExpandedTablesHandler extends BaseHandlerWithClient { /** * Initialize the executor * @@ -44,19 +43,18 @@ public function run(): Task { $taskFn = static function ( Payload $payload, Client $manticoreClient, - TableFormatter $tableFormatter ): TaskResult { - $time0 = hrtime(true); // First, get response from the manticore $query = 'SHOW TABLES'; if ($payload->like) { $query .= " LIKE '{$payload->like}'"; } - $resp = $manticoreClient->sendRequest($query, $payload->path); + $resp = $manticoreClient->sendRequest($query); + $resp = $manticoreClient->sendRequest($query); + /** @var array>,total?:int,columns?:string}> $result */ $result = $resp->getResult(); /** @var array{data:array>,total?:int} $resultStruct */ $resultStruct = $result[0]; - $total = $resultStruct['total'] ?? -1; // Adjust result row to be mysql like $resultData = $resultStruct['data']; if ($resultData) { @@ -77,10 +75,6 @@ public function run(): Task { } } - if ($payload->hasCliEndpoint) { - return TaskResult::raw($tableFormatter->getTable($time0, $resultData, $total)); - } - return match ($payload->tableType) { 'full' => TaskResult::withData($resultData) ->column("Tables_in_{$payload->database}", Column::String) @@ -96,7 +90,7 @@ public function run(): Task { return Task::create( $taskFn, - [$this->payload, $this->manticoreClient, $this->tableFormatter] + [$this->payload, $this->manticoreClient] )->run(); } } diff --git a/src/Plugin/Show/FullColumnsHandler.php b/src/Plugin/Show/FullColumnsHandler.php index 63ffe017..60b7a501 100644 --- a/src/Plugin/Show/FullColumnsHandler.php +++ b/src/Plugin/Show/FullColumnsHandler.php @@ -12,7 +12,7 @@ namespace Manticoresearch\Buddy\Base\Plugin\Show; use Manticoresearch\Buddy\Core\ManticoreSearch\Client; -use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithTableFormatter; +use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; use Manticoresearch\Buddy\Core\Task\Column; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskResult; @@ -21,7 +21,7 @@ /** * This is the parent class to handle erroneous Manticore queries */ -class FullColumnsHandler extends BaseHandlerWithTableFormatter { +class FullColumnsHandler extends BaseHandlerWithClient { /** * Initialize the executor * @@ -53,7 +53,7 @@ public function run(): Task { $taskFn = static function (Payload $payload, Client $manticoreClient): TaskResult { $query = "DESC {$payload->table}"; /** @var array{0:array{data:array}} */ - $result = $manticoreClient->sendRequest($query, $payload->path)->getResult(); + $result = $manticoreClient->sendRequest($query)->getResult(); $base = [ 'Field' => '', 'Type' => '', diff --git a/src/Plugin/Show/Payload.php b/src/Plugin/Show/Payload.php index d79042c2..6f74b083 100644 --- a/src/Plugin/Show/Payload.php +++ b/src/Plugin/Show/Payload.php @@ -47,9 +47,6 @@ final class Payload extends BasePayload { public string $tableType; - public string $path; - public bool $hasCliEndpoint; - /** * Get description for this plugin * @return string @@ -68,8 +65,7 @@ public static function fromRequest(Request $request): static { return match (static::$type) { 'expanded tables' => static::fromExpandedTablesRequest($request), 'create table' => static::fromCreateTableRequest($request), - 'schemas', 'queries' => static::fromSimpleRequest($request), - 'version' => static::fromVersionRequest($request), + 'schemas', 'queries', 'version' => new static(), 'full columns' => static::fromColumnsRequest($request), 'unsupported' => static::fromUnsupportedStmtRequest($request), default => throw new Exception('Failed to match type of request: ' . static::$type), @@ -105,17 +101,6 @@ protected static function fromExpandedTablesRequest(Request $request): static { } elseif ($m['where'] ?? '') { $self->like = $m['where']; } - [$self->path, $self->hasCliEndpoint] = self::getEndpointInfo($request); - return $self; - } - - /** - * @param Request $request - * @return static - */ - protected static function fromVersionRequest(Request $request): static { - $self = new static(); - [$self->path, $self->hasCliEndpoint] = self::getEndpointInfo($request); return $self; } @@ -135,17 +120,6 @@ protected static function fromCreateTableRequest(Request $request): static { $self->database = $m[1]; $self->table = $m[2]; - [$self->path, $self->hasCliEndpoint] = self::getEndpointInfo($request); - return $self; - } - - /** - * @param Request $request - * @return static - */ - protected static function fromSimpleRequest(Request $request): static { - $self = new static(); - [$self->path, $self->hasCliEndpoint] = self::getEndpointInfo($request); return $self; } @@ -155,7 +129,6 @@ protected static function fromSimpleRequest(Request $request): static { */ protected static function fromUnsupportedStmtRequest(Request $request): static { $self = new static(); - [$self->path] = self::getEndpointInfo($request); $self->query = $request->payload; return $self; } @@ -173,7 +146,6 @@ protected static function fromColumnsRequest(Request $request): static { $self = new static(); $self->database = $m[2]; $self->table = $m[1]; - [$self->path, $self->hasCliEndpoint] = self::getEndpointInfo($request); return $self; } /** diff --git a/src/Plugin/Show/QueriesHandler.php b/src/Plugin/Show/QueriesHandler.php index be43f7d3..0c958973 100644 --- a/src/Plugin/Show/QueriesHandler.php +++ b/src/Plugin/Show/QueriesHandler.php @@ -12,8 +12,9 @@ namespace Manticoresearch\Buddy\Base\Plugin\Show; use Manticoresearch\Buddy\Core\ManticoreSearch\Client; -use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithTableFormatter; -use Manticoresearch\Buddy\Core\Plugin\TableFormatter; +use Manticoresearch\Buddy\Core\ManticoreSearch\Response; +use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; +use Manticoresearch\Buddy\Core\Task\Column; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskPool; use Manticoresearch\Buddy\Core\Task\TaskResult; @@ -22,7 +23,7 @@ /** * This is the parent class to handle erroneous Manticore queries */ -class QueriesHandler extends BaseHandlerWithTableFormatter { +class QueriesHandler extends BaseHandlerWithClient { const COL_MAP = [ 'connid' => 'id', 'last cmd' => 'query', @@ -50,94 +51,58 @@ public function run(): Task { // We run in a thread anyway but in case if we need blocking // We just waiting for a thread to be done $taskFn = static function ( - Payload $payload, Client $manticoreClient, - TableFormatter $tableFormatter, array $tasks ): TaskResult { // First, get response from the manticore - $time0 = hrtime(true); $resp = $manticoreClient->sendRequest( - 'SELECT * FROM @@system.sessions', - $payload->path + 'SELECT * FROM @@system.sessions' ); - $result = static::formatResponse($resp->getBody()); - // Second, get our own queries and append to the final result - /** @var array{0:array{data:array,total:int}} $result */ - $result[0]['data'] = array_merge($result[0]['data'], $tasks); - $result[0]['total'] += sizeof($tasks); - if ($payload->hasCliEndpoint) { - return TaskResult::raw($tableFormatter->getTable($time0, $result[0]['data'], $result[0]['total'])); - } - return TaskResult::raw($result); + return static::buildTaskResult($resp, $tasks); }; return Task::create( $taskFn, - [$this->payload, $this->manticoreClient, $this->tableFormatter, static::getTasksToAppend()] + [$this->manticoreClient, static::getTasksToAppend()] )->run(); } /** * Process the results * - * @param string $origResp - * @return array + * @param Response $response + * @param array $tasks + * @return TaskResult */ - public static function formatResponse(string $origResp): array { - $struct = [ - 'columns' => [ - ['id' => [ - 'type' => 'long long', - ], - ], - ['query' => [ - 'type' => 'string', - ], - ], - ['time' => [ - 'type' => 'string', - ], - ], - ['protocol' => [ - 'type' => 'string', - ], - ], - ['host' => [ - 'type' => 'string', - ], - ], - ], - 'data' => [], - 'total' => 0, - 'error' => '', - 'warning' => '', - ]; - $resp = (array)json_decode($origResp, true); - /** @var array{0:array{error?:string,warning?:string,data?:array>}} $resp */ - if (isset($resp[0]['data'])) { - $struct['error'] = $resp[0]['error'] ?? ''; - $struct['warning'] = $resp[0]['warning'] ?? ''; - foreach ($resp[0]['data'] as $row) { - ++$struct['total']; - $newRow = []; - foreach (static::COL_MAP as $oldKey => $newKey) { - if (!isset($row[$oldKey])) { - continue; - } - - $newRow[$newKey] = $row[$oldKey]; + public static function buildTaskResult(Response $response, array $tasks): TaskResult { + /** @var array $data */ + $data = $response->getData(); + $newData = []; + foreach ($data as &$row) { + $newRow = []; + foreach (static::COL_MAP as $oldKey => $newKey) { + if (!isset($row[$oldKey])) { + continue; } - $struct['data'][] = $newRow; + + $newRow[$newKey] = $row[$oldKey]; } + $newData[] = $newRow; } - return [$struct]; + unset($data); + $newData = array_merge($newData, $tasks); + return TaskResult::withData($newData) + ->column('id', Column::Long) + ->column('query', Column::String) + ->column('time', Column::String) + ->column('protocol', Column::String) + ->column('host', Column::String); } /** * This method appends our running queries from global state to result * - * @return array + * @return array */ protected static function getTasksToAppend(): array { $data = []; diff --git a/src/Plugin/Show/SchemasHandler.php b/src/Plugin/Show/SchemasHandler.php index 7856bef1..bdb449f2 100644 --- a/src/Plugin/Show/SchemasHandler.php +++ b/src/Plugin/Show/SchemasHandler.php @@ -12,8 +12,7 @@ namespace Manticoresearch\Buddy\Base\Plugin\Show; use Manticoresearch\Buddy\Core\ManticoreSearch\Client; -use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithTableFormatter; -use Manticoresearch\Buddy\Core\Plugin\TableFormatter; +use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; use Manticoresearch\Buddy\Core\Task\Column; use Manticoresearch\Buddy\Core\Task\Task; use Manticoresearch\Buddy\Core\Task\TaskResult; @@ -22,7 +21,7 @@ /** * This is the parent class to handle erroneous Manticore queries */ -class SchemasHandler extends BaseHandlerWithTableFormatter { +class SchemasHandler extends BaseHandlerWithClient { /** * Initialize the executor * @@ -42,26 +41,19 @@ public function run(): Task { // We run in a thread anyway but in case if we need blocking // We just waiting for a thread to be done $taskFn = static function ( - Payload $payload, Client $manticoreClient, - TableFormatter $tableFormatter ): TaskResult { - $time0 = hrtime(true); // First, get response from the manticore $query = 'SHOW DATABASES'; /** @var array{0:array{data:array}} */ - $result = $manticoreClient->sendRequest($query, $payload->path)->getResult(); - $total = sizeof($result[0]['data']); - if ($payload->hasCliEndpoint) { - return TaskResult::raw($tableFormatter->getTable($time0, $result[0]['data'], $total)); - } + $result = $manticoreClient->sendRequest($query)->getResult(); return TaskResult::withData($result[0]['data']) ->column('Database', Column::String); }; return Task::create( $taskFn, - [$this->payload, $this->manticoreClient, $this->tableFormatter] + [$this->manticoreClient] )->run(); } } diff --git a/src/Plugin/Show/UnsupportedStmtHandler.php b/src/Plugin/Show/UnsupportedStmtHandler.php index f05751e7..29b249e7 100644 --- a/src/Plugin/Show/UnsupportedStmtHandler.php +++ b/src/Plugin/Show/UnsupportedStmtHandler.php @@ -193,7 +193,7 @@ public static function handleQuery( if (preg_match('/^show( open)? tables from (Manticore|`Manticore`)(\s.*|$)/is', $payload->query)) { $query = 'SHOW TABLES'; /** @var array{0:array{data:array}} */ - $result = $manticoreClient->sendRequest($query, $payload->path)->getResult(); + $result = $manticoreClient->sendRequest($query)->getResult(); $data = $result[0]['data']; return TaskResult::withData($data) ->column('Table', Column::String) @@ -203,7 +203,7 @@ public static function handleQuery( if (preg_match('/^show table status from( Manticore| `Manticore`)?(\s*.*|$)/is', $payload->query, $matches)) { $query = 'SHOW TABLES'; /** @var array{0:array{data:array>}} */ - $result = $manticoreClient->sendRequest($query, $payload->path)->getResult(); + $result = $manticoreClient->sendRequest($query)->getResult(); $tableNames = array_map( fn($item) => $item['Table'] ?? '', $result[0]['data'] @@ -294,7 +294,7 @@ public static function handleQuery( if (stripos($payload->query, 'show variables') === 0) { $query = 'SHOW VARIABLES'; /** @var array{0:array{data:array>}} */ - $result = $manticoreClient->sendRequest($query, $payload->path)->getResult(); + $result = $manticoreClient->sendRequest($query)->getResult(); $condData = static::getVariablesWithCondition($result[0]['data'], $payload->query); return TaskResult::withData($condData) ->column('Variable_name', Column::String) diff --git a/src/init.php b/src/init.php index af0cba78..8e0e8c5d 100644 --- a/src/init.php +++ b/src/init.php @@ -15,7 +15,6 @@ use Manticoresearch\Buddy\Core\Cache\Flag as FlagCache; use Manticoresearch\Buddy\Core\ManticoreSearch\Client as HTTPClient; use Manticoresearch\Buddy\Core\Plugin\Pluggable; -use Manticoresearch\Buddy\Core\Plugin\TableFormatter; use Manticoresearch\Buddy\Core\Tool\Buddy; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\ExpressionLanguage\Expression; @@ -43,7 +42,6 @@ $container ->register('manticoreClient', HTTPClient::class) ->addArgument($opts['listen']); -$container->register('tableFormatter', TableFormatter::class); $container->register('flagCache', FlagCache::class); $container @@ -62,7 +60,6 @@ 'manticoresoftware/buddy-plugin-alias', 'manticoresoftware/buddy-plugin-select', 'manticoresoftware/buddy-plugin-show', - 'manticoresoftware/buddy-plugin-cli-table', 'manticoresoftware/buddy-plugin-plugin', 'manticoresoftware/buddy-plugin-test', 'manticoresoftware/buddy-plugin-alter-column', @@ -75,6 +72,7 @@ 'manticoresoftware/buddy-plugin-sharding', 'manticoresoftware/buddy-plugin-update', 'manticoresoftware/buddy-plugin-autocomplete', + 'manticoresoftware/buddy-plugin-cli-table', ]; // Filtering out the plugins that we don't need $plugins = array_filter( diff --git a/test/Plugin/CliTable/CliTableHandlerTest.php b/test/Plugin/CliTable/CliTableHandlerTest.php index a1ed5984..7d246809 100644 --- a/test/Plugin/CliTable/CliTableHandlerTest.php +++ b/test/Plugin/CliTable/CliTableHandlerTest.php @@ -15,7 +15,6 @@ use Manticoresearch\Buddy\Core\ManticoreSearch\Endpoint as ManticoreEndpoint; use Manticoresearch\Buddy\Core\ManticoreSearch\RequestFormat; use Manticoresearch\Buddy\Core\Network\Request; -use Manticoresearch\Buddy\Core\Plugin\TableFormatter; use Manticoresearch\Buddy\Core\Tool\Buddy; use Manticoresearch\Buddy\CoreTest\Trait\TestHTTPServerTrait; use Manticoresearch\Buddy\CoreTest\Trait\TestInEnvironmentTrait; @@ -55,20 +54,18 @@ public function testCliTableOk(): void { $serverUrl = self::setUpMockManticoreServer(false); $manticoreClient = new HTTPClient($serverUrl); $manticoreClient->setForceSync(true); - $tableFormatter = new TableFormatter(); Payload::$type = 'queries'; $payload = Payload::fromRequest($request); $handler = new Handler($payload); $refCls = new ReflectionClass($handler); $refCls->getProperty('manticoreClient')->setValue($handler, $manticoreClient); - $refCls->getProperty('tableFormatter')->setValue($handler, $tableFormatter); go( function () use ($handler, $respBody) { $task = $handler->run(); $task->wait(true); $this->assertEquals(true, $task->isSucceed()); - $result = $task->getResult()->getStruct(); + $result = $task->getResult()->getTableFormatted(0); $this->assertIsString($result); $this->assertStringContainsString($respBody, $result); self::finishMockManticoreServer(); diff --git a/test/Plugin/Insert/InsertQuery/InsertQueryHandlerTest.php b/test/Plugin/Insert/InsertQuery/InsertQueryHandlerTest.php index c93f4233..0bfe0e4d 100644 --- a/test/Plugin/Insert/InsertQuery/InsertQueryHandlerTest.php +++ b/test/Plugin/Insert/InsertQuery/InsertQueryHandlerTest.php @@ -75,7 +75,7 @@ function () use ($handler, $resp) { $this->assertEquals(true, $task->isSucceed()); /** @var Struct */ $result = $task->getResult()->getStruct(); - $this->assertEquals($resp, $result->toJson()); + $this->assertEquals($resp, json_encode($result)); } ); \Swoole\Event::wait(); diff --git a/test/Plugin/Show/ShowQueries/ShowQueriesHandlerTest.php b/test/Plugin/Show/ShowQueries/ShowQueriesHandlerTest.php index 9062a377..e7e2e575 100644 --- a/test/Plugin/Show/ShowQueries/ShowQueriesHandlerTest.php +++ b/test/Plugin/Show/ShowQueries/ShowQueriesHandlerTest.php @@ -15,7 +15,7 @@ use Manticoresearch\Buddy\Core\ManticoreSearch\Endpoint as ManticoreEndpoint; use Manticoresearch\Buddy\Core\ManticoreSearch\RequestFormat; use Manticoresearch\Buddy\Core\Network\Request as NetRequest; -use Manticoresearch\Buddy\Core\Plugin\TableFormatter; + use Manticoresearch\Buddy\Core\Tool\Buddy; use Manticoresearch\Buddy\CoreTest\Trait\TestHTTPServerTrait; use Manticoresearch\Buddy\CoreTest\Trait\TestInEnvironmentTrait; @@ -62,7 +62,6 @@ public function testShowQueriesExecutesProperly(): void { $handler = new Handler($payload); $handler->setManticoreClient($manticoreClient); - $handler->setTableFormatter(new TableFormatter()); go( function () use ($handler, $respBody) { $task = $handler->run(); diff --git a/test/src/Trait/TestFunctionalTrait.php b/test/src/Trait/TestFunctionalTrait.php index 213b1ed6..3434f23b 100644 --- a/test/src/Trait/TestFunctionalTrait.php +++ b/test/src/Trait/TestFunctionalTrait.php @@ -309,10 +309,10 @@ protected static function runHttpQuery( ? 'Content-type: application/x-www-form-urlencoded' : 'Content-type: application/json' ); - exec( - "curl -s 127.0.0.1:$port/$path -H '$header' --data-binary @$payloadFile $redirect", - $output - ); + + $command = "curl -s 127.0.0.1:$port/$path -H '$header' --data-binary @$payloadFile $redirect"; + echo 'Commmand: ' . $command . PHP_EOL; + exec($command, $output); /** @var array{error:string}|array>,total?:string,columns?:string}> $result */ $result = match ($path) {