mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-26 23:49:10 +00:00
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".
This commit is contained in:
parent
e6b26330df
commit
646d1e13ca
8 changed files with 255 additions and 264 deletions
|
@ -1,6 +1,6 @@
|
||||||
//! AST types specific to CREATE/ALTER variants of `SQLStatement`
|
//! AST types specific to CREATE/ALTER variants of `SQLStatement`
|
||||||
//! (commonly referred to as Data Definition Language, or DDL)
|
//! (commonly referred to as Data Definition Language, or DDL)
|
||||||
use super::{ASTNode, SQLIdent, SQLObjectName, SQLType};
|
use super::{Expr, SQLIdent, SQLObjectName, SQLType};
|
||||||
|
|
||||||
/// An `ALTER TABLE` (`SQLStatement::SQLAlterTable`) operation
|
/// An `ALTER TABLE` (`SQLStatement::SQLAlterTable`) operation
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
|
@ -42,7 +42,7 @@ pub enum TableConstraint {
|
||||||
/// `[ CONSTRAINT <name> ] CHECK (<expr>)`
|
/// `[ CONSTRAINT <name> ] CHECK (<expr>)`
|
||||||
Check {
|
Check {
|
||||||
name: Option<SQLIdent>,
|
name: Option<SQLIdent>,
|
||||||
expr: Box<ASTNode>,
|
expr: Box<Expr>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ pub enum ColumnOption {
|
||||||
/// `NOT NULL`
|
/// `NOT NULL`
|
||||||
NotNull,
|
NotNull,
|
||||||
/// `DEFAULT <restricted-expr>`
|
/// `DEFAULT <restricted-expr>`
|
||||||
Default(ASTNode),
|
Default(Expr),
|
||||||
/// `{ PRIMARY KEY | UNIQUE }`
|
/// `{ PRIMARY KEY | UNIQUE }`
|
||||||
Unique {
|
Unique {
|
||||||
is_primary: bool,
|
is_primary: bool,
|
||||||
|
@ -157,7 +157,7 @@ pub enum ColumnOption {
|
||||||
referred_columns: Vec<SQLIdent>,
|
referred_columns: Vec<SQLIdent>,
|
||||||
},
|
},
|
||||||
// `CHECK (<expr>)`
|
// `CHECK (<expr>)`
|
||||||
Check(ASTNode),
|
Check(Expr),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for ColumnOption {
|
impl ToString for ColumnOption {
|
||||||
|
|
|
@ -53,7 +53,7 @@ pub type SQLIdent = String;
|
||||||
/// (e.g. boolean vs string), so the caller must handle expressions of
|
/// (e.g. boolean vs string), so the caller must handle expressions of
|
||||||
/// inappropriate type, like `WHERE 1` or `SELECT 1=1`, as necessary.
|
/// inappropriate type, like `WHERE 1` or `SELECT 1=1`, as necessary.
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub enum ASTNode {
|
pub enum Expr {
|
||||||
/// Identifier e.g. table name or column name
|
/// Identifier e.g. table name or column name
|
||||||
SQLIdentifier(SQLIdent),
|
SQLIdentifier(SQLIdent),
|
||||||
/// Unqualified wildcard (`*`). SQL allows this in limited contexts, such as:
|
/// Unqualified wildcard (`*`). SQL allows this in limited contexts, such as:
|
||||||
|
@ -69,55 +69,52 @@ pub enum ASTNode {
|
||||||
/// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
|
/// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
|
||||||
SQLCompoundIdentifier(Vec<SQLIdent>),
|
SQLCompoundIdentifier(Vec<SQLIdent>),
|
||||||
/// `IS NULL` expression
|
/// `IS NULL` expression
|
||||||
SQLIsNull(Box<ASTNode>),
|
SQLIsNull(Box<Expr>),
|
||||||
/// `IS NOT NULL` expression
|
/// `IS NOT NULL` expression
|
||||||
SQLIsNotNull(Box<ASTNode>),
|
SQLIsNotNull(Box<Expr>),
|
||||||
/// `[ NOT ] IN (val1, val2, ...)`
|
/// `[ NOT ] IN (val1, val2, ...)`
|
||||||
SQLInList {
|
SQLInList {
|
||||||
expr: Box<ASTNode>,
|
expr: Box<Expr>,
|
||||||
list: Vec<ASTNode>,
|
list: Vec<Expr>,
|
||||||
negated: bool,
|
negated: bool,
|
||||||
},
|
},
|
||||||
/// `[ NOT ] IN (SELECT ...)`
|
/// `[ NOT ] IN (SELECT ...)`
|
||||||
SQLInSubquery {
|
SQLInSubquery {
|
||||||
expr: Box<ASTNode>,
|
expr: Box<Expr>,
|
||||||
subquery: Box<SQLQuery>,
|
subquery: Box<SQLQuery>,
|
||||||
negated: bool,
|
negated: bool,
|
||||||
},
|
},
|
||||||
/// `<expr> [ NOT ] BETWEEN <low> AND <high>`
|
/// `<expr> [ NOT ] BETWEEN <low> AND <high>`
|
||||||
SQLBetween {
|
SQLBetween {
|
||||||
expr: Box<ASTNode>,
|
expr: Box<Expr>,
|
||||||
negated: bool,
|
negated: bool,
|
||||||
low: Box<ASTNode>,
|
low: Box<Expr>,
|
||||||
high: Box<ASTNode>,
|
high: Box<Expr>,
|
||||||
},
|
},
|
||||||
/// Binary operation e.g. `1 + 1` or `foo > bar`
|
/// Binary operation e.g. `1 + 1` or `foo > bar`
|
||||||
SQLBinaryOp {
|
SQLBinaryOp {
|
||||||
left: Box<ASTNode>,
|
left: Box<Expr>,
|
||||||
op: SQLBinaryOperator,
|
op: SQLBinaryOperator,
|
||||||
right: Box<ASTNode>,
|
right: Box<Expr>,
|
||||||
},
|
},
|
||||||
/// Unary operation e.g. `NOT foo`
|
/// Unary operation e.g. `NOT foo`
|
||||||
SQLUnaryOp {
|
SQLUnaryOp {
|
||||||
op: SQLUnaryOperator,
|
op: SQLUnaryOperator,
|
||||||
expr: Box<ASTNode>,
|
expr: Box<Expr>,
|
||||||
},
|
},
|
||||||
/// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
|
/// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
|
||||||
SQLCast {
|
SQLCast { expr: Box<Expr>, data_type: SQLType },
|
||||||
expr: Box<ASTNode>,
|
|
||||||
data_type: SQLType,
|
|
||||||
},
|
|
||||||
SQLExtract {
|
SQLExtract {
|
||||||
field: SQLDateTimeField,
|
field: SQLDateTimeField,
|
||||||
expr: Box<ASTNode>,
|
expr: Box<Expr>,
|
||||||
},
|
},
|
||||||
/// `expr COLLATE collation`
|
/// `expr COLLATE collation`
|
||||||
SQLCollate {
|
SQLCollate {
|
||||||
expr: Box<ASTNode>,
|
expr: Box<Expr>,
|
||||||
collation: SQLObjectName,
|
collation: SQLObjectName,
|
||||||
},
|
},
|
||||||
/// Nested expression e.g. `(foo > bar)` or `(1)`
|
/// Nested expression e.g. `(foo > bar)` or `(1)`
|
||||||
SQLNested(Box<ASTNode>),
|
SQLNested(Box<Expr>),
|
||||||
/// SQLValue
|
/// SQLValue
|
||||||
SQLValue(Value),
|
SQLValue(Value),
|
||||||
/// Scalar function call e.g. `LEFT(foo, 5)`
|
/// Scalar function call e.g. `LEFT(foo, 5)`
|
||||||
|
@ -128,10 +125,10 @@ pub enum ASTNode {
|
||||||
/// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
|
/// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
|
||||||
/// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
|
/// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
|
||||||
SQLCase {
|
SQLCase {
|
||||||
operand: Option<Box<ASTNode>>,
|
operand: Option<Box<Expr>>,
|
||||||
conditions: Vec<ASTNode>,
|
conditions: Vec<Expr>,
|
||||||
results: Vec<ASTNode>,
|
results: Vec<Expr>,
|
||||||
else_result: Option<Box<ASTNode>>,
|
else_result: Option<Box<Expr>>,
|
||||||
},
|
},
|
||||||
/// An exists expression `EXISTS(SELECT ...)`, used in expressions like
|
/// An exists expression `EXISTS(SELECT ...)`, used in expressions like
|
||||||
/// `WHERE EXISTS (SELECT ...)`.
|
/// `WHERE EXISTS (SELECT ...)`.
|
||||||
|
@ -141,16 +138,16 @@ pub enum ASTNode {
|
||||||
SQLSubquery(Box<SQLQuery>),
|
SQLSubquery(Box<SQLQuery>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for ASTNode {
|
impl ToString for Expr {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
ASTNode::SQLIdentifier(s) => s.to_string(),
|
Expr::SQLIdentifier(s) => s.to_string(),
|
||||||
ASTNode::SQLWildcard => "*".to_string(),
|
Expr::SQLWildcard => "*".to_string(),
|
||||||
ASTNode::SQLQualifiedWildcard(q) => q.join(".") + ".*",
|
Expr::SQLQualifiedWildcard(q) => q.join(".") + ".*",
|
||||||
ASTNode::SQLCompoundIdentifier(s) => s.join("."),
|
Expr::SQLCompoundIdentifier(s) => s.join("."),
|
||||||
ASTNode::SQLIsNull(ast) => format!("{} IS NULL", ast.as_ref().to_string()),
|
Expr::SQLIsNull(ast) => format!("{} IS NULL", ast.as_ref().to_string()),
|
||||||
ASTNode::SQLIsNotNull(ast) => format!("{} IS NOT NULL", ast.as_ref().to_string()),
|
Expr::SQLIsNotNull(ast) => format!("{} IS NOT NULL", ast.as_ref().to_string()),
|
||||||
ASTNode::SQLInList {
|
Expr::SQLInList {
|
||||||
expr,
|
expr,
|
||||||
list,
|
list,
|
||||||
negated,
|
negated,
|
||||||
|
@ -160,7 +157,7 @@ impl ToString for ASTNode {
|
||||||
if *negated { "NOT " } else { "" },
|
if *negated { "NOT " } else { "" },
|
||||||
comma_separated_string(list)
|
comma_separated_string(list)
|
||||||
),
|
),
|
||||||
ASTNode::SQLInSubquery {
|
Expr::SQLInSubquery {
|
||||||
expr,
|
expr,
|
||||||
subquery,
|
subquery,
|
||||||
negated,
|
negated,
|
||||||
|
@ -170,7 +167,7 @@ impl ToString for ASTNode {
|
||||||
if *negated { "NOT " } else { "" },
|
if *negated { "NOT " } else { "" },
|
||||||
subquery.to_string()
|
subquery.to_string()
|
||||||
),
|
),
|
||||||
ASTNode::SQLBetween {
|
Expr::SQLBetween {
|
||||||
expr,
|
expr,
|
||||||
negated,
|
negated,
|
||||||
low,
|
low,
|
||||||
|
@ -182,32 +179,32 @@ impl ToString for ASTNode {
|
||||||
low.to_string(),
|
low.to_string(),
|
||||||
high.to_string()
|
high.to_string()
|
||||||
),
|
),
|
||||||
ASTNode::SQLBinaryOp { left, op, right } => format!(
|
Expr::SQLBinaryOp { left, op, right } => format!(
|
||||||
"{} {} {}",
|
"{} {} {}",
|
||||||
left.as_ref().to_string(),
|
left.as_ref().to_string(),
|
||||||
op.to_string(),
|
op.to_string(),
|
||||||
right.as_ref().to_string()
|
right.as_ref().to_string()
|
||||||
),
|
),
|
||||||
ASTNode::SQLUnaryOp { op, expr } => {
|
Expr::SQLUnaryOp { op, expr } => {
|
||||||
format!("{} {}", op.to_string(), expr.as_ref().to_string())
|
format!("{} {}", op.to_string(), expr.as_ref().to_string())
|
||||||
}
|
}
|
||||||
ASTNode::SQLCast { expr, data_type } => format!(
|
Expr::SQLCast { expr, data_type } => format!(
|
||||||
"CAST({} AS {})",
|
"CAST({} AS {})",
|
||||||
expr.as_ref().to_string(),
|
expr.as_ref().to_string(),
|
||||||
data_type.to_string()
|
data_type.to_string()
|
||||||
),
|
),
|
||||||
ASTNode::SQLExtract { field, expr } => {
|
Expr::SQLExtract { field, expr } => {
|
||||||
format!("EXTRACT({} FROM {})", field.to_string(), expr.to_string())
|
format!("EXTRACT({} FROM {})", field.to_string(), expr.to_string())
|
||||||
}
|
}
|
||||||
ASTNode::SQLCollate { expr, collation } => format!(
|
Expr::SQLCollate { expr, collation } => format!(
|
||||||
"{} COLLATE {}",
|
"{} COLLATE {}",
|
||||||
expr.as_ref().to_string(),
|
expr.as_ref().to_string(),
|
||||||
collation.to_string()
|
collation.to_string()
|
||||||
),
|
),
|
||||||
ASTNode::SQLNested(ast) => format!("({})", ast.as_ref().to_string()),
|
Expr::SQLNested(ast) => format!("({})", ast.as_ref().to_string()),
|
||||||
ASTNode::SQLValue(v) => v.to_string(),
|
Expr::SQLValue(v) => v.to_string(),
|
||||||
ASTNode::SQLFunction(f) => f.to_string(),
|
Expr::SQLFunction(f) => f.to_string(),
|
||||||
ASTNode::SQLCase {
|
Expr::SQLCase {
|
||||||
operand,
|
operand,
|
||||||
conditions,
|
conditions,
|
||||||
results,
|
results,
|
||||||
|
@ -228,8 +225,8 @@ impl ToString for ASTNode {
|
||||||
}
|
}
|
||||||
s + " END"
|
s + " END"
|
||||||
}
|
}
|
||||||
ASTNode::SQLExists(s) => format!("EXISTS ({})", s.to_string()),
|
Expr::SQLExists(s) => format!("EXISTS ({})", s.to_string()),
|
||||||
ASTNode::SQLSubquery(s) => format!("({})", s.to_string()),
|
Expr::SQLSubquery(s) => format!("({})", s.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,7 +234,7 @@ impl ToString for ASTNode {
|
||||||
/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`)
|
/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`)
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub struct SQLWindowSpec {
|
pub struct SQLWindowSpec {
|
||||||
pub partition_by: Vec<ASTNode>,
|
pub partition_by: Vec<Expr>,
|
||||||
pub order_by: Vec<SQLOrderByExpr>,
|
pub order_by: Vec<SQLOrderByExpr>,
|
||||||
pub window_frame: Option<SQLWindowFrame>,
|
pub window_frame: Option<SQLWindowFrame>,
|
||||||
}
|
}
|
||||||
|
@ -374,14 +371,14 @@ pub enum SQLStatement {
|
||||||
/// Column assignments
|
/// Column assignments
|
||||||
assignments: Vec<SQLAssignment>,
|
assignments: Vec<SQLAssignment>,
|
||||||
/// WHERE
|
/// WHERE
|
||||||
selection: Option<ASTNode>,
|
selection: Option<Expr>,
|
||||||
},
|
},
|
||||||
/// DELETE
|
/// DELETE
|
||||||
SQLDelete {
|
SQLDelete {
|
||||||
/// FROM
|
/// FROM
|
||||||
table_name: SQLObjectName,
|
table_name: SQLObjectName,
|
||||||
/// WHERE
|
/// WHERE
|
||||||
selection: Option<ASTNode>,
|
selection: Option<Expr>,
|
||||||
},
|
},
|
||||||
/// CREATE VIEW
|
/// CREATE VIEW
|
||||||
SQLCreateView {
|
SQLCreateView {
|
||||||
|
@ -604,7 +601,7 @@ impl ToString for SQLObjectName {
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub struct SQLAssignment {
|
pub struct SQLAssignment {
|
||||||
pub id: SQLIdent,
|
pub id: SQLIdent,
|
||||||
pub value: ASTNode,
|
pub value: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for SQLAssignment {
|
impl ToString for SQLAssignment {
|
||||||
|
@ -617,7 +614,7 @@ impl ToString for SQLAssignment {
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub struct SQLFunction {
|
pub struct SQLFunction {
|
||||||
pub name: SQLObjectName,
|
pub name: SQLObjectName,
|
||||||
pub args: Vec<ASTNode>,
|
pub args: Vec<Expr>,
|
||||||
pub over: Option<SQLWindowSpec>,
|
pub over: Option<SQLWindowSpec>,
|
||||||
// aggregate functions may specify eg `COUNT(DISTINCT x)`
|
// aggregate functions may specify eg `COUNT(DISTINCT x)`
|
||||||
pub distinct: bool,
|
pub distinct: bool,
|
||||||
|
|
|
@ -23,9 +23,9 @@ pub struct SQLQuery {
|
||||||
/// ORDER BY
|
/// ORDER BY
|
||||||
pub order_by: Vec<SQLOrderByExpr>,
|
pub order_by: Vec<SQLOrderByExpr>,
|
||||||
/// `LIMIT { <N> | ALL }`
|
/// `LIMIT { <N> | ALL }`
|
||||||
pub limit: Option<ASTNode>,
|
pub limit: Option<Expr>,
|
||||||
/// `OFFSET <N> { ROW | ROWS }`
|
/// `OFFSET <N> { ROW | ROWS }`
|
||||||
pub offset: Option<ASTNode>,
|
pub offset: Option<Expr>,
|
||||||
/// `FETCH { FIRST | NEXT } <N> [ PERCENT ] { ROW | ROWS } | { ONLY | WITH TIES }`
|
/// `FETCH { FIRST | NEXT } <N> [ PERCENT ] { ROW | ROWS } | { ONLY | WITH TIES }`
|
||||||
pub fetch: Option<Fetch>,
|
pub fetch: Option<Fetch>,
|
||||||
}
|
}
|
||||||
|
@ -127,11 +127,11 @@ pub struct SQLSelect {
|
||||||
/// FROM
|
/// FROM
|
||||||
pub from: Vec<TableWithJoins>,
|
pub from: Vec<TableWithJoins>,
|
||||||
/// WHERE
|
/// WHERE
|
||||||
pub selection: Option<ASTNode>,
|
pub selection: Option<Expr>,
|
||||||
/// GROUP BY
|
/// GROUP BY
|
||||||
pub group_by: Vec<ASTNode>,
|
pub group_by: Vec<Expr>,
|
||||||
/// HAVING
|
/// HAVING
|
||||||
pub having: Option<ASTNode>,
|
pub having: Option<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for SQLSelect {
|
impl ToString for SQLSelect {
|
||||||
|
@ -177,9 +177,9 @@ impl ToString for Cte {
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub enum SQLSelectItem {
|
pub enum SQLSelectItem {
|
||||||
/// Any expression, not followed by `[ AS ] alias`
|
/// Any expression, not followed by `[ AS ] alias`
|
||||||
UnnamedExpression(ASTNode),
|
UnnamedExpr(Expr),
|
||||||
/// An expression, followed by `[ AS ] alias`
|
/// An expression, followed by `[ AS ] alias`
|
||||||
ExpressionWithAlias { expr: ASTNode, alias: SQLIdent },
|
ExprWithAlias { expr: Expr, alias: SQLIdent },
|
||||||
/// `alias.*` or even `schema.table.*`
|
/// `alias.*` or even `schema.table.*`
|
||||||
QualifiedWildcard(SQLObjectName),
|
QualifiedWildcard(SQLObjectName),
|
||||||
/// An unqualified `*`
|
/// An unqualified `*`
|
||||||
|
@ -189,8 +189,8 @@ pub enum SQLSelectItem {
|
||||||
impl ToString for SQLSelectItem {
|
impl ToString for SQLSelectItem {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
match &self {
|
match &self {
|
||||||
SQLSelectItem::UnnamedExpression(expr) => expr.to_string(),
|
SQLSelectItem::UnnamedExpr(expr) => expr.to_string(),
|
||||||
SQLSelectItem::ExpressionWithAlias { expr, alias } => {
|
SQLSelectItem::ExprWithAlias { expr, alias } => {
|
||||||
format!("{} AS {}", expr.to_string(), alias)
|
format!("{} AS {}", expr.to_string(), alias)
|
||||||
}
|
}
|
||||||
SQLSelectItem::QualifiedWildcard(prefix) => format!("{}.*", prefix.to_string()),
|
SQLSelectItem::QualifiedWildcard(prefix) => format!("{}.*", prefix.to_string()),
|
||||||
|
@ -224,9 +224,9 @@ pub enum TableFactor {
|
||||||
/// Arguments of a table-valued function, as supported by Postgres
|
/// Arguments of a table-valued function, as supported by Postgres
|
||||||
/// and MSSQL. Note that deprecated MSSQL `FROM foo (NOLOCK)` syntax
|
/// and MSSQL. Note that deprecated MSSQL `FROM foo (NOLOCK)` syntax
|
||||||
/// will also be parsed as `args`.
|
/// will also be parsed as `args`.
|
||||||
args: Vec<ASTNode>,
|
args: Vec<Expr>,
|
||||||
/// MSSQL-specific `WITH (...)` hints such as NOLOCK.
|
/// MSSQL-specific `WITH (...)` hints such as NOLOCK.
|
||||||
with_hints: Vec<ASTNode>,
|
with_hints: Vec<Expr>,
|
||||||
},
|
},
|
||||||
Derived {
|
Derived {
|
||||||
lateral: bool,
|
lateral: bool,
|
||||||
|
@ -361,7 +361,7 @@ pub enum JoinOperator {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub enum JoinConstraint {
|
pub enum JoinConstraint {
|
||||||
On(ASTNode),
|
On(Expr),
|
||||||
Using(Vec<SQLIdent>),
|
Using(Vec<SQLIdent>),
|
||||||
Natural,
|
Natural,
|
||||||
}
|
}
|
||||||
|
@ -369,7 +369,7 @@ pub enum JoinConstraint {
|
||||||
/// SQL ORDER BY expression
|
/// SQL ORDER BY expression
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub struct SQLOrderByExpr {
|
pub struct SQLOrderByExpr {
|
||||||
pub expr: ASTNode,
|
pub expr: Expr,
|
||||||
pub asc: Option<bool>,
|
pub asc: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +387,7 @@ impl ToString for SQLOrderByExpr {
|
||||||
pub struct Fetch {
|
pub struct Fetch {
|
||||||
pub with_ties: bool,
|
pub with_ties: bool,
|
||||||
pub percent: bool,
|
pub percent: bool,
|
||||||
pub quantity: Option<ASTNode>,
|
pub quantity: Option<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for Fetch {
|
impl ToString for Fetch {
|
||||||
|
@ -408,7 +408,7 @@ impl ToString for Fetch {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub struct SQLValues(pub Vec<Vec<ASTNode>>);
|
pub struct SQLValues(pub Vec<Vec<Expr>>);
|
||||||
|
|
||||||
impl ToString for SQLValues {
|
impl ToString for SQLValues {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
|
|
110
src/sqlparser.rs
110
src/sqlparser.rs
|
@ -151,12 +151,12 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a new expression
|
/// Parse a new expression
|
||||||
pub fn parse_expr(&mut self) -> Result<ASTNode, ParserError> {
|
pub fn parse_expr(&mut self) -> Result<Expr, ParserError> {
|
||||||
self.parse_subexpr(0)
|
self.parse_subexpr(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse tokens until the precedence changes
|
/// Parse tokens until the precedence changes
|
||||||
pub fn parse_subexpr(&mut self, precedence: u8) -> Result<ASTNode, ParserError> {
|
pub fn parse_subexpr(&mut self, precedence: u8) -> Result<Expr, ParserError> {
|
||||||
debug!("parsing expr");
|
debug!("parsing expr");
|
||||||
let mut expr = self.parse_prefix()?;
|
let mut expr = self.parse_prefix()?;
|
||||||
debug!("prefix: {:?}", expr);
|
debug!("prefix: {:?}", expr);
|
||||||
|
@ -173,7 +173,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an expression prefix
|
/// Parse an expression prefix
|
||||||
pub fn parse_prefix(&mut self) -> Result<ASTNode, ParserError> {
|
pub fn parse_prefix(&mut self) -> Result<Expr, ParserError> {
|
||||||
let tok = self
|
let tok = self
|
||||||
.next_token()
|
.next_token()
|
||||||
.ok_or_else(|| ParserError::ParserError("Unexpected EOF".to_string()))?;
|
.ok_or_else(|| ParserError::ParserError("Unexpected EOF".to_string()))?;
|
||||||
|
@ -183,18 +183,18 @@ impl Parser {
|
||||||
self.prev_token();
|
self.prev_token();
|
||||||
self.parse_sql_value()
|
self.parse_sql_value()
|
||||||
}
|
}
|
||||||
"CASE" => self.parse_case_expression(),
|
"CASE" => self.parse_case_expr(),
|
||||||
"CAST" => self.parse_cast_expression(),
|
"CAST" => self.parse_cast_expr(),
|
||||||
"DATE" => Ok(ASTNode::SQLValue(Value::Date(self.parse_literal_string()?))),
|
"DATE" => Ok(Expr::SQLValue(Value::Date(self.parse_literal_string()?))),
|
||||||
"EXISTS" => self.parse_exists_expression(),
|
"EXISTS" => self.parse_exists_expr(),
|
||||||
"EXTRACT" => self.parse_extract_expression(),
|
"EXTRACT" => self.parse_extract_expr(),
|
||||||
"INTERVAL" => self.parse_literal_interval(),
|
"INTERVAL" => self.parse_literal_interval(),
|
||||||
"NOT" => Ok(ASTNode::SQLUnaryOp {
|
"NOT" => Ok(Expr::SQLUnaryOp {
|
||||||
op: SQLUnaryOperator::Not,
|
op: SQLUnaryOperator::Not,
|
||||||
expr: Box::new(self.parse_subexpr(Self::UNARY_NOT_PREC)?),
|
expr: Box::new(self.parse_subexpr(Self::UNARY_NOT_PREC)?),
|
||||||
}),
|
}),
|
||||||
"TIME" => Ok(ASTNode::SQLValue(Value::Time(self.parse_literal_string()?))),
|
"TIME" => Ok(Expr::SQLValue(Value::Time(self.parse_literal_string()?))),
|
||||||
"TIMESTAMP" => Ok(ASTNode::SQLValue(Value::Timestamp(
|
"TIMESTAMP" => Ok(Expr::SQLValue(Value::Timestamp(
|
||||||
self.parse_literal_string()?,
|
self.parse_literal_string()?,
|
||||||
))),
|
))),
|
||||||
// Here `w` is a word, check if it's a part of a multi-part
|
// Here `w` is a word, check if it's a part of a multi-part
|
||||||
|
@ -217,25 +217,25 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ends_with_wildcard {
|
if ends_with_wildcard {
|
||||||
Ok(ASTNode::SQLQualifiedWildcard(id_parts))
|
Ok(Expr::SQLQualifiedWildcard(id_parts))
|
||||||
} else if self.consume_token(&Token::LParen) {
|
} else if self.consume_token(&Token::LParen) {
|
||||||
self.prev_token();
|
self.prev_token();
|
||||||
self.parse_function(SQLObjectName(id_parts))
|
self.parse_function(SQLObjectName(id_parts))
|
||||||
} else {
|
} else {
|
||||||
Ok(ASTNode::SQLCompoundIdentifier(id_parts))
|
Ok(Expr::SQLCompoundIdentifier(id_parts))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Ok(ASTNode::SQLIdentifier(w.as_sql_ident())),
|
_ => Ok(Expr::SQLIdentifier(w.as_sql_ident())),
|
||||||
},
|
},
|
||||||
}, // End of Token::SQLWord
|
}, // End of Token::SQLWord
|
||||||
Token::Mult => Ok(ASTNode::SQLWildcard),
|
Token::Mult => Ok(Expr::SQLWildcard),
|
||||||
tok @ Token::Minus | tok @ Token::Plus => {
|
tok @ Token::Minus | tok @ Token::Plus => {
|
||||||
let op = if tok == Token::Plus {
|
let op = if tok == Token::Plus {
|
||||||
SQLUnaryOperator::Plus
|
SQLUnaryOperator::Plus
|
||||||
} else {
|
} else {
|
||||||
SQLUnaryOperator::Minus
|
SQLUnaryOperator::Minus
|
||||||
};
|
};
|
||||||
Ok(ASTNode::SQLUnaryOp {
|
Ok(Expr::SQLUnaryOp {
|
||||||
op,
|
op,
|
||||||
expr: Box::new(self.parse_subexpr(Self::PLUS_MINUS_PREC)?),
|
expr: Box::new(self.parse_subexpr(Self::PLUS_MINUS_PREC)?),
|
||||||
})
|
})
|
||||||
|
@ -250,9 +250,9 @@ impl Parser {
|
||||||
Token::LParen => {
|
Token::LParen => {
|
||||||
let expr = if self.parse_keyword("SELECT") || self.parse_keyword("WITH") {
|
let expr = if self.parse_keyword("SELECT") || self.parse_keyword("WITH") {
|
||||||
self.prev_token();
|
self.prev_token();
|
||||||
ASTNode::SQLSubquery(Box::new(self.parse_query()?))
|
Expr::SQLSubquery(Box::new(self.parse_query()?))
|
||||||
} else {
|
} else {
|
||||||
ASTNode::SQLNested(Box::new(self.parse_expr()?))
|
Expr::SQLNested(Box::new(self.parse_expr()?))
|
||||||
};
|
};
|
||||||
self.expect_token(&Token::RParen)?;
|
self.expect_token(&Token::RParen)?;
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
|
@ -261,7 +261,7 @@ impl Parser {
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
if self.parse_keyword("COLLATE") {
|
if self.parse_keyword("COLLATE") {
|
||||||
Ok(ASTNode::SQLCollate {
|
Ok(Expr::SQLCollate {
|
||||||
expr: Box::new(expr),
|
expr: Box::new(expr),
|
||||||
collation: self.parse_object_name()?,
|
collation: self.parse_object_name()?,
|
||||||
})
|
})
|
||||||
|
@ -270,7 +270,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_function(&mut self, name: SQLObjectName) -> Result<ASTNode, ParserError> {
|
pub fn parse_function(&mut self, name: SQLObjectName) -> Result<Expr, ParserError> {
|
||||||
self.expect_token(&Token::LParen)?;
|
self.expect_token(&Token::LParen)?;
|
||||||
let all = self.parse_keyword("ALL");
|
let all = self.parse_keyword("ALL");
|
||||||
let distinct = self.parse_keyword("DISTINCT");
|
let distinct = self.parse_keyword("DISTINCT");
|
||||||
|
@ -306,7 +306,7 @@ impl Parser {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ASTNode::SQLFunction(SQLFunction {
|
Ok(Expr::SQLFunction(SQLFunction {
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
over,
|
over,
|
||||||
|
@ -366,7 +366,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_case_expression(&mut self) -> Result<ASTNode, ParserError> {
|
pub fn parse_case_expr(&mut self) -> Result<Expr, ParserError> {
|
||||||
let mut operand = None;
|
let mut operand = None;
|
||||||
if !self.parse_keyword("WHEN") {
|
if !self.parse_keyword("WHEN") {
|
||||||
operand = Some(Box::new(self.parse_expr()?));
|
operand = Some(Box::new(self.parse_expr()?));
|
||||||
|
@ -388,7 +388,7 @@ impl Parser {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
self.expect_keyword("END")?;
|
self.expect_keyword("END")?;
|
||||||
Ok(ASTNode::SQLCase {
|
Ok(Expr::SQLCase {
|
||||||
operand,
|
operand,
|
||||||
conditions,
|
conditions,
|
||||||
results,
|
results,
|
||||||
|
@ -397,33 +397,33 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a SQL CAST function e.g. `CAST(expr AS FLOAT)`
|
/// Parse a SQL CAST function e.g. `CAST(expr AS FLOAT)`
|
||||||
pub fn parse_cast_expression(&mut self) -> Result<ASTNode, ParserError> {
|
pub fn parse_cast_expr(&mut self) -> Result<Expr, ParserError> {
|
||||||
self.expect_token(&Token::LParen)?;
|
self.expect_token(&Token::LParen)?;
|
||||||
let expr = self.parse_expr()?;
|
let expr = self.parse_expr()?;
|
||||||
self.expect_keyword("AS")?;
|
self.expect_keyword("AS")?;
|
||||||
let data_type = self.parse_data_type()?;
|
let data_type = self.parse_data_type()?;
|
||||||
self.expect_token(&Token::RParen)?;
|
self.expect_token(&Token::RParen)?;
|
||||||
Ok(ASTNode::SQLCast {
|
Ok(Expr::SQLCast {
|
||||||
expr: Box::new(expr),
|
expr: Box::new(expr),
|
||||||
data_type,
|
data_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a SQL EXISTS expression e.g. `WHERE EXISTS(SELECT ...)`.
|
/// Parse a SQL EXISTS expression e.g. `WHERE EXISTS(SELECT ...)`.
|
||||||
pub fn parse_exists_expression(&mut self) -> Result<ASTNode, ParserError> {
|
pub fn parse_exists_expr(&mut self) -> Result<Expr, ParserError> {
|
||||||
self.expect_token(&Token::LParen)?;
|
self.expect_token(&Token::LParen)?;
|
||||||
let exists_node = ASTNode::SQLExists(Box::new(self.parse_query()?));
|
let exists_node = Expr::SQLExists(Box::new(self.parse_query()?));
|
||||||
self.expect_token(&Token::RParen)?;
|
self.expect_token(&Token::RParen)?;
|
||||||
Ok(exists_node)
|
Ok(exists_node)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_extract_expression(&mut self) -> Result<ASTNode, ParserError> {
|
pub fn parse_extract_expr(&mut self) -> Result<Expr, ParserError> {
|
||||||
self.expect_token(&Token::LParen)?;
|
self.expect_token(&Token::LParen)?;
|
||||||
let field = self.parse_date_time_field()?;
|
let field = self.parse_date_time_field()?;
|
||||||
self.expect_keyword("FROM")?;
|
self.expect_keyword("FROM")?;
|
||||||
let expr = self.parse_expr()?;
|
let expr = self.parse_expr()?;
|
||||||
self.expect_token(&Token::RParen)?;
|
self.expect_token(&Token::RParen)?;
|
||||||
Ok(ASTNode::SQLExtract {
|
Ok(Expr::SQLExtract {
|
||||||
field,
|
field,
|
||||||
expr: Box::new(expr),
|
expr: Box::new(expr),
|
||||||
})
|
})
|
||||||
|
@ -462,7 +462,7 @@ impl Parser {
|
||||||
/// 6. `INTERVAL '1:1' HOUR (5) TO MINUTE (5)`
|
/// 6. `INTERVAL '1:1' HOUR (5) TO MINUTE (5)`
|
||||||
///
|
///
|
||||||
/// Note that we do not currently attempt to parse the quoted value.
|
/// Note that we do not currently attempt to parse the quoted value.
|
||||||
pub fn parse_literal_interval(&mut self) -> Result<ASTNode, ParserError> {
|
pub fn parse_literal_interval(&mut self) -> Result<Expr, ParserError> {
|
||||||
// The SQL standard allows an optional sign before the value string, but
|
// The SQL standard allows an optional sign before the value string, but
|
||||||
// it is not clear if any implementations support that syntax, so we
|
// it is not clear if any implementations support that syntax, so we
|
||||||
// don't currently try to parse it. (The sign can instead be included
|
// don't currently try to parse it. (The sign can instead be included
|
||||||
|
@ -504,7 +504,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ASTNode::SQLValue(Value::Interval {
|
Ok(Expr::SQLValue(Value::Interval {
|
||||||
value,
|
value,
|
||||||
leading_field,
|
leading_field,
|
||||||
leading_precision,
|
leading_precision,
|
||||||
|
@ -514,7 +514,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an operator following an expression
|
/// Parse an operator following an expression
|
||||||
pub fn parse_infix(&mut self, expr: ASTNode, precedence: u8) -> Result<ASTNode, ParserError> {
|
pub fn parse_infix(&mut self, expr: Expr, precedence: u8) -> Result<Expr, ParserError> {
|
||||||
debug!("parsing infix");
|
debug!("parsing infix");
|
||||||
let tok = self.next_token().unwrap(); // safe as EOF's precedence is the lowest
|
let tok = self.next_token().unwrap(); // safe as EOF's precedence is the lowest
|
||||||
|
|
||||||
|
@ -547,7 +547,7 @@ impl Parser {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(op) = regular_binary_operator {
|
if let Some(op) = regular_binary_operator {
|
||||||
Ok(ASTNode::SQLBinaryOp {
|
Ok(Expr::SQLBinaryOp {
|
||||||
left: Box::new(expr),
|
left: Box::new(expr),
|
||||||
op,
|
op,
|
||||||
right: Box::new(self.parse_subexpr(precedence)?),
|
right: Box::new(self.parse_subexpr(precedence)?),
|
||||||
|
@ -556,9 +556,9 @@ impl Parser {
|
||||||
match k.keyword.as_ref() {
|
match k.keyword.as_ref() {
|
||||||
"IS" => {
|
"IS" => {
|
||||||
if self.parse_keyword("NULL") {
|
if self.parse_keyword("NULL") {
|
||||||
Ok(ASTNode::SQLIsNull(Box::new(expr)))
|
Ok(Expr::SQLIsNull(Box::new(expr)))
|
||||||
} else if self.parse_keywords(vec!["NOT", "NULL"]) {
|
} else if self.parse_keywords(vec!["NOT", "NULL"]) {
|
||||||
Ok(ASTNode::SQLIsNotNull(Box::new(expr)))
|
Ok(Expr::SQLIsNotNull(Box::new(expr)))
|
||||||
} else {
|
} else {
|
||||||
self.expected("NULL or NOT NULL after IS", self.peek_token())
|
self.expected("NULL or NOT NULL after IS", self.peek_token())
|
||||||
}
|
}
|
||||||
|
@ -586,17 +586,17 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the parens following the `[ NOT ] IN` operator
|
/// Parses the parens following the `[ NOT ] IN` operator
|
||||||
pub fn parse_in(&mut self, expr: ASTNode, negated: bool) -> Result<ASTNode, ParserError> {
|
pub fn parse_in(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
|
||||||
self.expect_token(&Token::LParen)?;
|
self.expect_token(&Token::LParen)?;
|
||||||
let in_op = if self.parse_keyword("SELECT") || self.parse_keyword("WITH") {
|
let in_op = if self.parse_keyword("SELECT") || self.parse_keyword("WITH") {
|
||||||
self.prev_token();
|
self.prev_token();
|
||||||
ASTNode::SQLInSubquery {
|
Expr::SQLInSubquery {
|
||||||
expr: Box::new(expr),
|
expr: Box::new(expr),
|
||||||
subquery: Box::new(self.parse_query()?),
|
subquery: Box::new(self.parse_query()?),
|
||||||
negated,
|
negated,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ASTNode::SQLInList {
|
Expr::SQLInList {
|
||||||
expr: Box::new(expr),
|
expr: Box::new(expr),
|
||||||
list: self.parse_expr_list()?,
|
list: self.parse_expr_list()?,
|
||||||
negated,
|
negated,
|
||||||
|
@ -607,13 +607,13 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses `BETWEEN <low> AND <high>`, assuming the `BETWEEN` keyword was already consumed
|
/// Parses `BETWEEN <low> AND <high>`, assuming the `BETWEEN` keyword was already consumed
|
||||||
pub fn parse_between(&mut self, expr: ASTNode, negated: bool) -> Result<ASTNode, ParserError> {
|
pub fn parse_between(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
|
||||||
// Stop parsing subexpressions for <low> and <high> on tokens with
|
// Stop parsing subexpressions for <low> and <high> on tokens with
|
||||||
// precedence lower than that of `BETWEEN`, such as `AND`, `IS`, etc.
|
// precedence lower than that of `BETWEEN`, such as `AND`, `IS`, etc.
|
||||||
let low = self.parse_subexpr(Self::BETWEEN_PREC)?;
|
let low = self.parse_subexpr(Self::BETWEEN_PREC)?;
|
||||||
self.expect_keyword("AND")?;
|
self.expect_keyword("AND")?;
|
||||||
let high = self.parse_subexpr(Self::BETWEEN_PREC)?;
|
let high = self.parse_subexpr(Self::BETWEEN_PREC)?;
|
||||||
Ok(ASTNode::SQLBetween {
|
Ok(Expr::SQLBetween {
|
||||||
expr: Box::new(expr),
|
expr: Box::new(expr),
|
||||||
negated,
|
negated,
|
||||||
low: Box::new(low),
|
low: Box::new(low),
|
||||||
|
@ -622,8 +622,8 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a postgresql casting style which is in the form of `expr::datatype`
|
/// Parse a postgresql casting style which is in the form of `expr::datatype`
|
||||||
pub fn parse_pg_cast(&mut self, expr: ASTNode) -> Result<ASTNode, ParserError> {
|
pub fn parse_pg_cast(&mut self, expr: Expr) -> Result<Expr, ParserError> {
|
||||||
Ok(ASTNode::SQLCast {
|
Ok(Expr::SQLCast {
|
||||||
expr: Box::new(expr),
|
expr: Box::new(expr),
|
||||||
data_type: self.parse_data_type()?,
|
data_type: self.parse_data_type()?,
|
||||||
})
|
})
|
||||||
|
@ -1132,8 +1132,8 @@ impl Parser {
|
||||||
Ok(values)
|
Ok(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_sql_value(&mut self) -> Result<ASTNode, ParserError> {
|
fn parse_sql_value(&mut self) -> Result<Expr, ParserError> {
|
||||||
Ok(ASTNode::SQLValue(self.parse_value()?))
|
Ok(Expr::SQLValue(self.parse_value()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_tab_value(&mut self) -> Result<Vec<Option<String>>, ParserError> {
|
fn parse_tab_value(&mut self) -> Result<Vec<Option<String>>, ParserError> {
|
||||||
|
@ -1826,8 +1826,8 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a comma-delimited list of SQL expressions
|
/// Parse a comma-delimited list of SQL expressions
|
||||||
pub fn parse_expr_list(&mut self) -> Result<Vec<ASTNode>, ParserError> {
|
pub fn parse_expr_list(&mut self) -> Result<Vec<Expr>, ParserError> {
|
||||||
let mut expr_list: Vec<ASTNode> = vec![];
|
let mut expr_list: Vec<Expr> = vec![];
|
||||||
loop {
|
loop {
|
||||||
expr_list.push(self.parse_expr()?);
|
expr_list.push(self.parse_expr()?);
|
||||||
if !self.consume_token(&Token::Comma) {
|
if !self.consume_token(&Token::Comma) {
|
||||||
|
@ -1837,7 +1837,7 @@ impl Parser {
|
||||||
Ok(expr_list)
|
Ok(expr_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_optional_args(&mut self) -> Result<Vec<ASTNode>, ParserError> {
|
pub fn parse_optional_args(&mut self) -> Result<Vec<Expr>, ParserError> {
|
||||||
if self.consume_token(&Token::RParen) {
|
if self.consume_token(&Token::RParen) {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
} else {
|
} else {
|
||||||
|
@ -1852,18 +1852,18 @@ impl Parser {
|
||||||
let mut projections: Vec<SQLSelectItem> = vec![];
|
let mut projections: Vec<SQLSelectItem> = vec![];
|
||||||
loop {
|
loop {
|
||||||
let expr = self.parse_expr()?;
|
let expr = self.parse_expr()?;
|
||||||
if let ASTNode::SQLWildcard = expr {
|
if let Expr::SQLWildcard = expr {
|
||||||
projections.push(SQLSelectItem::Wildcard);
|
projections.push(SQLSelectItem::Wildcard);
|
||||||
} else if let ASTNode::SQLQualifiedWildcard(prefix) = expr {
|
} else if let Expr::SQLQualifiedWildcard(prefix) = expr {
|
||||||
projections.push(SQLSelectItem::QualifiedWildcard(SQLObjectName(prefix)));
|
projections.push(SQLSelectItem::QualifiedWildcard(SQLObjectName(prefix)));
|
||||||
} else {
|
} else {
|
||||||
// `expr` is a regular SQL expression and can be followed by an alias
|
// `expr` is a regular SQL expression and can be followed by an alias
|
||||||
if let Some(alias) =
|
if let Some(alias) =
|
||||||
self.parse_optional_alias(keywords::RESERVED_FOR_COLUMN_ALIAS)?
|
self.parse_optional_alias(keywords::RESERVED_FOR_COLUMN_ALIAS)?
|
||||||
{
|
{
|
||||||
projections.push(SQLSelectItem::ExpressionWithAlias { expr, alias });
|
projections.push(SQLSelectItem::ExprWithAlias { expr, alias });
|
||||||
} else {
|
} else {
|
||||||
projections.push(SQLSelectItem::UnnamedExpression(expr));
|
projections.push(SQLSelectItem::UnnamedExpr(expr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1897,20 +1897,20 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a LIMIT clause
|
/// Parse a LIMIT clause
|
||||||
pub fn parse_limit(&mut self) -> Result<Option<ASTNode>, ParserError> {
|
pub fn parse_limit(&mut self) -> Result<Option<Expr>, ParserError> {
|
||||||
if self.parse_keyword("ALL") {
|
if self.parse_keyword("ALL") {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
} else {
|
} else {
|
||||||
self.parse_literal_uint()
|
self.parse_literal_uint()
|
||||||
.map(|n| Some(ASTNode::SQLValue(Value::Long(n))))
|
.map(|n| Some(Expr::SQLValue(Value::Long(n))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an OFFSET clause
|
/// Parse an OFFSET clause
|
||||||
pub fn parse_offset(&mut self) -> Result<ASTNode, ParserError> {
|
pub fn parse_offset(&mut self) -> Result<Expr, ParserError> {
|
||||||
let value = self
|
let value = self
|
||||||
.parse_literal_uint()
|
.parse_literal_uint()
|
||||||
.map(|n| ASTNode::SQLValue(Value::Long(n)))?;
|
.map(|n| Expr::SQLValue(Value::Long(n)))?;
|
||||||
self.expect_one_of_keywords(&["ROW", "ROWS"])?;
|
self.expect_one_of_keywords(&["ROW", "ROWS"])?;
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ impl TestedDialects {
|
||||||
|
|
||||||
/// Ensures that `sql` parses as an expression, and is not modified
|
/// Ensures that `sql` parses as an expression, and is not modified
|
||||||
/// after a serialization round-trip.
|
/// after a serialization round-trip.
|
||||||
pub fn verified_expr(&self, sql: &str) -> ASTNode {
|
pub fn verified_expr(&self, sql: &str) -> Expr {
|
||||||
let ast = self.run_parser_method(sql, Parser::parse_expr).unwrap();
|
let ast = self.run_parser_method(sql, Parser::parse_expr).unwrap();
|
||||||
assert_eq!(sql, &ast.to_string(), "round-tripping without changes");
|
assert_eq!(sql, &ast.to_string(), "round-tripping without changes");
|
||||||
ast
|
ast
|
||||||
|
@ -130,9 +130,9 @@ pub fn only<T>(v: impl IntoIterator<Item = T>) -> T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expr_from_projection(item: &SQLSelectItem) -> &ASTNode {
|
pub fn expr_from_projection(item: &SQLSelectItem) -> &Expr {
|
||||||
match item {
|
match item {
|
||||||
SQLSelectItem::UnnamedExpression(expr) => expr,
|
SQLSelectItem::UnnamedExpr(expr) => expr,
|
||||||
_ => panic!("Expected UnnamedExpression"),
|
_ => panic!("Expected UnnamedExpr"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,9 @@ use sqlparser::test_utils::{all_dialects, expr_from_projection, only};
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_insert_values() {
|
fn parse_insert_values() {
|
||||||
let row = vec![
|
let row = vec![
|
||||||
ASTNode::SQLValue(Value::Long(1)),
|
Expr::SQLValue(Value::Long(1)),
|
||||||
ASTNode::SQLValue(Value::Long(2)),
|
Expr::SQLValue(Value::Long(2)),
|
||||||
ASTNode::SQLValue(Value::Long(3)),
|
Expr::SQLValue(Value::Long(3)),
|
||||||
];
|
];
|
||||||
let rows1 = vec![row.clone()];
|
let rows1 = vec![row.clone()];
|
||||||
let rows2 = vec![row.clone(), row];
|
let rows2 = vec![row.clone(), row];
|
||||||
|
@ -58,7 +58,7 @@ fn parse_insert_values() {
|
||||||
sql: &str,
|
sql: &str,
|
||||||
expected_table_name: &str,
|
expected_table_name: &str,
|
||||||
expected_columns: &[String],
|
expected_columns: &[String],
|
||||||
expected_rows: &[Vec<ASTNode>],
|
expected_rows: &[Vec<Expr>],
|
||||||
) {
|
) {
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
SQLStatement::SQLInsert {
|
SQLStatement::SQLInsert {
|
||||||
|
@ -109,19 +109,19 @@ fn parse_update() {
|
||||||
vec![
|
vec![
|
||||||
SQLAssignment {
|
SQLAssignment {
|
||||||
id: "a".into(),
|
id: "a".into(),
|
||||||
value: ASTNode::SQLValue(Value::Long(1)),
|
value: Expr::SQLValue(Value::Long(1)),
|
||||||
},
|
},
|
||||||
SQLAssignment {
|
SQLAssignment {
|
||||||
id: "b".into(),
|
id: "b".into(),
|
||||||
value: ASTNode::SQLValue(Value::Long(2)),
|
value: Expr::SQLValue(Value::Long(2)),
|
||||||
},
|
},
|
||||||
SQLAssignment {
|
SQLAssignment {
|
||||||
id: "c".into(),
|
id: "c".into(),
|
||||||
value: ASTNode::SQLValue(Value::Long(3)),
|
value: Expr::SQLValue(Value::Long(3)),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(selection.unwrap(), ASTNode::SQLIdentifier("d".into()));
|
assert_eq!(selection.unwrap(), Expr::SQLIdentifier("d".into()));
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ fn parse_delete_statement() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_where_delete_statement() {
|
fn parse_where_delete_statement() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
use self::SQLBinaryOperator::*;
|
use self::SQLBinaryOperator::*;
|
||||||
|
|
||||||
let sql = "DELETE FROM foo WHERE name = 5";
|
let sql = "DELETE FROM foo WHERE name = 5";
|
||||||
|
@ -208,17 +208,17 @@ fn parse_simple_select() {
|
||||||
assert_eq!(false, select.distinct);
|
assert_eq!(false, select.distinct);
|
||||||
assert_eq!(3, select.projection.len());
|
assert_eq!(3, select.projection.len());
|
||||||
let select = verified_query(sql);
|
let select = verified_query(sql);
|
||||||
assert_eq!(Some(ASTNode::SQLValue(Value::Long(5))), select.limit);
|
assert_eq!(Some(Expr::SQLValue(Value::Long(5))), select.limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_limit_is_not_an_alias() {
|
fn parse_limit_is_not_an_alias() {
|
||||||
// In dialects supporting LIMIT it shouldn't be parsed as a table alias
|
// In dialects supporting LIMIT it shouldn't be parsed as a table alias
|
||||||
let ast = verified_query("SELECT id FROM customer LIMIT 1");
|
let ast = verified_query("SELECT id FROM customer LIMIT 1");
|
||||||
assert_eq!(Some(ASTNode::SQLValue(Value::Long(1))), ast.limit);
|
assert_eq!(Some(Expr::SQLValue(Value::Long(1))), ast.limit);
|
||||||
|
|
||||||
let ast = verified_query("SELECT 1 LIMIT 5");
|
let ast = verified_query("SELECT 1 LIMIT 5");
|
||||||
assert_eq!(Some(ASTNode::SQLValue(Value::Long(5))), ast.limit);
|
assert_eq!(Some(Expr::SQLValue(Value::Long(5))), ast.limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -227,7 +227,7 @@ fn parse_select_distinct() {
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(true, select.distinct);
|
assert_eq!(true, select.distinct);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&SQLSelectItem::UnnamedExpression(ASTNode::SQLIdentifier("name".to_string())),
|
&SQLSelectItem::UnnamedExpr(Expr::SQLIdentifier("name".to_string())),
|
||||||
only(&select.projection)
|
only(&select.projection)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -281,18 +281,18 @@ fn parse_count_wildcard() {
|
||||||
fn parse_column_aliases() {
|
fn parse_column_aliases() {
|
||||||
let sql = "SELECT a.col + 1 AS newname FROM foo AS a";
|
let sql = "SELECT a.col + 1 AS newname FROM foo AS a";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
if let SQLSelectItem::ExpressionWithAlias {
|
if let SQLSelectItem::ExprWithAlias {
|
||||||
expr: ASTNode::SQLBinaryOp {
|
expr: Expr::SQLBinaryOp {
|
||||||
ref op, ref right, ..
|
ref op, ref right, ..
|
||||||
},
|
},
|
||||||
ref alias,
|
ref alias,
|
||||||
} = only(&select.projection)
|
} = only(&select.projection)
|
||||||
{
|
{
|
||||||
assert_eq!(&SQLBinaryOperator::Plus, op);
|
assert_eq!(&SQLBinaryOperator::Plus, op);
|
||||||
assert_eq!(&ASTNode::SQLValue(Value::Long(1)), right.as_ref());
|
assert_eq!(&Expr::SQLValue(Value::Long(1)), right.as_ref());
|
||||||
assert_eq!("newname", alias);
|
assert_eq!("newname", alias);
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected ExpressionWithAlias")
|
panic!("Expected ExprWithAlias")
|
||||||
}
|
}
|
||||||
|
|
||||||
// alias without AS is parsed correctly:
|
// alias without AS is parsed correctly:
|
||||||
|
@ -319,9 +319,9 @@ fn parse_select_count_wildcard() {
|
||||||
let sql = "SELECT COUNT(*) FROM customer";
|
let sql = "SELECT COUNT(*) FROM customer";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLFunction(SQLFunction {
|
&Expr::SQLFunction(SQLFunction {
|
||||||
name: SQLObjectName(vec!["COUNT".to_string()]),
|
name: SQLObjectName(vec!["COUNT".to_string()]),
|
||||||
args: vec![ASTNode::SQLWildcard],
|
args: vec![Expr::SQLWildcard],
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
}),
|
}),
|
||||||
|
@ -334,11 +334,11 @@ fn parse_select_count_distinct() {
|
||||||
let sql = "SELECT COUNT(DISTINCT + x) FROM customer";
|
let sql = "SELECT COUNT(DISTINCT + x) FROM customer";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLFunction(SQLFunction {
|
&Expr::SQLFunction(SQLFunction {
|
||||||
name: SQLObjectName(vec!["COUNT".to_string()]),
|
name: SQLObjectName(vec!["COUNT".to_string()]),
|
||||||
args: vec![ASTNode::SQLUnaryOp {
|
args: vec![Expr::SQLUnaryOp {
|
||||||
op: SQLUnaryOperator::Plus,
|
op: SQLUnaryOperator::Plus,
|
||||||
expr: Box::new(ASTNode::SQLIdentifier("x".to_string()))
|
expr: Box::new(Expr::SQLIdentifier("x".to_string()))
|
||||||
}],
|
}],
|
||||||
over: None,
|
over: None,
|
||||||
distinct: true,
|
distinct: true,
|
||||||
|
@ -382,7 +382,7 @@ fn parse_collate() {
|
||||||
let sql = "SELECT name COLLATE \"de_DE\" FROM customer";
|
let sql = "SELECT name COLLATE \"de_DE\" FROM customer";
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
only(&all_dialects().verified_only_select(sql).projection),
|
only(&all_dialects().verified_only_select(sql).projection),
|
||||||
SQLSelectItem::UnnamedExpression(ASTNode::SQLCollate { .. })
|
SQLSelectItem::UnnamedExpr(Expr::SQLCollate { .. })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,14 +406,14 @@ fn parse_null_in_select() {
|
||||||
let sql = "SELECT NULL";
|
let sql = "SELECT NULL";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::Null),
|
&Expr::SQLValue(Value::Null),
|
||||||
expr_from_projection(only(&select.projection)),
|
expr_from_projection(only(&select.projection)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_escaped_single_quote_string_predicate() {
|
fn parse_escaped_single_quote_string_predicate() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
use self::SQLBinaryOperator::*;
|
use self::SQLBinaryOperator::*;
|
||||||
let sql = "SELECT id, fname, lname FROM customer \
|
let sql = "SELECT id, fname, lname FROM customer \
|
||||||
WHERE salary <> 'Jim''s salary'";
|
WHERE salary <> 'Jim''s salary'";
|
||||||
|
@ -432,7 +432,7 @@ fn parse_escaped_single_quote_string_predicate() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_compound_expr_1() {
|
fn parse_compound_expr_1() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
use self::SQLBinaryOperator::*;
|
use self::SQLBinaryOperator::*;
|
||||||
let sql = "a + b * c";
|
let sql = "a + b * c";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -451,7 +451,7 @@ fn parse_compound_expr_1() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_compound_expr_2() {
|
fn parse_compound_expr_2() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
use self::SQLBinaryOperator::*;
|
use self::SQLBinaryOperator::*;
|
||||||
let sql = "a * b + c";
|
let sql = "a * b + c";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -470,7 +470,7 @@ fn parse_compound_expr_2() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_unary_math() {
|
fn parse_unary_math() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
let sql = "- a + - b";
|
let sql = "- a + - b";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
SQLBinaryOp {
|
SQLBinaryOp {
|
||||||
|
@ -490,7 +490,7 @@ fn parse_unary_math() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_is_null() {
|
fn parse_is_null() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
let sql = "a IS NULL";
|
let sql = "a IS NULL";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
SQLIsNull(Box::new(SQLIdentifier("a".to_string()))),
|
SQLIsNull(Box::new(SQLIdentifier("a".to_string()))),
|
||||||
|
@ -500,7 +500,7 @@ fn parse_is_null() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_is_not_null() {
|
fn parse_is_not_null() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
let sql = "a IS NOT NULL";
|
let sql = "a IS NOT NULL";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
SQLIsNotNull(Box::new(SQLIdentifier("a".to_string()))),
|
SQLIsNotNull(Box::new(SQLIdentifier("a".to_string()))),
|
||||||
|
@ -510,7 +510,7 @@ fn parse_is_not_null() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_not_precedence() {
|
fn parse_not_precedence() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
// NOT has higher precedence than OR/AND, so the following must parse as (NOT true) OR true
|
// NOT has higher precedence than OR/AND, so the following must parse as (NOT true) OR true
|
||||||
let sql = "NOT true OR true";
|
let sql = "NOT true OR true";
|
||||||
assert_matches!(verified_expr(sql), SQLBinaryOp {
|
assert_matches!(verified_expr(sql), SQLBinaryOp {
|
||||||
|
@ -578,16 +578,14 @@ fn parse_like() {
|
||||||
);
|
);
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ASTNode::SQLBinaryOp {
|
Expr::SQLBinaryOp {
|
||||||
left: Box::new(ASTNode::SQLIdentifier("name".to_string())),
|
left: Box::new(Expr::SQLIdentifier("name".to_string())),
|
||||||
op: if negated {
|
op: if negated {
|
||||||
SQLBinaryOperator::NotLike
|
SQLBinaryOperator::NotLike
|
||||||
} else {
|
} else {
|
||||||
SQLBinaryOperator::Like
|
SQLBinaryOperator::Like
|
||||||
},
|
},
|
||||||
right: Box::new(ASTNode::SQLValue(Value::SingleQuotedString(
|
right: Box::new(Expr::SQLValue(Value::SingleQuotedString("%a".to_string()))),
|
||||||
"%a".to_string()
|
|
||||||
))),
|
|
||||||
},
|
},
|
||||||
select.selection.unwrap()
|
select.selection.unwrap()
|
||||||
);
|
);
|
||||||
|
@ -600,16 +598,14 @@ fn parse_like() {
|
||||||
);
|
);
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ASTNode::SQLIsNull(Box::new(ASTNode::SQLBinaryOp {
|
Expr::SQLIsNull(Box::new(Expr::SQLBinaryOp {
|
||||||
left: Box::new(ASTNode::SQLIdentifier("name".to_string())),
|
left: Box::new(Expr::SQLIdentifier("name".to_string())),
|
||||||
op: if negated {
|
op: if negated {
|
||||||
SQLBinaryOperator::NotLike
|
SQLBinaryOperator::NotLike
|
||||||
} else {
|
} else {
|
||||||
SQLBinaryOperator::Like
|
SQLBinaryOperator::Like
|
||||||
},
|
},
|
||||||
right: Box::new(ASTNode::SQLValue(Value::SingleQuotedString(
|
right: Box::new(Expr::SQLValue(Value::SingleQuotedString("%a".to_string()))),
|
||||||
"%a".to_string()
|
|
||||||
))),
|
|
||||||
})),
|
})),
|
||||||
select.selection.unwrap()
|
select.selection.unwrap()
|
||||||
);
|
);
|
||||||
|
@ -627,11 +623,11 @@ fn parse_in_list() {
|
||||||
);
|
);
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ASTNode::SQLInList {
|
Expr::SQLInList {
|
||||||
expr: Box::new(ASTNode::SQLIdentifier("segment".to_string())),
|
expr: Box::new(Expr::SQLIdentifier("segment".to_string())),
|
||||||
list: vec![
|
list: vec![
|
||||||
ASTNode::SQLValue(Value::SingleQuotedString("HIGH".to_string())),
|
Expr::SQLValue(Value::SingleQuotedString("HIGH".to_string())),
|
||||||
ASTNode::SQLValue(Value::SingleQuotedString("MED".to_string())),
|
Expr::SQLValue(Value::SingleQuotedString("MED".to_string())),
|
||||||
],
|
],
|
||||||
negated,
|
negated,
|
||||||
},
|
},
|
||||||
|
@ -647,8 +643,8 @@ fn parse_in_subquery() {
|
||||||
let sql = "SELECT * FROM customers WHERE segment IN (SELECT segm FROM bar)";
|
let sql = "SELECT * FROM customers WHERE segment IN (SELECT segm FROM bar)";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ASTNode::SQLInSubquery {
|
Expr::SQLInSubquery {
|
||||||
expr: Box::new(ASTNode::SQLIdentifier("segment".to_string())),
|
expr: Box::new(Expr::SQLIdentifier("segment".to_string())),
|
||||||
subquery: Box::new(verified_query("SELECT segm FROM bar")),
|
subquery: Box::new(verified_query("SELECT segm FROM bar")),
|
||||||
negated: false,
|
negated: false,
|
||||||
},
|
},
|
||||||
|
@ -665,10 +661,10 @@ fn parse_between() {
|
||||||
);
|
);
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ASTNode::SQLBetween {
|
Expr::SQLBetween {
|
||||||
expr: Box::new(ASTNode::SQLIdentifier("age".to_string())),
|
expr: Box::new(Expr::SQLIdentifier("age".to_string())),
|
||||||
low: Box::new(ASTNode::SQLValue(Value::Long(25))),
|
low: Box::new(Expr::SQLValue(Value::Long(25))),
|
||||||
high: Box::new(ASTNode::SQLValue(Value::Long(32))),
|
high: Box::new(Expr::SQLValue(Value::Long(32))),
|
||||||
negated,
|
negated,
|
||||||
},
|
},
|
||||||
select.selection.unwrap()
|
select.selection.unwrap()
|
||||||
|
@ -680,22 +676,22 @@ fn parse_between() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_between_with_expr() {
|
fn parse_between_with_expr() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
use self::SQLBinaryOperator::*;
|
use self::SQLBinaryOperator::*;
|
||||||
let sql = "SELECT * FROM t WHERE 1 BETWEEN 1 + 2 AND 3 + 4 IS NULL";
|
let sql = "SELECT * FROM t WHERE 1 BETWEEN 1 + 2 AND 3 + 4 IS NULL";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ASTNode::SQLIsNull(Box::new(ASTNode::SQLBetween {
|
Expr::SQLIsNull(Box::new(Expr::SQLBetween {
|
||||||
expr: Box::new(ASTNode::SQLValue(Value::Long(1))),
|
expr: Box::new(Expr::SQLValue(Value::Long(1))),
|
||||||
low: Box::new(SQLBinaryOp {
|
low: Box::new(SQLBinaryOp {
|
||||||
left: Box::new(ASTNode::SQLValue(Value::Long(1))),
|
left: Box::new(Expr::SQLValue(Value::Long(1))),
|
||||||
op: Plus,
|
op: Plus,
|
||||||
right: Box::new(ASTNode::SQLValue(Value::Long(2))),
|
right: Box::new(Expr::SQLValue(Value::Long(2))),
|
||||||
}),
|
}),
|
||||||
high: Box::new(SQLBinaryOp {
|
high: Box::new(SQLBinaryOp {
|
||||||
left: Box::new(ASTNode::SQLValue(Value::Long(3))),
|
left: Box::new(Expr::SQLValue(Value::Long(3))),
|
||||||
op: Plus,
|
op: Plus,
|
||||||
right: Box::new(ASTNode::SQLValue(Value::Long(4))),
|
right: Box::new(Expr::SQLValue(Value::Long(4))),
|
||||||
}),
|
}),
|
||||||
negated: false,
|
negated: false,
|
||||||
})),
|
})),
|
||||||
|
@ -705,21 +701,21 @@ fn parse_between_with_expr() {
|
||||||
let sql = "SELECT * FROM t WHERE 1 = 1 AND 1 + x BETWEEN 1 AND 2";
|
let sql = "SELECT * FROM t WHERE 1 = 1 AND 1 + x BETWEEN 1 AND 2";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ASTNode::SQLBinaryOp {
|
Expr::SQLBinaryOp {
|
||||||
left: Box::new(ASTNode::SQLBinaryOp {
|
left: Box::new(Expr::SQLBinaryOp {
|
||||||
left: Box::new(ASTNode::SQLValue(Value::Long(1))),
|
left: Box::new(Expr::SQLValue(Value::Long(1))),
|
||||||
op: SQLBinaryOperator::Eq,
|
op: SQLBinaryOperator::Eq,
|
||||||
right: Box::new(ASTNode::SQLValue(Value::Long(1))),
|
right: Box::new(Expr::SQLValue(Value::Long(1))),
|
||||||
}),
|
}),
|
||||||
op: SQLBinaryOperator::And,
|
op: SQLBinaryOperator::And,
|
||||||
right: Box::new(ASTNode::SQLBetween {
|
right: Box::new(Expr::SQLBetween {
|
||||||
expr: Box::new(ASTNode::SQLBinaryOp {
|
expr: Box::new(Expr::SQLBinaryOp {
|
||||||
left: Box::new(ASTNode::SQLValue(Value::Long(1))),
|
left: Box::new(Expr::SQLValue(Value::Long(1))),
|
||||||
op: SQLBinaryOperator::Plus,
|
op: SQLBinaryOperator::Plus,
|
||||||
right: Box::new(ASTNode::SQLIdentifier("x".to_string())),
|
right: Box::new(Expr::SQLIdentifier("x".to_string())),
|
||||||
}),
|
}),
|
||||||
low: Box::new(ASTNode::SQLValue(Value::Long(1))),
|
low: Box::new(Expr::SQLValue(Value::Long(1))),
|
||||||
high: Box::new(ASTNode::SQLValue(Value::Long(2))),
|
high: Box::new(Expr::SQLValue(Value::Long(2))),
|
||||||
negated: false,
|
negated: false,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
@ -734,15 +730,15 @@ fn parse_select_order_by() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
SQLOrderByExpr {
|
SQLOrderByExpr {
|
||||||
expr: ASTNode::SQLIdentifier("lname".to_string()),
|
expr: Expr::SQLIdentifier("lname".to_string()),
|
||||||
asc: Some(true),
|
asc: Some(true),
|
||||||
},
|
},
|
||||||
SQLOrderByExpr {
|
SQLOrderByExpr {
|
||||||
expr: ASTNode::SQLIdentifier("fname".to_string()),
|
expr: Expr::SQLIdentifier("fname".to_string()),
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
},
|
},
|
||||||
SQLOrderByExpr {
|
SQLOrderByExpr {
|
||||||
expr: ASTNode::SQLIdentifier("id".to_string()),
|
expr: Expr::SQLIdentifier("id".to_string()),
|
||||||
asc: None,
|
asc: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -763,17 +759,17 @@ fn parse_select_order_by_limit() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
SQLOrderByExpr {
|
SQLOrderByExpr {
|
||||||
expr: ASTNode::SQLIdentifier("lname".to_string()),
|
expr: Expr::SQLIdentifier("lname".to_string()),
|
||||||
asc: Some(true),
|
asc: Some(true),
|
||||||
},
|
},
|
||||||
SQLOrderByExpr {
|
SQLOrderByExpr {
|
||||||
expr: ASTNode::SQLIdentifier("fname".to_string()),
|
expr: Expr::SQLIdentifier("fname".to_string()),
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
select.order_by
|
select.order_by
|
||||||
);
|
);
|
||||||
assert_eq!(Some(ASTNode::SQLValue(Value::Long(2))), select.limit);
|
assert_eq!(Some(Expr::SQLValue(Value::Long(2))), select.limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -782,8 +778,8 @@ fn parse_select_group_by() {
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
ASTNode::SQLIdentifier("lname".to_string()),
|
Expr::SQLIdentifier("lname".to_string()),
|
||||||
ASTNode::SQLIdentifier("fname".to_string()),
|
Expr::SQLIdentifier("fname".to_string()),
|
||||||
],
|
],
|
||||||
select.group_by
|
select.group_by
|
||||||
);
|
);
|
||||||
|
@ -794,15 +790,15 @@ fn parse_select_having() {
|
||||||
let sql = "SELECT foo FROM bar GROUP BY foo HAVING COUNT(*) > 1";
|
let sql = "SELECT foo FROM bar GROUP BY foo HAVING COUNT(*) > 1";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(ASTNode::SQLBinaryOp {
|
Some(Expr::SQLBinaryOp {
|
||||||
left: Box::new(ASTNode::SQLFunction(SQLFunction {
|
left: Box::new(Expr::SQLFunction(SQLFunction {
|
||||||
name: SQLObjectName(vec!["COUNT".to_string()]),
|
name: SQLObjectName(vec!["COUNT".to_string()]),
|
||||||
args: vec![ASTNode::SQLWildcard],
|
args: vec![Expr::SQLWildcard],
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false
|
distinct: false
|
||||||
})),
|
})),
|
||||||
op: SQLBinaryOperator::Gt,
|
op: SQLBinaryOperator::Gt,
|
||||||
right: Box::new(ASTNode::SQLValue(Value::Long(1)))
|
right: Box::new(Expr::SQLValue(Value::Long(1)))
|
||||||
}),
|
}),
|
||||||
select.having
|
select.having
|
||||||
);
|
);
|
||||||
|
@ -825,8 +821,8 @@ fn parse_cast() {
|
||||||
let sql = "SELECT CAST(id AS bigint) FROM customer";
|
let sql = "SELECT CAST(id AS bigint) FROM customer";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLCast {
|
&Expr::SQLCast {
|
||||||
expr: Box::new(ASTNode::SQLIdentifier("id".to_string())),
|
expr: Box::new(Expr::SQLIdentifier("id".to_string())),
|
||||||
data_type: SQLType::BigInt
|
data_type: SQLType::BigInt
|
||||||
},
|
},
|
||||||
expr_from_projection(only(&select.projection))
|
expr_from_projection(only(&select.projection))
|
||||||
|
@ -854,9 +850,9 @@ fn parse_extract() {
|
||||||
let sql = "SELECT EXTRACT(YEAR FROM d)";
|
let sql = "SELECT EXTRACT(YEAR FROM d)";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLExtract {
|
&Expr::SQLExtract {
|
||||||
field: SQLDateTimeField::Year,
|
field: SQLDateTimeField::Year,
|
||||||
expr: Box::new(ASTNode::SQLIdentifier("d".to_string())),
|
expr: Box::new(Expr::SQLIdentifier("d".to_string())),
|
||||||
},
|
},
|
||||||
expr_from_projection(only(&select.projection)),
|
expr_from_projection(only(&select.projection)),
|
||||||
);
|
);
|
||||||
|
@ -1141,9 +1137,9 @@ fn parse_scalar_function_in_projection() {
|
||||||
let sql = "SELECT sqrt(id) FROM foo";
|
let sql = "SELECT sqrt(id) FROM foo";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLFunction(SQLFunction {
|
&Expr::SQLFunction(SQLFunction {
|
||||||
name: SQLObjectName(vec!["sqrt".to_string()]),
|
name: SQLObjectName(vec!["sqrt".to_string()]),
|
||||||
args: vec![ASTNode::SQLIdentifier("id".to_string())],
|
args: vec![Expr::SQLIdentifier("id".to_string())],
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
}),
|
}),
|
||||||
|
@ -1164,13 +1160,13 @@ fn parse_window_functions() {
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(4, select.projection.len());
|
assert_eq!(4, select.projection.len());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLFunction(SQLFunction {
|
&Expr::SQLFunction(SQLFunction {
|
||||||
name: SQLObjectName(vec!["row_number".to_string()]),
|
name: SQLObjectName(vec!["row_number".to_string()]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
over: Some(SQLWindowSpec {
|
over: Some(SQLWindowSpec {
|
||||||
partition_by: vec![],
|
partition_by: vec![],
|
||||||
order_by: vec![SQLOrderByExpr {
|
order_by: vec![SQLOrderByExpr {
|
||||||
expr: ASTNode::SQLIdentifier("dt".to_string()),
|
expr: Expr::SQLIdentifier("dt".to_string()),
|
||||||
asc: Some(false)
|
asc: Some(false)
|
||||||
}],
|
}],
|
||||||
window_frame: None,
|
window_frame: None,
|
||||||
|
@ -1194,15 +1190,15 @@ fn parse_literal_string() {
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(3, select.projection.len());
|
assert_eq!(3, select.projection.len());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::SingleQuotedString("one".to_string())),
|
&Expr::SQLValue(Value::SingleQuotedString("one".to_string())),
|
||||||
expr_from_projection(&select.projection[0])
|
expr_from_projection(&select.projection[0])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::NationalStringLiteral("national string".to_string())),
|
&Expr::SQLValue(Value::NationalStringLiteral("national string".to_string())),
|
||||||
expr_from_projection(&select.projection[1])
|
expr_from_projection(&select.projection[1])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::HexStringLiteral("deadBEEF".to_string())),
|
&Expr::SQLValue(Value::HexStringLiteral("deadBEEF".to_string())),
|
||||||
expr_from_projection(&select.projection[2])
|
expr_from_projection(&select.projection[2])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1214,7 +1210,7 @@ fn parse_literal_date() {
|
||||||
let sql = "SELECT DATE '1999-01-01'";
|
let sql = "SELECT DATE '1999-01-01'";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::Date("1999-01-01".into())),
|
&Expr::SQLValue(Value::Date("1999-01-01".into())),
|
||||||
expr_from_projection(only(&select.projection)),
|
expr_from_projection(only(&select.projection)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1224,7 +1220,7 @@ fn parse_literal_time() {
|
||||||
let sql = "SELECT TIME '01:23:34'";
|
let sql = "SELECT TIME '01:23:34'";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::Time("01:23:34".into())),
|
&Expr::SQLValue(Value::Time("01:23:34".into())),
|
||||||
expr_from_projection(only(&select.projection)),
|
expr_from_projection(only(&select.projection)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1234,7 +1230,7 @@ fn parse_literal_timestamp() {
|
||||||
let sql = "SELECT TIMESTAMP '1999-01-01 01:23:34'";
|
let sql = "SELECT TIMESTAMP '1999-01-01 01:23:34'";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::Timestamp("1999-01-01 01:23:34".into())),
|
&Expr::SQLValue(Value::Timestamp("1999-01-01 01:23:34".into())),
|
||||||
expr_from_projection(only(&select.projection)),
|
expr_from_projection(only(&select.projection)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1244,7 +1240,7 @@ fn parse_literal_interval() {
|
||||||
let sql = "SELECT INTERVAL '1-1' YEAR TO MONTH";
|
let sql = "SELECT INTERVAL '1-1' YEAR TO MONTH";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::Interval {
|
&Expr::SQLValue(Value::Interval {
|
||||||
value: "1-1".into(),
|
value: "1-1".into(),
|
||||||
leading_field: SQLDateTimeField::Year,
|
leading_field: SQLDateTimeField::Year,
|
||||||
leading_precision: None,
|
leading_precision: None,
|
||||||
|
@ -1257,7 +1253,7 @@ fn parse_literal_interval() {
|
||||||
let sql = "SELECT INTERVAL '01:01.01' MINUTE (5) TO SECOND (5)";
|
let sql = "SELECT INTERVAL '01:01.01' MINUTE (5) TO SECOND (5)";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::Interval {
|
&Expr::SQLValue(Value::Interval {
|
||||||
value: "01:01.01".into(),
|
value: "01:01.01".into(),
|
||||||
leading_field: SQLDateTimeField::Minute,
|
leading_field: SQLDateTimeField::Minute,
|
||||||
leading_precision: Some(5),
|
leading_precision: Some(5),
|
||||||
|
@ -1270,7 +1266,7 @@ fn parse_literal_interval() {
|
||||||
let sql = "SELECT INTERVAL '1' SECOND (5, 4)";
|
let sql = "SELECT INTERVAL '1' SECOND (5, 4)";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::Interval {
|
&Expr::SQLValue(Value::Interval {
|
||||||
value: "1".into(),
|
value: "1".into(),
|
||||||
leading_field: SQLDateTimeField::Second,
|
leading_field: SQLDateTimeField::Second,
|
||||||
leading_precision: Some(5),
|
leading_precision: Some(5),
|
||||||
|
@ -1283,7 +1279,7 @@ fn parse_literal_interval() {
|
||||||
let sql = "SELECT INTERVAL '10' HOUR";
|
let sql = "SELECT INTERVAL '10' HOUR";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::Interval {
|
&Expr::SQLValue(Value::Interval {
|
||||||
value: "10".into(),
|
value: "10".into(),
|
||||||
leading_field: SQLDateTimeField::Hour,
|
leading_field: SQLDateTimeField::Hour,
|
||||||
leading_precision: None,
|
leading_precision: None,
|
||||||
|
@ -1296,7 +1292,7 @@ fn parse_literal_interval() {
|
||||||
let sql = "SELECT INTERVAL '10' HOUR (1)";
|
let sql = "SELECT INTERVAL '10' HOUR (1)";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::Interval {
|
&Expr::SQLValue(Value::Interval {
|
||||||
value: "10".into(),
|
value: "10".into(),
|
||||||
leading_field: SQLDateTimeField::Hour,
|
leading_field: SQLDateTimeField::Hour,
|
||||||
leading_precision: Some(1),
|
leading_precision: Some(1),
|
||||||
|
@ -1369,11 +1365,11 @@ fn parse_delimited_identifiers() {
|
||||||
// check SELECT
|
// check SELECT
|
||||||
assert_eq!(3, select.projection.len());
|
assert_eq!(3, select.projection.len());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLCompoundIdentifier(vec![r#""alias""#.to_string(), r#""bar baz""#.to_string()]),
|
&Expr::SQLCompoundIdentifier(vec![r#""alias""#.to_string(), r#""bar baz""#.to_string()]),
|
||||||
expr_from_projection(&select.projection[0]),
|
expr_from_projection(&select.projection[0]),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLFunction(SQLFunction {
|
&Expr::SQLFunction(SQLFunction {
|
||||||
name: SQLObjectName(vec![r#""myfun""#.to_string()]),
|
name: SQLObjectName(vec![r#""myfun""#.to_string()]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
over: None,
|
over: None,
|
||||||
|
@ -1382,11 +1378,11 @@ fn parse_delimited_identifiers() {
|
||||||
expr_from_projection(&select.projection[1]),
|
expr_from_projection(&select.projection[1]),
|
||||||
);
|
);
|
||||||
match &select.projection[2] {
|
match &select.projection[2] {
|
||||||
SQLSelectItem::ExpressionWithAlias { expr, alias } => {
|
SQLSelectItem::ExprWithAlias { expr, alias } => {
|
||||||
assert_eq!(&ASTNode::SQLIdentifier(r#""simple id""#.to_string()), expr);
|
assert_eq!(&Expr::SQLIdentifier(r#""simple id""#.to_string()), expr);
|
||||||
assert_eq!(r#""column alias""#, alias);
|
assert_eq!(r#""column alias""#, alias);
|
||||||
}
|
}
|
||||||
_ => panic!("Expected ExpressionWithAlias"),
|
_ => panic!("Expected ExprWithAlias"),
|
||||||
}
|
}
|
||||||
|
|
||||||
verified_stmt(r#"CREATE TABLE "foo" ("bar" "int")"#);
|
verified_stmt(r#"CREATE TABLE "foo" ("bar" "int")"#);
|
||||||
|
@ -1396,7 +1392,7 @@ fn parse_delimited_identifiers() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_parens() {
|
fn parse_parens() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
use self::SQLBinaryOperator::*;
|
use self::SQLBinaryOperator::*;
|
||||||
let sql = "(a + b) - (c + d)";
|
let sql = "(a + b) - (c + d)";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1418,9 +1414,9 @@ fn parse_parens() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_searched_case_expression() {
|
fn parse_searched_case_expr() {
|
||||||
let sql = "SELECT CASE WHEN bar IS NULL THEN 'null' WHEN bar = 0 THEN '=0' WHEN bar >= 0 THEN '>=0' ELSE '<0' END FROM foo";
|
let sql = "SELECT CASE WHEN bar IS NULL THEN 'null' WHEN bar = 0 THEN '=0' WHEN bar >= 0 THEN '>=0' ELSE '<0' END FROM foo";
|
||||||
use self::ASTNode::{SQLBinaryOp, SQLCase, SQLIdentifier, SQLIsNull, SQLValue};
|
use self::Expr::{SQLBinaryOp, SQLCase, SQLIdentifier, SQLIsNull, SQLValue};
|
||||||
use self::SQLBinaryOperator::*;
|
use self::SQLBinaryOperator::*;
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1453,11 +1449,11 @@ fn parse_searched_case_expression() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_simple_case_expression() {
|
fn parse_simple_case_expr() {
|
||||||
// ANSI calls a CASE expression with an operand "<simple case>"
|
// ANSI calls a CASE expression with an operand "<simple case>"
|
||||||
let sql = "SELECT CASE foo WHEN 1 THEN 'Y' ELSE 'N' END";
|
let sql = "SELECT CASE foo WHEN 1 THEN 'Y' ELSE 'N' END";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
use self::ASTNode::{SQLCase, SQLIdentifier, SQLValue};
|
use self::Expr::{SQLCase, SQLIdentifier, SQLValue};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&SQLCase {
|
&SQLCase {
|
||||||
operand: Some(Box::new(SQLIdentifier("foo".to_string()))),
|
operand: Some(Box::new(SQLIdentifier("foo".to_string()))),
|
||||||
|
@ -1587,10 +1583,10 @@ fn parse_joins_on() {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
with_hints: vec![],
|
with_hints: vec![],
|
||||||
},
|
},
|
||||||
join_operator: f(JoinConstraint::On(ASTNode::SQLBinaryOp {
|
join_operator: f(JoinConstraint::On(Expr::SQLBinaryOp {
|
||||||
left: Box::new(ASTNode::SQLIdentifier("c1".into())),
|
left: Box::new(Expr::SQLIdentifier("c1".into())),
|
||||||
op: SQLBinaryOperator::Eq,
|
op: SQLBinaryOperator::Eq,
|
||||||
right: Box::new(ASTNode::SQLIdentifier("c2".into())),
|
right: Box::new(Expr::SQLIdentifier("c2".into())),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1834,7 +1830,7 @@ fn parse_ctes() {
|
||||||
let sql = &format!("SELECT ({})", with);
|
let sql = &format!("SELECT ({})", with);
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
match expr_from_projection(only(&select.projection)) {
|
match expr_from_projection(only(&select.projection)) {
|
||||||
ASTNode::SQLSubquery(ref subquery) => {
|
Expr::SQLSubquery(ref subquery) => {
|
||||||
assert_ctes_in_select(&cte_sqls, subquery.as_ref());
|
assert_ctes_in_select(&cte_sqls, subquery.as_ref());
|
||||||
}
|
}
|
||||||
_ => panic!("Expected subquery"),
|
_ => panic!("Expected subquery"),
|
||||||
|
@ -1991,7 +1987,7 @@ fn parse_multiple_statements() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_scalar_subqueries() {
|
fn parse_scalar_subqueries() {
|
||||||
use self::ASTNode::*;
|
use self::Expr::*;
|
||||||
let sql = "(SELECT 1) + (SELECT 2)";
|
let sql = "(SELECT 1) + (SELECT 2)";
|
||||||
assert_matches!(verified_expr(sql), SQLBinaryOp {
|
assert_matches!(verified_expr(sql), SQLBinaryOp {
|
||||||
op: SQLBinaryOperator::Plus, ..
|
op: SQLBinaryOperator::Plus, ..
|
||||||
|
@ -2006,16 +2002,16 @@ fn parse_exists_subquery() {
|
||||||
let sql = "SELECT * FROM t WHERE EXISTS (SELECT 1)";
|
let sql = "SELECT * FROM t WHERE EXISTS (SELECT 1)";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ASTNode::SQLExists(Box::new(expected_inner.clone())),
|
Expr::SQLExists(Box::new(expected_inner.clone())),
|
||||||
select.selection.unwrap(),
|
select.selection.unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let sql = "SELECT * FROM t WHERE NOT EXISTS (SELECT 1)";
|
let sql = "SELECT * FROM t WHERE NOT EXISTS (SELECT 1)";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ASTNode::SQLUnaryOp {
|
Expr::SQLUnaryOp {
|
||||||
op: SQLUnaryOperator::Not,
|
op: SQLUnaryOperator::Not,
|
||||||
expr: Box::new(ASTNode::SQLExists(Box::new(expected_inner))),
|
expr: Box::new(Expr::SQLExists(Box::new(expected_inner))),
|
||||||
},
|
},
|
||||||
select.selection.unwrap(),
|
select.selection.unwrap(),
|
||||||
);
|
);
|
||||||
|
@ -2208,26 +2204,26 @@ fn parse_invalid_subquery_without_parens() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_offset() {
|
fn parse_offset() {
|
||||||
let ast = verified_query("SELECT foo FROM bar OFFSET 2 ROWS");
|
let ast = verified_query("SELECT foo FROM bar OFFSET 2 ROWS");
|
||||||
assert_eq!(ast.offset, Some(ASTNode::SQLValue(Value::Long(2))));
|
assert_eq!(ast.offset, Some(Expr::SQLValue(Value::Long(2))));
|
||||||
let ast = verified_query("SELECT foo FROM bar WHERE foo = 4 OFFSET 2 ROWS");
|
let ast = verified_query("SELECT foo FROM bar WHERE foo = 4 OFFSET 2 ROWS");
|
||||||
assert_eq!(ast.offset, Some(ASTNode::SQLValue(Value::Long(2))));
|
assert_eq!(ast.offset, Some(Expr::SQLValue(Value::Long(2))));
|
||||||
let ast = verified_query("SELECT foo FROM bar ORDER BY baz OFFSET 2 ROWS");
|
let ast = verified_query("SELECT foo FROM bar ORDER BY baz OFFSET 2 ROWS");
|
||||||
assert_eq!(ast.offset, Some(ASTNode::SQLValue(Value::Long(2))));
|
assert_eq!(ast.offset, Some(Expr::SQLValue(Value::Long(2))));
|
||||||
let ast = verified_query("SELECT foo FROM bar WHERE foo = 4 ORDER BY baz OFFSET 2 ROWS");
|
let ast = verified_query("SELECT foo FROM bar WHERE foo = 4 ORDER BY baz OFFSET 2 ROWS");
|
||||||
assert_eq!(ast.offset, Some(ASTNode::SQLValue(Value::Long(2))));
|
assert_eq!(ast.offset, Some(Expr::SQLValue(Value::Long(2))));
|
||||||
let ast = verified_query("SELECT foo FROM (SELECT * FROM bar OFFSET 2 ROWS) OFFSET 2 ROWS");
|
let ast = verified_query("SELECT foo FROM (SELECT * FROM bar OFFSET 2 ROWS) OFFSET 2 ROWS");
|
||||||
assert_eq!(ast.offset, Some(ASTNode::SQLValue(Value::Long(2))));
|
assert_eq!(ast.offset, Some(Expr::SQLValue(Value::Long(2))));
|
||||||
match ast.body {
|
match ast.body {
|
||||||
SQLSetExpr::Select(s) => match only(s.from).relation {
|
SQLSetExpr::Select(s) => match only(s.from).relation {
|
||||||
TableFactor::Derived { subquery, .. } => {
|
TableFactor::Derived { subquery, .. } => {
|
||||||
assert_eq!(subquery.offset, Some(ASTNode::SQLValue(Value::Long(2))));
|
assert_eq!(subquery.offset, Some(Expr::SQLValue(Value::Long(2))));
|
||||||
}
|
}
|
||||||
_ => panic!("Test broke"),
|
_ => panic!("Test broke"),
|
||||||
},
|
},
|
||||||
_ => panic!("Test broke"),
|
_ => panic!("Test broke"),
|
||||||
}
|
}
|
||||||
let ast = verified_query("SELECT 'foo' OFFSET 0 ROWS");
|
let ast = verified_query("SELECT 'foo' OFFSET 0 ROWS");
|
||||||
assert_eq!(ast.offset, Some(ASTNode::SQLValue(Value::Long(0))));
|
assert_eq!(ast.offset, Some(Expr::SQLValue(Value::Long(0))));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2243,7 +2239,7 @@ fn parse_fetch() {
|
||||||
const FETCH_FIRST_TWO_ROWS_ONLY: Fetch = Fetch {
|
const FETCH_FIRST_TWO_ROWS_ONLY: Fetch = Fetch {
|
||||||
with_ties: false,
|
with_ties: false,
|
||||||
percent: false,
|
percent: false,
|
||||||
quantity: Some(ASTNode::SQLValue(Value::Long(2))),
|
quantity: Some(Expr::SQLValue(Value::Long(2))),
|
||||||
};
|
};
|
||||||
let ast = verified_query("SELECT foo FROM bar FETCH FIRST 2 ROWS ONLY");
|
let ast = verified_query("SELECT foo FROM bar FETCH FIRST 2 ROWS ONLY");
|
||||||
assert_eq!(ast.fetch, Some(FETCH_FIRST_TWO_ROWS_ONLY));
|
assert_eq!(ast.fetch, Some(FETCH_FIRST_TWO_ROWS_ONLY));
|
||||||
|
@ -2270,7 +2266,7 @@ fn parse_fetch() {
|
||||||
Some(Fetch {
|
Some(Fetch {
|
||||||
with_ties: true,
|
with_ties: true,
|
||||||
percent: false,
|
percent: false,
|
||||||
quantity: Some(ASTNode::SQLValue(Value::Long(2))),
|
quantity: Some(Expr::SQLValue(Value::Long(2))),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
let ast = verified_query("SELECT foo FROM bar FETCH FIRST 50 PERCENT ROWS ONLY");
|
let ast = verified_query("SELECT foo FROM bar FETCH FIRST 50 PERCENT ROWS ONLY");
|
||||||
|
@ -2279,13 +2275,13 @@ fn parse_fetch() {
|
||||||
Some(Fetch {
|
Some(Fetch {
|
||||||
with_ties: false,
|
with_ties: false,
|
||||||
percent: true,
|
percent: true,
|
||||||
quantity: Some(ASTNode::SQLValue(Value::Long(50))),
|
quantity: Some(Expr::SQLValue(Value::Long(50))),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
let ast = verified_query(
|
let ast = verified_query(
|
||||||
"SELECT foo FROM bar WHERE foo = 4 ORDER BY baz OFFSET 2 ROWS FETCH FIRST 2 ROWS ONLY",
|
"SELECT foo FROM bar WHERE foo = 4 ORDER BY baz OFFSET 2 ROWS FETCH FIRST 2 ROWS ONLY",
|
||||||
);
|
);
|
||||||
assert_eq!(ast.offset, Some(ASTNode::SQLValue(Value::Long(2))));
|
assert_eq!(ast.offset, Some(Expr::SQLValue(Value::Long(2))));
|
||||||
assert_eq!(ast.fetch, Some(FETCH_FIRST_TWO_ROWS_ONLY));
|
assert_eq!(ast.fetch, Some(FETCH_FIRST_TWO_ROWS_ONLY));
|
||||||
let ast = verified_query(
|
let ast = verified_query(
|
||||||
"SELECT foo FROM (SELECT * FROM bar FETCH FIRST 2 ROWS ONLY) FETCH FIRST 2 ROWS ONLY",
|
"SELECT foo FROM (SELECT * FROM bar FETCH FIRST 2 ROWS ONLY) FETCH FIRST 2 ROWS ONLY",
|
||||||
|
@ -2301,12 +2297,12 @@ fn parse_fetch() {
|
||||||
_ => panic!("Test broke"),
|
_ => panic!("Test broke"),
|
||||||
}
|
}
|
||||||
let ast = verified_query("SELECT foo FROM (SELECT * FROM bar OFFSET 2 ROWS FETCH FIRST 2 ROWS ONLY) OFFSET 2 ROWS FETCH FIRST 2 ROWS ONLY");
|
let ast = verified_query("SELECT foo FROM (SELECT * FROM bar OFFSET 2 ROWS FETCH FIRST 2 ROWS ONLY) OFFSET 2 ROWS FETCH FIRST 2 ROWS ONLY");
|
||||||
assert_eq!(ast.offset, Some(ASTNode::SQLValue(Value::Long(2))));
|
assert_eq!(ast.offset, Some(Expr::SQLValue(Value::Long(2))));
|
||||||
assert_eq!(ast.fetch, Some(FETCH_FIRST_TWO_ROWS_ONLY));
|
assert_eq!(ast.fetch, Some(FETCH_FIRST_TWO_ROWS_ONLY));
|
||||||
match ast.body {
|
match ast.body {
|
||||||
SQLSetExpr::Select(s) => match only(s.from).relation {
|
SQLSetExpr::Select(s) => match only(s.from).relation {
|
||||||
TableFactor::Derived { subquery, .. } => {
|
TableFactor::Derived { subquery, .. } => {
|
||||||
assert_eq!(subquery.offset, Some(ASTNode::SQLValue(Value::Long(2))));
|
assert_eq!(subquery.offset, Some(Expr::SQLValue(Value::Long(2))));
|
||||||
assert_eq!(subquery.fetch, Some(FETCH_FIRST_TWO_ROWS_ONLY));
|
assert_eq!(subquery.fetch, Some(FETCH_FIRST_TWO_ROWS_ONLY));
|
||||||
}
|
}
|
||||||
_ => panic!("Test broke"),
|
_ => panic!("Test broke"),
|
||||||
|
@ -2354,7 +2350,7 @@ fn lateral_derived() {
|
||||||
let join = &from.joins[0];
|
let join = &from.joins[0];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
join.join_operator,
|
join.join_operator,
|
||||||
JoinOperator::LeftOuter(JoinConstraint::On(ASTNode::SQLValue(Value::Boolean(true))))
|
JoinOperator::LeftOuter(JoinConstraint::On(Expr::SQLValue(Value::Boolean(true))))
|
||||||
);
|
);
|
||||||
if let TableFactor::Derived {
|
if let TableFactor::Derived {
|
||||||
lateral,
|
lateral,
|
||||||
|
@ -2545,6 +2541,6 @@ fn verified_only_select(query: &str) -> SQLSelect {
|
||||||
all_dialects().verified_only_select(query)
|
all_dialects().verified_only_select(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verified_expr(query: &str) -> ASTNode {
|
fn verified_expr(query: &str) -> Expr {
|
||||||
all_dialects().verified_expr(query)
|
all_dialects().verified_expr(query)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,11 @@ fn parse_mssql_identifiers() {
|
||||||
let sql = "SELECT @@version, _foo$123 FROM ##temp";
|
let sql = "SELECT @@version, _foo$123 FROM ##temp";
|
||||||
let select = ms_and_generic().verified_only_select(sql);
|
let select = ms_and_generic().verified_only_select(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLIdentifier("@@version".to_string()),
|
&Expr::SQLIdentifier("@@version".to_string()),
|
||||||
expr_from_projection(&select.projection[0]),
|
expr_from_projection(&select.projection[0]),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLIdentifier("_foo$123".to_string()),
|
&Expr::SQLIdentifier("_foo$123".to_string()),
|
||||||
expr_from_projection(&select.projection[1]),
|
expr_from_projection(&select.projection[1]),
|
||||||
);
|
);
|
||||||
assert_eq!(2, select.projection.len());
|
assert_eq!(2, select.projection.len());
|
||||||
|
|
|
@ -106,9 +106,7 @@ fn parse_create_table_with_defaults() {
|
||||||
options: vec![
|
options: vec![
|
||||||
ColumnOptionDef {
|
ColumnOptionDef {
|
||||||
name: None,
|
name: None,
|
||||||
option: ColumnOption::Default(ASTNode::SQLValue(Value::Boolean(
|
option: ColumnOption::Default(Expr::SQLValue(Value::Boolean(true))),
|
||||||
true
|
|
||||||
))),
|
|
||||||
},
|
},
|
||||||
ColumnOptionDef {
|
ColumnOptionDef {
|
||||||
name: None,
|
name: None,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue