Skip to content

Commit

Permalink
Merge pull request #4 from ytake/feature/added-fetch-style
Browse files Browse the repository at this point in the history
Feature/added fetch style
  • Loading branch information
ytake authored Sep 18, 2017
2 parents b64d45e + 7991191 commit 07ae7ad
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 24 deletions.
73 changes: 73 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,76 @@ $result = $resultSession->execute()->yieldResults();
$result = $resultSession->execute()->getResults();
```

## Fetch Styles

### FixData Object

```php
<?php

$client = new \Ytake\PrestoClient\StatementClient(
new \Ytake\PrestoClient\ClientSession('http://localhost:8080/', 'acme'),
'SELECT * FROM acme.acme.acme'
);
$resultSession = new \Ytake\PrestoClient\ResultsSession($client);
$result = $resultSession->execute()->yieldResults();
/** @var \Ytake\PrestoClient\QueryResult $row */
foreach ($result as $row) {
foreach ($row->yieldData() as $yieldRow) {
if ($yieldRow instanceof \Ytake\PrestoClient\FixData) {
var_dump($yieldRow->offsetGet('column_name'), $yieldRow['column_name']);
}
}
}
```

### Array Keys

```php
<?php

$client = new \Ytake\PrestoClient\StatementClient(
new \Ytake\PrestoClient\ClientSession('http://localhost:8080/', 'acme'),
'SELECT * FROM acme.acme.acme'
);
$resultSession = new \Ytake\PrestoClient\ResultsSession($client);
$result = $resultSession->execute()->yieldResults();
/** @var \Ytake\PrestoClient\QueryResult $row */
foreach ($result as $row) {
/** @var array $item */
foreach ($row->yieldDataArray() as $item) {
if (!is_null($item)) {
var_dump($item);
}
}
}
```

### Mapping Class

```php
<?php

class Testing
{
private $_key;

private $_value;
}

