Documentation
¶
Overview ¶
Package db is codefit's neutral, format-agnostic model of a database's structure — the schema a DB-dimension rule reasons over, blind to where it came from (Prisma or SQL-DDL — both parsers ship today).
It is a LEAF: it imports nothing from internal/providers (or any other codefit package). The provider layer depends on db, never the reverse — the same one-way arrow core/findings keeps (ADR 0014). A provider's schema parser FILLS this model; the core only consumes it.
The model defines the whole surface Phase 2 audits — OLTP structure plus the analytic facts the DW rules need (db.Index.Method, db.Table.Partitioning) — even what a given parser cannot express: a Prisma parse fills Tables/Columns/Indexes/ForeignKeys and leaves Views/Procedures/Triggers empty, which the SQL-DDL parser does fill. Every element carries an origin db.Pos{File, Line} so a finding and the baseline can anchor by file+line/content.
Index ¶
- func CoveredByOrderedPrefix(coverers [][]string, cols []string) bool
- func CoveredBySetPrefix(coverers [][]string, cols []string) bool
- func CoveredByUniqueSubset(uniqueKeys [][]string, cols []string) bool
- func IndexLike(t Table) [][]string
- func IsAuditTimestampColumn(c Column) bool
- func UniqueKeys(t Table) [][]string
- type Body
- type Column
- type ForeignKey
- type Index
- type Partitioning
- type Pos
- type Procedure
- type Reason
- type Schema
- type Table
- type Trigger
- type Type
- type Unreduced
- type View
- type Withheld
- type WithheldReason
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CoveredByOrderedPrefix ¶ added in v0.2.4
CoveredByOrderedPrefix reports whether some coverer has cols as a LEADING prefix in EXACTLY THAT ORDER. A B-tree serves a lookup on the leading columns of an index in order, so an index [a,b] covers a lookup on [a] and on [a,b], but NOT on [b] alone, and NOT on [b,a] — order matters.
Question it answers: "is this ORDERED column sequence a leading prefix of some index-like list?" Used TODAY by DB-001 (FK coverage — the FK's declared column order is meaningful) and DB-010 (a single filtered column — order is trivial for one column). Do NOT use it for a multi-column EQUALITY filter, where the WHERE order is irrelevant and [b,a] must cover (a,b): that is CoveredBySetPrefix.
func CoveredBySetPrefix ¶ added in v0.2.4
CoveredBySetPrefix reports whether some coverer's LEADING columns, taken as a SET, equal cols as a set. A WHERE a=? AND b=? is served by a composite index on (a,b) OR (b,a) — both have {a,b} as their leading set — but NOT by (a,c,b), where c breaks the leading run, nor by an index shorter than the set.
Question it answers: "do some index's leading columns, IGNORING ORDER, equal this column set?" Used TODAY by DB-013 (a multi-column, all-equality filter). Do NOT use it where order matters — a FK's declared order (DB-001) or a positional prefix: that is CoveredByOrderedPrefix. It is order-insensitive precisely because an equality set has no order; codefit does not capture equality-vs-range (a declared limit, ADR 0031), so it takes the columns as an unordered set and leaves the order/range judgment to the agent.
func CoveredByUniqueSubset ¶ added in v0.2.4
CoveredByUniqueSubset reports whether some unique key's column set is a SUBSET of the filtered column set — meaning the filter CONSTRAINS a unique key and therefore resolves to at most one row. When that holds, NO additional index helps (the lookup is already a single-row seek), so the rule must not flag a missing index.
This covers @id (PK), a single @unique column, and a composite @@unique in one rule: e.g. filter (id, salonId) with id the PK is covered (id ⊆ {id, salonId}), but filter (a, c) with a @@unique([a,b]) is NOT ({a,b} ⊄ {a,c}) — do not over-kill. It is ROBUST to the equality-vs-range limit (ADR 0031): even a range on the PK still uses the PK index for a bounded seek, so the short-circuit introduces no new false negative. Used by DB-010 and DB-013 (ADR 0032).
func IndexLike ¶ added in v0.2.4
IndexLike returns every index-like leading-column list of a table: each index's columns, plus the primary key treated as an implicit index. It is the neutral notion of "what a lookup can be served by", shared by every rule that reasons about index coverage — DB-001 (FK without index, dbrules), DB-010 (filtered column without index, crossrules), and DB-013 (missing composite index) — so the leftmost-prefix semantics are defined ONCE and never drift (ADR 0015, ADR 0029).
func IsAuditTimestampColumn ¶ added in v0.2.5
IsAuditTimestampColumn reports whether a COLUMN denotes a row-level audit timestamp — the moment the row was created, last changed, or recorded.
It lives here, in the neutral model, for the same reason IndexLike does: the notion is shared by rules in two different packages and must be defined ONCE so the two cannot drift (ADR 0015). Its consumers today are
- dbrules' DB-052, which asks it PER TABLE ("does this table stamp its rows?"), and
- paradigm's no_audit_timestamps warehouse signal, which asks it PER SCHEMA ("does NOT ONE table stamp its rows?").
It takes a Column and not a name so the type gate below cannot be skipped by a caller holding only a string. There is deliberately no name-only export.
The rule: a VERB, a TIME AFFIX, and a TYPE that can hold a time ¶
The three parts are separately load-bearing, and the measurement behind each is recorded here rather than in a changelog nobody reads at the call site. ADR 0047 is the long form; ADR 0046 is the fixed list this supersedes.
A VERB of creation or modification (auditStampVerbs) is what makes a name an audit stamp. The SUFFIX alone cannot: across the 29 measured corpora, 75 distinct columns end in `At`, and 74 of them are business event times — expiresAt, startedAt, finishedAt, lastSyncAt, paidAt, clickedAt, bannedAt, publishedAt, sentAt and the rest. A table whose only time column is `expires_at` genuinely does not record when its row came into being, so admitting the suffix alone would go quiet over a table that should still speak. That is the error nobody sees, and the reason the verb is required.
A TIME AFFIX (auditStampTimePrefixes / auditStampTimeSuffixes) is what makes the verb about a moment. It is load-bearing in the other direction too: `created_by` is a creation verb on a genuine audit field and it is a PERSON, not a time. DB-052 asks about time tracking, so `_by` is not a time affix and `created_by` does not match. formbricks declares `created_by TEXT` beside `created_at` and `last_sync_at` in one migration; all three are tested.
A bare verb with NO affix does not match. `created` says WHETHER, not WHEN, and no corpus shows one used as a stamp; `last_update` (36 measured columns) reaches the answer through its `last` prefix, which is itself a time word.
Why a rule and not a list ¶
This function used to be a fixed list of sixteen measured names. Every entry was real, which was right, and the list could still only ever know spellings that happened to appear in the corpora that happened to be cloned. It rejected `created_on`, `date_created`, `inserted_at`, `modified_at`, `last_modified` and `updated_ts` for lack of measured support — all unmistakably audit stamps — so any project spelling it one of those ways got the same false warning the list was built to remove. A verb plus a time affix closes the family instead of enumerating the members of it.
Prefixed forms stay out, which is what the fixed list's equality test bought and this rule keeps by requiring the affixes to be the WHOLE remainder: tpcds spells its dbgen stamps `dv_create_date` / `dv_create_time` and dw-p4pa spells one `cst_create_date`; admitting those means admitting every `<anything>_create_date`, including a business column.
func UniqueKeys ¶ added in v0.2.4
UniqueKeys returns every column list that UNIQUELY identifies a row of the table: the primary key (if any), plus the columns of each UNIQUE index/constraint. It is the neutral notion of "what makes a row addressable to at most one", shared by the cross rules (ADR 0031/0032).
Types ¶
type Body ¶ added in v0.2.2
Body is a routine/view definition as the parser RECOVERED it. Complete=false means the captured text may be TRUNCATED — the tokenizer could not prove the whole body is here — an honest partial, never a silent one; Note says why. This is deliberately a struct, not a plain string: a string cannot express "partial", so every consumer would have to trust it blindly. A dbrules rule reading Body.Text MUST treat Complete==false as grounds to abstain or downgrade to a surface item, never to emit a deterministic finding — ADR 0004's "a mutilated rule is worse than an absent one" made mechanical instead of aspirational (architecture/tsql-body-truncation-limit).
type Column ¶
type Column struct {
Name string
// DBName is the real column name in the database when remapped via @map. EMPTY
// means "no remap" (fall back to Name) — not defaulted to Name, same rationale
// as Table.DBName.
DBName string
Pos Pos
Type Type
RawType string
Nullable bool
List bool // multivalued / array, e.g. Prisma String[] (DB-002)
}
Column is one field of a table. Type is the neutral classification; RawType is the origin type verbatim ("String", "String @db.Text", "Role") so a rule can still see what the source actually wrote (e.g. TEXT used as a FK, DB-051). The "is this sensitive / encrypted" judgment is the rule's, never a flag here.
type ForeignKey ¶
ForeignKey is a relationship from local Columns to RefColumns of RefTable. Composite keys are supported. Only explicit relations are modeled; implicit many-to-many (no local FK columns) is a declared limit this slice (ADR 0014).
type Index ¶
type Index struct {
Pos Pos
Columns []string // composite supported (DB-013)
Unique bool
// Method is the index's declared access method/type (PostgreSQL's `USING
// <method>`, MySQL's `USING BTREE|HASH`, T-SQL's CLUSTERED/NONCLUSTERED/
// COLUMNSTORE kind, Prisma's `@@index(..., type: ...)`), lowercased at
// every capture site so one convention holds across dialects. EMPTY means
// "no access method declared in source" — the same empty-means-none
// convention as Table.DBName and Trigger.ExecutesFunction — and is
// deliberately NEVER defaulted to a guessed vocabulary word like "btree":
// a consumer that needs a default applies its own, this field only
// reports what the source actually said.
//
// A dialect that does not (yet) capture Method for a given statement
// shape leaves it empty exactly like a dialect that never declared one —
// the two are indistinguishable through this field alone (architecture/
// two-classes-of-parser-blindness, "ceguera por omisión"); a provider's
// own coverage manifest (internal/core/dbcoverage) is the place that
// states which shapes it does and does not read.
//
// Prisma's `type:` vocabulary is NOT codefit-maintained: whatever value
// the schema declares is captured verbatim (lowercased), never validated
// against an assumed enum — codefit has not verified Prisma's own
// documented set of accepted index types against every provider, so it
// makes no claim here beyond "this is what the source said".
Method string
}
Index is an index over one or more columns. Unique distinguishes a unique constraint/index from a plain one. PK is NOT represented as an Index — it is Table.PrimaryKey; a rule that treats the PK as an implicit index does so itself (deferred consideration, ADR 0014).
type Partitioning ¶ added in v0.2.5
type Partitioning struct {
// Declaration is the partitioning clause VERBATIM from the user's own
// DDL (modulo the identifier-quote canonicalization every SQL-DDL
// statement goes through before reduction) — the structural analogue of
// Unreduced.Text: parser internals never reach it. NON-EMPTY is the
// authoritative "this table declares partitioning" answer.
Declaration string
// Strategy is the partitioning strategy word as the SOURCE spells it,
// lowercased: "range", "list", "hash", "key", … EMPTY means the strategy
// is not in the DDL read — either because the dialect does not state one
// at the table (T-SQL puts it in the partition FUNCTION) or because the
// clause was not decomposed. codefit does not maintain a closed
// vocabulary here: whatever word follows PARTITION BY is captured.
Strategy string
// Scheme is the T-SQL partition scheme the table is created ON, name
// only (normalized like any other identifier in the model). EMPTY on
// dialects that have no partition schemes. codefit does NOT resolve the
// scheme's range boundaries — only, when the DDL read also contains the
// scheme's CREATE PARTITION FUNCTION, its Strategy.
Scheme string
// Key is the partition key as a list of plain COLUMN identifiers, in
// source order. EMPTY when the source key is not a plain column list —
// most commonly an expression (`PARTITION BY RANGE (YEAR(sold_on))`,
// `PARTITION BY RANGE (extract(year from d))`). A partition key is never
// GUESSED into columns: an expression decomposed by a column-list
// splitter yields an invented column name ("YEAR(sold_on") that exists in
// no table, which is exactly the fabrication class the completeness
// contract cannot catch (it covers drops, not fabrications). When Key is
// empty and Declaration is not, read Declaration.
Key []string
// Of names the PARENT table of a partition CHILD (PostgreSQL's `CREATE
// TABLE c PARTITION OF p ...`), normalized like every other table
// reference. EMPTY means the source did not declare this table as a
// child — which is not proof that it is not one (see the type doc).
Of string
}
Partitioning is what a table's DDL declares about TABLE PARTITIONING — PostgreSQL's `PARTITION BY <strategy> (<key>)` and `PARTITION OF <parent>`, MySQL's `PARTITION BY RANGE|LIST|HASH|KEY (<key>)`, T-SQL's `ON <partition scheme> (<column>)`. It is NOT window-function `PARTITION BY`, which is query syntax and never reaches this model.
Every field follows the empty-means-not-declared convention db.Index.Method and db.Table.DBName already hold to: a value here was READ FROM THE SOURCE (lowercased where the source word is a keyword), never guessed, never defaulted.
WHAT A CONSUMER MAY CONCLUDE
- Declaration != "" — the DDL codefit read declares table partitioning for this table. This is the single authoritative "is it partitioned?" predicate: Strategy, Scheme, Key and Of may ALL be empty for a form the reducer recognized as partitioning but could not decompose, and reading any one of them alone would then answer "no" to a table that said yes.
- Declaration == "" — the DDL codefit read declares NO partitioning for this table. That is NOT the same as "this table is not partitioned in the database": a table can be partitioned by a form this parser does not read, by a statement in a file the scan never saw, or by a PostgreSQL `ALTER TABLE ... ATTACH PARTITION` naming it (which lands on the parent's honest-abstention floor, not here). This field reports the SOURCE, not the database.
- Of != "" — the source declares this table AS A PARTITION of that parent. A partition child is modelled as ITS OWN TABLE (it is one: it has its own storage, its own indexes, and pg_dump emits most of them as ordinary standalone CREATE TABLEs) AND carries this back-reference. It is deliberately not folded into the parent, which would discard the child's own indexes, and not left parentless, which would make a rule count every monthly child of one partitioned fact table as a separate unpartitioned fact table.
- Of == "" does NOT mean "not a child": a child attached by `ALTER TABLE ... ATTACH PARTITION`, or dumped as a standalone CREATE TABLE with no partition grammar of its own (what pg_dump actually emits — Pagila's payment_p2022_01 is exactly this), is indistinguishable here from an ordinary table.
type Pos ¶
Pos is the origin of a schema element: the file it was parsed from and its 1-based line. Every element carries one so a finding and the baseline can anchor by file+line/content (the access-layer missing-line gap, relevamiento §E, not repeated here).
type Reason ¶ added in v0.2.5
type Reason string
Reason is why a table's structure could not be proven complete. A distinct named type (F7, 4R ledger obs #1282, verified — one lens declared the closed-vocabulary claim clean and was WRONG): MarkUnproven previously took a plain string, and the Reason* values were untyped constants, so the "type-level control" ADR 0034 and two doc comments claimed did not exist — the ONLY barrier was a doc comment. A provider computing a diagnostic string at runtime (a reducer function name, a dispatch branch) could pass it straight through with zero compiler friction. Making Reason its own type does not make it impossible to violate — an untyped string constant (a literal, visible in code review) still converts implicitly — but it DOES make it impossible to pass a computed `string` VARIABLE (the actual runtime-diagnostic-leak shape ADR 0034 §2.8 forbids) without an explicit, reviewable `db.Reason(...)` conversion at the call site.
const ( // ReasonUnreducedTableStatement: a statement affecting this table could // not be reduced by the parser. ReasonUnreducedTableStatement Reason = "a statement affecting this table could not be reduced" // ReasonMalformedTableBody: the table's declaration body could not be // parsed at all (e.g. an unbalanced CREATE TABLE(...) body). ReasonMalformedTableBody Reason = "the table's declaration body could not be parsed" // ReasonTableNeverDeclared: this table entry was materialized by a // statement that REFERENCES a table (e.g. ALTER TABLE, CREATE INDEX ... // ON) before any CREATE TABLE for that name was ever seen. It has zero // genuine structure — no columns were ever read — and an absence-based // rule that affirms over it (F4, 4R ledger obs #1282) would be affirming // over a table the parser never actually read at all, not merely one it // read incompletely. ReasonTableNeverDeclared Reason = "no CREATE TABLE statement was ever seen for this table" // ReasonPartitionChildInheritsStructure: this table is declared as a // PARTITION OF a parent table (PostgreSQL's "CREATE TABLE c PARTITION OF // p FOR VALUES ..."). That statement declares the child's PARTITION // BOUNDS and nothing else: its columns, primary key, foreign keys and // constraints all come from the parent and appear NOWHERE in it. The // child is therefore genuinely read (its name and its parent are in // Partitioning.Of) but structurally unproven — distinct from // ReasonUnreducedTableStatement, where the parser met a statement it // could not decompose at all, and from ReasonTableNeverDeclared, where // no CREATE TABLE was ever seen. An absence-based rule that affirmed // over this table would report "no primary key" about a table whose // primary key is declared on its parent. ReasonPartitionChildInheritsStructure Reason = "this table is declared as a partition of another table: its columns and keys are inherited from the parent, not declared here" )
Reasons a table's structure could not be proven complete. A CLOSED set, defined in this package (never provider-authored prose) — the type-level half of the measurement/diagnostics boundary (ADR 0034).
type Schema ¶
type Schema struct {
Tables []Table
Views []View // OLTP surface; not filled by the Prisma parser
Procedures []Procedure // idem
Triggers []Trigger // idem
// Unreduced carries statements the parser recognized as table-affecting
// (e.g. "alter table ...") but could not attribute to any specific table
// (a regex miss on the table name itself) — design §2, drop site 2. It
// gates NOTHING per-table (there is no table to gate); it surfaces only in
// the per-scan completeness inventory (sensors/db.Result.Note).
Unreduced []Unreduced
// Withheld carries declarations the parser READ correctly and
// DELIBERATELY did not model (ADR 0043). It is a different fact from
// Unreduced and deliberately a different channel: Unreduced means the
// parser could not read a statement, Withheld means it could and chose,
// for a stated reason, that the thing it read does not belong in the
// schema codefit audits. Reporting a scoping decision as a parser failure
// would misdescribe it in the opposite direction — it would tell an agent
// codefit is blind where it is in fact seeing clearly.
//
// Withholding is never silent (CLAUDE.md, developer autonomy): it reaches
// the agent through its own bounded trace in the per-scan note
// (sensors/db.Result.Note), aggregated by reason, never one line per table.
// It gates nothing per-table — there is no table to gate, because the
// withheld declaration never entered the model.
Withheld []Withheld
}
Schema is the parsed structure of a database. It models the whole OLTP surface Phase 2 audits; a given parser fills the subset its format expresses (a Prisma parse leaves Views/Procedures/Triggers empty — slice 3's SQL-DDL parser fills them).
func (*Schema) ExecutedProcedure ¶ added in v0.2.2
ExecutedProcedure resolves t.ExecutesFunction to the Procedure with that name in s, or (nil, false) when t names no function (this dialect embeds the trigger's logic directly in Body) or no Procedure with that name is present in the schema — e.g. a PostgreSQL built-in like tsvector_update_trigger, which has no CREATE FUNCTION statement of its own and therefore never appears as a Procedure.
Resolution lives HERE, in the neutral model, never in a rule and never in a provider: both Trigger and Procedure are neutral model elements, and the mapping between them is pure name-based schema data — the binding placement of architecture/pg-trigger-body-link (Unit A2).
type Table ¶
type Table struct {
Name string
// DBName is the real table name in the database when remapped via @@map (or the
// SQL identifier when it differs from the model name). EMPTY means "no remap" —
// a consumer falls back to Name; it is deliberately NOT defaulted to Name, so a
// rule can tell an explicit remap from none. FKs/indexes reference by model
// name, not DBName (ADR 0014).
DBName string
Pos Pos
Columns []Column
PrimaryKey []string // column names; empty = no PK (DB-050); len>1 = composite
ForeignKeys []ForeignKey
Indexes []Index
// Partitioning is what this table's DDL declares about TABLE
// partitioning. Its zero value means "the source codefit read declares
// none" — see the type's own doc for what a consumer may and may not
// conclude from that.
Partitioning Partitioning
// Complete=false means the parser met at least one statement affecting
// this table that it could NOT reduce, and could not rule out that the
// statement declared a key, index or column. A rule that concludes from
// ABSENCE MUST treat Complete==false as grounds to abstain or downgrade to
// a surface item, never to emit a deterministic finding — ADR 0004 made
// mechanical for the STRUCTURAL model exactly as ADR 0025 made it
// mechanical for routine bodies (Body.Complete).
//
// BOUNDARY, so the contract does not over-promise: Complete covers DROPS,
// not FABRICATIONS. A reducer that believes it succeeded while inventing
// data reports Complete=true; that class needs its own control (design
// §8e). The boundary still holds, but the class is SMALLER than when it was
// written and is known to be reachable on ordinary real DDL, not only on
// constructed input: ADR 0042 closed the missing-comma-before-a-table-level-
// key fabrication (measured on three public warehouse corpora) with a
// grammar-decided boundary rule in the reducer, plus a second instance where
// an inline-constraint keyword was read out of a string literal. Each such
// instance needs its own control at its own site — none of them can be caught
// HERE.
//
// A DECLARED skip is NOT incompleteness: a form the parser recognizes and
// deliberately does not model (CHECK, EXCLUDE, ALTER COLUMN, RENAME,
// OWNER, ...) is known not to be a key/index/column and leaves
// Complete=true (ADR 0018's declared subset, made machine-visible).
//
// A table's PARTITIONING clause is neither: it is now READ, into
// Partitioning below. Reading it likewise leaves Complete=true, and for
// the same reason — a partition key is not a primary key, an index or a
// column, so even a partitioning form the reducer cannot decompose
// cannot have hidden one. Partitioning reports its own partial reads
// internally (Partitioning.Declaration) instead of demoting the table.
//
// Zero value is false (fail-closed, design §1-D1b): a table nobody
// explicitly proved complete is unproven by default, never trustworthy by
// accident. Every construction site MUST set this explicitly.
Complete bool
// Note is WHY, drawn from this package's closed Reason* vocabulary —
// never provider prose. A provider can only SELECT a reason and QUOTE the
// user's own source (Unreduced[].Text); it has no channel through which
// parser-internal diagnostics (a function name, a dispatch branch, a
// regex) can reach scan output (ADR 0034's measurement/diagnostics
// boundary). Deduplicated by reason: two drops for the same reason add one
// Note entry, not two.
Note string
// Unreduced is the raw statement text the parser could not reduce, kept
// VERBATIM with its origin so the agent can read the SOURCE itself — the
// structural analogue of Body.Text. This is the USER's DDL, never
// codefit's internals.
Unreduced []Unreduced
}
Table is a relation: its columns, primary key, foreign keys and indexes. PK and FK live at the table level (not as Column flags) because they can be composite and the membership is derivable by column name — see ADR 0014.
func (*Table) MarkUnproven ¶ added in v0.2.5
MarkUnproven records that a statement affecting t could not be reduced. It sets Complete=false (fail-closed), appends the verbatim statement to Unreduced, and adds reason to Note exactly once (deduplicated by reason — architect resolved decision #3). reason is TYPE-CONSTRAINED to this package's Reason* constants (F7) — not merely documented as such; text is the VERBATIM source statement, never a diagnostic. This is a CORE method (ADR 0014), not a reducer-local function, because more than one provider needs it (the sqlddl reducer and the Prisma parser) and both must dedupe identically.
func (Table) StructureProven ¶ added in v0.2.5
StructureProven reports whether every statement affecting t was reduced into the model. An absence-based rule (one that concludes "I did not see X, therefore X is missing") MUST consult this before concluding — reading Complete==false as grounds to abstain (or, for DB-050, to route to a surface item instead of affirming), never to emit a deterministic finding.
type Trigger ¶
type Trigger struct {
Name string
Pos Pos
Table string
Body Body
// ExecutesFunction is the name of the function/procedure this trigger
// invokes, when the dialect expresses that as a distinct name in the
// trigger statement (PostgreSQL: "... EXECUTE FUNCTION|PROCEDURE fn()").
// EMPTY means the dialect embeds the trigger's logic directly in Body
// instead (MySQL, T-SQL), or the executed routine's name could not be
// parsed. This is the trigger→function LINK (Phase 2.2, Unit A2,
// architecture/pg-trigger-body-link): a PostgreSQL trigger carries no
// inline body of its own — the logic lives in the named function, which a
// consumer resolves via Schema.ExecutedProcedure(t), never by re-deriving
// completeness on the trigger's own (bodyless) statement.
ExecutesFunction string
}
type Type ¶
type Type string
Type is the neutral column type. TypeText is distinct from TypeString so a rule can tell a TEXT column used as a FK (DB-051) from a normal string. TypeUnknown is the honest fallback for a type the parser does not classify.
type Unreduced ¶ added in v0.2.5
Unreduced is one statement the parser recognized as affecting a table (or, on Schema.Unreduced, the schema as a whole) but could not reduce into the model, kept verbatim with its source position.
type View ¶
View, Procedure and Trigger complete the OLTP surface. They are DEFINED here so the model is format-agnostic, but the Prisma parser leaves them empty; the SQL-DDL parser populates them, INCLUDING Body (Phase 2.2, RF-03.6).
type Withheld ¶ added in v0.2.5
type Withheld struct {
// Name is the declared name, as the source spells it, when the recognized
// form puts it somewhere the parser knows. EMPTY means the form carries
// none the parser can read faithfully — never a guess, and never
// back-filled from the statement text.
Name string
// Text is the VERBATIM source statement — the user's own DDL, never
// codefit's internals (the same measurement/diagnostics boundary
// Unreduced.Text observes, ADR 0034 §2.8).
Text string
Pos Pos
// Reason is drawn from this package's closed WithheldReason vocabulary.
Reason WithheldReason
}
Withheld is one declaration the parser read and deliberately left out of the model, kept verbatim with its source position so the agent can read the DDL itself (ADR 0043).
type WithheldReason ¶ added in v0.2.5
type WithheldReason string
WithheldReason is why a declaration the parser RECOGNIZED was deliberately left out of the model. A CLOSED set, and a DISTINCT type from Reason rather than a new constant added to it: Reason answers "why could this table's structure not be proven complete", and an answer to that question is grounds for an absence-based rule to abstain. A withheld declaration raises no such question — nothing about it is unproven, it is simply not part of the persistent schema — so the two vocabularies must not be assignable to each other, or a future reader will route one into the other's carrier and turn a scoping decision into a reported parser failure.
const ( // ReasonSessionScopedTable: the declaration is a TEMPORARY table — // PostgreSQL's and MySQL's TEMP/TEMPORARY (with or without GLOBAL/LOCAL) // and T-SQL's '#'/'##' name prefix. Such a table lives only for the // duration of a session and is dropped with it, so it is not part of the // persistent schema the DB dimension audits. Admitting it would put // scratch space in front of every absence-based rule — DB-050 would // affirm "table without a primary key" over a temporary work table, at // confidence 1.0. ReasonSessionScopedTable WithheldReason = "" /* 137-byte string literal not displayed */ )
Reasons a recognized declaration is deliberately not modeled. A CLOSED set, defined in this package (never provider-authored prose).