Skip to content
Closed
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
4 changes: 2 additions & 2 deletions src/geo/geoset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ void SpatialSetType::RegisterTypes(ExtensionLoader &loader){
}

void SpatialSetType::RegisterCastFunctions(ExtensionLoader &loader) {
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
LogicalType::VARCHAR,
SpatialSetType::geomset(),
SpatialSetFunctions::Text_to_geoset
);
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
LogicalType::VARCHAR,
SpatialSetType::geogset(),
SpatialSetFunctions::Text_to_geoset
Expand Down
14 changes: 7 additions & 7 deletions src/geo/stbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,43 +27,43 @@ void StboxType::RegisterType(ExtensionLoader &loader) {
}

void StboxType::RegisterCastFunctions(ExtensionLoader &loader) {
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
LogicalType::VARCHAR,
STBOX(),
StboxFunctions::Stbox_in_cast
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
STBOX(),
LogicalType::VARCHAR,
StboxFunctions::Stbox_out
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
GeoTypes::GEOMETRY(),
STBOX(),
StboxFunctions::Geo_to_stbox_cast
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
LogicalType::TIMESTAMP_TZ,
STBOX(),
StboxFunctions::Timestamptz_to_stbox_cast
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SetTypes::tstzset(),
STBOX(),
StboxFunctions::Tstzset_to_stbox_cast
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SpanTypes::TSTZSPAN(),
STBOX(),
StboxFunctions::Tstzspan_to_stbox_cast
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SpansetTypes::tstzspanset(),
STBOX(),
StboxFunctions::Tstzspanset_to_stbox_cast
Expand Down
8 changes: 4 additions & 4 deletions src/geo/tgeogpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,25 @@ void TgeogpointType::RegisterType(ExtensionLoader &loader) {
}

void TgeogpointType::RegisterCastFunctions(ExtensionLoader &loader) {
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
LogicalType::VARCHAR,
TGEOGPOINT(),
TgeogpointFunctions::Tpoint_in
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
TGEOGPOINT(),
LogicalType::VARCHAR,
TemporalFunctions::Temporal_out
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
TGEOGPOINT(),
StboxType::STBOX(),
TgeompointFunctions::Tspatial_to_stbox_cast
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
TGEOGPOINT(),
SpanTypes::TSTZSPAN(),
TgeompointFunctions::Temporal_to_tstzspan_cast
Expand Down
5 changes: 3 additions & 2 deletions src/geo/tgeogpoint_in_out.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "geo/tgeogpoint.hpp"
#include "geo/tgeogpoint_functions.hpp"
#include "mobilityduck/meos_exec_serial.hpp"
#include "duckdb/main/extension/extension_loader.hpp"
#include "duckdb/common/extension_type_info.hpp"
#include <regex>
Expand Down Expand Up @@ -215,8 +216,8 @@ void TGeogpointType::RegisterScalarInOutFunctions(ExtensionLoader &loader){


void TGeogpointType::RegisterCastFunctions(ExtensionLoader &loader) {
loader.RegisterCastFunction( LogicalType::VARCHAR, TGeogpointType::TGEOGPOINT(), TgeogpointFunctions::StringToTgeogpoint);
loader.RegisterCastFunction( TGeogpointType::TGEOGPOINT(), LogicalType::VARCHAR, TgeogpointFunctions::TgeogpointToString);
RegisterMeosCastFunction(loader, LogicalType::VARCHAR, TGeogpointType::TGEOGPOINT(), TgeogpointFunctions::StringToTgeogpoint);
RegisterMeosCastFunction(loader, TGeogpointType::TGEOGPOINT(), LogicalType::VARCHAR, TgeogpointFunctions::TgeogpointToString);
}

}
4 changes: 2 additions & 2 deletions src/geo/tgeography_in_out.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ void TGeographyTypes::RegisterScalarInOutFunctions(ExtensionLoader &loader){


void TGeographyTypes::RegisterCastFunctions(ExtensionLoader &loader) {
loader.RegisterCastFunction( LogicalType::VARCHAR, TGeographyTypes::TGEOGRAPHY(), TgeographyFunctions::StringToTgeography);
loader.RegisterCastFunction( TGeographyTypes::TGEOGRAPHY(), LogicalType::VARCHAR, TgeographyFunctions::TgeographyToString);
RegisterMeosCastFunction(loader, LogicalType::VARCHAR, TGeographyTypes::TGEOGRAPHY(), TgeographyFunctions::StringToTgeography);
RegisterMeosCastFunction(loader, TGeographyTypes::TGEOGRAPHY(), LogicalType::VARCHAR, TgeographyFunctions::TgeographyToString);
}

}
4 changes: 2 additions & 2 deletions src/geo/tgeometry_in_out.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,8 @@ void TGeometryTypes::RegisterScalarInOutFunctions(ExtensionLoader &loader){


void TGeometryTypes::RegisterCastFunctions(ExtensionLoader &loader) {
loader.RegisterCastFunction( LogicalType::VARCHAR, TGeometryTypes::TGEOMETRY(), TgeometryFunctions::StringToTgeometry);
loader.RegisterCastFunction( TGeometryTypes::TGEOMETRY(), LogicalType::VARCHAR, TgeometryFunctions::TgeometryToString);
RegisterMeosCastFunction(loader, LogicalType::VARCHAR, TGeometryTypes::TGEOMETRY(), TgeometryFunctions::StringToTgeometry);
RegisterMeosCastFunction(loader, TGeometryTypes::TGEOMETRY(), LogicalType::VARCHAR, TgeometryFunctions::TgeometryToString);
}

}
8 changes: 4 additions & 4 deletions src/geo/tgeompoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,25 @@ void TgeompointType::RegisterType(ExtensionLoader &loader) {
}

void TgeompointType::RegisterCastFunctions(ExtensionLoader &loader) {
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
LogicalType::VARCHAR,
TGEOMPOINT(),
TgeompointFunctions::Tpoint_in
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
TGEOMPOINT(),
LogicalType::VARCHAR,
TemporalFunctions::Temporal_out
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
TGEOMPOINT(),
StboxType::STBOX(),
TgeompointFunctions::Tspatial_to_stbox_cast
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
TGEOMPOINT(),
SpanTypes::TSTZSPAN(),
TgeompointFunctions::Temporal_to_tstzspan_cast
Expand Down
32 changes: 32 additions & 0 deletions src/include/mobilityduck/meos_exec_serial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

#include <mutex>

#include "duckdb/function/cast/default_casts.hpp"
#include "duckdb/function/scalar_function.hpp"
#include "duckdb/main/extension/extension_loader.hpp"
#include "mobilityduck/meos_thread.hpp"

namespace duckdb {

Expand All @@ -26,6 +28,7 @@ inline ScalarFunction WrapScalarFunctionWithMeosExecMutex(ScalarFunction sf) {
scalar_function_t orig = std::move(sf.function);
sf.function = [orig = std::move(orig)](DataChunk &args, ExpressionState &state, Vector &result) {
std::lock_guard<std::mutex> guard(MeosSerializedExecMutex());
EnsureMeosThreadInitialized();
orig(args, state, result);
};
return sf;
Expand All @@ -35,4 +38,33 @@ inline void RegisterSerializedScalarFunction(ExtensionLoader &loader, ScalarFunc
loader.RegisterFunction(WrapScalarFunctionWithMeosExecMutex(std::move(sf)));
}

/**
* Cast functions are a separate registration path from scalar functions and
* have no shared execution wrapper, yet they call MEOS just the same (e.g. the
* VARCHAR -> tgeompoint parse). The original function pointer is stashed in
* the bound cast data and reached through a trampoline that runs the
* per-thread MEOS init before delegating. MobilityDuck cast functions do not
* use cast_data themselves, so forwarding it untouched is safe.
*/
struct MeosCastData : BoundCastData {
explicit MeosCastData(cast_function_t orig_p) : orig(orig_p) {
}
cast_function_t orig;
unique_ptr<BoundCastData> Copy() const override {
return make_uniq<MeosCastData>(orig);
}
};

inline bool MeosCastTrampoline(Vector &source, Vector &result, idx_t count, CastParameters &parameters) {
EnsureMeosThreadInitialized();
auto &data = parameters.cast_data->Cast<MeosCastData>();
return data.orig(source, result, count, parameters);
}

inline void RegisterMeosCastFunction(ExtensionLoader &loader, const LogicalType &source, const LogicalType &target,
cast_function_t function, int64_t implicit_cast_cost = -1) {
loader.RegisterCastFunction(source, target, BoundCastInfo(MeosCastTrampoline, make_uniq<MeosCastData>(function)),
implicit_cast_cost);
}

} // namespace duckdb
34 changes: 34 additions & 0 deletions src/include/mobilityduck/meos_thread.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

extern "C" {
#include <meos.h>
}

// Defined in mobilityduck_extension.cpp. Converts MEOS errors into DuckDB
// exceptions instead of the process-exiting default handler.
extern "C" void MobilityduckMeosErrorHandler(int errlevel, int errcode, const char *errmsg);

namespace duckdb {

// MEOS keeps the session timezone, errno, PROJ context and the RNGs in
// thread-local storage; each thread that calls MEOS must initialise it
// before its first call (see meos.h, "Multithreading"). DuckDB runs
// scalar, cast and aggregate bodies on TaskScheduler worker threads, so a
// one-shot init on the load thread leaves workers with a NULL
// session_timezone and pg_next_dst_boundary segfaults on the first
// timestamp parse. This runs the per-thread init exactly once per thread.
//
// meos_initialize() resets the process-global error handler to the
// exit-on-error default, so MobilityduckMeosErrorHandler is re-installed
// here; the store is an idempotent atomic write of the same pointer.
inline void EnsureMeosThreadInitialized() {
static thread_local const bool meos_thread_ready = []() {
meos_initialize();
meos_initialize_error_handler(&MobilityduckMeosErrorHandler);
meos_initialize_timezone("Europe/Brussels");
return true;
}();
(void) meos_thread_ready;
}

} // namespace duckdb
14 changes: 7 additions & 7 deletions src/temporal/set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,43 +93,43 @@ LogicalType SetTypeMapping::GetChildType(const LogicalType &type) {
// Register all cast functions
void SetTypes::RegisterCastFunctions(ExtensionLoader &loader) {
for (const auto &set_type : SetTypes::AllTypes()) {
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
set_type,
LogicalType::VARCHAR,
SetFunctions::Set_to_text
); // Blob to text
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
LogicalType::VARCHAR,
set_type,
SetFunctions::Text_to_set
); // text to blob

auto base_type = SetTypeMapping::GetChildType(set_type);
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
base_type,
set_type,
SetFunctions::Value_to_set_cast // set from base type
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SetTypes::intset(),
SetTypes::floatset(),
SetFunctions::Intset_to_floatset_cast // intset -> floatset
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SetTypes::floatset(),
SetTypes::intset(),
SetFunctions::Floatset_to_intset_cast // floatset --> intset
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SetTypes::dateset(),
SetTypes::tstzset(),
SetFunctions::Dateset_to_tstzset_cast // dateset -> tstzset
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SetTypes::tstzset(),
SetTypes::dateset(),
SetFunctions::Tstzset_to_dateset_cast // tstz -> dateset
Expand Down
30 changes: 15 additions & 15 deletions src/temporal/span.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,68 +89,68 @@ LogicalType SpanTypeMapping::GetChildType(const LogicalType &type) {
// Register all cast functions
void SpanTypes::RegisterCastFunctions(ExtensionLoader &loader) {
for (const auto &span_type : SpanTypes::AllTypes()) {
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
span_type,
LogicalType::VARCHAR,
SpanFunctions::Span_to_text
); // Blob to text
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
LogicalType::VARCHAR,
span_type,
SpanFunctions::Text_to_span
); // text to blob

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SpanTypes::INTSPAN(),
SpanTypes::FLOATSPAN(),
SpanFunctions::Intspan_to_floatspan_cast // intspan -> floatspan
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SpanTypes::FLOATSPAN(),
SpanTypes::INTSPAN(),
SpanFunctions::Floatspan_to_intspan_cast // floatspan -> intspan
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SpanTypes::DATESPAN(),
SpanTypes::TSTZSPAN(),
SpanFunctions::Datespan_to_tstzspan_cast // datespan -> tstzspan
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SpanTypes::TSTZSPAN(),
SpanTypes::DATESPAN(),
SpanFunctions::Tstzspan_to_datespan_cast // tstzspan -> datespan
);

loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SetTypes::intset(),
SpanTypes::INTSPAN(),
SpanFunctions::Set_to_span_cast // intset -> intspan
);
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SetTypes::bigintset(),
SpanTypes::BIGINTSPAN(),
SpanFunctions::Set_to_span_cast // bigintset -> bigintspan
);
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SetTypes::floatset(),
SpanTypes::FLOATSPAN(),
SpanFunctions::Set_to_span_cast // floatset -> floatspan
);
loader.RegisterCastFunction(
RegisterMeosCastFunction(loader,
SetTypes::tstzset(),
SpanTypes::TSTZSPAN(),
SpanFunctions::Set_to_span_cast // tstzset -> tstzspan
);

// Scalar value -> span casts
loader.RegisterCastFunction(LogicalType::INTEGER, SpanTypes::INTSPAN(), SpanFunctions::Value_to_span_cast);
loader.RegisterCastFunction(LogicalType::BIGINT, SpanTypes::BIGINTSPAN(), SpanFunctions::Value_to_span_cast);
loader.RegisterCastFunction(LogicalType::DOUBLE, SpanTypes::FLOATSPAN(), SpanFunctions::Value_to_span_cast);
loader.RegisterCastFunction(LogicalType::DATE, SpanTypes::DATESPAN(), SpanFunctions::Value_to_span_cast);
loader.RegisterCastFunction(LogicalType::TIMESTAMP_TZ, SpanTypes::TSTZSPAN(), SpanFunctions::Value_to_span_cast);
RegisterMeosCastFunction(loader, LogicalType::INTEGER, SpanTypes::INTSPAN(), SpanFunctions::Value_to_span_cast);
RegisterMeosCastFunction(loader, LogicalType::BIGINT, SpanTypes::BIGINTSPAN(), SpanFunctions::Value_to_span_cast);
RegisterMeosCastFunction(loader, LogicalType::DOUBLE, SpanTypes::FLOATSPAN(), SpanFunctions::Value_to_span_cast);
RegisterMeosCastFunction(loader, LogicalType::DATE, SpanTypes::DATESPAN(), SpanFunctions::Value_to_span_cast);
RegisterMeosCastFunction(loader, LogicalType::TIMESTAMP_TZ, SpanTypes::TSTZSPAN(), SpanFunctions::Value_to_span_cast);
}
}

Expand Down
Loading
Loading