Documentation
¶
Overview ¶
Package rules implements the structural rule checks R1–R9. This file is R1 (slot legality + node completeness), which runs in phase P2's pipeline position; catalog-free and catalog-dependent rule passes (R2–R9) arrive in P3. See docs/design/02-rendering.md §4 and 03-structural-rules.md.
Index ¶
- func CheckLexical(profile dialect.LexerProfile, q *template.QueryTemplate) []diagnostics.Diagnostic
- func CheckR1(profile dialect.LexerProfile, fe dialect.Frontend, q *template.QueryTemplate, ...) []diagnostics.Diagnostic
- func CheckResolved(profile dialect.LexerProfile, q *template.QueryTemplate, maxR ast.Rendering, ...) []diagnostics.Diagnostic
- func CheckTypeAgreement(q *template.QueryTemplate, rs []ast.Rendering, descs []dialect.Desc) []diagnostics.Diagnostic
- func DeriveNullableParams(profile dialect.LexerProfile, q *template.QueryTemplate, maxR ast.Rendering, ...) map[string]bool
- type ColumnResolver
- type ParamType
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CheckLexical ¶
func CheckLexical(profile dialect.LexerProfile, q *template.QueryTemplate) []diagnostics.Diagnostic
CheckLexical runs the catalog-free rule pass: R6 (anchored clauses) and R9 (parameter discipline). As a side effect it classifies each parameter's optionality (consumed by codegen). See docs/design/03-structural-rules.md §3–4.
func CheckR1 ¶
func CheckR1(profile dialect.LexerProfile, fe dialect.Frontend, q *template.QueryTemplate, rs []ast.Rendering) []diagnostics.Diagnostic
CheckR1 validates that every fragment is one complete AST node in its slot and that every rendering parses as a single DML statement. rs must come from ast.Renderings (maximal first).
Order matters for diagnostics quality: fragment-local probes run first (they pinpoint the offending fragment), then whole-rendering parses, then AST-membership consistency checks on the maximal tree.
func CheckResolved ¶
func CheckResolved(profile dialect.LexerProfile, q *template.QueryTemplate, maxR ast.Rendering, maxTree dialect.Tree, cat *cache.Catalog) []diagnostics.Diagnostic
CheckResolved runs the catalog-dependent rule pass on the parsed maximal rendering: R3 (resolution-based guarded scope), R2's star expansion, ambiguity detection, and the planner-sensitive combination table. See docs/design/03-structural-rules.md §6–7.
Qualified column references are resolved innermost-first (design 03 §6): a qualifier introduced by an enclosing subquery scope (ColRef.ScopeAliases) shadows a same-named top-level relation, so the reference binds locally and the top-level guard is not re-derived for it; a correlated qualified reference (qualifier absent from every enclosing subquery FROM) is still checked. UNqualified references inside subquery scopes remain skipped — resolving a bare column against nested scopes is not modeled — with the per-shape EXPLAIN property test as the mechanical backstop.
func CheckTypeAgreement ¶
func CheckTypeAgreement(q *template.QueryTemplate, rs []ast.Rendering, descs []dialect.Desc) []diagnostics.Diagnostic
CheckTypeAgreement verifies the cross-rendering obligations of design 04 §5: every rendering agrees with the maximal one on result columns (SQLETCH210) and every template parameter has a single type across all renderings that bind it (SQLETCH211). descs[i] must correspond to rs[i].
func DeriveNullableParams ¶ added in v0.0.3
func DeriveNullableParams(profile dialect.LexerProfile, q *template.QueryTemplate, maxR ast.Rendering, maxTree dialect.Tree, cat *cache.Catalog) map[string]bool
DeriveNullableParams reports the parameters whose Go type becomes optional.Option[T] because they write SQL NULL-able columns (design 20 §3): a parameter is nullable iff EVERY one of its bind occurrences is a direct value position (dialect.Tree.ValueTargets) of a nullable column of the statement's base-table target. The returned map holds only true entries; a nil catalog derives nothing.
Every uncertainty resolves to "not nullable" — the parameter stays a plain value, which is the pre-design-20 behavior. A wrong "nullable" can only surface as a loud constraint error when a caller passes None, but nothing here guesses in that direction either.
Types ¶
type ColumnResolver ¶ added in v0.0.6
type ColumnResolver struct {
// contains filtered or unexported fields
}
ColumnResolver binds a bare column reference against a statement's top-level relations with the same resolver R3 uses (dialect-correct name folding, catalog lookup). It is exported for internal/lint (SQLETCHL005), so the lint never forks name resolution.
func NewColumnResolver ¶ added in v0.0.6
func NewColumnResolver(profile dialect.LexerProfile, q *template.QueryTemplate, maxR ast.Rendering, maxTree dialect.Tree, cat *cache.Catalog) *ColumnResolver
NewColumnResolver builds a resolver over the maximal rendering's top-level relations.
func (*ColumnResolver) Column ¶ added in v0.0.6
func (c *ColumnResolver) Column(qualifier, name string) (col *cache.Column, relation string)
Column returns the catalog column `qualifier.name` and the name of the relation (its Table, as written) it resolved through, so a caller can refuse a relation the catalog cannot vouch for (a CTE sharing a base table's name). An empty qualifier means an unqualified reference, which must match exactly one relation's catalog columns. col is nil when unresolved.
type ParamType ¶
ParamType is one template parameter's pinned type (premise P1), ordered like q.ParamOrder.
func ResolveParamTypes ¶
func ResolveParamTypes(q *template.QueryTemplate, rs []ast.Rendering, descs []dialect.Desc) ([]ParamType, []diagnostics.Diagnostic)
ResolveParamTypes unifies each template parameter's type across all renderings (they must agree — SQLETCH211) and returns the pinned types in q.ParamOrder.