diff --git a/src/geo/stbox.cpp b/src/geo/stbox.cpp index 3b667360..e38f184a 100644 --- a/src/geo/stbox.cpp +++ b/src/geo/stbox.cpp @@ -4,6 +4,9 @@ #include "geo/stbox.hpp" #include "geo/stbox_functions.hpp" #include "geo/tgeompoint.hpp" +#include "geo/tgeogpoint.hpp" +#include "geo/tgeometry.hpp" +#include "geo/tgeography.hpp" #include "duckdb/common/types/blob.hpp" #include "duckdb/function/function.hpp" @@ -377,7 +380,7 @@ void StboxType::RegisterScalarFunctions(ExtensionLoader &loader) { ) ); - duckdb::RegisterSerializedScalarFunction(loader, + duckdb::RegisterSerializedScalarFunction(loader, ScalarFunction( "expandSpace", {STBOX(), LogicalType::DOUBLE}, @@ -386,7 +389,33 @@ void StboxType::RegisterScalarFunctions(ExtensionLoader &loader) { ) ); - duckdb::RegisterSerializedScalarFunction(loader, + duckdb::RegisterSerializedScalarFunction(loader, + ScalarFunction( + "expandSpace", + {GeoTypes::GEOMETRY(), LogicalType::DOUBLE}, + STBOX(), + StboxFunctions::Geo_expand_space + ) + ); + + { + const auto D = LogicalType::DOUBLE; + const auto B = STBOX(); + const auto P = TgeompointType::TGEOMPOINT(); + const auto GP = TgeogpointType::TGEOGPOINT(); + const auto TGM = TGeometryTypes::TGEOMETRY(); + const auto TGG = TGeographyTypes::TGEOGRAPHY(); + duckdb::RegisterSerializedScalarFunction(loader, + ScalarFunction("expandSpace", {P, D}, B, StboxFunctions::Tspatial_expand_space)); + duckdb::RegisterSerializedScalarFunction(loader, + ScalarFunction("expandSpace", {GP, D}, B, StboxFunctions::Tspatial_expand_space)); + duckdb::RegisterSerializedScalarFunction(loader, + ScalarFunction("expandSpace", {TGM, D}, B, StboxFunctions::Tspatial_expand_space)); + duckdb::RegisterSerializedScalarFunction(loader, + ScalarFunction("expandSpace", {TGG, D}, B, StboxFunctions::Tspatial_expand_space)); + } + + duckdb::RegisterSerializedScalarFunction(loader, ScalarFunction( "stbox_contains", {STBOX(), STBOX()}, diff --git a/src/geo/stbox_functions.cpp b/src/geo/stbox_functions.cpp index b5398f02..25347f48 100644 --- a/src/geo/stbox_functions.cpp +++ b/src/geo/stbox_functions.cpp @@ -1419,6 +1419,84 @@ void StboxFunctions::Stbox_expand_space(DataChunk &args, ExpressionState &state, } } +void StboxFunctions::Geo_expand_space(DataChunk &args, ExpressionState &state, Vector &result) { + BinaryExecutor::ExecuteWithNulls( + args.data[0], args.data[1], result, args.size(), + [&](string_t geometry_blob, double d, ValidityMask &mask, idx_t idx) -> string_t { + int32 srid = 0; + GSERIALIZED *gs = GeometryToGSerialized(geometry_blob, srid); + if (!gs) { + throw InvalidInputException("Invalid geometry format in Geo_expand_space"); + } + STBox *box = geo_to_stbox(gs); + free(gs); + if (!box) { + mask.SetInvalid(idx); + return string_t(); + } + STBox *ret = stbox_expand_space(box, d); + free(box); + if (!ret) { + mask.SetInvalid(idx); + return string_t(); + } + size_t stbox_size = sizeof(STBox); + uint8_t *stbox_data = (uint8_t*)malloc(stbox_size); + if (!stbox_data) { + free(ret); + throw InternalException("Failure in Geo_expand_space: unable to allocate memory for stbox"); + } + memcpy(stbox_data, ret, stbox_size); + string_t ret_str(reinterpret_cast(stbox_data), stbox_size); + string_t stored_data = StringVector::AddStringOrBlob(result, ret_str); + free(stbox_data); + free(ret); + return stored_data; + } + ); +} + +void StboxFunctions::Tspatial_expand_space(DataChunk &args, ExpressionState &state, Vector &result) { + BinaryExecutor::ExecuteWithNulls( + args.data[0], args.data[1], result, args.size(), + [&](string_t input_blob, double d, ValidityMask &mask, idx_t idx) -> string_t { + const uint8_t *data = reinterpret_cast(input_blob.GetData()); + size_t data_size = input_blob.GetSize(); + uint8_t *data_copy = (uint8_t*)malloc(data_size); + memcpy(data_copy, data, data_size); + Temporal *temp = reinterpret_cast(data_copy); + if (!temp) { + free(data_copy); + throw InvalidInputException("Invalid temporal value in Tspatial_expand_space"); + } + STBox *box = tspatial_to_stbox(temp); + free(temp); + if (!box) { + mask.SetInvalid(idx); + return string_t(); + } + STBox *ret = stbox_expand_space(box, d); + free(box); + if (!ret) { + mask.SetInvalid(idx); + return string_t(); + } + size_t stbox_size = sizeof(STBox); + uint8_t *stbox_data = (uint8_t*)malloc(stbox_size); + if (!stbox_data) { + free(ret); + throw InternalException("Failure in Tspatial_expand_space: unable to allocate memory for stbox"); + } + memcpy(stbox_data, ret, stbox_size); + string_t ret_str(reinterpret_cast(stbox_data), stbox_size); + string_t stored_data = StringVector::AddStringOrBlob(result, ret_str); + free(stbox_data); + free(ret); + return stored_data; + } + ); +} + /* *************************************************** * Topological operators ****************************************************/ diff --git a/src/include/geo/stbox_functions.hpp b/src/include/geo/stbox_functions.hpp index 2bd041f5..eb10f038 100644 --- a/src/include/geo/stbox_functions.hpp +++ b/src/include/geo/stbox_functions.hpp @@ -89,6 +89,8 @@ struct StboxFunctions { static void Stbox_shift_scale_time(DataChunk &args, ExpressionState &state, Vector &result); static void Stbox_get_space(DataChunk &args, ExpressionState &state, Vector &result); static void Stbox_expand_space(DataChunk &args, ExpressionState &state, Vector &result); + static void Geo_expand_space(DataChunk &args, ExpressionState &state, Vector &result); + static void Tspatial_expand_space(DataChunk &args, ExpressionState &state, Vector &result); static void Stbox_expand_time(DataChunk &args, ExpressionState &state, Vector &result); /* *************************************************** diff --git a/src/include/temporal/temporal_functions.hpp b/src/include/temporal/temporal_functions.hpp index bbb895c3..6a791493 100644 --- a/src/include/temporal/temporal_functions.hpp +++ b/src/include/temporal/temporal_functions.hpp @@ -232,6 +232,9 @@ struct TemporalFunctions { static void Tfloat_exp(DataChunk &args, ExpressionState &state, Vector &result); static void Tfloat_ln(DataChunk &args, ExpressionState &state, Vector &result); static void Tfloat_log10(DataChunk &args, ExpressionState &state, Vector &result); + static void Tfloat_sin(DataChunk &args, ExpressionState &state, Vector &result); + static void Tfloat_cos(DataChunk &args, ExpressionState &state, Vector &result); + static void Tfloat_tan(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); diff --git a/src/temporal/temporal.cpp b/src/temporal/temporal.cpp index 9abf2973..b5c59d9e 100644 --- a/src/temporal/temporal.cpp +++ b/src/temporal/temporal.cpp @@ -1367,6 +1367,9 @@ void TemporalTypes::RegisterScalarFunctions(ExtensionLoader &loader) { duckdb::RegisterSerializedScalarFunction(loader, ScalarFunction("exp", {TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Tfloat_exp)); duckdb::RegisterSerializedScalarFunction(loader, ScalarFunction("ln", {TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Tfloat_ln)); duckdb::RegisterSerializedScalarFunction(loader, ScalarFunction("log10", {TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Tfloat_log10)); + duckdb::RegisterSerializedScalarFunction(loader, ScalarFunction("sin", {TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Tfloat_sin)); + duckdb::RegisterSerializedScalarFunction(loader, ScalarFunction("cos", {TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Tfloat_cos)); + duckdb::RegisterSerializedScalarFunction(loader, ScalarFunction("tan", {TemporalTypes::TFLOAT()}, TemporalTypes::TFLOAT(), TemporalFunctions::Tfloat_tan)); // deltaValue / trend on tnumber duckdb::RegisterSerializedScalarFunction(loader, ScalarFunction("deltaValue", {TemporalTypes::TINT()}, TemporalTypes::TINT(), TemporalFunctions::Tnumber_delta_value)); diff --git a/src/temporal/temporal_functions.cpp b/src/temporal/temporal_functions.cpp index fc8a2b68..5b110e00 100644 --- a/src/temporal/temporal_functions.cpp +++ b/src/temporal/temporal_functions.cpp @@ -4816,6 +4816,18 @@ void TemporalFunctions::Tfloat_log10(DataChunk &args, ExpressionState &state, Ve TemporalUnary(args, result, [](Temporal *t) { return tfloat_log10(t); }); } +void TemporalFunctions::Tfloat_sin(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalUnary(args, result, [](Temporal *t) { return tfloat_sin(t); }); +} + +void TemporalFunctions::Tfloat_cos(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalUnary(args, result, [](Temporal *t) { return tfloat_cos(t); }); +} + +void TemporalFunctions::Tfloat_tan(DataChunk &args, ExpressionState &state, Vector &result) { + TemporalUnary(args, result, [](Temporal *t) { return tfloat_tan(t); }); +} + namespace { template diff --git a/test/sql/parity/026c_tfloat_trig.test b/test/sql/parity/026c_tfloat_trig.test new file mode 100644 index 00000000..1ede88d3 --- /dev/null +++ b/test/sql/parity/026c_tfloat_trig.test @@ -0,0 +1,56 @@ +# name: test/sql/parity/026c_tfloat_trig.test +# description: Trigonometric lifts for tfloat — sin, cos, tan. +# group: [sql] + +require mobilityduck + +# Instant: sin(0) = 0 +query I +SELECT sin(tfloat '[0@2000-01-01]'); +---- +[0@2000-01-01 00:00:00+01] + +# Instant: cos(0) = 1 +query I +SELECT cos(tfloat '[0@2000-01-01]'); +---- +[1@2000-01-01 00:00:00+01] + +# Instant: tan(0) = 0 +query I +SELECT tan(tfloat '[0@2000-01-01]'); +---- +[0@2000-01-01 00:00:00+01] + +# Sequence endpoints: sin lifted over [0, pi/2] starts at 0 and ends at 1 +query I +SELECT round(startValue(sin(tfloat '[0@2000-01-01, 1.5707963267948966@2000-01-02]')), 6); +---- +0.0 + +query I +SELECT round(endValue(sin(tfloat '[0@2000-01-01, 1.5707963267948966@2000-01-02]')), 6); +---- +1.0 + +# Sequence endpoints: cos lifted over [0, pi/2] starts at 1 and ends at 0 +query I +SELECT round(startValue(cos(tfloat '[0@2000-01-01, 1.5707963267948966@2000-01-02]')), 6); +---- +1.0 + +query I +SELECT round(endValue(cos(tfloat '[0@2000-01-01, 1.5707963267948966@2000-01-02]')), 6); +---- +0.0 + +# Sequence endpoints: tan lifted over [0, pi/4] starts at 0 and ends at 1 +query I +SELECT round(startValue(tan(tfloat '[0@2000-01-01, 0.7853981633974483@2000-01-02]')), 6); +---- +0.0 + +query I +SELECT round(endValue(tan(tfloat '[0@2000-01-01, 0.7853981633974483@2000-01-02]')), 6); +---- +1.0 diff --git a/test/sql/stbox.test b/test/sql/stbox.test index 87b4dcc7..a6d96dfa 100644 --- a/test/sql/stbox.test +++ b/test/sql/stbox.test @@ -101,6 +101,31 @@ SELECT expandSpace(stbox 'STBOX XT(((1.0,1.0),(2.0,2.0)),[2000-01-01,2000-01-01] ---- STBOX XT(((1.5,1.5),(1.5,1.5)),[2000-01-01 00:00:00+01, 2000-01-01 00:00:00+01]) +query I +SELECT expandSpace(ST_Point(1.0, 2.0), 1.0); +---- +STBOX X((0,1),(2,3)) + +query I +SELECT expandSpace(tgeompoint '[Point(0 0)@2000-01-01, Point(2 2)@2000-01-02]', 1.0); +---- +STBOX XT(((-1,-1),(3,3)),[2000-01-01 00:00:00+01, 2000-01-02 00:00:00+01]) + +query I +SELECT expandSpace(tgeogpoint '[Point(0 0)@2000-01-01, Point(2 2)@2000-01-02]', 1.0); +---- +SRID=4326;GEODSTBOX XT(((-1,-1),(3,3)),[2000-01-01 00:00:00+01, 2000-01-02 00:00:00+01]) + +query I +SELECT expandSpace(tgeometry '[Point(0 0)@2000-01-01, Point(2 2)@2000-01-02]', 1.0); +---- +STBOX XT(((-1,-1),(3,3)),[2000-01-01 00:00:00+01, 2000-01-02 00:00:00+01]) + +query I +SELECT expandSpace(tgeography '[Point(0 0)@2000-01-01, Point(2 2)@2000-01-02]', 1.0); +---- +SRID=4326;GEODSTBOX XT(((-1,-1),(3,3)),[2000-01-01 00:00:00+01, 2000-01-02 00:00:00+01]) + query I SELECT STBOX(ST_Point(1, 1)); ---- diff --git a/vcpkg_ports/meos/portfile.cmake b/vcpkg_ports/meos/portfile.cmake index fd0da052..738c9f17 100644 --- a/vcpkg_ports/meos/portfile.cmake +++ b/vcpkg_ports/meos/portfile.cmake @@ -1,8 +1,8 @@ vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO estebanzimanyi/MobilityDB - REF 278863520b000b735cc361beab88387174909ed7 - SHA512 2e617cac4bfed919eee8bd73e35f9b3da8ffd7a51f68104a9497c0d3339dbb1af4a2ec6feab3e8fffb880481badf86c352ad1efb39cab533de19d2c1192a8e5b + REF 59ba0ad59cb93db6fa46929394e475b7851c00be + SHA512 e6a4a1578e5760326a596248865ccb487850120ca423f5675d1f014e9146de4f407c699afa63a102d8ba4ef1f895946d206ee4ab2f870dc4508ec2ca3d771869 ) vcpkg_replace_string(