Skip to content

tdfs4ds.migration.executor

tdfs4ds.migration.executor

Cross-store migration executor (v0.3.1.150) — the write phase.

migrate_objects(plan, approvals) takes an approved manifest from :func:tdfs4ds.plan_migration and recreates the selected objects in the primary store, wave by wave (upstream-first), bringing along:

  • non-FS upstream objects (intermediate views recreated from DDL; raw source tables copied or referenced cross-DB per choice),
  • the filter/time managers (recreate or unify onto an equivalent primary one),
  • the processes (re-registered with fresh primary ids; a source→primary id map is threaded everywhere),
  • the feature-value data (default: recompute via run(); fallback: copy the FS_T_* rows remapping the store-local FEATURE_ID),
  • the datasets (view recreated with FEATURE_VERSION refs remapped),
  • the business dictionary (rows re-homed under the primary DATABASE_NAME),
  • the lineage graph (re-derived from the primary DDL — primary-scoped), and
  • the Teradata vector index (rebuilt so the migrated docs are searchable).

The executor refuses to run unless every conflict is approved and no approved replace is still blocking (the lab→prod downstream-safety gate). Every auxiliary step (BD / lineage / vector) is fail-open — a doc/index failure never corrupts an otherwise-migrated feature (same discipline as upload_features).

_PROCESS_DOC_TABLES module-attribute

_PROCESS_DOC_TABLES = ('DOCUMENTATION_PROCESS_BUSINESS_LOGIC', 'DOCUMENTATION_PROCESS_EXPLAIN')

_PERIOD_COLUMNS module-attribute

_PERIOD_COLUMNS = {'PROCESS_ID', 'VALIDSTART', 'VALIDEND', 'VALIDPERIOD'}

logger_safe

logger_safe(level, message, *args, **kwargs)

Wrapper around the global logger that only emits logs when tdfs4ds.DISPLAY_LOGS is True. level is a string like "info", "error", etc.

norm_name

norm_name(name: Optional[str]) -> str

Uppercase, de-quoted, stripped — the canonical comparison form.

split_qualified

split_qualified(name: Optional[str]) -> Tuple[str, str]

Split 'db.obj' / '"db"."obj"' / 'obj' into (db, obj) (raw, de-quoted but original case preserved). db is '' when unqualified.

_emit

_emit(progress: Optional[Callable[[str], None]], msg: str)

_decisions

_decisions(plan, approvals) -> Tuple[Set[str], Set[str]]

Return (skip_keys, replace_keys) from the approval map.

_effective_placement

_effective_placement(plan, skip_object_keys) -> Dict[Tuple[str, str], Tuple[str, str]]

Source→primary placement for reference rewriting.

  • copied tables / recreated views → their primary placement (rewrite refs),
  • reference-mode source tables → identity (keep the cross-DB source ref),
  • skip (already-present) objects → their primary placement (refs point at the existing primary object).

_rewrite_and_replace_view

_rewrite_and_replace_view(src_db, src_obj, dst_db, dst_obj, placement, pid_map, progress)

Recreate a view in the primary: SHOW VIEW → rewrite refs + remap pids → REPLACE VIEW.

_copy_or_reference_table

_copy_or_reference_table(o, progress) -> bool

Copy a raw source table into the primary (WITH DATA) or leave it cross-DB.

_order_upstream

_order_upstream(plan) -> List[Dict[str, Any]]

Upstream non-FS objects (tables + intermediate views), dependencies first.

_build_entity_id_dict

_build_entity_id_dict(entity_csv: Optional[str]) -> Dict[str, str]

Entity columns -> {col: 'BIGINT'} (types are placeholders; run() recomputes the real SQL types from the live view — registration only uses the keys).

_parse_json

_parse_json(s) -> dict

_register_process

_register_process(m, dst_db, dst_obj, filtermanager, target_domain, progress) -> Optional[str]

Re-register a migrated process view in the primary; return the primary PID.

_copy_process_options

_copy_process_options(source_schema, source_pid, primary_pid, progress) -> None

Carry the source process's execution options over: FS_PROCESS_OPTIONS (close_absent_entities) and FS_PROCESS_SETTINGS (track_entity_refresh).

Read from the source store by explicit schema (never through federation). Fail-open: a source without the table, or a refused write, only loses the option, said in the progress stream. The FS_R_* refresh tables are not copied (a recompute regenerates them).

_record_migrated_time_manager

_record_migrated_time_manager(act, primary_pid, placement, progress) -> None

Record, for a migrated process, the TimeManager it reads in the primary.

The association drives run(): without it the recompute below ran in real time, wrote today's value, and a later roll_out over past dates could no longer insert anything before it (its merges only update the overlap). The manager's primary location is the placement of the source manager's view. Fail-open: a failure only loses the association, logged.

_migrate_domain_clocks

_migrate_domain_clocks(plan, placement, target_domain, report, progress) -> None

Recreate the clock of each migrated data domain in the primary and declare it (0.3.6.0).

The processes' soft clones are migrated as views over the clock's table of dates, which Phase A copies (it is a source table of every clone); the clock view and the domain's FS_DATA_DOMAIN_SETTINGS row were not, so the domain lost its clock. The clock view is made over the placed table (or the table is copied first, as a hard clone, when no clone brought it), at the source clock's cursor, and declared for the target domain. Fail-open: a failure is reported, the processes keep their clones.

_migrate_manager

_migrate_manager(m, act, progress, placement=None) -> Optional[object]

Recreate or unify a process's filter manager; return a FilterManager for registration (or None). Time managers are metadata-only (recorded via roll_out) and repointed if unified.

_kept_objects

_kept_objects(plan, skipped) -> set

