semantic

package
v0.0.0-...-68be0e9 Latest Latest
Warning

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

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

Documentation

Overview

Package semantic is the Go port of Java's `com.apple.foundationdb.relational.recordlayer.query.SemanticAnalyzer` plus related Identifier / Expression / reference-resolution helpers.

The Java class is a 1280-line monolith doing identifier normalization, table / CTE / function lookup, index validation, ORDER BY validation, type inference, star expansion, nested-field resolution, and correlated-identifier resolution. The Go port breaks that up across focused files:

  • identifier.go — Identifier type + case-folding normalization.
  • (future) — table / column / CTE / index lookup, type inference, star expansion.

Currently ships only the identifier machinery; the resolution + type passes are follow-up work.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NormalizeString

func NormalizeString(s string, caseSensitive bool) string

NormalizeString is the lower-level helper underlying New. Exposed for call sites that have a raw string and don't need the full Identifier wrapper (e.g. dedup keys in the parser). Mirrors Java's `SemanticAnalyzer.normalizeString`.

  • Empty string → empty string.
  • Quoted (single or double) → strip quotes verbatim.
  • Unquoted + caseSensitive → return unchanged.
  • Unquoted + !caseSensitive → upper-case.

Types

type AmbiguousColumnError

type AmbiguousColumnError struct {
	Id Identifier
	// Matches is always equal to len(Sources); exists as a
	// convenience accessor for callers who don't need the full
	// alias list. Future API tightening may remove it — prefer
	// len(Sources) for new code.
	Matches int
	// Sources is the list of ScopeSource aliases that matched,
	// allowing the user-facing message to suggest
	// `alias.column` for each candidate.
	Sources []Identifier
}

AmbiguousColumnError is returned when a bare column reference matches multiple sources at the same scope level. Carries the conflicting identifier and the conflicting source aliases so the user knows which tables to qualify against.

func (*AmbiguousColumnError) Error

func (e *AmbiguousColumnError) Error() string

type Analyzer

type Analyzer struct {
	// contains filtered or unexported fields
}

Analyzer ties Catalog lookups + identifier normalization into the resolution helpers that rule authors / logical-plan builders invoke. Mirrors the instance surface of Java's `SemanticAnalyzer` (the static methods on that class — case folding etc. — live as free functions in this package).

Seed scope: resolve table references, resolve bare/qualified column references. Star expansion, nested-field lookup, correlated-identifier resolution all land in follow-up shifts.

Not safe for concurrent mutation of the underlying Catalog; the Analyzer itself is stateless once constructed.

func NewAnalyzer

func NewAnalyzer(catalog Catalog, caseSensitive bool) *Analyzer

NewAnalyzer wires up an Analyzer against the given catalog. A nil catalog is rejected — callers who don't have a real schema yet should use NewInMemoryCatalog() with no tables.

func (*Analyzer) BuildScopeFromFromClause

func (a *Analyzer) BuildScopeFromFromClause(parent *Scope, fromCtx antlrgen.IFromClauseContext) (*Scope, error)

BuildScopeFromFromClause walks a parsed FROM clause and produces a Scope populated with one ScopeSource per TableSource. The analyzer resolves each table via its catalog; missing tables return the first TableNotFoundError encountered.

Supports the simple shape (comma-separated AtomTableItem entries + optional alias); subquery-in-FROM and JOIN clauses are deferred until the join/derived-table resolution passes land. Unsupported shapes return an UnsupportedFromShapeError so callers can fall back to the existing logical-builder path cleanly.

Pass parent=nil for a top-level query; pass the enclosing scope for correlated subqueries.

func (*Analyzer) CaseSensitive

func (a *Analyzer) CaseSensitive() bool

CaseSensitive reports the analyzer's case-sensitivity setting.

func (*Analyzer) Catalog

func (a *Analyzer) Catalog() Catalog

Catalog returns the underlying Catalog. Exposed so higher-level passes (e.g. LogicalPlan builder) can thread the same catalog through without re-wiring.

func (*Analyzer) ExpandQualifiedStar

func (a *Analyzer) ExpandQualifiedStar(scope *Scope, qualifier Identifier) ([]ExpandedColumn, error)

