Skip to content

v0.8.1 — Arrow transport for typed exports; DECIMAL and warning fixes

Latest

Choose a tag to compare

@ralfbecher ralfbecher released this 25 Jul 22:16
52c2f75

Patch release on top of v0.8.0. Anyone using exports: with parquet or arrow should upgrade — 0.8.0 wrote DECIMAL columns with the wrong type.

Fixed — DECIMAL landed in Parquet as string

OBSL delivers governed DECIMAL cells in raw JSON as exact decimal strings rather than floats (so precision past float64's ~15-16 digits survives the wire) and reports the column as decimal(18, 2). The 0.8.0 exporter only special-cased datetime / binary, so those columns fell through to inference and were written as text — every money measure got the wrong Parquet schema.

Values were never lost or corrupted: the strings are exact, and re-running after upgrading rewrites the files with the right types. Reports, TSV exports, and run logs were unaffected.

Fixed — a query carrying a warning failed the run

OBSL returns structured warnings — {code, severity, message, path, hint, context} — on execute, compile, and model-load, while the runner declared warnings: list[str]. Pydantic rejected the whole response, so the query was recorded as failed and the report never rendered.

This one is not a 0.8.0 regression: StructuredWarning has been in OBSL since 2.2, so warning-carrying queries have been failing across every earlier runner release. Warnings now flatten to "code: message (hint: …)" in the run log and plain strings still parse.

Added — typed exports read OBSL's Arrow transport

Parquet and Arrow targets now request ?format=arrow and decode OBSL's result frame:

[u32 big-endian json_len][JSON envelope utf-8][gzip'd Arrow IPC stream]

The server's table is written through untouched — real decimal128 / timestamp / int64, no JSON round trip and no client-side inference. The JSON envelope is a full ExecuteResult minus rows, so the run log is unchanged.

A deployment that ignores the parameter answers JSON; that's detected by content type and handled with the inference path in the same request (no retry), which is why the DECIMAL fix above still applies there. That fallback yields double where the transport gives exact decimal128.

Compatibility

No spec changes — every 0.8.0 spec runs unmodified. The OBSL pin is unchanged: 0.8.x ↔ OBSL 2.23.x. The Arrow transport needs OBSL >= 2.21, comfortably inside the supported line.

Verified: ruff, ruff format, mypy, pytest on 3.12 and 3.14 (127 passed, 1 skipped); end-to-end against a stub speaking the real frame writes Revenue: decimal128(18, 2) with exact values and parses a structured warning from the same envelope.

Full changes: v0.8.0...v0.8.1