mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-07 17:04:59 +00:00
Merge branch 'main' into solontsev/clickhouse-mergetree-fix
This commit is contained in:
commit
2163da3449
6 changed files with 82 additions and 33 deletions
|
@ -1709,7 +1709,7 @@ pub struct ColumnPolicyProperty {
|
|||
/// ```
|
||||
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
|
||||
pub with: bool,
|
||||
pub policy_name: Ident,
|
||||
pub policy_name: ObjectName,
|
||||
pub using_columns: Option<Vec<Ident>>,
|
||||
}
|
||||
|
||||
|
|
|
@ -809,7 +809,7 @@ pub enum Expr {
|
|||
any: bool,
|
||||
expr: Box<Expr>,
|
||||
pattern: Box<Expr>,
|
||||
escape_char: Option<String>,
|
||||
escape_char: Option<Value>,
|
||||
},
|
||||
/// `ILIKE` (case-insensitive `LIKE`)
|
||||
ILike {
|
||||
|
@ -819,14 +819,14 @@ pub enum Expr {
|
|||
any: bool,
|
||||
expr: Box<Expr>,
|
||||
pattern: Box<Expr>,
|
||||
escape_char: Option<String>,
|
||||
escape_char: Option<Value>,
|
||||
},
|
||||
/// SIMILAR TO regex
|
||||
SimilarTo {
|
||||
negated: bool,
|
||||
expr: Box<Expr>,
|
||||
pattern: Box<Expr>,
|
||||
escape_char: Option<String>,
|
||||
escape_char: Option<Value>,
|
||||
},
|
||||
/// MySQL: RLIKE regex or REGEXP regex
|
||||
RLike {
|
||||
|
@ -1488,7 +1488,7 @@ impl fmt::Display for Expr {
|
|||
} => match escape_char {
|
||||
Some(ch) => write!(
|
||||
f,
|
||||
"{} {}LIKE {}{} ESCAPE '{}'",
|
||||
"{} {}LIKE {}{} ESCAPE {}",
|
||||
expr,
|
||||
if *negated { "NOT " } else { "" },
|
||||
if *any { "ANY " } else { "" },
|
||||
|
@ -1513,7 +1513,7 @@ impl fmt::Display for Expr {
|
|||
} => match escape_char {
|
||||
Some(ch) => write!(
|
||||
f,
|
||||
"{} {}ILIKE {}{} ESCAPE '{}'",
|
||||
"{} {}ILIKE {}{} ESCAPE {}",
|
||||
expr,
|
||||
if *negated { "NOT " } else { "" },
|
||||
if *any { "ANY" } else { "" },
|
||||
|
@ -1568,7 +1568,7 @@ impl fmt::Display for Expr {
|
|||
} => match escape_char {
|
||||
Some(ch) => write!(
|
||||
f,
|
||||
"{} {}SIMILAR TO {} ESCAPE '{}'",
|
||||
"{} {}SIMILAR TO {} ESCAPE {}",
|
||||
expr,
|
||||
if *negated { "NOT " } else { "" },
|
||||
pattern,
|
||||
|
@ -9372,12 +9372,12 @@ impl Display for RowAccessPolicy {
|
|||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
pub struct Tag {
|
||||
pub key: Ident,
|
||||
pub key: ObjectName,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
impl Tag {
|
||||
pub fn new(key: Ident, value: String) -> Self {
|
||||
pub fn new(key: ObjectName, value: String) -> Self {
|
||||
Self { key, value }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1189,7 +1189,7 @@ fn parse_column_policy_property(
|
|||
parser: &mut Parser,
|
||||
with: bool,
|
||||
) -> Result<ColumnPolicyProperty, ParserError> {
|
||||
let policy_name = parser.parse_identifier()?;
|
||||
let policy_name = parser.parse_object_name(false)?;
|
||||
let using_columns = if parser.parse_keyword(Keyword::USING) {
|
||||
parser.expect_token(&Token::LParen)?;
|
||||
let columns = parser.parse_comma_separated(|p| p.parse_identifier())?;
|
||||
|
|
|
@ -3654,9 +3654,9 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parse the `ESCAPE CHAR` portion of `LIKE`, `ILIKE`, and `SIMILAR TO`
|
||||
pub fn parse_escape_char(&mut self) -> Result<Option<String>, ParserError> {
|
||||
pub fn parse_escape_char(&mut self) -> Result<Option<Value>, ParserError> {
|
||||
if self.parse_keyword(Keyword::ESCAPE) {
|
||||
Ok(Some(self.parse_literal_string()?))
|
||||
Ok(Some(self.parse_value()?.into()))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
|
@ -7884,7 +7884,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
pub(crate) fn parse_tag(&mut self) -> Result<Tag, ParserError> {
|
||||
let name = self.parse_identifier()?;
|
||||
let name = self.parse_object_name(false)?;
|
||||
self.expect_token(&Token::Eq)?;
|
||||
let value = self.parse_literal_string()?;
|
||||
|
||||
|
|
|
@ -2040,7 +2040,7 @@ fn parse_ilike() {
|
|||
pattern: Box::new(Expr::Value(
|
||||
(Value::SingleQuotedString("%a".to_string())).with_empty_span()
|
||||
)),
|
||||
escape_char: Some('^'.to_string()),
|
||||
escape_char: Some(Value::SingleQuotedString('^'.to_string())),
|
||||
any: false,
|
||||
},
|
||||
select.selection.unwrap()
|
||||
|
@ -2104,7 +2104,7 @@ fn parse_like() {
|
|||
pattern: Box::new(Expr::Value(
|
||||
(Value::SingleQuotedString("%a".to_string())).with_empty_span()
|
||||
)),
|
||||
escape_char: Some('^'.to_string()),
|
||||
escape_char: Some(Value::SingleQuotedString('^'.to_string())),
|
||||
any: false,
|
||||
},
|
||||
select.selection.unwrap()
|
||||
|
@ -2167,7 +2167,24 @@ fn parse_similar_to() {
|
|||
pattern: Box::new(Expr::Value(
|
||||
(Value::SingleQuotedString("%a".to_string())).with_empty_span()
|
||||
)),
|
||||
escape_char: Some('^'.to_string()),
|
||||
escape_char: Some(Value::SingleQuotedString('^'.to_string())),
|
||||
},
|
||||
select.selection.unwrap()
|
||||
);
|
||||
|
||||
let sql = &format!(
|
||||
"SELECT * FROM customers WHERE name {}SIMILAR TO '%a' ESCAPE NULL",
|
||||
if negated { "NOT " } else { "" }
|
||||
);
|
||||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
Expr::SimilarTo {
|
||||
expr: Box::new(Expr::Identifier(Ident::new("name"))),
|
||||
negated,
|
||||
pattern: Box::new(Expr::Value(
|
||||
(Value::SingleQuotedString("%a".to_string())).with_empty_span()
|
||||
)),
|
||||
escape_char: Some(Value::Null),
|
||||
},
|
||||
select.selection.unwrap()
|
||||
);
|
||||
|
@ -2185,7 +2202,7 @@ fn parse_similar_to() {
|
|||
pattern: Box::new(Expr::Value(
|
||||
(Value::SingleQuotedString("%a".to_string())).with_empty_span()
|
||||
)),
|
||||
escape_char: Some('^'.to_string()),
|
||||
escape_char: Some(Value::SingleQuotedString('^'.to_string())),
|
||||
})),
|
||||
select.selection.unwrap()
|
||||
);
|
||||
|
|
|
@ -270,8 +270,8 @@ fn test_snowflake_create_table_with_tag() {
|
|||
assert_eq!("my_table", name.to_string());
|
||||
assert_eq!(
|
||||
Some(vec![
|
||||
Tag::new("A".into(), "TAG A".to_string()),
|
||||
Tag::new("B".into(), "TAG B".to_string())
|
||||
Tag::new(ObjectName::from(vec![Ident::new("A")]), "TAG A".to_string()),
|
||||
Tag::new(ObjectName::from(vec![Ident::new("B")]), "TAG B".to_string())
|
||||
]),
|
||||
with_tags
|
||||
);
|
||||
|
@ -291,8 +291,8 @@ fn test_snowflake_create_table_with_tag() {
|
|||
assert_eq!("my_table", name.to_string());
|
||||
assert_eq!(
|
||||
Some(vec![
|
||||
Tag::new("A".into(), "TAG A".to_string()),
|
||||
Tag::new("B".into(), "TAG B".to_string())
|
||||
Tag::new(ObjectName::from(vec![Ident::new("A")]), "TAG A".to_string()),
|
||||
Tag::new(ObjectName::from(vec![Ident::new("B")]), "TAG B".to_string())
|
||||
]),
|
||||
with_tags
|
||||
);
|
||||
|
@ -731,7 +731,7 @@ fn test_snowflake_create_table_with_columns_masking_policy() {
|
|||
option: ColumnOption::Policy(ColumnPolicy::MaskingPolicy(
|
||||
ColumnPolicyProperty {
|
||||
with,
|
||||
policy_name: "p".into(),
|
||||
policy_name: ObjectName::from(vec![Ident::new("p")]),
|
||||
using_columns,
|
||||
}
|
||||
))
|
||||
|
@ -765,7 +765,7 @@ fn test_snowflake_create_table_with_columns_projection_policy() {
|
|||
option: ColumnOption::Policy(ColumnPolicy::ProjectionPolicy(
|
||||
ColumnPolicyProperty {
|
||||
with,
|
||||
policy_name: "p".into(),
|
||||
policy_name: ObjectName::from(vec![Ident::new("p")]),
|
||||
using_columns: None,
|
||||
}
|
||||
))
|
||||
|
@ -802,8 +802,14 @@ fn test_snowflake_create_table_with_columns_tags() {
|
|||
option: ColumnOption::Tags(TagsColumnOption {
|
||||
with,
|
||||
tags: vec![
|
||||
Tag::new("A".into(), "TAG A".into()),
|
||||
Tag::new("B".into(), "TAG B".into()),
|
||||
Tag::new(
|
||||
ObjectName::from(vec![Ident::new("A")]),
|
||||
"TAG A".into()
|
||||
),
|
||||
Tag::new(
|
||||
ObjectName::from(vec![Ident::new("B")]),
|
||||
"TAG B".into()
|
||||
),
|
||||
]
|
||||
}),
|
||||
}],
|
||||
|
@ -846,7 +852,7 @@ fn test_snowflake_create_table_with_several_column_options() {
|
|||
option: ColumnOption::Policy(ColumnPolicy::MaskingPolicy(
|
||||
ColumnPolicyProperty {
|
||||
with: true,
|
||||
policy_name: "p1".into(),
|
||||
policy_name: ObjectName::from(vec![Ident::new("p1")]),
|
||||
using_columns: Some(vec!["a".into(), "b".into()]),
|
||||
}
|
||||
)),
|
||||
|
@ -856,8 +862,14 @@ fn test_snowflake_create_table_with_several_column_options() {
|
|||
option: ColumnOption::Tags(TagsColumnOption {
|
||||
with: true,
|
||||
tags: vec![
|
||||
Tag::new("A".into(), "TAG A".into()),
|
||||
Tag::new("B".into(), "TAG B".into()),
|
||||
Tag::new(
|
||||
ObjectName::from(vec![Ident::new("A")]),
|
||||
"TAG A".into()
|
||||
),
|
||||
Tag::new(
|
||||
ObjectName::from(vec![Ident::new("B")]),
|
||||
"TAG B".into()
|
||||
),
|
||||
]
|
||||
}),
|
||||
}
|
||||
|
@ -878,7 +890,7 @@ fn test_snowflake_create_table_with_several_column_options() {
|
|||
option: ColumnOption::Policy(ColumnPolicy::ProjectionPolicy(
|
||||
ColumnPolicyProperty {
|
||||
with: false,
|
||||
policy_name: "p2".into(),
|
||||
policy_name: ObjectName::from(vec![Ident::new("p2")]),
|
||||
using_columns: None,
|
||||
}
|
||||
)),
|
||||
|
@ -888,8 +900,14 @@ fn test_snowflake_create_table_with_several_column_options() {
|
|||
option: ColumnOption::Tags(TagsColumnOption {
|
||||
with: false,
|
||||
tags: vec![
|
||||
Tag::new("C".into(), "TAG C".into()),
|
||||
Tag::new("D".into(), "TAG D".into()),
|
||||
Tag::new(
|
||||
ObjectName::from(vec![Ident::new("C")]),
|
||||
"TAG C".into()
|
||||
),
|
||||
Tag::new(
|
||||
ObjectName::from(vec![Ident::new("D")]),
|
||||
"TAG D".into()
|
||||
),
|
||||
]
|
||||
}),
|
||||
}
|
||||
|
@ -942,8 +960,8 @@ fn test_snowflake_create_iceberg_table_all_options() {
|
|||
with_aggregation_policy.map(|name| name.to_string())
|
||||
);
|
||||
assert_eq!(Some(vec![
|
||||
Tag::new("A".into(), "TAG A".into()),
|
||||
Tag::new("B".into(), "TAG B".into()),
|
||||
Tag::new(ObjectName::from(vec![Ident::new("A")]), "TAG A".into()),
|
||||
Tag::new(ObjectName::from(vec![Ident::new("B")]), "TAG B".into()),
|
||||
]), with_tags);
|
||||
|
||||
}
|
||||
|
@ -4172,3 +4190,17 @@ fn test_snowflake_create_view_with_multiple_column_options() {
|
|||
r#"CREATE VIEW X (COL WITH TAG (pii='email') COMMENT 'foobar') AS SELECT * FROM Y"#;
|
||||
snowflake().verified_stmt(create_view_with_tag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_snowflake_create_view_with_composite_tag() {
|
||||
let create_view_with_tag =
|
||||
r#"CREATE VIEW X (COL WITH TAG (foo.bar.baz.pii='email')) AS SELECT * FROM Y"#;
|
||||
snowflake().verified_stmt(create_view_with_tag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_snowflake_create_view_with_composite_policy_name() {
|
||||
let create_view_with_tag =
|
||||
r#"CREATE VIEW X (COL WITH MASKING POLICY foo.bar.baz) AS SELECT * FROM Y"#;
|
||||
snowflake().verified_stmt(create_view_with_tag);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue