Change ALTER TABLE constraints parsing

- merge PrimaryKey and UniqueKey variants
- support `CHECK` constraints, removing the separate `Key` struct
- make `CONSTRAINT constraint_name` optional
- remove `KEY` without qualifiers (wasn't parsed and there doesn't
  appear to be such a thing)
- change `UNIQUE KEY` -> `UNIQUE`
- change `REMOVE CONSTRAINT` -> `DROP CONSTRAINT` and note its parsing
  is not implemented

Spec:
- ANSI SQL: see <table constraint definition> in https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#_11_6_table_constraint_definition
- Postgres: look for "and table_constraint is:" in https://www.postgresql.org/docs/11/sql-altertable.html
This commit is contained in:
Nickolay Ponomarev 2019-05-08 03:06:40 +03:00
parent 721c24188a
commit c69a1881c7
5 changed files with 150 additions and 114 deletions

View file

@ -736,26 +736,31 @@ fn parse_create_external_table() {
}
#[test]
fn parse_alter_table_constraint_primary_key() {
let sql = "ALTER TABLE bazaar.address \
ADD CONSTRAINT address_pkey PRIMARY KEY (address_id)";
match verified_stmt(sql) {
SQLStatement::SQLAlterTable { name, .. } => {
assert_eq!(name.to_string(), "bazaar.address");
}
_ => unreachable!(),
}
}
fn parse_alter_table_constraints() {
check_one("CONSTRAINT address_pkey PRIMARY KEY (address_id)");
check_one("CONSTRAINT uk_task UNIQUE (report_date, task_id)");
check_one(
"CONSTRAINT customer_address_id_fkey FOREIGN KEY (address_id) \
REFERENCES public.address(address_id)",
);
check_one("CONSTRAINT ck CHECK (rtrim(ltrim(REF_CODE)) <> '')");
#[test]
fn parse_alter_table_constraint_foreign_key() {
let sql = "ALTER TABLE public.customer \
ADD CONSTRAINT customer_address_id_fkey FOREIGN KEY (address_id) REFERENCES public.address(address_id)";
match verified_stmt(sql) {
SQLStatement::SQLAlterTable { name, .. } => {
assert_eq!(name.to_string(), "public.customer");
check_one("PRIMARY KEY (foo, bar)");
check_one("UNIQUE (id)");
check_one("FOREIGN KEY (foo, bar) REFERENCES AnotherTable(foo, bar)");
check_one("CHECK (end_date > start_date OR end_date IS NULL)");
fn check_one(constraint_text: &str) {
match verified_stmt(&format!("ALTER TABLE tab ADD {}", constraint_text)) {
SQLStatement::SQLAlterTable {
name,
operation: AlterOperation::AddConstraint(constraint),
} => {
assert_eq!("tab", name.to_string());
assert_eq!(constraint_text, constraint.to_string());
}
_ => unreachable!(),
}
_ => unreachable!(),
}
}