From af560ee42f9931149f4b9330d9dff5b91afcb896 Mon Sep 17 00:00:00 2001 From: gainings Date: Sat, 8 Jun 2024 15:43:41 +0900 Subject: [PATCH 01/13] Add keyword for postgres --- src/keywords.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/keywords.rs b/src/keywords.rs index 6c6c642c3..d24e384f4 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -508,6 +508,7 @@ define_keywords!( OVERLAY, OVERWRITE, OWNED, + OWNER, PARALLEL, PARAMETER, PARQUET, From c351eb8ba0e6f0d08f1e647e0aba3141471244c5 Mon Sep 17 00:00:00 2001 From: gainings Date: Sun, 9 Jun 2024 13:31:43 +0900 Subject: [PATCH 02/13] Add OwnerTo ddl ast --- src/ast/ddl.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index 9c30999ab..c22e3b1d0 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -157,6 +157,11 @@ pub enum AlterTableOperation { SwapWith { table_name: ObjectName }, /// 'SET TBLPROPERTIES ( { property_key [ = ] property_val } [, ...] )' SetTblProperties { table_properties: Vec }, + + /// `OWNER TO ` + /// + /// Note: this is a PostgreSQL-specific operation. + OwnerTo { new_role: Ident }, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] @@ -322,6 +327,9 @@ impl fmt::Display for AlterTableOperation { AlterTableOperation::SwapWith { table_name } => { write!(f, "SWAP WITH {table_name}") } + AlterTableOperation::OwnerTo { new_role } => { + write!(f, "OWNER TO {new_role}") + } AlterTableOperation::SetTblProperties { table_properties } => { write!( f, From e4d1e95515bf89b8a7e574c97d79cd440abff933 Mon Sep 17 00:00:00 2001 From: gainings Date: Sun, 9 Jun 2024 13:33:35 +0900 Subject: [PATCH 03/13] Add owner to parser in alter talbe operation --- src/parser/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index c6750644c..297898e24 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6274,6 +6274,9 @@ impl<'a> Parser<'a> { self.expect_keyword(Keyword::WITH)?; let table_name = self.parse_object_name(false)?; AlterTableOperation::SwapWith { table_name } + } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { + let new_role = self.parse_identifier(false)?; + AlterTableOperation::OwnerTo { new_role: new_role } } else { let options: Vec = self.parse_options_with_keywords(&[Keyword::SET, Keyword::TBLPROPERTIES])?; From 1d5f01d77b2fcf96e3ffe5fc474756bf3c583772 Mon Sep 17 00:00:00 2001 From: gainings Date: Sun, 9 Jun 2024 13:41:06 +0900 Subject: [PATCH 04/13] Add postgres test for owner to --- tests/sqlparser_postgres.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 677246a51..083a12d6c 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -713,6 +713,33 @@ fn parse_alter_table_add_columns() { } } +#[test] +fn parse_alter_table_owner_to() { + match pg().verified_stmt("ALTER TABLE tab OWNER TO new_owner") { + Statement::AlterTable { + name, + if_exists: _, + only: _, + operations, + location: _, + } => { + assert_eq!(name.to_string(), "tab"); + assert_eq!( + operations, + vec![ + AlterTableOperation::OwnerTo { + new_role: Ident { + value: "new_owner".to_string(), + quote_style: None, + } + }, + ] + ); + } + _ => unreachable!(), + } +} + #[test] fn parse_create_table_if_not_exists() { let sql = "CREATE TABLE IF NOT EXISTS uk_cities ()"; From c56120ed322a7ee24d758422e2f526cd845e78b7 Mon Sep 17 00:00:00 2001 From: gainings Date: Sun, 9 Jun 2024 14:41:42 +0900 Subject: [PATCH 05/13] Parse OWNER TO clause only for Postgresql --- src/parser/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 297898e24..7e762dfdc 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6274,7 +6274,7 @@ impl<'a> Parser<'a> { self.expect_keyword(Keyword::WITH)?; let table_name = self.parse_object_name(false)?; AlterTableOperation::SwapWith { table_name } - } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { + } else if dialect_of!(self is PostgreSqlDialect) && self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { let new_role = self.parse_identifier(false)?; AlterTableOperation::OwnerTo { new_role: new_role } } else { From 5c21442a65c9c7ca12cab6afc849ddbaf0bd69b8 Mon Sep 17 00:00:00 2001 From: gainings Date: Sat, 15 Jun 2024 22:01:48 +0900 Subject: [PATCH 06/13] Support CURRENT_ROLE, CURRENT_USER, SESSION_USER Functions for OwnerTo Clause --- src/ast/ddl.rs | 30 ++++++++++++++++++++++-------- src/ast/mod.rs | 2 +- src/parser/mod.rs | 23 +++++++++++++++++++++-- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index c22e3b1d0..f4b41d60b 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -24,10 +24,7 @@ use serde::{Deserialize, Serialize}; use sqlparser_derive::{Visit, VisitMut}; use crate::ast::value::escape_single_quote_string; -use crate::ast::{ - display_comma_separated, display_separated, DataType, Expr, Ident, MySQLColumnPosition, - ObjectName, SequenceOptions, SqlOption, -}; +use crate::ast::{display_comma_separated, display_separated, DataType, Expr, Ident, MySQLColumnPosition, ObjectName, SequenceOptions, SqlOption}; use crate::tokenizer::Token; /// An `ALTER TABLE` (`Statement::AlterTable`) operation @@ -158,10 +155,27 @@ pub enum AlterTableOperation { /// 'SET TBLPROPERTIES ( { property_key [ = ] property_val } [, ...] )' SetTblProperties { table_properties: Vec }, - /// `OWNER TO ` + /// `OWNER TO { | CURRENT_ROLE | CURRENT_USER | SESSION_USER }` /// /// Note: this is a PostgreSQL-specific operation. - OwnerTo { new_role: Ident }, + OwnerTo { new_owner: Owner }, +} + +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub enum Owner { + Ident(Ident), + Expr(Expr), +} + +impl fmt::Display for Owner { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Owner::Ident(ident) => write!(f, "{}", ident), + Owner::Expr(expr) => write!(f, "{}", expr), + } + } } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] @@ -327,8 +341,8 @@ impl fmt::Display for AlterTableOperation { AlterTableOperation::SwapWith { table_name } => { write!(f, "SWAP WITH {table_name}") } - AlterTableOperation::OwnerTo { new_role } => { - write!(f, "OWNER TO {new_role}") + AlterTableOperation::OwnerTo { new_owner } => { + write!(f, "OWNER TO {new_owner}") } AlterTableOperation::SetTblProperties { table_properties } => { write!( diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 320dfc60e..04de4ee14 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -34,7 +34,7 @@ pub use self::dcl::{AlterRoleOperation, ResetConfig, RoleOption, SetConfigValue} pub use self::ddl::{ AlterColumnOperation, AlterIndexOperation, AlterTableOperation, ColumnDef, ColumnOption, ColumnOptionDef, ConstraintCharacteristics, DeferrableInitial, GeneratedAs, - GeneratedExpressionMode, IndexOption, IndexType, KeyOrIndexDisplay, Partition, ProcedureParam, + GeneratedExpressionMode, IndexOption, IndexType, KeyOrIndexDisplay, Owner, Partition, ProcedureParam, ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef, }; diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 7e762dfdc..5a65678a9 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6275,8 +6275,27 @@ impl<'a> Parser<'a> { let table_name = self.parse_object_name(false)?; AlterTableOperation::SwapWith { table_name } } else if dialect_of!(self is PostgreSqlDialect) && self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { - let new_role = self.parse_identifier(false)?; - AlterTableOperation::OwnerTo { new_role: new_role } + let next_token = self.next_token(); + let new_owner = match next_token.token { + Token::DoubleQuotedString(ref s) => Owner::Ident(Ident::new(s.to_string())), + Token::Word(ref w) => match w.keyword { + Keyword::CURRENT_USER | Keyword::CURRENT_ROLE | Keyword::SESSION_USER => { + Owner::Expr(Expr::Function(Function { + name: ObjectName(vec![w.to_ident()]), + args: FunctionArguments::None, + null_treatment: None, + filter: None, + over: None, + within_group: vec![], + })) + }, + Keyword::NoKeyword => Owner::Ident(w.to_ident()), + _ => self.expected("CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier expected after OWNER TO clause", next_token)?, + }, + _ => self.expected("Token::Word", next_token)? + }; + + AlterTableOperation::OwnerTo { new_owner } } else { let options: Vec = self.parse_options_with_keywords(&[Keyword::SET, Keyword::TBLPROPERTIES])?; From 4d06a6167b16e87a3e9592675f7604c99039f0c2 Mon Sep 17 00:00:00 2001 From: gainings Date: Sat, 15 Jun 2024 23:08:28 +0900 Subject: [PATCH 07/13] Fix expected error message for OwnerTo --- src/parser/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 5a65678a9..121df1a54 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6290,7 +6290,7 @@ impl<'a> Parser<'a> { })) }, Keyword::NoKeyword => Owner::Ident(w.to_ident()), - _ => self.expected("CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier expected after OWNER TO clause", next_token)?, + _ => self.expected("CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO clause", next_token)?, }, _ => self.expected("Token::Word", next_token)? }; From 52c162d02c03102a3fb5481172736fdd6d976336 Mon Sep 17 00:00:00 2001 From: gainings Date: Sat, 15 Jun 2024 23:09:00 +0900 Subject: [PATCH 08/13] Fix postgres test to support CURRENT_USER, CURRENT_ROLE, SESSION_USER --- tests/sqlparser_postgres.rs | 87 ++++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 20 deletions(-) diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 083a12d6c..3760c4bb5 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -715,29 +715,76 @@ fn parse_alter_table_add_columns() { #[test] fn parse_alter_table_owner_to() { - match pg().verified_stmt("ALTER TABLE tab OWNER TO new_owner") { - Statement::AlterTable { - name, - if_exists: _, - only: _, - operations, - location: _, - } => { - assert_eq!(name.to_string(), "tab"); - assert_eq!( + struct TestCase { + sql: &'static str, + expected_owner: Owner, + } + + let test_cases = vec![ + TestCase { + sql: "ALTER TABLE tab OWNER TO new_owner", + expected_owner: Owner::Ident(Ident::new("new_owner".to_string())), + }, + TestCase { + sql: "ALTER TABLE tab OWNER TO \"new_owner\"", + expected_owner: Owner::Ident(Ident::with_quote('\"', "new_owner".to_string())), + }, + TestCase { + sql: "ALTER TABLE tab OWNER TO CURRENT_USER", + expected_owner: Owner::Expr(Expr::Function(Function { + name: ObjectName(vec![Ident::new("CURRENT_USER")]), + args: FunctionArguments::None, + null_treatment: None, + filter: None, + over: None, + within_group: vec![], + })), + }, + TestCase { + sql: "ALTER TABLE tab OWNER TO CURRENT_ROLE", + expected_owner: Owner::Expr(Expr::Function(Function { + name: ObjectName(vec![Ident::new("CURRENT_ROLE")]), + args: FunctionArguments::None, + null_treatment: None, + filter: None, + over: None, + within_group: vec![], + })), + }, + TestCase { + sql: "ALTER TABLE tab OWNER TO SESSION_USER", + expected_owner: Owner::Expr(Expr::Function(Function { + name: ObjectName(vec![Ident::new("SESSION_USER")]), + args: FunctionArguments::None, + null_treatment: None, + filter: None, + over: None, + within_group: vec![], + })), + }, + ]; + + for case in test_cases { + match pg().verified_stmt(case.sql) { + Statement::AlterTable { + name, + if_exists: _, + only: _, operations, - vec![ - AlterTableOperation::OwnerTo { - new_role: Ident { - value: "new_owner".to_string(), - quote_style: None, - } - }, - ] - ); + location: _, + } => { + assert_eq!(name.to_string(), "tab"); + assert_eq!(operations, vec![AlterTableOperation::OwnerTo { new_owner: case.expected_owner.clone() }]); + } + _ => unreachable!("Expected an AlterTable statement"), } - _ => unreachable!(), } + + let res = pg().parse_sql_statements("ALTER TABLE tab OWNER TO CREATE"); + assert_eq!( + ParserError::ParserError("Expected CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO clause, found: CREATE".to_string()), + res.unwrap_err() + ); } #[test] From 6076c2d1d53c986ea9a2284d773795cbd0898306 Mon Sep 17 00:00:00 2001 From: gainings Date: Sat, 15 Jun 2024 23:17:04 +0900 Subject: [PATCH 09/13] Apply cargo fmt --- src/ast/ddl.rs | 5 ++++- src/ast/mod.rs | 4 ++-- src/parser/mod.rs | 4 +++- tests/sqlparser_postgres.rs | 7 ++++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index f4b41d60b..0f50356d7 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -24,7 +24,10 @@ use serde::{Deserialize, Serialize}; use sqlparser_derive::{Visit, VisitMut}; use crate::ast::value::escape_single_quote_string; -use crate::ast::{display_comma_separated, display_separated, DataType, Expr, Ident, MySQLColumnPosition, ObjectName, SequenceOptions, SqlOption}; +use crate::ast::{ + display_comma_separated, display_separated, DataType, Expr, Ident, MySQLColumnPosition, + ObjectName, SequenceOptions, SqlOption, +}; use crate::tokenizer::Token; /// An `ALTER TABLE` (`Statement::AlterTable`) operation diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 04de4ee14..ba01ec2df 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -34,8 +34,8 @@ pub use self::dcl::{AlterRoleOperation, ResetConfig, RoleOption, SetConfigValue} pub use self::ddl::{ AlterColumnOperation, AlterIndexOperation, AlterTableOperation, ColumnDef, ColumnOption, ColumnOptionDef, ConstraintCharacteristics, DeferrableInitial, GeneratedAs, - GeneratedExpressionMode, IndexOption, IndexType, KeyOrIndexDisplay, Owner, Partition, ProcedureParam, - ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef, + GeneratedExpressionMode, IndexOption, IndexType, KeyOrIndexDisplay, Owner, Partition, + ProcedureParam, ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef, }; pub use self::dml::{Delete, Insert}; diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 121df1a54..5d6e6acce 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6274,7 +6274,9 @@ impl<'a> Parser<'a> { self.expect_keyword(Keyword::WITH)?; let table_name = self.parse_object_name(false)?; AlterTableOperation::SwapWith { table_name } - } else if dialect_of!(self is PostgreSqlDialect) && self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { + } else if dialect_of!(self is PostgreSqlDialect) + && self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) + { let next_token = self.next_token(); let new_owner = match next_token.token { Token::DoubleQuotedString(ref s) => Owner::Ident(Ident::new(s.to_string())), diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 3760c4bb5..70a225b8c 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -774,7 +774,12 @@ fn parse_alter_table_owner_to() { location: _, } => { assert_eq!(name.to_string(), "tab"); - assert_eq!(operations, vec![AlterTableOperation::OwnerTo { new_owner: case.expected_owner.clone() }]); + assert_eq!( + operations, + vec![AlterTableOperation::OwnerTo { + new_owner: case.expected_owner.clone() + }] + ); } _ => unreachable!("Expected an AlterTable statement"), } From a3a499638d3d79df4d0f700f8453ee736e494c6d Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Mon, 8 Jul 2024 06:49:34 -0400 Subject: [PATCH 10/13] Add link --- src/ast/ddl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index 0f50356d7..98bb1d39d 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -160,7 +160,7 @@ pub enum AlterTableOperation { /// `OWNER TO { | CURRENT_ROLE | CURRENT_USER | SESSION_USER }` /// - /// Note: this is a PostgreSQL-specific operation. + /// Note: this is PostgreSQL-specific OwnerTo { new_owner: Owner }, } From 25d6a40c1c6848c6e50ce6041e705490ba818bca Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Mon, 8 Jul 2024 06:53:22 -0400 Subject: [PATCH 11/13] Support generic dialect --- src/parser/mod.rs | 2 +- tests/sqlparser_postgres.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 5d6e6acce..0de4ef07f 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6274,7 +6274,7 @@ impl<'a> Parser<'a> { self.expect_keyword(Keyword::WITH)?; let table_name = self.parse_object_name(false)?; AlterTableOperation::SwapWith { table_name } - } else if dialect_of!(self is PostgreSqlDialect) + } else if dialect_of!(self is PostgreSqlDialect | GenericDialect) && self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { let next_token = self.next_token(); diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 70a225b8c..de8f30d13 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -765,7 +765,7 @@ fn parse_alter_table_owner_to() { ]; for case in test_cases { - match pg().verified_stmt(case.sql) { + match pg_and_generic().verified_stmt(case.sql) { Statement::AlterTable { name, if_exists: _, From 0ff17d78d173dd38a37254ab5210a0ebcab2c9bc Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Mon, 8 Jul 2024 07:23:28 -0400 Subject: [PATCH 12/13] Use explicit variants --- src/ast/ddl.rs | 8 ++++++-- src/parser/mod.rs | 29 +++++++++++--------------- tests/sqlparser_postgres.rs | 41 ++++++++++++++----------------------- 3 files changed, 33 insertions(+), 45 deletions(-) diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index 98bb1d39d..1ed3857d7 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -169,14 +169,18 @@ pub enum AlterTableOperation { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum Owner { Ident(Ident), - Expr(Expr), + CurrentRole, + CurrentUser, + SessionUser, } impl fmt::Display for Owner { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Owner::Ident(ident) => write!(f, "{}", ident), - Owner::Expr(expr) => write!(f, "{}", expr), + Owner::CurrentRole => write!(f, "CURRENT_ROLE"), + Owner::CurrentUser => write!(f, "CURRENT_USER"), + Owner::SessionUser => write!(f, "SESSION_USER"), } } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0de4ef07f..c5f39bc0a 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6277,24 +6277,19 @@ impl<'a> Parser<'a> { } else if dialect_of!(self is PostgreSqlDialect | GenericDialect) && self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { - let next_token = self.next_token(); - let new_owner = match next_token.token { - Token::DoubleQuotedString(ref s) => Owner::Ident(Ident::new(s.to_string())), - Token::Word(ref w) => match w.keyword { - Keyword::CURRENT_USER | Keyword::CURRENT_ROLE | Keyword::SESSION_USER => { - Owner::Expr(Expr::Function(Function { - name: ObjectName(vec![w.to_ident()]), - args: FunctionArguments::None, - null_treatment: None, - filter: None, - over: None, - within_group: vec![], - })) - }, - Keyword::NoKeyword => Owner::Ident(w.to_ident()), - _ => self.expected("CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO clause", next_token)?, + let new_owner = match self.parse_one_of_keywords( &[Keyword::CURRENT_USER, Keyword::CURRENT_ROLE, Keyword::SESSION_USER]) { + Some(Keyword::CURRENT_USER) => Owner::CurrentUser, + Some(Keyword::CURRENT_ROLE) => Owner::CurrentRole, + Some(Keyword::SESSION_USER) => Owner::SessionUser, + Some(_) => unreachable!(), + None => { + match self.parse_identifier(false) { + Ok(ident) => Owner::Ident(ident), + Err(e) => { + return Err(ParserError::ParserError(format!("Expected CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO. {e}"))) + } + } }, - _ => self.expected("Token::Word", next_token)? }; AlterTableOperation::OwnerTo { new_owner } diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index de8f30d13..130ced51c 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -725,42 +725,25 @@ fn parse_alter_table_owner_to() { sql: "ALTER TABLE tab OWNER TO new_owner", expected_owner: Owner::Ident(Ident::new("new_owner".to_string())), }, + TestCase { + sql: "ALTER TABLE tab OWNER TO postgres", + expected_owner: Owner::Ident(Ident::new("postgres".to_string())), + }, TestCase { sql: "ALTER TABLE tab OWNER TO \"new_owner\"", expected_owner: Owner::Ident(Ident::with_quote('\"', "new_owner".to_string())), }, TestCase { sql: "ALTER TABLE tab OWNER TO CURRENT_USER", - expected_owner: Owner::Expr(Expr::Function(Function { - name: ObjectName(vec![Ident::new("CURRENT_USER")]), - args: FunctionArguments::None, - null_treatment: None, - filter: None, - over: None, - within_group: vec![], - })), + expected_owner: Owner::CurrentUser, }, TestCase { sql: "ALTER TABLE tab OWNER TO CURRENT_ROLE", - expected_owner: Owner::Expr(Expr::Function(Function { - name: ObjectName(vec![Ident::new("CURRENT_ROLE")]), - args: FunctionArguments::None, - null_treatment: None, - filter: None, - over: None, - within_group: vec![], - })), + expected_owner: Owner::CurrentRole, }, TestCase { sql: "ALTER TABLE tab OWNER TO SESSION_USER", - expected_owner: Owner::Expr(Expr::Function(Function { - name: ObjectName(vec![Ident::new("SESSION_USER")]), - args: FunctionArguments::None, - null_treatment: None, - filter: None, - over: None, - within_group: vec![], - })), + expected_owner: Owner::SessionUser, }, ]; @@ -785,9 +768,15 @@ fn parse_alter_table_owner_to() { } } - let res = pg().parse_sql_statements("ALTER TABLE tab OWNER TO CREATE"); + let res = pg().parse_sql_statements("ALTER TABLE tab OWNER TO CREATE FOO"); + assert_eq!( + ParserError::ParserError("Expected end of statement, found: FOO".to_string()), + res.unwrap_err() + ); + + let res = pg().parse_sql_statements("ALTER TABLE tab OWNER TO 4"); assert_eq!( - ParserError::ParserError("Expected CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO clause, found: CREATE".to_string()), + ParserError::ParserError("Expected CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO. sql parser error: Expected identifier, found: 4".to_string()), res.unwrap_err() ); } From 4340c6570f2592568347eac512093923b32884cb Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Mon, 8 Jul 2024 07:42:51 -0400 Subject: [PATCH 13/13] Update for latest error messages --- src/parser/mod.rs | 2 +- tests/sqlparser_postgres.rs | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 3b2caba26..acc6dc7e1 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6437,7 +6437,7 @@ impl<'a> Parser<'a> { match self.parse_identifier(false) { Ok(ident) => Owner::Ident(ident), Err(e) => { - return Err(ParserError::ParserError(format!("Expected CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO. {e}"))) + return Err(ParserError::ParserError(format!("Expected: CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO. {e}"))) } } }, diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index eb9d4a887..a9683819b 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -729,6 +729,10 @@ fn parse_alter_table_owner_to() { sql: "ALTER TABLE tab OWNER TO postgres", expected_owner: Owner::Ident(Ident::new("postgres".to_string())), }, + TestCase { + sql: "ALTER TABLE tab OWNER TO CREATE", // treats CREATE as an identifier + expected_owner: Owner::Ident(Ident::new("CREATE".to_string())), + }, TestCase { sql: "ALTER TABLE tab OWNER TO \"new_owner\"", expected_owner: Owner::Ident(Ident::with_quote('\"', "new_owner".to_string())), @@ -770,13 +774,13 @@ fn parse_alter_table_owner_to() { let res = pg().parse_sql_statements("ALTER TABLE tab OWNER TO CREATE FOO"); assert_eq!( - ParserError::ParserError("Expected end of statement, found: FOO".to_string()), + ParserError::ParserError("Expected: end of statement, found: FOO".to_string()), res.unwrap_err() ); let res = pg().parse_sql_statements("ALTER TABLE tab OWNER TO 4"); assert_eq!( - ParserError::ParserError("Expected CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO. sql parser error: Expected identifier, found: 4".to_string()), + ParserError::ParserError("Expected: CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO. sql parser error: Expected: identifier, found: 4".to_string()), res.unwrap_err() ); }