Merge pull request #119 from andygrove/astnode-expr

Rename ASTNode to Expr
This commit is contained in:
Nikhil Benesch 2019-06-19 21:45:49 -04:00 committed by GitHub
commit 5b23ad1d4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 255 additions and 264 deletions

View file

@ -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 {

View file

@ -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,

View file

@ -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 {

View file

@ -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)
}

View file

@ -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"),
}
}

View file

@ -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)
}

View file

@ -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());

View file

@ -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,