Merging upstream version 26.28.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
893214206a
commit
c79efa667c
96 changed files with 58442 additions and 56422 deletions
|
@ -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"')
|
||||
|
|
|
@ -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)",
|
||||
},
|
||||
)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 */",
|
||||
|
|
380
tests/dialects/test_pipe_syntax.py
Normal file
380
tests/dialects/test_pipe_syntax.py
Normal 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",
|
||||
)
|
|
@ -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")')
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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*'"})
|
||||
|
|
|
@ -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)"
|
||||
|
|
4
tests/fixtures/identity.sql
vendored
4
tests/fixtures/identity.sql
vendored
|
@ -890,4 +890,6 @@ CAST(x AS UINT128)
|
|||
CAST(x AS UINT256)
|
||||
SELECT export
|
||||
SELECT ARG_MAX(DISTINCT selected_col, filtered_col) FROM table
|
||||
SELECT ARG_MIN(DISTINCT selected_col, filtered_col) FROM table
|
||||
SELECT ARG_MIN(DISTINCT selected_col, filtered_col) FROM table
|
||||
a.b.c.D()
|
||||
a.b.c.d.e.f.G()
|
||||
|
|
|
@ -1003,3 +1003,9 @@ class TestParser(unittest.TestCase):
|
|||
|
||||
table_meta = ast.args["from"].this.this.meta
|
||||
self.assertEqual(sql[table_meta["start"] : table_meta["end"] + 1], '"test_table_a"')
|
||||
|
||||
def test_qualified_function(self):
|
||||
sql = "a.b.c.d.e.f.g.foo()"
|
||||
ast = parse_one(sql)
|
||||
assert not any(isinstance(n, exp.Column) for n in ast.walk())
|
||||
assert len(list(ast.find_all(exp.Dot))) == 7
|
||||
|
|
|
@ -17,7 +17,8 @@ class TestTransforms(unittest.TestCase):
|
|||
def validate(self, transform, sql, target, dialect=None):
|
||||
with self.subTest(f"{dialect} - {sql}"):
|
||||
self.assertEqual(
|
||||
parse_one(sql, dialect=dialect).transform(transform).sql(dialect=dialect), target
|
||||
parse_one(sql, dialect=dialect).transform(transform).sql(dialect=dialect),
|
||||
target,
|
||||
)
|
||||
|
||||
def test_unalias_group(self):
|
||||
|
@ -274,6 +275,42 @@ class TestTransforms(unittest.TestCase):
|
|||
== "SELECT a.id FROM a LEFT JOIN b ON a.id = b.id AND b.d = const"
|
||||
)
|
||||
|
||||
# validate parens
|
||||
self.validate(
|
||||
eliminate_join_marks,
|
||||
"select t1.a, t2.b from t1, t2 where (1 = 1) and (t1.id = t2.id1 (+))",
|
||||
"SELECT t1.a, t2.b FROM t1 LEFT JOIN t2 ON t1.id = t2.id1 WHERE (1 = 1)",
|
||||
dialect,
|
||||
)
|
||||
|
||||
# validate a CASE
|
||||
self.validate(
|
||||
eliminate_join_marks,
|
||||
"select t1.a, t2.b from t1, t2 where t1.id = case when t2.id (+) = 'n/a' then null else t2.id (+) end",
|
||||
"SELECT t1.a, t2.b FROM t1 LEFT JOIN t2 ON t1.id = CASE WHEN t2.id = 'n/a' THEN NULL ELSE t2.id END",
|
||||
dialect,
|
||||
)
|
||||
|
||||
# validate OR
|
||||
self.validate(
|
||||
eliminate_join_marks,
|
||||
"select t1.a, t2.b from t1, t2 where t1.id = t2.id1 (+) or t1.id = t2.id2 (+)",
|
||||
"SELECT t1.a, t2.b FROM t1 LEFT JOIN t2 ON t1.id = t2.id1 OR t1.id = t2.id2",
|
||||
dialect,
|
||||
)
|
||||
|
||||
# validate knockout
|
||||
script = """
|
||||
SELECT c.customer_name,
|
||||
(SELECT MAX(o.order_date)
|
||||
FROM orders o
|
||||
WHERE o.customer_id(+) = c.customer_id) AS latest_order_date
|
||||
FROM customers c
|
||||
"""
|
||||
self.assertRaises(
|
||||
AssertionError, eliminate_join_marks, parse_one(script, dialect=dialect)
|
||||
)
|
||||
|
||||
def test_eliminate_window_clause(self):
|
||||
self.validate(
|
||||
eliminate_window_clause,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue