Loading core/lib/Drupal/Core/Database/SupportsTemporaryTablesInterface.php 0 → 100644 +39 −0 Original line number Diff line number Diff line <?php namespace Drupal\Core\Database; /** * Adds support for temporary tables. * * @ingroup database */ interface SupportsTemporaryTablesInterface { /** * Runs a SELECT query and stores its results in a temporary table. * * Use this as a substitute for ->query() when the results need to stored * in a temporary table. Temporary tables exist for the duration of the page * request. User-supplied arguments to the query should be passed in as * separate parameters so that they can be properly escaped to avoid SQL * injection attacks. * * Note that if you need to know how many results were returned, you should do * a SELECT COUNT(*) on the temporary table afterwards. * * @param string $query * A string containing a normal SELECT SQL query. * @param array $args * (optional) An array of values to substitute into the query at placeholder * markers. * @param array $options * (optional) An associative array of options to control how the query is * run. See the documentation for DatabaseConnection::defaultOptions() for * details. * * @return string * The name of the temporary table. */ public function queryTemporary($query, array $args = [], array $options = []); } core/misc/cspell/dictionary.txt +2 −0 Original line number Diff line number Diff line Loading @@ -1024,6 +1024,7 @@ renderered renormalize reparenting reparsed relpersistence replyto resave resaved Loading @@ -1042,6 +1043,7 @@ revisionid revisioning revlog revpub relname ribisi ritchie rolename Loading core/modules/mysql/src/Driver/Database/mysql/Connection.php +11 −1 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ use Drupal\Core\Database\DatabaseNotFoundException; use Drupal\Core\Database\DatabaseException; use Drupal\Core\Database\Connection as DatabaseConnection; use Drupal\Core\Database\SupportsTemporaryTablesInterface; use Drupal\Core\Database\TransactionNoActiveException; /** Loading @@ -19,7 +20,7 @@ /** * MySQL implementation of \Drupal\Core\Database\Connection. */ class Connection extends DatabaseConnection { class Connection extends DatabaseConnection implements SupportsTemporaryTablesInterface { /** * Error code for "Unknown database" error. Loading Loading @@ -222,6 +223,15 @@ public function queryRange($query, $from, $count, array $args = [], array $optio return $this->query($query . ' LIMIT ' . (int) $from . ', ' . (int) $count, $args, $options); } /** * {@inheritdoc} */ public function queryTemporary($query, array $args = [], array $options = []) { $tablename = 'db_temporary_' . uniqid(); $this->query('CREATE TEMPORARY TABLE {' . $tablename . '} Engine=MEMORY ' . $query, $args, $options); return $tablename; } public function driver() { return 'mysql'; } Loading core/modules/mysql/tests/src/Kernel/mysql/TemporaryQueryTest.php 0 → 100644 +39 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\mysql\Kernel\mysql; use Drupal\KernelTests\Core\Database\TemporaryQueryTestBase; /** * Tests the temporary query functionality. * * @group Database */ class TemporaryQueryTest extends TemporaryQueryTestBase { /** * Confirms that temporary tables work. */ public function testTemporaryQuery() { parent::testTemporaryQuery(); $connection = $this->getConnection(); $table_name_test = $connection->queryTemporary('SELECT [name] FROM {test}', []); // Assert that the table is indeed a temporary one. $temporary_table_info = $connection->query("SHOW CREATE TABLE {" . $table_name_test . "}")->fetchAssoc(); $this->stringContains($temporary_table_info["Create Table"], "CREATE TEMPORARY TABLE"); // Assert that both have the same field names. $normal_table_fields = $connection->query("SELECT * FROM {test}")->fetch(); $temp_table_name = $connection->queryTemporary('SELECT * FROM {test}'); $temp_table_fields = $connection->query("SELECT * FROM {" . $temp_table_name . "}")->fetch(); $normal_table_fields = array_keys(get_object_vars($normal_table_fields)); $temp_table_fields = array_keys(get_object_vars($temp_table_fields)); $this->assertEmpty(array_diff($normal_table_fields, $temp_table_fields)); } } core/modules/pgsql/src/Driver/Database/pgsql/Connection.php +11 −1 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ use Drupal\Core\Database\DatabaseNotFoundException; use Drupal\Core\Database\StatementInterface; use Drupal\Core\Database\StatementWrapper; use Drupal\Core\Database\SupportsTemporaryTablesInterface; // cSpell:ignore ilike nextval Loading @@ -19,7 +20,7 @@ /** * PostgreSQL implementation of \Drupal\Core\Database\Connection. */ class Connection extends DatabaseConnection { class Connection extends DatabaseConnection implements SupportsTemporaryTablesInterface { /** * The name by which to obtain a lock for retrieve the next insert id. Loading Loading @@ -209,6 +210,15 @@ public function queryRange($query, $from, $count, array $args = [], array $optio return $this->query($query . ' LIMIT ' . (int) $count . ' OFFSET ' . (int) $from, $args, $options); } /** * {@inheritdoc} */ public function queryTemporary($query, array $args = [], array $options = []) { $tablename = 'db_temporary_' . uniqid(); $this->query('CREATE TEMPORARY TABLE {' . $tablename . '} AS ' . $query, $args, $options); return $tablename; } public function driver() { return 'pgsql'; } Loading Loading
core/lib/Drupal/Core/Database/SupportsTemporaryTablesInterface.php 0 → 100644 +39 −0 Original line number Diff line number Diff line <?php namespace Drupal\Core\Database; /** * Adds support for temporary tables. * * @ingroup database */ interface SupportsTemporaryTablesInterface { /** * Runs a SELECT query and stores its results in a temporary table. * * Use this as a substitute for ->query() when the results need to stored * in a temporary table. Temporary tables exist for the duration of the page * request. User-supplied arguments to the query should be passed in as * separate parameters so that they can be properly escaped to avoid SQL * injection attacks. * * Note that if you need to know how many results were returned, you should do * a SELECT COUNT(*) on the temporary table afterwards. * * @param string $query * A string containing a normal SELECT SQL query. * @param array $args * (optional) An array of values to substitute into the query at placeholder * markers. * @param array $options * (optional) An associative array of options to control how the query is * run. See the documentation for DatabaseConnection::defaultOptions() for * details. * * @return string * The name of the temporary table. */ public function queryTemporary($query, array $args = [], array $options = []); }
core/misc/cspell/dictionary.txt +2 −0 Original line number Diff line number Diff line Loading @@ -1024,6 +1024,7 @@ renderered renormalize reparenting reparsed relpersistence replyto resave resaved Loading @@ -1042,6 +1043,7 @@ revisionid revisioning revlog revpub relname ribisi ritchie rolename Loading
core/modules/mysql/src/Driver/Database/mysql/Connection.php +11 −1 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ use Drupal\Core\Database\DatabaseNotFoundException; use Drupal\Core\Database\DatabaseException; use Drupal\Core\Database\Connection as DatabaseConnection; use Drupal\Core\Database\SupportsTemporaryTablesInterface; use Drupal\Core\Database\TransactionNoActiveException; /** Loading @@ -19,7 +20,7 @@ /** * MySQL implementation of \Drupal\Core\Database\Connection. */ class Connection extends DatabaseConnection { class Connection extends DatabaseConnection implements SupportsTemporaryTablesInterface { /** * Error code for "Unknown database" error. Loading Loading @@ -222,6 +223,15 @@ public function queryRange($query, $from, $count, array $args = [], array $optio return $this->query($query . ' LIMIT ' . (int) $from . ', ' . (int) $count, $args, $options); } /** * {@inheritdoc} */ public function queryTemporary($query, array $args = [], array $options = []) { $tablename = 'db_temporary_' . uniqid(); $this->query('CREATE TEMPORARY TABLE {' . $tablename . '} Engine=MEMORY ' . $query, $args, $options); return $tablename; } public function driver() { return 'mysql'; } Loading
core/modules/mysql/tests/src/Kernel/mysql/TemporaryQueryTest.php 0 → 100644 +39 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\mysql\Kernel\mysql; use Drupal\KernelTests\Core\Database\TemporaryQueryTestBase; /** * Tests the temporary query functionality. * * @group Database */ class TemporaryQueryTest extends TemporaryQueryTestBase { /** * Confirms that temporary tables work. */ public function testTemporaryQuery() { parent::testTemporaryQuery(); $connection = $this->getConnection(); $table_name_test = $connection->queryTemporary('SELECT [name] FROM {test}', []); // Assert that the table is indeed a temporary one. $temporary_table_info = $connection->query("SHOW CREATE TABLE {" . $table_name_test . "}")->fetchAssoc(); $this->stringContains($temporary_table_info["Create Table"], "CREATE TEMPORARY TABLE"); // Assert that both have the same field names. $normal_table_fields = $connection->query("SELECT * FROM {test}")->fetch(); $temp_table_name = $connection->queryTemporary('SELECT * FROM {test}'); $temp_table_fields = $connection->query("SELECT * FROM {" . $temp_table_name . "}")->fetch(); $normal_table_fields = array_keys(get_object_vars($normal_table_fields)); $temp_table_fields = array_keys(get_object_vars($temp_table_fields)); $this->assertEmpty(array_diff($normal_table_fields, $temp_table_fields)); } }
core/modules/pgsql/src/Driver/Database/pgsql/Connection.php +11 −1 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ use Drupal\Core\Database\DatabaseNotFoundException; use Drupal\Core\Database\StatementInterface; use Drupal\Core\Database\StatementWrapper; use Drupal\Core\Database\SupportsTemporaryTablesInterface; // cSpell:ignore ilike nextval Loading @@ -19,7 +20,7 @@ /** * PostgreSQL implementation of \Drupal\Core\Database\Connection. */ class Connection extends DatabaseConnection { class Connection extends DatabaseConnection implements SupportsTemporaryTablesInterface { /** * The name by which to obtain a lock for retrieve the next insert id. Loading Loading @@ -209,6 +210,15 @@ public function queryRange($query, $from, $count, array $args = [], array $optio return $this->query($query . ' LIMIT ' . (int) $count . ' OFFSET ' . (int) $from, $args, $options); } /** * {@inheritdoc} */ public function queryTemporary($query, array $args = [], array $options = []) { $tablename = 'db_temporary_' . uniqid(); $this->query('CREATE TEMPORARY TABLE {' . $tablename . '} AS ' . $query, $args, $options); return $tablename; } public function driver() { return 'pgsql'; } Loading