Loading core/modules/pgsql/src/Driver/Database/pgsql/Schema.php +33 −6 Original line number Diff line number Diff line Loading @@ -893,12 +893,11 @@ public function changeField($table, $field, $field_new, $spec, $new_keys = []) { // Type 'serial' is known to PostgreSQL, but only during table creation, // not when altering. Because of that, we create it here as an 'int'. After // we create it we manually re-apply the sequence. if (in_array($spec['pgsql_type'], ['serial', 'bigserial'])) { $field_def = 'int'; } else { $field_def = $spec['pgsql_type']; } $field_def = match($spec['pgsql_type']) { 'serial' => 'int', 'bigserial' => 'bigint', default => $spec['pgsql_type'], }; if (in_array($spec['pgsql_type'], ['varchar', 'character', 'text']) && isset($spec['length'])) { $field_def .= '(' . $spec['length'] . ')'; Loading @@ -910,6 +909,14 @@ public function changeField($table, $field, $field_new, $spec, $new_keys = []) { // Remove old check constraints. $field_info = $this->queryFieldInformation($table, $field); // Remove old sequence. $seq_name = $this->getSequenceName($table, $field); if (!empty($seq_name)) { // We need to add CASCADE otherwise we cannot alter the sequence because // the table depends on it. $this->connection->query('DROP SEQUENCE IF EXISTS ' . $seq_name . ' CASCADE'); } foreach ($field_info as $check) { $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT [' . $check . ']'); } Loading Loading @@ -1062,6 +1069,26 @@ public function extensionExists($name): bool { ])->fetchField(); } /** * Retrieves a sequence name that is owned by the table and column.. * * @param string $table * A table name that is not prefixed or quoted. * @param string $column * The column name. * * @return string|null * The name of the sequence or NULL if it does not exist. */ protected function getSequenceName(string $table, string $column): ?string { return $this->connection ->query("SELECT pg_get_serial_sequence(:table, :column)", [ ':table' => $this->connection->getPrefix() . $table, ':column' => $column, ]) ->fetchField(); } } /** Loading core/tests/Drupal/KernelTests/Core/Database/DriverSpecificSchemaTestBase.php +42 −0 Original line number Diff line number Diff line Loading @@ -1308,4 +1308,46 @@ public function testReservedKeywordsForNaming(): void { $this->assertFalse($this->schema->tableExists($table_name_new)); } /** * Tests changing a field length. */ public function testChangeSerialFieldLength(): void { $specification = [ 'fields' => [ 'id' => [ 'type' => 'serial', 'not null' => TRUE, 'description' => 'Primary Key: Unique ID.', ], 'text' => [ 'type' => 'text', 'description' => 'A text field', ], ], 'primary key' => ['id'], ]; $this->schema->createTable('change_serial_to_big', $specification); // Increase the size of the field. $new_specification = [ 'size' => 'big', 'type' => 'serial', 'not null' => TRUE, 'description' => 'Primary Key: Unique ID.', ]; $this->schema->changeField('change_serial_to_big', 'id', 'id', $new_specification); $this->assertTrue($this->schema->fieldExists('change_serial_to_big', 'id')); // Test if we can actually add a big int. $id = $this->connection->insert('change_serial_to_big')->fields([ 'id' => 21474836470, ])->execute(); $id_two = $this->connection->insert('change_serial_to_big')->fields([ 'text' => 'Testing for ID generation', ])->execute(); $this->assertEquals($id + 1, $id_two); } } Loading
core/modules/pgsql/src/Driver/Database/pgsql/Schema.php +33 −6 Original line number Diff line number Diff line Loading @@ -893,12 +893,11 @@ public function changeField($table, $field, $field_new, $spec, $new_keys = []) { // Type 'serial' is known to PostgreSQL, but only during table creation, // not when altering. Because of that, we create it here as an 'int'. After // we create it we manually re-apply the sequence. if (in_array($spec['pgsql_type'], ['serial', 'bigserial'])) { $field_def = 'int'; } else { $field_def = $spec['pgsql_type']; } $field_def = match($spec['pgsql_type']) { 'serial' => 'int', 'bigserial' => 'bigint', default => $spec['pgsql_type'], }; if (in_array($spec['pgsql_type'], ['varchar', 'character', 'text']) && isset($spec['length'])) { $field_def .= '(' . $spec['length'] . ')'; Loading @@ -910,6 +909,14 @@ public function changeField($table, $field, $field_new, $spec, $new_keys = []) { // Remove old check constraints. $field_info = $this->queryFieldInformation($table, $field); // Remove old sequence. $seq_name = $this->getSequenceName($table, $field); if (!empty($seq_name)) { // We need to add CASCADE otherwise we cannot alter the sequence because // the table depends on it. $this->connection->query('DROP SEQUENCE IF EXISTS ' . $seq_name . ' CASCADE'); } foreach ($field_info as $check) { $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT [' . $check . ']'); } Loading Loading @@ -1062,6 +1069,26 @@ public function extensionExists($name): bool { ])->fetchField(); } /** * Retrieves a sequence name that is owned by the table and column.. * * @param string $table * A table name that is not prefixed or quoted. * @param string $column * The column name. * * @return string|null * The name of the sequence or NULL if it does not exist. */ protected function getSequenceName(string $table, string $column): ?string { return $this->connection ->query("SELECT pg_get_serial_sequence(:table, :column)", [ ':table' => $this->connection->getPrefix() . $table, ':column' => $column, ]) ->fetchField(); } } /** Loading
core/tests/Drupal/KernelTests/Core/Database/DriverSpecificSchemaTestBase.php +42 −0 Original line number Diff line number Diff line Loading @@ -1308,4 +1308,46 @@ public function testReservedKeywordsForNaming(): void { $this->assertFalse($this->schema->tableExists($table_name_new)); } /** * Tests changing a field length. */ public function testChangeSerialFieldLength(): void { $specification = [ 'fields' => [ 'id' => [ 'type' => 'serial', 'not null' => TRUE, 'description' => 'Primary Key: Unique ID.', ], 'text' => [ 'type' => 'text', 'description' => 'A text field', ], ], 'primary key' => ['id'], ]; $this->schema->createTable('change_serial_to_big', $specification); // Increase the size of the field. $new_specification = [ 'size' => 'big', 'type' => 'serial', 'not null' => TRUE, 'description' => 'Primary Key: Unique ID.', ]; $this->schema->changeField('change_serial_to_big', 'id', 'id', $new_specification); $this->assertTrue($this->schema->fieldExists('change_serial_to_big', 'id')); // Test if we can actually add a big int. $id = $this->connection->insert('change_serial_to_big')->fields([ 'id' => 21474836470, ])->execute(); $id_two = $this->connection->insert('change_serial_to_big')->fields([ 'text' => 'Testing for ID generation', ])->execute(); $this->assertEquals($id + 1, $id_two); } }