mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 15:04:04 +00:00
Add support for generated columns skipping 'GENERATED ALWAYS' keywords (#1058)
This commit is contained in:
parent
d0fce121ef
commit
da2296e6d6
4 changed files with 49 additions and 1 deletions
|
@ -600,6 +600,8 @@ pub enum ColumnOption {
|
||||||
sequence_options: Option<Vec<SequenceOptions>>,
|
sequence_options: Option<Vec<SequenceOptions>>,
|
||||||
generation_expr: Option<Expr>,
|
generation_expr: Option<Expr>,
|
||||||
generation_expr_mode: Option<GeneratedExpressionMode>,
|
generation_expr_mode: Option<GeneratedExpressionMode>,
|
||||||
|
/// false if 'GENERATED ALWAYS' is skipped (option starts with AS)
|
||||||
|
generated_keyword: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,6 +643,7 @@ impl fmt::Display for ColumnOption {
|
||||||
sequence_options,
|
sequence_options,
|
||||||
generation_expr,
|
generation_expr,
|
||||||
generation_expr_mode,
|
generation_expr_mode,
|
||||||
|
generated_keyword,
|
||||||
} => {
|
} => {
|
||||||
if let Some(expr) = generation_expr {
|
if let Some(expr) = generation_expr {
|
||||||
let modifier = match generation_expr_mode {
|
let modifier = match generation_expr_mode {
|
||||||
|
@ -648,7 +651,11 @@ impl fmt::Display for ColumnOption {
|
||||||
Some(GeneratedExpressionMode::Virtual) => " VIRTUAL",
|
Some(GeneratedExpressionMode::Virtual) => " VIRTUAL",
|
||||||
Some(GeneratedExpressionMode::Stored) => " STORED",
|
Some(GeneratedExpressionMode::Stored) => " STORED",
|
||||||
};
|
};
|
||||||
write!(f, "GENERATED ALWAYS AS ({expr}){modifier}")?;
|
if *generated_keyword {
|
||||||
|
write!(f, "GENERATED ALWAYS AS ({expr}){modifier}")?;
|
||||||
|
} else {
|
||||||
|
write!(f, "AS ({expr}){modifier}")?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
// Like Postgres - generated from sequence
|
// Like Postgres - generated from sequence
|
||||||
|
|
|
@ -4288,6 +4288,10 @@ impl<'a> Parser<'a> {
|
||||||
Ok(Some(ColumnOption::OnUpdate(expr)))
|
Ok(Some(ColumnOption::OnUpdate(expr)))
|
||||||
} else if self.parse_keyword(Keyword::GENERATED) {
|
} else if self.parse_keyword(Keyword::GENERATED) {
|
||||||
self.parse_optional_column_option_generated()
|
self.parse_optional_column_option_generated()
|
||||||
|
} else if self.parse_keyword(Keyword::AS)
|
||||||
|
&& dialect_of!(self is MySqlDialect | SQLiteDialect | DuckDbDialect | GenericDialect)
|
||||||
|
{
|
||||||
|
self.parse_optional_column_option_as()
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -4306,6 +4310,7 @@ impl<'a> Parser<'a> {
|
||||||
sequence_options: Some(sequence_options),
|
sequence_options: Some(sequence_options),
|
||||||
generation_expr: None,
|
generation_expr: None,
|
||||||
generation_expr_mode: None,
|
generation_expr_mode: None,
|
||||||
|
generated_keyword: true,
|
||||||
}))
|
}))
|
||||||
} else if self.parse_keywords(&[
|
} else if self.parse_keywords(&[
|
||||||
Keyword::BY,
|
Keyword::BY,
|
||||||
|
@ -4323,6 +4328,7 @@ impl<'a> Parser<'a> {
|
||||||
sequence_options: Some(sequence_options),
|
sequence_options: Some(sequence_options),
|
||||||
generation_expr: None,
|
generation_expr: None,
|
||||||
generation_expr_mode: None,
|
generation_expr_mode: None,
|
||||||
|
generated_keyword: true,
|
||||||
}))
|
}))
|
||||||
} else if self.parse_keywords(&[Keyword::ALWAYS, Keyword::AS]) {
|
} else if self.parse_keywords(&[Keyword::ALWAYS, Keyword::AS]) {
|
||||||
if self.expect_token(&Token::LParen).is_ok() {
|
if self.expect_token(&Token::LParen).is_ok() {
|
||||||
|
@ -4347,6 +4353,7 @@ impl<'a> Parser<'a> {
|
||||||
sequence_options: None,
|
sequence_options: None,
|
||||||
generation_expr: Some(expr),
|
generation_expr: Some(expr),
|
||||||
generation_expr_mode: expr_mode,
|
generation_expr_mode: expr_mode,
|
||||||
|
generated_keyword: true,
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
@ -4356,6 +4363,32 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_optional_column_option_as(&mut self) -> Result<Option<ColumnOption>, ParserError> {
|
||||||
|
// Some DBs allow 'AS (expr)', shorthand for GENERATED ALWAYS AS
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let expr = self.parse_expr()?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
|
||||||
|
let (gen_as, expr_mode) = if self.parse_keywords(&[Keyword::STORED]) {
|
||||||
|
(
|
||||||
|
GeneratedAs::ExpStored,
|
||||||
|
Some(GeneratedExpressionMode::Stored),
|
||||||
|
)
|
||||||
|
} else if self.parse_keywords(&[Keyword::VIRTUAL]) {
|
||||||
|
(GeneratedAs::Always, Some(GeneratedExpressionMode::Virtual))
|
||||||
|
} else {
|
||||||
|
(GeneratedAs::Always, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(ColumnOption::Generated {
|
||||||
|
generated_as: gen_as,
|
||||||
|
sequence_options: None,
|
||||||
|
generation_expr: Some(expr),
|
||||||
|
generation_expr_mode: expr_mode,
|
||||||
|
generated_keyword: false,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_referential_action(&mut self) -> Result<ReferentialAction, ParserError> {
|
pub fn parse_referential_action(&mut self) -> Result<ReferentialAction, ParserError> {
|
||||||
if self.parse_keyword(Keyword::RESTRICT) {
|
if self.parse_keyword(Keyword::RESTRICT) {
|
||||||
Ok(ReferentialAction::Restrict)
|
Ok(ReferentialAction::Restrict)
|
||||||
|
|
|
@ -517,6 +517,10 @@ fn parse_create_table_gencol() {
|
||||||
|
|
||||||
let sql_stored = "CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a * 2) STORED)";
|
let sql_stored = "CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a * 2) STORED)";
|
||||||
mysql_and_generic().verified_stmt(sql_stored);
|
mysql_and_generic().verified_stmt(sql_stored);
|
||||||
|
|
||||||
|
mysql_and_generic().verified_stmt("CREATE TABLE t1 (a INT, b INT AS (a * 2))");
|
||||||
|
mysql_and_generic().verified_stmt("CREATE TABLE t1 (a INT, b INT AS (a * 2) VIRTUAL)");
|
||||||
|
mysql_and_generic().verified_stmt("CREATE TABLE t1 (a INT, b INT AS (a * 2) STORED)");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -215,6 +215,10 @@ fn parse_create_table_gencol() {
|
||||||
|
|
||||||
let sql_stored = "CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a * 2) STORED)";
|
let sql_stored = "CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a * 2) STORED)";
|
||||||
sqlite_and_generic().verified_stmt(sql_stored);
|
sqlite_and_generic().verified_stmt(sql_stored);
|
||||||
|
|
||||||
|
sqlite_and_generic().verified_stmt("CREATE TABLE t1 (a INT, b INT AS (a * 2))");
|
||||||
|
sqlite_and_generic().verified_stmt("CREATE TABLE t1 (a INT, b INT AS (a * 2) VIRTUAL)");
|
||||||
|
sqlite_and_generic().verified_stmt("CREATE TABLE t1 (a INT, b INT AS (a * 2) STORED)");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue