use pgsafe::{lint_sql, LintOptions};
fn fires(sql: &str, rule_id: &str) -> bool {
lint_sql(sql, &LintOptions::default())
.unwrap()
.iter()
.any(|f| f.rule_id == rule_id)
}
#[test]
fn public_qualified_correlates_with_bare_table() {
assert!(!fires(
"CREATE TABLE public.t (id int); DROP TABLE t;",
"drop-table"
));
assert!(!fires(
"CREATE TABLE t (id int); DROP TABLE public.t;",
"drop-table"
));
assert!(!fires(
"CREATE TABLE t (id int); TRUNCATE public.t;",
"truncate"
));
assert!(!fires(
"CREATE TABLE public.t (id int); TRUNCATE t;",
"truncate"
));
assert!(!fires(
"CREATE TABLE public.child (pid int REFERENCES parent); CREATE INDEX ON child (pid);",
"fk-without-covering-index"
));
assert!(!fires(
"CREATE TABLE child (pid int REFERENCES parent); CREATE INDEX ON public.child (pid);",
"fk-without-covering-index"
));
}
#[test]
fn non_public_schema_stays_distinct() {
assert!(fires(
"CREATE TABLE app.t (id int); DROP TABLE t;",
"drop-table"
));
assert!(fires(
"CREATE TABLE child (pid int REFERENCES parent); CREATE INDEX ON app.child (pid);",
"fk-without-covering-index"
));
}
#[test]
fn merge_populated_new_table_still_fires() {
assert!(fires(
"CREATE TABLE foo (id int); \
MERGE INTO foo USING src ON foo.id = src.id WHEN NOT MATCHED THEN INSERT VALUES (src.id); \
ALTER TABLE foo ADD CONSTRAINT u UNIQUE (id);",
"add-unique-constraint"
));
}
#[test]
fn directive_on_dropped_new_table_op_is_not_unused() {
let fs = lint_sql(
"CREATE TABLE foo (id int);\n\
-- pgsafe:ignore add-unique-constraint belt and suspenders\n\
ALTER TABLE foo ADD CONSTRAINT u UNIQUE (id);",
&LintOptions::default(),
)
.unwrap();
assert!(
!fs.iter().any(|f| f.rule_id == "suppression-unused"),
"directive on a dropped new-table op must not be reported unused"
);
assert!(fs.is_empty(), "the run should be clean");
}
#[test]
fn empty_new_table_operations_are_dropped() {
assert!(!fires(
"CREATE TABLE foo (id int); ALTER TABLE foo ADD CONSTRAINT u UNIQUE (id);",
"add-unique-constraint"
));
assert!(!fires(
"CREATE TABLE foo (id int); ALTER TABLE foo ADD COLUMN c uuid DEFAULT gen_random_uuid();",
"add-column-volatile-default"
));
assert!(!fires(
"CREATE TABLE foo (id int); CREATE INDEX i ON foo (id);",
"add-index-non-concurrent"
));
assert!(!fires(
"CREATE TABLE foo (id int); ALTER TABLE foo ADD COLUMN x int CHECK (x > 0);",
"add-check-without-not-valid"
));
assert!(!fires(
"CREATE TABLE foo (id int); ALTER TABLE foo ADD COLUMN x int DEFAULT 5 CHECK (x > 0);",
"add-check-without-not-valid"
));
}
#[test]
fn drop_truncate_rename_on_new_empty_table_are_dropped() {
assert!(!fires(
"CREATE TABLE foo (id int); DROP TABLE foo;",
"drop-table"
));
assert!(!fires(
"CREATE TABLE foo (id int); TRUNCATE foo;",
"truncate"
));
assert!(!fires(
"CREATE TABLE foo (id int); ALTER TABLE foo RENAME TO bar;",
"rename"
));
assert!(!fires(
"CREATE TABLE foo (id int, a int); ALTER TABLE foo RENAME COLUMN a TO b;",
"rename"
));
}
#[test]
fn drop_truncate_rename_on_existing_or_populated_table_still_fire() {
assert!(fires("DROP TABLE foo;", "drop-table"));
assert!(fires("TRUNCATE foo;", "truncate"));
assert!(fires("ALTER TABLE foo RENAME TO bar;", "rename"));
assert!(fires(
"CREATE TABLE foo (id int); INSERT INTO foo VALUES (1); DROP TABLE foo;",
"drop-table"
));
assert!(fires(
"CREATE TABLE foo (id int); INSERT INTO foo VALUES (1); TRUNCATE foo;",
"truncate"
));
assert!(fires(
"CREATE TABLE foo (id int); CREATE TABLE bar (id int); DROP TABLE foo, bar;",
"drop-table"
));
assert!(fires(
"CREATE TABLE foo (id int); CREATE TABLE bar (id int); TRUNCATE foo, bar;",
"truncate"
));
}
#[test]
fn populated_new_table_still_fires() {
assert!(fires(
"CREATE TABLE foo (id int); INSERT INTO foo VALUES (1); ALTER TABLE foo ADD CONSTRAINT u UNIQUE (id);",
"add-unique-constraint"
));
assert!(fires(
"CREATE TABLE foo (id int); COPY foo FROM '/tmp/data.csv'; ALTER TABLE foo ADD CONSTRAINT u UNIQUE (id);",
"add-unique-constraint"
));
assert!(fires(
"CREATE TABLE foo AS SELECT 1 AS id; ALTER TABLE foo ADD CONSTRAINT u UNIQUE (id);",
"add-unique-constraint"
));
}
#[test]
fn not_a_new_table_still_fires() {
assert!(fires(
"ALTER TABLE bar ADD CONSTRAINT u UNIQUE (id);",
"add-unique-constraint"
));
assert!(fires(
"CREATE TABLE foo (id int); ALTER TABLE other ADD CONSTRAINT u UNIQUE (id);",
"add-unique-constraint"
));
assert!(fires(
"CREATE TABLE s.foo (id int); ALTER TABLE foo ADD CONSTRAINT u UNIQUE (id);",
"add-unique-constraint"
));
}
#[test]
fn alter_before_create_still_fires() {
assert!(fires(
"ALTER TABLE foo ADD CONSTRAINT u UNIQUE (id); CREATE TABLE foo (id int);",
"add-unique-constraint"
));
}