1) Removed unused date/time parsing methods from `Parser`
I don't see how the token-based parsing code would ever be used: the
date/time literals are usually quoted, like `DATE 'yyyy-mm-dd'` or
simply `'YYYYMMDD'`, so the date will be a single token.
2) Removed unused date/time related variants from `Value` and the
dependency on `chrono`.
We don't support parsing date/time literals at the moment and when we
do I think we should store the exact String to let the consumer parse
it as they see fit.
3) Removed `parse_timestamps_example` and
`parse_timestamps_with_millis_example` tests. They parsed as
`number(2016) minus number(02) minus number(15) <END OF EXPRESSION>`
(leaving the time part unparsed) as it makes no sense to try parsing
a yyyy-mm-dd value as an SQL expression.
`parse_example_value` parses as compound identifier, which makes no
sense ("SARAH"."LEWISE@sakilacustomer"."org")
`parse_function_now` is unnecessary since we already test the parsing
of functions in `parse_scalar_function_in_projection`
The name was confusing:
SQLStatement::SQLSelect(
SQLQuery {
body: SQLSetExpr::Select(SQLSelect)
}
)
Fix the `large_enum_variant` clippy lint for `SQLStatement::SQLQuery`
`SQLStatement::SQLCreateView`, and `SQLSetExpr::Select`, while we're
changing the AST anyway
https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant
Also move more things to use SQLIdent instead of String in the hope of
making it a newtype eventually.
Add tests that quoted identifiers round-trip parsing/serialization correctly.
Store (and parse) `table_name: SQLObjectName` instead of
`relation: Option<Box<ASTNode>>`, which can be an arbitrary expression.
Also remove the `Option<>`: the table name is not optional in any dialects
I'm familiar with. While the FROM keyword itself _is_ optional in some
dialects, there are more things to implement for those dialects, see
https://stackoverflow.com/a/4484271/1026
...to match the name of the recently introduced `SQLObjectName` struct
and to avoid any reservations about using it with multi-part names of
objects other than tables (as in the `type_name` case).
(To store "A name of a table, view, custom type, etc., possibly
multi-part, i.e. db.schema.obj".)
Before this change
- some places used `String` for this (these are updated in this commit)
- while others (notably SQLStatement::SQLDelete::relation, which is
the reason for this series of commits) relied on
ASTNode::SQLCompoundIdentifier (which is also backed by a
Vec<SQLIdent>, but, as a variant of ASTNode enum, is not convenient
to use when you know you need that specific variant).
This makes the parser more strict when handling SELECTs nested
somewhere in the main statement:
1) instead of accepting SELECT anywhere in the expression where an
operand was expected, we only accept it inside parens. (I've added a
test for the currently supported syntax, <scalar subquery> in ANSI
SQL terms)
2) instead of accepting any expression in the derived table context:
`FROM ( ... )` - we only look for a SELECT subquery there.
Due to #1, I had to swith the 'ansi' test from invoking the expression
parser to the statement parser.
Before this change an expression like `(a+b)-(c+d)` was parsed correctly
(as a Minus node with two Plus nodes as children), but when serializing
back to an SQL string, it came up as a+b-c+d, since we don't store
parens in AST and don't attempt to insert them when necessary during
serialization. The latter would be hard, and we already had an SQLNested
enum variant, so I changed the code to wrap the AST node for the
parenthesized expression in it.
Before this commit there was a single `parse_expr(u8)` method, which
was called both
1) from within the expression parser (to parse subexpression consisting
of operators with higher priority than the current one), and
2) from the top-down parser both
a) to parse true expressions (such as an item of the SELECT list or
the condition after WHERE or after ON), and
b) to parse sequences which are not exactly "expressions".
This starts cleaning this up by renaming the `parse_expr(u8)` method to
`parse_subexpr()` and using it only for (1) - i.e. usually providing a
non-zero precedence parameter.
The non-intuitively called `parse()` method is renamed to `parse_expr()`,
which became available and is used for (2a).
While reviewing the existing callers of `parse_expr`, four points to
follow up on were identified (marked "TBD (#)" in the commit):
1) Do not lose parens (e.g. `(1+2)*3`) when roundtripping
String->AST->String by using SQLNested.
2) Incorrect precedence of the NOT unary
3) `parse_table_factor` accepts any expression where a SELECT subquery
is expected.
4) parse_delete uses parse_expr() to retrieve a table name
These are dealt with in the commits to follow.