Skip to content

Generate the box (TBox/STBox) scalar accessors - #228

Open
estebanzimanyi wants to merge 4 commits into
mainfrom
feat/duck-box-scalar-accessors
Open

Generate the box (TBox/STBox) scalar accessors#228
estebanzimanyi wants to merge 4 commits into
mainfrom
feat/duck-box-scalar-accessors

Conversation

@estebanzimanyi

Copy link
Copy Markdown
Member

Generates the TBox/STBox scalar accessors from the MEOS catalog instead of
hand-registering them, extending the generator's box coverage from operators
and box-returning ops to the scalar-return surface.

Generator

The single-typed box descriptors (scope=None, one concrete accessor) now
reach the unary and binary scalar-return paths:

  • the unary and bsc shape gates are relaxed so a scope-less box passes;
  • a new (Box,Box)->scalar case (gated on the box single marker) emits the
    box comparison and metric accessors;
  • box registration arms register over the single concrete accessor instead of
    the span name-scope loop.

Emitted surface

hasX / hasZ / hasT / isGeodetic, SRID, volume, getSpace,
area / perimeter (explicit spheroid form), stbox_hash / tbox_hash
(native-unsigned UINTEGER), stbox_hash_extended / tbox_hash_extended
(UBIGINT), cmp, and nearestApproachDistance / |=| for stbox.

Generate-then-retire

Removes the hand registrations the generated surface now covers identically:
hasX/hasZ/hasT/isGeodetic/volume/getSpace on stbox and
hasX/hasT/tbox_hash/tbox_hash_extended on tbox. The generated tbox
hash uses the faithful native-unsigned return, matching the temporal/span/set
hashes. area/perimeter (1-arg defaulted form) and stbox_cmp/tbox_cmp
stay as-is — the generated surface adds the explicit 2-arg and the canonical
bare cmp alongside them, so no SQL surface is removed.

Known gap

nearestApproachDistance(tbox, tbox) is intentionally not emitted: the only
public backings each assert a single span basetype and error on the other,
while the generic implementation is internal, so no single public overload is
faithful. The generator detects this base-type collapse and logs the skipped
surface rather than emitting a lossy or type-restricted binding; closing it
belongs at the source (exporting the generic).

Tests

Adds test/sql/parity/051_stbox_scalar_accessors.test covering SRID, volume,
hash, hash_extended, cmp, nearestApproachDistance, and |=|. The committed
src/generated file is the generator's output for the current catalog.

nhungoc1508 and others added 4 commits July 22, 2026 21:40
…ical

Regenerates the generated UDF surface from MobilityDB master (which brings in
the generic temporal_hash surface). The MEOS-API catalog now renders the uint32
canonical type as `unsigned int` (it was `uint32_t`); key the scalar type maps
on it so the *_hash functions keep registering instead of being dropped.

uint32 hashes map to DuckDB's native `UINTEGER`, not a signed `INTEGER` — a hash
>= 2**31 is out of range for INT32 and DuckDB range-checks the cast rather than
bit-reinterpreting the way PostgreSQL/C do; DuckDB has real unsigned SQL types,
so `UINTEGER` is the faithful representation.
Generates the extended (64-bit, seeded) hash `temporal_hash_extended(<ttype>,
UBIGINT)` for every temporal family, inherited through Temporal<T> — the Duck
side of the MEOS temporal_hash_extended surface.

The uint64 hash and its seed use DuckDB's native `UBIGINT`, not a signed BIGINT:
a MEOS hash fills the full unsigned range (e.g. temporal_hash_extended(tint
'1@2000-01-01', 0) = 11445401048662056440, which is > 2**63 and does not fit in
a signed BIGINT), and DuckDB range-checks the cast rather than bit-reinterpreting
the way PostgreSQL/C do.

Generator: key uint64_t to UBIGINT in the scalar arg/return maps (SCALAR,
SCALAR_ARG, SCALAR_RET_CPP), and check the Tcell cell-id branch before the
generic scalar branch in ret_type and shape_emittable so a uint64 cell id keeps
its cell type instead of collapsing to UBIGINT.
Extends the seeded 64-bit hash to the value containers whose plain hash already
generates: span_hash_extended / spanset_hash_extended / set_hash_extended, as
`hash_extended(<span|set>, UBIGINT)` and `spanset_hash_extended(spanset, UBIGINT)`,
all returning UBIGINT (the native unsigned type, per the temporal case).

Generator: add a (container, by-value scalar) -> by-value scalar shape ("bsc")
to shape_span and shape_set, mirroring the existing unary u_scalar hash, plus
the matching registration arms so the seed registers as its scalar type
(UBIGINT) rather than a second container operand.

(The box hashes tbox/stbox and cbuffer are a separate gap — their PLAIN hash
does not generate yet either, so their extended form is out of scope here.)
Relax the box shape gates so the single-typed TBox/STBox descriptors reach
the unary and binary scalar-return paths, and add a (Box,Box)->scalar case.
The box scalar accessors are now generated from the catalog: hasX/hasZ/hasT/
isGeodetic, SRID, volume, getSpace, area/perimeter, the native-unsigned
hash/hashExtended (UINTEGER/UBIGINT), cmp, and nearestApproachDistance.

Retire the hand registrations the generated surface now covers identically
(hasX/hasZ/hasT/isGeodetic/volume/getSpace on stbox; hasX/hasT/tbox_hash/
tbox_hash_extended on tbox). The generated tbox hash uses the faithful
native-unsigned UINTEGER/UBIGINT return, matching temporal/span/set hashes.

Skip the base-type-collapsed nearestApproachDistance(tbox,tbox): its only
public backings each assert a single span basetype and error on the other,
while the generic implementation is internal, so no single public overload
is faithful. The generator detects the collapse and logs the skipped
surface; it is left to a source export fix rather than a lossy or
type-restricted binding.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants