parser: make to and table independently optional in add column
Previously the grammar accepted only `to table` together or neither. The user-stated convention is that bare table identifiers are accepted in unambiguous positions (matching how `add 1:n relationship from <T>.<col> to <T>.<col>` takes bare table names). Both `to` and `table` are now or_not'd independently, so all four combinations parse identically. Updates the in-app `help` listing to advertise the new shape: `add column [to] [table] <T>: <col> (<type>)`. 3 new parser tests cover the variants.
This commit is contained in:
+51
-6
@@ -129,14 +129,19 @@ fn command_parser<'a>()
|
||||
.ignore_then(identifier())
|
||||
.map(|name| Command::DropTable { name });
|
||||
|
||||
// `to table` is optional — both `add column to table T: c (text)`
|
||||
// and `add column T: c (text)` parse identically.
|
||||
let to_table_optional = keyword_ci("to")
|
||||
.ignore_then(keyword_ci("table"))
|
||||
.or_not();
|
||||
// Both `to` and `table` are independently optional —
|
||||
// `add column to table T: c (text)`,
|
||||
// `add column to T: c (text)`,
|
||||
// `add column table T: c (text)`,
|
||||
// and `add column T: c (text)` all parse identically.
|
||||
// Matches the convention elsewhere in the DSL where bare
|
||||
// identifiers are accepted in unambiguous positions.
|
||||
let optional_to = keyword_ci("to").or_not();
|
||||
let optional_table = keyword_ci("table").or_not();
|
||||
let add_column = keyword_ci("add")
|
||||
.ignore_then(keyword_ci("column"))
|
||||
.ignore_then(to_table_optional)
|
||||
.ignore_then(optional_to)
|
||||
.ignore_then(optional_table)
|
||||
.ignore_then(identifier())
|
||||
.then_ignore(just(':').padded())
|
||||
.then(identifier())
|
||||
@@ -764,6 +769,46 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_column_accepts_bare_table_name() {
|
||||
// `to table` are both optional; bare table identifier
|
||||
// is accepted in this unambiguous position.
|
||||
assert_eq!(
|
||||
ok("add column Customers: Name (text)"),
|
||||
Command::AddColumn {
|
||||
table: "Customers".to_string(),
|
||||
column: "Name".to_string(),
|
||||
ty: Type::Text,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_column_accepts_to_alone() {
|
||||
// `to` without `table`.
|
||||
assert_eq!(
|
||||
ok("add column to Customers: Name (text)"),
|
||||
Command::AddColumn {
|
||||
table: "Customers".to_string(),
|
||||
column: "Name".to_string(),
|
||||
ty: Type::Text,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_column_accepts_table_alone() {
|
||||
// `table` without `to`.
|
||||
assert_eq!(
|
||||
ok("add column table Customers: Name (text)"),
|
||||
Command::AddColumn {
|
||||
table: "Customers".to_string(),
|
||||
column: "Name".to_string(),
|
||||
ty: Type::Text,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_column_tolerates_whitespace_around_punctuation() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user