Skip to content

Commit 4efece4

Browse files
authored
Merge pull request #159257 from spilchen/backport26.1-159188
release-26.1: workload: remove FK dependency check in schemachanger drop column
2 parents e15b1ec + c1e5412 commit 4efece4

File tree

3 files changed

+21
-508
lines changed

3 files changed

+21
-508
lines changed

pkg/sql/logictest/testdata/logic_test/fk

Lines changed: 0 additions & 366 deletions
Original file line numberDiff line numberDiff line change
@@ -4837,369 +4837,3 @@ DROP TABLE t2_fk;
48374837
DROP TABLE t1_fk;
48384838

48394839
subtest 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

Comments
 (0)