From 3de10b3e694bce4a9baa37a36a0dae2ab19a049e Mon Sep 17 00:00:00 2001 From: Marco Pfeiffer Date: Sun, 22 Mar 2020 20:45:32 +0100 Subject: [PATCH] fix failure when setting fetch mode before execute --- src/RdsDataStatement.php | 17 +++++- tests/RdsDataConnectionTest.php | 87 ++++++++++++----------------- tests/RdsDataServiceClientTrait.php | 44 +++++++++++++++ tests/RdsDataStatementTest.php | 56 +++++++++++++++++++ 4 files changed, 153 insertions(+), 51 deletions(-) create mode 100644 tests/RdsDataServiceClientTrait.php create mode 100644 tests/RdsDataStatementTest.php diff --git a/src/RdsDataStatement.php b/src/RdsDataStatement.php index b478e43..28c226e 100644 --- a/src/RdsDataStatement.php +++ b/src/RdsDataStatement.php @@ -5,6 +5,7 @@ use Aws\RDSDataService\Exception\RDSDataServiceException; use Doctrine\DBAL\Driver\Statement; +use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; /** @@ -42,6 +43,13 @@ class RdsDataStatement implements \IteratorAggregate, Statement */ private $sql; + /** + * Retain the fetch mode across results + * + * @var array + */ + private $fetchMode = [FetchMode::MIXED]; + /** * @var RdsDataResult */ @@ -78,7 +86,13 @@ public function columnCount(): int */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null): bool { - return $this->result->setFetchMode($fetchMode, $arg2, $arg3); + $this->fetchMode = func_get_args(); + + if ($this->result !== null) { + $this->result->setFetchMode(...$this->fetchMode); + } + + return true; } /** @@ -196,6 +210,7 @@ public function execute($params = null): bool } $this->result = new RdsDataResult($result, $this->dataConverter); + $this->result->setFetchMode(...$this->fetchMode); return true; } catch (RDSDataServiceException $exception) { if ($exception->getAwsErrorCode() === 'BadRequestException') { diff --git a/tests/RdsDataConnectionTest.php b/tests/RdsDataConnectionTest.php index 1e0fc87..4f253bb 100644 --- a/tests/RdsDataConnectionTest.php +++ b/tests/RdsDataConnectionTest.php @@ -3,62 +3,25 @@ namespace Nemo64\DbalRdsData\Tests; -use Aws\RDSDataService\RDSDataServiceClient; -use Aws\Result; use Doctrine\DBAL\FetchMode; -use Nemo64\DbalRdsData\RdsDataConnection; use PHPUnit\Framework\TestCase; class RdsDataConnectionTest extends TestCase { - private const DEFAULT_OPTIONS = [ - 'resourceArn' => 'resource_arm', - 'secretArn' => 'secret_arm', - ]; - - /** - * @var \PHPUnit\Framework\MockObject\MockObject|RDSDataServiceClient - */ - private $client; - - private $expectedCalls = [ - // ['executeStatement', ['options' => 'value'], 'returnValue'] - ]; - - /** - * @var RdsDataConnection - */ - private $connection; + use RdsDataServiceClientTrait; protected function setUp() { - $this->client = $this->createMock(RDSDataServiceClient::class); - $this->client->method('__call')->willReturnCallback(function ($methodName, $arguments) { - $nextCall = array_shift($this->expectedCalls); - $this->assertIsArray($nextCall, "there must be another call planned"); - $this->assertEquals($nextCall[0], $methodName, "method call"); - $this->assertEquals($nextCall[1], $arguments[0], "options of $methodName"); - return $nextCall[2]; - }); - - $this->connection = new RdsDataConnection( - $this->client, - self::DEFAULT_OPTIONS['resourceArn'], - self::DEFAULT_OPTIONS['secretArn'], - 'db' - ); - } - - private function addClientCall(string $method, array $options, array $result) - { - $this->expectedCalls[] = [$method, $options, new Result($result)]; + $this->createRdsDataServiceClient(); } public function testSimpleQuery() { $this->addClientCall( 'executeStatement', - self::DEFAULT_OPTIONS + [ + [ + 'resourceArn' => 'arn:resource', + 'secretArn' => 'arn:secret', 'database' => 'db', 'continueAfterTimeout' => false, 'includeResultMetadata' => true, @@ -88,7 +51,11 @@ public function testTransaction() { $this->addClientCall( 'beginTransaction', - self::DEFAULT_OPTIONS + ['database' => 'db'], + [ + 'resourceArn' => 'arn:resource', + 'secretArn' => 'arn:secret', + 'database' => 'db', + ], ['transactionId' => '~~transaction id~~'] ); $this->assertTrue($this->connection->beginTransaction()); @@ -96,7 +63,9 @@ public function testTransaction() $this->addClientCall( 'executeStatement', - self::DEFAULT_OPTIONS + [ + [ + 'resourceArn' => 'arn:resource', + 'secretArn' => 'arn:secret', 'database' => 'db', 'continueAfterTimeout' => false, 'includeResultMetadata' => true, @@ -125,7 +94,11 @@ public function testTransaction() $this->addClientCall( 'commitTransaction', - self::DEFAULT_OPTIONS + ['transactionId' => '~~transaction id~~'], + [ + 'resourceArn' => 'arn:resource', + 'secretArn' => 'arn:secret', + 'transactionId' => '~~transaction id~~', + ], ['transactionStatus' => 'cleaning up'] ); $this->assertTrue($this->connection->commit()); @@ -137,7 +110,11 @@ public function testRollBack() { $this->addClientCall( 'beginTransaction', - self::DEFAULT_OPTIONS + ['database' => 'db'], + [ + 'resourceArn' => 'arn:resource', + 'secretArn' => 'arn:secret', + 'database' => 'db', + ], ['transactionId' => '~~transaction id~~'] ); $this->assertTrue($this->connection->beginTransaction()); @@ -146,7 +123,11 @@ public function testRollBack() $this->addClientCall( 'rollbackTransaction', - self::DEFAULT_OPTIONS + ['transactionId' => '~~transaction id~~'], + [ + 'resourceArn' => 'arn:resource', + 'secretArn' => 'arn:secret', + 'transactionId' => '~~transaction id~~', + ], ['transactionStatus' => 'cleaning up'] ); $this->assertTrue($this->connection->rollBack()); @@ -158,7 +139,9 @@ public function testUpdate() { $this->addClientCall( 'executeStatement', - self::DEFAULT_OPTIONS + [ + [ + 'resourceArn' => 'arn:resource', + 'secretArn' => 'arn:secret', 'database' => 'db', 'continueAfterTimeout' => false, 'includeResultMetadata' => true, @@ -179,7 +162,9 @@ public function testParameters() { $this->addClientCall( 'executeStatement', - self::DEFAULT_OPTIONS + [ + [ + 'resourceArn' => 'arn:resource', + 'secretArn' => 'arn:secret', 'database' => 'db', 'continueAfterTimeout' => false, 'includeResultMetadata' => true, @@ -222,7 +207,9 @@ public function testInsert() $this->addClientCall( 'executeStatement', - self::DEFAULT_OPTIONS + [ + [ + 'resourceArn' => 'arn:resource', + 'secretArn' => 'arn:secret', 'database' => 'db', 'continueAfterTimeout' => false, 'includeResultMetadata' => true, diff --git a/tests/RdsDataServiceClientTrait.php b/tests/RdsDataServiceClientTrait.php new file mode 100644 index 0000000..ad8fab8 --- /dev/null +++ b/tests/RdsDataServiceClientTrait.php @@ -0,0 +1,44 @@ + 'value'], 'returnValue'] + ]; + + /** + * @var RdsDataConnection + */ + private $connection; + + protected function createRdsDataServiceClient() + { + $this->client = $this->createMock(RDSDataServiceClient::class); + $this->client->method('__call')->willReturnCallback(function ($methodName, $arguments) { + $nextCall = array_shift($this->expectedCalls); + $this->assertIsArray($nextCall, "there must be another call planned"); + $this->assertEquals($nextCall[0], $methodName, "method call"); + $this->assertEquals($nextCall[1], $arguments[0], "options of $methodName"); + return $nextCall[2]; + }); + + $this->connection = new RdsDataConnection($this->client, 'arn:resource', 'arn:secret', 'db'); + } + + private function addClientCall(string $method, array $options, array $result) + { + $this->expectedCalls[] = [$method, $options, new Result($result)]; + } +} diff --git a/tests/RdsDataStatementTest.php b/tests/RdsDataStatementTest.php new file mode 100644 index 0000000..8c6bf49 --- /dev/null +++ b/tests/RdsDataStatementTest.php @@ -0,0 +1,56 @@ +createRdsDataServiceClient(); + } + + public function testRetainFetchMode() + { + foreach (range(1, 2) as $item) { + $this->addClientCall( + 'executeStatement', + [ + 'resourceArn' => 'arn:resource', + 'secretArn' => 'arn:secret', + 'database' => 'db', + 'continueAfterTimeout' => false, + 'includeResultMetadata' => true, + 'parameters' => [], + 'resultSetOptions' => ['decimalReturnType' => 'STRING'], + 'sql' => 'SELECT 1 AS id', + ], + [ + "columnMetadata" => [ + ["label" => "id"], + ], + "numberOfRecordsUpdated" => 0, + "records" => [ + [ + ["longValue" => 1], + ], + ], + ] + ); + } + + $statement = new RdsDataStatement($this->connection, 'SELECT 1 AS id'); + + $statement->setFetchMode(FetchMode::NUMERIC); + $statement->execute(); + $this->assertEquals([[1]], $statement->fetchAll()); + $statement->execute(); + $this->assertEquals([[1]], $statement->fetchAll()); + } +}