ExpandQualifiedStar implements `SELECT alias.*` against a Scope: looks up the named source, then its columns. Walks the parent chain for correlated-star references. Returns SourceNotFoundError (with the Available alias list populated from every visible scope for "did you mean?" rendering) when no source matches.

func (*Analyzer) ExpandScopeStar

func (a *Analyzer) ExpandScopeStar(scope *Scope) []ExpandedColumn

ExpandScopeStar implements unqualified `SELECT *` against a Scope: concatenates each source's columns in FROM-order. Ambiguity is NOT flagged here — Java's SQL lets two sources expose same-named columns through `SELECT *` (the output just gets two columns); only bare *references* error. Downstream callers tag each ExpandedColumn with its source so later projection rewrites can qualify.

func (*Analyzer) ExpandStar

func (a *Analyzer) ExpandStar(table Table) []Column

ExpandStar implements the `SELECT *` rewrite — returns the full column list of the given table in declared order. Each Column is returned unchanged (same Id, Type, Nullable) so downstream plan builders can wrap each into a ColumnReference / ProjectionItem.

Mirrors the single-qualifier case of Java's `SemanticAnalyzer.expandStar`. The multi-table / alias-qualified cases (`SELECT t.* FROM t JOIN u`) come with the FROM-scope port.

func (*Analyzer) ResolveColumn

func (a *Analyzer) ResolveColumn(table Table, id Identifier) (Column, error)

ResolveColumn looks up a column by identifier against a resolved table. Mirrors the simple case of Java's resolveIdentifier — qualifier resolution (`t.col` → column on aliased table) comes later with the FROM-clause scope machinery.

func (*Analyzer) ResolveColumnRef

func (a *Analyzer) ResolveColumnRef(scope *Scope, qualifier, id Identifier) (Column, ScopeSource, error)

ResolveColumnRef is the one-shot column-reference resolver: given a qualifier (may be zero) and a column identifier, dispatch to bare or qualified lookup against the provided scope. This is the analyzer's top-level hook for every identifier reference the expression resolver sees.

- qualifier.IsZero() → Scope.ResolveColumn (bare). - qualifier non-zero → Scope.ResolveQualifiedColumn.

Returns the same typed errors as the underlying scope methods.

func (*Analyzer) ResolveTable

func (a *Analyzer) ResolveTable(name QualifiedName) (Table, error)

ResolveTable looks up a table by qualified name. Returns a typed error when the name is missing so callers can wrap it into the API-level error shape without string-matching.

func (*Analyzer) ResolveTableRef

func (a *Analyzer) ResolveTableRef(ctx antlrgen.IFullIdContext) (Table, error)

