lint

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

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

View Source
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.

func Check

func Check(sql string) (Report, error)

Check lints a DDL script: every statement is parsed with the PostgreSQL grammar and classified with zero live facts. A parse failure is an error; an unsupported operation is not — it is an error-severity finding, so one bad statement never hides the rest of the report.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL