Encapsulate Insert and Delete into specific structs (#1224)

Signed-off-by: tison <wander4096@gmail.com>
This commit is contained in:
tison 2024-04-21 21:13:18 +08:00 committed by GitHub
parent d2c2b15f9e
commit bf89b7d808
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 187 additions and 147 deletions

84
src/ast/dml.rs Normal file
View file

@ -0,0 +1,84 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, vec::Vec};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "visitor")]
use sqlparser_derive::{Visit, VisitMut};
use super::{
Expr, FromTable, Ident, InsertAliases, MysqlInsertPriority, ObjectName, OnInsert, OrderByExpr,
Query, SelectItem, SqliteOnConflict, TableWithJoins,
};
/// INSERT statement.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct Insert {
/// Only for Sqlite
pub or: Option<SqliteOnConflict>,
/// Only for mysql
pub ignore: bool,
/// INTO - optional keyword
pub into: bool,
/// TABLE
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
pub table_name: ObjectName,
/// table_name as foo (for PostgreSQL)
pub table_alias: Option<Ident>,
/// COLUMNS
pub columns: Vec<Ident>,
/// Overwrite (Hive)
pub overwrite: bool,
/// A SQL query that specifies what to insert
pub source: Option<Box<Query>>,
/// partitioned insert (Hive)
pub partitioned: Option<Vec<Expr>>,
/// Columns defined after PARTITION
pub after_columns: Vec<Ident>,
/// whether the insert has the table keyword (Hive)
pub table: bool,
pub on: Option<OnInsert>,
/// RETURNING
pub returning: Option<Vec<SelectItem>>,
/// Only for mysql
pub replace_into: bool,
/// Only for mysql
pub priority: Option<MysqlInsertPriority>,
/// Only for mysql
pub insert_alias: Option<InsertAliases>,
}
/// DELETE statement.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct Delete {
/// Multi tables delete are supported in mysql
pub tables: Vec<ObjectName>,
/// FROM
pub from: FromTable,
/// USING (Snowflake, Postgres, MySQL)
pub using: Option<Vec<TableWithJoins>>,
/// WHERE
pub selection: Option<Expr>,
/// RETURNING
pub returning: Option<Vec<SelectItem>>,
/// ORDER BY (MySQL)
pub order_by: Vec<OrderByExpr>,
/// LIMIT (MySQL)
pub limit: Option<Expr>,
}

View file

