From f804b21b6b1ac3bebb612d6c531c92851a5f1058 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 15 Nov 2021 17:18:25 +0100 Subject: [PATCH 1/4] Fix getServerVersion for OCI8 when assertions are disabled Signed-off-by: Alexander M. Turek --- src/Driver/OCI8/Connection.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Driver/OCI8/Connection.php b/src/Driver/OCI8/Connection.php index 1bc5c62cede..b05892f9666 100644 --- a/src/Driver/OCI8/Connection.php +++ b/src/Driver/OCI8/Connection.php @@ -78,7 +78,8 @@ public function getServerVersion() throw Error::new($this->dbh); } - assert(preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', $version, $matches) === 1); + $result = preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', $version, $matches); + assert($result === 1); return $matches[1]; } From 9f64c2b11d56f0f2d88d79305782d26f710b07f8 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Fri, 19 Nov 2021 17:52:42 -0800 Subject: [PATCH 2/4] Always cache the full result --- docs/en/reference/caching.rst | 24 +-- psalm.xml.dist | 5 - src/Cache/CachingResult.php | 185 ------------------ src/Connection.php | 35 ++-- ...ResultCacheTest.php => QueryCacheTest.php} | 29 +-- 5 files changed, 20 insertions(+), 258 deletions(-) delete mode 100644 src/Cache/CachingResult.php rename tests/Functional/{ResultCacheTest.php => QueryCacheTest.php} (94%) diff --git a/docs/en/reference/caching.rst b/docs/en/reference/caching.rst index e22f4aeb0c0..3f620ac9c33 100644 --- a/docs/en/reference/caching.rst +++ b/docs/en/reference/caching.rst @@ -1,7 +1,7 @@ Caching ======= -A ``Doctrine\DBAL\Statement`` can automatically cache result sets. The +A ``Doctrine\DBAL\Connection`` can automatically cache result sets. The feature is optional though, and by default, no result set is cached. To use the result cache, there are three mandatory steps: @@ -9,7 +9,6 @@ To use the result cache, there are three mandatory steps: 1. Configure a global result cache, or provide one at query time. 2. Provide a cache profile for the result set you want to cache when making a query. -3. Read the entire result set from the database. Configuring the result cache ---------------------------- @@ -53,24 +52,3 @@ default cache instance: executeCacheQuery($query, $params, $types, new QueryCacheProfile(0, "some key")); - $data = $stmt->fetchAllAssociative(); - -.. warning:: - - When using the cache layer not all fetch modes are supported. See - the code of the ``Doctrine\DBAL\Cache\CachingResult`` for - details. diff --git a/psalm.xml.dist b/psalm.xml.dist index 57e27061c50..4628c1fe9b7 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -46,11 +46,6 @@ is no longer supported. --> - - diff --git a/src/Cache/CachingResult.php b/src/Cache/CachingResult.php deleted file mode 100644 index 3f8698625f9..00000000000 --- a/src/Cache/CachingResult.php +++ /dev/null @@ -1,185 +0,0 @@ ->|null */ - private $data; - - /** - * @param string $cacheKey - * @param string $realKey - * @param int $lifetime - */ - public function __construct(Result $result, CacheItemPoolInterface $cache, $cacheKey, $realKey, $lifetime) - { - $this->result = $result; - $this->cache = $cache; - $this->cacheKey = $cacheKey; - $this->realKey = $realKey; - $this->lifetime = $lifetime; - } - - /** - * {@inheritdoc} - */ - public function fetchNumeric() - { - $row = $this->fetch(); - - if ($row === false) { - return false; - } - - return array_values($row); - } - - /** - * {@inheritdoc} - */ - public function fetchAssociative() - { - return $this->fetch(); - } - - /** - * {@inheritdoc} - */ - public function fetchOne() - { - return FetchUtils::fetchOne($this); - } - - /** - * {@inheritdoc} - */ - public function fetchAllNumeric(): array - { - return array_map('array_values', $this->fetchAllAssociative()); - } - - /** - * {@inheritdoc} - */ - public function fetchAllAssociative(): array - { - $data = $this->result->fetchAllAssociative(); - - $this->store($data); - - return $data; - } - - /** - * {@inheritdoc} - */ - public function fetchFirstColumn(): array - { - return FetchUtils::fetchFirstColumn($this); - } - - public function rowCount(): int - { - return $this->result->rowCount(); - } - - public function columnCount(): int - { - return $this->result->columnCount(); - } - - public function free(): void - { - $this->data = null; - } - - /** - * @return array|false - * - * @throws Exception - */ - private function fetch() - { - if ($this->data === null) { - $this->data = []; - } - - $row = $this->result->fetchAssociative(); - - if ($row !== false) { - $this->data[] = $row; - - return $row; - } - - $this->saveToCache(); - - return false; - } - - /** - * @param array> $data - */ - private function store(array $data): void - { - $this->data = $data; - - $this->saveToCache(); - } - - private function saveToCache(): void - { - if ($this->data === null) { - return; - } - - $item = $this->cache->getItem($this->cacheKey); - $data = $item->isHit() ? $item->get() : []; - $data[$this->realKey] = $this->data; - - $item->set($data); - if ($this->lifetime > 0) { - $item->expiresAfter($this->lifetime); - } - - $this->cache->save($item); - } -} diff --git a/src/Connection.php b/src/Connection.php index a1c68fa7a43..23f214e49dd 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -6,7 +6,6 @@ use Doctrine\Common\EventManager; use Doctrine\DBAL\Cache\ArrayResult; use Doctrine\DBAL\Cache\CacheException; -use Doctrine\DBAL\Cache\CachingResult; use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Driver\API\ExceptionConverter; use Doctrine\DBAL\Driver\Connection as DriverConnection; @@ -28,7 +27,6 @@ use Throwable; use Traversable; -use function array_key_exists; use function assert; use function count; use function get_class; @@ -1066,30 +1064,31 @@ public function executeCacheQuery($sql, $params, $types, QueryCacheProfile $qcp) [$cacheKey, $realKey] = $qcp->generateCacheKeys($sql, $params, $types, $connectionParams); - // fetch the row pointers entry $item = $resultCache->getItem($cacheKey); if ($item->isHit()) { - $data = $item->get(); - // is the real key part of this row pointers map or is the cache only pointing to other cache keys? - if (isset($data[$realKey])) { - $result = new ArrayResult($data[$realKey]); - } elseif (array_key_exists($realKey, $data)) { - $result = new ArrayResult([]); + $value = $item->get(); + if (isset($value[$realKey])) { + return new Result(new ArrayResult($value[$realKey]), $this); } + } else { + $value = []; } - if (! isset($result)) { - $result = new CachingResult( - $this->executeQuery($sql, $params, $types), - $resultCache, - $cacheKey, - $realKey, - $qcp->getLifetime() - ); + $data = $this->fetchAllAssociative($sql, $params, $types); + + $value[$realKey] = $data; + + $item->set($value); + + $lifetime = $qcp->getLifetime(); + if ($lifetime > 0) { + $item->expiresAfter($lifetime); } - return new Result($result, $this); + $resultCache->save($item); + + return new Result(new ArrayResult($data), $this); } /** diff --git a/tests/Functional/ResultCacheTest.php b/tests/Functional/QueryCacheTest.php similarity index 94% rename from tests/Functional/ResultCacheTest.php rename to tests/Functional/QueryCacheTest.php index 47459398592..b87a17a8638 100644 --- a/tests/Functional/ResultCacheTest.php +++ b/tests/Functional/QueryCacheTest.php @@ -19,7 +19,7 @@ use const CASE_LOWER; -class ResultCacheTest extends FunctionalTestCase +class QueryCacheTest extends FunctionalTestCase { /** @var list */ private $expectedResult = [ @@ -156,7 +156,7 @@ public function testFetchViaIteration(callable $fetch, callable $fetchAll): void self::assertEquals($data, $dataIterator); } - public function testFetchAndFinishSavesCache(): void + public function testFetchSavesCache(): void { $result = $this->connection->executeQuery( 'SELECT * FROM caching ORDER BY test_int ASC', @@ -179,31 +179,6 @@ public function testFetchAndFinishSavesCache(): void self::assertCount(1, $this->sqlLogger->queries, 'Only one query has hit the database.'); } - public function testDontFinishNoCache(): void - { - $result = $this->connection->executeQuery( - 'SELECT * FROM caching ORDER BY test_int ASC', - [], - [], - new QueryCacheProfile(0, 'testcachekey') - ); - - $result->fetchAssociative(); - - $result = $this->connection->executeQuery( - 'SELECT * FROM caching ORDER BY test_int ASC', - [], - [], - new QueryCacheProfile(0, 'testcachekey') - ); - - $this->hydrateViaIteration($result, static function (Result $result) { - return $result->fetchNumeric(); - }); - - self::assertCount(2, $this->sqlLogger->queries, 'Two queries have hit the database.'); - } - /** * @dataProvider fetchAllProvider */ From 00058636a4ac79a104165c7381adf44454d7810c Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Sat, 20 Nov 2021 15:19:04 -0800 Subject: [PATCH 3/4] Refactor query caching tests --- tests/Connection/CachedQueryTest.php | 103 ++++++ tests/Functional/QueryCacheTest.php | 494 --------------------------- 2 files changed, 103 insertions(+), 494 deletions(-) create mode 100644 tests/Connection/CachedQueryTest.php delete mode 100644 tests/Functional/QueryCacheTest.php diff --git a/tests/Connection/CachedQueryTest.php b/tests/Connection/CachedQueryTest.php new file mode 100644 index 00000000000..a3ca56f30ae --- /dev/null +++ b/tests/Connection/CachedQueryTest.php @@ -0,0 +1,103 @@ +assertCachedQueryIsExecutedOnceAndYieldsTheSameResult($cache, __FUNCTION__); + self::assertCount(1, $cache->getItem(__FUNCTION__)->get()); + } + + public function testCachedQueryLegacy(): void + { + if (! class_exists(ArrayCache::class)) { + self::markTestSkipped('This test requires the legacy ArrayCache class.'); + } + + $cache = new ArrayCache(); + $this->assertCachedQueryIsExecutedOnceAndYieldsTheSameResult($cache, __FUNCTION__); + + self::assertCount(1, $cache->fetch(__FUNCTION__)); + } + + public function testCachedQueryLegacyWrapped(): void + { + $cache = new ArrayAdapter(); + $legacy = DoctrineProvider::wrap($cache); + $this->assertCachedQueryIsExecutedOnceAndYieldsTheSameResult($legacy, __FUNCTION__); + + self::assertCount(1, $cache->getItem(__FUNCTION__)->get()); + } + + /** + * @param CacheItemPoolInterface|Cache $cache + */ + private function assertCachedQueryIsExecutedOnceAndYieldsTheSameResult(object $cache, string $cacheKey): void + { + $data = [['foo' => 'bar']]; + + $connection = $this->createConnection(1, $data); + $qcp = new QueryCacheProfile(0, $cacheKey, $cache); + + self::assertSame($data, $connection->executeCacheQuery('SELECT 1', [], [], $qcp)->fetchAllAssociative()); + self::assertSame($data, $connection->executeCacheQuery('SELECT 1', [], [], $qcp)->fetchAllAssociative()); + } + + public function testCachedQueryWithChangedImplementationIsExecutedTwice(): void + { + $data = [['baz' => 'qux']]; + + $connection = $this->createConnection(2, $data); + + self::assertSame($data, $connection->executeCacheQuery( + 'SELECT 1', + [], + [], + new QueryCacheProfile(0, __FUNCTION__, new ArrayAdapter()) + )->fetchAllAssociative()); + + self::assertSame($data, $connection->executeCacheQuery( + 'SELECT 1', + [], + [], + new QueryCacheProfile(0, __FUNCTION__, new ArrayAdapter()) + )->fetchAllAssociative()); + } + + /** + * @param list> $data + */ + private function createConnection(int $expectedQueryCount, array $data): Connection + { + $connection = $this->createMock(Driver\Connection::class); + $connection->expects(self::exactly($expectedQueryCount)) + ->method('query') + ->willReturnCallback(static function () use ($data): ArrayResult { + return new ArrayResult($data); + }); + + $driver = $this->createMock(Driver::class); + $driver->method('connect') + ->willReturn($connection); + + return new Connection([], $driver); + } +} diff --git a/tests/Functional/QueryCacheTest.php b/tests/Functional/QueryCacheTest.php deleted file mode 100644 index b87a17a8638..00000000000 --- a/tests/Functional/QueryCacheTest.php +++ /dev/null @@ -1,494 +0,0 @@ - */ - private $expectedResult = [ - ['test_int' => 100, 'test_string' => 'foo'], - ['test_int' => 200, 'test_string' => 'bar'], - ['test_int' => 300, 'test_string' => 'baz'], - ]; - - /** @var DebugStack */ - private $sqlLogger; - - protected function setUp(): void - { - $table = new Table('caching'); - $table->addColumn('test_int', 'integer'); - $table->addColumn('test_string', 'string', ['notnull' => false]); - $table->setPrimaryKey(['test_int']); - - $this->dropAndCreateTable($table); - - foreach ($this->expectedResult as $row) { - $this->connection->insert('caching', $row); - } - - $config = $this->connection->getConfiguration(); - $config->setSQLLogger($this->sqlLogger = new DebugStack()); - - $cache = new ArrayAdapter(); - $config->setResultCache($cache); - } - - protected function tearDown(): void - { - $this->connection->getSchemaManager()->dropTable('caching'); - } - - public function testCacheFetchAssociative(): void - { - $this->assertCacheNonCacheSelectSameFetchModeAreEqual( - $this->expectedResult, - static function (Result $result) { - return $result->fetchAssociative(); - } - ); - } - - public function testFetchNumeric(): void - { - $expectedResult = []; - foreach ($this->expectedResult as $v) { - $expectedResult[] = array_values($v); - } - - $this->assertCacheNonCacheSelectSameFetchModeAreEqual( - $expectedResult, - static function (Result $result) { - return $result->fetchNumeric(); - } - ); - } - - public function testFetchOne(): void - { - $expectedResult = []; - foreach ($this->expectedResult as $v) { - $expectedResult[] = array_shift($v); - } - - $this->assertCacheNonCacheSelectSameFetchModeAreEqual( - $expectedResult, - static function (Result $result) { - return $result->fetchOne(); - } - ); - } - - public function testMixingFetch(): void - { - $numExpectedResult = []; - foreach ($this->expectedResult as $v) { - $numExpectedResult[] = array_values($v); - } - - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching ORDER BY test_int ASC', - [], - [], - new QueryCacheProfile(0, 'testcachekey') - ); - - $data = $this->hydrateViaFetchAll($stmt, static function (Result $result) { - return $result->fetchAllAssociative(); - }); - - self::assertEquals($this->expectedResult, $data); - - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching ORDER BY test_int ASC', - [], - [], - new QueryCacheProfile(0, 'testcachekey') - ); - - $data = $this->hydrateViaFetchAll($stmt, static function (Result $result) { - return $result->fetchAllNumeric(); - }); - - self::assertEquals($numExpectedResult, $data); - } - - /** - * @dataProvider fetchProvider - */ - public function testFetchViaIteration(callable $fetch, callable $fetchAll): void - { - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching ORDER BY test_int ASC', - [], - [], - new QueryCacheProfile(0, 'testcachekey') - ); - - $data = $this->hydrateViaFetchAll($stmt, $fetchAll); - - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching ORDER BY test_int ASC', - [], - [], - new QueryCacheProfile(0, 'testcachekey') - ); - - $dataIterator = $this->hydrateViaIteration($stmt, $fetch); - - self::assertEquals($data, $dataIterator); - } - - public function testFetchSavesCache(): void - { - $result = $this->connection->executeQuery( - 'SELECT * FROM caching ORDER BY test_int ASC', - [], - [], - new QueryCacheProfile(0, 'testcachekey') - ); - - $result->fetchAllAssociative(); - - $result = $this->connection->executeQuery( - 'SELECT * FROM caching ORDER BY test_int ASC', - [], - [], - new QueryCacheProfile(0, 'testcachekey') - ); - - $result->fetchAllNumeric(); - - self::assertCount(1, $this->sqlLogger->queries, 'Only one query has hit the database.'); - } - - /** - * @dataProvider fetchAllProvider - */ - public function testFetchingAllRowsSavesCache(callable $fetchAll): void - { - $layerCache = new ArrayAdapter(); - - $result = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(0, 'testcachekey', $layerCache) - ); - - $fetchAll($result); - - self::assertCount(1, $layerCache->getItem('testcachekey')->get()); - } - - /** - * @dataProvider fetchAllProvider - */ - public function testFetchingAllRowsSavesCacheLegacy(callable $fetchAll): void - { - if (! class_exists(ArrayCache::class)) { - self::markTestSkipped('This test requires the legacy ArrayCache class.'); - } - - $layerCache = new ArrayCache(); - - $result = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(0, 'testcachekey', $layerCache) - ); - - $fetchAll($result); - - self::assertCount(1, $layerCache->fetch('testcachekey')); - } - - /** - * @dataProvider fetchAllProvider - */ - public function testFetchingAllRowsSavesCacheLegacyWrapped(callable $fetchAll): void - { - $arrayAdapter = new ArrayAdapter(); - $layerCache = DoctrineProvider::wrap($arrayAdapter); - - $result = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(0, 'testcachekey', $layerCache) - ); - - $fetchAll($result); - - self::assertCount(1, $arrayAdapter->getItem('testcachekey')->get()); - } - - /** - * @return iterable> - */ - public static function fetchAllProvider(): iterable - { - yield 'fetchAllAssociative' => [ - static function (Result $result): void { - $result->fetchAllAssociative(); - }, - ]; - - yield 'fetchAllNumeric' => [ - static function (Result $result): void { - $result->fetchAllNumeric(); - }, - ]; - - yield 'fetchFirstColumn' => [ - static function (Result $result): void { - $result->fetchFirstColumn(); - }, - ]; - } - - public function testFetchColumn(): void - { - $query = $this->connection->getDatabasePlatform() - ->getDummySelectSQL('1'); - - $qcp = new QueryCacheProfile(0, null, new ArrayAdapter()); - - $result = $this->connection->executeCacheQuery($query, [], [], $qcp); - $result->fetchFirstColumn(); - - $query = $this->connection->executeCacheQuery($query, [], [], $qcp); - - self::assertEquals([1], $query->fetchFirstColumn()); - } - - /** - * @param list $expectedResult - */ - private function assertCacheNonCacheSelectSameFetchModeAreEqual(array $expectedResult, callable $fetchMode): void - { - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching ORDER BY test_int ASC', - [], - [], - new QueryCacheProfile(0, 'testcachekey') - ); - - self::assertEquals(2, $stmt->columnCount()); - $data = $this->hydrateViaIteration($stmt, $fetchMode); - self::assertEquals($expectedResult, $data); - - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching ORDER BY test_int ASC', - [], - [], - new QueryCacheProfile(0, 'testcachekey') - ); - - self::assertEquals(2, $stmt->columnCount()); - $data = $this->hydrateViaIteration($stmt, $fetchMode); - self::assertEquals($expectedResult, $data); - self::assertCount(1, $this->sqlLogger->queries, 'Only one query has hit the database.'); - } - - public function testEmptyResultCache(): void - { - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(10, 'emptycachekey') - ); - - $this->hydrateViaIteration($stmt, static function (Result $result) { - return $result->fetchAssociative(); - }); - - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(10, 'emptycachekey') - ); - - $this->hydrateViaIteration($stmt, static function (Result $result) { - return $result->fetchAssociative(); - }); - - self::assertCount(1, $this->sqlLogger->queries, 'Only one query has hit the database.'); - } - - public function testChangeCacheImpl(): void - { - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(10, 'emptycachekey') - ); - - $this->hydrateViaIteration($stmt, static function (Result $result) { - return $result->fetchAssociative(); - }); - - $secondCache = new ArrayAdapter(); - - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(10, 'emptycachekey', $secondCache) - ); - - $this->hydrateViaIteration($stmt, static function (Result $result) { - return $result->fetchAssociative(); - }); - - self::assertCount(2, $this->sqlLogger->queries, 'Two queries have hit the database.'); - self::assertCount(1, $secondCache->getItem('emptycachekey')->get()); - } - - public function testChangeCacheImplLegacy(): void - { - if (! class_exists(ArrayCache::class)) { - self::markTestSkipped('This test requires the legacy ArrayCache class.'); - } - - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(10, 'emptycachekey') - ); - - $this->hydrateViaIteration($stmt, static function (Result $result) { - return $result->fetchAssociative(); - }); - - $secondCache = new ArrayCache(); - - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(10, 'emptycachekey', $secondCache) - ); - - $this->hydrateViaIteration($stmt, static function (Result $result) { - return $result->fetchAssociative(); - }); - - self::assertCount(2, $this->sqlLogger->queries, 'Two queries have hit the database.'); - self::assertCount(1, $secondCache->fetch('emptycachekey')); - } - - public function testChangeCacheImplLegacyWrapped(): void - { - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(10, 'emptycachekey') - ); - - $this->hydrateViaIteration($stmt, static function (Result $result) { - return $result->fetchAssociative(); - }); - - $arrayAdapter = new ArrayAdapter(); - $secondCache = DoctrineProvider::wrap($arrayAdapter); - - $stmt = $this->connection->executeQuery( - 'SELECT * FROM caching WHERE test_int > 500', - [], - [], - new QueryCacheProfile(10, 'emptycachekey', $secondCache) - ); - - $this->hydrateViaIteration($stmt, static function (Result $result) { - return $result->fetchAssociative(); - }); - - self::assertCount(2, $this->sqlLogger->queries, 'Two queries have hit the database.'); - self::assertCount(1, $arrayAdapter->getItem('emptycachekey')->get()); - } - - /** - * @return iterable> - */ - public static function fetchProvider(): iterable - { - yield 'associative' => [ - static function (Result $result) { - return $result->fetchAssociative(); - }, - static function (Result $result) { - return $result->fetchAllAssociative(); - }, - ]; - - yield 'numeric' => [ - static function (Result $result) { - return $result->fetchNumeric(); - }, - static function (Result $result) { - return $result->fetchAllNumeric(); - }, - ]; - - yield 'column' => [ - static function (Result $result) { - return $result->fetchOne(); - }, - static function (Result $result) { - return $result->fetchFirstColumn(); - }, - ]; - } - - /** - * @return array - */ - private function hydrateViaFetchAll(Result $result, callable $fetchAll): array - { - $data = []; - - foreach ($fetchAll($result) as $row) { - $data[] = is_array($row) ? array_change_key_case($row, CASE_LOWER) : $row; - } - - return $data; - } - - /** - * @return array - */ - private function hydrateViaIteration(Result $result, callable $fetch): array - { - $data = []; - - while (($row = $fetch($result)) !== false) { - $data[] = is_array($row) ? array_change_key_case($row, CASE_LOWER) : $row; - } - - return $data; - } -} From afbf9472b06b35971139b7739fc11470e5e9489b Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sun, 21 Nov 2021 04:00:48 +0100 Subject: [PATCH 4/4] PHPStan 1.2.0, Psalm 4.13.0 --- composer.json | 4 ++-- psalm.xml.dist | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 746c2c8977d..6ca2f814f2b 100644 --- a/composer.json +++ b/composer.json @@ -41,13 +41,13 @@ "require-dev": { "doctrine/coding-standard": "9.0.0", "jetbrains/phpstorm-stubs": "2021.1", - "phpstan/phpstan": "1.1.1", + "phpstan/phpstan": "1.2.0", "phpunit/phpunit": "^7.5.20|^8.5|9.5.10", "psalm/plugin-phpunit": "0.16.1", "squizlabs/php_codesniffer": "3.6.1", "symfony/cache": "^4.4", "symfony/console": "^2.0.5|^3.0|^4.0|^5.0", - "vimeo/psalm": "4.12.0" + "vimeo/psalm": "4.13.0" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." diff --git a/psalm.xml.dist b/psalm.xml.dist index bc69c1da9c4..35aafa3532a 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -360,12 +360,6 @@ - - - - - -