Skip to content

Commit 0fc29b2

Browse files
committed
Merge remote-tracking branch 'upstream/main' into eper/snowflake-with-column-options
2 parents ba00077 + b9365b3 commit 0fc29b2

15 files changed

Lines changed: 608 additions & 154 deletions

src/ast/data_type.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,14 @@ pub enum DataType {
446446
///
447447
/// [PostgreSQL]: https://www.postgresql.org/docs/9.5/functions-geometry.html
448448
GeometricType(GeometricTypeKind),
449+
/// PostgreSQL text search vectors, see [PostgreSQL].
450+
///
451+
/// [PostgreSQL]: https://www.postgresql.org/docs/17/datatype-textsearch.html
452+
TsVector,
453+
/// PostgreSQL text search query, see [PostgreSQL].
454+
///
455+
/// [PostgreSQL]: https://www.postgresql.org/docs/17/datatype-textsearch.html
456+
TsQuery,
449457
}
450458

451459
impl fmt::Display for DataType {
@@ -738,6 +746,8 @@ impl fmt::Display for DataType {
738746
write!(f, "{} TABLE ({})", name, display_comma_separated(columns))
739747
}
740748
DataType::GeometricType(kind) => write!(f, "{}", kind),
749+
DataType::TsVector => write!(f, "TSVECTOR"),
750+
DataType::TsQuery => write!(f, "TSQUERY"),
741751
}
742752
}
743753
}

src/ast/ddl.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ use sqlparser_derive::{Visit, VisitMut};
3030

3131
use crate::ast::value::escape_single_quote_string;
3232
use crate::ast::{
33-
display_comma_separated, display_separated, CommentDef, CreateFunctionBody,
33+
display_comma_separated, display_separated, ArgMode, CommentDef, CreateFunctionBody,
3434
CreateFunctionUsing, DataType, Expr, FunctionBehavior, FunctionCalledOnNull,
35-
FunctionDeterminismSpecifier, FunctionParallel, Ident, MySQLColumnPosition, ObjectName,
36-
OperateFunctionArg, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Tag, Value,
37-
ValueWithSpan,
35+
FunctionDeterminismSpecifier, FunctionParallel, Ident, IndexColumn, MySQLColumnPosition,
36+
ObjectName, OperateFunctionArg, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Tag,
37+
Value, ValueWithSpan,
3838
};
3939
use crate::keywords::Keyword;
4040
use crate::tokenizer::Token;
@@ -979,7 +979,7 @@ pub enum TableConstraint {
979979
/// [1]: IndexType
980980
index_type: Option<IndexType>,
981981
/// Identifiers of the columns that are unique.
982-
columns: Vec<Ident>,
982+
columns: Vec<IndexColumn>,
983983
index_options: Vec<IndexOption>,
984984
characteristics: Option<ConstraintCharacteristics>,
985985
/// Optional Postgres nulls handling: `[ NULLS [ NOT ] DISTINCT ]`
@@ -1015,7 +1015,7 @@ pub enum TableConstraint {
10151015
/// [1]: IndexType
10161016
index_type: Option<IndexType>,
10171017
/// Identifiers of the columns that form the primary key.
1018-
columns: Vec<Ident>,
1018+
columns: Vec<IndexColumn>,
10191019
index_options: Vec<IndexOption>,
10201020
characteristics: Option<ConstraintCharacteristics>,
10211021
},
@@ -1060,7 +1060,7 @@ pub enum TableConstraint {
10601060
/// [1]: IndexType
10611061
index_type: Option<IndexType>,
10621062
/// Referred column identifier list.
1063-
columns: Vec<Ident>,
1063+
columns: Vec<IndexColumn>,
10641064
},
10651065
/// MySQLs [fulltext][1] definition. Since the [`SPATIAL`][2] definition is exactly the same,
10661066
/// and MySQL displays both the same way, it is part of this definition as well.
@@ -1083,7 +1083,7 @@ pub enum TableConstraint {
10831083
/// Optional index name.
10841084
opt_index_name: Option<Ident>,
10851085
/// Referred column identifier list.
1086-
columns: Vec<Ident>,
1086+
columns: Vec<IndexColumn>,
10871087
},
10881088
}
10891089

