Skip to content

Commit

Permalink
sql: ignore shard column during unique constraint searching
Browse files Browse the repository at this point in the history
Fixes cockroachdb#69192

Referencing table does not know about the shard column. So
need to ignore it when looking for a valid unique constraint.

Release note (bug fix): Foreign key referencing hash sharded
key won't fail anymore.
  • Loading branch information
chengxiong-ruan committed Dec 21, 2021
1 parent 2bf8508 commit 60b2a8f
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 3 deletions.
19 changes: 16 additions & 3 deletions pkg/sql/catalog/descpb/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,26 @@ func (desc *IndexDescriptor) IsValidOriginIndex(originColIDs ColumnIDs) bool {
return !desc.IsPartial() && ColumnIDs(desc.KeyColumnIDs).HasPrefix(originColIDs)
}

// ExplicitColumnIDsWithoutShardColumn returns explicit column ids of the index
// excluding the shard column.
func (desc *IndexDescriptor) ExplicitColumnIDsWithoutShardColumn() []ColumnID {
explicitColIDs := desc.KeyColumnIDs[desc.ExplicitColumnStartIdx():]
explicitColNames := desc.KeyColumnNames[desc.ExplicitColumnStartIdx():]
colIDs := make([]ColumnID, 0, len(explicitColIDs))
for i := range explicitColNames {
if !desc.IsSharded() || explicitColNames[i] != desc.Sharded.Name {
colIDs = append(colIDs, explicitColIDs[i])
}
}
return colIDs
}

// IsValidReferencedUniqueConstraint is part of the UniqueConstraint interface.
// It returns whether the index can serve as a referenced index for a foreign
// key constraint with the provided set of referencedColumnIDs.
func (desc *IndexDescriptor) IsValidReferencedUniqueConstraint(referencedColIDs ColumnIDs) bool {
return desc.Unique &&
!desc.IsPartial() &&
ColumnIDs(desc.KeyColumnIDs[desc.Partitioning.NumImplicitColumns:]).PermutationOf(referencedColIDs)
colIDs := desc.ExplicitColumnIDsWithoutShardColumn()
return desc.Unique && !desc.IsPartial() && ColumnIDs(colIDs).PermutationOf(referencedColIDs)
}

// GetName is part of the UniqueConstraint interface.
Expand Down
127 changes: 127 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/hash_sharded_index
Original file line number Diff line number Diff line change
Expand Up @@ -680,3 +680,130 @@ descriptor_id descriptor_name index_id index_name index_type is_unique is

statement ok
DROP TABLE poor_t

subtest fk_reference_shard_pk

statement ok
DROP TABLE IF EXISTS child

statement ok
DROP TABLE IF EXISTS parent

statement ok
CREATE TABLE parent (
id INT PRIMARY KEY USING HASH WITH BUCKET_COUNT = 8
);

statement ok
CREATE TABLE child (
id INT PRIMARY KEY,
pid INT,
CONSTRAINT fk_child_pid FOREIGN KEY (pid) REFERENCES parent(id) ON DELETE CASCADE
);

statement error pq: insert on table "child" violates foreign key constraint "fk_child_pid"
INSERT INTO child VALUES (1,1)

statement ok
INSERT INTO parent VALUES (1)

statement ok
INSERT INTO child VALUES (1,1)

subtest fk_reference_shard_index

statement ok
DROP TABLE IF EXISTS child

statement ok
DROP TABLE IF EXISTS parent

statement ok
CREATE TABLE parent (
id INT PRIMARY KEY,
oid INT
);

statement ok
CREATE UNIQUE INDEX t_idx_oid ON parent(oid) USING HASH WITH BUCKET_COUNT = 8

statement ok
CREATE TABLE child (
id INT PRIMARY KEY,
poid INT,
CONSTRAINT fk_child_pid FOREIGN KEY (poid) REFERENCES parent(oid) ON DELETE CASCADE
);

statement error pq: insert on table "child" violates foreign key constraint "fk_child_pid"
INSERT INTO child VALUES (1,11)

statement ok
INSERT INTO parent VALUES (1,11)

statement ok
INSERT INTO child VALUES (1,11)

subtest fk_reference_shard_pk_multi_col

statement ok
DROP TABLE IF EXISTS child

statement ok
DROP TABLE IF EXISTS parent

statement ok
CREATE TABLE parent (
a INT NOT NULL,
b INT NOT NULL,
PRIMARY KEY (a, b) USING HASH WITH BUCKET_COUNT = 8
);

statement ok
CREATE TABLE child (
ca INT PRIMARY KEY,
cb INT,
CONSTRAINT fk_child_ca_cb FOREIGN KEY (ca, cb) REFERENCES parent(a, b) ON DELETE CASCADE
);

statement error pq: insert on table "child" violates foreign key constraint "fk_child_ca_cb"
INSERT INTO child VALUES (1,1)

statement ok
INSERT INTO parent VALUES (1,1)

statement ok
INSERT INTO child VALUES (1,1)

subtest fk_reference_shard_index_multi_col

statement ok
DROP TABLE IF EXISTS child

statement ok
DROP TABLE IF EXISTS parent

statement ok
CREATE TABLE parent (
a INT,
b INT
);

statement ok
CREATE UNIQUE INDEX t_idx_a_b ON parent(a, b) USING HASH WITH BUCKET_COUNT = 8


statement ok
CREATE TABLE child (
ca INT PRIMARY KEY,
cb INT,
CONSTRAINT fk_child_ca_cb FOREIGN KEY (ca, cb) REFERENCES parent(a, b) ON DELETE CASCADE
);

statement error pq: insert on table "child" violates foreign key constraint "fk_child_ca_cb"
INSERT INTO child VALUES (1,1)

statement ok
INSERT INTO parent VALUES (1,1)

statement ok
INSERT INTO child VALUES (1,1)

0 comments on commit 60b2a8f

Please sign in to comment.