Skip to content

Commit

Permalink
sql: block FKs to/from TTL tables
Browse files Browse the repository at this point in the history
This table blocks FKs to and from TTL tables. Note the RFC previously
only said to not block from TTL tables, but I actually thought of a
new case and decided that is was probably prudent to block this both
ways. RFC is reflected accordingly.

Release note: None
  • Loading branch information
otan committed Feb 15, 2022
1 parent c7446c5 commit 3dafe1b
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 4 deletions.
14 changes: 10 additions & 4 deletions docs/RFCS/20220120_row_level_ttl.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,16 @@ Rows that have expired their TTL can be optionally removed from all SQL query
results. Work for this is required at the optimizer layer. However, this is not
planned to be implemented for the first iteration of TTL.

## Foreign Keys to a TTL Table
To avoid additional complexity in the initial implementation, foreign keys to
TTL tables will not be permitted. More thought has to be put on ON
DELETE/ON UPDATE CASCADEs before we can look at allowing this functionality.
## Foreign Keys to/from TTL Tables
To avoid additional complexity in the initial implementation, foreign keys (FK)
to and from TTL tables will not be permitted due to complexities with the
implementation which are complex to handle, for example:
* When having a non-TTL table with a FK dependent on a TTL table with an
`ON UPDATE/DELETE CASCADE`, the non-TTL table need to hide any rows which
are linked to an expired TTL row.
* When having a TTL table with an FK dependent on a non-TTL table,
`ON DELETE RESTRICT` should only block a delete on the non-TTL table
if the row has expired.

## Introspection
The TTL definition for the table will appear in `SHOW CREATE TABLE`. The options
Expand Down
2 changes: 2 additions & 0 deletions pkg/sql/catalog/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,8 @@ type TableDescriptor interface {
GetRegionalByRowTableRegionColumnName() (tree.Name, error)
// GetRowLevelTTL returns the row-level TTL config for the table.
GetRowLevelTTL() *descpb.TableDescriptor_RowLevelTTL
// HasRowLevelTTL returns where there is a row-level TTL config for the table.
HasRowLevelTTL() bool
// GetExcludeDataFromBackup returns true if the table's row data is configured
// to be excluded during backup.
GetExcludeDataFromBackup() bool
Expand Down
5 changes: 5 additions & 0 deletions pkg/sql/catalog/tabledesc/structured.go
Original file line number Diff line number Diff line change
Expand Up @@ -2440,6 +2440,11 @@ func (desc *wrapper) GetRowLevelTTL() *descpb.TableDescriptor_RowLevelTTL {
return desc.RowLevelTTL
}

// HasRowLevelTTL implements the TableDescriptor interface.
func (desc *wrapper) HasRowLevelTTL() bool {
return desc.RowLevelTTL != nil
}

// GetExcludeDataFromBackup implements the TableDescriptor interface.
func (desc *wrapper) GetExcludeDataFromBackup() bool {
return desc.ExcludeDataFromBackup
Expand Down
7 changes: 7 additions & 0 deletions pkg/sql/catalog/tabledesc/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ func (desc *wrapper) ValidateCrossReferences(
}

// Check foreign keys.
if desc.HasRowLevelTTL() && (len(desc.OutboundFKs) > 0 || len(desc.InboundFKs) > 0) {
vea.Report(unimplemented.NewWithIssuef(
76407,
`foreign keys to/from table with TTL "%s" are not permitted`,
desc.Name,
))
}
for i := range desc.OutboundFKs {
vea.Report(desc.validateOutboundFK(&desc.OutboundFKs[i], vdg))
}
Expand Down
25 changes: 25 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/row_level_ttl
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,28 @@ CREATE TABLE public.tbl (
CONSTRAINT tbl_pkey PRIMARY KEY (id ASC),
FAMILY fam_0_id_text_crdb_internal_expiration (id, text, crdb_internal_expiration)
) WITH (ttl = 'on', ttl_automatic_column = 'on', ttl_expire_after = '00:10:00':::INTERVAL)

# Test we cannot add FKs to a TTL table.
statement ok
CREATE TABLE ref_table (id INT PRIMARY KEY, ref INT)

statement error foreign keys to/from table with TTL "ttl_table" are not permitted
CREATE TABLE ttl_table (id INT PRIMARY KEY, ref INT REFERENCES ref_table(id)) WITH (ttl_expire_after = '10 mins')

statement ok
CREATE TABLE ttl_table (id INT PRIMARY KEY, ref INT) WITH (ttl_expire_after = '10 mins')

statement error foreign keys to/from table with TTL "ttl_table" are not permitted
CREATE TABLE new_ref_table (id INT PRIMARY KEY, ref INT REFERENCES ttl_table(id))

statement error foreign keys to/from table with TTL "ttl_table" are not permitted
ALTER TABLE ref_table ADD CONSTRAINT fk FOREIGN KEY (ref) REFERENCES ttl_table (id)

statement error foreign keys to/from table with TTL "ttl_table" are not permitted
ALTER TABLE ttl_table ADD CONSTRAINT fk FOREIGN KEY (ref) REFERENCES ttl_table (id)

statement ok
CREATE TABLE ttl_become_table (id INT PRIMARY KEY, ref INT REFERENCES ref_table (id))

statement error foreign keys to/from table with TTL "ttl_become_table" are not permitted
ALTER TABLE ttl_become_table SET (ttl_expire_after = '10 minutes')

0 comments on commit 3dafe1b

Please sign in to comment.