Skip to content

Commit

Permalink
snowflake column identifier
Browse files Browse the repository at this point in the history
Signed-off-by: Pawel Leszczynski <[email protected]>
  • Loading branch information
pawel-big-lebowski committed Jun 9, 2022
1 parent aa46e93 commit 396ea62
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 2 deletions.
7 changes: 7 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,12 @@ pub enum Expr {
Identifier(Ident),
/// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
CompoundIdentifier(Vec<Ident>),
/// Multi-part identifier with a column number, e.g. [alias.]$file_col_num[.element]
CompoundIdentifierWithColumnNumber {
alias: Ident,
col_num: String,
element: Ident
},
/// JSON access (postgres) eg: data->'tags'
JsonAccess {
left: Box<Expr>,
Expand Down Expand Up @@ -375,6 +381,7 @@ impl fmt::Display for Expr {
Ok(())
}
Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
Expr::CompoundIdentifierWithColumnNumber {alias, col_num, element} => write!(f, "{}.{}.{}", alias, col_num, element),
Expr::IsTrue(ast) => write!(f, "{} IS TRUE", ast),
Expr::IsFalse(ast) => write!(f, "{} IS FALSE", ast),
Expr::IsNull(ast) => write!(f, "{} IS NULL", ast),
Expand Down
3 changes: 2 additions & 1 deletion src/dialect/snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct SnowflakeDialect;
impl Dialect for SnowflakeDialect {
// see https://docs.snowflake.com/en/sql-reference/identifiers-syntax.html
fn is_identifier_start(&self, ch: char) -> bool {
('a'..='z').contains(&ch) || ('A'..='Z').contains(&ch) || ch == '_'
('a'..='z').contains(&ch) || ('A'..='Z').contains(&ch) || ch == '_' || ch == '@'
}

fn is_identifier_part(&self, ch: char) -> bool {
Expand All @@ -27,5 +27,6 @@ impl Dialect for SnowflakeDialect {
|| ('0'..='9').contains(&ch)
|| ch == '$'
|| ch == '_'
|| ch == ':'
}
}
17 changes: 16 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ impl<'a> Parser<'a> {

while self.consume_token(&Token::Period) {
match self.next_token() {
Token::Placeholder(_s) => if id_parts.len()==1 {
// do nothing -> wildcard expression does not occur together with id column number placeholder
}
Token::Word(w) => id_parts.push(w.to_ident()),
Token::Mul => {
return Ok(WildcardExpr::QualifiedWildcard(ObjectName(id_parts)));
Expand Down Expand Up @@ -444,8 +447,12 @@ impl<'a> Parser<'a> {
_ => match self.peek_token() {
Token::LParen | Token::Period => {
let mut id_parts: Vec<Ident> = vec![w.to_ident()];
let mut col_num:Option<String> = None;
while self.consume_token(&Token::Period) {
match self.next_token() {
Token::Placeholder(s) => if id_parts.len()==1 {
col_num = Some(s);
}
Token::Word(w) => id_parts.push(w.to_ident()),
unexpected => {
return self
Expand All @@ -458,7 +465,15 @@ impl<'a> Parser<'a> {
self.prev_token();
self.parse_function(ObjectName(id_parts))
} else {
Ok(Expr::CompoundIdentifier(id_parts))
if !col_num.is_none() && id_parts.len()==2 {
Ok(Expr::CompoundIdentifierWithColumnNumber {
alias: id_parts[0].clone(),
col_num: col_num.unwrap(),
element: id_parts[1].clone()
})
} else {
Ok(Expr::CompoundIdentifier(id_parts))
}
}
}
_ => Ok(Expr::Identifier(w.to_ident())),
Expand Down
6 changes: 6 additions & 0 deletions tests/sqlparser_snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ fn test_single_table_in_parenthesis() {
);
}

#[test]
fn test_snowflake_variables() {
let sql = "SELECT t.$1.st AS st FROM @schema.general_finished";
snowflake().verified_stmt(sql);
}

#[test]
fn test_single_table_in_parenthesis_with_alias() {
snowflake_and_generic().one_statement_parses_to(
Expand Down

0 comments on commit 396ea62

Please sign in to comment.