Skip to content

Commit 0a74aea

Browse files
authored
Merge branch 'apache:main' into solontsev/clickhouse-map-setting-support
2 parents f693735 + 95d16e3 commit 0a74aea

17 files changed

Lines changed: 798 additions & 197 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: 40 additions & 11 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

@@ -1421,7 +1426,24 @@ impl fmt::Display for ColumnDef {
14211426
pub struct ViewColumnDef {
14221427
pub name: Ident,
14231428
pub data_type: Option<DataType>,
1424-
pub options: Option<Vec<ColumnOption>>,
1429+
pub options: Option<ColumnOptions>,
1430+
}
1431+
1432+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1433+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1434+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1435+
pub enum ColumnOptions {
1436+
CommaSeparated(Vec<ColumnOption>),
1437+
SpaceSeparated(Vec<ColumnOption>),
1438+
}
1439+
1440+
impl ColumnOptions {
1441+
pub fn as_slice(&self) -> &[ColumnOption] {
1442+
match self {
1443+
ColumnOptions::CommaSeparated(options) => options.as_slice(),
1444+
ColumnOptions::SpaceSeparated(options) => options.as_slice(),
1445+
}
1446+
}
14251447
}
14261448

14271449
impl fmt::Display for ViewColumnDef {
@@ -1431,7 +1453,14 @@ impl fmt::Display for ViewColumnDef {
14311453
write!(f, " {}", data_type)?;
14321454
}
14331455
if let Some(options) = self.options.as_ref() {
1434-
write!(f, " {}", display_comma_separated(options.as_slice()))?;
1456+
match options {
1457+
ColumnOptions::CommaSeparated(column_options) => {
1458+
write!(f, " {}", display_comma_separated(column_options.as_slice()))?;
1459+
}
1460+
ColumnOptions::SpaceSeparated(column_options) => {
1461+
write!(f, " {}", display_separated(column_options.as_slice(), " "))?
1462+
}
1463+
}
14351464
}
14361465
Ok(())
14371466
}

src/ast/mod.rs

Lines changed: 107 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use helpers::{
2828
stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
2929
};
3030

31+
use core::cmp::Ordering;
3132
use core::ops::Deref;
3233
use core::{
3334
fmt::{self, Display},
@@ -60,13 +61,14 @@ pub use self::ddl::{
6061
AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
6162
AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterType, AlterTypeAddValue,
6263
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
63-
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnPolicy, ColumnPolicyProperty,
64-
ConstraintCharacteristics, CreateConnector, CreateDomain, CreateFunction, Deduplicate,
65-
DeferrableInitial, DropBehavior, GeneratedAs, GeneratedExpressionMode, IdentityParameters,
66-
IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder,
67-
IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition,
68-
ProcedureParam, ReferentialAction, ReplicaIdentity, TableConstraint, TagsColumnOption,
69-
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef,
64+
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
65+
ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain, CreateFunction,
66+
Deduplicate, DeferrableInitial, DropBehavior, GeneratedAs, GeneratedExpressionMode,
67+
IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind,
68+
IdentityPropertyOrder, IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner,
69+
Partition, ProcedureParam, ReferentialAction, ReplicaIdentity, TableConstraint,
70+
TagsColumnOption, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
71+
ViewColumnDef,
7072
};
7173
pub use self::dml::{CreateIndex, CreateTable, Delete, IndexColumn, Insert};
7274
pub use self::operator::{BinaryOperator, UnaryOperator};
@@ -172,7 +174,7 @@ fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fm
172174
}
173175

174176
/// An identifier, decomposed into its value or character data and the quote style.
175-
#[derive(Debug, Clone, PartialOrd, Ord)]
177+
#[derive(Debug, Clone)]
176178
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
177179
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
178180
pub struct Ident {
@@ -214,6 +216,35 @@ impl core::hash::Hash for Ident {
214216

215217
impl Eq for Ident {}
216218

219+
impl PartialOrd for Ident {
220+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
221+
Some(self.cmp(other))
222+
}
223+
}
224+
225+
impl Ord for Ident {
226+
fn cmp(&self, other: &Self) -> Ordering {
227+
let Ident {
228+
value,
229+
quote_style,
230+
// exhaustiveness check; we ignore spans in ordering
231+
span: _,
232+
} = self;
233+
234+
let Ident {
235+
value: other_value,
236+
quote_style: other_quote_style,
237+
// exhaustiveness check; we ignore spans in ordering
238+
span: _,
239+
} = other;
240+
241+
// First compare by value, then by quote_style
242+
value
243+
.cmp(other_value)
244+
.then_with(|| quote_style.cmp(other_quote_style))
245+
}
246+
}
247+
217248
impl Ident {
218249
/// Create a new identifier with the given value and no quotes and an empty span.
219250
pub fn new<S>(value: S) -> Self
@@ -748,7 +779,7 @@ pub enum Expr {
748779
/// `[ NOT ] IN (SELECT ...)`
749780
InSubquery {
750781
expr: Box<Expr>,
751-
subquery: Box<SetExpr>,
782+
subquery: Box<Query>,
752783
negated: bool,
753784
},
754785
/// `[ NOT ] IN UNNEST(array_expression)`
@@ -2990,6 +3021,36 @@ impl From<Set> for Statement {
29903021
}
29913022
}
29923023

3024+
/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3025+
/// for the arm.
3026+
///
3027+
/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3028+
/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3029+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3030+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3031+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3032+
pub struct ExceptionWhen {
3033+
pub idents: Vec<Ident>,
3034+
pub statements: Vec<Statement>,
3035+
}
3036+
3037+
impl Display for ExceptionWhen {
3038+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3039+
write!(
3040+
f,
3041+
"WHEN {idents} THEN",
3042+
idents = display_separated(&self.idents, " OR ")
3043+
)?;
3044+
3045+
if !self.statements.is_empty() {
3046+
write!(f, " ")?;
3047+
format_statement_list(f, &self.statements)?;
3048+
}
3049+
3050+
Ok(())
3051+
}
3052+
}
3053+
29933054
/// A top-level statement (SELECT, INSERT, CREATE, etc.)
29943055
#[allow(clippy::large_enum_variant)]
29953056
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
@@ -3678,17 +3739,20 @@ pub enum Statement {
36783739
/// END;
36793740
/// ```
36803741
statements: Vec<Statement>,
3681-
/// Statements of an exception clause.
3742+
/// Exception handling with exception clauses.
36823743
/// Example:
36833744
/// ```sql
3684-
/// BEGIN
3685-
/// SELECT 1;
3686-
/// EXCEPTION WHEN ERROR THEN
3687-
/// SELECT 2;
3688-
/// SELECT 3;
3689-
/// END;
3745+
/// EXCEPTION
3746+
/// WHEN EXCEPTION_1 THEN
3747+
/// SELECT 2;
3748+
/// WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
3749+
/// SELECT 3;
3750+
/// WHEN OTHER THEN
3751+
/// SELECT 4;
3752+
/// ```
36903753
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3691-
exception_statements: Option<Vec<Statement>>,
3754+
/// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3755+
exception: Option<Vec<ExceptionWhen>>,
36923756
/// TRUE if the statement has an `END` keyword.
36933757
has_end_keyword: bool,
36943758
},
@@ -3881,6 +3945,7 @@ pub enum Statement {
38813945
or_alter: bool,
38823946
name: ObjectName,
38833947
params: Option<Vec<ProcedureParam>>,
3948+
language: Option<Ident>,
38843949
body: ConditionalStatements,
38853950
},
38863951
/// ```sql
@@ -4181,7 +4246,7 @@ pub enum Statement {
41814246
/// ```sql
41824247
/// NOTIFY channel [ , payload ]
41834248
/// ```
4184-
/// send a notification event together with an optional payload string to channel
4249+
/// send a notification event together with an optional "payload" string to channel
41854250
///
41864251
/// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
41874252
NOTIFY {
@@ -4784,6 +4849,7 @@ impl fmt::Display for Statement {
47844849
name,
47854850
or_alter,
47864851
params,
4852+
language,
47874853
body,
47884854
} => {
47894855
write!(
@@ -4799,6 +4865,10 @@ impl fmt::Display for Statement {
47994865
}
48004866
}
48014867

4868+
if let Some(language) = language {
4869+
write!(f, " LANGUAGE {language}")?;
4870+
}
4871+
48024872
write!(f, " AS {body}")
48034873
}
48044874
Statement::CreateMacro {
@@ -5533,7 +5603,7 @@ impl fmt::Display for Statement {
55335603
transaction,
55345604
modifier,
55355605
statements,
5536-
exception_statements,
5606+
exception,
55375607
has_end_keyword,
55385608
} => {
55395609
if *syntax_begin {
@@ -5555,11 +5625,10 @@ impl fmt::Display for Statement {
55555625
write!(f, " ")?;
55565626
format_statement_list(f, statements)?;
55575627
}
5558-
if let Some(exception_statements) = exception_statements {
5559-
write!(f, " EXCEPTION WHEN ERROR THEN")?;
5560-
if !exception_statements.is_empty() {
5561-
write!(f, " ")?;
5562-
format_statement_list(f, exception_statements)?;
5628+
if let Some(exception_when) = exception {
5629+
write!(f, " EXCEPTION")?;
5630+
for when in exception_when {
5631+
write!(f, " {when}")?;
55635632
}
55645633
}
55655634
if *has_end_keyword {
@@ -9739,6 +9808,8 @@ impl fmt::Display for NullInclusion {
97399808

97409809
#[cfg(test)]
97419810
mod tests {
9811+
use crate::tokenizer::Location;
9812+
97429813
use super::*;
97439814

97449815
#[test]
@@ -10034,4 +10105,16 @@ mod tests {
1003410105
test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
1003510106
test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
1003610107
}
10108+
10109+
// Tests that the position in the code of an `Ident` does not affect its
10110+
// ordering.
10111+
#[test]
10112+
fn test_ident_ord() {
10113+
let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
10114+
let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
10115+
10116+
assert!(a < b);
10117+
std::mem::swap(&mut a.span, &mut b.span);
10118+
assert!(a < b);
10119+
}
1003710120
}

0 commit comments

Comments
 (0)