mirror of
https://github.com/apache/superset.git
synced 2026-05-10 10:25:51 +00:00
198 lines
6.3 KiB
Python
198 lines
6.3 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.
|
|
|
|
from sqlglot import parse_one
|
|
|
|
from superset.sql.dialects.vertica import Vertica
|
|
|
|
|
|
def test_last_day_round_trips_natively() -> None:
|
|
"""
|
|
Vertica supports LAST_DAY natively, unlike Postgres which rewrites it into
|
|
DATE_TRUNC + INTERVAL arithmetic.
|
|
"""
|
|
sql = "SELECT LAST_DAY(DATE('2026-01-15'))"
|
|
|
|
ast = parse_one(sql, dialect=Vertica)
|
|
regenerated = ast.sql(dialect=Vertica)
|
|
|
|
assert regenerated == "SELECT LAST_DAY(DATE('2026-01-15'))"
|
|
|
|
|
|
def test_last_day_not_rewritten_like_postgres() -> None:
|
|
"""
|
|
Postgres rewrites LAST_DAY because it lacks the function. Verify Vertica
|
|
does not inherit that rewrite.
|
|
"""
|
|
sql = "SELECT LAST_DAY(DATE('2026-01-15'))"
|
|
|
|
postgres_sql = parse_one(sql, dialect="postgres").sql(dialect="postgres")
|
|
vertica_sql = parse_one(sql, dialect=Vertica).sql(dialect=Vertica)
|
|
|
|
assert "DATE_TRUNC" in postgres_sql
|
|
assert "DATE_TRUNC" not in vertica_sql
|
|
assert "LAST_DAY" in vertica_sql
|
|
|
|
|
|
def test_translate_from_postgres_to_vertica() -> None:
|
|
"""
|
|
A LAST_DAY expression parsed from Postgres should generate the native
|
|
Vertica form, not the Postgres rewrite.
|
|
"""
|
|
sql = "SELECT LAST_DAY(DATE('2026-01-15'))"
|
|
|
|
ast = parse_one(sql, dialect="postgres")
|
|
regenerated = ast.sql(dialect=Vertica)
|
|
|
|
assert regenerated == "SELECT LAST_DAY(DATE('2026-01-15'))"
|
|
|
|
|
|
def test_postgres_features_still_work() -> None:
|
|
"""
|
|
Vertica inherits from Postgres, so unrelated Postgres syntax should still
|
|
parse and regenerate correctly.
|
|
"""
|
|
sql = "SELECT a::INT, b || c FROM t WHERE d ~ '^foo'"
|
|
|
|
ast = parse_one(sql, dialect=Vertica)
|
|
regenerated = ast.sql(dialect=Vertica)
|
|
|
|
assert regenerated == "SELECT CAST(a AS INT), b || c FROM t WHERE d ~ '^foo'"
|
|
|
|
|
|
def test_datediff_round_trips_natively() -> None:
|
|
"""
|
|
Vertica's DATEDIFF is ``DATEDIFF(unit, start, end)``. Postgres rewrites it
|
|
into ``EXTRACT(epoch ...) / N`` arithmetic.
|
|
"""
|
|
sql = "SELECT DATEDIFF('day', a, b) FROM t"
|
|
|
|
ast = parse_one(sql, dialect=Vertica)
|
|
regenerated = ast.sql(dialect=Vertica)
|
|
|
|
assert regenerated == "SELECT DATEDIFF(DAY, a, b) FROM t"
|
|
|
|
|
|
def test_datediff_month_round_trips_natively() -> None:
|
|
"""
|
|
The MONTH unit exercises Postgres's ``AGE()`` rewrite branch, which Vertica
|
|
does not need.
|
|
"""
|
|
sql = "SELECT DATEDIFF('month', a, b) FROM t"
|
|
|
|
ast = parse_one(sql, dialect=Vertica)
|
|
regenerated = ast.sql(dialect=Vertica)
|
|
|
|
assert regenerated == "SELECT DATEDIFF(MONTH, a, b) FROM t"
|
|
|
|
|
|
def test_datediff_not_rewritten_like_postgres() -> None:
|
|
"""
|
|
Postgres rewrites DATEDIFF; Vertica should keep the native call.
|
|
"""
|
|
sql = "SELECT DATEDIFF('day', a, b) FROM t"
|
|
|
|
postgres_sql = parse_one(sql, dialect="postgres").sql(dialect="postgres")
|
|
vertica_sql = parse_one(sql, dialect=Vertica).sql(dialect=Vertica)
|
|
|
|
assert "DATEDIFF" not in postgres_sql
|
|
assert "DATEDIFF(DAY" in vertica_sql
|
|
|
|
|
|
def test_median_round_trips_natively() -> None:
|
|
"""
|
|
Vertica supports MEDIAN as a native analytic/aggregate function. Postgres
|
|
rewrites it into PERCENTILE_CONT + WITHIN GROUP.
|
|
"""
|
|
sql = "SELECT MEDIAN(x) FROM t"
|
|
|
|
ast = parse_one(sql, dialect=Vertica)
|
|
regenerated = ast.sql(dialect=Vertica)
|
|
|
|
assert regenerated == "SELECT MEDIAN(x) FROM t"
|
|
|
|
|
|
def test_median_not_rewritten_like_postgres() -> None:
|
|
sql = "SELECT MEDIAN(x) FROM t"
|
|
|
|
postgres_sql = parse_one(sql, dialect="postgres").sql(dialect="postgres")
|
|
vertica_sql = parse_one(sql, dialect=Vertica).sql(dialect=Vertica)
|
|
|
|
assert "PERCENTILE_CONT" in postgres_sql
|
|
assert "PERCENTILE_CONT" not in vertica_sql
|
|
assert "MEDIAN" in vertica_sql
|
|
|
|
|
|
def test_nvl2_round_trips_natively() -> None:
|
|
"""
|
|
Vertica supports NVL2 natively; Postgres rewrites it into a CASE.
|
|
"""
|
|
sql = "SELECT NVL2(a, b, c) FROM t"
|
|
|
|
ast = parse_one(sql, dialect=Vertica)
|
|
regenerated = ast.sql(dialect=Vertica)
|
|
|
|
assert regenerated == "SELECT NVL2(a, b, c) FROM t"
|
|
|
|
|
|
def test_nvl2_not_rewritten_like_postgres() -> None:
|
|
sql = "SELECT NVL2(a, b, c) FROM t"
|
|
|
|
postgres_sql = parse_one(sql, dialect="postgres").sql(dialect="postgres")
|
|
vertica_sql = parse_one(sql, dialect=Vertica).sql(dialect=Vertica)
|
|
|
|
assert "CASE" in postgres_sql
|
|
assert "CASE" not in vertica_sql
|
|
assert "NVL2" in vertica_sql
|
|
|
|
|
|
def test_interval_uses_sql_standard_form() -> None:
|
|
"""
|
|
Vertica miscomputes month/year arithmetic when given the Postgres-style
|
|
single-string interval (``INTERVAL '2 MONTH'``). The SQL-standard form
|
|
``INTERVAL '2' MONTH`` is correct on all Vertica versions.
|
|
See https://forum.vertica.com/discussion/229329/.
|
|
"""
|
|
sql = "SELECT date_col + INTERVAL '2 MONTH' FROM t"
|
|
|
|
ast = parse_one(sql, dialect=Vertica)
|
|
regenerated = ast.sql(dialect=Vertica)
|
|
|
|
assert regenerated == "SELECT date_col + INTERVAL '2' MONTH FROM t"
|
|
|
|
|
|
def test_interval_year_uses_sql_standard_form() -> None:
|
|
sql = "SELECT date_col + INTERVAL '1 YEAR' FROM t"
|
|
|
|
ast = parse_one(sql, dialect=Vertica)
|
|
regenerated = ast.sql(dialect=Vertica)
|
|
|
|
assert regenerated == "SELECT date_col + INTERVAL '1' YEAR FROM t"
|
|
|
|
|
|
def test_interval_diverges_from_postgres() -> None:
|
|
"""
|
|
Postgres emits the combined-string form; Vertica should not.
|
|
"""
|
|
sql = "SELECT date_col + INTERVAL '2 MONTH' FROM t"
|
|
|
|
postgres_sql = parse_one(sql, dialect="postgres").sql(dialect="postgres")
|
|
vertica_sql = parse_one(sql, dialect=Vertica).sql(dialect=Vertica)
|
|
|
|
assert "INTERVAL '2 MONTH'" in postgres_sql
|
|
assert "INTERVAL '2' MONTH" in vertica_sql
|