Rename ASTNode to Expr

The ASTNode enum was confusingly named. In the past, the name made
sense, as the enum contained nearly all of the nodes in the AST, but
over time, pieces have been split into different structs, like
SQLStatement and SQLQuery. The ASTNode enum now contains only contains
expression nodes, so Expr is a better name.

Also rename the UnnamedExpression and ExpressionWithAlias variants
of SQLSelectItem to UnnamedExpr and ExprWithAlias, respectively, to
match the new shorthand for the word "expression".
This commit is contained in:
Nikhil Benesch 2019-06-04 13:56:37 -04:00
parent e6b26330df
commit 646d1e13ca
No known key found for this signature in database
GPG key ID: F7386C5DEADABA7F
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,
@ -361,7 +361,7 @@ pub enum JoinOperator {
#[derive(Debug, Clone, PartialEq, Hash)]
pub enum JoinConstraint {
On(ASTNode),
On(Expr),
Using(Vec<SQLIdent>),
Natural,
}
@ -369,7 +369,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>,
}
@ -387,7 +387,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 {
@ -408,7 +408,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> {
@ -1826,8 +1826,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) {
@ -1837,7 +1837,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 {
@ -1852,18 +1852,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));
}
}
@ -1897,20 +1897,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,