mirror of
https://github.com/apache/superset.git
synced 2026-04-08 02:45:22 +00:00
434 lines
7.7 KiB
Python
434 lines
7.7 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import pytest
|
|
import sqlglot
|
|
|
|
from superset.sql.dialects.firebolt import Firebolt, FireboltOld
|
|
|
|
|
|
def test_not_sql() -> None: # pylint: disable=invalid-name
|
|
"""
|
|
Test the `not_sql` method in the generator.
|
|
"""
|
|
# use generic parser, since the Firebolt dialect will parenthesize
|
|
ast = sqlglot.parse_one("SELECT * FROM t WHERE NOT col IN (1, 2)")
|
|
|
|
# make sure generated SQL is parenthesized
|
|
assert (
|
|
Firebolt().generate(expression=ast, pretty=True)
|
|
== """
|
|
SELECT
|
|
*
|
|
FROM t
|
|
WHERE
|
|
NOT (col IN (1, 2))
|
|
""".strip()
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"sql, expected",
|
|
[
|
|
(
|
|
"SELECT price, quantity, price * quantity AS sales_amount FROM Sales",
|
|
"""
|
|
SELECT
|
|
price,
|
|
quantity,
|
|
price * quantity AS sales_amount
|
|
FROM Sales
|
|
""".strip(),
|
|
),
|
|
(
|
|
"SELECT ALL * FROM Sales",
|
|
"""
|
|
SELECT
|
|
*
|
|
FROM Sales
|
|
""".strip(),
|
|
),
|
|
(
|
|
"SELECT DISTINCT product FROM Sales",
|
|
"""
|
|
SELECT DISTINCT
|
|
product
|
|
FROM Sales
|
|
""".strip(),
|
|
),
|
|
(
|
|
"SELECT * FROM Sales, Products",
|
|
"""
|
|
SELECT
|
|
*
|
|
FROM Sales, Products
|
|
""".strip(),
|
|
),
|
|
],
|
|
)
|
|
def test_select_from(sql: str, expected: str) -> None:
|
|
"""
|
|
Test the `SELECT` statement in the old dialect.
|
|
"""
|
|
ast = sqlglot.parse_one(sql, FireboltOld)
|
|
assert FireboltOld().generate(expression=ast, pretty=True) == expected
|
|
|
|
|
|
def test_unnest() -> None:
|
|
"""
|
|
Test the `UNNEST` in the old dialect.
|
|
"""
|
|
ast = sqlglot.parse_one(
|
|
"""
|
|
SELECT
|
|
id,
|
|
tags
|
|
FROM visits
|
|
UNNEST(tags);
|
|
""",
|
|
FireboltOld,
|
|
)
|
|
|
|
assert (
|
|
FireboltOld().generate(expression=ast, pretty=True)
|
|
== """
|
|
SELECT
|
|
id,
|
|
tags
|
|
FROM visits UNNEST(tags)
|
|
""".strip()
|
|
)
|
|
|
|
|
|
def test_unnest_with_array() -> None:
|
|
"""
|
|
Test the `UNNEST` in the old dialect with array columns.
|
|
"""
|
|
ast = sqlglot.parse_one(
|
|
"""
|
|
SELECT
|
|
id,
|
|
a_keys,
|
|
a_vals
|
|
FROM
|
|
visits
|
|
UNNEST(agent_props_keys as a_keys,
|
|
agent_props_vals as a_vals)
|
|
|
|
""",
|
|
FireboltOld,
|
|
)
|
|
|
|
assert (
|
|
FireboltOld().generate(expression=ast, pretty=True)
|
|
== """
|
|
SELECT
|
|
id,
|
|
a_keys,
|
|
a_vals
|
|
FROM visits UNNEST(agent_props_keys AS a_keys, agent_props_vals AS a_vals)
|
|
""".strip()
|
|
)
|
|
|
|
|
|
def test_unnest_multiple() -> None:
|
|
"""
|
|
Test multiple `UNNEST` in the old dialect.
|
|
"""
|
|
ast = sqlglot.parse_one(
|
|
"""
|
|
SELECT
|
|
id,
|
|
a_keys,
|
|
a_vals
|
|
FROM
|
|
visits
|
|
UNNEST(agent_props_keys as a_keys)
|
|
UNNEST(agent_props_vals as a_vals)
|
|
""",
|
|
FireboltOld,
|
|
)
|
|
|
|
assert (
|
|
FireboltOld().generate(expression=ast, pretty=True)
|
|
== """
|
|
SELECT
|
|
id,
|
|
a_keys,
|
|
a_vals
|
|
FROM visits UNNEST(agent_props_keys AS a_keys) UNNEST(agent_props_vals AS a_vals)
|
|
""".strip()
|
|
)
|
|
|
|
|
|
def test_unnest_translating() -> None:
|
|
"""
|
|
Test translating the `UNNEST` from the old to the new dialect.
|
|
"""
|
|
ast = sqlglot.parse_one(
|
|
"""
|
|
SELECT
|
|
id,
|
|
tags
|
|
FROM visits
|
|
UNNEST(tags);
|
|
""",
|
|
FireboltOld,
|
|
)
|
|
|
|
assert (
|
|
Firebolt().generate(expression=ast, pretty=True)
|
|
== """
|
|
SELECT
|
|
id,
|
|
tags
|
|
FROM visits, UNNEST(tags)
|
|
""".strip()
|
|
)
|
|
|
|
|
|
def test_join_on() -> None:
|
|
"""
|
|
Test the `JOIN ... ON` syntax in the Firebolt dialect.
|
|
"""
|
|
ast = sqlglot.parse_one(
|
|
"""
|
|
SELECT
|
|
*
|
|
FROM
|
|
t1
|
|
JOIN
|
|
t2
|
|
ON t1.foo = t2.id;
|
|
""",
|
|
FireboltOld,
|
|
)
|
|
|
|
assert (
|
|
FireboltOld().generate(expression=ast, pretty=True)
|
|
== """
|
|
SELECT
|
|
*
|
|
FROM t1
|
|
JOIN t2
|
|
ON t1.foo = t2.id
|
|
""".strip()
|
|
)
|
|
|
|
|
|
def test_join_using() -> None:
|
|
"""
|
|
Test the `JOIN ... USING` syntax in the Firebolt dialect.
|
|
"""
|
|
ast = sqlglot.parse_one(
|
|
"""
|
|
SELECT
|
|
*
|
|
FROM
|
|
t1
|
|
JOIN
|
|
t2 USING (id, age);
|
|
""",
|
|
FireboltOld,
|
|
)
|
|
|
|
assert (
|
|
FireboltOld().generate(expression=ast, pretty=True)
|
|
== """
|
|
SELECT
|
|
*
|
|
FROM t1
|
|
JOIN t2
|
|
USING (id, age)
|
|
""".strip()
|
|
)
|
|
|
|
|
|
def test_cte() -> None:
|
|
"""
|
|
Test the `WITH` clause in the Firebolt dialect.
|
|
"""
|
|
ast = sqlglot.parse_one(
|
|
"""
|
|
WITH nl_subscribers AS (
|
|
SELECT
|
|
*
|
|
FROM
|
|
players
|
|
WHERE
|
|
issubscribedtonewsletter=TRUE
|
|
)
|
|
SELECT
|
|
nickname,
|
|
email
|
|
FROM
|
|
players
|
|
ORDER BY
|
|
nickname
|
|
""",
|
|
FireboltOld,
|
|
)
|
|
|
|
assert (
|
|
FireboltOld().generate(expression=ast, pretty=True)
|
|
== """
|
|
WITH nl_subscribers AS (
|
|
SELECT
|
|
*
|
|
FROM players
|
|
WHERE
|
|
issubscribedtonewsletter = TRUE
|
|
)
|
|
SELECT
|
|
nickname,
|
|
email
|
|
FROM players
|
|
ORDER BY
|
|
nickname
|
|
""".strip()
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"sql, expected",
|
|
[
|
|
(
|
|
"""
|
|
SELECT
|
|
*
|
|
FROM
|
|
num_test
|
|
INNER JOIN
|
|
num_test2
|
|
USING (
|
|
firstname,
|
|
score
|
|
);
|
|
""",
|
|
"""
|
|
SELECT
|
|
*
|
|
FROM num_test
|
|
INNER JOIN num_test2
|
|
USING (firstname, score)
|
|
""".strip(),
|
|
),
|
|
(
|
|
"""
|
|
SELECT
|
|
*
|
|
FROM
|
|
num_test
|
|
INNER JOIN
|
|
num_test2
|
|
ON num_test.firstname = num_test2.firstname
|
|
AND num_test.score = num_test2.score;
|
|
""",
|
|
"""
|
|
SELECT
|
|
*
|
|
FROM num_test
|
|
INNER JOIN num_test2
|
|
ON num_test.firstname = num_test2.firstname AND num_test.score = num_test2.score
|
|
""".strip(),
|
|
),
|
|
(
|
|
"""
|
|
SELECT
|
|
num_test.firstname,
|
|
num_test2.firstname
|
|
FROM num_test
|
|
LEFT OUTER JOIN
|
|
num_test2
|
|
USING (firstname);
|
|
""",
|
|
"""
|
|
SELECT
|
|
num_test.firstname,
|
|
num_test2.firstname
|
|
FROM num_test
|
|
LEFT OUTER JOIN num_test2
|
|
USING (firstname)
|
|
""".strip(),
|
|
),
|
|
(
|
|
"""
|
|
SELECT
|
|
num_test.firstname,
|
|
num_test2.firstname
|
|
FROM
|
|
num_test
|
|
RIGHT OUTER JOIN
|
|
num_test2
|
|
USING (firstname);
|
|
""",
|
|
"""
|
|
SELECT
|
|
num_test.firstname,
|
|
num_test2.firstname
|
|
FROM num_test
|
|
RIGHT OUTER JOIN num_test2
|
|
USING (firstname)
|
|
""".strip(),
|
|
),
|
|
(
|
|
"""
|
|
SELECT
|
|
num_test.firstname,
|
|
num_test2.firstname
|
|
FROM
|
|
num_test
|
|
FULL OUTER JOIN
|
|
num_test2
|
|
USING (firstname);
|
|
""",
|
|
"""
|
|
SELECT
|
|
num_test.firstname,
|
|
num_test2.firstname
|
|
FROM num_test
|
|
FULL OUTER JOIN num_test2
|
|
USING (firstname)
|
|
""".strip(),
|
|
),
|
|
(
|
|
"""
|
|
SELECT
|
|
crossjoin_test.letter,
|
|
crossjoin_test2.letter
|
|
FROM
|
|
crossjoin_test
|
|
CROSS JOIN
|
|
crossjoin_test2;
|
|
""",
|
|
"""
|
|
SELECT
|
|
crossjoin_test.letter,
|
|
crossjoin_test2.letter
|
|
FROM crossjoin_test
|
|
CROSS JOIN crossjoin_test2
|
|
""".strip(),
|
|
),
|
|
],
|
|
)
|
|
def test_join(sql: str, expected: str) -> None:
|
|
"""
|
|
Test different joins in the old dialect.
|
|
"""
|
|
ast = sqlglot.parse_one(sql, FireboltOld)
|
|
assert FireboltOld().generate(expression=ast, pretty=True) == expected
|