mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 15:04:04 +00:00
Turn type Ident into struct Ident
The Ident type was previously an alias for a String. Turn it into a full fledged struct, so that the parser can preserve the distinction between identifier value and quote style already made by the tokenizer's Word structure.
This commit is contained in:
parent
9b2287f14c
commit
b1cbc55128
6 changed files with 160 additions and 88 deletions
|
@ -68,8 +68,61 @@ where
|
|||
DisplaySeparated { slice, sep: ", " }
|
||||
}
|
||||
|
||||
/// Identifier name, in the originally quoted form (e.g. `"id"`)
|
||||
pub type Ident = String;
|
||||
/// An identifier, decomposed into its value or character data and the quote style.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Ident {
|
||||
/// The value of the identifier without quotes.
|
||||
pub value: String,
|
||||
/// The starting quote if any. Valid quote characters are the single quote,
|
||||
/// double quote, backtick, and opening square bracket.
|
||||
pub quote_style: Option<char>,
|
||||
}
|
||||
|
||||
impl Ident {
|
||||
/// Create a new identifier with the given value and no quotes.
|
||||
pub fn new<S>(value: S) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
{
|
||||
Ident {
|
||||
value: value.into(),
|
||||
quote_style: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new quoted identifier with the given quote and value. This function
|
||||
/// panics if the given quote is not a valid quote character.
|
||||
pub fn with_quote<S>(quote: char, value: S) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
{
|
||||
assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
|
||||
Ident {
|
||||
value: value.into(),
|
||||
quote_style: Some(quote),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Ident {
|
||||
fn from(value: &str) -> Self {
|
||||
Ident {
|
||||
value: value.to_string(),
|
||||
quote_style: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Ident {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.quote_style {
|
||||
Some(q) if q == '"' || q == '\'' || q == '`' => write!(f, "{}{}{}", q, self.value, q),
|
||||
Some(q) if q == '[' => write!(f, "[{}]", self.value),
|
||||
None => f.write_str(&self.value),
|
||||
_ => panic!("unexpected quote style"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -175,7 +228,7 @@ pub enum Expr {
|
|||
impl fmt::Display for Expr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Expr::Identifier(s) => f.write_str(s),
|
||||
Expr::Identifier(s) => write!(f, "{}", s),
|
||||
Expr::Wildcard => f.write_str("*"),
|
||||
Expr::QualifiedWildcard(q) => write!(f, "{}.*", display_separated(q, ".")),
|
||||
Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
|
||||
|
@ -864,7 +917,7 @@ impl fmt::Display for SetVariableValue {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use SetVariableValue::*;
|
||||
match self {
|
||||
Ident(ident) => f.write_str(ident),
|
||||
Ident(ident) => write!(f, "{}", ident),
|
||||
Literal(literal) => write!(f, "{}", literal),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,11 +201,11 @@ impl Parser {
|
|||
// identifier, a function call, or a simple identifier:
|
||||
_ => match self.peek_token() {
|
||||
Some(Token::LParen) | Some(Token::Period) => {
|
||||
let mut id_parts: Vec<Ident> = vec![w.as_ident()];
|
||||
let mut id_parts: Vec<Ident> = vec![w.to_ident()];
|
||||
let mut ends_with_wildcard = false;
|
||||
while self.consume_token(&Token::Period) {
|
||||
match self.next_token() {
|
||||
Some(Token::Word(w)) => id_parts.push(w.as_ident()),
|
||||
Some(Token::Word(w)) => id_parts.push(w.to_ident()),
|
||||
Some(Token::Mult) => {
|
||||
ends_with_wildcard = true;
|
||||
break;
|
||||
|
@ -225,7 +225,7 @@ impl Parser {
|
|||
Ok(Expr::CompoundIdentifier(id_parts))
|
||||
}
|
||||
}
|
||||
_ => Ok(Expr::Identifier(w.as_ident())),
|
||||
_ => Ok(Expr::Identifier(w.to_ident())),
|
||||
},
|
||||
}, // End of Token::Word
|
||||
Token::Mult => Ok(Expr::Wildcard),
|
||||
|
@ -871,7 +871,7 @@ impl Parser {
|
|||
let table_name = self.parse_object_name()?;
|
||||
let (columns, constraints) = self.parse_columns()?;
|
||||
self.expect_keywords(&["STORED", "AS"])?;
|
||||
let file_format = self.parse_identifier()?.parse::<FileFormat>()?;
|
||||
let file_format = self.parse_identifier()?.value.parse::<FileFormat>()?;
|
||||
|
||||
self.expect_keyword("LOCATION")?;
|
||||
let location = self.parse_literal_string()?;
|
||||
|
@ -976,7 +976,7 @@ impl Parser {
|
|||
}
|
||||
|
||||
columns.push(ColumnDef {
|
||||
name: column_name.as_ident(),
|
||||
name: column_name.to_ident(),
|
||||
data_type,
|
||||
collation,
|
||||
options,
|
||||
|
@ -1318,11 +1318,11 @@ impl Parser {
|
|||
Some(Token::Word(ref w))
|
||||
if after_as || !reserved_kwds.contains(&w.keyword.as_str()) =>
|
||||
{
|
||||
Ok(Some(w.as_ident()))
|
||||
Ok(Some(w.to_ident()))
|
||||
}
|
||||
// MSSQL supports single-quoted strings as aliases for columns
|
||||
// We accept them as table aliases too, although MSSQL does not.
|
||||
Some(Token::SingleQuotedString(ref s)) => Ok(Some(format!("'{}'", s))),
|
||||
Some(Token::SingleQuotedString(ref s)) => Ok(Some(Ident::with_quote('\'', s.clone()))),
|
||||
not_an_ident => {
|
||||
if after_as {
|
||||
return self.expected("an identifier after AS", not_an_ident);
|
||||
|
@ -1366,7 +1366,7 @@ impl Parser {
|
|||
/// Parse a simple one-word identifier (possibly quoted, possibly a keyword)
|
||||
pub fn parse_identifier(&mut self) -> Result<Ident, ParserError> {
|
||||
match self.next_token() {
|
||||
Some(Token::Word(w)) => Ok(w.as_ident()),
|
||||
Some(Token::Word(w)) => Ok(w.to_ident()),
|
||||
unexpected => self.expected("identifier", unexpected),
|
||||
}
|
||||
}
|
||||
|
@ -1609,7 +1609,7 @@ impl Parser {
|
|||
let token = self.peek_token();
|
||||
let value = match (self.parse_value(), token) {
|
||||
(Ok(value), _) => SetVariableValue::Literal(value),
|
||||
(Err(_), Some(Token::Word(ident))) => SetVariableValue::Ident(ident.as_ident()),
|
||||
(Err(_), Some(Token::Word(ident))) => SetVariableValue::Ident(ident.to_ident()),
|
||||
(Err(_), other) => self.expected("variable value", other)?,
|
||||
};
|
||||
Ok(Statement::SetVariable {
|
||||
|
@ -1617,7 +1617,7 @@ impl Parser {
|
|||
variable,
|
||||
value,
|
||||
})
|
||||
} else if variable == "TRANSACTION" && modifier.is_none() {
|
||||
} else if variable.value == "TRANSACTION" && modifier.is_none() {
|
||||
Ok(Statement::SetTransaction {
|
||||
modes: self.parse_transaction_modes()?,
|
||||
})
|
||||
|
@ -2066,8 +2066,11 @@ impl Parser {
|
|||
}
|
||||
|
||||
impl Word {
|
||||
pub fn as_ident(&self) -> Ident {
|
||||
self.to_string()
|
||||
pub fn to_ident(&self) -> Ident {
|
||||
Ident {
|
||||
value: self.value.clone(),
|
||||
quote_style: self.quote_style,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,10 @@ fn parse_insert_values() {
|
|||
..
|
||||
} => {
|
||||
assert_eq!(table_name.to_string(), expected_table_name);
|
||||
assert_eq!(columns, expected_columns);
|
||||
assert_eq!(columns.len(), expected_columns.len());
|
||||
for (index, column) in columns.iter().enumerate() {
|
||||
assert_eq!(column, &Ident::new(expected_columns[index].clone()));
|
||||
}
|
||||
match &source.body {
|
||||
SetExpr::Values(Values(values)) => assert_eq!(values.as_slice(), expected_rows),
|
||||
_ => unreachable!(),
|
||||
|
@ -158,7 +161,10 @@ fn parse_delete_statement() {
|
|||
let sql = "DELETE FROM \"table\"";
|
||||
match verified_stmt(sql) {
|
||||
Statement::Delete { table_name, .. } => {
|
||||
assert_eq!(ObjectName(vec!["\"table\"".to_string()]), table_name);
|
||||
assert_eq!(
|
||||
ObjectName(vec![Ident::with_quote('"', "table")]),
|
||||
table_name
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -175,11 +181,11 @@ fn parse_where_delete_statement() {
|
|||
selection,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(ObjectName(vec!["foo".to_string()]), table_name);
|
||||
assert_eq!(ObjectName(vec![Ident::new("foo")]), table_name);
|
||||
|
||||
assert_eq!(
|
||||
Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier("name".to_string())),
|
||||
left: Box::new(Expr::Identifier(Ident::new("name"))),
|
||||
op: Eq,
|
||||
right: Box::new(Expr::Value(number("5"))),
|
||||
},
|
||||
|
@ -224,7 +230,7 @@ fn parse_select_distinct() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(true, select.distinct);
|
||||
assert_eq!(
|
||||
&SelectItem::UnnamedExpr(Expr::Identifier("name".to_string())),
|
||||
&SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name"))),
|
||||
only(&select.projection)
|
||||
);
|
||||
}
|
||||
|
@ -252,7 +258,7 @@ fn parse_select_wildcard() {
|
|||
let sql = "SELECT foo.* FROM foo";
|
||||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
&SelectItem::QualifiedWildcard(ObjectName(vec!["foo".to_string()])),
|
||||
&SelectItem::QualifiedWildcard(ObjectName(vec![Ident::new("foo")])),
|
||||
only(&select.projection)
|
||||
);
|
||||
|
||||
|
@ -260,8 +266,8 @@ fn parse_select_wildcard() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
&SelectItem::QualifiedWildcard(ObjectName(vec![
|
||||
"myschema".to_string(),
|
||||
"mytable".to_string(),
|
||||
Ident::new("myschema"),
|
||||
Ident::new("mytable"),
|
||||
])),
|
||||
only(&select.projection)
|
||||
);
|
||||
|
@ -287,7 +293,7 @@ fn parse_column_aliases() {
|
|||
{
|
||||
assert_eq!(&BinaryOperator::Plus, op);
|
||||
assert_eq!(&Expr::Value(number("1")), right.as_ref());
|
||||
assert_eq!("newname", alias);
|
||||
assert_eq!(&Ident::new("newname"), alias);
|
||||
} else {
|
||||
panic!("Expected ExprWithAlias")
|
||||
}
|
||||
|
@ -317,7 +323,7 @@ fn parse_select_count_wildcard() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec!["COUNT".to_string()]),
|
||||
name: ObjectName(vec![Ident::new("COUNT")]),
|
||||
args: vec![Expr::Wildcard],
|
||||
over: None,
|
||||
distinct: false,
|
||||
|
@ -332,10 +338,10 @@ fn parse_select_count_distinct() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec!["COUNT".to_string()]),
|
||||
name: ObjectName(vec![Ident::new("COUNT")]),
|
||||
args: vec![Expr::UnaryOp {
|
||||
op: UnaryOperator::Plus,
|
||||
expr: Box::new(Expr::Identifier("x".to_string()))
|
||||
expr: Box::new(Expr::Identifier(Ident::new("x")))
|
||||
}],
|
||||
over: None,
|
||||
distinct: true,
|
||||
|
@ -416,7 +422,7 @@ fn parse_escaped_single_quote_string_predicate() {
|
|||
let ast = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
Some(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier("salary".to_string())),
|
||||
left: Box::new(Expr::Identifier(Ident::new("salary"))),
|
||||
op: NotEq,
|
||||
right: Box::new(Expr::Value(Value::SingleQuotedString(
|
||||
"Jim's salary".to_string()
|
||||
|
@ -447,12 +453,12 @@ fn parse_compound_expr_1() {
|
|||
let sql = "a + b * c";
|
||||
assert_eq!(
|
||||
BinaryOp {
|
||||
left: Box::new(Identifier("a".to_string())),
|
||||
left: Box::new(Identifier(Ident::new("a"))),
|
||||
op: Plus,
|
||||
right: Box::new(BinaryOp {
|
||||
left: Box::new(Identifier("b".to_string())),
|
||||
left: Box::new(Identifier(Ident::new("b"))),
|
||||
op: Multiply,
|
||||
right: Box::new(Identifier("c".to_string()))
|
||||
right: Box::new(Identifier(Ident::new("c")))
|
||||
})
|
||||
},
|
||||
verified_expr(sql)
|
||||
|
@ -467,12 +473,12 @@ fn parse_compound_expr_2() {
|
|||
assert_eq!(
|
||||
BinaryOp {
|
||||
left: Box::new(BinaryOp {
|
||||
left: Box::new(Identifier("a".to_string())),
|
||||
left: Box::new(Identifier(Ident::new("a"))),
|
||||
op: Multiply,
|
||||
right: Box::new(Identifier("b".to_string()))
|
||||
right: Box::new(Identifier(Ident::new("b")))
|
||||
}),
|
||||
op: Plus,
|
||||
right: Box::new(Identifier("c".to_string()))
|
||||
right: Box::new(Identifier(Ident::new("c")))
|
||||
},
|
||||
verified_expr(sql)
|
||||
);
|
||||
|
@ -486,12 +492,12 @@ fn parse_unary_math() {
|
|||
BinaryOp {
|
||||
left: Box::new(UnaryOp {
|
||||
op: UnaryOperator::Minus,
|
||||
expr: Box::new(Identifier("a".to_string())),
|
||||
expr: Box::new(Identifier(Ident::new("a"))),
|
||||
}),
|
||||
op: BinaryOperator::Plus,
|
||||
right: Box::new(UnaryOp {
|
||||
op: UnaryOperator::Minus,
|
||||
expr: Box::new(Identifier("b".to_string())),
|
||||
expr: Box::new(Identifier(Ident::new("b"))),
|
||||
}),
|
||||
},
|
||||
verified_expr(sql)
|
||||
|
@ -503,7 +509,7 @@ fn parse_is_null() {
|
|||
use self::Expr::*;
|
||||
let sql = "a IS NULL";
|
||||
assert_eq!(
|
||||
IsNull(Box::new(Identifier("a".to_string()))),
|
||||
IsNull(Box::new(Identifier(Ident::new("a")))),
|
||||
verified_expr(sql)
|
||||
);
|
||||
}
|
||||
|
@ -513,7 +519,7 @@ fn parse_is_not_null() {
|
|||
use self::Expr::*;
|
||||
let sql = "a IS NOT NULL";
|
||||
assert_eq!(
|
||||
IsNotNull(Box::new(Identifier("a".to_string()))),
|
||||
IsNotNull(Box::new(Identifier(Ident::new("a")))),
|
||||
verified_expr(sql)
|
||||
);
|
||||
}
|
||||
|
@ -588,7 +594,7 @@ fn parse_like() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier("name".to_string())),
|
||||
left: Box::new(Expr::Identifier(Ident::new("name"))),
|
||||
op: if negated {
|
||||
BinaryOperator::NotLike
|
||||
} else {
|
||||
|
@ -608,7 +614,7 @@ fn parse_like() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
Expr::IsNull(Box::new(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier("name".to_string())),
|
||||
left: Box::new(Expr::Identifier(Ident::new("name"))),
|
||||
op: if negated {
|
||||
BinaryOperator::NotLike
|
||||
} else {
|
||||
|
@ -633,7 +639,7 @@ fn parse_in_list() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
Expr::InList {
|
||||
expr: Box::new(Expr::Identifier("segment".to_string())),
|
||||
expr: Box::new(Expr::Identifier(Ident::new("segment"))),
|
||||
list: vec![
|
||||
Expr::Value(Value::SingleQuotedString("HIGH".to_string())),
|
||||
Expr::Value(Value::SingleQuotedString("MED".to_string())),
|
||||
|
@ -653,7 +659,7 @@ fn parse_in_subquery() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
Expr::InSubquery {
|
||||
expr: Box::new(Expr::Identifier("segment".to_string())),
|
||||
expr: Box::new(Expr::Identifier(Ident::new("segment"))),
|
||||
subquery: Box::new(verified_query("SELECT segm FROM bar")),
|
||||
negated: false,
|
||||
},
|
||||
|
@ -671,7 +677,7 @@ fn parse_between() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
Expr::Between {
|
||||
expr: Box::new(Expr::Identifier("age".to_string())),
|
||||
expr: Box::new(Expr::Identifier(Ident::new("age"))),
|
||||
low: Box::new(Expr::Value(number("25"))),
|
||||
high: Box::new(Expr::Value(number("32"))),
|
||||
negated,
|
||||
|
@ -720,7 +726,7 @@ fn parse_between_with_expr() {
|
|||
expr: Box::new(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Value(number("1"))),
|
||||
op: BinaryOperator::Plus,
|
||||
right: Box::new(Expr::Identifier("x".to_string())),
|
||||
right: Box::new(Expr::Identifier(Ident::new("x"))),
|
||||
}),
|
||||
low: Box::new(Expr::Value(number("1"))),
|
||||
high: Box::new(Expr::Value(number("2"))),
|
||||
|
@ -738,15 +744,15 @@ fn parse_select_order_by() {
|
|||
assert_eq!(
|
||||
vec![
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier("lname".to_string()),
|
||||
expr: Expr::Identifier(Ident::new("lname")),
|
||||
asc: Some(true),
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier("fname".to_string()),
|
||||
expr: Expr::Identifier(Ident::new("fname")),
|
||||
asc: Some(false),
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier("id".to_string()),
|
||||
expr: Expr::Identifier(Ident::new("id")),
|
||||
asc: None,
|
||||
},
|
||||
],
|
||||
|
@ -767,11 +773,11 @@ fn parse_select_order_by_limit() {
|
|||
assert_eq!(
|
||||
vec![
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier("lname".to_string()),
|
||||
expr: Expr::Identifier(Ident::new("lname")),
|
||||
asc: Some(true),
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier("fname".to_string()),
|
||||
expr: Expr::Identifier(Ident::new("fname")),
|
||||
asc: Some(false),
|
||||
},
|
||||
],
|
||||
|
@ -786,8 +792,8 @@ fn parse_select_group_by() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
vec![
|
||||
Expr::Identifier("lname".to_string()),
|
||||
Expr::Identifier("fname".to_string()),
|
||||
Expr::Identifier(Ident::new("lname")),
|
||||
Expr::Identifier(Ident::new("fname")),
|
||||
],
|
||||
select.group_by
|
||||
);
|
||||
|
@ -800,7 +806,7 @@ fn parse_select_having() {
|
|||
assert_eq!(
|
||||
Some(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Function(Function {
|
||||
name: ObjectName(vec!["COUNT".to_string()]),
|
||||
name: ObjectName(vec![Ident::new("COUNT")]),
|
||||
args: vec![Expr::Wildcard],
|
||||
over: None,
|
||||
distinct: false
|
||||
|
@ -830,7 +836,7 @@ fn parse_cast() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
&Expr::Cast {
|
||||
expr: Box::new(Expr::Identifier("id".to_string())),
|
||||
expr: Box::new(Expr::Identifier(Ident::new("id"))),
|
||||
data_type: DataType::BigInt
|
||||
},
|
||||
expr_from_projection(only(&select.projection))
|
||||
|
@ -860,7 +866,7 @@ fn parse_extract() {
|
|||
assert_eq!(
|
||||
&Expr::Extract {
|
||||
field: DateTimeField::Year,
|
||||
expr: Box::new(Expr::Identifier("d".to_string())),
|
||||
expr: Box::new(Expr::Identifier(Ident::new("d"))),
|
||||
},
|
||||
expr_from_projection(only(&select.projection)),
|
||||
);
|
||||
|
@ -1146,8 +1152,8 @@ fn parse_scalar_function_in_projection() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec!["sqrt".to_string()]),
|
||||
args: vec![Expr::Identifier("id".to_string())],
|
||||
name: ObjectName(vec![Ident::new("sqrt")]),
|
||||
args: vec![Expr::Identifier(Ident::new("id"))],
|
||||
over: None,
|
||||
distinct: false,
|
||||
}),
|
||||
|
@ -1169,12 +1175,12 @@ fn parse_window_functions() {
|
|||
assert_eq!(4, select.projection.len());
|
||||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec!["row_number".to_string()]),
|
||||
name: ObjectName(vec![Ident::new("row_number")]),
|
||||
args: vec![],
|
||||
over: Some(WindowSpec {
|
||||
partition_by: vec![],
|
||||
order_by: vec![OrderByExpr {
|
||||
expr: Expr::Identifier("dt".to_string()),
|
||||
expr: Expr::Identifier(Ident::new("dt")),
|
||||
asc: Some(false)
|
||||
}],
|
||||
window_frame: None,
|
||||
|
@ -1380,8 +1386,8 @@ fn parse_delimited_identifiers() {
|
|||
args,
|
||||
with_hints,
|
||||
} => {
|
||||
assert_eq!(vec![r#""a table""#.to_string()], name.0);
|
||||
assert_eq!(r#""alias""#, alias.unwrap().name);
|
||||
assert_eq!(vec![Ident::with_quote('"', "a table")], name.0);
|
||||
assert_eq!(Ident::with_quote('"', "alias"), alias.unwrap().name);
|
||||
assert!(args.is_empty());
|
||||
assert!(with_hints.is_empty());
|
||||
}
|
||||
|
@ -1390,12 +1396,15 @@ fn parse_delimited_identifiers() {
|
|||
// check SELECT
|
||||
assert_eq!(3, select.projection.len());
|
||||
assert_eq!(
|
||||
&Expr::CompoundIdentifier(vec![r#""alias""#.to_string(), r#""bar baz""#.to_string()]),
|
||||
&Expr::CompoundIdentifier(vec![
|
||||
Ident::with_quote('"', "alias"),
|
||||
Ident::with_quote('"', "bar baz")
|
||||
]),
|
||||
expr_from_projection(&select.projection[0]),
|
||||
);
|
||||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec![r#""myfun""#.to_string()]),
|
||||
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
||||
args: vec![],
|
||||
over: None,
|
||||
distinct: false,
|
||||
|
@ -1404,8 +1413,8 @@ fn parse_delimited_identifiers() {
|
|||
);
|
||||
match &select.projection[2] {
|
||||
SelectItem::ExprWithAlias { expr, alias } => {
|
||||
assert_eq!(&Expr::Identifier(r#""simple id""#.to_string()), expr);
|
||||
assert_eq!(r#""column alias""#, alias);
|
||||
assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr);
|
||||
assert_eq!(&Ident::with_quote('"', "column alias"), alias);
|
||||
}
|
||||
_ => panic!("Expected ExprWithAlias"),
|
||||
}
|
||||
|
@ -1423,15 +1432,15 @@ fn parse_parens() {
|
|||
assert_eq!(
|
||||
BinaryOp {
|
||||
left: Box::new(Nested(Box::new(BinaryOp {
|
||||
left: Box::new(Identifier("a".to_string())),
|
||||
left: Box::new(Identifier(Ident::new("a"))),
|
||||
op: Plus,
|
||||
right: Box::new(Identifier("b".to_string()))
|
||||
right: Box::new(Identifier(Ident::new("b")))
|
||||
}))),
|
||||
op: Minus,
|
||||
right: Box::new(Nested(Box::new(BinaryOp {
|
||||
left: Box::new(Identifier("c".to_string())),
|
||||
left: Box::new(Identifier(Ident::new("c"))),
|
||||
op: Plus,
|
||||
right: Box::new(Identifier("d".to_string()))
|
||||
right: Box::new(Identifier(Ident::new("d")))
|
||||
})))
|
||||
},
|
||||
verified_expr(sql)
|
||||
|
@ -1448,14 +1457,14 @@ fn parse_searched_case_expr() {
|
|||
&Case {
|
||||
operand: None,
|
||||
conditions: vec![
|
||||
IsNull(Box::new(Identifier("bar".to_string()))),
|
||||
IsNull(Box::new(Identifier(Ident::new("bar")))),
|
||||
BinaryOp {
|
||||
left: Box::new(Identifier("bar".to_string())),
|
||||
left: Box::new(Identifier(Ident::new("bar"))),
|
||||
op: Eq,
|
||||
right: Box::new(Expr::Value(number("0")))
|
||||
},
|
||||
BinaryOp {
|
||||
left: Box::new(Identifier("bar".to_string())),
|
||||
left: Box::new(Identifier(Ident::new("bar"))),
|
||||
op: GtEq,
|
||||
right: Box::new(Expr::Value(number("0")))
|
||||
}
|
||||
|
@ -1481,7 +1490,7 @@ fn parse_simple_case_expr() {
|
|||
use self::Expr::{Case, Identifier};
|
||||
assert_eq!(
|
||||
&Case {
|
||||
operand: Some(Box::new(Identifier("foo".to_string()))),
|
||||
operand: Some(Box::new(Identifier(Ident::new("foo")))),
|
||||
conditions: vec![Expr::Value(number("1"))],
|
||||
results: vec![Expr::Value(Value::SingleQuotedString("Y".to_string())),],
|
||||
else_result: Some(Box::new(Expr::Value(Value::SingleQuotedString(
|
||||
|
@ -1576,7 +1585,7 @@ fn parse_cross_join() {
|
|||
assert_eq!(
|
||||
Join {
|
||||
relation: TableFactor::Table {
|
||||
name: ObjectName(vec!["t2".to_string()]),
|
||||
name: ObjectName(vec![Ident::new("t2")]),
|
||||
alias: None,
|
||||
args: vec![],
|
||||
with_hints: vec![],
|
||||
|
@ -1589,7 +1598,7 @@ fn parse_cross_join() {
|
|||
|
||||
fn table_alias(name: impl Into<String>) -> Option<TableAlias> {
|
||||
Some(TableAlias {
|
||||
name: name.into(),
|
||||
name: Ident::new(name),
|
||||
columns: vec![],
|
||||
})
|
||||
}
|
||||
|
@ -1603,7 +1612,7 @@ fn parse_joins_on() {
|
|||
) -> Join {
|
||||
Join {
|
||||
relation: TableFactor::Table {
|
||||
name: ObjectName(vec![relation.into()]),
|
||||
name: ObjectName(vec![Ident::new(relation.into())]),
|
||||
alias,
|
||||
args: vec![],
|
||||
with_hints: vec![],
|
||||
|
@ -1656,7 +1665,7 @@ fn parse_joins_using() {
|
|||
) -> Join {
|
||||
Join {
|
||||
relation: TableFactor::Table {
|
||||
name: ObjectName(vec![relation.into()]),
|
||||
name: ObjectName(vec![Ident::new(relation.into())]),
|
||||
alias,
|
||||
args: vec![],
|
||||
with_hints: vec![],
|
||||
|
@ -1701,7 +1710,7 @@ fn parse_natural_join() {
|
|||
fn natural_join(f: impl Fn(JoinConstraint) -> JoinOperator) -> Join {
|
||||
Join {
|
||||
relation: TableFactor::Table {
|
||||
name: ObjectName(vec!["t2".to_string()]),
|
||||
name: ObjectName(vec![Ident::new("t2")]),
|
||||
alias: None,
|
||||
args: vec![],
|
||||
with_hints: vec![],
|
||||
|
@ -1743,7 +1752,7 @@ fn parse_complex_join() {
|
|||
fn parse_join_nesting() {
|
||||
fn table(name: impl Into<String>) -> TableFactor {
|
||||
TableFactor::Table {
|
||||
name: ObjectName(vec![name.into()]),
|
||||
name: ObjectName(vec![Ident::new(name.into())]),
|
||||
alias: None,
|
||||
args: vec![],
|
||||
with_hints: vec![],
|
||||
|
@ -1843,7 +1852,14 @@ fn parse_ctes() {
|
|||
for exp in expected {
|
||||
let Cte { alias, query } = &sel.ctes[i];
|
||||
assert_eq!(*exp, query.to_string());
|
||||
assert_eq!(if i == 0 { "a" } else { "b" }, alias.name);
|
||||
assert_eq!(
|
||||
if i == 0 {
|
||||
Ident::new("a")
|
||||
} else {
|
||||
Ident::new("b")
|
||||
},
|
||||
alias.name
|
||||
);
|
||||
assert!(alias.columns.is_empty());
|
||||
i += 1;
|
||||
}
|
||||
|
@ -1886,7 +1902,7 @@ fn parse_cte_renamed_columns() {
|
|||
let sql = "WITH cte (col1, col2) AS (SELECT foo, bar FROM baz) SELECT * FROM cte";
|
||||
let query = all_dialects().verified_query(sql);
|
||||
assert_eq!(
|
||||
vec!["col1", "col2"],
|
||||
vec![Ident::new("col1"), Ident::new("col2")],
|
||||
query.ctes.first().unwrap().alias.columns
|
||||
);
|
||||
}
|
||||
|
@ -2116,7 +2132,7 @@ fn parse_create_view_with_columns() {
|
|||
materialized,
|
||||
} => {
|
||||
assert_eq!("v", name.to_string());
|
||||
assert_eq!(columns, vec!["has".to_string(), "cols".to_string()]);
|
||||
assert_eq!(columns, vec![Ident::new("has"), Ident::new("cols")]);
|
||||
assert_eq!(with_options, vec![]);
|
||||
assert_eq!("SELECT 1, 2", query.to_string());
|
||||
assert!(!materialized);
|
||||
|
@ -2383,7 +2399,7 @@ fn lateral_derived() {
|
|||
} = join.relation
|
||||
{
|
||||
assert_eq!(lateral_in, lateral);
|
||||
assert_eq!("order".to_string(), alias.name);
|
||||
assert_eq!(Ident::new("order"), alias.name);
|
||||
assert_eq!(
|
||||
subquery.to_string(),
|
||||
"SELECT * FROM order WHERE order.customer = customer.id LIMIT 3"
|
||||
|
|
|
@ -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!(
|
||||
&Expr::Identifier("@@version".to_string()),
|
||||
&Expr::Identifier(Ident::new("@@version")),
|
||||
expr_from_projection(&select.projection[0]),
|
||||
);
|
||||
assert_eq!(
|
||||
&Expr::Identifier("_foo$123".to_string()),
|
||||
&Expr::Identifier(Ident::new("_foo$123")),
|
||||
expr_from_projection(&select.projection[1]),
|
||||
);
|
||||
assert_eq!(2, select.projection.len());
|
||||
|
|
|
@ -26,7 +26,7 @@ fn parse_identifiers() {
|
|||
|
||||
#[test]
|
||||
fn parse_show_columns() {
|
||||
let table_name = ObjectName(vec!["mytable".to_string()]);
|
||||
let table_name = ObjectName(vec![Ident::new("mytable")]);
|
||||
assert_eq!(
|
||||
mysql_and_generic().verified_stmt("SHOW COLUMNS FROM mytable"),
|
||||
Statement::ShowColumns {
|
||||
|
@ -41,7 +41,7 @@ fn parse_show_columns() {
|
|||
Statement::ShowColumns {
|
||||
extended: false,
|
||||
full: false,
|
||||
table_name: ObjectName(vec!["mydb".to_string(), "mytable".to_string()]),
|
||||
table_name: ObjectName(vec![Ident::new("mydb"), Ident::new("mytable")]),
|
||||
filter: None,
|
||||
}
|
||||
);
|
||||
|
|
|
@ -79,7 +79,7 @@ fn parse_create_table_with_defaults() {
|
|||
ColumnDef {
|
||||
name: "last_name".into(),
|
||||
data_type: DataType::Varchar(Some(45)),
|
||||
collation: Some(ObjectName(vec!["\"es_ES\"".into()])),
|
||||
collation: Some(ObjectName(vec![Ident::with_quote('"', "es_ES")])),
|
||||
options: vec![ColumnOptionDef {
|
||||
name: None,
|
||||
option: ColumnOption::NotNull,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue