@@ -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
@@ -16222,45 +16220,44 @@ fn parse_set_names() {
1622216220 dialects.verified_stmt("SET NAMES UTF8 COLLATE bogus");
1622316221}
1622416222
16225- #[test]
16226- fn parse_pipeline_operator() {
16227- // Macro to test pipe operator parsing with explicit input and canonical output.
16228- // test_pipe!(dialect, input = "...", canonical = "...")
16229- macro_rules! test_pipe {
16230- ($ctx:expr, input = $input:expr, canonical = $canonical:expr $(,)?) => {{
16231- let (dialects, from_first) = $ctx;
16232- let prefix = if from_first {
16233- "FROM tbl"
16234- } else {
16235- "SELECT * FROM tbl"
16236- };
16237- dialects.verified_query_with_canonical(
16238- &format!("{prefix} |> {}", $input),
16239- &format!("{prefix} |> {}", $canonical),
16240- );
16241- }};
16242- }
16243-
16244- // Test pipe operators with two dialect configurations:
16245- // 1. Dialects supporting FROM-first syntax (e.g., "FROM users |> ...")
16246- // 2. Dialects requiring SELECT-first syntax (e.g., "SELECT * FROM users |> ...")
16247- let from_first_dialects =
16223+ /// Returns dialect configurations for pipe operator tests:
16224+ /// 1. Dialects supporting FROM-first syntax (e.g., "FROM users |> ...")
16225+ /// 2. Dialects requiring SELECT-first syntax (e.g., "SELECT * FROM users |> ...")
16226+ fn pipe_dialects() -> [(TestedDialects, bool); 2] {
16227+ let from_first =
1624816228 all_dialects_where(|d| d.supports_pipe_operator() && d.supports_from_first_select());
16249- let select_first_dialects =
16229+ let select_first =
1625016230 all_dialects_where(|d| d.supports_pipe_operator() && !d.supports_from_first_select());
16231+ [(from_first, true), (select_first, false)]
16232+ }
1625116233
16252- for dialect in [
16253- (&from_first_dialects, true),
16254- (&select_first_dialects, false),
16255- ] {
16256- // ------------------------------------
16257- // 'AS' pipe operator
16258- // ------------------------------------
16234+ /// Macro to test pipe operator parsing with explicit input and canonical output.
16235+ /// Usage: `test_pipe!(ctx, input = "...", canonical = "...")`
16236+ macro_rules! test_pipe {
16237+ ($ctx:expr, input = $input:expr, canonical = $canonical:expr $(,)?) => {{
16238+ let (ref dialects, from_first) = $ctx;
16239+ let prefix = if from_first {
16240+ "FROM tbl"
16241+ } else {
16242+ "SELECT * FROM tbl"
16243+ };
16244+ dialects.verified_query_with_canonical(
16245+ &format!("{prefix} |> {}", $input),
16246+ &format!("{prefix} |> {}", $canonical),
16247+ );
16248+ }};
16249+ }
16250+
16251+ #[test]
16252+ fn parse_pipe_operator_as() {
16253+ for dialect in pipe_dialects() {
1625916254 test_pipe!(dialect, input = "AS new_users", canonical = "AS new_users");
16255+ }
16256+ }
1626016257
16261- // ------------------------------------
16262- // 'SELECT' pipe operator
16263- // ------------------------------------
16258+ #[test]
16259+ fn parse_pipe_operator_select() {
16260+ for dialect in pipe_dialects() {
1626416261 test_pipe!(dialect, input = "SELECT id", canonical = "SELECT id");
1626516262 test_pipe!(
1626616263 dialect,
@@ -16277,10 +16274,12 @@ fn parse_pipeline_operator() {
1627716274 input = "SELECT id AS user_id",
1627816275 canonical = "SELECT id AS user_id"
1627916276 );
16277+ }
16278+ }
1628016279
16281- // ------------------------------------
16282- // 'EXTEND' pipe operator
16283- // ------------------------------------
16280+ #[test]
16281+ fn parse_pipe_operator_extend() {
16282+ for dialect in pipe_dialects() {
1628416283 test_pipe!(
1628516284 dialect,
1628616285 input = "EXTEND id + 1 AS new_id",
@@ -16296,10 +16295,12 @@ fn parse_pipeline_operator() {
1629616295 input = "EXTEND id user_id",
1629716296 canonical = "EXTEND id AS user_id"
1629816297 );
16298+ }
16299+ }
1629916300
16300- // ------------------------------------
16301- // 'SET' pipe operator
16302- // ------------------------------------
16301+ #[test]
16302+ fn parse_pipe_operator_set() {
16303+ for dialect in pipe_dialects() {
1630316304 test_pipe!(
1630416305 dialect,
1630516306 input = "SET id = id + 1",
@@ -16310,10 +16311,12 @@ fn parse_pipeline_operator() {
1631016311 input = "SET id = id + 1, name = name + ' Doe'",
1631116312 canonical = "SET id = id + 1, name = name + ' Doe'"
1631216313 );
16314+ }
16315+ }
1631316316
16314- // ------------------------------------
16315- // 'DROP' pipe operator
16316- // ------------------------------------
16317+ #[test]
16318+ fn parse_pipe_operator_drop() {
16319+ for dialect in pipe_dialects() {
1631716320 test_pipe!(dialect, input = "DROP id", canonical = "DROP id");
1631816321 test_pipe!(
1631916322 dialect,
@@ -16330,10 +16333,12 @@ fn parse_pipeline_operator() {
1633016333 input = "DROP a, b |> SELECT c",
1633116334 canonical = "DROP a, b |> SELECT c"
1633216335 );
16336+ }
16337+ }
1633316338
16334- // ------------------------------------
16335- // 'LIMIT' pipe operator
16336- // ------------------------------------
16339+ #[test]
16340+ fn parse_pipe_operator_limit() {
16341+ for dialect in pipe_dialects() {
1633716342 test_pipe!(dialect, input = "LIMIT 10", canonical = "LIMIT 10");
1633816343 test_pipe!(
1633916344 dialect,
@@ -16350,10 +16355,12 @@ fn parse_pipeline_operator() {
1635016355 input = "LIMIT 10 |> WHERE true",
1635116356 canonical = "LIMIT 10 |> WHERE true"
1635216357 );
16358+ }
16359+ }
1635316360
16354- // ------------------------------------
16355- // 'WHERE' pipe operator
16356- // ------------------------------------
16361+ #[test]
16362+ fn parse_pipe_operator_where() {
16363+ for dialect in pipe_dialects() {
1635716364 test_pipe!(dialect, input = "WHERE id = 1", canonical = "WHERE id = 1");
1635816365 test_pipe!(
1635916366 dialect,
@@ -16365,10 +16372,12 @@ fn parse_pipeline_operator() {
1636516372 input = "WHERE id = 1 OR name = 'John'",
1636616373 canonical = "WHERE id = 1 OR name = 'John'"
1636716374 );
16375+ }
16376+ }
1636816377
16369- // ------------------------------------
16370- // 'AGGREGATE' pipe operator
16371- // ------------------------------------
16378+ #[test]
16379+ fn parse_pipe_operator_aggregate() {
16380+ for dialect in pipe_dialects() {
1637216381 test_pipe!(
1637316382 dialect,
1637416383 input = "AGGREGATE COUNT(*)",
@@ -16419,10 +16428,12 @@ fn parse_pipeline_operator() {
1641916428 input = "AGGREGATE SUM(c) ASC",
1642016429 canonical = "AGGREGATE SUM(c) ASC"
1642116430 );
16431+ }
16432+ }
1642216433
16423- // ------------------------------------
16424- // 'ORDER BY' pipe operator
16425- // ------------------------------------
16434+ #[test]
16435+ fn parse_pipe_operator_order_by() {
16436+ for dialect in pipe_dialects() {
1642616437 test_pipe!(
1642716438 dialect,
1642816439 input = "ORDER BY id ASC",
@@ -16438,10 +16449,12 @@ fn parse_pipeline_operator() {
1643816449 input = "ORDER BY id DESC, name ASC",
1643916450 canonical = "ORDER BY id DESC, name ASC"
1644016451 );
16452+ }
16453+ }
1644116454
16442- // ------------------------------------
16443- // 'TABLESAMPLE' pipe operator
16444- // ------------------------------------
16455+ #[test]
16456+ fn parse_pipe_operator_tablesample() {
16457+ for dialect in pipe_dialects() {
1644516458 test_pipe!(
1644616459 dialect,
1644716460 input = "TABLESAMPLE BERNOULLI (50)",
@@ -16457,10 +16470,12 @@ fn parse_pipeline_operator() {
1645716470 input = "TABLESAMPLE SYSTEM (50) REPEATABLE (10)",
1645816471 canonical = "TABLESAMPLE SYSTEM (50) REPEATABLE (10)"
1645916472 );
16473+ }
16474+ }
1646016475
16461- // ------------------------------------
16462- // 'RENAME' pipe operator
16463- // ------------------------------------
16476+ #[test]
16477+ fn parse_pipe_operator_rename() {
16478+ for dialect in pipe_dialects() {
1646416479 test_pipe!(
1646516480 dialect,
1646616481 input = "RENAME old_name AS new_name",
@@ -16476,10 +16491,12 @@ fn parse_pipeline_operator() {
1647616491 input = "RENAME id user_id",
1647716492 canonical = "RENAME id AS user_id"
1647816493 );
16494+ }
16495+ }
1647916496
16480- // ------------------------------------
16481- // 'UNION' pipe operator
16482- // ------------------------------------
16497+ #[test]
16498+ fn parse_pipe_operator_union() {
16499+ for dialect in pipe_dialects() {
1648316500 test_pipe!(
1648416501 dialect,
1648516502 input = "UNION ALL (SELECT * FROM admins)",
@@ -16530,10 +16547,12 @@ fn parse_pipeline_operator() {
1653016547 input = "UNION BY NAME (SELECT * FROM admins), (SELECT * FROM guests)",
1653116548 canonical = "UNION BY NAME (SELECT * FROM admins), (SELECT * FROM guests)"
1653216549 );
16550+ }
16551+ }
1653316552
16534- // ------------------------------------
16535- // 'INTERSECT' pipe operator
16536- // ------------------------------------
16553+ #[test]
16554+ fn parse_pipe_operator_intersect() {
16555+ for dialect in pipe_dialects() {
1653716556 test_pipe!(
1653816557 dialect,
1653916558 input = "INTERSECT DISTINCT (SELECT * FROM admins)",
@@ -16554,10 +16573,12 @@ fn parse_pipeline_operator() {
1655416573 input = "INTERSECT DISTINCT BY NAME (SELECT * FROM admins), (SELECT * FROM guests)",
1655516574 canonical = "INTERSECT DISTINCT BY NAME (SELECT * FROM admins), (SELECT * FROM guests)"
1655616575 );
16576+ }
16577+ }
1655716578
16558- // ------------------------------------
16559- // 'EXCEPT' pipe operator
16560- // ------------------------------------
16579+ #[test]
16580+ fn parse_pipe_operator_except() {
16581+ for dialect in pipe_dialects() {
1656116582 test_pipe!(
1656216583 dialect,
1656316584 input = "EXCEPT DISTINCT (SELECT * FROM admins)",
@@ -16578,10 +16599,12 @@ fn parse_pipeline_operator() {
1657816599 input = "EXCEPT DISTINCT BY NAME (SELECT * FROM admins), (SELECT * FROM guests)",
1657916600 canonical = "EXCEPT DISTINCT BY NAME (SELECT * FROM admins), (SELECT * FROM guests)"
1658016601 );
16602+ }
16603+ }
1658116604
16582- // ------------------------------------
16583- // 'CALL' pipe operator
16584- // ------------------------------------
16605+ #[test]
16606+ fn parse_pipe_operator_call() {
16607+ for dialect in pipe_dialects() {
1658516608 test_pipe!(
1658616609 dialect,
1658716610 input = "CALL my_function()",
@@ -16652,10 +16675,12 @@ fn parse_pipeline_operator() {
1665216675 input = "CALL preprocess() AS clean |> SELECT col1, col2 |> CALL validate()",
1665316676 canonical = "CALL preprocess() AS clean |> SELECT col1, col2 |> CALL validate()"
1665416677 );
16678+ }
16679+ }
1665516680
16656- // ------------------------------------
16657- // 'PIVOT' pipe operator
16658- // ------------------------------------
16681+ #[test]
16682+ fn parse_pipe_operator_pivot() {
16683+ for dialect in pipe_dialects() {
1665916684 test_pipe!(
1666016685 dialect,
1666116686 input = "PIVOT(SUM(amount) FOR quarter IN ('Q1', 'Q2', 'Q3', 'Q4'))",
@@ -16708,10 +16733,12 @@ fn parse_pipeline_operator() {
1670816733 input = "PIVOT(AVG(price) FOR category IN ('A', 'B', 'C')) avg_by_category",
1670916734 canonical = "PIVOT(AVG(price) FOR category IN ('A', 'B', 'C')) AS avg_by_category"
1671016735 );
16736+ }
16737+ }
1671116738
16712- // ------------------------------------
16713- // 'UNPIVOT' pipe operator
16714- // ------------------------------------
16739+ #[test]
16740+ fn parse_pipe_operator_unpivot() {
16741+ for dialect in pipe_dialects() {
1671516742 test_pipe!(
1671616743 dialect,
1671716744 input = "UNPIVOT(revenue FOR quarter IN (Q1, Q2, Q3, Q4))",
@@ -16768,10 +16795,12 @@ fn parse_pipeline_operator() {
1676816795 input = "UNPIVOT(value FOR category IN (A, B, C)) transformed_data",
1676916796 canonical = "UNPIVOT(value FOR category IN (A, B, C)) AS transformed_data"
1677016797 );
16798+ }
16799+ }
1677116800
16772- // ------------------------------------
16773- // 'JOIN' pipe operator
16774- // ------------------------------------
16801+ #[test]
16802+ fn parse_pipe_operator_join() {
16803+ for dialect in pipe_dialects() {
1677516804 test_pipe!(
1677616805 dialect,
1677716806 input = "JOIN orders ON users.id = orders.user_id",
@@ -16874,10 +16903,13 @@ fn parse_pipeline_operator() {
1687416903 canonical =
1687516904 "JOIN orders ON users.id = orders.user_id |> SELECT users.name, orders.amount"
1687616905 );
16906+ }
16907+ }
1687716908
16878- // ------------------------------------
16879- // Miscellaneous complex/chained pipes
16880- // ------------------------------------
16909+ #[test]
16910+ fn parse_pipe_operator_chained() {
16911+ // Long chain of pipe ops
16912+ for dialect in pipe_dialects() {
1688116913 test_pipe!(
1688216914 dialect,
1688316915 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