You are here

public function SchemaTest::testSchemaChangePrimaryKey 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::testSchemaChangePrimaryKey()
  2. 10 core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php \Drupal\KernelTests\Core\Database\SchemaTest::testSchemaChangePrimaryKey()

Tests various schema changes' effect on the table's primary key.

@dataProvider providerTestSchemaCreateTablePrimaryKey

@covers ::addField @covers ::changeField @covers ::dropField @covers ::findPrimaryKeyColumns

Parameters

array $initial_primary_key: The initial primary key of the test table.

array $renamed_primary_key: The primary key of the test table after renaming the test field.

File

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

Class

SchemaTest
Tests table creation and modification via the schema API.

Namespace

Drupal\KernelTests\Core\Database

Code

public function testSchemaChangePrimaryKey(array $initial_primary_key, array $renamed_primary_key) {
  $find_primary_key_columns = new \ReflectionMethod(get_class($this->schema), 'findPrimaryKeyColumns');
  $find_primary_key_columns
    ->setAccessible(TRUE);

  // Test making the field the primary key of the table upon creation.
  $table_name = 'test_table';
  $table_spec = [
    'fields' => [
      'test_field' => [
        'type' => 'int',
        'not null' => TRUE,
      ],
      'other_test_field' => [
        'type' => 'int',
        'not null' => TRUE,
      ],
    ],
    'primary key' => $initial_primary_key,
  ];
  $this->schema
    ->createTable($table_name, $table_spec);
  $this
    ->assertTrue($this->schema
    ->fieldExists($table_name, 'test_field'));
  $this
    ->assertEquals($initial_primary_key, $find_primary_key_columns
    ->invoke($this->schema, $table_name));

  // Change the field type and make sure the primary key stays in place.
  $this->schema
    ->changeField($table_name, 'test_field', 'test_field', [
    'type' => 'varchar',
    'length' => 32,
    'not null' => TRUE,
  ]);
  $this
    ->assertTrue($this->schema
    ->fieldExists($table_name, 'test_field'));
  $this
    ->assertEquals($initial_primary_key, $find_primary_key_columns
    ->invoke($this->schema, $table_name));

  // Add some data and change the field type back, to make sure that changing
  // the type leaves the primary key in place even with existing data.
  $this->connection
    ->insert($table_name)
    ->fields([
    'test_field' => 1,
    'other_test_field' => 2,
  ])
    ->execute();
  $this->schema
    ->changeField($table_name, 'test_field', 'test_field', [
    'type' => 'int',
    'not null' => TRUE,
  ]);
  $this
    ->assertTrue($this->schema
    ->fieldExists($table_name, 'test_field'));
  $this
    ->assertEquals($initial_primary_key, $find_primary_key_columns
    ->invoke($this->schema, $table_name));

  // Make sure that adding the primary key can be done as part of changing
  // a field, as well.
  $this->schema
    ->dropPrimaryKey($table_name);
  $this
    ->assertEquals([], $find_primary_key_columns
    ->invoke($this->schema, $table_name));
  $this->schema
    ->changeField($table_name, 'test_field', 'test_field', [
    'type' => 'int',
    'not null' => TRUE,
  ], [
    'primary key' => $initial_primary_key,
  ]);
  $this
    ->assertTrue($this->schema
    ->fieldExists($table_name, 'test_field'));
  $this
    ->assertEquals($initial_primary_key, $find_primary_key_columns
    ->invoke($this->schema, $table_name));

  // Rename the field and make sure the primary key was updated.
  $this->schema
    ->changeField($table_name, 'test_field', 'test_field_renamed', [
    'type' => 'int',
    'not null' => TRUE,
  ]);
  $this
    ->assertTrue($this->schema
    ->fieldExists($table_name, 'test_field_renamed'));
  $this
    ->assertEquals($renamed_primary_key, $find_primary_key_columns
    ->invoke($this->schema, $table_name));

  // Drop the field and make sure the primary key was dropped, as well.
  $this->schema
    ->dropField($table_name, 'test_field_renamed');
  $this
    ->assertFalse($this->schema
    ->fieldExists($table_name, 'test_field_renamed'));
  $this
    ->assertEquals([], $find_primary_key_columns
    ->invoke($this->schema, $table_name));

  // Add the field again and make sure adding the primary key can be done at
  // the same time.
  $this->schema
    ->addField($table_name, 'test_field', [
    'type' => 'int',
    'default' => 0,
    'not null' => TRUE,
  ], [
    'primary key' => $initial_primary_key,
  ]);
  $this
    ->assertTrue($this->schema
    ->fieldExists($table_name, 'test_field'));
  $this
    ->assertEquals($initial_primary_key, $find_primary_key_columns
    ->invoke($this->schema, $table_name));

  // Drop the field again and explicitly add a primary key.
  $this->schema
    ->dropField($table_name, 'test_field');
  $this->schema
    ->addPrimaryKey($table_name, [
    'other_test_field',
  ]);
  $this
    ->assertFalse($this->schema
    ->fieldExists($table_name, 'test_field'));
  $this
    ->assertEquals([
    'other_test_field',
  ], $find_primary_key_columns
    ->invoke($this->schema, $table_name));

  // Test that adding a field with a primary key will work even with a
  // pre-existing primary key.
  $this->schema
    ->addField($table_name, 'test_field', [
    'type' => 'int',
    'default' => 0,
    'not null' => TRUE,
  ], [
    'primary key' => $initial_primary_key,
  ]);
  $this
    ->assertTrue($this->schema
    ->fieldExists($table_name, 'test_field'));
  $this
    ->assertEquals($initial_primary_key, $find_primary_key_columns
    ->invoke($this->schema, $table_name));
}