Help us shape the future of Go! Take the 2026 Go Developer Survey

parser

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package parser provides multi-dialect SQL parsing, schema model types, and relationship detection for SQLGen code generation.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ApplyConstraintToColumns

func ApplyConstraintToColumns(table *Table, c Constraint)

ApplyConstraintToColumns updates column flags from a single constraint.

func ApplyTableConstraints

func ApplyTableConstraints(table *Table)

ApplyTableConstraints propagates table-level constraint metadata to columns.

func CheckTableDropRefs

func CheckTableDropRefs(tables []Table, schema, name string) error

CheckTableDropRefs checks whether any table in the schema has a foreign key reference to the table identified by (schema, name). Returns an error describing the first dangling reference found, or nil if the drop is safe.

func CheckTypeDropRefs

func CheckTypeDropRefs(tables []Table, schema, name string) error

CheckTypeDropRefs checks whether any column in the schema uses the given type name. Returns an error if a reference is found, or nil if the drop is safe.

func DetectRelationships

func DetectRelationships(schema *Schema)

DetectRelationships detects relationships from foreign key constraints in the schema. It identifies Many-to-Many (junction tables with exactly 2 FKs in a composite PK/UNIQUE), One-to-One (FK column with UNIQUE), and One-to-Many (FK column without UNIQUE, the default fallback). Detected relationships are appended to schema.Relationships.

func DetectSoftDelete

func DetectSoftDelete(table *Table, columns []string) (column string, strategy string, err error)

DetectSoftDelete checks the table's columns against the given column names in priority order. The first matching column determines the soft delete column. The strategy is inferred from the column's SQL type: "timestamp" for timestamp/timestamptz/datetime, "bool" for bool/boolean, "integer" for int/integer/smallint/tinyint. Returns empty strings if no column matches. Returns an error if a matching column has an unsupported type.

func DetectUpdateColumns

func DetectUpdateColumns(table *Table, names []string) []string

DetectUpdateColumns finds columns in the table that match the given column names. Returns matching column names in the order they appear in the names list.

func DiscoverFiles

func DiscoverFiles(paths []string) ([]string, error)

DiscoverFiles resolves a list of paths into an ordered list of SQL files suitable for parsing. Each path may be a file or a directory. Directories are expanded to their contained .sql files in lexicographic order. Down-migration files (*.down.sql, *_down.sql) are automatically excluded. Paths are processed in the order specified; ordering within a directory is lexicographic.

func IsAggregateFunction

func IsAggregateFunction(funcName string) bool

IsAggregateFunction returns true if funcName (uppercase) is a known SQL aggregate function. Dialect parsers use this when classifying SELECT expressions.

func MoveTableReferences

func MoveTableReferences(tables []Table, name, oldSchema, newSchema string)

MoveTableReferences repoints every foreign key that references the table (oldSchema, name) at (newSchema, name), so an ALTER TABLE … SET SCHEMA keeps the keys that reference the table resolvable.

func ParseFiles

func ParseFiles(p Parser, files []string) error

ParseFiles parses multiple SQL files sequentially, applying each file's statements to the parser's accumulating schema. Files are processed in the order provided (use DiscoverFiles to resolve paths).

Each file's DDL is applied as a natural SQL migration: ALTER TABLE extends or modifies tables, DROP TABLE removes tables, and so on. Duplicate CREATE statements (table, enum, composite type, domain type) are validation errors — each schema element must be defined exactly once.

func RecomputeColumnUnique

func RecomputeColumnUnique(table *Table, colName string)

RecomputeColumnUnique re-derives the column's Unique flag from the current table state — the column's InlineUnique flag plus any unconditional, single-column UNIQUE constraint remaining in table.Constraints. Callers must remove the dropped constraint from table.Constraints before invoking this helper; partial UNIQUE constraints (Where != "") are ignored because they cannot keep the column unconditionally unique.

func RenameColumn

func RenameColumn(table *Table, oldName, newName string) error

RenameColumn renames a column in the table from oldName to newName.

func RenameColumnReferences

func RenameColumnReferences(tables []Table, schema, table, oldName, newName string)

