function SchemaTest::testSchemaChangePrimaryKey

Same name in other branches
  1. 8.9.x 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 682

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));
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.