Skip to content

Schema Graph

Pretensor turns a SQL schema into a property graph stored in Kuzu. The shape of that graph is the whole point of the project — it’s what lets an agent ask for a path between two tables instead of guessing FOREIGN KEY clauses from a wall of DDL. The full inventory below is what the indexing pipeline writes; the schema MCP tool returns the live catalog at runtime, and a fresh client should call it before issuing Cypher.

NodeOne perNotable properties
SchemaTablephysical tableschema_name, table_name, row_count, comment, table_type (table / view / materialized view), classification (role, role_confidence, classification_signals)
SchemaColumncolumndata_type, nullable, is_primary_key, is_foreign_key, ordinal_position, statistics (distinct_count, min_value, max_value, histogram_bounds)
Entityinferred business entitygroups multiple physical tables that represent the same conceptual thing (e.g. a fact table sharded across 4 physical tables)
Clusterdomain communityoutput of community detection over the FK graph; labelled at index time
JoinPathprecomputed multi-hop paththe actual sequence of FK + inferred-join hops between two tables, stored so agents don’t re-solve traversal
MetricTemplatevalidated metricoptional; produced by the semantic subcommand group, not by default index
EdgeFrom → ToMeaning
HAS_COLUMNSchemaTable → SchemaColumncolumn belongs to table
HAS_SUBCOLUMNSchemaColumn → SchemaColumnnested struct field (used for JSON / STRUCT types)
FK_REFERENCESSchemaColumn → SchemaColumndeclared foreign-key constraint
INFERRED_JOINSchemaColumn → SchemaColumnheuristically-discovered join with confidence, source, reasoning
LINEAGESchemaTable → SchemaTableview depends on table; trigger writes to table; dbt model derives from source
REPRESENTSEntity → SchemaTablewhich physical tables make up an entity
IN_CLUSTERSchemaTable → Clusterwhich domain a table belongs to
METRIC_DEPENDSMetricTemplate → SchemaTablea compiled metric’s source tables
SAME_ENTITYSchemaTable ↔ SchemaTablecross-database equivalence (Postgres orders ≡ Snowflake orders)

The schema also reserves space for a richer semantic layer. These node and edge types exist in every graph but are empty unless you compile your own semantic-layer YAML through the semantic subcommand group:

ReservedTypeUsed for
Metricnodea defined business metric
Dimensionnodea defined dimension
BusinessRulenodea validation or governance rule
METRIC_DEPENDS_ONedgeMetric → SchemaTable
DIMENSION_LEVELedgeDimension → SchemaColumn
RULE_APPLIES_TOedgeBusinessRule → SchemaTable

If you don’t author semantic YAML, these slots stay empty and Cypher queries against them return zero rows.

A DDL dump is a flat list. A graph is queryable. With this representation:

  • The traverse tool can find paths between two tables by walking FK_REFERENCES and INFERRED_JOIN edges in Kuzu Cypher — no SQL guessing.
  • The impact tool walks the same graph in the other direction to surface every downstream table reachable through FK and inferred-join edges.
  • LINEAGE edges give column-grain dependency tracking: change users.id, see every downstream view, dbt model, and metric that depends on it.
  • Precomputed JoinPath nodes short-circuit multi-hop traversal at query time, so agents get answers in tens of milliseconds instead of running graph search themselves.
  • Cluster and Entity nodes abstract over physical fragmentation — the agent sees “orders,” not “orders_2024_q1 + orders_2024_q2 + orders_2024_q3 + orders_2024_q4.”
  • SAME_ENTITY edges connect equivalent tables across databases (e.g. a Postgres source-of-truth and a Snowflake replica), so traversal can produce confirmed cross-database paths. The edge type is part of the graph schema, but OSS indexing does not discover these links automatically — that entity-resolution pass is part of the hosted offering.