ResolveTableRef is the parse-tree convenience wrapper over ResolveTable. Reads the IFullIdContext (ANTLR's table reference node), builds a QualifiedName with the analyzer's case-sensitivity, then looks it up in the catalog.

Returns TableNotFoundError with the QualifiedName the caller requested; callers preserve user-facing names through `err.Name.String()`.

type Catalog

type Catalog interface {
	// LookupTable returns a Table handle for the given qualified
	// name, or (nil, false) if no such table exists. Name
	// normalization is the caller's job — QualifiedName already
	// carries the case-folded form.
	LookupTable(name QualifiedName) (Table, bool)

	// TableExists reports whether a Table with the given name is
	// registered. Equivalent to LookupTable's second return value;
	// surfaced separately because it's the common fast-path check
	// in existence-gating rules.
	TableExists(name QualifiedName) bool

	// AllTableNames returns every registered table's qualified
	// name. Order is unspecified; callers that need deterministic
	// ordering should sort. Used for INFORMATION_SCHEMA-style
	// reflection and for error messages that enumerate candidate
	// tables.
	AllTableNames() []QualifiedName
}

Catalog is the semantic analyzer's view of the schema. The analyzer looks up tables, columns, and indexes through this interface; concrete implementations bridge to `RecordMetaData` (for the embedded engine) or to test fixtures.

Mirrors the subset of Java's `SchemaTemplate` that the Go SemanticAnalyzer port needs. Keeping it narrow so the seed doesn't drag in the full RecordLayer metadata surface — callers who need more adapter methods can extend the Table interface later.

All lookups take QualifiedName so the analyzer can handle schema-qualified references uniformly; concrete impls decide how to resolve un-qualified names (walk the search path, default schema, etc.).

type Column

type Column struct {
	// Id is the column name.
	Id Identifier

	// Type is the column's SQL-ish data type as a string (e.g.
	// "INT", "STRING", "BYTES"). Will be replaced with a richer
	// `DataType` once the Type hierarchy is ported.
	Type string

	// Nullable reports whether the column allows NULL values.
	// Matters for NOT-NULL-gated simplifications (x = x → TRUE).
	Nullable bool

	// IsArray reports whether the column is an ARRAY (a repeated proto
	// field). The placeholder Type string carries only the scalar/element
	// kind, so this is the array signal callers need to type the resolved
	// column Value as an ArrayType — e.g. CARDINALITY()'s isArray() check.
	// When true, Type is the ELEMENT type string.
	IsArray bool
}

Column is the analyzer's view of a table column. Type is a placeholder string until the DataType / Type hierarchy port lands (Phase 4.0 continuation).

type ColumnNotFoundError

type ColumnNotFoundError struct {
	TableName QualifiedName
	Id        Identifier
}

ColumnNotFoundError is returned when ResolveColumn can't find a column on the given table.

func (*ColumnNotFoundError) Error

func (e *ColumnNotFoundError) Error() string

type DuplicateAliasError

type DuplicateAliasError struct {
	Alias Identifier
}

DuplicateAliasError is returned by AddSource when the same alias is already registered at this scope level.

func (*DuplicateAliasError) Error

func (e *DuplicateAliasError) Error() string

type ExpandedColumn

type ExpandedColumn struct {
	Column Column
	Source ScopeSource
}

ExpandedColumn pairs a Column with the ScopeSource it came from. The scope-aware star expander / qualified-star expander returns these so downstream plan builders know which FROM source to attribute each projected column to.

type FunctionArityError

type FunctionArityError struct {
	Function string
	Got      int
	Min      int
	Max      int
}

FunctionArityError signals too few / too many arguments.

func (*FunctionArityError) Error

func (e *FunctionArityError) Error() string

type FunctionCatalog

type FunctionCatalog struct {
	// contains filtered or unexported fields
}

FunctionCatalog holds the set of functions the analyzer recognizes. Seed ships the core SQL aggregates; scalar function catalogues come as the embedded engine's scalar-function library gets ported.

func NewFunctionCatalog

func NewFunctionCatalog() *FunctionCatalog

NewFunctionCatalog builds an empty catalog. Use RegisterDefaults or Register to populate.

func (*FunctionCatalog) Contains

func (c *FunctionCatalog) Contains(name Identifier) bool

Contains reports whether a function with the given identifier is registered. Equivalent to Lookup's second return.

func (*FunctionCatalog) Lookup

func (c *FunctionCatalog) Lookup(name Identifier) (FunctionSpec, bool)

Lookup returns the FunctionSpec for name (case-insensitive), or (_, false) when not registered.

func (*FunctionCatalog) Register

func (c *FunctionCatalog) Register(spec FunctionSpec) error

Register adds a FunctionSpec. Returns an error on duplicate name; caller can ignore when registering a known stable set or bubble up when the registry is built from user extensions.

func (*FunctionCatalog) RegisterDefaults

func (c *FunctionCatalog) RegisterDefaults()

RegisterDefaults populates the catalog with the standard SQL aggregate functions. Scalar functions are not seeded — they come from the dedicated scalar-function catalogue once that's ported.

type FunctionKind

type FunctionKind int

FunctionKind enumerates the classes of function the analyzer supports.

Values are assigned explicitly (not via `iota`) so inserting a new kind between existing ones doesn't renumber anything — future serialized-plan formats can assume these values are stable.

const (
	// FunctionScalar: per-row function (UPPER, LOWER, ABS, etc.).
	FunctionScalar FunctionKind = 1
	// FunctionAggregate: spans multiple rows (COUNT, SUM, MIN, MAX, AVG).
	FunctionAggregate FunctionKind = 2
)

func (FunctionKind) String

func (k FunctionKind) String() string

String returns the kind as a debug-friendly string.

type FunctionNotFoundError

type FunctionNotFoundError struct {
	Name Identifier
}

FunctionNotFoundError signals a lookup miss — the function name isn't registered in the catalogue.

func (*FunctionNotFoundError) Error

func (e *FunctionNotFoundError) Error() string

type FunctionSpec

type FunctionSpec struct {
	// Name is the canonical, case-folded function name (e.g. "COUNT").
	Name string
	// Kind classifies the function — scalar or aggregate (window
	// functions come later).
	Kind FunctionKind
	// MinArgs / MaxArgs bound accepted arity. A MaxArgs of -1 means
	// no upper bound (variadic).
	MinArgs int
	MaxArgs int
	// AllowsStar reports whether the function accepts `*` as its
	// argument (currently only COUNT does).
	AllowsStar bool
	// AllowsDistinct reports whether the function accepts a leading
	// DISTINCT modifier — e.g. `COUNT(DISTINCT col)`. All aggregates
	// in the SQL standard accept DISTINCT; the flag exists here so
	// future scalar extensions can opt out.
	AllowsDistinct bool
}

FunctionSpec describes a SQL-visible function the analyzer can resolve. The seed differentiates scalar vs aggregate functions since rule-matching / plan-building treats them differently.

func (FunctionSpec) ValidateArity

func (spec FunctionSpec) ValidateArity(argCount int) error

ValidateArity reports whether argCount is acceptable for spec. Zero = no arguments. A MaxArgs of -1 is treated as "no upper bound". Returns a typed error on mismatch so callers can build user-facing messages without string-matching.

Callers handling `*` (star-argument) functions should check `AllowsStar` BEFORE calling ValidateArity and skip the arity check for the star case. The star is syntactically 0 arguments, but COUNT(*) is legal despite COUNT's MinArgs=1 — that's not a contradiction the arity check should reason about.

type Identifier

type Identifier struct {
	// contains filtered or unexported fields
}

Identifier is a SQL identifier — a table, column, alias, or function name. Carries the normalized form (case-folded per SQL rules) so Identifiers can live in maps and compare by `==` directly. The original source text is the caller's responsibility (store it alongside via the parse tree's token stream when you need user-spelling-preserving error messages).

Mirrors Java's `com.apple.foundationdb.relational.recordlayer. query.Identifier`, trimmed to the essential equality surface.

func FromUidContext

func FromUidContext(ctx antlrgen.IUidContext, caseSensitive bool) Identifier

FromUidContext converts a single IUidContext to an Identifier. Used for unqualified references (column aliases, CTE names, etc.) where the full-id shape is overkill.

func New

func New(raw string, caseSensitive bool) Identifier

New constructs an Identifier by normalizing raw per SQL rules. When caseSensitive is true, unquoted identifiers retain their source casing; otherwise they're upper-cased. Quoted identifiers always retain case regardless of caseSensitive.

func NewUnquoted

func NewUnquoted(raw string) Identifier

NewUnquoted is the common path — a case-insensitive bare identifier. Equivalent to New(raw, false).

func (Identifier) EqualsIgnoreQuoting

func (i Identifier) EqualsIgnoreQuoting(other Identifier) bool

EqualsIgnoreQuoting compares by Name only, ignoring the quoting flag. For most lookups a quoted-vs-unquoted distinction doesn't matter — e.g. an `ORDER BY` clause referring to `"age"` still targets the same column as a SELECT projecting `age`. Use `==` on Identifier when the quoting distinction matters (resolving against a reserved-word shadow).

func (Identifier) IsZero

func (i Identifier) IsZero() bool

IsZero reports whether i is the zero-value Identifier (empty). Useful for nil-check replacement since Identifier is a value type.

func (Identifier) Name

func (i Identifier) Name() string

Name returns the normalized identifier text. Two Identifiers with the same Name AND same WasQuoted are equal via `==`.

func (Identifier) String

func (i Identifier) String() string

String implements fmt.Stringer.

func (Identifier) WasQuoted

func (i Identifier) WasQuoted() bool

