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