mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-31 05:44:25 +01:00
fix: prevent DROP TABLE when table is referenced by foreign keys
Add foreign key constraint check in translate_drop_table to reject dropping tables that are referenced by foreign keys when PRAGMA foreign_keys=ON
This commit is contained in:
@@ -231,7 +231,7 @@ pub fn translate_inner(
|
||||
ast::Stmt::DropTable {
|
||||
if_exists,
|
||||
tbl_name,
|
||||
} => translate_drop_table(tbl_name, resolver, if_exists, program)?,
|
||||
} => translate_drop_table(tbl_name, resolver, if_exists, program, connection)?,
|
||||
ast::Stmt::DropTrigger { .. } => bail_parse_error!("DROP TRIGGER not supported yet"),
|
||||
ast::Stmt::DropView {
|
||||
if_exists,
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::util::PRIMARY_KEY_AUTOMATIC_INDEX_NAME_PREFIX;
|
||||
use crate::vdbe::builder::CursorType;
|
||||
use crate::vdbe::insn::{CmpInsFlags, Cookie, InsertFlags, Insn};
|
||||
use crate::Connection;
|
||||
use crate::{bail_parse_error, Result};
|
||||
use crate::{bail_constraint_error, bail_parse_error, Result};
|
||||
|
||||
use turso_ext::VTabKind;
|
||||
|
||||
@@ -608,6 +608,7 @@ pub fn translate_drop_table(
|
||||
resolver: &Resolver,
|
||||
if_exists: bool,
|
||||
mut program: ProgramBuilder,
|
||||
connection: &Connection,
|
||||
) -> Result<ProgramBuilder> {
|
||||
if tbl_name
|
||||
.name
|
||||
@@ -657,6 +658,15 @@ pub fn translate_drop_table(
|
||||
tbl_name.name.as_str()
|
||||
);
|
||||
}
|
||||
|
||||
// Check if foreign keys are enabled and if this table is referenced by foreign keys
|
||||
if connection.foreign_keys_enabled()
|
||||
&& resolver
|
||||
.schema
|
||||
.any_resolved_fks_referencing(table.get_name())
|
||||
{
|
||||
bail_constraint_error!("FOREIGN KEY constraint failed");
|
||||
}
|
||||
let cdc_table = prepare_cdc_if_necessary(&mut program, resolver.schema, SQLITE_TABLEID)?;
|
||||
|
||||
let null_reg = program.alloc_register(); // r1
|
||||
|
||||
@@ -62,3 +62,24 @@ do_execsql_test_on_specific_db {:memory:} drop-table-after-ops-1 {
|
||||
DROP TABLE t6;
|
||||
SELECT count(*) FROM sqlite_schema WHERE type='table' AND name='t6';
|
||||
} {0}
|
||||
|
||||
# Test that DROP TABLE fails when table is referenced by foreign keys
|
||||
do_execsql_test_in_memory_any_error drop-table-fk-constraint-failed {
|
||||
PRAGMA foreign_keys=ON;
|
||||
CREATE TABLE parent(a INTEGER PRIMARY KEY);
|
||||
CREATE TABLE child(a INTEGER PRIMARY KEY, b INTEGER, FOREIGN KEY(b) REFERENCES parent(a));
|
||||
INSERT INTO parent VALUES (1);
|
||||
INSERT INTO child VALUES (123, 1);
|
||||
DROP TABLE parent;
|
||||
}
|
||||
|
||||
# Test that DROP TABLE succeeds when foreign keys are disabled
|
||||
do_execsql_test_on_specific_db {:memory:} drop-table-fk-disabled-ok {
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE parent(a INTEGER PRIMARY KEY);
|
||||
CREATE TABLE child(a INTEGER PRIMARY KEY, b INTEGER, FOREIGN KEY(b) REFERENCES parent(a));
|
||||
INSERT INTO parent VALUES (1);
|
||||
INSERT INTO child VALUES (123, 1);
|
||||
DROP TABLE parent;
|
||||
SELECT count(*) FROM sqlite_schema WHERE type='table' AND name='parent';
|
||||
} {0}
|
||||
|
||||
Reference in New Issue
Block a user