RenameColumnReferences rewrites every reference to column oldName of the table (schema, table) to newName: the column lists of that table's own constraints (PRIMARY KEY, UNIQUE, FOREIGN KEY, INDEX, CHECK), and every foreign key, on any table, that references the column. The database does the same on RENAME COLUMN; left on the old name, a composite key no longer matches its columns, so an M2M junction degrades to O2M and an upsert conflict target names a column that no longer exists. Call it after RenameColumn has renamed the column itself.

func RenameTableReferences

func RenameTableReferences(tables []Table, schema, oldName, newName string)

RenameTableReferences repoints every foreign key that references the table (schema, oldName) at (schema, newName), so a RENAME TABLE keeps the keys that reference the table resolvable.

func UnresolvedForeignKeys

func UnresolvedForeignKeys(tables []Table) []error

UnresolvedForeignKeys returns one error per foreign key whose referenced table is not in tables, sorted for deterministic output. Relationship detection builds an edge from every foreign key, and an edge whose far end was never parsed is dropped without a trace, so the caller reports these instead.

Types

type Attribute

type Attribute struct {
	Name string
	Type string
}

Attribute represents a named field with a type, used in composite types.

type Column

type Column struct {
	Name       string
	Type       string
	Nullable   bool
	PrimaryKey bool
	Unique     bool
	// InlineUnique reports whether the column carries a UNIQUE constraint
	// declared inline at column definition time (e.g. `email text UNIQUE`),
	// as opposed to a table-level UNIQUE constraint that lives in
	// Table.Constraints. The DDL parsers set this alongside Unique at column
	// parse time; RecomputeColumnUnique consults it when re-deriving the
	// effective Unique flag after a table-level UNIQUE is dropped, so an
	// inline declaration still in force at the DB level is not silently
	// stripped from the column.
	InlineUnique     bool
	Default          string
	FKReference      *FKReference
	AutoIncrement    bool
	Comment          string
	GeneratedExpr    string // Generated column expression (SQLite 3.31+)
	GeneratedStorage string // "VIRTUAL" or "STORED" (default: "VIRTUAL")
	// GoTypeLiteral is set for view columns whose type was resolved to a Go type
	// by @type annotation or aggregate inference. When non-empty, the code generator
	// uses this directly instead of running the SQL-to-Go resolver.
	GoTypeLiteral string
	// GoTypeImport is the import path for an external Go type (from @type annotation).
	GoTypeImport string
	// Aggregate names the SQL aggregate function (uppercase, e.g. "SUM") when this
	// view column is an aggregate whose Go type flows through the SQL-to-Go
	// resolver rather than a Go-type literal. Empty for table columns and for
	// aggregates resolved to a literal. The generator consults it so the
	// resolver can model dialect-specific result widening (e.g. SUM(integer) →
	// bigint in PostgreSQL); see gotype.Resolver.ResolveAggregate.
	Aggregate string
}

Column represents a column in a table.

func ColumnByName

func ColumnByName(table *Table, name string) *Column

ColumnByName returns a pointer to the named column in the table, or nil.

type CompositeType

type CompositeType struct {
	Name       string
	Schema     string
	Attributes []Attribute
	Comment    string
}

CompositeType represents a named struct-like type with attributes.

type Constraint

type Constraint struct {
	Name             string
	Type             ConstraintType
	Columns          []string
	ReferenceTable   string
	ReferenceSchema  string
	ReferenceColumns []string
	CheckExpression  string
	Method           string
	Where            string
}

Constraint represents a table-level constraint.

