From a03f7c53ad14ab803989fe0effb82d4e09b1d7e3 Mon Sep 17 00:00:00 2001 From: Ricky Stewart Date: Fri, 22 Mar 2024 10:52:21 -0500 Subject: [PATCH 1/2] changefeedccl: skip `TestChangefeedWithSimpleDistributionStrategy` This test is flaky. Epic: none Release note: None --- pkg/ccl/changefeedccl/changefeed_dist_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/ccl/changefeedccl/changefeed_dist_test.go b/pkg/ccl/changefeedccl/changefeed_dist_test.go index 69d2ca5abe0c..f313375d858e 100644 --- a/pkg/ccl/changefeedccl/changefeed_dist_test.go +++ b/pkg/ccl/changefeedccl/changefeed_dist_test.go @@ -496,6 +496,8 @@ func TestChangefeedWithSimpleDistributionStrategy(t *testing.T) { defer leaktest.AfterTest(t)() defer log.Scope(t).Close(t) + skip.WithIssue(t, 120870) + // The test is slow and will time out under deadlock/race/stress. skip.UnderShort(t) skip.UnderDuress(t) From 2999c9723629f0c08912f39a9540ba56c5a68909 Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Mon, 18 Mar 2024 20:21:09 -0400 Subject: [PATCH 2/2] sql: Allow Alter Column Drop Identity Command Informs: #110010 This change adds a new command, 'ALTER TABLE ALTER [COLUMN] DROP IDENTITY [ IF EXISTS ]', which allows an IDENTITY column to drop its Identity constraint and related sequence. 'IF EXISTS' is optional and will provide a notice if the column is not an identity. Release note (sql change): Identity Columns can drop the Identity constraint and related sequence by running: -'ALTER TABLE t ALTER COLUMN c DROP IDENTITY'. Option 'IF EXISTS' can be added to skip the command if the column in not an identity: -'ALTER TABLE t ALTER COLUMN c DROP IDENTITY [ IF EXISTS ]'. --- docs/generated/sql/bnf/alter_column.bnf | 8 ++++ docs/generated/sql/bnf/alter_table_cmds.bnf | 2 +- .../sql/bnf/alter_table_partition_by.bnf | 4 +- docs/generated/sql/bnf/stmt_block.bnf | 2 + pkg/sql/alter_table.go | 38 ++++++++++++++++++- pkg/sql/drop_sequence.go | 3 +- .../logictest/testdata/logic_test/alter_table | 24 ++++++++++++ .../testdata/logic_test/information_schema | 16 ++++++++ pkg/sql/parser/sql.y | 11 ++++++ pkg/sql/parser/testdata/alter_table | 16 ++++++++ pkg/sql/sem/tree/alter_table.go | 28 ++++++++++++++ pkg/sql/sequence_test.go | 7 ++++ 12 files changed, 153 insertions(+), 6 deletions(-) diff --git a/docs/generated/sql/bnf/alter_column.bnf b/docs/generated/sql/bnf/alter_column.bnf index 8920a52c987a..4c3a46f17b5a 100644 --- a/docs/generated/sql/bnf/alter_column.bnf +++ b/docs/generated/sql/bnf/alter_column.bnf @@ -23,6 +23,10 @@ alter_onetable_stmt ::= | 'ALTER' 'TABLE' table_name 'ALTER' column_name set_generated_default | 'ALTER' 'TABLE' table_name 'ALTER' 'COLUMN' column_name identity_option_list | 'ALTER' 'TABLE' table_name 'ALTER' column_name identity_option_list + | 'ALTER' 'TABLE' table_name 'ALTER' 'COLUMN' column_name 'DROP' 'IDENTITY' + | 'ALTER' 'TABLE' table_name 'ALTER' column_name 'DROP' 'IDENTITY' + | 'ALTER' 'TABLE' table_name 'ALTER' 'COLUMN' column_name 'DROP' 'IDENTITY' 'IF' 'EXISTS' + | 'ALTER' 'TABLE' table_name 'ALTER' column_name 'DROP' 'IDENTITY' 'IF' 'EXISTS' | 'ALTER' 'TABLE' table_name 'ALTER' 'COLUMN' column_name 'DROP' 'STORED' | 'ALTER' 'TABLE' table_name 'ALTER' column_name 'DROP' 'STORED' | 'ALTER' 'TABLE' table_name 'ALTER' 'COLUMN' column_name 'SET' 'NOT' 'NULL' @@ -67,6 +71,10 @@ alter_onetable_stmt ::= | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'ALTER' column_name set_generated_default | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'ALTER' 'COLUMN' column_name identity_option_list | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'ALTER' column_name identity_option_list + | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'ALTER' 'COLUMN' column_name 'DROP' 'IDENTITY' + | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'ALTER' column_name 'DROP' 'IDENTITY' + | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'ALTER' 'COLUMN' column_name 'DROP' 'IDENTITY' 'IF' 'EXISTS' + | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'ALTER' column_name 'DROP' 'IDENTITY' 'IF' 'EXISTS' | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'ALTER' 'COLUMN' column_name 'DROP' 'STORED' | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'ALTER' column_name 'DROP' 'STORED' | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'ALTER' 'COLUMN' column_name 'SET' 'NOT' 'NULL' diff --git a/docs/generated/sql/bnf/alter_table_cmds.bnf b/docs/generated/sql/bnf/alter_table_cmds.bnf index 4110549421d9..e332b57b0c13 100644 --- a/docs/generated/sql/bnf/alter_table_cmds.bnf +++ b/docs/generated/sql/bnf/alter_table_cmds.bnf @@ -1,2 +1,2 @@ alter_table_cmds ::= - ( ( 'RENAME' ( 'COLUMN' | ) column_name 'TO' column_new_name | 'RENAME' 'CONSTRAINT' constraint_name 'TO' constraint_new_name | 'ADD' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'IF' 'NOT' 'EXISTS' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'COLUMN' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'COLUMN' 'IF' 'NOT' 'EXISTS' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'DEFAULT' a_expr | 'DROP' 'DEFAULT' ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'ON' 'UPDATE' a_expr | 'DROP' 'ON' 'UPDATE' ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'VISIBLE' | 'SET' 'NOT' 'VISIBLE' ) | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'NOT' 'NULL' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_always_as 'IDENTITY' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_by_default_as 'IDENTITY' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_always_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_by_default_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' ( 'COLUMN' | ) column_name set_generated_always | 'ALTER' ( 'COLUMN' | ) column_name set_generated_default | 'ALTER' ( 'COLUMN' | ) column_name identity_option_list | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'STORED' | 'ALTER' ( 'COLUMN' | ) column_name 'SET' 'NOT' 'NULL' | 'DROP' ( 'COLUMN' | ) 'IF' 'EXISTS' column_name ( 'CASCADE' | 'RESTRICT' | ) | 'DROP' ( 'COLUMN' | ) column_name ( 'CASCADE' | 'RESTRICT' | ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'DATA' | ) 'TYPE' typename ( 'COLLATE' collation_name | ) ( 'USING' a_expr | ) | 'ADD' ( 'CONSTRAINT' constraint_name constraint_elem | constraint_elem ) ( 'NOT' 'VALID' | ) | 'ADD' 'CONSTRAINT' 'IF' 'NOT' 'EXISTS' constraint_name constraint_elem ( 'NOT' 'VALID' | ) | 'ALTER' 'PRIMARY' 'KEY' 'USING' 'COLUMNS' '(' index_params ')' ( 'USING' 'HASH' | ) ( 'WITH' '(' ( ( ( storage_parameter_key '=' value ) ) ( ( ',' ( storage_parameter_key '=' value ) ) )* ) ')' ) | 'VALIDATE' 'CONSTRAINT' constraint_name | 'DROP' 'CONSTRAINT' 'IF' 'EXISTS' constraint_name ( 'CASCADE' | 'RESTRICT' | ) | 'DROP' 'CONSTRAINT' constraint_name ( 'CASCADE' | 'RESTRICT' | ) | 'EXPERIMENTAL_AUDIT' 'SET' ( 'READ' 'WRITE' | 'OFF' ) | ( ( 'PARTITION' 'BY' ( 'LIST' '(' name_list ')' '(' list_partitions ')' | 'RANGE' '(' name_list ')' '(' range_partitions ')' | 'NOTHING' ) ) | 'PARTITION' 'ALL' 'BY' ( 'LIST' '(' name_list ')' '(' list_partitions ')' | 'RANGE' '(' name_list ')' '(' range_partitions ')' | 'NOTHING' ) ) | 'SET' '(' ( ( ( storage_parameter_key '=' value ) ) ( ( ',' ( storage_parameter_key '=' value ) ) )* ) ')' | 'RESET' '(' ( ( storage_parameter_key ) ( ( ',' storage_parameter_key ) )* ) ')' ) ) ( ( ',' ( 'RENAME' ( 'COLUMN' | ) column_name 'TO' column_new_name | 'RENAME' 'CONSTRAINT' constraint_name 'TO' constraint_new_name | 'ADD' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'IF' 'NOT' 'EXISTS' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'COLUMN' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'COLUMN' 'IF' 'NOT' 'EXISTS' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'DEFAULT' a_expr | 'DROP' 'DEFAULT' ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'ON' 'UPDATE' a_expr | 'DROP' 'ON' 'UPDATE' ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'VISIBLE' | 'SET' 'NOT' 'VISIBLE' ) | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'NOT' 'NULL' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_always_as 'IDENTITY' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_by_default_as 'IDENTITY' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_always_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_by_default_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' ( 'COLUMN' | ) column_name set_generated_always | 'ALTER' ( 'COLUMN' | ) column_name set_generated_default | 'ALTER' ( 'COLUMN' | ) column_name identity_option_list | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'STORED' | 'ALTER' ( 'COLUMN' | ) column_name 'SET' 'NOT' 'NULL' | 'DROP' ( 'COLUMN' | ) 'IF' 'EXISTS' column_name ( 'CASCADE' | 'RESTRICT' | ) | 'DROP' ( 'COLUMN' | ) column_name ( 'CASCADE' | 'RESTRICT' | ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'DATA' | ) 'TYPE' typename ( 'COLLATE' collation_name | ) ( 'USING' a_expr | ) | 'ADD' ( 'CONSTRAINT' constraint_name constraint_elem | constraint_elem ) ( 'NOT' 'VALID' | ) | 'ADD' 'CONSTRAINT' 'IF' 'NOT' 'EXISTS' constraint_name constraint_elem ( 'NOT' 'VALID' | ) | 'ALTER' 'PRIMARY' 'KEY' 'USING' 'COLUMNS' '(' index_params ')' ( 'USING' 'HASH' | ) ( 'WITH' '(' ( ( ( storage_parameter_key '=' value ) ) ( ( ',' ( storage_parameter_key '=' value ) ) )* ) ')' ) | 'VALIDATE' 'CONSTRAINT' constraint_name | 'DROP' 'CONSTRAINT' 'IF' 'EXISTS' constraint_name ( 'CASCADE' | 'RESTRICT' | ) | 'DROP' 'CONSTRAINT' constraint_name ( 'CASCADE' | 'RESTRICT' | ) | 'EXPERIMENTAL_AUDIT' 'SET' ( 'READ' 'WRITE' | 'OFF' ) | ( ( 'PARTITION' 'BY' ( 'LIST' '(' name_list ')' '(' list_partitions ')' | 'RANGE' '(' name_list ')' '(' range_partitions ')' | 'NOTHING' ) ) | 'PARTITION' 'ALL' 'BY' ( 'LIST' '(' name_list ')' '(' list_partitions ')' | 'RANGE' '(' name_list ')' '(' range_partitions ')' | 'NOTHING' ) ) | 'SET' '(' ( ( ( storage_parameter_key '=' value ) ) ( ( ',' ( storage_parameter_key '=' value ) ) )* ) ')' | 'RESET' '(' ( ( storage_parameter_key ) ( ( ',' storage_parameter_key ) )* ) ')' ) ) )* + ( ( 'RENAME' ( 'COLUMN' | ) column_name 'TO' column_new_name | 'RENAME' 'CONSTRAINT' constraint_name 'TO' constraint_new_name | 'ADD' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'IF' 'NOT' 'EXISTS' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'COLUMN' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'COLUMN' 'IF' 'NOT' 'EXISTS' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'DEFAULT' a_expr | 'DROP' 'DEFAULT' ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'ON' 'UPDATE' a_expr | 'DROP' 'ON' 'UPDATE' ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'VISIBLE' | 'SET' 'NOT' 'VISIBLE' ) | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'NOT' 'NULL' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_always_as 'IDENTITY' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_by_default_as 'IDENTITY' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_always_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_by_default_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' ( 'COLUMN' | ) column_name set_generated_always | 'ALTER' ( 'COLUMN' | ) column_name set_generated_default | 'ALTER' ( 'COLUMN' | ) column_name identity_option_list | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'IDENTITY' | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'IDENTITY' 'IF' 'EXISTS' | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'STORED' | 'ALTER' ( 'COLUMN' | ) column_name 'SET' 'NOT' 'NULL' | 'DROP' ( 'COLUMN' | ) 'IF' 'EXISTS' column_name ( 'CASCADE' | 'RESTRICT' | ) | 'DROP' ( 'COLUMN' | ) column_name ( 'CASCADE' | 'RESTRICT' | ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'DATA' | ) 'TYPE' typename ( 'COLLATE' collation_name | ) ( 'USING' a_expr | ) | 'ADD' ( 'CONSTRAINT' constraint_name constraint_elem | constraint_elem ) ( 'NOT' 'VALID' | ) | 'ADD' 'CONSTRAINT' 'IF' 'NOT' 'EXISTS' constraint_name constraint_elem ( 'NOT' 'VALID' | ) | 'ALTER' 'PRIMARY' 'KEY' 'USING' 'COLUMNS' '(' index_params ')' ( 'USING' 'HASH' | ) ( 'WITH' '(' ( ( ( storage_parameter_key '=' value ) ) ( ( ',' ( storage_parameter_key '=' value ) ) )* ) ')' ) | 'VALIDATE' 'CONSTRAINT' constraint_name | 'DROP' 'CONSTRAINT' 'IF' 'EXISTS' constraint_name ( 'CASCADE' | 'RESTRICT' | ) | 'DROP' 'CONSTRAINT' constraint_name ( 'CASCADE' | 'RESTRICT' | ) | 'EXPERIMENTAL_AUDIT' 'SET' ( 'READ' 'WRITE' | 'OFF' ) | ( ( 'PARTITION' 'BY' ( 'LIST' '(' name_list ')' '(' list_partitions ')' | 'RANGE' '(' name_list ')' '(' range_partitions ')' | 'NOTHING' ) ) | 'PARTITION' 'ALL' 'BY' ( 'LIST' '(' name_list ')' '(' list_partitions ')' | 'RANGE' '(' name_list ')' '(' range_partitions ')' | 'NOTHING' ) ) | 'SET' '(' ( ( ( storage_parameter_key '=' value ) ) ( ( ',' ( storage_parameter_key '=' value ) ) )* ) ')' | 'RESET' '(' ( ( storage_parameter_key ) ( ( ',' storage_parameter_key ) )* ) ')' ) ) ( ( ',' ( 'RENAME' ( 'COLUMN' | ) column_name 'TO' column_new_name | 'RENAME' 'CONSTRAINT' constraint_name 'TO' constraint_new_name | 'ADD' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'IF' 'NOT' 'EXISTS' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'COLUMN' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ADD' 'COLUMN' 'IF' 'NOT' 'EXISTS' ( column_name typename ( ( ) ( ( col_qualification ) )* ) ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'DEFAULT' a_expr | 'DROP' 'DEFAULT' ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'ON' 'UPDATE' a_expr | 'DROP' 'ON' 'UPDATE' ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'VISIBLE' | 'SET' 'NOT' 'VISIBLE' ) | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'NOT' 'NULL' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_always_as 'IDENTITY' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_by_default_as 'IDENTITY' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_always_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' ( 'COLUMN' | ) column_name 'ADD' generated_by_default_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' ( 'COLUMN' | ) column_name set_generated_always | 'ALTER' ( 'COLUMN' | ) column_name set_generated_default | 'ALTER' ( 'COLUMN' | ) column_name identity_option_list | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'IDENTITY' | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'IDENTITY' 'IF' 'EXISTS' | 'ALTER' ( 'COLUMN' | ) column_name 'DROP' 'STORED' | 'ALTER' ( 'COLUMN' | ) column_name 'SET' 'NOT' 'NULL' | 'DROP' ( 'COLUMN' | ) 'IF' 'EXISTS' column_name ( 'CASCADE' | 'RESTRICT' | ) | 'DROP' ( 'COLUMN' | ) column_name ( 'CASCADE' | 'RESTRICT' | ) | 'ALTER' ( 'COLUMN' | ) column_name ( 'SET' 'DATA' | ) 'TYPE' typename ( 'COLLATE' collation_name | ) ( 'USING' a_expr | ) | 'ADD' ( 'CONSTRAINT' constraint_name constraint_elem | constraint_elem ) ( 'NOT' 'VALID' | ) | 'ADD' 'CONSTRAINT' 'IF' 'NOT' 'EXISTS' constraint_name constraint_elem ( 'NOT' 'VALID' | ) | 'ALTER' 'PRIMARY' 'KEY' 'USING' 'COLUMNS' '(' index_params ')' ( 'USING' 'HASH' | ) ( 'WITH' '(' ( ( ( storage_parameter_key '=' value ) ) ( ( ',' ( storage_parameter_key '=' value ) ) )* ) ')' ) | 'VALIDATE' 'CONSTRAINT' constraint_name | 'DROP' 'CONSTRAINT' 'IF' 'EXISTS' constraint_name ( 'CASCADE' | 'RESTRICT' | ) | 'DROP' 'CONSTRAINT' constraint_name ( 'CASCADE' | 'RESTRICT' | ) | 'EXPERIMENTAL_AUDIT' 'SET' ( 'READ' 'WRITE' | 'OFF' ) | ( ( 'PARTITION' 'BY' ( 'LIST' '(' name_list ')' '(' list_partitions ')' | 'RANGE' '(' name_list ')' '(' range_partitions ')' | 'NOTHING' ) ) | 'PARTITION' 'ALL' 'BY' ( 'LIST' '(' name_list ')' '(' list_partitions ')' | 'RANGE' '(' name_list ')' '(' range_partitions ')' | 'NOTHING' ) ) | 'SET' '(' ( ( ( storage_parameter_key '=' value ) ) ( ( ',' ( storage_parameter_key '=' value ) ) )* ) ')' | 'RESET' '(' ( ( storage_parameter_key ) ( ( ',' storage_parameter_key ) )* ) ')' ) ) )* diff --git a/docs/generated/sql/bnf/alter_table_partition_by.bnf b/docs/generated/sql/bnf/alter_table_partition_by.bnf index 0d8cc3054016..b522f4b96a3b 100644 --- a/docs/generated/sql/bnf/alter_table_partition_by.bnf +++ b/docs/generated/sql/bnf/alter_table_partition_by.bnf @@ -1,3 +1,3 @@ alter_onetable_stmt ::= - 'ALTER' 'TABLE' table_name 'PARTITION' 'ALL' 'BY' partition_by_inner ( ( ',' ( 'RENAME' opt_column column_name 'TO' column_name | 'RENAME' 'CONSTRAINT' column_name 'TO' column_name | 'ADD' column_table_def | 'ADD' 'IF' 'NOT' 'EXISTS' column_table_def | 'ADD' 'COLUMN' column_table_def | 'ADD' 'COLUMN' 'IF' 'NOT' 'EXISTS' column_table_def | 'ALTER' opt_column column_name alter_column_default | 'ALTER' opt_column column_name alter_column_on_update | 'ALTER' opt_column column_name alter_column_visible | 'ALTER' opt_column column_name 'DROP' 'NOT' 'NULL' | 'ALTER' opt_column column_name 'ADD' generated_always_as 'IDENTITY' | 'ALTER' opt_column column_name 'ADD' generated_by_default_as 'IDENTITY' | 'ALTER' opt_column column_name 'ADD' generated_always_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' opt_column column_name 'ADD' generated_by_default_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' opt_column column_name set_generated_always | 'ALTER' opt_column column_name set_generated_default | 'ALTER' opt_column column_name identity_option_list | 'ALTER' opt_column column_name 'DROP' 'STORED' | 'ALTER' opt_column column_name 'SET' 'NOT' 'NULL' | 'DROP' opt_column 'IF' 'EXISTS' column_name opt_drop_behavior | 'DROP' opt_column column_name opt_drop_behavior | 'ALTER' opt_column column_name opt_set_data 'TYPE' typename opt_collate opt_alter_column_using | 'ADD' table_constraint opt_validate_behavior | 'ADD' 'CONSTRAINT' 'IF' 'NOT' 'EXISTS' constraint_name constraint_elem opt_validate_behavior | 'ALTER' 'PRIMARY' 'KEY' 'USING' 'COLUMNS' '(' index_params ')' opt_hash_sharded opt_with_storage_parameter_list | 'VALIDATE' 'CONSTRAINT' constraint_name | 'DROP' 'CONSTRAINT' 'IF' 'EXISTS' constraint_name opt_drop_behavior | 'DROP' 'CONSTRAINT' constraint_name opt_drop_behavior | 'EXPERIMENTAL_AUDIT' 'SET' audit_mode | ( 'PARTITION' 'BY' partition_by_inner | 'PARTITION' 'ALL' 'BY' partition_by_inner ) | 'SET' '(' storage_parameter_list ')' | 'RESET' '(' storage_parameter_key_list ')' ) ) )* - | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'PARTITION' 'ALL' 'BY' partition_by_inner ( ( ',' ( 'RENAME' opt_column column_name 'TO' column_name | 'RENAME' 'CONSTRAINT' column_name 'TO' column_name | 'ADD' column_table_def | 'ADD' 'IF' 'NOT' 'EXISTS' column_table_def | 'ADD' 'COLUMN' column_table_def | 'ADD' 'COLUMN' 'IF' 'NOT' 'EXISTS' column_table_def | 'ALTER' opt_column column_name alter_column_default | 'ALTER' opt_column column_name alter_column_on_update | 'ALTER' opt_column column_name alter_column_visible | 'ALTER' opt_column column_name 'DROP' 'NOT' 'NULL' | 'ALTER' opt_column column_name 'ADD' generated_always_as 'IDENTITY' | 'ALTER' opt_column column_name 'ADD' generated_by_default_as 'IDENTITY' | 'ALTER' opt_column column_name 'ADD' generated_always_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' opt_column column_name 'ADD' generated_by_default_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' opt_column column_name set_generated_always | 'ALTER' opt_column column_name set_generated_default | 'ALTER' opt_column column_name identity_option_list | 'ALTER' opt_column column_name 'DROP' 'STORED' | 'ALTER' opt_column column_name 'SET' 'NOT' 'NULL' | 'DROP' opt_column 'IF' 'EXISTS' column_name opt_drop_behavior | 'DROP' opt_column column_name opt_drop_behavior | 'ALTER' opt_column column_name opt_set_data 'TYPE' typename opt_collate opt_alter_column_using | 'ADD' table_constraint opt_validate_behavior | 'ADD' 'CONSTRAINT' 'IF' 'NOT' 'EXISTS' constraint_name constraint_elem opt_validate_behavior | 'ALTER' 'PRIMARY' 'KEY' 'USING' 'COLUMNS' '(' index_params ')' opt_hash_sharded opt_with_storage_parameter_list | 'VALIDATE' 'CONSTRAINT' constraint_name | 'DROP' 'CONSTRAINT' 'IF' 'EXISTS' constraint_name opt_drop_behavior | 'DROP' 'CONSTRAINT' constraint_name opt_drop_behavior | 'EXPERIMENTAL_AUDIT' 'SET' audit_mode | ( 'PARTITION' 'BY' partition_by_inner | 'PARTITION' 'ALL' 'BY' partition_by_inner ) | 'SET' '(' storage_parameter_list ')' | 'RESET' '(' storage_parameter_key_list ')' ) ) )* + 'ALTER' 'TABLE' table_name 'PARTITION' 'ALL' 'BY' partition_by_inner ( ( ',' ( 'RENAME' opt_column column_name 'TO' column_name | 'RENAME' 'CONSTRAINT' column_name 'TO' column_name | 'ADD' column_table_def | 'ADD' 'IF' 'NOT' 'EXISTS' column_table_def | 'ADD' 'COLUMN' column_table_def | 'ADD' 'COLUMN' 'IF' 'NOT' 'EXISTS' column_table_def | 'ALTER' opt_column column_name alter_column_default | 'ALTER' opt_column column_name alter_column_on_update | 'ALTER' opt_column column_name alter_column_visible | 'ALTER' opt_column column_name 'DROP' 'NOT' 'NULL' | 'ALTER' opt_column column_name 'ADD' generated_always_as 'IDENTITY' | 'ALTER' opt_column column_name 'ADD' generated_by_default_as 'IDENTITY' | 'ALTER' opt_column column_name 'ADD' generated_always_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' opt_column column_name 'ADD' generated_by_default_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' opt_column column_name set_generated_always | 'ALTER' opt_column column_name set_generated_default | 'ALTER' opt_column column_name identity_option_list | 'ALTER' opt_column column_name 'DROP' 'IDENTITY' | 'ALTER' opt_column column_name 'DROP' 'IDENTITY' 'IF' 'EXISTS' | 'ALTER' opt_column column_name 'DROP' 'STORED' | 'ALTER' opt_column column_name 'SET' 'NOT' 'NULL' | 'DROP' opt_column 'IF' 'EXISTS' column_name opt_drop_behavior | 'DROP' opt_column column_name opt_drop_behavior | 'ALTER' opt_column column_name opt_set_data 'TYPE' typename opt_collate opt_alter_column_using | 'ADD' table_constraint opt_validate_behavior | 'ADD' 'CONSTRAINT' 'IF' 'NOT' 'EXISTS' constraint_name constraint_elem opt_validate_behavior | 'ALTER' 'PRIMARY' 'KEY' 'USING' 'COLUMNS' '(' index_params ')' opt_hash_sharded opt_with_storage_parameter_list | 'VALIDATE' 'CONSTRAINT' constraint_name | 'DROP' 'CONSTRAINT' 'IF' 'EXISTS' constraint_name opt_drop_behavior | 'DROP' 'CONSTRAINT' constraint_name opt_drop_behavior | 'EXPERIMENTAL_AUDIT' 'SET' audit_mode | ( 'PARTITION' 'BY' partition_by_inner | 'PARTITION' 'ALL' 'BY' partition_by_inner ) | 'SET' '(' storage_parameter_list ')' | 'RESET' '(' storage_parameter_key_list ')' ) ) )* + | 'ALTER' 'TABLE' 'IF' 'EXISTS' table_name 'PARTITION' 'ALL' 'BY' partition_by_inner ( ( ',' ( 'RENAME' opt_column column_name 'TO' column_name | 'RENAME' 'CONSTRAINT' column_name 'TO' column_name | 'ADD' column_table_def | 'ADD' 'IF' 'NOT' 'EXISTS' column_table_def | 'ADD' 'COLUMN' column_table_def | 'ADD' 'COLUMN' 'IF' 'NOT' 'EXISTS' column_table_def | 'ALTER' opt_column column_name alter_column_default | 'ALTER' opt_column column_name alter_column_on_update | 'ALTER' opt_column column_name alter_column_visible | 'ALTER' opt_column column_name 'DROP' 'NOT' 'NULL' | 'ALTER' opt_column column_name 'ADD' generated_always_as 'IDENTITY' | 'ALTER' opt_column column_name 'ADD' generated_by_default_as 'IDENTITY' | 'ALTER' opt_column column_name 'ADD' generated_always_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' opt_column column_name 'ADD' generated_by_default_as 'IDENTITY' '(' opt_sequence_option_list ')' | 'ALTER' opt_column column_name set_generated_always | 'ALTER' opt_column column_name set_generated_default | 'ALTER' opt_column column_name identity_option_list | 'ALTER' opt_column column_name 'DROP' 'IDENTITY' | 'ALTER' opt_column column_name 'DROP' 'IDENTITY' 'IF' 'EXISTS' | 'ALTER' opt_column column_name 'DROP' 'STORED' | 'ALTER' opt_column column_name 'SET' 'NOT' 'NULL' | 'DROP' opt_column 'IF' 'EXISTS' column_name opt_drop_behavior | 'DROP' opt_column column_name opt_drop_behavior | 'ALTER' opt_column column_name opt_set_data 'TYPE' typename opt_collate opt_alter_column_using | 'ADD' table_constraint opt_validate_behavior | 'ADD' 'CONSTRAINT' 'IF' 'NOT' 'EXISTS' constraint_name constraint_elem opt_validate_behavior | 'ALTER' 'PRIMARY' 'KEY' 'USING' 'COLUMNS' '(' index_params ')' opt_hash_sharded opt_with_storage_parameter_list | 'VALIDATE' 'CONSTRAINT' constraint_name | 'DROP' 'CONSTRAINT' 'IF' 'EXISTS' constraint_name opt_drop_behavior | 'DROP' 'CONSTRAINT' constraint_name opt_drop_behavior | 'EXPERIMENTAL_AUDIT' 'SET' audit_mode | ( 'PARTITION' 'BY' partition_by_inner | 'PARTITION' 'ALL' 'BY' partition_by_inner ) | 'SET' '(' storage_parameter_list ')' | 'RESET' '(' storage_parameter_key_list ')' ) ) )* diff --git a/docs/generated/sql/bnf/stmt_block.bnf b/docs/generated/sql/bnf/stmt_block.bnf index 1eceebbbd739..db7c666071ee 100644 --- a/docs/generated/sql/bnf/stmt_block.bnf +++ b/docs/generated/sql/bnf/stmt_block.bnf @@ -3428,6 +3428,8 @@ alter_table_cmd ::= | 'ALTER' opt_column column_name set_generated_always | 'ALTER' opt_column column_name set_generated_default | 'ALTER' opt_column column_name identity_option_list + | 'ALTER' opt_column column_name 'DROP' 'IDENTITY' + | 'ALTER' opt_column column_name 'DROP' 'IDENTITY' 'IF' 'EXISTS' | 'ALTER' opt_column column_name 'DROP' 'STORED' | 'ALTER' opt_column column_name 'SET' 'NOT' 'NULL' | 'DROP' opt_column 'IF' 'EXISTS' column_name opt_drop_behavior diff --git a/pkg/sql/alter_table.go b/pkg/sql/alter_table.go index 3eb1f6ce7c10..794f9de568cc 100644 --- a/pkg/sql/alter_table.go +++ b/pkg/sql/alter_table.go @@ -1188,7 +1188,7 @@ func applyColumnMutation( col.GetName(), tableDesc.GetName()) } - // It is assummed that an identiy column owns only one sequence. + // It is assumed that an identify column owns only one sequence. if col.NumUsesSequences() != 1 { return errors.AssertionFailedf( "identity column %q of relation %q has %d sequences instead of 1", @@ -1221,6 +1221,42 @@ func applyColumnMutation( s := tree.Serialize(&optsNode) col.ColumnDesc().GeneratedAsIdentitySequenceOption = &s + case *tree.AlterTableDropIdentity: + if !col.IsGeneratedAsIdentity() { + if t.IfExists { + params.p.BufferClientNotice( + params.ctx, + pgnotice.Newf("column %q of relation %q is not an identity column, skipping", col.GetName(), tableDesc.GetName()), + ) + return nil + } + return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, + "column %q of relation %q is not an identity column", + col.GetName(), tableDesc.GetName()) + } + + // It is assumed that an identify column owns only one sequence. + if col.NumUsesSequences() != 1 { + return errors.AssertionFailedf( + "identity column %q of relation %q has %d sequences instead of 1", + col.GetName(), tableDesc.GetName(), col.NumUsesSequences()) + } + + // Verify sequence is not depended on by another column. + // Use tree.DropDefault behavior to verify without the need to alter other dependencies via tree.DropCascade. + if err := params.p.canRemoveAllColumnOwnedSequences(params.ctx, tableDesc, col, tree.DropDefault); err != nil { + return err + } + // Drop the identity sequence and remove it from the column OwnsSequenceIds and DefaultExpr. + // Use tree.DropCascade behavior to remove dependencies on the column. + if err := params.p.dropSequencesOwnedByCol(params.ctx, col, true /* queueJob */, tree.DropCascade); err != nil { + return err + } + + // Remove column identity descriptors + col.ColumnDesc().GeneratedAsIdentityType = catpb.GeneratedAsIdentityType_NOT_IDENTITY_COLUMN + col.ColumnDesc().GeneratedAsIdentitySequenceOption = nil + } return nil } diff --git a/pkg/sql/drop_sequence.go b/pkg/sql/drop_sequence.go index 0d13f54316fc..36e441bbdf9f 100644 --- a/pkg/sql/drop_sequence.go +++ b/pkg/sql/drop_sequence.go @@ -24,7 +24,6 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scerrors" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" - "github.com/cockroachdb/cockroach/pkg/util/iterutil" "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/log/eventpb" "github.com/cockroachdb/errors" @@ -190,7 +189,7 @@ func (p *planner) canRemoveOwnedSequencesImpl( var firstDep *descpb.TableDescriptor_Reference multipleIterationErr := seqDesc.ForeachDependedOnBy(func(dep *descpb.TableDescriptor_Reference) error { if firstDep != nil { - return iterutil.StopIteration() + return errors.Newf("multiple iterations") } firstDep = dep return nil diff --git a/pkg/sql/logictest/testdata/logic_test/alter_table b/pkg/sql/logictest/testdata/logic_test/alter_table index f70dcae32d5b..091281efb648 100644 --- a/pkg/sql/logictest/testdata/logic_test/alter_table +++ b/pkg/sql/logictest/testdata/logic_test/alter_table @@ -3826,3 +3826,27 @@ SELECT b from t_alter_identity ORDER BY b; 9 18 20 + +statement ok +CREATE TABLE t_identity_drop (a int GENERATED ALWAYS AS IDENTITY (START WITH 10), b int GENERATED BY DEFAULT AS IDENTITY); + +statement error pgcode 428C9 pq: cannot insert into column "a"\nDETAIL: Column "a" is an identity column defined as GENERATED ALWAYS +INSERT INTO t_identity_drop (a) VALUES (3); + +statement ok +ALTER TABLE t_identity_drop ALTER COLUMN a DROP IDENTITY; + +statement error pgcode 55000 pq: column "a" of relation "t_identity_drop" is not an identity column +ALTER TABLE t_identity_drop ALTER COLUMN a DROP IDENTITY; + +statement notice NOTICE: column "a" of relation "t_identity_drop" is not an identity column, skipping +ALTER TABLE t_identity_drop ALTER COLUMN a DROP IDENTITY IF EXISTS; + +statement ok +INSERT INTO t_identity_drop (a) VALUES (3); + +statement ok +CREATE TABLE t_identity_drop_dependency(id INT PRIMARY KEY DEFAULT nextval('public.t_identity_drop_b_seq')); + +statement error pgcode 2BP01 pq: cannot drop table t_identity_drop because other objects depend on it +ALTER TABLE t_identity_drop ALTER COLUMN b DROP IDENTITY; diff --git a/pkg/sql/logictest/testdata/logic_test/information_schema b/pkg/sql/logictest/testdata/logic_test/information_schema index b3b9d8bf8ede..d79634df6485 100644 --- a/pkg/sql/logictest/testdata/logic_test/information_schema +++ b/pkg/sql/logictest/testdata/logic_test/information_schema @@ -3428,6 +3428,22 @@ a YES BY DEFAULT NO nextval('public.set_ b YES ALWAYS NO nextval('public.set_generated_as_identity_b_seq'::REGCLASS) 10 1 9223372036854775807 1 NULL rowid NO · NO unique_rowid() NULL NULL NULL NULL NULL +statement ok +CREATE TABLE drop_generated_as_identity (a INT GENERATED ALWAYS AS IDENTITY (START WITH 10)) + +statement ok +ALTER TABLE drop_generated_as_identity ALTER COLUMN a DROP IDENTITY; + +query TTTTTTTTTT colnames +SELECT column_name, is_identity, identity_generation, is_nullable, column_default, identity_start, identity_increment, identity_maximum, identity_minimum, identity_cycle +FROM information_schema.columns +WHERE table_schema = 'public' AND table_name = 'drop_generated_as_identity' +ORDER BY column_name +---- +column_name is_identity identity_generation is_nullable column_default identity_start identity_increment identity_maximum identity_minimum identity_cycle +a NO · NO NULL NULL NULL NULL NULL NULL +rowid NO · NO unique_rowid() NULL NULL NULL NULL NULL + query TTTTIIITTTTT colnames SELECT * FROM information_schema.sequences ORDER BY sequence_name ---- diff --git a/pkg/sql/parser/sql.y b/pkg/sql/parser/sql.y index 7c416a900824..8108ac0a480b 100644 --- a/pkg/sql/parser/sql.y +++ b/pkg/sql/parser/sql.y @@ -1866,6 +1866,7 @@ alter_ddl_stmt: // ALTER TABLE ... ALTER [COLUMN] ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( opt_sequence_option_list ) ] // ALTER TABLE ... ALTER [COLUMN] SET GENERATED { ALWAYS | BY DEFAULT } // ALTER TABLE ... ALTER [COLUMN] +// ALTER TABLE ... ALTER [COLUMN] DROP IDENTITY [ IF EXISTS ] // ALTER TABLE ... ALTER [COLUMN] [SET DATA] TYPE [COLLATE ] // ALTER TABLE ... ALTER PRIMARY KEY USING COLUMNS ( ) // ALTER TABLE ... RENAME TO @@ -2800,6 +2801,16 @@ alter_table_cmd: { $$.val = &tree.AlterTableIdentity{Column: tree.Name($3), SeqOptions: $4.seqOpts()} } + // ALTER TABLE ALTER [COLUMN] DROP IDENTITY +| ALTER opt_column column_name DROP IDENTITY + { + $$.val = &tree.AlterTableDropIdentity{Column: tree.Name($3), IfExists: false} + } + // ALTER TABLE ALTER [COLUMN] DROP IDENTITY IF EXISTS +| ALTER opt_column column_name DROP IDENTITY IF EXISTS + { + $$.val = &tree.AlterTableDropIdentity{Column: tree.Name($3), IfExists: true} + } // ALTER TABLE ALTER [COLUMN] DROP STORED | ALTER opt_column column_name DROP STORED { diff --git a/pkg/sql/parser/testdata/alter_table b/pkg/sql/parser/testdata/alter_table index 28f097aaa785..0dedd427ad7d 100644 --- a/pkg/sql/parser/testdata/alter_table +++ b/pkg/sql/parser/testdata/alter_table @@ -1462,3 +1462,19 @@ at or near "EOF": syntax error: sequence option "AS" not supported here DETAIL: source SQL: ALTER TABLE a ALTER COLUMN b SET AS INT8 ^ + +parse +ALTER TABLE a ALTER COLUMN b DROP IDENTITY +---- +ALTER TABLE a ALTER COLUMN b DROP IDENTITY +ALTER TABLE a ALTER COLUMN b DROP IDENTITY -- fully parenthesized +ALTER TABLE a ALTER COLUMN b DROP IDENTITY -- literals removed +ALTER TABLE _ ALTER COLUMN _ DROP IDENTITY -- identifiers removed + +parse +ALTER TABLE a ALTER COLUMN b DROP IDENTITY IF EXISTS +---- +ALTER TABLE a ALTER COLUMN b DROP IDENTITY IF EXISTS +ALTER TABLE a ALTER COLUMN b DROP IDENTITY IF EXISTS -- fully parenthesized +ALTER TABLE a ALTER COLUMN b DROP IDENTITY IF EXISTS -- literals removed +ALTER TABLE _ ALTER COLUMN _ DROP IDENTITY IF EXISTS -- identifiers removed diff --git a/pkg/sql/sem/tree/alter_table.go b/pkg/sql/sem/tree/alter_table.go index 2351c4c38dfb..b4ee63c70efb 100644 --- a/pkg/sql/sem/tree/alter_table.go +++ b/pkg/sql/sem/tree/alter_table.go @@ -79,6 +79,7 @@ func (*AlterTableResetStorageParams) alterTableCmd() {} func (*AlterTableAddIdentity) alterTableCmd() {} func (*AlterTableSetIdentity) alterTableCmd() {} func (*AlterTableIdentity) alterTableCmd() {} +func (*AlterTableDropIdentity) alterTableCmd() {} var _ AlterTableCmd = &AlterTableAddColumn{} var _ AlterTableCmd = &AlterTableAddConstraint{} @@ -102,6 +103,7 @@ var _ AlterTableCmd = &AlterTableResetStorageParams{} var _ AlterTableCmd = &AlterTableAddIdentity{} var _ AlterTableCmd = &AlterTableSetIdentity{} var _ AlterTableCmd = &AlterTableIdentity{} +var _ AlterTableCmd = &AlterTableDropIdentity{} // ColumnMutationCmd is the subset of AlterTableCmds that modify an // existing column. @@ -839,6 +841,32 @@ func (node *AlterTableIdentity) Format(ctx *FmtCtx) { } +// AlterTableDropIdentity represents an ALTER COLUMN DROP IDENTITY [ IF EXISTS ]. +type AlterTableDropIdentity struct { + Column Name + IfExists bool +} + +// GetColumn implemnets the ColumnMutationCmd interface. +func (node *AlterTableDropIdentity) GetColumn() Name { + return node.Column +} + +// TelemetryName implements the AlterTableCmd interface. +func (node *AlterTableDropIdentity) TelemetryName() string { + return "drop_identity" +} + +// Format implements the NodeFormatter interface. +func (node *AlterTableDropIdentity) Format(ctx *FmtCtx) { + ctx.WriteString(" ALTER COLUMN ") + ctx.FormatNode(&node.Column) + ctx.WriteString(" DROP IDENTITY") + if node.IfExists { + ctx.WriteString(" IF EXISTS") + } +} + // GetTableType returns a string representing the type of table the command // is operating on. // It is assumed if the table is not a sequence or a view, then it is a diff --git a/pkg/sql/sequence_test.go b/pkg/sql/sequence_test.go index 865d6fabccfa..a83706bb4de4 100644 --- a/pkg/sql/sequence_test.go +++ b/pkg/sql/sequence_test.go @@ -198,6 +198,13 @@ CREATE TABLE t.test(a INT PRIMARY KEY, b INT)`); err != nil { } assertColumnOwnsSequences(t, kvDB, "t", "test2", 0 /* colIdx */, []string{"test2_a_seq"}) assertColumnOwnsSequences(t, kvDB, "t", "test2", 1 /* colIdx */, []string{"test2_b_seq"}) + + // Ensure dropping identity column owns no sequence + if _, err := sqlConn.Exec("ALTER TABLE t.test2 ALTER COLUMN b DROP IDENTITY"); err != nil { + t.Fatal(err) + } + assertColumnOwnsSequences(t, kvDB, "t", "test2", 0 /* colIdx */, []string{"test2_a_seq"}) + assertColumnOwnsSequences(t, kvDB, "t", "test2", 1 /* colIdx */, nil /* seqNames */) } // assertColumnOwnsSequences ensures that the column at (DbName, tbName, colIdx)