Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ All notable changes to this project are documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

## [Unreleased]

### Added

- Vertica dialect (`vertica`) across the Rust crate, FFI, Python, WASM, and
TypeScript SDK. Semantics follow the
[vertica-sqlglot-dialect](https://github.com/luisdelatorre012/vertica-sqlglot-dialect)
reference: 64-bit integer and double-precision type aliasing, `LONG VARCHAR`
/ `LONG VARBINARY`, `MINUS`, the `//`, `!`, `!!`, and `@` operators,
`LISTAGG ... USING PARAMETERS`, native `NVL2`/`DECODE`/`ZEROIFNULL`,
`TIMESTAMPADD`/`DATEDIFF`, and statement-start `GETDATE()`/`SYSDATE`, which
lower to `STATEMENT_TIMESTAMP()` for PostgreSQL. Vertica's type-dependent
NULL ordering is never assumed when it is the source and is made explicit
when it is the target. Vertica-only DDL (projections, segmentation),
`TIMESERIES`, `MATCH`, and partitioned `LIMIT ... OVER` are not yet modeled.

## [0.12.1] - 2026-09-21

### Added
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ test-rust-feature-gates:
cargo check -p polyglot-sql --no-default-features --features transpile,dialect-clickhouse,dialect-postgresql
cargo check -p polyglot-sql --no-default-features --features transpile,dialect-tsql
cargo check -p polyglot-sql --no-default-features --features transpile,dialect-fabric
cargo check -p polyglot-sql --no-default-features --features transpile,dialect-vertica
cargo check -p polyglot-sql --no-default-features --features dialect-snowflake
cargo check -p polyglot-sql --no-default-features --features generate,dialect-snowflake
cargo check -p polyglot-sql --no-default-features --features transpile,dialect-snowflake
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Release notes are tracked in [`CHANGELOG.md`](CHANGELOG.md).
| MySQL | Oracle | PostgreSQL | Presto | Redshift |
| RisingWave | SingleStore | Snowflake | Solr | Spark |
| SQLite | StarRocks | Tableau | Teradata | TiDB |
| Trino | TSQL | DataFusion | Generic SQL | |
| Trino | TSQL | Vertica | DataFusion | Generic SQL |

## Quick Start

Expand Down
3 changes: 2 additions & 1 deletion crates/polyglot-sql-ffi/src/dialects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use polyglot_sql::dialects::DialectType;
use std::os::raw::c_char;
use std::ptr;

const DIALECTS: [DialectType; 34] = [
const DIALECTS: [DialectType; 35] = [
DialectType::Generic,
DialectType::PostgreSQL,
DialectType::MySQL,
Expand Down Expand Up @@ -38,6 +38,7 @@ const DIALECTS: [DialectType; 34] = [
DialectType::Dremio,
DialectType::Exasol,
DialectType::DataFusion,
DialectType::Vertica,
];

/// Return supported dialect names as JSON.
Expand Down
2 changes: 1 addition & 1 deletion crates/polyglot-sql-ffi/tests/ffi_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2050,7 +2050,7 @@ fn test_dialect_list_and_count() {
let list: Vec<String> = serde_json::from_str(&json).expect("invalid dialect list json");
let count = polyglot_dialect_count();
assert_eq!(list.len() as i32, count);
assert_eq!(count, 34);
assert_eq!(count, 35);
let unique: BTreeSet<&str> = list.iter().map(String::as_str).collect();
assert_eq!(unique.len(), list.len());
assert!(list.iter().any(|d| d == "generic"));
Expand Down
2 changes: 1 addition & 1 deletion crates/polyglot-sql-python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ All functions are exported from `polyglot_sql`.

Current dialect names returned by `polyglot_sql.dialects()`:

`athena`, `bigquery`, `clickhouse`, `cockroachdb`, `datafusion`, `databricks`, `doris`, `dremio`, `drill`, `druid`, `duckdb`, `dune`, `exasol`, `fabric`, `generic`, `hive`, `materialize`, `mysql`, `oracle`, `postgres`, `presto`, `redshift`, `risingwave`, `singlestore`, `snowflake`, `solr`, `spark`, `sqlite`, `starrocks`, `tableau`, `teradata`, `tidb`, `trino`, `tsql`.
`athena`, `bigquery`, `clickhouse`, `cockroachdb`, `datafusion`, `databricks`, `doris`, `dremio`, `drill`, `druid`, `duckdb`, `dune`, `exasol`, `fabric`, `generic`, `hive`, `materialize`, `mysql`, `oracle`, `postgres`, `presto`, `redshift`, `risingwave`, `singlestore`, `snowflake`, `solr`, `spark`, `sqlite`, `starrocks`, `tableau`, `teradata`, `tidb`, `trino`, `tsql`, `vertica`.

## Error Handling

Expand Down
1 change: 1 addition & 0 deletions crates/polyglot-sql-python/src/dialects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const DIALECT_NAMES: &[&str] = &[
"tidb",
"trino",
"tsql",
"vertica",
];

#[pyfunction]
Expand Down
1 change: 1 addition & 0 deletions crates/polyglot-sql-python/tests/test_dialects.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"tidb",
"trino",
"tsql",
"vertica",
}


Expand Down
2 changes: 2 additions & 0 deletions crates/polyglot-sql-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ all-dialects = [
"dialect-druid", "dialect-solr", "dialect-tableau",
"dialect-dune", "dialect-fabric", "dialect-drill",
"dialect-dremio", "dialect-exasol", "dialect-datafusion",
"dialect-vertica",
]
dialect-postgresql = ["polyglot-sql/dialect-postgresql"]
dialect-mysql = ["polyglot-sql/dialect-mysql"]
Expand Down Expand Up @@ -108,6 +109,7 @@ dialect-drill = ["polyglot-sql/dialect-drill"]
dialect-dremio = ["polyglot-sql/dialect-dremio"]
dialect-exasol = ["polyglot-sql/dialect-exasol"]
dialect-datafusion = ["polyglot-sql/dialect-datafusion"]
dialect-vertica = ["polyglot-sql/dialect-vertica"]
function-catalog-clickhouse = [
"dialect-clickhouse",
"semantic",
Expand Down
5 changes: 4 additions & 1 deletion crates/polyglot-sql-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,8 @@ fn get_dialects_internal() -> Vec<&'static str> {
dialects.push("exasol");
#[cfg(feature = "dialect-datafusion")]
dialects.push("datafusion");
#[cfg(feature = "dialect-vertica")]
dialects.push("vertica");
dialects
}

Expand Down Expand Up @@ -2927,7 +2929,7 @@ mod tests {
let dialects: Vec<String> = serde_json::from_str(&result).unwrap();
let unique: std::collections::BTreeSet<&str> =
dialects.iter().map(String::as_str).collect();
assert_eq!(dialects.len(), 34);
assert_eq!(dialects.len(), 35);
assert_eq!(unique.len(), dialects.len());
assert!(unique.contains("generic"));
assert!(unique.contains("postgresql"));
Expand Down Expand Up @@ -3570,6 +3572,7 @@ mod tests {
"dremio",
"exasol",
"datafusion",
"vertica",
];

for dialect in dialects {
Expand Down
2 changes: 2 additions & 0 deletions crates/polyglot-sql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ all-dialects = [
"dialect-druid", "dialect-solr", "dialect-tableau",
"dialect-dune", "dialect-fabric", "dialect-drill",
"dialect-dremio", "dialect-exasol", "dialect-datafusion",
"dialect-vertica",
]
dialect-postgresql = []
dialect-mysql = []
Expand Down Expand Up @@ -82,6 +83,7 @@ dialect-drill = []
dialect-dremio = []
dialect-exasol = []
dialect-datafusion = []
dialect-vertica = []
function-catalog-clickhouse = [
"semantic",
"dep:polyglot-sql-function-catalogs",
Expand Down
2 changes: 1 addition & 1 deletion crates/polyglot-sql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ assert_eq!(err.line(), None);

## Supported Dialects

Athena, BigQuery, ClickHouse, CockroachDB, DataFusion, Databricks, Doris, Dremio, Drill, Druid, DuckDB, Dune, Exasol, Fabric, Generic SQL, Hive, Materialize, MySQL, Oracle, PostgreSQL, Presto, Redshift, RisingWave, SingleStore, Snowflake, Solr, Spark, SQLite, StarRocks, Tableau, Teradata, TiDB, Trino, TSQL
Athena, BigQuery, ClickHouse, CockroachDB, DataFusion, Databricks, Doris, Dremio, Drill, Druid, DuckDB, Dune, Exasol, Fabric, Generic SQL, Hive, Materialize, MySQL, Oracle, PostgreSQL, Presto, Redshift, RisingWave, SingleStore, Snowflake, Solr, Spark, SQLite, StarRocks, Tableau, Teradata, TiDB, Trino, TSQL, Vertica

## Feature Flags

Expand Down
2 changes: 2 additions & 0 deletions crates/polyglot-sql/src/dialects/duckdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ impl DialectImpl for DuckDBDialect {
this: f.this,
separator: f.separator,
on_overflow: None,
max_length: None,
order_by: f.order_by,
distinct: f.distinct,
filter: f.filter,
Expand All @@ -216,6 +217,7 @@ impl DialectImpl for DuckDBDialect {
this: f.this,
separator: f.separator,
on_overflow: None,
max_length: None,
order_by: f.order_by,
distinct: f.distinct,
filter: f.filter,
Expand Down
1 change: 1 addition & 0 deletions crates/polyglot-sql/src/dialects/exasol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ impl DialectImpl for ExasolDialect {
this: f.this,
separator: f.separator,
on_overflow: None,
max_length: None,
order_by: f.order_by,
distinct: f.distinct,
filter: f.filter,
Expand Down
19 changes: 19 additions & 0 deletions crates/polyglot-sql/src/dialects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ mod tidb;
mod trino;
#[cfg(any(feature = "dialect-tsql", feature = "dialect-fabric"))]
mod tsql;
#[cfg(feature = "dialect-vertica")]
mod vertica;

pub use generic::GenericDialect; // Always available

Expand Down Expand Up @@ -158,6 +160,8 @@ pub use tidb::TiDBDialect;
pub use trino::TrinoDialect;
#[cfg(feature = "dialect-tsql")]
pub use tsql::TSQLDialect;
#[cfg(feature = "dialect-vertica")]
pub use vertica::VerticaDialect;

use crate::error::Result;
#[cfg(feature = "transpile")]
Expand Down Expand Up @@ -274,6 +278,8 @@ pub enum DialectType {
Exasol,
/// Apache DataFusion -- Arrow-based query engine with modern SQL extensions.
DataFusion,
/// Vertica (OpenText Analytics Database) -- columnar MPP analytic database.
Vertica,
}

impl DialectType {
Expand Down Expand Up @@ -330,6 +336,7 @@ impl std::fmt::Display for DialectType {
DialectType::Dremio => write!(f, "dremio"),
DialectType::Exasol => write!(f, "exasol"),
DialectType::DataFusion => write!(f, "datafusion"),
DialectType::Vertica => write!(f, "vertica"),
}
}
}
Expand Down Expand Up @@ -373,6 +380,7 @@ impl std::str::FromStr for DialectType {
"dremio" => Ok(DialectType::Dremio),
"exasol" => Ok(DialectType::Exasol),
"datafusion" | "arrow-datafusion" | "arrow_datafusion" => Ok(DialectType::DataFusion),
"vertica" => Ok(DialectType::Vertica),
_ => Err(crate::error::Error::parse(
format!("Unknown dialect: {}", s),
0,
Expand Down Expand Up @@ -2387,6 +2395,7 @@ cached_dialect!(CACHED_DRILL, DrillDialect, "dialect-drill");
cached_dialect!(CACHED_DREMIO, DremioDialect, "dialect-dremio");
cached_dialect!(CACHED_EXASOL, ExasolDialect, "dialect-exasol");
cached_dialect!(CACHED_DATAFUSION, DataFusionDialect, "dialect-datafusion");
cached_dialect!(CACHED_VERTICA, VerticaDialect, "dialect-vertica");

fn configs_for_dialect_type(dt: DialectType) -> DialectConfigs {
/// Clone configs from a cached static and pair with a fresh transform closure.
Expand Down Expand Up @@ -2469,6 +2478,8 @@ fn configs_for_dialect_type(dt: DialectType) -> DialectConfigs {
DialectType::Exasol => from_cache!(CACHED_EXASOL, ExasolDialect),
#[cfg(feature = "dialect-datafusion")]
DialectType::DataFusion => from_cache!(CACHED_DATAFUSION, DataFusionDialect),
#[cfg(feature = "dialect-vertica")]
DialectType::Vertica => from_cache!(CACHED_VERTICA, VerticaDialect),
_ => from_cache!(CACHED_GENERIC, GenericDialect),
}
}
Expand Down Expand Up @@ -3211,6 +3222,7 @@ impl Dialect {
feature = "dialect-oracle",
feature = "dialect-clickhouse",
feature = "dialect-fabric",
feature = "dialect-vertica",
))]
use crate::transforms;

Expand Down Expand Up @@ -3380,6 +3392,13 @@ impl Dialect {
// DataFusion supports QUALIFY and semi/anti joins natively
#[cfg(feature = "dialect-datafusion")]
DialectType::DataFusion => Ok(expr),
// Vertica doesn't support QUALIFY or semi/anti join syntax
#[cfg(feature = "dialect-vertica")]
DialectType::Vertica => {
let expr = transforms::eliminate_qualify(expr)?;
let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
Ok(expr)
}
// Oracle doesn't support QUALIFY
#[cfg(feature = "dialect-oracle")]
DialectType::Oracle => {
Expand Down
3 changes: 3 additions & 0 deletions crates/polyglot-sql/src/dialects/normalization/aggregates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ pub(super) fn rewrite(
this: sa.this,
separator: sa.separator,
on_overflow: None,
max_length: None,
order_by: sa.order_by,
distinct: sa.distinct,
filter: None,
Expand Down Expand Up @@ -541,6 +542,7 @@ pub(super) fn rewrite(
this,
separator: Some(sep),
on_overflow: None,
max_length: None,
order_by: gc.order_by,
distinct: gc.distinct,
filter: gc.filter,
Expand Down Expand Up @@ -634,6 +636,7 @@ pub(super) fn rewrite(
this: gc.this,
separator: Some(sep),
on_overflow: None,
max_length: None,
order_by: gc.order_by,
distinct: gc.distinct,
filter: None,
Expand Down
20 changes: 17 additions & 3 deletions crates/polyglot-sql/src/dialects/normalization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod scalar;
mod statements;
pub(in crate::dialects) mod temporal;
mod types;
mod vertica;

#[derive(Debug, Clone, Copy)]
struct NormalizationContext {
Expand Down Expand Up @@ -86,6 +87,13 @@ pub(super) fn normalize(
let expr = statements::normalize_root(expr, &context);

transform_recursive(expr, &|e| {
let e = if matches!(source, DialectType::Vertica) && !matches!(target, DialectType::Vertica)
{
vertica::normalize_from_vertica(e, target)?
} else {
e
};

if matches!(source, DialectType::DataFusion) && matches!(target, DialectType::DuckDB) {
if let Expression::Function(ref function) = e {
if function.name.eq_ignore_ascii_case("NOW") && function.args.is_empty() {
Expand Down Expand Up @@ -2363,15 +2371,18 @@ pub(super) fn normalize(
| DialectType::Teradata
| DialectType::Spark
| DialectType::Databricks
| DialectType::Redshift => Action::None,
| DialectType::Redshift
| DialectType::Vertica => Action::None,
_ => Action::Scalar(scalar::Action::Nvl2Expand),
}
}
Expression::Decode(_) | Expression::DecodeCase(_) => {
// DECODE(a, b, c[, d, e[, ...]]) -> CASE WHEN with null-safe comparisons
// Keep as DECODE for Oracle/Snowflake
// Keep as DECODE for Oracle/Snowflake/Vertica
match target {
DialectType::Oracle | DialectType::Snowflake => Action::None,
DialectType::Oracle | DialectType::Snowflake | DialectType::Vertica => {
Action::None
}
_ => Action::Scalar(scalar::Action::DecodeSimplify),
}
}
Expand Down Expand Up @@ -2728,8 +2739,11 @@ pub(super) fn normalize(
| DialectType::StarRocks
| DialectType::Doris
);
// Vertica's implicit NULL placement depends on the sort key's data
// type (NULLS AUTO), so there is no source default to make explicit.
if o.nulls_first.is_none()
&& source != target
&& source != DialectType::Vertica
&& (target_supports_nulls || target_rewrites_nulls)
{
Action::Operators(operators::Action::NullsOrdering)
Expand Down
7 changes: 5 additions & 2 deletions crates/polyglot-sql/src/dialects/normalization/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,11 @@ pub(super) fn rewrite(
is_asc
};

// Only add explicit nulls ordering if source and target defaults differ
if source_nulls_first != target_nulls_first {
// Only add explicit nulls ordering if source and target defaults differ.
// Vertica's default is data-type dependent, so always make it explicit.
if source_nulls_first != target_nulls_first
|| matches!(target, DialectType::Vertica)
{
o.nulls_first = Some(source_nulls_first);
}
// If they match, leave nulls_first as None so the generator won't output it
Expand Down
Loading
Loading