Skip to content

Commit 112aa3b

Browse files
Merge branch 'main' into create-user-consumes-terminator
2 parents 81a6fb0 + c3701e2 commit 112aa3b

11 files changed

Lines changed: 776 additions & 362 deletions

File tree

sqlparser_bench/benches/sqlparser_bench.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,34 @@ fn parse_prefix_case_chain(c: &mut Criterion) {
245245
group.finish();
246246
}
247247

248+
/// Benchmark parsing pathological paren chains that previously caused 2^N
249+
/// work in `parse_table_factor`. The input `SELECT 1 FROM ((((...` rejects
250+
/// at EOF, which used to force exponential backtracking through the chain.
251+
fn parse_table_factor_paren_chain(c: &mut Criterion) {
252+
let mut group = c.benchmark_group("parse_table_factor_paren_chain");
253+
let dialect = GenericDialect {};
254+
255+
for &n in &[10usize, 20, 30] {
256+
let mut sql = String::from("SELECT 1 ");
257+
for _ in 0..5 {
258+
sql.push_str("FROM ");
259+
sql.push_str(&"(".repeat(n));
260+
sql.push(' ');
261+
}
262+
263+
group.bench_function(format!("chain_{n}"), |b| {
264+
b.iter(|| {
265+
let _ = Parser::new(&dialect)
266+
.with_recursion_limit(256)
267+
.try_with_sql(std::hint::black_box(&sql))
268+
.and_then(|mut p| p.parse_statements());
269+
});
270+
});
271+
}
272+
273+
group.finish();
274+
}
275+
248276
criterion_group!(
249277
benches,
250278
basic_queries,
@@ -253,6 +281,7 @@ criterion_group!(
253281
parse_compound_chain,
254282
parse_compound_keyword_chain,
255283
parse_prefix_keyword_call_chain,
256-
parse_prefix_case_chain
284+
parse_prefix_case_chain,
285+
parse_table_factor_paren_chain
257286
);
258287
criterion_main!(benches);

src/ast/ddl.rs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5632,6 +5632,161 @@ impl Spanned for AlterFunction {
56325632
}
56335633
}
56345634

5635+
/// Text search object kind.
5636+
///
5637+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-intro.html).
5638+
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
5639+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5640+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5641+
pub enum TextSearchObjectType {
5642+
/// `DICTIONARY`
5643+
Dictionary,
5644+
/// `CONFIGURATION`
5645+
Configuration,
5646+
/// `TEMPLATE`
5647+
Template,
5648+
/// `PARSER`
5649+
Parser,
5650+
}
5651+
5652+
impl fmt::Display for TextSearchObjectType {
5653+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5654+
match self {
5655+
TextSearchObjectType::Dictionary => write!(f, "DICTIONARY"),
5656+
TextSearchObjectType::Configuration => write!(f, "CONFIGURATION"),
5657+
TextSearchObjectType::Template => write!(f, "TEMPLATE"),
5658+
TextSearchObjectType::Parser => write!(f, "PARSER"),
5659+
}
5660+
}
5661+
}
5662+
5663+
/// `CREATE TEXT SEARCH ...` statement.
5664+
///
5665+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createtsdictionary.html).
5666+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5667+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5668+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5669+
pub struct CreateTextSearch {
5670+
/// The specific text search object type.
5671+
pub object_type: TextSearchObjectType,
5672+
/// Object name.
5673+
pub name: ObjectName,
5674+
/// Parenthesized options.
5675+
pub options: Vec<SqlOption>,
5676+
}
5677+
5678+
impl fmt::Display for CreateTextSearch {
5679+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5680+
write!(
5681+
f,
5682+
"CREATE TEXT SEARCH {} {} ({})",
5683+
self.object_type,
5684+
self.name,
5685+
display_comma_separated(&self.options)
5686+
)
5687+
}
5688+
}
5689+
5690+
impl Spanned for CreateTextSearch {
5691+
fn span(&self) -> Span {
5692+
Span::empty()
5693+
}
5694+
}
5695+
5696+
/// Option assignment used by `ALTER TEXT SEARCH ... ( ... )`.
5697+
///
5698+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertsdictionary.html).
5699+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5700+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5701+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5702+
pub struct AlterTextSearchOption {
5703+
/// Option name.
5704+
pub key: Ident,
5705+
/// Optional value (`option [= value]`).
5706+
pub value: Option<Expr>,
5707+
}
5708+
5709+
impl fmt::Display for AlterTextSearchOption {
5710+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5711+
match &self.value {
5712+
Some(value) => write!(f, "{} = {}", self.key, value),
5713+
None => write!(f, "{}", self.key),
5714+
}
5715+
}
5716+
}
5717+
5718+
/// Operation for `ALTER TEXT SEARCH ...`.
5719+
///
5720+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertsdictionary.html).
5721+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5722+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5723+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5724+
pub enum AlterTextSearchOperation {
5725+
/// `RENAME TO new_name`
5726+
RenameTo {
5727+
/// New name.
5728+
new_name: Ident,
5729+
},
5730+
/// `OWNER TO ...`
5731+
OwnerTo(Owner),
5732+
/// `SET SCHEMA schema_name`
5733+
SetSchema {
5734+
/// Target schema.
5735+
schema_name: ObjectName,
5736+
},
5737+
/// `( option [= value] [, ...] )`
5738+
SetOptions {
5739+
/// Text search options to apply.
5740+
options: Vec<AlterTextSearchOption>,
5741+
},
5742+
}
5743+
5744+
impl fmt::Display for AlterTextSearchOperation {
5745+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5746+
match self {
5747+
AlterTextSearchOperation::RenameTo { new_name } => write!(f, "RENAME TO {new_name}"),
5748+
AlterTextSearchOperation::OwnerTo(owner) => write!(f, "OWNER TO {owner}"),
5749+
AlterTextSearchOperation::SetSchema { schema_name } => {
5750+
write!(f, "SET SCHEMA {schema_name}")
5751+
}
5752+
AlterTextSearchOperation::SetOptions { options } => {
5753+
write!(f, "({})", display_comma_separated(options))
5754+
}
5755+
}
5756+
}
5757+
}
5758+
5759+
/// `ALTER TEXT SEARCH ...` statement.
5760+
///
5761+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertsdictionary.html).
5762+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5763+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5764+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5765+
pub struct AlterTextSearch {
5766+
/// The specific text search object type.
5767+
pub object_type: TextSearchObjectType,
5768+
/// Object name.
5769+
pub name: ObjectName,
5770+
/// Operation to apply.
5771+
pub operation: AlterTextSearchOperation,
5772+
}
5773+
5774+
impl fmt::Display for AlterTextSearch {
5775+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5776+
write!(
5777+
f,
5778+
"ALTER TEXT SEARCH {} {} {}",
5779+
self.object_type, self.name, self.operation
5780+
)
5781+
}
5782+
}
5783+
5784+
impl Spanned for AlterTextSearch {
5785+
fn span(&self) -> Span {
5786+
Span::empty()
5787+
}
5788+
}
5789+
56355790
/// CREATE POLICY statement.
56365791
///
56375792
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)

