Skip to content

Commit

Permalink
Support use of BY NAME quantifier across all set ops (#1309)
Browse files Browse the repository at this point in the history
Co-authored-by: Alexander Beedie <alexander.beedie@adia.ae>
Co-authored-by: Joey Hain <joey@sigmacomputing.com>
  • Loading branch information
3 people authored Jun 17, 2024
1 parent deac269 commit 0330f9d
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 21 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,12 @@ $ cargo run --features json_example --example cli FILENAME.sql [--dialectname]

## Users

This parser is currently being used by the [DataFusion] query engine,
[LocustDB], [Ballista], [GlueSQL], [Opteryx], [PRQL], [Qrlew], [JumpWire], and [ParadeDB].
This parser is currently being used by the [DataFusion] query engine, [LocustDB],
[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
to this list.


## Design

The core expression parser uses the [Pratt Parser] design, which is a top-down
Expand Down Expand Up @@ -210,6 +209,7 @@ licensed as above, without any additional terms or conditions.
[Ballista]: https://github.com/apache/arrow-ballista
[GlueSQL]: https://github.com/gluesql/gluesql
[Opteryx]: https://github.com/mabel-dev/opteryx
[Polars]: https://pola.rs/
[PRQL]: https://github.com/PRQL/prql
[Qrlew]: https://github.com/Qrlew/qrlew
[JumpWire]: https://github.com/extragoodlabs/jumpwire
Expand Down
4 changes: 2 additions & 2 deletions src/ast/data_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ pub enum DataType {
UnsignedInt(Option<u64>),
/// Unsigned int4 with optional display width e.g. INT4 UNSIGNED or INT4(11) UNSIGNED
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>),
/// Unsigned integer type in [clickhouse]
/// Note: UInt8 mean 8 bits in [clickhouse]
Expand Down Expand Up @@ -699,7 +699,7 @@ pub enum CharacterLength {
/// Optional unit. If not informed, the ANSI handles it as CHARACTERS implicitly
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,
}

Expand Down
6 changes: 3 additions & 3 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2265,7 +2265,7 @@ pub enum Statement {
/// 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
/// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
Expand All @@ -2283,7 +2283,7 @@ pub enum Statement {
/// ```
///
/// 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.
SetVariable {
local: bool,
Expand Down Expand Up @@ -4750,7 +4750,7 @@ impl fmt::Display for FunctionArguments {
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct FunctionArgumentList {
/// `[ ALL | DISTINCT ]
/// `[ ALL | DISTINCT ]`
pub duplicate_treatment: Option<DuplicateTreatment>,
/// The function arguments.
pub args: Vec<FunctionArg>,
Expand Down
15 changes: 3 additions & 12 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8138,7 +8138,7 @@ impl<'a> Parser<'a> {

pub fn parse_set_quantifier(&mut self, op: &Option<SetOperator>) -> SetQuantifier {
match op {
Some(SetOperator::Union) => {
Some(SetOperator::Except | SetOperator::Intersect | SetOperator::Union) => {
if self.parse_keywords(&[Keyword::DISTINCT, Keyword::BY, Keyword::NAME]) {
SetQuantifier::DistinctByName
} else if self.parse_keywords(&[Keyword::BY, Keyword::NAME]) {
Expand All @@ -8155,15 +8155,6 @@ impl<'a> Parser<'a> {
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,
}
}
Expand Down Expand Up @@ -8547,10 +8538,10 @@ impl<'a> Parser<'a> {
})
} else if variable.to_string() == "TRANSACTION" && modifier.is_none() {
if self.parse_keyword(Keyword::SNAPSHOT) {
let snaphot_id = self.parse_value()?;
let snapshot_id = self.parse_value()?;
return Ok(Statement::SetTransaction {
modes: vec![],
snapshot: Some(snaphot_id),
snapshot: Some(snapshot_id),
session: false,
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/tokenizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ impl<'a> Tokenizer<'a> {
Ok(())
}

// Tokenize the identifer or keywords in `ch`
// Tokenize the identifier or keywords in `ch`
fn tokenize_identifier_or_keyword(
&self,
ch: impl IntoIterator<Item = char>,
Expand Down
6 changes: 6 additions & 0 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6010,6 +6010,12 @@ fn parse_union_except_intersect() {
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 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]
Expand Down

0 comments on commit 0330f9d

Please sign in to comment.