From 30bc1f15d6afbf105e1def26843b90bbfb3f8e02 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 19 Sep 2026 18:59:00 -0700 Subject: [PATCH 1/2] Add DuckLake storage extension with SQL pushdown support Mirrors the Iceberg/Unity Catalog extensions: embeds DuckDB, LOADs the ducklake (+httpfs) extension, and ATTACHes 'ducklake:' inside the embedded instance. Reuses DuckDBCatalog + AttachedDuckDBDatabase, so information_schema column lookups and the ForeignJoinPushDownOptimizer work with no core changes (default schema 'main', like DuckDB). - DBTYPE DUCKLAKE; 'ducklake:'-prefixed, postgres-style, and file metadata paths pass through; empty path uses the TYPE ducklake secret. - ducklake_data_path / ducklake_read_only options (SET-able, env-seeded), forwarded as DATA_PATH + OVERRIDE_DATA_PATH / READ_ONLY. - Hermetic e2e test (ducklake.test) with checked-in file-backed catalog; rel tables need explicit CREATE REL TABLE ... WITH (storage=...) since DuckLake stores no PK/FK constraints for auto-detection. --- CMakeLists.txt | 1 + ducklake/CMakeLists.txt | 37 +++++++ ducklake/src/connector/CMakeLists.txt | 9 ++ ducklake/src/connector/ducklake_connector.cpp | 39 +++++++ .../include/connector/ducklake_connector.h | 15 +++ .../src/include/main/ducklake_extension.h | 17 +++ .../src/include/options/ducklake_options.h | 52 ++++++++++ .../src/include/storage/ducklake_storage.h | 25 +++++ ducklake/src/installer/CMakeLists.txt | 11 ++ .../src/installer/ducklake_install_func.cpp | 16 +++ ducklake/src/main/CMakeLists.txt | 7 ++ ducklake/src/main/ducklake_extension.cpp | 38 +++++++ ducklake/src/options/CMakeLists.txt | 7 ++ ducklake/src/options/ducklake_options.cpp | 97 ++++++++++++++++++ ducklake/src/storage/CMakeLists.txt | 13 +++ ducklake/src/storage/ducklake_storage.cpp | 46 +++++++++ ducklake/test/test_files/ducklake.test | 61 +++++++++++ ducklake/test/test_files/users.ducklake | Bin 0 -> 4206592 bytes extension_config.cmake | 2 +- 19 files changed, 492 insertions(+), 1 deletion(-) create mode 100644 ducklake/CMakeLists.txt create mode 100644 ducklake/src/connector/CMakeLists.txt create mode 100644 ducklake/src/connector/ducklake_connector.cpp create mode 100644 ducklake/src/include/connector/ducklake_connector.h create mode 100644 ducklake/src/include/main/ducklake_extension.h create mode 100644 ducklake/src/include/options/ducklake_options.h create mode 100644 ducklake/src/include/storage/ducklake_storage.h create mode 100644 ducklake/src/installer/CMakeLists.txt create mode 100644 ducklake/src/installer/ducklake_install_func.cpp create mode 100644 ducklake/src/main/CMakeLists.txt create mode 100644 ducklake/src/main/ducklake_extension.cpp create mode 100644 ducklake/src/options/CMakeLists.txt create mode 100644 ducklake/src/options/ducklake_options.cpp create mode 100644 ducklake/src/storage/CMakeLists.txt create mode 100644 ducklake/src/storage/ducklake_storage.cpp create mode 100644 ducklake/test/test_files/ducklake.test create mode 100644 ducklake/test/test_files/users.ducklake diff --git a/CMakeLists.txt b/CMakeLists.txt index f7f0860b..aebf4153 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,7 @@ add_extension_if_enabled_and_skip_32bit("delta") add_extension_if_enabled_and_skip_32bit("iceberg") add_extension_if_enabled_and_skip_32bit("azure") add_extension_if_enabled_and_skip_32bit("unity_catalog") +add_extension_if_enabled_and_skip_32bit("ducklake") add_extension_if_enabled("json") add_extension_if_enabled("fts") add_extension_if_enabled("vector") diff --git a/ducklake/CMakeLists.txt b/ducklake/CMakeLists.txt new file mode 100644 index 00000000..07c7ba21 --- /dev/null +++ b/ducklake/CMakeLists.txt @@ -0,0 +1,37 @@ +if (WIN32 OR BUILD_STATIC_EXTENSION) + set(DuckDB_USE_STATIC_LIBS ON) +else () + set(DuckDB_USE_STATIC_LIBS OFF) +endif () +find_package(DuckDB REQUIRED) + +include_directories( + ${PROJECT_SOURCE_DIR}/src/include + ${CMAKE_BINARY_DIR}/src/include + src/include + ${PROJECT_SOURCE_DIR}/extension/duckdb/src/include + ${PROJECT_SOURCE_DIR}/extension/httpfs/src/include # For S3 configuration + ${DuckDB_INCLUDE_DIRS}) + +add_subdirectory(src/installer) +add_subdirectory(src/main) +add_subdirectory(src/connector) +add_subdirectory(src/storage) +add_subdirectory(src/options) + +build_extension_lib(${BUILD_STATIC_EXTENSION} "ducklake") + +target_link_libraries(lbug_${EXTENSION_LIB_NAME}_extension + PRIVATE + ${DuckDB_LIBRARIES}) + +if (NOT WIN32 AND NOT BUILD_STATIC_EXTENSION) + add_library(ducklake_loader + SHARED + ${PROJECT_SOURCE_DIR}/extension/duckdb/src/loader/duckdb_loader.cpp) + set_extension_properties(ducklake_loader ducklake_loader ducklake) +endif () + +if (APPLE AND NOT BUILD_STATIC_EXTENSION) + set_apple_dynamic_lookup(ducklake_loader) +endif () diff --git a/ducklake/src/connector/CMakeLists.txt b/ducklake/src/connector/CMakeLists.txt new file mode 100644 index 00000000..865df879 --- /dev/null +++ b/ducklake/src/connector/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(lbug_ducklake_connector + OBJECT + ducklake_connector.cpp + ${PROJECT_SOURCE_DIR}/extension/duckdb/src/connector/duckdb_connector.cpp + ${PROJECT_SOURCE_DIR}/extension/duckdb/src/connector/duckdb_result_converter.cpp) + +set(DUCKLAKE_EXTENSION_OBJECT_FILES + ${DUCKLAKE_EXTENSION_OBJECT_FILES} $ + PARENT_SCOPE) diff --git a/ducklake/src/connector/ducklake_connector.cpp b/ducklake/src/connector/ducklake_connector.cpp new file mode 100644 index 00000000..8fea8323 --- /dev/null +++ b/ducklake/src/connector/ducklake_connector.cpp @@ -0,0 +1,39 @@ +#include "connector/ducklake_connector.h" + +#include "options/ducklake_options.h" +#include + +namespace lbug { +namespace ducklake_extension { + +// Ensures a DuckDB extension is loaded. LOAD is attempted first so that an +// already-installed extension is reused as-is (no network, no repository +// origin check). INSTALL runs only as a fallback when the extension is +// missing, e.g. on a fresh machine. +static void ensureExtensionLoaded(const duckdb_extension::DuckDBConnector& connector, + const std::string& extensionName) { + try { + connector.executeQuery(std::format("load {};", extensionName)); + return; + } catch (const common::Exception&) { + // Not installed yet: fall through to INSTALL. + } + connector.executeQuery(std::format("install {};", extensionName)); + connector.executeQuery(std::format("load {};", extensionName)); +} + +void DuckLakeConnector::connect(const std::string& dbPath, const std::string& catalogName, + const std::string& /*schemaName*/, main::ClientContext* context) { + // Creates an in-memory DuckDB instance, loads the ducklake extension + // (plus httpfs for remote DATA_PATHs such as s3://), then attaches the + // DuckLake catalog inside the embedded instance so its tables can be + // referenced by fully qualified name (e.g. my_lake.main.person). + instance = std::make_unique(nullptr); + connection = std::make_unique(*instance); + ensureExtensionLoaded(*this, "ducklake"); + ensureExtensionLoaded(*this, "httpfs"); + executeQuery(DuckLakeAttachHelper::getAttachQuery(dbPath, catalogName, context)); +} + +} // namespace ducklake_extension +} // namespace lbug diff --git a/ducklake/src/include/connector/ducklake_connector.h b/ducklake/src/include/connector/ducklake_connector.h new file mode 100644 index 00000000..5055beba --- /dev/null +++ b/ducklake/src/include/connector/ducklake_connector.h @@ -0,0 +1,15 @@ +#pragma once + +#include "connector/duckdb_connector.h" + +namespace lbug { +namespace ducklake_extension { + +class DuckLakeConnector : public duckdb_extension::DuckDBConnector { +public: + void connect(const std::string& dbPath, const std::string& catalogName, + const std::string& schemaName, main::ClientContext* context) override; +}; + +} // namespace ducklake_extension +} // namespace lbug diff --git a/ducklake/src/include/main/ducklake_extension.h b/ducklake/src/include/main/ducklake_extension.h new file mode 100644 index 00000000..f42b4d07 --- /dev/null +++ b/ducklake/src/include/main/ducklake_extension.h @@ -0,0 +1,17 @@ +#pragma once + +#include "extension/extension.h" + +namespace lbug { +namespace ducklake_extension { + +class DuckLakeExtension final : public extension::Extension { +public: + static constexpr char EXTENSION_NAME[] = "DUCKLAKE"; + +public: + static void load(main::ClientContext* context); +}; + +} // namespace ducklake_extension +} // namespace lbug diff --git a/ducklake/src/include/options/ducklake_options.h b/ducklake/src/include/options/ducklake_options.h new file mode 100644 index 00000000..6d8d92a2 --- /dev/null +++ b/ducklake/src/include/options/ducklake_options.h @@ -0,0 +1,52 @@ +#pragma once + +#include "common/types/value/value.h" + +namespace lbug { +namespace main { +class Database; +class ClientContext; +} // namespace main + +namespace ducklake_extension { + +// Optional override for the DuckLake `DATA_PATH` ATTACH parameter. When set, +// it is appended to the `ATTACH 'ducklake:...'` statement executed on the +// embedded DuckDB instance as `(DATA_PATH '...', OVERRIDE_DATA_PATH true)`, +// so the given directory is used instead of the data path stored in the +// DuckLake metadata for the current connection (the stored value is left +// untouched). Empty (the default) leaves the stored path untouched, which is +// the common case for file-backed catalogs. The override form is required +// because DuckDB rejects a plain `DATA_PATH` that differs from the stored +// path, and it is what makes relocated catalogs (e.g. checked-in test data) +// queryable. +struct DuckLakeDataPath { + static constexpr const char* NAME = "ducklake_data_path"; + static constexpr common::LogicalTypeID TYPE = common::LogicalTypeID::STRING; + static common::Value getDefaultValue() { return common::Value{std::string()}; } +}; + +// Optional read-only flag, forwarded as `READ_ONLY` to the embedded `ATTACH`. +struct DuckLakeReadOnly { + static constexpr const char* NAME = "ducklake_read_only"; + static constexpr common::LogicalTypeID TYPE = common::LogicalTypeID::BOOL; + static common::Value getDefaultValue() { return common::Value{false}; } +}; + +struct DuckLakeOptions { + static void registerExtensionOptions(main::Database* db); + static void setEnvValue(main::ClientContext* context); + static std::string getDataPath(main::ClientContext* context); + static bool getReadOnly(main::ClientContext* context); +}; + +// Translates the Ladybug ATTACH path and extension options into the +// `ATTACH 'ducklake:...' AS (...)` statement executed on the embedded +// DuckDB instance. +struct DuckLakeAttachHelper { + static std::string getAttachQuery(const std::string& dbPath, const std::string& catalogAlias, + main::ClientContext* context); +}; + +} // namespace ducklake_extension +} // namespace lbug diff --git a/ducklake/src/include/storage/ducklake_storage.h b/ducklake/src/include/storage/ducklake_storage.h new file mode 100644 index 00000000..5f53eb5b --- /dev/null +++ b/ducklake/src/include/storage/ducklake_storage.h @@ -0,0 +1,25 @@ +#pragma once + +#include "storage/storage_extension.h" + +namespace lbug { +namespace main { +class Database; +} // namespace main + +namespace ducklake_extension { + +class DuckLakeStorageExtension final : public storage::StorageExtension { +public: + static constexpr const char* DB_TYPE = "DUCKLAKE"; + + // DuckLake catalogs live in DuckDB, whose default schema is `main`. + static constexpr const char* DEFAULT_SCHEMA_NAME = "main"; + + explicit DuckLakeStorageExtension(main::Database& database); + + bool canHandleDB(std::string dbType) const override; +}; + +} // namespace ducklake_extension +} // namespace lbug diff --git a/ducklake/src/installer/CMakeLists.txt b/ducklake/src/installer/CMakeLists.txt new file mode 100644 index 00000000..ef5e2524 --- /dev/null +++ b/ducklake/src/installer/CMakeLists.txt @@ -0,0 +1,11 @@ +if (NOT WIN32) + add_library(ducklake_installer + SHARED + ducklake_install_func.cpp + ${PROJECT_SOURCE_DIR}/extension/duckdb/src/installer/duckdb_installer.cpp) + set_extension_properties(ducklake_installer ducklake_installer ducklake) +endif () + +if (APPLE) + set_apple_dynamic_lookup(ducklake_installer) +endif () diff --git a/ducklake/src/installer/ducklake_install_func.cpp b/ducklake/src/installer/ducklake_install_func.cpp new file mode 100644 index 00000000..77ee9728 --- /dev/null +++ b/ducklake/src/installer/ducklake_install_func.cpp @@ -0,0 +1,16 @@ +#include "installer/duckdb_installer.h" + +extern "C" { +// Because we link against the static library on windows, we implicitly inherit LBUG_STATIC_DEFINE, +// which cancels out any exporting, so we can't use LBUG_API. +#if defined(_WIN32) +#define INIT_EXPORT __declspec(dllexport) +#else +#define INIT_EXPORT __attribute__((visibility("default"))) +#endif +INIT_EXPORT void install(const std::string& repo, lbug::main::ClientContext& context) { + lbug::extension::InstallExtensionInfo info{"ducklake", repo, false /* forceInstall */}; + lbug::duckdb_extension::DuckDBInstaller installer{info, context}; + installer.install(); +} +} diff --git a/ducklake/src/main/CMakeLists.txt b/ducklake/src/main/CMakeLists.txt new file mode 100644 index 00000000..eebaf4aa --- /dev/null +++ b/ducklake/src/main/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(ducklake_extension_main + OBJECT + ducklake_extension.cpp) + +set(DUCKLAKE_EXTENSION_OBJECT_FILES + ${DUCKLAKE_EXTENSION_OBJECT_FILES} $ + PARENT_SCOPE) diff --git a/ducklake/src/main/ducklake_extension.cpp b/ducklake/src/main/ducklake_extension.cpp new file mode 100644 index 00000000..90f5a29d --- /dev/null +++ b/ducklake/src/main/ducklake_extension.cpp @@ -0,0 +1,38 @@ + +#include "main/ducklake_extension.h" + +#include "main/client_context.h" +#include "options/ducklake_options.h" +#include "storage/ducklake_storage.h" + +namespace lbug { +namespace ducklake_extension { + +void DuckLakeExtension::load(main::ClientContext* context) { + auto& db = *context->getDatabase(); + db.registerStorageExtension(EXTENSION_NAME, std::make_unique(db)); + DuckLakeOptions::registerExtensionOptions(&db); + DuckLakeOptions::setEnvValue(context); +} + +} // namespace ducklake_extension +} // namespace lbug + +#if defined(BUILD_DYNAMIC_LOAD) +extern "C" { +// Because we link against the static library on windows, we implicitly inherit LBUG_STATIC_DEFINE, +// which cancels out any exporting, so we can't use LBUG_API. +#if defined(_WIN32) +#define INIT_EXPORT __declspec(dllexport) +#else +#define INIT_EXPORT __attribute__((visibility("default"))) +#endif +INIT_EXPORT void init(lbug::main::ClientContext* context) { + lbug::ducklake_extension::DuckLakeExtension::load(context); +} + +INIT_EXPORT const char* name() { + return lbug::ducklake_extension::DuckLakeExtension::EXTENSION_NAME; +} +} +#endif diff --git a/ducklake/src/options/CMakeLists.txt b/ducklake/src/options/CMakeLists.txt new file mode 100644 index 00000000..f74972ca --- /dev/null +++ b/ducklake/src/options/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(lbug_ducklake_options + OBJECT + ducklake_options.cpp) + +set(DUCKLAKE_EXTENSION_OBJECT_FILES + ${DUCKLAKE_EXTENSION_OBJECT_FILES} $ + PARENT_SCOPE) diff --git a/ducklake/src/options/ducklake_options.cpp b/ducklake/src/options/ducklake_options.cpp new file mode 100644 index 00000000..538f6a6b --- /dev/null +++ b/ducklake/src/options/ducklake_options.cpp @@ -0,0 +1,97 @@ +#include "options/ducklake_options.h" + +#include "common/string_utils.h" +#include "extension/extension.h" +#include "main/client_context.h" +#include "main/database.h" +#include + +namespace lbug { +namespace ducklake_extension { + +using namespace common; + +namespace { + +std::string escapeSingleQuotes(std::string value) { + StringUtils::replaceAll(value, "'", "''"); + return value; +} + +// Reads an option value from the environment. Both the option name as-is and +// its upper-case form are accepted (e.g. `ducklake_data_path` or +// `DUCKLAKE_DATA_PATH`). +std::string getEnvOption(const char* name) { + auto value = main::ClientContext::getEnvVariable(name); + if (value.empty()) { + value = main::ClientContext::getEnvVariable(StringUtils::getUpper(std::string(name))); + } + return value; +} + +void setEnvOption(main::ClientContext* context, const char* name) { + auto value = getEnvOption(name); + if (!value.empty()) { + context->setExtensionOption(name, Value::createValue(value)); + } +} + +} // namespace + +void DuckLakeOptions::registerExtensionOptions(main::Database* db) { + ADD_EXTENSION_OPTION(DuckLakeDataPath); + ADD_EXTENSION_OPTION(DuckLakeReadOnly); +} + +void DuckLakeOptions::setEnvValue(main::ClientContext* context) { + setEnvOption(context, DuckLakeDataPath::NAME); + auto readOnly = getEnvOption(DuckLakeReadOnly::NAME); + if (!readOnly.empty()) { + StringUtils::toLower(readOnly); + context->setExtensionOption(DuckLakeReadOnly::NAME, + Value::createValue(readOnly == "true" || readOnly == "1")); + } +} + +std::string DuckLakeOptions::getDataPath(main::ClientContext* context) { + return context->getCurrentSetting(DuckLakeDataPath::NAME).toString(); +} + +bool DuckLakeOptions::getReadOnly(main::ClientContext* context) { + auto value = context->getCurrentSetting(DuckLakeReadOnly::NAME); + return value.getDataType().getLogicalTypeID() == LogicalTypeID::BOOL && value.getValue(); +} + +std::string DuckLakeAttachHelper::getAttachQuery(const std::string& dbPath, + const std::string& catalogAlias, main::ClientContext* context) { + // Normalize the ATTACH target. An empty path means "read the + // configuration from the default (unnamed) TYPE ducklake secret" + // (`ATTACH 'ducklake:'`). A path that already carries the `ducklake:` + // scheme (e.g. `ducklake:postgres:dbname=...`) is used as-is; anything + // else is treated as the metadata catalog path and prefixed. + std::string target; + if (dbPath.empty()) { + target = "ducklake:"; + } else if (dbPath.rfind("ducklake:", 0) == 0) { + target = dbPath; + } else { + target = "ducklake:" + dbPath; + } + std::string options; + auto dataPath = DuckLakeOptions::getDataPath(context); + if (!dataPath.empty()) { + // OVERRIDE_DATA_PATH is required: DuckDB rejects a DATA_PATH that + // differs from the catalog's stored path without it. + options += + std::format(", DATA_PATH '{}', OVERRIDE_DATA_PATH true", escapeSingleQuotes(dataPath)); + } + if (DuckLakeOptions::getReadOnly(context)) { + options += ", READ_ONLY"; + } + // Strip the leading ", " when options are present. + auto params = options.empty() ? std::string{} : " (" + options.substr(2) + ")"; + return std::format("ATTACH '{}' AS {}{};", escapeSingleQuotes(target), catalogAlias, params); +} + +} // namespace ducklake_extension +} // namespace lbug diff --git a/ducklake/src/storage/CMakeLists.txt b/ducklake/src/storage/CMakeLists.txt new file mode 100644 index 00000000..41002c82 --- /dev/null +++ b/ducklake/src/storage/CMakeLists.txt @@ -0,0 +1,13 @@ +add_library(lbug_ducklake_storage + OBJECT + ducklake_storage.cpp + ${PROJECT_SOURCE_DIR}/extension/duckdb/src/catalog/duckdb_catalog.cpp + ${PROJECT_SOURCE_DIR}/extension/duckdb/src/function/duckdb_scan.cpp + ${PROJECT_SOURCE_DIR}/extension/duckdb/src/function/clear_cache.cpp + ${PROJECT_SOURCE_DIR}/extension/duckdb/src/connector/duckdb_type_converter.cpp + ${PROJECT_SOURCE_DIR}/extension/duckdb/src/catalog/duckdb_table_catalog_entry.cpp +) + +set(DUCKLAKE_EXTENSION_OBJECT_FILES + ${DUCKLAKE_EXTENSION_OBJECT_FILES} $ + PARENT_SCOPE) diff --git a/ducklake/src/storage/ducklake_storage.cpp b/ducklake/src/storage/ducklake_storage.cpp new file mode 100644 index 00000000..3d417612 --- /dev/null +++ b/ducklake/src/storage/ducklake_storage.cpp @@ -0,0 +1,46 @@ +#include "storage/ducklake_storage.h" + +#include "catalog/duckdb_catalog.h" +#include "common/string_utils.h" +#include "connector/ducklake_connector.h" +#include "extension/extension.h" +#include "function/clear_cache.h" +#include "storage/attached_duckdb_database.h" + +namespace lbug { +namespace ducklake_extension { + +std::unique_ptr attachDuckLake(std::string dbName, std::string dbPath, + main::ClientContext* clientContext, const binder::AttachOption& attachOption) { + if (dbName == "") { + dbName = dbPath; + } + auto connector = std::make_unique(); + // The DuckDB-side catalog is attached AS dbName, so DuckDBCatalog must use + // dbName (not dbPath) as its catalog name: information_schema lookups and + // generated SQL reference the attached alias. The catalog is constructed + // before connecting so that ATTACH option validation happens before any + // filesystem or network I/O. + auto catalog = std::make_unique(dbPath, dbName, + DuckLakeStorageExtension::DEFAULT_SCHEMA_NAME, clientContext, *connector, attachOption, + dbName); + connector->connect(dbPath, dbName, DuckLakeStorageExtension::DEFAULT_SCHEMA_NAME, + clientContext); + catalog->init(); + return std::make_unique(dbName, + DuckLakeStorageExtension::DB_TYPE, std::move(catalog), std::move(connector)); +} + +DuckLakeStorageExtension::DuckLakeStorageExtension(main::Database& database) + : StorageExtension{attachDuckLake} { + extension::ExtensionUtils::addStandaloneTableFunc( + database); +} + +bool DuckLakeStorageExtension::canHandleDB(std::string dbType_) const { + common::StringUtils::toUpper(dbType_); + return dbType_ == DB_TYPE; +} + +} // namespace ducklake_extension +} // namespace lbug diff --git a/ducklake/test/test_files/ducklake.test b/ducklake/test/test_files/ducklake.test new file mode 100644 index 00000000..d8a770b8 --- /dev/null +++ b/ducklake/test/test_files/ducklake.test @@ -0,0 +1,61 @@ +-DATASET CSV empty + +-- + +-CASE DuckLakeScan +-SKIP_FSM_LEAK_CHECK +-LOAD_DYNAMIC_EXTENSION ducklake +# Data files are referenced by relative paths, so the checked-in catalog is +# relocatable as long as users.ducklake.files/ sits next to users.ducklake. +# Setting ducklake_data_path exercises the override plumbing (it is forwarded +# as DATA_PATH + OVERRIDE_DATA_PATH to the embedded DuckDB ATTACH). +-STATEMENT CALL ducklake_data_path='${LBUG_ROOT_DIRECTORY}/extension/ducklake/test/test_files/users.ducklake.files/'; +---- ok +-STATEMENT ATTACH '${LBUG_ROOT_DIRECTORY}/extension/ducklake/test/test_files/users.ducklake' as dl (dbtype ducklake); +---- 1 +Attached database successfully. +-STATEMENT LOAD FROM dl.person RETURN name ORDER BY name; +---- 3 +Alice +Bob +Carol +-STATEMENT LOAD FROM dl.knows RETURN src_id, dst_id ORDER BY src_id, dst_id; +---- 4 +0|1 +0|2 +1|0 +2|1 +-STATEMENT MATCH (p:dl.person) RETURN count(*); +---- 1 +3 +-STATEMENT MATCH (p:dl.person) WHERE p.name = 'Alice' RETURN count(*); +---- 1 +1 +-STATEMENT CALL TABLE_INFO('dl.person') RETURN *; +---- ok +-STATEMENT DETACH dl; +---- ok + +# DuckLake stores no PRIMARY KEY / FOREIGN KEY constraints, so rel tables are +# not auto-detected from duckdb_constraints(). Declare the rel explicitly with +# storage pointing at the DuckLake table; the src/dst column convention then +# lets the foreign join pushdown fire (same as SQL catalogs without FKs). +-CASE DuckLakeJoinPushdown +-SKIP_FSM_LEAK_CHECK +-LOAD_DYNAMIC_EXTENSION ducklake +-STATEMENT CALL ducklake_data_path='${LBUG_ROOT_DIRECTORY}/extension/ducklake/test/test_files/users.ducklake.files/'; +---- ok +-STATEMENT ATTACH '${LBUG_ROOT_DIRECTORY}/extension/ducklake/test/test_files/users.ducklake' as dl (dbtype ducklake); +---- 1 +Attached database successfully. +-STATEMENT CREATE REL TABLE knows_rel (FROM dl.person TO dl.person) WITH (storage = 'dl.knows'); +---- 1 +Table knows_rel has been created. +-LOG JoinPushdownOverDuckLake +-STATEMENT MATCH (a:dl.person)-[b:knows_rel]->(c:dl.person) RETURN count(*); +---- 1 +4 +-STATEMENT EXPLAIN MATCH (a:dl.person)-[b:knows_rel]->(c:dl.person) RETURN count(*); +---- ok +-STATEMENT DETACH dl; +---- ok diff --git a/ducklake/test/test_files/users.ducklake b/ducklake/test/test_files/users.ducklake new file mode 100644 index 0000000000000000000000000000000000000000..88be8a97d9ed8e171db11e44e45f0d6b29190ef8 GIT binary patch literal 4206592 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 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAn@cC`1CJ-`nw9((-fzPo86K!5-N0tBAy0%f=4TE1{3&E~TIXDebco3i!AvKava z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAn+6w_@}S_u^;=vpMAqS z=Zf>6FXrXv0~0c?R4hT;=3Na>-?ABdbso0^Io6L z-~Bi8`Cs@{KL3r)eE!l2$0=7IFBams2h-xD{mbxY-M>8kGaJV**P9a{K!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009EC3%vCsue<+4-+1VK zk8hd?5FkK+0D&jFK-ojMmMdYOOKUkji*!;*`;c%ds&lmIJE2Yoa z7p)*bfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 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 z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBoLD+2weOCNeCM+Z;h z^m2@q7?VvXPbiTdzdZjtlOq;EG+Nd|C ziaC!b9)|Sox~L5&7gxW`$uF8OUv)d}R$9zy)f;J1ci)^)75^>&o}$Z}009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U_>;i-bbaE}+4s|O zOjcq{VyxbAj@JSK0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ P009C72oNCf4+`7>TMzwh literal 0 HcmV?d00001 diff --git a/extension_config.cmake b/extension_config.cmake index f77bf2dc..63d2a8aa 100644 --- a/extension_config.cmake +++ b/extension_config.cmake @@ -1,4 +1,4 @@ -set(EXTENSION_LIST adbc azure delta duckdb fts httpfs iceberg json llm pg_client postgres sqlite unity_catalog vector neo4j algo gql) +set(EXTENSION_LIST adbc azure delta duckdb ducklake fts httpfs iceberg json llm pg_client postgres sqlite unity_catalog vector neo4j algo gql) #set(EXTENSION_STATIC_LINK_LIST fts) foreach(extension IN LISTS EXTENSION_STATIC_LINK_LIST) From 1d08efe282c7696c85e44fe99cdae93138405bc4 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 19 Sep 2026 20:31:42 -0700 Subject: [PATCH 2/2] CI: build the ducklake extension The e2e runner executes every test file under extension/, including ducklake.test, but libducklake.lbug_extension was never built because EXTENSION_LIST omitted ducklake. LOAD_DYNAMIC_EXTENSION then failed and both DuckLake cases cascaded (unknown option, no DBTYPE handler). --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 16f34da7..fa7a39f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ concurrency: env: # pg_client requires libpq (PostgreSQL) at build time and a running # PostgreSQL instance at test time (provided by run_pgembed_fixture.py). - EXTENSION_LIST: adbc;azure;delta;duckdb;fts;httpfs;iceberg;json;llm;neo4j;pg_client;postgres;sqlite;unity_catalog;vector;algo;gql + EXTENSION_LIST: adbc;azure;delta;duckdb;ducklake;fts;httpfs;iceberg;json;llm;neo4j;pg_client;postgres;sqlite;unity_catalog;vector;algo;gql jobs: # ─────────────────────────────────────────────────────────────────