Skip to content

Commit 7e40539

Browse files
craig[bot]rafiss
andcommitted
Merge #157834
157834: sql: unset RBRUsingConstraint during rollback r=rafiss a=rafiss Previously, if a rollback dropped a constraint due to a FK validation error, it would never update the RBRUsingConstraint field even if the constraint being rolled back was referenced by that field. Now the field is cleared properly when needed. fixes #157832 Release note (bug fix): Fixed a bug that could cause a schema change to be stuck in the reverting state if the infer_rbr_region_col_using_constraint storage parameter was being set at the same time as adding a constraint that had a foreign key violation. Co-authored-by: Rafi Shamim <rafi@cockroachlabs.com>
2 parents e04fc04 + abf90df commit 7e40539

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

pkg/ccl/logictestccl/testdata/logic_test/regional_by_row_foreign_key

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,3 +2237,67 @@ DROP FUNCTION display_child;
22372237
DROP TABLE child;
22382238

22392239
subtest end
2240+
2241+
# ==============================================================================
2242+
# Verify that a foreign key violation causes the addition of the
2243+
# rbr_using_constraint to be reverted properly.
2244+
# ==============================================================================
2245+
2246+
subtest revert_fk_violation
2247+
2248+
statement ok
2249+
SET create_table_with_schema_locked = false;
2250+
2251+
statement ok
2252+
CREATE TABLE a (
2253+
id uuid NOT NULL PRIMARY KEY
2254+
) LOCALITY REGIONAL BY ROW
2255+
2256+
statement ok
2257+
CREATE TABLE b (
2258+
id uuid NOT NULL,
2259+
a_id uuid NULL,
2260+
CONSTRAINT b_pkey PRIMARY KEY (id ASC),
2261+
CONSTRAINT a_id_fk FOREIGN KEY (a_id) REFERENCES a (id)
2262+
) LOCALITY REGIONAL BY ROW
2263+
2264+
# Insert data that will cause a foreign key violation when we try to add the composite FK.
2265+
statement ok
2266+
INSERT INTO a (id, crdb_region) VALUES ('4227eceb-71d6-422c-808b-6a12ec8a1e54', 'us-east-1')
2267+
2268+
statement ok
2269+
INSERT INTO b (id, a_id, crdb_region) VALUES ('8f6ce660-423e-4823-8e41-bf001a007b46', '4227eceb-71d6-422c-808b-6a12ec8a1e54', 'ca-central-1')
2270+
2271+
# This statement should fail with a foreign key violation, and the schema change
2272+
# should properly revert without causing infinite retries due to the missing RBRUsingConstraint.
2273+
# Prior to the bugfix, the rollback logic would would drop the constraint but
2274+
# not clear the RBRUsingConstraint field, causing validation to fail during
2275+
# the rollback.
2276+
statement error pgcode 23503 pq: foreign key violation: "b" row crdb_region='ca-central-1', a_id='4227eceb-71d6-422c-808b-6a12ec8a1e54', id='8f6ce660-423e-4823-8e41-bf001a007b46' has no match in "a"
2277+
ALTER TABLE b
2278+
DROP CONSTRAINT a_id_fk,
2279+
ADD CONSTRAINT a_crdb_region_id_fk
2280+
FOREIGN KEY (crdb_region, a_id) REFERENCES a (crdb_region, id) ON UPDATE CASCADE ON DELETE CASCADE,
2281+
SET (infer_rbr_region_col_using_constraint = a_crdb_region_id_fk)
2282+
2283+
# Verify the tables are still functional after the failed schema change.
2284+
query I
2285+
SELECT count(*) FROM a
2286+
----
2287+
1
2288+
2289+
query I
2290+
SELECT count(*) FROM b
2291+
----
2292+
1
2293+
2294+
statement ok
2295+
DROP TABLE b CASCADE
2296+
2297+
statement ok
2298+
DROP TABLE a CASCADE
2299+
2300+
statement ok
2301+
RESET create_table_with_schema_locked;
2302+
2303+
subtest end

pkg/sql/schema_changer.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,6 +2531,11 @@ func (sc *SchemaChanger) maybeDropValidatingConstraint(
25312531
constraint.GetName(),
25322532
)
25332533
} else if constraint.AsForeignKey() != nil {
2534+
// If the constraint being dropped is the regional-by-row constraint,
2535+
// we must clear the reference to it.
2536+
if desc.RBRUsingConstraint == constraint.GetConstraintID() {
2537+
desc.RBRUsingConstraint = descpb.ConstraintID(0)
2538+
}
25342539
for i, fk := range desc.OutboundFKs {
25352540
if fk.Name == constraint.GetName() {
25362541
desc.OutboundFKs = append(desc.OutboundFKs[:i], desc.OutboundFKs[i+1:]...)

0 commit comments

Comments
 (0)