Commit graph

92 commits

Author SHA1 Message Date
Nikhil Benesch
b5621c0fe8
Don't lose precision when parsing decimal fractions
The SQL standard requires that numeric literals with a decimal point,
like 1.23, are represented exactly, up to some precision. That means
that parsing these literals into f64s is invalid, as it is impossible
to represent many decimal numbers exactly in binary floating point (for
example, 0.3).

This commit parses all numeric literals into a new `Value` variant
`Number(String)`, removing the old `Long(u64)` and `Double(f64)`
variants. This is slightly less convenient for downstream consumers, but
far more flexible, as numbers that do not fit into a u64 and f64 are now
representable.
2019-09-01 13:21:30 -04:00
Nikhil Benesch
106c9f8efb
Remove "SQL" prefix from "SQLDateTimeField" struct
I realized a moment too late that I'd missed a type name in
when removing the "SQL" prefix from types in ac555d7e8. As far as I can
tell, this was the only oversight.
2019-06-25 13:24:31 -04:00
Nikhil Benesch
ac555d7e86
Remove "SQL" prefix from types
The rationale here is the same as the last commit: since this crate
exclusively parses SQL, there's no need to restate that in every type
name. (The prefix seems to be an artifact of this crate's history as a
submodule of Datafusion, where it was useful to explicitly call out
which types were related to SQL parsing.)

This commit has the additional benefit of making all type names
consistent; over type we'd added some types which were not prefixed with
"SQL".
2019-06-25 13:11:11 -04:00
Nikhil Benesch
cf655ad1a6
Remove "sql" prefix from module names
Since this crate only deals with SQL parsing, the modules are understood
to refer to SQL and don't need to restate that explicitly.
2019-06-24 12:56:26 -04:00
Nikhil Benesch
5b23ad1d4c
Merge pull request #119 from andygrove/astnode-expr
Rename ASTNode to Expr
2019-06-19 21:45:49 -04:00
Nikhil Benesch
646d1e13ca
Rename ASTNode to Expr
The ASTNode enum was confusingly named. In the past, the name made
sense, as the enum contained nearly all of the nodes in the AST, but
over time, pieces have been split into different structs, like
SQLStatement and SQLQuery. The ASTNode enum now contains only contains
expression nodes, so Expr is a better name.

