From 07a3820c5defa167d58ca7d8df2bcfdfb164c259 Mon Sep 17 00:00:00 2001 From: catch Date: Mon, 27 May 2019 14:29:04 +0100 Subject: [PATCH] Issue #3000931 by mondrake, voleger, andypost, longwave, alexpott, git commit -m 'Issue #3000931 by mondrake, voleger, andypost, longwave, alexpott: Connection::query() does not support '\''targe: Connection::query() does not support 'target' option --- core/includes/database.inc | 96 +++++++++---------- core/lib/Drupal/Core/Database/Connection.php | 10 +- .../Core/Database/DatabaseLegacyTest.php | 18 ++++ 3 files changed, 65 insertions(+), 59 deletions(-) diff --git a/core/includes/database.inc b/core/includes/database.inc index e5927fa65b9..df0b5acbc86 100644 --- a/core/includes/database.inc +++ b/core/includes/database.inc @@ -53,11 +53,7 @@ use Drupal\Core\Database\Query\Condition; * @see \Drupal\Core\Database\Connection::defaultOptions() */ function db_query($query, array $args = [], array $options = []) { - if (empty($options['target'])) { - $options['target'] = 'default'; - } - - return Database::getConnection($options['target'])->query($query, $args, $options); + return Database::getConnection(_db_get_target($options))->query($query, $args, $options); } /** @@ -92,11 +88,7 @@ function db_query($query, array $args = [], array $options = []) { */ function db_query_range($query, $from, $count, array $args = [], array $options = []) { @trigger_error('db_query_range() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call queryRange() on it. For example, $injected_database->queryRange($query, $from, $count, $args, $options). See https://www.drupal.org/node/2993033', E_USER_DEPRECATED); - if (empty($options['target'])) { - $options['target'] = 'default'; - } - - return Database::getConnection($options['target'])->queryRange($query, $from, $count, $args, $options); + return Database::getConnection(_db_get_target($options))->queryRange($query, $from, $count, $args, $options); } /** @@ -129,11 +121,7 @@ function db_query_range($query, $from, $count, array $args = [], array $options */ function db_query_temporary($query, array $args = [], array $options = []) { @trigger_error('db_query_temporary() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call queryTemporary() on it. For example, $injected_database->queryTemporary($query, $args, $options). See https://www.drupal.org/node/2993033', E_USER_DEPRECATED); - if (empty($options['target'])) { - $options['target'] = 'default'; - } - - return Database::getConnection($options['target'])->queryTemporary($query, $args, $options); + return Database::getConnection(_db_get_target($options))->queryTemporary($query, $args, $options); } /** @@ -157,10 +145,7 @@ function db_query_temporary($query, array $args = [], array $options = []) { */ function db_insert($table, array $options = []) { @trigger_error('db_insert() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call insert() on it. For example, $injected_database->insert($table, $options); See https://www.drupal.org/node/2993033', E_USER_DEPRECATED); - if (empty($options['target']) || $options['target'] == 'replica') { - $options['target'] = 'default'; - } - return Database::getConnection($options['target'])->insert($table, $options); + return Database::getConnection(_db_get_target($options, FALSE))->insert($table, $options); } /** @@ -184,12 +169,7 @@ function db_insert($table, array $options = []) { */ function db_merge($table, array $options = []) { @trigger_error('db_merge() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call merge() on it. For example, $injected_database->merge($table, $options). See https://www.drupal.org/node/2993033', E_USER_DEPRECATED); - // @todo Move away from here setting default target connection, - // https://www.drupal.org/node/2947775 - if (empty($options['target']) || $options['target'] == 'replica') { - $options['target'] = 'default'; - } - return Database::getConnection($options['target'])->merge($table, $options); + return Database::getConnection(_db_get_target($options, FALSE))->merge($table, $options); } /** @@ -213,10 +193,7 @@ function db_merge($table, array $options = []) { */ function db_update($table, array $options = []) { @trigger_error('db_update() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call call update() on it. For example, $injected_database->update($table, $options); See https://www.drupal.org/node/2993033', E_USER_DEPRECATED); - if (empty($options['target']) || $options['target'] == 'replica') { - $options['target'] = 'default'; - } - return Database::getConnection($options['target'])->update($table, $options); + return Database::getConnection(_db_get_target($options, FALSE))->update($table, $options); } /** @@ -240,12 +217,7 @@ function db_update($table, array $options = []) { */ function db_delete($table, array $options = []) { @trigger_error('db_delete is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call delete() on it. For example, $injected_database->delete($table, $options). See https://www.drupal.org/node/2993033', E_USER_DEPRECATED); - // @todo Move away from here setting default target connection, - // https://www.drupal.org/node/2947775 - if (empty($options['target']) || $options['target'] == 'replica') { - $options['target'] = 'default'; - } - return Database::getConnection($options['target'])->delete($table, $options); + return Database::getConnection(_db_get_target($options, FALSE))->delete($table, $options); } /** @@ -269,10 +241,7 @@ function db_delete($table, array $options = []) { */ function db_truncate($table, array $options = []) { @trigger_error('db_truncate() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call truncate() on it. For example, $injected_database->truncate($table, $options). See https://www.drupal.org/node/2993033', E_USER_DEPRECATED); - if (empty($options['target']) || $options['target'] == 'replica') { - $options['target'] = 'default'; - } - return Database::getConnection($options['target'])->truncate($table, $options); + return Database::getConnection(_db_get_target($options, FALSE))->truncate($table, $options); } /** @@ -300,10 +269,7 @@ function db_truncate($table, array $options = []) { */ function db_select($table, $alias = NULL, array $options = []) { @trigger_error('db_select() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call call select() on it. For example, $injected_database->db_select($table, $alias, $options); See https://www.drupal.org/node/2993033', E_USER_DEPRECATED); - if (empty($options['target'])) { - $options['target'] = 'default'; - } - return Database::getConnection($options['target'])->select($table, $alias, $options); + return Database::getConnection(_db_get_target($options))->select($table, $alias, $options); } /** @@ -328,12 +294,7 @@ function db_select($table, $alias = NULL, array $options = []) { */ function db_transaction($name = NULL, array $options = []) { @trigger_error('db_transaction is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call startTransaction() on it. For example, $injected_database->startTransaction($name). See https://www.drupal.org/node/2993033', E_USER_DEPRECATED); - // @todo Move away from here setting default target connection, - // https://www.drupal.org/node/2947775 - if (empty($options['target'])) { - $options['target'] = 'default'; - } - return Database::getConnection($options['target'])->startTransaction($name); + return Database::getConnection(_db_get_target($options))->startTransaction($name); } /** @@ -472,10 +433,41 @@ function db_driver() { */ function db_close(array $options = []) { @trigger_error('db_close() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Database\Database::closeConnection() instead. See https://www.drupal.org/node/2993033.', E_USER_DEPRECATED); - if (empty($options['target'])) { - $options['target'] = NULL; + Database::closeConnection(_db_get_target($options)); +} + +/** + * Get target helper. + * + * Helps get "target" database from the query options. + * + * @param array $options + * An array of options to control how the query operates. The array is passed + * by reference, and its 'target' key is removed from it during the process, + * so that it will not leak in calls to methods in the Database class. + * @param bool $allow_replica + * (Optional) When false, 'replica' connection will be redirected to the + * 'default' one. Defaults to TRUE. + * + * @return string + * The target database key for the database connection. + * + * @internal + * + * @deprecated in drupal:8.8.0 and will be removed from drupal:9.0.0. There is + * no replacement, this function should not be used. It was introduced in + * Drupal 8.8.0 only as a byproduct of the deprecation of the db_* procedural + * functions. + * + * @see https://www.drupal.org/node/2993033 + */ +function _db_get_target(array &$options, $allow_replica = TRUE) { + if (empty($options['target']) || ($options['target'] === 'replica' && !$allow_replica)) { + $options['target'] = 'default'; } - Database::closeConnection($options['target']); + $target = $options['target']; + unset($options['target']); + return $target; } /** diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php index e0a5d59d390..f45c359fd83 100644 --- a/core/lib/Drupal/Core/Database/Connection.php +++ b/core/lib/Drupal/Core/Database/Connection.php @@ -212,12 +212,6 @@ abstract class Connection { * * A given query can be customized with a number of option flags in an * associative array: - * - target: The database "target" against which to execute a query. Valid - * values are "default" or "replica". The system will first try to open a - * connection to a database specified with the user-supplied key. If one - * is not available, it will silently fall back to the "default" target. - * If multiple databases connections are specified with the same target, - * one will be selected at random for the duration of the request. * - fetch: This element controls how rows from a result set will be * returned. Legal values include PDO::FETCH_ASSOC, PDO::FETCH_BOTH, * PDO::FETCH_OBJ, PDO::FETCH_NUM, or a string representing the name of a @@ -260,7 +254,6 @@ abstract class Connection { */ protected function defaultOptions() { return [ - 'target' => 'default', 'fetch' => \PDO::FETCH_OBJ, 'return' => Database::RETURN_STATEMENT, 'throw_exception' => TRUE, @@ -606,6 +599,9 @@ abstract class Connection { public function query($query, array $args = [], $options = []) { // Use default values if not already set. $options += $this->defaultOptions(); + if (isset($options['target'])) { + @trigger_error('Passing a \'target\' key to \\Drupal\\Core\\Database\\Connection::query $options argument is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, use \\Drupal\\Core\\Database\\Database::getConnection($target)->query(). See https://www.drupal.org/node/2993033.', E_USER_DEPRECATED); + } try { // We allow either a pre-bound statement object or a literal string. diff --git a/core/tests/Drupal/KernelTests/Core/Database/DatabaseLegacyTest.php b/core/tests/Drupal/KernelTests/Core/Database/DatabaseLegacyTest.php index dd80305f1e9..becc74e0010 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/DatabaseLegacyTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/DatabaseLegacyTest.php @@ -428,6 +428,24 @@ class DatabaseLegacyTest extends DatabaseTestBase { $this->assertInstanceOf(Truncate::class, db_truncate('test')); } + /** + * Tests deprecation of the $options 'target' key in Connection::query. + * + * @expectedDeprecation Passing a 'target' key to \Drupal\Core\Database\Connection::query $options argument is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, use \Drupal\Core\Database\Database::getConnection($target)->query(). See https://www.drupal.org/node/2993033. + */ + public function testDbOptionsTarget() { + $this->assertNotNull($this->connection->query('SELECT * FROM {test}', [], ['target' => 'bar'])); + } + + /** + * Tests deprecation of the $options 'target' key in Select. + * + * @expectedDeprecation Passing a 'target' key to \Drupal\Core\Database\Connection::query $options argument is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Instead, use \Drupal\Core\Database\Database::getConnection($target)->query(). See https://www.drupal.org/node/2993033. + */ + public function testDbOptionsTargetInSelect() { + $this->assertNotNull($this->connection->select('test', 't', ['target' => 'bar'])->fields('t')->execute()); + } + /** * Tests deprecation of the db_query_temporary() function. *