switch to more complete null package, implement nicer sql logging

This commit is contained in:
Alex Grintsvayg 2017-07-06 15:15:00 -04:00
parent ed423a3606
commit 05c7f7d06a
21 changed files with 291 additions and 85 deletions

View file

@ -170,11 +170,12 @@ func newImporter() importer {
`"time"`, `"time"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/pkg/errors"`, `"github.com/lbryio/null.go"`,
`"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/boil"`,
`"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries"`,
`"github.com/lbryio/sqlboiler/queries/qm"`, `"github.com/lbryio/sqlboiler/queries/qm"`,
`"github.com/lbryio/sqlboiler/strmangle"`, `"github.com/lbryio/sqlboiler/strmangle"`,
`"github.com/pkg/errors"`,
}, },
} }
@ -183,6 +184,10 @@ func newImporter() importer {
standard: importList{ standard: importList{
`"database/sql"`, `"database/sql"`,
`"fmt"`, `"fmt"`,
`"reflect"`,
`"strconv"`,
`"strings"`,
`"time"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/boil"`,
@ -190,6 +195,7 @@ func newImporter() importer {
`"github.com/lbryio/sqlboiler/queries/qm"`, `"github.com/lbryio/sqlboiler/queries/qm"`,
`"github.com/lbryio/sqlboiler/strmangle"`, `"github.com/lbryio/sqlboiler/strmangle"`,
`"github.com/pkg/errors"`, `"github.com/pkg/errors"`,
`"github.com/lbryio/null.go"`,
}, },
}, },
"boil_types": { "boil_types": {
@ -315,55 +321,55 @@ func newImporter() importer {
// TranslateColumnType to see the type assignments. // TranslateColumnType to see the type assignments.
imp.BasedOnType = mapImports{ imp.BasedOnType = mapImports{
"null.Float32": { "null.Float32": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Float64": { "null.Float64": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Int": { "null.Int": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Int8": { "null.Int8": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Int16": { "null.Int16": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Int32": { "null.Int32": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Int64": { "null.Int64": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Uint": { "null.Uint": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Uint8": { "null.Uint8": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Uint16": { "null.Uint16": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Uint32": { "null.Uint32": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Uint64": { "null.Uint64": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.String": { "null.String": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Bool": { "null.Bool": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Time": { "null.Time": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.JSON": { "null.JSON": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"null.Bytes": { "null.Bytes": {
thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, thirdParty: importList{`"github.com/lbryio/null.go"`},
}, },
"time.Time": { "time.Time": {
standard: importList{`"time"`}, standard: importList{`"time"`},

View file

@ -246,7 +246,7 @@ func TestCombineTypeImports(t *testing.T) {
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/boil"`,
`"gopkg.in/nullbio/null.v6"`, `"github.com/lbryio/null.go"`,
}, },
} }
@ -281,7 +281,7 @@ func TestCombineTypeImports(t *testing.T) {
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/boil"`,
`"gopkg.in/nullbio/null.v6"`, `"github.com/lbryio/null.go"`,
}, },
} }
@ -297,7 +297,7 @@ func TestCombineImports(t *testing.T) {
a := imports{ a := imports{
standard: importList{"fmt"}, standard: importList{"fmt"},
thirdParty: importList{"github.com/lbryio/sqlboiler", "gopkg.in/nullbio/null.v6"}, thirdParty: importList{"github.com/lbryio/sqlboiler", "github.com/lbryio/null.go"},
} }
b := imports{ b := imports{
standard: importList{"os"}, standard: importList{"os"},
@ -309,8 +309,8 @@ func TestCombineImports(t *testing.T) {
if c.standard[0] != "fmt" && c.standard[1] != "os" { if c.standard[0] != "fmt" && c.standard[1] != "os" {
t.Errorf("Wanted: fmt, os got: %#v", c.standard) t.Errorf("Wanted: fmt, os got: %#v", c.standard)
} }
if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "gopkg.in/nullbio/null.v6" { if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "github.com/lbryio/null.go" {
t.Errorf("Wanted: github.com/lbryio/sqlboiler, gopkg.in/nullbio/null.v6 got: %#v", c.thirdParty) t.Errorf("Wanted: github.com/lbryio/sqlboiler, github.com/lbryio/null.go got: %#v", c.thirdParty)
} }
} }

View file

@ -5,7 +5,7 @@ import (
"testing" "testing"
"time" "time"
null "gopkg.in/nullbio/null.v6" null "github.com/lbryio/null.go"
) )
type testObj struct { type testObj struct {

View file

@ -3,8 +3,15 @@ package queries
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"reflect"
"strconv"
"strings"
"time"
"github.com/lbryio/null.go"
"github.com/lbryio/sqlboiler/boil" "github.com/lbryio/sqlboiler/boil"
"github.com/go-errors/errors"
) )
// joinKind is the type of join // joinKind is the type of join
@ -105,8 +112,11 @@ func RawG(query string, args ...interface{}) *Query {
func (q *Query) Exec() (sql.Result, error) { func (q *Query) Exec() (sql.Result, error) {
qs, args := buildQuery(q) qs, args := buildQuery(q)
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, qs) qStr, err := interpolateParams(qs, args...)
fmt.Fprintln(boil.DebugWriter, args) if err != nil {
return nil, err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
return q.executor.Exec(qs, args...) return q.executor.Exec(qs, args...)
} }
@ -115,8 +125,11 @@ func (q *Query) Exec() (sql.Result, error) {
func (q *Query) QueryRow() *sql.Row { func (q *Query) QueryRow() *sql.Row {
qs, args := buildQuery(q) qs, args := buildQuery(q)
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, qs) qStr, err := interpolateParams(qs, args...)
fmt.Fprintln(boil.DebugWriter, args) if err != nil {
panic(err)
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
return q.executor.QueryRow(qs, args...) return q.executor.QueryRow(qs, args...)
} }
@ -125,8 +138,11 @@ func (q *Query) QueryRow() *sql.Row {
func (q *Query) Query() (*sql.Rows, error) { func (q *Query) Query() (*sql.Rows, error) {
qs, args := buildQuery(q) qs, args := buildQuery(q)
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, qs) qStr, err := interpolateParams(qs, args...)
fmt.Fprintln(boil.DebugWriter, args) if err != nil {
return nil, err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
return q.executor.Query(qs, args...) return q.executor.Query(qs, args...)
} }
@ -280,3 +296,69 @@ func AppendGroupBy(q *Query, clause string) {
func AppendOrderBy(q *Query, clause string) { func AppendOrderBy(q *Query, clause string) {
q.orderBy = append(q.orderBy, clause) q.orderBy = append(q.orderBy, clause)
} }
// duplicated in boil_queries.tpl
func interpolateParams(query string, args ...interface{}) (string, error) {
for i := 0; i < len(args); i++ {
field := reflect.ValueOf(args[i])
if value, ok := field.Interface().(time.Time); ok {
query = strings.Replace(query, "?", `"`+value.Format("2006-01-02 15:04:05")+`"`, 1)
} else if nullable, ok := field.Interface().(null.Nullable); ok {
if nullable.IsNull() {
query = strings.Replace(query, "?", "NULL", 1)
} else {
switch field.Type() {
case reflect.TypeOf(null.Time{}):
query = strings.Replace(query, "?", `"`+field.Interface().(null.Time).Time.Format("2006-01-02 15:04:05")+`"`, 1)
case reflect.TypeOf(null.Int{}):
query = strings.Replace(query, "?", strconv.FormatInt(int64(field.Interface().(null.Int).Int), 10), 1)
case reflect.TypeOf(null.Int8{}):
query = strings.Replace(query, "?", strconv.FormatInt(int64(field.Interface().(null.Int8).Int8), 10), 1)
case reflect.TypeOf(null.Int16{}):
query = strings.Replace(query, "?", strconv.FormatInt(int64(field.Interface().(null.Int16).Int16), 10), 1)
case reflect.TypeOf(null.Int32{}):
query = strings.Replace(query, "?", strconv.FormatInt(int64(field.Interface().(null.Int32).Int32), 10), 1)
case reflect.TypeOf(null.Int64{}):
query = strings.Replace(query, "?", strconv.FormatInt(field.Interface().(null.Int64).Int64, 10), 1)
case reflect.TypeOf(null.Uint{}):
query = strings.Replace(query, "?", strconv.FormatUint(uint64(field.Interface().(null.Uint).Uint), 10), 1)
case reflect.TypeOf(null.Uint8{}):
query = strings.Replace(query, "?", strconv.FormatUint(uint64(field.Interface().(null.Uint8).Uint8), 10), 1)
case reflect.TypeOf(null.Uint16{}):
query = strings.Replace(query, "?", strconv.FormatUint(uint64(field.Interface().(null.Uint16).Uint16), 10), 1)
case reflect.TypeOf(null.Uint32{}):
query = strings.Replace(query, "?", strconv.FormatUint(uint64(field.Interface().(null.Uint32).Uint32), 10), 1)
case reflect.TypeOf(null.Uint64{}):
query = strings.Replace(query, "?", strconv.FormatUint(field.Interface().(null.Uint64).Uint64, 10), 1)
case reflect.TypeOf(null.String{}):
query = strings.Replace(query, "?", `"`+field.Interface().(null.String).String+`"`, 1)
case reflect.TypeOf(null.Bool{}):
if field.Interface().(null.Bool).Bool {
query = strings.Replace(query, "?", "1", 1)
} else {
query = strings.Replace(query, "?", "0", 1)
}
}
}
} else {
switch field.Kind() {
case reflect.Bool:
boolString := "0"
if field.Bool() {
boolString = "1"
}
query = strings.Replace(query, "?", boolString, 1)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
query = strings.Replace(query, "?", strconv.FormatInt(field.Int(), 10), 1)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
query = strings.Replace(query, "?", strconv.FormatUint(field.Uint(), 10), 1)
case reflect.String:
query = strings.Replace(query, "?", `"`+field.String()+`"`, 1)
default:
return "", errors.New("Dont know how to interpolate type " + field.Type().String())
}
}
}
return query, nil
}

View file

@ -14,7 +14,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
null "gopkg.in/nullbio/null.v6" null "github.com/lbryio/null.go"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/satori/go.uuid" "github.com/satori/go.uuid"

View file

@ -5,7 +5,7 @@ import (
"testing" "testing"
"time" "time"
null "gopkg.in/nullbio/null.v6" null "github.com/lbryio/null.go"
) )
func TestRandomizeStruct(t *testing.T) { func TestRandomizeStruct(t *testing.T) {

View file

@ -40,7 +40,11 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
) )
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintf(boil.DebugWriter, "%s\n%v\n", query, args) qStr, err := interpolateParams(query, args...)
if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
results, err := e.Query(query, args...) results, err := e.Query(query, args...)

View file

@ -40,7 +40,11 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
) )
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintf(boil.DebugWriter, "%s\n%v\n", query, args) qStr, err := interpolateParams(query, args...)
if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
results, err := e.Query(query, args...) results, err := e.Query(query, args...)

View file

@ -49,7 +49,11 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
{{end -}} {{end -}}
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintf(boil.DebugWriter, "%s\n%v\n", query, args) qStr, err := interpolateParams(query, args...)
if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
results, err := e.Query(query, args...) results, err := e.Query(query, args...)

View file

@ -53,8 +53,11 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo
values := []interface{}{related.{{$txt.ForeignTable.ColumnNameGo}}, o.{{$dot.Table.PKey.Columns | stringMap $dot.StringFuncs.titleCase | join ", o."}}{{"}"}} values := []interface{}{related.{{$txt.ForeignTable.ColumnNameGo}}, o.{{$dot.Table.PKey.Columns | stringMap $dot.StringFuncs.titleCase | join ", o."}}{{"}"}}
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, updateQuery) qStr, err := interpolateParams(updateQuery, values...)
fmt.Fprintln(boil.DebugWriter, values) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
if _, err = exec.Exec(updateQuery, values...); err != nil { if _, err = exec.Exec(updateQuery, values...); err != nil {

View file

@ -59,8 +59,11 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo
values := []interface{}{o.{{$txt.LocalTable.ColumnNameGo}}, related.{{$foreignPKeyCols | stringMap $dot.StringFuncs.titleCase | join ", related."}}{{"}"}} values := []interface{}{o.{{$txt.LocalTable.ColumnNameGo}}, related.{{$foreignPKeyCols | stringMap $dot.StringFuncs.titleCase | join ", related."}}{{"}"}}
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, updateQuery) qStr, err := interpolateParams(updateQuery, values...)
fmt.Fprintln(boil.DebugWriter, values) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
if _, err = exec.Exec(updateQuery, values...); err != nil { if _, err = exec.Exec(updateQuery, values...); err != nil {

View file

@ -66,8 +66,11 @@ func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}(exec boil.Executo
values := []interface{}{o.{{$txt.LocalTable.ColumnNameGo}}, rel.{{$foreignPKeyCols | stringMap $dot.StringFuncs.titleCase | join ", rel."}}{{"}"}} values := []interface{}{o.{{$txt.LocalTable.ColumnNameGo}}, rel.{{$foreignPKeyCols | stringMap $dot.StringFuncs.titleCase | join ", rel."}}{{"}"}}
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, updateQuery) qStr, err := interpolateParams(updateQuery, values...)
fmt.Fprintln(boil.DebugWriter, values) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
if _, err = exec.Exec(updateQuery, values...); err != nil { if _, err = exec.Exec(updateQuery, values...); err != nil {
@ -87,8 +90,11 @@ func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}(exec boil.Executo
values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}, rel.{{$txt.ForeignTable.ColumnNameGo}}} values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}, rel.{{$txt.ForeignTable.ColumnNameGo}}}
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, query) qStr, err := interpolateParams(query, values...)
fmt.Fprintln(boil.DebugWriter, values) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
_, err = exec.Exec(query, values...) _, err = exec.Exec(query, values...)
@ -184,8 +190,11 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo
values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}} values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}}
{{end -}} {{end -}}
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, query) qStr, err := interpolateParams(query, values...)
fmt.Fprintln(boil.DebugWriter, values) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
_, err := exec.Exec(query, values...) _, err := exec.Exec(query, values...)
@ -260,8 +269,11 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Exec
} }
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, query) qStr, err := interpolateParams(query, values...)
fmt.Fprintln(boil.DebugWriter, values) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
_, err = exec.Exec(query, values...) _, err = exec.Exec(query, values...)

View file

@ -98,8 +98,11 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
vals := queries.ValuesFromMapping(value, cache.valueMapping) vals := queries.ValuesFromMapping(value, cache.valueMapping)
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, cache.query) qStr, err := interpolateParams(cache.query, vals...)
fmt.Fprintln(boil.DebugWriter, vals) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
{{if .UseLastInsertID -}} {{if .UseLastInsertID -}}
@ -144,8 +147,11 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
} }
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, cache.retQuery) qStr, err := interpolateParams(cache.retQuery, identifierCols...)
fmt.Fprintln(boil.DebugWriter, identifierCols...) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...) err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...)

