Commit graph

1040 commits

Author SHA1 Message Date
Nickolay Ponomarev
de177f107c Remove dead datetime-related code
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.
2019-05-04 01:00:13 +03:00
Nickolay Ponomarev
9297ffbe18 Move tests using standard SQL from the postgresql-specific file 2019-05-04 01:00:13 +03:00
Nickolay Ponomarev
d1b088bd43 Switch remaining tests to the standard format 2019-05-04 01:00:13 +03:00
Nickolay Ponomarev
0233604f9b Remove extraneous tests
`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`
2019-05-04 01:00:13 +03:00
Nickolay Ponomarev
fe635350f0 Improve INSERT tests
De-duplicate and check for specific error in `parse_insert_invalid`.
2019-05-04 01:00:13 +03:00
Nickolay Ponomarev
364f62f333 Parse table-valued functions and MSSQL-specific WITH hints
1) Table-valued functions (`FROM possibly_qualified.fn(arg1, ...)`) is
not part of ANSI SQL, but is supported in Postgres and MSSQL at least:
- "38.5.7. SQL Functions as Table Sources" <https://www.postgresql.org/docs/current/xfunc-sql.html#XFUNC-SQL-TABLE-FUNCTIONS>
- `user_defined_function` in "FROM (Transact-SQL)" <https://docs.microsoft.com/en-us/sql/t-sql/queries/from-transact-sql?view=sql-server-2017>

I've considered renaming TableFactor::Table to something else (Object?),
now that it can be a TVF, but couldn't come up with a satisfactory name.

2) "WITH hints" is MSSQL-specific syntax
<https://docs.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table?view=sql-server-2017>

Note that MSSQL supports the following ways of specifying hints, which
are parsed with varying degrees of accuracy:
- `FROM tab (NOLOCK)` -- deprecated syntax, parsed as a function with a `NOLOCK` argument
- `FROM tab C (NOLOCK)` -- deprecated syntax, rejected ATM
- `FROM TAB C WITH (NOLOCK)` -- OK
2019-04-27 21:14:18 +03:00
Nickolay Ponomarev
e5e3d71354 Support CASE operand WHEN expected_value THEN ..
Another part of #15
2019-04-27 21:14:18 +03:00
Nickolay Ponomarev
6bb2acc9f8
Merge pull request #50 from nickolay/window-functions
Support OVER clause for window/analytic functions, add support for qualified function names
2019-04-27 21:12:08 +03:00
Andy Grove
07d66a93ef
Merge pull request #53 from thomas-jeepe/master
Fix qualified wildcard stringifying
2019-04-27 08:53:08 -06:00
Justin Haug
76d2d46496 run cargo fmt 2019-04-22 18:06:00 -04:00
Justin Haug
f9fb4bedfb Move wildcard test to generic parser 2019-04-22 17:52:15 -04:00
Justin Haug
80aceba630 run cargo fmt 2019-04-22 17:50:12 -04:00
Justin Haug
80dccf6885 Add support for escaping single quote strings 2019-04-22 13:32:05 -04:00
Justin Haug
5b464e6b1a Fix qualified wildcard stringifying 2019-04-22 13:10:29 -04:00
Nickolay Ponomarev
098d1c4a17 Enable clippy lints by default in RLS 2019-04-21 04:46:19 +03:00
Nickolay Ponomarev
50a2310173 Rename SQLStatement::SQLSelect to SQLQuery
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
2019-04-21 04:46:19 +03:00
Nickolay Ponomarev
08bbce8992 Use assert_matches! instead of matching manually
To fix clippy warnings about assert!(true / false)
2019-04-21 04:46:19 +03:00
Nickolay Ponomarev
dee30aabe0 Fix the clippy assert!(false) lint
https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants

