preprocess

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Sep 14, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package preprocess rewrites sqlc's query syntax into native SQL before any engine parser sees a query.

sqlc.arg(), sqlc.narg(), sqlc.slice(), sqlc.embed() and @name are sqlc syntax, not SQL. Historically they survived all the way through each engine's parser and were replaced by walking the resulting AST, which meant every engine had to round-trip a schema-qualified function call it did not understand. This package removes that requirement: it scans the query text with a dialect-parameterized lexer, replaces each construct with the engine's native placeholder, and records what it replaced. Engines then only ever see valid SQL.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Dialect

type Dialect struct {
	// Style is the native placeholder syntax used for rewritten parameters.
	Style Style

	// AtSign reports whether a bare "@name" is sqlc named-parameter syntax.
	// It is false for MySQL, where "@name" is a user variable.
	AtSign bool

	// DollarQuote reports whether $tag$ ... $tag$ string literals are valid.
	DollarQuote bool

	// DollarNumber reports whether $1 is a bind parameter.
	DollarNumber bool

	// Question reports whether ? is a bind parameter.
	Question bool

	// Backtick reports whether `ident` is a quoted identifier.
	Backtick bool

	// HashComment reports whether # starts a line comment.
	HashComment bool

	// DoubleQuoteString reports whether "..." is a string literal rather than
	// a quoted identifier. MySQL treats it as a string unless ANSI_QUOTES is
	// enabled.
	DoubleQuoteString bool

	// NestedBlockComment reports whether /* ... /* ... */ ... */ nests.
	NestedBlockComment bool

	// Backslash reports whether a backslash escapes the next character inside
	// a string literal.
	Backslash bool

	// FoldIdentifier reports whether the dialect lowercases unquoted
	// identifiers. It decides the case of a parameter named by a bare
	// reference, e.g. sqlc.arg(FooBar).
	FoldIdentifier bool
}

Dialect describes the lexical rules the preprocessor needs to walk a query without parsing it: how the dialect quotes strings and identifiers, how it writes comments and which placeholder syntax it accepts.

The preprocessor never interprets SQL. It only needs to know enough to skip the regions of a query where sqlc syntax must not be rewritten.

func DialectFor

func DialectFor(engine config.Engine) (Dialect, bool)

DialectFor returns the lexical rules for an engine, and whether the engine is preprocessed at all. GoogleSQL is not: it handles its own parameter syntax, so its queries reach the parser unchanged.

type Embed

type Embed struct {
	Table *ast.TableName

	// Location is the offset of the rewritten "table.*" in the preprocessed
	// text. The compiler uses it to tell a rewritten star reference apart from
	// one the user wrote.
	Location int
	// contains filtered or unexported fields
}

Embed is a rewritten sqlc.embed(table) call.

func (Embed) Orig

func (e Embed) Orig() string

Orig returns the sqlc syntax this embed was rewritten from.

type EmbedSet

type EmbedSet []*Embed

EmbedSet is the set of embeds in a single statement.

func (EmbedSet) Find

func (es EmbedSet) Find(locations ...int) (*Embed, bool)

Find returns the embed recorded at any of the given locations. Engines do not all populate the same location fields, so callers pass every location that could identify the node.

type Result

type Result struct {
	// Text is the rewritten SQL. It has the same number of statements and the
	// same line structure as the input.
	Text string
	// contains filtered or unexported fields
}

Result is the outcome of preprocessing a SQL file.

func Dialected

func Dialected(d Dialect, src string) *Result

Dialected rewrites src using an explicit dialect.

func File

func File(engine config.Engine, src string) *Result

File rewrites every sqlc construct in src to native SQL for the given engine.

An engine that is not preprocessed — GoogleSQL, which handles its own parameter syntax — gets the source back unchanged, with an empty side table. sqlc.arg() and friends are not rewritten for it, so they reach the parser as the function calls they look like.

func (*Result) Origin

func (r *Result) Origin(location int) int

Origin maps an offset in the rewritten text back to the offset in the original source, so errors can be reported against what the user wrote.

func (*Result) Statement

func (r *Result) Statement(location int) *Statement

Statement returns the preprocessing results for the statement covering the given offset in the rewritten text. It never returns nil.

func (*Result) Statements

func (r *Result) Statements() []*Statement

Statements returns every statement in the rewritten text, in source order.

type Statement

type Statement struct {
	// Start and End delimit the statement in the rewritten text.
	Start, End int

	// Params maps each placeholder number to its sqlc metadata.
	Params *named.ParamSet

	// Embeds records the sqlc.embed() calls that were rewritten to "table.*".
	Embeds EmbedSet

	// Slices holds the offset, in the rewritten text, of every placeholder that
	// came from sqlc.slice(), mapped to the parameter name.
	Slices map[int]string

	// Numbers maps the offset of every placeholder in the rewritten text to the
	// number assigned to it. Engines number bind parameters in whatever order
	// they happen to convert the AST, so the compiler uses this to restore
	// source order.
	Numbers map[int]int

	// Dollar reports whether the statement's own placeholders are numbered.
	Dollar bool

	// ParamErr is set when the placeholders the user wrote are inconsistent:
	// numbered and unnumbered styles mixed, or a gap in the numbering.
	ParamErr error

	// Err is a validation error found while rewriting. The statement text is
	// left untouched when this is set, so the engine still sees the original
	// query and the error can be reported against it.
	Err error
}

Statement holds everything the preprocessor learned about a single statement.

type Style

type Style int

Style is the native placeholder syntax a dialect uses for bind parameters.

const (
	// StyleDollar numbers parameters as $1, $2, ... (PostgreSQL)
	StyleDollar Style = iota
	// StyleQuestion uses an unnumbered ? for every parameter (MySQL)
	StyleQuestion
	// StyleOrdinal numbers parameters as ?1, ?2, ... (SQLite)
	StyleOrdinal
)

Jump to

Keyboard shortcuts

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