src/ast/mod.rs

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,23 +65,25 @@ pub use self::ddl::{
6565
AlterIndexOperation, AlterOperator, AlterOperatorClass, AlterOperatorClassOperation,
6666
AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
6767
AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
68-
AlterTableLock, AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue,
69-
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
70-
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
71-
ColumnPolicyProperty, ConstraintCharacteristics, CreateCollation, CreateCollationDefinition,
72-
CreateConnector, CreateDomain, CreateExtension, CreateFunction, CreateIndex, CreateOperator,
68+
AlterTableLock, AlterTableOperation, AlterTableType, AlterTextSearch, AlterTextSearchOperation,
69+
AlterTextSearchOption, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
70+
AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef,
71+
ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, ColumnPolicyProperty,
72+
ConstraintCharacteristics, CreateCollation, CreateCollationDefinition, CreateConnector,
73+
CreateDomain, CreateExtension, CreateFunction, CreateIndex, CreateOperator,
7374
CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
74-
CreateTable, CreateTrigger, CreateView, Deduplicate, DeferrableInitial, DistStyle,
75-
DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily,
76-
DropOperatorSignature, DropPolicy, DropTrigger, ForValues, FunctionReturnType, GeneratedAs,
77-
GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
78-
IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
79-
KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes, OperatorClassItem,
80-
OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition,
81-
PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity,
82-
TagsColumnOption, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
83-
UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
84-
UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef, WithData,
75+
CreateTable, CreateTextSearch, CreateTrigger, CreateView, Deduplicate, DeferrableInitial,
76+
DistStyle, DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass,
77+
DropOperatorFamily, DropOperatorSignature, DropPolicy, DropTrigger, ForValues,
78+
FunctionReturnType, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
79+
IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
80+
IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes,
81+
OperatorClassItem, OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose,
82+
Owner, Partition, PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind,
83+
ReplicaIdentity, TagsColumnOption, TextSearchObjectType, TriggerObjectKind, Truncate,
84+
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
85+
UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
86+
UserDefinedTypeStorage, ViewColumnDef, WithData,
8587
};
8688
pub use self::dml::{
8789
Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
@@ -3754,6 +3756,10 @@ pub enum Statement {
37543756
/// ```
37553757
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
37563758
CreateOperatorClass(CreateOperatorClass),
3759+
/// A `CREATE TEXT SEARCH` statement.
3760+
///
3761+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-intro.html)
3762+
CreateTextSearch(CreateTextSearch),
37573763
/// ```sql
37583764
/// ALTER TABLE
37593765
/// ```
@@ -3818,6 +3824,10 @@ pub enum Statement {
38183824
/// ```
38193825
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
38203826
AlterOperatorClass(AlterOperatorClass),
3827+
/// An `ALTER TEXT SEARCH` statement.
3828+
///
3829+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-configuration.html)
3830+
AlterTextSearch(AlterTextSearch),
38213831
/// ```sql
38223832
/// ALTER ROLE
38233833
/// ```
@@ -5578,6 +5588,7 @@ impl fmt::Display for Statement {
55785588
create_operator_family.fmt(f)
55795589
}
55805590
Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5591+
Statement::CreateTextSearch(create_text_search) => create_text_search.fmt(f),
55815592
Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
55825593
Statement::AlterIndex { name, operation } => {
55835594
write!(f, "ALTER INDEX {name} {operation}")
@@ -5609,6 +5620,7 @@ impl fmt::Display for Statement {
56095620
Statement::AlterOperatorClass(alter_operator_class) => {
56105621
write!(f, "{alter_operator_class}")
56115622
}
5623+
Statement::AlterTextSearch(alter_text_search) => write!(f, "{alter_text_search}"),
56125624
Statement::AlterRole { name, operation } => {
56135625
write!(f, "ALTER ROLE {name} {operation}")
56145626
}
@@ -12269,6 +12281,12 @@ impl From<CreateOperatorClass> for Statement {
1226912281
}
1227012282
}
1227112283

12284+
impl From<CreateTextSearch> for Statement {
12285+
fn from(c: CreateTextSearch) -> Self {
12286+
Self::CreateTextSearch(c)
12287+
}
12288+
}
12289+
1227212290
impl From<AlterSchema> for Statement {
1227312291
fn from(a: AlterSchema) -> Self {
1227412292
Self::AlterSchema(a)
@@ -12311,6 +12329,12 @@ impl From<AlterOperatorClass> for Statement {
1231112329
}
1231212330
}
1231312331

12332+
impl From<AlterTextSearch> for Statement {
12333+
fn from(a: AlterTextSearch) -> Self {
12334+
Self::AlterTextSearch(a)
12335+
}
12336+
}
12337+
1231412338
impl From<Merge> for Statement {
1231512339
fn from(m: Merge) -> Self {
1231612340
Self::Merge(m)

src/ast/spans.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ impl Spanned for Statement {
400400
create_operator_family.span()
401401
}
402402
Statement::CreateOperatorClass(create_operator_class) => create_operator_class.span(),
403+
Statement::CreateTextSearch(create_text_search) => create_text_search.span(),
403404
Statement::AlterTable(alter_table) => alter_table.span(),
404405
Statement::AlterIndex { name, operation } => name.span().union(&operation.span()),
405406
Statement::AlterView {
@@ -420,6 +421,7 @@ impl Spanned for Statement {
420421
Statement::AlterOperator { .. } => Span::empty(),
421422
Statement::AlterOperatorFamily { .. } => Span::empty(),
422423
Statement::AlterOperatorClass { .. } => Span::empty(),
424+
Statement::AlterTextSearch { .. } => Span::empty(),
423425
Statement::AlterRole { .. } => Span::empty(),
424426
Statement::AlterSession { .. } => Span::empty(),
425427
Statement::AttachDatabase { .. } => Span::empty(),

src/dialect/mysql.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ impl Dialect for MySqlDialect {
221221
fn supports_group_by_with_modifier(&self) -> bool {
222222
true
223223
}
224+
225+
fn supports_left_associative_joins_without_parens(&self) -> bool {
226+
false
227+
}
224228
}
225229

226230
/// `LOCK TABLES`

src/dialect/redshift.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ impl Dialect for RedshiftSqlDialect {
147147
true
148148
}
149149

150+
fn supports_left_associative_joins_without_parens(&self) -> bool {
151+
false
152+
}
153+
150154
fn supports_select_exclude(&self) -> bool {
151155
true
152156
}

src/keywords.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ define_keywords!(
247247
COMPUTE,
248248
CONCURRENTLY,
249249
CONDITION,
250+
CONFIGURATION,
250251
CONFLICT,
251252
CONNECT,
252253
CONNECTION,
@@ -334,6 +335,7 @@ define_keywords!(
334335
DETACH,
335336
DETAIL,
336337
DETERMINISTIC,
338+
DICTIONARY,
337339
DIMENSIONS,
338340
DIRECTORY,
339341
DISABLE,
@@ -768,6 +770,7 @@ define_keywords!(
768770
PARALLEL,
769771
PARAMETER,
770772
PARQUET,
773+
PARSER,
771774
PART,
772775
PARTIAL,
773776
PARTITION,
@@ -1039,6 +1042,7 @@ define_keywords!(
10391042
TASK,
10401043
TBLPROPERTIES,
10411044
TEMP,
1045+
TEMPLATE,
10421046
TEMPORARY,
10431047
TEMPTABLE,
10441048
TERMINATED,

0 commit comments

Comments
 (0)