Skip to content

Commit c24e109

Browse files
committed
async-aws(Athena Client): (quick work around too) add GetQueryResults operation
1 parent ce38a70 commit c24e109

15 files changed

+810
-1
lines changed

manifest.json

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"GetDatabase",
3939
"GetNamedQuery",
4040
"GetQueryExecution",
41+
"GetQueryResults",
4142
"GetSession",
4243
"GetSessionStatus",
4344
"GetTableMetadata",

src/CodeGenerator/src/Generator/OperationGenerator.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
*/
2727
class OperationGenerator
2828
{
29+
private const PAGINATE_STRUCTURE_SHAPE = ['GetQueryResults'];
30+
2931
/**
3032
* @var ClassRegistry
3133
*/
@@ -137,7 +139,8 @@ public function generate(Operation $operation): void
137139
}
138140
if (null !== $operation->getOutput()) {
139141
$resultClass = $this->resultGenerator->generate($operation);
140-
if (null !== $operation->getPagination()) {
142+
$isPaginateListShape = false === \in_array($operation->getName(), self::PAGINATE_STRUCTURE_SHAPE);
143+
if (null !== $operation->getPagination() && $isPaginateListShape) {
141144
$this->paginationGenerator->generate($operation);
142145
}
143146

src/Service/Athena/src/AthenaClient.php

+36
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use AsyncAws\Athena\Input\GetDataCatalogInput;
1515
use AsyncAws\Athena\Input\GetNamedQueryInput;
1616
use AsyncAws\Athena\Input\GetQueryExecutionInput;
17+
use AsyncAws\Athena\Input\GetQueryResultsInput;
1718
use AsyncAws\Athena\Input\GetSessionRequest;
1819
use AsyncAws\Athena\Input\GetSessionStatusRequest;
1920
use AsyncAws\Athena\Input\GetTableMetadataInput;
@@ -34,6 +35,7 @@
3435
use AsyncAws\Athena\Result\GetDataCatalogOutput;
3536
use AsyncAws\Athena\Result\GetNamedQueryOutput;
3637
use AsyncAws\Athena\Result\GetQueryExecutionOutput;
38+
use AsyncAws\Athena\Result\GetQueryResultsOutput;
3739
use AsyncAws\Athena\Result\GetSessionResponse;
3840
use AsyncAws\Athena\Result\GetSessionStatusResponse;
3941
use AsyncAws\Athena\Result\GetTableMetadataOutput;
@@ -227,6 +229,40 @@ public function getQueryExecution($input): GetQueryExecutionOutput
227229
return new GetQueryExecutionOutput($response);
228230
}
229231

232+
/**
233+
* Streams the results of a single query execution specified by `QueryExecutionId` from the Athena query results
234+
* location in Amazon S3. For more information, see Working with query results, recent queries, and output files in the
235+
* *Amazon Athena User Guide*. This request does not execute the query but returns results. Use StartQueryExecution to
236+
* run a query.
237+
*
238+
* @see https://docs.aws.amazon.com/athena/latest/ug/querying.html
239+
* @see https://docs.aws.amazon.com/athena/latest/APIReference/API_GetQueryResults.html
240+
* @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-athena-2017-05-18.html#getqueryresults
241+
*
242+
* @param array{
243+
* QueryExecutionId: string,
244+
* NextToken?: string,
245+
* MaxResults?: int,
246+
*
247+
* @region?: string,
248+
* }|GetQueryResultsInput $input
249+
*
250+
* @throws InternalServerException
251+
* @throws InvalidRequestException
252+
* @throws TooManyRequestsException
253+
*/
254+
public function getQueryResults($input): GetQueryResultsOutput
255+
{
256+
$input = GetQueryResultsInput::create($input);
257+
$response = $this->getResponse($input->request(), new RequestContext(['operation' => 'GetQueryResults', 'region' => $input->getRegion(), 'exceptionMapping' => [
258+
'InternalServerException' => InternalServerException::class,
259+
'InvalidRequestException' => InvalidRequestException::class,
260+
'TooManyRequestsException' => TooManyRequestsException::class,
261+
]]));
262+
263+
return new GetQueryResultsOutput($response, $this, $input);
264+
}
265+
230266
/**
231267
* Gets the full details of a previously created session, including the session status and configuration.
232268
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace AsyncAws\Athena\Enum;
4+
5+
/**
6+
* Indicates the column's nullable status.
7+
*/
8+
final class ColumnNullable
9+
{
10+
public const NOT_NULL = 'NOT_NULL';
11+
public const NULLABLE = 'NULLABLE';
12+
public const UNKNOWN = 'UNKNOWN';
13+
14+
public static function exists(string $value): bool
15+
{
16+
return isset([
17+
self::NOT_NULL => true,
18+
self::NULLABLE => true,
19+
self::UNKNOWN => true,
20+
][$value]);
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php
2+
3+
namespace AsyncAws\Athena\Input;
4+
5+
use AsyncAws\Core\Exception\InvalidArgument;
6+
use AsyncAws\Core\Input;
7+
use AsyncAws\Core\Request;
8+
use AsyncAws\Core\Stream\StreamFactory;
9+
10+
final class GetQueryResultsInput extends Input
11+
{
12+
/**
13+
* The unique ID of the query execution.
14+
*
15+
* @required
16+
*
17+
* @var string|null
18+
*/
19+
private $queryExecutionId;
20+
21+
/**
22+
* A token generated by the Athena service that specifies where to continue pagination if a previous request was
23+
* truncated. To obtain the next set of pages, pass in the `NextToken` from the response object of the previous page
24+
* call.
25+
*
26+
* @var string|null
27+
*/
28+
private $nextToken;
29+
30+
/**
31+
* The maximum number of results (rows) to return in this request.
32+
*
33+
* @var int|null
34+
*/
35+
private $maxResults;
36+
37+
/**
38+
* @param array{
39+
* QueryExecutionId?: string,
40+
* NextToken?: string,
41+
* MaxResults?: int,
42+
*
43+
* @region?: string,
44+
* } $input
45+
*/
46+
public function __construct(array $input = [])
47+
{
48+
$this->queryExecutionId = $input['QueryExecutionId'] ?? null;
49+
$this->nextToken = $input['NextToken'] ?? null;
50+
$this->maxResults = $input['MaxResults'] ?? null;
51+
parent::__construct($input);
52+
}
53+
54+
public static function create($input): self
55+
{
56+
return $input instanceof self ? $input : new self($input);
57+
}
58+
59+
public function getMaxResults(): ?int
60+
{
61+
return $this->maxResults;
62+
}
63+
64+
public function getNextToken(): ?string
65+
{
66+
return $this->nextToken;
67+
}
68+
69+
public function getQueryExecutionId(): ?string
70+
{
71+
return $this->queryExecutionId;
72+
}
73+
74+
/**
75+
* @internal
76+
*/
77+
public function request(): Request
78+
{
79+
// Prepare headers
80+
$headers = [
81+
'Content-Type' => 'application/x-amz-json-1.1',
82+
'X-Amz-Target' => 'AmazonAthena.GetQueryResults',
83+
];
84+
85+
// Prepare query
86+
$query = [];
87+
88+
// Prepare URI
89+
$uriString = '/';
90+
91+
// Prepare Body
92+
$bodyPayload = $this->requestBody();
93+
$body = empty($bodyPayload) ? '{}' : json_encode($bodyPayload, 4194304);
94+
95+
// Return the Request
96+
return new Request('POST', $uriString, $query, $headers, StreamFactory::create($body));
97+
}
98+
99+
public function setMaxResults(?int $value): self
100+
{
101+
$this->maxResults = $value;
102+
103+
return $this;
104+
}
105+
106+
public function setNextToken(?string $value): self
107+
{
108+
$this->nextToken = $value;
109+
110+
return $this;
111+
}
112+
113+
public function setQueryExecutionId(?string $value): self
114+
{
115+
$this->queryExecutionId = $value;
116+
117+
return $this;
118+
}
119+
120+
private function requestBody(): array
121+
{
122+
$payload = [];
123+
if (null === $v = $this->queryExecutionId) {
124+
throw new InvalidArgument(sprintf('Missing parameter "QueryExecutionId" for "%s". The value cannot be null.', __CLASS__));
125+
}
126+
$payload['QueryExecutionId'] = $v;
127+
if (null !== $v = $this->nextToken) {
128+
$payload['NextToken'] = $v;
129+
}
130+
if (null !== $v = $this->maxResults) {
131+
$payload['MaxResults'] = $v;
132+
}
133+
134+
return $payload;
135+
}
136+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<?php
2+
3+
namespace AsyncAws\Athena\Result;
4+
5+
use AsyncAws\Athena\ValueObject\ColumnInfo;
6+
use AsyncAws\Athena\ValueObject\Datum;
7+
use AsyncAws\Athena\ValueObject\ResultSet;
8+
use AsyncAws\Athena\ValueObject\ResultSetMetadata;
9+
use AsyncAws\Athena\ValueObject\Row;
10+
use AsyncAws\Core\Response;
11+
use AsyncAws\Core\Result;
12+
13+
class GetQueryResultsOutput extends Result
14+
{
15+
/**
16+
* The number of rows inserted with a `CREATE TABLE AS SELECT` statement.
17+
*/
18+
private $updateCount;
19+
20+
/**
21+
* The results of the query execution.
22+
*/
23+
private $resultSet;
24+
25+
/**
26+
* A token generated by the Athena service that specifies where to continue pagination if a previous request was
27+
* truncated. To obtain the next set of pages, pass in the `NextToken` from the response object of the previous page
28+
* call.
29+
*/
30+
private $nextToken;
31+
32+
public function getNextToken(): ?string
33+
{
34+
$this->initialize();
35+
36+
return $this->nextToken;
37+
}
38+
39+
public function getResultSet(): ?ResultSet
40+
{
41+
$this->initialize();
42+
43+
return $this->resultSet;
44+
}
45+
46+
public function getUpdateCount(): ?string
47+
{
48+
$this->initialize();
49+
50+
return $this->updateCount;
51+
}
52+
53+
protected function populateResult(Response $response): void
54+
{
55+
$data = $response->toArray();
56+
57+
$this->updateCount = isset($data['UpdateCount']) ? (string) $data['UpdateCount'] : null;
58+
$this->resultSet = empty($data['ResultSet']) ? null : $this->populateResultResultSet($data['ResultSet']);
59+
$this->nextToken = isset($data['NextToken']) ? (string) $data['NextToken'] : null;
60+
}
61+
62+
private function populateResultColumnInfo(array $json): ColumnInfo
63+
{
64+
return new ColumnInfo([
65+
'CatalogName' => isset($json['CatalogName']) ? (string) $json['CatalogName'] : null,
66+
'SchemaName' => isset($json['SchemaName']) ? (string) $json['SchemaName'] : null,
67+
'TableName' => isset($json['TableName']) ? (string) $json['TableName'] : null,
68+
'Name' => (string) $json['Name'],
69+
'Label' => isset($json['Label']) ? (string) $json['Label'] : null,
70+
'Type' => (string) $json['Type'],
71+
'Precision' => isset($json['Precision']) ? (int) $json['Precision'] : null,
72+
'Scale' => isset($json['Scale']) ? (int) $json['Scale'] : null,
73+
'Nullable' => isset($json['Nullable']) ? (string) $json['Nullable'] : null,
74+
'CaseSensitive' => isset($json['CaseSensitive']) ? filter_var($json['CaseSensitive'], \FILTER_VALIDATE_BOOLEAN) : null,
75+
]);
76+
}
77+
78+
/**
79+
* @return ColumnInfo[]
80+
*/
81+
private function populateResultColumnInfoList(array $json): array
82+
{
83+
$items = [];
84+
foreach ($json as $item) {
85+
$items[] = $this->populateResultColumnInfo($item);
86+
}
87+
88+
return $items;
89+
}
90+
91+
private function populateResultDatum(array $json): Datum
92+
{
93+
return new Datum([
94+
'VarCharValue' => isset($json['VarCharValue']) ? (string) $json['VarCharValue'] : null,
95+
]);
96+
}
97+
98+
/**
99+
* @return Datum[]
100+
*/
101+
private function populateResultDatumList(array $json): array
102+
{
103+
$items = [];
104+
foreach ($json as $item) {
105+
$items[] = $this->populateResultDatum($item);
106+
}
107+
108+
return $items;
109+
}
110+
111+
private function populateResultResultSet(array $json): ResultSet
112+
{
113+
return new ResultSet([
114+
'Rows' => !isset($json['Rows']) ? null : $this->populateResultRowList($json['Rows']),
115+
'ResultSetMetadata' => empty($json['ResultSetMetadata']) ? null : $this->populateResultResultSetMetadata($json['ResultSetMetadata']),
116+
]);
117+
}
118+
119+
private function populateResultResultSetMetadata(array $json): ResultSetMetadata
120+
{
121+
return new ResultSetMetadata([
122+
'ColumnInfo' => !isset($json['ColumnInfo']) ? null : $this->populateResultColumnInfoList($json['ColumnInfo']),
123+
]);
124+
}
125+
126+
private function populateResultRow(array $json): Row
127+
{
128+
return new Row([
129+
'Data' => !isset($json['Data']) ? null : $this->populateResultDatumList($json['Data']),
130+
]);
131+
}
132+
133+
/**
134+
* @return Row[]
135+
*/
136+
private function populateResultRowList(array $json): array
137+
{
138+
$items = [];
139+
foreach ($json as $item) {
140+
$items[] = $this->populateResultRow($item);
141+
}
142+
143+
return $items;
144+
}
145+
}

0 commit comments

Comments
 (0)