Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This catalog is the foundation for generating language bindings (Python, Java, R
- [Getting started](#getting-started)
- [Output format](#output-format)
- [Adding metadata](#adding-metadata)
- [Portable bare-name dialect](#portable-bare-name-dialect)

## How it works

Expand Down Expand Up @@ -83,3 +84,21 @@ A typical function entry looks like this:
## Adding metadata

Manual annotations (ownership rules, additional documentation, deprecation flags, etc.) live in `meta/meos-meta.json`. The merger applies them on top of the libclang-parsed structure when generating the final catalog.

## Portable bare-name dialect

`meta/portable-aliases.json` is the **single codegen source of truth**
(RFC #920) for the canonical portable bare-name dialect — the operator →
bare-name mapping that MobilityDB now registers natively (PR #1075). The
pipeline folds it into the catalog as `portableAliases` (with `byOperator`
/ `byBareName` lookups), so **every binding/engine generates the identical
bare names** and a user learns one reference and assumes the rest.

It is curated canonical data, kept verbatim (only bijective lookups are
derived — no C-symbol guessing; upstream aliases reuse each operator's own
backing function, equivalence by construction). The mapping is
type-agnostic and applies to **every** temporal type family —
`temporal`, `geo`, `cbuffer`, `npoint`, `pose`, `rgeo` are all in scope and
must not be excluded from any parity headline. `python tools/portable_parity.py`
audits it against the catalog — currently **29/29 = 100%** backed (verified,
no guessing). See [`docs/portable-aliases.md`](docs/portable-aliases.md).
85 changes: 85 additions & 0 deletions docs/portable-aliases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Portable bare-name dialect

`meta/portable-aliases.json` is the **single codegen source of truth**
(RFC #920) for the canonical portable bare-name dialect. The pipeline folds
it into `meos-idl.json` as `portableAliases`. Every binding/engine
(PyMEOS, JMEOS, MEOS.NET, MobilityDuck, MobilitySpark, …) generates the
**identical** bare names from this one mapping, so a user learns one
reference and can assume the rest behaves the same — no per-engine
exceptions to memorise.

## What it is

For one-query-three-platforms portability, a SQL operator must be callable
by a stable bare function name. The mapping is **operator → bare name**, by
family, and is **type-agnostic** (it applies to every temporal type):

| Family | Operator → bare name |
|---|---|
| Topology | `&&`→`overlaps` `@>`→`contains` `<@`→`contained` `-\|-`→`adjacent` |
| Time position | `<<#`→`before` `#>>`→`after` `&<#`→`overbefore` `#&>`→`overafter` |
| Space X | `<<`→`left` `>>`→`right` `&<`→`overleft` `&>`→`overright` |
| Space Y | `<<\|`→`below` `\|>>`→`above` `&<\|`→`overbelow` `\|&>`→`overabove` |
| Space Z | `<</`→`front` `/>>`→`back` `&</`→`overfront` `/&>`→`overback` |
| Temporal comparison | `#=`→`teq` `#<>`→`tne` `#<`→`tlt` `#<=`→`tle` `#>`→`tgt` `#>=`→`tge` |
| Distance | `<->`→`tdistance` `\|=\|`→`nearestApproachDistance` |
| Same | `~=`→`same` |

29 operator→bare-name pairs. Already-canonical (no aliasing needed):
`ever_*`/`always_*` (`?=`/`%=`), `eIntersects`, `atTime`, restriction and
spatial-relationship functions.

## In the catalog

`portableAliases` carries the verbatim `families`, plus derived bijective
lookups for codegen:

```json
"portableAliases": {
"byOperator": { "&&": "overlaps", "#=": "teq", "~=": "same", ... },
"byBareName": { "overlaps": "&&", "teq": "#=", "same": "~=", ... },
"bareNames": ["above", "adjacent", ..., "tdistance", "tge", "tne"],
"count": 29, "provenance": {...}, "scope": {...}, "notes": [...]
}
```

The mapping is preserved exactly — **no C-symbol guessing**. Upstream
generates each alias by reusing the operator's *own* backing C function
(equivalence by construction; mirror MobilityDB
`tools/portable_aliases/generate.py` + its 100%-coverage audit).

## Scope (the corrected rule)

`cbuffer`, `npoint`, `pose`, `rgeo` are **full user-facing temporal types
and are in scope** — covered like every other type. MobilityDB PR #1075
already aliases all six families (`temporal`, `geo`, `cbuffer`, `npoint`,
`pose`, `rgeo` — 1303 aliases). They must **not** be excluded from any
parity headline. An upstream/audit note that "defers" or "jointly excludes"
them is a known error being corrected: where another engine defers them,
that is incomplete work to close (a gap with a plan), never an accepted
end state.

`trgeometry` is the user-facing name; internal functions keep the
`trgeo_` prefix — do **not** normalize the internal prefix.

## Parity audit

`portable_parity.py` is the meos-api.json analogue of MobilityDB's
`tools/portable_aliases/generate.py --check`: it cross-references every
bare name against the catalog's function families (by the MEOS bare-name
prefix convention) and writes `output/meos-portable-parity.json`.

Live result: **29 / 29 = 100%** — every operator's bare name is backed in
the catalog (28 directly by prefix; `nearestApproachDistance` via the
*verified* `explicitBacking` entry `nad` — the `nad_*` family, 35
functions, confirmed present, not guessed). A bare name whose C family
prefix differs is resolved through `explicitBacking`, never false-flagged
as a gap and never silently dropped; `tests/test_portable_parity.py`
gates this (no bare name may be unclassified or regressed).

## Provenance

Discussion MobilityDB#861 · RFC #920
(`doc/rfc/sql-portability/README.md`, branch `rfc/sql-portability`) ·
native in MobilityDB#1075 · manual chapter MobilityDB#1078.
`tests/test_portable.py` validates the mapping and guards the scope rule.
193 changes: 193 additions & 0 deletions meta/portable-aliases.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
{
"_comment": "Canonical portable bare-name dialect \u2014 the single codegen source of truth (RFC #920). Every binding/engine generates the SAME bare names from this mapping so users learn one reference and assume the rest. Operators are SQL operator symbols; bareName is the portable function name. The mapping is type-agnostic: it applies to EVERY temporal type family.",
"provenance": {
"discussion": "MobilityDB#861",
"rfc": "MobilityDB RFC #920 (doc/rfc/sql-portability/README.md, branch rfc/sql-portability)",
"nativePR": "MobilityDB#1075 (1303 operator-overload aliases, each reusing the operator's own C symbol \u2014 identical by construction; CI-gated by tools/portable_aliases/generate.py --check)",
"manualChapter": "MobilityDB#1078"
},
"families": {
"topology": [
{
"operator": "&&",
"bareName": "overlaps"
},
{
"operator": "@>",
"bareName": "contains"
},
{
"operator": "<@",
"bareName": "contained"
},
{
"operator": "-|-",
"bareName": "adjacent"
}
],
"timePosition": [
{
"operator": "<<#",
"bareName": "before"
},
{
"operator": "#>>",
"bareName": "after"
},
{
"operator": "&<#",
"bareName": "overbefore"
},
{
"operator": "#&>",
"bareName": "overafter"
}
],
"spaceX": [
{
"operator": "<<",
"bareName": "left"
},
{
"operator": ">>",
"bareName": "right"
},
{
"operator": "&<",
"bareName": "overleft"
},
{
"operator": "&>",
"bareName": "overright"
}
],
"spaceY": [
{
"operator": "<<|",
"bareName": "below"
},
{
"operator": "|>>",
"bareName": "above"
},
{
"operator": "&<|",
"bareName": "overbelow"
},
{
"operator": "|&>",
"bareName": "overabove"
}
],
"spaceZ": [
{
"operator": "<</",
"bareName": "front"
},
{
"operator": "/>>",
"bareName": "back"
},
{
"operator": "&</",
"bareName": "overfront"
},
{
"operator": "/&>",
"bareName": "overback"
}
],
"temporalComparison": [
{
"operator": "#=",
"bareName": "teq"
},
{
"operator": "#<>",
"bareName": "tne"
},
{
"operator": "#<",
"bareName": "tlt"
},
{
"operator": "#<=",
"bareName": "tle"
},
{
"operator": "#>",
"bareName": "tgt"
},
{
"operator": "#>=",
"bareName": "tge"
}
],
"distance": [
{
"operator": "<->",
"bareName": "tdistance"
},
{
"operator": "|=|",
"bareName": "nearestApproachDistance"
}
],
"same": [
{
"operator": "~=",
"bareName": "same"
}
]
},
"alreadyCanonical": [
{
"kind": "family",
"family": "ever",
"operators": [
"?="
],
"pattern": "ever_*"
},
{
"kind": "family",
"family": "always",
"operators": [
"%="
],
"pattern": "always_*"
},
{
"kind": "functions",
"functions": [
"eIntersects",
"atTime",
"restriction functions",
"spatial-relationship functions"
]
}
],
"_explicitBackingComment": "Bare names whose MEOS C family prefix differs from the bare name itself. Verified against the catalog (not guessed): `nearestApproachDistance` is backed by the `nad_*` family (35 functions). Lets the parity audit resolve 100% honestly instead of false-flagging a real, present family.",
"explicitBacking": {
"nearestApproachDistance": [
"nad"
]
},
"scope": {
"inScopeTypeFamilies": [
"temporal",
"geo",
"cbuffer",
"npoint",
"pose",
"rgeo"
],
"note": "cbuffer / npoint / pose / rgeo are FULL user-facing temporal types and ARE in scope \u2014 covered like every other type. PR #1075 already aliases all six families (1303 aliases). They must NOT be excluded from any parity headline; an upstream/audit note that 'defers' or 'jointly excludes' them is a known error being corrected \u2014 where another engine defers them, that is incomplete work to close (a gap with a plan), never an accepted exclusion.",
"deferralIsError": true
},
"notes": [
"Generate aliases by reusing each operator's own backing C function (equivalence by construction), never by reimplementing; mirror MobilityDB tools/portable_aliases/generate.py + its 100%-coverage audit.",
"User-facing API uses the full name `trgeometry`; internal functions keep the `trgeo_` prefix \u2014 do NOT normalize the internal prefix.",
"Goal: 100% parity ecosystem-wide \u2014 every operator has its bare name on every engine, no gaps, no headline exclusions."
]
}
Loading