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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 11 additions & 37 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ endif()
# -----------------------------
# Dependencies (vcpkg)
# -----------------------------
find_package(GEOS CONFIG REQUIRED)
find_package(PROJ CONFIG REQUIRED)
find_package(GSL REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(GEOS CONFIG REQUIRED)
find_package(PROJ CONFIG REQUIRED)
find_package(GSL REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(json-c CONFIG QUIET)
if(NOT json-c_FOUND)
find_package(JSON-C REQUIRED)
find_package(JSON-C REQUIRED)
endif()

# MEOS from overlay port
find_package(MEOS CONFIG REQUIRED)
find_package(MEOS CONFIG REQUIRED)

if(TARGET GEOS::geos_c)
set(GEOS_TGT GEOS::geos_c)
Expand All @@ -54,7 +54,8 @@ set(LOADABLE_EXTENSION_NAME ${TARGET_NAME}_loadable_extension)
include_directories(src/include)

set(EXTENSION_SOURCES
src/mobilityduck_extension.cpp
src/spatial_ref_sys_csv.inc
src/mobilityduck_extension.cpp
src/temporal/temporal.cpp
src/temporal/temporal_functions.cpp
src/temporal/tbox.cpp
Expand All @@ -78,32 +79,10 @@ set(EXTENSION_SOURCES
build_static_extension(${TARGET_NAME} ${EXTENSION_SOURCES})
build_loadable_extension(${TARGET_NAME} "" ${EXTENSION_SOURCES})

# ----- SRID CSV defaults (works with/without vcpkg) -----
if(DEFINED VCPKG_INSTALLED_DIR AND DEFINED VCPKG_TARGET_TRIPLET)
target_compile_definitions(${EXTENSION_NAME} PRIVATE
MDUCK_DEFAULT_SRID_CSV="${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/spatial_ref_sys.csv"
MDUCK_SRID_ENV_NAME="SPATIAL_REF_SYS"
)
target_compile_definitions(${LOADABLE_EXTENSION_NAME} PRIVATE
MDUCK_DEFAULT_SRID_CSV="${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/spatial_ref_sys.csv"
MDUCK_SRID_ENV_NAME="SPATIAL_REF_SYS"
)
else()
target_compile_definitions(${EXTENSION_NAME} PRIVATE
MDUCK_DEFAULT_SRID_CSV="${CMAKE_SOURCE_DIR}/data/spatial_ref_sys.csv"
MDUCK_SRID_ENV_NAME="SPATIAL_REF_SYS"
)
target_compile_definitions(${LOADABLE_EXTENSION_NAME} PRIVATE
MDUCK_DEFAULT_SRID_CSV="${CMAKE_SOURCE_DIR}/data/spatial_ref_sys.csv"
MDUCK_SRID_ENV_NAME="SPATIAL_REF_SYS"
)
endif()


# -----------------------------
# json-c target / include handling
# -----------------------------
if (TARGET json-c::json-c)
if(TARGET json-c::json-c)
set(JSONC_TGT json-c::json-c)
else()
target_include_directories(${EXTENSION_NAME} PRIVATE ${JSON-C_INCLUDE_DIRS})
Expand Down Expand Up @@ -136,13 +115,8 @@ target_link_libraries(${LOADABLE_EXTENSION_NAME}
OpenSSL::Crypto
)

if (WIN32)
# target_link_libraries(${EXTENSION_NAME} ws2_32 crypt32)
# target_link_libraries(${LOADABLE_EXTENSION_NAME} ws2_32 crypt32)
endif()

# -----------------------------
# Install (static extension)
# Install (static & loadable)
# -----------------------------
install(
TARGETS ${EXTENSION_NAME}
Expand All @@ -156,4 +130,4 @@ install(
LIBRARY DESTINATION "${INSTALL_LIB_DIR}"
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
RUNTIME DESTINATION "${INSTALL_LIB_DIR}"
)
)
2 changes: 1 addition & 1 deletion src/geo/tgeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ inline void Tsequence_constructor(DataChunk &args, ExpressionState &state, Vecto
continue;
}

TSequence *sequence_result = tsequence_make((const TInstant **) instants, element_count,
TSequence *sequence_result = tsequence_make((TInstant **) instants, element_count,
lower_inc, upper_inc, interp, true);

if (!sequence_result) {
Expand Down
2 changes: 1 addition & 1 deletion src/geo/tgeompoint_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ void TgeompointFunctions::Tgeompoint_sequence_constructor(DataChunk &args, Expre
valid_idx++;
}

TSequence *seq = tsequence_make((const TInstant **)instants, valid_count,
TSequence *seq = tsequence_make((TInstant **)instants, valid_count,
lower_inc, upper_inc, interp, true);
if (!seq) {
for (idx_t j = 0; j < valid_count; j++) {
Expand Down
126 changes: 93 additions & 33 deletions src/mobilityduck_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@
#include "duckdb/main/extension_util.hpp"
#include <duckdb/parser/parsed_data/create_scalar_function_info.hpp>
#include "index/rtree_module.hpp"

#include <mutex>
#include <fstream>
#include <cstdlib>
#include <string>

#if defined(_WIN32)
#include <sys/types.h>
#include <sys/stat.h>
Expand All @@ -29,7 +34,8 @@
#include <sys/stat.h>
#include <unistd.h>
#endif
extern "C"{

extern "C" {
#include <stdarg.h>
#include <geos_c.h>
#include <meos.h>
Expand All @@ -39,66 +45,119 @@ extern "C"{
#include <openssl/opensslv.h>

namespace duckdb {
#include "spatial_ref_sys_csv.inc"

// =====================================================================
// 2. Utility: OpenSSL version scalar function
// =====================================================================

inline void MobilityduckOpenSSLVersionScalarFun(DataChunk &args, ExpressionState &state, Vector &result) {
auto &name_vector = args.data[0];
UnaryExecutor::Execute<string_t, string_t>(name_vector, result, args.size(), [&](string_t name) {
return StringVector::AddString(result, "Mobilityduck " + name.GetString() + ", my linked OpenSSL version is " +
OPENSSL_VERSION_TEXT);
return StringVector::AddString(
result,
"Mobilityduck " + name.GetString() +
", my linked OpenSSL version is " + OPENSSL_VERSION_TEXT
);
});
}

#ifndef MDUCK_DEFAULT_SRID_CSV
#define MDUCK_DEFAULT_SRID_CSV ""
#endif
#ifndef MDUCK_VCPKG_SRID_CSV
#define MDUCK_VCPKG_SRID_CSV ""
// =====================================================================
// 3. SRID CSV configuration for MEOS (embedded bytes)
// =====================================================================

#ifndef MDUCK_SRID_ENV_NAME
#define MDUCK_SRID_ENV_NAME "SPATIAL_REF_SYS"
#endif

static bool file_exists(const char *p) {
struct stat st{};
struct stat st {};
return p && *p && (stat(p, &st) == 0);
}

static bool file_exists(const std::string &p) {
return file_exists(p.c_str());
}

static std::string GetTempDir() {
const char *tmp = std::getenv("TMPDIR");
if (!tmp || !*tmp) {
tmp = "/tmp";
}
return std::string(tmp);
}

static std::string EnsureEmbeddedSridCsvOnDisk() {
std::string dir = GetTempDir();
std::string path = dir + "/mobilityduck_spatial_ref_sys.csv";

if (!file_exists(path)) {
std::ofstream out(path, std::ios::binary);
if (!out) {
throw duckdb::IOException(
"mobilityduck: cannot write embedded spatial_ref_sys.csv to " + path
);
}
out.write(
reinterpret_cast<const char *>(spatial_ref_sys_csv),
static_cast<std::streamsize>(spatial_ref_sys_csv_len)
);
out.close();
}
return path;
}

// Configure MEOS exactly once with a CSV path
static void ConfigureMeosSridCsvOnce() {
static std::once_flag once;
std::call_once(once, [] {
const char *env_path = std::getenv("SPATIAL_REF_SYS");
std::call_once(once, [] {
const char *env_path = std::getenv(MDUCK_SRID_ENV_NAME);
const char *chosen = nullptr;

if (env_path && *env_path && file_exists(env_path)) {
chosen = env_path;
} else if (file_exists(MDUCK_VCPKG_SRID_CSV)) {
chosen = MDUCK_VCPKG_SRID_CSV;
} else if (file_exists(MDUCK_DEFAULT_SRID_CSV)) {
chosen = MDUCK_DEFAULT_SRID_CSV;
} else {
static std::string embedded_path = EnsureEmbeddedSridCsvOnDisk();
chosen = embedded_path.c_str();
}

if (chosen) {
meos_set_spatial_ref_sys_csv(chosen);
fprintf(stderr, "[mobilityduck] Using SRID CSV: %s\n", chosen);
}
}
});
}

// =====================================================================
// 4. Extension load logic
// =====================================================================

static void LoadInternal(DatabaseInstance &instance) {
// Configure MEOS SRID CSV once (env / embedded)
ConfigureMeosSridCsvOnce();
// Initialize MEOS

// Initialize MEOS once
static std::once_flag meos_init_flag;
std::call_once(meos_init_flag, []() {
meos_initialize();
});

Connection con(instance);

// Ensure DuckDB spatial extension is available
con.Query("INSTALL spatial;");
con.Query("LOAD spatial;");

// Register another scalar function
auto mobilityduck_openssl_version_scalar_function = ScalarFunction("mobilityduck_openssl_version", {LogicalType::VARCHAR},
LogicalType::VARCHAR, MobilityduckOpenSSLVersionScalarFun);
// Register scalar function: mobilityduck_openssl_version
auto mobilityduck_openssl_version_scalar_function =
ScalarFunction(
"mobilityduck_openssl_version",
{LogicalType::VARCHAR},
LogicalType::VARCHAR,
MobilityduckOpenSSLVersionScalarFun
);
ExtensionUtil::RegisterFunction(instance, mobilityduck_openssl_version_scalar_function);

// Temporal and related types/functions
TemporalTypes::RegisterTypes(instance);
TemporalTypes::RegisterCastFunctions(instance);
TemporalTypes::RegisterScalarFunctions(instance);
Expand All @@ -111,8 +170,8 @@ static void LoadInternal(DatabaseInstance &instance) {
StboxType::RegisterType(instance);
StboxType::RegisterCastFunctions(instance);
StboxType::RegisterScalarFunctions(instance);
SpanTypes::RegisterScalarFunctions(instance);

SpanTypes::RegisterScalarFunctions(instance);
SpanTypes::RegisterTypes(instance);
SpanTypes::RegisterCastFunctions(instance);

Expand All @@ -130,23 +189,23 @@ static void LoadInternal(DatabaseInstance &instance) {
SetTypes::RegisterScalarFunctions(instance);
SetTypes::RegisterSetUnnest(instance);

SpatialSetType::RegisterTypes(instance);
SpatialSetType::RegisterCastFunctions(instance);
SpatialSetType::RegisterScalarFunctions(instance);
SpatialSetType::RegisterTypes(instance);
SpatialSetType::RegisterCastFunctions(instance);
SpatialSetType::RegisterScalarFunctions(instance);

SpansetTypes::RegisterTypes(instance);
SpansetTypes::RegisterCastFunctions(instance);
SpansetTypes::RegisterCastFunctions(instance);
SpansetTypes::RegisterScalarFunctions(instance);
RTreeModule::RegisterRTreeIndex(instance);

RTreeModule::RegisterRTreeIndex(instance);
RTreeModule::RegisterIndexScan(instance);
RTreeModule::RegisterScanOptimizer(instance);
}

void MobilityduckExtension::Load(DuckDB &db) {
LoadInternal(*db.instance);

}

std::string MobilityduckExtension::Name() {
return "mobilityduck";
}
Expand All @@ -171,8 +230,9 @@ DUCKDB_EXTENSION_API void mobilityduck_init(duckdb::DatabaseInstance &db) {
DUCKDB_EXTENSION_API const char *mobilityduck_version() {
return duckdb::DuckDB::LibraryVersion();
}
}

} // extern "C"

#ifndef DUCKDB_EXTENSION_MAIN
#error DUCKDB_EXTENSION_MAIN not defined
#endif
#endif
Loading
Loading