{(DB_UP, OBJ_UP)} (source keys) of objects that already exist in the target and are kept: skipped by approval, or a reused source table. Their target documentation is never overwritten; the source's only fills gaps.

_target_documented_keys

_target_documented_keys(names) -> dict

{source: {key tuple}} of the target's current business-dictionary rows for names ({(DB_UP, OBJ_UP)}): what a kept object already has documented.

_migrate_business_dictionary

_migrate_business_dictionary(plan, pid_map, progress, placement=None, keep_target=())

Re-home the migrated objects' BD rows under their target DATABASE_NAME.

placement (_effective_placement): a source table left in its database (reference) keeps its documentation there. keep_target: objects the target already has (skipped, reused) -- their documentation there wins, the source only fills parts the target lacks.

process_doc_copy_sql

process_doc_copy_sql(src_db: str, dst_db: str, table: str, columns, pid_map: Dict[str, str]) -> List[str]

[DELETE, INSERT] copying the current rows of a process-documentation table from the source store to the target, PROCESS_ID re-keyed. Pure. The DELETE ends the target's current rows for those processes (a replace keeps its id).

_table_columns

_table_columns(db: str, table: str) -> List[str]

_migrate_process_documentation

_migrate_process_documentation(plan, pid_map, registered, progress, report)

Copy the business logic and EXPLAIN documentation of the processes this run registered, then link their feature descriptions (needs the features in the catalog: a process registered with data_strategy='none' gets them at its first run, with tdfs4ds.link_feature_documentation(pid)).

migrate_objects

migrate_objects(plan: Dict[str, Any], approvals: Optional[Dict[str, str]] = None, *, dry_run: bool = False, rebuild_vector_index: bool = True, progress: Optional[Callable[[str], None]] = None) -> Dict[str, Any]

Execute an approved migration manifest against the primary store.

Parameters

plan : dict The manifest from :func:tdfs4ds.plan_migration. approvals : dict[str, str] | None {conflict_key: 'skip'|'replace'} for every conflict. Required whenever the plan has conflicts; a replace that is still blocking (the downstream-safety gate) is rejected. dry_run : bool Validate approvals and return the plan of record without writing. rebuild_vector_index : bool Rebuild the Teradata vector index after BD migration (default True; skipped unless VECTOR_STORE_BACKEND == 'teradata'). progress : callable(str) | None Per-step progress hook (for the SSE panel).

Returns

dict Execution report: pid_map (source→primary), per-object outcomes, skipped/replaced, and any post-migration downstream compile breakages.

_run_phases

_run_phases(plan, src, target_domain, objects, placement, pid_map, report, skip_keys, _obj_skipped, rebuild_vector_index, progress)

Execute the migration phases (primary-only; see migrate_objects).

_lineage_refresh_objects

_lineage_refresh_objects(objects: dict, report: dict, skipped=lambda o: False) -> list

Objects whose lineage Phase F refreshes: only those this run created.

A dataset counts only when Phase D built it (ok=True): a deferred one (data_strategy='none'), one whose processes did not migrate, or a failed build does not exist in the primary, and naming it used to abort the whole refresh. A view whose creation failed is left out the same way.

_resolve_primary_pid

_resolve_primary_pid(db, obj) -> Optional[str]

PROCESS_ID of a process view already registered in the primary (or None).

_read_source_dataset_entity

_read_source_dataset_entity(src, dataset_id) -> Dict[str, str]

{entity_col: type} for a source dataset (from its FS_V_*_ENTITY view).

_dataset_build_options

_dataset_build_options(ddl, placement)

build_dataset keyword arguments reproducing the source view's build.

The strategy (grouped or not), the join type and the point in time are read from the source view's own DDL. A plain build_dataset call would silently turn a grouped, fixed-date or TimeManager dataset into a current multi-join one in the target store.

A TimeManager dataset is re-pointed to the manager's migrated copy when the plan placed one; otherwise it keeps referencing the source store's manager (cross-database), and the second value returned says so for the report.

_dataset_offset_options

_dataset_offset_options(spec)

{base feature: [offset ISO, ...]} of a parsed dataset, {} without offsets.

_offset_feature_map

_offset_feature_map(ddl)

{column alias (upper): base feature (upper)} and {base: process id} of the offset columns.

selection_from_spec

selection_from_spec(spec, base_names, pid_map)

(selected_features, feature_offsets) rebuilding spec's columns under their names. Pure.

base_names {FEATURE_ID: catalog name} (source store), pid_map {source PROCESS_ID: target PROCESS_ID}. A column named like its feature stays a plain process id (the call of a dataset without alias is unchanged); any other name travels as the version's alias. None when a feature name is unknown or a process was not migrated (the caller falls back).

_source_feature_names

_source_feature_names(src, spec) -> Dict[int, str]

{FEATURE_ID: FEATURE_NAME} of spec's features in the source store's catalog.

_rebuild_dataset

_rebuild_dataset(o, src, pid_map, target_domain, progress, report, placement=None)

Rebuild a migrated dataset in the primary via build_dataset — NOT a view copy. The source dataset view refs the store-local FEATURE_ID / FEATURE_VERSION of the source; build_dataset regenerates them against the primary's freshly-registered features and registers the primary dataset catalog rows. The source feature→process map (from the source DDL) has its process ids remapped source→primary. The strategy, join type and point in time are carried over from the source view (_dataset_build_options).

_copy_feature_values

_copy_feature_values(m, source_pid, primary_pid, src, target_domain, progress, report)

Copy the FS_T_* feature-value rows for a process from the source store into the primary, remapping the store-local FEATURE_ID and preserving VALIDTIME history.

Best-effort fallback (used when recompute is not possible). Registers the entity + features in the primary first (assigning fresh FEATURE_IDs), then INSERTs the source values with each source FEATURE_ID mapped to its primary FEATURE_ID.