polyglot-sql 0.5.15

SQL parsing, validating, formatting, and dialect translation library
Documentation
use polyglot_sql::{Dialect, DialectType, TranspileOptions};

fn pg_to_target(sql: &str, target: DialectType) -> String {
    Dialect::get(DialectType::PostgreSQL)
        .transpile_with(sql, target, TranspileOptions::strict())
        .unwrap_or_else(|err| panic!("transpile failed for {sql:?} to {target:?}: {err}"))
        .into_iter()
        .next()
        .expect("expected one generated statement")
}

#[test]
fn distinct_order_by_asc_nulls_last_uses_valid_wrapper_for_tsql_and_fabric() {
    let expected = "SELECT v FROM (SELECT DISTINCT v, CASE WHEN v IS NULL THEN 1 ELSE 0 END AS _polyglot_order_null_0, v AS _polyglot_order_key_0 FROM t) AS _polyglot_distinct_order ORDER BY _polyglot_order_null_0, _polyglot_order_key_0";

    for target in [DialectType::TSQL, DialectType::Fabric] {
        assert_eq!(
            pg_to_target("SELECT DISTINCT v FROM t ORDER BY v", target),
            expected,
            "failed for target {target:?}"
        );
    }
}

#[test]
fn distinct_order_by_desc_nulls_first_uses_valid_wrapper_for_tsql_and_fabric() {
    let expected = "SELECT v FROM (SELECT DISTINCT v, CASE WHEN v IS NULL THEN 1 ELSE 0 END AS _polyglot_order_null_0, v AS _polyglot_order_key_0 FROM t) AS _polyglot_distinct_order ORDER BY _polyglot_order_null_0 DESC, _polyglot_order_key_0 DESC";

    for target in [DialectType::TSQL, DialectType::Fabric] {
        assert_eq!(
            pg_to_target("SELECT DISTINCT v FROM t ORDER BY v DESC", target),
            expected,
            "failed for target {target:?}"
        );
    }
}

#[test]
fn distinct_order_by_alias_resolves_to_selected_expression() {
    let expected = "SELECT x FROM (SELECT DISTINCT v AS x, CASE WHEN v IS NULL THEN 1 ELSE 0 END AS _polyglot_order_null_0, v AS _polyglot_order_key_0 FROM t) AS _polyglot_distinct_order ORDER BY _polyglot_order_null_0, _polyglot_order_key_0";

    for target in [DialectType::TSQL, DialectType::Fabric] {
        assert_eq!(
            pg_to_target("SELECT DISTINCT v AS x FROM t ORDER BY x", target),
            expected,
            "failed for target {target:?}"
        );
    }
}

#[test]
fn distinct_order_by_target_default_null_ordering_does_not_wrap() {
    for target in [DialectType::TSQL, DialectType::Fabric] {
        assert_eq!(
            pg_to_target("SELECT DISTINCT v FROM t ORDER BY v NULLS FIRST", target),
            "SELECT DISTINCT v FROM t ORDER BY v",
            "failed for target {target:?}"
        );
    }
}

#[test]
fn non_distinct_order_by_keeps_existing_tsql_null_ordering_emulation() {
    let expected = "SELECT v FROM t ORDER BY CASE WHEN v IS NULL THEN 1 ELSE 0 END, v";

    for target in [DialectType::TSQL, DialectType::Fabric] {
        assert_eq!(
            pg_to_target("SELECT v FROM t ORDER BY v", target),
            expected,
            "failed for target {target:?}"
        );
    }
}

#[test]
fn strict_mode_rejects_distinct_order_by_unselected_expression() {
    for target in [DialectType::TSQL, DialectType::Fabric] {
        let err = Dialect::get(DialectType::PostgreSQL)
            .transpile_with(
                "SELECT DISTINCT v FROM t ORDER BY LOWER(v)",
                target,
                TranspileOptions::strict(),
            )
            .expect_err("strict mode should reject unselected emulated ORDER BY expression");

        assert!(
            err.to_string()
                .contains("SELECT DISTINCT with emulated NULL ordering"),
            "unexpected error for {target:?}: {err}"
        );
    }
}