cockroachdb / cockroachdb/cockroach

sql: allow FK on minimal subset of columns that functionally determine a unique constraint

Open
#144,246 0 comments 0 reactions 0 assignees View on GitHub
A-hash-sharding A-sql-fks C-enhancement T-sql-queries
Dominant language
Go
Stars
32.5k
Forks
4.1k
PR merge metrics
PR metrics pending

Description

If we manually create a hash-sharded index with a hash function dependent on a prefix of columns, we are unable to create a FK reference to that unique index:

```sql
CREATE TABLE p (
id1 INT,
id2 INT,
val STRING NULL,
hash INT NOT VISIBLE NOT NULL AS
(mod(fnv32(md5(crdb_internal.datums_to_bytes(id1))), 16:::INT8)) STORED,
PRIMARY KEY (hash, id1, id2)
);

CREATE TABLE c (
id INT PRIMARY KEY,
p_id1 INT,
p_id2 INT,
FOREIGN KEY (p_id1, p_id2) REFERENCES p (id1, id2)
);
-- ERROR: there is no unique constraint matching given keys for referenced table p
-- SQLSTATE: 23503
```

This FK reference should be allowed because the value of `hash` is functionally determined by `id1`.

The current workaround is to create a computed column in the child table:

```sql
CREATE TABLE p (
id1 INT,
id2 INT,
val STRING NULL,
hash INT NOT VISIBLE NOT NULL AS
(mod(fnv32(md5(crdb_internal.datums_to_bytes(id1))), 16:::INT8)) STORED,
PRIMARY KEY (hash, id1, id2)
);

CREATE TABLE c (
id INT PRIMARY KEY,
p_id1 INT,
p_id2 INT,
p_hash INT NOT VISIBLE NOT NULL AS
(mod(fnv32(md5(crdb_internal.datums_to_bytes(p_id1))), 16:::INT8)) STORED,
FOREIGN KEY (p_hash, p_id1, p_id2) REFERENCES p (hash, id1, id2)
);
```

When we allow this we should take care to ensure that the optimizer can generate optimal query plans for FK checks and FK cascades.

This is related to:

* #69192
* #74140
* #76798
* #59671

Jira issue: CRDB-49288

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.