WasQuoted reports whether the source text was quoted. Callers that need to preserve user intent (e.g. "keyword" vs keyword) check this flag.

type InMemoryCatalog

type InMemoryCatalog struct {
	// contains filtered or unexported fields
}

InMemoryCatalog is a test-friendly Catalog built from a fixed list of tables. Keeps the test surface small — production impls bridge to RecordMetaData; tests construct one of these in a line or two.

func NewInMemoryCatalog

func NewInMemoryCatalog(tables ...Table) *InMemoryCatalog

NewInMemoryCatalog builds a Catalog from the given tables. Table names key the map by their canonical String() form so lookups are O(1).

func (*InMemoryCatalog) AllTableNames

func (c *InMemoryCatalog) AllTableNames() []QualifiedName

AllTableNames implements Catalog. Iterates the map — order is unspecified.

func (*InMemoryCatalog) LookupTable

func (c *InMemoryCatalog) LookupTable(name QualifiedName) (Table, bool)

LookupTable implements Catalog.

func (*InMemoryCatalog) TableExists

func (c *InMemoryCatalog) TableExists(name QualifiedName) bool

TableExists implements Catalog.

type QualifiedName

type QualifiedName struct {
	// contains filtered or unexported fields
}

QualifiedName is a dot-separated SQL name like `schema.table.col`. The leaf (last segment) is the "simple name"; the preceding segments are the "qualifier". Both normalized together — callers never see a QualifiedName with one segment upper-cased and another in source case.

Mirrors Java's Identifier-with-qualifier shape. The Go port breaks it off into its own type because:

  • Slices aren't comparable, so bundling segments into Identifier would lose the map-as-key ergonomics.
  • Most callsites touch only the leaf — an unqualified Identifier stays simple.

Use QualifiedName when you need to preserve the qualifier chain (table aliases, schema-scoped tables). Use Identifier for bare column / alias references.

func FromFullIdContext

func FromFullIdContext(ctx antlrgen.IFullIdContext, caseSensitive bool) QualifiedName

FromFullIdContext converts an ANTLR IFullIdContext parse-tree node to a QualifiedName. Each Uid segment is read via GetText() (which preserves source casing), then normalized per caseSensitive.

The typical call site is table-name resolution:

tbl := semantic.FromFullIdContext(tblCtx.FullId(), false)
if resolved, err := catalog.LookupTable(tbl); err != nil { ... }

Returns the zero QualifiedName when ctx is nil or has no Uid children — callers should test IsZero before trusting the result.

func FromSegments

func FromSegments(segments []string, caseSensitive bool) QualifiedName

FromSegments builds a QualifiedName from already-normalized segments (each passed through NormalizeString or equivalent). Empty input returns the zero value.

func ParseQualifiedName

func ParseQualifiedName(raw string, caseSensitive bool) QualifiedName

ParseQualifiedName splits a raw dotted string into a QualifiedName. Each segment is normalized independently (stripped of its own surrounding quotes, case-folded unless caseSensitive or quoted).

Semantics match Java's token-per-segment handling: `t."X"` parses as qualifier=[T], name="X" (first segment upper-cased because unquoted, second preserved because quoted).

Quote-embedded dots are NOT handled (e.g. `"a.b".c` still splits on every dot). The ANTLR parser already tokenises individual identifiers, so callers feeding us pre-tokenised segments won't hit this edge — see FromSegments for that path.

func (QualifiedName) EqualsIgnoreQuoting

func (q QualifiedName) EqualsIgnoreQuoting(other QualifiedName) bool

EqualsIgnoreQuoting compares segment-by-segment by normalized text only, ignoring per-segment quoting flags. This is the common "these target the same database object" semantics that Java's Identifier.equals uses.

func (QualifiedName) IsQualified

func (q QualifiedName) IsQualified() bool

IsQualified reports whether the name has at least one qualifier segment preceding the leaf.

func (QualifiedName) IsZero

func (q QualifiedName) IsZero() bool

IsZero reports whether q is the zero-value (empty) QualifiedName.

func (QualifiedName) LeafIdentifier

func (q QualifiedName) LeafIdentifier() Identifier

LeafIdentifier returns the leaf segment wrapped as an Identifier (preserving the leaf's wasQuoted flag). Useful when a caller resolved a qualified name and now wants to work with just the column name.

func (QualifiedName) Name

func (q QualifiedName) Name() string

Name returns the leaf (last) segment. For `schema.table.col` this is `col`. Zero QualifiedName returns the empty string.

func (QualifiedName) PrefixedWith

func (q QualifiedName) PrefixedWith(prefix QualifiedName) bool

PrefixedWith reports whether q starts with prefix's segments. `schema.table.col` is prefixed with `schema.table`. Useful for resolving a bare column against a set of alias-qualified candidates.

func (QualifiedName) Qualifier

func (q QualifiedName) Qualifier() []string

Qualifier returns the segments before the leaf. For `schema.table.col` this returns [schema, table]. An unqualified name returns an empty slice (never nil).

func (QualifiedName) Segments

func (q QualifiedName) Segments() []string

Segments returns all segments, leaf-last. Zero QualifiedName returns nil; otherwise a defensive copy.

func (QualifiedName) String

func (q QualifiedName) String() string

String returns the canonical dotted representation. Suitable for map keys (two QualifiedNames with the same String value are equal under EqualsIgnoreQuoting).

type Scope

type Scope struct {
	// contains filtered or unexported fields
}

Scope is the set of named resolutions visible at a point during query analysis. A scope knows about the FROM-clause sources (tables + their aliases) at that level and, via parent-chain, inherits correlated sources from enclosing scopes (for nested subqueries).

Mirrors the subset of Java's `LogicalPlanFragment` + scope chain the analyzer uses for identifier resolution.

Construction: start with NewScope(parent) — parent nil means the outermost query. Call AddSource to push each FROM source as the analyzer walks FROM clauses left-to-right.

Not concurrency-safe; the analyzer is single-threaded per query.

func NewScope

func NewScope(parent *Scope) *Scope

NewScope constructs a Scope inheriting from parent. parent may be nil for the outermost query.

func (*Scope) AddSource

func (s *Scope) AddSource(src ScopeSource) error

AddSource appends a FROM-clause source. Returns an error on duplicate alias within the same scope (SQL forbids two sources sharing an alias at the same level).

func (*Scope) AllSourcesRecursive

func (s *Scope) AllSourcesRecursive() []ScopeSource

AllSourcesRecursive returns sources from this scope and every ancestor, inner-first. Useful for "did you mean?" error suggestions when a qualifier misses — callers can enumerate all visible aliases and suggest the closest.

func (*Scope) Parent

func (s *Scope) Parent() *Scope

Parent returns the enclosing scope, or nil if this is the outermost.

func (*Scope) ResolveColumn

func (s *Scope) ResolveColumn(id Identifier) (Column, ScopeSource, error)

ResolveColumn looks up a bare column reference (no qualifier) against the scope's sources, following the parent chain if no local match. Ambiguous matches within a single scope level (multiple tables with a column of this name) return an error — the caller should instruct the user to qualify.

Mirrors Java's resolution: inner scopes shadow outer; within a scope, ambiguity is a hard error.

func (*Scope) ResolveQualifiedColumn

func (s *Scope) ResolveQualifiedColumn(qualifier, col Identifier) (Column, ScopeSource, error)

ResolveQualifiedColumn handles `alias.col` — looks up a source whose Alias matches the qualifier, then the column on that source's Table. Unlike ResolveColumn, a qualifier-matched source is unambiguous; if the qualifier doesn't match any source in any enclosing scope, returns SourceNotFoundError.

func (*Scope) Sources

func (s *Scope) Sources() []ScopeSource

Sources returns the FROM-clause sources at this scope level (defensive copy, does NOT include parent sources).

type ScopeSource

type ScopeSource struct {
	// Table is the resolved schema-level table.
	Table Table
	// Alias is the name used to reference this source in the
	// enclosing query (column qualifier). For `FROM t AS x` → Alias
	// is `x`; for `FROM t` with no alias → Alias is `t`.
	Alias Identifier
	// CorrelationName is the identifier the analyzer uses to tie
	// this source back to a Quantifier when building
	// QuantifiedObjectValue / FieldValue trees that reference it.
	// Stored as a string so the semantic package doesn't take a
	// dependency on cascades/values/CorrelationIdentifier — callers wrap
	// this into a cascades.values.CorrelationIdentifier themselves.
	CorrelationName string
	// Shadowing marks a source whose columns SHADOW same-named columns of
	// non-shadowing sources at this scope level (instead of colliding into
	// an ambiguity error). A lateral array unnest (`FROM t, t.arr AS x`)
	// uses this: its AS/AT binding shadows a same-named real column of `t`
	// — Java's generateCorrelatedFieldAccess binding wins over the outer
	// (RFC-142). When ≥1 shadowing source matches a bare column, the
	// shadowing match is taken and the non-shadowing matches are ignored;
	// two shadowing matches are still ambiguous.
	Shadowing bool
}

ScopeSource is one FROM-clause entry: a resolved Table plus the alias it's visible under. Alias is always non-zero — when the user doesn't write AS, the Table's own name fills in.

type SourceNotFoundError

type SourceNotFoundError struct {
	Alias     Identifier
	Available []Identifier
}

SourceNotFoundError is returned when a qualifier doesn't match any FROM-clause alias in the scope chain. Carries the list of available aliases (inner-first) so callers can render a "did you mean?" suggestion.

func (*SourceNotFoundError) Error

func (e *SourceNotFoundError) Error() string

type StaticTable

type StaticTable struct {
	TableName    QualifiedName
	TableColumns []Column
	TableIndexes []string
}

StaticTable is a test-friendly Table impl backing InMemoryCatalog. Production code should implement Table directly (bridging to RecordType) rather than use this value-type.

func (*StaticTable) Columns

func (t *StaticTable) Columns() []Column

Columns implements Table; returns a defensive copy so callers can't mutate the backing slice.

func (*StaticTable) Indexes

func (t *StaticTable) Indexes() []string

Indexes implements Table.

func (*StaticTable) LookupColumn

func (t *StaticTable) LookupColumn(id Identifier) (Column, bool)

LookupColumn implements Table — case-insensitive match on Identifier.Name.

func (*StaticTable) Name

func (t *StaticTable) Name() QualifiedName

Name implements Table.

type Table

type Table interface {
	// Name returns the qualified table name.
	Name() QualifiedName

	// Columns returns the table's column definitions in declared
	// order. Empty slice if the table has no columns (a valid state
	// for views / CTEs). Never nil.
	Columns() []Column

	// LookupColumn returns a Column by identifier, matching
	// case-insensitively under SQL rules (the Identifier's
	// normalized form). Returns (Column{}, false) if no match.
	LookupColumn(id Identifier) (Column, bool)

	// Indexes returns the index names defined on this table. The
	// seed returns just names; richer IndexInfo follows once
	// index-pushdown rules need per-index metadata.
	Indexes() []string
}

Table is the analyzer's view of a single SQL table. Minimal for the seed — Name + Columns + Indexes. Richer methods (PK shape, fields-of-interest, RecordType bridging) land as the analyzer grows.

type TableNotFoundError

type TableNotFoundError struct {
	Name QualifiedName
}

TableNotFoundError is returned when ResolveTable can't find a table. Carries the qualified name the caller requested; follows the error-type pattern from CLAUDE.md (Java exception = Go error struct).

func (*TableNotFoundError) Error

func (e *TableNotFoundError) Error() string

type UnsupportedFromShapeError

type UnsupportedFromShapeError struct {
	Shape string
}

UnsupportedFromShapeError signals a FROM-clause shape the seed analyzer doesn't handle yet. Carried up so callers can fall back to the existing logical-builder path rather than erroring out at the SQL level.

func (*UnsupportedFromShapeError) Error

func (e *UnsupportedFromShapeError) Error() string

Directories

Path Synopsis
Package rlcatalog adapts the Record Layer's `RecordMetaData` into the `semantic.Catalog` interface.
Package rlcatalog adapts the Record Layer's `RecordMetaData` into the `semantic.Catalog` interface.

Jump to

Keyboard shortcuts

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