From 0d4e1a8b29dd987704842f0465aded378f441dca Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Sun, 20 Sep 2020 16:17:48 -0700 Subject: [PATCH 1/8] Release 2.11.0 --- .doctrine-project.json | 20 +++-- README.md | 26 +++--- composer.json | 3 +- composer.lock | 150 +++++++++++++++++++++++++++++++++- lib/Doctrine/DBAL/Version.php | 2 +- 5 files changed, 177 insertions(+), 24 deletions(-) diff --git a/.doctrine-project.json b/.doctrine-project.json index 7b97cb45129..f68f2fd0bc3 100644 --- a/.doctrine-project.json +++ b/.doctrine-project.json @@ -11,21 +11,27 @@ "slug": "latest", "upcoming": true }, + { + "name": "2.11", + "branchName": "2.11.x", + "slug": "2.11", + "current": true, + "aliases": [ + "current", + "stable" + ] + }, { "name": "2.10", - "branchName": "master", + "branchName": "2.10.x", "slug": "2.10", - "upcoming": true + "maintained": false }, { "name": "2.9", "branchName": "2.9", "slug": "2.9", - "current": true, - "aliases": [ - "current", - "stable" - ] + "maintained": false }, { "name": "2.8", diff --git a/README.md b/README.md index 5a3582b8951..8f21ee0b5b5 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Doctrine DBAL -| [Master][Master] | [2.10][2.10] | +| [Master][Master] | [2.11][2.11] | |:----------------:|:----------:| -| [![Build status][Master image]][Master] | [![Build status][2.10 image]][2.10] | -| [![GitHub Actions][GA master image]][GA master] | [![GitHub Actions][GA 2.10 image]][GA 2.10] | -| [![AppVeyor][AppVeyor master image]][AppVeyor master] | [![AppVeyor][AppVeyor 2.10 image]][AppVeyor 2.10] | -| [![Code Coverage][Coverage image]][CodeCov Master] | [![Code Coverage][Coverage 2.10 image]][CodeCov 2.10] | +| [![Build status][Master image]][Master] | [![Build status][2.11 image]][2.11] | +| [![GitHub Actions][GA master image]][GA master] | [![GitHub Actions][GA 2.11 image]][GA 2.11] | +| [![AppVeyor][AppVeyor master image]][AppVeyor master] | [![AppVeyor][AppVeyor 2.11 image]][AppVeyor 2.11] | +| [![Code Coverage][Coverage image]][CodeCov Master] | [![Code Coverage][Coverage 2.11 image]][CodeCov 2.11] | Powerful database abstraction layer with many features for database schema introspection, schema management and PDO abstraction. @@ -24,11 +24,11 @@ Powerful database abstraction layer with many features for database schema intro [GA master]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3Amaster [GA master image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg - [2.10 image]: https://img.shields.io/travis/doctrine/dbal/2.10.x.svg?style=flat-square - [Coverage 2.10 image]: https://codecov.io/gh/doctrine/dbal/branch/2.10.x/graph/badge.svg - [2.10]: https://github.com/doctrine/dbal/tree/2.10.x - [CodeCov 2.10]: https://codecov.io/gh/doctrine/dbal/branch/2.10.x - [AppVeyor 2.10]: https://ci.appveyor.com/project/doctrine/dbal/branch/2.10.x - [AppVeyor 2.10 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/2.10.x?svg=true - [GA 2.10]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A2.10.x - [GA 2.10 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=2.10.x + [2.11 image]: https://img.shields.io/travis/doctrine/dbal/2.11.x.svg?style=flat-square + [Coverage 2.11 image]: https://codecov.io/gh/doctrine/dbal/branch/2.11.x/graph/badge.svg + [2.11]: https://github.com/doctrine/dbal/tree/2.11.x + [CodeCov 2.11]: https://codecov.io/gh/doctrine/dbal/branch/2.11.x + [AppVeyor 2.11]: https://ci.appveyor.com/project/doctrine/dbal/branch/2.11.x + [AppVeyor 2.11 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/2.11.x?svg=true + [GA 2.11]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A2.11.x + [GA 2.11 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=2.11.x diff --git a/composer.json b/composer.json index 28b74a542d8..e3c26687995 100644 --- a/composer.json +++ b/composer.json @@ -65,8 +65,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.10.x-dev", - "dev-develop": "3.0.x-dev" + "dev-master": "4.0.x-dev" } } } diff --git a/composer.lock b/composer.lock index a826b9c29e3..c0e3434b50c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a197851427d005342e778cba6dbffd04", + "content-hash": "2a7bb91be55d10f401c5f03dd7f235bc", "packages": [ { "name": "doctrine/cache", @@ -78,6 +78,10 @@ "cache", "caching" ], + "support": { + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/v1.7.1" + }, "time": "2017-08-25T07:02:50+00:00" }, { @@ -152,6 +156,10 @@ "eventdispatcher", "eventmanager" ], + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/master" + }, "time": "2018-06-11T11:59:03+00:00" } ], @@ -232,6 +240,11 @@ "non-blocking", "promise" ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/master" + }, "funding": [ { "url": "https://github.com/amphp", @@ -304,6 +317,11 @@ "non-blocking", "stream" ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/master" + }, "time": "2020-06-29T18:35:05+00:00" }, { @@ -359,6 +377,10 @@ } ], "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "support": { + "issues": "https://github.com/composer/package-versions-deprecated/issues", + "source": "https://github.com/composer/package-versions-deprecated/tree/1.10.99.1" + }, "funding": [ { "url": "https://packagist.com", @@ -434,6 +456,11 @@ "validation", "versioning" ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/1.5.1" + }, "time": "2020-01-13T12:06:48+00:00" }, { @@ -478,6 +505,11 @@ "Xdebug", "performance" ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/1.4.3" + }, "funding": [ { "url": "https://packagist.com", @@ -558,6 +590,10 @@ "stylecheck", "tests" ], + "support": { + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + }, "time": "2020-06-25T14:57:39+00:00" }, { @@ -614,6 +650,10 @@ "standard", "style" ], + "support": { + "issues": "https://github.com/doctrine/coding-standard/issues", + "source": "https://github.com/doctrine/coding-standard/tree/8.1.x" + }, "time": "2020-07-05T20:35:22+00:00" }, { @@ -729,6 +769,10 @@ } ], "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", + "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/master" + }, "time": "2020-03-11T15:21:41+00:00" }, { @@ -776,6 +820,10 @@ "php", "server" ], + "support": { + "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.4.0" + }, "time": "2019-06-23T21:03:50+00:00" }, { @@ -820,6 +868,9 @@ "stubs", "type" ], + "support": { + "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" + }, "time": "2019-12-05T16:56:26+00:00" }, { @@ -924,6 +975,11 @@ } ], "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/master" + }, "time": "2020-04-16T18:48:43+00:00" }, { @@ -976,6 +1032,10 @@ "parser", "php" ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/master" + }, "time": "2020-08-18T19:48:01+00:00" }, { @@ -1025,6 +1085,10 @@ "xml", "xml conversion" ], + "support": { + "issues": "https://github.com/nullivex/lib-array2xml/issues", + "source": "https://github.com/nullivex/lib-array2xml/tree/master" + }, "time": "2019-03-29T20:06:56+00:00" }, { @@ -1185,6 +1249,10 @@ "reflection", "static analysis" ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, "time": "2020-06-27T09:03:43+00:00" }, { @@ -1237,6 +1305,10 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + }, "time": "2020-08-15T11:14:08+00:00" }, { @@ -1282,6 +1354,10 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.x" + }, "time": "2020-06-27T10:12:23+00:00" }, { @@ -1398,6 +1474,10 @@ "MIT" ], "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/master" + }, "time": "2020-04-13T16:28:46+00:00" }, { @@ -1929,6 +2009,10 @@ } ], "description": "Psalm plugin for PHPUnit", + "support": { + "issues": "https://github.com/psalm/psalm-plugin-phpunit/issues", + "source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.10.1" + }, "time": "2020-05-24T20:30:10+00:00" }, { @@ -1978,6 +2062,10 @@ "container-interop", "psr" ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/master" + }, "time": "2017-02-14T16:28:37+00:00" }, { @@ -2025,6 +2113,9 @@ "psr", "psr-3" ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.3" + }, "time": "2020-03-23T09:12:05+00:00" }, { @@ -2980,6 +3071,10 @@ "MIT" ], "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "support": { + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/6.3.10" + }, "funding": [ { "url": "https://github.com/kukulich", @@ -3041,6 +3136,11 @@ "phpcs", "standards" ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, "time": "2020-04-17T01:09:41+00:00" }, { @@ -3117,6 +3217,23 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/console/tree/v4.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-30T11:41:10+00:00" }, { @@ -3173,6 +3290,9 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug/tree/4.0" + }, "time": "2018-02-28T21:50:02+00:00" }, { @@ -3235,6 +3355,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.18.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3308,6 +3431,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/master" + }, "time": "2019-11-27T14:18:11+00:00" }, { @@ -3366,6 +3492,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.13.0" + }, "time": "2019-11-27T16:25:15+00:00" }, { @@ -3424,6 +3553,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v1.1.8" + }, "time": "2019-10-14T12:27:06+00:00" }, { @@ -3571,6 +3703,10 @@ "inspection", "php" ], + "support": { + "issues": "https://github.com/vimeo/psalm/issues", + "source": "https://github.com/vimeo/psalm/tree/3.14.2" + }, "time": "2020-08-22T14:01:26+00:00" }, { @@ -3620,6 +3756,10 @@ "check", "validate" ], + "support": { + "issues": "https://github.com/webmozart/assert/issues", + "source": "https://github.com/webmozart/assert/tree/master" + }, "time": "2020-07-08T17:02:28+00:00" }, { @@ -3667,6 +3807,10 @@ } ], "description": "A PHP implementation of Ant's glob.", + "support": { + "issues": "https://github.com/webmozart/glob/issues", + "source": "https://github.com/webmozart/glob/tree/master" + }, "time": "2015-12-29T11:14:33+00:00" }, { @@ -3713,6 +3857,10 @@ } ], "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", + "support": { + "issues": "https://github.com/webmozart/path-util/issues", + "source": "https://github.com/webmozart/path-util/tree/2.3.0" + }, "time": "2015-12-17T08:42:14+00:00" } ], diff --git a/lib/Doctrine/DBAL/Version.php b/lib/Doctrine/DBAL/Version.php index 454a28884e6..cc4069ee9d2 100644 --- a/lib/Doctrine/DBAL/Version.php +++ b/lib/Doctrine/DBAL/Version.php @@ -17,7 +17,7 @@ class Version /** * Current Doctrine Version. */ - public const VERSION = '2.11.0-DEV'; + public const VERSION = '2.11.0'; /** * Compares a Doctrine version with the current one. From 5d2282389438138b91b31742f7b7f4779e1a2122 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Sun, 20 Sep 2020 16:53:37 -0700 Subject: [PATCH 2/8] Bump version to 2.11.1-DEV --- lib/Doctrine/DBAL/Version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Doctrine/DBAL/Version.php b/lib/Doctrine/DBAL/Version.php index cc4069ee9d2..0acc959aeaf 100644 --- a/lib/Doctrine/DBAL/Version.php +++ b/lib/Doctrine/DBAL/Version.php @@ -17,7 +17,7 @@ class Version /** * Current Doctrine Version. */ - public const VERSION = '2.11.0'; + public const VERSION = '2.11.1-DEV'; /** * Compares a Doctrine version with the current one. From 7ca934c979d9cf8908084d40958b1130d9583a63 Mon Sep 17 00:00:00 2001 From: Quentin Dequippe Date: Tue, 22 Sep 2020 17:34:28 +0200 Subject: [PATCH 3/8] Fix phpdoc of deprecated Remove "All" for some deprecated phpdoc --- lib/Doctrine/DBAL/Connection.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Doctrine/DBAL/Connection.php b/lib/Doctrine/DBAL/Connection.php index 82ef5d80170..af803e5db26 100644 --- a/lib/Doctrine/DBAL/Connection.php +++ b/lib/Doctrine/DBAL/Connection.php @@ -541,7 +541,7 @@ public function setFetchMode($fetchMode) * Prepares and executes an SQL query and returns the first row of the result * as an associative array. * - * @deprecated Use fetchAllAssociative() + * @deprecated Use fetchAssociative() * * @param string $sql The query SQL * @param mixed[] $params The query parameters @@ -560,7 +560,7 @@ public function fetchAssoc($sql, array $params = [], array $types = []) * Prepares and executes an SQL query and returns the first row of the result * as a numerically indexed array. * - * @deprecated Use fetchAllNumeric() + * @deprecated Use fetchNumeric() * * @param string $sql The query SQL * @param mixed[] $params The query parameters From 8557a3227a5ecdfee613671040048e3a91e9b140 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Tue, 22 Sep 2020 15:06:04 -0700 Subject: [PATCH 4/8] Restore PDOStatement::quote() for backward compatibility --- lib/Doctrine/DBAL/Driver/PDOConnection.php | 9 +++++++++ phpcs.xml.dist | 5 +++++ .../DBAL/Functional/Driver/PDO/ConnectionTest.php | 10 ++++++++++ 3 files changed, 24 insertions(+) diff --git a/lib/Doctrine/DBAL/Driver/PDOConnection.php b/lib/Doctrine/DBAL/Driver/PDOConnection.php index 43b8280ef70..8409952cb4e 100644 --- a/lib/Doctrine/DBAL/Driver/PDOConnection.php +++ b/lib/Doctrine/DBAL/Driver/PDOConnection.php @@ -5,6 +5,7 @@ use Doctrine\DBAL\Driver\Connection as ConnectionInterface; use Doctrine\DBAL\Driver\PDO\Exception; use Doctrine\DBAL\Driver\PDO\Statement; +use Doctrine\DBAL\ParameterType; use PDO; use PDOException; use PDOStatement; @@ -101,6 +102,14 @@ public function query() } } + /** + * {@inheritdoc} + */ + public function quote($value, $type = ParameterType::STRING) + { + return parent::quote($value, $type); + } + /** * {@inheritdoc} */ diff --git a/phpcs.xml.dist b/phpcs.xml.dist index c82ca439eca..8c6b82da6b0 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -110,6 +110,11 @@ lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php + + + lib/Doctrine/DBAL/Driver/PDOConnection.php + + lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php diff --git a/tests/Doctrine/Tests/DBAL/Functional/Driver/PDO/ConnectionTest.php b/tests/Doctrine/Tests/DBAL/Functional/Driver/PDO/ConnectionTest.php index f54cb07b06a..c9f748fbce6 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Driver/PDO/ConnectionTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Driver/PDO/ConnectionTest.php @@ -1,5 +1,7 @@ driverConnection->query('foo'); } + + /** + * This test ensures backward compatibility with DBAL 2.x and should be removed in 3.0. + */ + public function testQuoteInteger(): void + { + self::assertSame("'1'", $this->connection->getWrappedConnection()->quote(1)); + } } From 0325f424ae9d85d5085b6ebe13bae13c84bea9cb Mon Sep 17 00:00:00 2001 From: Benjamin Morel Date: Tue, 22 Sep 2020 23:51:37 +0200 Subject: [PATCH 5/8] Fix BC break Ignore empty strings in QueryBuilder::and/orWhere() & and/orHaving(). --- lib/Doctrine/DBAL/Query/QueryBuilder.php | 5 + .../Tests/DBAL/Query/QueryBuilderTest.php | 100 ++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/lib/Doctrine/DBAL/Query/QueryBuilder.php b/lib/Doctrine/DBAL/Query/QueryBuilder.php index 6c4aa6ef029..a1306754836 100644 --- a/lib/Doctrine/DBAL/Query/QueryBuilder.php +++ b/lib/Doctrine/DBAL/Query/QueryBuilder.php @@ -8,6 +8,7 @@ use Doctrine\DBAL\Query\Expression\CompositeExpression; use Doctrine\DBAL\Query\Expression\ExpressionBuilder; +use function array_filter; use function array_key_exists; use function array_keys; use function array_unshift; @@ -829,6 +830,7 @@ public function where($predicates) public function andWhere($where) { $args = func_get_args(); + $args = array_filter($args); // https://github.com/doctrine/dbal/issues/4282 $where = $this->getQueryPart('where'); if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) { @@ -862,6 +864,7 @@ public function andWhere($where) public function orWhere($where) { $args = func_get_args(); + $args = array_filter($args); // https://github.com/doctrine/dbal/issues/4282 $where = $this->getQueryPart('where'); if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) { @@ -1010,6 +1013,7 @@ public function having($having) public function andHaving($having) { $args = func_get_args(); + $args = array_filter($args); // https://github.com/doctrine/dbal/issues/4282 $having = $this->getQueryPart('having'); if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) { @@ -1033,6 +1037,7 @@ public function andHaving($having) public function orHaving($having) { $args = func_get_args(); + $args = array_filter($args); // https://github.com/doctrine/dbal/issues/4282 $having = $this->getQueryPart('having'); if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) { diff --git a/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php b/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php index bc671787877..038097c8910 100644 --- a/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php +++ b/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php @@ -949,4 +949,104 @@ public function testJoinWithNonUniqueAliasThrowsException(): void $qb->getSQL(); } + + public function testAndWhereEmptyStringStartingWithEmptyExpression(): void + { + $qb = new QueryBuilder($this->conn); + + $qb->select('id') + ->from('foo'); + + $qb->andWhere('', 'a = b'); + + self::assertSame('SELECT id FROM foo WHERE a = b', $qb->getSQL()); + } + + public function testAndWhereEmptyStringStartingWithNonEmptyExpression(): void + { + $qb = new QueryBuilder($this->conn); + + $qb->select('id') + ->from('foo') + ->where('a = b'); + + $qb->andWhere('', 'c = d'); + + self::assertSame('SELECT id FROM foo WHERE (a = b) AND (c = d)', $qb->getSQL()); + } + + public function testOrWhereEmptyStringStartingWithEmptyExpression(): void + { + $qb = new QueryBuilder($this->conn); + + $qb->select('id') + ->from('foo'); + + $qb->orWhere('', 'a = b'); + + self::assertSame('SELECT id FROM foo WHERE a = b', $qb->getSQL()); + } + + public function testOrWhereEmptyStringStartingWithNonEmptyExpression(): void + { + $qb = new QueryBuilder($this->conn); + + $qb->select('id') + ->from('foo') + ->where('a = b'); + + $qb->orWhere('', 'c = d'); + + self::assertSame('SELECT id FROM foo WHERE (a = b) OR (c = d)', $qb->getSQL()); + } + + public function testAndHavingEmptyStringStartingWithEmptyExpression(): void + { + $qb = new QueryBuilder($this->conn); + + $qb->select('id') + ->from('foo'); + + $qb->andHaving('', 'a = b'); + + self::assertSame('SELECT id FROM foo HAVING a = b', $qb->getSQL()); + } + + public function testAndHavingEmptyStringStartingWithNonEmptyExpression(): void + { + $qb = new QueryBuilder($this->conn); + + $qb->select('id') + ->from('foo') + ->having('a = b'); + + $qb->andHaving('', 'c = d'); + + self::assertSame('SELECT id FROM foo HAVING (a = b) AND (c = d)', $qb->getSQL()); + } + + public function testOrHavingEmptyStringStartingWithEmptyExpression(): void + { + $qb = new QueryBuilder($this->conn); + + $qb->select('id') + ->from('foo'); + + $qb->orHaving('', 'a = b'); + + self::assertSame('SELECT id FROM foo HAVING a = b', $qb->getSQL()); + } + + public function testOrHavingEmptyStringStartingWithNonEmptyExpression(): void + { + $qb = new QueryBuilder($this->conn); + + $qb->select('id') + ->from('foo') + ->having('a = b'); + + $qb->orHaving('', 'c = d'); + + self::assertSame('SELECT id FROM foo HAVING (a = b) OR (c = d)', $qb->getSQL()); + } } From e90de0cdefa9791cb19a91e3d9e77785c251713b Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Wed, 23 Sep 2020 12:15:09 -0700 Subject: [PATCH 6/8] Deprecated the Abstraction\Result interface --- UPGRADE.md | 4 ++++ lib/Doctrine/DBAL/Abstraction/Result.php | 2 ++ 2 files changed, 6 insertions(+) diff --git a/UPGRADE.md b/UPGRADE.md index 9eb98d764a3..e8c8997dc67 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,9 @@ # Upgrade to 2.11 +## Deprecated `Abstraction\Result` + +The usage of the `Doctrine\DBAL\Abstraction\Result` interface is deprecated. In DBAL 3.0, the statement result at the wrapper level will be represented by the `Doctrine\DBAL\Result` class. + ## Deprecated the functionality of dropping client connections when dropping a database The corresponding `getDisallowDatabaseConnectionsSQL()` and `getCloseActiveDatabaseConnectionsSQL` methods diff --git a/lib/Doctrine/DBAL/Abstraction/Result.php b/lib/Doctrine/DBAL/Abstraction/Result.php index 42ff3419e37..2b1f8e69f3f 100644 --- a/lib/Doctrine/DBAL/Abstraction/Result.php +++ b/lib/Doctrine/DBAL/Abstraction/Result.php @@ -11,6 +11,8 @@ /** * Abstraction-level result statement execution result. Provides additional methods on top * of the driver-level interface. + * + * @deprecated */ interface Result extends DriverResult { From 35c778bcfdf743c9bee88348e4c09fbe200536f0 Mon Sep 17 00:00:00 2001 From: Benjamin Morel Date: Mon, 20 Jul 2020 00:58:01 +0200 Subject: [PATCH 7/8] Fix 2nd/3rd parameter not allowed for PDO::FETCH_COLUMN --- lib/Doctrine/DBAL/Statement.php | 10 ++- .../Functional/ExternalPDOInstanceTest.php | 70 +++++++++++++++++++ .../DBAL/Functional/StatementTestModel.php | 24 +++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tests/Doctrine/Tests/DBAL/Functional/ExternalPDOInstanceTest.php create mode 100644 tests/Doctrine/Tests/DBAL/Functional/StatementTestModel.php diff --git a/lib/Doctrine/DBAL/Statement.php b/lib/Doctrine/DBAL/Statement.php index 0e47e09303c..294866921ec 100644 --- a/lib/Doctrine/DBAL/Statement.php +++ b/lib/Doctrine/DBAL/Statement.php @@ -264,7 +264,15 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX */ public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) { - return $this->stmt->fetchAll($fetchMode, $fetchArgument, $ctorArgs); + if ($ctorArgs !== null) { + return $this->stmt->fetchAll($fetchMode, $fetchArgument, $ctorArgs); + } + + if ($fetchArgument !== null) { + return $this->stmt->fetchAll($fetchMode, $fetchArgument); + } + + return $this->stmt->fetchAll($fetchMode); } /** diff --git a/tests/Doctrine/Tests/DBAL/Functional/ExternalPDOInstanceTest.php b/tests/Doctrine/Tests/DBAL/Functional/ExternalPDOInstanceTest.php new file mode 100644 index 00000000000..42af9d29ea5 --- /dev/null +++ b/tests/Doctrine/Tests/DBAL/Functional/ExternalPDOInstanceTest.php @@ -0,0 +1,70 @@ +getDriver() instanceof PDOSqliteDriver) { + $this->markTestSkipped('External PDO instance tests are only run on PDO SQLite for now'); + } + + $pdo = new PDO('sqlite::memory:'); + + $this->connection = new Connection(['pdo' => $pdo], new PDOSqliteDriver()); + + $table = new Table('stmt_fetch_all'); + $table->addColumn('a', 'integer'); + $table->addColumn('b', 'integer'); + + $this->connection->getSchemaManager()->createTable($table); + + $this->connection->insert('stmt_fetch_all', [ + 'a' => 1, + 'b' => 2, + ]); + } + + public function testFetchAllWithOneArgument(): void + { + $stmt = $this->connection->prepare('SELECT a, b FROM stmt_fetch_all'); + $stmt->execute(); + + self::assertEquals([[1, 2]], $stmt->fetchAll(FetchMode::NUMERIC)); + } + + public function testFetchAllWithTwoArguments(): void + { + $stmt = $this->connection->prepare('SELECT a, b FROM stmt_fetch_all'); + $stmt->execute(); + + self::assertEquals([2], $stmt->fetchAll(FetchMode::COLUMN, 1)); + } + + public function testFetchAllWithThreeArguments(): void + { + $stmt = $this->connection->prepare('SELECT a, b FROM stmt_fetch_all'); + $stmt->execute(); + + [$obj] = $stmt->fetchAll(FetchMode::CUSTOM_OBJECT, StatementTestModel::class, ['foo', 'bar']); + + $this->assertInstanceOf(StatementTestModel::class, $obj); + + self::assertEquals(1, $obj->a); + self::assertEquals(2, $obj->b); + self::assertEquals('foo', $obj->x); + self::assertEquals('bar', $obj->y); + } +} diff --git a/tests/Doctrine/Tests/DBAL/Functional/StatementTestModel.php b/tests/Doctrine/Tests/DBAL/Functional/StatementTestModel.php new file mode 100644 index 00000000000..16bb6e1e1a3 --- /dev/null +++ b/tests/Doctrine/Tests/DBAL/Functional/StatementTestModel.php @@ -0,0 +1,24 @@ +x = $x; + $this->y = $y; + } + + /** @var int */ + public $a; + + /** @var int */ + public $b; + + /** @var string */ + public $x; + + /** @var string */ + public $y; +} From e06d0bb64fff1bd0d8c1f184c593762eaa956ff7 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Fri, 25 Sep 2020 17:53:20 -0700 Subject: [PATCH 8/8] Fix ExceptionTest::testConnectionExceptionSqLite() on macOS --- tests/Doctrine/Tests/DBAL/Functional/ExceptionTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Doctrine/Tests/DBAL/Functional/ExceptionTest.php b/tests/Doctrine/Tests/DBAL/Functional/ExceptionTest.php index f5136c66c47..338d3a7aee4 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/ExceptionTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/ExceptionTest.php @@ -29,6 +29,7 @@ use function version_compare; use const PHP_OS; +use const PHP_OS_FAMILY; class ExceptionTest extends DbalFunctionalTestCase { @@ -303,7 +304,7 @@ public function testConnectionExceptionSqLite(): void } // mode 0 is considered read-only on Windows - $mode = PHP_OS === 'Linux' ? 0444 : 0000; + $mode = PHP_OS_FAMILY === 'Windows' ? 0000 : 0444; $filename = sprintf('%s/%s', sys_get_temp_dir(), 'doctrine_failed_connection_' . $mode . '.db');