sets ducklake fingerprint to storage fingerprint (#3388)

This commit is contained in:
rudolfix
2025-11-27 17:08:46 +01:00
committed by GitHub
parent ff6d28185d
commit e15f5510b3
3 changed files with 15 additions and 1 deletions

View File

@@ -130,7 +130,10 @@ class DuckLakeClientConfiguration(WithLocalFiles, DestinationClientDwhWithStagin
create_indexes: bool = False # does nothing but required
def fingerprint(self) -> str:
return digest128(self.__str__())
"""Use fingerprint of underlying storage. This is precise to bucket level"""
if self.credentials.storage is None:
return ""
return self.credentials.storage.fingerprint()
def on_resolved(self) -> None:
# redirect local catalog database file to `local_dir`

View File

@@ -8,6 +8,7 @@ import dlt
from dlt.common.configuration.exceptions import ConfigFieldMissingException, ConfigurationValueError
from dlt.common.configuration.resolve import resolve_configuration
from dlt.common.configuration.specs.connection_string_credentials import ConnectionStringCredentials
from dlt.common.utils import digest128
from dlt.destinations.impl.ducklake.sql_client import DuckLakeSqlClient
from dlt.destinations.impl.ducklake.configuration import (
DuckLakeCredentials,
@@ -101,6 +102,8 @@ def test_ducklake_configuration_default() -> None:
assert credentials.storage_url == str(local_dir / "ducklake.files")
# file url
assert credentials.storage.bucket_url.startswith("file://")
# fingerprint is local
assert configuration.fingerprint() == digest128("file://")
def test_ducklake_configuration_duckdb_catalog() -> None:
@@ -118,6 +121,7 @@ def test_ducklake_configuration_duckdb_catalog() -> None:
assert credentials.ducklake_name == DEFAULT_DUCKLAKE_NAME
conn_str = credentials.catalog.to_native_representation()
assert conn_str.endswith(str(local_dir / "ducklake.duckdb"))
assert configuration.fingerprint() == digest128("file://")
def test_ducklake_configuration_ducklake_name() -> None:
@@ -134,6 +138,8 @@ def test_ducklake_configuration_ducklake_name() -> None:
conn_str = credentials.catalog.to_native_representation()
assert conn_str.endswith(str(local_dir / "my_ducklake.sqlite"))
assert credentials.storage_url == str(local_dir / "my_ducklake.files")
# fingerprint is local
assert configuration.fingerprint() == digest128("file://")
def test_ducklake_configuration_destination_name() -> None:
@@ -150,6 +156,8 @@ def test_ducklake_configuration_destination_name() -> None:
conn_str = credentials.catalog.to_native_representation()
assert conn_str.endswith(str(local_dir / "ducklake.sqlite"))
assert credentials.storage_url == str(local_dir / "ducklake.files")
# fingerprint is local
assert configuration.fingerprint() == digest128("file://")
def test_ducklake_configuration_pipeline_name() -> None:
@@ -194,6 +202,8 @@ def test_ducklake_configuration_storage_credentials() -> None:
)
# NOTE: dataset folders will be created in /lake/
assert credentials.storage_url == "s3://dlt-ci-test-bucket/lake"
# fingerprint is NOT local
assert configuration.fingerprint() == digest128("s3://dlt-ci-test-bucket")
def test_ducklake_configuration_catalog_credentials() -> None:

View File

@@ -69,6 +69,7 @@ def _client_factory(fs: filesystem) -> FilesystemClient:
(
(None, ""),
("/path/path2", digest128("")),
("file:///home/ducklake.d", digest128("file://")),
("s3://cool", digest128("s3://cool")),
("s3://cool.domain/path/path2", digest128("s3://cool.domain")),
),