You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.6 KiB
105 lines
2.6 KiB
// Copyright 2018 Huan Du. All rights reserved. |
|
// Licensed under the MIT license that can be found in the LICENSE file. |
|
|
|
package sqlbuilder |
|
|
|
import ( |
|
"fmt" |
|
) |
|
|
|
// Builder is a general SQL builder. |
|
// It's used by Args to create nested SQL like the `IN` expression in |
|
// `SELECT * FROM t1 WHERE id IN (SELECT id FROM t2)`. |
|
type Builder interface { |
|
Build() (sql string, args []interface{}) |
|
BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{}) |
|
} |
|
|
|
type compiledBuilder struct { |
|
args *Args |
|
format string |
|
} |
|
|
|
func (cb *compiledBuilder) Build() (sql string, args []interface{}) { |
|
return cb.args.Compile(cb.format) |
|
} |
|
|
|
func (cb *compiledBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{}) { |
|
return cb.args.CompileWithFlavor(cb.format, flavor, initialArg...) |
|
} |
|
|
|
type flavoredBuilder struct { |
|
builder Builder |
|
flavor Flavor |
|
} |
|
|
|
func (fb *flavoredBuilder) Build() (sql string, args []interface{}) { |
|
return fb.builder.BuildWithFlavor(fb.flavor) |
|
} |
|
|
|
func (fb *flavoredBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{}) { |
|
return fb.builder.BuildWithFlavor(flavor, initialArg...) |
|
} |
|
|
|
// WithFlavor creates a new Builder based on builder with a default flavor. |
|
func WithFlavor(builder Builder, flavor Flavor) Builder { |
|
return &flavoredBuilder{ |
|
builder: builder, |
|
flavor: flavor, |
|
} |
|
} |
|
|
|
// Buildf creates a Builder from a format string using `fmt.Sprintf`-like syntax. |
|
// As all arguments will be converted to a string internally, e.g. "$0", |
|
// only `%v` and `%s` are valid. |
|
func Buildf(format string, arg ...interface{}) Builder { |
|
args := &Args{ |
|
Flavor: DefaultFlavor, |
|
} |
|
vars := make([]interface{}, 0, len(arg)) |
|
|
|
for _, a := range arg { |
|
vars = append(vars, args.Add(a)) |
|
} |
|
|
|
return &compiledBuilder{ |
|
args: args, |
|
format: fmt.Sprintf(Escape(format), vars...), |
|
} |
|
} |
|
|
|
// Build creates a Builder from a format string. |
|
// The format string uses special syntax to represent arguments. |
|
// See doc in `Args#Compile` for syntax details. |
|
func Build(format string, arg ...interface{}) Builder { |
|
args := &Args{ |
|
Flavor: DefaultFlavor, |
|
} |
|
|
|
for _, a := range arg { |
|
args.Add(a) |
|
} |
|
|
|
return &compiledBuilder{ |
|
args: args, |
|
format: format, |
|
} |
|
} |
|
|
|
// BuildNamed creates a Builder from a format string. |
|
// The format string uses `${key}` to refer the value of named by key. |
|
func BuildNamed(format string, named map[string]interface{}) Builder { |
|
args := &Args{ |
|
Flavor: DefaultFlavor, |
|
onlyNamed: true, |
|
} |
|
|
|
for n, v := range named { |
|
args.Add(Named(n, v)) |
|
} |
|
|
|
return &compiledBuilder{ |
|
args: args, |
|
format: format, |
|
} |
|
}
|
|
|