diff --git a/src/dve/core_engine/backends/base/rules.py b/src/dve/core_engine/backends/base/rules.py index acfe079..ee93106 100644 --- a/src/dve/core_engine/backends/base/rules.py +++ b/src/dve/core_engine/backends/base/rules.py @@ -51,6 +51,7 @@ from dve.core_engine.exceptions import CriticalProcessingError from dve.core_engine.loggers import get_logger from dve.core_engine.message import FeedbackMessage +from dve.core_engine.templating import template_object from dve.core_engine.type_hints import URI, DVEStageName, EntityName, Messages, TemplateVariables T_contra = TypeVar("T_contra", bound=AbstractStep, contravariant=True) @@ -446,7 +447,10 @@ def process_node(node: HierarchyNode): entity=node.entity_name, record=record, # type: ignore error_location=location, - error_message=node.missing_parent_id_error_message, + error_message=template_object( + node.missing_parent_id_error_message, + record + ), failure_type="record", error_type="record", error_code=node.missing_parent_id_error_code, @@ -518,7 +522,10 @@ def process_node(node: HierarchyNode) -> bool: entity=node.parent_entity, record=record, # type: ignore error_location=location, - error_message=node.no_valid_records_error_message, + error_message=template_object( + node.no_valid_records_error_message, + record + ), failure_type="record", error_type="record", error_code=node.no_valid_records_error_code, diff --git a/src/dve/core_engine/backends/implementations/duckdb/rules.py b/src/dve/core_engine/backends/implementations/duckdb/rules.py index c99b152..dbbbc54 100644 --- a/src/dve/core_engine/backends/implementations/duckdb/rules.py +++ b/src/dve/core_engine/backends/implementations/duckdb/rules.py @@ -439,6 +439,15 @@ def remove_orphans(self, entities: DuckDBEntities, *, config: OrphanRemoval) -> .filter(f"entity_name = '{config.entity_name}'") .set_alias("orphan") ) + message_rel = ( + entities[config.entity_name] + .set_alias(config.entity_name) + .join( + orphan_rel, + f"{config.entity_name}.{RECORD_INDEX_COLUMN_NAME} = orphan.{RECORD_INDEX_COLUMN_NAME}", # pylint: disable=C0301 + "semi", + ) + ) filtered_rel = ( entities[config.entity_name] .set_alias(config.entity_name) @@ -451,7 +460,7 @@ def remove_orphans(self, entities: DuckDBEntities, *, config: OrphanRemoval) -> entities[config.entity_name] = filtered_rel - return duckdb_rel_to_dictionaries(orphan_rel) + return duckdb_rel_to_dictionaries(message_rel) def check_mandatory_group( self, entities: DuckDBEntities, *, config: GroupIdentification diff --git a/tests/testdata/flights/flights.dischema.json b/tests/testdata/flights/flights.dischema.json index 1ea7837..1e3a83d 100644 --- a/tests/testdata/flights/flights.dischema.json +++ b/tests/testdata/flights/flights.dischema.json @@ -176,9 +176,9 @@ }, "mandatory": true, "missing_parent_id_error_code": "StaffHasNoAirport", - "missing_parent_id_error_message": "Record rejected - No valid airport id found for staff", + "missing_parent_id_error_message": "Record rejected - No valid airport id found for staff. Airport ID = {{ airport_id }}, Staff ID = {{ staff_id }}", "no_valid_records_error_code": "AirportHasNoStaff", - "no_valid_records_error_message": "Group rejected - Airport has no valid staff" + "no_valid_records_error_message": "Group rejected - Airport has no valid staff. Airport ID = {{ airport_id }}" }, "flights": { "parent_entity": "airport",