Files
upstream-mirror 0f4df23290
Some checks failed
kotlin / test (push) Has been skipped
python / test (push) Has been skipped
typescript / test (push) Has been skipped
go / build darwin/amd64 (push) Has been cancelled
go / build linux/amd64 (push) Has been cancelled
go / build windows/amd64 (push) Has been cancelled
go / build darwin/arm64 (push) Has been cancelled
go / build linux/arm64 (push) Has been cancelled
go / build windows/arm64 (push) Has been cancelled
go / test (push) Has been cancelled
go / vuln_check (push) Has been cancelled
snapshot of https://github.com/sqlc-dev/sqlc.git (main, 2026-09-16; blobs > 131072B omitted)
2026-09-16 02:17:34 +05:00

115 lines
3.4 KiB
Go

package preprocess
import (
"github.com/sqlc-dev/sqlc/internal/config"
)
// Style is the native placeholder syntax a dialect uses for bind parameters.
type Style int
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
)
// 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.
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
}
var dialects = map[config.Engine]Dialect{
config.EnginePostgreSQL: {
Style: StyleDollar,
AtSign: true,
DollarQuote: true,
DollarNumber: true,
NestedBlockComment: true,
FoldIdentifier: true,
},
config.EngineMySQL: {
Style: StyleQuestion,
Question: true,
Backtick: true,
HashComment: true,
DoubleQuoteString: true,
Backslash: true,
FoldIdentifier: true,
},
config.EngineSQLite: {
Style: StyleOrdinal,
AtSign: true,
Question: true,
Backtick: true,
Backslash: true,
},
// ClickHouse binds with an unnumbered ?, like MySQL, and its identifiers
// keep their case.
config.EngineClickHouse: {
Style: StyleQuestion,
Question: true,
Backtick: true,
Backslash: true,
},
}
// 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.
func DialectFor(engine config.Engine) (Dialect, bool) {
d, ok := dialects[engine]
return d, ok
}
// hasNamedSupport reports whether repeated uses of the same parameter name can
// share a single placeholder. MySQL sends an argument per "?", so every
// occurrence needs its own number.
func (d Dialect) hasNamedSupport() bool {
return d.Style != StyleQuestion
}