diff -u b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php --- b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php +++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php @@ -337,6 +337,7 @@ if ($this->tableExists($destination)) { throw new SchemaObjectExistsException(t("Cannot copy @source to @destination: table @destination already exists.", array('@source' => $source, '@destination' => $destination))); } + $info = $this->getPrefixInfo($destination); return $this->connection->query('CREATE TABLE `' . $info['table'] . '` LIKE {' . $source . '}'); } diff -u b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php --- b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php +++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php @@ -358,6 +358,9 @@ if ($this->tableExists($destination)) { throw new SchemaObjectExistsException(t("Cannot copy @source to @destination: table @destination already exists.", array('@source' => $source, '@destination' => $destination))); } + // @TODO The server is likely going to rename indexes and constraints + // during the copy process, and it will not match our + // table_name + constraint name convention anymore. Fix this. $info = $this->getPrefixInfo($destination); return $this->connection->query('CREATE TABLE `' . $info['table'] . '` (LIKE {' . $source . '} INCLUDING ALL)'); } diff -u b/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php --- b/core/lib/Drupal/Core/Database/Schema.php +++ b/core/lib/Drupal/Core/Database/Schema.php @@ -408,7 +408,7 @@ abstract public function dropTable($table); /** - * Copies a table. + * Copies the structure of a table without copying the content. * * @param string $source * The name of the table to be used as source. @@ -417,6 +417,11 @@ * * @return \Drupal\Core\Database\StatementInterface * The result of the executed query. + * + * @throws \Drupal\Core\Database\SchemaObjectExistsException + * Thrown when the source table does not exist. + * @throws \Drupal\Core\Database\SchemaObjectDoesNotExistException + * Thrown when the destination table already exists. */ abstract public function copyTable($source, $destination); only in patch2: unchanged: --- a/core/modules/system/lib/Drupal/system/Tests/Database/SchemaTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Database/SchemaTest.php @@ -87,6 +87,19 @@ function testSchema() { $index_exists = Database::getConnection()->schema()->indexExists('test_table2', 'test_field'); $this->assertTrue($index_exists, 'Index was renamed.'); + // Copy the schema of the table. + db_copy_table('test_table2', 'test_table3'); + + // Index should be copied. + $index_exists = Database::getConnection()->schema()->indexExists('test_table3', 'test_field'); + $this->assertTrue($index_exists, 'Index was copied.'); + + // Data should still exist on the old table but not on the new one. + $count = db_select('test_table2')->countQuery()->execute()->fetchField(); + $this->assertEqual($count, 1, 'The old table still has its content.'); + $count = db_select('test_table3')->countQuery()->execute()->fetchField(); + $this->assertEqual($count, 0, 'The new table has no content.'); + // We need the default so that we can insert after the rename. db_field_set_default('test_table2', 'test_field', 0); $this->assertFalse($this->tryInsert(), 'Insert into the old table failed.'); @@ -154,9 +167,9 @@ function testSchema() { */ function tryInsert($table = 'test_table') { try { - db_insert($table) - ->fields(array('id' => mt_rand(10, 20))) - ->execute(); + db_insert($table) + ->fields(array('id' => mt_rand(10, 20))) + ->execute(); return TRUE; } catch (\Exception $e) { @@ -227,8 +240,8 @@ function testUnsignedColumns() { function tryUnsignedInsert($table_name, $column_name) { try { db_insert($table_name) - ->fields(array($column_name => -1)) - ->execute(); + ->fields(array($column_name => -1)) + ->execute(); return TRUE; } catch (\Exception $e) {