@@ -1367,11 +1367,16 @@ impl fmt::Display for NullsDistinctOption {
13671367
pub struct ProcedureParam {
13681368
pub name: Ident,
13691369
pub data_type: DataType,
1370+
pub mode: Option<ArgMode>,
13701371
}
13711372

13721373
impl fmt::Display for ProcedureParam {
13731374
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1374-
write!(f, "{} {}", self.name, self.data_type)
1375+
if let Some(mode) = &self.mode {
1376+
write!(f, "{mode} {} {}", self.name, self.data_type)
1377+
} else {
1378+
write!(f, "{} {}", self.name, self.data_type)
1379+
}
13751380
}
13761381
}
13771382

src/ast/mod.rs

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ pub enum Expr {
749749
/// `[ NOT ] IN (SELECT ...)`
750750
InSubquery {
751751
expr: Box<Expr>,
752-
subquery: Box<SetExpr>,
752+
subquery: Box<Query>,
753753
negated: bool,
754754
},
755755
/// `[ NOT ] IN UNNEST(array_expression)`
@@ -2991,6 +2991,36 @@ impl From<Set> for Statement {
29912991
}
29922992
}
29932993

2994+
/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
2995+
/// for the arm.
2996+
///
2997+
/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
2998+
/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
2999+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3000+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3001+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3002+
pub struct ExceptionWhen {
3003+
pub idents: Vec<Ident>,
3004+
pub statements: Vec<Statement>,
3005+
}
3006+
3007+
impl Display for ExceptionWhen {
3008+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3009+
write!(
3010+
f,
3011+
"WHEN {idents} THEN",
3012+
idents = display_separated(&self.idents, " OR ")
3013+
)?;
3014+
3015+
if !self.statements.is_empty() {
3016+
write!(f, " ")?;
3017+
format_statement_list(f, &self.statements)?;
3018+
}
3019+
3020+
Ok(())
3021+
}
3022+
}
3023+
29943024
/// A top-level statement (SELECT, INSERT, CREATE, etc.)
29953025
#[allow(clippy::large_enum_variant)]
29963026
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
@@ -3679,17 +3709,20 @@ pub enum Statement {
36793709
/// END;
36803710
/// ```
36813711
statements: Vec<Statement>,
3682-
/// Statements of an exception clause.
3712+
/// Exception handling with exception clauses.
36833713
/// Example:
36843714
/// ```sql
3685-
/// BEGIN
3686-
/// SELECT 1;
3687-
/// EXCEPTION WHEN ERROR THEN
3688-
/// SELECT 2;
3689-
/// SELECT 3;
3690-
/// END;
3715+
/// EXCEPTION
3716+
/// WHEN EXCEPTION_1 THEN
3717+
/// SELECT 2;
3718+
/// WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
3719+
/// SELECT 3;
3720+
/// WHEN OTHER THEN
3721+
/// SELECT 4;
3722+
/// ```
36913723
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3692-
exception_statements: Option<Vec<Statement>>,
3724+
/// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3725+
exception: Option<Vec<ExceptionWhen>>,
36933726
/// TRUE if the statement has an `END` keyword.
36943727
has_end_keyword: bool,
36953728
},
@@ -5534,7 +5567,7 @@ impl fmt::Display for Statement {
55345567
transaction,
55355568
modifier,
55365569
statements,
5537-
exception_statements,
5570+
exception,
55385571
has_end_keyword,
55395572
} => {
55405573
if *syntax_begin {
@@ -5556,11 +5589,10 @@ impl fmt::Display for Statement {
55565589
write!(f, " ")?;
55575590
format_statement_list(f, statements)?;
55585591
}
5559-
if let Some(exception_statements) = exception_statements {
5560-
write!(f, " EXCEPTION WHEN ERROR THEN")?;
5561-
if !exception_statements.is_empty() {
5562-
write!(f, " ")?;
5563-
format_statement_list(f, exception_statements)?;
5592+
if let Some(exception_when) = exception {
5593+
write!(f, " EXCEPTION")?;
5594+
for when in exception_when {
5595+
write!(f, " {when}")?;
55645596
}
55655597
}
55665598
if *has_end_keyword {

src/ast/spans.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,17 @@ use super::{
2828
ConstraintCharacteristics, CopySource, CreateIndex, CreateTable, CreateTableOptions, Cte,
2929
Delete, DoUpdate, ExceptSelectItem, ExcludeSelectItem, Expr, ExprWithAlias, Fetch, FromTable,
3030
Function, FunctionArg, FunctionArgExpr, FunctionArgumentClause, FunctionArgumentList,
31-
FunctionArguments, GroupByExpr, HavingBound, IfStatement, IlikeSelectItem, Insert, Interpolate,
32-
InterpolateExpr, Join, JoinConstraint, JoinOperator, JsonPath, JsonPathElem, LateralView,
33-
LimitClause, MatchRecognizePattern, Measure, NamedParenthesizedList, NamedWindowDefinition,
34-
ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction, OnInsert, OpenStatement,
35-
OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource, ProjectionSelect, Query,
36-
RaiseStatement, RaiseStatementValue, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
37-
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SqlOption, Statement, Subscript,
38-
SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor, TableObject,
39-
TableOptionsClustered, TableWithJoins, UpdateTableFromKind, Use, Value, Values, ViewColumnDef,
40-
WhileStatement, WildcardAdditionalOptions, With, WithFill,
31+
FunctionArguments, GroupByExpr, HavingBound, IfStatement, IlikeSelectItem, IndexColumn, Insert,
32+
Interpolate, InterpolateExpr, Join, JoinConstraint, JoinOperator, JsonPath, JsonPathElem,
33+
LateralView, LimitClause, MatchRecognizePattern, Measure, NamedParenthesizedList,
34+
NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction,
35+
OnInsert, OpenStatement, OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource,
36+
ProjectionSelect, Query, RaiseStatement, RaiseStatementValue, ReferentialAction,
37+
RenameSelectItem, ReplaceSelectElement, ReplaceSelectItem, Select, SelectInto, SelectItem,
38+
SetExpr, SqlOption, Statement, Subscript, SymbolDefinition, TableAlias, TableAliasColumnDef,
39+
TableConstraint, TableFactor, TableObject, TableOptionsClustered, TableWithJoins,
40+
UpdateTableFromKind, Use, Value, Values, ViewColumnDef, WhileStatement,
41+
WildcardAdditionalOptions, With, WithFill,
4142
};
4243

4344
/// Given an iterator of spans, return the [Span::union] of all spans.
@@ -650,7 +651,7 @@ impl Spanned for TableConstraint {
650651
name.iter()
651652
.map(|i| i.span)
652653
.chain(index_name.iter().map(|i| i.span))
653-
.chain(columns.iter().map(|i| i.span))
654+
.chain(columns.iter().map(|i| i.span()))
654655
.chain(characteristics.iter().map(|i| i.span())),
655656
),
656657
TableConstraint::PrimaryKey {
@@ -664,7 +665,7 @@ impl Spanned for TableConstraint {
664665
name.iter()
665666
.map(|i| i.span)
666667
.chain(index_name.iter().map(|i| i.span))
667-
.chain(columns.iter().map(|i| i.span))
668+
.chain(columns.iter().map(|i| i.span()))
668669
.chain(characteristics.iter().map(|i| i.span())),
669670
),
670671
TableConstraint::ForeignKey {
@@ -700,7 +701,7 @@ impl Spanned for TableConstraint {
700701
} => union_spans(
701702
name.iter()
702703
.map(|i| i.span)
703-
.chain(columns.iter().map(|i| i.span)),
704+
.chain(columns.iter().map(|i| i.span())),
704705
),
705706
TableConstraint::FulltextOrSpatial {
706707
fulltext: _,
@@ -711,7 +712,7 @@ impl Spanned for TableConstraint {
711712
opt_index_name
712713
.iter()
713714
.map(|i| i.span)
714-
.chain(columns.iter().map(|i| i.span)),
715+
.chain(columns.iter().map(|i| i.span())),
715716
),
716717
}
717718
}
@@ -745,6 +746,12 @@ impl Spanned for CreateIndex {
745746
}
746747
}
747748

749+
impl Spanned for IndexColumn {
750+
fn span(&self) -> Span {
751+
self.column.span()
752+
}
753+
}
754+
748755
impl Spanned for CaseStatement {
749756
fn span(&self) -> Span {
750757
let CaseStatement {

src/dialect/bigquery.rs

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ pub struct BigQueryDialect;
4646

4747
impl Dialect for BigQueryDialect {
4848
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
49-
self.maybe_parse_statement(parser)
49+
if parser.parse_keyword(Keyword::BEGIN) {
50+
return Some(parser.parse_begin_exception_end());
51+
}
52+
53+
None
5054
}
5155

5256
/// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers>
@@ -141,48 +145,3 @@ impl Dialect for BigQueryDialect {
141145
true
142146
}
143147
}
144-
145-
impl BigQueryDialect {
146-
fn maybe_parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
147-
if parser.peek_keyword(Keyword::BEGIN) {
148-
return Some(self.parse_begin(parser));
149-
}
150-
None
151-
}
152-
153-
/// Parse a `BEGIN` statement.
154-
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
155-
fn parse_begin(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
156-
parser.expect_keyword(Keyword::BEGIN)?;
157-
158-
let statements = parser.parse_statement_list(&[Keyword::EXCEPTION, Keyword::END])?;
159-
160-
let has_exception_when_clause = parser.parse_keywords(&[
161-
Keyword::EXCEPTION,
162-
Keyword::WHEN,
163-
Keyword::ERROR,
164-
Keyword::THEN,
165-
]);
166-
let exception_statements = if has_exception_when_clause {
167-
if !parser.peek_keyword(Keyword::END) {
168-
Some(parser.parse_statement_list(&[Keyword::END])?)
169-
} else {
170-
Some(Default::default())
171-
}
172-
} else {
173-
None
174-
};
175-
176-
parser.expect_keyword(Keyword::END)?;
177-
178-
Ok(Statement::StartTransaction {
179-
begin: true,
180-
statements,
181-
exception_statements,
182-
has_end_keyword: true,
183-
transaction: None,
184-
modifier: None,
185-
modes: Default::default(),
186-
})
187-
}
188-
}

src/dialect/snowflake.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ impl Dialect for SnowflakeDialect {
131131
}
132132

133133
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
134+
if parser.parse_keyword(Keyword::BEGIN) {
135+
return Some(parser.parse_begin_exception_end());
136+
}
137+
134138
if parser.parse_keywords(&[Keyword::ALTER, Keyword::SESSION]) {
135139
// ALTER SESSION
136140
let set = match parser.parse_one_of_keywords(&[Keyword::SET, Keyword::UNSET]) {

src/keywords.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@ define_keywords!(
646646
ORDER,
647647
ORDINALITY,
648648
ORGANIZATION,
649+
OTHER,
649650
OUT,
650651
OUTER,
651652
OUTPUT,
@@ -934,6 +935,8 @@ define_keywords!(
934935
TRY,
935936
TRY_CAST,
936937
TRY_CONVERT,
938+
TSQUERY,
939+
TSVECTOR,
937940
TUPLE,
938941
TYPE,
939942
UBIGINT,

0 commit comments

Comments
 (0)