Prefix: meta_.
The schema describing itself: which families exist, where the exceptions live, and how the roster closes against the relations actually observed. These rows are versioned with the schema definition and never change at run time. The reference pages you are reading are rendered from this family’s rows and the comments beside them.
Where to start
- meta_family
-
The family roster: one row per relation-name prefix, keyed by the prefix under the schema’s naming discipline (a family is named for whose vocabulary its rows are written in, never for its reader or its role).
- meta_relation_family
-
The census that closes the roster: every relation in the schema, its kind, the family whose prefix covers it, and whether an exemption row places it.
- meta_relation
-
One declared relation: which grain it is at, which gatherer owns it, what one of its rows is, one example of one, and why the relation exists at all.
How this family meets the others
No crossing is declared for this family and no foreign key crosses its boundary; its rows meet the other families' only where a reader joins them.
Why the name is right
The schema’s own description: the family roster, each family’s headline relations and its sanctioned normalization crossings, the placement of relations no prefix covers, the census that closes both rosters against the observed schema, the declared key edges resolved out of the engine’s catalog, the corpus, gatherer and grain rosters with the per-relation declarations binding each declared relation to them, and the roster of relations this file supplies the rows of rather than any gatherer. Rows that are a function of this file alone, versioned with the DDL they describe and never refreshable apart from it, which is the property that matters and which every form in the family keeps: a roster stated as a VALUES view has rows that are part of the definition, and a roster stated as a table has rows an INSERT in this same file supplies before any run opens the store. A resident whose rows a constraint should defend takes the table form, a key, a foreign key and a CHECK being nothing a view can carry: the declaration rosters around meta_relation are tables whose rows an INSERT in this same file supplies; the two older rosters keep the view form until an item converts them.
meta_corpus
One corpus the store reads: an input that exists outside the store and independently of the other inputs, named so gatherers and grains can say which input they are about. For example the row named sdl is the GraphQL schema documents. Keyed on the name; the gatherer junction and the grain roster resolve into it by foreign key, so a corpus cannot be misspelled at either site.
Primary key: (corpus_name). Check: CHAR_LENGTH("DEFINITION") BETWEEN 1 AND 300.
corpus_name(CHARACTER VARYING, not null)-
the corpus’s name, the roster’s key, in lowercase kebab case
definition(CHARACTER VARYING, not null)-
one sentence saying what the corpus is; length-checked by the CHECK beside it
meta_family (view)
The family roster: one row per relation-name prefix, keyed by the prefix under the schema’s naming discipline (a family is named for whose vocabulary its rows are written in, never for its reader or its role). The introduction column presents each family to a first-time reader and the definition column carries its charter, the latter migrated out of this file’s header so the roster has one home; the generated schema reference renders one page per row, ordered by ordinal, and the schema gates close the roster against the observed relations in both directions.
prefix(CHARACTER VARYING, nullable)-
the family’s relation-name prefix, trailing underscore included; the roster’s key, unique by gate since a view carries no PRIMARY KEY, and no prefix may be a prefix of another (gated), which is what lets the census match exactly
title(CHARACTER VARYING, nullable)-
the family’s rendered page title in the generated schema reference; plain prose, display material only
ordinal(INTEGER, nullable)-
the family’s position in the reference’s page order and index roster, 0-based; unique by gate
introduction(CHARACTER VARYING, nullable)-
the family’s introduction: one short paragraph presenting the family to a first-time reader, in plain language, saying what its rows transcribe or derive. It opens the family page, where the charter beside it now sits under its own heading further down; the two are complements, the introduction presenting and the charter defending the name. An introduction deliberately names no relation and no other family. The headline roster and the meeting section carry those, and both are gated, so a name stated here instead would go stale with nothing failing. No gate can read intent, which is what makes this comment the enforcement.
definition(CHARACTER VARYING, nullable)-
the family’s charter: whose vocabulary its rows are written in and why the name is right, rendered on the family page under its own heading, below the introduction and the two rosters the page now opens with
meta_family_bridge (view)
The sanctioned normalization crossings: one row says that this relation owns the rule by which a name written in one family’s vocabulary is matched against another family’s census. How two families meet is a fact about the schema rather than prose an author writes about it, so the crossings are declared here in the DDL the way the family roster and the gatherer roster are, and the reference renders the declarations. What the roster defends against is a fork: a new view can re-derive a normalization with its own function calls in a join predicate, produce plausible rows, and quietly leave two rules where the schema states one. Membership is two tests together. A relation is on the roster when it owns a normalization rule of its own, spelled in its own body, not when it reads a relation that states one; and when that rule mediates a meeting between two families' vocabularies, not a normalization inside one. Where the DDL assigns a rule’s ownership in its own comments, the roster follows that assignment, so a coordinate-shaped sibling whose comment says the rule is argued at the other site restates a body rather than a rule and earns no second row. Crossings by plain column equality on a shared natural key are deliberately absent: a foreign key is already a declared, engine-checked join path, and an identity comparison has no rule to re-derive differently, so there is nothing a new view could silently fork. The declarations are resolve-gated only. Whether they cover every crossing the views actually perform is a derivation over the view-read census, which no declaration can answer on its own, and until that closure exists the reference presents these rows as declarations and claims no exhaustiveness.
relation_name(CHARACTER VARYING, nullable)-
the relation owning the rule, named as a consumer reads it; must resolve to an observed relation (gated). For a stage-written relation that is the table rather than the _rule view it is filled from, whose own comment tells readers not to spell it, since the reference cross-links what a row names and the table is the name every reader spells. A gate closing this roster against what a view’s stored definition reads therefore resolves such a row to the rule view first.
spelled_prefix(CHARACTER VARYING, nullable)-
the family whose vocabulary the name is written in, a meta_family prefix; rostered, and distinct from census_prefix (both gated). Named for the role rather than as one half of a from-and-to pair, because a normalization always has a spelled side and a census side while a direction pair would assert something the population only usually carries, and would read ambiguously against the bridge’s own residence family.
census_prefix(CHARACTER VARYING, nullable)-
the family whose census the written name is matched against, a meta_family prefix; rostered, and distinct from spelled_prefix (both gated). The role name is true of every row for the same reason its spelled counterpart is.
rule(CHARACTER VARYING, nullable)-
the rule in one sentence: what meets what, and by what normalization. Non-blank (gated), and prose no gate can check beyond that, which is why it stays one sentence stating the rule the relation’s own body spells rather than restating the body.
meta_family_headline (view)
The headline roster: the relations a reader should meet first in each family, typically its central grain plus the derivations that make the grain useful. Curation is judgment, which is why membership is authored here and nothing else about a row is: the family comes from the meta_relation_family census by join rather than being stored beside the name, and what each headline means comes from the relation’s own comment, so there is no second blurb to drift from the first. The generated schema reference renders the roster as the family page’s starting point, each entry the relation name linked to its own entry further down the page plus the first sentence of that comment. Not named for the store glossary’s word grain, which this roster does not mean: a reader of the reference must never have to disambiguate a load-bearing word.
relation_name(CHARACTER VARYING, nullable)-
the headline relation’s name as declared; the roster’s subject, and it must resolve to an observed relation that the census places in a family (gated). The family follows from that census row, so a relation moving between families moves its headline with it and no second copy can disagree.
ordinal(INTEGER, nullable)-
the headline’s position within its own family’s roster, 0-based; dense from zero within each family (gated), which is the schema-gate convention here because uniqueness alone would let a gap through and a gap is how a dropped row hides. Every family carries at least one row, single-relation families listing their one resident.
meta_gatherer
One fact gatherer: a producer that fills this store, rostered so a relation can declare which one owns it. For example the row named sdl is the gatherer whose class is SdlFactCapture. The class column is what keeps the roster from becoming a second vocabulary: a gate loads every named class, so a row cannot quietly outlive the code it points at. What a gatherer reads is stated beside it, its corpora in meta_gatherer_corpus and its declared read edges in meta_gatherer_dependency.
Primary key: (gatherer_name).
gatherer_name(CHARACTER VARYING, not null)-
the gatherer’s name, the roster’s key, in lowercase kebab case
gatherer_class(CHARACTER VARYING, not null)-
the fully qualified Java class that is the gatherer’s entry point, unique per row; a class-loading gate in the graphitron module holds every value to a class that exists. The derivation gatherer names DerivationStratum, the post-capture stratum its relations sit beside: the four it still owns are views evaluated on read, each reading a family its computed owner declares no dependency on, and each waits for the gatherer it belongs to.
meta_gatherer_corpus
One corpus a gatherer reads: a declared pairing of one gatherer with one outside input. For example the catalog gatherer carries two rows, catalog and classpath. A gatherer with at least one row here is a crawler, and this junction is the store’s definition of that word: a transcription pass whose rows about its own corpus may not vary with any other corpus’s contents. A gatherer with no row here reads no corpus at all: it reads captured rows, and is thereby free to cross corpora, which is what the derivation gatherer and the graphitron gatherer both are. The second is worth naming because its family is a decode of the SDL and reads as a crawler until you ask what it reads: it reads the sdl gatherer’s transcription of the documents rather than the documents, and the catalog beside it, so a decode with a default to resolve resolves it here rather than pushing the question up a family.
Primary key: (gatherer_name, corpus_name). Foreign key: (gatherer_name) references meta_gatherer (gatherer_name). Foreign key: (corpus_name) references meta_corpus (corpus_name).
gatherer_name(CHARACTER VARYING, not null)-
the reading gatherer, a meta_gatherer key
corpus_name(CHARACTER VARYING, not null)-
the corpus read, a meta_corpus key
meta_gatherer_dependency
One declared read edge between gatherers: the first may read rows the second produced. For example the derivation gatherer depends on every crawler, which is what running last means once it stops being a position. Declared rather than derived from the view bodies, deliberately: the declaration states the intended shape, and the view-ownership gate denies a declared view that reads outside its owner’s dependency set, so a view forking the shape fails instead of widening it. A crawler carries no edges at all: its rows about its own corpus may not vary with any other corpus’s contents, which is the same statement as depending on nobody, so the sdl and catalog gatherers stand independent of each other and of everything else. Every edge therefore runs from a gatherer that reads no corpus, and there are two of those: the graphitron gatherer, which decodes what the sdl gatherer transcribed and may read the catalog beside it, and the derivation gatherer downstream of them all. The roster drives no execution: the order gatherers run in is FactCapture.capture’s statement order, and these edges are what that order has to satisfy. What makes the order able to satisfy them is that each gatherer’s rows are flushed to the store before the next one starts, a flush inside the load’s one transaction being what lets a downstream gatherer read an upstream’s rows without publishing a partition mid-load.
Primary key: (gatherer_name, depends_on). Foreign key: (gatherer_name) references meta_gatherer (gatherer_name). Foreign key: (depends_on) references meta_gatherer (gatherer_name). Check: "GATHERER_NAME" <> "DEPENDS_ON".
gatherer_name(CHARACTER VARYING, not null)-
the dependent gatherer, the one performing the read; a meta_gatherer key
depends_on(CHARACTER VARYING, not null)-
the prerequisite gatherer whose rows may be read; a meta_gatherer key, and never the dependent itself, the CHECK refusing the length-one cycle
meta_grain
One grain this store knows about: what one row of a relation at this grain is about. For example a grain named field with key shape graph_name, type_name, field_name says one row is one field of one type in one graph. The store already states every grain twice without naming it, a relation’s primary key being its grain as columns and its comment’s first sentence being its grain as prose; this roster is the same fact as data, and a declared base table’s key must equal its grain’s shape (gated).
Primary key: (grain_name). Foreign key: (corpus_name) references meta_corpus (corpus_name). Check: CHAR_LENGTH("INSTANCE_TEXT") BETWEEN 1 AND 300. Check: CHAR_LENGTH("KEY_SHAPE") >= 1.
grain_name(CHARACTER VARYING, not null)-
the grain’s name, the roster’s key, in lowercase kebab case
instance_text(CHARACTER VARYING, not null)-
one sentence saying what one instance of the grain is; length-checked
key_shape(CHARACTER VARYING, not null)-
the canonical key as a comma-separated column list in key order; a declared base table at this grain carries exactly this primary key (gated)
corpus_name(CHARACTER VARYING, not null)-
the corpus the grain lives in, a meta_corpus key; where a declared relation’s owner reads any corpus at all, the grain’s corpus must be among them (gated)
meta_prefixless_relation (view)
The placement exemptions: one row per relation deliberately outside every family, in the exemption polarity the schema gates use throughout, so a new prefix-less relation fails the roster gate until an authored row argues it in. The page column places the relation in the generated reference; the reason column carries the no-family argument beside the relation’s own comment.
relation_name(CHARACTER VARYING, nullable)-
the exempted relation’s name as declared; the exemption’s key, and it must resolve to an observed relation (gated)
page(CHARACTER VARYING, nullable)-
the family page that renders the relation, a meta_family prefix; NULL in the stated absent bucket: the relation belongs on no family’s page and renders on the reference’s index instead
reason(CHARACTER VARYING, nullable)-
why no family covers the relation, rendered beside the relation in the reference
meta_relation
One declared relation: which grain it is at, which gatherer owns it, what one of its rows is, one example of one, and why the relation exists at all. For example a row for sql_column names its grain, the catalog gatherer as its owner, and one concrete column as its example. A relation with no row is one nobody has declared yet; the roster of those is pinned in MetaDeclarationGateTest, frozen when this model landed and only ever shrinking, so a new relation cannot arrive undeclared. A declared relation’s own comment must equal grain_text and example joined (gated), which keeps the inline description a SQL client shows and these columns from drifting apart.
Primary key: (relation_name). Foreign key: (grain_name) references meta_grain (grain_name). Foreign key: (owner_name) references meta_gatherer (gatherer_name). Check: CHAR_LENGTH("GRAIN_TEXT") BETWEEN 1 AND 300. Check: CHAR_LENGTH("EXAMPLE") BETWEEN 1 AND 300. Check: CHAR_LENGTH("RATIONALE") BETWEEN 1 AND 1500.
relation_name(CHARACTER VARYING, not null)-
the declared relation’s name, the key; must name an observed relation (gated)
grain_name(CHARACTER VARYING, not null)-
the grain the relation is at, a meta_grain key
owner_name(CHARACTER VARYING, not null)-
the gatherer that owns the relation, a meta_gatherer key, the column named for the role the reference plays; a declared view may read only relations its owner owns or declares a dependency on (gated)
grain_text(CHARACTER VARYING, not null)-
the one sentence saying what one row is: a single sentence by GrainSentence’s own rule, and the first sentence of the relation’s comment (both gated)
example(CHARACTER VARYING, not null)-
one example row stated concretely, and the remainder of the relation’s comment after the grain sentence (gated)
rationale(CHARACTER VARYING, not null)-
why this relation exists, a paragraph at most by the CHECK beside it; measurements, rejected shapes and arguments with earlier authors belong in the architecture docs rather than here
meta_relation_family (view)
The census that closes the roster: every relation in the schema, its kind, the family whose prefix covers it, and whether an exemption row places it. The one relational answer to which family a relation belongs to: the schema gates, the generated reference and the docs drift guard all read this view rather than re-deriving the match, so two mechanisms of different fidelity can never answer the question differently.
relation_name(CHARACTER VARYING, nullable)-
the relation’s name as declared, lowercased from the engine’s catalog spelling
relation_type(CHARACTER VARYING, nullable)-
the engine’s kind for the relation: BASE TABLE or VIEW; both carry comments and columns and both render in the reference, but only base tables additionally carry keys and constraints
prefix(CHARACTER VARYING, nullable)-
the covering family’s prefix, by exact prefix match against meta_family; NULL where no family covers the relation, which the gates require an exemption row to justify
exempted(BOOLEAN, nullable)-
whether a meta_prefixless_relation row places this relation; TRUE must hold exactly where prefix is NULL, in both directions (gated)
meta_relation_reference (view)
The declared key edges: one row per FOREIGN KEY the schema declares, naming the relation that references and the relation referenced, each with the family the census places it in. At constraint grain deliberately, and not filtered to the edges that leave a family: cross-family is a predicate a reader applies to these rows, not a population baked into the relation, and the name says what a row is rather than where it happens to render. Resolved out of the engine’s own catalog, a referential constraint through the key columns on both ends, so the edges are exactly what the DDL declares and no second list can fall behind them. A store view rather than something a renderer aggregates for itself, because family assignment is never re-derived outside the census, and because the generated reference is only the first reader: a gate closing the declared normalization crossings and the schema surface the editor tooling reads both ask this same question. Derivation seeded by declaration is the shape the whole family relationship rests on, here the declared foreign keys.
child_relation_name(CHARACTER VARYING, nullable)-
the referencing relation, the one whose columns carry the foreign key; a base table always, since only base tables carry constraints
child_prefix(CHARACTER VARYING, nullable)-
the referencing relation’s family, from the census rather than from its name; NULL only where the census places the relation in no family, which an exemption row would have to argue
parent_relation_name(CHARACTER VARYING, nullable)-
the referenced relation, the one whose unique key the foreign key resolves against
parent_prefix(CHARACTER VARYING, nullable)-
the referenced relation’s family, from the census on the same terms as the referencing side’s
meta_stated_relation
One relation whose rows this file supplies: what one of its rows is, an example of one, and why it is stated rather than gathered. For example lint_rule is stated, its rows being the vocabulary the schema’s own constraints rest on.
Primary key: (relation_name). Check: CHAR_LENGTH("GRAIN_TEXT") BETWEEN 1 AND 300. Check: CHAR_LENGTH("EXAMPLE") BETWEEN 1 AND 300. Check: CHAR_LENGTH("RATIONALE") BETWEEN 1 AND 1500.
relation_name(CHARACTER VARYING, not null)-
the stated relation’s name as declared; the roster’s key, and it must resolve to an observed relation (gated) on meta_relation’s terms
grain_text(CHARACTER VARYING, not null)-
what one row of it is, in one sentence, on meta_relation.grain_text’s terms including the echo against the relation’s own comment
example(CHARACTER VARYING, not null)-
one concrete row, on meta_relation.example’s terms
rationale(CHARACTER VARYING, not null)-
why the rows are the file’s rather than a gatherer’s. The bar is not that the rows change rarely: a gathered relation whose corpus never changes is still gathered. It is that no corpus outside the store could be read to produce them, because they are the vocabulary this file itself declares, so a refresh has nothing to re-read and a gate has nothing to compare against but the DDL