mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-27 16:09:09 +00:00
SET with a list of comma separated assignments (#1757)
This commit is contained in:
parent
3392623b00
commit
85f855150f
12 changed files with 564 additions and 375 deletions
361
src/ast/mod.rs
361
src/ast/mod.rs
|
@ -2394,6 +2394,168 @@ pub enum CreatePolicyCommand {
|
||||||
Delete,
|
Delete,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub enum Set {
|
||||||
|
/// SQL Standard-style
|
||||||
|
/// SET a = 1;
|
||||||
|
SingleAssignment {
|
||||||
|
local: bool,
|
||||||
|
hivevar: bool,
|
||||||
|
variable: ObjectName,
|
||||||
|
values: Vec<Expr>,
|
||||||
|
},
|
||||||
|
/// Snowflake-style
|
||||||
|
/// SET (a, b, ..) = (1, 2, ..);
|
||||||
|
ParenthesizedAssignments {
|
||||||
|
variables: Vec<ObjectName>,
|
||||||
|
values: Vec<Expr>,
|
||||||
|
},
|
||||||
|
/// MySQL-style
|
||||||
|
/// SET a = 1, b = 2, ..;
|
||||||
|
MultipleAssignments { assignments: Vec<SetAssignment> },
|
||||||
|
/// MS-SQL session
|
||||||
|
///
|
||||||
|
/// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
|
||||||
|
SetSessionParam(SetSessionParamKind),
|
||||||
|
/// ```sql
|
||||||
|
/// SET [ SESSION | LOCAL ] ROLE role_name
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
|
||||||
|
///
|
||||||
|
/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
|
||||||
|
/// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
|
||||||
|
/// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
|
||||||
|
/// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
|
||||||
|
SetRole {
|
||||||
|
/// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
|
||||||
|
context_modifier: ContextModifier,
|
||||||
|
/// Role name. If NONE is specified, then the current role name is removed.
|
||||||
|
role_name: Option<Ident>,
|
||||||
|
},
|
||||||
|
/// ```sql
|
||||||
|
/// SET TIME ZONE <value>
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Note: this is a PostgreSQL-specific statements
|
||||||
|
/// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
|
||||||
|
/// However, we allow it for all dialects.
|
||||||
|
SetTimeZone { local: bool, value: Expr },
|
||||||
|
/// ```sql
|
||||||
|
/// SET NAMES 'charset_name' [COLLATE 'collation_name']
|
||||||
|
/// ```
|
||||||
|
SetNames {
|
||||||
|
charset_name: Ident,
|
||||||
|
collation_name: Option<String>,
|
||||||
|
},
|
||||||
|
/// ```sql
|
||||||
|
/// SET NAMES DEFAULT
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Note: this is a MySQL-specific statement.
|
||||||
|
SetNamesDefault {},
|
||||||
|
/// ```sql
|
||||||
|
/// SET TRANSACTION ...
|
||||||
|
/// ```
|
||||||
|
SetTransaction {
|
||||||
|
modes: Vec<TransactionMode>,
|
||||||
|
snapshot: Option<Value>,
|
||||||
|
session: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Set {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::ParenthesizedAssignments { variables, values } => write!(
|
||||||
|
f,
|
||||||
|
"SET ({}) = ({})",
|
||||||
|
display_comma_separated(variables),
|
||||||
|
display_comma_separated(values)
|
||||||
|
),
|
||||||
|
Self::MultipleAssignments { assignments } => {
|
||||||
|
write!(f, "SET {}", display_comma_separated(assignments))
|
||||||
|
}
|
||||||
|
Self::SetRole {
|
||||||
|
context_modifier,
|
||||||
|
role_name,
|
||||||
|
} => {
|
||||||
|
let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
|
||||||
|
write!(f, "SET{context_modifier} ROLE {role_name}")
|
||||||
|
}
|
||||||
|
Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
|
||||||
|
Self::SetTransaction {
|
||||||
|
modes,
|
||||||
|
snapshot,
|
||||||
|
session,
|
||||||
|
} => {
|
||||||
|
if *session {
|
||||||
|
write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
|
||||||
|
} else {
|
||||||
|
write!(f, "SET TRANSACTION")?;
|
||||||
|
}
|
||||||
|
if !modes.is_empty() {
|
||||||
|
write!(f, " {}", display_comma_separated(modes))?;
|
||||||
|
}
|
||||||
|
if let Some(snapshot_id) = snapshot {
|
||||||
|
write!(f, " SNAPSHOT {snapshot_id}")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Self::SetTimeZone { local, value } => {
|
||||||
|
f.write_str("SET ")?;
|
||||||
|
if *local {
|
||||||
|
f.write_str("LOCAL ")?;
|
||||||
|
}
|
||||||
|
write!(f, "TIME ZONE {value}")
|
||||||
|
}
|
||||||
|
Self::SetNames {
|
||||||
|
charset_name,
|
||||||
|
collation_name,
|
||||||
|
} => {
|
||||||
|
write!(f, "SET NAMES {}", charset_name)?;
|
||||||
|
|
||||||
|
if let Some(collation) = collation_name {
|
||||||
|
f.write_str(" COLLATE ")?;
|
||||||
|
f.write_str(collation)?;
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Self::SetNamesDefault {} => {
|
||||||
|
f.write_str("SET NAMES DEFAULT")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Set::SingleAssignment {
|
||||||
|
local,
|
||||||
|
hivevar,
|
||||||
|
variable,
|
||||||
|
values,
|
||||||
|
} => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"SET {}{}{} = {}",
|
||||||
|
if *local { "LOCAL " } else { "" },
|
||||||
|
if *hivevar { "HIVEVAR:" } else { "" },
|
||||||
|
variable,
|
||||||
|
display_comma_separated(values)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a `Set` into a `Statement`.
|
||||||
|
/// Convenience function, instead of writing `Statement::Set(Set::Set...{...})`
|
||||||
|
impl From<Set> for Statement {
|
||||||
|
fn from(set: Set) -> Self {
|
||||||
|
Statement::Set(set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A top-level statement (SELECT, INSERT, CREATE, etc.)
|
/// A top-level statement (SELECT, INSERT, CREATE, etc.)
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
@ -2419,6 +2581,7 @@ pub enum Statement {
|
||||||
compute_statistics: bool,
|
compute_statistics: bool,
|
||||||
has_table_keyword: bool,
|
has_table_keyword: bool,
|
||||||
},
|
},
|
||||||
|
Set(Set),
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// TRUNCATE
|
/// TRUNCATE
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -2846,7 +3009,10 @@ pub enum Statement {
|
||||||
/// DROP CONNECTOR
|
/// DROP CONNECTOR
|
||||||
/// ```
|
/// ```
|
||||||
/// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
|
/// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
|
||||||
DropConnector { if_exists: bool, name: Ident },
|
DropConnector {
|
||||||
|
if_exists: bool,
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// DECLARE
|
/// DECLARE
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -2854,7 +3020,9 @@ pub enum Statement {
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific statement,
|
/// Note: this is a PostgreSQL-specific statement,
|
||||||
/// but may also compatible with other SQL.
|
/// but may also compatible with other SQL.
|
||||||
Declare { stmts: Vec<Declare> },
|
Declare {
|
||||||
|
stmts: Vec<Declare>,
|
||||||
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
|
/// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
|
||||||
/// [ WITH ] [ SCHEMA schema_name ]
|
/// [ WITH ] [ SCHEMA schema_name ]
|
||||||
|
@ -2916,67 +3084,23 @@ pub enum Statement {
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific statement,
|
/// Note: this is a PostgreSQL-specific statement,
|
||||||
/// but may also compatible with other SQL.
|
/// but may also compatible with other SQL.
|
||||||
Discard { object_type: DiscardObject },
|
Discard {
|
||||||
/// ```sql
|
object_type: DiscardObject,
|
||||||
/// SET [ SESSION | LOCAL ] ROLE role_name
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
|
|
||||||
///
|
|
||||||
/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
|
|
||||||
/// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
|
|
||||||
/// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
|
|
||||||
/// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
|
|
||||||
SetRole {
|
|
||||||
/// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
|
|
||||||
context_modifier: ContextModifier,
|
|
||||||
/// Role name. If NONE is specified, then the current role name is removed.
|
|
||||||
role_name: Option<Ident>,
|
|
||||||
},
|
},
|
||||||
/// ```sql
|
|
||||||
/// SET <variable> = expression;
|
|
||||||
/// SET (variable[, ...]) = (expression[, ...]);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Note: this is not a standard SQL statement, but it is supported by at
|
|
||||||
/// least MySQL and PostgreSQL. Not all MySQL-specific syntactic forms are
|
|
||||||
/// supported yet.
|
|
||||||
SetVariable {
|
|
||||||
local: bool,
|
|
||||||
hivevar: bool,
|
|
||||||
variables: OneOrManyWithParens<ObjectName>,
|
|
||||||
value: Vec<Expr>,
|
|
||||||
},
|
|
||||||
/// ```sql
|
|
||||||
/// SET TIME ZONE <value>
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Note: this is a PostgreSQL-specific statements
|
|
||||||
/// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
|
|
||||||
SetTimeZone { local: bool, value: Expr },
|
|
||||||
/// ```sql
|
|
||||||
/// SET NAMES 'charset_name' [COLLATE 'collation_name']
|
|
||||||
/// ```
|
|
||||||
SetNames {
|
|
||||||
charset_name: Ident,
|
|
||||||
collation_name: Option<String>,
|
|
||||||
},
|
|
||||||
/// ```sql
|
|
||||||
/// SET NAMES DEFAULT
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Note: this is a MySQL-specific statement.
|
|
||||||
SetNamesDefault {},
|
|
||||||
/// `SHOW FUNCTIONS`
|
/// `SHOW FUNCTIONS`
|
||||||
///
|
///
|
||||||
/// Note: this is a Presto-specific statement.
|
/// Note: this is a Presto-specific statement.
|
||||||
ShowFunctions { filter: Option<ShowStatementFilter> },
|
ShowFunctions {
|
||||||
|
filter: Option<ShowStatementFilter>,
|
||||||
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// SHOW <variable>
|
/// SHOW <variable>
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific statement.
|
/// Note: this is a PostgreSQL-specific statement.
|
||||||
ShowVariable { variable: Vec<Ident> },
|
ShowVariable {
|
||||||
|
variable: Vec<Ident>,
|
||||||
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
|
/// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -3060,7 +3184,9 @@ pub enum Statement {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Note: this is a MySQL-specific statement.
|
/// Note: this is a MySQL-specific statement.
|
||||||
ShowCollation { filter: Option<ShowStatementFilter> },
|
ShowCollation {
|
||||||
|
filter: Option<ShowStatementFilter>,
|
||||||
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// `USE ...`
|
/// `USE ...`
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -3103,14 +3229,6 @@ pub enum Statement {
|
||||||
has_end_keyword: bool,
|
has_end_keyword: bool,
|
||||||
},
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// SET TRANSACTION ...
|
|
||||||
/// ```
|
|
||||||
SetTransaction {
|
|
||||||
modes: Vec<TransactionMode>,
|
|
||||||
snapshot: Option<Value>,
|
|
||||||
session: bool,
|
|
||||||
},
|
|
||||||
/// ```sql
|
|
||||||
/// COMMENT ON ...
|
/// COMMENT ON ...
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -3329,7 +3447,10 @@ pub enum Statement {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific statement.
|
/// Note: this is a PostgreSQL-specific statement.
|
||||||
Deallocate { name: Ident, prepare: bool },
|
Deallocate {
|
||||||
|
name: Ident,
|
||||||
|
prepare: bool,
|
||||||
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// An `EXECUTE` statement
|
/// An `EXECUTE` statement
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -3415,11 +3536,15 @@ pub enum Statement {
|
||||||
/// SAVEPOINT
|
/// SAVEPOINT
|
||||||
/// ```
|
/// ```
|
||||||
/// Define a new savepoint within the current transaction
|
/// Define a new savepoint within the current transaction
|
||||||
Savepoint { name: Ident },
|
Savepoint {
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// RELEASE [ SAVEPOINT ] savepoint_name
|
/// RELEASE [ SAVEPOINT ] savepoint_name
|
||||||
/// ```
|
/// ```
|
||||||
ReleaseSavepoint { name: Ident },
|
ReleaseSavepoint {
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// A `MERGE` statement.
|
/// A `MERGE` statement.
|
||||||
///
|
///
|
||||||
/// ```sql
|
/// ```sql
|
||||||
|
@ -3499,7 +3624,9 @@ pub enum Statement {
|
||||||
/// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
|
/// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
|
||||||
/// ```
|
/// ```
|
||||||
/// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
|
/// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
|
||||||
LockTables { tables: Vec<LockTable> },
|
LockTables {
|
||||||
|
tables: Vec<LockTable>,
|
||||||
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// UNLOCK TABLES
|
/// UNLOCK TABLES
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -3533,14 +3660,18 @@ pub enum Statement {
|
||||||
/// listen for a notification channel
|
/// listen for a notification channel
|
||||||
///
|
///
|
||||||
/// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
|
/// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
|
||||||
LISTEN { channel: Ident },
|
LISTEN {
|
||||||
|
channel: Ident,
|
||||||
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// UNLISTEN
|
/// UNLISTEN
|
||||||
/// ```
|
/// ```
|
||||||
/// stop listening for a notification
|
/// stop listening for a notification
|
||||||
///
|
///
|
||||||
/// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
|
/// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
|
||||||
UNLISTEN { channel: Ident },
|
UNLISTEN {
|
||||||
|
channel: Ident,
|
||||||
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// NOTIFY channel [ , payload ]
|
/// NOTIFY channel [ , payload ]
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -3580,10 +3711,6 @@ pub enum Statement {
|
||||||
/// Snowflake `REMOVE`
|
/// Snowflake `REMOVE`
|
||||||
/// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
|
/// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
|
||||||
Remove(FileStagingCommand),
|
Remove(FileStagingCommand),
|
||||||
/// MS-SQL session
|
|
||||||
///
|
|
||||||
/// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
|
|
||||||
SetSessionParam(SetSessionParamKind),
|
|
||||||
/// RaiseError (MSSQL)
|
/// RaiseError (MSSQL)
|
||||||
/// RAISERROR ( { msg_id | msg_str | @local_variable }
|
/// RAISERROR ( { msg_id | msg_str | @local_variable }
|
||||||
/// { , severity , state }
|
/// { , severity , state }
|
||||||
|
@ -4644,59 +4771,7 @@ impl fmt::Display for Statement {
|
||||||
write!(f, "DISCARD {object_type}")?;
|
write!(f, "DISCARD {object_type}")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Self::SetRole {
|
Self::Set(set) => write!(f, "{set}"),
|
||||||
context_modifier,
|
|
||||||
role_name,
|
|
||||||
} => {
|
|
||||||
let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
|
|
||||||
write!(f, "SET{context_modifier} ROLE {role_name}")
|
|
||||||
}
|
|
||||||
Statement::SetVariable {
|
|
||||||
local,
|
|
||||||
variables,
|
|
||||||
hivevar,
|
|
||||||
value,
|
|
||||||
} => {
|
|
||||||
f.write_str("SET ")?;
|
|
||||||
if *local {
|
|
||||||
f.write_str("LOCAL ")?;
|
|
||||||
}
|
|
||||||
let parenthesized = matches!(variables, OneOrManyWithParens::Many(_));
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{hivevar}{name} = {l_paren}{value}{r_paren}",
|
|
||||||
hivevar = if *hivevar { "HIVEVAR:" } else { "" },
|
|
||||||
name = variables,
|
|
||||||
l_paren = parenthesized.then_some("(").unwrap_or_default(),
|
|
||||||
value = display_comma_separated(value),
|
|
||||||
r_paren = parenthesized.then_some(")").unwrap_or_default(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Statement::SetTimeZone { local, value } => {
|
|
||||||
f.write_str("SET ")?;
|
|
||||||
if *local {
|
|
||||||
f.write_str("LOCAL ")?;
|
|
||||||
}
|
|
||||||
write!(f, "TIME ZONE {value}")
|
|
||||||
}
|
|
||||||
Statement::SetNames {
|
|
||||||
charset_name,
|
|
||||||
collation_name,
|
|
||||||
} => {
|
|
||||||
write!(f, "SET NAMES {}", charset_name)?;
|
|
||||||
|
|
||||||
if let Some(collation) = collation_name {
|
|
||||||
f.write_str(" COLLATE ")?;
|
|
||||||
f.write_str(collation)?;
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Statement::SetNamesDefault {} => {
|
|
||||||
f.write_str("SET NAMES DEFAULT")?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Statement::ShowVariable { variable } => {
|
Statement::ShowVariable { variable } => {
|
||||||
write!(f, "SHOW")?;
|
write!(f, "SHOW")?;
|
||||||
if !variable.is_empty() {
|
if !variable.is_empty() {
|
||||||
|
@ -4885,24 +4960,6 @@ impl fmt::Display for Statement {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Statement::SetTransaction {
|
|
||||||
modes,
|
|
||||||
snapshot,
|
|
||||||
session,
|
|
||||||
} => {
|
|
||||||
if *session {
|
|
||||||
write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
|
|
||||||
} else {
|
|
||||||
write!(f, "SET TRANSACTION")?;
|
|
||||||
}
|
|
||||||
if !modes.is_empty() {
|
|
||||||
write!(f, " {}", display_comma_separated(modes))?;
|
|
||||||
}
|
|
||||||
if let Some(snapshot_id) = snapshot {
|
|
||||||
write!(f, " SNAPSHOT {snapshot_id}")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Statement::Commit {
|
Statement::Commit {
|
||||||
chain,
|
chain,
|
||||||
end: end_syntax,
|
end: end_syntax,
|
||||||
|
@ -5333,7 +5390,6 @@ impl fmt::Display for Statement {
|
||||||
|
|
||||||
Statement::List(command) => write!(f, "LIST {command}"),
|
Statement::List(command) => write!(f, "LIST {command}"),
|
||||||
Statement::Remove(command) => write!(f, "REMOVE {command}"),
|
Statement::Remove(command) => write!(f, "REMOVE {command}"),
|
||||||
Statement::SetSessionParam(kind) => write!(f, "SET {kind}"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5397,6 +5453,21 @@ impl fmt::Display for SequenceOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assignment for a `SET` statement (name [=|TO] value)
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub struct SetAssignment {
|
||||||
|
pub name: ObjectName,
|
||||||
|
pub value: Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SetAssignment {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{} = {}", self.name, self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Target of a `TRUNCATE TABLE` command
|
/// Target of a `TRUNCATE TABLE` command
|
||||||
///
|
///
|
||||||
/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
|
/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
|
||||||
|
|
|
@ -230,11 +230,7 @@ impl Spanned for Values {
|
||||||
/// - [Statement::Fetch]
|
/// - [Statement::Fetch]
|
||||||
/// - [Statement::Flush]
|
/// - [Statement::Flush]
|
||||||
/// - [Statement::Discard]
|
/// - [Statement::Discard]
|
||||||
/// - [Statement::SetRole]
|
/// - [Statement::Set]
|
||||||
/// - [Statement::SetVariable]
|
|
||||||
/// - [Statement::SetTimeZone]
|
|
||||||
/// - [Statement::SetNames]
|
|
||||||
/// - [Statement::SetNamesDefault]
|
|
||||||
/// - [Statement::ShowFunctions]
|
/// - [Statement::ShowFunctions]
|
||||||
/// - [Statement::ShowVariable]
|
/// - [Statement::ShowVariable]
|
||||||
/// - [Statement::ShowStatus]
|
/// - [Statement::ShowStatus]
|
||||||
|
@ -244,7 +240,6 @@ impl Spanned for Values {
|
||||||
/// - [Statement::ShowTables]
|
/// - [Statement::ShowTables]
|
||||||
/// - [Statement::ShowCollation]
|
/// - [Statement::ShowCollation]
|
||||||
/// - [Statement::StartTransaction]
|
/// - [Statement::StartTransaction]
|
||||||
/// - [Statement::SetTransaction]
|
|
||||||
/// - [Statement::Comment]
|
/// - [Statement::Comment]
|
||||||
/// - [Statement::Commit]
|
/// - [Statement::Commit]
|
||||||
/// - [Statement::Rollback]
|
/// - [Statement::Rollback]
|
||||||
|
@ -445,11 +440,7 @@ impl Spanned for Statement {
|
||||||
Statement::Fetch { .. } => Span::empty(),
|
Statement::Fetch { .. } => Span::empty(),
|
||||||
Statement::Flush { .. } => Span::empty(),
|
Statement::Flush { .. } => Span::empty(),
|
||||||
Statement::Discard { .. } => Span::empty(),
|
Statement::Discard { .. } => Span::empty(),
|
||||||
Statement::SetRole { .. } => Span::empty(),
|
Statement::Set(_) => Span::empty(),
|
||||||
Statement::SetVariable { .. } => Span::empty(),
|
|
||||||
Statement::SetTimeZone { .. } => Span::empty(),
|
|
||||||
Statement::SetNames { .. } => Span::empty(),
|
|
||||||
Statement::SetNamesDefault {} => Span::empty(),
|
|
||||||
Statement::ShowFunctions { .. } => Span::empty(),
|
Statement::ShowFunctions { .. } => Span::empty(),
|
||||||
Statement::ShowVariable { .. } => Span::empty(),
|
Statement::ShowVariable { .. } => Span::empty(),
|
||||||
Statement::ShowStatus { .. } => Span::empty(),
|
Statement::ShowStatus { .. } => Span::empty(),
|
||||||
|
@ -460,7 +451,6 @@ impl Spanned for Statement {
|
||||||
Statement::ShowCollation { .. } => Span::empty(),
|
Statement::ShowCollation { .. } => Span::empty(),
|
||||||
Statement::Use(u) => u.span(),
|
Statement::Use(u) => u.span(),
|
||||||
Statement::StartTransaction { .. } => Span::empty(),
|
Statement::StartTransaction { .. } => Span::empty(),
|
||||||
Statement::SetTransaction { .. } => Span::empty(),
|
|
||||||
Statement::Comment { .. } => Span::empty(),
|
Statement::Comment { .. } => Span::empty(),
|
||||||
Statement::Commit { .. } => Span::empty(),
|
Statement::Commit { .. } => Span::empty(),
|
||||||
Statement::Rollback { .. } => Span::empty(),
|
Statement::Rollback { .. } => Span::empty(),
|
||||||
|
@ -509,7 +499,6 @@ impl Spanned for Statement {
|
||||||
Statement::RenameTable { .. } => Span::empty(),
|
Statement::RenameTable { .. } => Span::empty(),
|
||||||
Statement::RaisError { .. } => Span::empty(),
|
Statement::RaisError { .. } => Span::empty(),
|
||||||
Statement::List(..) | Statement::Remove(..) => Span::empty(),
|
Statement::List(..) | Statement::Remove(..) => Span::empty(),
|
||||||
Statement::SetSessionParam { .. } => Span::empty(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -399,6 +399,16 @@ pub trait Dialect: Debug + Any {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the dialect supports multiple `SET` statements
|
||||||
|
/// in a single statement.
|
||||||
|
///
|
||||||
|
/// ```sql
|
||||||
|
/// SET variable = expression [, variable = expression];
|
||||||
|
/// ```
|
||||||
|
fn supports_comma_separated_set_assignments(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the dialect supports an `EXCEPT` clause following a
|
/// Returns true if the dialect supports an `EXCEPT` clause following a
|
||||||
/// wildcard in a select list.
|
/// wildcard in a select list.
|
||||||
///
|
///
|
||||||
|
|
|
@ -82,6 +82,7 @@ impl Dialect for MsSqlDialect {
|
||||||
fn supports_start_transaction_modifier(&self) -> bool {
|
fn supports_start_transaction_modifier(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn supports_end_transaction_modifier(&self) -> bool {
|
fn supports_end_transaction_modifier(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,10 @@ impl Dialect for MySqlDialect {
|
||||||
fn supports_set_names(&self) -> bool {
|
fn supports_set_names(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn supports_comma_separated_set_assignments(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `LOCK TABLES`
|
/// `LOCK TABLES`
|
||||||
|
|
|
@ -173,6 +173,7 @@ define_keywords!(
|
||||||
CHANNEL,
|
CHANNEL,
|
||||||
CHAR,
|
CHAR,
|
||||||
CHARACTER,
|
CHARACTER,
|
||||||
|
CHARACTERISTICS,
|
||||||
CHARACTERS,
|
CHARACTERS,
|
||||||
CHARACTER_LENGTH,
|
CHARACTER_LENGTH,
|
||||||
CHARSET,
|
CHARSET,
|
||||||
|
@ -557,6 +558,7 @@ define_keywords!(
|
||||||
MULTISET,
|
MULTISET,
|
||||||
MUTATION,
|
MUTATION,
|
||||||
NAME,
|
NAME,
|
||||||
|
NAMES,
|
||||||
NANOSECOND,
|
NANOSECOND,
|
||||||
NANOSECONDS,
|
NANOSECONDS,
|
||||||
NATIONAL,
|
NATIONAL,
|
||||||
|
|
|
@ -4314,7 +4314,8 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run a parser method `f`, reverting back to the current position if unsuccessful.
|
/// Run a parser method `f`, reverting back to the current position if unsuccessful.
|
||||||
/// Returns `None` if `f` returns an error
|
/// Returns `ParserError::RecursionLimitExceeded` if `f` returns a `RecursionLimitExceeded`.
|
||||||
|
/// Returns `Ok(None)` if `f` returns any other error.
|
||||||
pub fn maybe_parse<T, F>(&mut self, f: F) -> Result<Option<T>, ParserError>
|
pub fn maybe_parse<T, F>(&mut self, f: F) -> Result<Option<T>, ParserError>
|
||||||
where
|
where
|
||||||
F: FnMut(&mut Parser) -> Result<T, ParserError>,
|
F: FnMut(&mut Parser) -> Result<T, ParserError>,
|
||||||
|
@ -10978,47 +10979,108 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
Some(self.parse_identifier()?)
|
Some(self.parse_identifier()?)
|
||||||
};
|
};
|
||||||
Ok(Statement::SetRole {
|
Ok(Statement::Set(Set::SetRole {
|
||||||
context_modifier,
|
context_modifier,
|
||||||
role_name,
|
role_name,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_set(&mut self) -> Result<Statement, ParserError> {
|
fn parse_set_values(
|
||||||
let modifier =
|
&mut self,
|
||||||
self.parse_one_of_keywords(&[Keyword::SESSION, Keyword::LOCAL, Keyword::HIVEVAR]);
|
parenthesized_assignment: bool,
|
||||||
if let Some(Keyword::HIVEVAR) = modifier {
|
) -> Result<Vec<Expr>, ParserError> {
|
||||||
self.expect_token(&Token::Colon)?;
|
let mut values = vec![];
|
||||||
} else if let Some(set_role_stmt) =
|
|
||||||
self.maybe_parse(|parser| parser.parse_set_role(modifier))?
|
if parenthesized_assignment {
|
||||||
{
|
self.expect_token(&Token::LParen)?;
|
||||||
return Ok(set_role_stmt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let variables = if self.parse_keywords(&[Keyword::TIME, Keyword::ZONE]) {
|
loop {
|
||||||
OneOrManyWithParens::One(ObjectName::from(vec!["TIMEZONE".into()]))
|
let value = if let Some(expr) = self.try_parse_expr_sub_query()? {
|
||||||
} else if self.dialect.supports_parenthesized_set_variables()
|
expr
|
||||||
|
} else if let Ok(expr) = self.parse_expr() {
|
||||||
|
expr
|
||||||
|
} else {
|
||||||
|
self.expected("variable value", self.peek_token())?
|
||||||
|
};
|
||||||
|
|
||||||
|
values.push(value);
|
||||||
|
if self.consume_token(&Token::Comma) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if parenthesized_assignment {
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
}
|
||||||
|
return Ok(values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_set_assignment(
|
||||||
|
&mut self,
|
||||||
|
) -> Result<(OneOrManyWithParens<ObjectName>, Expr), ParserError> {
|
||||||
|
let variables = if self.dialect.supports_parenthesized_set_variables()
|
||||||
&& self.consume_token(&Token::LParen)
|
&& self.consume_token(&Token::LParen)
|
||||||
{
|
{
|
||||||
let variables = OneOrManyWithParens::Many(
|
let vars = OneOrManyWithParens::Many(
|
||||||
self.parse_comma_separated(|parser: &mut Parser<'a>| parser.parse_identifier())?
|
self.parse_comma_separated(|parser: &mut Parser<'a>| parser.parse_identifier())?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|ident| ObjectName::from(vec![ident]))
|
.map(|ident| ObjectName::from(vec![ident]))
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
self.expect_token(&Token::RParen)?;
|
self.expect_token(&Token::RParen)?;
|
||||||
variables
|
vars
|
||||||
} else {
|
} else {
|
||||||
OneOrManyWithParens::One(self.parse_object_name(false)?)
|
OneOrManyWithParens::One(self.parse_object_name(false)?)
|
||||||
};
|
};
|
||||||
|
|
||||||
let names = matches!(&variables, OneOrManyWithParens::One(variable) if variable.to_string().eq_ignore_ascii_case("NAMES"));
|
if !(self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO)) {
|
||||||
|
return self.expected("assignment operator", self.peek_token());
|
||||||
|
}
|
||||||
|
|
||||||
if names && self.dialect.supports_set_names() {
|
let values = self.parse_expr()?;
|
||||||
if self.parse_keyword(Keyword::DEFAULT) {
|
|
||||||
return Ok(Statement::SetNamesDefault {});
|
Ok((variables, values))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_set(&mut self) -> Result<Statement, ParserError> {
|
||||||
|
let modifier =
|
||||||
|
self.parse_one_of_keywords(&[Keyword::SESSION, Keyword::LOCAL, Keyword::HIVEVAR]);
|
||||||
|
|
||||||
|
if let Some(Keyword::HIVEVAR) = modifier {
|
||||||
|
self.expect_token(&Token::Colon)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(set_role_stmt) = self.maybe_parse(|parser| parser.parse_set_role(modifier))? {
|
||||||
|
return Ok(set_role_stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle special cases first
|
||||||
|
if self.parse_keywords(&[Keyword::TIME, Keyword::ZONE])
|
||||||
|
|| self.parse_keyword(Keyword::TIMEZONE)
|
||||||
|
{
|
||||||
|
if self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO) {
|
||||||
|
return Ok(Set::SingleAssignment {
|
||||||
|
local: modifier == Some(Keyword::LOCAL),
|
||||||
|
hivevar: modifier == Some(Keyword::HIVEVAR),
|
||||||
|
variable: ObjectName::from(vec!["TIMEZONE".into()]),
|
||||||
|
values: self.parse_set_values(false)?,
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
} else {
|
||||||
|
// A shorthand alias for SET TIME ZONE that doesn't require
|
||||||
|
// the assignment operator. It's originally PostgreSQL specific,
|
||||||
|
// but we allow it for all the dialects
|
||||||
|
return Ok(Set::SetTimeZone {
|
||||||
|
local: modifier == Some(Keyword::LOCAL),
|
||||||
|
value: self.parse_expr()?,
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
} else if self.dialect.supports_set_names() && self.parse_keyword(Keyword::NAMES) {
|
||||||
|
if self.parse_keyword(Keyword::DEFAULT) {
|
||||||
|
return Ok(Set::SetNamesDefault {}.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let charset_name = self.parse_identifier()?;
|
let charset_name = self.parse_identifier()?;
|
||||||
let collation_name = if self.parse_one_of_keywords(&[Keyword::COLLATE]).is_some() {
|
let collation_name = if self.parse_one_of_keywords(&[Keyword::COLLATE]).is_some() {
|
||||||
Some(self.parse_literal_string()?)
|
Some(self.parse_literal_string()?)
|
||||||
|
@ -11026,86 +11088,117 @@ impl<'a> Parser<'a> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(Statement::SetNames {
|
return Ok(Set::SetNames {
|
||||||
charset_name,
|
charset_name,
|
||||||
collation_name,
|
collation_name,
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let parenthesized_assignment = matches!(&variables, OneOrManyWithParens::Many(_));
|
|
||||||
|
|
||||||
if self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO) {
|
|
||||||
if parenthesized_assignment {
|
|
||||||
self.expect_token(&Token::LParen)?;
|
|
||||||
}
|
}
|
||||||
|
.into());
|
||||||
let mut values = vec![];
|
} else if self.parse_keyword(Keyword::CHARACTERISTICS) {
|
||||||
loop {
|
|
||||||
let value = if let Some(expr) = self.try_parse_expr_sub_query()? {
|
|
||||||
expr
|
|
||||||
} else if let Ok(expr) = self.parse_expr() {
|
|
||||||
expr
|
|
||||||
} else {
|
|
||||||
self.expected("variable value", self.peek_token())?
|
|
||||||
};
|
|
||||||
|
|
||||||
values.push(value);
|
|
||||||
if self.consume_token(&Token::Comma) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if parenthesized_assignment {
|
|
||||||
self.expect_token(&Token::RParen)?;
|
|
||||||
}
|
|
||||||
return Ok(Statement::SetVariable {
|
|
||||||
local: modifier == Some(Keyword::LOCAL),
|
|
||||||
hivevar: Some(Keyword::HIVEVAR) == modifier,
|
|
||||||
variables,
|
|
||||||
value: values,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let OneOrManyWithParens::One(variable) = variables else {
|
|
||||||
return self.expected("set variable", self.peek_token());
|
|
||||||
};
|
|
||||||
|
|
||||||
if variable.to_string().eq_ignore_ascii_case("TIMEZONE") {
|
|
||||||
// for some db (e.g. postgresql), SET TIME ZONE <value> is an alias for SET TIMEZONE [TO|=] <value>
|
|
||||||
match self.parse_expr() {
|
|
||||||
Ok(expr) => Ok(Statement::SetTimeZone {
|
|
||||||
local: modifier == Some(Keyword::LOCAL),
|
|
||||||
value: expr,
|
|
||||||
}),
|
|
||||||
_ => self.expected("timezone value", self.peek_token())?,
|
|
||||||
}
|
|
||||||
} else if variable.to_string() == "CHARACTERISTICS" {
|
|
||||||
self.expect_keywords(&[Keyword::AS, Keyword::TRANSACTION])?;
|
self.expect_keywords(&[Keyword::AS, Keyword::TRANSACTION])?;
|
||||||
Ok(Statement::SetTransaction {
|
return Ok(Set::SetTransaction {
|
||||||
modes: self.parse_transaction_modes()?,
|
modes: self.parse_transaction_modes()?,
|
||||||
snapshot: None,
|
snapshot: None,
|
||||||
session: true,
|
session: true,
|
||||||
})
|
}
|
||||||
} else if variable.to_string() == "TRANSACTION" && modifier.is_none() {
|
.into());
|
||||||
|
} else if self.parse_keyword(Keyword::TRANSACTION) {
|
||||||
if self.parse_keyword(Keyword::SNAPSHOT) {
|
if self.parse_keyword(Keyword::SNAPSHOT) {
|
||||||
let snapshot_id = self.parse_value()?.value;
|
let snapshot_id = self.parse_value()?.value;
|
||||||
return Ok(Statement::SetTransaction {
|
return Ok(Set::SetTransaction {
|
||||||
modes: vec![],
|
modes: vec![],
|
||||||
snapshot: Some(snapshot_id),
|
snapshot: Some(snapshot_id),
|
||||||
session: false,
|
session: false,
|
||||||
});
|
}
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
Ok(Statement::SetTransaction {
|
return Ok(Set::SetTransaction {
|
||||||
modes: self.parse_transaction_modes()?,
|
modes: self.parse_transaction_modes()?,
|
||||||
snapshot: None,
|
snapshot: None,
|
||||||
session: false,
|
session: false,
|
||||||
})
|
}
|
||||||
} else if self.dialect.supports_set_stmt_without_operator() {
|
.into());
|
||||||
self.prev_token();
|
|
||||||
self.parse_set_session_params()
|
|
||||||
} else {
|
|
||||||
self.expected("equals sign or TO", self.peek_token())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.dialect.supports_comma_separated_set_assignments() {
|
||||||
|
if let Some(assignments) = self
|
||||||
|
.maybe_parse(|parser| parser.parse_comma_separated(Parser::parse_set_assignment))?
|
||||||
|
{
|
||||||
|
return if assignments.len() > 1 {
|
||||||
|
let assignments = assignments
|
||||||
|
.into_iter()
|
||||||
|
.map(|(var, val)| match var {
|
||||||
|
OneOrManyWithParens::One(v) => Ok(SetAssignment {
|
||||||
|
name: v,
|
||||||
|
value: val,
|
||||||
|
}),
|
||||||
|
OneOrManyWithParens::Many(_) => {
|
||||||
|
self.expected("List of single identifiers", self.peek_token())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
|
Ok(Set::MultipleAssignments { assignments }.into())
|
||||||
|
} else {
|
||||||
|
let (vars, values): (Vec<_>, Vec<_>) = assignments.into_iter().unzip();
|
||||||
|
|
||||||
|
let variable = match vars.into_iter().next() {
|
||||||
|
Some(OneOrManyWithParens::One(v)) => Ok(v),
|
||||||
|
Some(OneOrManyWithParens::Many(_)) => self.expected(
|
||||||
|
"Single assignment or list of assignments",
|
||||||
|
self.peek_token(),
|
||||||
|
),
|
||||||
|
None => self.expected("At least one identifier", self.peek_token()),
|
||||||
|
}?;
|
||||||
|
|
||||||
|
Ok(Set::SingleAssignment {
|
||||||
|
local: modifier == Some(Keyword::LOCAL),
|
||||||
|
hivevar: modifier == Some(Keyword::HIVEVAR),
|
||||||
|
variable,
|
||||||
|
values,
|
||||||
|
}
|
||||||
|
.into())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let variables = if self.dialect.supports_parenthesized_set_variables()
|
||||||
|
&& self.consume_token(&Token::LParen)
|
||||||
|
{
|
||||||
|
let vars = OneOrManyWithParens::Many(
|
||||||
|
self.parse_comma_separated(|parser: &mut Parser<'a>| parser.parse_identifier())?
|
||||||
|
.into_iter()
|
||||||
|
.map(|ident| ObjectName::from(vec![ident]))
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
vars
|
||||||
|
} else {
|
||||||
|
OneOrManyWithParens::One(self.parse_object_name(false)?)
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO) {
|
||||||
|
let stmt = match variables {
|
||||||
|
OneOrManyWithParens::One(var) => Set::SingleAssignment {
|
||||||
|
local: modifier == Some(Keyword::LOCAL),
|
||||||
|
hivevar: modifier == Some(Keyword::HIVEVAR),
|
||||||
|
variable: var,
|
||||||
|
values: self.parse_set_values(false)?,
|
||||||
|
},
|
||||||
|
OneOrManyWithParens::Many(vars) => Set::ParenthesizedAssignments {
|
||||||
|
variables: vars,
|
||||||
|
values: self.parse_set_values(true)?,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(stmt.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.dialect.supports_set_stmt_without_operator() {
|
||||||
|
self.prev_token();
|
||||||
|
return self.parse_set_session_params();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.expected("equals sign or TO", self.peek_token())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_set_session_params(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_set_session_params(&mut self) -> Result<Statement, ParserError> {
|
||||||
|
@ -11123,15 +11216,20 @@ impl<'a> Parser<'a> {
|
||||||
_ => return self.expected("IO, PROFILE, TIME or XML", self.peek_token()),
|
_ => return self.expected("IO, PROFILE, TIME or XML", self.peek_token()),
|
||||||
};
|
};
|
||||||
let value = self.parse_session_param_value()?;
|
let value = self.parse_session_param_value()?;
|
||||||
Ok(Statement::SetSessionParam(SetSessionParamKind::Statistics(
|
Ok(
|
||||||
SetSessionParamStatistics { topic, value },
|
Set::SetSessionParam(SetSessionParamKind::Statistics(SetSessionParamStatistics {
|
||||||
)))
|
topic,
|
||||||
|
value,
|
||||||
|
}))
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
} else if self.parse_keyword(Keyword::IDENTITY_INSERT) {
|
} else if self.parse_keyword(Keyword::IDENTITY_INSERT) {
|
||||||
let obj = self.parse_object_name(false)?;
|
let obj = self.parse_object_name(false)?;
|
||||||
let value = self.parse_session_param_value()?;
|
let value = self.parse_session_param_value()?;
|
||||||
Ok(Statement::SetSessionParam(
|
Ok(Set::SetSessionParam(SetSessionParamKind::IdentityInsert(
|
||||||
SetSessionParamKind::IdentityInsert(SetSessionParamIdentityInsert { obj, value }),
|
SetSessionParamIdentityInsert { obj, value },
|
||||||
))
|
))
|
||||||
|
.into())
|
||||||
} else if self.parse_keyword(Keyword::OFFSETS) {
|
} else if self.parse_keyword(Keyword::OFFSETS) {
|
||||||
let keywords = self.parse_comma_separated(|parser| {
|
let keywords = self.parse_comma_separated(|parser| {
|
||||||
let next_token = parser.next_token();
|
let next_token = parser.next_token();
|
||||||
|
@ -11141,9 +11239,13 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
let value = self.parse_session_param_value()?;
|
let value = self.parse_session_param_value()?;
|
||||||
Ok(Statement::SetSessionParam(SetSessionParamKind::Offsets(
|
Ok(
|
||||||
SetSessionParamOffsets { keywords, value },
|
Set::SetSessionParam(SetSessionParamKind::Offsets(SetSessionParamOffsets {
|
||||||
)))
|
keywords,
|
||||||
|
value,
|
||||||
|
}))
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
let names = self.parse_comma_separated(|parser| {
|
let names = self.parse_comma_separated(|parser| {
|
||||||
let next_token = parser.next_token();
|
let next_token = parser.next_token();
|
||||||
|
@ -11153,9 +11255,13 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
let value = self.parse_expr()?.to_string();
|
let value = self.parse_expr()?.to_string();
|
||||||
Ok(Statement::SetSessionParam(SetSessionParamKind::Generic(
|
Ok(
|
||||||
SetSessionParamGeneric { names, value },
|
Set::SetSessionParam(SetSessionParamKind::Generic(SetSessionParamGeneric {
|
||||||
)))
|
names,
|
||||||
|
value,
|
||||||
|
}))
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8555,11 +8555,11 @@ fn parse_set_transaction() {
|
||||||
// TRANSACTION, so no need to duplicate the tests here. We just do a quick
|
// TRANSACTION, so no need to duplicate the tests here. We just do a quick
|
||||||
// sanity check.
|
// sanity check.
|
||||||
match verified_stmt("SET TRANSACTION READ ONLY, READ WRITE, ISOLATION LEVEL SERIALIZABLE") {
|
match verified_stmt("SET TRANSACTION READ ONLY, READ WRITE, ISOLATION LEVEL SERIALIZABLE") {
|
||||||
Statement::SetTransaction {
|
Statement::Set(Set::SetTransaction {
|
||||||
modes,
|
modes,
|
||||||
session,
|
session,
|
||||||
snapshot,
|
snapshot,
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
modes,
|
modes,
|
||||||
vec![
|
vec![
|
||||||
|
@ -8578,20 +8578,17 @@ fn parse_set_transaction() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_set_variable() {
|
fn parse_set_variable() {
|
||||||
match verified_stmt("SET SOMETHING = '1'") {
|
match verified_stmt("SET SOMETHING = '1'") {
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local,
|
local,
|
||||||
hivevar,
|
hivevar,
|
||||||
variables,
|
variable,
|
||||||
value,
|
values,
|
||||||
} => {
|
}) => {
|
||||||
assert!(!local);
|
assert!(!local);
|
||||||
assert!(!hivevar);
|
assert!(!hivevar);
|
||||||
|
assert_eq!(variable, ObjectName::from(vec!["SOMETHING".into()]));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
variables,
|
values,
|
||||||
OneOrManyWithParens::One(ObjectName::from(vec!["SOMETHING".into()]))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
value,
|
|
||||||
vec![Expr::Value(
|
vec![Expr::Value(
|
||||||
(Value::SingleQuotedString("1".into())).with_empty_span()
|
(Value::SingleQuotedString("1".into())).with_empty_span()
|
||||||
)]
|
)]
|
||||||
|
@ -8603,24 +8600,17 @@ fn parse_set_variable() {
|
||||||
let multi_variable_dialects = all_dialects_where(|d| d.supports_parenthesized_set_variables());
|
let multi_variable_dialects = all_dialects_where(|d| d.supports_parenthesized_set_variables());
|
||||||
let sql = r#"SET (a, b, c) = (1, 2, 3)"#;
|
let sql = r#"SET (a, b, c) = (1, 2, 3)"#;
|
||||||
match multi_variable_dialects.verified_stmt(sql) {
|
match multi_variable_dialects.verified_stmt(sql) {
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::ParenthesizedAssignments { variables, values }) => {
|
||||||
local,
|
|
||||||
hivevar,
|
|
||||||
variables,
|
|
||||||
value,
|
|
||||||
} => {
|
|
||||||
assert!(!local);
|
|
||||||
assert!(!hivevar);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
variables,
|
variables,
|
||||||
OneOrManyWithParens::Many(vec![
|
vec![
|
||||||
ObjectName::from(vec!["a".into()]),
|
ObjectName::from(vec!["a".into()]),
|
||||||
ObjectName::from(vec!["b".into()]),
|
ObjectName::from(vec!["b".into()]),
|
||||||
ObjectName::from(vec!["c".into()]),
|
ObjectName::from(vec!["c".into()]),
|
||||||
])
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
value,
|
values,
|
||||||
vec![
|
vec![
|
||||||
Expr::value(number("1")),
|
Expr::value(number("1")),
|
||||||
Expr::value(number("2")),
|
Expr::value(number("2")),
|
||||||
|
@ -8680,20 +8670,17 @@ fn parse_set_variable() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_set_role_as_variable() {
|
fn parse_set_role_as_variable() {
|
||||||
match verified_stmt("SET role = 'foobar'") {
|
match verified_stmt("SET role = 'foobar'") {
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local,
|
local,
|
||||||
hivevar,
|
hivevar,
|
||||||
variables,
|
variable,
|
||||||
value,
|
values,
|
||||||
} => {
|
}) => {
|
||||||
assert!(!local);
|
assert!(!local);
|
||||||
assert!(!hivevar);
|
assert!(!hivevar);
|
||||||
|
assert_eq!(variable, ObjectName::from(vec!["role".into()]));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
variables,
|
values,
|
||||||
OneOrManyWithParens::One(ObjectName::from(vec!["role".into()]))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
value,
|
|
||||||
vec![Expr::Value(
|
vec![Expr::Value(
|
||||||
(Value::SingleQuotedString("foobar".into())).with_empty_span()
|
(Value::SingleQuotedString("foobar".into())).with_empty_span()
|
||||||
)]
|
)]
|
||||||
|
@ -8730,20 +8717,17 @@ fn parse_double_colon_cast_at_timezone() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_set_time_zone() {
|
fn parse_set_time_zone() {
|
||||||
match verified_stmt("SET TIMEZONE = 'UTC'") {
|
match verified_stmt("SET TIMEZONE = 'UTC'") {
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local,
|
local,
|
||||||
hivevar,
|
hivevar,
|
||||||
variables: variable,
|
variable,
|
||||||
value,
|
values,
|
||||||
} => {
|
}) => {
|
||||||
assert!(!local);
|
assert!(!local);
|
||||||
assert!(!hivevar);
|
assert!(!hivevar);
|
||||||
|
assert_eq!(variable, ObjectName::from(vec!["TIMEZONE".into()]));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
variable,
|
values,
|
||||||
OneOrManyWithParens::One(ObjectName::from(vec!["TIMEZONE".into()]))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
value,
|
|
||||||
vec![Expr::Value(
|
vec![Expr::Value(
|
||||||
(Value::SingleQuotedString("UTC".into())).with_empty_span()
|
(Value::SingleQuotedString("UTC".into())).with_empty_span()
|
||||||
)]
|
)]
|
||||||
|
@ -8755,20 +8739,6 @@ fn parse_set_time_zone() {
|
||||||
one_statement_parses_to("SET TIME ZONE TO 'UTC'", "SET TIMEZONE = 'UTC'");
|
one_statement_parses_to("SET TIME ZONE TO 'UTC'", "SET TIMEZONE = 'UTC'");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parse_set_time_zone_alias() {
|
|
||||||
match verified_stmt("SET TIME ZONE 'UTC'") {
|
|
||||||
Statement::SetTimeZone { local, value } => {
|
|
||||||
assert!(!local);
|
|
||||||
assert_eq!(
|
|
||||||
value,
|
|
||||||
Expr::Value((Value::SingleQuotedString("UTC".into())).with_empty_span())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_commit() {
|
fn parse_commit() {
|
||||||
match verified_stmt("COMMIT") {
|
match verified_stmt("COMMIT") {
|
||||||
|
@ -14681,3 +14651,44 @@ fn parse_set_names() {
|
||||||
dialects.verified_stmt("SET NAMES 'utf8'");
|
dialects.verified_stmt("SET NAMES 'utf8'");
|
||||||
dialects.verified_stmt("SET NAMES UTF8 COLLATE bogus");
|
dialects.verified_stmt("SET NAMES UTF8 COLLATE bogus");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_multiple_set_statements() -> Result<(), ParserError> {
|
||||||
|
let dialects = all_dialects_where(|d| d.supports_comma_separated_set_assignments());
|
||||||
|
let stmt = dialects.verified_stmt("SET @a = 1, b = 2");
|
||||||
|
|
||||||
|
match stmt {
|
||||||
|
Statement::Set(Set::MultipleAssignments { assignments }) => {
|
||||||
|
assert_eq!(
|
||||||
|
assignments,
|
||||||
|
vec![
|
||||||
|
SetAssignment {
|
||||||
|
name: ObjectName::from(vec!["@a".into()]),
|
||||||
|
value: Expr::value(number("1"))
|
||||||
|
},
|
||||||
|
SetAssignment {
|
||||||
|
name: ObjectName::from(vec!["b".into()]),
|
||||||
|
value: Expr::value(number("2"))
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => panic!("Expected SetVariable with 2 variables and 2 values"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_set_time_zone_alias() {
|
||||||
|
match all_dialects().verified_stmt("SET TIME ZONE 'UTC'") {
|
||||||
|
Statement::Set(Set::SetTimeZone { local, value }) => {
|
||||||
|
assert!(!local);
|
||||||
|
assert_eq!(
|
||||||
|
value,
|
||||||
|
Expr::Value((Value::SingleQuotedString("UTC".into())).with_empty_span())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,9 +22,8 @@
|
||||||
|
|
||||||
use sqlparser::ast::{
|
use sqlparser::ast::{
|
||||||
ClusteredBy, CommentDef, CreateFunction, CreateFunctionBody, CreateFunctionUsing, CreateTable,
|
ClusteredBy, CommentDef, CreateFunction, CreateFunctionBody, CreateFunctionUsing, CreateTable,
|
||||||
Expr, Function, FunctionArgumentList, FunctionArguments, Ident, ObjectName,
|
Expr, Function, FunctionArgumentList, FunctionArguments, Ident, ObjectName, OrderByExpr,
|
||||||
OneOrManyWithParens, OrderByExpr, OrderByOptions, SelectItem, Statement, TableFactor,
|
OrderByOptions, SelectItem, Set, Statement, TableFactor, UnaryOperator, Use, Value,
|
||||||
UnaryOperator, Use, Value,
|
|
||||||
};
|
};
|
||||||
use sqlparser::dialect::{GenericDialect, HiveDialect, MsSqlDialect};
|
use sqlparser::dialect::{GenericDialect, HiveDialect, MsSqlDialect};
|
||||||
use sqlparser::parser::ParserError;
|
use sqlparser::parser::ParserError;
|
||||||
|
@ -92,7 +91,7 @@ fn parse_msck() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_set() {
|
fn parse_set_hivevar() {
|
||||||
let set = "SET HIVEVAR:name = a, b, c_d";
|
let set = "SET HIVEVAR:name = a, b, c_d";
|
||||||
hive().verified_stmt(set);
|
hive().verified_stmt(set);
|
||||||
}
|
}
|
||||||
|
@ -369,20 +368,20 @@ fn from_cte() {
|
||||||
fn set_statement_with_minus() {
|
fn set_statement_with_minus() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hive().verified_stmt("SET hive.tez.java.opts = -Xmx4g"),
|
hive().verified_stmt("SET hive.tez.java.opts = -Xmx4g"),
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local: false,
|
local: false,
|
||||||
hivevar: false,
|
hivevar: false,
|
||||||
variables: OneOrManyWithParens::One(ObjectName::from(vec![
|
variable: ObjectName::from(vec![
|
||||||
Ident::new("hive"),
|
Ident::new("hive"),
|
||||||
Ident::new("tez"),
|
Ident::new("tez"),
|
||||||
Ident::new("java"),
|
Ident::new("java"),
|
||||||
Ident::new("opts")
|
Ident::new("opts")
|
||||||
])),
|
]),
|
||||||
value: vec![Expr::UnaryOp {
|
values: vec![Expr::UnaryOp {
|
||||||
op: UnaryOperator::Minus,
|
op: UnaryOperator::Minus,
|
||||||
expr: Box::new(Expr::Identifier(Ident::new("Xmx4g")))
|
expr: Box::new(Expr::Identifier(Ident::new("Xmx4g")))
|
||||||
}],
|
}],
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -1254,14 +1254,14 @@ fn parse_mssql_declare() {
|
||||||
for_query: None
|
for_query: None
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local: false,
|
local: false,
|
||||||
hivevar: false,
|
hivevar: false,
|
||||||
variables: OneOrManyWithParens::One(ObjectName::from(vec![Ident::new("@bar")])),
|
variable: ObjectName::from(vec![Ident::new("@bar")]),
|
||||||
value: vec![Expr::Value(
|
values: vec![Expr::Value(
|
||||||
(Value::Number("2".parse().unwrap(), false)).with_empty_span()
|
(Value::Number("2".parse().unwrap(), false)).with_empty_span()
|
||||||
)],
|
)],
|
||||||
},
|
}),
|
||||||
Statement::Query(Box::new(Query {
|
Statement::Query(Box::new(Query {
|
||||||
with: None,
|
with: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
|
|
|
@ -617,12 +617,12 @@ fn parse_set_variables() {
|
||||||
mysql_and_generic().verified_stmt("SET sql_mode = CONCAT(@@sql_mode, ',STRICT_TRANS_TABLES')");
|
mysql_and_generic().verified_stmt("SET sql_mode = CONCAT(@@sql_mode, ',STRICT_TRANS_TABLES')");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
mysql_and_generic().verified_stmt("SET LOCAL autocommit = 1"),
|
mysql_and_generic().verified_stmt("SET LOCAL autocommit = 1"),
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local: true,
|
local: true,
|
||||||
hivevar: false,
|
hivevar: false,
|
||||||
variables: OneOrManyWithParens::One(ObjectName::from(vec!["autocommit".into()])),
|
variable: ObjectName::from(vec!["autocommit".into()]),
|
||||||
value: vec![Expr::value(number("1"))],
|
values: vec![Expr::value(number("1"))],
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2705,19 +2705,19 @@ fn parse_set_names() {
|
||||||
let stmt = mysql_and_generic().verified_stmt("SET NAMES utf8mb4");
|
let stmt = mysql_and_generic().verified_stmt("SET NAMES utf8mb4");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetNames {
|
Statement::Set(Set::SetNames {
|
||||||
charset_name: "utf8mb4".into(),
|
charset_name: "utf8mb4".into(),
|
||||||
collation_name: None,
|
collation_name: None,
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let stmt = mysql_and_generic().verified_stmt("SET NAMES utf8mb4 COLLATE bogus");
|
let stmt = mysql_and_generic().verified_stmt("SET NAMES utf8mb4 COLLATE bogus");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetNames {
|
Statement::Set(Set::SetNames {
|
||||||
charset_name: "utf8mb4".into(),
|
charset_name: "utf8mb4".into(),
|
||||||
collation_name: Some("bogus".to_string()),
|
collation_name: Some("bogus".to_string()),
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let stmt = mysql_and_generic()
|
let stmt = mysql_and_generic()
|
||||||
|
@ -2725,14 +2725,14 @@ fn parse_set_names() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
vec![Statement::SetNames {
|
vec![Statement::Set(Set::SetNames {
|
||||||
charset_name: "utf8mb4".into(),
|
charset_name: "utf8mb4".into(),
|
||||||
collation_name: Some("bogus".to_string()),
|
collation_name: Some("bogus".to_string()),
|
||||||
}]
|
})]
|
||||||
);
|
);
|
||||||
|
|
||||||
let stmt = mysql_and_generic().verified_stmt("SET NAMES DEFAULT");
|
let stmt = mysql_and_generic().verified_stmt("SET NAMES DEFAULT");
|
||||||
assert_eq!(stmt, Statement::SetNamesDefault {});
|
assert_eq!(stmt, Statement::Set(Set::SetNamesDefault {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1432,81 +1432,77 @@ fn parse_set() {
|
||||||
let stmt = pg_and_generic().verified_stmt("SET a = b");
|
let stmt = pg_and_generic().verified_stmt("SET a = b");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local: false,
|
local: false,
|
||||||
hivevar: false,
|
hivevar: false,
|
||||||
variables: OneOrManyWithParens::One(ObjectName::from(vec![Ident::new("a")])),
|
variable: ObjectName::from(vec![Ident::new("a")]),
|
||||||
value: vec![Expr::Identifier(Ident {
|
values: vec![Expr::Identifier(Ident {
|
||||||
value: "b".into(),
|
value: "b".into(),
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
span: Span::empty(),
|
span: Span::empty(),
|
||||||
})],
|
})],
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let stmt = pg_and_generic().verified_stmt("SET a = 'b'");
|
let stmt = pg_and_generic().verified_stmt("SET a = 'b'");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local: false,
|
local: false,
|
||||||
hivevar: false,
|
hivevar: false,
|
||||||
variables: OneOrManyWithParens::One(ObjectName::from(vec![Ident::new("a")])),
|
variable: ObjectName::from(vec![Ident::new("a")]),
|
||||||
value: vec![Expr::Value(
|
values: vec![Expr::Value(
|
||||||
(Value::SingleQuotedString("b".into())).with_empty_span()
|
(Value::SingleQuotedString("b".into())).with_empty_span()
|
||||||
)],
|
)],
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let stmt = pg_and_generic().verified_stmt("SET a = 0");
|
let stmt = pg_and_generic().verified_stmt("SET a = 0");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local: false,
|
local: false,
|
||||||
hivevar: false,
|
hivevar: false,
|
||||||
variables: OneOrManyWithParens::One(ObjectName::from(vec![Ident::new("a")])),
|
variable: ObjectName::from(vec![Ident::new("a")]),
|
||||||
value: vec![Expr::value(number("0"))],
|
values: vec![Expr::value(number("0"))],
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let stmt = pg_and_generic().verified_stmt("SET a = DEFAULT");
|
let stmt = pg_and_generic().verified_stmt("SET a = DEFAULT");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local: false,
|
local: false,
|
||||||
hivevar: false,
|
hivevar: false,
|
||||||
variables: OneOrManyWithParens::One(ObjectName::from(vec![Ident::new("a")])),
|
variable: ObjectName::from(vec![Ident::new("a")]),
|
||||||
value: vec![Expr::Identifier(Ident::new("DEFAULT"))],
|
values: vec![Expr::Identifier(Ident::new("DEFAULT"))],
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let stmt = pg_and_generic().verified_stmt("SET LOCAL a = b");
|
let stmt = pg_and_generic().verified_stmt("SET LOCAL a = b");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local: true,
|
local: true,
|
||||||
hivevar: false,
|
hivevar: false,
|
||||||
variables: OneOrManyWithParens::One(ObjectName::from(vec![Ident::new("a")])),
|
variable: ObjectName::from(vec![Ident::new("a")]),
|
||||||
value: vec![Expr::Identifier("b".into())],
|
values: vec![Expr::Identifier("b".into())],
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let stmt = pg_and_generic().verified_stmt("SET a.b.c = b");
|
let stmt = pg_and_generic().verified_stmt("SET a.b.c = b");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local: false,
|
local: false,
|
||||||
hivevar: false,
|
hivevar: false,
|
||||||
variables: OneOrManyWithParens::One(ObjectName::from(vec![
|
variable: ObjectName::from(vec![Ident::new("a"), Ident::new("b"), Ident::new("c")]),
|
||||||
Ident::new("a"),
|
values: vec![Expr::Identifier(Ident {
|
||||||
Ident::new("b"),
|
|
||||||
Ident::new("c")
|
|
||||||
])),
|
|
||||||
value: vec![Expr::Identifier(Ident {
|
|
||||||
value: "b".into(),
|
value: "b".into(),
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
span: Span::empty(),
|
span: Span::empty(),
|
||||||
})],
|
})],
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let stmt = pg_and_generic().one_statement_parses_to(
|
let stmt = pg_and_generic().one_statement_parses_to(
|
||||||
|
@ -1515,18 +1511,18 @@ fn parse_set() {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetVariable {
|
Statement::Set(Set::SingleAssignment {
|
||||||
local: false,
|
local: false,
|
||||||
hivevar: false,
|
hivevar: false,
|
||||||
variables: OneOrManyWithParens::One(ObjectName::from(vec![
|
variable: ObjectName::from(vec![
|
||||||
Ident::new("hive"),
|
Ident::new("hive"),
|
||||||
Ident::new("tez"),
|
Ident::new("tez"),
|
||||||
Ident::new("auto"),
|
Ident::new("auto"),
|
||||||
Ident::new("reducer"),
|
Ident::new("reducer"),
|
||||||
Ident::new("parallelism")
|
Ident::new("parallelism")
|
||||||
])),
|
]),
|
||||||
value: vec![Expr::Value((Value::Boolean(false)).with_empty_span())],
|
values: vec![Expr::Value((Value::Boolean(false)).with_empty_span())],
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
pg_and_generic().one_statement_parses_to("SET a TO b", "SET a = b");
|
pg_and_generic().one_statement_parses_to("SET a TO b", "SET a = b");
|
||||||
|
@ -1560,10 +1556,10 @@ fn parse_set_role() {
|
||||||
let stmt = pg_and_generic().verified_stmt(query);
|
let stmt = pg_and_generic().verified_stmt(query);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetRole {
|
Statement::Set(Set::SetRole {
|
||||||
context_modifier: ContextModifier::Session,
|
context_modifier: ContextModifier::Session,
|
||||||
role_name: None,
|
role_name: None,
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(query, stmt.to_string());
|
assert_eq!(query, stmt.to_string());
|
||||||
|
|
||||||
|
@ -1571,14 +1567,14 @@ fn parse_set_role() {
|
||||||
let stmt = pg_and_generic().verified_stmt(query);
|
let stmt = pg_and_generic().verified_stmt(query);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetRole {
|
Statement::Set(Set::SetRole {
|
||||||
context_modifier: ContextModifier::Local,
|
context_modifier: ContextModifier::Local,
|
||||||
role_name: Some(Ident {
|
role_name: Some(Ident {
|
||||||
value: "rolename".to_string(),
|
value: "rolename".to_string(),
|
||||||
quote_style: Some('\"'),
|
quote_style: Some('\"'),
|
||||||
span: Span::empty(),
|
span: Span::empty(),
|
||||||
}),
|
}),
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(query, stmt.to_string());
|
assert_eq!(query, stmt.to_string());
|
||||||
|
|
||||||
|
@ -1586,14 +1582,14 @@ fn parse_set_role() {
|
||||||
let stmt = pg_and_generic().verified_stmt(query);
|
let stmt = pg_and_generic().verified_stmt(query);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetRole {
|
Statement::Set(Set::SetRole {
|
||||||
context_modifier: ContextModifier::None,
|
context_modifier: ContextModifier::None,
|
||||||
role_name: Some(Ident {
|
role_name: Some(Ident {
|
||||||
value: "rolename".to_string(),
|
value: "rolename".to_string(),
|
||||||
quote_style: Some('\''),
|
quote_style: Some('\''),
|
||||||
span: Span::empty(),
|
span: Span::empty(),
|
||||||
}),
|
}),
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(query, stmt.to_string());
|
assert_eq!(query, stmt.to_string());
|
||||||
}
|
}
|
||||||
|
@ -2982,16 +2978,16 @@ fn test_transaction_statement() {
|
||||||
let statement = pg().verified_stmt("SET TRANSACTION SNAPSHOT '000003A1-1'");
|
let statement = pg().verified_stmt("SET TRANSACTION SNAPSHOT '000003A1-1'");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
statement,
|
statement,
|
||||||
Statement::SetTransaction {
|
Statement::Set(Set::SetTransaction {
|
||||||
modes: vec![],
|
modes: vec![],
|
||||||
snapshot: Some(Value::SingleQuotedString(String::from("000003A1-1"))),
|
snapshot: Some(Value::SingleQuotedString(String::from("000003A1-1"))),
|
||||||
session: false
|
session: false
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
let statement = pg().verified_stmt("SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ WRITE, ISOLATION LEVEL SERIALIZABLE");
|
let statement = pg().verified_stmt("SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ WRITE, ISOLATION LEVEL SERIALIZABLE");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
statement,
|
statement,
|
||||||
Statement::SetTransaction {
|
Statement::Set(Set::SetTransaction {
|
||||||
modes: vec![
|
modes: vec![
|
||||||
TransactionMode::AccessMode(TransactionAccessMode::ReadOnly),
|
TransactionMode::AccessMode(TransactionAccessMode::ReadOnly),
|
||||||
TransactionMode::AccessMode(TransactionAccessMode::ReadWrite),
|
TransactionMode::AccessMode(TransactionAccessMode::ReadWrite),
|
||||||
|
@ -2999,7 +2995,7 @@ fn test_transaction_statement() {
|
||||||
],
|
],
|
||||||
snapshot: None,
|
snapshot: None,
|
||||||
session: true
|
session: true
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue