mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-23 23:44:07 +00:00
Support use of BY NAME
quantifier across all set ops (#1309)
Co-authored-by: Alexander Beedie <alexander.beedie@adia.ae> Co-authored-by: Joey Hain <joey@sigmacomputing.com>
This commit is contained in:
parent
deac269710
commit
0330f9def5
6 changed files with 18 additions and 21 deletions
|
@ -114,13 +114,12 @@ $ cargo run --features json_example --example cli FILENAME.sql [--dialectname]
|
||||||
|
|
||||||
## Users
|
## Users
|
||||||
|
|
||||||
This parser is currently being used by the [DataFusion] query engine,
|
This parser is currently being used by the [DataFusion] query engine, [LocustDB],
|
||||||
[LocustDB], [Ballista], [GlueSQL], [Opteryx], [PRQL], [Qrlew], [JumpWire], and [ParadeDB].
|
[Ballista], [GlueSQL], [Opteryx], [Polars], [PRQL], [Qrlew], [JumpWire], and [ParadeDB].
|
||||||
|
|
||||||
If your project is using sqlparser-rs feel free to make a PR to add it
|
If your project is using sqlparser-rs feel free to make a PR to add it
|
||||||
to this list.
|
to this list.
|
||||||
|
|
||||||
|
|
||||||
## Design
|
## Design
|
||||||
|
|
||||||
The core expression parser uses the [Pratt Parser] design, which is a top-down
|
The core expression parser uses the [Pratt Parser] design, which is a top-down
|
||||||
|
@ -210,6 +209,7 @@ licensed as above, without any additional terms or conditions.
|
||||||
[Ballista]: https://github.com/apache/arrow-ballista
|
[Ballista]: https://github.com/apache/arrow-ballista
|
||||||
[GlueSQL]: https://github.com/gluesql/gluesql
|
[GlueSQL]: https://github.com/gluesql/gluesql
|
||||||
[Opteryx]: https://github.com/mabel-dev/opteryx
|
[Opteryx]: https://github.com/mabel-dev/opteryx
|
||||||
|
[Polars]: https://pola.rs/
|
||||||
[PRQL]: https://github.com/PRQL/prql
|
[PRQL]: https://github.com/PRQL/prql
|
||||||
[Qrlew]: https://github.com/Qrlew/qrlew
|
[Qrlew]: https://github.com/Qrlew/qrlew
|
||||||
[JumpWire]: https://github.com/extragoodlabs/jumpwire
|
[JumpWire]: https://github.com/extragoodlabs/jumpwire
|
||||||
|
|
|
@ -168,7 +168,7 @@ pub enum DataType {
|
||||||
UnsignedInt(Option<u64>),
|
UnsignedInt(Option<u64>),
|
||||||
/// Unsigned int4 with optional display width e.g. INT4 UNSIGNED or INT4(11) UNSIGNED
|
/// Unsigned int4 with optional display width e.g. INT4 UNSIGNED or INT4(11) UNSIGNED
|
||||||
UnsignedInt4(Option<u64>),
|
UnsignedInt4(Option<u64>),
|
||||||
/// Unsigned integer with optional display width e.g. INTGER UNSIGNED or INTEGER(11) UNSIGNED
|
/// Unsigned integer with optional display width e.g. INTEGER UNSIGNED or INTEGER(11) UNSIGNED
|
||||||
UnsignedInteger(Option<u64>),
|
UnsignedInteger(Option<u64>),
|
||||||
/// Unsigned integer type in [clickhouse]
|
/// Unsigned integer type in [clickhouse]
|
||||||
/// Note: UInt8 mean 8 bits in [clickhouse]
|
/// Note: UInt8 mean 8 bits in [clickhouse]
|
||||||
|
@ -699,7 +699,7 @@ pub enum CharacterLength {
|
||||||
/// Optional unit. If not informed, the ANSI handles it as CHARACTERS implicitly
|
/// Optional unit. If not informed, the ANSI handles it as CHARACTERS implicitly
|
||||||
unit: Option<CharLengthUnits>,
|
unit: Option<CharLengthUnits>,
|
||||||
},
|
},
|
||||||
/// VARCHAR(MAX) or NVARCHAR(MAX), used in T-SQL (Miscrosoft SQL Server)
|
/// VARCHAR(MAX) or NVARCHAR(MAX), used in T-SQL (Microsoft SQL Server)
|
||||||
Max,
|
Max,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2265,7 +2265,7 @@ pub enum Statement {
|
||||||
/// SET [ SESSION | LOCAL ] ROLE role_name
|
/// SET [ SESSION | LOCAL ] ROLE role_name
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Sets sesssion state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
|
/// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
|
||||||
///
|
///
|
||||||
/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
|
/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
|
||||||
/// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
|
/// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
|
||||||
|
@ -2283,7 +2283,7 @@ pub enum Statement {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Note: this is not a standard SQL statement, but it is supported by at
|
/// Note: this is not a standard SQL statement, but it is supported by at
|
||||||
/// least MySQL and PostgreSQL. Not all MySQL-specific syntatic forms are
|
/// least MySQL and PostgreSQL. Not all MySQL-specific syntactic forms are
|
||||||
/// supported yet.
|
/// supported yet.
|
||||||
SetVariable {
|
SetVariable {
|
||||||
local: bool,
|
local: bool,
|
||||||
|
@ -4750,7 +4750,7 @@ impl fmt::Display for FunctionArguments {
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
pub struct FunctionArgumentList {
|
pub struct FunctionArgumentList {
|
||||||
/// `[ ALL | DISTINCT ]
|
/// `[ ALL | DISTINCT ]`
|
||||||
pub duplicate_treatment: Option<DuplicateTreatment>,
|
pub duplicate_treatment: Option<DuplicateTreatment>,
|
||||||
/// The function arguments.
|
/// The function arguments.
|
||||||
pub args: Vec<FunctionArg>,
|
pub args: Vec<FunctionArg>,
|
||||||
|
|
|
@ -8138,7 +8138,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
pub fn parse_set_quantifier(&mut self, op: &Option<SetOperator>) -> SetQuantifier {
|
pub fn parse_set_quantifier(&mut self, op: &Option<SetOperator>) -> SetQuantifier {
|
||||||
match op {
|
match op {
|
||||||
Some(SetOperator::Union) => {
|
Some(SetOperator::Except | SetOperator::Intersect | SetOperator::Union) => {
|
||||||
if self.parse_keywords(&[Keyword::DISTINCT, Keyword::BY, Keyword::NAME]) {
|
if self.parse_keywords(&[Keyword::DISTINCT, Keyword::BY, Keyword::NAME]) {
|
||||||
SetQuantifier::DistinctByName
|
SetQuantifier::DistinctByName
|
||||||
} else if self.parse_keywords(&[Keyword::BY, Keyword::NAME]) {
|
} else if self.parse_keywords(&[Keyword::BY, Keyword::NAME]) {
|
||||||
|
@ -8155,15 +8155,6 @@ impl<'a> Parser<'a> {
|
||||||
SetQuantifier::None
|
SetQuantifier::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(SetOperator::Except) | Some(SetOperator::Intersect) => {
|
|
||||||
if self.parse_keyword(Keyword::ALL) {
|
|
||||||
SetQuantifier::All
|
|
||||||
} else if self.parse_keyword(Keyword::DISTINCT) {
|
|
||||||
SetQuantifier::Distinct
|
|
||||||
} else {
|
|
||||||
SetQuantifier::None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => SetQuantifier::None,
|
_ => SetQuantifier::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8547,10 +8538,10 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
} else if variable.to_string() == "TRANSACTION" && modifier.is_none() {
|
} else if variable.to_string() == "TRANSACTION" && modifier.is_none() {
|
||||||
if self.parse_keyword(Keyword::SNAPSHOT) {
|
if self.parse_keyword(Keyword::SNAPSHOT) {
|
||||||
let snaphot_id = self.parse_value()?;
|
let snapshot_id = self.parse_value()?;
|
||||||
return Ok(Statement::SetTransaction {
|
return Ok(Statement::SetTransaction {
|
||||||
modes: vec![],
|
modes: vec![],
|
||||||
snapshot: Some(snaphot_id),
|
snapshot: Some(snapshot_id),
|
||||||
session: false,
|
session: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -654,7 +654,7 @@ impl<'a> Tokenizer<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tokenize the identifer or keywords in `ch`
|
// Tokenize the identifier or keywords in `ch`
|
||||||
fn tokenize_identifier_or_keyword(
|
fn tokenize_identifier_or_keyword(
|
||||||
&self,
|
&self,
|
||||||
ch: impl IntoIterator<Item = char>,
|
ch: impl IntoIterator<Item = char>,
|
||||||
|
|
|
@ -6010,6 +6010,12 @@ fn parse_union_except_intersect() {
|
||||||
verified_stmt("SELECT foo FROM tab UNION SELECT bar FROM TAB");
|
verified_stmt("SELECT foo FROM tab UNION SELECT bar FROM TAB");
|
||||||
verified_stmt("(SELECT * FROM new EXCEPT SELECT * FROM old) UNION ALL (SELECT * FROM old EXCEPT SELECT * FROM new) ORDER BY 1");
|
verified_stmt("(SELECT * FROM new EXCEPT SELECT * FROM old) UNION ALL (SELECT * FROM old EXCEPT SELECT * FROM new) ORDER BY 1");
|
||||||
verified_stmt("(SELECT * FROM new EXCEPT DISTINCT SELECT * FROM old) UNION DISTINCT (SELECT * FROM old EXCEPT DISTINCT SELECT * FROM new) ORDER BY 1");
|
verified_stmt("(SELECT * FROM new EXCEPT DISTINCT SELECT * FROM old) UNION DISTINCT (SELECT * FROM old EXCEPT DISTINCT SELECT * FROM new) ORDER BY 1");
|
||||||
|
verified_stmt("SELECT 1 AS x, 2 AS y EXCEPT BY NAME SELECT 9 AS y, 8 AS x");
|
||||||
|
verified_stmt("SELECT 1 AS x, 2 AS y EXCEPT ALL BY NAME SELECT 9 AS y, 8 AS x");
|
||||||
|
verified_stmt("SELECT 1 AS x, 2 AS y EXCEPT DISTINCT BY NAME SELECT 9 AS y, 8 AS x");
|
||||||
|
verified_stmt("SELECT 1 AS x, 2 AS y INTERSECT BY NAME SELECT 9 AS y, 8 AS x");
|
||||||
|
verified_stmt("SELECT 1 AS x, 2 AS y INTERSECT ALL BY NAME SELECT 9 AS y, 8 AS x");
|
||||||
|
verified_stmt("SELECT 1 AS x, 2 AS y INTERSECT DISTINCT BY NAME SELECT 9 AS y, 8 AS x");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue