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
115 lines
3.4 KiB
Go
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
|
|
}
|