/** * Shared utilities for graph algorithm tools (S2) * Handles table validation, temp table lifecycle, and edge subquery building. * * CRITICAL: All graph algorithms use iterative SQL with temp tables. * NO recursive CTEs (segfault risk on DuckDB 1.4.x). * * v1.2.0 update: utilities now operate on a `ComputeSession` instead of a * raw `DuckDBService`. The session pins all queries to a single connection * so TEMP tables created in one step are visible in later steps. See * `src/compute-session.ts` for the full rationale. * * Backward compat: existing callers can still pass a DuckDBService — the * helpers wrap it via `openComputeSession()` on entry. */ import { type ComputeSession, type DuckDBLike } from '../compute-session.js'; import type { GraphInputBase } from '../types/graph-schemas.js'; /** * Generate a unique temp table prefix to avoid collisions. */ export declare function tempTablePrefix(): string; /** * Options for validateGraphTables. * @since v1.3.0 */ export interface ValidateGraphTablesOptions { /** * If set, validateGraphTables returns the first N distinct node_ids in the * `topNodesPreview` field. Useful for visual diagnostic when a graph * algorithm is producing unexpected results — lets the caller see "what * does the plugin actually see" without re-running a query. Default: undefined * (no preview, no extra query). */ previewNodes?: number; } /** * Result of validateGraphTables. * @since v1.3.0 — `topNodesPreview` added (opt-in via options.previewNodes) */ export interface ValidateGraphTablesResult { nodeCount: number; edgeCount: number; /** @since v1.2.2 — DISTINCT count of node_id values, post-filter */ distinctNodeCount: number; /** @since v1.3.0 — opt-in via options.previewNodes; undefined otherwise */ topNodesPreview?: Array; } /** * Validate that the graph tables and columns exist, return node/edge counts. * * Accepts a `ComputeSession` (preferred) or a `DuckDBLike` for backward * compat — the latter is auto-wrapped. All validation queries run on the * same pinned connection so the caller can rely on subsequent statements * (CREATE TEMP TABLE, etc.) seeing the same context. */ export declare function validateGraphTables(target: ComputeSession | DuckDBLike, config: GraphInputBase, options?: ValidateGraphTablesOptions): Promise; /** * Build an edge subquery that applies optional WHERE filter. * Returns a subquery alias that can be used as a table reference. */ export declare function buildEdgeSubquery(config: GraphInputBase): string; /** * Build a deduplicated node subquery. Robust against pathological input * data — many real-world entity tables (e.g. deposium_MCPs' * uploaded_files_graph_entities) keep soft-deleted orphans or have * imperfect dedup, leaving multiple rows per logical node_id. * * **Why this matters for iterative algorithms** (PageRank, Eigenvector, * Community label propagation): the iteration formula * * new_rank(v) = (1-d)/N + d * SUM(pr[s].rank / oc[s].cnt for in-edges) * * is correct only when each node appears once. If `nodeTable` has K * duplicate rows for source s, the JOIN `pr ON e.source = pr.node_id` * matches K rows and contributes K × (rank/oc.cnt) per edge — amplifying * the rank by factor K each iteration. Over 20 iterations with K≈7, * scores explode to ~9×10^16 (observed live 2026-04-26 on space * 89b04306 with 5,332 duplicates / 50,062 nodes). * * Behaviour: * - Without filter: `(SELECT DISTINCT node_id_col AS node_id_col FROM table)` * - With filter: `(SELECT DISTINCT node_id_col FROM table WHERE filter)` * * The DISTINCT collapses duplicate rows by node_id_col only — any * additional metadata (entity_name, type, …) is dropped here. Algorithms * that need names should JOIN back to nodeTable AT THE END. * * @since v1.2.2 (Sprint α — root cause: dedup-cascade-explosion) */ export declare function buildNodeSubquery(config: GraphInputBase): string; /** * Get column references for a graph config. * * `nodeSub` is the dedup-safe view of the node table — algorithms * iterating over nodes should always read from `nodeSub`, never from raw * `nodeTable`, to avoid the cascade-amplification bug. Use `nodeTable` * only for things like JOIN-back-for-metadata at the end of an algorithm. */ export declare function getColumnRefs(config: GraphInputBase): { nodeTable: string; edgeTable: string; nodeIdCol: string; sourceCol: string; targetCol: string; weightCol: string | null; edgeSub: string; nodeSub: string; }; /** * Safely drop a temp table if it exists. Operates on the session's pinned * connection — must be the same connection that created the table. */ export declare function dropTempTable(target: ComputeSession | DuckDBLike, name: string): Promise; /** * Clean up all temp tables matching a prefix. */ export declare function cleanupTempTables(target: ComputeSession | DuckDBLike, prefix: string, names: string[]): Promise; //# sourceMappingURL=graph-utils.d.ts.map