# 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