mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 23:14:07 +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,
|
display_comma_separated, display_separated, DataType, Expr, Ident, MySQLColumnPosition,
|
||||||
ObjectName, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Value,
|
ObjectName, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Value,
|
||||||
};
|
};
|
||||||
|
use crate::keywords::Keyword;
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
|
|
||||||
/// An `ALTER TABLE` (`Statement::AlterTable`) operation
|
/// 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
|
/// [MS SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property
|
||||||
Identity(Option<IdentityProperty>),
|
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 {
|
impl fmt::Display for ColumnOption {
|
||||||
|
@ -1294,6 +1298,10 @@ impl fmt::Display for ColumnOption {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
OnConflict(keyword) => {
|
||||||
|
write!(f, "ON CONFLICT {:?}", keyword)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6224,6 +6224,19 @@ impl<'a> Parser<'a> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
Ok(Some(ColumnOption::Identity(property)))
|
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 {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod test_utils;
|
mod test_utils;
|
||||||
|
|
||||||
|
use sqlparser::keywords::Keyword;
|
||||||
use test_utils::*;
|
use test_utils::*;
|
||||||
|
|
||||||
use sqlparser::ast::SelectItem::UnnamedExpr;
|
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)");
|
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]
|
#[test]
|
||||||
fn parse_create_table_untyped() {
|
fn parse_create_table_untyped() {
|
||||||
sqlite().verified_stmt("CREATE TABLE t1 (a, b AS (a * 2), c NOT NULL)");
|
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