Since PR https://github.com/ballista-compute/sqlparser-rs/pull/93
`parse_column_def` parses a set of column options in a loop, e.g. given:
```
_______ column_def _______
CREATE TABLE foo (bar INT NOT NULL DEFAULT 1, )
-------- ---------
option 1 option 2
````
it parses column options until it encounters one of the delimiter tokens
First when we only supported `CREATE TABLE`, the set of delimiters that
stopped the parsing used to be `Token::Comma | Token::RParen`.
Then we added support for `ALTER TABLE ADD COLUMN <column_def>`. Turns
out the parser started to bail if the statement ended with a semicolon,
while attempting to parse the semicolon as a column option, as we forgot
to add it to the set of delimiter tokens.
This was recently fixed in https://github.com/ballista-compute/sqlparser-rs/pull/246
by including Token::SemiColon to the list, but it felt wrong to have
to update this list, and to have a common list of delimiters for two
different contexts (CREATE TABLE with parens vs ALTER TABLE ADD COLUMN
without parens).
Also our current approach cannot handle multiple statements NOT
separated by a semicolon, as is common in MS SQL DDL. We don't
explicitly support it in `parse_statements`, but that's a use-case
like to keep in mind nevertheless.
* Change `Parser { ... }` to store the dialect used:
`Parser<'a> { ... dialect: &'a dyn Dialect }`
Thanks to @c7hm4r for the initial version of this submitted as
part of https://github.com/ballista-compute/sqlparser-rs/pull/170
* Introduce `dialect_of!(parser is SQLiteDialect | GenericDialect)` helper
to branch on the dialect's type
* Use the new functionality to make `AUTO_INCREMENT` and `AUTOINCREMENT`
parsing dialect-dependent.
Co-authored-by: Christoph Müller <pmzqxfmn@runbox.com>
Co-authored-by: Nickolay Ponomarev <asqueella@gmail.com>
* Support create or replace table
* Support create or replace view
* Simplify create or replace table parser
* Add tests for create or replace external table and materialized view
* Formatting
* Address review comments
* Create error if we didn't see a (external) table or (materialized) view afer create or replace
This implements `DROP [ COLUMN ] [ IF EXISTS ] column_name [ CASCADE ]`
sub-command of `ALTER TABLE`, which is what PostgreSQL supports https://www.postgresql.org/docs/12/sql-altertable.html
(except for the RESTRICT option)
Co-authored-by: Nickolay Ponomarev <asqueella@gmail.com>
Fixes#168 by enabling `DATE` and other keywords to be used as
identifiers when not followed by a string literal.
A "typed string" is our term for generalized version of `DATE '...'`/`TIME '...'`/
`TIMESTAMP '...'` literals, represented as `TypedString { data_type, value }`
in the AST.
Unlike DATE/TIME/TIMESTAMP literals, this is a non-standard extension
supported by PostgreSQL at least.
This is a port of MaterializeInc/materialize#3146
Co-authored-by: Nikhil Benesch <nikhil.benesch@gmail.com>
Co-authored-by: Nickolay Ponomarev <asqueella@gmail.com>
Alter INTERVAL to support postgres syntax
This patch updates our INTERVAL implementation such that the Postgres
and Redshfit variation of the syntax is supported: namely that 'leading
field' is optional.
Fixes#177.
This patch provides an initial implemenation of LISTAGG[1]. Notably this
implemenation deviates from ANSI SQL by allowing both WITHIN GROUP and
the delimiter to be optional. We do so because Redshift SQL works this
way and this approach is ultimately more flexible.
Fixes#169.
[1] https://modern-sql.com/feature/listagg
Specifically, `FOREIGN KEY REFERENCES <foreign_table> (<referred_columns>)`
can now be followed by `ON DELETE <referential_action>` and/or by
`ON UPDATE <referential_action>`.
The Ident type was previously an alias for a String. Turn it into a full
fledged struct, so that the parser can preserve the distinction between
identifier value and quote style already made by the tokenizer's Word
structure.
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.
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.
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".
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".
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.
`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.