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 today, SQL-DDL later).
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 entire OLTP surface Phase 2 audits, even what a given parser cannot express: a Prisma parse fills Tables/Columns/Indexes/ForeignKeys and leaves Views/Procedures/Triggers empty (the SQL-DDL parser of slice 3 fills those). 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 UniqueKeys(t Table) [][]string
- type Body
- type Column
- type ForeignKey
- type Index
- type Pos
- type Procedure
- type Schema
- type Table
- type Trigger
- type Type
- type View
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 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 ¶
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 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 Schema ¶
type Schema struct {
Tables []Table
Views []View // OLTP surface; not filled by the Prisma parser
Procedures []Procedure // idem
Triggers []Trigger // idem
}
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
}
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.
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
}