From 322b5b0370a223ab0e48bd0b2a6992e265d78d71 Mon Sep 17 00:00:00 2001 From: Steve Dignam Date: Wed, 25 Feb 2026 09:48:52 -0500 Subject: [PATCH] linter: undo foreign key constraint check in create table --- .../rules/adding_foreign_key_constraint.rs | 47 ++++--------------- ...ld_with_default__test__add_numbers_ok.snap | 5 -- ...d_with_default__test__default_bool_ok.snap | 5 -- ...default__test__default_empty_array_ok.snap | 5 -- ...d_with_default__test__default_enum_ok.snap | 5 -- ...st__default_func_current_timestamp_ok.snap | 5 -- ...th_default__test__default_func_now_ok.snap | 5 -- ..._with_default__test__default_jsonb_ok.snap | 5 -- ...ld_with_default__test__default_str_ok.snap | 5 -- ...lt__test__default_with_const_bin_expr.snap | 5 -- ...d_with_default__test__docs_example_ok.snap | 5 -- ...ult__test__docs_example_ok_post_pg_11.snap | 5 -- ...__create_table_with_column_references.snap | 10 ---- ...ate_table_with_foreign_key_constraint.snap | 12 ----- 14 files changed, 9 insertions(+), 115 deletions(-) delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__add_numbers_ok.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_bool_ok.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_empty_array_ok.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_enum_ok.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_func_current_timestamp_ok.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_func_now_ok.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_jsonb_ok.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_str_ok.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_with_const_bin_expr.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__docs_example_ok.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__docs_example_ok_post_pg_11.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_foreign_key_constraint__test__create_table_with_column_references.snap delete mode 100644 crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_foreign_key_constraint__test__create_table_with_foreign_key_constraint.snap diff --git a/crates/squawk_linter/src/rules/adding_foreign_key_constraint.rs b/crates/squawk_linter/src/rules/adding_foreign_key_constraint.rs index 42c4c192..92a2cacc 100644 --- a/crates/squawk_linter/src/rules/adding_foreign_key_constraint.rs +++ b/crates/squawk_linter/src/rules/adding_foreign_key_constraint.rs @@ -74,42 +74,9 @@ pub(crate) fn adding_foreign_key_constraint(ctx: &mut Linter, parse: &Parse { - if let Some(table_arg_list) = create_table.table_arg_list() { - for arg in table_arg_list.args() { - match arg { - ast::TableArg::TableConstraint( - ast::TableConstraint::ForeignKeyConstraint(fk), - ) => { - ctx.report( - Violation::for_node( - Rule::AddingForeignKeyConstraint, - message.into(), - fk.syntax(), - ) - .help(help), - ); - } - ast::TableArg::Column(column) => { - for constraint in column.constraints() { - if let ast::ColumnConstraint::ReferencesConstraint(refs) = - constraint - { - ctx.report( - Violation::for_node( - Rule::AddingForeignKeyConstraint, - message.into(), - refs.syntax(), - ) - .help(help), - ); - } - } - } - _ => (), - } - } - } + ast::Stmt::CreateTable(_) => { + // NOTE: we don't consider foreign key constraints in create + // table stmts as there are no rows in the current table. } _ => (), } @@ -129,6 +96,8 @@ mod test { #[test] fn create_table_with_foreign_key_constraint() { + // Okay as there are no rows in the current table. We'll take a share + // row exclusive lock on the related table but won't hold it for long. let sql = r#" BEGIN; CREATE TABLE email ( @@ -143,11 +112,13 @@ CREATE TABLE email ( COMMIT; "#; - assert_snapshot!(lint_errors(sql, Rule::AddingForeignKeyConstraint)); + lint_ok(sql, Rule::AddingForeignKeyConstraint); } #[test] fn create_table_with_column_references() { + // Okay as there are no rows in the current table. We'll take a share + // row exclusive lock on the related table but won't hold it for long. let sql = r#" CREATE TABLE table_name ( id BIGSERIAL NOT NULL, @@ -155,7 +126,7 @@ CREATE TABLE table_name ( ); "#; - assert_snapshot!(lint_errors(sql, Rule::AddingForeignKeyConstraint)); + lint_ok(sql, Rule::AddingForeignKeyConstraint); } #[test] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__add_numbers_ok.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__add_numbers_ok.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__add_numbers_ok.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_bool_ok.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_bool_ok.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_bool_ok.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_empty_array_ok.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_empty_array_ok.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_empty_array_ok.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_enum_ok.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_enum_ok.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_enum_ok.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_func_current_timestamp_ok.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_func_current_timestamp_ok.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_func_current_timestamp_ok.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_func_now_ok.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_func_now_ok.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_func_now_ok.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_jsonb_ok.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_jsonb_ok.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_jsonb_ok.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_str_ok.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_str_ok.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_str_ok.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_with_const_bin_expr.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_with_const_bin_expr.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__default_with_const_bin_expr.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__docs_example_ok.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__docs_example_ok.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__docs_example_ok.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__docs_example_ok_post_pg_11.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__docs_example_ok_post_pg_11.snap deleted file mode 100644 index 5563b6de..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_field_with_default__test__docs_example_ok_post_pg_11.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_field_with_default.rs -expression: errors ---- -[] diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_foreign_key_constraint__test__create_table_with_column_references.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_foreign_key_constraint__test__create_table_with_column_references.snap deleted file mode 100644 index 99f84a8b..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_foreign_key_constraint__test__create_table_with_column_references.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_foreign_key_constraint.rs -expression: "lint_errors(sql, Rule::AddingForeignKeyConstraint)" ---- -warning[adding-foreign-key-constraint]: Adding a foreign key constraint requires a table scan and a `SHARE ROW EXCLUSIVE` lock on both tables, which blocks writes to each table. - ╭▸ -4 │ my_fk_id INTEGER NOT NULL REFERENCES other_table (id) ON DELETE CASCADE - │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - │ - ╰ help: Add `NOT VALID` to the constraint in one transaction and then VALIDATE the constraint in a separate transaction. diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_foreign_key_constraint__test__create_table_with_foreign_key_constraint.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_foreign_key_constraint__test__create_table_with_foreign_key_constraint.snap deleted file mode 100644 index 2f9766d8..00000000 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__adding_foreign_key_constraint__test__create_table_with_foreign_key_constraint.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: crates/squawk_linter/src/rules/adding_foreign_key_constraint.rs -expression: "lint_errors(sql, Rule::AddingForeignKeyConstraint)" ---- -warning[adding-foreign-key-constraint]: Adding a foreign key constraint requires a table scan and a `SHARE ROW EXCLUSIVE` lock on both tables, which blocks writes to each table. - ╭▸ - 8 │ ┏ CONSTRAINT fk_user - 9 │ ┃ FOREIGN KEY ("user_id") -10 │ ┃ REFERENCES "user" ("id") - │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - │ - ╰ help: Add `NOT VALID` to the constraint in one transaction and then VALIDATE the constraint in a separate transaction.