1
0
Fork 0

Merging upstream version 26.28.1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-06-15 10:36:04 +02:00
parent 893214206a
commit c79efa667c
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
96 changed files with 58442 additions and 56422 deletions

View file

@ -42,6 +42,7 @@ class TestBigQuery(Validator):
self.assertEqual(table.db, "x-0")
self.assertEqual(table.name, "_y")
self.validate_identity("SAFE.SUBSTR('foo', 0, -2)").assert_is(exp.Dot)
self.validate_identity("SELECT * FROM x-0.y")
self.assertEqual(exp.to_table("`a.b`.`c.d`", dialect="bigquery").sql(), '"a"."b"."c"."d"')
self.assertEqual(exp.to_table("`x`.`y.z`", dialect="bigquery").sql(), '"x"."y"."z"')

View file

@ -3504,141 +3504,3 @@ FROM subquery2""",
parse_one("SELECT 0xCC", read=read_dialect).sql(other_integer_dialects),
"SELECT 0xCC",
)
def test_pipe_syntax(self):
self.validate_identity("FROM x", "SELECT * FROM x")
self.validate_identity("FROM x |> SELECT x1, x2", "SELECT x1, x2 FROM (SELECT * FROM x)")
self.validate_identity(
"FROM x |> SELECT x1 as c1, x2 as c2",
"SELECT x1 AS c1, x2 AS c2 FROM (SELECT * FROM x)",
)
self.validate_identity(
"FROM x |> SELECT x1 + 1 as x1_a, x2 - 1 as x2_a |> WHERE x1_a > 1",
"SELECT x1 + 1 AS x1_a, x2 - 1 AS x2_a FROM (SELECT * FROM x) WHERE x1_a > 1",
)
self.validate_identity(
"FROM x |> SELECT x1 + 1 as x1_a, x2 - 1 as x2_a |> WHERE x1_a > 1 |> SELECT x2_a",
"SELECT x2_a FROM (SELECT x1 + 1 AS x1_a, x2 - 1 AS x2_a FROM (SELECT * FROM x) WHERE x1_a > 1)",
)
self.validate_identity(
"FROM x |> WHERE x1 > 0 OR x2 > 0 |> WHERE x3 > 1 AND x4 > 1 |> SELECT x1, x4",
"SELECT x1, x4 FROM (SELECT * FROM x WHERE (x1 > 0 OR x2 > 0) AND (x3 > 1 AND x4 > 1))",
)
self.validate_identity(
"FROM x |> WHERE x1 > 1 |> WHERE x2 > 2 |> SELECT x1 as gt1, x2 as gt2",
"SELECT x1 AS gt1, x2 AS gt2 FROM (SELECT * FROM x WHERE x1 > 1 AND x2 > 2)",
)
self.validate_identity(
"FROM x |> WHERE x1 > 1 AND x2 > 2 |> SELECT x1 as gt1, x2 as gt2 |> SELECT gt1 * 2 + gt2 * 2 AS gt2_2",
"SELECT gt1 * 2 + gt2 * 2 AS gt2_2 FROM (SELECT x1 AS gt1, x2 AS gt2 FROM (SELECT * FROM x WHERE x1 > 1 AND x2 > 2))",
)
self.validate_identity("FROM x |> ORDER BY x1", "SELECT * FROM x ORDER BY x1")
self.validate_identity(
"FROM x |> ORDER BY x1 |> ORDER BY x2", "SELECT * FROM x ORDER BY x1, x2"
)
self.validate_identity(
"FROM x |> ORDER BY x1 |> WHERE x1 > 0 OR x1 != 1 |> ORDER BY x2 |> WHERE x2 > 0 AND x2 != 1 |> SELECT x1, x2",
"SELECT x1, x2 FROM (SELECT * FROM x WHERE (x1 > 0 OR x1 <> 1) AND (x2 > 0 AND x2 <> 1) ORDER BY x1, x2)",
)
self.validate_identity(
"FROM x |> ORDER BY x1 |> WHERE x1 > 0 |> SELECT x1",
"SELECT x1 FROM (SELECT * FROM x WHERE x1 > 0 ORDER BY x1)",
)
self.validate_identity(
"FROM x |> WHERE x1 > 0 |> SELECT x1 |> ORDER BY x1",
"SELECT x1 FROM (SELECT * FROM x WHERE x1 > 0) ORDER BY x1",
)
self.validate_identity(
"FROM x |> SELECT x1, x2, x3 |> ORDER BY x1 DESC NULLS FIRST, x2 ASC NULLS LAST, x3",
"SELECT x1, x2, x3 FROM (SELECT * FROM x) ORDER BY x1 DESC NULLS FIRST, x2 ASC NULLS LAST, x3",
)
for option in ("LIMIT 1", "OFFSET 2", "LIMIT 1 OFFSET 2"):
with self.subTest(f"Testing pipe syntax LIMIT and OFFSET option: {option}"):
self.validate_identity(f"FROM x |> {option}", f"SELECT * FROM x {option}")
self.validate_identity(f"FROM x |> {option}", f"SELECT * FROM x {option}")
self.validate_identity(
f"FROM x |> {option} |> SELECT x1, x2 |> WHERE x1 > 0 |> WHERE x2 > 0 |> ORDER BY x1, x2 ",
f"SELECT x1, x2 FROM (SELECT * FROM x {option}) WHERE x1 > 0 AND x2 > 0 ORDER BY x1, x2",
)
self.validate_identity(
f"FROM x |> SELECT x1, x2 |> WHERE x1 > 0 |> WHERE x2 > 0 |> ORDER BY x1, x2 |> {option}",
f"SELECT x1, x2 FROM (SELECT * FROM x) WHERE x1 > 0 AND x2 > 0 ORDER BY x1, x2 {option}",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1), MAX(x2), MIN(x3)",
"SELECT SUM(x1), MAX(x2), MIN(x3) FROM (SELECT * FROM x)",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1) AS s_x1 |> SELECT s_x1",
"SELECT s_x1 FROM (SELECT SUM(x1) AS s_x1 FROM (SELECT * FROM x))",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1), MAX(x2), MIN(x3) GROUP BY x4, x5",
"SELECT SUM(x1), MAX(x2), MIN(x3), x4, x5 FROM (SELECT * FROM x) GROUP BY x4, x5",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1), MAX(x2), MIN(x3) GROUP BY x4 AS a_x4, x5 AS a_x5",
"SELECT SUM(x1), MAX(x2), MIN(x3), x4 AS a_x4, x5 AS a_x5 FROM (SELECT * FROM x) GROUP BY a_x4, a_x5",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1) as s_x1 GROUP BY x1 |> SELECT s_x1, x1 as ss_x1",
"SELECT s_x1, x1 AS ss_x1 FROM (SELECT SUM(x1) AS s_x1, x1 FROM (SELECT * FROM x) GROUP BY x1)",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1) GROUP", "SELECT SUM(x1) AS GROUP FROM (SELECT * FROM x)"
)
for order_option in ("ASC", "DESC", "ASC NULLS LAST", "DESC NULLS FIRST"):
with self.subTest(f"Testing pipe syntax AGGREGATE for order option: {order_option}"):
self.validate_all(
f"SELECT SUM(x1) AS x_s FROM (SELECT * FROM x) ORDER BY x_s {order_option}",
read={
"bigquery": f"FROM x |> AGGREGATE SUM(x1) AS x_s {order_option}",
},
)
self.validate_all(
f"SELECT SUM(x1) AS x_s, x1 AS g_x1 FROM (SELECT * FROM x) GROUP BY g_x1 ORDER BY x_s {order_option}",
read={
"bigquery": f"FROM x |> AGGREGATE SUM(x1) AS x_s {order_option} GROUP BY x1 AS g_x1",
},
)
with self.subTest(
f"Testing pipe syntax AGGREGATE with GROUP AND ORDER BY for order option: {order_option}"
):
self.validate_all(
f"SELECT g_x1, x_s FROM (SELECT SUM(x1) AS x_s, x1 AS g_x1 FROM (SELECT * FROM x) GROUP BY g_x1 ORDER BY g_x1 {order_option})",
read={
"bigquery": f"FROM x |> AGGREGATE SUM(x1) AS x_s GROUP AND ORDER BY x1 AS g_x1 {order_option} |> SELECT g_x1, x_s",
},
)
for op_operator in (
"UNION ALL",
"UNION DISTINCT",
"INTERSECT DISTINCT",
"EXCEPT DISTINCT",
):
with self.subTest(f"Testing pipe syntax SET OPERATORS: {op_operator}"):
self.validate_all(
f"FROM x|> {op_operator} (SELECT y1 FROM y), (SELECT z1 FROM z)",
write={
"bigquery": f"SELECT * FROM x {op_operator} (SELECT y1 FROM y) {op_operator} (SELECT z1 FROM z)",
},
)
for op_prefix in ("LEFT OUTER", "FULL OUTER"):
for op_operator in (
"UNION ALL",
"UNION DISTINCT",
"INTERSECT DISTINCT",
"EXCEPT DISTINCT",
):
for suffix_operator in ("BY NAME", "CORRESPONDING"):
with self.subTest(
f"Testing pipe syntax SET OPERATORS: {op_prefix} {op_operator} {suffix_operator}"
):
self.validate_all(
f"FROM x|> SELECT x1, x2 FROM x |> {op_prefix} {op_operator} {suffix_operator} (SELECT y1, y2 FROM y), (SELECT z1, z2 FROM z)",
write={
"bigquery": f"SELECT x1, x2 FROM (SELECT * FROM x) {op_prefix} {op_operator} BY NAME (SELECT y1, y2 FROM y) {op_prefix} {op_operator} BY NAME (SELECT z1, z2 FROM z)",
},
)

View file

@ -732,12 +732,20 @@ class TestHive(Validator):
},
)
self.validate_all(
"x div y",
"x DIV y",
read={
"databricks": "x DIV y",
"duckdb": "x // y",
"hive": "x DIV y",
"spark2": "x DIV y",
"spark": "x DIV y",
},
write={
"duckdb": "x // y",
"databricks": "x DIV y",
"presto": "CAST(CAST(x AS DOUBLE) / y AS INTEGER)",
"hive": "CAST(x / y AS INT)",
"spark": "CAST(x / y AS INT)",
"spark2": "x DIV y",
"spark": "x DIV y",
},
)
self.validate_all(

View file

@ -89,6 +89,20 @@ class TestMySQL(Validator):
self.validate_identity(
"CREATE TABLE test_table (id INT AUTO_INCREMENT, PRIMARY KEY (id) USING HASH)"
)
self.validate_identity(
"CREATE TABLE test (a INT, b INT GENERATED ALWAYS AS (a + a) STORED)"
)
self.validate_identity(
"CREATE TABLE test (a INT, b INT GENERATED ALWAYS AS (a + a) VIRTUAL)"
)
self.validate_identity(
"CREATE TABLE test (a INT, b INT AS (a + a) STORED)",
"CREATE TABLE test (a INT, b INT GENERATED ALWAYS AS (a + a) STORED)",
)
self.validate_identity(
"CREATE TABLE test (a INT, b INT AS (a + a) VIRTUAL)",
"CREATE TABLE test (a INT, b INT GENERATED ALWAYS AS (a + a) VIRTUAL)",
)
self.validate_identity(
"/*left*/ EXPLAIN SELECT /*hint*/ col FROM t1 /*right*/",
"/* left */ DESCRIBE /* hint */ SELECT col FROM t1 /* right */",

View file

@ -0,0 +1,380 @@
from tests.dialects.test_dialect import Validator
class TestPipeSyntax(Validator):
def test_select(self):
self.validate_identity("FROM x", "SELECT * FROM x")
self.validate_identity(
"FROM x |> SELECT x1, x2", "WITH __tmp1 AS (SELECT x1, x2 FROM x) SELECT * FROM __tmp1"
)
self.validate_identity(
"FROM x |> SELECT x.x1, x.x2",
"WITH __tmp1 AS (SELECT x.x1, x.x2 FROM x) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> SELECT x1 as c1, x2 as c2",
"WITH __tmp1 AS (SELECT x1 AS c1, x2 AS c2 FROM x) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> SELECT x1 + 1 as x1_a, x2 - 1 as x2_a |> WHERE x1_a > 1",
"WITH __tmp1 AS (SELECT x1 + 1 AS x1_a, x2 - 1 AS x2_a FROM x) SELECT * FROM __tmp1 WHERE x1_a > 1",
)
self.validate_identity(
"FROM x |> SELECT x1 + 1 as x1_a, x2 - 1 as x2_a |> WHERE x1_a > 1 |> SELECT x2_a",
"WITH __tmp1 AS (SELECT x1 + 1 AS x1_a, x2 - 1 AS x2_a FROM x), __tmp2 AS (SELECT * FROM __tmp1 WHERE x1_a > 1) SELECT x2_a FROM __tmp2",
)
self.validate_identity(
"FROM x |> WHERE x1 > 0 OR x2 > 0 |> WHERE x3 > 1 AND x4 > 1 |> SELECT x1, x4",
"WITH __tmp1 AS (SELECT x1, x4 FROM x WHERE (x1 > 0 OR x2 > 0) AND (x3 > 1 AND x4 > 1)) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> WHERE x1 > 1 |> WHERE x2 > 2 |> SELECT x1 as gt1, x2 as gt2",
"WITH __tmp1 AS (SELECT x1 AS gt1, x2 AS gt2 FROM x WHERE x1 > 1 AND x2 > 2) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> WHERE x1 > 1 AND x2 > 2 |> SELECT x1 as gt1, x2 as gt2 |> SELECT gt1 * 2 + gt2 * 2 AS gt2_2",
"WITH __tmp1 AS (SELECT x1 AS gt1, x2 AS gt2 FROM x WHERE x1 > 1 AND x2 > 2), __tmp2 AS (SELECT * FROM __tmp1) SELECT gt1 * 2 + gt2 * 2 AS gt2_2 FROM __tmp2",
)
def test_order_by(self):
self.validate_identity("FROM x |> ORDER BY x1", "SELECT * FROM x ORDER BY x1")
self.validate_identity(
"FROM x |> ORDER BY x1 |> ORDER BY x2", "SELECT * FROM x ORDER BY x2"
)
self.validate_identity(
"FROM x |> ORDER BY x1 |> WHERE x1 > 0 OR x1 != 1 |> ORDER BY x2 |> WHERE x2 > 0 AND x2 != 1 |> SELECT x1, x2",
"WITH __tmp1 AS (SELECT x1, x2 FROM x WHERE (x1 > 0 OR x1 <> 1) AND (x2 > 0 AND x2 <> 1) ORDER BY x2) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> ORDER BY x1 |> WHERE x1 > 0 |> SELECT x1",
"WITH __tmp1 AS (SELECT x1 FROM x WHERE x1 > 0 ORDER BY x1) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> WHERE x1 > 0 |> SELECT x1 |> ORDER BY x1",
"WITH __tmp1 AS (SELECT x1 FROM x WHERE x1 > 0) SELECT * FROM __tmp1 ORDER BY x1",
)
self.validate_identity(
"FROM x |> SELECT x1, x2, x3 |> ORDER BY x1 DESC NULLS FIRST, x2 ASC NULLS LAST, x3",
"WITH __tmp1 AS (SELECT x1, x2, x3 FROM x) SELECT * FROM __tmp1 ORDER BY x1 DESC NULLS FIRST, x2 ASC NULLS LAST, x3",
)
def test_limit(self):
for option in ("LIMIT 1", "LIMIT 1 OFFSET 2"):
with self.subTest(f"Testing pipe syntax LIMIT and OFFSET option: {option}"):
self.validate_identity(f"FROM x |> {option}", f"SELECT * FROM x {option}")
self.validate_identity(f"FROM x |> {option}", f"SELECT * FROM x {option}")
self.validate_identity(
f"FROM x |> {option} |> SELECT x1, x2 |> WHERE x1 > 0 |> WHERE x2 > 0 |> ORDER BY x1, x2",
f"WITH __tmp1 AS (SELECT x1, x2 FROM x {option}) SELECT * FROM __tmp1 WHERE x1 > 0 AND x2 > 0 ORDER BY x1, x2",
)
self.validate_identity(
f"FROM x |> SELECT x1, x2 |> WHERE x1 > 0 |> WHERE x2 > 0 |> ORDER BY x1, x2 |> {option}",
f"WITH __tmp1 AS (SELECT x1, x2 FROM x) SELECT * FROM __tmp1 WHERE x1 > 0 AND x2 > 0 ORDER BY x1, x2 {option}",
)
self.validate_identity(
"FROM x |> SELECT x1, x2 |> LIMIT 2 |> LIMIT 4",
"WITH __tmp1 AS (SELECT x1, x2 FROM x) SELECT * FROM __tmp1 LIMIT 2",
)
self.validate_identity(
"FROM x |> SELECT x1, x2 |> LIMIT 2 OFFSET 2 |> LIMIT 4 OFFSET 2",
"WITH __tmp1 AS (SELECT x1, x2 FROM x) SELECT * FROM __tmp1 LIMIT 2 OFFSET 4",
)
def test_aggregate(self):
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1), MAX(x2), MIN(x3)",
"WITH __tmp1 AS (SELECT SUM(x1), MAX(x2), MIN(x3) FROM x) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1) AS s_x1 |> SELECT s_x1",
"WITH __tmp1 AS (SELECT SUM(x1) AS s_x1 FROM x), __tmp2 AS (SELECT * FROM __tmp1) SELECT s_x1 FROM __tmp2",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1), MAX(x2), MIN(x3) GROUP BY x4, x5",
"WITH __tmp1 AS (SELECT SUM(x1), MAX(x2), MIN(x3), x4, x5 FROM x GROUP BY x4, x5) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1), MAX(x2), MIN(x3) GROUP BY x4 AS a_x4, x5 AS a_x5",
"WITH __tmp1 AS (SELECT SUM(x1), MAX(x2), MIN(x3), x4 AS a_x4, x5 AS a_x5 FROM x GROUP BY a_x4, a_x5) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1) as s_x1 GROUP BY x1 |> SELECT s_x1, x1 as ss_x1",
"WITH __tmp1 AS (SELECT SUM(x1) AS s_x1, x1 FROM x GROUP BY x1), __tmp2 AS (SELECT * FROM __tmp1) SELECT s_x1, x1 AS ss_x1 FROM __tmp2",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1) GROUP",
"WITH __tmp1 AS (SELECT SUM(x1) AS GROUP FROM x) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> AGGREGATE SUM(x1) as s_x1 GROUP BY x2 as g_x2 |> WHERE s_x1 > 0",
"WITH __tmp1 AS (SELECT SUM(x1) AS s_x1, x2 AS g_x2 FROM x GROUP BY g_x2) SELECT * FROM __tmp1 WHERE s_x1 > 0",
)
for order_option in ("ASC", "DESC", "ASC NULLS LAST", "DESC NULLS FIRST"):
with self.subTest(f"Testing pipe syntax AGGREGATE for order option: {order_option}"):
self.validate_all(
f"WITH __tmp1 AS (SELECT SUM(x1) AS x_s FROM x ORDER BY x_s {order_option}) SELECT * FROM __tmp1",
read={
"bigquery": f"FROM x |> AGGREGATE SUM(x1) AS x_s {order_option}",
},
)
self.validate_all(
f"WITH __tmp1 AS (SELECT SUM(x1) AS x_s, x1 AS g_x1 FROM x GROUP BY g_x1 ORDER BY x_s {order_option}) SELECT * FROM __tmp1",
read={
"bigquery": f"FROM x |> AGGREGATE SUM(x1) AS x_s {order_option} GROUP BY x1 AS g_x1",
},
)
with self.subTest(
f"Testing pipe syntax AGGREGATE with GROUP AND ORDER BY for order option: {order_option}"
):
self.validate_all(
f"WITH __tmp1 AS (SELECT SUM(x1) AS x_s, x1 AS g_x1 FROM x GROUP BY g_x1 ORDER BY g_x1 {order_option}), __tmp2 AS (SELECT * FROM __tmp1) SELECT g_x1, x_s FROM __tmp2",
read={
"bigquery": f"FROM x |> AGGREGATE SUM(x1) AS x_s GROUP AND ORDER BY x1 AS g_x1 {order_option} |> SELECT g_x1, x_s",
},
)
def test_set_operators(self):
self.validate_identity(
"FROM x |> SELECT x.x1 |> UNION ALL (SELECT 1 AS c)",
"WITH __tmp1 AS (SELECT x.x1 FROM x), __tmp2 AS (SELECT * FROM __tmp1), __tmp3 AS (SELECT * FROM __tmp2 UNION ALL (SELECT 1 AS c)) SELECT * FROM __tmp3",
)
for op_operator in (
"UNION ALL",
"UNION DISTINCT",
"INTERSECT DISTINCT",
"EXCEPT DISTINCT",
):
with self.subTest(f"Testing pipe syntax SET OPERATORS: {op_operator}"):
self.validate_all(
f"FROM x|> {op_operator} (SELECT y1 FROM y), (SELECT z1 FROM z)",
write={
"bigquery": f"WITH __tmp1 AS (SELECT * FROM x), __tmp2 AS (SELECT * FROM __tmp1 {op_operator} (SELECT y1 FROM y) {op_operator} (SELECT z1 FROM z)) SELECT * FROM __tmp2"
},
)
for op_prefix in ("LEFT OUTER", "FULL OUTER"):
for op_operator in (
"UNION ALL",
"UNION DISTINCT",
"INTERSECT DISTINCT",
"EXCEPT DISTINCT",
):
with self.subTest(f"Testing pipe syntax SET OPERATORS: {op_prefix} {op_operator}"):
self.validate_all(
f"FROM x|> SELECT x1, x2 |> {op_prefix} {op_operator} BY NAME (SELECT y1, y2 FROM y), (SELECT z1, z2 FROM z)",
write={
"bigquery": f"WITH __tmp1 AS (SELECT x1, x2 FROM x), __tmp2 AS (SELECT * FROM __tmp1), __tmp3 AS (SELECT * FROM __tmp2 {op_prefix} {op_operator} BY NAME (SELECT y1, y2 FROM y) {op_prefix} {op_operator} BY NAME (SELECT z1, z2 FROM z)) SELECT * FROM __tmp3",
},
)
self.validate_identity(
"FROM d.x |> SELECT x.x1 |> UNION (SELECT 2 AS a1) |> SELECT x1 |> UNION (SELECT 3 as a2) |> SELECT x1 |> WHERE x1 > 100",
"""WITH __tmp1 AS (
SELECT
x.x1
FROM d.x
), __tmp2 AS (
SELECT
*
FROM __tmp1
), __tmp3 AS (
SELECT
*
FROM __tmp2
UNION
(
SELECT
2 AS a1
)
), __tmp4 AS (
SELECT
*
FROM __tmp3
), __tmp5 AS (
SELECT
x1
FROM __tmp4
), __tmp6 AS (
SELECT
*
FROM __tmp5
UNION
(
SELECT
3 AS a2
)
), __tmp7 AS (
SELECT
*
FROM __tmp6
)
SELECT
x1
FROM __tmp7
WHERE
x1 > 100""",
pretty=True,
)
self.validate_identity(
"FROM c.x |> UNION ALL (SELECT 2 AS a1, '2' as a2) |> AGGREGATE AVG(x1) as m_x1 |> SELECT * |> UNION ALL (SELECT y1 FROM c.y) |> SELECT m_x1",
"""WITH __tmp1 AS (
SELECT
*
FROM c.x
), __tmp2 AS (
SELECT
*
FROM __tmp1
UNION ALL
(
SELECT
2 AS a1,
'2' AS a2
)
), __tmp3 AS (
SELECT
*,
AVG(x1) AS m_x1
FROM __tmp2
), __tmp4 AS (
SELECT
*
FROM __tmp3
), __tmp5 AS (
SELECT
*
FROM __tmp4
), __tmp6 AS (
SELECT
*
FROM __tmp5
UNION ALL
(
SELECT
y1
FROM c.y
)
), __tmp7 AS (
SELECT
*
FROM __tmp6
)
SELECT
m_x1
FROM __tmp7""",
pretty=True,
)
self.validate_identity(
"FROM c.x |> UNION ALL (SELECT 2 AS a1, '2' as a2) |> UNION ALL (SELECT y1 FROM c.y) |> WHERE x > 200",
"""WITH __tmp1 AS (
SELECT
*
FROM c.x
), __tmp2 AS (
SELECT
*
FROM __tmp1
UNION ALL
(
SELECT
2 AS a1,
'2' AS a2
)
), __tmp3 AS (
SELECT
*
FROM __tmp2
), __tmp4 AS (
SELECT
*
FROM __tmp3
UNION ALL
(
SELECT
y1
FROM c.y
)
)
SELECT
*
FROM __tmp4
WHERE
x > 200""",
pretty=True,
)
def test_join(self):
self.validate_identity("FROM x |> CROSS JOIN y", "SELECT * FROM x CROSS JOIN y")
for join_type in (
"JOIN",
"INNER JOIN",
"FULL JOIN",
"FULL OUTER JOIN",
"LEFT JOIN",
"LEFT OUTER JOIN",
"RIGHT JOIN",
"RIGHT OUTER JOIN",
):
with self.subTest(f"Testing pipe syntax no projecton with JOIN : {join_type}"):
self.validate_identity(
f"FROM x |> {join_type} y ON x.id = y.id",
f"SELECT * FROM x {join_type} y ON x.id = y.id",
)
with self.subTest(f"Testing pipe syntax projection with JOIN: {join_type}"):
self.validate_identity(
f"FROM x |> SELECT id |> {join_type} y ON x.id = y.id",
f"WITH __tmp1 AS (SELECT id FROM x) SELECT * FROM __tmp1 {join_type} y ON x.id = y.id",
)
with self.subTest(f"Testing pipe syntax complex queries with JOIN: {join_type}"):
self.validate_identity(
f"FROM x |> {join_type} y ON x.id = y.id |> SELECT x1 as a_x1, x2 |> UNION ALL (SELECT 1, 2) |> WHERE a_x1 > 0",
f"""WITH __tmp1 AS (
SELECT
x1 AS a_x1,
x2
FROM x
{join_type} y
ON x.id = y.id
), __tmp2 AS (
SELECT
*
FROM __tmp1
), __tmp3 AS (
SELECT
*
FROM __tmp2
UNION ALL
(
SELECT
1,
2
)
)
SELECT
*
FROM __tmp3
WHERE
a_x1 > 0""",
pretty=True,
)
def test_pivot_unpivot(self):
self.validate_identity(
"FROM x |> PIVOT(SUM(x1) FOR quarter IN ('foo1', 'foo2'))",
"WITH __tmp1 AS (SELECT * FROM x PIVOT(SUM(x1) FOR quarter IN ('foo1', 'foo2'))) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> JOIN y on x.id = y.id |> PIVOT(SUM(x1) FOR quarter IN ('foo1', 'foo2'))",
"WITH __tmp1 AS (SELECT * FROM x PIVOT(SUM(x1) FOR quarter IN ('foo1', 'foo2')) JOIN y ON x.id = y.id) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> UNPIVOT(col FOR item IN (foo1, foo2))",
"WITH __tmp1 AS (SELECT * FROM x UNPIVOT(col FOR item IN (foo1, foo2))) SELECT * FROM __tmp1",
)
self.validate_identity(
"FROM x |> JOIN y on x.id = y.id |> UNPIVOT(col FOR item IN (foo1, foo2))",
"WITH __tmp1 AS (SELECT * FROM x UNPIVOT(col FOR item IN (foo1, foo2)) JOIN y ON x.id = y.id) SELECT * FROM __tmp1",
)

View file

@ -1449,3 +1449,14 @@ CROSS JOIN JSON_ARRAY_ELEMENTS(CAST(JSON_EXTRACT_PATH(tbox, 'boxes') AS JSON)) A
"clickhouse": "SELECT JSONExtractString(foo, '12')",
},
)
def test_udt(self):
def _validate_udt(sql: str):
self.validate_identity(sql).to.assert_is(exp.DataType)
_validate_udt("CAST(5 AS MyType)")
_validate_udt('CAST(5 AS "MyType")')
_validate_udt("CAST(5 AS MySchema.MyType)")
_validate_udt('CAST(5 AS "MySchema"."MyType")')
_validate_udt('CAST(5 AS MySchema."MyType")')
_validate_udt('CAST(5 AS "MyCatalog"."MySchema"."MyType")')

View file

@ -22,6 +22,9 @@ class TestSnowflake(Validator):
expr.selects[0].assert_is(exp.AggFunc)
self.assertEqual(expr.sql(dialect="snowflake"), "SELECT APPROX_TOP_K(C4, 3, 5) FROM t")
self.validate_identity("STRTOK_TO_ARRAY('a b c')")
self.validate_identity("STRTOK_TO_ARRAY('a.b.c', '.')")
self.validate_identity("GET(a, b)")
self.validate_identity("INSERT INTO test VALUES (x'48FAF43B0AFCEF9B63EE3A93EE2AC2')")
self.validate_identity("SELECT STAR(tbl, exclude := [foo])")
self.validate_identity("SELECT CAST([1, 2, 3] AS VECTOR(FLOAT, 3))")
@ -107,6 +110,10 @@ class TestSnowflake(Validator):
self.validate_identity(
"""SELECT TO_TIMESTAMP('2025-01-16T14:45:30.123+0500', 'yyyy-mm-DD"T"hh24:mi:ss.ff3TZHTZM')"""
)
self.validate_identity(
"GET(value, 'foo')::VARCHAR",
"CAST(GET(value, 'foo') AS VARCHAR)",
)
self.validate_identity(
"SELECT 1 put",
"SELECT 1 AS put",

View file

@ -247,6 +247,8 @@ TBLPROPERTIES (
"REFRESH TABLE t",
)
self.validate_identity("ALTER TABLE foo ADD PARTITION(event = 'click')")
self.validate_identity("ALTER TABLE foo ADD IF NOT EXISTS PARTITION(event = 'click')")
self.validate_identity("IF(cond, foo AS bar, bla AS baz)")
self.validate_identity("any_value(col, true)", "ANY_VALUE(col) IGNORE NULLS")
self.validate_identity("first(col, true)", "FIRST(col) IGNORE NULLS")

View file

@ -20,14 +20,18 @@ class TestSQLite(Validator):
self.validate_identity("SELECT (JULIANDAY('now') - 2440587.5) * 86400.0")
self.validate_identity("SELECT UNIXEPOCH('now', 'subsec')")
self.validate_identity("SELECT TIMEDIFF('now', '1809-02-12')")
self.validate_identity("SELECT * FROM GENERATE_SERIES(1, 5)")
self.validate_identity("SELECT INSTR(haystack, needle)")
self.validate_identity(
"SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[2]', '$[0]', '$[1]')",
)
self.validate_identity(
"""SELECT item AS "item", some AS "some" FROM data WHERE (item = 'value_1' COLLATE NOCASE) AND (some = 't' COLLATE NOCASE) ORDER BY item ASC LIMIT 1 OFFSET 0"""
)
self.validate_identity("SELECT * FROM GENERATE_SERIES(1, 5)")
self.validate_identity("SELECT INSTR(haystack, needle)")
self.validate_identity(
"ALTER TABLE t RENAME a TO b",
"ALTER TABLE t RENAME COLUMN a TO b",
)
self.validate_all("SELECT LIKE(y, x)", write={"sqlite": "SELECT x LIKE y"})
self.validate_all("SELECT GLOB('*y*', 'xyz')", write={"sqlite": "SELECT 'xyz' GLOB '*y*'"})

View file

@ -39,7 +39,7 @@ class TestTSQL(Validator):
self.validate_identity("CAST(x AS int) OR y", "CAST(x AS INTEGER) <> 0 OR y <> 0")
self.validate_identity("TRUNCATE TABLE t1 WITH (PARTITIONS(1, 2 TO 5, 10 TO 20, 84))")
self.validate_identity(
"SELECT TOP 10 s.RECORDID, n.c.value('(/*:FORM_ROOT/*:SOME_TAG)[1]', 'float') AS SOME_TAG_VALUE FROM source_table.dbo.source_data AS s(nolock) CROSS APPLY FormContent.nodes('/*:FORM_ROOT') AS N(C)"
"SELECT TOP 10 s.RECORDID, n.c.VALUE('(/*:FORM_ROOT/*:SOME_TAG)[1]', 'float') AS SOME_TAG_VALUE FROM source_table.dbo.source_data AS s(nolock) CROSS APPLY FormContent.nodes('/*:FORM_ROOT') AS N(C)"
)
self.validate_identity(
"CREATE CLUSTERED INDEX [IX_OfficeTagDetail_TagDetailID] ON [dbo].[OfficeTagDetail]([TagDetailID] ASC)"