Merge branch 'main' into alter-operator

This commit is contained in:
Luca Cappelletti 2025-12-04 11:35:12 +01:00 committed by GitHub
commit 699ce46560
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 213 additions and 10 deletions

View file

@ -18,7 +18,7 @@
[package]
name = "sqlparser"
description = "Extensible SQL Lexer and Parser with support for ANSI SQL:2011"
version = "0.59.0"
version = "0.60.0"
authors = ["Apache DataFusion <dev@datafusion.apache.org>"]
homepage = "https://github.com/apache/datafusion-sqlparser-rs"
documentation = "https://docs.rs/sqlparser/"

98
changelog/0.60.0.md Normal file
View file

@ -0,0 +1,98 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# sqlparser-rs 0.60.0 Changelog
This release consists of 37 commits from 20 contributors. See credits at the end of this changelog for more information.
**Implemented enhancements:**
- feat: Add RESET to the base dialect #2078 [#2079](https://github.com/apache/datafusion-sqlparser-rs/pull/2079) (watford-ep)
- feat: Add support for SET SESSION AUTHORIZATION #2086 [#2087](https://github.com/apache/datafusion-sqlparser-rs/pull/2087) (watford-ep)
**Fixed bugs:**
- fix: parse error on unnamed arg with default syntax [#2091](https://github.com/apache/datafusion-sqlparser-rs/pull/2091) (r1b)
**Other:**
- Add support for INVISIBLE columns in MySQL [#2033](https://github.com/apache/datafusion-sqlparser-rs/pull/2033) (altmannmarcelo)
- Link to actual change logs in CHANGELOG.md [#2040](https://github.com/apache/datafusion-sqlparser-rs/pull/2040) (lovasoa)
- Snowflake: ALTER USER and KeyValueOptions Refactoring [#2035](https://github.com/apache/datafusion-sqlparser-rs/pull/2035) (yoavcloud)
- Correctly tokenize nested comments in Databricks, ClickHouse, and ANSI [#2044](https://github.com/apache/datafusion-sqlparser-rs/pull/2044) (jmhain)
- MySQL: `CREATE INDEX`: allow `USING` clause before `ON` [#2029](https://github.com/apache/datafusion-sqlparser-rs/pull/2029) (MohamedAbdeen21)
- [databricks] update dialect to support grouping by with modifier [#2047](https://github.com/apache/datafusion-sqlparser-rs/pull/2047) (n-young)
- Moved constraint variant outside of `TableConstraint` enum [#2054](https://github.com/apache/datafusion-sqlparser-rs/pull/2054) (LucaCappelletti94)
- Add support for procedure parameter default values [#2041](https://github.com/apache/datafusion-sqlparser-rs/pull/2041) (aharpervc)
- Support updating PRs using github UI [#2052](https://github.com/apache/datafusion-sqlparser-rs/pull/2052) (blaginin)
- Increase version of sqlparser_derive from 0.3.0 to 0.4.0 [#2060](https://github.com/apache/datafusion-sqlparser-rs/pull/2060) (jjbayer)
- Moving several struct variants out of `Statement` enum to allow for trait impls for specific sub-variants [#2057](https://github.com/apache/datafusion-sqlparser-rs/pull/2057) (LucaCappelletti94)
- Added support for SQLite triggers [#2037](https://github.com/apache/datafusion-sqlparser-rs/pull/2037) (LucaCappelletti94)
- Added support for MATCH syntax and unified column option ForeignKey [#2062](https://github.com/apache/datafusion-sqlparser-rs/pull/2062) (LucaCappelletti94)
- chore: add stack overflow warning for Visitor and VisitorMut [#2068](https://github.com/apache/datafusion-sqlparser-rs/pull/2068) (niebayes)
- Reused `CheckConstraint` in `ColumnOption` [#2063](https://github.com/apache/datafusion-sqlparser-rs/pull/2063) (LucaCappelletti94)
- Refactored `ColumnOption::Unique` to reuse `UniqueConstraint` and `PrimaryKeyConstraint` [#2064](https://github.com/apache/datafusion-sqlparser-rs/pull/2064) (LucaCappelletti94)
- Redshift: more copy options [#2072](https://github.com/apache/datafusion-sqlparser-rs/pull/2072) (yoavcloud)
- SQLite: make period optional for CREATE TRIGGER [#2071](https://github.com/apache/datafusion-sqlparser-rs/pull/2071) (takluyver)
- Added TIMESTAMP_NTZ type support with precision to Snowflake dialect [#2080](https://github.com/apache/datafusion-sqlparser-rs/pull/2080) (romanoff)
- Make `BitwiseNot` ("~") available for all dialects, not just PostgreSQL [#2081](https://github.com/apache/datafusion-sqlparser-rs/pull/2081) (alexander-beedie)
- Add snowflake dynamic table parsing [#2083](https://github.com/apache/datafusion-sqlparser-rs/pull/2083) (romanoff)
- Add support for `INSERT INTO VALUE` [#2085](https://github.com/apache/datafusion-sqlparser-rs/pull/2085) (etgarperets)
- Complete PostgreSQL `CREATE TYPE` Support [#2094](https://github.com/apache/datafusion-sqlparser-rs/pull/2094) (LucaCappelletti94)
- Include DML keyword in statement span [#2090](https://github.com/apache/datafusion-sqlparser-rs/pull/2090) (xitep)
- Add PostgreSQL Operator DDL Support [#2096](https://github.com/apache/datafusion-sqlparser-rs/pull/2096) (LucaCappelletti94)
- impl `Spanned` for MERGE statements [#2100](https://github.com/apache/datafusion-sqlparser-rs/pull/2100) (xitep)
- Preserve optional `AS` keyword in aliases [#2103](https://github.com/apache/datafusion-sqlparser-rs/pull/2103) (xitep)
- Added support for `DROP OPERATOR` syntax [#2102](https://github.com/apache/datafusion-sqlparser-rs/pull/2102) (LucaCappelletti94)
- Only set `hive_formats` on `CreateTable` if formats are present [#2105](https://github.com/apache/datafusion-sqlparser-rs/pull/2105) (mvzink)
- Support PostgreSQL C Functions with Multiple AS Parameters [#2095](https://github.com/apache/datafusion-sqlparser-rs/pull/2095) (LucaCappelletti94)
- Added support for `DROP OPERATOR FAMILY` [#2106](https://github.com/apache/datafusion-sqlparser-rs/pull/2106) (LucaCappelletti94)
- Update criterion requirement from 0.7 to 0.8 in /sqlparser_bench [#2111](https://github.com/apache/datafusion-sqlparser-rs/pull/2111) (dependabot[bot])
- Added support for `DROP OPERATOR CLASS` syntax [#2109](https://github.com/apache/datafusion-sqlparser-rs/pull/2109) (LucaCappelletti94)
- Introduce Oracle dialect [#2113](https://github.com/apache/datafusion-sqlparser-rs/pull/2113) (xitep)
## Credits
Thank you to everyone who contributed to this release. Here is a breakdown of commits (PRs merged) per contributor.
```
12 Luca Cappelletti
4 xitep
2 Andriy Romanov
2 Christopher Watford
2 Yoav Cohen
1 Alexander Beedie
1 Andrew Harper
1 Dmitrii Blaginin
1 Joey Hain
1 Joris Bayer
1 Marcelo Altmann
1 Michael Victor Zink
1 Mohamed Abdeen
1 Ophir LOJKINE
1 Thomas Kluyver
1 dependabot[bot]
1 etgarperets
1 nick young
1 niebayes
1 r1b
```
Thank you also to everyone who contributed in other ways such as filing issues, reviewing PRs, and providing feedback on this release.

View file

@ -124,13 +124,15 @@ test_source_distribution() {
cargo build
cargo test --all-features
if ( find -iname 'Cargo.toml' | xargs grep SNAPSHOT ); then
if ( find . -iname 'Cargo.toml' | xargs grep SNAPSHOT ); then
echo "Cargo.toml version should not contain SNAPSHOT for releases"
exit 1
fi
# Can't test using dry-run because sqlparser depends on sqlparser_derive
# see https://github.com/crate-ci/cargo-release/issues/691#issuecomment-2059866021
# Check that publish works
cargo publish --dry-run
# cargo publish --dry-run
}
TEST_SUCCESS=no

View file

@ -58,6 +58,7 @@ $ cargo run --example cli - [--dialectname]
"--clickhouse" => Box::new(ClickHouseDialect {}),
"--duckdb" => Box::new(DuckDbDialect {}),
"--sqlite" => Box::new(SQLiteDialect {}),
"--oracle" => Box::new(OracleDialect {}),
"--generic" | "" => Box::new(GenericDialect {}),
s => panic!("Unexpected parameter: {s}"),
};

View file

@ -2900,7 +2900,9 @@ impl fmt::Display for CreateTable {
if let Some(file_format) = self.file_format {
write!(f, " STORED AS {file_format}")?;
}
write!(f, " LOCATION '{}'", self.location.as_ref().unwrap())?;
if let Some(location) = &self.location {
write!(f, " LOCATION '{location}'")?;
}
}
match &self.table_options {

View file

@ -24,6 +24,7 @@ mod generic;
mod hive;
mod mssql;
mod mysql;
mod oracle;
mod postgresql;
mod redshift;
mod snowflake;
@ -45,6 +46,7 @@ pub use self::generic::GenericDialect;
pub use self::hive::HiveDialect;
pub use self::mssql::MsSqlDialect;
pub use self::mysql::MySqlDialect;
pub use self::oracle::OracleDialect;
pub use self::postgresql::PostgreSqlDialect;
pub use self::redshift::RedshiftSqlDialect;
pub use self::snowflake::SnowflakeDialect;
@ -1260,6 +1262,7 @@ pub fn dialect_from_str(dialect_name: impl AsRef<str>) -> Option<Box<dyn Dialect
"ansi" => Some(Box::new(AnsiDialect {})),
"duckdb" => Some(Box::new(DuckDbDialect {})),
"databricks" => Some(Box::new(DatabricksDialect {})),
"oracle" => Some(Box::new(OracleDialect {})),
_ => None,
}
}

81
src/dialect/oracle.rs Normal file
View file

@ -0,0 +1,81 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
use super::Dialect;
/// A [`Dialect`] for [Oracle Databases](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/index.html)
#[derive(Debug)]
pub struct OracleDialect;
impl Dialect for OracleDialect {
// ~ appears not to be called anywhere
fn identifier_quote_style(&self, _identifier: &str) -> Option<char> {
Some('"')
}
fn is_delimited_identifier_start(&self, ch: char) -> bool {
ch == '"'
}
fn is_identifier_start(&self, ch: char) -> bool {
ch.is_alphabetic()
}
fn is_identifier_part(&self, ch: char) -> bool {
ch.is_alphanumeric() || ch == '_' || ch == '$' || ch == '#' || ch == '@'
}
fn supports_outer_join_operator(&self) -> bool {
true
}
fn supports_connect_by(&self) -> bool {
true
}
fn supports_execute_immediate(&self) -> bool {
true
}
fn supports_match_recognize(&self) -> bool {
true
}
fn supports_window_function_null_treatment_arg(&self) -> bool {
true
}
fn supports_boolean_literals(&self) -> bool {
false
}
fn supports_comment_on(&self) -> bool {
true
}
fn supports_create_table_select(&self) -> bool {
true
}
fn supports_set_stmt_without_operator(&self) -> bool {
true
}
fn supports_group_by_expr(&self) -> bool {
true
}
}

View file

@ -229,6 +229,7 @@ define_keywords!(
COMMITTED,
COMMUTATOR,
COMPATIBLE,
COMPRESS,
COMPRESSION,
COMPUPDATE,
COMPUTE,
@ -473,6 +474,7 @@ define_keywords!(
IAM_ROLE,
ICEBERG,
ID,
IDENTIFIED,
IDENTITY,
IDENTITY_INSERT,
IF,
@ -576,6 +578,7 @@ define_keywords!(
LOG,
LOGIN,
LOGS,
LONG,
LONGBLOB,
LONGTEXT,
LOWCARDINALITY,
@ -661,6 +664,7 @@ define_keywords!(
NFKD,
NO,
NOBYPASSRLS,
NOCOMPRESS,
NOCREATEDB,
NOCREATEROLE,
NOINHERIT,
@ -684,6 +688,7 @@ define_keywords!(
NULLABLE,
NULLIF,
NULLS,
NUMBER,
NUMERIC,
NVARCHAR,
OBJECT,
@ -750,6 +755,7 @@ define_keywords!(
PAST,
PATH,
PATTERN,
PCTFREE,
PER,
PERCENT,
PERCENTILE_CONT,
@ -922,6 +928,7 @@ define_keywords!(
SIGNED,
SIMILAR,
SIMPLE,
SIZE,
SKIP,
SLOW,
SMALLINT,
@ -983,6 +990,7 @@ define_keywords!(
SWAP,
SYMMETRIC,
SYNC,
SYNONYM,
SYSTEM,
SYSTEM_TIME,
SYSTEM_USER,
@ -1094,6 +1102,7 @@ define_keywords!(
VARBINARY,
VARBIT,
VARCHAR,
VARCHAR2,
VARIABLE,
VARIABLES,
VARYING,

View file

@ -12400,7 +12400,7 @@ impl<'a> Parser<'a> {
let (tables, with_from_keyword) = if !self.parse_keyword(Keyword::FROM) {
// `FROM` keyword is optional in BigQuery SQL.
// https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement
if dialect_of!(self is BigQueryDialect | GenericDialect) {
if dialect_of!(self is BigQueryDialect | OracleDialect | GenericDialect) {
(vec![], false)
} else {
let tables = self.parse_comma_separated(|p| p.parse_object_name(false))?;

View file

@ -291,6 +291,7 @@ pub fn all_dialects() -> TestedDialects {
Box::new(DuckDbDialect {}),
Box::new(DatabricksDialect {}),
Box::new(ClickHouseDialect {}),
Box::new(OracleDialect {}),
])
}

View file

@ -34,8 +34,8 @@ use sqlparser::ast::TableFactor::{Pivot, Unpivot};
use sqlparser::ast::*;
use sqlparser::dialect::{
AnsiDialect, BigQueryDialect, ClickHouseDialect, DatabricksDialect, Dialect, DuckDbDialect,
GenericDialect, HiveDialect, MsSqlDialect, MySqlDialect, PostgreSqlDialect, RedshiftSqlDialect,
SQLiteDialect, SnowflakeDialect,
GenericDialect, HiveDialect, MsSqlDialect, MySqlDialect, OracleDialect, PostgreSqlDialect,
RedshiftSqlDialect, SQLiteDialect, SnowflakeDialect,
};
use sqlparser::keywords::{Keyword, ALL_KEYWORDS};
use sqlparser::parser::{Parser, ParserError, ParserOptions};
@ -712,7 +712,9 @@ fn parse_delete_statement() {
fn parse_delete_without_from_error() {
let sql = "DELETE \"table\" WHERE 1";
let dialects = all_dialects_except(|d| d.is::<BigQueryDialect>() || d.is::<GenericDialect>());
let dialects = all_dialects_except(|d| {
d.is::<BigQueryDialect>() || d.is::<OracleDialect>() || d.is::<GenericDialect>()
});
let res = dialects.parse_sql_statements(sql);
assert_eq!(
ParserError::ParserError("Expected: FROM, found: WHERE".to_string()),
@ -723,7 +725,9 @@ fn parse_delete_without_from_error() {
#[test]
fn parse_delete_statement_for_multi_tables() {
let sql = "DELETE schema1.table1, schema2.table2 FROM schema1.table1 JOIN schema2.table2 ON schema2.table2.col1 = schema1.table1.col1 WHERE schema2.table2.col2 = 1";
let dialects = all_dialects_except(|d| d.is::<BigQueryDialect>() || d.is::<GenericDialect>());
let dialects = all_dialects_except(|d| {
d.is::<BigQueryDialect>() || d.is::<OracleDialect>() || d.is::<GenericDialect>()
});
match dialects.verified_stmt(sql) {
Statement::Delete(Delete {
tables,
@ -12943,7 +12947,7 @@ fn test_match_recognize_patterns() {
fn check(pattern: &str, expect: MatchRecognizePattern) {
let select =
all_dialects_where(|d| d.supports_match_recognize()).verified_only_select(&format!(
"SELECT * FROM my_table MATCH_RECOGNIZE(PATTERN ({pattern}) DEFINE DUMMY AS true)" // "select * from my_table match_recognize ("
"SELECT * FROM my_table MATCH_RECOGNIZE(PATTERN ({pattern}) DEFINE DUMMY AS 1 = 1)" // "select * from my_table match_recognize ("
));
let TableFactor::MatchRecognize {
pattern: actual, ..

View file

@ -34,10 +34,12 @@ fn parse_table_create() {
let sql = r#"CREATE TABLE IF NOT EXISTS db.table (a BIGINT, b STRING, c TIMESTAMP) PARTITIONED BY (d STRING, e TIMESTAMP) STORED AS ORC LOCATION 's3://...' TBLPROPERTIES ("prop" = "2", "asdf" = '1234', 'asdf' = "1234", "asdf" = 2)"#;
let iof = r#"CREATE TABLE IF NOT EXISTS db.table (a BIGINT, b STRING, c TIMESTAMP) PARTITIONED BY (d STRING, e TIMESTAMP) STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat' LOCATION 's3://...'"#;
let serdeproperties = r#"CREATE EXTERNAL TABLE IF NOT EXISTS db.table (a STRING, b STRING, c STRING) PARTITIONED BY (d STRING, e STRING) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde.config' WITH SERDEPROPERTIES ('prop_a' = 'a', 'prop_b' = 'b') STORED AS TEXTFILE LOCATION 's3://...' TBLPROPERTIES ('prop_c' = 'c')"#;
let externaltable = r#"CREATE EXTERNAL TABLE t (c INT)"#;
hive().verified_stmt(sql);
hive().verified_stmt(iof);
hive().verified_stmt(serdeproperties);
hive().verified_stmt(externaltable);
}
#[test]