diff --git a/src/include/meos_wrapper_simple.hpp b/src/include/meos_wrapper_simple.hpp index a4f13a93..1acdc1b3 100644 --- a/src/include/meos_wrapper_simple.hpp +++ b/src/include/meos_wrapper_simple.hpp @@ -10,25 +10,6 @@ extern "C" { #include } -// The symmetric box/span × temporal topological predicates (overlaps, same, -// adjacent) are canonicalized in MEOS to a single argument direction -// (temporal-first). The reverse-argument overloads the DuckDB surface exposes -// derive from that one kernel by commutativity (swap the operands). The -// non-symmetric predicates (contains/contained/overbefore/overafter) keep both -// MEOS directions and are used directly. -static inline bool overlaps_tstzspan_temporal(const Span *s, const Temporal *t) { return overlaps_temporal_tstzspan(t, s); } -static inline bool same_tstzspan_temporal (const Span *s, const Temporal *t) { return same_temporal_tstzspan(t, s); } -static inline bool adjacent_tstzspan_temporal(const Span *s, const Temporal *t) { return adjacent_temporal_tstzspan(t, s); } -static inline bool overlaps_stbox_tspatial(const STBox *b, const Temporal *t) { return overlaps_tspatial_stbox(t, b); } -static inline bool same_stbox_tspatial (const STBox *b, const Temporal *t) { return same_tspatial_stbox(t, b); } -static inline bool adjacent_stbox_tspatial(const STBox *b, const Temporal *t) { return adjacent_tspatial_stbox(t, b); } -static inline bool overlaps_numspan_tnumber(const Span *s, const Temporal *t) { return overlaps_tnumber_numspan(t, s); } -static inline bool same_numspan_tnumber (const Span *s, const Temporal *t) { return same_tnumber_numspan(t, s); } -static inline bool adjacent_numspan_tnumber(const Span *s, const Temporal *t) { return adjacent_tnumber_numspan(t, s); } -static inline bool overlaps_tbox_tnumber(const TBox *b, const Temporal *t) { return overlaps_tnumber_tbox(t, b); } -static inline bool same_tbox_tnumber (const TBox *b, const Temporal *t) { return same_tnumber_tbox(t, b); } -static inline bool adjacent_tbox_tnumber(const TBox *b, const Temporal *t) { return adjacent_tnumber_tbox(t, b); } - // Create explicit aliases for MEOS types // Use the original MEOS type names but with explicit qualification using MeosInterval = ::Interval; // Explicitly use global MEOS Interval diff --git a/src/mobilityduck_extension.cpp b/src/mobilityduck_extension.cpp index c268abc1..ee4a4508 100644 --- a/src/mobilityduck_extension.cpp +++ b/src/mobilityduck_extension.cpp @@ -83,7 +83,7 @@ inline void MobilityduckOpenSSLVersionScalarFun(DataChunk &args, ExpressionState // MEOS does not expose a runtime version symbol, so the build-time pin // is the most precise version stamp the extension can report. #ifndef MOBILITYDUCK_MEOS_PIN -#define MOBILITYDUCK_MEOS_PIN "f11b7443e" +#define MOBILITYDUCK_MEOS_PIN "23331ac50" #endif inline std::string MobilityduckShortVersion() { diff --git a/src/temporal/temporal_functions.cpp b/src/temporal/temporal_functions.cpp index 5b110e00..17eabc43 100644 --- a/src/temporal/temporal_functions.cpp +++ b/src/temporal/temporal_functions.cpp @@ -199,7 +199,7 @@ void TemporalFunctions::Tinstant_constructor_text(Vector &value, Vector &ts, Vec timestamp_tz_t meos_ts = DuckDBToMeosTimestamp(ts); std::string str = value.GetString(); - text *txt = cstring2text(str.c_str()); + text *txt = cstring_to_text(str.c_str()); TInstant *inst = ttextinst_make(txt, (TimestampTz)meos_ts.value); Temporal *temp = (Temporal*)inst; @@ -446,7 +446,7 @@ void TemporalFunctions::Tsequence_from_base_tstzset(DataChunk &args, ExpressionS BinaryExecutor::Execute( args.data[0], args.data[1], result, count, [&](string_t value, string_t set_blob) { - text *txt = cstring2text(value.GetString().c_str()); + text *txt = cstring_to_text(value.GetString().c_str()); return Tsequence_from_base_tstzset_impl(PointerGetDatum(txt), set_blob, temptype, result); }); } else if (arg_type.id() == LogicalTypeId::BLOB) { @@ -528,7 +528,7 @@ void TemporalFunctions::Tsequence_from_base_tstzspan(DataChunk &args, Expression BinaryExecutor::Execute( args.data[0], args.data[1], result, count, [&](string_t value, string_t span_blob) { - text *txt = cstring2text(value.GetString().c_str()); + text *txt = cstring_to_text(value.GetString().c_str()); return Tsequence_from_base_tstzspan_impl(PointerGetDatum(txt), span_blob, temptype, interp, result); }); } else if (arg_type.id() == LogicalTypeId::BLOB) { @@ -611,7 +611,7 @@ void TemporalFunctions::Tsequenceset_from_base_tstzspanset(DataChunk &args, Expr BinaryExecutor::Execute( args.data[0], args.data[1], result, count, [&](string_t value, string_t spanset_blob) { - text *txt = cstring2text(value.GetString().c_str()); + text *txt = cstring_to_text(value.GetString().c_str()); return Tsequenceset_from_base_tstzspanset_impl(PointerGetDatum(txt), spanset_blob, temptype, interp, result); }); } else if (arg_type.id() == LogicalTypeId::BLOB) { @@ -1335,7 +1335,7 @@ void TemporalFunctions::Temporal_value_n(DataChunk &args, ExpressionState &state return string_t(); } text *txt = DatumGetTextP(ret); - char *cstr = text2cstring(txt); + char *cstr = text_to_cstring(txt); return StringVector::AddString(result, cstr); } ); @@ -2798,7 +2798,7 @@ static void temporal_at_minus_values_dispatch(DataChunk &args, ExpressionState & BinaryExecutor::ExecuteWithNulls( args.data[0], args.data[1], result, count, [&](string_t temp_str, string_t value, ValidityMask &mask, idx_t idx) -> string_t { - text *txt = cstring2text(value.GetString().c_str()); + text *txt = cstring_to_text(value.GetString().c_str()); string_t stored = temporal_restrict_value_impl(temp_str, PointerGetDatum(txt), atfunc, result, mask, idx); return stored; }); @@ -3523,7 +3523,7 @@ void TemporalFunctions::Temporal_value_at_timestamptz(DataChunk &args, Expressio mask.SetInvalid(idx); return string_t(); } - char *cstr = text2cstring(value); + char *cstr = text_to_cstring(value); string_t stored = StringVector::AddString(result, cstr); return stored; }); @@ -5872,7 +5872,7 @@ void TemporalFunctions::Temporal_dump_common(DataChunk &args, Vector &result, Me values.push_back(actual_value); } else if constexpr (std::is_same_v) { text *txt = DatumGetTextP(val); - char *actual_value = text2cstring(txt); + char *actual_value = text_to_cstring(txt); values.push_back(string_t(actual_value)); } diff --git a/vcpkg_ports/meos/portfile.cmake b/vcpkg_ports/meos/portfile.cmake index 738c9f17..d2ed8cc0 100644 --- a/vcpkg_ports/meos/portfile.cmake +++ b/vcpkg_ports/meos/portfile.cmake @@ -1,113 +1,29 @@ vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO estebanzimanyi/MobilityDB - REF 59ba0ad59cb93db6fa46929394e475b7851c00be - SHA512 e6a4a1578e5760326a596248865ccb487850120ca423f5675d1f014e9146de4f407c699afa63a102d8ba4ef1f895946d206ee4ab2f870dc4508ec2ca3d771869 + REF 23331ac50e73e43567536d837d3e182bb45b3bdb + SHA512 c7eaf762b5aa3c7c6714d57fc22aaf3aa8ba852e18f72f23bbaba1bd54719c764aaf62eddf36e495daf79e346d3b561a0b589487ef55e1d437beb5a1035de675 ) +# Upstream gap: `pgtypes/postgres.h` line 74 has +# #include "../../meos/include/meos_error.h" +# which was authored for the former `postgres/include/postgres.h` +# two-level nesting; with `pgtypes/postgres.h` one level deep the +# relative `../../` path escapes the source tree entirely. +# Inject `${CMAKE_SOURCE_DIR}/meos/include` as a private include +# directory on the `pgtypes` target so the header resolves via the +# explicit search path. vcpkg_replace_string( - "${SOURCE_PATH}/postgres/utils/CMakeLists.txt" - "set_property(TARGET utils PROPERTY POSITION_INDEPENDENT_CODE ON)" - [=[ -set_property(TARGET utils PROPERTY POSITION_INDEPENDENT_CODE ON) - + "${SOURCE_PATH}/pgtypes/CMakeLists.txt" + [=[target_include_directories(pgtypes PUBLIC "${CMAKE_SOURCE_DIR}/pgtypes") +target_include_directories(pgtypes PUBLIC "${CMAKE_BINARY_DIR}/pgtypes")]=] + [=[target_include_directories(pgtypes PUBLIC "${CMAKE_SOURCE_DIR}/pgtypes") +target_include_directories(pgtypes PUBLIC "${CMAKE_BINARY_DIR}/pgtypes") if(MEOS) - target_include_directories(utils PRIVATE "${CMAKE_SOURCE_DIR}/meos/include") -endif() -]=] -) - -# Upstream gap at commit beddae670: `meos/include/h3/th3index_internal.h` -# does `#include ` unconditionally. `fmgr.h` is a PG-internal -# header and is not bundled in MEOS's `postgres/` subtree, so the -# standalone MEOS build of `meos/src/h3/h3index.c` fails with -# `fatal error: fmgr.h: No such file or directory`. Guard the -# include with `#if !MEOS`, mirroring the same idiom already used by -# `meos/include/temporal/temporal.h`. -vcpkg_replace_string( - "${SOURCE_PATH}/meos/include/h3/th3index_internal.h" - [=[ -#include -#include -]=] - [=[ -#include -#if ! MEOS -#include -#endif -]=] -) - -# Upstream gap at commit beddae670: `meos/CMakeLists.txt` builds the -# `h3` OBJECT library (via `add_subdirectory(h3)` + `add_library`) -# but the `PROJECT_OBJECTS` list that feeds the final -# `add_library(meos ${PROJECT_OBJECTS})` lists every other optional -# family (cbuffer / npoint / pose / rgeo) and silently omits `h3`. -# Without this injection libmeos ships without H3 symbols, so any -# consumer linking against `meos` sees ~120 `undefined reference to -# 'th3index_*'` link errors. -vcpkg_replace_string( - "${SOURCE_PATH}/meos/CMakeLists.txt" - [=[if(RGEO) - message(STATUS "Including rigid geometries") - set(PROJECT_OBJECTS ${PROJECT_OBJECTS} "$") -endif()]=] - [=[if(RGEO) - message(STATUS "Including rigid geometries") - set(PROJECT_OBJECTS ${PROJECT_OBJECTS} "$") -endif() -if(H3) - message(STATUS "Including temporal H3 index (th3index)") - set(PROJECT_OBJECTS ${PROJECT_OBJECTS} "$") + target_include_directories(pgtypes PRIVATE "${CMAKE_SOURCE_DIR}/meos/include") endif()]=] ) -# Upstream gap at commit beddae670: `meos/CMakeLists.txt` carries -# `install()` rules for `meos_npoint.h` / `meos_pose.h` / -# `meos_rgeo.h` / `meos_cbuffer.h` but no rule for `meos_h3.h`. -# Without it the H3 public header is missing from the installed -# `include/` directory, so any consumer of `#include ` -# fails to compile. -vcpkg_replace_string( - "${SOURCE_PATH}/meos/CMakeLists.txt" - [=[if(RGEO) - install( - FILES "${CMAKE_SOURCE_DIR}/meos/include/meos_rgeo.h" - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") -endif()]=] - [=[if(RGEO) - install( - FILES "${CMAKE_SOURCE_DIR}/meos/include/meos_rgeo.h" - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") -endif() -if(H3) - install( - FILES "${CMAKE_SOURCE_DIR}/meos/include/meos_h3.h" - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") -endif()]=] -) - -# Upstream gap at commit beddae670: the h3-side source files call -# `ensure_srid_is_latlong()` (declared in -# `meos/include/geo/tgeo_spatialfuncs.h`) without including that -# header, yielding implicit-declaration errors under `MEOS=1`. -foreach(_h3_src - meos/src/h3/h3_geo.c - meos/src/h3/th3index_latlng.c - meos/src/h3/th3index_metrics.c) - if(EXISTS "${SOURCE_PATH}/${_h3_src}") - vcpkg_replace_string( - "${SOURCE_PATH}/${_h3_src}" - "#include " - [=[ -#include - -#include "geo/tgeo_spatialfuncs.h" -]=] - ) - endif() -endforeach() - # vcpkg installs h3 at the per-triplet # `installed//{lib,include/h3}` layout, but MEOS's own # `find_library(NAMES h3)` / `find_path(NAMES h3api.h PATH_SUFFIXES h3)` @@ -145,6 +61,130 @@ if(NOT _MEOS_H3_INC) message(FATAL_ERROR "MEOS port: cannot locate vcpkg-installed h3api.h under ${CURRENT_INSTALLED_DIR}/include or ${CURRENT_INSTALLED_DIR}/include/h3") endif() +# Upstream gap: `meos/src/CMakeLists.txt` is missing the +# `if(H3) add_subdirectory(h3) endif()` block. The top-level +# `meos/CMakeLists.txt` references `$` when H3=ON, +# but without add_subdirectory the `h3` OBJECT library target is never +# defined and cmake configure fails with +# "Objects of target h3 referenced but no such target exists." +vcpkg_replace_string( + "${SOURCE_PATH}/meos/src/CMakeLists.txt" + [=[if(JSON) + add_subdirectory(json) +endif()]=] + [=[if(H3) + add_subdirectory(h3) +endif() +if(JSON) + add_subdirectory(json) +endif()]=] +) + +# Upstream gap: `pgtypes/libpq/pqformat.h` contains a deprecated +# static-inline helper `pq_sendint` that calls `elog()`. In the +# standalone MEOS build the pgtypes shim does not declare `elog`, and +# GCC 14 (Ubuntu 24.04 runners) treats implicit-function-declaration +# as a hard error. Replace the call with `meos_error` — both symbols +# are in scope via the postgres.h → meos_error.h chain that pqformat.c +# already includes before pulling in pqformat.h. +vcpkg_replace_string( + "${SOURCE_PATH}/pgtypes/libpq/pqformat.h" + [=[elog(ERROR, "unsupported integer size %d", b);]=] + [=[meos_error(ERROR, MEOS_ERR_INTERNAL_ERROR, "unsupported integer size %d", b);]=] +) + +# Upstream gap: the MEOS=1 include path (`postgres_int_defs.h` → `pg_timestamp.h`) +# does not reach `pgtypes/utils/timestamp.h`, so the four Timestamp/TimestampTz +# Datum accessors are absent from pure MEOS=1 TUs (e.g. `meos/src/h3/th3index_boxops.c` +# calls `TimestampTzGetDatum`). GCC 14 treats implicit-function-declaration as a +# hard error. Adding the functions unconditionally to `pg_timestamp.h` causes +# redefinition errors in pgtypes TUs that explicitly include `utils/timestamp.h` +# (e.g. `pgtypes/common/stringinfo.c`), because both files define the same four +# static-inline functions. +# +# Fix — cross-guard the definitions so the header processed first wins: +# · `pg_timestamp.h` adds the four functions under `#ifndef TIMESTAMP_H` +# (the include-guard of `utils/timestamp.h`). +# · `utils/timestamp.h` wraps its four matching functions under +# `#ifndef __PG_TIMESTAMP_H__` (the include-guard of `pg_timestamp.h`). +vcpkg_replace_string( + "${SOURCE_PATH}/pgtypes/pg_timestamp.h" + [=[typedef int64 TimestampTz;]=] + [=[typedef int64 TimestampTz; +#ifndef TIMESTAMP_H +static inline Datum TimestampGetDatum(Timestamp X) { return Int64GetDatum(X); } +static inline Datum TimestampTzGetDatum(TimestampTz X) { return Int64GetDatum(X); } +static inline Timestamp DatumGetTimestamp(Datum X) { return (Timestamp) DatumGetInt64(X); } +static inline TimestampTz DatumGetTimestampTz(Datum X) { return (TimestampTz) DatumGetInt64(X); } +#endif]=] +) + +vcpkg_replace_string( + "${SOURCE_PATH}/pgtypes/utils/timestamp.h" + [=[static inline Timestamp +DatumGetTimestamp(Datum X) +{ + return (Timestamp) DatumGetInt64(X); +} + +static inline TimestampTz +DatumGetTimestampTz(Datum X) +{ + return (TimestampTz) DatumGetInt64(X); +} + +static inline Interval * +DatumGetIntervalP(Datum X) +{ + return (Interval *) DatumGetPointer(X); +} + +static inline Datum +TimestampGetDatum(Timestamp X) +{ + return Int64GetDatum(X); +} + +static inline Datum +TimestampTzGetDatum(TimestampTz X) +{ + return Int64GetDatum(X); +}]=] + [=[#ifndef __PG_TIMESTAMP_H__ +static inline Timestamp +DatumGetTimestamp(Datum X) +{ + return (Timestamp) DatumGetInt64(X); +} + +static inline TimestampTz +DatumGetTimestampTz(Datum X) +{ + return (TimestampTz) DatumGetInt64(X); +} +#endif + +static inline Interval * +DatumGetIntervalP(Datum X) +{ + return (Interval *) DatumGetPointer(X); +} + +#ifndef __PG_TIMESTAMP_H__ +static inline Datum +TimestampGetDatum(Timestamp X) +{ + return Int64GetDatum(X); +} + +static inline Datum +TimestampTzGetDatum(TimestampTz X) +{ + return Int64GetDatum(X); +} +#endif]=] +) + vcpkg_cmake_configure( SOURCE_PATH "${SOURCE_PATH}" OPTIONS @@ -160,9 +200,17 @@ vcpkg_cmake_configure( -DCMAKE_CXX_FLAGS="-Dsession_timezone=meos_session_timezone" ) -vcpkg_cmake_build(TARGET all) vcpkg_cmake_install() +# meos_tls.h and meos_json.h are not listed in the upstream install() rules at +# this pin. meos_tls.h is included verbatim by the cmake-generated meos.h; +# meos_json.h exposes the public JSONB / temporal-JSONB API used by TJSONB +# bindings. Copy both alongside the other installed headers. +file(COPY "${SOURCE_PATH}/meos/include/meos_tls.h" + DESTINATION "${CURRENT_PACKAGES_DIR}/include") +file(COPY "${SOURCE_PATH}/meos/include/meos_json.h" + DESTINATION "${CURRENT_PACKAGES_DIR}/include") + file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/share/meos") file(WRITE "${CURRENT_PACKAGES_DIR}/share/meos/MEOSConfig.cmake" [=[ # Minimal imported target for MEOS