Skip to content

Commit bf242f5

Browse files
Merge branch 'main' into xmlparse
2 parents a019bf9 + e79119c commit bf242f5

20 files changed

Lines changed: 1337 additions & 429 deletions

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ edition = "2021"
3636
name = "sqlparser"
3737
path = "src/lib.rs"
3838

39+
[lints.rust]
40+
unsafe_code = "forbid"
41+
3942
[features]
4043
default = ["std", "recursive-protection"]
4144
std = []

derive/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ edition = "2021"
3535
[lib]
3636
proc-macro = true
3737

38+
[lints.rust]
39+
unsafe_code = "forbid"
40+
3841
[dependencies]
3942
syn = { version = "2.0", default-features = false, features = ["full", "printing", "parsing", "derive", "proc-macro", "clone-impls"] }
4043
proc-macro2 = "1.0"

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: 43 additions & 18 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,
@@ -138,8 +140,9 @@ mod dml;
138140
pub mod helpers;
139141
pub mod table_constraints;
140142
pub use table_constraints::{
141-
CheckConstraint, ConstraintUsingIndex, ForeignKeyConstraint, FullTextOrSpatialConstraint,
142-
IndexConstraint, PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
143+
CheckConstraint, ConstraintUsingIndex, ExcludeConstraint, ExcludeConstraintElement,
144+
ExcludeConstraintOperator, ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint,
145+
PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
143146
};
144147
mod operator;
145148
mod query;
@@ -3794,6 +3797,10 @@ pub enum Statement {
37943797
/// ```
37953798
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
37963799
CreateOperatorClass(CreateOperatorClass),
3800+
/// A `CREATE TEXT SEARCH` statement.
3801+
///
3802+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-intro.html)
3803+
CreateTextSearch(CreateTextSearch),
37973804
/// ```sql
37983805
/// ALTER TABLE
37993806
/// ```
@@ -3858,6 +3865,10 @@ pub enum Statement {
38583865
/// ```
38593866
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
38603867
AlterOperatorClass(AlterOperatorClass),
3868+
/// An `ALTER TEXT SEARCH` statement.
3869+
///
3870+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-configuration.html)
3871+
AlterTextSearch(AlterTextSearch),
38613872
/// ```sql
38623873
/// ALTER ROLE
38633874
/// ```
@@ -5618,6 +5629,7 @@ impl fmt::Display for Statement {
56185629
create_operator_family.fmt(f)
56195630
}
56205631
Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5632+
Statement::CreateTextSearch(create_text_search) => create_text_search.fmt(f),
56215633
Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
56225634
Statement::AlterIndex { name, operation } => {
56235635
write!(f, "ALTER INDEX {name} {operation}")
@@ -5649,6 +5661,7 @@ impl fmt::Display for Statement {
56495661
Statement::AlterOperatorClass(alter_operator_class) => {
56505662
write!(f, "{alter_operator_class}")
56515663
}
5664+
Statement::AlterTextSearch(alter_text_search) => write!(f, "{alter_text_search}"),
56525665
Statement::AlterRole { name, operation } => {
56535666
write!(f, "ALTER ROLE {name} {operation}")
56545667
}
@@ -12309,6 +12322,12 @@ impl From<CreateOperatorClass> for Statement {
1230912322
}
1231012323
}
1231112324

12325+
impl From<CreateTextSearch> for Statement {
12326+
fn from(c: CreateTextSearch) -> Self {
12327+
Self::CreateTextSearch(c)
12328+
}
12329+
}
12330+
1231212331
impl From<AlterSchema> for Statement {
1231312332
fn from(a: AlterSchema) -> Self {
1231412333
Self::AlterSchema(a)
@@ -12351,6 +12370,12 @@ impl From<AlterOperatorClass> for Statement {
1235112370
}
1235212371
}
1235312372

12373+
impl From<AlterTextSearch> for Statement {
12374+
fn from(a: AlterTextSearch) -> Self {
12375+
Self::AlterTextSearch(a)
12376+
}
12377+
}
12378+
1235412379
impl From<Merge> for Statement {
1235512380
fn from(m: Merge) -> Self {
1235612381
Self::Merge(m)

src/ast/operator.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ pub enum BinaryOperator {
144144
Match,
145145
/// REGEXP operator, e.g. `a REGEXP b` (SQLite-specific)
146146
Regexp,
147+
/// GLOB operator, e.g. `a GLOB b` (SQLite-specific)
148+
/// See <https://www.sqlite.org/lang_expr.html#the_like_glob_regexp_match_and_extract_operators>
149+
Glob,
147150
/// Support for custom operators (such as Postgres custom operators)
148151
Custom(String),
149152
/// Bitwise XOR, e.g. `a # b` (PostgreSQL-specific)
@@ -357,6 +360,7 @@ impl fmt::Display for BinaryOperator {
357360
BinaryOperator::MyIntegerDivide => f.write_str("DIV"),
358361
BinaryOperator::Match => f.write_str("MATCH"),
359362
BinaryOperator::Regexp => f.write_str("REGEXP"),
363+
BinaryOperator::Glob => f.write_str("GLOB"),
360364
BinaryOperator::Custom(s) => f.write_str(s),
361365
BinaryOperator::PGBitwiseXor => f.write_str("#"),
362366
BinaryOperator::PGBitwiseShiftLeft => f.write_str("<<"),

0 commit comments

Comments
 (0)