Add quote dialects
This commit is contained in:
parent
817189fbfd
commit
9e6a3d5ee3
9 changed files with 109 additions and 9 deletions
|
@ -123,3 +123,18 @@ func (m *MockDriver) Open() error { return nil }
|
||||||
|
|
||||||
// Close mimics a database close call
|
// Close mimics a database close call
|
||||||
func (m *MockDriver) Close() {}
|
func (m *MockDriver) Close() {}
|
||||||
|
|
||||||
|
// RightQuote is the quoting character for the right side of the identifier
|
||||||
|
func (m *MockDriver) RightQuote() string {
|
||||||
|
return "`"
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeftQuote is the quoting character for the left side of the identifier
|
||||||
|
func (m *MockDriver) LeftQuote() string {
|
||||||
|
return `"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexPlaceholders returns true to indicate fake support of indexed placeholders
|
||||||
|
func (m *MockDriver) IndexPlaceholders() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -318,3 +318,18 @@ func mySQLIsValidated(typ string) bool {
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RightQuote is the quoting character for the right side of the identifier
|
||||||
|
func (m *MySQLDriver) RightQuote() string {
|
||||||
|
return "`"
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeftQuote is the quoting character for the left side of the identifier
|
||||||
|
func (m *MySQLDriver) LeftQuote() string {
|
||||||
|
return "`"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexPlaceholders returns false to indicate MySQL doesnt support indexed placeholders
|
||||||
|
func (m *MySQLDriver) IndexPlaceholders() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -340,3 +340,18 @@ func psqlIsValidated(typ string) bool {
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RightQuote is the quoting character for the right side of the identifier
|
||||||
|
func (p *PostgresDriver) RightQuote() string {
|
||||||
|
return `"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeftQuote is the quoting character for the left side of the identifier
|
||||||
|
func (p *PostgresDriver) LeftQuote() string {
|
||||||
|
return `"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexPlaceholders returns true to indicate PSQL supports indexed placeholders
|
||||||
|
func (p *PostgresDriver) IndexPlaceholders() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,13 @@ type Interface interface {
|
||||||
Open() error
|
Open() error
|
||||||
// Close the database connection
|
// Close the database connection
|
||||||
Close()
|
Close()
|
||||||
|
|
||||||
|
// Dialect helpers, these provide the values that will go into
|
||||||
|
// a boil.Dialect, so the query builder knows how to support
|
||||||
|
// your database driver properly.
|
||||||
|
LeftQuote() string
|
||||||
|
RightQuote() string
|
||||||
|
IndexPlaceholders() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tables returns the metadata for all tables, minus the tables
|
// Tables returns the metadata for all tables, minus the tables
|
||||||
|
|
|
@ -19,6 +19,7 @@ const (
|
||||||
// Query holds the state for the built up query
|
// Query holds the state for the built up query
|
||||||
type Query struct {
|
type Query struct {
|
||||||
executor Executor
|
executor Executor
|
||||||
|
dialect *Dialect
|
||||||
plainSQL plainSQL
|
plainSQL plainSQL
|
||||||
load []string
|
load []string
|
||||||
delete bool
|
delete bool
|
||||||
|
@ -37,6 +38,20 @@ type Query struct {
|
||||||
forlock string
|
forlock string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dialect holds values that direct the query builder
|
||||||
|
// how to build compatible queries for each database.
|
||||||
|
// Each database driver needs to implement functions
|
||||||
|
// that provide these values.
|
||||||
|
type Dialect struct {
|
||||||
|
// The left quote character for SQL identifiers
|
||||||
|
LQ string
|
||||||
|
// The right quote character for SQL identifiers
|
||||||
|
RQ string
|
||||||
|
// Bool flag indicating whether indexed
|
||||||
|
// placeholders ($1) are used, or ? placeholders.
|
||||||
|
IndexPlaceholders bool
|
||||||
|
}
|
||||||
|
|
||||||
type where struct {
|
type where struct {
|
||||||
clause string
|
clause string
|
||||||
orSeparator bool
|
orSeparator bool
|
||||||
|
@ -121,6 +136,11 @@ func GetExecutor(q *Query) Executor {
|
||||||
return q.executor
|
return q.executor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDialect on the query.
|
||||||
|
func SetDialect(q *Query, dialect *Dialect) {
|
||||||
|
q.dialect = dialect
|
||||||
|
}
|
||||||
|
|
||||||
// SetSQL on the query.
|
// SetSQL on the query.
|
||||||
func SetSQL(q *Query, sql string, args ...interface{}) {
|
func SetSQL(q *Query, sql string, args ...interface{}) {
|
||||||
q.plainSQL = plainSQL{sql: sql, args: args}
|
q.plainSQL = plainSQL{sql: sql, args: args}
|
||||||
|
|
|
@ -34,6 +34,7 @@ type State struct {
|
||||||
|
|
||||||
Driver bdb.Interface
|
Driver bdb.Interface
|
||||||
Tables []bdb.Table
|
Tables []bdb.Table
|
||||||
|
Dialect boil.Dialect
|
||||||
|
|
||||||
Templates *templateList
|
Templates *templateList
|
||||||
TestTemplates *templateList
|
TestTemplates *templateList
|
||||||
|
@ -102,6 +103,7 @@ func (s *State) Run(includeTests bool) error {
|
||||||
PkgName: s.Config.PkgName,
|
PkgName: s.Config.PkgName,
|
||||||
NoHooks: s.Config.NoHooks,
|
NoHooks: s.Config.NoHooks,
|
||||||
NoAutoTimestamps: s.Config.NoAutoTimestamps,
|
NoAutoTimestamps: s.Config.NoAutoTimestamps,
|
||||||
|
Dialect: s.Dialect,
|
||||||
|
|
||||||
StringFuncs: templateStringMappers,
|
StringFuncs: templateStringMappers,
|
||||||
}
|
}
|
||||||
|
@ -135,6 +137,7 @@ func (s *State) Run(includeTests bool) error {
|
||||||
NoHooks: s.Config.NoHooks,
|
NoHooks: s.Config.NoHooks,
|
||||||
NoAutoTimestamps: s.Config.NoAutoTimestamps,
|
NoAutoTimestamps: s.Config.NoAutoTimestamps,
|
||||||
Tags: s.Config.Tags,
|
Tags: s.Config.Tags,
|
||||||
|
Dialect: s.Dialect,
|
||||||
|
|
||||||
StringFuncs: templateStringMappers,
|
StringFuncs: templateStringMappers,
|
||||||
}
|
}
|
||||||
|
@ -246,6 +249,10 @@ func (s *State) initDriver(driverName string) error {
|
||||||
return errors.New("An invalid driver name was provided")
|
return errors.New("An invalid driver name was provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.Dialect.LQ = s.Driver.LeftQuote()
|
||||||
|
s.Dialect.RQ = s.Driver.RightQuote()
|
||||||
|
s.Dialect.IndexPlaceholders = s.Driver.IndexPlaceholders()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,18 @@ func SchemaTable(driver string, schema string, table string) string {
|
||||||
return fmt.Sprintf(`"%s"`, table)
|
return fmt.Sprintf(`"%s"`, table)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WrapQuote wraps a quote character in quotes.
|
||||||
|
func WrapQuote(s string) string {
|
||||||
|
if s == `"` {
|
||||||
|
return "`\"`"
|
||||||
|
}
|
||||||
|
if s == "`" {
|
||||||
|
return "\"`\""
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("`%s`", s)
|
||||||
|
}
|
||||||
|
|
||||||
// IdentQuote attempts to quote simple identifiers in SQL tatements
|
// IdentQuote attempts to quote simple identifiers in SQL tatements
|
||||||
func IdentQuote(s string) string {
|
func IdentQuote(s string) string {
|
||||||
if strings.ToLower(s) == "null" {
|
if strings.ToLower(s) == "null" {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/vattle/sqlboiler/bdb"
|
"github.com/vattle/sqlboiler/bdb"
|
||||||
|
"github.com/vattle/sqlboiler/boil"
|
||||||
"github.com/vattle/sqlboiler/strmangle"
|
"github.com/vattle/sqlboiler/strmangle"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,8 +23,8 @@ type templateData struct {
|
||||||
NoHooks bool
|
NoHooks bool
|
||||||
NoAutoTimestamps bool
|
NoAutoTimestamps bool
|
||||||
Tags []string
|
Tags []string
|
||||||
|
|
||||||
StringFuncs map[string]func(string) string
|
StringFuncs map[string]func(string) string
|
||||||
|
Dialect boil.Dialect
|
||||||
}
|
}
|
||||||
|
|
||||||
type templateList struct {
|
type templateList struct {
|
||||||
|
@ -116,6 +117,7 @@ var templateFunctions = template.FuncMap{
|
||||||
// String ops
|
// String ops
|
||||||
"quoteWrap": func(a string) string { return fmt.Sprintf(`"%s"`, a) },
|
"quoteWrap": func(a string) string { return fmt.Sprintf(`"%s"`, a) },
|
||||||
"id": strmangle.Identifier,
|
"id": strmangle.Identifier,
|
||||||
|
"wrapQuote": strmangle.WrapQuote,
|
||||||
|
|
||||||
// Pluralization
|
// Pluralization
|
||||||
"singular": strmangle.Singular,
|
"singular": strmangle.Singular,
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
var dialect boil.Dialect = boil.Dialect{
|
||||||
|
LQ: {{wrapQuote .Dialect.LQ}},
|
||||||
|
RQ: {{wrapQuote .Dialect.RQ}},
|
||||||
|
IndexPlaceholders: {{.Dialect.IndexPlaceholders}},
|
||||||
|
}
|
||||||
|
|
||||||
// NewQueryG initializes a new Query using the passed in QueryMods
|
// NewQueryG initializes a new Query using the passed in QueryMods
|
||||||
func NewQueryG(mods ...qm.QueryMod) *boil.Query {
|
func NewQueryG(mods ...qm.QueryMod) *boil.Query {
|
||||||
return NewQuery(boil.GetDB(), mods...)
|
return NewQuery(boil.GetDB(), mods...)
|
||||||
|
@ -7,6 +13,7 @@ func NewQueryG(mods ...qm.QueryMod) *boil.Query {
|
||||||
func NewQuery(exec boil.Executor, mods ...qm.QueryMod) *boil.Query {
|
func NewQuery(exec boil.Executor, mods ...qm.QueryMod) *boil.Query {
|
||||||
q := &boil.Query{}
|
q := &boil.Query{}
|
||||||
boil.SetExecutor(q, exec)
|
boil.SetExecutor(q, exec)
|
||||||
|
boil.SetDialect(q, &dialect)
|
||||||
qm.Apply(q, mods...)
|
qm.Apply(q, mods...)
|
||||||
|
|
||||||
return q
|
return q
|
||||||
|
|
Loading…
Reference in a new issue