Documentation
¶
Overview ¶
Package lint checks DDL offline for patterns the engine would refuse, rewrite, or gate. It runs the same parse-and-classify pipeline as the front doors but with zero live facts, so it needs no database and is strictly conservative: a change lint passes without findings can still sharpen at execution time, but a change lint flags will never quietly get worse. Findings carry typed codes automation branches on — never prose.
Index ¶
Constants ¶
const FormatVersion = 1
FormatVersion identifies the report contract. A consumer must reject a report whose version it does not understand instead of guessing at the field semantics.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Code ¶
type Code string
Code is the typed finding kind; automation branches on it, never on prose.
const ( // CodeUnsupportedOperation: no known safe path — the engine refuses it. CodeUnsupportedOperation Code = "unsupported-operation" // CodeBlockingIdiom: the submitted form blocks readers or writers and // a safer native form exists; Suggestion carries it when the linter // can construct one. The safer form is not a semantic equivalent — // a CONCURRENTLY build is non-transactional and a failure leaves an // invalid index the engine detects and rebuilds at execution time. CodeBlockingIdiom Code = "blocking-idiom" // CodeTableRewrite: the operation needs a full table rewrite — only // the engine's copy-and-swap path can run it online. Reason carries // the specific cause. CodeTableRewrite Code = "table-rewrite" // CodePossibleTableRewrite: the linter cannot verify the operation // against live column facts, so the engine would fail closed to the // rewrite path — but the change may be a free relabel that a live // database would prove. The route is what the engine would do, not a // proven property of the change. CodePossibleTableRewrite Code = "possible-table-rewrite" // CodeAppBreakingRename: the statement renames a column or table in // place — metadata-only for PostgreSQL, but running application code // still referencing the old name breaks the instant it commits. For // a column the safe sequence is expand/contract: add the new column, // dual-write and backfill, switch reads, then drop the old column as // its own reviewed change. For a table, coordinate the rename with // the application deploy that adopts the new name. CodeAppBreakingRename Code = "app-breaking-rename" // CodeDestructive: the operation discards live structure (a column, // constraint, or index drop) and cannot be undone by re-running the // schema. Index drops are included because the linter cannot see // whether an index is unique — and a dropped unique index whose gap // admitted duplicates cannot be recreated at all. CodeDestructive Code = "destructive" )
The finding codes.
type Finding ¶
type Finding struct {
// Statement is the 1-based index of the statement in the script.
Statement int `json:"statement"`
// Line is the 1-based source line of the statement's first token, so
// a CI system can annotate the finding onto the file it came from.
Line int `json:"line"`
// Column is the 1-based source column of the statement's first token.
Column int `json:"column"`
// SQL is the verbatim source text of that statement, so it can be
// found in the source by exact match.
SQL string `json:"sql"`
// Operation is the operator-facing label of the flagged operation
// (display only).
Operation string `json:"operation"`
// Code is the typed finding kind.
Code Code `json:"code"`
// Severity is what the engine would do about it.
Severity Severity `json:"severity"`
// Reason is the classifier's typed cause, present for findings the
// classifier produced (blocking-idiom, table-rewrite, unsupported).
Reason planner.Reason `json:"reason,omitempty"`
// Suggestion is the ordered safer SQL, present only for
// blocking-idiom findings where the linter could construct it. It is
// advisory: a safer form, not a semantic equivalent — running it by
// hand forgoes the engine's execution-time guards (invalid-index
// detection after a concurrent build).
Suggestion []string `json:"suggestion,omitempty"`
// SuggestionExecution is the typed execution contract for Suggestion
// (planner.Execution), present exactly when Suggestion is. A consumer
// that runs the suggestion branches on it — it is what says the steps
// must not be wrapped in a transaction block.
SuggestionExecution planner.Execution `json:"suggestion_execution,omitempty"`
}
Finding is one lint result: the statement it is about, the typed code, and the severity.
type Report ¶
type Report struct {
// FormatVersion is the report contract version; always FormatVersion.
FormatVersion int `json:"format_version"`
// PostgresVersions is the inclusive PostgreSQL major-version range
// the offline rules are derived for (planner.RulesPostgresVersions).
// The linter never sees a server, so a stored report names the
// assumptions behind it instead.
PostgresVersions string `json:"postgres_versions"`
// Findings are the results in statement order; empty means the script
// is clean.
Findings []Finding `json:"findings"`
// Errors counts error-severity findings.
Errors int `json:"errors"`
// Warnings counts warning-severity findings.
Warnings int `json:"warnings"`
}
Report is the lint result for one script.
type Severity ¶
type Severity string
Severity ranks a finding by what the engine would do with it.
const ( // SeverityError: the engine would refuse the statement — it cannot // execute as written. SeverityError Severity = "error" // SeverityWarning: the engine would execute the statement, but it has // a safer form, needs a heavier path, or discards live structure. SeverityWarning Severity = "warning" )
The severities a finding can carry.