-- data_factory init schema (issue 0097). -- Idempotente. Aplicado al arrancar via embed.FS (Go side / bridge a C++). -- -- Tablas: -- nodes — extractors/transformers/databases/sinks declarados localmente -- connections — aristas (lineage) entre nodes -- runs — historico de ejecuciones (rows/kb/duration por run) -- databases — registro de DBs externas que sirven como sink/source -- -- Datos NUNCA viajan entre PCs por sync (per-PC, igual que dag_engine.db). CREATE TABLE IF NOT EXISTS nodes ( id TEXT PRIMARY KEY, kind TEXT NOT NULL CHECK(kind IN ('extractor','transformer','database','sink','validator')), name TEXT NOT NULL, function_id TEXT NOT NULL DEFAULT '', -- FK logico a registry.functions.id (sin enforcement) description TEXT NOT NULL DEFAULT '', config_json TEXT NOT NULL DEFAULT '{}', schedule_cron TEXT NOT NULL DEFAULT '', -- '' = manual, sino expresion cron (parseable con parse_cron_expr_go_core) enabled INTEGER NOT NULL DEFAULT 1, tags_csv TEXT NOT NULL DEFAULT '', created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_nodes_kind ON nodes(kind); CREATE INDEX IF NOT EXISTS idx_nodes_function_id ON nodes(function_id); CREATE INDEX IF NOT EXISTS idx_nodes_enabled ON nodes(enabled); CREATE TABLE IF NOT EXISTS connections ( id TEXT PRIMARY KEY, src_node TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE, dst_node TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE, payload_schema TEXT NOT NULL DEFAULT '{}', -- JSON schema del dato que viaja created_at TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_connections_src ON connections(src_node); CREATE INDEX IF NOT EXISTS idx_connections_dst ON connections(dst_node); CREATE UNIQUE INDEX IF NOT EXISTS uniq_connection_edge ON connections(src_node, dst_node); CREATE TABLE IF NOT EXISTS runs ( id TEXT PRIMARY KEY, node_id TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE, started_at TEXT NOT NULL, finished_at TEXT, status TEXT NOT NULL DEFAULT 'running' CHECK(status IN ('running','success','failed','cancelled')), rows_in INTEGER NOT NULL DEFAULT 0, rows_out INTEGER NOT NULL DEFAULT 0, kb_in INTEGER NOT NULL DEFAULT 0, kb_out INTEGER NOT NULL DEFAULT 0, duration_ms INTEGER NOT NULL DEFAULT 0, trigger TEXT NOT NULL DEFAULT 'manual' CHECK(trigger IN ('manual','cron','dag','api')), error TEXT NOT NULL DEFAULT '', notes TEXT NOT NULL DEFAULT '' ); CREATE INDEX IF NOT EXISTS idx_runs_node ON runs(node_id); CREATE INDEX IF NOT EXISTS idx_runs_status ON runs(status); CREATE INDEX IF NOT EXISTS idx_runs_started ON runs(started_at DESC); CREATE TABLE IF NOT EXISTS databases ( id TEXT PRIMARY KEY, kind TEXT NOT NULL CHECK(kind IN ('sqlite','postgres','bigquery','duckdb','mongo','parquet','csv','other')), label TEXT NOT NULL, uri TEXT NOT NULL DEFAULT '', -- connection string redacted (no creds) description TEXT NOT NULL DEFAULT '', tags_csv TEXT NOT NULL DEFAULT '', last_seen_at TEXT NOT NULL DEFAULT '', table_count INTEGER NOT NULL DEFAULT 0, size_bytes INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_databases_kind ON databases(kind);