mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 15:04:04 +00:00
Add SQLite "ON CONFLICT" column option in CREATE TABLE statements (#1442)
Co-authored-by: hulk <hulk.website@gmail.com> Co-authored-by: Ifeanyi Ubah <ify1992@yahoo.com>
This commit is contained in:
parent
84348d483e
commit
8badcdc200
3 changed files with 62 additions and 0 deletions
|
@ -33,6 +33,7 @@ use crate::ast::{
|
|||
display_comma_separated, display_separated, DataType, Expr, Ident, MySQLColumnPosition,
|
||||
ObjectName, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Value,
|
||||
};
|
||||
use crate::keywords::Keyword;
|
||||
use crate::tokenizer::Token;
|
||||
|
||||
/// An `ALTER TABLE` (`Statement::AlterTable`) operation
|
||||
|
@ -1186,6 +1187,9 @@ pub enum ColumnOption {
|
|||
/// ```
|
||||
/// [MS SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property
|
||||
Identity(Option<IdentityProperty>),
|
||||
/// SQLite specific: ON CONFLICT option on column definition
|
||||
/// <https://www.sqlite.org/lang_conflict.html>
|
||||
OnConflict(Keyword),
|
||||
}
|
||||
|
||||
impl fmt::Display for ColumnOption {
|
||||
|
@ -1294,6 +1298,10 @@ impl fmt::Display for ColumnOption {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
OnConflict(keyword) => {
|
||||
write!(f, "ON CONFLICT {:?}", keyword)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6224,6 +6224,19 @@ impl<'a> Parser<'a> {
|
|||
None
|
||||
};
|
||||
Ok(Some(ColumnOption::Identity(property)))
|
||||
} else if dialect_of!(self is SQLiteDialect | GenericDialect)
|
||||
&& self.parse_keywords(&[Keyword::ON, Keyword::CONFLICT])
|
||||
{
|
||||
// Support ON CONFLICT for SQLite
|
||||
Ok(Some(ColumnOption::OnConflict(
|
||||
self.expect_one_of_keywords(&[
|
||||
Keyword::ROLLBACK,
|
||||
Keyword::ABORT,
|
||||
Keyword::FAIL,
|
||||
Keyword::IGNORE,
|
||||
Keyword::REPLACE,
|
||||
])?,
|
||||
)))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#[macro_use]
|
||||
mod test_utils;
|
||||
|
||||
use sqlparser::keywords::Keyword;
|
||||
use test_utils::*;
|
||||
|
||||
use sqlparser::ast::SelectItem::UnnamedExpr;
|
||||
|
@ -281,6 +282,46 @@ fn parse_create_table_gencol() {
|
|||
sqlite_and_generic().verified_stmt("CREATE TABLE t1 (a INT, b INT AS (a * 2) STORED)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_create_table_on_conflict_col() {
|
||||
for keyword in [
|
||||
Keyword::ROLLBACK,
|
||||
Keyword::ABORT,
|
||||
Keyword::FAIL,
|
||||
Keyword::IGNORE,
|
||||
Keyword::REPLACE,
|
||||
] {
|
||||
let sql = format!("CREATE TABLE t1 (a INT, b INT ON CONFLICT {:?})", keyword);
|
||||
match sqlite_and_generic().verified_stmt(&sql) {
|
||||
Statement::CreateTable(CreateTable { columns, .. }) => {
|
||||
assert_eq!(
|
||||
vec![ColumnOptionDef {
|
||||
name: None,
|
||||
option: ColumnOption::OnConflict(keyword),
|
||||
}],
|
||||
columns[1].options
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_create_table_on_conflict_col_err() {
|
||||
let sql_err = "CREATE TABLE t1 (a INT, b INT ON CONFLICT BOH)";
|
||||
let err = sqlite_and_generic()
|
||||
.parse_sql_statements(sql_err)
|
||||
.unwrap_err();
|
||||
assert_eq!(
|
||||
err,
|
||||
ParserError::ParserError(
|
||||
"Expected: one of ROLLBACK or ABORT or FAIL or IGNORE or REPLACE, found: BOH"
|
||||
.to_string()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_create_table_untyped() {
|
||||
sqlite().verified_stmt("CREATE TABLE t1 (a, b AS (a * 2), c NOT NULL)");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue