Skip to content

PG->Fabric (T-SQL): @ (absolute value) operator emitted verbatim -> @col parsed as a variable #306

Description

@NivasSA

PG->Fabric (T-SQL): @ (absolute value) operator emitted verbatim -> @col parsed as a variable (sibling of #287 / #296 / #300)

Description

Transpiling PostgreSQL → Fabric (and TSQL) with TranspileOptions::strict(), the
PostgreSQL prefix @ operator (absolute value) is passed through verbatim:
SELECT f1, @ f1 AS abs_f1 FROM t emits SELECT f1, @f1 AS abs_f1 FROM t.

In T-SQL @f1 denotes a scalar variable, so Fabric rejects the statement at runtime:
Sql Error 137 (Class 15 State 2): Must declare the scalar variable "@f1".

This is a sibling of the operator-verbatim issues
#287 (->),
#296 (~),
#300 (#), and 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 ABS(f1) for the function abs(f1), but passes the @ operator through
untranslated.

Root cause (pointer)

The PG→Fabric mapping translates the named function abs() to ABS(...) but has no entry
for the @ operator alias of absolute value, so it is rendered verbatim. Behavioral
localization: abs(f1)ABS(f1) (correct); @ f1@f1 (verbatim).

Affected constructs

  • PostgreSQL prefix @ (absolute value) operator on any numeric type (float4, float8,
    numeric, int).
  • More generally: PG operator aliases of built-in functions that have a valid T-SQL
    function form but no operator→function mapping.

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, @ f1 AS abs_f1 FROM float4_tbl",
            DialectType::Fabric, TranspileOptions::strict())
        .unwrap();
    println!("{out:?}");
    // actual: ["SELECT f1, @f1 AS abs_f1 FROM float4_tbl"]
    //         → Fabric Sql Error 137: Must declare the scalar variable "@f1".

    // --- Contrast: the FUNCTION form already translates correctly (same run) ---
    let ok = pg
        .transpile_with("SELECT abs(f1) AS a FROM float4_tbl",
            DialectType::Fabric, TranspileOptions::strict())
        .unwrap();
    println!("{ok:?}");
    // actual: ["SELECT ABS(f1) AS a FROM float4_tbl"]
}

Expected

@ x should translate to the T-SQL built-in ABS(x) — a valid target form exists, so the
correct fix is a REWRITE, not rejection. Failing that, strict() should return Err so
callers can fall back instead of emitting a @name variable reference.

Notes

  • Reproduced on polyglot-sql 0.5.15; transpiler output captured directly from transpile_with.
  • Type-agnostic (the abs operator applies to every numeric type); observed on float4 and float8.
  • 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