@@ -72,9 +72,7 @@ fn parse_numeric_literal_underscore() {
7272
7373 assert_eq!(
7474 select.projection,
75- vec![UnnamedExpr(Expr::Value(
76- (number("10_000")).with_empty_span()
77- ))]
75+ vec![UnnamedExpr(Expr::Value(number("10_000").with_empty_span()))]
7876 );
7977}
8078
@@ -16200,45 +16198,44 @@ fn parse_set_names() {
1620016198 dialects.verified_stmt("SET NAMES UTF8 COLLATE bogus");
1620116199}
1620216200
16203- #[test]
16204- fn parse_pipeline_operator() {
16205- // Macro to test pipe operator parsing with explicit input and canonical output.
16206- // test_pipe!(dialect, input = "...", canonical = "...")
16207- macro_rules! test_pipe {
16208- ($ctx:expr, input = $input:expr, canonical = $canonical:expr $(,)?) => {{
16209- let (dialects, from_first) = $ctx;
16210- let prefix = if from_first {
16211- "FROM tbl"
16212- } else {
16213- "SELECT * FROM tbl"
16214- };
16215- dialects.verified_query_with_canonical(
16216- &format!("{prefix} |> {}", $input),
16217- &format!("{prefix} |> {}", $canonical),
16218- );
16219- }};
16220- }
16221-
16222- // Test pipe operators with two dialect configurations:
16223- // 1. Dialects supporting FROM-first syntax (e.g., "FROM users |> ...")
16224- // 2. Dialects requiring SELECT-first syntax (e.g., "SELECT * FROM users |> ...")
16225- let from_first_dialects =
16201+ /// Returns dialect configurations for pipe operator tests:
16202+ /// 1. Dialects supporting FROM-first syntax (e.g., "FROM users |> ...")
16203+ /// 2. Dialects requiring SELECT-first syntax (e.g., "SELECT * FROM users |> ...")
16204+ fn pipe_dialects() -> [(TestedDialects, bool); 2] {
16205+ let from_first =
1622616206 all_dialects_where(|d| d.supports_pipe_operator() && d.supports_from_first_select());
16227- let select_first_dialects =
16207+ let select_first =
1622816208 all_dialects_where(|d| d.supports_pipe_operator() && !d.supports_from_first_select());
16209+ [(from_first, true), (select_first, false)]
16210+ }
1622916211
16230- for dialect in [
16231- (&from_first_dialects, true),
16232- (&select_first_dialects, false),
16233- ] {
16234- // ------------------------------------
16235- // 'AS' pipe operator
16236- // ------------------------------------
16212+ /// Macro to test pipe operator parsing with explicit input and canonical output.
16213+ /// Usage: `test_pipe!(ctx, input = "...", canonical = "...")`
16214+ macro_rules! test_pipe {
16215+ ($ctx:expr, input = $input:expr, canonical = $canonical:expr $(,)?) => {{
16216+ let (ref dialects, from_first) = $ctx;
16217+ let prefix = if from_first {
16218+ "FROM tbl"
16219+ } else {
16220+ "SELECT * FROM tbl"
16221+ };
16222+ dialects.verified_query_with_canonical(
16223+ &format!("{prefix} |> {}", $input),
16224+ &format!("{prefix} |> {}", $canonical),
16225+ );
16226+ }};
16227+ }
16228+
16229+ #[test]
16230+ fn parse_pipe_operator_as() {
16231+ for dialect in pipe_dialects() {
1623716232 test_pipe!(dialect, input = "AS new_users", canonical = "AS new_users");
16233+ }
16234+ }
1623816235
16239- // ------------------------------------
16240- // 'SELECT' pipe operator
16241- // ------------------------------------
16236+ #[test]
16237+ fn parse_pipe_operator_select() {
16238+ for dialect in pipe_dialects() {
1624216239 test_pipe!(dialect, input = "SELECT id", canonical = "SELECT id");
1624316240 test_pipe!(
1624416241 dialect,
@@ -16255,10 +16252,12 @@ fn parse_pipeline_operator() {
1625516252 input = "SELECT id AS user_id",
1625616253 canonical = "SELECT id AS user_id"
1625716254 );
16255+ }
16256+ }
1625816257
16259- // ------------------------------------
16260- // 'EXTEND' pipe operator
16261- // ------------------------------------
16258+ #[test]
16259+ fn parse_pipe_operator_extend() {
16260+ for dialect in pipe_dialects() {
1626216261 test_pipe!(
1626316262 dialect,
1626416263 input = "EXTEND id + 1 AS new_id",
@@ -16274,10 +16273,12 @@ fn parse_pipeline_operator() {
1627416273 input = "EXTEND id user_id",
1627516274 canonical = "EXTEND id AS user_id"
1627616275 );
16276+ }
16277+ }
1627716278
16278- // ------------------------------------
16279- // 'SET' pipe operator
16280- // ------------------------------------
16279+ #[test]
16280+ fn parse_pipe_operator_set() {
16281+ for dialect in pipe_dialects() {
1628116282 test_pipe!(
1628216283 dialect,
1628316284 input = "SET id = id + 1",
@@ -16288,10 +16289,12 @@ fn parse_pipeline_operator() {
1628816289 input = "SET id = id + 1, name = name + ' Doe'",
1628916290 canonical = "SET id = id + 1, name = name + ' Doe'"
1629016291 );
16292+ }
16293+ }
1629116294
16292- // ------------------------------------
16293- // 'DROP' pipe operator
16294- // ------------------------------------
16295+ #[test]
16296+ fn parse_pipe_operator_drop() {
16297+ for dialect in pipe_dialects() {
1629516298 test_pipe!(dialect, input = "DROP id", canonical = "DROP id");
1629616299 test_pipe!(
1629716300 dialect,
@@ -16308,10 +16311,12 @@ fn parse_pipeline_operator() {
1630816311 input = "DROP a, b |> SELECT c",
1630916312 canonical = "DROP a, b |> SELECT c"
1631016313 );
16314+ }
16315+ }
1631116316
16312- // ------------------------------------
16313- // 'LIMIT' pipe operator
16314- // ------------------------------------
16317+ #[test]
16318+ fn parse_pipe_operator_limit() {
16319+ for dialect in pipe_dialects() {
1631516320 test_pipe!(dialect, input = "LIMIT 10", canonical = "LIMIT 10");
1631616321 test_pipe!(
1631716322 dialect,
@@ -16328,10 +16333,12 @@ fn parse_pipeline_operator() {
1632816333 input = "LIMIT 10 |> WHERE true",
1632916334 canonical = "LIMIT 10 |> WHERE true"
1633016335 );
16336+ }
16337+ }
1633116338
16332- // ------------------------------------
16333- // 'WHERE' pipe operator
16334- // ------------------------------------
16339+ #[test]
16340+ fn parse_pipe_operator_where() {
16341+ for dialect in pipe_dialects() {
1633516342 test_pipe!(dialect, input = "WHERE id = 1", canonical = "WHERE id = 1");
1633616343 test_pipe!(
1633716344 dialect,
@@ -16343,10 +16350,12 @@ fn parse_pipeline_operator() {
1634316350 input = "WHERE id = 1 OR name = 'John'",
1634416351 canonical = "WHERE id = 1 OR name = 'John'"
1634516352 );
16353+ }
16354+ }
1634616355
16347- // ------------------------------------
16348- // 'AGGREGATE' pipe operator
16349- // ------------------------------------
16356+ #[test]
16357+ fn parse_pipe_operator_aggregate() {
16358+ for dialect in pipe_dialects() {
1635016359 test_pipe!(
1635116360 dialect,
1635216361 input = "AGGREGATE COUNT(*)",
@@ -16397,10 +16406,12 @@ fn parse_pipeline_operator() {
1639716406 input = "AGGREGATE SUM(c) ASC",
1639816407 canonical = "AGGREGATE SUM(c) ASC"
1639916408 );
16409+ }
16410+ }
1640016411
16401- // ------------------------------------
16402- // 'ORDER BY' pipe operator
16403- // ------------------------------------
16412+ #[test]
16413+ fn parse_pipe_operator_order_by() {
16414+ for dialect in pipe_dialects() {
1640416415 test_pipe!(
1640516416 dialect,
1640616417 input = "ORDER BY id ASC",
@@ -16416,10 +16427,12 @@ fn parse_pipeline_operator() {
1641616427 input = "ORDER BY id DESC, name ASC",
1641716428 canonical = "ORDER BY id DESC, name ASC"
1641816429 );
16430+ }
16431+ }
1641916432
16420- // ------------------------------------
16421- // 'TABLESAMPLE' pipe operator
16422- // ------------------------------------
16433+ #[test]
16434+ fn parse_pipe_operator_tablesample() {
16435+ for dialect in pipe_dialects() {
1642316436 test_pipe!(
1642416437 dialect,
1642516438 input = "TABLESAMPLE BERNOULLI (50)",
@@ -16435,10 +16448,12 @@ fn parse_pipeline_operator() {
1643516448 input = "TABLESAMPLE SYSTEM (50) REPEATABLE (10)",
1643616449 canonical = "TABLESAMPLE SYSTEM (50) REPEATABLE (10)"
1643716450 );
16451+ }
16452+ }
1643816453
16439- // ------------------------------------
16440- // 'RENAME' pipe operator
16441- // ------------------------------------
16454+ #[test]
16455+ fn parse_pipe_operator_rename() {
16456+ for dialect in pipe_dialects() {
1644216457 test_pipe!(
1644316458 dialect,
1644416459 input = "RENAME old_name AS new_name",
@@ -16454,10 +16469,12 @@ fn parse_pipeline_operator() {
1645416469 input = "RENAME id user_id",
1645516470 canonical = "RENAME id AS user_id"
1645616471 );
16472+ }
16473+ }
1645716474
16458- // ------------------------------------
16459- // 'UNION' pipe operator
16460- // ------------------------------------
16475+ #[test]
16476+ fn parse_pipe_operator_union() {
16477+ for dialect in pipe_dialects() {
1646116478 test_pipe!(
1646216479 dialect,
1646316480 input = "UNION ALL (SELECT * FROM admins)",
@@ -16508,10 +16525,12 @@ fn parse_pipeline_operator() {
1650816525 input = "UNION BY NAME (SELECT * FROM admins), (SELECT * FROM guests)",
1650916526 canonical = "UNION BY NAME (SELECT * FROM admins), (SELECT * FROM guests)"
1651016527 );
16528+ }
16529+ }
1651116530
16512- // ------------------------------------
16513- // 'INTERSECT' pipe operator
16514- // ------------------------------------
16531+ #[test]
16532+ fn parse_pipe_operator_intersect() {
16533+ for dialect in pipe_dialects() {
1651516534 test_pipe!(
1651616535 dialect,
1651716536 input = "INTERSECT DISTINCT (SELECT * FROM admins)",
@@ -16532,10 +16551,12 @@ fn parse_pipeline_operator() {
1653216551 input = "INTERSECT DISTINCT BY NAME (SELECT * FROM admins), (SELECT * FROM guests)",
1653316552 canonical = "INTERSECT DISTINCT BY NAME (SELECT * FROM admins), (SELECT * FROM guests)"
1653416553 );
16554+ }
16555+ }
1653516556
16536- // ------------------------------------
16537- // 'EXCEPT' pipe operator
16538- // ------------------------------------
16557+ #[test]
16558+ fn parse_pipe_operator_except() {
16559+ for dialect in pipe_dialects() {
1653916560 test_pipe!(
1654016561 dialect,
1654116562 input = "EXCEPT DISTINCT (SELECT * FROM admins)",
@@ -16556,10 +16577,12 @@ fn parse_pipeline_operator() {
1655616577 input = "EXCEPT DISTINCT BY NAME (SELECT * FROM admins), (SELECT * FROM guests)",
1655716578 canonical = "EXCEPT DISTINCT BY NAME (SELECT * FROM admins), (SELECT * FROM guests)"
1655816579 );
16580+ }
16581+ }
1655916582
16560- // ------------------------------------
16561- // 'CALL' pipe operator
16562- // ------------------------------------
16583+ #[test]
16584+ fn parse_pipe_operator_call() {
16585+ for dialect in pipe_dialects() {
1656316586 test_pipe!(
1656416587 dialect,
1656516588 input = "CALL my_function()",
@@ -16630,10 +16653,12 @@ fn parse_pipeline_operator() {
1663016653 input = "CALL preprocess() AS clean |> SELECT col1, col2 |> CALL validate()",
1663116654 canonical = "CALL preprocess() AS clean |> SELECT col1, col2 |> CALL validate()"
1663216655 );
16656+ }
16657+ }
1663316658
16634- // ------------------------------------
16635- // 'PIVOT' pipe operator
16636- // ------------------------------------
16659+ #[test]
16660+ fn parse_pipe_operator_pivot() {
16661+ for dialect in pipe_dialects() {
1663716662 test_pipe!(
1663816663 dialect,
1663916664 input = "PIVOT(SUM(amount) FOR quarter IN ('Q1', 'Q2', 'Q3', 'Q4'))",
@@ -16686,10 +16711,12 @@ fn parse_pipeline_operator() {
1668616711 input = "PIVOT(AVG(price) FOR category IN ('A', 'B', 'C')) avg_by_category",
1668716712 canonical = "PIVOT(AVG(price) FOR category IN ('A', 'B', 'C')) AS avg_by_category"
1668816713 );
16714+ }
16715+ }
1668916716
16690- // ------------------------------------
16691- // 'UNPIVOT' pipe operator
16692- // ------------------------------------
16717+ #[test]
16718+ fn parse_pipe_operator_unpivot() {
16719+ for dialect in pipe_dialects() {
1669316720 test_pipe!(
1669416721 dialect,
1669516722 input = "UNPIVOT(revenue FOR quarter IN (Q1, Q2, Q3, Q4))",
@@ -16746,10 +16773,12 @@ fn parse_pipeline_operator() {
1674616773 input = "UNPIVOT(value FOR category IN (A, B, C)) transformed_data",
1674716774 canonical = "UNPIVOT(value FOR category IN (A, B, C)) AS transformed_data"
1674816775 );
16776+ }
16777+ }
1674916778
16750- // ------------------------------------
16751- // 'JOIN' pipe operator
16752- // ------------------------------------
16779+ #[test]
16780+ fn parse_pipe_operator_join() {
16781+ for dialect in pipe_dialects() {
1675316782 test_pipe!(
1675416783 dialect,
1675516784 input = "JOIN orders ON users.id = orders.user_id",
@@ -16852,10 +16881,13 @@ fn parse_pipeline_operator() {
1685216881 canonical =
1685316882 "JOIN orders ON users.id = orders.user_id |> SELECT users.name, orders.amount"
1685416883 );
16884+ }
16885+ }
1685516886
16856- // ------------------------------------
16857- // Miscellaneous complex/chained pipes
16858- // ------------------------------------
16887+ #[test]
16888+ fn parse_pipe_operator_chained() {
16889+ // Long chain of pipe ops
16890+ for dialect in pipe_dialects() {
1685916891 test_pipe!(
1686016892 dialect,
1686116893 input = "AGGREGATE SUM(cost) AS total_cost GROUP BY customer_id, state, item_type |> EXTEND COUNT(*) OVER (PARTITION BY customer_id) AS num_orders |> WHERE num_orders > 1 |> AGGREGATE AVG(total_cost) AS average GROUP BY state DESC, item_type ASC",
0 commit comments