Skip to content

Commit 86693d3

Browse files
Merge branch 'main' into extended-create-func
2 parents 4f4fcbf + e380494 commit 86693d3

File tree

9 files changed

+254
-55
lines changed

9 files changed

+254
-55
lines changed

src/ast/ddl.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4192,3 +4192,62 @@ impl fmt::Display for OperatorPurpose {
41924192
}
41934193
}
41944194
}
4195+
4196+
/// `DROP OPERATOR` statement
4197+
/// See <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4198+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4199+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4200+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4201+
pub struct DropOperator {
4202+
/// `IF EXISTS` clause
4203+
pub if_exists: bool,
4204+
/// One or more operators to drop with their signatures
4205+
pub operators: Vec<DropOperatorSignature>,
4206+
/// `CASCADE or RESTRICT`
4207+
pub drop_behavior: Option<DropBehavior>,
4208+
}
4209+
4210+
/// Operator signature for a `DROP OPERATOR` statement
4211+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4212+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4213+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4214+
pub struct DropOperatorSignature {
4215+
/// Operator name
4216+
pub name: ObjectName,
4217+
/// Left operand type
4218+
pub left_type: Option<DataType>,
4219+
/// Right operand type
4220+
pub right_type: DataType,
4221+
}
4222+
4223+
impl fmt::Display for DropOperatorSignature {
4224+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4225+
write!(f, "{} (", self.name)?;
4226+
if let Some(left_type) = &self.left_type {
4227+
write!(f, "{}", left_type)?;
4228+
} else {
4229+
write!(f, "NONE")?;
4230+
}
4231+
write!(f, ", {})", self.right_type)
4232+
}
4233+
}
4234+
4235+
impl fmt::Display for DropOperator {
4236+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4237+
write!(f, "DROP OPERATOR")?;
4238+
if self.if_exists {
4239+
write!(f, " IF EXISTS")?;
4240+
}
4241+
write!(f, " {}", display_comma_separated(&self.operators))?;
4242+
if let Some(drop_behavior) = &self.drop_behavior {
4243+
write!(f, " {}", drop_behavior)?;
4244+
}
4245+
Ok(())
4246+
}
4247+
}
4248+
4249+
impl Spanned for DropOperator {
4250+
fn span(&self) -> Span {
4251+
Span::empty()
4252+
}
4253+
}