View file

@ -78,8 +78,11 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string
values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping) values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping)
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, cache.query) qStr, err := interpolateParams(cache.query, values...)
fmt.Fprintln(boil.DebugWriter, values) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
_, err = exec.Exec(cache.query, values...) _, err = exec.Exec(cache.query, values...)
@ -170,8 +173,11 @@ func (o {{$tableNameSingular}}Slice) UpdateAll(exec boil.Executor, cols M) error
strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), {{if .Dialect.IndexPlaceholders}}len(colNames)+1{{else}}0{{end}}, {{$varNameSingular}}PrimaryKeyColumns, len(o))) strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), {{if .Dialect.IndexPlaceholders}}len(colNames)+1{{else}}0{{end}}, {{$varNameSingular}}PrimaryKeyColumns, len(o)))
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, sql) qStr, err := interpolateParams(sql, args...)
fmt.Fprintln(boil.DebugWriter, args...) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
_, err := exec.Exec(sql, args...) _, err := exec.Exec(sql, args...)

View file

@ -147,8 +147,11 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName
} }
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, cache.query) qStr, err := interpolateParams(cache.query, vals...)
fmt.Fprintln(boil.DebugWriter, vals) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
{{if .UseLastInsertID -}} {{if .UseLastInsertID -}}
@ -193,8 +196,11 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName
} }
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, cache.retQuery) qStr, err := interpolateParams(cache.retQuery, identifierCols...)
fmt.Fprintln(boil.DebugWriter, identifierCols...) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(returns...) err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(returns...)

