Skip to content

Commit 1949e63

Browse files
authored
Support more CREATE/ALTER/DROP statements (#111)
We might want to provide a knob to decide if the the arguments of `ALTER TABLE` should be considered top level or not.
1 parent 832fa6e commit 1949e63

File tree

2 files changed

+106
-16
lines changed

2 files changed

+106
-16
lines changed

src/lib.rs

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,46 @@ mod tests {
660660
assert_eq!(format(input, &QueryParams::None, &options), expected);
661661
}
662662

663+
#[test]
664+
fn it_does_format_drop() {
665+
let input = indoc!(
666+
"
667+
DROP INDEX IF EXISTS idx_a;
668+
DROP INDEX IF EXISTS idx_b;
669+
"
670+
);
671+
672+
let options = FormatOptions {
673+
..Default::default()
674+
};
675+
676+
let expected = indoc!(
677+
"
678+
DROP INDEX IF EXISTS
679+
idx_a;
680+
DROP INDEX IF EXISTS
681+
idx_b;"
682+
);
683+
684+
assert_eq!(format(input, &QueryParams::None, &options), expected);
685+
686+
let input = indoc!(
687+
r#"
688+
-- comment
689+
DROP TABLE IF EXISTS "public"."table_name";
690+
"#
691+
);
692+
693+
let expected = indoc!(
694+
r#"
695+
-- comment
696+
DROP TABLE IF EXISTS
697+
"public"."table_name";"#
698+
);
699+
700+
assert_eq!(format(input, &QueryParams::None, &options), expected);
701+
}
702+
663703
#[test]
664704
fn it_formats_select_query_with_inner_join() {
665705
let input = indoc!(
@@ -995,8 +1035,12 @@ mod tests {
9951035
fn it_formats_simple_drop_query() {
9961036
let input = "DROP TABLE IF EXISTS admin_role;";
9971037
let options = FormatOptions::default();
998-
999-
assert_eq!(format(input, &QueryParams::None, &options), input);
1038+
let output = indoc!(
1039+
"
1040+
DROP TABLE IF EXISTS
1041+
admin_role;"
1042+
);
1043+
assert_eq!(format(input, &QueryParams::None, &options), output);
10001044
}
10011045

10021046
#[test]
@@ -1418,8 +1462,30 @@ mod tests {
14181462
"
14191463
ALTER TABLE
14201464
supplier
1421-
ALTER COLUMN
1422-
supplier_name VARCHAR(100) NOT NULL;"
1465+
ALTER COLUMN supplier_name VARCHAR(100) NOT NULL;"
1466+
);
1467+
1468+
assert_eq!(format(input, &QueryParams::None, &options), expected);
1469+
}
1470+
1471+
#[test]
1472+
fn it_formats_alter_table_add_and_drop() {
1473+
let input = r#"ALTER TABLE "public"."event" DROP CONSTRAINT "validate_date", ADD CONSTRAINT "validate_date" CHECK (end_date IS NULL
1474+
OR (start_date IS NOT NULL AND end_date > start_date));"#;
1475+
1476+
let options = FormatOptions::default();
1477+
let expected = indoc!(
1478+
r#"
1479+
ALTER TABLE
1480+
"public"."event"
1481+
DROP CONSTRAINT "validate_date",
1482+
ADD CONSTRAINT "validate_date" CHECK (
1483+
end_date IS NULL
1484+
OR (
1485+
start_date IS NOT NULL
1486+
AND end_date > start_date
1487+
)
1488+
);"#
14231489
);
14241490

14251491
assert_eq!(format(input, &QueryParams::None, &options), expected);
@@ -2196,8 +2262,7 @@ mod tests {
21962262
-- 自动加载数据到 Hive 分区中
21972263
ALTER TABLE
21982264
sales_data
2199-
ADD
2200-
PARTITION (sale_year = '2024', sale_month = '08') LOCATION '/user/hive/warehouse/sales_data/2024/08';"
2265+
ADD PARTITION (sale_year = '2024', sale_month = '08') LOCATION '/user/hive/warehouse/sales_data/2024/08';"
22012266
);
22022267

22032268
assert_eq!(format(input, &QueryParams::None, &options), expected);

src/tokenizer.rs

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -488,35 +488,60 @@ fn get_top_level_reserved_token<'a>(
488488
// First peek at the first character to determine which group to check
489489
let first_char = peek(any).parse_next(input)?.to_ascii_uppercase();
490490

491+
let create_or_replace = (
492+
"AGGREGATE",
493+
"FUNCTION",
494+
"LANGUAGE",
495+
"PROCEDURE",
496+
"RULE",
497+
"TRIGGER",
498+
"VIEW",
499+
);
500+
501+
let alterable_or_droppable = alt((alt(create_or_replace), "TABLE", "INDEX"));
502+
let create_or_replace = alt(create_or_replace);
503+
491504
// Match keywords based on their first letter
492505
let result: Result<&str> = match first_char {
493506
'A' => alt((
494-
terminated("ADD", end_of_word),
495507
terminated("AFTER", end_of_word),
496-
terminated("ALTER COLUMN", end_of_word),
497-
terminated("ALTER TABLE", end_of_word),
508+
terminated(("ALTER ", alterable_or_droppable).take(), end_of_word),
498509
))
499510
.parse_next(&mut uc_input),
500511

501512
'C' => terminated(
502513
(
503514
"CREATE ",
504-
opt(alt((
505-
"UNLOGGED ",
515+
alt((
516+
create_or_replace,
517+
(opt("UNIQUE "), "INDEX").take(),
506518
(
507-
alt(("GLOBAL ", "LOCAL ")),
508-
opt(alt(("TEMPORARY ", "TEMP "))),
519+
opt(alt((
520+
"UNLOGGED ",
521+
(
522+
alt(("GLOBAL ", "LOCAL ")),
523+
opt(alt(("TEMPORARY ", "TEMP "))),
524+
)
525+
.take(),
526+
))),
527+
"TABLE",
509528
)
510529
.take(),
511-
))),
512-
"TABLE",
530+
)),
513531
)
514532
.take(),
515533
end_of_word,
516534
)
517535
.parse_next(&mut uc_input),
518536

519-
'D' => terminated("DELETE FROM", end_of_word).parse_next(&mut uc_input),
537+
'D' => alt((
538+
terminated("DELETE FROM", end_of_word),
539+
terminated(
540+
("DROP ", alterable_or_droppable, opt(" IF EXISTS")).take(),
541+
end_of_word,
542+
),
543+
))
544+
.parse_next(&mut uc_input),
520545

521546
'E' => terminated("EXCEPT", end_of_word).parse_next(&mut uc_input),
522547

0 commit comments

Comments
 (0)