Skip to content
Merged
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
413 changes: 212 additions & 201 deletions src/generated/generated_temporal_udfs_0.cpp

Large diffs are not rendered by default.

647 changes: 335 additions & 312 deletions src/generated/generated_temporal_udfs_1.cpp

Large diffs are not rendered by default.

608 changes: 322 additions & 286 deletions src/generated/generated_temporal_udfs_2.cpp

Large diffs are not rendered by default.

398 changes: 206 additions & 192 deletions src/generated/generated_temporal_udfs_3.cpp

Large diffs are not rendered by default.

566 changes: 290 additions & 276 deletions src/generated/generated_temporal_udfs_4.cpp

Large diffs are not rendered by default.

532 changes: 247 additions & 285 deletions src/generated/generated_temporal_udfs_5.cpp

Large diffs are not rendered by default.

672 changes: 319 additions & 353 deletions src/generated/generated_temporal_udfs_6.cpp

Large diffs are not rendered by default.

485 changes: 236 additions & 249 deletions src/generated/generated_temporal_udfs_7.cpp

Large diffs are not rendered by default.

6 changes: 0 additions & 6 deletions src/geo/tgeogpoint_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,8 +588,6 @@ void TGeogpointOps::RegisterScalarFunctions(ExtensionLoader &loader) {

// Centroid / convexHull / traversedArea — produce a non-temporal
// geometry summary of the trajectory.
loader.RegisterFunction(ScalarFunction(
"centroid", {TGEOM}, TGEOM, TgeoCentroidExec));
loader.RegisterFunction(ScalarFunction(
"convexHull", {TGEOM}, GEOM, TgeoConvexHullExec));
loader.RegisterFunction(ScalarFunction(
Expand Down Expand Up @@ -750,10 +748,6 @@ void TGeogpointOps::RegisterScalarFunctions(ExtensionLoader &loader) {
};
};

loader.RegisterFunction(ScalarFunction(
"minDistSimplify", {TGEOM, DBL}, TGEOM,
simplify_double_exec_factory(temporal_simplify_min_dist)));

loader.RegisterFunction(ScalarFunction(
"minTimeDeltaSimplify", {TGEOM, LogicalType::INTERVAL}, TGEOM,
[](DataChunk &args, ExpressionState &, Vector &result) {
Expand Down
6 changes: 0 additions & 6 deletions src/geo/tgeography_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,6 @@ void TGeographyOps::RegisterScalarFunctions(ExtensionLoader &loader) {

// Centroid / convexHull / traversedArea — produce a non-temporal
// geometry summary of the trajectory.
loader.RegisterFunction(ScalarFunction(
"centroid", {TGEOM}, TGEOM, TgeoCentroidExec));
loader.RegisterFunction(ScalarFunction(
"convexHull", {TGEOM}, GEOM, TgeoConvexHullExec));
loader.RegisterFunction(ScalarFunction(
Expand Down Expand Up @@ -753,10 +751,6 @@ void TGeographyOps::RegisterScalarFunctions(ExtensionLoader &loader) {
};
};

loader.RegisterFunction(ScalarFunction(
"minDistSimplify", {TGEOM, DBL}, TGEOM,
simplify_double_exec_factory(temporal_simplify_min_dist)));

loader.RegisterFunction(ScalarFunction(
"minTimeDeltaSimplify", {TGEOM, LogicalType::INTERVAL}, TGEOM,
[](DataChunk &args, ExpressionState &, Vector &result) {
Expand Down
6 changes: 0 additions & 6 deletions src/geo/tgeometry_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -587,8 +587,6 @@ void TGeometryOps::RegisterScalarFunctions(ExtensionLoader &loader) {

// Centroid / convexHull / traversedArea — produce a non-temporal
// geometry summary of the trajectory.
loader.RegisterFunction(ScalarFunction(
"centroid", {TGEOM}, TGEOM, TgeoCentroidExec));
loader.RegisterFunction(ScalarFunction(
"convexHull", {TGEOM}, GEOM, TgeoConvexHullExec));
loader.RegisterFunction(ScalarFunction(
Expand Down Expand Up @@ -749,10 +747,6 @@ void TGeometryOps::RegisterScalarFunctions(ExtensionLoader &loader) {
};
};

loader.RegisterFunction(ScalarFunction(
"minDistSimplify", {TGEOM, DBL}, TGEOM,
simplify_double_exec_factory(temporal_simplify_min_dist)));

loader.RegisterFunction(ScalarFunction(
"minTimeDeltaSimplify", {TGEOM, LogicalType::INTERVAL}, TGEOM,
[](DataChunk &args, ExpressionState &, Vector &result) {
Expand Down
15 changes: 15 additions & 0 deletions test/sql/parity/036_tnumber_distance.test
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,18 @@ query I
SELECT nad(tfloat '[1@2000-01-01, 5@2000-01-05]', tfloat '[3@2000-01-01, 3@2000-01-05]');
----
0.0

# ── tDistance over two tints answers a tint, as MobilityDB declares ───────────
# 036_tnumber_distance.in.sql:103 reads `tDistance(tint, tint) RETURNS tint`;
# the operand type carries the answer here, so no float widening happens.
query I
SELECT typeof(tDistance('1@2000-01-01'::tint, '2@2000-01-01'::tint));
----
tint

# DuckDB defines no custom infix operators, so the operator NAME is a quoted
# function; it shares tDistance's backing and therefore its return type.
query I
SELECT typeof("<->"('1@2000-01-01'::tint, '2@2000-01-01'::tint));
----
tint
26 changes: 26 additions & 0 deletions test/sql/parity/040_tgeometry_parity.test
Original file line number Diff line number Diff line change
Expand Up @@ -355,3 +355,29 @@ SELECT (len(spaceTimeBoxes(t::tgeometry, 1.0, 1.0, 1.0, INTERVAL '1 day')) >= 1)
('[Point(0 0)@2000-01-01, Point(2 2)@2000-01-03]')) t(t);
----
true

# ── the return type is the one MobilityDB declares, not the operand's ─────────
# A Temporal->Temporal function returns the operand's own type only where the
# family is CLOSED under the operation. centroid and minDistSimplify are not:
# MobilityDB declares centroid(tgeometry) RETURNS tgeompoint,
# centroid(tgeography) RETURNS tgeogpoint, minDistSimplify(tgeography,float)
# RETURNS tgeometry and minDistSimplify(tgeogpoint,float) RETURNS tgeompoint.
query I
SELECT typeof(centroid('SRID=4326;[Point(1 1)@2000-01-01,Point(2 2)@2000-01-02]'::tgeometry));
----
tgeompoint

query I
SELECT typeof(centroid('SRID=4326;[Point(1 1)@2000-01-01,Point(2 2)@2000-01-02]'::tgeography));
----
tgeogpoint

query I
SELECT typeof(minDistSimplify('SRID=4326;[Point(1 1)@2000-01-01,Point(3 3)@2000-01-03]'::tgeography, 1.0));
----
tgeometry

query I
SELECT typeof(minDistSimplify('SRID=4326;[Point(1 1)@2000-01-01,Point(3 3)@2000-01-03]'::tgeogpoint, 1.0));
----
tgeompoint
7 changes: 7 additions & 0 deletions test/sql/th3index.test
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,10 @@ query I
SELECT startValue(getResolution(cellToParent(th3index('SRID=4326;[Point(1 1)@2000-01-01]'::tgeompoint, 5), 3)));
----
3

# the cell boundary leaves the cell family: H3 is geodetic, so it answers a
# tgeography, where quadbin answers a planar tgeometry (see tquadbin.test)
query I
SELECT typeof(cellToBoundary(th3index('SRID=4326;[Point(1 1)@2000-01-01]'::tgeompoint, 5)));
----
tgeography
11 changes: 11 additions & 0 deletions test/sql/tquadbin.test
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,14 @@ query I
SELECT startValue(cellToParent(tquadbin(quadbinTileToCell(1,0,1), TIMESTAMPTZ '2024-01-01'), 0))::VARCHAR;
----
5192650370358181887

# the planar counterpart of the H3 boundary in th3index.test
query I
SELECT typeof(cellToBoundary(tquadbin(quadbinTileToCell(1,0,1), TIMESTAMPTZ '2024-01-01')));
----
tgeometry

query I
SELECT typeof(startValue(cellToBoundary(tquadbin(quadbinTileToCell(1,0,1), TIMESTAMPTZ '2024-01-01'))));
----
GEOMETRY
27 changes: 19 additions & 8 deletions tools/codegen_duck_udfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,14 +524,6 @@ def reg_scope(name):
# for quadbin and tgeography for h3). No name heuristic expresses that, so defer to the
# catalog: "all" hands the function to sig_declared_accs, which registers exactly the
# overloads MobilityDB CREATE FUNCTIONs.
# ⛔ cell_to_boundary is the one slot whose answer LEAVES the family — the catalog declares
# tgeography for th3index and tgeometry for tquadbin — and ret_temporal_type answers the
# operand's own type for a Temporal->Temporal function. Registering it would label a
# geography as a cell. Reading the return from the catalog per overload is the fix, and it
# moves six unrelated registrations (centroid, minDistSimplify, <->) that each need their
# own adjudication, so this slot DECLINES until that lands: absent, never mislabelled.
if name.startswith("tcellindex_cell_to_boundary"):
return None
if name.startswith("tcellindex_") or re.search(r'_tcellindex(?=_|$)', name):
return ("all", None)
# the temporal JSONB family (its own gated non-spatial type): a tjsonb_* prefix, or a
Expand Down Expand Up @@ -1970,6 +1962,22 @@ def _sig_ret_for(f, sqlname, tail=()):
return s.get("ret")
return None

def sig_declared_ret(f, acc, arity):
"""The DuckDB return accessor the catalog declares for the overload taking `acc` first at
`arity` arguments, else None. `ret_temporal_type` answers the OPERAND'S OWN TYPE for a
Temporal->Temporal function, which holds only where the family is CLOSED under the
operation; where MobilityDB says the answer leaves the family the catalog is the SoT --
centroid(tgeometry) is tgeompoint, cellToBoundary(th3index) is tgeography,
minDistSimplify(tgeography,float) is tgeometry, tDistance(tint,tint) is tint. Only an
UNAMBIGUOUS match counts (one signature on that operand at that arity), so a shape the
catalog describes with several overloads keeps the heuristic."""
on = [s for s in (f.get("sqlSignatures") or [])
if (s.get("args") or [None])[0] == _acc_sqlname(acc)
and len(s.get("args") or []) == arity]
if len(on) == 1 and on[0].get("ret") in SIG_TEMPORAL_ACC:
return SIG_TEMPORAL_ACC[on[0]["ret"]]
return None

def array_declared_accs(f, tail=()):
"""The registered DuckDB accessors this array-return is CREATE FUNCTION'd for, from the catalog
sqlSignatures whose SQL return is an array (`<base>[]`). Extended/unregistered arg types map to
Expand Down Expand Up @@ -3481,6 +3489,8 @@ def gen_cpp(fns, out_path, declared=None, aliases=None):
for a in accs:
sig = spec_sig % ((a,) * spec_sig.count("%s")) # 1 or 2 accessor slots
r2 = ret_temporal_type(fn, a, f.get("group"), f.get("sqlReturnType")) if dret == "MD_TEMPORAL" else dret
if dret == "MD_TEMPORAL":
r2 = sig_declared_ret(f, a, sig.count(",") + 1) or r2
for nm in names:
specific_regs.append(f' RegisterSerializedScalarFunction(loader, ScalarFunction('
f'"{reg_name(nm, f)}", {sig}, {r2}, Gen_{fn}));')
Expand All @@ -3499,6 +3509,7 @@ def gen_cpp(fns, out_path, declared=None, aliases=None):
else:
for a in accs:
r2 = ret_temporal_type(fn, a, f.get("group"), f.get("sqlReturnType"))
r2 = sig_declared_ret(f, a, 1) or r2
for nm in names:
specific_regs.append(f' RegisterSerializedScalarFunction(loader, ScalarFunction('
f'"{reg_name(nm, f)}", {{{a}}}, {r2}, Gen_{fn}_d));')
Expand Down
Loading