"""Storage-route helpers based on DBNames records. This module maps platform DBNames roles to physical SQL name candidates. It does not infer business semantics or concrete metadata object names. """ from __future__ import annotations from dataclasses import asdict, dataclass from typing import Iterable from .dbnames import DBNamesRecord TABLE_ROLE_PREFIX = { "Reference": "_Reference", "ReferenceChngR": "_ReferenceChngR", "Document": "_Document", "DocumentChngR": "_DocumentChngR", "Enum": "_Enum", "InfoRg": "_InfoRg", "InfoRgChngR": "_InfoRgChngR", "AccumRg": "_AccumRg", "AccumRgChngR": "_AccumRgChngR", "AccumRgOpt": "_AccumRgOpt", "AccumRgT": "_AccumRgT", "AccRg": "_AccRg", "AccRgAT0": "_AccRgAT0", "AccRgCT": "_AccRgCT", "AccRgChngR": "_AccRgChngR", "AccRgOpt": "_AccRgOpt", "Const": "_Const", "ConstChngR": "_ConstChngR", "DocumentJournal": "_DocumentJournal", "Node": "_Node", "ScheduledJobs": "_ScheduledJobs", "BPr": "_BPr", "BPrPoints": "_BPrPoints", "BPrChngR": "_BPrChngR", "Task": "_Task", "TaskChngR": "_TaskChngR", "Acc": "_Acc", "AccSInf": "_AccSInf", "AccChngR": "_AccChngR", "CKinds": "_CKinds", "CKindsChngR": "_CKindsChngR", "IntegServiceSettings": "_IntegServiceSettings", "IntegServiceMsgBody": "_IntegServiceMsgBody", "IntegServiceExtMsgBody": "_IntegServiceExtMsgBody", "IntegChannelInQueue": "_IntegChannelInQueue", "IntegChannelOutQueue": "_IntegChannelOutQueue", } FIELD_ROLE_PREFIX = { "Fld": "_Fld", } STRUCTURAL_ROLES = { "VT", "LineNo", "ByDims", "ByField", "ByResource", "ByProperty", "TurnoverDt", "TurnoverCt", "Turnover", } @dataclass(frozen=True) class StorageRoute: guid: str storage_role: str sql_number: int source: str route_kind: str physical_name_candidate: str | None note: str def to_dict(self) -> dict[str, object]: return asdict(self) def storage_route(record: DBNamesRecord) -> StorageRoute: """Return the mechanical SQL route candidate for one DBNames record.""" role = record.storage_role if role in TABLE_ROLE_PREFIX: return StorageRoute( guid=record.guid, storage_role=role, sql_number=record.sql_number, source=record.source, route_kind="table", physical_name_candidate=f"{TABLE_ROLE_PREFIX[role]}{record.sql_number}", note="table-like DBNames storage role", ) if role in FIELD_ROLE_PREFIX: return StorageRoute( guid=record.guid, storage_role=role, sql_number=record.sql_number, source=record.source, route_kind="field", physical_name_candidate=f"{FIELD_ROLE_PREFIX[role]}{record.sql_number}", note="field DBNames storage role; value suffixes depend on type evidence", ) if role in STRUCTURAL_ROLES: return StorageRoute( guid=record.guid, storage_role=role, sql_number=record.sql_number, source=record.source, route_kind="structural", physical_name_candidate=None, note="structural DBNames role; requires parent object/section context", ) return StorageRoute( guid=record.guid, storage_role=role, sql_number=record.sql_number, source=record.source, route_kind="unknown", physical_name_candidate=None, note="unclassified DBNames storage role", ) def group_records_by_guid(records: Iterable[DBNamesRecord]) -> dict[str, list[DBNamesRecord]]: grouped: dict[str, list[DBNamesRecord]] = {} for record in records: grouped.setdefault(record.guid, []).append(record) return grouped def storage_routes(records: Iterable[DBNamesRecord]) -> list[StorageRoute]: return [storage_route(record) for record in records]