Skip to content

PG->Fabric (T-SQL): round(x) single-argument emitted as ROUND(x) — missing mandatory length argument #307

Description

@NivasSA

PG->Fabric (T-SQL): round(x) single-argument emitted as ROUND(x) — missing mandatory length argument (sibling of #227 / #253)

Description

Transpiling PostgreSQL → Fabric (and TSQL) with TranspileOptions::strict(),
PostgreSQL's single-argument round(x) is emitted as T-SQL ROUND(x):
SELECT round(f1) FROM t emits SELECT ROUND(f1) FROM t.

T-SQL's ROUND requires a length argument
(ROUND(numeric_expression, length [, function])), so Fabric rejects it:
Sql Error 189 (Class 15 State 1): The round function requires 2 to 3 arguments.

This is a sibling of the strict() fail-fast class
#227 /
#253: strict() returns Ok(...) with
invalid SQL. The asymmetry is the giveaway — in the same run, strict() correctly
emits a 2-argument ROUND(..., 0) for round(x, 0), but the 1-argument overload drops to
invalid ROUND(x).

Root cause (pointer)

The round translation handles the 2-argument PG overload (emitting ROUND(expr, n)) but
the 1-argument overload is emitted as ROUND(expr) without supplying the default length
0 that T-SQL requires. Behavioral localization: round(x, 0)
ROUND(CAST(x AS DECIMAL(38,10)), 0) (correct); round(x)ROUND(x) (invalid).

Affected constructs

  • PostgreSQL single-argument round(double precision) and round(numeric).
  • More generally: PG built-ins whose T-SQL counterpart has a mandatory argument that the
    arg-count-preserving translation omits.

Repro

polyglot-sql 0.5.15, features transpile, dialect-postgresql, dialect-tsql, dialect-fabric:

# Cargo.toml
[dependencies]
polyglot-sql = { version = "0.5.15", default-features = false, features = [
    "transpile", "dialect-postgresql", "dialect-tsql", "dialect-fabric",
] }
use polyglot_sql::{Dialect, DialectType, TranspileOptions};

fn main() {
    let pg = Dialect::get(DialectType::PostgreSQL);

    // --- Flagged: strict() returns Ok(...) with invalid SQL (target = Fabric) ---
    let out = pg
        .transpile_with("SELECT f1, round(f1) AS round_f1 FROM float8_tbl",
            DialectType::Fabric, TranspileOptions::strict())
        .unwrap();
    println!("{out:?}");
    // actual: ["SELECT f1, ROUND(f1) AS round_f1 FROM float8_tbl"]
    //         → Fabric Sql Error 189: The round function requires 2 to 3 arguments.

    // --- Contrast: the 2-arg form already translates correctly (same run) ---
    let ok = pg
        .transpile_with("SELECT round(f1::numeric, 0) AS r FROM float8_tbl",
            DialectType::Fabric, TranspileOptions::strict())
        .unwrap();
    println!("{ok:?}");
    // actual: ["SELECT ROUND(CAST(f1 AS DECIMAL(38, 10)), 0) AS r FROM float8_tbl"]
}

Expected

round(x) should translate to ROUND(x, 0) — a valid target form exists, so the correct
fix is a REWRITE. Failing that, strict() should return Err rather than emit a ROUND
call Fabric rejects.

Notes

  • Reproduced on polyglot-sql 0.5.15; transpiler output captured directly from transpile_with.
  • Not affected: the 2-argument round(x, n) form (already correct).
  • The same generator underlies the Fabric and TSQL targets.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions