Skip to content

Derive the catalog of a stable release line - #199

Merged
estebanzimanyi merged 7 commits into
MobilityDB:masterfrom
estebanzimanyi:catalog/derive-release-line
Oct 21, 2026
Merged

estebanzimanyi merged 7 commits into
MobilityDB:masterfrom
estebanzimanyi:catalog/derive-release-line

Conversation

@estebanzimanyi

Copy link
Copy Markdown
Member

Read the families of a release line from its family options

A MobilityDB tree without the if(ALL) foreach(_family ...) list -- a release line
older than that list, stable-1.3 -- states each family as an option of its own,
option(CBUFFER or, for a family needing another one, CMAKE_DEPENDENT_OPTION(RGEO.
read_all_families reads those options, keeping each whose meos/src/ directory
holds the family's sources. A tree with the list reads the list, and a tree with
neither raises FamiliesUnavailable.

Witness. Deriving a catalog from MobilityDB stable-1.3, as PyMEOS-CFFI's refresh recipe
does at its MDB_REF=stable-1.3, raises "carries no if(ALL) foreach(_family ...)
list", so no binding pinned to the 1.3 line can derive its catalog.

Measured. On stable-1.3 bda9e5bac7 the reader answers CBUFFER, NPOINT, POSE, RGEO, the
four families with a source directory; on master it answers the families of the list,
identical to the reader without the change. Two family tests are new: a stable-1.3
shape reads its four family options, the dependent one among them, and leaves MEOS and
GEOS out, and options without a source directory raise.

Why. The families of a tree are what the tree states, and a release line states them
as options; the source directory a family lives in is what separates a family option
from MEOS or GEOS, read from the tree rather than restated as a list.

Read the relation tables of a release line through the one catalog reader

A MobilityDB tree older than the type-indexed MEOS_RELTYPE_CATALOG -- stable-1.3 --
states each relation as a table of {outer, inner} pairs headed by the relation's two
names, /* settype basetype */, and spells the parameter of a membership predicate
meosType. catalog_rows reads those tables into the entries the type-indexed array
gives, (T_INTSET, {settype_basetype: T_INT4}), ordered by MEOS_TYPE_NAMES, which
lists every type in MeosType order there, and typerelations states the parameter
spelling once, MEOSTYPE_PARAM. TypeFacts reads its container relations through
catalog_rows, the object model and the type scope read their predicates through
MEOSTYPE_PARAM, and the temporal-type registry reads its rows from the catalog with
its block comments kept, since a pair table names its relation in its header comment.

Witness. Deriving stable-1.3 bda9e5bac7 refuses 77 functions as of an underivable
type scope, reads no temporal_type predicate in meos_catalog.c, and finds no base
type for any temporal type.

Measured. Master's catalog is byte-identical with and without the change. New tests:
the pair tables resolve to the registry the relation array gives, the temporal role in
MeosType order although the table lists tgeometry first; TypeFacts reads the same
containers and predicates from either catalog shape; the temporal-type registry gives
each type its base from pair tables, with no bounding box, which those tables do not
state. Each fails on the reader without the change.

Why. meos_catalog.c is read in one place, typerelations, so a catalog shape is learned
once and every reader of the relations follows it; the private relation readers of the
type scope and the predicate spelling of the object model each held a second copy of
the shape, which is how one of them read stable-1.3 and the others did not.

Read the linear predicate under the name its release line gives it

The temporal-type registry decides each class by a predicate of meos_catalog.c, and
CLASSES names each predicate under every name a release line gives it, the current one
first: the linear one is temptype_supports_linear, and temptype_continuous on
stable-1.3. defined_name takes the first name the catalog defines, and a predicate
defined under none of its names raises, naming the current one.

Witness. Deriving stable-1.3 raises "no definition of temptype_supports_linear()".

Measured. Master's catalog is byte-identical with and without the change. A new test
reads the same registry from a catalog naming the predicate temptype_continuous, and a
catalog naming it otherwise raises.

Why. stable-1.3's temptype_continuous admits the types master's
temptype_supports_linear admits, and master's own note on the predicate says why the
name changed: every MEOS temporal type is continuous in having a value at every
instant of its domain, and the predicate states the subset interpolated linearly.

Leave out of the object model the leaves of the types a release line lacks

meta/object-model.json models every temporal type MEOS has on master. release_nodes
keeps the nodes of the model the release line of meos_catalog.c has: a leaf whose type
MEOS_TYPE_NAMES does not list is a type that line lacks, tjsonb and tbigint on
stable-1.3, and is no class of it. A leaf whose type the line lists but does not relate
still raises in derive_membership, and a catalog whose type names do not parse keeps
every node, so that the derivation reports the leaf it cannot relate.

Witness. Deriving stable-1.3 raises "TJsonb models T_TJSONB, which the relation
catalog gives no base type".

Measured. Master's catalog is byte-identical with and without the change. New tests: a
leaf of a type the line does not list is dropped while one it lists but does not relate
raises, and a catalog without MEOS_TYPE_NAMES keeps its nodes.

Why. A type MEOS gained after a release is not a disagreement between that release's
catalog and the model, which is what the refusal exists for; the type names of the
catalog say which types the line has.

Read the position names in the spelling of their release line

attach_position_names reads the SQL name of each position and topological operator by
class, the class being the name less its stem. A release line spells the names one
way throughout: master's , spanLeft, or the _ of a release
before the class names, span_left and temporal_left on stable-1.3. A name in neither
form raises, and so does a name in the other form than the catalog's other names.

Witness. Deriving stable-1.3 raises "adjacent_span_bigint has @sqlop -|- and @sqlfn
span_adjacent, which is not Adjacent"; stable-1.3 creates span_adjacent 40 times
and temporal_left 60 times, its released SQL.

Measured. Master's catalog is byte-identical with and without the change. New tests:
the stable-1.3 spelling gives the class less _, temporal among them, and a name in
the other spelling than the rest raises in either direction. A master name such as
temporal_left among the names raises, as the existing test requires.

Why. The class names of #2717 and #2930 came after the 1.3 release, so the 1.3 names
are its surface, not tags to correct; reading one spelling per catalog keeps the
refusal of a name no release states.

Read only the SQL and the wrappers of the families the headers carry

A libmeos built without a family installs no public header of it: the stable-1.3
default build, the one PyMEOS-CFFI and its wheels build, installs meos_npoint.h and not
meos_cbuffer.h, meos_pose.h or meos_rgeo.h. unbuilt_families names the families whose
header the checkout has and the parsed tree lacks, and built_files lists the files
under a tree less those inside the directory of such a family, mobilitydb/sql/cbuffer
or mobilitydb/src/pose. Every reader of mobilitydb/sql and mobilitydb/src -- the SQL
signatures, the compositions and their casts, the aggregates, the index searches, the
alternative names and the bound arguments -- lists its files through built_files. The
source headers and a build of every family leave no family out, and a family fronted
by no header of its own is never left out.

Witness. Deriving stable-1.3 from its default build refuses twelve compositions of
the cbuffer and pose families, nearestApproachDistance(stbox, tcbuffer) among them,
each reaching a signature whose C function the headers do not declare.

Measured. Master's catalog is byte-identical with and without the change. New tests: a
build without cbuffer leaves out its SQL and keeps the rest, the source headers leave
out nothing, and families fronted by no header are never left out.

Why. A catalog states the library it is derived from, so the SQL it reads is the SQL
of the families that library has; reading the SQL of a family the headers do not carry
attaches signatures to functions no binding can call.

Compose a call through a plain forward, and not through a body that is no composition

A composition reaches the C function of each call through a C-backed signature or
through the composition of the SQL function it calls. A call can also reach a body that
is no composition of its own. A plain forward binds literals and converts nothing,
translate(t, x, y, z) forwarding to affine on stable-1.3; a body calling it composes
through it, as through a composition. A body that is no composition is a program
outside the form, stable-1.3's rotate over cos and -sin, a body over a function
MobilityDB does not declare, or a forward stating no call of its C function, affine,
whose wrapper packs twelve floats into one AFFINE argument; a body calling it is no
composition either, as one calling the function directly is not.

Witness. Deriving stable-1.3 refuses rotateZ(tgeompoint, float8),
translate(tgeompoint, float8, float8) and their tgeometry twins: each reaches a body
the resolver read as no composition and then reported as resolving to nothing.

Measured. Master's catalog is byte-identical with and without the change. New tests:
a call of a program and a call of a PostGIS forward are no composition, a call of a
forward stating no C call is none, and a call of a plain forward reaches its C function
with the literal it binds. Each fails on the resolver without the change. With the
families of the headers it is built with and the stable-1.3 tag corrections that
accompany it in MobilityDB, deriving stable-1.3 completes: 2397 functions.

Why. Whether a body is a composition is a property of that body, and a call reaching
it inherits it; a refusal there reported as a missing step a body the resolver had
already classified.

A MobilityDB tree without the `if(ALL) foreach(_family ...)` list -- a release line
older than that list, stable-1.3 -- states each family as an option of its own,
`option(CBUFFER` or, for a family needing another one, `CMAKE_DEPENDENT_OPTION(RGEO`.
read_all_families reads those options, keeping each whose meos/src/<family> directory
holds the family's sources. A tree with the list reads the list, and a tree with
neither raises FamiliesUnavailable.

Witness. Deriving a catalog from MobilityDB stable-1.3, as PyMEOS-CFFI's refresh recipe
does at its MDB_REF=stable-1.3, raises "carries no `if(ALL) foreach(_family ...)`
list", so no binding pinned to the 1.3 line can derive its catalog.

Measured. On stable-1.3 bda9e5bac7 the reader answers CBUFFER, NPOINT, POSE, RGEO, the
four families with a source directory; on master it answers the families of the list,
identical to the reader without the change. Two family tests are new: a stable-1.3
shape reads its four family options, the dependent one among them, and leaves MEOS and
GEOS out, and options without a source directory raise.

Why. The families of a tree are what the tree states, and a release line states them
as options; the source directory a family lives in is what separates a family option
from MEOS or GEOS, read from the tree rather than restated as a list.
…ader

A MobilityDB tree older than the type-indexed MEOS_RELTYPE_CATALOG -- stable-1.3 --
states each relation as a table of {outer, inner} pairs headed by the relation's two
names, `/* settype basetype */`, and spells the parameter of a membership predicate
`meosType`. catalog_rows reads those tables into the entries the type-indexed array
gives, `(T_INTSET, {settype_basetype: T_INT4})`, ordered by MEOS_TYPE_NAMES, which
lists every type in MeosType order there, and typerelations states the parameter
spelling once, MEOSTYPE_PARAM. TypeFacts reads its container relations through
catalog_rows, the object model and the type scope read their predicates through
MEOSTYPE_PARAM, and the temporal-type registry reads its rows from the catalog with
its block comments kept, since a pair table names its relation in its header comment.

Witness. Deriving stable-1.3 bda9e5bac7 refuses 77 functions as of an underivable
type scope, reads no `temporal_type` predicate in meos_catalog.c, and finds no base
type for any temporal type.

Measured. Master's catalog is byte-identical with and without the change. New tests:
the pair tables resolve to the registry the relation array gives, the temporal role in
MeosType order although the table lists tgeometry first; TypeFacts reads the same
containers and predicates from either catalog shape; the temporal-type registry gives
each type its base from pair tables, with no bounding box, which those tables do not
state. Each fails on the reader without the change.

Why. meos_catalog.c is read in one place, typerelations, so a catalog shape is learned
once and every reader of the relations follows it; the private relation readers of the
type scope and the predicate spelling of the object model each held a second copy of
the shape, which is how one of them read stable-1.3 and the others did not.
The temporal-type registry decides each class by a predicate of meos_catalog.c, and
CLASSES names each predicate under every name a release line gives it, the current one
first: the linear one is temptype_supports_linear, and temptype_continuous on
stable-1.3. defined_name takes the first name the catalog defines, and a predicate
defined under none of its names raises, naming the current one.

Witness. Deriving stable-1.3 raises "no definition of temptype_supports_linear()".

Measured. Master's catalog is byte-identical with and without the change. A new test
reads the same registry from a catalog naming the predicate temptype_continuous, and a
catalog naming it otherwise raises.

Why. stable-1.3's temptype_continuous admits the types master's
temptype_supports_linear admits, and master's own note on the predicate says why the
name changed: every MEOS temporal type is continuous in having a value at every
instant of its domain, and the predicate states the subset interpolated linearly.
…lacks

meta/object-model.json models every temporal type MEOS has on master. release_nodes
keeps the nodes of the model the release line of meos_catalog.c has: a leaf whose type
MEOS_TYPE_NAMES does not list is a type that line lacks, tjsonb and tbigint on
stable-1.3, and is no class of it. A leaf whose type the line lists but does not relate
still raises in derive_membership, and a catalog whose type names do not parse keeps
every node, so that the derivation reports the leaf it cannot relate.

Witness. Deriving stable-1.3 raises "TJsonb models T_TJSONB, which the relation
catalog gives no base type".

Measured. Master's catalog is byte-identical with and without the change. New tests: a
leaf of a type the line does not list is dropped while one it lists but does not relate
raises, and a catalog without MEOS_TYPE_NAMES keeps its nodes.

Why. A type MEOS gained after a release is not a disagreement between that release's
catalog and the model, which is what the refusal exists for; the type names of the
catalog say which types the line has.
attach_position_names reads the SQL name of each position and topological operator by
class, the class being the name less its stem. A release line spells the names one
way throughout: master's <class><Stem>, spanLeft, or the <class>_<stem> of a release
before the class names, span_left and temporal_left on stable-1.3. A name in neither
form raises, and so does a name in the other form than the catalog's other names.

Witness. Deriving stable-1.3 raises "adjacent_span_bigint has @sqlop -|- and @sqlfn
span_adjacent, which is not <class>Adjacent"; stable-1.3 creates span_adjacent 40 times
and temporal_left 60 times, its released SQL.

Measured. Master's catalog is byte-identical with and without the change. New tests:
the stable-1.3 spelling gives the class less _<stem>, temporal among them, and a name in
the other spelling than the rest raises in either direction. A master name such as
temporal_left among the <class><Stem> names raises, as the existing test requires.

Why. The class names of #2717 and #2930 came after the 1.3 release, so the 1.3 names
are its surface, not tags to correct; reading one spelling per catalog keeps the
refusal of a name no release states.
A libmeos built without a family installs no public header of it: the stable-1.3
default build, the one PyMEOS-CFFI and its wheels build, installs meos_npoint.h and not
meos_cbuffer.h, meos_pose.h or meos_rgeo.h. unbuilt_families names the families whose
header the checkout has and the parsed tree lacks, and built_files lists the files
under a tree less those inside the directory of such a family, mobilitydb/sql/cbuffer
or mobilitydb/src/pose. Every reader of mobilitydb/sql and mobilitydb/src -- the SQL
signatures, the compositions and their casts, the aggregates, the index searches, the
alternative names and the bound arguments -- lists its files through built_files. The
source headers and a build of every family leave no family out, and a family fronted
by no header of its own is never left out.

Witness. Deriving stable-1.3 from its default build refuses twelve compositions of
the cbuffer and pose families, nearestApproachDistance(stbox, tcbuffer) among them,
each reaching a signature whose C function the headers do not declare.

Measured. Master's catalog is byte-identical with and without the change. New tests: a
build without cbuffer leaves out its SQL and keeps the rest, the source headers leave
out nothing, and families fronted by no header are never left out.

Why. A catalog states the library it is derived from, so the SQL it reads is the SQL
of the families that library has; reading the SQL of a family the headers do not carry
attaches signatures to functions no binding can call.
…s no composition

A composition reaches the C function of each call through a C-backed signature or
through the composition of the SQL function it calls. A call can also reach a body that
is no composition of its own. A plain forward binds literals and converts nothing,
translate(t, x, y, z) forwarding to affine on stable-1.3; a body calling it composes
through it, as through a composition. A body that is no composition is a program
outside the form, stable-1.3's rotate over cos and -sin, a body over a function
MobilityDB does not declare, or a forward stating no call of its C function, affine,
whose wrapper packs twelve floats into one AFFINE argument; a body calling it is no
composition either, as one calling the function directly is not.

Witness. Deriving stable-1.3 refuses rotateZ(tgeompoint, float8),
translate(tgeompoint, float8, float8) and their tgeometry twins: each reaches a body
the resolver read as no composition and then reported as resolving to nothing.

Measured. Master's catalog is byte-identical with and without the change. New tests:
a call of a program and a call of a PostGIS forward are no composition, a call of a
forward stating no C call is none, and a call of a plain forward reaches its C function
with the literal it binds. Each fails on the resolver without the change. With the
families of the headers it is built with and the stable-1.3 tag corrections that
accompany it in MobilityDB, deriving stable-1.3 completes: 2397 functions.

Why. Whether a body is a composition is a property of that body, and a call reaching
it inherits it; a refusal there reported as a missing step a body the resolver had
already classified.
@estebanzimanyi
estebanzimanyi merged commit 07b0b4e into MobilityDB:master Oct 21, 2026
3 checks passed
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