You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Issue #134 requires every declared decimal(p,s) value to become a Tiberius Numeric at the declared scale. Data Spark's accepted schema contract permits decimal(38,38) (0 <= s <= p <= 38), but Tiberius 0.12.3 panics for that valid declaration:
thread panicked at tiberius-0.12.3/src/tds/numeric.rs:35:9:
assertion failed: scale < 38
The same assertion remains on the Tiberius upstream main branch as of 2026-09-02. Upstream PR tiberius-rs/tiberius#436 now proposes accepting scale 38, but its current patch leaves Numeric::precision() returning 39 for values with no integral digits at scale 38. The optional rust_decimal and bigdecimal conversions ultimately call the same constructor, so enabling either feature does not restore the complete scale-38 invariant.
This blocks #134. Silently narrowing the schema contract would conflict with ADR-0044, and treating the value as a write failure would conflict with ADR-0062's exhaustive two-sliver list. ADR-0069 already defines the applicable response ladder: use a pinned revision on a maintainer-controlled fork when this connector needs an upstream fix that has not been released.
Reproduction
Construct an Arrow Decimal128(38, 38) containing scaled value -1, then encode it with:
Numeric::new_with_scale(-1,38)
Tiberius 0.12.3 panics before a bulk row can be emitted. Merely changing the constructor assertion is incomplete: the current zero-integral-part precision calculation returns 1 + scale, which would describe the value as the invalid NUMERIC(39,38) when Tiberius emits parameter metadata without destination type context.
Decision
Preserve Data Spark's complete declared Decimal contract and fix Tiberius through the fork path anticipated by ADR-0069.
decimal(38,38) remains a valid Declared Type and maps to SQL Server DECIMAL(38,38) verbatim.
The Tiberius behavior is a dependency defect, not a Rejected Record condition or a third SQL Server representability sliver.
Base a public, maintainer-controlled fork on upstream tag v0.12.3 and carry one focused Numeric patch.
Correct the zero-integral-part precision invariant to max(scale, 1). Thus 0.05 is described as NUMERIC(2,2), and a scale-38 fractional value is described as NUMERIC(38,38). Preserve integral_digits + scale when integral digits exist.
Pin Data Spark to the fork with an immutable full commit SHA in Cargo.toml and Cargo.lock; do not track a branch.
Keep the fork as a patch carrier rather than continuously syncing upstream main. It carries its tests, but Data Spark does not maintain a separate fork CI system; every new revision must pass the required local/live verification before adoption.
Return to crates.io after an upstream release contains the complete fix and passes the same Data Spark probes.
Unsafe construction of Tiberius's private Numeric fields is not acceptable.
Upstream coordination
Start with a factual comment on tiberius-rs/tiberius#436 showing the precision-39 reproduction and the complete invariant. If its author or an upstream maintainer requests a split, open a focused upstream issue and PR. Record a public upstream trace before closing this issue, but do not wait for upstream merge or release.
This issue owns the dependency resolution: the fork patch and tests, immutable dependency revision, ADR updates, upstream trace, and a direct Data Spark dependency smoke test.
Issue #134 continues to own the production Dataset Schema-to-SQL-Server-row seam. Its row-encoding tests must include the focused Arrow Decimal128(38,38) scaled value -1 to Tiberius Numeric value -1, scale 38 regression. #134 remains blocked until this issue closes, then moves back to ready-for-agent.
Acceptance criteria
A maintainer-controlled fork based on upstream v0.12.3 contains a focused Numeric patch with no unrelated dependency or driver changes.
Fork unit tests cover scale 38 construction, corrected precision metadata, encode/decode, relevant positive/negative/zero boundaries, and continued rejection of scale 39.
A live Tiberius test round-trips a DECIMAL(38,38) value through SQL Server, including parameter metadata, without panic, rounding, or value change.
Data Spark pins the fork by full commit SHA, regenerates Cargo.lock, and has a direct dependency smoke test proving scaled value -1 at scale 38 is deterministic and reports precision 38.
ADR-0069 records the activated fork path, base and pinned revision, minimal patch, upstream trace, verification posture, and crates.io exit condition. ADR-0062 records that patched Tiberius preserves the decimal(38,38) exact-fit mapping and does not add a representability sliver. ADR-0044 and CONTEXT.md remain unchanged.
The upstream coordination trace described above is linked from this issue; upstream merge or release is not required.
Problem
Issue #134 requires every declared
decimal(p,s)value to become a TiberiusNumericat the declared scale. Data Spark's accepted schema contract permitsdecimal(38,38)(0 <= s <= p <= 38), but Tiberius 0.12.3 panics for that valid declaration:The same assertion remains on the Tiberius upstream
mainbranch as of 2026-09-02. Upstream PR tiberius-rs/tiberius#436 now proposes accepting scale 38, but its current patch leavesNumeric::precision()returning 39 for values with no integral digits at scale 38. The optionalrust_decimalandbigdecimalconversions ultimately call the same constructor, so enabling either feature does not restore the complete scale-38 invariant.This blocks #134. Silently narrowing the schema contract would conflict with ADR-0044, and treating the value as a write failure would conflict with ADR-0062's exhaustive two-sliver list. ADR-0069 already defines the applicable response ladder: use a pinned revision on a maintainer-controlled fork when this connector needs an upstream fix that has not been released.
Reproduction
Construct an Arrow
Decimal128(38, 38)containing scaled value-1, then encode it with:Tiberius 0.12.3 panics before a bulk row can be emitted. Merely changing the constructor assertion is incomplete: the current zero-integral-part precision calculation returns
1 + scale, which would describe the value as the invalidNUMERIC(39,38)when Tiberius emits parameter metadata without destination type context.Decision
Preserve Data Spark's complete declared Decimal contract and fix Tiberius through the fork path anticipated by ADR-0069.
decimal(38,38)remains a valid Declared Type and maps to SQL ServerDECIMAL(38,38)verbatim.v0.12.3and carry one focused Numeric patch.scale <= 38; continue rejecting scales above 38.max(scale, 1). Thus0.05is described asNUMERIC(2,2), and a scale-38 fractional value is described asNUMERIC(38,38). Preserveintegral_digits + scalewhen integral digits exist.Cargo.tomlandCargo.lock; do not track a branch.main. It carries its tests, but Data Spark does not maintain a separate fork CI system; every new revision must pass the required local/live verification before adoption.Unsafe construction of Tiberius's private
Numericfields is not acceptable.Upstream coordination
Start with a factual comment on tiberius-rs/tiberius#436 showing the precision-39 reproduction and the complete invariant. If its author or an upstream maintainer requests a split, open a focused upstream issue and PR. Record a public upstream trace before closing this issue, but do not wait for upstream merge or release.
Scope split with #134
This issue owns the dependency resolution: the fork patch and tests, immutable dependency revision, ADR updates, upstream trace, and a direct Data Spark dependency smoke test.
Issue #134 continues to own the production Dataset Schema-to-SQL-Server-row seam. Its row-encoding tests must include the focused Arrow
Decimal128(38,38)scaled value-1to TiberiusNumericvalue-1, scale38regression. #134 remains blocked until this issue closes, then moves back toready-for-agent.Acceptance criteria
v0.12.3contains a focused Numeric patch with no unrelated dependency or driver changes.DECIMAL(38,38)value through SQL Server, including parameter metadata, without panic, rounding, or value change.Cargo.lock, and has a direct dependency smoke test proving scaled value-1at scale 38 is deterministic and reports precision 38.decimal(38,38)exact-fit mapping and does not add a representability sliver. ADR-0044 andCONTEXT.mdremain unchanged.blockedtoready-for-agentwhen this issue completes.Out of scope
decimal(38,38).