Skip to content
Open
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
32 changes: 31 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,39 @@ 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/<duckdb_version>/<platform>/icu.duckdb_extension
# and falls back to a hub download. That fails both inside the linux_amd64
# test docker container (empty path, no network egress) and on the macOS
# osx_arm64 test runner (hub icu not reliably resolvable). 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,
# matched to the DuckDB platform string, before running the unittester.
DUCKDB_VERSION_TAG := v1.4.4

define stage_icu
@if [ -f ./build/$(1)/extension/icu/icu.duckdb_extension ]; then \
case "$$(uname -s)-$$(uname -m)" in \
Linux-x86_64) platform=linux_amd64 ;; \
Linux-aarch64) platform=linux_arm64 ;; \
Darwin-arm64) platform=osx_arm64 ;; \
Darwin-x86_64) platform=osx_amd64 ;; \
*) platform=$$(uname -m) ;; \
esac; \
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/*"
$(call stage_icu,reldebug)
./build/reldebug/$(TEST_PATH) "$(PROJ_DIR)test/*"
1 change: 1 addition & 0 deletions src/include/index/rtree_module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class TRTreeIndex : public BoundIndex {

MeosType bbox_meostype;
size_t bbox_size_;
LogicalType column_type_;

size_t current_size_ = 0;
size_t current_capacity_ = 0;
Expand Down
26 changes: 21 additions & 5 deletions src/include/tydef.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,27 @@ extern "C" {
#include <meos_internal.h>
}

// 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 {

Expand Down
99 changes: 16 additions & 83 deletions src/index/rtree_index_create_physical.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,99 +151,32 @@ class TRTreeIndexConstructTask final : public ExecutorTask {

const auto count = scan_chunk.size();

auto &vec_vec = scan_chunk.data[0];
auto &rowid_vec = scan_chunk.data[1];
auto &vec_vec = scan_chunk.data[0];
auto &rowid_vec = scan_chunk.data[1];

auto vector_type = vec_vec.GetType();

if (vec_vec.GetVectorType() != VectorType::FLAT_VECTOR) {
vec_vec.Flatten(count);
}
if (rowid_vec.GetVectorType() != VectorType::FLAT_VECTOR) {
rowid_vec.Flatten(count);
}

UnifiedVectorFormat vec_format;
UnifiedVectorFormat rowid_format;

vec_vec.ToUnifiedFormat(count, vec_format);
rowid_vec.ToUnifiedFormat(count, rowid_format);

const auto row_ptr = UnifiedVectorFormat::GetData<row_t>(rowid_format);
STBox* boxes = (STBox*)malloc(sizeof(STBox) * count);
if (!boxes) {
executor.PushError(ErrorData("Failed to allocate memory for STBox array"));
return TaskExecutionResult::TASK_ERROR;
}

idx_t valid_count = 0;
vector<row_t> valid_row_ids;

for (idx_t i = 0; i < count; i++) {
const auto vec_idx = vec_format.sel->get_index(i);
const auto row_idx = rowid_format.sel->get_index(i);

const auto vec_valid = vec_format.validity.RowIsValid(vec_idx);
const auto rowid_valid = rowid_format.validity.RowIsValid(row_idx);

if (!vec_valid || !rowid_valid) {
continue;
}

fprintf(stderr, "Processing row %zu (vec_idx=%zu, row_idx=%zu)\n", i, vec_idx, row_idx);

STBox *box = nullptr;

if (vector_type.id() == LogicalTypeId::BLOB) {

const auto stbox_data_ptr = UnifiedVectorFormat::GetData<string_t>(vec_format);
auto blob_data = stbox_data_ptr[vec_idx];
const uint8_t *stbox_bytes = reinterpret_cast<const uint8_t*>(blob_data.GetData());
size_t stbox_size = blob_data.GetSize();
box = (STBox*)malloc(stbox_size);
memcpy(box, stbox_bytes, stbox_size);

int32_t box_srid = stbox_srid(box);

if (box_srid != 0) {
STBox *normalized_box = stbox_set_srid(box, 0);
if (normalized_box) {
free(box);
box = normalized_box;
}
}

// Copy to our batch array
memcpy(&boxes[valid_count], box, sizeof(STBox));
valid_row_ids.push_back(row_ptr[row_idx]);
valid_count++;

free(box);


}
else {
free(boxes);
executor.PushError(ErrorData("Unsupported data type for RTree index: " + vector_type.ToString()));
return TaskExecutionResult::TASK_ERROR;
}
// Build a one-column DataChunk with the indexed expression so we
// can hand it to TRTreeIndex::Construct, which dispatches on the
// indexed column type to choose between rtree_insert (for box /
// span blobs whose bytes ARE the bbox) and rtree_insert_temporal
// (for Temporal blobs whose bbox is extracted at insert time).
DataChunk col_chunk;
vector<LogicalType> col_types = {vec_vec.GetType()};
col_chunk.Initialize(Allocator::DefaultAllocator(), col_types);
col_chunk.SetCardinality(count);
col_chunk.data[0].Reference(vec_vec);

{
lock_guard<mutex> l(gstate.glock);
gstate.global_index->Construct(col_chunk, rowid_vec);
}

// Now batch insert the valid STBoxes into the index
if (valid_count > 0) {
auto &rtree_index = gstate.global_index;

auto result = rtree_index->BulkConstruct(boxes, valid_row_ids.data(), valid_count);
if (result.HasError()) {
free(boxes);
executor.PushError(result);
return TaskExecutionResult::TASK_ERROR;
}

}

free(boxes);

gstate.built_count += count;

if (mode == TaskExecutionMode::PROCESS_PARTIAL) {
Expand Down
Loading
Loading