Method and Where apply only to index-shaped constraints (Index and Unique). Method holds the access-method name when the DDL declares one — "btree", "gin", "gist", "hash", and so on — and is empty otherwise; consumers that need a default treat the empty string as "btree" (PostgreSQL's default). Where holds the predicate text of a partial index (PostgreSQL / SQLite) without the leading WHERE keyword; MySQL does not support partial indexes so Where stays empty for that dialect.

type ConstraintType

type ConstraintType int

ConstraintType represents the kind of a table constraint.

const (
	// PrimaryKey is a PRIMARY KEY constraint.
	PrimaryKey ConstraintType = iota + 1
	// ForeignKey is a FOREIGN KEY constraint.
	ForeignKey
	// Unique is a UNIQUE constraint.
	Unique
	// Check is a CHECK constraint.
	Check
	// Index is an INDEX constraint.
	Index
)

func (ConstraintType) String

func (ct ConstraintType) String() string

String returns the string representation of the constraint type.

type DomainType

type DomainType struct {
	Name        string
	Schema      string
	BaseType    string
	Constraints []Constraint
	Comment     string
}

DomainType represents a named alias type with optional constraints.

type Enum

type Enum struct {
	Name    string
	Schema  string
	Values  []string
	Comment string
}

Enum represents a named enum type with ordered values.

type FKReference

type FKReference struct {
	Table  string
	Schema string
	Column string
	// Synthetic marks a reference invented by a config-declared relationship
	// (gen.applyConfigDeclaredFKs) rather than read from a SQL REFERENCES
	// clause. The database does not enforce it, and it may name a column that
	// holds no foreign key at all, so any consumer deciding something about
	// the *referential contract* — as opposed to how a column is filtered or
	// typed — must exclude it. Column is empty for synthetic references, but
	// that is not a usable test: the MySQL and SQLite parsers also leave it
	// empty when a REFERENCES clause omits the referenced column list.
	Synthetic bool
}

FKReference represents a foreign key reference to another table's column.

type Parser

type Parser interface {
	// Parse parses the SQL from the given file into the internal schema model.
	// It can be called multiple times with different files; results accumulate.
	Parse(filename string, sql []byte) error

	// Schema returns the accumulated schema model.
	Schema() *Schema
}

Parser parses SQL DDL statements into a Schema model. Implementations are dialect-specific (PostgreSQL, MySQL, SQLite). A Parser is re-entrant: Parse can be called multiple times with different files, and the schema is accumulated across calls.

type Relationship

type Relationship struct {
	Name                string
	BaseName            string
	Type                RelationshipType
	Side                RelationshipSide
	SourceTable         string
	TargetTable         string
	FKColumn            string
	JunctionTable       string
	JunctionLocalFK     string
	JunctionReferenceFK string
	Filter              string
	Sort                []RelationshipSort
}

Relationship represents a detected or configured relationship between tables.

BaseName is the pre-disambiguation Name produced at emission time (DetectRelationships) — the child table for O2M, the target table for O2O, the M2M-target table for ManyToMany. When multiple FK edges connect the same (SourceTable, TargetTable) pair, Name is rewritten by disambiguateRelationshipNames to a unique form derived from the FK column (O2M / O2O) or junction table (M2M); BaseName preserves the original so `exclude_relationships` entries written against the bare table name (PRD §4.8 / §13.4) continue to match every disambiguated edge in the group.

type RelationshipSide

type RelationshipSide int

RelationshipSide identifies which end of a relationship edge this entry represents. For O2O / O2M / M2O, "parent" is the FK-holder (source of the directed edge) and "child" is the referenced side. For M2M, both peers are "parent" — the cardinality is symmetric.

const (
	// SideUnspecified is the zero value. Production emit paths
	// (DetectRelationships' addO2O / addO2M / addM2M, plus the codegen's
	// config-relationship builder) always populate Side, so consumers that
	// observe SideUnspecified are reading a hand-built fixture that
	// bypassed those builders — surface that as "no signal" rather than
	// guessing.
	SideUnspecified RelationshipSide = iota
	// SideParent marks the FK-holder end of an O2O / O2M / M2O edge, or
	// either peer of an M2M edge.
	SideParent
	// SideChild marks the referenced end of an O2O / O2M / M2O edge.
	SideChild
)

func (RelationshipSide) String

func (s RelationshipSide) String() string

String returns the string representation of the relationship side.

type RelationshipSort

type RelationshipSort struct {
	Column    string
	Direction string
}

RelationshipSort defines the ordering for loaded related entities.

type RelationshipType

type RelationshipType int

RelationshipType represents the cardinality of a relationship.

const (
	// OneToOne is a one-to-one relationship.
	OneToOne RelationshipType = iota + 1
	// OneToMany is a one-to-many relationship.
	OneToMany
	// ManyToMany is a many-to-many relationship.
	ManyToMany
)

func (RelationshipType) String

func (rt RelationshipType) String() string

String returns the string representation of the relationship type.

type Schema

type Schema struct {
	Tables         []Table
	Enums          []Enum
	Sets           []Set
	CompositeTypes []CompositeType
	DomainTypes    []DomainType
	Views          []View
	Relationships  []Relationship
	Warnings       []string
}

Schema is the top-level container for a parsed SQL schema.

func (*Schema) Sort

func (s *Schema) Sort()

Sort sorts all elements in the schema deterministically. Tables, enums, composite types, domain types, and views sort by schema then name. Columns within tables maintain their insertion order (ordinal position). Relationships sort by name.

type Set

type Set struct {
	Name    string
	Schema  string
	Values  []string
	Comment string
}

Set represents a MySQL SET type with ordered allowed values. Unlike enums, SET columns store zero or more values as a comma-separated string.

type Table

type Table struct {
	Name         string
	Schema       string
	Columns      []Column
	Constraints  []Constraint
	Comment      string
	Strict       bool // SQLite STRICT table modifier (3.37+)
	WithoutRowID bool // SQLite WITHOUT ROWID table modifier (3.8.2+)
}

Table represents a parsed SQL table.

type View

type View struct {
	Name    string
	Schema  string
	SQL     string
	Columns []Column

	// Materialized reports whether this is a PostgreSQL MATERIALIZED VIEW.
	// When true, the generator emits Refresh methods and the FROM clause still
	// targets the relation by name (reads are identical to a regular view).
	Materialized bool

	// ConcurrentlyRefreshable reports whether the matview carries at least one
	// UNIQUE index covering all rows — the prerequisite for
	// REFRESH MATERIALIZED VIEW CONCURRENTLY. Set during introspection; for
	// annotation-file matviews it follows from an @pk directive.
	// Always false for regular views (Materialized == false implies
	// ConcurrentlyRefreshable == false).
	ConcurrentlyRefreshable bool
}

View represents a SQL view (regular or materialized) with its source SQL and inferred columns.

func BuildView

func BuildView(parsed ViewSQL, rawSQL string, annotations *ViewAnnotations, tables []Table) (*View, error)

BuildView constructs a View from pre-parsed SQL metadata, annotations, and known tables. The parsed field is produced by a dialect-specific parser's ParseViewSQL method; annotations come from ParseViewAnnotations.

func MergeViewAnnotations

func MergeViewAnnotations(introspected []View, annotated []View, annotationMap map[string]*ViewAnnotations) []View

MergeViewAnnotations merges annotation overlays onto introspected views. For each view that has a matching annotation file, annotation @pk, @type, and @nullable take precedence over introspected values.

type ViewAnnotations

type ViewAnnotations struct {
	PKColumns       []string
	TypeOverrides   map[string]ViewTypeAnnotation
	NullableColumns []string
}

ViewAnnotations holds all parsed annotations from a view annotation file.

func ParseViewAnnotations

func ParseViewAnnotations(content string) (*ViewAnnotations, error)

ParseViewAnnotations extracts @pk, @type, and @nullable directives from SQL line comments at the top of a view annotation file.

type ViewSQL

type ViewSQL struct {
	Name         string
	Schema       string
	Columns      []ViewSelectColumn
	TableAliases map[string]string

	// Materialized reports whether the statement was CREATE MATERIALIZED VIEW
	// (PostgreSQL-only; the MySQL/SQLite parsers reject the syntax).
	Materialized bool
}

ViewSQL holds the metadata extracted from a CREATE VIEW or CREATE MATERIALIZED VIEW statement by a dialect-specific parser.

type ViewSelectColumn

type ViewSelectColumn struct {
	Alias        string // output column name (alias or inferred from expression)
	SourceTable  string // table alias the column comes from (if qualified reference)
	SourceColumn string // column name in the source table
	Aggregate    string // aggregate function name (uppercase), empty if not aggregate
}

ViewSelectColumn represents a column extracted from a view's SELECT clause by a dialect-specific parser.

type ViewTypeAnnotation

type ViewTypeAnnotation struct {
	GoType     string
	ImportPath string
}

ViewTypeAnnotation holds a Go type override from an @type directive.

Directories

Path Synopsis
Package introspect provides live database schema introspection capabilities.
Package introspect provides live database schema introspection capabilities.
Package mysql provides a MySQL dialect parser using vitess/sqlparser.
Package mysql provides a MySQL dialect parser using vitess/sqlparser.
Package postgres provides a PostgreSQL dialect parser using pg_query_go.
Package postgres provides a PostgreSQL dialect parser using pg_query_go.
Package sqlite provides a SQLite dialect parser using rqlite/sql.
Package sqlite provides a SQLite dialect parser using rqlite/sql.

Jump to

Keyboard shortcuts

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