While I don't feel it's valid, fixing it lets us act on the other, more
useful, lints.
2019-04-21 04:46:19 +03:00
Nickolay Ponomarev
c223eaf0aa Fix a bunch of trivial clippy lints 2019-04-21 04:46:19 +03:00
Nickolay Ponomarev
0634ec4a83 Apply suggestions from cargo fix --edition-idioms 2019-04-21 04:41:11 +03:00
Nickolay Ponomarev
b12a19e197 Switch to the Rust 2018 edition
This requires Rust 1.31 (from last year) to build, but is otherwise
compatible with the 2015-edition code.
2019-04-21 04:41:11 +03:00
Nickolay Ponomarev
085e8a6b04 Use named fields in ExpressionWithAlias instead of a tuple
(This produces more natural JSON representation when serializing AST
with serde.)
2019-04-20 22:51:29 +03:00
Nickolay Ponomarev
4a5dc8dd4b Support qualified function names
...e.g. `db.schema.func()`
2019-04-20 22:51:29 +03:00
Nickolay Ponomarev
d4de248c73 Support OVER clause for window/analytic functions
Since this changes SQLFunction anyway, changed its `id` field to `name`,
as we don't seem to use "id" to mean "name" anywhere else.
2019-04-20 22:51:29 +03:00
Nickolay Ponomarev
bbf1805729 Support SELECT DISTINCT 2019-04-20 14:21:26 +03:00
Zhiyuan Zheng
d8f824c400 merge CreateExternalTable & CreateTable. 2019-04-14 01:05:26 +08:00
Zhiyuan Zheng
26940920ac Add unit tests. 2019-04-09 13:28:01 +08:00
Nickolay Ponomarev
f30ab89ad2 Re-run cargo fmt 2019-03-08 15:46:40 +03:00
Nikhil Benesch
23a0fc79f5
Support CREATE MATERIALIZED VIEW 2019-03-07 13:14:33 -05:00
Nickolay Ponomarev
52e0f55b6f Support UNION/EXCEPT/INTERSECT 2019-02-11 05:14:36 +03:00
Nickolay Ponomarev
54c9ca8619 Support unary + / - 2019-02-11 05:13:48 +03:00
Nickolay Ponomarev
786b1cf18a Support BETWEEN 2019-02-11 05:13:48 +03:00
Nickolay Ponomarev
264319347d Support IN 2019-02-11 05:13:48 +03:00
Nickolay Ponomarev
bed03abe44 Support AS and qualified wildcards in SELECT 2019-02-11 05:13:48 +03:00
Nickolay Ponomarev
bf0c07bb1b Support basic CTEs (WITH)
Some unsupported features are noted as TODOs.
2019-02-11 05:13:48 +03:00
Nickolay Ponomarev
35dd9342e2 Support national string literals (N'...')
Widely used in MS SQL and specified in ANSI.
2019-02-07 05:34:33 +03:00
Nickolay Ponomarev
0c0cbcaff4 Support basic CREATE VIEW 2019-02-07 05:34:12 +03:00
Nickolay Ponomarev
6b107065ac Switch some tests to verified_select_stmt
(the tests affected by "unboxing" in the previous commits.)
2019-02-07 05:33:54 +03:00
Nickolay Ponomarev
e3b981a0e2 Don't Box<ASTNode> in SQLSelect
Instead change ASTNode::SQLSubquery to be Box<SQLSelect>
2019-02-07 05:33:51 +03:00
Nickolay Ponomarev
c5bbfc33fd Don't Box<ASTNode> in SQLStatement
This used to be needed when it was a variant in the ASTNode enum itself.
2019-02-07 05:33:46 +03:00
Nickolay Ponomarev
3619e89e9c Remove Box<> from SQLOrderByExpr
It was probably copied from somewhere else when most types were variants
in ASTNode, and needed Box<> to prevent recursion in the ASTNode definition.
2019-02-07 05:33:43 +03:00
Nickolay Ponomarev
9967031cba Move TableFactor to be a separate enum
ASTNode can now be renamed SQLExpression, as it represents a node in
the "expression" part of the AST -- other nodes have their own types.
2019-02-07 05:33:41 +03:00
Nickolay Ponomarev
e0ceacd1ad Store original, quoted form in SQLIdent
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.
2019-02-07 05:33:12 +03:00
Nickolay Ponomarev
07790fe4c4 Improve DELETE FROM parsing (4.4/4.4)
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
2019-02-07 05:31:51 +03:00
Nickolay Ponomarev
39e98cb11a Rename parse_tablename -> parse_object_name (4.2/4.4)
...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).
2019-02-07 05:31:44 +03:00
Nickolay Ponomarev
523f086be7 Introduce SQLObjectName struct (4.1/4.4)
(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).
2019-02-07 05:31:40 +03:00
Nickolay Ponomarev
215820ef66 Stricter parsing for subqueries (3/4)
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.
2019-02-07 05:31:36 +03:00
Nickolay Ponomarev
82dc581639 Fix precedence for the NOT operator (2/4)
I checked the docs of a few of the most popular RDBMSes, and it seems
there's consensus that the precedence of `NOT` is higher than `AND`,
but lower than `IS NULL`.

Postgresql[1], Oracle[2] and MySQL[3] docs say that explicitly.

T-SQL docs[4] do mention it's higher than `AND`, and while they don't
explicitly mention IS NULL, this snippet:

    select * from (select 1 as a)x
    where (not x.a) is null

...is a parsing error, while the following works like IS NOT NULL:

    select * from (select 1 as a)x
    where not x.a is null

sqlite doesn't seem to mention `NOT` precedence, but I assume it works
similarly.

[1] https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-OPERATORS
[2] https://docs.oracle.com/cd/B19306_01/server.102/b14200/conditions001.htm#i1034834
[3] https://dev.mysql.com/doc/refman/8.0/en/operator-precedence.html
[4] https://docs.microsoft.com/en-us/sql/t-sql/language-elements/operator-precedence-transact-sql?view=sql-server-2017
2019-02-07 05:24:55 +03:00
Nickolay Ponomarev
29db619792 Stop losing parens when roundtripping (1/4)
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.
2019-02-07 05:24:54 +03:00
Nickolay Ponomarev
b57c60a78c Only use parse_expr() when we expect an expression (0/4)
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.
2019-02-07 05:24:54 +03:00