Also rename the UnnamedExpression and ExpressionWithAlias variants
of SQLSelectItem to UnnamedExpr and ExprWithAlias, respectively, to
match the new shorthand for the word "expression".
2019-06-19 00:00:59 -04:00
Nickolay Ponomarev
4294581ded [mssql] Parse CROSS/OUTER APPLY
T-SQL (and Oracle) support non-standard syntax, which is similar in
functionality to LATERAL joins in ANSI and PostgreSQL
<https://blog.jooq.org/tag/lateral-derived-table/>: it allows to use
the columns from the tables defined to the left of `APPLY` in the
"derived tables" (subqueries) to the right of `APPLY`. Unlike ANSI
LATERAL (but like Postgres' implementation), APPLY is also used with
table-valued function calls.

Despite them being similar, we represent "APPLY" joins with
`JoinOperator`s of its own (`CrossApply` and `OuterApply`). Doing
otherwise seemed like it would cause unnecessary confusion, as those
interested in dialect-specific parsing would probably not expect APPLY
being parsed as LATERAL, and those wanting to forbid non-standard SQL
would not be helped by this either.

This also renames existing JoinOperator::Cross -> CrossJoin to avoid
confusion with CrossApply.
2019-06-19 02:45:47 +03:00
Nikhil Benesch
2c99635709
Don't silently accept naked OUTER JOINS
`SELECT * FROM a OUTER JOIN b` was previously being parsed as an inner
join where table `a` was aliased to `OUTER`. This is extremely
surprising, as the user likely intended to say FULL OUTER JOIN. Since
the SQL specification lists OUTER as a keyword, we are well within our
rights to return an error here.
2019-06-18 12:03:15 -04:00
Nickolay Ponomarev
eb3450dd51 Support HAVING without GROUP BY
...which is weird but allowed:
https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#table-expression
https://dba.stackexchange.com/a/57453/15599

Also add a test for GROUP BY .. HAVING
2019-06-17 01:06:32 +03:00
Nickolay Ponomarev
d60bdc0b92 Allow LIMIT/OFFSET/FETCH without FROM
Postgres allows it, as does ANSI SQL per the <query expression> definition:
https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#_7_13_query_expression
2019-06-17 00:54:37 +03:00
Nickolay Ponomarev
c1509b36ec Use FETCH_FIRST_TWO_ROWS_ONLY in tests to reduce duplication 2019-06-17 00:49:25 +03:00
Nickolay Ponomarev
f87e8d5158 Don't duplicate all the parse_simple_select assertions in the LIMIT test 2019-06-17 00:39:00 +03:00
Nickolay Ponomarev
3c073a4c34 Use TableAlias in Cte 2019-06-16 21:18:57 +03:00
Nickolay Ponomarev
dc26c4abd5
Merge pull request #115 from nickolay/pr/followups
Doc improvements and follow-ups to the recent PRs
2019-06-15 01:57:52 +03:00
Nickolay Ponomarev
535505bb96
Update the error message in parse_query_body 2019-06-14 16:28:53 -04:00
Nikhil Benesch
4ee461bae4
Require that nested joins always have one join
The SQL specification prohibits constructions like

    SELECT * FROM a NATURAL JOIN (b)

where b sits alone inside parentheses. Parentheses in a FROM entry
always introduce either a derived table or a join.
2019-06-14 16:28:52 -04:00
Nikhil Benesch
8bee74277a
Handle derived tables with set operations
This commit adds support for derived tables (i.e., subqueries) that
incorporate set operations, like:

    SELECT * FROM (((SELECT 1) UNION (SELECT 2)) t1 AS NATURAL JOIN t2)

This introduces a bit of complexity around determining whether a left
paren starts a subquery, starts a nested join, or belongs to an
already-started subquery. The details are explained in a comment within
the patch.
2019-06-14 16:28:52 -04:00
Nickolay Ponomarev
5c7ff79e78 Add a test for parsing the NULL literal
(Coveralls notices we didn't have one.)
2019-06-13 11:17:36 +03:00
Nickolay Ponomarev
45c9aa1cc2 Use self.expected() more 2019-06-13 11:15:10 +03:00
Nickolay Ponomarev
32cf36e64f Add a testcase, which passes thanks to PR #109 2019-06-12 21:04:31 +03:00
Nikhil Benesch
ae25dce246
Split operators by arity
It is useful downstream to have two separate enums, one for unary
operators and one for binary operators, so that the compiler can check
exhaustiveness. Otherwise downstream consumers need to manually encode
which operators are unary and which operators are binary when matching
on an Operator enum.
2019-06-10 23:03:11 -04:00
Nikhil Benesch
9e33cea9b8
Standardize BinaryOp and UnaryOp nodes
These were previously called "BinaryExpr" and "Unary"; besides being
inconsistent, it's also not correct to say "binary expression" or "unary
expression", as it's the operators that have arities, not the
expression. Adjust the naming of the variants accordingly.
2019-06-10 23:02:17 -04:00
Andy Grove
b379480b7a
Merge pull request #79 from benesch/license
Standardize license headers
2019-06-10 19:39:12 -06:00
Nikhil Benesch
ce171c2a3d
Support VALUES and parenthesized SELECTs as top-level statements 2019-06-10 11:11:26 -04:00
Nikhil Benesch
b841dccc2c
Properly handle mixed implicit and explicit joins
Parse a query like

    SELECT * FROM a NATURAL JOIN b, c NATURAL JOIN d

as the SQL specification requires, i.e.:

    from: [
        TableReference {
            relation: TableFactor::Table("a"),
            joins: [Join {
                relation: TableFactor::Table("b"),
                join_operator: JoinOperator::Natural,
            }]
        },
        TableReference {
            relation: TableFactor::Table("c"),
            joins: [Join {
                relation: TableFactor::Table("d"),
                join_operator: JoinOperator::Natural,
            }]
        }
    ]

Previously we were parsing such queries as

    relation: TableFactor::Table("a"),
    joins: [
        Join {
            relation: TableFactor::Table("b"),
            join_operator: JoinOperator::Natural,
        },
        Join {
            relation: TableFactor::Table("c"),
            join_operator: JoinOperator::Implicit,
        },
        Join {
            relation: TableFactor::Table("d"),
            join_operator: JoinOperator::Natural,
        },
    ]

which did not make the join hierarchy clear.
2019-06-10 11:11:25 -04:00
Nickolay Ponomarev
518c8833d2
Merge pull request #110 from nickolay/pr/cleanups
Minor code clean-ups
2019-06-09 20:24:13 +03:00
Nikhil Benesch
2d1e05e21d
Merge pull request #103 from benesch/intervals
Support interval literals
2019-06-09 12:41:57 -04:00
Nikhil Benesch
2798ddf5fd
Support interval literals 2019-06-09 12:37:57 -04:00
Nickolay Ponomarev
99768711dc Fix redundant closures in tests
We don't have the tests checked by clippy on CI, despite [passing the
`--all-targets`](5536cd1f9e/.travis.yml (L46)),
but VSCode+RLS display warnings for these.

See: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
2019-06-09 17:05:19 +03:00
Nikhil Benesch
5536cd1f9e
Merge pull request #106 from offscale/transactions
Transaction support
2019-06-09 01:35:05 -04:00
Nikhil Benesch
7e96d81b47
Merge pull request #93 from benesch/col-constr-order
Parse column constraints in any order
2019-06-09 00:36:51 -04:00
Agustin Chiappe Berrini
582b25add6
Add basic support for transaction statements
Co-authored-by: Samuel Marks <807580+SamuelMarks@users.noreply.github.com>
Co-authored-by: Nikhil Benesch <nikhil.benesch@gmail.com>
2019-06-09 00:36:20 -04:00
Nikhil Benesch
ffa1c8f853
Parse column constraints in any order
CREATE TABLE t (a INT NOT NULL DEFAULT 1 PRIMARY KEY) is as valid as
CREATE TABLE t (a INT DEFAULT 1 PRIMARY KEY NOT NULL).
2019-06-08 12:13:55 -04:00
Nikhil Benesch
ccbd048dda
Test that redundant nesting is supported
SELECT * FROM (((SELECT 1))) is just as valid as
SELECT * FROM (SELECT 1). Add a test to ensure that we can parse the
first form.

Addresses a comment from #100.
2019-06-07 23:54:56 -04:00
Nikhil Benesch
5f9f17de8a
Merge pull request #100 from benesch/nested-joins
Support nested joins
2019-06-07 22:37:53 -04:00
Nikhil Benesch
525f4d7501
Fix precedence of unary NOT
get_next_precedence deals with left-binding power, not right binding
power. Therefore, when it encounters a standalone NOT operator (i.e., a
"NOT" token that is not followed by "BETWEEN", "LIKE", or "IN"), it
should return 0, because unary NOT is not an infix operator, it's a
prefix operator, and therefore it has no left-binding power.
2019-06-06 17:20:07 -04:00
Nikhil Benesch
e78cf0483e
Standardize license headers
Standardize the license header, removing the Grove Enterprise copyright
notice where it exists per #58. Also add a CI check to ensure that files
without license headers don't get merged.

Fix #58.
2019-06-04 10:54:12 -04:00
Nikhil Benesch
8fbf82deb0
Support nested joins
Fix #83.
2019-06-04 10:25:07 -04:00
Nikhil Benesch
ed3ed26bb1
Support parsing dates, times, and timestamps as strings 2019-06-04 00:12:09 -04:00
Nikhil Benesch
11fc833433
Merge pull request #96 from benesch/extract
Support EXTRACT function-like operator
2019-06-04 00:07:23 -04:00
Nikhil Benesch
4c2722280d
Merge pull request #98 from benesch/col-names
Support column names in more places
2019-06-04 00:00:07 -04:00
Nikhil Benesch
9abcac350e
Support aliasing columns
A table alias can specify new names for the columns within the aliased
table, in addition to a new name for the table itself.
2019-06-03 23:51:23 -04:00
Nikhil Benesch
73ed685879
Support views with explicit column names
A `CREATE VIEW` statement may provide names for its columns that
override the names of the columns derived from the view's query.
2019-06-03 23:50:23 -04:00
Nikhil Benesch
fdbf64c64d
Merge pull request #94 from benesch/empty-create-table
Support CREATE TABLE with no columns
2019-06-03 23:44:18 -04:00
Nikhil Benesch
d484756182
Support EXTRACT function-like operator
The EXTRACT function, for extracting components of a date from a
timestamp, has special syntax: `EXTRACT(<field> FROM <timestamp>)`.
2019-06-03 23:37:39 -04:00
Nikhil Benesch
a594375966
Merge pull request #97 from benesch/update
Support UPDATE statements
2019-06-03 23:32:23 -04:00
Nikhil Benesch
69f0082db6
Support arbitrary WITH options for CREATE [TABLE|VIEW]
Both Postgres and MSSQL accept this syntax, though the particular
options they accept differ.
2019-06-03 13:32:13 -04:00
Nikhil Benesch
b12fb34f3d
Merge pull request #95 from benesch/hex-literals
Support hexadecimal string literals
2019-06-03 11:49:25 -04:00
Nikhil Benesch
b8ba188191
Merge pull request #91 from benesch/from-values
Improve VALUES-related syntax parsing
2019-06-03 11:44:52 -04:00
Nikhil Benesch
eba3983268
Support hexadecimal string literals 2019-06-03 11:33:51 -04:00