Skip to content

Commit 7017a1c

Browse files
committed
Merge remote-tracking branch 'upstream/main' into eper/ident-ord
2 parents 4448ea6 + b9365b3 commit 7017a1c

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
@@ -778,7 +778,7 @@ pub enum Expr {
778778
/// `[ NOT ] IN (SELECT ...)`
779779
InSubquery {
780780
expr: Box<Expr>,
781-
subquery: Box<SetExpr>,
781+
subquery: Box<Query>,
782782
negated: bool,
783783
},
784784
/// `[ NOT ] IN UNNEST(array_expression)`
@@ -3020,6 +3020,36 @@ impl From<Set> for Statement {
30203020
}
30213021
}
30223022

3023+
/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3024+
/// for the arm.
3025+
///
3026+
/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3027+
/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3028+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3029+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3030+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3031+
pub struct ExceptionWhen {
3032+
pub idents: Vec<Ident>,
3033+
pub statements: Vec<Statement>,
3034+
}
3035+
3036+
impl Display for ExceptionWhen {
3037+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3038+
write!(
3039+
f,
3040+
"WHEN {idents} THEN",
3041+
idents = display_separated(&self.idents, " OR ")
3042+
)?;
3043+
3044+
if !self.statements.is_empty() {
3045+
write!(f, " ")?;
3046+
format_statement_list(f, &self.statements)?;
3047+
}
3048+
3049+
Ok(())
3050+
}
3051+
}
3052+
30233053
/// A top-level statement (SELECT, INSERT, CREATE, etc.)
30243054
#[allow(clippy::large_enum_variant)]
30253055
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
@@ -3708,17 +3738,20 @@ pub enum Statement {
37083738
/// END;
37093739
/// ```
37103740
statements: Vec<Statement>,
3711-
/// Statements of an exception clause.
3741+
/// Exception handling with exception clauses.
37123742
/// Example:
37133743
/// ```sql
3714-
/// BEGIN
3715-
/// SELECT 1;
3716-
/// EXCEPTION WHEN ERROR THEN
3717-
/// SELECT 2;
3718-
/// SELECT 3;
3719-
/// END;
3744+
/// EXCEPTION
3745+
/// WHEN EXCEPTION_1 THEN
3746+
/// SELECT 2;
3747+
/// WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
3748+
/// SELECT 3;
3749+
/// WHEN OTHER THEN
3750+
/// SELECT 4;
3751+
/// ```
37203752
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3721-
exception_statements: Option<Vec<Statement>>,
3753+
/// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3754+
exception: Option<Vec<ExceptionWhen>>,
37223755
/// TRUE if the statement has an `END` keyword.
37233756
has_end_keyword: bool,
37243757
},
@@ -5563,7 +5596,7 @@ impl fmt::Display for Statement {
55635596
transaction,
55645597
modifier,
55655598
statements,
5566-
exception_statements,
5599+
exception,
55675600
has_end_keyword,
55685601
} => {
55695602
if *syntax_begin {
@@ -5585,11 +5618,10 @@ impl fmt::Display for Statement {
55855618
write!(f, " ")?;
55865619
format_statement_list(f, statements)?;
55875620
}
5588-
if let Some(exception_statements) = exception_statements {
5589-
write!(f, " EXCEPTION WHEN ERROR THEN")?;
5590-
if !exception_statements.is_empty() {
5591-
write!(f, " ")?;
5592-
format_statement_list(f, exception_statements)?;
5621+
if let Some(exception_when) = exception {
5622+
write!(f, " EXCEPTION")?;
5623+
for when in exception_when {
5624+
write!(f, " {when}")?;
55935625
}
55945626
}
55955627
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)