@@ -4837,369 +4837,3 @@ DROP TABLE t2_fk;
48374837DROP TABLE t1_fk;
48384838
48394839subtest end
4840-
4841- subtest drop_col_dep_non_self_fk_stored
4842-
4843- # The logic in this UDF is equivalent to and originated from
4844- # columnDropViolatesFKIndexRequirements() in pkg/workload/schemachange/error_screening.go.
4845- statement ok
4846- CREATE FUNCTION column_drop_violates_fk_index_requirements(table_name STRING, column_name STRING)
4847- RETURNS BOOL
4848- LANGUAGE SQL
4849- AS $$
4850- WITH fk AS (
4851- SELECT oid,
4852- (
4853- SELECT r.relname
4854- FROM pg_class AS r
4855- WHERE r.oid = c.confrelid
4856- ) AS base_table,
4857- a.attname AS base_col,
4858- array_position(
4859- c.confkey,
4860- a.attnum
4861- ) AS base_ordinal,
4862- (
4863- SELECT r.relname
4864- FROM pg_class AS r
4865- WHERE r.oid = c.conrelid
4866- ) AS referencing_table,
4867- unnest(
4868- (
4869- SELECT array_agg(attname)
4870- FROM pg_attribute
4871- WHERE attrelid = c.conrelid
4872- AND ARRAY[attnum] <@ c.conkey
4873- AND array_position(
4874- c.confkey,
4875- a.attnum
4876- )
4877- = array_position(
4878- c.conkey,
4879- attnum
4880- )
4881- )
4882- ) AS referencing_col
4883- FROM pg_constraint AS c
4884- JOIN pg_attribute AS a ON c.confrelid
4885- = a.attrelid
4886- AND ARRAY[
4887- attnum
4888- ]
4889- <@ c.conkey
4890- WHERE c.confrelid = table_name::REGCLASS::OID
4891- ),
4892- all_index_columns AS (
4893- SELECT
4894- i.indexrelid::REGCLASS::STRING
4895- AS index_name,
4896- a.attname AS col_name,
4897- NOT
4898- i.indisunique AS non_unique,
4899- a.attnum
4900- > i.indnkeyatts AS storing,
4901- a.attnum AS index_ordinal
4902- FROM
4903- pg_index AS i
4904- JOIN pg_attribute AS a ON
4905- a.attrelid
4906- = i.indexrelid
4907- AND a.attnum > 0
4908- WHERE
4909- i.indrelid
4910- = table_name::REGCLASS::OID
4911- ),
4912- valid_indexes AS (
4913- SELECT *
4914- FROM all_index_columns
4915- WHERE index_name
4916- NOT IN (
4917- SELECT DISTINCT
4918- index_name
4919- FROM all_index_columns
4920- WHERE col_name = column_name
4921- AND index_name
4922- NOT LIKE '%_pkey'
4923- )
4924- ),
4925- fk_col_counts AS (
4926- SELECT oid, count(*) AS num_cols
4927- FROM fk
4928- GROUP BY oid
4929- ),
4930- index_column_counts AS (
4931- SELECT index_name, count(*) as num_cols FROM valid_indexes WHERE storing='f' GROUP BY index_name
4932- ),
4933- matching_fks AS (
4934- SELECT fk.oid
4935- FROM fk
4936- JOIN valid_indexes ON
4937- fk.base_col
4938- = valid_indexes.col_name
4939- JOIN index_column_counts ON
4940- valid_indexes.index_name = index_column_counts.index_name
4941- JOIN fk_col_counts ON
4942- fk.oid
4943- = fk_col_counts.oid
4944- WHERE valid_indexes.storing
4945- = false
4946- AND valid_indexes.non_unique
4947- = false
4948- AND index_column_counts.num_cols = fk_col_counts.num_cols
4949- GROUP BY fk.oid,
4950- valid_indexes.index_name,
4951- fk_col_counts.num_cols
4952- HAVING count(DISTINCT fk.base_col)
4953- = fk_col_counts.num_cols
4954- )
4955- SELECT EXISTS(
4956- SELECT *
4957- FROM fk
4958- WHERE oid NOT IN (SELECT DISTINCT oid FROM matching_fks)
4959- )
4960- $$;
4961-
4962- statement ok
4963- CREATE TABLE parent_dep_store (
4964- id INT PRIMARY KEY,
4965- key_col INT UNIQUE,
4966- stored STRING,
4967- FAMILY f1 (id, key_col, stored)
4968- ) WITH (schema_locked = false);
4969-
4970- statement ok
4971- CREATE UNIQUE INDEX idx_parent_dep_store ON parent_dep_store (key_col) STORING (stored);
4972-
4973- statement ok
4974- CREATE TABLE child_dep_store (
4975- id INT PRIMARY KEY,
4976- parent_key INT REFERENCES parent_dep_store (key_col),
4977- FAMILY f1 (id, parent_key)
4978- ) WITH (schema_locked = false);
4979-
4980- query B
4981- SELECT column_drop_violates_fk_index_requirements('parent_dep_store', 'stored');
4982- ----
4983- false
4984-
4985- statement ok
4986- ALTER TABLE parent_dep_store DROP COLUMN stored;
4987-
4988- query TT
4989- SHOW CREATE TABLE parent_dep_store
4990- ----
4991- parent_dep_store CREATE TABLE public.parent_dep_store (
4992- id INT8 NOT NULL,
4993- key_col INT8 NULL,
4994- CONSTRAINT parent_dep_store_pkey PRIMARY KEY (id ASC),
4995- UNIQUE INDEX parent_dep_store_key_col_key (key_col ASC),
4996- FAMILY f1 (id, key_col)
4997- );
4998-
4999- statement ok
5000- DROP TABLE child_dep_store;
5001-
5002- statement ok
5003- DROP TABLE parent_dep_store;
5004-
5005- subtest end
5006-
5007- subtest drop_col_dep_non_self_fk_key
5008-
5009- statement ok
5010- CREATE TABLE parent_dep_key (
5011- id INT PRIMARY KEY,
5012- key_col INT,
5013- stored STRING,
5014- FAMILY f1 (id, key_col, stored)
5015- ) WITH (schema_locked = false);
5016-
5017- statement ok
5018- CREATE UNIQUE INDEX idx_parent_dep_key ON parent_dep_key (key_col) STORING (stored);
5019-
5020- statement ok
5021- CREATE TABLE child_dep_key (
5022- id INT PRIMARY KEY,
5023- parent_key INT REFERENCES parent_dep_key (key_col),
5024- FAMILY f1 (id, parent_key)
5025- ) WITH (schema_locked = false);
5026-
5027- query B
5028- SELECT column_drop_violates_fk_index_requirements('parent_dep_key', 'key_col');
5029- ----
5030- true
5031-
5032- statement error pq: "idx_parent_dep_key" is referenced by foreign key from table "child_dep_key"
5033- ALTER TABLE parent_dep_key DROP COLUMN key_col;
5034-
5035- query TT
5036- SHOW CREATE TABLE parent_dep_key
5037- ----
5038- parent_dep_key CREATE TABLE public.parent_dep_key (
5039- id INT8 NOT NULL,
5040- key_col INT8 NULL,
5041- stored STRING NULL,
5042- CONSTRAINT parent_dep_key_pkey PRIMARY KEY (id ASC),
5043- UNIQUE INDEX idx_parent_dep_key (key_col ASC) STORING (stored),
5044- FAMILY f1 (id, key_col, stored)
5045- );
5046-
5047- statement ok
5048- DROP TABLE child_dep_key;
5049-
5050- statement ok
5051- DROP TABLE parent_dep_key;
5052-
5053- subtest end
5054-
5055- subtest drop_col_dep_self_ref_stored
5056-
5057- statement ok
5058- CREATE TABLE self_dep_store (
5059- id INT PRIMARY KEY,
5060- ref INT,
5061- stored STRING,
5062- FAMILY f1 (id, ref, stored)
5063- ) WITH (schema_locked = false);
5064-
5065- statement ok
5066- CREATE UNIQUE INDEX idx_self_dep_store ON self_dep_store (ref) STORING (stored);
5067-
5068- statement ok
5069- ALTER TABLE self_dep_store ADD CONSTRAINT fk_self_dep_store FOREIGN KEY (ref) REFERENCES self_dep_store (id);
5070-
5071- query B
5072- SELECT column_drop_violates_fk_index_requirements('self_dep_store', 'stored');
5073- ----
5074- false
5075-
5076- statement ok
5077- ALTER TABLE self_dep_store DROP COLUMN stored;
5078-
5079- query TT
5080- SHOW CREATE TABLE self_dep_store
5081- ----
5082- self_dep_store CREATE TABLE public.self_dep_store (
5083- id INT8 NOT NULL,
5084- ref INT8 NULL,
5085- CONSTRAINT self_dep_store_pkey PRIMARY KEY (id ASC),
5086- CONSTRAINT fk_self_dep_store FOREIGN KEY (ref) REFERENCES public.self_dep_store(id),
5087- FAMILY f1 (id, ref)
5088- );
5089-
5090- statement ok
5091- DROP TABLE self_dep_store;
5092-
5093- subtest end
5094-
5095- subtest drop_col_dep_self_ref_key
5096-
5097- statement ok
5098- CREATE TABLE self_dep_key (
5099- id INT PRIMARY KEY,
5100- ref INT,
5101- stored STRING,
5102- FAMILY f1 (id, ref, stored)
5103- ) WITH (schema_locked = false);
5104-
5105- statement ok
5106- CREATE UNIQUE INDEX idx_self_dep_key ON self_dep_key (ref) STORING (stored);
5107-
5108- statement ok
5109- ALTER TABLE self_dep_key ADD CONSTRAINT fk_self_dep_key FOREIGN KEY (ref) REFERENCES self_dep_key (id);
5110-
5111- query B
5112- SELECT column_drop_violates_fk_index_requirements('self_dep_key', 'ref');
5113- ----
5114- false
5115-
5116- statement ok
5117- ALTER TABLE self_dep_key DROP COLUMN ref;
5118-
5119- query TT
5120- SHOW CREATE TABLE self_dep_key
5121- ----
5122- self_dep_key CREATE TABLE public.self_dep_key (
5123- id INT8 NOT NULL,
5124- stored STRING NULL,
5125- CONSTRAINT self_dep_key_pkey PRIMARY KEY (id ASC),
5126- FAMILY f1 (id, stored)
5127- );
5128-
5129- statement ok
5130- DROP TABLE self_dep_key;
5131-
5132- # Alternative secondary index has more storing columns, but has the correct key column
5133- # prefix to work.
5134- statement ok
5135- CREATE TABLE self_dep_key_2 (
5136- col1_w4_6 INET NOT NULL,
5137- col1_w4_7 DATE NOT NULL,
5138- col1_w4_8 STRING COLLATE da_DK NOT NULL,
5139- col1_w4_11 STRING NOT NULL,
5140- col1_w4_13 INTERVAL NOT NULL,
5141- col1_w4_14 UUID NOT NULL,
5142- col1_w4_15 "char" NOT NULL,
5143- CONSTRAINT table_w4_1_pkey PRIMARY KEY (col1_w4_6 ASC) USING HASH WITH (bucket_count=16),
5144- CONSTRAINT table_w4_1_col1_w4_6_table_w4_1_col1_w4_6_fk FOREIGN KEY (col1_w4_6) REFERENCES self_dep_key_2 (col1_w4_6) ON DELETE CASCADE ON UPDATE CASCADE,
5145- UNIQUE INDEX table_w4_1_col1_w4_6_key (col1_w4_6 ASC) STORING (col1_w4_7, col1_w4_11, col1_w4_13, col1_w4_14, col1_w4_15),
5146- UNIQUE INDEX table_w4_1_col1_w4_6_col1_w4_8_key (col1_w4_6 ASC, col1_w4_8 DESC)
5147- );
5148-
5149- query B
5150- SELECT column_drop_violates_fk_index_requirements('self_dep_key_2', 'col1_w4_8');
5151- ----
5152- false
5153-
5154- # Sanity this should work.
5155- statement ok
5156- ALTER TABLE self_dep_key_2 DROP COLUMN col1_w4_8;
5157-
5158-
5159- # Self reference where dropping the stored column will be trouble.
5160- statement ok
5161- CREATE TABLE self_dep_key_3 (
5162- id INT PRIMARY KEY,
5163- indexed_col INT NOT NULL,
5164- stored_col INT NOT NULL,
5165- UNIQUE (indexed_col) STORING (stored_col)
5166- );
5167-
5168- statement ok
5169- ALTER TABLE self_dep_key_3 ADD CONSTRAINT t_fk
5170- FOREIGN KEY (indexed_col) REFERENCES self_dep_key_3 (indexed_col);
5171-
5172- query B
5173- SELECT column_drop_violates_fk_index_requirements('self_dep_key_3', 'stored_col');
5174- ----
5175- true
5176-
5177- # This should fail
5178- statement error pq: "self_dep_key_3_indexed_col_key" is referenced by foreign key from table "self_dep_key_3"
5179- ALTER TABLE self_dep_key_3 DROP COLUMN stored_col;
5180-
5181- # Self reference where dropping the stored column will lead to the only other
5182- # index not being usable (not the same prefix + length).
5183- statement ok
5184- CREATE TABLE self_dep_key_4 (
5185- id INT PRIMARY KEY,
5186- indexed_col INT NOT NULL,
5187- stored_col INT NOT NULL,
5188- UNIQUE (indexed_col) STORING (stored_col),
5189- UNIQUE (indexed_col, id)
5190- );
5191-
5192- statement ok
5193- ALTER TABLE self_dep_key_4 ADD CONSTRAINT t_fk
5194- FOREIGN KEY (indexed_col) REFERENCES self_dep_key_4 (indexed_col);
5195-
5196- query B
5197- SELECT column_drop_violates_fk_index_requirements('self_dep_key_4', 'stored_col');
5198- ----
5199- true
5200-
5201- # This should fail
5202- statement error pq: "self_dep_key_4_indexed_col_key" is referenced by foreign key from table "self_dep_key_4"
5203- ALTER TABLE self_dep_key_4 DROP COLUMN stored_col;
5204-
5205- subtest end
0 commit comments