diff --git a/manifest.json b/manifest.json index 9f095be90..9898811aa 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "variables": { - "${LATEST}": "3.324.7" + "${LATEST}": "3.324.8" }, "endpoints": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/endpoints.json", "services": { diff --git a/src/Service/TimestreamQuery/CHANGELOG.md b/src/Service/TimestreamQuery/CHANGELOG.md index 4754ba8bf..63c2cfcb4 100644 --- a/src/Service/TimestreamQuery/CHANGELOG.md +++ b/src/Service/TimestreamQuery/CHANGELOG.md @@ -2,6 +2,10 @@ ## NOT RELEASED +### Added + +- AWS api-change: This release adds support for Query Insights, a feature that provides details of query execution, enabling users to identify areas for improvement to optimize their queries, resulting in improved query performance and lower query costs. + ## 2.0.4 ### Changed diff --git a/src/Service/TimestreamQuery/composer.json b/src/Service/TimestreamQuery/composer.json index c828e605c..0b1c72050 100644 --- a/src/Service/TimestreamQuery/composer.json +++ b/src/Service/TimestreamQuery/composer.json @@ -29,7 +29,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" } } } diff --git a/src/Service/TimestreamQuery/src/Enum/QueryInsightsMode.php b/src/Service/TimestreamQuery/src/Enum/QueryInsightsMode.php new file mode 100644 index 000000000..b2a788837 --- /dev/null +++ b/src/Service/TimestreamQuery/src/Enum/QueryInsightsMode.php @@ -0,0 +1,17 @@ + true, + self::ENABLED_WITH_RATE_CONTROL => true, + ][$value]); + } +} diff --git a/src/Service/TimestreamQuery/src/Input/QueryRequest.php b/src/Service/TimestreamQuery/src/Input/QueryRequest.php index cc642d475..dfa416a33 100644 --- a/src/Service/TimestreamQuery/src/Input/QueryRequest.php +++ b/src/Service/TimestreamQuery/src/Input/QueryRequest.php @@ -6,6 +6,7 @@ use AsyncAws\Core\Input; use AsyncAws\Core\Request; use AsyncAws\Core\Stream\StreamFactory; +use AsyncAws\TimestreamQuery\ValueObject\QueryInsights; final class QueryRequest extends Input { @@ -78,12 +79,23 @@ final class QueryRequest extends Input */ private $maxRows; + /** + * Encapsulates settings for enabling `QueryInsights`. + * + * Enabling `QueryInsights` returns insights and metrics in addition to query results for the query that you executed. + * You can use `QueryInsights` to tune your query performance. + * + * @var QueryInsights|null + */ + private $queryInsights; + /** * @param array{ * QueryString?: string, * ClientToken?: null|string, * NextToken?: null|string, * MaxRows?: null|int, + * QueryInsights?: null|QueryInsights|array, * '@region'?: string|null, * } $input */ @@ -93,6 +105,7 @@ public function __construct(array $input = []) $this->clientToken = $input['ClientToken'] ?? null; $this->nextToken = $input['NextToken'] ?? null; $this->maxRows = $input['MaxRows'] ?? null; + $this->queryInsights = isset($input['QueryInsights']) ? QueryInsights::create($input['QueryInsights']) : null; parent::__construct($input); } @@ -102,6 +115,7 @@ public function __construct(array $input = []) * ClientToken?: null|string, * NextToken?: null|string, * MaxRows?: null|int, + * QueryInsights?: null|QueryInsights|array, * '@region'?: string|null, * }|QueryRequest $input */ @@ -125,6 +139,11 @@ public function getNextToken(): ?string return $this->nextToken; } + public function getQueryInsights(): ?QueryInsights + { + return $this->queryInsights; + } + public function getQueryString(): ?string { return $this->queryString; @@ -177,6 +196,13 @@ public function setNextToken(?string $value): self return $this; } + public function setQueryInsights(?QueryInsights $value): self + { + $this->queryInsights = $value; + + return $this; + } + public function setQueryString(?string $value): self { $this->queryString = $value; @@ -201,6 +227,9 @@ private function requestBody(): array if (null !== $v = $this->maxRows) { $payload['MaxRows'] = $v; } + if (null !== $v = $this->queryInsights) { + $payload['QueryInsights'] = $v->requestBody(); + } return $payload; } diff --git a/src/Service/TimestreamQuery/src/Result/QueryResponse.php b/src/Service/TimestreamQuery/src/Result/QueryResponse.php index 4a73c1f59..2dbfcc3cf 100644 --- a/src/Service/TimestreamQuery/src/Result/QueryResponse.php +++ b/src/Service/TimestreamQuery/src/Result/QueryResponse.php @@ -9,7 +9,12 @@ use AsyncAws\TimestreamQuery\TimestreamQueryClient; use AsyncAws\TimestreamQuery\ValueObject\ColumnInfo; use AsyncAws\TimestreamQuery\ValueObject\Datum; +use AsyncAws\TimestreamQuery\ValueObject\QueryInsightsResponse; +use AsyncAws\TimestreamQuery\ValueObject\QuerySpatialCoverage; +use AsyncAws\TimestreamQuery\ValueObject\QuerySpatialCoverageMax; use AsyncAws\TimestreamQuery\ValueObject\QueryStatus; +use AsyncAws\TimestreamQuery\ValueObject\QueryTemporalRange; +use AsyncAws\TimestreamQuery\ValueObject\QueryTemporalRangeMax; use AsyncAws\TimestreamQuery\ValueObject\Row; use AsyncAws\TimestreamQuery\ValueObject\TimeSeriesDataPoint; use AsyncAws\TimestreamQuery\ValueObject\Type; @@ -54,6 +59,13 @@ class QueryResponse extends Result implements \IteratorAggregate */ private $queryStatus; + /** + * Encapsulates `QueryInsights` containing insights and metrics related to the query that you executed. + * + * @var QueryInsightsResponse|null + */ + private $queryInsightsResponse; + /** * @return ColumnInfo[] */ @@ -88,6 +100,13 @@ public function getQueryId(): string return $this->queryId; } + public function getQueryInsightsResponse(): ?QueryInsightsResponse + { + $this->initialize(); + + return $this->queryInsightsResponse; + } + public function getQueryStatus(): ?QueryStatus { $this->initialize(); @@ -148,6 +167,7 @@ protected function populateResult(Response $response): void $this->rows = $this->populateResultRowList($data['Rows'] ?? []); $this->columnInfo = $this->populateResultColumnInfoList($data['ColumnInfo'] ?? []); $this->queryStatus = empty($data['QueryStatus']) ? null : $this->populateResultQueryStatus($data['QueryStatus']); + $this->queryInsightsResponse = empty($data['QueryInsightsResponse']) ? null : $this->populateResultQueryInsightsResponse($data['QueryInsightsResponse']); } private function populateResultColumnInfo(array $json): ColumnInfo @@ -195,6 +215,52 @@ private function populateResultDatumList(array $json): array return $items; } + /** + * @return string[] + */ + private function populateResultPartitionKeyList(array $json): array + { + $items = []; + foreach ($json as $item) { + $a = isset($item) ? (string) $item : null; + if (null !== $a) { + $items[] = $a; + } + } + + return $items; + } + + private function populateResultQueryInsightsResponse(array $json): QueryInsightsResponse + { + return new QueryInsightsResponse([ + 'QuerySpatialCoverage' => empty($json['QuerySpatialCoverage']) ? null : $this->populateResultQuerySpatialCoverage($json['QuerySpatialCoverage']), + 'QueryTemporalRange' => empty($json['QueryTemporalRange']) ? null : $this->populateResultQueryTemporalRange($json['QueryTemporalRange']), + 'QueryTableCount' => isset($json['QueryTableCount']) ? (int) $json['QueryTableCount'] : null, + 'OutputRows' => isset($json['OutputRows']) ? (int) $json['OutputRows'] : null, + 'OutputBytes' => isset($json['OutputBytes']) ? (int) $json['OutputBytes'] : null, + 'UnloadPartitionCount' => isset($json['UnloadPartitionCount']) ? (int) $json['UnloadPartitionCount'] : null, + 'UnloadWrittenRows' => isset($json['UnloadWrittenRows']) ? (int) $json['UnloadWrittenRows'] : null, + 'UnloadWrittenBytes' => isset($json['UnloadWrittenBytes']) ? (int) $json['UnloadWrittenBytes'] : null, + ]); + } + + private function populateResultQuerySpatialCoverage(array $json): QuerySpatialCoverage + { + return new QuerySpatialCoverage([ + 'Max' => empty($json['Max']) ? null : $this->populateResultQuerySpatialCoverageMax($json['Max']), + ]); + } + + private function populateResultQuerySpatialCoverageMax(array $json): QuerySpatialCoverageMax + { + return new QuerySpatialCoverageMax([ + 'Value' => isset($json['Value']) ? (float) $json['Value'] : null, + 'TableArn' => isset($json['TableArn']) ? (string) $json['TableArn'] : null, + 'PartitionKey' => !isset($json['PartitionKey']) ? null : $this->populateResultPartitionKeyList($json['PartitionKey']), + ]); + } + private function populateResultQueryStatus(array $json): QueryStatus { return new QueryStatus([ @@ -204,6 +270,21 @@ private function populateResultQueryStatus(array $json): QueryStatus ]); } + private function populateResultQueryTemporalRange(array $json): QueryTemporalRange + { + return new QueryTemporalRange([ + 'Max' => empty($json['Max']) ? null : $this->populateResultQueryTemporalRangeMax($json['Max']), + ]); + } + + private function populateResultQueryTemporalRangeMax(array $json): QueryTemporalRangeMax + { + return new QueryTemporalRangeMax([ + 'Value' => isset($json['Value']) ? (int) $json['Value'] : null, + 'TableArn' => isset($json['TableArn']) ? (string) $json['TableArn'] : null, + ]); + } + private function populateResultRow(array $json): Row { return new Row([ diff --git a/src/Service/TimestreamQuery/src/TimestreamQueryClient.php b/src/Service/TimestreamQuery/src/TimestreamQueryClient.php index ccdef0802..36841315f 100644 --- a/src/Service/TimestreamQuery/src/TimestreamQueryClient.php +++ b/src/Service/TimestreamQuery/src/TimestreamQueryClient.php @@ -22,6 +22,7 @@ use AsyncAws\TimestreamQuery\Result\DescribeEndpointsResponse; use AsyncAws\TimestreamQuery\Result\PrepareQueryResponse; use AsyncAws\TimestreamQuery\Result\QueryResponse; +use AsyncAws\TimestreamQuery\ValueObject\QueryInsights; class TimestreamQueryClient extends AbstractApi { @@ -135,9 +136,16 @@ public function prepareQuery($input): PrepareQueryResponse } /** - * `Query` is a synchronous operation that enables you to run a query against your Amazon Timestream data. `Query` will - * time out after 60 seconds. You must update the default timeout in the SDK to support a timeout of 60 seconds. See the - * code sample [^1] for details. + * `Query` is a synchronous operation that enables you to run a query against your Amazon Timestream data. + * + * If you enabled `QueryInsights`, this API also returns insights and metrics related to the query that you executed. + * `QueryInsights` helps with performance tuning of your query. + * + * > The maximum number of `Query` API requests you're allowed to make with `QueryInsights` enabled is 1 query per + * > second (QPS). If you exceed this query rate, it might result in throttling. + * + * `Query` will time out after 60 seconds. You must update the default timeout in the SDK to support a timeout of 60 + * seconds. See the code sample [^1] for details. * * Your query request will fail in the following cases: * @@ -162,6 +170,7 @@ public function prepareQuery($input): PrepareQueryResponse * ClientToken?: null|string, * NextToken?: null|string, * MaxRows?: null|int, + * QueryInsights?: null|QueryInsights|array, * '@region'?: string|null, * }|QueryRequest $input * diff --git a/src/Service/TimestreamQuery/src/ValueObject/QueryInsights.php b/src/Service/TimestreamQuery/src/ValueObject/QueryInsights.php new file mode 100644 index 000000000..4b2d43a7a --- /dev/null +++ b/src/Service/TimestreamQuery/src/ValueObject/QueryInsights.php @@ -0,0 +1,98 @@ + The maximum number of `Query` API requests you're allowed to make with `QueryInsights` enabled is 1 query per + * > second (QPS). If you exceed this query rate, it might result in throttling. + */ +final class QueryInsights +{ + /** + * Provides the following modes to enable `QueryInsights`: + * + * - `ENABLED_WITH_RATE_CONTROL` – Enables `QueryInsights` for the queries being processed. This mode also includes a + * rate control mechanism, which limits the `QueryInsights` feature to 1 query per second (QPS). + * - `DISABLED` – Disables `QueryInsights`. + * + * @var QueryInsightsMode::* + */ + private $mode; + + /** + * @param array{ + * Mode: QueryInsightsMode::*, + * } $input + */ + public function __construct(array $input) + { + $this->mode = $input['Mode'] ?? $this->throwException(new InvalidArgument('Missing required field "Mode".')); + } + + /** + * @param array{ + * Mode: QueryInsightsMode::*, + * }|QueryInsights $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return QueryInsightsMode::* + */ + public function getMode(): string + { + return $this->mode; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + $v = $this->mode; + if (!QueryInsightsMode::exists($v)) { + throw new InvalidArgument(\sprintf('Invalid parameter "Mode" for "%s". The value "%s" is not a valid "QueryInsightsMode".', __CLASS__, $v)); + } + $payload['Mode'] = $v; + + return $payload; + } + + /** + * @return never + */ + private function throwException(\Throwable $exception) + { + throw $exception; + } +} diff --git a/src/Service/TimestreamQuery/src/ValueObject/QueryInsightsResponse.php b/src/Service/TimestreamQuery/src/ValueObject/QueryInsightsResponse.php new file mode 100644 index 000000000..e441caa13 --- /dev/null +++ b/src/Service/TimestreamQuery/src/ValueObject/QueryInsightsResponse.php @@ -0,0 +1,155 @@ +querySpatialCoverage = isset($input['QuerySpatialCoverage']) ? QuerySpatialCoverage::create($input['QuerySpatialCoverage']) : null; + $this->queryTemporalRange = isset($input['QueryTemporalRange']) ? QueryTemporalRange::create($input['QueryTemporalRange']) : null; + $this->queryTableCount = $input['QueryTableCount'] ?? null; + $this->outputRows = $input['OutputRows'] ?? null; + $this->outputBytes = $input['OutputBytes'] ?? null; + $this->unloadPartitionCount = $input['UnloadPartitionCount'] ?? null; + $this->unloadWrittenRows = $input['UnloadWrittenRows'] ?? null; + $this->unloadWrittenBytes = $input['UnloadWrittenBytes'] ?? null; + } + + /** + * @param array{ + * QuerySpatialCoverage?: null|QuerySpatialCoverage|array, + * QueryTemporalRange?: null|QueryTemporalRange|array, + * QueryTableCount?: null|int, + * OutputRows?: null|int, + * OutputBytes?: null|int, + * UnloadPartitionCount?: null|int, + * UnloadWrittenRows?: null|int, + * UnloadWrittenBytes?: null|int, + * }|QueryInsightsResponse $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getOutputBytes(): ?int + { + return $this->outputBytes; + } + + public function getOutputRows(): ?int + { + return $this->outputRows; + } + + public function getQuerySpatialCoverage(): ?QuerySpatialCoverage + { + return $this->querySpatialCoverage; + } + + public function getQueryTableCount(): ?int + { + return $this->queryTableCount; + } + + public function getQueryTemporalRange(): ?QueryTemporalRange + { + return $this->queryTemporalRange; + } + + public function getUnloadPartitionCount(): ?int + { + return $this->unloadPartitionCount; + } + + public function getUnloadWrittenBytes(): ?int + { + return $this->unloadWrittenBytes; + } + + public function getUnloadWrittenRows(): ?int + { + return $this->unloadWrittenRows; + } +} diff --git a/src/Service/TimestreamQuery/src/ValueObject/QuerySpatialCoverage.php b/src/Service/TimestreamQuery/src/ValueObject/QuerySpatialCoverage.php new file mode 100644 index 000000000..ac9289fb0 --- /dev/null +++ b/src/Service/TimestreamQuery/src/ValueObject/QuerySpatialCoverage.php @@ -0,0 +1,54 @@ +max = isset($input['Max']) ? QuerySpatialCoverageMax::create($input['Max']) : null; + } + + /** + * @param array{ + * Max?: null|QuerySpatialCoverageMax|array, + * }|QuerySpatialCoverage $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getMax(): ?QuerySpatialCoverageMax + { + return $this->max; + } +} diff --git a/src/Service/TimestreamQuery/src/ValueObject/QuerySpatialCoverageMax.php b/src/Service/TimestreamQuery/src/ValueObject/QuerySpatialCoverageMax.php new file mode 100644 index 000000000..e556e2934 --- /dev/null +++ b/src/Service/TimestreamQuery/src/ValueObject/QuerySpatialCoverageMax.php @@ -0,0 +1,77 @@ +value = $input['Value'] ?? null; + $this->tableArn = $input['TableArn'] ?? null; + $this->partitionKey = $input['PartitionKey'] ?? null; + } + + /** + * @param array{ + * Value?: null|float, + * TableArn?: null|string, + * PartitionKey?: null|string[], + * }|QuerySpatialCoverageMax $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return string[] + */ + public function getPartitionKey(): array + { + return $this->partitionKey ?? []; + } + + public function getTableArn(): ?string + { + return $this->tableArn; + } + + public function getValue(): ?float + { + return $this->value; + } +} diff --git a/src/Service/TimestreamQuery/src/ValueObject/QueryTemporalRange.php b/src/Service/TimestreamQuery/src/ValueObject/QueryTemporalRange.php new file mode 100644 index 000000000..b4a629bda --- /dev/null +++ b/src/Service/TimestreamQuery/src/ValueObject/QueryTemporalRange.php @@ -0,0 +1,45 @@ +max = isset($input['Max']) ? QueryTemporalRangeMax::create($input['Max']) : null; + } + + /** + * @param array{ + * Max?: null|QueryTemporalRangeMax|array, + * }|QueryTemporalRange $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getMax(): ?QueryTemporalRangeMax + { + return $this->max; + } +} diff --git a/src/Service/TimestreamQuery/src/ValueObject/QueryTemporalRangeMax.php b/src/Service/TimestreamQuery/src/ValueObject/QueryTemporalRangeMax.php new file mode 100644 index 000000000..a80a96d98 --- /dev/null +++ b/src/Service/TimestreamQuery/src/ValueObject/QueryTemporalRangeMax.php @@ -0,0 +1,56 @@ +value = $input['Value'] ?? null; + $this->tableArn = $input['TableArn'] ?? null; + } + + /** + * @param array{ + * Value?: null|int, + * TableArn?: null|string, + * }|QueryTemporalRangeMax $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getTableArn(): ?string + { + return $this->tableArn; + } + + public function getValue(): ?int + { + return $this->value; + } +}