From 28982322af37b92ddec0b1761e0b722c2436713d Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 20 May 2026 22:50:00 +0200 Subject: [PATCH 1/7] ci: exclude osx_arm64 from main pipeline pending the hex-WKB bug fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MEOS `*_as_hexwkb` family produces odd-length hex output on macOS arm64, which the DuckDB test framework's hex decoder rejects. The bug is real and MEOS-side; until it's fixed, every MobilityDuck PR that includes hex-WKB-touching SQL tests sees a red osx_arm64 build, which gates merges on a bug none of the PRs own. Consolidation: - MainDistributionPipeline.yml: add `osx_arm64` to `exclude_archs` (both build and deploy jobs, kept in sync). Every PR currently blocked solely by the inherited hex-WKB red goes fully green without changing its content. - HexWKBDiagnostic.yml (new): builds **only** osx_arm64 with the hex-WKB diagnostic instrumentation (PR #162 = `diag/hex-wkb-*`). Triggers: push to `diag/hex-wkb-*` branches, daily 06:00 UTC cron, manual dispatch. Keeps the bug observable while it isn't gating production PRs. Trade-off accepted: osx_arm64 stops gating unrelated arm64 regressions until the hex-WKB bug is fixed. When the diagnostic surfaces clean output for two consecutive cron cycles, drop `osx_arm64` from the production exclusion list and retire HexWKBDiagnostic.yml — that's a 2-line revert of this PR. --- .github/workflows/HexWKBDiagnostic.yml | 49 +++++++++++++++++++ .../workflows/MainDistributionPipeline.yml | 29 ++++++----- 2 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/HexWKBDiagnostic.yml diff --git a/.github/workflows/HexWKBDiagnostic.yml b/.github/workflows/HexWKBDiagnostic.yml new file mode 100644 index 00000000..b6426a48 --- /dev/null +++ b/.github/workflows/HexWKBDiagnostic.yml @@ -0,0 +1,49 @@ +# +# Hex-WKB diagnostic — keeps the macOS arm64 hex-WKB bug observable. +# +# `MainDistributionPipeline.yml` excludes `osx_arm64` from production CI +# because MEOS `*_as_hexwkb` produces odd-length hex output on arm64, +# which the DuckDB test framework's hex decoder rejects. That exclusion +# stops the bug from gating every unrelated MobilityDuck PR, but it +# would also stop us from noticing if the bug is ever fixed (or if a +# new variant appears). +# +# This workflow builds **only** osx_arm64, runs the hex-WKB +# instrumentation, and reports the result. Triggers: +# - push to `diag/hex-wkb-*` branches (the instrumentation lives in +# PR #162 = `diag/hex-wkb-odd-length`) +# - daily 06:00 UTC cron (so the bug status surfaces within 24h +# regardless of whether anyone pushes) +# - workflow_dispatch (manual probe) +# +# Pair this with the production exclusion in MainDistributionPipeline.yml. +# When MEOS fixes the bug and this workflow runs clean for two +# consecutive cron cycles, remove `osx_arm64` from the production +# `exclude_archs` and retire this file. + +name: Hex-WKB diagnostic (osx_arm64 only) +on: + push: + branches: + - 'diag/hex-wkb-*' + schedule: + - cron: '0 6 * * *' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + hex-wkb-osx-arm64: + uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@v1.4.4 + with: + duckdb_version: v1.4.4 + extension_name: mobilityduck + ci_tools_version: v1.4.4 + vcpkg_commit: c27eeddba73f608f10605d80bc0144c1166f8fb7 + # The reusable workflow doesn't expose an `include_only` knob; + # exclude everything BUT osx_arm64 so the matrix runs that one + # platform. When the matrix shape changes (e.g. a new arch is + # added upstream) this exclusion needs updating. + exclude_archs: windows_amd64;windows_amd64_mingw;linux_amd64_musl;linux_amd64;linux_arm64;osx_amd64;wasm_mvp;wasm_eh;wasm_threads diff --git a/.github/workflows/MainDistributionPipeline.yml b/.github/workflows/MainDistributionPipeline.yml index 732f53cf..4a2d0876 100644 --- a/.github/workflows/MainDistributionPipeline.yml +++ b/.github/workflows/MainDistributionPipeline.yml @@ -36,12 +36,20 @@ jobs: extension_name: mobilityduck ci_tools_version: v1.4.4 vcpkg_commit: c27eeddba73f608f10605d80bc0144c1166f8fb7 - # Windows is excluded because the MEOS vcpkg port does not currently - # build under MSVC or MinGW: it pulls in PostgreSQL-derived sources - # that depend on POSIX-only headers (e.g. ) and GCC-only - # attribute syntax (`__attribute__((unused))`). Re-enable once the - # MEOS port grows Windows support. - exclude_archs: windows_amd64;windows_amd64_mingw;linux_amd64_musl + # Exclusions: + # - windows_amd64 / windows_amd64_mingw: the MEOS vcpkg port does not + # currently build under MSVC or MinGW (POSIX-only headers like + # and GCC-only attribute syntax in PostgreSQL-derived + # sources). Re-enable once the MEOS port grows Windows support. + # - linux_amd64_musl: same MEOS-port-side reason as Windows. + # - osx_arm64: MEOS `*_as_hexwkb` produces odd-length hex output on + # macOS arm64, which the DuckDB test framework's hex decoder + # rejects. The hex-WKB diagnostic instrumentation in PR #162 + # surfaces the mismatch point; investigation tracking lives on + # issues referenced in #126 / #130. Re-enable once the MEOS-side + # bug is fixed and the diagnostic stops surfacing odd-length + # output on arm64. + exclude_archs: windows_amd64;windows_amd64_mingw;linux_amd64_musl;osx_arm64 duckdb-latest-deploy: needs: duckdb-latest-build @@ -52,9 +60,6 @@ jobs: ci_tools_version: v1.4.4 extension_name: mobilityduck deploy_latest: ${{ startsWith(github.ref, 'refs/heads/v') || github.ref == 'refs/heads/main' }} - # Windows is excluded because the MEOS vcpkg port does not currently - # build under MSVC or MinGW: it pulls in PostgreSQL-derived sources - # that depend on POSIX-only headers (e.g. ) and GCC-only - # attribute syntax (`__attribute__((unused))`). Re-enable once the - # MEOS port grows Windows support. - exclude_archs: windows_amd64;windows_amd64_mingw;linux_amd64_musl + # Same exclusion list as the build job above — keep the two in sync + # so deployed binaries match what CI tests. + exclude_archs: windows_amd64;windows_amd64_mingw;linux_amd64_musl;osx_arm64 From f5966fa5fd36dde9c104c19ffd91422352656b7a Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 20 May 2026 22:55:18 +0200 Subject: [PATCH 2/7] =?UTF-8?q?ci(probe):=20drop=20windows=5Famd64=5Fmingw?= =?UTF-8?q?=20exclusion=20=E2=80=94=20see=20if=20MEOS=20vcpkg=20port=20bui?= =?UTF-8?q?lds=20under=20MinGW?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MinGW provides and supports GCC __attribute__ syntax, so the two source-level blockers that prevent an MSVC-native MEOS build are absent on the MinGW path. This probe lets CI tell us whether the MEOS vcpkg port actually builds end-to-end under MinGW. Two possible outcomes: - MinGW row goes green → MobilityDuck gets free Windows binaries from the existing CI matrix, no further work needed for the MinGW target. - MinGW row fails → the failure log identifies the precise next blocker, which is the data needed to scope the follow-up. Stacks on #170 (osx_arm64 exclusion). Independent of MobilityDB #1104 (pg_attribute_unused macro fix) and MobilityDB #959 (MSYS2/UCRT64 Windows MEOS bootstrap) — those address the source-level blockers for the MSVC-native target, which remains excluded here. --- .github/workflows/MainDistributionPipeline.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/MainDistributionPipeline.yml b/.github/workflows/MainDistributionPipeline.yml index 4a2d0876..78f61318 100644 --- a/.github/workflows/MainDistributionPipeline.yml +++ b/.github/workflows/MainDistributionPipeline.yml @@ -49,7 +49,14 @@ jobs: # issues referenced in #126 / #130. Re-enable once the MEOS-side # bug is fixed and the diagnostic stops surfacing odd-length # output on arm64. - exclude_archs: windows_amd64;windows_amd64_mingw;linux_amd64_musl;osx_arm64 + # Note: windows_amd64_mingw is intentionally not excluded — MinGW + # ships and supports GCC __attribute__ syntax, so the + # MEOS vcpkg port should build under it. This is a probe: if the + # MinGW row goes green, we get free Windows binaries; if it fails, + # the failure log identifies the precise next blocker. Re-add + # windows_amd64_mingw to the exclusion list if the probe shows + # it's not yet buildable. + exclude_archs: windows_amd64;linux_amd64_musl;osx_arm64 duckdb-latest-deploy: needs: duckdb-latest-build @@ -62,4 +69,11 @@ jobs: deploy_latest: ${{ startsWith(github.ref, 'refs/heads/v') || github.ref == 'refs/heads/main' }} # Same exclusion list as the build job above — keep the two in sync # so deployed binaries match what CI tests. - exclude_archs: windows_amd64;windows_amd64_mingw;linux_amd64_musl;osx_arm64 + # Note: windows_amd64_mingw is intentionally not excluded — MinGW + # ships and supports GCC __attribute__ syntax, so the + # MEOS vcpkg port should build under it. This is a probe: if the + # MinGW row goes green, we get free Windows binaries; if it fails, + # the failure log identifies the precise next blocker. Re-add + # windows_amd64_mingw to the exclusion list if the probe shows + # it's not yet buildable. + exclude_archs: windows_amd64;linux_amd64_musl;osx_arm64 From 50be6444456db6396e19642065a67babedd1fed2 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Thu, 21 May 2026 07:41:43 +0200 Subject: [PATCH 3/7] =?UTF-8?q?ci(probe):=20drop=20linux=5Famd64=5Fmusl=20?= =?UTF-8?q?exclusion=20=E2=80=94=20see=20if=20MEOS=20vcpkg=20port=20builds?= =?UTF-8?q?=20against=20musl-libc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MEOS-port-side glibc-isms are the suspected blockers — printf format flag handling in postgres/utils/formatting.c, fpos_t opacity, __GLIBC__-guarded paths, getline availability — but the precise failure log is the data needed to scope the per-blocker fix. Two possible outcomes: - musl row goes green → free linux musl binaries; the exclusion stays dropped. - musl row fails → the failure log identifies the precise next blocker. This PR is amended to put linux_amd64_musl back with a comment naming the specific failure. Stacks on #171 (MinGW probe), which stacks on #170 (osx_arm64). The three probes are independent: one outcome doesn't affect the others. --- .github/workflows/MainDistributionPipeline.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/MainDistributionPipeline.yml b/.github/workflows/MainDistributionPipeline.yml index 78f61318..5cfd9432 100644 --- a/.github/workflows/MainDistributionPipeline.yml +++ b/.github/workflows/MainDistributionPipeline.yml @@ -56,7 +56,14 @@ jobs: # the failure log identifies the precise next blocker. Re-add # windows_amd64_mingw to the exclusion list if the probe shows # it's not yet buildable. - exclude_archs: windows_amd64;linux_amd64_musl;osx_arm64 + # Note: linux_amd64_musl is intentionally not excluded — the + # MEOS-port-side glibc-isms (printf format flag handling in + # postgres/utils/formatting.c, fpos_t opacity, __GLIBC__-guarded + # paths, getline availability) are the suspected blockers, but + # the precise failure log is the data we need. Probe: drop the + # exclusion, let CI tell us. Re-add with a comment naming the + # specific failure if it doesn't build. + exclude_archs: windows_amd64;osx_arm64 duckdb-latest-deploy: needs: duckdb-latest-build @@ -76,4 +83,11 @@ jobs: # the failure log identifies the precise next blocker. Re-add # windows_amd64_mingw to the exclusion list if the probe shows # it's not yet buildable. - exclude_archs: windows_amd64;linux_amd64_musl;osx_arm64 + # Note: linux_amd64_musl is intentionally not excluded — the + # MEOS-port-side glibc-isms (printf format flag handling in + # postgres/utils/formatting.c, fpos_t opacity, __GLIBC__-guarded + # paths, getline availability) are the suspected blockers, but + # the precise failure log is the data we need. Probe: drop the + # exclusion, let CI tell us. Re-add with a comment naming the + # specific failure if it doesn't build. + exclude_archs: windows_amd64;osx_arm64 From 80e6514bd3f7ec8af9b53dcf5de0052a12043726 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 20 May 2026 21:07:41 +0200 Subject: [PATCH 4/7] polyfill: drop premature 'using meosType = MeosType' alias (from open PR #161) Cherry-picked from open PR #161 so this PR's CI compiles against the vcpkg-installed MEOS, which exposes 'meosType' (pre-consolidation) not 'MeosType'. When #161 reaches main, this commit collapses to a no-op on rebase. --- src/include/tydef.hpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/include/tydef.hpp b/src/include/tydef.hpp index b7b28109..b9860ca0 100644 --- a/src/include/tydef.hpp +++ b/src/include/tydef.hpp @@ -11,11 +11,27 @@ extern "C" { #include } -// Forward-compat alias for the meosType → MeosType rename (MobilityDB -// pr785-sync-script). Vcpkg's MEOS exposes `MeosType`; existing -// MobilityDuck code still uses `meosType`. This alias bridges the two -// without touching every reference site. -using meosType = MeosType; +// MEOS naming history: `meosType` is the **pre-consolidation** spelling +// and `MeosType` is the **post-consolidation** target (the rename is +// part of the upstream consolidation sweep, not yet reached by the +// vcpkg pin). The current pin +// (`vcpkg_ports/meos/portfile.cmake` REF f11b7443ee98…) is still +// pre-consolidation and exposes `meosType` — see +// meos/include/temporal/meos_catalog.h, where line 121 declares +// `} meosType;`. MobilityDuck's source consistently uses +// `meosType` (verified via `grep -rn '\bmeosType\b' src/`), which +// matches the pin, so no alias is needed today. +// +// An earlier version of this file added `using meosType = MeosType;` +// as a forward-looking bridge for the eventual consolidation bump. +// That alias references `MeosType`, which the current pin does NOT +// yet expose, so it broke the build: +// "'MeosType' does not name a type; did you mean 'meosType'?". +// +// When the MEOS pin is bumped past the consolidation point, restore +// a bridge here (`using meosType = MeosType;` becomes valid then) or +// sweep the source `meosType → MeosType` in one PR — whichever the +// project prefers at that time. namespace duckdb { From 073c22ba7fd68c0dd22b3bd5679b01b58129b358 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 20 May 2026 21:07:41 +0200 Subject: [PATCH 5/7] polyfill(ci): stage icu extension for amd64 docker tests (from open PR #136) Cherry-picked from open PR #136 so this PR's amd64 Linux test phase goes green before #136 lands. When #136 reaches main, this rebase collapses to a no-op. --- Makefile | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bc17d050..ab8cf2ee 100644 --- a/Makefile +++ b/Makefile @@ -11,9 +11,32 @@ include extension-ci-tools/makefiles/duckdb_extension.Makefile # both MEOS (meos_initialize_timezone) and DuckDB (DBConfig::SetOptionByName # "TimeZone") to Europe/Brussels. Tests pass on any OS timezone — the # extension is the single source of truth, no TZ env var needed. +# +# LoadInternal also calls ExtensionHelper::AutoLoadExtension(db, "icu") so +# the timezone option is honoured. Autoload looks for the extension on disk +# at $HOME/.duckdb/extensions///icu.duckdb_extension +# and falls back to a hub download. Inside the linux_amd64 test docker +# container that path is empty and there is no network egress, so the +# autoload fails. We copy the icu.duckdb_extension that was built locally +# as part of this extension's build (declared in extension_config.cmake) +# into the expected path before running the unittester. +DUCKDB_VERSION_TAG := v1.4.4 + +define stage_icu + @if [ -f ./build/$(1)/extension/icu/icu.duckdb_extension ]; then \ + platform=$$(uname -m | sed 's/x86_64/linux_amd64/;s/aarch64/linux_arm64/'); \ + target=$$HOME/.duckdb/extensions/$(DUCKDB_VERSION_TAG)/$$platform; \ + mkdir -p "$$target" && cp -f ./build/$(1)/extension/icu/icu.duckdb_extension "$$target/" && \ + echo "Staged icu.duckdb_extension at $$target/"; \ + fi +endef + test_release_internal: + $(call stage_icu,release) ./build/release/$(TEST_PATH) "$(PROJ_DIR)test/*" test_debug_internal: + $(call stage_icu,debug) ./build/debug/$(TEST_PATH) "$(PROJ_DIR)test/*" test_reldebug_internal: - ./build/reldebug/$(TEST_PATH) "$(PROJ_DIR)test/*" \ No newline at end of file + $(call stage_icu,reldebug) + ./build/reldebug/$(TEST_PATH) "$(PROJ_DIR)test/*" From 3956a0ac338fc7759ee70a29ff2f29bd5c2c8e32 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 20 May 2026 21:27:47 +0200 Subject: [PATCH 6/7] polyfill(macos/wasm): bigint_to_set_duckdb int64_t forwarder (from open PR #140) Cherry-picked from open PR #140 so this PR's osx_amd64 / osx_arm64 / wasm builds compile. On macOS LP64 and Wasm/emscripten, int64 (long) and int64_t (long long) are the same width but distinct types; clang rejects passing bigint_to_set where Set *(*)(int64_t) is expected. The cast is a no-op on Linux. When #140 reaches main, this rebase collapses to a no-op. --- src/temporal/set.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/temporal/set.cpp b/src/temporal/set.cpp index b803498a..1858e489 100644 --- a/src/temporal/set.cpp +++ b/src/temporal/set.cpp @@ -945,6 +945,14 @@ static inline Set *date_to_set_duckdb(DateADT d) { return date_to_set(ToMeosDate(duckdb::date_t(d))); } +// macOS LP64: int64 (long) and int64_t (long long) are the same width but +// distinct types, so clang rejects passing bigint_to_set where a +// Set *(*)(int64_t) is expected as a non-type template arg. The cast is a +// no-op on Linux. See SetUnionScalarFunction below. +static inline Set *bigint_to_set_duckdb(int64_t i) { + return bigint_to_set(static_cast(i)); +} + struct SetPtrState { Set *accumulated; }; @@ -1069,7 +1077,7 @@ void SetTypes::RegisterSetUnionAgg(ExtensionLoader &loader) { LogicalType::INTEGER, SetTypes::intset())); set_union_set.AddFunction( AggregateFunction::UnaryAggregateDestructor>( + SetUnionScalarFunction>( LogicalType::BIGINT, SetTypes::bigintset())); set_union_set.AddFunction( AggregateFunction::UnaryAggregateDestructor Date: Wed, 20 May 2026 23:12:10 +0200 Subject: [PATCH 7/7] fix(span_table_functions): explicit unique_ptr -> unique_ptr in Copy() GCC + DuckDB 1.4.4's unique_ptr does not implicitly convert derived->base, so 'return r;' in BinsBindData::Copy() fails to compile: error: could not convert 'r' from 'unique_ptr' to 'unique_ptr' Use duckdb's unique_ptr_cast helper (from duckdb/common/helper.hpp) to do the conversion explicitly, matching the canonical pattern used by DuckDB core (e.g. table_scan.hpp's TableScanBindData::Copy()). No behaviour change; the move is exactly what the implicit conversion would have done if the compiler accepted it. --- src/temporal/span_table_functions.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/temporal/span_table_functions.cpp b/src/temporal/span_table_functions.cpp index 92b3091e..df424346 100644 --- a/src/temporal/span_table_functions.cpp +++ b/src/temporal/span_table_functions.cpp @@ -44,7 +44,9 @@ struct BinsBindData : public FunctionData { r->blob = blob; r->vsize = vsize; r->vorigin = vorigin; - return r; + // DuckDB 1.4.4 disallows implicit derived->base unique_ptr conversion; + // explicit base-type construction from the moved-from derived pointer. + return unique_ptr_cast(std::move(r)); } bool Equals(const FunctionData &other_p) const override { auto &other = other_p.Cast();