@ -37,6 +37,7 @@ pub use self::ddl::{
ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef, ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef,
UserDefinedTypeRepresentation, ViewColumnDef, UserDefinedTypeRepresentation, ViewColumnDef,
}; };
pub use self::dml::{Delete, Insert};
pub use self::operator::{BinaryOperator, UnaryOperator}; pub use self::operator::{BinaryOperator, UnaryOperator};
pub use self::query::{ pub use self::query::{
Cte, CteAsMaterialized, Distinct, ExceptSelectItem, ExcludeSelectItem, Fetch, ForClause, Cte, CteAsMaterialized, Distinct, ExceptSelectItem, ExcludeSelectItem, Fetch, ForClause,
@ -60,6 +61,7 @@ pub use visitor::*;
mod data_type; mod data_type;
mod dcl; mod dcl;
mod ddl; mod ddl;
mod dml;
pub mod helpers; pub mod helpers;
mod operator; mod operator;
mod query; mod query;
@ -1800,40 +1802,7 @@ pub enum Statement {
/// ```sql /// ```sql
/// INSERT /// INSERT
/// ``` /// ```
Insert { Insert(Insert),
/// Only for Sqlite
or: Option<SqliteOnConflict>,
/// Only for mysql
ignore: bool,
/// INTO - optional keyword
into: bool,
/// TABLE
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
/// table_name as foo (for PostgreSQL)
table_alias: Option<Ident>,
/// COLUMNS
columns: Vec<Ident>,
/// Overwrite (Hive)
overwrite: bool,
/// A SQL query that specifies what to insert
source: Option<Box<Query>>,
/// partitioned insert (Hive)
partitioned: Option<Vec<Expr>>,
/// Columns defined after PARTITION
after_columns: Vec<Ident>,
/// whether the insert has the table keyword (Hive)
table: bool,
on: Option<OnInsert>,
/// RETURNING
returning: Option<Vec<SelectItem>>,
/// Only for mysql
replace_into: bool,
/// Only for mysql
priority: Option<MysqlInsertPriority>,
/// Only for mysql
insert_alias: Option<InsertAliases>,
},
/// ```sql /// ```sql
/// INSTALL /// INSTALL
/// ``` /// ```
@ -1923,22 +1892,7 @@ pub enum Statement {
/// ```sql /// ```sql
/// DELETE /// DELETE
/// ``` /// ```
Delete { Delete(Delete),
/// Multi tables delete are supported in mysql
tables: Vec<ObjectName>,
/// FROM
from: FromTable,
/// USING (Snowflake, Postgres, MySQL)
using: Option<Vec<TableWithJoins>>,
/// WHERE
selection: Option<Expr>,
/// RETURNING
returning: Option<Vec<SelectItem>>,
/// ORDER BY (MySQL)
order_by: Vec<OrderByExpr>,
/// LIMIT (MySQL)
limit: Option<Expr>,
},
/// ```sql /// ```sql
/// CREATE VIEW /// CREATE VIEW
/// ``` /// ```
@ -2912,24 +2866,25 @@ impl fmt::Display for Statement {
} }
Ok(()) Ok(())
} }
Statement::Insert { Statement::Insert(insert) => {
or, let Insert {
ignore, or,
into, ignore,
table_name, into,
table_alias, table_name,
overwrite, table_alias,
partitioned, overwrite,
columns, partitioned,
after_columns, columns,
source, after_columns,
table, source,
on, table,
returning, on,
replace_into, returning,
priority, replace_into,
insert_alias, priority,
} => { insert_alias,
} = insert;
let table_name = if let Some(alias) = table_alias { let table_name = if let Some(alias) = table_alias {
format!("{table_name} AS {alias}") format!("{table_name} AS {alias}")
} else { } else {
@ -3074,15 +3029,16 @@ impl fmt::Display for Statement {
} }
Ok(()) Ok(())
} }
Statement::Delete { Statement::Delete(delete) => {
tables, let Delete {
from, tables,
using, from,
selection, using,
returning, selection,
order_by, returning,
limit, order_by,
} => { limit,
} = delete;
write!(f, "DELETE ")?; write!(f, "DELETE ")?;
if !tables.is_empty() { if !tables.is_empty() {
write!(f, "{} ", display_comma_separated(tables))?; write!(f, "{} ", display_comma_separated(tables))?;

View file

@ -7082,7 +7082,7 @@ impl<'a> Parser<'a> {
None None
}; };
Ok(Statement::Delete { Ok(Statement::Delete(Delete {
tables, tables,
from: if with_from_keyword { from: if with_from_keyword {
FromTable::WithFromKeyword(from) FromTable::WithFromKeyword(from)
@ -7094,7 +7094,7 @@ impl<'a> Parser<'a> {
returning, returning,
order_by, order_by,
limit, limit,
}) }))
} }
// KILL [CONNECTION | QUERY | MUTATION] processlist_id // KILL [CONNECTION | QUERY | MUTATION] processlist_id
@ -8658,7 +8658,7 @@ impl<'a> Parser<'a> {
} }
let insert = &mut self.parse_insert()?; let insert = &mut self.parse_insert()?;
if let Statement::Insert { replace_into, .. } = insert { if let Statement::Insert(Insert { replace_into, .. }) = insert {
*replace_into = true; *replace_into = true;
} }
@ -8826,7 +8826,7 @@ impl<'a> Parser<'a> {
None None
}; };
Ok(Statement::Insert { Ok(Statement::Insert(Insert {
or, or,
table_name, table_name,
table_alias, table_alias,
@ -8843,7 +8843,7 @@ impl<'a> Parser<'a> {
replace_into, replace_into,
priority, priority,
insert_alias, insert_alias,
}) }))
} }
} }

View file

@ -90,10 +90,10 @@ fn parse_raw_literal() {
fn parse_delete_statement() { fn parse_delete_statement() {
let sql = "DELETE \"table\" WHERE 1"; let sql = "DELETE \"table\" WHERE 1";
match bigquery_and_generic().verified_stmt(sql) { match bigquery_and_generic().verified_stmt(sql) {
Statement::Delete { Statement::Delete(Delete {
from: FromTable::WithoutKeyword(from), from: FromTable::WithoutKeyword(from),
.. ..
} => { }) => {
assert_eq!( assert_eq!(
TableFactor::Table { TableFactor::Table {
name: ObjectName(vec![Ident::with_quote('"', "table")]), name: ObjectName(vec![Ident::with_quote('"', "table")]),

View file

@ -84,12 +84,12 @@ fn parse_insert_values() {
expected_rows: &[Vec<Expr>], expected_rows: &[Vec<Expr>],
) { ) {
match verified_stmt(sql) { match verified_stmt(sql) {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source: Some(source), source: Some(source),
.. ..
} => { }) => {
assert_eq!(table_name.to_string(), expected_table_name); assert_eq!(table_name.to_string(), expected_table_name);
assert_eq!(columns.len(), expected_columns.len()); assert_eq!(columns.len(), expected_columns.len());
for (index, column) in columns.iter().enumerate() { for (index, column) in columns.iter().enumerate() {
@ -125,7 +125,7 @@ fn parse_insert_default_values() {
let insert_with_default_values = verified_stmt("INSERT INTO test_table DEFAULT VALUES"); let insert_with_default_values = verified_stmt("INSERT INTO test_table DEFAULT VALUES");
match insert_with_default_values { match insert_with_default_values {
Statement::Insert { Statement::Insert(Insert {
after_columns, after_columns,
columns, columns,
on, on,
@ -134,7 +134,7 @@ fn parse_insert_default_values() {
source, source,
table_name, table_name,
.. ..
} => { }) => {
assert_eq!(columns, vec![]); assert_eq!(columns, vec![]);
assert_eq!(after_columns, vec![]); assert_eq!(after_columns, vec![]);
assert_eq!(on, None); assert_eq!(on, None);
@ -150,7 +150,7 @@ fn parse_insert_default_values() {
verified_stmt("INSERT INTO test_table DEFAULT VALUES RETURNING test_column"); verified_stmt("INSERT INTO test_table DEFAULT VALUES RETURNING test_column");
match insert_with_default_values_and_returning { match insert_with_default_values_and_returning {
Statement::Insert { Statement::Insert(Insert {
after_columns, after_columns,
columns, columns,
on, on,
@ -159,7 +159,7 @@ fn parse_insert_default_values() {
source, source,
table_name, table_name,
.. ..
} => { }) => {
assert_eq!(after_columns, vec![]); assert_eq!(after_columns, vec![]);
assert_eq!(columns, vec![]); assert_eq!(columns, vec![]);
assert_eq!(on, None); assert_eq!(on, None);
@ -175,7 +175,7 @@ fn parse_insert_default_values() {
verified_stmt("INSERT INTO test_table DEFAULT VALUES ON CONFLICT DO NOTHING"); verified_stmt("INSERT INTO test_table DEFAULT VALUES ON CONFLICT DO NOTHING");
match insert_with_default_values_and_on_conflict { match insert_with_default_values_and_on_conflict {
Statement::Insert { Statement::Insert(Insert {
after_columns, after_columns,
columns, columns,
on, on,
@ -184,7 +184,7 @@ fn parse_insert_default_values() {
source, source,
table_name, table_name,
.. ..
} => { }) => {
assert_eq!(after_columns, vec![]); assert_eq!(after_columns, vec![]);
assert_eq!(columns, vec![]); assert_eq!(columns, vec![]);
assert!(on.is_some()); assert!(on.is_some());
@ -230,11 +230,11 @@ fn parse_insert_select_returning() {
verified_stmt("INSERT INTO t SELECT 1 RETURNING 2"); verified_stmt("INSERT INTO t SELECT 1 RETURNING 2");
let stmt = verified_stmt("INSERT INTO t SELECT x RETURNING x AS y"); let stmt = verified_stmt("INSERT INTO t SELECT x RETURNING x AS y");
match stmt { match stmt {
Statement::Insert { Statement::Insert(Insert {
returning: Some(ret), returning: Some(ret),
source: Some(_), source: Some(_),
.. ..
} => assert_eq!(ret.len(), 1), }) => assert_eq!(ret.len(), 1),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -255,7 +255,7 @@ fn parse_insert_sqlite() {
.pop() .pop()
.unwrap() .unwrap()
{ {
Statement::Insert { or, .. } => assert_eq!(or, expected_action), Statement::Insert(Insert { or, .. }) => assert_eq!(or, expected_action),
_ => panic!("{}", sql), _ => panic!("{}", sql),
}; };
@ -545,10 +545,10 @@ fn parse_no_table_name() {
fn parse_delete_statement() { fn parse_delete_statement() {
let sql = "DELETE FROM \"table\""; let sql = "DELETE FROM \"table\"";
match verified_stmt(sql) { match verified_stmt(sql) {
Statement::Delete { Statement::Delete(Delete {
from: FromTable::WithFromKeyword(from), from: FromTable::WithFromKeyword(from),
.. ..
} => { }) => {
assert_eq!( assert_eq!(
TableFactor::Table { TableFactor::Table {
name: ObjectName(vec![Ident::with_quote('"', "table")]), name: ObjectName(vec![Ident::with_quote('"', "table")]),
@ -582,11 +582,11 @@ fn parse_delete_statement_for_multi_tables() {
let sql = "DELETE schema1.table1, schema2.table2 FROM schema1.table1 JOIN schema2.table2 ON schema2.table2.col1 = schema1.table1.col1 WHERE schema2.table2.col2 = 1"; let sql = "DELETE schema1.table1, schema2.table2 FROM schema1.table1 JOIN schema2.table2 ON schema2.table2.col1 = schema1.table1.col1 WHERE schema2.table2.col2 = 1";
let dialects = all_dialects_except(|d| d.is::<BigQueryDialect>() || d.is::<GenericDialect>()); let dialects = all_dialects_except(|d| d.is::<BigQueryDialect>() || d.is::<GenericDialect>());
match dialects.verified_stmt(sql) { match dialects.verified_stmt(sql) {
Statement::Delete { Statement::Delete(Delete {
tables, tables,
from: FromTable::WithFromKeyword(from), from: FromTable::WithFromKeyword(from),
.. ..
} => { }) => {
assert_eq!( assert_eq!(
ObjectName(vec![Ident::new("schema1"), Ident::new("table1")]), ObjectName(vec![Ident::new("schema1"), Ident::new("table1")]),
tables[0] tables[0]
@ -626,11 +626,11 @@ fn parse_delete_statement_for_multi_tables() {
fn parse_delete_statement_for_multi_tables_with_using() { fn parse_delete_statement_for_multi_tables_with_using() {
let sql = "DELETE FROM schema1.table1, schema2.table2 USING schema1.table1 JOIN schema2.table2 ON schema2.table2.pk = schema1.table1.col1 WHERE schema2.table2.col2 = 1"; let sql = "DELETE FROM schema1.table1, schema2.table2 USING schema1.table1 JOIN schema2.table2 ON schema2.table2.pk = schema1.table1.col1 WHERE schema2.table2.col2 = 1";
match verified_stmt(sql) { match verified_stmt(sql) {
Statement::Delete { Statement::Delete(Delete {
from: FromTable::WithFromKeyword(from), from: FromTable::WithFromKeyword(from),
using: Some(using), using: Some(using),
.. ..
} => { }) => {
assert_eq!( assert_eq!(
TableFactor::Table { TableFactor::Table {
name: ObjectName(vec![Ident::new("schema1"), Ident::new("table1")]), name: ObjectName(vec![Ident::new("schema1"), Ident::new("table1")]),
@ -686,14 +686,14 @@ fn parse_where_delete_statement() {
let sql = "DELETE FROM foo WHERE name = 5"; let sql = "DELETE FROM foo WHERE name = 5";
match verified_stmt(sql) { match verified_stmt(sql) {
Statement::Delete { Statement::Delete(Delete {
tables: _, tables: _,
from: FromTable::WithFromKeyword(from), from: FromTable::WithFromKeyword(from),
using, using,
selection, selection,
returning, returning,
.. ..
} => { }) => {
assert_eq!( assert_eq!(
TableFactor::Table { TableFactor::Table {
name: ObjectName(vec![Ident::new("foo")]), name: ObjectName(vec![Ident::new("foo")]),
@ -727,14 +727,14 @@ fn parse_where_delete_with_alias_statement() {
let sql = "DELETE FROM basket AS a USING basket AS b WHERE a.id < b.id"; let sql = "DELETE FROM basket AS a USING basket AS b WHERE a.id < b.id";
match verified_stmt(sql) { match verified_stmt(sql) {
Statement::Delete { Statement::Delete(Delete {
tables: _, tables: _,
from: FromTable::WithFromKeyword(from), from: FromTable::WithFromKeyword(from),
using, using,
selection, selection,
returning, returning,
.. ..
} => { }) => {
assert_eq!( assert_eq!(
TableFactor::Table { TableFactor::Table {
name: ObjectName(vec![Ident::new("basket")]), name: ObjectName(vec![Ident::new("basket")]),

View file

@ -1211,13 +1211,13 @@ fn parse_simple_insert() {
let sql = r"INSERT INTO tasks (title, priority) VALUES ('Test Some Inserts', 1), ('Test Entry 2', 2), ('Test Entry 3', 3)"; let sql = r"INSERT INTO tasks (title, priority) VALUES ('Test Some Inserts', 1), ('Test Entry 2', 2), ('Test Entry 3', 3)";
match mysql().verified_stmt(sql) { match mysql().verified_stmt(sql) {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source, source,
on, on,
.. ..
} => { }) => {
assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name); assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name);
assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns); assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns);
assert!(on.is_none()); assert!(on.is_none());
@ -1263,14 +1263,14 @@ fn parse_ignore_insert() {
let sql = r"INSERT IGNORE INTO tasks (title, priority) VALUES ('Test Some Inserts', 1)"; let sql = r"INSERT IGNORE INTO tasks (title, priority) VALUES ('Test Some Inserts', 1)";
match mysql_and_generic().verified_stmt(sql) { match mysql_and_generic().verified_stmt(sql) {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source, source,
on, on,
ignore, ignore,
.. ..
} => { }) => {
assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name); assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name);
assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns); assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns);
assert!(on.is_none()); assert!(on.is_none());
@ -1305,14 +1305,14 @@ fn parse_priority_insert() {
let sql = r"INSERT HIGH_PRIORITY INTO tasks (title, priority) VALUES ('Test Some Inserts', 1)"; let sql = r"INSERT HIGH_PRIORITY INTO tasks (title, priority) VALUES ('Test Some Inserts', 1)";
match mysql_and_generic().verified_stmt(sql) { match mysql_and_generic().verified_stmt(sql) {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source, source,
on, on,
priority, priority,
.. ..
} => { }) => {
assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name); assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name);
assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns); assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns);
assert!(on.is_none()); assert!(on.is_none());
@ -1344,14 +1344,14 @@ fn parse_priority_insert() {
let sql2 = r"INSERT LOW_PRIORITY INTO tasks (title, priority) VALUES ('Test Some Inserts', 1)"; let sql2 = r"INSERT LOW_PRIORITY INTO tasks (title, priority) VALUES ('Test Some Inserts', 1)";
match mysql().verified_stmt(sql2) { match mysql().verified_stmt(sql2) {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source, source,
on, on,
priority, priority,
.. ..
} => { }) => {
assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name); assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name);
assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns); assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns);
assert!(on.is_none()); assert!(on.is_none());
@ -1385,13 +1385,13 @@ fn parse_priority_insert() {
fn parse_insert_as() { fn parse_insert_as() {
let sql = r"INSERT INTO `table` (`date`) VALUES ('2024-01-01') AS `alias`"; let sql = r"INSERT INTO `table` (`date`) VALUES ('2024-01-01') AS `alias`";
match mysql_and_generic().verified_stmt(sql) { match mysql_and_generic().verified_stmt(sql) {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source, source,
insert_alias, insert_alias,
.. ..
} => { }) => {
assert_eq!( assert_eq!(
ObjectName(vec![Ident::with_quote('`', "table")]), ObjectName(vec![Ident::with_quote('`', "table")]),
table_name table_name
@ -1435,13 +1435,13 @@ fn parse_insert_as() {
let sql = r"INSERT INTO `table` (`id`, `date`) VALUES (1, '2024-01-01') AS `alias` (`mek_id`, `mek_date`)"; let sql = r"INSERT INTO `table` (`id`, `date`) VALUES (1, '2024-01-01') AS `alias` (`mek_id`, `mek_date`)";
match mysql_and_generic().verified_stmt(sql) { match mysql_and_generic().verified_stmt(sql) {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source, source,
insert_alias, insert_alias,
.. ..
} => { }) => {
assert_eq!( assert_eq!(
ObjectName(vec![Ident::with_quote('`', "table")]), ObjectName(vec![Ident::with_quote('`', "table")]),
table_name table_name
@ -1491,7 +1491,7 @@ fn parse_insert_as() {
fn parse_replace_insert() { fn parse_replace_insert() {
let sql = r"REPLACE DELAYED INTO tasks (title, priority) VALUES ('Test Some Inserts', 1)"; let sql = r"REPLACE DELAYED INTO tasks (title, priority) VALUES ('Test Some Inserts', 1)";
match mysql().verified_stmt(sql) { match mysql().verified_stmt(sql) {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source, source,
@ -1499,7 +1499,7 @@ fn parse_replace_insert() {
replace_into, replace_into,
priority, priority,
.. ..
} => { }) => {
assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name); assert_eq!(ObjectName(vec![Ident::new("tasks")]), table_name);
assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns); assert_eq!(vec![Ident::new("title"), Ident::new("priority")], columns);
assert!(on.is_none()); assert!(on.is_none());
@ -1535,13 +1535,13 @@ fn parse_empty_row_insert() {
let sql = "INSERT INTO tb () VALUES (), ()"; let sql = "INSERT INTO tb () VALUES (), ()";
match mysql().one_statement_parses_to(sql, "INSERT INTO tb VALUES (), ()") { match mysql().one_statement_parses_to(sql, "INSERT INTO tb VALUES (), ()") {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source, source,
on, on,
.. ..
} => { }) => {
assert_eq!(ObjectName(vec![Ident::new("tb")]), table_name); assert_eq!(ObjectName(vec![Ident::new("tb")]), table_name);
assert!(columns.is_empty()); assert!(columns.is_empty());
assert!(on.is_none()); assert!(on.is_none());
@ -1572,13 +1572,13 @@ fn parse_insert_with_on_duplicate_update() {
let sql = "INSERT INTO permission_groups (name, description, perm_create, perm_read, perm_update, perm_delete) VALUES ('accounting_manager', 'Some description about the group', true, true, true, true) ON DUPLICATE KEY UPDATE description = VALUES(description), perm_create = VALUES(perm_create), perm_read = VALUES(perm_read), perm_update = VALUES(perm_update), perm_delete = VALUES(perm_delete)"; let sql = "INSERT INTO permission_groups (name, description, perm_create, perm_read, perm_update, perm_delete) VALUES ('accounting_manager', 'Some description about the group', true, true, true, true) ON DUPLICATE KEY UPDATE description = VALUES(description), perm_create = VALUES(perm_create), perm_read = VALUES(perm_read), perm_update = VALUES(perm_update), perm_delete = VALUES(perm_delete)";
match mysql().verified_stmt(sql) { match mysql().verified_stmt(sql) {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source, source,
on, on,
.. ..
} => { }) => {
assert_eq!( assert_eq!(
ObjectName(vec![Ident::new("permission_groups")]), ObjectName(vec![Ident::new("permission_groups")]),
table_name table_name
@ -1804,11 +1804,11 @@ fn parse_select_with_concatenation_of_exp_number_and_numeric_prefix_column() {
fn parse_insert_with_numeric_prefix_column_name() { fn parse_insert_with_numeric_prefix_column_name() {
let sql = "INSERT INTO s1.t1 (123col_$@length123) VALUES (67.654)"; let sql = "INSERT INTO s1.t1 (123col_$@length123) VALUES (67.654)";
match mysql().verified_stmt(sql) { match mysql().verified_stmt(sql) {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
.. ..
} => { }) => {
assert_eq!( assert_eq!(
ObjectName(vec![Ident::new("s1"), Ident::new("t1")]), ObjectName(vec![Ident::new("s1"), Ident::new("t1")]),
table_name table_name
@ -1898,7 +1898,7 @@ fn parse_update_with_joins() {
fn parse_delete_with_order_by() { fn parse_delete_with_order_by() {
let sql = "DELETE FROM customers ORDER BY id DESC"; let sql = "DELETE FROM customers ORDER BY id DESC";
match mysql().verified_stmt(sql) { match mysql().verified_stmt(sql) {
Statement::Delete { order_by, .. } => { Statement::Delete(Delete { order_by, .. }) => {
assert_eq!( assert_eq!(
vec![OrderByExpr { vec![OrderByExpr {
expr: Expr::Identifier(Ident { expr: Expr::Identifier(Ident {
@ -1919,7 +1919,7 @@ fn parse_delete_with_order_by() {
fn parse_delete_with_limit() { fn parse_delete_with_limit() {
let sql = "DELETE FROM customers LIMIT 100"; let sql = "DELETE FROM customers LIMIT 100";
match mysql().verified_stmt(sql) { match mysql().verified_stmt(sql) {
Statement::Delete { limit, .. } => { Statement::Delete(Delete { limit, .. }) => {
assert_eq!(Some(Expr::Value(number("100"))), limit); assert_eq!(Some(Expr::Value(number("100"))), limit);
} }
_ => unreachable!(), _ => unreachable!(),

View file

@ -1482,12 +1482,12 @@ fn parse_prepare() {
_ => unreachable!(), _ => unreachable!(),
}; };
match sub_stmt.as_ref() { match sub_stmt.as_ref() {
Statement::Insert { Statement::Insert(Insert {
table_name, table_name,
columns, columns,
source: Some(source), source: Some(source),
.. ..
} => { }) => {
assert_eq!(table_name.to_string(), "customers"); assert_eq!(table_name.to_string(), "customers");
assert!(columns.is_empty()); assert!(columns.is_empty());
@ -1539,14 +1539,14 @@ fn parse_pg_on_conflict() {
DO UPDATE SET dname = EXCLUDED.dname", DO UPDATE SET dname = EXCLUDED.dname",
); );
match stmt { match stmt {
Statement::Insert { Statement::Insert(Insert {
on: on:
Some(OnInsert::OnConflict(OnConflict { Some(OnInsert::OnConflict(OnConflict {
conflict_target: Some(ConflictTarget::Columns(cols)), conflict_target: Some(ConflictTarget::Columns(cols)),
action, action,
})), })),
.. ..
} => { }) => {
assert_eq!(vec![Ident::from("did")], cols); assert_eq!(vec![Ident::from("did")], cols);
assert_eq!( assert_eq!(
OnConflictAction::DoUpdate(DoUpdate { OnConflictAction::DoUpdate(DoUpdate {
@ -1569,14 +1569,14 @@ fn parse_pg_on_conflict() {
DO UPDATE SET dname = EXCLUDED.dname, area = EXCLUDED.area", DO UPDATE SET dname = EXCLUDED.dname, area = EXCLUDED.area",
); );
match stmt { match stmt {
Statement::Insert { Statement::Insert(Insert {
on: on:
Some(OnInsert::OnConflict(OnConflict { Some(OnInsert::OnConflict(OnConflict {
conflict_target: Some(ConflictTarget::Columns(cols)), conflict_target: Some(ConflictTarget::Columns(cols)),
action, action,
})), })),
.. ..
} => { }) => {
assert_eq!(vec![Ident::from("did"), Ident::from("area"),], cols); assert_eq!(vec![Ident::from("did"), Ident::from("area"),], cols);
assert_eq!( assert_eq!(
OnConflictAction::DoUpdate(DoUpdate { OnConflictAction::DoUpdate(DoUpdate {
@ -1607,14 +1607,14 @@ fn parse_pg_on_conflict() {
ON CONFLICT DO NOTHING", ON CONFLICT DO NOTHING",
); );
match stmt { match stmt {
Statement::Insert { Statement::Insert(Insert {
on: on:
Some(OnInsert::OnConflict(OnConflict { Some(OnInsert::OnConflict(OnConflict {
conflict_target: None, conflict_target: None,
action, action,
})), })),
.. ..
} => { }) => {
assert_eq!(OnConflictAction::DoNothing, action); assert_eq!(OnConflictAction::DoNothing, action);
} }
_ => unreachable!(), _ => unreachable!(),
@ -1627,14 +1627,14 @@ fn parse_pg_on_conflict() {
DO UPDATE SET dname = $1 WHERE dsize > $2", DO UPDATE SET dname = $1 WHERE dsize > $2",
); );
match stmt { match stmt {
Statement::Insert { Statement::Insert(Insert {
on: on:
Some(OnInsert::OnConflict(OnConflict { Some(OnInsert::OnConflict(OnConflict {
conflict_target: Some(ConflictTarget::Columns(cols)), conflict_target: Some(ConflictTarget::Columns(cols)),
action, action,
})), })),
.. ..
} => { }) => {
assert_eq!(vec![Ident::from("did")], cols); assert_eq!(vec![Ident::from("did")], cols);
assert_eq!( assert_eq!(
OnConflictAction::DoUpdate(DoUpdate { OnConflictAction::DoUpdate(DoUpdate {
@ -1664,14 +1664,14 @@ fn parse_pg_on_conflict() {
DO UPDATE SET dname = $1 WHERE dsize > $2", DO UPDATE SET dname = $1 WHERE dsize > $2",
); );
match stmt { match stmt {
Statement::Insert { Statement::Insert(Insert {
on: on:
Some(OnInsert::OnConflict(OnConflict { Some(OnInsert::OnConflict(OnConflict {
conflict_target: Some(ConflictTarget::OnConstraint(cname)), conflict_target: Some(ConflictTarget::OnConstraint(cname)),
action, action,
})), })),
.. ..
} => { }) => {
assert_eq!(vec![Ident::from("distributors_did_pkey")], cname.0); assert_eq!(vec![Ident::from("distributors_did_pkey")], cname.0);
assert_eq!( assert_eq!(
OnConflictAction::DoUpdate(DoUpdate { OnConflictAction::DoUpdate(DoUpdate {
@ -1701,7 +1701,7 @@ fn parse_pg_returning() {
"INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') RETURNING did", "INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') RETURNING did",
); );
match stmt { match stmt {
Statement::Insert { returning, .. } => { Statement::Insert(Insert { returning, .. }) => {
assert_eq!( assert_eq!(
Some(vec![SelectItem::UnnamedExpr(Expr::Identifier( Some(vec![SelectItem::UnnamedExpr(Expr::Identifier(
"did".into() "did".into()
@ -1739,7 +1739,7 @@ fn parse_pg_returning() {
let stmt = let stmt =
pg_and_generic().verified_stmt("DELETE FROM tasks WHERE status = 'DONE' RETURNING *"); pg_and_generic().verified_stmt("DELETE FROM tasks WHERE status = 'DONE' RETURNING *");
match stmt { match stmt {
Statement::Delete { returning, .. } => { Statement::Delete(Delete { returning, .. }) => {
assert_eq!( assert_eq!(
Some(vec![SelectItem::Wildcard( Some(vec![SelectItem::Wildcard(
WildcardAdditionalOptions::default() WildcardAdditionalOptions::default()
@ -3570,7 +3570,7 @@ fn test_simple_postgres_insert_with_alias() {
assert_eq!( assert_eq!(
statement, statement,
Statement::Insert { Statement::Insert(Insert {
or: None, or: None,
ignore: false, ignore: false,
into: true, into: true,
@ -3621,7 +3621,7 @@ fn test_simple_postgres_insert_with_alias() {
replace_into: false, replace_into: false,
priority: None, priority: None,
insert_alias: None insert_alias: None
} })
) )
} }
@ -3634,7 +3634,7 @@ fn test_simple_postgres_insert_with_alias() {
assert_eq!( assert_eq!(
statement, statement,
Statement::Insert { Statement::Insert(Insert {
or: None, or: None,
ignore: false, ignore: false,
into: true, into: true,
@ -3688,7 +3688,7 @@ fn test_simple_postgres_insert_with_alias() {
replace_into: false, replace_into: false,
priority: None, priority: None,
insert_alias: None insert_alias: None
} })
) )
} }
@ -3700,7 +3700,7 @@ fn test_simple_insert_with_quoted_alias() {
assert_eq!( assert_eq!(
statement, statement,
Statement::Insert { Statement::Insert(Insert {
or: None, or: None,
ignore: false, ignore: false,
into: true, into: true,
@ -3751,7 +3751,7 @@ fn test_simple_insert_with_quoted_alias() {
replace_into: false, replace_into: false,
priority: None, priority: None,
insert_alias: None, insert_alias: None,
} })
) )
} }