mirror of
https://github.com/simonw/sqlite-utils.git
synced 2026-07-25 02:14:31 +02:00
Capture and preserve foreign key ON DELETE/ON UPDATE actions
ForeignKey gains on_delete and on_update fields (default "NO ACTION"), populated from PRAGMA foreign_key_list. create_table_sql() renders the corresponding clauses for both inline and compound table-level foreign keys, which means table.transform() now preserves actions such as ON DELETE CASCADE - previously they were silently stripped whenever a table was transformed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
b75edf4b30
commit
be27a96484
3 changed files with 139 additions and 10 deletions
|
|
@ -190,6 +190,8 @@ class ForeignKey:
|
|||
columns: List[str] = field(default_factory=list)
|
||||
other_columns: List[str] = field(default_factory=list)
|
||||
is_compound: bool = False
|
||||
on_delete: str = "NO ACTION"
|
||||
on_update: str = "NO ACTION"
|
||||
|
||||
def __post_init__(self):
|
||||
# Populate columns/other_columns for single-column foreign keys
|
||||
|
|
@ -201,6 +203,16 @@ class ForeignKey:
|
|||
)
|
||||
|
||||
|
||||
def _fk_actions_sql(fk: ForeignKey) -> str:
|
||||
"ON UPDATE/ON DELETE clauses for a foreign key, or an empty string."
|
||||
actions = ""
|
||||
if fk.on_update and fk.on_update != "NO ACTION":
|
||||
actions += " ON UPDATE {}".format(fk.on_update)
|
||||
if fk.on_delete and fk.on_delete != "NO ACTION":
|
||||
actions += " ON DELETE {}".format(fk.on_delete)
|
||||
return actions
|
||||
|
||||
|
||||
Index = namedtuple("Index", ("seq", "name", "unique", "origin", "partial", "columns"))
|
||||
XIndex = namedtuple("XIndex", ("name", "columns"))
|
||||
XIndexColumn = namedtuple(
|
||||
|
|
@ -1345,14 +1357,12 @@ class Database:
|
|||
"DEFAULT {}".format(self.quote_default_value(defaults[column_name]))
|
||||
)
|
||||
if column_name in foreign_keys_by_column:
|
||||
fk = foreign_keys_by_column[column_name]
|
||||
column_extras.append(
|
||||
"REFERENCES {}({})".format(
|
||||
quote_identifier(
|
||||
foreign_keys_by_column[column_name].other_table
|
||||
),
|
||||
quote_identifier(
|
||||
cast(str, foreign_keys_by_column[column_name].other_column)
|
||||
),
|
||||
"REFERENCES {}({}){}".format(
|
||||
quote_identifier(fk.other_table),
|
||||
quote_identifier(cast(str, fk.other_column)),
|
||||
_fk_actions_sql(fk),
|
||||
)
|
||||
)
|
||||
column_type_str = COLUMN_TYPE_MAPPING[column_type]
|
||||
|
|
@ -1385,12 +1395,13 @@ class Database:
|
|||
"No such column: {}".format(", ".join(sorted(missing)))
|
||||
)
|
||||
column_defs.append(
|
||||
" FOREIGN KEY ({columns}) REFERENCES {other_table}({other_columns})".format(
|
||||
" FOREIGN KEY ({columns}) REFERENCES {other_table}({other_columns}){actions}".format(
|
||||
columns=", ".join(quote_identifier(c) for c in fk.columns),
|
||||
other_table=quote_identifier(fk.other_table),
|
||||
other_columns=", ".join(
|
||||
quote_identifier(c) for c in fk.other_columns
|
||||
),
|
||||
actions=_fk_actions_sql(fk),
|
||||
)
|
||||
)
|
||||
columns_sql = ",\n".join(column_defs)
|
||||
|
|
@ -2055,7 +2066,9 @@ class Table(Queryable):
|
|||
).fetchall():
|
||||
if row is not None:
|
||||
id, seq, table_name, from_, to_, on_update, on_delete, match = row
|
||||
by_id.setdefault(id, []).append((seq, table_name, from_, to_))
|
||||
by_id.setdefault(id, []).append(
|
||||
(seq, table_name, from_, to_, on_update, on_delete)
|
||||
)
|
||||
fks = []
|
||||
for id in sorted(by_id):
|
||||
rows = sorted(by_id[id]) # order columns by seq
|
||||
|
|
@ -2072,6 +2085,8 @@ class Table(Queryable):
|
|||
columns=columns,
|
||||
other_columns=other_columns,
|
||||
is_compound=is_compound,
|
||||
on_update=rows[0][4],
|
||||
on_delete=rows[0][5],
|
||||
)
|
||||
)
|
||||
return fks
|
||||
|
|
@ -2434,9 +2449,16 @@ class Table(Queryable):
|
|||
columns=columns,
|
||||
other_columns=fk.other_columns,
|
||||
is_compound=True,
|
||||
on_delete=fk.on_delete,
|
||||
on_update=fk.on_update,
|
||||
)
|
||||
return ForeignKey(
|
||||
self.name, columns[0], fk.other_table, fk.other_columns[0]
|
||||
self.name,
|
||||
columns[0],
|
||||
fk.other_table,
|
||||
fk.other_columns[0],
|
||||
on_delete=fk.on_delete,
|
||||
on_update=fk.on_update,
|
||||
)
|
||||
|
||||
create_table_foreign_keys = []
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue