feat: consolidate database management work
Add catalog-owned logical relationships and runtime snapshots, extend the database-management UI and validation coverage, and document the updated operational workflow. Keep active sensitive-generation status in a tooltip and indicator, and update the layout E2E to follow the history action in its new database-scoped location.
This commit is contained in:
@@ -10,6 +10,12 @@ from tht.adapters.factory import build_dwh
|
||||
from tht.cli.config_cmd import CONFIG_OPT
|
||||
from tht.config import ConfigError, load_config
|
||||
from tht.db.sampling import is_text_type
|
||||
from tht.mschema.context import (
|
||||
SchemaContextError,
|
||||
annotations_path,
|
||||
load_schema_context,
|
||||
physical_path,
|
||||
)
|
||||
from tht.mschema.eligibility import classify_all
|
||||
|
||||
schema_app = typer.Typer(help="Gestione mschema (rappresentazione canonica dello schema)")
|
||||
@@ -40,20 +46,6 @@ def _load_config_or_exit(config: Path):
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
|
||||
def physical_path(cfg) -> Path:
|
||||
from tht.jobs.dwh_pipeline import resolve_dwh_snapshot
|
||||
|
||||
if not (cfg.paths.artifacts.parent / ".tht-dwh").exists():
|
||||
return cfg.paths.artifacts / "mschema" / "physical.yaml"
|
||||
return resolve_dwh_snapshot(cfg).physical
|
||||
|
||||
|
||||
def annotations_path(cfg) -> Path:
|
||||
if cfg.paths.annotations_root is not None:
|
||||
return cfg.paths.annotations_root / "mschema" / "annotations.yaml"
|
||||
return cfg.paths.artifacts / "mschema" / "annotations.yaml"
|
||||
|
||||
|
||||
def refresh_catalog(cfg, *, dwh=None, output_path: Path | None = None):
|
||||
"""Run the existing catalog algorithm and persist its canonical output."""
|
||||
target = dwh if dwh is not None else build_dwh(cfg)
|
||||
@@ -432,6 +424,21 @@ def suggest_fks_cmd(
|
||||
from tht.mschema.models import Annotations, PhysicalSchema, TableAnnotation
|
||||
|
||||
cfg = _load_config_or_exit(config)
|
||||
if write and cfg.paths.effective_relationships is not None:
|
||||
error = "effective relationships are managed by the catalog; --write is disabled"
|
||||
if json_output:
|
||||
_emit_json({
|
||||
"code": "catalog_relationships_managed",
|
||||
"error": error,
|
||||
"operation": "schema_suggest_fks",
|
||||
"schemaVersion": 1,
|
||||
"status": "failed",
|
||||
"workspaceId": cfg._workspace_id,
|
||||
"workspaceRevision": cfg._workspace_revision,
|
||||
})
|
||||
else:
|
||||
typer.secho(f"ERRORE: {error}", fg=typer.colors.RED, err=True)
|
||||
raise typer.Exit(code=1)
|
||||
phys_file = physical_path(cfg)
|
||||
if not phys_file.exists():
|
||||
if json_output:
|
||||
@@ -556,7 +563,6 @@ def render_cmd(
|
||||
"""Serializza mschema (physical + annotations) nel formato richiesto."""
|
||||
import json
|
||||
|
||||
from tht.mschema.models import Annotations, PhysicalSchema
|
||||
from tht.mschema.render import to_markdown, to_mschema_text, to_schema_dict
|
||||
|
||||
cfg = _load_config_or_exit(config)
|
||||
@@ -564,19 +570,40 @@ def render_cmd(
|
||||
if not phys_file.exists():
|
||||
typer.secho(
|
||||
f"ERRORE: {phys_file} non trovato. Esegui prima `tht schema introspect`.",
|
||||
fg=typer.colors.RED, err=True,
|
||||
fg=typer.colors.RED,
|
||||
err=True,
|
||||
)
|
||||
raise typer.Exit(code=1)
|
||||
physical = PhysicalSchema.from_yaml(phys_file)
|
||||
annotations = Annotations.from_yaml(annotations_path(cfg))
|
||||
try:
|
||||
context = load_schema_context(cfg, physical_file=phys_file)
|
||||
except SchemaContextError as exc:
|
||||
typer.secho(f"ERRORE: {exc}", fg=typer.colors.RED, err=True)
|
||||
raise typer.Exit(code=1) from None
|
||||
table_filter = list(tables) if tables else None
|
||||
|
||||
if format == "markdown":
|
||||
out = to_markdown(physical, annotations)
|
||||
out = to_markdown(
|
||||
context.physical,
|
||||
context.annotations,
|
||||
effective_relationships=context.effective_relationships,
|
||||
)
|
||||
elif format == "mschema-text":
|
||||
out = to_mschema_text(physical, annotations, tables=table_filter)
|
||||
out = to_mschema_text(
|
||||
context.physical,
|
||||
context.annotations,
|
||||
tables=table_filter,
|
||||
effective_relationships=context.effective_relationships,
|
||||
)
|
||||
elif format == "schema-dict":
|
||||
out = json.dumps(to_schema_dict(physical, annotations), ensure_ascii=False, indent=2)
|
||||
out = json.dumps(
|
||||
to_schema_dict(
|
||||
context.physical,
|
||||
context.annotations,
|
||||
effective_relationships=context.effective_relationships,
|
||||
),
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
)
|
||||
else:
|
||||
typer.secho(f"ERRORE: formato sconosciuto: {format}", fg=typer.colors.RED, err=True)
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
Reference in New Issue
Block a user