diff --git a/src/include/temporal/temporal_functions.hpp b/src/include/temporal/temporal_functions.hpp index d8425d02..9a1902af 100644 --- a/src/include/temporal/temporal_functions.hpp +++ b/src/include/temporal/temporal_functions.hpp @@ -196,6 +196,269 @@ struct TemporalFunctions { static void Tor_tbool_tbool(DataChunk &args, ExpressionState &state, Vector &result); static void Tnot_tbool(DataChunk &args, ExpressionState &state, Vector &result); + /* *************************************************** + * Arithmetic operators on tnumber + ****************************************************/ + static void Add_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Add_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Add_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Add_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Add_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Sub_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Sub_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Sub_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Sub_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Sub_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Mult_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Mult_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Mult_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Mult_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Mult_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Div_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Div_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Div_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Div_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Div_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + + /* *************************************************** + * Unary tnumber functions + ****************************************************/ + static void Tnumber_abs(DataChunk &args, ExpressionState &state, Vector &result); + // Temporal_derivative declared in the math-functions block below. + static void Tfloat_degrees(DataChunk &args, ExpressionState &state, Vector &result); + static void Tfloat_radians(DataChunk &args, ExpressionState &state, Vector &result); + + /* *************************************************** + * Distance operator on tnumber + ****************************************************/ + static void Tdistance_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Tdistance_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Tdistance_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Tdistance_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Tdistance_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Nad_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Nad_tint_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Nad_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Nad_tfloat_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + + /* *************************************************** + * Temporal topological predicates + ****************************************************/ + static void Contains_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Contained_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Overlaps_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Adjacent_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Contains_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Contained_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Overlaps_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Adjacent_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Contains_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Contained_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Overlaps_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Adjacent_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result); + + /* *************************************************** + * Temporal time-position predicates (<<#, #>>, &<#, #&>) + ****************************************************/ + static void Before_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void After_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Overbefore_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Overafter_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Before_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result); + static void After_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Overbefore_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Overafter_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Before_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void After_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Overbefore_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result); + static void Overafter_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result); + + /* *************************************************** + * Ever / always equality and inequality + * (DuckDB parser cannot accept ?= / #= operator names, + * so the upstream MobilityDB ?= / ?<> / #= / #<> map to + * named functions ever_eq / ever_ne / always_eq / always_ne.) + ****************************************************/ + // ever_eq + static void Ever_eq_bool_tbool(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_eq_tbool_bool(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_eq_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_eq_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_eq_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_eq_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_eq_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + // always_eq + static void Always_eq_bool_tbool(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_eq_tbool_bool(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_eq_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_eq_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_eq_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_eq_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_eq_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + // ever_ne + static void Ever_ne_bool_tbool(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_ne_tbool_bool(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_ne_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_ne_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_ne_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_ne_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_ne_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + // always_ne + static void Always_ne_bool_tbool(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_ne_tbool_bool(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_ne_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_ne_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_ne_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_ne_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_ne_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + + // Ever / always ordering (no tbool — boolean has no ordering) + // ever_lt + static void Ever_lt_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_lt_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_lt_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_lt_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_lt_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + // always_lt + static void Always_lt_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_lt_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_lt_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_lt_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_lt_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + // ever_le + static void Ever_le_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_le_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_le_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_le_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_le_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + // always_le + static void Always_le_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_le_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_le_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_le_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_le_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + // ever_gt + static void Ever_gt_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_gt_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_gt_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_gt_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_gt_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + // always_gt + static void Always_gt_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_gt_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_gt_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_gt_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_gt_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + // ever_ge + static void Ever_ge_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_ge_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_ge_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_ge_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Ever_ge_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + // always_ge + static void Always_ge_int_tint(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_ge_tint_int(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_ge_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_ge_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result); + static void Always_ge_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result); + + /* *************************************************** + * Similarity measures + ****************************************************/ + static void Temporal_frechet_distance(DataChunk &args, ExpressionState &state, Vector &result); + static void Temporal_dyntimewarp_distance(DataChunk &args, ExpressionState &state, Vector &result); + static void Temporal_hausdorff_distance(DataChunk &args, ExpressionState &state, Vector &result); + + /* *************************************************** + * tnumber × {numspan, tbox} topological predicates + * (4 ops × 4 type-pair shapes = 16 wrappers) + ****************************************************/ + static void Contains_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Contained_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Overlaps_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Adjacent_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Contains_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Contained_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Overlaps_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Adjacent_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Contains_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Contained_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Overlaps_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Adjacent_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Contains_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Contained_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Overlaps_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Adjacent_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + + /* *************************************************** + * tnumber × {numspan, tbox} position predicates + * (4 ops × 4 type-pair shapes × 2 directions) + ****************************************************/ + static void Left_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Right_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Overleft_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Overright_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result); + static void Left_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Right_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Overleft_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Overright_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Left_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Right_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Overleft_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Overright_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Left_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Right_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Overleft_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Overright_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + // tnumber × tnumber position + static void Left_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Right_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Overleft_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + static void Overright_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result); + + /* *************************************************** + * tspatial × {stbox, tspatial} position predicates + * (12 directions × 3 type-pair shapes) + ****************************************************/ + static void Left_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Right_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Below_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Above_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Front_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Back_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Overleft_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Overright_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Overbelow_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Overabove_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Overfront_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + static void Overback_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result); + + static void Left_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Right_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Below_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Above_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Front_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Back_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overleft_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overright_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overbelow_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overabove_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overfront_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overback_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + + static void Left_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Right_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Below_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Above_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Front_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Back_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overleft_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overright_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overbelow_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overabove_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overfront_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + static void Overback_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result); + /* *************************************************** * Text functions on ttext ****************************************************/ diff --git a/src/temporal/temporal.cpp b/src/temporal/temporal.cpp index 241ae4bc..2bd0ca32 100644 --- a/src/temporal/temporal.cpp +++ b/src/temporal/temporal.cpp @@ -7,6 +7,8 @@ #include "temporal/tbox.hpp" #include "temporal/set.hpp" #include "temporal/span.hpp" +#include "geo/stbox.hpp" +#include "geo/tgeompoint.hpp" #include "duckdb/common/types/blob.hpp" #include "duckdb/common/exception.hpp" @@ -1313,6 +1315,280 @@ void TemporalTypes::RegisterScalarFunctions(ExtensionLoader &loader) { loader.RegisterFunction(ScalarFunction("|", {TemporalTypes::TBOOL(), TemporalTypes::TBOOL()}, TemporalTypes::TBOOL(), TemporalFunctions::Tor_tbool_tbool)); loader.RegisterFunction(ScalarFunction("~", {TemporalTypes::TBOOL()}, TemporalTypes::TBOOL(), TemporalFunctions::Tnot_tbool)); + // tnumber arithmetic operators + loader.RegisterFunction(ScalarFunction("+", {LogicalType::INTEGER, TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Add_int_tint)); + loader.RegisterFunction(ScalarFunction("+", {TemporalTypes::TINT(), LogicalType::INTEGER}, TemporalTypes::TINT(), TemporalFunctions::Add_tint_int)); + loader.RegisterFunction(ScalarFunction("+", {LogicalType::DOUBLE, TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Add_float_tfloat)); + loader.RegisterFunction(ScalarFunction("+", {TemporalTypes::TFLOAT(), LogicalType::DOUBLE}, TemporalTypes::TFLOAT(), TemporalFunctions::Add_tfloat_float)); + loader.RegisterFunction(ScalarFunction("+", {TemporalTypes::TINT(), TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Add_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction("+", {TemporalTypes::TFLOAT(), TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Add_tnumber_tnumber)); + + loader.RegisterFunction(ScalarFunction("-", {LogicalType::INTEGER, TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Sub_int_tint)); + loader.RegisterFunction(ScalarFunction("-", {TemporalTypes::TINT(), LogicalType::INTEGER}, TemporalTypes::TINT(), TemporalFunctions::Sub_tint_int)); + loader.RegisterFunction(ScalarFunction("-", {LogicalType::DOUBLE, TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Sub_float_tfloat)); + loader.RegisterFunction(ScalarFunction("-", {TemporalTypes::TFLOAT(), LogicalType::DOUBLE}, TemporalTypes::TFLOAT(), TemporalFunctions::Sub_tfloat_float)); + loader.RegisterFunction(ScalarFunction("-", {TemporalTypes::TINT(), TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Sub_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction("-", {TemporalTypes::TFLOAT(), TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Sub_tnumber_tnumber)); + + loader.RegisterFunction(ScalarFunction("*", {LogicalType::INTEGER, TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Mult_int_tint)); + loader.RegisterFunction(ScalarFunction("*", {TemporalTypes::TINT(), LogicalType::INTEGER}, TemporalTypes::TINT(), TemporalFunctions::Mult_tint_int)); + loader.RegisterFunction(ScalarFunction("*", {LogicalType::DOUBLE, TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Mult_float_tfloat)); + loader.RegisterFunction(ScalarFunction("*", {TemporalTypes::TFLOAT(), LogicalType::DOUBLE}, TemporalTypes::TFLOAT(), TemporalFunctions::Mult_tfloat_float)); + loader.RegisterFunction(ScalarFunction("*", {TemporalTypes::TINT(), TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Mult_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction("*", {TemporalTypes::TFLOAT(), TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Mult_tnumber_tnumber)); + + loader.RegisterFunction(ScalarFunction("/", {LogicalType::INTEGER, TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Div_int_tint)); + loader.RegisterFunction(ScalarFunction("/", {TemporalTypes::TINT(), LogicalType::INTEGER}, TemporalTypes::TINT(), TemporalFunctions::Div_tint_int)); + loader.RegisterFunction(ScalarFunction("/", {LogicalType::DOUBLE, TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Div_float_tfloat)); + loader.RegisterFunction(ScalarFunction("/", {TemporalTypes::TFLOAT(), LogicalType::DOUBLE}, TemporalTypes::TFLOAT(), TemporalFunctions::Div_tfloat_float)); + loader.RegisterFunction(ScalarFunction("/", {TemporalTypes::TINT(), TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Div_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction("/", {TemporalTypes::TFLOAT(), TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Div_tnumber_tnumber)); + + // Unary tnumber functions + loader.RegisterFunction(ScalarFunction("abs", {TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Tnumber_abs)); + loader.RegisterFunction(ScalarFunction("abs", {TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Tnumber_abs)); + loader.RegisterFunction(ScalarFunction("derivative", {TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Temporal_derivative)); + loader.RegisterFunction(ScalarFunction("degrees", {TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Tfloat_degrees)); + loader.RegisterFunction(ScalarFunction("degrees", {TemporalTypes::TFLOAT(), LogicalType::BOOLEAN}, TemporalTypes::TFLOAT(), TemporalFunctions::Tfloat_degrees)); + loader.RegisterFunction(ScalarFunction("radians", {TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Tfloat_radians)); + + // tnumber distance and nearest-approach-distance. + // + // Value-distance variants `<-> ` for (tint, INTEGER), (INTEGER, tint), + // (tfloat, DOUBLE), (DOUBLE, tfloat) are intentionally NOT registered + // here: in the installed MEOS library, tdistance_tfloat_float / tint_int + // return the temporal's own value at each instant rather than the + // |t.value - v| absolute difference. Verified by smoke test: + // SELECT 5.0::DOUBLE <-> tfloat '5.0@2000-01-01'; -- returns 5.0, expected 0.0 + // SELECT 100.0::DOUBLE <-> tfloat '2.5@2000-01-01'; -- returns 2.5, expected 97.5 + // The temporal-temporal variant DOES work correctly, and so does nad_*. + // Restore the value-distance registrations once the MEOS issue is resolved. + loader.RegisterFunction(ScalarFunction("<->", {TemporalTypes::TINT(), TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Tdistance_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction("<->", {TemporalTypes::TFLOAT(), TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Tdistance_tnumber_tnumber)); + + // nearestApproachDistance / nad — scalar return + loader.RegisterFunction(ScalarFunction("nad", {TemporalTypes::TINT(), LogicalType::INTEGER}, LogicalType::INTEGER, TemporalFunctions::Nad_tint_int)); + loader.RegisterFunction(ScalarFunction("nad", {TemporalTypes::TINT(), TemporalTypes::TINT()}, LogicalType::INTEGER, TemporalFunctions::Nad_tint_tint)); + loader.RegisterFunction(ScalarFunction("nad", {TemporalTypes::TFLOAT(), LogicalType::DOUBLE}, LogicalType::DOUBLE, TemporalFunctions::Nad_tfloat_float)); + loader.RegisterFunction(ScalarFunction("nad", {TemporalTypes::TFLOAT(), TemporalTypes::TFLOAT()}, LogicalType::DOUBLE, TemporalFunctions::Nad_tfloat_tfloat)); + loader.RegisterFunction(ScalarFunction("nearestApproachDistance", {TemporalTypes::TINT(), LogicalType::INTEGER}, LogicalType::INTEGER, TemporalFunctions::Nad_tint_int)); + loader.RegisterFunction(ScalarFunction("nearestApproachDistance", {TemporalTypes::TINT(), TemporalTypes::TINT()}, LogicalType::INTEGER, TemporalFunctions::Nad_tint_tint)); + loader.RegisterFunction(ScalarFunction("nearestApproachDistance", {TemporalTypes::TFLOAT(), LogicalType::DOUBLE}, LogicalType::DOUBLE, TemporalFunctions::Nad_tfloat_float)); + loader.RegisterFunction(ScalarFunction("nearestApproachDistance", {TemporalTypes::TFLOAT(), TemporalTypes::TFLOAT()}, LogicalType::DOUBLE, TemporalFunctions::Nad_tfloat_tfloat)); + + // Temporal topological predicates: temporal × temporal (4 ops × 4 type pairs) + for (auto &t1 : TemporalTypes::AllTypes()) { + for (auto &t2 : TemporalTypes::AllTypes()) { + loader.RegisterFunction(ScalarFunction("@>", {t1, t2}, LogicalType::BOOLEAN, TemporalFunctions::Contains_temporal_temporal)); + loader.RegisterFunction(ScalarFunction("<@", {t1, t2}, LogicalType::BOOLEAN, TemporalFunctions::Contained_temporal_temporal)); + loader.RegisterFunction(ScalarFunction("&&", {t1, t2}, LogicalType::BOOLEAN, TemporalFunctions::Overlaps_temporal_temporal)); + loader.RegisterFunction(ScalarFunction("-|-", {t1, t2}, LogicalType::BOOLEAN, TemporalFunctions::Adjacent_temporal_temporal)); + } + } + // Temporal × tstzspan (and the reverse direction) + for (auto &t : TemporalTypes::AllTypes()) { + loader.RegisterFunction(ScalarFunction("@>", {t, SpanTypes::TSTZSPAN()}, LogicalType::BOOLEAN, TemporalFunctions::Contains_temporal_tstzspan)); + loader.RegisterFunction(ScalarFunction("<@", {t, SpanTypes::TSTZSPAN()}, LogicalType::BOOLEAN, TemporalFunctions::Contained_temporal_tstzspan)); + loader.RegisterFunction(ScalarFunction("&&", {t, SpanTypes::TSTZSPAN()}, LogicalType::BOOLEAN, TemporalFunctions::Overlaps_temporal_tstzspan)); + loader.RegisterFunction(ScalarFunction("-|-", {t, SpanTypes::TSTZSPAN()}, LogicalType::BOOLEAN, TemporalFunctions::Adjacent_temporal_tstzspan)); + loader.RegisterFunction(ScalarFunction("@>", {SpanTypes::TSTZSPAN(), t}, LogicalType::BOOLEAN, TemporalFunctions::Contains_tstzspan_temporal)); + loader.RegisterFunction(ScalarFunction("<@", {SpanTypes::TSTZSPAN(), t}, LogicalType::BOOLEAN, TemporalFunctions::Contained_tstzspan_temporal)); + loader.RegisterFunction(ScalarFunction("&&", {SpanTypes::TSTZSPAN(), t}, LogicalType::BOOLEAN, TemporalFunctions::Overlaps_tstzspan_temporal)); + loader.RegisterFunction(ScalarFunction("-|-", {SpanTypes::TSTZSPAN(), t}, LogicalType::BOOLEAN, TemporalFunctions::Adjacent_tstzspan_temporal)); + } + + // Temporal time-position predicates registered as named functions: + // DuckDB's parser does not accept `#` as an operator-name character, + // so the upstream MobilityDB operators `<<#`, `#>>`, `&<#`, `#&>` + // are unreachable from SQL. The named-function forms `before`, + // `after`, `overbefore`, `overafter` provide equivalent behaviour. + for (auto &t1 : TemporalTypes::AllTypes()) { + for (auto &t2 : TemporalTypes::AllTypes()) { + loader.RegisterFunction(ScalarFunction("before", {t1, t2}, LogicalType::BOOLEAN, TemporalFunctions::Before_temporal_temporal)); + loader.RegisterFunction(ScalarFunction("after", {t1, t2}, LogicalType::BOOLEAN, TemporalFunctions::After_temporal_temporal)); + loader.RegisterFunction(ScalarFunction("overbefore", {t1, t2}, LogicalType::BOOLEAN, TemporalFunctions::Overbefore_temporal_temporal)); + loader.RegisterFunction(ScalarFunction("overafter", {t1, t2}, LogicalType::BOOLEAN, TemporalFunctions::Overafter_temporal_temporal)); + } + } + for (auto &t : TemporalTypes::AllTypes()) { + loader.RegisterFunction(ScalarFunction("before", {t, SpanTypes::TSTZSPAN()}, LogicalType::BOOLEAN, TemporalFunctions::Before_temporal_tstzspan)); + loader.RegisterFunction(ScalarFunction("after", {t, SpanTypes::TSTZSPAN()}, LogicalType::BOOLEAN, TemporalFunctions::After_temporal_tstzspan)); + loader.RegisterFunction(ScalarFunction("overbefore", {t, SpanTypes::TSTZSPAN()}, LogicalType::BOOLEAN, TemporalFunctions::Overbefore_temporal_tstzspan)); + loader.RegisterFunction(ScalarFunction("overafter", {t, SpanTypes::TSTZSPAN()}, LogicalType::BOOLEAN, TemporalFunctions::Overafter_temporal_tstzspan)); + loader.RegisterFunction(ScalarFunction("before", {SpanTypes::TSTZSPAN(), t}, LogicalType::BOOLEAN, TemporalFunctions::Before_tstzspan_temporal)); + loader.RegisterFunction(ScalarFunction("after", {SpanTypes::TSTZSPAN(), t}, LogicalType::BOOLEAN, TemporalFunctions::After_tstzspan_temporal)); + loader.RegisterFunction(ScalarFunction("overbefore", {SpanTypes::TSTZSPAN(), t}, LogicalType::BOOLEAN, TemporalFunctions::Overbefore_tstzspan_temporal)); + loader.RegisterFunction(ScalarFunction("overafter", {SpanTypes::TSTZSPAN(), t}, LogicalType::BOOLEAN, TemporalFunctions::Overafter_tstzspan_temporal)); + } + + // Ever / always equality and inequality (named functions; DuckDB + // parser does not accept ?= / #= operator names). +#define REG_EA(NAME, FN) \ + loader.RegisterFunction(ScalarFunction(NAME, {LogicalType::BOOLEAN, TemporalTypes::TBOOL()}, LogicalType::BOOLEAN, TemporalFunctions::FN##_bool_tbool)); \ + loader.RegisterFunction(ScalarFunction(NAME, {TemporalTypes::TBOOL(), LogicalType::BOOLEAN}, LogicalType::BOOLEAN, TemporalFunctions::FN##_tbool_bool)); \ + loader.RegisterFunction(ScalarFunction(NAME, {LogicalType::INTEGER, TemporalTypes::TINT()}, LogicalType::BOOLEAN, TemporalFunctions::FN##_int_tint)); \ + loader.RegisterFunction(ScalarFunction(NAME, {TemporalTypes::TINT(), LogicalType::INTEGER}, LogicalType::BOOLEAN, TemporalFunctions::FN##_tint_int)); \ + loader.RegisterFunction(ScalarFunction(NAME, {LogicalType::DOUBLE, TemporalTypes::TFLOAT()}, LogicalType::BOOLEAN, TemporalFunctions::FN##_float_tfloat)); \ + loader.RegisterFunction(ScalarFunction(NAME, {TemporalTypes::TFLOAT(), LogicalType::DOUBLE}, LogicalType::BOOLEAN, TemporalFunctions::FN##_tfloat_float)); \ + loader.RegisterFunction(ScalarFunction(NAME, {TemporalTypes::TINT(), TemporalTypes::TINT()}, LogicalType::BOOLEAN, TemporalFunctions::FN##_temporal_temporal)); \ + loader.RegisterFunction(ScalarFunction(NAME, {TemporalTypes::TFLOAT(), TemporalTypes::TFLOAT()}, LogicalType::BOOLEAN, TemporalFunctions::FN##_temporal_temporal)); \ + loader.RegisterFunction(ScalarFunction(NAME, {TemporalTypes::TBOOL(), TemporalTypes::TBOOL()}, LogicalType::BOOLEAN, TemporalFunctions::FN##_temporal_temporal)); + + REG_EA("ever_eq", Ever_eq) + REG_EA("always_eq", Always_eq) + REG_EA("ever_ne", Ever_ne) + REG_EA("always_ne", Always_ne) +#undef REG_EA + + // Ordering ever/always — no tbool variant (booleans have no ordering) +#define REG_EA_ORD(NAME, FN) \ + loader.RegisterFunction(ScalarFunction(NAME, {LogicalType::INTEGER, TemporalTypes::TINT()}, LogicalType::BOOLEAN, TemporalFunctions::FN##_int_tint)); \ + loader.RegisterFunction(ScalarFunction(NAME, {TemporalTypes::TINT(), LogicalType::INTEGER}, LogicalType::BOOLEAN, TemporalFunctions::FN##_tint_int)); \ + loader.RegisterFunction(ScalarFunction(NAME, {LogicalType::DOUBLE, TemporalTypes::TFLOAT()}, LogicalType::BOOLEAN, TemporalFunctions::FN##_float_tfloat)); \ + loader.RegisterFunction(ScalarFunction(NAME, {TemporalTypes::TFLOAT(), LogicalType::DOUBLE}, LogicalType::BOOLEAN, TemporalFunctions::FN##_tfloat_float)); \ + loader.RegisterFunction(ScalarFunction(NAME, {TemporalTypes::TINT(), TemporalTypes::TINT()}, LogicalType::BOOLEAN, TemporalFunctions::FN##_temporal_temporal)); \ + loader.RegisterFunction(ScalarFunction(NAME, {TemporalTypes::TFLOAT(), TemporalTypes::TFLOAT()}, LogicalType::BOOLEAN, TemporalFunctions::FN##_temporal_temporal)); + + REG_EA_ORD("ever_lt", Ever_lt) + REG_EA_ORD("always_lt", Always_lt) + REG_EA_ORD("ever_le", Ever_le) + REG_EA_ORD("always_le", Always_le) + REG_EA_ORD("ever_gt", Ever_gt) + REG_EA_ORD("always_gt", Always_gt) + REG_EA_ORD("ever_ge", Ever_ge) + REG_EA_ORD("always_ge", Always_ge) +#undef REG_EA_ORD + + // Similarity measures (tnumber × tnumber) + for (auto &t : {TemporalTypes::TINT(), TemporalTypes::TFLOAT()}) { + loader.RegisterFunction(ScalarFunction("frechetDistance", {t, t}, LogicalType::DOUBLE, TemporalFunctions::Temporal_frechet_distance)); + loader.RegisterFunction(ScalarFunction("discreteFrechet", {t, t}, LogicalType::DOUBLE, TemporalFunctions::Temporal_frechet_distance)); + loader.RegisterFunction(ScalarFunction("dynTimeWarp", {t, t}, LogicalType::DOUBLE, TemporalFunctions::Temporal_dyntimewarp_distance)); + loader.RegisterFunction(ScalarFunction("hausdorffDistance", {t, t}, LogicalType::DOUBLE, TemporalFunctions::Temporal_hausdorff_distance)); + } + + // tnumber × {numspan, tbox} topological predicates (4 ops × 8 shape pairs) + { + auto tint = TemporalTypes::TINT(); + auto tflt = TemporalTypes::TFLOAT(); + auto ispan = SpanTypes::INTSPAN(); + auto fspan = SpanTypes::FLOATSPAN(); + auto tbox = TboxType::TBOX(); + + // tnumber × numspan + loader.RegisterFunction(ScalarFunction("@>", {tint, ispan}, LogicalType::BOOLEAN, TemporalFunctions::Contains_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("<@", {tint, ispan}, LogicalType::BOOLEAN, TemporalFunctions::Contained_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("&&", {tint, ispan}, LogicalType::BOOLEAN, TemporalFunctions::Overlaps_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("-|-", {tint, ispan}, LogicalType::BOOLEAN, TemporalFunctions::Adjacent_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("@>", {tflt, fspan}, LogicalType::BOOLEAN, TemporalFunctions::Contains_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("<@", {tflt, fspan}, LogicalType::BOOLEAN, TemporalFunctions::Contained_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("&&", {tflt, fspan}, LogicalType::BOOLEAN, TemporalFunctions::Overlaps_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("-|-", {tflt, fspan}, LogicalType::BOOLEAN, TemporalFunctions::Adjacent_tnumber_numspan)); + // numspan × tnumber + loader.RegisterFunction(ScalarFunction("@>", {ispan, tint}, LogicalType::BOOLEAN, TemporalFunctions::Contains_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("<@", {ispan, tint}, LogicalType::BOOLEAN, TemporalFunctions::Contained_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("&&", {ispan, tint}, LogicalType::BOOLEAN, TemporalFunctions::Overlaps_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("-|-", {ispan, tint}, LogicalType::BOOLEAN, TemporalFunctions::Adjacent_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("@>", {fspan, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Contains_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("<@", {fspan, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Contained_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("&&", {fspan, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Overlaps_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("-|-", {fspan, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Adjacent_numspan_tnumber)); + // tnumber × tbox + for (auto &t : {tint, tflt}) { + loader.RegisterFunction(ScalarFunction("@>", {t, tbox}, LogicalType::BOOLEAN, TemporalFunctions::Contains_tnumber_tbox)); + loader.RegisterFunction(ScalarFunction("<@", {t, tbox}, LogicalType::BOOLEAN, TemporalFunctions::Contained_tnumber_tbox)); + loader.RegisterFunction(ScalarFunction("&&", {t, tbox}, LogicalType::BOOLEAN, TemporalFunctions::Overlaps_tnumber_tbox)); + loader.RegisterFunction(ScalarFunction("-|-", {t, tbox}, LogicalType::BOOLEAN, TemporalFunctions::Adjacent_tnumber_tbox)); + loader.RegisterFunction(ScalarFunction("@>", {tbox, t}, LogicalType::BOOLEAN, TemporalFunctions::Contains_tbox_tnumber)); + loader.RegisterFunction(ScalarFunction("<@", {tbox, t}, LogicalType::BOOLEAN, TemporalFunctions::Contained_tbox_tnumber)); + loader.RegisterFunction(ScalarFunction("&&", {tbox, t}, LogicalType::BOOLEAN, TemporalFunctions::Overlaps_tbox_tnumber)); + loader.RegisterFunction(ScalarFunction("-|-", {tbox, t}, LogicalType::BOOLEAN, TemporalFunctions::Adjacent_tbox_tnumber)); + } + + // Position ops (<<, >>, &<, &>) — same surface + loader.RegisterFunction(ScalarFunction("<<", {tint, ispan}, LogicalType::BOOLEAN, TemporalFunctions::Left_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction(">>", {tint, ispan}, LogicalType::BOOLEAN, TemporalFunctions::Right_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("&<", {tint, ispan}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("&>", {tint, ispan}, LogicalType::BOOLEAN, TemporalFunctions::Overright_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("<<", {tflt, fspan}, LogicalType::BOOLEAN, TemporalFunctions::Left_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction(">>", {tflt, fspan}, LogicalType::BOOLEAN, TemporalFunctions::Right_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("&<", {tflt, fspan}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("&>", {tflt, fspan}, LogicalType::BOOLEAN, TemporalFunctions::Overright_tnumber_numspan)); + loader.RegisterFunction(ScalarFunction("<<", {ispan, tint}, LogicalType::BOOLEAN, TemporalFunctions::Left_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction(">>", {ispan, tint}, LogicalType::BOOLEAN, TemporalFunctions::Right_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("&<", {ispan, tint}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("&>", {ispan, tint}, LogicalType::BOOLEAN, TemporalFunctions::Overright_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("<<", {fspan, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Left_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction(">>", {fspan, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Right_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("&<", {fspan, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_numspan_tnumber)); + loader.RegisterFunction(ScalarFunction("&>", {fspan, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Overright_numspan_tnumber)); + for (auto &t : {tint, tflt}) { + loader.RegisterFunction(ScalarFunction("<<", {t, tbox}, LogicalType::BOOLEAN, TemporalFunctions::Left_tnumber_tbox)); + loader.RegisterFunction(ScalarFunction(">>", {t, tbox}, LogicalType::BOOLEAN, TemporalFunctions::Right_tnumber_tbox)); + loader.RegisterFunction(ScalarFunction("&<", {t, tbox}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_tnumber_tbox)); + loader.RegisterFunction(ScalarFunction("&>", {t, tbox}, LogicalType::BOOLEAN, TemporalFunctions::Overright_tnumber_tbox)); + loader.RegisterFunction(ScalarFunction("<<", {tbox, t}, LogicalType::BOOLEAN, TemporalFunctions::Left_tbox_tnumber)); + loader.RegisterFunction(ScalarFunction(">>", {tbox, t}, LogicalType::BOOLEAN, TemporalFunctions::Right_tbox_tnumber)); + loader.RegisterFunction(ScalarFunction("&<", {tbox, t}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_tbox_tnumber)); + loader.RegisterFunction(ScalarFunction("&>", {tbox, t}, LogicalType::BOOLEAN, TemporalFunctions::Overright_tbox_tnumber)); + } + // tnumber × tnumber (same base type) + loader.RegisterFunction(ScalarFunction("<<", {tint, tint}, LogicalType::BOOLEAN, TemporalFunctions::Left_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction(">>", {tint, tint}, LogicalType::BOOLEAN, TemporalFunctions::Right_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction("&<", {tint, tint}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction("&>", {tint, tint}, LogicalType::BOOLEAN, TemporalFunctions::Overright_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction("<<", {tflt, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Left_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction(">>", {tflt, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Right_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction("&<", {tflt, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_tnumber_tnumber)); + loader.RegisterFunction(ScalarFunction("&>", {tflt, tflt}, LogicalType::BOOLEAN, TemporalFunctions::Overright_tnumber_tnumber)); + } + + // tspatial × {stbox, tspatial} position predicates + { + auto tg = TgeompointType::TGEOMPOINT(); + auto stbox = StboxType::STBOX(); + + // L/R operators (DuckDB parser-friendly) + loader.RegisterFunction(ScalarFunction("<<", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Left_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction(">>", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Right_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("&<", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("&>", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Overright_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("<<", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Left_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction(">>", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Right_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("&<", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("&>", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overright_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("<<", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Left_tspatial_tspatial)); + loader.RegisterFunction(ScalarFunction(">>", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Right_tspatial_tspatial)); + loader.RegisterFunction(ScalarFunction("&<", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overleft_tspatial_tspatial)); + loader.RegisterFunction(ScalarFunction("&>", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overright_tspatial_tspatial)); + + // Above/below/front/back as named functions (DuckDB parser rejects |>>, <<|, etc.) + loader.RegisterFunction(ScalarFunction("below", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Below_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("above", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Above_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("front", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Front_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("back", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Back_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("overbelow", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Overbelow_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("overabove", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Overabove_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("overfront", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Overfront_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("overback", {tg, stbox}, LogicalType::BOOLEAN, TemporalFunctions::Overback_tspatial_stbox)); + loader.RegisterFunction(ScalarFunction("below", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Below_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("above", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Above_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("front", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Front_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("back", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Back_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("overbelow", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overbelow_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("overabove", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overabove_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("overfront", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overfront_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("overback", {stbox, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overback_stbox_tspatial)); + loader.RegisterFunction(ScalarFunction("below", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Below_tspatial_tspatial)); + loader.RegisterFunction(ScalarFunction("above", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Above_tspatial_tspatial)); + loader.RegisterFunction(ScalarFunction("front", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Front_tspatial_tspatial)); + loader.RegisterFunction(ScalarFunction("back", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Back_tspatial_tspatial)); + loader.RegisterFunction(ScalarFunction("overbelow", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overbelow_tspatial_tspatial)); + loader.RegisterFunction(ScalarFunction("overabove", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overabove_tspatial_tspatial)); + loader.RegisterFunction(ScalarFunction("overfront", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overfront_tspatial_tspatial)); + loader.RegisterFunction(ScalarFunction("overback", {tg, tg}, LogicalType::BOOLEAN, TemporalFunctions::Overback_tspatial_tspatial)); + } + // ttext text functions loader.RegisterFunction(ScalarFunction("lower", {TemporalTypes::TTEXT()}, TemporalTypes::TTEXT(), TemporalFunctions::Ttext_lower)); loader.RegisterFunction(ScalarFunction("upper", {TemporalTypes::TTEXT()}, TemporalTypes::TTEXT(), TemporalFunctions::Ttext_upper)); diff --git a/src/temporal/temporal_functions.cpp b/src/temporal/temporal_functions.cpp index bdfa599c..c925094d 100644 --- a/src/temporal/temporal_functions.cpp +++ b/src/temporal/temporal_functions.cpp @@ -4720,6 +4720,596 @@ void TemporalFunctions::Tnot_tbool(DataChunk &args, ExpressionState &state, Vect TemporalUnary(args, result, [](Temporal *t) { return tnot_tbool(t); }); } +/* *************************************************** + * Arithmetic operators on tnumber + ****************************************************/ + +void TemporalFunctions::Add_int_tint(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV1(args, result, [](int32_t i, Temporal *t) { return add_int_tint(i, t); }); +} +void TemporalFunctions::Add_tint_int(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV(args, result, [](Temporal *t, int32_t i) { return add_tint_int(t, i); }); +} +void TemporalFunctions::Add_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV1(args, result, [](double d, Temporal *t) { return add_float_tfloat(d, t); }); +} +void TemporalFunctions::Add_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV(args, result, [](Temporal *t, double d) { return add_tfloat_float(t, d); }); +} +void TemporalFunctions::Add_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryTT(args, result, [](Temporal *a, Temporal *b) { return add_tnumber_tnumber(a, b); }); +} + +void TemporalFunctions::Sub_int_tint(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV1(args, result, [](int32_t i, Temporal *t) { return sub_int_tint(i, t); }); +} +void TemporalFunctions::Sub_tint_int(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV(args, result, [](Temporal *t, int32_t i) { return sub_tint_int(t, i); }); +} +void TemporalFunctions::Sub_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV1(args, result, [](double d, Temporal *t) { return sub_float_tfloat(d, t); }); +} +void TemporalFunctions::Sub_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV(args, result, [](Temporal *t, double d) { return sub_tfloat_float(t, d); }); +} +void TemporalFunctions::Sub_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryTT(args, result, [](Temporal *a, Temporal *b) { return sub_tnumber_tnumber(a, b); }); +} + +void TemporalFunctions::Mult_int_tint(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV1(args, result, [](int32_t i, Temporal *t) { return mult_int_tint(i, t); }); +} +void TemporalFunctions::Mult_tint_int(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV(args, result, [](Temporal *t, int32_t i) { return mult_tint_int(t, i); }); +} +void TemporalFunctions::Mult_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV1(args, result, [](double d, Temporal *t) { return mult_float_tfloat(d, t); }); +} +void TemporalFunctions::Mult_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV(args, result, [](Temporal *t, double d) { return mult_tfloat_float(t, d); }); +} +void TemporalFunctions::Mult_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryTT(args, result, [](Temporal *a, Temporal *b) { return mult_tnumber_tnumber(a, b); }); +} + +void TemporalFunctions::Div_int_tint(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV1(args, result, [](int32_t i, Temporal *t) { return div_int_tint(i, t); }); +} +void TemporalFunctions::Div_tint_int(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV(args, result, [](Temporal *t, int32_t i) { return div_tint_int(t, i); }); +} +void TemporalFunctions::Div_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV1(args, result, [](double d, Temporal *t) { return div_float_tfloat(d, t); }); +} +void TemporalFunctions::Div_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV(args, result, [](Temporal *t, double d) { return div_tfloat_float(t, d); }); +} +void TemporalFunctions::Div_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryTT(args, result, [](Temporal *a, Temporal *b) { return div_tnumber_tnumber(a, b); }); +} + +/* *************************************************** + * Unary tnumber functions + ****************************************************/ + +void TemporalFunctions::Tnumber_abs(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalUnary(args, result, [](Temporal *t) { return tnumber_abs(t); }); +} + +// Temporal_derivative is implemented later in this file in the Math +// functions block (existed before the unary-tnumber additions). + +void TemporalFunctions::Tfloat_degrees(DataChunk &args, ExpressionState &state, Vector &result) { + if (args.ColumnCount() == 2) { + TemporalBinaryV(args, result, [](Temporal *t, bool normalize) { + return tfloat_degrees(t, normalize); + }); + } else { + TemporalUnary(args, result, [](Temporal *t) { return tfloat_degrees(t, false); }); + } +} + +void TemporalFunctions::Tfloat_radians(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalUnary(args, result, [](Temporal *t) { return tfloat_radians(t); }); +} + +/* *************************************************** + * Distance operator on tnumber + ****************************************************/ + +void TemporalFunctions::Tdistance_tint_int(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV(args, result, [](Temporal *t, int32_t i) { return tdistance_tint_int(t, i); }); +} +void TemporalFunctions::Tdistance_int_tint(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV1(args, result, [](int32_t i, Temporal *t) { return tdistance_tint_int(t, i); }); +} +void TemporalFunctions::Tdistance_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV(args, result, [](Temporal *t, double d) { return tdistance_tfloat_float(t, d); }); +} +void TemporalFunctions::Tdistance_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryV1(args, result, [](double d, Temporal *t) { return tdistance_tfloat_float(t, d); }); +} +void TemporalFunctions::Tdistance_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalBinaryTT(args, result, [](Temporal *a, Temporal *b) { return tdistance_tnumber_tnumber(a, b); }); +} + +void TemporalFunctions::Nad_tint_int(DataChunk &args, ExpressionState &state, Vector &result) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t blob, int32_t i) -> int32_t { + Temporal *t = BlobToTemporal(blob); + int32_t r = nad_tint_int(t, i); + free(t); + return r; + }); +} +void TemporalFunctions::Nad_tint_tint(DataChunk &args, ExpressionState &state, Vector &result) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t a_blob, string_t b_blob) -> int32_t { + Temporal *a = BlobToTemporal(a_blob); + Temporal *b = BlobToTemporal(b_blob); + int32_t r = nad_tint_tint(a, b); + free(a); free(b); + return r; + }); +} +void TemporalFunctions::Nad_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t blob, double d) -> double { + Temporal *t = BlobToTemporal(blob); + double r = nad_tfloat_float(t, d); + free(t); + return r; + }); +} +void TemporalFunctions::Nad_tfloat_tfloat(DataChunk &args, ExpressionState &state, Vector &result) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t a_blob, string_t b_blob) -> double { + Temporal *a = BlobToTemporal(a_blob); + Temporal *b = BlobToTemporal(b_blob); + double r = nad_tfloat_tfloat(a, b); + free(a); free(b); + return r; + }); +} + +/* *************************************************** + * Temporal topological predicates + ****************************************************/ + +namespace { + +template +void TempTempBoolPred(DataChunk &args, Vector &result, Fn fn) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t a_blob, string_t b_blob) -> bool { + Temporal *a = BlobToTemporal(a_blob); + Temporal *b = BlobToTemporal(b_blob); + bool r = fn(a, b); + free(a); free(b); + return r; + }); +} + +template +void TempSpanBoolPred(DataChunk &args, Vector &result, Fn fn) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t blob, string_t span_blob) -> bool { + Temporal *t = BlobToTemporal(blob); + // Spans are blobs of fixed size; copy into a Span struct. + Span *s = (Span *)malloc(span_blob.GetSize()); + memcpy(s, span_blob.GetData(), span_blob.GetSize()); + bool r = fn(t, s); + free(t); free(s); + return r; + }); +} + +template +void SpanTempBoolPred(DataChunk &args, Vector &result, Fn fn) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t span_blob, string_t blob) -> bool { + Span *s = (Span *)malloc(span_blob.GetSize()); + memcpy(s, span_blob.GetData(), span_blob.GetSize()); + Temporal *t = BlobToTemporal(blob); + bool r = fn(s, t); + free(s); free(t); + return r; + }); +} + +} // namespace + +void TemporalFunctions::Contains_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempBoolPred(args, result, [](Temporal *a, Temporal *b) { return contains_temporal_temporal(a, b); }); +} +void TemporalFunctions::Contained_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempBoolPred(args, result, [](Temporal *a, Temporal *b) { return contained_temporal_temporal(a, b); }); +} +void TemporalFunctions::Overlaps_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempBoolPred(args, result, [](Temporal *a, Temporal *b) { return overlaps_temporal_temporal(a, b); }); +} +void TemporalFunctions::Adjacent_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempBoolPred(args, result, [](Temporal *a, Temporal *b) { return adjacent_temporal_temporal(a, b); }); +} + +void TemporalFunctions::Contains_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempSpanBoolPred(args, result, [](Temporal *t, Span *s) { return contains_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::Contained_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempSpanBoolPred(args, result, [](Temporal *t, Span *s) { return contained_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::Overlaps_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempSpanBoolPred(args, result, [](Temporal *t, Span *s) { return overlaps_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::Adjacent_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempSpanBoolPred(args, result, [](Temporal *t, Span *s) { return adjacent_temporal_tstzspan(t, s); }); +} + +// Span-temporal direction: MEOS only exposes the temporal-span functions, +// so we swap arg order and use the inverse op (contains <-> contained). +void TemporalFunctions::Contains_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + SpanTempBoolPred(args, result, [](Span *s, Temporal *t) { return contained_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::Contained_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + SpanTempBoolPred(args, result, [](Span *s, Temporal *t) { return contains_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::Overlaps_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + SpanTempBoolPred(args, result, [](Span *s, Temporal *t) { return overlaps_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::Adjacent_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + SpanTempBoolPred(args, result, [](Span *s, Temporal *t) { return adjacent_temporal_tstzspan(t, s); }); +} + +/* *************************************************** + * Temporal time-position predicates + ****************************************************/ + +void TemporalFunctions::Before_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempBoolPred(args, result, [](Temporal *a, Temporal *b) { return before_temporal_temporal(a, b); }); +} +void TemporalFunctions::After_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempBoolPred(args, result, [](Temporal *a, Temporal *b) { return after_temporal_temporal(a, b); }); +} +void TemporalFunctions::Overbefore_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempBoolPred(args, result, [](Temporal *a, Temporal *b) { return overbefore_temporal_temporal(a, b); }); +} +void TemporalFunctions::Overafter_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempBoolPred(args, result, [](Temporal *a, Temporal *b) { return overafter_temporal_temporal(a, b); }); +} + +void TemporalFunctions::Before_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempSpanBoolPred(args, result, [](Temporal *t, Span *s) { return before_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::After_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempSpanBoolPred(args, result, [](Temporal *t, Span *s) { return after_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::Overbefore_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempSpanBoolPred(args, result, [](Temporal *t, Span *s) { return overbefore_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::Overafter_temporal_tstzspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempSpanBoolPred(args, result, [](Temporal *t, Span *s) { return overafter_temporal_tstzspan(t, s); }); +} + +// Reverse direction: tstzspan op temporal — swap inverse op, +// e.g. `tstzspan <<# temporal` (span is before temporal) means +// the temporal is after the span: after_temporal_tstzspan(t, s). +void TemporalFunctions::Before_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + SpanTempBoolPred(args, result, [](Span *s, Temporal *t) { return after_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::After_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + SpanTempBoolPred(args, result, [](Span *s, Temporal *t) { return before_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::Overbefore_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + SpanTempBoolPred(args, result, [](Span *s, Temporal *t) { return overafter_temporal_tstzspan(t, s); }); +} +void TemporalFunctions::Overafter_tstzspan_temporal(DataChunk &args, ExpressionState &state, Vector &result) { + SpanTempBoolPred(args, result, [](Span *s, Temporal *t) { return overbefore_temporal_tstzspan(t, s); }); +} + +/* *************************************************** + * Ever / always equality and inequality + ****************************************************/ + +namespace { + +// MEOS ever/always functions return int (1=true, 0=false, -1=null/error). +template +void EverAlwaysValTemp(DataChunk &args, Vector &result, Fn fn) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](TVal v, string_t blob) -> bool { + Temporal *t = BlobToTemporal(blob); + int r = fn(v, t); + free(t); + return r > 0; + }); +} + +template +void EverAlwaysTempVal(DataChunk &args, Vector &result, Fn fn) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t blob, TVal v) -> bool { + Temporal *t = BlobToTemporal(blob); + int r = fn(t, v); + free(t); + return r > 0; + }); +} + +template +void EverAlwaysTempTemp(DataChunk &args, Vector &result, Fn fn) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t a_blob, string_t b_blob) -> bool { + Temporal *a = BlobToTemporal(a_blob); + Temporal *b = BlobToTemporal(b_blob); + int r = fn(a, b); + free(a); free(b); + return r > 0; + }); +} + +} // namespace + +#define DEFINE_EA_OP(NAME, MEOS_NAME) \ +void TemporalFunctions::NAME##_bool_tbool(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysValTemp(args, result, [](bool b, Temporal *t) { return MEOS_NAME##_bool_tbool(b, t); }); \ +} \ +void TemporalFunctions::NAME##_tbool_bool(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysTempVal(args, result, [](Temporal *t, bool b) { return MEOS_NAME##_tbool_bool(t, b); }); \ +} \ +void TemporalFunctions::NAME##_int_tint(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysValTemp(args, result, [](int32_t i, Temporal *t) { return MEOS_NAME##_int_tint(i, t); }); \ +} \ +void TemporalFunctions::NAME##_tint_int(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysTempVal(args, result, [](Temporal *t, int32_t i) { return MEOS_NAME##_tint_int(t, i); }); \ +} \ +void TemporalFunctions::NAME##_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysValTemp(args, result, [](double d, Temporal *t) { return MEOS_NAME##_float_tfloat(d, t); }); \ +} \ +void TemporalFunctions::NAME##_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysTempVal(args, result, [](Temporal *t, double d) { return MEOS_NAME##_tfloat_float(t, d); }); \ +} \ +void TemporalFunctions::NAME##_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysTempTemp(args, result, [](Temporal *a, Temporal *b) { return MEOS_NAME##_temporal_temporal(a, b); }); \ +} + +DEFINE_EA_OP(Ever_eq, ever_eq) +DEFINE_EA_OP(Always_eq, always_eq) +DEFINE_EA_OP(Ever_ne, ever_ne) +DEFINE_EA_OP(Always_ne, always_ne) + +#undef DEFINE_EA_OP + +// Ordering ops have no tbool variant. +#define DEFINE_EA_ORD_OP(NAME, MEOS_NAME) \ +void TemporalFunctions::NAME##_int_tint(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysValTemp(args, result, [](int32_t i, Temporal *t) { return MEOS_NAME##_int_tint(i, t); }); \ +} \ +void TemporalFunctions::NAME##_tint_int(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysTempVal(args, result, [](Temporal *t, int32_t i) { return MEOS_NAME##_tint_int(t, i); }); \ +} \ +void TemporalFunctions::NAME##_float_tfloat(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysValTemp(args, result, [](double d, Temporal *t) { return MEOS_NAME##_float_tfloat(d, t); }); \ +} \ +void TemporalFunctions::NAME##_tfloat_float(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysTempVal(args, result, [](Temporal *t, double d) { return MEOS_NAME##_tfloat_float(t, d); }); \ +} \ +void TemporalFunctions::NAME##_temporal_temporal(DataChunk &args, ExpressionState &state, Vector &result) { \ + EverAlwaysTempTemp(args, result, [](Temporal *a, Temporal *b) { return MEOS_NAME##_temporal_temporal(a, b); }); \ +} + +DEFINE_EA_ORD_OP(Ever_lt, ever_lt) +DEFINE_EA_ORD_OP(Always_lt, always_lt) +DEFINE_EA_ORD_OP(Ever_le, ever_le) +DEFINE_EA_ORD_OP(Always_le, always_le) +DEFINE_EA_ORD_OP(Ever_gt, ever_gt) +DEFINE_EA_ORD_OP(Always_gt, always_gt) +DEFINE_EA_ORD_OP(Ever_ge, ever_ge) +DEFINE_EA_ORD_OP(Always_ge, always_ge) + +#undef DEFINE_EA_ORD_OP + +/* *************************************************** + * Similarity measures + ****************************************************/ + +namespace { + +template +void TempTempDoublePred(DataChunk &args, Vector &result, Fn fn) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t a_blob, string_t b_blob) -> double { + Temporal *a = BlobToTemporal(a_blob); + Temporal *b = BlobToTemporal(b_blob); + double r = fn(a, b); + free(a); free(b); + return r; + }); +} + +} // namespace + +void TemporalFunctions::Temporal_frechet_distance(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempDoublePred(args, result, [](Temporal *a, Temporal *b) { return temporal_frechet_distance(a, b); }); +} +void TemporalFunctions::Temporal_dyntimewarp_distance(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempDoublePred(args, result, [](Temporal *a, Temporal *b) { return temporal_dyntimewarp_distance(a, b); }); +} +void TemporalFunctions::Temporal_hausdorff_distance(DataChunk &args, ExpressionState &state, Vector &result) { + TempTempDoublePred(args, result, [](Temporal *a, Temporal *b) { return temporal_hausdorff_distance(a, b); }); +} + +/* *************************************************** + * tnumber × {numspan, tbox} topological predicates + ****************************************************/ + +namespace { + +template +void TempBoxBoolPred(DataChunk &args, Vector &result, Fn fn) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t blob, string_t box_blob) -> bool { + Temporal *t = BlobToTemporal(blob); + Box *b = (Box *)malloc(box_blob.GetSize()); + memcpy(b, box_blob.GetData(), box_blob.GetSize()); + bool r = fn(t, b); + free(t); free(b); + return r; + }); +} + +template +void BoxTempBoolPred(DataChunk &args, Vector &result, Fn fn) { + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), + [&](string_t box_blob, string_t blob) -> bool { + Box *b = (Box *)malloc(box_blob.GetSize()); + memcpy(b, box_blob.GetData(), box_blob.GetSize()); + Temporal *t = BlobToTemporal(blob); + bool r = fn(b, t); + free(b); free(t); + return r; + }); +} + +} // namespace + +// tnumber × numspan (uses Span) +void TemporalFunctions::Contains_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempBoxBoolPred(args, result, [](Temporal *t, Span *s) { return contains_tnumber_numspan(t, s); }); +} +void TemporalFunctions::Contained_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempBoxBoolPred(args, result, [](Temporal *t, Span *s) { return contained_tnumber_numspan(t, s); }); +} +void TemporalFunctions::Overlaps_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempBoxBoolPred(args, result, [](Temporal *t, Span *s) { return overlaps_tnumber_numspan(t, s); }); +} +void TemporalFunctions::Adjacent_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result) { + TempBoxBoolPred(args, result, [](Temporal *t, Span *s) { return adjacent_tnumber_numspan(t, s); }); +} +// numspan × tnumber +void TemporalFunctions::Contains_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + BoxTempBoolPred(args, result, [](Span *s, Temporal *t) { return contains_numspan_tnumber(s, t); }); +} +void TemporalFunctions::Contained_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + BoxTempBoolPred(args, result, [](Span *s, Temporal *t) { return contained_numspan_tnumber(s, t); }); +} +void TemporalFunctions::Overlaps_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + BoxTempBoolPred(args, result, [](Span *s, Temporal *t) { return overlaps_numspan_tnumber(s, t); }); +} +void TemporalFunctions::Adjacent_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + BoxTempBoolPred(args, result, [](Span *s, Temporal *t) { return adjacent_numspan_tnumber(s, t); }); +} +// tnumber × tbox (uses TBox) +void TemporalFunctions::Contains_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result) { + TempBoxBoolPred(args, result, [](Temporal *t, TBox *b) { return contains_tnumber_tbox(t, b); }); +} +void TemporalFunctions::Contained_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result) { + TempBoxBoolPred(args, result, [](Temporal *t, TBox *b) { return contained_tnumber_tbox(t, b); }); +} +void TemporalFunctions::Overlaps_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result) { + TempBoxBoolPred(args, result, [](Temporal *t, TBox *b) { return overlaps_tnumber_tbox(t, b); }); +} +void TemporalFunctions::Adjacent_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result) { + TempBoxBoolPred(args, result, [](Temporal *t, TBox *b) { return adjacent_tnumber_tbox(t, b); }); +} +// tbox × tnumber +void TemporalFunctions::Contains_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + BoxTempBoolPred(args, result, [](TBox *b, Temporal *t) { return contains_tbox_tnumber(b, t); }); +} +void TemporalFunctions::Contained_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + BoxTempBoolPred(args, result, [](TBox *b, Temporal *t) { return contained_tbox_tnumber(b, t); }); +} +void TemporalFunctions::Overlaps_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + BoxTempBoolPred(args, result, [](TBox *b, Temporal *t) { return overlaps_tbox_tnumber(b, t); }); +} +void TemporalFunctions::Adjacent_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { + BoxTempBoolPred(args, result, [](TBox *b, Temporal *t) { return adjacent_tbox_tnumber(b, t); }); +} + +/* *************************************************** + * tnumber × {numspan, tbox} position predicates + ****************************************************/ + +#define DEFINE_NUMSPAN_POS(NAME, MEOS_FN) \ +void TemporalFunctions::NAME##_tnumber_numspan(DataChunk &args, ExpressionState &state, Vector &result) { \ + TempBoxBoolPred(args, result, [](Temporal *t, Span *s) { return MEOS_FN##_tnumber_numspan(t, s); }); \ +} \ +void TemporalFunctions::NAME##_numspan_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { \ + BoxTempBoolPred(args, result, [](Span *s, Temporal *t) { return MEOS_FN##_numspan_tnumber(s, t); }); \ +} + +#define DEFINE_TBOX_POS(NAME, MEOS_FN) \ +void TemporalFunctions::NAME##_tnumber_tbox(DataChunk &args, ExpressionState &state, Vector &result) { \ + TempBoxBoolPred(args, result, [](Temporal *t, TBox *b) { return MEOS_FN##_tnumber_tbox(t, b); }); \ +} \ +void TemporalFunctions::NAME##_tbox_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { \ + BoxTempBoolPred(args, result, [](TBox *b, Temporal *t) { return MEOS_FN##_tbox_tnumber(b, t); }); \ +} + +#define DEFINE_TNUM_POS(NAME, MEOS_FN) \ +void TemporalFunctions::NAME##_tnumber_tnumber(DataChunk &args, ExpressionState &state, Vector &result) { \ + TempTempBoolPred(args, result, [](Temporal *a, Temporal *b) { return MEOS_FN##_tnumber_tnumber(a, b); }); \ +} + +DEFINE_NUMSPAN_POS(Left, left) +DEFINE_NUMSPAN_POS(Right, right) +DEFINE_NUMSPAN_POS(Overleft, overleft) +DEFINE_NUMSPAN_POS(Overright, overright) +DEFINE_TBOX_POS(Left, left) +DEFINE_TBOX_POS(Right, right) +DEFINE_TBOX_POS(Overleft, overleft) +DEFINE_TBOX_POS(Overright, overright) +DEFINE_TNUM_POS(Left, left) +DEFINE_TNUM_POS(Right, right) +DEFINE_TNUM_POS(Overleft, overleft) +DEFINE_TNUM_POS(Overright, overright) + +#undef DEFINE_NUMSPAN_POS +#undef DEFINE_TBOX_POS +#undef DEFINE_TNUM_POS + +/* *************************************************** + * tspatial × {stbox, tspatial} position predicates + ****************************************************/ + +#define DEFINE_TSPATIAL_STBOX_POS(NAME, MEOS_FN) \ +void TemporalFunctions::NAME##_tspatial_stbox(DataChunk &args, ExpressionState &state, Vector &result) { \ + TempBoxBoolPred(args, result, [](Temporal *t, STBox *b) { return MEOS_FN##_tspatial_stbox(t, b); }); \ +} \ +void TemporalFunctions::NAME##_stbox_tspatial(DataChunk &args, ExpressionState &state, Vector &result) { \ + BoxTempBoolPred(args, result, [](STBox *b, Temporal *t) { return MEOS_FN##_stbox_tspatial(b, t); }); \ +} \ +void TemporalFunctions::NAME##_tspatial_tspatial(DataChunk &args, ExpressionState &state, Vector &result) { \ + TempTempBoolPred(args, result, [](Temporal *a, Temporal *b) { return MEOS_FN##_tspatial_tspatial(a, b); }); \ +} + +DEFINE_TSPATIAL_STBOX_POS(Left, left) +DEFINE_TSPATIAL_STBOX_POS(Right, right) +DEFINE_TSPATIAL_STBOX_POS(Below, below) +DEFINE_TSPATIAL_STBOX_POS(Above, above) +DEFINE_TSPATIAL_STBOX_POS(Front, front) +DEFINE_TSPATIAL_STBOX_POS(Back, back) +DEFINE_TSPATIAL_STBOX_POS(Overleft, overleft) +DEFINE_TSPATIAL_STBOX_POS(Overright, overright) +DEFINE_TSPATIAL_STBOX_POS(Overbelow, overbelow) +DEFINE_TSPATIAL_STBOX_POS(Overabove, overabove) +DEFINE_TSPATIAL_STBOX_POS(Overfront, overfront) +DEFINE_TSPATIAL_STBOX_POS(Overback, overback) + +#undef DEFINE_TSPATIAL_STBOX_POS + /* *************************************************** * Text functions on ttext ****************************************************/