Skip to content

Answer the value MEOS writes through an out-parameter - #26

Merged
estebanzimanyi merged 2 commits into
MobilityDB:mainfrom
estebanzimanyi:gen/bool-result-out-params
Sep 2, 2026
Merged

estebanzimanyi merged 2 commits into
MobilityDB:mainfrom
estebanzimanyi:gen/bool-result-out-params

Conversation

@estebanzimanyi

Copy link
Copy Markdown
Member

MEOS answers some values by writing them through an out-parameter and
returning whether the value exists at all — tbox_xmax(box, double *result),
floatset_value_n(set, n, double *result),
tfloat_value_at_timestamptz(temp, t, strict, double *result). The object
layer answers that as a nullable: the buffer is allocated for the call, and a
false return answers null while a true one answers what MEOS wrote.

The out-parameter never appears in the C# signature, so a caller cannot pass a
buffer of the wrong size or read one MEOS did not fill. The reader comes from
the pointee: double, bool, int, long, and a TimestampTz or DateADT
through the same conversion the rest of the layer uses. 35 accessors reach the
object layer that way — TBox.Xmin, TBox.TminInc, FloatSet.ValueN,
TsTzSet.ValueN, TFloat.ValueAtTimestamptz and their kin — 646 methods
against 611. The 19 whose out-parameter is a GSERIALIZED **, text **,
Cbuffer **, Npoint **, Pose ** or Jsonb ** name that pointee as their
reason, since the model gives those values no class.

Four tests read both answers: a float box answers its bounds and a box without
an x dimension answers null for them while still answering its time bounds, a
float set answers the value at an index and null past the end, and a temporal
float answers its value at a moment inside its span and null outside.

MEOS reads an array of its own values through a pointer to the first element
and a count — `tsequence_make`, `tsequenceset_make`, `temporal_merge_array`
and the trgeometry twin of each. The object layer takes that as one C# array:
the wrappers' pointers are gathered into an `IntPtr[]` and pinned across the
call. The pin lasts exactly that long because the array is the caller's
throughout — `tsequence_make_free` is the twin that takes ownership, and it
does so by calling `tsequence_make` and then `pfree_array` on the array it
passed, which is sound only if `tsequence_make` neither frees nor retains it.
Eight constructors reach the object layer that way, 611 methods against 607.

The length parameter never appears in the C# signature, so it cannot disagree
with the array. That also settles which parameter is an array at all: the
length is named `count`, while a parameter named `n` is the index of the `*_n`
accessors, whose pointer is the receiver and no array — reading `n` as a
length turns `trgeometry_instant_n(temp, n)` into a call passing the
receiver's own length.

Three tests: a sequence made of three instants reads back as the text of all
three, merging two sequences answers four instants across two sequences, and
an empty array reaches MEOS as the invalid argument it is.
MEOS answers some values by writing them through an out-parameter and
returning whether the value exists at all — `tbox_xmax(box, double *result)`,
`floatset_value_n(set, n, double *result)`,
`tfloat_value_at_timestamptz(temp, t, strict, double *result)`. The object
layer answers that as a nullable: the buffer is allocated for the call, and a
`false` return answers null while a `true` one answers what MEOS wrote.

The out-parameter never appears in the C# signature, so a caller cannot pass a
buffer of the wrong size or read one MEOS did not fill. The reader comes from
the pointee: `double`, `bool`, `int`, `long`, and a `TimestampTz` or `DateADT`
through the same conversion the rest of the layer uses. 35 accessors reach the
object layer that way — `TBox.Xmin`, `TBox.TminInc`, `FloatSet.ValueN`,
`TsTzSet.ValueN`, `TFloat.ValueAtTimestamptz` and their kin — 646 methods
against 611. The 19 whose out-parameter is a `GSERIALIZED **`, `text **`,
`Cbuffer **`, `Npoint **`, `Pose **` or `Jsonb **` name that pointee as their
reason, since the model gives those values no class.

Four tests read both answers: a float box answers its bounds and a box without
an x dimension answers null for them while still answering its time bounds, a
float set answers the value at an index and null past the end, and a temporal
float answers its value at a moment inside its span and null outside.
@estebanzimanyi
estebanzimanyi merged commit b151afb into MobilityDB:main Sep 2, 2026
1 check passed
@estebanzimanyi
estebanzimanyi deleted the gen/bool-result-out-params branch September 2, 2026 21:53
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.

1 participant