Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,20 @@ def write_to_table(
# skip is internally used for dlt tables
table.append(table_data)
elif write_disposition == "merge":
strategy = self.prepare_load_table(table_name)["x-merge-strategy"] # type:ignore
dlt_schema = self.prepare_load_table(table_name)
join_columns = None
if not table.schema().identifier_field_ids:
join_columns = [
name
for name, column in dlt_schema["columns"].items()
if column.get("merge_key", False)
]
# provide merge key columns if no identifier-field-ids exist to mark the primary key columns
strategy = dlt_schema["x-merge-strategy"] # type:ignore
if strategy == "upsert":
# requires the indentifier fields to have been defined
table.upsert(
df=table_data,
join_cols=join_columns,
when_matched_update_all=True,
when_not_matched_insert_all=True,
case_sensitive=True,
Expand Down
2 changes: 1 addition & 1 deletion elt-common/tests/e2e_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class Settings(BaseSettings):
# trino
trino_http_scheme: str = "http"
trino_host: str = "localhost"
trino_port: str = "58088"
trino_port: str = "59088"
trino_user: str = "trino"
trino_password: str = ""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,19 @@ def pipeline_name(frame: FrameType | None):
return frame.f_code.co_name if frame is not None else "pipeline_name_frame_none"


def resource_factory(data: List[Dict[str, Any]] | None = None, primary_key: str | None = "id"):
def resource_factory(
data: List[Dict[str, Any]] | None = None,
primary_key: str | None = "id",
merge_key: str | None = None,
):
kwargs = {}
if primary_key is not None:
decorator = dlt.resource(primary_key=primary_key)
kwargs["primary_key"] = primary_key
if merge_key is not None:
kwargs["merge_key"] = merge_key

if kwargs:
decorator = dlt.resource(**kwargs)
else:
decorator = dlt.resource

Expand Down Expand Up @@ -168,10 +178,18 @@ def test_explicit_replace(
)


@pytest.mark.parametrize(
"identifier_keys",
[
{"primary_key": "id", "merge_key": None},
{"primary_key": None, "merge_key": "id"},
],
)
def test_explicit_merge_updates_expected_values(
warehouse: Warehouse,
pipelines_dir,
destination_config: PyIcebergDestinationTestConfiguration,
identifier_keys: dict,
) -> None:
num_records_first_run = 1000
data = [
Expand All @@ -187,7 +205,7 @@ def test_explicit_merge_updates_expected_values(
pipelines_dir=pipelines_dir,
)
# first run
pipeline.run(resource_factory(data, primary_key="id"))
pipeline.run(resource_factory(data, **identifier_keys))
assert_table_has_data(
pipeline,
f"{pipeline.dataset_name}.data_items",
Expand All @@ -204,7 +222,7 @@ def test_explicit_merge_updates_expected_values(
}
for i in range(num_records_upserted)
]
pipeline.run(resource_factory(data_updated, primary_key="id"), write_disposition="merge")
pipeline.run(resource_factory(data_updated, **identifier_keys), write_disposition="merge")
expected_data = [
{"id": i + 1, "category": "A" if i + 1 < id_updated_start else "B"}
for i in range(num_records_first_run + num_records_upserted - id_updated_start + 1)
Expand All @@ -217,6 +235,28 @@ def test_explicit_merge_updates_expected_values(
)


def test_merge_without_primary_or_merge_key_raises_error(
warehouse: Warehouse,
pipelines_dir,
destination_config: PyIcebergDestinationTestConfiguration,
) -> None:
num_records_first_run = 1000
data = [
{
"id": i + 1,
"category": "A",
}
for i in range(num_records_first_run)
]
pipeline = destination_config.setup_pipeline(
warehouse,
pipeline_name(inspect.currentframe()),
pipelines_dir=pipelines_dir,
)
with pytest.raises(Exception):
pipeline.run(resource_factory(data, primary_key=None), write_disposition="merge")


@pytest.mark.parametrize("merge_strategy", ["delete-insert", "scd2"])
def test_explicit_merge_not_supported_for_strategies_other_than_upsert(
warehouse: Warehouse,
Expand Down
4 changes: 2 additions & 2 deletions infra/local/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#
# - Keycloak identity provider: http://localhost:58080/auth
# - Lakekeeper iceberg catalog UI: http://localhost:58080/iceberg/ui. Log in with the credentials listed in keycloak/README
# - Trino query engine: http://localhost:58088
# - Trino query engine: http://localhost:59088
# - Superset BI tool: http://localhost:58080/workspace/playground. Log in with the credentials defined in env-for-testing
#
# Login credentials
Expand Down Expand Up @@ -97,7 +97,7 @@ services:
start_period: 5s
ports:
- "58080:80"
- "58088:8088" # Trino won't allow itself to be deployed on a prefix path
- "59088:8088" # Trino won't allow itself to be deployed on a prefix path
volumes:
- "./traefik/traefik.yml:/etc/traefik/traefik.yml"
- "./traefik/traefik-dynamic.yml:/etc/traefik/traefik-dynamic.yml"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,11 @@ def read_as_dataframe(file_obj: M365DriveItem) -> pd.DataFrame | None:
df = read_power_consumption_excel(io.BytesIO(file_bytes), skip_rows)
case _:
raise RuntimeError(f"Unsupported file extension in '{file_name}'")
except pd.errors.EmptyDataError as exc:
raise RuntimeError(
f"'{file_name} ({len(file_bytes)} bytes)': {str(exc)}"
) from exc
except Exception as exc:
LOGGER.error(
f"'Error loading {file_name} ({len(file_bytes)} bytes)'. File skipped.\nDetails: {str(exc)}"
)
return None

df["file_name"] = file_obj["file_name"]
return df
Expand All @@ -140,7 +141,7 @@ def read_as_dataframe(file_obj: M365DriveItem) -> pd.DataFrame | None:
yield df_batch


@dlt.resource(merge_key="file_name")
@dlt.resource(merge_key="DateTime", columns={"DateTime": {"nullable": False}})
Comment thread
martyngigg marked this conversation as resolved.
def rdm_data(
datetime_cur=dlt.sources.incremental(
"DateTime",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ trino_catalog:
password: "{{ env_var('DBT_TRINO_PASSWORD', '') }}"
http_scheme: "{{ env_var('DBT_TRINO_HTTP_SCHEME', 'http') }}"
host: "{{ env_var('DBT_TRINO_HOST', 'analytics.localhost') }}"
port: "{{ env_var('DBT_TRINO_PORT', '58088') | int }}"
port: "{{ env_var('DBT_TRINO_PORT', '59088') | int }}"
database: "{{ env_var('DBT_TRINO_CATALOG', 'accelerator') }}"
schema: "{{ env_var('DBT_TRINO_CATALOG_SCHEMA_PREFIX', 'dev_') }}analytics"
threads: "{{ env_var('DBT_TRINO_THREADS', '8') | int }}"