View file

@ -46,8 +46,11 @@ func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error {
sql := "DELETE FROM {{$schemaTable}} WHERE {{if .Dialect.IndexPlaceholders}}{{whereClause .LQ .RQ 1 .Table.PKey.Columns}}{{else}}{{whereClause .LQ .RQ 0 .Table.PKey.Columns}}{{end}}" sql := "DELETE FROM {{$schemaTable}} WHERE {{if .Dialect.IndexPlaceholders}}{{whereClause .LQ .RQ 1 .Table.PKey.Columns}}{{else}}{{whereClause .LQ .RQ 0 .Table.PKey.Columns}}{{end}}"
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, sql) qStr, err := interpolateParams(sql, args...)
fmt.Fprintln(boil.DebugWriter, args...) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
_, err := exec.Exec(sql, args...) _, err := exec.Exec(sql, args...)
@ -139,8 +142,11 @@ func (o {{$tableNameSingular}}Slice) DeleteAll(exec boil.Executor) error {
strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), {{if .Dialect.IndexPlaceholders}}1{{else}}0{{end}}, {{$varNameSingular}}PrimaryKeyColumns, len(o)) strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), {{if .Dialect.IndexPlaceholders}}1{{else}}0{{end}}, {{$varNameSingular}}PrimaryKeyColumns, len(o))
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, sql) qStr, err := interpolateParams(sql, args...)
fmt.Fprintln(boil.DebugWriter, args) if err != nil {
return err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
_, err := exec.Exec(sql, args...) _, err := exec.Exec(sql, args...)

View file

@ -14,8 +14,11 @@ func {{$tableNameSingular}}Exists(exec boil.Executor, {{$pkArgs}}) (bool, error)
{{- end}} {{- end}}
if boil.DebugMode { if boil.DebugMode {
fmt.Fprintln(boil.DebugWriter, sql) qStr, err := interpolateParams(sql, {{$pkNames | join ", "}})
fmt.Fprintln(boil.DebugWriter, {{$pkNames | join ", "}}) if err != nil {
return false, err
}
fmt.Fprintln(boil.DebugWriter, qStr)
} }
row := exec.QueryRow(sql, {{$pkNames | join ", "}}) row := exec.QueryRow(sql, {{$pkNames | join ", "}})

View file

@ -16,7 +16,7 @@ func (q *{{$tableNameSingular}}Query) Where(filters {{$tableNameSingular}}Filter
for i := 0; i < r.NumField(); i++ { for i := 0; i < r.NumField(); i++ {
f := r.Field(i) f := r.Field(i)
if f.Elem().IsValid() { if f.Elem().IsValid() {
if nullable, ok := f.Elem().Interface().(Nullable); ok && nullable.IsZero() { if nullable, ok := f.Elem().Interface().(null.Nullable); ok && nullable.IsNull() {
queries.AppendWhere(q.Query, r.Type().Field(i).Tag.Get("boil")+" IS NULL") queries.AppendWhere(q.Query, r.Type().Field(i).Tag.Get("boil")+" IS NULL")
} else { } else {
queries.AppendWhere(q.Query, r.Type().Field(i).Tag.Get("boil")+" = ?", f.Elem().Interface()) queries.AppendWhere(q.Query, r.Type().Field(i).Tag.Get("boil")+" = ?", f.Elem().Interface())

View file

@ -72,7 +72,7 @@ func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID
pf := pr.Elem().Field(i) pf := pr.Elem().Field(i)
sf := sr.Elem().Field(i) sf := sr.Elem().Field(i)
if sf.IsValid() { if sf.IsValid() {
if nullable, ok := sf.Interface().(Nullable); ok && !nullable.IsZero() && pf.Interface().(Nullable).IsZero() { if nullable, ok := sf.Interface().(null.Nullable); ok && !nullable.IsNull() && pf.Interface().(null.Nullable).IsNull() {
pf.Set(sf) pf.Set(sf)
} }
} }

View file

@ -136,3 +136,69 @@ func checkMerge(tx *sql.Tx, foreignKeys []foreignKey) error {
return nil return nil
} }
// duplicated in queries/query.go
func interpolateParams(query string, args ...interface{}) (string, error) {
for i := 0; i < len(args); i++ {
field := reflect.ValueOf(args[i])
if value, ok := field.Interface().(time.Time); ok {
query = strings.Replace(query, "?", `"`+value.Format("2006-01-02 15:04:05")+`"`, 1)
} else if nullable, ok := field.Interface().(null.Nullable); ok {
if nullable.IsNull() {
query = strings.Replace(query, "?", "NULL", 1)
} else {
switch field.Type() {
case reflect.TypeOf(null.Time{}):
query = strings.Replace(query, "?", `"`+field.Interface().(null.Time).Time.Format("2006-01-02 15:04:05")+`"`, 1)
case reflect.TypeOf(null.Int{}):
query = strings.Replace(query, "?", strconv.FormatInt(int64(field.Interface().(null.Int).Int), 10), 1)
case reflect.TypeOf(null.Int8{}):
query = strings.Replace(query, "?", strconv.FormatInt(int64(field.Interface().(null.Int8).Int8), 10), 1)
case reflect.TypeOf(null.Int16{}):
query = strings.Replace(query, "?", strconv.FormatInt(int64(field.Interface().(null.Int16).Int16), 10), 1)
case reflect.TypeOf(null.Int32{}):
query = strings.Replace(query, "?", strconv.FormatInt(int64(field.Interface().(null.Int32).Int32), 10), 1)
case reflect.TypeOf(null.Int64{}):
query = strings.Replace(query, "?", strconv.FormatInt(field.Interface().(null.Int64).Int64, 10), 1)
case reflect.TypeOf(null.Uint{}):
query = strings.Replace(query, "?", strconv.FormatUint(uint64(field.Interface().(null.Uint).Uint), 10), 1)
case reflect.TypeOf(null.Uint8{}):
query = strings.Replace(query, "?", strconv.FormatUint(uint64(field.Interface().(null.Uint8).Uint8), 10), 1)
case reflect.TypeOf(null.Uint16{}):
query = strings.Replace(query, "?", strconv.FormatUint(uint64(field.Interface().(null.Uint16).Uint16), 10), 1)
case reflect.TypeOf(null.Uint32{}):
query = strings.Replace(query, "?", strconv.FormatUint(uint64(field.Interface().(null.Uint32).Uint32), 10), 1)
case reflect.TypeOf(null.Uint64{}):
query = strings.Replace(query, "?", strconv.FormatUint(field.Interface().(null.Uint64).Uint64, 10), 1)
case reflect.TypeOf(null.String{}):
query = strings.Replace(query, "?", `"`+field.Interface().(null.String).String+`"`, 1)
case reflect.TypeOf(null.Bool{}):
if field.Interface().(null.Bool).Bool {
query = strings.Replace(query, "?", "1", 1)
} else {
query = strings.Replace(query, "?", "0", 1)
}
}
}
} else {
switch field.Kind() {
case reflect.Bool:
boolString := "0"
if field.Bool() {
boolString = "1"
}
query = strings.Replace(query, "?", boolString, 1)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
query = strings.Replace(query, "?", strconv.FormatInt(field.Int(), 10), 1)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
query = strings.Replace(query, "?", strconv.FormatUint(field.Uint(), 10), 1)
case reflect.String:
query = strings.Replace(query, "?", `"`+field.String()+`"`, 1)
default:
return "", errors.New("Dont know how to interpolate type " + field.Type().String())
}
}
}
return query, nil
}

View file

@ -1,11 +1,6 @@
// M type is for providing columns and column values to UpdateAll. // M type is for providing columns and column values to UpdateAll.
type M map[string]interface{} type M map[string]interface{}
// Nullable means the value may represent an sql NULL. It is implemented by null.* types.
type Nullable interface {
IsZero() bool
}
// foreignKey connects two tables. When merging records, foreign keys from secondary record must // foreignKey connects two tables. When merging records, foreign keys from secondary record must
// be reassigned to primary record. // be reassigned to primary record.
type foreignKey struct { type foreignKey struct {