Skip to content

Commit 2fdb016

Browse files
committed
Merge branch 'master' into materialize-master
2 parents 92e0d59 + 391a54b commit 2fdb016

File tree

9 files changed

+324
-360
lines changed

9 files changed

+324
-360
lines changed

CHANGELOG.md

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Changelog
2+
All notable changes to this project will be documented in this file.
3+
4+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project aims to adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5+
6+
Given that the parser produces a typed AST, any changes to the AST will technically be breaking and thus will result in a `0.(N+1)` version. We document changes that break via addition as "Added".
7+
8+
## [Unreleased]
9+
Nothing here yet! Check https://github.com/andygrove/sqlparser-rs/commits/master for undocumented changes.
10+
11+
## [0.4.0] - 2019-07-02
12+
This release brings us closer to SQL-92 support, mainly thanks to the improvements contributed back from @MaterializeInc's fork and other work by @benesch.
13+
14+
### Changed
15+
- Remove "SQL" from type and enum variant names, `SQLType` -> `DataType`, remove "sql" prefix from module names (#105, #122)
16+
- Rename `ASTNode` -> `Expr` (#119)
17+
- Improve consistency of binary/unary op nodes (#112):
18+
- `ASTNode::SQLBinaryExpr` is now `Expr::BinaryOp` and `ASTNode::SQLUnary` is `Expr::UnaryOp`;
19+
- The `op: SQLOperator` field is now either a `BinaryOperator` or an `UnaryOperator`.
20+
- Change the representation of JOINs to match the standard (#109): `SQLSelect`'s `relation` and `joins` are replaced with `from: Vec<TableWithJoins>`. Before this change `FROM foo NATURAL JOIN bar, baz` was represented as "foo" as the `relation` followed by two joins (`Inner(Natural)` and `Implicit`); now it's two `TableWithJoins` (`foo NATURAL JOIN bar` and `baz`).
21+
- Extract a `SQLFunction` struct (#89)
22+
- Replace `Option<Vec<T>>` with `Vec<T>` in the AST structs (#73)
23+
- Change `Value::Long()` to be unsigned, use u64 consistently (#65)
24+
25+
### Added
26+
- Infra:
27+
- Implement `fmt::Display` on AST nodes (#124) - thanks @vemoo!
28+
- Implement `Hash` (#88) and `Eq` (#123) on all AST nodes
29+
- Implement `std::error::Error` for `ParserError` (#72)
30+
- Handle Windows line-breaks (#54)
31+
- Expressions:
32+
- Support `INTERVAL` literals (#103)
33+
- Support `DATE` / `TIME` / `TIMESTAMP` literals (#99)
34+
- Support `EXTRACT` (#96)
35+
- Support `X'hex value'` literals (#95)
36+
- Support `EXISTS` subqueries (#90)
37+
- Support nested expressions in `BETWEEN` (#80)
38+
- Support `COUNT(DISTINCT x)` and similar (#77)
39+
- Support `CASE operand WHEN expected_value THEN ..` and table-valued functions (#59)
40+
- Support analytic (window) functions (`OVER` clause) (#50)
41+
- Queries / DML:
42+
- Support nested joins (#100) and derived tables with set operations (#111)
43+
- Support `UPDATE` statements (#97)
44+
- Support `INSERT INTO foo SELECT * FROM bar` and `FROM VALUES (...)` (#91)
45+
- Support `SELECT ALL` (#76)
46+
- Add `FETCH` and `OFFSET` support, and `LATERAL` (#69) - thanks @thomas-jeepe!
47+
- Support `COLLATE`, optional column list in CTEs (#64)
48+
- DDL/TCL:
49+
- Support `START/SET/COMMIT/ROLLBACK TRANSACTION` (#106) - thanks @SamuelMarks!
50+
- Parse column constraints in any order (#93)
51+
- Parse `DECIMAL` and `DEC` aliases for `NUMERIC` type (#92)
52+
- Support `DROP [TABLE|VIEW]` (#75)
53+
- Support arbitrary `WITH` options for `CREATE [TABLE|VIEW]` (#74)
54+
- Support constraints in `CREATE TABLE` (#65)
55+
- Add basic MSSQL dialect (#61) and some MSSQL-specific features:
56+
- `CROSS`/`OUTER APPLY` (#120)
57+
- MSSQL identifier and alias parsing rules (#66)
58+
- `WITH` hints (#59)
59+
60+
### Fixed
61+
- Report an error for `SELECT * FROM a OUTER JOIN b` instead of parsing `OUTER` as an alias (#118)
62+
- Fix the precedence of `NOT LIKE` (#82) and unary `NOT` (#107)
63+
- Do not panic when `NOT` is not followed by an expected keyword (#71)
64+
successfully instead of returning a parse error - thanks @ivanceras! (#67) - and similar fixes for queries with no `FROM` (#116)
65+
- Fix issues with `ALTER TABLE ADD CONSTRAINT` parsing (#65)
66+
- Serialize the "not equals" operator as `<>` instead of `!=` (#64)
67+
- Remove dependencies on `uuid` (#59) and `chrono` (#61)
68+
- Make `SELECT` query with `LIMIT` clause but no `WHERE` parse - Fix incorrect behavior of `ASTNode::SQLQualifiedWildcard::to_string()` (returned `foo*` instead of `foo.*`) - thanks @thomas-jeepe! (#52)
69+
70+
## [0.3.1] - 2019-04-20
71+
### Added
72+
- Extended `SQLStatement::SQLCreateTable` to support Hive's EXTERNAL TABLES (`CREATE EXTERNAL TABLE .. STORED AS .. LOCATION '..'`) - thanks @zhzy0077! (#46)
73+
- Parse `SELECT DISTINCT` to `SQLSelect::distinct` (#49)
74+
75+
## [0.3.0] - 2019-04-03
76+
### Changed
77+
This release includes major changes to the AST structs to add a number of features, as described in #37 and #43. In particular:
78+
- `ASTNode` variants that represent statements were extracted from `ASTNode` into a separate `SQLStatement` enum;
79+
- `Parser::parse_sql` now returns a `Vec` of parsed statements.
80+
- `ASTNode` now represents an expression (renamed to `Expr` in 0.4.0)
81+
- The query representation (formerly `ASTNode::SQLSelect`) became more complicated to support:
82+
- `WITH` and `UNION`/`EXCEPT`/`INTERSECT` (via `SQLQuery`, `Cte`, and `SQLSetExpr`),
83+
- aliases and qualified wildcards in `SELECT` (via `SQLSelectItem`),
84+
- and aliases in `FROM`/`JOIN` (via `TableFactor`).
85+
- A new `SQLObjectName` struct is used instead of `String` or `ASTNode::SQLCompoundIdentifier` - for objects like tables, custom types, etc.
86+
- Added support for "delimited identifiers" and made keywords context-specific (thus accepting them as valid identifiers in most contexts) - **this caused a regression in parsing `SELECT .. FROM .. LIMIT ..` (#67), fixed in 0.4.0**
87+
88+
### Added
89+
Other than the changes listed above, some less intrusive additions include:
90+
- Support `CREATE [MATERIALIZED] VIEW` statement
91+
- Support `IN`, `BETWEEN`, unary +/- in epressions
92+
- Support `CHAR` data type and `NUMERIC` not followed by `(p,s)`.
93+
- Support national string literals (`N'...'`)
94+
95+
## [0.2.4] - 2019-03-08
96+
Same as 0.2.2.
97+
98+
## [0.2.3] - 2019-03-08 [YANKED]
99+
100+
## [0.2.2] - 2019-03-08
101+
### Changed
102+
- Removed `Value::String`, `Value::DoubleQuotedString`, and `Token::String`, making
103+
- `'...'` parse as a string literal (`Value::SingleQuotedString`), and
104+
- `"..."` fail to parse until version 0.3.0 (#36)
105+
106+
## [0.2.1] - 2019-01-13
107+
We don't have a changelog for the changes made in 2018, but thanks to @crw5996, @cswinter, @fredrikroos, @ivanceras, @nickolay, @virattara for their contributions in the early stages of the project!
108+
109+
## [0.1.0] - 2018-09-03
110+
Initial release

src/ast/mod.rs

+54-66
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ where
7272
/// Identifier name, in the originally quoted form (e.g. `"id"`)
7373
pub type Ident = String;
7474

75+
/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
76+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
77+
pub struct ObjectName(pub Vec<Ident>);
78+
79+
impl fmt::Display for ObjectName {
80+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81+
write!(f, "{}", display_separated(&self.0, "."))
82+
}
83+
}
84+
7585
/// An SQL expression of any type.
7686
///
7787
/// The parser does not distinguish between expressions of different types
@@ -166,12 +176,9 @@ pub enum Expr {
166176
impl fmt::Display for Expr {
167177
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168178
match self {
169-
Expr::Identifier(s) => write!(f, "{}", s),
179+
Expr::Identifier(s) => f.write_str(s),
170180
Expr::Wildcard => f.write_str("*"),
171-
Expr::QualifiedWildcard(q) => {
172-
write!(f, "{}", display_separated(q, "."))?;
173-
f.write_str(".*")
174-
}
181+
Expr::QualifiedWildcard(q) => write!(f, "{}.*", display_separated(q, ".")),
175182
Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
176183
Expr::IsNull(ast) => write!(f, "{} IS NULL", ast),
177184
Expr::IsNotNull(ast) => write!(f, "{} IS NOT NULL", ast),
@@ -286,11 +293,16 @@ impl fmt::Display for WindowSpec {
286293

287294
/// Specifies the data processed by a window function, e.g.
288295
/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
296+
///
297+
/// Note: The parser does not validate the specified bounds; the caller should
298+
/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
289299
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
290300
pub struct WindowFrame {
291301
pub units: WindowFrameUnits,
292302
pub start_bound: WindowFrameBound,
293-
/// The right bound of the `BETWEEN .. AND` clause.
303+
/// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
304+
/// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
305+
/// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
294306
pub end_bound: Option<WindowFrameBound>,
295307
// TBD: EXCLUDE
296308
}
@@ -328,14 +340,14 @@ impl FromStr for WindowFrameUnits {
328340
}
329341
}
330342

343+
/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
331344
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
332345
pub enum WindowFrameBound {
333346
/// `CURRENT ROW`
334347
CurrentRow,
335348
/// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
336349
Preceding(Option<u64>),
337-
/// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`. This can only appear in
338-
/// [WindowFrame::end_bound].
350+
/// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
339351
Following(Option<u64>),
340352
}
341353

@@ -437,11 +449,16 @@ pub enum Statement {
437449
name: ObjectName,
438450
operation: AlterTableOperation,
439451
},
440-
/// DROP TABLE
452+
/// DROP
441453
Drop {
454+
/// The type of the object to drop: TABLE, VIEW, etc.
442455
object_type: ObjectType,
456+
/// An optional `IF EXISTS` clause. (Non-standard.)
443457
if_exists: bool,
458+
/// One or more objects to drop. (ANSI SQL requires exactly one.)
444459
names: Vec<ObjectName>,
460+
/// Whether `CASCADE` was specified. This will be `false` when
461+
/// `RESTRICT` or no drop behavior at all was specified.
445462
cascade: bool,
446463
},
447464
/// { BEGIN [ TRANSACTION | WORK ] | START TRANSACTION } ...
@@ -453,10 +470,7 @@ pub enum Statement {
453470
/// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
454471
Rollback { chain: bool },
455472
/// PEEK [ IMMEDIATE ]
456-
Peek {
457-
name: ObjectName,
458-
immediate: bool,
459-
},
473+
Peek { name: ObjectName, immediate: bool },
460474
/// TAIL
461475
Tail { name: ObjectName },
462476
/// The mysql-ish `SHOW COLUMNS FROM`
@@ -701,7 +715,7 @@ impl fmt::Display for Statement {
701715
f.write_str("IMMEDIATE ")?;
702716
}
703717
write!(f, "{}", name)
704-
},
718+
}
705719
Statement::Show { object_type } => {
706720
use ObjectType::*;
707721
write!(
@@ -721,16 +735,6 @@ impl fmt::Display for Statement {
721735
}
722736
}
723737

724-
/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
725-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
726-
pub struct ObjectName(pub Vec<Ident>);
727-
728-
impl fmt::Display for ObjectName {
729-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
730-
write!(f, "{}", display_separated(&self.0, "."))
731-
}
732-
}
733-
734738
/// SQL assignment `foo = expr` as used in SQLUpdate
735739
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
736740
pub struct Assignment {
@@ -795,19 +799,15 @@ pub enum FileFormat {
795799
impl fmt::Display for FileFormat {
796800
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
797801
use self::FileFormat::*;
798-
write!(
799-
f,
800-
"{}",
801-
match self {
802-
TEXTFILE => "TEXTFILE",
803-
SEQUENCEFILE => "SEQUENCEFILE",
804-
ORC => "ORC",
805-
PARQUET => "PARQUET",
806-
AVRO => "AVRO",
807-
RCFILE => "RCFILE",
808-
JSONFILE => "TEXTFILE",
809-
}
810-
)
802+
f.write_str(match self {
803+
TEXTFILE => "TEXTFILE",
804+
SEQUENCEFILE => "SEQUENCEFILE",
805+
ORC => "ORC",
806+
PARQUET => "PARQUET",
807+
AVRO => "AVRO",
808+
RCFILE => "RCFILE",
809+
JSONFILE => "TEXTFILE",
810+
})
811811
}
812812
}
813813

@@ -844,16 +844,12 @@ pub enum ObjectType {
844844

845845
impl fmt::Display for ObjectType {
846846
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
847-
write!(
848-
f,
849-
"{}",
850-
match self {
851-
ObjectType::Table => "TABLE",
852-
ObjectType::View => "VIEW",
853-
ObjectType::Source => "SOURCE",
854-
ObjectType::Sink => "SINK",
855-
}
856-
)
847+
f.write_str(match self {
848+
ObjectType::Table => "TABLE",
849+
ObjectType::View => "VIEW",
850+
ObjectType::Source => "SOURCE",
851+
ObjectType::Sink => "SINK",
852+
})
857853
}
858854
}
859855

@@ -879,7 +875,7 @@ impl fmt::Display for TransactionMode {
879875
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
880876
use TransactionMode::*;
881877
match self {
882-
AccessMode(access_mode) => write!(f, "{}", access_mode.to_string()),
878+
AccessMode(access_mode) => write!(f, "{}", access_mode),
883879
IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {}", iso_level),
884880
}
885881
}
@@ -894,14 +890,10 @@ pub enum TransactionAccessMode {
894890
impl fmt::Display for TransactionAccessMode {
895891
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
896892
use TransactionAccessMode::*;
897-
write!(
898-
f,
899-
"{}",
900-
match self {
901-
ReadOnly => "READ ONLY",
902-
ReadWrite => "READ WRITE",
903-
}
904-
)
893+
f.write_str(match self {
894+
ReadOnly => "READ ONLY",
895+
ReadWrite => "READ WRITE",
896+
})
905897
}
906898
}
907899

@@ -916,15 +908,11 @@ pub enum TransactionIsolationLevel {
916908
impl fmt::Display for TransactionIsolationLevel {
917909
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
918910
use TransactionIsolationLevel::*;
919-
write!(
920-
f,
921-
"{}",
922-
match self {
923-
ReadUncommitted => "READ UNCOMMITTED",
924-
ReadCommitted => "READ COMMITTED",
925-
RepeatableRead => "REPEATABLE READ",
926-
Serializable => "SERIALIZABLE",
927-
}
928-
)
911+
f.write_str(match self {
912+
ReadUncommitted => "READ UNCOMMITTED",
913+
ReadCommitted => "READ COMMITTED",
914+
RepeatableRead => "REPEATABLE READ",
915+
Serializable => "SERIALIZABLE",
916+
})
929917
}
930918
}

0 commit comments

Comments
 (0)