You are here

public function SchemaTest::testIndexLength in Drupal 9

Same name and namespace in other branches
  1. 8 core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php \Drupal\KernelTests\Core\Database\SchemaTest::testIndexLength()
  2. 10 core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php \Drupal\KernelTests\Core\Database\SchemaTest::testIndexLength()

Tests that indexes on string fields are limited to 191 characters on MySQL.

See also

\Drupal\Core\Database\Driver\mysql\Schema::getNormalizedIndexes()

File

core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php, line 360

Class

SchemaTest
Tests table creation and modification via the schema API.

Namespace

Drupal\KernelTests\Core\Database

Code

public function testIndexLength() {
  if ($this->connection
    ->databaseType() !== 'mysql') {
    $this
      ->markTestSkipped("The '{$this->connection->databaseType()}' database type does not support setting column length for indexes.");
  }
  $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 $e) {

    // 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 $e) {

    // 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) {
    foreach ($index as $field) {
      $column_count++;
    }
  }
  $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.');
}