Fix column definition COLLATE parsing (#1986)
Some checks failed
Rust / lint (push) Has been cancelled
license / Release Audit Tool (RAT) (push) Has been cancelled
Rust / codestyle (push) Has been cancelled
Rust / test (beta) (push) Has been cancelled
Rust / test (nightly) (push) Has been cancelled
Rust / test (stable) (push) Has been cancelled
Rust / benchmark-lint (push) Has been cancelled
Rust / compile (push) Has been cancelled
Rust / docs (push) Has been cancelled
Rust / compile-no-std (push) Has been cancelled

This commit is contained in:
Michael Victor Zink 2025-08-13 02:05:15 -07:00 committed by GitHub
parent b2f977384c
commit 60a5c8d42a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 64 additions and 26 deletions

View file

@ -110,7 +110,11 @@ impl Dialect for PostgreSqlDialect {
// we only return some custom value here when the behaviour (not merely the numeric value) differs
// from the default implementation
match token.token {
Token::Word(w) if w.keyword == Keyword::COLLATE => Some(Ok(COLLATE_PREC)),
Token::Word(w)
if w.keyword == Keyword::COLLATE && !parser.in_column_definition_state() =>
{
Some(Ok(COLLATE_PREC))
}
Token::LBracket => Some(Ok(BRACKET_PREC)),
Token::Arrow
| Token::LongArrow

View file

@ -1722,7 +1722,7 @@ impl<'a> Parser<'a> {
_ => self.expected_at("an expression", next_token_index),
}?;
if self.parse_keyword(Keyword::COLLATE) {
if !self.in_column_definition_state() && self.parse_keyword(Keyword::COLLATE) {
Ok(Expr::Collate {
expr: Box::new(expr),
collation: self.parse_object_name(false)?,
@ -3372,6 +3372,7 @@ impl<'a> Parser<'a> {
self.advance_token();
let tok = self.get_current_token();
debug!("infix: {tok:?}");
let tok_index = self.get_current_index();
let span = tok.span;
let regular_binary_operator = match &tok.token {
@ -17822,30 +17823,6 @@ mod tests {
assert!(Parser::parse_sql(&MySqlDialect {}, sql).is_err());
}
#[test]
fn test_parse_not_null_in_column_options() {
let canonical = concat!(
"CREATE TABLE foo (",
"abc INT DEFAULT (42 IS NOT NULL) NOT NULL,",
" def INT,",
" def_null BOOL GENERATED ALWAYS AS (def IS NOT NULL) STORED,",
" CHECK (abc IS NOT NULL)",
")"
);
all_dialects().verified_stmt(canonical);
all_dialects().one_statement_parses_to(
concat!(
"CREATE TABLE foo (",
"abc INT DEFAULT (42 NOT NULL) NOT NULL,",
" def INT,",
" def_null BOOL GENERATED ALWAYS AS (def NOT NULL) STORED,",
" CHECK (abc NOT NULL)",
")"
),
canonical,
);
}
#[test]
fn test_placeholder_invalid_whitespace() {
for w in [" ", "/*invalid*/"] {

View file

@ -16598,3 +16598,60 @@ fn parse_create_view_if_not_exists() {
res.unwrap_err()
);
}
#[test]
fn test_parse_not_null_in_column_options() {
let canonical = concat!(
"CREATE TABLE foo (",
"abc INT DEFAULT (42 IS NOT NULL) NOT NULL,",
" def INT,",
" def_null BOOL GENERATED ALWAYS AS (def IS NOT NULL) STORED,",
" CHECK (abc IS NOT NULL)",
")"
);
all_dialects().verified_stmt(canonical);
all_dialects().one_statement_parses_to(
concat!(
"CREATE TABLE foo (",
"abc INT DEFAULT (42 NOT NULL) NOT NULL,",
" def INT,",
" def_null BOOL GENERATED ALWAYS AS (def NOT NULL) STORED,",
" CHECK (abc NOT NULL)",
")"
),
canonical,
);
}
#[test]
fn test_parse_default_with_collate_column_option() {
let sql = "CREATE TABLE foo (abc TEXT DEFAULT 'foo' COLLATE 'en_US')";
let stmt = all_dialects().verified_stmt(sql);
if let Statement::CreateTable(CreateTable { mut columns, .. }) = stmt {
let mut column = columns.pop().unwrap();
assert_eq!(&column.name.value, "abc");
assert_eq!(column.data_type, DataType::Text);
let collate_option = column.options.pop().unwrap();
if let ColumnOptionDef {
name: None,
option: ColumnOption::Collation(collate),
} = collate_option
{
assert_eq!(collate.to_string(), "'en_US'");
} else {
panic!("Expected collate column option, got {collate_option}");
}
let default_option = column.options.pop().unwrap();
if let ColumnOptionDef {
name: None,
option: ColumnOption::Default(Expr::Value(value)),
} = default_option
{
assert_eq!(value.to_string(), "'foo'");
} else {
panic!("Expected default column option, got {default_option}");
}
} else {
panic!("Expected create table statement");
}
}