src/ast/mod.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,15 @@ pub use self::ddl::{
6767
ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain,
6868
CreateExtension, CreateFunction, CreateIndex, CreateOperator, CreateOperatorClass,
6969
CreateOperatorFamily, CreateTable, CreateTrigger, CreateView, Deduplicate, DeferrableInitial,
70-
DropBehavior, DropExtension, DropFunction, DropTrigger, GeneratedAs, GeneratedExpressionMode,
71-
IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind,
72-
IdentityPropertyOrder, IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, Msck,
73-
NullsDistinctOption, OperatorArgTypes, OperatorClassItem, OperatorPurpose, Owner, Partition,
74-
ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TagsColumnOption,
75-
TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
76-
UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
77-
UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef,
70+
DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorSignature, DropTrigger,
71+
GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
72+
IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
73+
IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes,
74+
OperatorClassItem, OperatorPurpose, Owner, Partition, ProcedureParam, ReferentialAction,
75+
RenameTableNameKind, ReplicaIdentity, TagsColumnOption, TriggerObjectKind, Truncate,
76+
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
77+
UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
78+
UserDefinedTypeStorage, ViewColumnDef,
7879
};
7980
pub use self::dml::{Delete, Insert, Update};
8081
pub use self::operator::{BinaryOperator, UnaryOperator};
@@ -3573,6 +3574,12 @@ pub enum Statement {
35733574
/// <https://www.postgresql.org/docs/current/sql-dropextension.html>
35743575
DropExtension(DropExtension),
35753576
/// ```sql
3577+
/// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
3578+
/// ```
3579+
/// Note: this is a PostgreSQL-specific statement.
3580+
/// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
3581+
DropOperator(DropOperator),
3582+
/// ```sql
35763583
/// FETCH
35773584
/// ```
35783585
/// Retrieve rows from a query using a cursor
@@ -4836,6 +4843,7 @@ impl fmt::Display for Statement {
48364843
Statement::CreateIndex(create_index) => create_index.fmt(f),
48374844
Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
48384845
Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
4846+
Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
48394847
Statement::CreateRole(create_role) => write!(f, "{create_role}"),
48404848
Statement::CreateSecret {
48414849
or_replace,

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ impl Spanned for Statement {
375375
Statement::CreateRole(create_role) => create_role.span(),
376376
Statement::CreateExtension(create_extension) => create_extension.span(),
377377
Statement::DropExtension(drop_extension) => drop_extension.span(),
378+
Statement::DropOperator(drop_operator) => drop_operator.span(),
378379
Statement::CreateSecret { .. } => Span::empty(),
379380
Statement::CreateServer { .. } => Span::empty(),
380381
Statement::CreateConnector { .. } => Span::empty(),

src/dialect/snowflake.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ impl Dialect for SnowflakeDialect {
393393

394394
fn is_column_alias(&self, kw: &Keyword, parser: &mut Parser) -> bool {
395395
match kw {
396-
// The following keywords can be considered an alias as long as
396+
// The following keywords can be considered an alias as long as
397397
// they are not followed by other tokens that may change their meaning
398398
// e.g. `SELECT * EXCEPT (col1) FROM tbl`
399399
Keyword::EXCEPT
@@ -408,7 +408,7 @@ impl Dialect for SnowflakeDialect {
408408
Keyword::LIMIT | Keyword::OFFSET if peek_for_limit_options(parser) => false,
409409

410410
// `FETCH` can be considered an alias as long as it's not followed by `FIRST`` or `NEXT`
411-
// which would give it a different meanings, for example:
411+
// which would give it a different meanings, for example:
412412
// `SELECT 1 FETCH FIRST 10 ROWS` - not an alias
413413
// `SELECT 1 FETCH 10` - not an alias
414414
Keyword::FETCH if parser.peek_one_of_keywords(&[Keyword::FIRST, Keyword::NEXT]).is_some()
@@ -417,8 +417,8 @@ impl Dialect for SnowflakeDialect {
417417
false
418418
}
419419

420-
// Reserved keywords by the Snowflake dialect, which seem to be less strictive
421-
// than what is listed in `keywords::RESERVED_FOR_COLUMN_ALIAS`. The following
420+
// Reserved keywords by the Snowflake dialect, which seem to be less strictive
421+
// than what is listed in `keywords::RESERVED_FOR_COLUMN_ALIAS`. The following
422422
// keywords were tested with the this statement: `SELECT 1 <KW>`.
423423
Keyword::FROM
424424
| Keyword::GROUP
@@ -688,7 +688,7 @@ pub fn parse_create_table(
688688
.iceberg(iceberg)
689689
.global(global)
690690
.dynamic(dynamic)
691-
.hive_formats(Some(Default::default()));
691+
.hive_formats(None);
692692

693693
// Snowflake does not enforce order of the parameters in the statement. The parser needs to
694694
// parse the statement in a loop.

src/parser/mod.rs

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5832,15 +5832,19 @@ impl<'a> Parser<'a> {
58325832
let hive_distribution = self.parse_hive_distribution()?;
58335833
let hive_formats = self.parse_hive_formats()?;
58345834

5835-
let file_format = if let Some(ff) = &hive_formats.storage {
5836-
match ff {
5837-
HiveIOFormat::FileFormat { format } => Some(*format),
5838-
_ => None,
5835+
let file_format = if let Some(ref hf) = hive_formats {
5836+
if let Some(ref ff) = hf.storage {
5837+
match ff {
5838+
HiveIOFormat::FileFormat { format } => Some(*format),
5839+
_ => None,
5840+
}
5841+
} else {
5842+
None
58395843
}
58405844
} else {
58415845
None
58425846
};
5843-
let location = hive_formats.location.clone();
5847+
let location = hive_formats.as_ref().and_then(|hf| hf.location.clone());
58445848
let table_properties = self.parse_options(Keyword::TBLPROPERTIES)?;
58455849
let table_options = if !table_properties.is_empty() {
58465850
CreateTableOptions::TableProperties(table_properties)
@@ -5851,7 +5855,7 @@ impl<'a> Parser<'a> {
58515855
.columns(columns)
58525856
.constraints(constraints)
58535857
.hive_distribution(hive_distribution)
5854-
.hive_formats(Some(hive_formats))
5858+
.hive_formats(hive_formats)
58555859
.table_options(table_options)
58565860
.or_replace(or_replace)
58575861
.if_not_exists(if_not_exists)
@@ -6768,9 +6772,11 @@ impl<'a> Parser<'a> {
67686772
return self.parse_drop_trigger();
67696773
} else if self.parse_keyword(Keyword::EXTENSION) {
67706774
return self.parse_drop_extension();
6775+
} else if self.parse_keyword(Keyword::OPERATOR) {
6776+
return self.parse_drop_operator();
67716777
} else {
67726778
return self.expected(
6773-
"CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW or USER after DROP",
6779+
"CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW or USER after DROP",
67746780
self.peek_token(),
67756781
);
67766782
};
@@ -7526,6 +7532,46 @@ impl<'a> Parser<'a> {
75267532
}))
75277533
}
75287534

7535+
/// Parse a[Statement::DropOperator] statement.
7536+
///
7537+
pub fn parse_drop_operator(&mut self) -> Result<Statement, ParserError> {
7538+
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
7539+
let operators = self.parse_comma_separated(|p| p.parse_drop_operator_signature())?;
7540+
let drop_behavior = self.parse_optional_drop_behavior();
7541+
Ok(Statement::DropOperator(DropOperator {
7542+
if_exists,
7543+
operators,
7544+
drop_behavior,
7545+
}))
7546+
}
7547+
7548+
/// Parse an operator signature for a [Statement::DropOperator]
7549+
/// Format: `name ( { left_type | NONE } , right_type )`
7550+
fn parse_drop_operator_signature(&mut self) -> Result<DropOperatorSignature, ParserError> {
7551+
let name = self.parse_operator_name()?;
7552+
self.expect_token(&Token::LParen)?;
7553+
7554+
// Parse left operand type (or NONE for prefix operators)
7555+
let left_type = if self.parse_keyword(Keyword::NONE) {
7556+
None
7557+
} else {
7558+
Some(self.parse_data_type()?)
7559+
};
7560+
7561+
self.expect_token(&Token::Comma)?;
7562+
7563+
// Parse right operand type (always required)
7564+
let right_type = self.parse_data_type()?;
7565+
7566+
self.expect_token(&Token::RParen)?;
7567+
7568+
Ok(DropOperatorSignature {
7569+
name,
7570+
left_type,
7571+
right_type,
7572+
})
7573+
}
7574+
75297575
//TODO: Implement parsing for Skewed
75307576
pub fn parse_hive_distribution(&mut self) -> Result<HiveDistributionStyle, ParserError> {
75317577
if self.parse_keywords(&[Keyword::PARTITIONED, Keyword::BY]) {
@@ -7538,8 +7584,8 @@ impl<'a> Parser<'a> {
75387584
}
75397585
}
75407586

7541-
pub fn parse_hive_formats(&mut self) -> Result<HiveFormat, ParserError> {
7542-
let mut hive_format = HiveFormat::default();
7587+
pub fn parse_hive_formats(&mut self) -> Result<Option<HiveFormat>, ParserError> {
7588+
let mut hive_format: Option<HiveFormat> = None;
75437589
loop {
75447590
match self.parse_one_of_keywords(&[
75457591
Keyword::ROW,
@@ -7548,32 +7594,39 @@ impl<'a> Parser<'a> {
75487594
Keyword::WITH,
75497595
]) {
75507596
Some(Keyword::ROW) => {
7551-
hive_format.row_format = Some(self.parse_row_format()?);
7597+
hive_format
7598+
.get_or_insert_with(HiveFormat::default)
7599+
.row_format = Some(self.parse_row_format()?);
75527600
}
75537601
Some(Keyword::STORED) => {
75547602
self.expect_keyword_is(Keyword::AS)?;
75557603
if self.parse_keyword(Keyword::INPUTFORMAT) {
75567604
let input_format = self.parse_expr()?;
75577605
self.expect_keyword_is(Keyword::OUTPUTFORMAT)?;
75587606
let output_format = self.parse_expr()?;
7559-
hive_format.storage = Some(HiveIOFormat::IOF {
7560-
input_format,
7561-
output_format,
7562-
});
7607+
hive_format.get_or_insert_with(HiveFormat::default).storage =
7608+
Some(HiveIOFormat::IOF {
7609+
input_format,
7610+
output_format,
7611+
});
75637612
} else {
75647613
let format = self.parse_file_format()?;
7565-
hive_format.storage = Some(HiveIOFormat::FileFormat { format });
7614+
hive_format.get_or_insert_with(HiveFormat::default).storage =
7615+
Some(HiveIOFormat::FileFormat { format });
75667616
}
75677617
}
75687618
Some(Keyword::LOCATION) => {
7569-
hive_format.location = Some(self.parse_literal_string()?);
7619+
hive_format.get_or_insert_with(HiveFormat::default).location =
7620+
Some(self.parse_literal_string()?);
75707621
}
75717622
Some(Keyword::WITH) => {
75727623
self.prev_token();
75737624
let properties = self
75747625
.parse_options_with_keywords(&[Keyword::WITH, Keyword::SERDEPROPERTIES])?;
75757626
if !properties.is_empty() {
7576-
hive_format.serde_properties = Some(properties);
7627+
hive_format
7628+
.get_or_insert_with(HiveFormat::default)
7629+
.serde_properties = Some(properties);
75777630
} else {
75787631
break;
75797632
}
@@ -7788,7 +7841,7 @@ impl<'a> Parser<'a> {
77887841
.if_not_exists(if_not_exists)
77897842
.transient(transient)
77907843
.hive_distribution(hive_distribution)
7791-
.hive_formats(Some(hive_formats))
7844+
.hive_formats(hive_formats)
77927845
.global(global)
77937846
.query(query)
77947847
.without_rowid(without_rowid)

tests/sqlparser_common.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4724,6 +4724,17 @@ fn parse_create_external_table_lowercase() {
47244724
assert_matches!(ast, Statement::CreateTable(CreateTable { .. }));
47254725
}
47264726

4727+
#[test]
4728+
fn parse_create_table_hive_formats_none_when_no_options() {
4729+
let sql = "CREATE TABLE simple_table (id INT, name VARCHAR(100))";
4730+
match verified_stmt(sql) {
4731+
Statement::CreateTable(CreateTable { hive_formats, .. }) => {
4732+
assert_eq!(hive_formats, None);
4733+
}
4734+
_ => unreachable!(),
4735+
}
4736+
}
4737+
47274738
#[test]
47284739
fn parse_alter_table() {
47294740
let add_column = "ALTER TABLE tab ADD COLUMN foo TEXT;";

tests/sqlparser_duckdb.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -739,12 +739,7 @@ fn test_duckdb_union_datatype() {
739739
],
740740
constraints: Default::default(),
741741
hive_distribution: HiveDistributionStyle::NONE,
742-
hive_formats: Some(HiveFormat {
743-
row_format: Default::default(),
744-
serde_properties: Default::default(),
745-
storage: Default::default(),
746-
location: Default::default()
747-
}),
742+
hive_formats: None,
748743
file_format: Default::default(),
749744
location: Default::default(),
750745
query: Default::default(),

tests/sqlparser_mssql.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,12 +1881,7 @@ fn parse_create_table_with_valid_options() {
18811881
],
18821882
constraints: vec![],
18831883
hive_distribution: HiveDistributionStyle::NONE,
1884-
hive_formats: Some(HiveFormat {
1885-
row_format: None,
1886-
serde_properties: None,
1887-
storage: None,
1888-
location: None,
1889-
},),
1884+
hive_formats: None,
18901885
file_format: None,
18911886
location: None,
18921887
query: None,
@@ -2053,12 +2048,7 @@ fn parse_create_table_with_identity_column() {
20532048
},],
20542049
constraints: vec![],
20552050
hive_distribution: HiveDistributionStyle::NONE,
2056-
hive_formats: Some(HiveFormat {
2057-
row_format: None,
2058-
serde_properties: None,
2059-
storage: None,
2060-
location: None,
2061-
},),
2051+
hive_formats: None,
20622052
file_format: None,
20632053
location: None,
20642054
query: None,

0 commit comments

Comments
 (0)