diff --git a/.gitattributes b/.gitattributes index 5bbaf359701..54d8bd65621 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,15 +1,16 @@ /.appveyor.yml export-ignore +/composer.lock export-ignore +/docs export-ignore +/.doctrine-project.json export-ignore /.gitattributes export-ignore /.github export-ignore /.gitignore export-ignore -/.scrutinizer.yml export-ignore -/.travis.yml export-ignore -/build.properties export-ignore -/build.xml export-ignore -/composer.lock export-ignore -/docs export-ignore /phpcs.xml.dist export-ignore /phpstan.neon.dist export-ignore /phpunit.xml.dist export-ignore /run-all.sh export-ignore +/.scrutinizer.yml export-ignore +/SECURITY.md export-ignore /tests export-ignore +/.travis.yml export-ignore +/UPGRADE.md export-ignore diff --git a/UPGRADE.md b/UPGRADE.md index 205bf991974..adb9ffd904e 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,3 +1,45 @@ +# Upgrade to 2.11 + +## Deprecated `EchoSQLLogger` + +The `EchoSQLLogger` is has been deprecated. Implement your logger with the desired logic. + +## Deprecated database platforms: + +1. PostgreSQL 9.3 and older +2. MariaDB 10.0 and older +3. SQL Server 2008 and older +4. SQL Anywhere 12 and older +5. Drizzle +6. Azure SQL Database + +## Deprecated database drivers: + +1. PDO-based IBM DB2 driver +2. Drizzle MySQL driver + +## Deprecated `Doctrine\DBAL\Sharding` package + +The sharding functionality in DBAL has been effectively unmaintained for a long time. + +## Deprecated `Doctrine\DBAL\Version` class + +The usage of the `Doctrine\DBAL\Version` class is deprecated as internal implementation detail. Please refrain from checking the DBAL version at runtime. + +## Deprecated `ExpressionBuilder` methods + +The usage of the `andX()` and `orX()` methods of the `ExpressionBuilder` class has been deprecated. Use `and()` and `or()` instead. + +## Deprecated `CompositeExpression` methods + +- The usage of the `add()` and `addMultiple()` methods of the `CompositeExpression` class has been deprecated. Use `with()` instead, which returns a new instance. +In the future, the `add*()` methods will be removed and the class will be effectively immutable. +- The usage of the `CompositeExpression` constructor has been deprecated. Use the `and()` / `or()` factory methods. + +## Deprecated calling `QueryBuilder` methods with an array argument + +Calling the `select()`, `addSelect()`, `groupBy()` and `addGroupBy()` methods with an array argument is deprecated. + # Upgrade to 2.10 ## Deprecated `Doctrine\DBAL\Event\ConnectionEventArgs` methods diff --git a/bin/doctrine-dbal.php b/bin/doctrine-dbal.php index f3e064ffd62..61a4098c9b0 100644 --- a/bin/doctrine-dbal.php +++ b/bin/doctrine-dbal.php @@ -1,5 +1,6 @@ select('id', 'name') ->from('users') ->where( - $queryBuilder->expr()->andX( + $queryBuilder->expr()->and( $queryBuilder->expr()->eq('username', '?'), $queryBuilder->expr()->eq('email', '?') ) ); -The ``andX()`` and ``orX()`` methods accept an arbitrary amount +The ``and()`` and ``or()`` methods accept an arbitrary amount of arguments and can be nested in each other. There is a bunch of methods to create comparisons and other SQL snippets diff --git a/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php b/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php index 4089ab26e11..058bd19e2d0 100644 --- a/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php +++ b/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php @@ -5,6 +5,9 @@ use Doctrine\DBAL\Driver\PDOConnection; use Doctrine\DBAL\ParameterType; +/** + * @deprecated + */ class Connection extends PDOConnection { /** diff --git a/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php b/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php index dbf342814f9..37bd0729efa 100644 --- a/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php +++ b/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php @@ -7,6 +7,8 @@ /** * Drizzle driver using PDO MySql. + * + * @deprecated */ class Driver extends \Doctrine\DBAL\Driver\PDOMySql\Driver { diff --git a/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php b/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php index 7ea26d4d4c1..20332adbd16 100644 --- a/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php +++ b/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php @@ -7,6 +7,8 @@ /** * Driver for the PDO IBM extension. + * + * @deprecated Use the driver based on the ibm_db2 extension instead. */ class Driver extends AbstractDB2Driver { diff --git a/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php b/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php index c722797dd8b..bd2d2f93eab 100644 --- a/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php +++ b/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php @@ -7,6 +7,8 @@ /** * A SQL logger that logs to the standard output using echo/var_dump. + * + * @deprecated */ class EchoSQLLogger implements SQLLogger { diff --git a/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php b/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php index f796a48c786..b13676775a1 100644 --- a/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php @@ -23,6 +23,8 @@ /** * Drizzle platform + * + * @deprecated */ class DrizzlePlatform extends AbstractPlatform { diff --git a/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php b/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php index f558409831c..7e3aac30e07 100644 --- a/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php +++ b/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php @@ -6,6 +6,8 @@ /** * Provides the behavior, features and SQL dialect of the PostgreSQL 9.1 database platform. + * + * @deprecated Use PostgreSQL 9.4 or newer */ class PostgreSQL91Platform extends PostgreSqlPlatform { diff --git a/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php b/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php index 1703056143f..c0b5675a383 100644 --- a/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php +++ b/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php @@ -7,6 +7,8 @@ /** * Provides the behavior, features and SQL dialect of the PostgreSQL 9.2 database platform. + * + * @deprecated Use PostgreSQL 9.4 or newer */ class PostgreSQL92Platform extends PostgreSQL91Platform { diff --git a/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php b/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php index 7c62d5f8c66..9d17a2bb5c1 100644 --- a/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php @@ -35,6 +35,8 @@ /** * PostgreSqlPlatform. * + * @deprecated Use PostgreSQL 9.4 or newer + * * @todo Rename: PostgreSQLPlatform */ class PostgreSqlPlatform extends AbstractPlatform diff --git a/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php b/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php index a46ae9352c4..71922b22769 100644 --- a/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php @@ -5,6 +5,8 @@ /** * The SQLAnywhere11Platform provides the behavior, features and SQL dialect of the * SAP Sybase SQL Anywhere 11 database platform. + * + * @deprecated Use SQLAnywhere 16 or newer */ class SQLAnywhere11Platform extends SQLAnywherePlatform { diff --git a/lib/Doctrine/DBAL/Platforms/SQLAnywhere12Platform.php b/lib/Doctrine/DBAL/Platforms/SQLAnywhere12Platform.php index dd73ef736ad..4fb3c63f70f 100644 --- a/lib/Doctrine/DBAL/Platforms/SQLAnywhere12Platform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLAnywhere12Platform.php @@ -8,6 +8,8 @@ /** * The SQLAnywhere12Platform provides the behavior, features and SQL dialect of the * SAP Sybase SQL Anywhere 12 database platform. + * + * @deprecated Use SQLAnywhere 16 or newer */ class SQLAnywhere12Platform extends SQLAnywhere11Platform { diff --git a/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php b/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php index e9cb363c6b8..4deda5238a0 100644 --- a/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php @@ -34,6 +34,8 @@ /** * The SQLAnywherePlatform provides the behavior, features and SQL dialect of the * SAP Sybase SQL Anywhere 10 database platform. + * + * @deprecated Use SQLAnywhere 16 or newer */ class SQLAnywherePlatform extends AbstractPlatform { diff --git a/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php b/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php index a104848f84e..f281f4fc4e4 100644 --- a/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php @@ -10,6 +10,8 @@ * On top of SQL Server 2008 the following functionality is added: * * - Create tables with the FEDERATED ON syntax. + * + * @deprecated */ class SQLAzurePlatform extends SQLServer2008Platform { diff --git a/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php b/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php index 1026a934f00..5cd3475c1e2 100644 --- a/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php @@ -15,6 +15,8 @@ * NVARCHAR(max) replace the old TEXT, NTEXT and IMAGE types. See * {@link http://www.sql-server-helper.com/faq/sql-server-2005-varchar-max-p01.aspx} * for more information. + * + * @deprecated Use SQL Server 2012 or newer */ class SQLServer2005Platform extends SQLServerPlatform { diff --git a/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php b/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php index c2e36f34e67..9cbcb3872e6 100644 --- a/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php @@ -7,6 +7,8 @@ * * Differences to SQL Server 2005 and before are that a new DATETIME2 type was * introduced that has a higher precision. + * + * @deprecated Use SQL Server 2012 or newer */ class SQLServer2008Platform extends SQLServer2005Platform { diff --git a/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php b/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php index 322fe1ec621..2bccffbfdd3 100644 --- a/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php @@ -38,6 +38,8 @@ /** * The SQLServerPlatform provides the behavior, features and SQL dialect of the * Microsoft SQL Server database platform. + * + * @deprecated Use SQL Server 2012 or newer */ class SQLServerPlatform extends AbstractPlatform { diff --git a/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php b/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php index 96f94a36e66..41f9f74e22c 100644 --- a/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php +++ b/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php @@ -3,6 +3,7 @@ namespace Doctrine\DBAL\Query\Expression; use Countable; +use function array_merge; use function count; use function implode; @@ -36,6 +37,8 @@ class CompositeExpression implements Countable private $parts = []; /** + * @internal Use the and() / or() factory methods. + * * @param string $type Instance type of composite expression. * @param self[]|string[] $parts Composition of expressions to be joined on composite expression. */ @@ -46,9 +49,29 @@ public function __construct($type, array $parts = []) $this->addMultiple($parts); } + /** + * @param self|string $part + * @param self|string ...$parts + */ + public static function and($part, ...$parts) : self + { + return new self(self::TYPE_AND, array_merge([$part], $parts)); + } + + /** + * @param self|string $part + * @param self|string ...$parts + */ + public static function or($part, ...$parts) : self + { + return new self(self::TYPE_OR, array_merge([$part], $parts)); + } + /** * Adds multiple parts to composite expression. * + * @deprecated This class will be made immutable. Use with() instead. + * * @param self[]|string[] $parts * * @return CompositeExpression @@ -65,6 +88,8 @@ public function addMultiple(array $parts = []) /** * Adds an expression to composite expression. * + * @deprecated This class will be made immutable. Use with() instead. + * * @param mixed $part * * @return CompositeExpression @@ -84,6 +109,25 @@ public function add($part) return $this; } + /** + * Returns a new CompositeExpression with the given parts added. + * + * @param self|string $part + * @param self|string ...$parts + */ + public function with($part, ...$parts) : self + { + $that = clone $this; + + $that->parts[] = $part; + + foreach ($parts as $part) { + $that->parts[] = $part; + } + + return $that; + } + /** * Retrieves the amount of expressions on composite expression. * diff --git a/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php b/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php index dfcc31ec709..ef0e6eebb00 100644 --- a/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php +++ b/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php @@ -39,13 +39,29 @@ public function __construct(Connection $connection) } /** - * Creates a conjunction of the given boolean expressions. + * Creates a conjunction of the given expressions. * - * Example: + * @param string|CompositeExpression $expression + * @param string|CompositeExpression ...$expressions + */ + public function and($expression, ...$expressions) : CompositeExpression + { + return CompositeExpression::and($expression, ...$expressions); + } + + /** + * Creates a disjunction of the given expressions. * - * [php] - * // (u.type = ?) AND (u.role = ?) - * $expr->andX('u.type = ?', 'u.role = ?')); + * @param string|CompositeExpression $expression + * @param string|CompositeExpression ...$expressions + */ + public function or($expression, ...$expressions) : CompositeExpression + { + return CompositeExpression::or($expression, ...$expressions); + } + + /** + * @deprecated Use `and()` instead. * * @param mixed $x Optional clause. Defaults = null, but requires * at least one defined when converting to string. @@ -58,13 +74,7 @@ public function andX($x = null) } /** - * Creates a disjunction of the given boolean expressions. - * - * Example: - * - * [php] - * // (u.type = ?) OR (u.role = ?) - * $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?')); + * @deprecated Use `or()` instead. * * @param mixed $x Optional clause. Defaults = null, but requires * at least one defined when converting to string. diff --git a/lib/Doctrine/DBAL/Query/QueryBuilder.php b/lib/Doctrine/DBAL/Query/QueryBuilder.php index 6d1d1ff740b..a2fa05f422a 100644 --- a/lib/Doctrine/DBAL/Query/QueryBuilder.php +++ b/lib/Doctrine/DBAL/Query/QueryBuilder.php @@ -451,6 +451,8 @@ public function add($sqlPartName, $sqlPart, $append = false) * Specifies an item that is to be returned in the query result. * Replaces any previously specified selections, if any. * + * USING AN ARRAY ARGUMENT IS DEPRECATED. Pass each value as an individual argument. + * * * $qb = $conn->createQueryBuilder() * ->select('u.id', 'p.id') @@ -458,11 +460,12 @@ public function add($sqlPartName, $sqlPart, $append = false) * ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id'); * * - * @param mixed $select The selection expressions. + * @param string|string[]|null $select The selection expression. USING AN ARRAY OR NULL IS DEPRECATED. + * Pass each value as an individual argument. * * @return $this This QueryBuilder instance. */ - public function select($select = null) + public function select($select = null/*, string ...$selects*/) { $this->type = self::SELECT; @@ -497,6 +500,8 @@ public function distinct() : self /** * Adds an item that is to be returned in the query result. * + * USING AN ARRAY ARGUMENT IS DEPRECATED. Pass each value as an individual argument. + * * * $qb = $conn->createQueryBuilder() * ->select('u.id') @@ -505,11 +510,12 @@ public function distinct() : self * ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id'); * * - * @param mixed $select The selection expression. + * @param string|string[]|null $select The selection expression. USING AN ARRAY OR NULL IS DEPRECATED. + * Pass each value as an individual argument. * * @return $this This QueryBuilder instance. */ - public function addSelect($select = null) + public function addSelect($select = null/*, string ...$selects*/) { $this->type = self::SELECT; @@ -793,7 +799,7 @@ public function set($key, $value) public function where($predicates) { if (! (func_num_args() === 1 && $predicates instanceof CompositeExpression)) { - $predicates = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); + $predicates = CompositeExpression::and(...func_get_args()); } return $this->add('where', $predicates); @@ -823,10 +829,10 @@ public function andWhere($where) $where = $this->getQueryPart('where'); if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) { - $where->addMultiple($args); + $where = $where->with(...$args); } else { array_unshift($args, $where); - $where = new CompositeExpression(CompositeExpression::TYPE_AND, $args); + $where = CompositeExpression::and(...$args); } return $this->add('where', $where, true); @@ -856,10 +862,10 @@ public function orWhere($where) $where = $this->getQueryPart('where'); if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) { - $where->addMultiple($args); + $where = $where->with(...$args); } else { array_unshift($args, $where); - $where = new CompositeExpression(CompositeExpression::TYPE_OR, $args); + $where = CompositeExpression::or(...$args); } return $this->add('where', $where, true); @@ -869,6 +875,8 @@ public function orWhere($where) * Specifies a grouping over the results of the query. * Replaces any previously specified groupings, if any. * + * USING AN ARRAY ARGUMENT IS DEPRECATED. Pass each value as an individual argument. + * * * $qb = $conn->createQueryBuilder() * ->select('u.name') @@ -876,11 +884,12 @@ public function orWhere($where) * ->groupBy('u.id'); * * - * @param mixed $groupBy The grouping expression. + * @param string|string[] $groupBy The grouping expression. USING AN ARRAY IS DEPRECATED. + * Pass each value as an individual argument. * * @return $this This QueryBuilder instance. */ - public function groupBy($groupBy) + public function groupBy($groupBy/*, string ...$groupBys*/) { if (empty($groupBy)) { return $this; @@ -894,6 +903,8 @@ public function groupBy($groupBy) /** * Adds a grouping expression to the query. * + * USING AN ARRAY ARGUMENT IS DEPRECATED. Pass each value as an individual argument. + * * * $qb = $conn->createQueryBuilder() * ->select('u.name') @@ -902,11 +913,12 @@ public function groupBy($groupBy) * ->addGroupBy('u.createdAt'); * * - * @param mixed $groupBy The grouping expression. + * @param string|string[] $groupBy The grouping expression. USING AN ARRAY IS DEPRECATED. + * Pass each value as an individual argument. * * @return $this This QueryBuilder instance. */ - public function addGroupBy($groupBy) + public function addGroupBy($groupBy/*, string ...$groupBys*/) { if (empty($groupBy)) { return $this; @@ -978,7 +990,7 @@ public function values(array $values) public function having($having) { if (! (func_num_args() === 1 && $having instanceof CompositeExpression)) { - $having = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); + $having = CompositeExpression::and(...func_get_args()); } return $this->add('having', $having); @@ -998,10 +1010,10 @@ public function andHaving($having) $having = $this->getQueryPart('having'); if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) { - $having->addMultiple($args); + $having = $having->with(...$args); } else { array_unshift($args, $having); - $having = new CompositeExpression(CompositeExpression::TYPE_AND, $args); + $having = CompositeExpression::and(...$args); } return $this->add('having', $having); @@ -1021,10 +1033,10 @@ public function orHaving($having) $having = $this->getQueryPart('having'); if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) { - $having->addMultiple($args); + $having = $having->with(...$args); } else { array_unshift($args, $having); - $having = new CompositeExpression(CompositeExpression::TYPE_OR, $args); + $having = CompositeExpression::or(...$args); } return $this->add('having', $having); diff --git a/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php b/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php index 8d8134127d7..871b54eec9e 100644 --- a/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php +++ b/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php @@ -32,6 +32,8 @@ * * Instantiation through the DriverManager looks like: * + * @deprecated + * * @example * * $conn = DriverManager::getConnection(array( diff --git a/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php b/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php index 5edc56b8778..2687c9d98ea 100644 --- a/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php +++ b/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php @@ -7,6 +7,8 @@ /** * Shard Manager for the Connection Pooling Shard Strategy + * + * @deprecated */ class PoolingShardManager implements ShardManager { diff --git a/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php b/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php index 417f674a3e0..e889edbc5d7 100644 --- a/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php +++ b/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php @@ -20,6 +20,8 @@ * by partitioning the passed schema into subschemas for the federation and the * global database and then applying the operations step by step using the * {@see \Doctrine\DBAL\Schema\Synchronizer\SingleDatabaseSynchronizer}. + * + * @deprecated */ class SQLAzureFederationsSynchronizer extends AbstractSchemaSynchronizer { diff --git a/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php b/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php index d8178ee07db..62a6fd48447 100644 --- a/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php +++ b/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php @@ -11,6 +11,8 @@ /** * Sharding using the SQL Azure Federations support. + * + * @deprecated */ class SQLAzureShardManager implements ShardManager { diff --git a/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php b/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php index e85a3025f18..7d8307ec920 100644 --- a/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php +++ b/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php @@ -30,6 +30,8 @@ * (otherwise they will affect the same-id rows from other tenants as well). * SQLAzure throws errors when you try to create IDENTIY columns on federated * tables. + * + * @deprecated */ class MultiTenantVisitor implements Visitor { diff --git a/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php b/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php index 584e8155ae9..f44c3af4322 100644 --- a/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php +++ b/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php @@ -7,6 +7,8 @@ /** * The MultiTenant Shard choser assumes that the distribution value directly * maps to the shard id. + * + * @deprecated */ class MultiTenantShardChoser implements ShardChoser { diff --git a/lib/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php b/lib/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php index 6f8a9d47702..92510d704b1 100644 --- a/lib/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php +++ b/lib/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php @@ -7,6 +7,8 @@ /** * Given a distribution value this shard-choser strategy will pick the shard to * connect to for retrieving rows with the distribution value. + * + * @deprecated */ interface ShardChoser { diff --git a/lib/Doctrine/DBAL/Sharding/ShardManager.php b/lib/Doctrine/DBAL/Sharding/ShardManager.php index 7b37bb2c7e1..dbb229a1907 100644 --- a/lib/Doctrine/DBAL/Sharding/ShardManager.php +++ b/lib/Doctrine/DBAL/Sharding/ShardManager.php @@ -17,6 +17,8 @@ * executed against the last shard that was selected. If a query is created for * a shard Y but then a shard X is selected when its actually executed you * will hit the wrong shard. + * + * @deprecated */ interface ShardManager { diff --git a/lib/Doctrine/DBAL/Sharding/ShardingException.php b/lib/Doctrine/DBAL/Sharding/ShardingException.php index f760dc7baa2..2df764a6ff2 100644 --- a/lib/Doctrine/DBAL/Sharding/ShardingException.php +++ b/lib/Doctrine/DBAL/Sharding/ShardingException.php @@ -7,6 +7,8 @@ /** * Sharding related Exceptions * + * @deprecated + * * @psalm-immutable */ class ShardingException extends DBALException diff --git a/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php b/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php index cc3d1611ecf..5d19cb5e40b 100644 --- a/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php +++ b/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php @@ -21,6 +21,8 @@ use Doctrine\DBAL\Platforms\Keywords\SQLServer2008Keywords; use Doctrine\DBAL\Platforms\Keywords\SQLServer2012Keywords; use Doctrine\DBAL\Platforms\Keywords\SQLServerKeywords; +use Doctrine\DBAL\Tools\Console\ConnectionProvider; +use Exception; use InvalidArgumentException; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -30,6 +32,9 @@ use function assert; use function count; use function implode; +use function is_string; +use function trigger_error; +use const E_USER_DEPRECATED; class ReservedWordsCommand extends Command { @@ -54,6 +59,20 @@ class ReservedWordsCommand extends Command 'sqlanywhere16' => SQLAnywhere16Keywords::class, ]; + /** @var ConnectionProvider|null */ + private $connectionProvider; + + public function __construct(?ConnectionProvider $connectionProvider = null) + { + parent::__construct(); + $this->connectionProvider = $connectionProvider; + if ($connectionProvider !== null) { + return; + } + + @trigger_error('Not passing a connection provider as the first constructor argument is deprecated', E_USER_DEPRECATED); + } + /** * If you want to add or replace a keywords list use this command. * @@ -73,12 +92,14 @@ protected function configure() $this ->setName('dbal:reserved-words') ->setDescription('Checks if the current database contains identifiers that are reserved.') - ->setDefinition([new InputOption( - 'list', - 'l', - InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, - 'Keyword-List name.' - ), + ->setDefinition([ + new InputOption('connection', null, InputOption::VALUE_REQUIRED, 'The named database connection'), + new InputOption( + 'list', + 'l', + InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + 'Keyword-List name.' + ), ]) ->setHelp(<<getHelper('db')->getConnection(); - assert($conn instanceof Connection); + $conn = $this->getConnection($input); $keywordLists = (array) $input->getOption('list'); if (! $keywordLists) { @@ -178,4 +198,24 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } + + private function getConnection(InputInterface $input) : Connection + { + $connectionName = $input->getOption('connection'); + assert(is_string($connectionName) || $connectionName === null); + + if ($this->connectionProvider === null) { + if ($connectionName !== null) { + throw new Exception('Specifying a connection is only supported when a ConnectionProvider is used.'); + } + + return $this->getHelper('db')->getConnection(); + } + + if ($connectionName !== null) { + return $this->connectionProvider->getConnection($connectionName); + } + + return $this->connectionProvider->getDefaultConnection(); + } } diff --git a/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php b/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php index 5111a6505db..37c3c8973ca 100644 --- a/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php +++ b/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php @@ -2,7 +2,10 @@ namespace Doctrine\DBAL\Tools\Console\Command; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Tools\Console\ConnectionProvider; use Doctrine\DBAL\Tools\Dumper; +use Exception; use LogicException; use RuntimeException; use Symfony\Component\Console\Command\Command; @@ -14,6 +17,8 @@ use function is_numeric; use function is_string; use function stripos; +use function trigger_error; +use const E_USER_DEPRECATED; /** * Task for executing arbitrary SQL that can come from a file or directly from @@ -21,6 +26,20 @@ */ class RunSqlCommand extends Command { + /** @var ConnectionProvider|null */ + private $connectionProvider; + + public function __construct(?ConnectionProvider $connectionProvider = null) + { + parent::__construct(); + $this->connectionProvider = $connectionProvider; + if ($connectionProvider !== null) { + return; + } + + @trigger_error('Not passing a connection provider as the first constructor argument is deprecated', E_USER_DEPRECATED); + } + /** @return void */ protected function configure() { @@ -28,6 +47,7 @@ protected function configure() ->setName('dbal:run-sql') ->setDescription('Executes arbitrary SQL directly from the command line.') ->setDefinition([ + new InputOption('connection', null, InputOption::VALUE_REQUIRED, 'The named database connection'), new InputArgument('sql', InputArgument::REQUIRED, 'The SQL statement to execute.'), new InputOption('depth', null, InputOption::VALUE_REQUIRED, 'Dumping depth of result set.', 7), new InputOption('force-fetch', null, InputOption::VALUE_NONE, 'Forces fetching the result.'), @@ -43,7 +63,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $conn = $this->getHelper('db')->getConnection(); + $conn = $this->getConnection($input); $sql = $input->getArgument('sql'); @@ -69,4 +89,24 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } + + private function getConnection(InputInterface $input) : Connection + { + $connectionName = $input->getOption('connection'); + assert(is_string($connectionName) || $connectionName === null); + + if ($this->connectionProvider === null) { + if ($connectionName !== null) { + throw new Exception('Specifying a connection is only supported when a ConnectionProvider is used.'); + } + + return $this->getHelper('db')->getConnection(); + } + + if ($connectionName !== null) { + return $this->connectionProvider->getConnection($connectionName); + } + + return $this->connectionProvider->getDefaultConnection(); + } } diff --git a/lib/Doctrine/DBAL/Tools/Console/ConnectionNotFound.php b/lib/Doctrine/DBAL/Tools/Console/ConnectionNotFound.php new file mode 100644 index 00000000000..81ca4182a03 --- /dev/null +++ b/lib/Doctrine/DBAL/Tools/Console/ConnectionNotFound.php @@ -0,0 +1,9 @@ +connection = $connection; + $this->defaultConnectionName = $defaultConnectionName; + } + + public function getDefaultConnection() : Connection + { + return $this->connection; + } + + public function getConnection(string $name) : Connection + { + if ($name !== $this->defaultConnectionName) { + throw new ConnectionNotFound(sprintf('Connection with name "%s" does not exist.', $name)); + } + + return $this->connection; + } +} diff --git a/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php b/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php index e028c807c01..f0e65c33928 100644 --- a/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php +++ b/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php @@ -11,6 +11,10 @@ use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\HelperSet; +use TypeError; +use function sprintf; +use function trigger_error; +use const E_USER_DEPRECATED; /** * Handles running the Console Tools inside Symfony Console context. @@ -20,6 +24,8 @@ class ConsoleRunner /** * Create a Symfony Console HelperSet * + * @deprecated use a ConnectionProvider instead. + * * @return HelperSet */ public static function createHelperSet(Connection $connection) @@ -30,20 +36,31 @@ public static function createHelperSet(Connection $connection) } /** - * Runs console with the given helperset. + * Runs console with the given connection provider or helperset (deprecated). * - * @param Command[] $commands + * @param ConnectionProvider|HelperSet $helperSetOrConnectionProvider + * @param Command[] $commands * * @return void */ - public static function run(HelperSet $helperSet, $commands = []) + public static function run($helperSetOrConnectionProvider, $commands = []) { $cli = new Application('Doctrine Command Line Interface', Version::VERSION); $cli->setCatchExceptions(true); - $cli->setHelperSet($helperSet); - self::addCommands($cli); + $connectionProvider = null; + if ($helperSetOrConnectionProvider instanceof HelperSet) { + @trigger_error(sprintf('Passing an instance of "%s" as the first argument is deprecated. Pass an instance of "%s" instead.', HelperSet::class, ConnectionProvider::class), E_USER_DEPRECATED); + $connectionProvider = null; + $cli->setHelperSet($helperSetOrConnectionProvider); + } elseif ($helperSetOrConnectionProvider instanceof ConnectionProvider) { + $connectionProvider = $helperSetOrConnectionProvider; + } else { + throw new TypeError(sprintf('First argument must be an instance of "%s" or "%s"', HelperSet::class, ConnectionProvider::class)); + } + + self::addCommands($cli, $connectionProvider); $cli->addCommands($commands); $cli->run(); @@ -52,12 +69,12 @@ public static function run(HelperSet $helperSet, $commands = []) /** * @return void */ - public static function addCommands(Application $cli) + public static function addCommands(Application $cli, ?ConnectionProvider $connectionProvider = null) { $cli->addCommands([ - new RunSqlCommand(), + new RunSqlCommand($connectionProvider), new ImportCommand(), - new ReservedWordsCommand(), + new ReservedWordsCommand($connectionProvider), ]); } @@ -74,14 +91,17 @@ public static function printCliConfigTemplate() following sample as a template: - ./tests/Doctrine/Tests/DBAL - ./tests/Doctrine/Tests/DBAL/Performance - - - ./tests/Doctrine/Tests/DBAL/Performance + tests/Doctrine/Tests/DBAL @@ -57,14 +53,4 @@ lib/Doctrine - - - - - - - - performance - - diff --git a/tests/Doctrine/Tests/DBAL/Performance/TypeConversionPerformanceTest.php b/tests/Doctrine/Tests/DBAL/Performance/TypeConversionPerformanceTest.php deleted file mode 100644 index fefc973a699..00000000000 --- a/tests/Doctrine/Tests/DBAL/Performance/TypeConversionPerformanceTest.php +++ /dev/null @@ -1,45 +0,0 @@ -connection->getDatabasePlatform(); - $this->startTiming(); - for ($i = 0; $i < $count; $i++) { - $type->convertToDatabaseValue($value, $platform); - } - - $this->stopTiming(); - } - - /** - * @return mixed[][] - */ - public static function itemCountProvider() : iterable - { - return [ - '100 items' => [100], - '1000 items' => [1000], - '10000 items' => [10000], - '100000 items' => [100000], - ]; - } -} diff --git a/tests/Doctrine/Tests/DBAL/Query/Expression/CompositeExpressionTest.php b/tests/Doctrine/Tests/DBAL/Query/Expression/CompositeExpressionTest.php index 0a8492f795f..1e9eee344d1 100644 --- a/tests/Doctrine/Tests/DBAL/Query/Expression/CompositeExpressionTest.php +++ b/tests/Doctrine/Tests/DBAL/Query/Expression/CompositeExpressionTest.php @@ -12,18 +12,18 @@ class CompositeExpressionTest extends DbalTestCase { public function testCount() : void { - $expr = new CompositeExpression(CompositeExpression::TYPE_OR, ['u.group_id = 1']); + $expr = CompositeExpression::or('u.group_id = 1'); self::assertCount(1, $expr); - $expr->add('u.group_id = 2'); + $expr = $expr->with('u.group_id = 2'); self::assertCount(2, $expr); } public function testAdd() : void { - $expr = new CompositeExpression(CompositeExpression::TYPE_OR, ['u.group_id = 1']); + $expr = CompositeExpression::or('u.group_id = 1'); self::assertCount(1, $expr); @@ -31,7 +31,7 @@ public function testAdd() : void self::assertCount(1, $expr); - $expr->add(new CompositeExpression(CompositeExpression::TYPE_OR, ['u.user_id = 1'])); + $expr->add(CompositeExpression::or('u.user_id = 1')); self::assertCount(2, $expr); @@ -44,6 +44,26 @@ public function testAdd() : void self::assertCount(3, $expr); } + public function testWith() : void + { + $expr = CompositeExpression::or('u.group_id = 1'); + + self::assertCount(1, $expr); + + // test immutability + $expr->with(CompositeExpression::or('u.user_id = 1')); + + self::assertCount(1, $expr); + + $expr = $expr->with(CompositeExpression::or('u.user_id = 1')); + + self::assertCount(2, $expr); + + $expr = $expr->with('u.user_id = 1'); + + self::assertCount(3, $expr); + } + /** * @param string[]|CompositeExpression[] $parts * @@ -86,9 +106,9 @@ public static function provideDataForConvertToString() : iterable CompositeExpression::TYPE_AND, [ 'u.user = 1', - new CompositeExpression( - CompositeExpression::TYPE_OR, - ['u.group_id = 1', 'u.group_id = 2'] + CompositeExpression::or( + 'u.group_id = 1', + 'u.group_id = 2' ), ], '(u.user = 1) AND ((u.group_id = 1) OR (u.group_id = 2))', @@ -97,9 +117,9 @@ public static function provideDataForConvertToString() : iterable CompositeExpression::TYPE_OR, [ 'u.group_id = 1', - new CompositeExpression( - CompositeExpression::TYPE_AND, - ['u.user = 1', 'u.group_id = 2'] + CompositeExpression::and( + 'u.user = 1', + 'u.group_id = 2' ), ], '(u.group_id = 1) OR ((u.user = 1) AND (u.group_id = 2))', diff --git a/tests/Doctrine/Tests/DBAL/Query/Expression/ExpressionBuilderTest.php b/tests/Doctrine/Tests/DBAL/Query/Expression/ExpressionBuilderTest.php index 817007d67d6..1c1915d7cb3 100644 --- a/tests/Doctrine/Tests/DBAL/Query/Expression/ExpressionBuilderTest.php +++ b/tests/Doctrine/Tests/DBAL/Query/Expression/ExpressionBuilderTest.php @@ -29,7 +29,19 @@ protected function setUp() : void /** * @param string[]|CompositeExpression[] $parts * - * @dataProvider provideDataForAndX + * @dataProvider provideDataForAnd + */ + public function testAnd(array $parts, string $expected) : void + { + $composite = $this->expr->and(...$parts); + + self::assertEquals($expected, (string) $composite); + } + + /** + * @param string[]|CompositeExpression[] $parts + * + * @dataProvider provideDataForAnd */ public function testAndX(array $parts, string $expected) : void { @@ -45,7 +57,7 @@ public function testAndX(array $parts, string $expected) : void /** * @return mixed[][] */ - public static function provideDataForAndX() : iterable + public static function provideDataForAnd() : iterable { return [ [ @@ -67,9 +79,9 @@ public static function provideDataForAndX() : iterable [ [ 'u.user = 1', - new CompositeExpression( - CompositeExpression::TYPE_OR, - ['u.group_id = 1', 'u.group_id = 2'] + CompositeExpression::or( + 'u.group_id = 1', + 'u.group_id = 2' ), ], '(u.user = 1) AND ((u.group_id = 1) OR (u.group_id = 2))', @@ -77,9 +89,9 @@ public static function provideDataForAndX() : iterable [ [ 'u.group_id = 1', - new CompositeExpression( - CompositeExpression::TYPE_AND, - ['u.user = 1', 'u.group_id = 2'] + CompositeExpression::and( + 'u.user = 1', + 'u.group_id = 2' ), ], '(u.group_id = 1) AND ((u.user = 1) AND (u.group_id = 2))', @@ -90,7 +102,19 @@ public static function provideDataForAndX() : iterable /** * @param string[]|CompositeExpression[] $parts * - * @dataProvider provideDataForOrX + * @dataProvider provideDataForOr + */ + public function testOr(array $parts, string $expected) : void + { + $composite = $this->expr->or(...$parts); + + self::assertEquals($expected, (string) $composite); + } + + /** + * @param string[]|CompositeExpression[] $parts + * + * @dataProvider provideDataForOr */ public function testOrX(array $parts, string $expected) : void { @@ -106,7 +130,7 @@ public function testOrX(array $parts, string $expected) : void /** * @return mixed[][] */ - public static function provideDataForOrX() : iterable + public static function provideDataForOr() : iterable { return [ [ @@ -128,9 +152,9 @@ public static function provideDataForOrX() : iterable [ [ 'u.user = 1', - new CompositeExpression( - CompositeExpression::TYPE_OR, - ['u.group_id = 1', 'u.group_id = 2'] + CompositeExpression::or( + 'u.group_id = 1', + 'u.group_id = 2' ), ], '(u.user = 1) OR ((u.group_id = 1) OR (u.group_id = 2))', @@ -138,9 +162,9 @@ public static function provideDataForOrX() : iterable [ [ 'u.group_id = 1', - new CompositeExpression( - CompositeExpression::TYPE_AND, - ['u.user = 1', 'u.group_id = 2'] + CompositeExpression::and( + 'u.user = 1', + 'u.group_id = 2' ), ], '(u.group_id = 1) OR ((u.user = 1) AND (u.group_id = 2))', diff --git a/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php b/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php index e19adad8940..20dd21594e1 100644 --- a/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php +++ b/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php @@ -68,7 +68,7 @@ public function testSelectWithSimpleWhere() : void $qb->select('u.id') ->from('users', 'u') - ->where($expr->andX($expr->eq('u.nickname', '?'))); + ->where($expr->and($expr->eq('u.nickname', '?'))); self::assertEquals('SELECT u.id FROM users u WHERE u.nickname = ?', (string) $qb); } diff --git a/tests/Doctrine/Tests/DbalPerformanceTestCase.php b/tests/Doctrine/Tests/DbalPerformanceTestCase.php deleted file mode 100644 index 9ab40f058b1..00000000000 --- a/tests/Doctrine/Tests/DbalPerformanceTestCase.php +++ /dev/null @@ -1,60 +0,0 @@ -startTime, 'Test timing was started'); - self::assertNotNull($this->runTime, 'Test timing was stopped'); - } - - /** - * begin timing - */ - protected function startTiming() : void - { - $this->startTime = microtime(true); - } - - /** - * end timing - */ - protected function stopTiming() : void - { - $this->runTime = microtime(true) - $this->startTime; - } - - /** - * @return float elapsed test execution time - */ - public function getTime() : float - { - return $this->runTime; - } -} diff --git a/tests/Doctrine/Tests/DbalPerformanceTestListener.php b/tests/Doctrine/Tests/DbalPerformanceTestListener.php deleted file mode 100644 index ba46ca04a68..00000000000 --- a/tests/Doctrine/Tests/DbalPerformanceTestListener.php +++ /dev/null @@ -1,62 +0,0 @@ -timings[$class])) { - $this->timings[$class] = []; - } - - // Store timing data for each test in the order they were run. - $this->timings[$class][$test->getName(true)] = $test->getTime(); - } - - /** - * Report performance test timings. - * - * Note: __destruct is used here because PHPUnit doesn't have a - * 'All tests over' hook. - */ - public function __destruct() - { - if (empty($this->timings)) { - return; - } - - // Report timings. - print "\nPerformance test results:\n\n"; - - foreach ($this->timings as $class => $tests) { - printf("%s:\n", $class); - foreach ($tests as $test => $time) { - printf("\t%s: %.3f seconds\n", $test, $time); - } - } - } -}