Skip to content

Commit e215e7f

Browse files
committed
intersect requires distinct
1 parent affe850 commit e215e7f

2 files changed

Lines changed: 35 additions & 7 deletions

File tree

src/parser/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11171,8 +11171,16 @@ impl<'a> Parser<'a> {
1117111171
pipe_operators.push(PipeOperator::Union { set_quantifier, queries });
1117211172
}
1117311173
Keyword::INTERSECT => {
11174-
// Reuse existing set quantifier parser for consistent modifier support
11175-
let set_quantifier = self.parse_set_quantifier(&Some(SetOperator::Intersect));
11174+
// BigQuery INTERSECT pipe operator requires DISTINCT modifier
11175+
let set_quantifier = if self.parse_keywords(&[Keyword::DISTINCT, Keyword::BY, Keyword::NAME]) {
11176+
SetQuantifier::DistinctByName
11177+
} else if self.parse_keyword(Keyword::DISTINCT) {
11178+
SetQuantifier::Distinct
11179+
} else {
11180+
return Err(ParserError::ParserError(
11181+
"INTERSECT pipe operator requires DISTINCT modifier".to_string()
11182+
));
11183+
};
1117611184
// BigQuery INTERSECT pipe operator requires parentheses around queries
1117711185
// Parse comma-separated list of parenthesized queries
1117811186
let queries = self.parse_comma_separated(|parser| {

tests/sqlparser_common.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15219,20 +15219,16 @@ fn parse_pipeline_operator() {
1521915219
// union pipe operator with BY NAME and multiple queries
1522015220
dialects.verified_stmt("SELECT * FROM users |> UNION BY NAME (SELECT * FROM admins), (SELECT * FROM guests)");
1522115221

15222-
// intersect pipe operator (BigQuery does not support ALL modifier for INTERSECT)
15223-
dialects.verified_stmt("SELECT * FROM users |> INTERSECT (SELECT * FROM admins)");
15222+
// intersect pipe operator (BigQuery requires DISTINCT modifier for INTERSECT)
1522415223
dialects.verified_stmt("SELECT * FROM users |> INTERSECT DISTINCT (SELECT * FROM admins)");
1522515224

1522615225
// intersect pipe operator with BY NAME modifier
15227-
dialects.verified_stmt("SELECT * FROM users |> INTERSECT BY NAME (SELECT * FROM admins)");
1522815226
dialects.verified_stmt("SELECT * FROM users |> INTERSECT DISTINCT BY NAME (SELECT * FROM admins)");
1522915227

1523015228
// intersect pipe operator with multiple queries
15231-
dialects.verified_stmt("SELECT * FROM users |> INTERSECT (SELECT * FROM admins), (SELECT * FROM guests)");
1523215229
dialects.verified_stmt("SELECT * FROM users |> INTERSECT DISTINCT (SELECT * FROM admins), (SELECT * FROM guests)");
1523315230

1523415231
// intersect pipe operator with BY NAME and multiple queries
15235-
dialects.verified_stmt("SELECT * FROM users |> INTERSECT BY NAME (SELECT * FROM admins), (SELECT * FROM guests)");
1523615232
dialects.verified_stmt("SELECT * FROM users |> INTERSECT DISTINCT BY NAME (SELECT * FROM admins), (SELECT * FROM guests)");
1523715233

1523815234
// except pipe operator (BigQuery requires DISTINCT modifier for EXCEPT)
@@ -15280,6 +15276,30 @@ fn parse_pipeline_operator_negative_tests() {
1528015276
ParserError::ParserError("EXCEPT pipe operator requires DISTINCT modifier".to_string()),
1528115277
dialects.parse_sql_statements("SELECT * FROM users |> EXCEPT ALL BY NAME (SELECT * FROM admins)").unwrap_err()
1528215278
);
15279+
15280+
// Test that plain INTERSECT without DISTINCT fails
15281+
assert_eq!(
15282+
ParserError::ParserError("INTERSECT pipe operator requires DISTINCT modifier".to_string()),
15283+
dialects.parse_sql_statements("SELECT * FROM users |> INTERSECT (SELECT * FROM admins)").unwrap_err()
15284+
);
15285+
15286+
// Test that INTERSECT ALL fails
15287+
assert_eq!(
15288+
ParserError::ParserError("INTERSECT pipe operator requires DISTINCT modifier".to_string()),
15289+
dialects.parse_sql_statements("SELECT * FROM users |> INTERSECT ALL (SELECT * FROM admins)").unwrap_err()
15290+
);
15291+
15292+
// Test that INTERSECT BY NAME without DISTINCT fails
15293+
assert_eq!(
15294+
ParserError::ParserError("INTERSECT pipe operator requires DISTINCT modifier".to_string()),
15295+
dialects.parse_sql_statements("SELECT * FROM users |> INTERSECT BY NAME (SELECT * FROM admins)").unwrap_err()
15296+
);
15297+
15298+
// Test that INTERSECT ALL BY NAME fails
15299+
assert_eq!(
15300+
ParserError::ParserError("INTERSECT pipe operator requires DISTINCT modifier".to_string()),
15301+
dialects.parse_sql_statements("SELECT * FROM users |> INTERSECT ALL BY NAME (SELECT * FROM admins)").unwrap_err()
15302+
);
1528315303
}
1528415304

1528515305
#[test]

0 commit comments

Comments
 (0)