$client = new \Ytake\PrestoClient\StatementClient(
new \Ytake\PrestoClient\ClientSession('http://localhost:8080/', 'acme'),
'SELECT * FROM acme.acme.acme'
);
$resultSession = new \Ytake\PrestoClient\ResultsSession($client);
$result = $resultSession->execute()->yieldResults();
/** @var \Ytake\PrestoClient\QueryResult $row */
foreach ($result as $row) {
foreach($row->yieldObject(Testing::class) as $object) {
if ($object instanceof Testing) {
var_dump($object);
}
}
}
```

42 changes: 42 additions & 0 deletions src/QueryResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,48 @@ public function yieldData(): \Generator
}
}

/**
* @return \Generator
*/
public function yieldDataArray(): \Generator
{
if (!count($this->data)) {
yield;
}
$columns = array_map(function (Column $item) {
return $item->getName();
}, $this->getColumns());
foreach ($this->data as $data) {
yield array_combine($columns, $data);
}
}

/**
* @param string $fetchClassName
*
* @return \Generator
*/
public function yieldObject(string $fetchClassName)
{
if (!count($this->data)) {
yield;
}
$column = $this->getColumns();
$columnCount = count($column);
$reflectionClass = new \ReflectionClass($fetchClassName);
$newInstance = $reflectionClass->newInstanceWithoutConstructor();
foreach ($this->data as $data) {
for ($i = 0; $i < $columnCount; $i++) {
if ($reflectionClass->hasProperty($column[$i]->getName())) {
$property = $reflectionClass->getProperty($column[$i]->getName());
$property->setAccessible(true);
$property->setValue($newInstance, $data[$i]);
}
}
yield $newInstance;
}
}

/**
* @param string $content
*
Expand Down
59 changes: 35 additions & 24 deletions src/StatementClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,31 +187,8 @@ public function advance(): bool
return false;
}
$this->prepareRequest();
$start = microtime(true);
$cause = null;
$attempts = 0;
do {
if ($attempts > 0) {
usleep($attempts * 100);
}
$attempts++;
try {
$response = $this->client->get($nextUri);
if ($response->getStatusCode() === StatusCodeInterface::STATUS_OK) {
$this->queryResult->set($response->getBody()->getContents());

return true;
}
} catch (ClientException $e) {
$cause = $e;
if ($e->getCode() != StatusCodeInterface::STATUS_SERVICE_UNAVAILABLE) {
throw $this->requestFailedException("fetching next", $nextUri, $e->getResponse());
}
}
} while (((microtime(true) - $start) < $this->nanoseconds) && !$this->isClosed());

$this->gone = true;
throw new \RuntimeException('Error fetching next', 0, $cause);
return $this->detectResponse($nextUri);
}

/**
Expand Down Expand Up @@ -342,4 +319,38 @@ private function requestFailedException(

return new RequestFailedException('server error.');
}

/**
* @param string $nextUri
*
* @return bool
*/
private function detectResponse(string $nextUri): bool
{
$start = microtime(true);
$cause = null;
$attempts = 0;
do {
if ($attempts > 0) {
usleep($attempts * 100);
}
$attempts++;
try {
$response = $this->client->get($nextUri);
if ($response->getStatusCode() === StatusCodeInterface::STATUS_OK) {
$this->queryResult->set($response->getBody()->getContents());

return true;
}
} catch (ClientException $e) {
$cause = $e;
if ($e->getCode() != StatusCodeInterface::STATUS_SERVICE_UNAVAILABLE) {
throw $this->requestFailedException("fetching next", $nextUri, $e->getResponse());
}
}
} while (((microtime(true) - $start) < $this->nanoseconds) && !$this->isClosed());

$this->gone = true;
throw new \RuntimeException('Error fetching next', 0, $cause);
}
}
72 changes: 72 additions & 0 deletions tests/ResultsSessionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,66 @@ public function testShouldReturnQueryResultGenerator()
$resultSession = new ResultsSession($client);
$result = $resultSession->execute()->yieldResults();
$this->assertInstanceOf(\Generator::class, $result);
/** @var \Ytake\PrestoClient\QueryResult $row */
foreach ($result as $row) {
$this->assertInstanceOf(QueryResult::class, $row);
$this->assertInstanceOf(\Generator::class, $row->yieldData());
foreach ($row->yieldData() as $item) {
if (!is_null($item)) {
$this->assertInstanceOf(\Ytake\PrestoClient\FixData::class, $item);
}
}
}
}

public function testShouldReturnQueryResultWithDataArray()
{
$mock = new MockHandler([
new Response(200, [], file_get_contents(realpath(__DIR__ . '/data/success.json'))),
new Response(200, [], file_get_contents(realpath(__DIR__ . '/data/next_response.json'))),
new Response(204, [], file_get_contents(realpath(__DIR__ . '/data/third_response.json'))),
new Response(200, [], file_get_contents(realpath(__DIR__ . '/data/fourth_response.json'))),
]);
$client = new \Ytake\PrestoClient\StatementClient(
$this->session(),
'SELECT * FROM example.hoge.fuga',
new Client(['handler' => HandlerStack::create($mock)])
);
$resultSession = new ResultsSession($client);
$result = $resultSession->execute()->yieldResults();
foreach ($result as $row) {
foreach ($row->yieldDataArray() as $item) {
if (!is_null($item)) {
$this->assertInternalType('array', $item);
$this->assertArrayHasKey('test_id', $item);
}
}
}
}

public function testShouldBeExpectInstance()
{
$mock = new MockHandler([
new Response(200, [], file_get_contents(realpath(__DIR__ . '/data/success.json'))),
new Response(200, [], file_get_contents(realpath(__DIR__ . '/data/next_response.json'))),
new Response(204, [], file_get_contents(realpath(__DIR__ . '/data/third_response.json'))),
new Response(200, [], file_get_contents(realpath(__DIR__ . '/data/fourth_response.json'))),
]);
$client = new \Ytake\PrestoClient\StatementClient(
$this->session(),
'SELECT * FROM example.hoge.fuga',
new Client(['handler' => HandlerStack::create($mock)])
);
$resultSession = new ResultsSession($client);
$result = $resultSession->execute()->yieldResults();
/** @var \Ytake\PrestoClient\QueryResult $row */
foreach ($result as $row) {
foreach ($row->yieldObject(MockResultTest::class) as $item) {
if (!is_null($item)) {
$this->assertInstanceOf(MockResultTest::class, $item);
$this->assertSame(1, $item->testId());
}
}
}
}

Expand All @@ -62,3 +120,17 @@ private function session(): ClientSession
return new ClientSession('http://localhost', 'testing');
}
}

class MockResultTest
{
/** @var int */
private $test_id;

/**
* @return int
*/
public function testId(): int
{
return $this->test_id;
}
}

0 comments on commit 07ae7ad

Please sign in to comment.