SchemaTest.php
Same filename in this branch
Same filename in other branches
- 9 core/modules/mysql/tests/src/Kernel/mysql/SchemaTest.php
- 9 core/modules/pgsql/tests/src/Unit/SchemaTest.php
- 9 core/modules/pgsql/tests/src/Kernel/pgsql/SchemaTest.php
- 9 core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
- 8.9.x core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
- 10 core/modules/sqlite/tests/src/Kernel/sqlite/SchemaTest.php
- 10 core/modules/mysql/tests/src/Kernel/mysql/SchemaTest.php
- 10 core/modules/pgsql/tests/src/Unit/SchemaTest.php
- 10 core/modules/pgsql/tests/src/Kernel/pgsql/SchemaTest.php
Namespace
Drupal\Tests\mysql\Kernel\mysqlFile
-
core/
modules/ mysql/ tests/ src/ Kernel/ mysql/ SchemaTest.php
View source
<?php
declare (strict_types=1);
namespace Drupal\Tests\mysql\Kernel\mysql;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Database\DatabaseExceptionWrapper;
use Drupal\Core\Database\Exception\SchemaTableColumnSizeTooLargeException;
use Drupal\Core\Database\Exception\SchemaTableKeyTooLargeException;
use Drupal\Core\Database\SchemaException;
use Drupal\Core\Database\SchemaObjectDoesNotExistException;
use Drupal\Core\Database\SchemaObjectExistsException;
use Drupal\KernelTests\Core\Database\DriverSpecificSchemaTestBase;
/**
* Tests schema API for the MySQL driver.
*
* @group Database
*/
class SchemaTest extends DriverSpecificSchemaTestBase {
/**
* {@inheritdoc}
*/
public function checkSchemaComment(string $description, string $table, ?string $column = NULL) : void {
$comment = $this->schema
->getComment($table, $column);
$max_length = $column ? 255 : 60;
$description = Unicode::truncate($description, $max_length, TRUE, TRUE);
$this->assertSame($description, $comment, 'The comment matches the schema description.');
}
/**
* {@inheritdoc}
*/
protected function assertCollation() : void {
// Make sure that varchar fields have the correct collations.
$columns = $this->connection
->query('SHOW FULL COLUMNS FROM {test_table}');
foreach ($columns as $column) {
if ($column->Field == 'test_field_string') {
$string_check = $column->Collation;
}
if ($column->Field == 'test_field_string_ascii') {
$string_ascii_check = $column->Collation;
}
}
$this->assertMatchesRegularExpression('#^(utf8mb4_general_ci|utf8mb4_0900_ai_ci)$#', $string_check, 'test_field_string should have a utf8mb4_general_ci or a utf8mb4_0900_ai_ci collation, but it has not.');
$this->assertSame('ascii_general_ci', $string_ascii_check, 'test_field_string_ascii should have a ascii_general_ci collation, but it has not.');
}
/**
* {@inheritdoc}
*/
public function testTableWithSpecificDataType() : void {
$table_specification = [
'description' => 'Schema table description.',
'fields' => [
'timestamp' => [
'mysql_type' => 'timestamp',
'not null' => FALSE,
'default' => NULL,
],
],
];
$this->schema
->createTable('test_timestamp', $table_specification);
$this->assertTrue($this->schema
->tableExists('test_timestamp'));
}
/**
* Tests that indexes on string fields are limited to 191 characters on MySQL.
*
* @see \Drupal\mysql\Driver\Database\mysql\Schema::getNormalizedIndexes()
*/
public function testIndexLength() : void {
$table_specification = [
'fields' => [
'id' => [
'type' => 'int',
'default' => NULL,
],
'test_field_text' => [
'type' => 'text',
'not null' => TRUE,
],
'test_field_string_long' => [
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
],
'test_field_string_ascii_long' => [
'type' => 'varchar_ascii',
'length' => 255,
],
'test_field_string_short' => [
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
],
],
'indexes' => [
'test_regular' => [
'test_field_text',
'test_field_string_long',
'test_field_string_ascii_long',
'test_field_string_short',
],
'test_length' => [
[
'test_field_text',
128,
],
[
'test_field_string_long',
128,
],
[
'test_field_string_ascii_long',
128,
],
[
'test_field_string_short',
128,
],
],
'test_mixed' => [
[
'test_field_text',
200,
],
'test_field_string_long',
[
'test_field_string_ascii_long',
200,
],
'test_field_string_short',
],
],
];
$this->schema
->createTable('test_table_index_length', $table_specification);
// Ensure expected exception thrown when adding index with missing info.
$expected_exception_message = "MySQL needs the 'test_field_text' field specification in order to normalize the 'test_regular' index";
$missing_field_spec = $table_specification;
unset($missing_field_spec['fields']['test_field_text']);
try {
$this->schema
->addIndex('test_table_index_length', 'test_separate', [
[
'test_field_text',
200,
],
], $missing_field_spec);
$this->fail('SchemaException not thrown when adding index with missing information.');
} catch (SchemaException $e) {
$this->assertEquals($expected_exception_message, $e->getMessage());
}
// Add a separate index.
$this->schema
->addIndex('test_table_index_length', 'test_separate', [
[
'test_field_text',
200,
],
], $table_specification);
$table_specification_with_new_index = $table_specification;
$table_specification_with_new_index['indexes']['test_separate'] = [
[
'test_field_text',
200,
],
];
// Ensure that the exceptions of addIndex are thrown as expected.
try {
$this->schema
->addIndex('test_table_index_length', 'test_separate', [
[
'test_field_text',
200,
],
], $table_specification);
$this->fail('\\Drupal\\Core\\Database\\SchemaObjectExistsException exception missed.');
} catch (SchemaObjectExistsException) {
// Expected exception; just continue testing.
}
try {
$this->schema
->addIndex('test_table_non_existing', 'test_separate', [
[
'test_field_text',
200,
],
], $table_specification);
$this->fail('\\Drupal\\Core\\Database\\SchemaObjectDoesNotExistException exception missed.');
} catch (SchemaObjectDoesNotExistException) {
// Expected exception; just continue testing.
}
// Get index information.
$results = $this->connection
->query('SHOW INDEX FROM {test_table_index_length}');
$expected_lengths = [
'test_regular' => [
'test_field_text' => 191,
'test_field_string_long' => 191,
'test_field_string_ascii_long' => NULL,
'test_field_string_short' => NULL,
],
'test_length' => [
'test_field_text' => 128,
'test_field_string_long' => 128,
'test_field_string_ascii_long' => 128,
'test_field_string_short' => NULL,
],
'test_mixed' => [
'test_field_text' => 191,
'test_field_string_long' => 191,
'test_field_string_ascii_long' => 200,
'test_field_string_short' => NULL,
],
'test_separate' => [
'test_field_text' => 191,
],
];
// Count the number of columns defined in the indexes.
$column_count = 0;
foreach ($table_specification_with_new_index['indexes'] as $index) {
$column_count += count($index);
}
$test_count = 0;
foreach ($results as $result) {
$this->assertEquals($expected_lengths[$result->Key_name][$result->Column_name], $result->Sub_part, 'Index length matches expected value.');
$test_count++;
}
$this->assertEquals($column_count, $test_count, 'Number of tests matches expected value.');
}
/**
* @covers \Drupal\mysql\Driver\Database\mysql\Schema::introspectIndexSchema
*/
public function testIntrospectIndexSchema() : void {
$table_specification = [
'fields' => [
'id' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
],
'test_field_1' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
],
'test_field_2' => [
'type' => 'int',
'default' => 0,
],
'test_field_3' => [
'type' => 'int',
'default' => 0,
],
'test_field_4' => [
'type' => 'int',
'default' => 0,
],
'test_field_5' => [
'type' => 'int',
'default' => 0,
],
],
'primary key' => [
'id',
'test_field_1',
],
'unique keys' => [
'test_field_2' => [
'test_field_2',
],
'test_field_3_test_field_4' => [
'test_field_3',
'test_field_4',
],
],
'indexes' => [
'test_field_4' => [
'test_field_4',
],
'test_field_4_test_field_5' => [
'test_field_4',
'test_field_5',
],
],
];
$table_name = strtolower($this->getRandomGenerator()
->name());
$this->schema
->createTable($table_name, $table_specification);
unset($table_specification['fields']);
$introspect_index_schema = new \ReflectionMethod(get_class($this->schema), 'introspectIndexSchema');
$index_schema = $introspect_index_schema->invoke($this->schema, $table_name);
$this->assertEquals($table_specification, $index_schema);
}
/**
* Tests SchemaTableKeyTooLargeException.
*/
public function testSchemaTableKeyTooLargeException() : void {
$this->expectException(SchemaTableKeyTooLargeException::class);
$this->schema
->createTable('test_schema', [
'description' => 'Tests SchemaTableKeyTooLargeException.',
'fields' => [
'id' => [
'type' => 'varchar',
'length' => 64,
'not null' => TRUE,
],
'id1' => [
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
],
'id2' => [
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
],
'id3' => [
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
],
'id4' => [
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
],
'id5' => [
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
],
],
'primary key' => [
'id',
],
'indexes' => [
'key1' => [
'id1',
'id2',
'id3',
'id4',
'id5',
],
],
]);
}
/**
* Tests SchemaTableColumnSizeTooLargeException.
*/
public function testSchemaTableColumnSizeTooLargeException() : void {
$this->expectException(SchemaTableColumnSizeTooLargeException::class);
$this->expectExceptionMessage("Column length too big for column 'too_large' (max = 16383); use BLOB or TEXT instead");
$this->schema
->createTable('test_schema', [
'description' => 'Tests SchemaTableColumnSizeTooLargeException.',
'fields' => [
'too_large' => [
'type' => 'varchar',
'length' => 65536,
'not null' => TRUE,
],
],
]);
}
/**
* Tests adding a primary key when sql_generate_invisible_primary_key is on.
*/
public function testGeneratedInvisiblePrimaryKey() : void {
$is_maria = method_exists($this->connection, 'isMariaDb') && $this->connection
->isMariaDb();
if ($this->connection
->databaseType() !== 'mysql' || $is_maria || version_compare($this->connection
->version(), '8.0.30', '<')) {
$this->markTestSkipped('This test only runs on MySQL 8.0.30 and above');
}
try {
$this->connection
->query("SET sql_generate_invisible_primary_key = 1;")
->execute();
} catch (DatabaseExceptionWrapper) {
$this->markTestSkipped('This test requires the SESSION_VARIABLES_ADMIN privilege.');
}
$this->schema
->createTable('test_primary_key', [
'fields' => [
'foo' => [
'type' => 'varchar',
'length' => 1,
],
],
]);
$this->schema
->addField('test_primary_key', 'id', [
'type' => 'serial',
'not null' => TRUE,
], [
'primary key' => [
'id',
],
]);
$this->assertTrue($this->schema
->fieldExists('test_primary_key', 'id'));
}
}
Classes
Title | Deprecated | Summary |
---|---|---|
SchemaTest | Tests schema API for the MySQL driver. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.