From 451723ccb9b1535c98a69b3cdb10f2cf64c9f460 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Mon, 8 May 2017 13:25:15 -0400 Subject: [PATCH 01/35] fix imports to point at lbryio repo --- bdb/column.go | 2 +- bdb/drivers/mock.go | 4 +-- bdb/drivers/mssql.go | 2 +- bdb/drivers/mysql.go | 2 +- bdb/drivers/postgres.go | 4 +-- bdb/interface_test.go | 2 +- boilingcore/boilingcore.go | 10 +++--- boilingcore/imports.go | 54 ++++++++++++++++---------------- boilingcore/imports_test.go | 16 +++++----- boilingcore/output.go | 2 +- boilingcore/templates.go | 6 ++-- boilingcore/text_helpers.go | 4 +-- boilingcore/text_helpers_test.go | 4 +-- main.go | 6 ++-- queries/eager_load.go | 4 +-- queries/eager_load_test.go | 2 +- queries/helpers.go | 2 +- queries/qm/query_mods.go | 2 +- queries/query.go | 2 +- queries/query_builders.go | 2 +- queries/reflect.go | 4 +-- randomize/randomize.go | 4 +-- 22 files changed, 70 insertions(+), 70 deletions(-) diff --git a/bdb/column.go b/bdb/column.go index a3632fc..da56e48 100644 --- a/bdb/column.go +++ b/bdb/column.go @@ -3,7 +3,7 @@ package bdb import ( "strings" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/strmangle" ) // Column holds information about a database column. diff --git a/bdb/drivers/mock.go b/bdb/drivers/mock.go index 1c91d0e..7d14f2a 100644 --- a/bdb/drivers/mock.go +++ b/bdb/drivers/mock.go @@ -1,8 +1,8 @@ package drivers import ( - "github.com/vattle/sqlboiler/bdb" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/bdb" + "github.com/lbryio/sqlboiler/strmangle" ) // MockDriver is a mock implementation of the bdb driver Interface diff --git a/bdb/drivers/mssql.go b/bdb/drivers/mssql.go index cb3290a..e59330b 100644 --- a/bdb/drivers/mssql.go +++ b/bdb/drivers/mssql.go @@ -8,7 +8,7 @@ import ( _ "github.com/denisenkom/go-mssqldb" "github.com/pkg/errors" - "github.com/vattle/sqlboiler/bdb" + "github.com/lbryio/sqlboiler/bdb" ) // MSSQLDriver holds the database connection string and a handle diff --git a/bdb/drivers/mysql.go b/bdb/drivers/mysql.go index 346e473..bb73574 100644 --- a/bdb/drivers/mysql.go +++ b/bdb/drivers/mysql.go @@ -8,7 +8,7 @@ import ( "github.com/go-sql-driver/mysql" "github.com/pkg/errors" - "github.com/vattle/sqlboiler/bdb" + "github.com/lbryio/sqlboiler/bdb" ) // TinyintAsBool is a global that is set from main.go if a user specifies diff --git a/bdb/drivers/postgres.go b/bdb/drivers/postgres.go index 34cdd78..ad73a2e 100644 --- a/bdb/drivers/postgres.go +++ b/bdb/drivers/postgres.go @@ -10,8 +10,8 @@ import ( _ "github.com/lib/pq" "github.com/pkg/errors" - "github.com/vattle/sqlboiler/bdb" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/bdb" + "github.com/lbryio/sqlboiler/strmangle" ) // PostgresDriver holds the database connection string and a handle diff --git a/bdb/interface_test.go b/bdb/interface_test.go index 4d429c6..e5d28fb 100644 --- a/bdb/interface_test.go +++ b/bdb/interface_test.go @@ -3,7 +3,7 @@ package bdb import ( "testing" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/strmangle" ) type testMockDriver struct{} diff --git a/boilingcore/boilingcore.go b/boilingcore/boilingcore.go index 5e00687..e667cae 100644 --- a/boilingcore/boilingcore.go +++ b/boilingcore/boilingcore.go @@ -13,10 +13,10 @@ import ( "text/template" "github.com/pkg/errors" - "github.com/vattle/sqlboiler/bdb" - "github.com/vattle/sqlboiler/bdb/drivers" - "github.com/vattle/sqlboiler/queries" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/bdb" + "github.com/lbryio/sqlboiler/bdb/drivers" + "github.com/lbryio/sqlboiler/queries" + "github.com/lbryio/sqlboiler/strmangle" ) const ( @@ -267,7 +267,7 @@ func (s *State) processReplacements() error { return nil } -var basePackage = "github.com/vattle/sqlboiler" +var basePackage = "github.com/lbryio/sqlboiler" func getBasePath(baseDirConfig string) (string, error) { if len(baseDirConfig) > 0 { diff --git a/boilingcore/imports.go b/boilingcore/imports.go index eafcf28..1fbca14 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -6,7 +6,7 @@ import ( "sort" "strings" - "github.com/vattle/sqlboiler/bdb" + "github.com/lbryio/sqlboiler/bdb" ) // imports defines the optional standard imports and @@ -171,25 +171,25 @@ func newImporter() importer { }, thirdParty: importList{ `"github.com/pkg/errors"`, - `"github.com/vattle/sqlboiler/boil"`, - `"github.com/vattle/sqlboiler/queries"`, - `"github.com/vattle/sqlboiler/queries/qm"`, - `"github.com/vattle/sqlboiler/strmangle"`, + `"github.com/lbryio/sqlboiler/boil"`, + `"github.com/lbryio/sqlboiler/queries"`, + `"github.com/lbryio/sqlboiler/queries/qm"`, + `"github.com/lbryio/sqlboiler/strmangle"`, }, } imp.Singleton = mapImports{ "boil_queries": { thirdParty: importList{ - `"github.com/vattle/sqlboiler/boil"`, - `"github.com/vattle/sqlboiler/queries"`, - `"github.com/vattle/sqlboiler/queries/qm"`, + `"github.com/lbryio/sqlboiler/boil"`, + `"github.com/lbryio/sqlboiler/queries"`, + `"github.com/lbryio/sqlboiler/queries/qm"`, }, }, "boil_types": { thirdParty: importList{ `"github.com/pkg/errors"`, - `"github.com/vattle/sqlboiler/strmangle"`, + `"github.com/lbryio/sqlboiler/strmangle"`, }, }, } @@ -201,9 +201,9 @@ func newImporter() importer { `"testing"`, }, thirdParty: importList{ - `"github.com/vattle/sqlboiler/boil"`, - `"github.com/vattle/sqlboiler/randomize"`, - `"github.com/vattle/sqlboiler/strmangle"`, + `"github.com/lbryio/sqlboiler/boil"`, + `"github.com/lbryio/sqlboiler/randomize"`, + `"github.com/lbryio/sqlboiler/strmangle"`, }, } @@ -223,7 +223,7 @@ func newImporter() importer { `"github.com/kat-co/vala"`, `"github.com/pkg/errors"`, `"github.com/spf13/viper"`, - `"github.com/vattle/sqlboiler/boil"`, + `"github.com/lbryio/sqlboiler/boil"`, }, }, "boil_queries_test": { @@ -236,7 +236,7 @@ func newImporter() importer { `"regexp"`, }, thirdParty: importList{ - `"github.com/vattle/sqlboiler/boil"`, + `"github.com/lbryio/sqlboiler/boil"`, }, }, "boil_suites_test": { @@ -261,8 +261,8 @@ func newImporter() importer { thirdParty: importList{ `"github.com/pkg/errors"`, `"github.com/spf13/viper"`, - `"github.com/vattle/sqlboiler/bdb/drivers"`, - `"github.com/vattle/sqlboiler/randomize"`, + `"github.com/lbryio/sqlboiler/bdb/drivers"`, + `"github.com/lbryio/sqlboiler/randomize"`, `_ "github.com/lib/pq"`, }, }, @@ -280,8 +280,8 @@ func newImporter() importer { thirdParty: importList{ `"github.com/pkg/errors"`, `"github.com/spf13/viper"`, - `"github.com/vattle/sqlboiler/bdb/drivers"`, - `"github.com/vattle/sqlboiler/randomize"`, + `"github.com/lbryio/sqlboiler/bdb/drivers"`, + `"github.com/lbryio/sqlboiler/randomize"`, `_ "github.com/go-sql-driver/mysql"`, }, }, @@ -297,8 +297,8 @@ func newImporter() importer { thirdParty: importList{ `"github.com/pkg/errors"`, `"github.com/spf13/viper"`, - `"github.com/vattle/sqlboiler/bdb/drivers"`, - `"github.com/vattle/sqlboiler/randomize"`, + `"github.com/lbryio/sqlboiler/bdb/drivers"`, + `"github.com/lbryio/sqlboiler/randomize"`, `_ "github.com/denisenkom/go-mssqldb"`, }, }, @@ -363,25 +363,25 @@ func newImporter() importer { standard: importList{`"time"`}, }, "types.JSON": { - thirdParty: importList{`"github.com/vattle/sqlboiler/types"`}, + thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`}, }, "types.BytesArray": { - thirdParty: importList{`"github.com/vattle/sqlboiler/types"`}, + thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`}, }, "types.Int64Array": { - thirdParty: importList{`"github.com/vattle/sqlboiler/types"`}, + thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`}, }, "types.Float64Array": { - thirdParty: importList{`"github.com/vattle/sqlboiler/types"`}, + thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`}, }, "types.BoolArray": { - thirdParty: importList{`"github.com/vattle/sqlboiler/types"`}, + thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`}, }, "types.StringArray": { - thirdParty: importList{`"github.com/vattle/sqlboiler/types"`}, + thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`}, }, "types.Hstore": { - thirdParty: importList{`"github.com/vattle/sqlboiler/types"`}, + thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`}, }, } diff --git a/boilingcore/imports_test.go b/boilingcore/imports_test.go index 6f2cde4..ff2362d 100644 --- a/boilingcore/imports_test.go +++ b/boilingcore/imports_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/pkg/errors" - "github.com/vattle/sqlboiler/bdb" + "github.com/lbryio/sqlboiler/bdb" ) func TestImportsSort(t *testing.T) { @@ -234,7 +234,7 @@ func TestCombineTypeImports(t *testing.T) { `"fmt"`, }, thirdParty: importList{ - `"github.com/vattle/sqlboiler/boil"`, + `"github.com/lbryio/sqlboiler/boil"`, }, } @@ -245,7 +245,7 @@ func TestCombineTypeImports(t *testing.T) { `"time"`, }, thirdParty: importList{ - `"github.com/vattle/sqlboiler/boil"`, + `"github.com/lbryio/sqlboiler/boil"`, `"gopkg.in/nullbio/null.v6"`, }, } @@ -280,7 +280,7 @@ func TestCombineTypeImports(t *testing.T) { `"time"`, }, thirdParty: importList{ - `"github.com/vattle/sqlboiler/boil"`, + `"github.com/lbryio/sqlboiler/boil"`, `"gopkg.in/nullbio/null.v6"`, }, } @@ -297,11 +297,11 @@ func TestCombineImports(t *testing.T) { a := imports{ standard: importList{"fmt"}, - thirdParty: importList{"github.com/vattle/sqlboiler", "gopkg.in/nullbio/null.v6"}, + thirdParty: importList{"github.com/lbryio/sqlboiler", "gopkg.in/nullbio/null.v6"}, } b := imports{ standard: importList{"os"}, - thirdParty: importList{"github.com/vattle/sqlboiler"}, + thirdParty: importList{"github.com/lbryio/sqlboiler"}, } c := combineImports(a, b) @@ -309,8 +309,8 @@ func TestCombineImports(t *testing.T) { if c.standard[0] != "fmt" && c.standard[1] != "os" { t.Errorf("Wanted: fmt, os got: %#v", c.standard) } - if c.thirdParty[0] != "github.com/vattle/sqlboiler" && c.thirdParty[1] != "gopkg.in/nullbio/null.v6" { - t.Errorf("Wanted: github.com/vattle/sqlboiler, gopkg.in/nullbio/null.v6 got: %#v", c.thirdParty) + if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "gopkg.in/nullbio/null.v6" { + t.Errorf("Wanted: github.com/lbryio/sqlboiler, gopkg.in/nullbio/null.v6 got: %#v", c.thirdParty) } } diff --git a/boilingcore/output.go b/boilingcore/output.go index 64f28b5..5c65634 100644 --- a/boilingcore/output.go +++ b/boilingcore/output.go @@ -14,7 +14,7 @@ import ( "github.com/pkg/errors" ) -var noEditDisclaimer = []byte(`// This file is generated by SQLBoiler (https://github.com/vattle/sqlboiler) +var noEditDisclaimer = []byte(`// This file is generated by SQLBoiler (https://github.com/lbryio/sqlboiler) // and is meant to be re-generated in place and/or deleted at any time. // DO NOT EDIT diff --git a/boilingcore/templates.go b/boilingcore/templates.go index 9c60739..62c0ae5 100644 --- a/boilingcore/templates.go +++ b/boilingcore/templates.go @@ -9,9 +9,9 @@ import ( "text/template" "github.com/pkg/errors" - "github.com/vattle/sqlboiler/bdb" - "github.com/vattle/sqlboiler/queries" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/bdb" + "github.com/lbryio/sqlboiler/queries" + "github.com/lbryio/sqlboiler/strmangle" ) // templateData for sqlboiler templates diff --git a/boilingcore/text_helpers.go b/boilingcore/text_helpers.go index e9577a7..0bce73f 100644 --- a/boilingcore/text_helpers.go +++ b/boilingcore/text_helpers.go @@ -4,8 +4,8 @@ import ( "fmt" "strings" - "github.com/vattle/sqlboiler/bdb" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/bdb" + "github.com/lbryio/sqlboiler/strmangle" ) // TxtToOne contains text that will be used by templates for a one-to-many or diff --git a/boilingcore/text_helpers_test.go b/boilingcore/text_helpers_test.go index 8beed50..835ed0d 100644 --- a/boilingcore/text_helpers_test.go +++ b/boilingcore/text_helpers_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/davecgh/go-spew/spew" - "github.com/vattle/sqlboiler/bdb" - "github.com/vattle/sqlboiler/bdb/drivers" + "github.com/lbryio/sqlboiler/bdb" + "github.com/lbryio/sqlboiler/bdb/drivers" ) func TestTxtsFromOne(t *testing.T) { diff --git a/main.go b/main.go index 793055d..5103116 100644 --- a/main.go +++ b/main.go @@ -10,8 +10,8 @@ import ( "github.com/kat-co/vala" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/vattle/sqlboiler/bdb/drivers" - "github.com/vattle/sqlboiler/boilingcore" + "github.com/lbryio/sqlboiler/bdb/drivers" + "github.com/lbryio/sqlboiler/boilingcore" ) const sqlBoilerVersion = "2.3.0" @@ -62,7 +62,7 @@ func main() { Use: "sqlboiler [flags] <driver>", Short: "SQL Boiler generates an ORM tailored to your database schema.", Long: "SQL Boiler generates a Go ORM from template files, tailored to your database schema.\n" + - `Complete documentation is available at http://github.com/vattle/sqlboiler`, + `Complete documentation is available at http://github.com/lbryio/sqlboiler`, Example: `sqlboiler postgres`, PreRunE: preRun, RunE: run, diff --git a/queries/eager_load.go b/queries/eager_load.go index 18abcc8..081aac4 100644 --- a/queries/eager_load.go +++ b/queries/eager_load.go @@ -6,8 +6,8 @@ import ( "strings" "github.com/pkg/errors" - "github.com/vattle/sqlboiler/boil" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/boil" + "github.com/lbryio/sqlboiler/strmangle" ) type loadRelationshipState struct { diff --git a/queries/eager_load_test.go b/queries/eager_load_test.go index dc3f5f1..c7b3cef 100644 --- a/queries/eager_load_test.go +++ b/queries/eager_load_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/vattle/sqlboiler/boil" + "github.com/lbryio/sqlboiler/boil" ) var testEagerCounters struct { diff --git a/queries/helpers.go b/queries/helpers.go index 59ad8a3..b953a67 100644 --- a/queries/helpers.go +++ b/queries/helpers.go @@ -4,7 +4,7 @@ import ( "fmt" "reflect" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/strmangle" ) // NonZeroDefaultSet returns the fields included in the diff --git a/queries/qm/query_mods.go b/queries/qm/query_mods.go index 81ae3a0..89d31d4 100644 --- a/queries/qm/query_mods.go +++ b/queries/qm/query_mods.go @@ -1,6 +1,6 @@ package qm -import "github.com/vattle/sqlboiler/queries" +import "github.com/lbryio/sqlboiler/queries" // QueryMod to modify the query object type QueryMod func(q *queries.Query) diff --git a/queries/query.go b/queries/query.go index 8c2abdb..be539e5 100644 --- a/queries/query.go +++ b/queries/query.go @@ -4,7 +4,7 @@ import ( "database/sql" "fmt" - "github.com/vattle/sqlboiler/boil" + "github.com/lbryio/sqlboiler/boil" ) // joinKind is the type of join diff --git a/queries/query_builders.go b/queries/query_builders.go index 2188044..d221aca 100644 --- a/queries/query_builders.go +++ b/queries/query_builders.go @@ -7,7 +7,7 @@ import ( "sort" "strings" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/strmangle" ) var ( diff --git a/queries/reflect.go b/queries/reflect.go index 9c55b33..8cf8f3d 100644 --- a/queries/reflect.go +++ b/queries/reflect.go @@ -8,8 +8,8 @@ import ( "sync" "github.com/pkg/errors" - "github.com/vattle/sqlboiler/boil" - "github.com/vattle/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/boil" + "github.com/lbryio/sqlboiler/strmangle" ) var ( diff --git a/randomize/randomize.go b/randomize/randomize.go index 59f7eff..ea99c43 100644 --- a/randomize/randomize.go +++ b/randomize/randomize.go @@ -18,8 +18,8 @@ import ( "github.com/pkg/errors" "github.com/satori/go.uuid" - "github.com/vattle/sqlboiler/strmangle" - "github.com/vattle/sqlboiler/types" + "github.com/lbryio/sqlboiler/strmangle" + "github.com/lbryio/sqlboiler/types" ) var ( From f863ecb48e3215e98d75dfebeefbd38061cad936 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Mon, 8 May 2017 16:30:40 -0400 Subject: [PATCH 02/35] add model Filters, FindOrCreate methods, IsNew() --- templates/00_struct.tpl | 7 ++++ templates/14_find.tpl | 79 +++++++++++++++++++++++++++++++++++++++++ templates/20_exists.tpl | 36 +++++++++++++++++++ 3 files changed, 122 insertions(+) diff --git a/templates/00_struct.tpl b/templates/00_struct.tpl index 585feee..f9c3a04 100644 --- a/templates/00_struct.tpl +++ b/templates/00_struct.tpl @@ -17,6 +17,13 @@ type {{$modelName}} struct { {{end -}} } +// {{$modelName}}Filter allows you to filter on any columns by making them all pointers. +type {{$modelName}}Filter struct { + {{range $column := .Table.Columns -}} + {{titleCase $column.Name}} *{{$column.Type}} `{{generateTags $dot.Tags $column.Name}}boil:"{{$column.Name}}" json:"{{$column.Name}},omitempty" toml:"{{$column.Name}}" yaml:"{{$column.Name}},omitempty"` + {{end -}} +} + {{- if .Table.IsJoinTable -}} {{- else}} // {{$modelNameCamel}}R is where relationships are stored. diff --git a/templates/14_find.tpl b/templates/14_find.tpl index 097f184..12ffa85 100644 --- a/templates/14_find.tpl +++ b/templates/14_find.tpl @@ -53,3 +53,82 @@ func Find{{$tableNameSingular}}P(exec boil.Executor, {{$pkArgs}}, selectCols ... return retobj } + +// FindOne{{$tableNameSingular}} retrieves a single record using filters. +func FindOne{{$tableNameSingular}}(exec boil.Executor, filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + {{$varNameSingular}}Obj := &{{$tableNameSingular}}{} + + query := NewQuery(exec, qm.Select("*"), qm.From("{{.Table.Name | .SchemaTable}}")) + + r := reflect.ValueOf(filters) + for i := 0; i < r.NumField(); i++ { + f := r.Field(i) + if f.Elem().IsValid() { + queries.AppendWhere(query, r.Type().Field(i).Tag.Get("boil")+" = ?", f.Elem().Interface()) + } + } + + queries.SetLimit(query, 1) + + err := query.Bind({{$varNameSingular}}Obj) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "{{.PkgName}}: unable to select from {{.Table.Name}}") + } + + return {{$varNameSingular}}Obj, nil +} + +// FindOne{{$tableNameSingular}}G retrieves a single record using filters. +func FindOne{{$tableNameSingular}}G(filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + return FindOne{{$tableNameSingular}}(boil.GetDB(), filters) +} + +// FindOne{{$tableNameSingular}}OrInit retrieves a single record using filters, or initializes a new record if one is not found. +func FindOne{{$tableNameSingular}}OrInit(exec boil.Executor, filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + {{$varNameSingular}}Obj, err := FindOne{{$tableNameSingular}}(exec, filters) + if err != nil && errors.Cause(err) != sql.ErrNoRows { + return nil, err + } + + if {{$varNameSingular}}Obj == nil { + {{$varNameSingular}}Obj = &{{$tableNameSingular}}{} + objR := reflect.ValueOf({{$varNameSingular}}Obj).Elem() + r := reflect.ValueOf(filters) + for i := 0; i < r.NumField(); i++ { + f := r.Field(i) + if f.Elem().IsValid() { + objR.FieldByName(r.Type().Field(i).Name).Set(f.Elem()) + } + } + } + + return {{$varNameSingular}}Obj, nil +} + +// FindOne{{$tableNameSingular}}OrInit retrieves a single record using filters, or initializes a new record if one is not found. +func FindOne{{$tableNameSingular}}OrInitG(filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + return FindOne{{$tableNameSingular}}OrInit(boil.GetDB(), filters) +} + +// FindOne{{$tableNameSingular}}OrInit retrieves a single record using filters, or initializes and inserts a new record if one is not found. +func FindOne{{$tableNameSingular}}OrCreate(exec boil.Executor, filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + {{$varNameSingular}}Obj, err := FindOne{{$tableNameSingular}}OrInit(exec, filters) + if err != nil { + return nil, err + } + if {{$varNameSingular}}Obj.IsNew() { + err := {{$varNameSingular}}Obj.Insert(exec) + if err != nil { + return nil, err + } + } + return {{$varNameSingular}}Obj, nil +} + +// FindOne{{$tableNameSingular}}OrInit retrieves a single record using filters, or initializes and inserts a new record if one is not found. +func FindOne{{$tableNameSingular}}OrCreateG(filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { + return FindOne{{$tableNameSingular}}OrCreate(boil.GetDB(), filters) +} diff --git a/templates/20_exists.tpl b/templates/20_exists.tpl index 22a67a0..2e20fa6 100644 --- a/templates/20_exists.tpl +++ b/templates/20_exists.tpl @@ -1,4 +1,5 @@ {{- $tableNameSingular := .Table.Name | singular | titleCase -}} +{{- $varNameSingular := .Table.Name | singular | camelCase -}} {{- $colDefs := sqlColDefinitions .Table.Columns .Table.PKey.Columns -}} {{- $pkNames := $colDefs.Names | stringMap .StringFuncs.camelCase | stringMap .StringFuncs.replaceReserved -}} {{- $pkArgs := joinSlices " " $pkNames $colDefs.Types | join ", " -}} @@ -51,3 +52,38 @@ func {{$tableNameSingular}}ExistsP(exec boil.Executor, {{$pkArgs}}) bool { return e } + +// IsNew() checks if record exists in db (aka if its primary key is set). +func (o *{{$tableNameSingular}}) IsNew() bool { + r := reflect.ValueOf(o).Elem() + for i := 0; i < r.NumField(); i++ { + column := r.Type().Field(i).Tag.Get("boil") + for _, pkColumn := range {{$varNameSingular}}PrimaryKeyColumns { + if column == pkColumn { + field := r.Field(i) + if field.Interface() != reflect.Zero(field.Type()).Interface() { + return false + } + } + } + } + return true +} + +// Save() inserts the record if it does not exist, or updates it if it does. +func (o *{{$tableNameSingular}}) Save(exec boil.Executor, whitelist ...string) error { + if o.IsNew() { + return o.Insert(exec, whitelist...) + } else { + return o.Update(exec, whitelist...) + } +} + +// SaveG() inserts the record if it does not exist, or updates it if it does. +func (o *{{$tableNameSingular}}) SaveG(whitelist ...string) error { + if o.IsNew() { + return o.InsertG(whitelist...) + } else { + return o.UpdateG(whitelist...) + } +} From ed43c9078f34416398d074fe772af8e1513289a6 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Tue, 9 May 2017 15:30:04 -0400 Subject: [PATCH 03/35] made query structs public, added IS NULL to filter --- .gitignore | 1 + templates/01_types.tpl | 2 +- templates/03_finishers.tpl | 20 ++++++------- templates/04_relationship_to_one.tpl | 6 ++-- templates/05_relationship_one_to_one.tpl | 6 ++-- templates/06_relationship_to_many.tpl | 6 ++-- templates/07_relationship_to_one_eager.tpl | 2 +- templates/13_all.tpl | 8 +++--- templates/14_find.tpl | 20 ++++--------- templates/16_update.tpl | 4 +-- templates/18_delete.tpl | 6 ++-- templates/22_query.tpl | 33 ++++++++++++++++++++++ templates/singleton/boil_types.tpl | 5 ++++ 13 files changed, 75 insertions(+), 44 deletions(-) create mode 100644 templates/22_query.tpl diff --git a/.gitignore b/.gitignore index 8f7858d..a7dc0b1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ sqlboiler.toml models/ testschema.sql .cover +/.idea diff --git a/templates/01_types.tpl b/templates/01_types.tpl index a1a1ef0..9340e42 100644 --- a/templates/01_types.tpl +++ b/templates/01_types.tpl @@ -21,7 +21,7 @@ type ( {{$tableNameSingular}}Hook func(boil.Executor, *{{$tableNameSingular}}) error {{- end}} - {{$varNameSingular}}Query struct { + {{$tableNameSingular}}Query struct { *queries.Query } ) diff --git a/templates/03_finishers.tpl b/templates/03_finishers.tpl index 0cc7e78..841769b 100644 --- a/templates/03_finishers.tpl +++ b/templates/03_finishers.tpl @@ -1,7 +1,7 @@ {{- $tableNameSingular := .Table.Name | singular | titleCase -}} {{- $varNameSingular := .Table.Name | singular | camelCase -}} -// OneP returns a single {{$varNameSingular}} record from the query, and panics on error. -func (q {{$varNameSingular}}Query) OneP() (*{{$tableNameSingular}}) { +// OneP returns a single {{$tableNameSingular}} record from the query, and panics on error. +func (q {{$tableNameSingular}}Query) OneP() (*{{$tableNameSingular}}) { o, err := q.One() if err != nil { panic(boil.WrapErr(err)) @@ -10,8 +10,8 @@ func (q {{$varNameSingular}}Query) OneP() (*{{$tableNameSingular}}) { return o } -// One returns a single {{$varNameSingular}} record from the query. -func (q {{$varNameSingular}}Query) One() (*{{$tableNameSingular}}, error) { +// One returns a single {{$tableNameSingular}} record from the query. +func (q {{$tableNameSingular}}Query) One() (*{{$tableNameSingular}}, error) { o := &{{$tableNameSingular}}{} queries.SetLimit(q.Query, 1) @@ -34,7 +34,7 @@ func (q {{$varNameSingular}}Query) One() (*{{$tableNameSingular}}, error) { } // AllP returns all {{$tableNameSingular}} records from the query, and panics on error. -func (q {{$varNameSingular}}Query) AllP() {{$tableNameSingular}}Slice { +func (q {{$tableNameSingular}}Query) AllP() {{$tableNameSingular}}Slice { o, err := q.All() if err != nil { panic(boil.WrapErr(err)) @@ -44,7 +44,7 @@ func (q {{$varNameSingular}}Query) AllP() {{$tableNameSingular}}Slice { } // All returns all {{$tableNameSingular}} records from the query. -func (q {{$varNameSingular}}Query) All() ({{$tableNameSingular}}Slice, error) { +func (q {{$tableNameSingular}}Query) All() ({{$tableNameSingular}}Slice, error) { var o []*{{$tableNameSingular}} err := q.Bind(&o) @@ -66,7 +66,7 @@ func (q {{$varNameSingular}}Query) All() ({{$tableNameSingular}}Slice, error) { } // CountP returns the count of all {{$tableNameSingular}} records in the query, and panics on error. -func (q {{$varNameSingular}}Query) CountP() int64 { +func (q {{$tableNameSingular}}Query) CountP() int64 { c, err := q.Count() if err != nil { panic(boil.WrapErr(err)) @@ -76,7 +76,7 @@ func (q {{$varNameSingular}}Query) CountP() int64 { } // Count returns the count of all {{$tableNameSingular}} records in the query. -func (q {{$varNameSingular}}Query) Count() (int64, error) { +func (q {{$tableNameSingular}}Query) Count() (int64, error) { var count int64 queries.SetSelect(q.Query, nil) @@ -91,7 +91,7 @@ func (q {{$varNameSingular}}Query) Count() (int64, error) { } // Exists checks if the row exists in the table, and panics on error. -func (q {{$varNameSingular}}Query) ExistsP() bool { +func (q {{$tableNameSingular}}Query) ExistsP() bool { e, err := q.Exists() if err != nil { panic(boil.WrapErr(err)) @@ -101,7 +101,7 @@ func (q {{$varNameSingular}}Query) ExistsP() bool { } // Exists checks if the row exists in the table. -func (q {{$varNameSingular}}Query) Exists() (bool, error) { +func (q {{$tableNameSingular}}Query) Exists() (bool, error) { var count int64 queries.SetCount(q.Query) diff --git a/templates/04_relationship_to_one.tpl b/templates/04_relationship_to_one.tpl index 05c75c9..9bc8c5f 100644 --- a/templates/04_relationship_to_one.tpl +++ b/templates/04_relationship_to_one.tpl @@ -3,14 +3,14 @@ {{- $dot := . -}} {{- range .Table.FKeys -}} {{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}} - {{- $varNameSingular := .ForeignTable | singular | camelCase}} + {{- $tableNameSingular := .ForeignTable | singular | titleCase}} // {{$txt.Function.Name}}G pointed to by the foreign key. -func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query { +func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}G(mods ...qm.QueryMod) {{$tableNameSingular}}Query { return o.{{$txt.Function.Name}}(boil.GetDB(), mods...) } // {{$txt.Function.Name}} pointed to by the foreign key. -func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) ({{$varNameSingular}}Query) { +func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) ({{$tableNameSingular}}Query) { queryMods := []qm.QueryMod{ qm.Where("{{$txt.ForeignTable.ColumnName}}=?", o.{{$txt.LocalTable.ColumnNameGo}}), } diff --git a/templates/05_relationship_one_to_one.tpl b/templates/05_relationship_one_to_one.tpl index e74279c..1dcd2ee 100644 --- a/templates/05_relationship_one_to_one.tpl +++ b/templates/05_relationship_one_to_one.tpl @@ -3,14 +3,14 @@ {{- $dot := . -}} {{- range .Table.ToOneRelationships -}} {{- $txt := txtsFromOneToOne $dot.Tables $dot.Table . -}} - {{- $varNameSingular := .ForeignTable | singular | camelCase}} + {{- $tableNameSingular := .ForeignTable | singular | titleCase}} // {{$txt.Function.Name}}G pointed to by the foreign key. -func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query { +func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}G(mods ...qm.QueryMod) {{$tableNameSingular}}Query { return o.{{$txt.Function.Name}}(boil.GetDB(), mods...) } // {{$txt.Function.Name}} pointed to by the foreign key. -func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) ({{$varNameSingular}}Query) { +func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) ({{$tableNameSingular}}Query) { queryMods := []qm.QueryMod{ qm.Where("{{$txt.ForeignTable.ColumnName}}=?", o.{{$txt.LocalTable.ColumnNameGo}}), } diff --git a/templates/06_relationship_to_many.tpl b/templates/06_relationship_to_many.tpl index c108eeb..10aa842 100644 --- a/templates/06_relationship_to_many.tpl +++ b/templates/06_relationship_to_many.tpl @@ -3,18 +3,18 @@ {{- $dot := . -}} {{- $table := .Table -}} {{- range .Table.ToManyRelationships -}} - {{- $varNameSingular := .ForeignTable | singular | camelCase -}} + {{- $tableNameSingular := .ForeignTable | singular | titleCase -}} {{- $txt := txtsFromToMany $dot.Tables $table . -}} {{- $schemaForeignTable := .ForeignTable | $dot.SchemaTable}} // {{$txt.Function.Name}}G retrieves all the {{.ForeignTable | singular}}'s {{$txt.ForeignTable.NameHumanReadable}} {{- if not (eq $txt.Function.Name $txt.ForeignTable.NamePluralGo)}} via {{.ForeignColumn}} column{{- end}}. -func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query { +func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}G(mods ...qm.QueryMod) {{$tableNameSingular}}Query { return o.{{$txt.Function.Name}}(boil.GetDB(), mods...) } // {{$txt.Function.Name}} retrieves all the {{.ForeignTable | singular}}'s {{$txt.ForeignTable.NameHumanReadable}} with an executor {{- if not (eq $txt.Function.Name $txt.ForeignTable.NamePluralGo)}} via {{.ForeignColumn}} column{{- end}}. -func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) {{$varNameSingular}}Query { +func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) {{$tableNameSingular}}Query { queryMods := []qm.QueryMod{ qm.Select("{{id 0 | $dot.Quotes}}.*"), } diff --git a/templates/07_relationship_to_one_eager.tpl b/templates/07_relationship_to_one_eager.tpl index dd1481a..3b24f1a 100644 --- a/templates/07_relationship_to_one_eager.tpl +++ b/templates/07_relationship_to_one_eager.tpl @@ -4,7 +4,7 @@ {{- range .Table.FKeys -}} {{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}} {{- $varNameSingular := $dot.Table.Name | singular | camelCase -}} - {{- $arg := printf "maybe%s" $txt.LocalTable.NameGo -}} + {{- $arg := printf "maybe%s" $txt.LocalTable.NameGo}} // Load{{$txt.Function.Name}} allows an eager lookup of values, cached into the // loaded structs of the objects. func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singular bool, {{$arg}} interface{}) error { diff --git a/templates/13_all.tpl b/templates/13_all.tpl index 42cf66a..c41f19c 100644 --- a/templates/13_all.tpl +++ b/templates/13_all.tpl @@ -1,12 +1,12 @@ {{- $tableNamePlural := .Table.Name | plural | titleCase -}} -{{- $varNameSingular := .Table.Name | singular | camelCase}} +{{- $tableNameSingular := .Table.Name | singular | titleCase}} // {{$tableNamePlural}}G retrieves all records. -func {{$tableNamePlural}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query { +func {{$tableNamePlural}}G(mods ...qm.QueryMod) {{$tableNameSingular}}Query { return {{$tableNamePlural}}(boil.GetDB(), mods...) } // {{$tableNamePlural}} retrieves all the records using an executor. -func {{$tableNamePlural}}(exec boil.Executor, mods ...qm.QueryMod) {{$varNameSingular}}Query { +func {{$tableNamePlural}}(exec boil.Executor, mods ...qm.QueryMod) {{$tableNameSingular}}Query { mods = append(mods, qm.From("{{.Table.Name | .SchemaTable}}")) - return {{$varNameSingular}}Query{NewQuery(exec, mods...)} + return {{$tableNameSingular}}Query{NewQuery(exec, mods...)} } diff --git a/templates/14_find.tpl b/templates/14_find.tpl index 12ffa85..e177959 100644 --- a/templates/14_find.tpl +++ b/templates/14_find.tpl @@ -56,21 +56,13 @@ func Find{{$tableNameSingular}}P(exec boil.Executor, {{$pkArgs}}, selectCols ... // FindOne{{$tableNameSingular}} retrieves a single record using filters. func FindOne{{$tableNameSingular}}(exec boil.Executor, filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { - {{$varNameSingular}}Obj := &{{$tableNameSingular}}{} + obj := &{{$tableNameSingular}}{} - query := NewQuery(exec, qm.Select("*"), qm.From("{{.Table.Name | .SchemaTable}}")) + err := {{$tableNameSingular}}NewQuery(exec). + Where(filters). + Limit(1). + Bind(obj) - r := reflect.ValueOf(filters) - for i := 0; i < r.NumField(); i++ { - f := r.Field(i) - if f.Elem().IsValid() { - queries.AppendWhere(query, r.Type().Field(i).Tag.Get("boil")+" = ?", f.Elem().Interface()) - } - } - - queries.SetLimit(query, 1) - - err := query.Bind({{$varNameSingular}}Obj) if err != nil { if errors.Cause(err) == sql.ErrNoRows { return nil, sql.ErrNoRows @@ -78,7 +70,7 @@ func FindOne{{$tableNameSingular}}(exec boil.Executor, filters {{$tableNameSingu return nil, errors.Wrap(err, "{{.PkgName}}: unable to select from {{.Table.Name}}") } - return {{$varNameSingular}}Obj, nil + return obj, nil } // FindOne{{$tableNameSingular}}G retrieves a single record using filters. diff --git a/templates/16_update.tpl b/templates/16_update.tpl index 50c7f49..bc4a6f5 100644 --- a/templates/16_update.tpl +++ b/templates/16_update.tpl @@ -101,14 +101,14 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string } // UpdateAllP updates all rows with matching column names, and panics on error. -func (q {{$varNameSingular}}Query) UpdateAllP(cols M) { +func (q {{$tableNameSingular}}Query) UpdateAllP(cols M) { if err := q.UpdateAll(cols); err != nil { panic(boil.WrapErr(err)) } } // UpdateAll updates all rows with the specified column values. -func (q {{$varNameSingular}}Query) UpdateAll(cols M) error { +func (q {{$tableNameSingular}}Query) UpdateAll(cols M) error { queries.SetUpdate(q.Query, cols) _, err := q.Query.Exec() diff --git a/templates/18_delete.tpl b/templates/18_delete.tpl index f2ddbb6..e9a5177 100644 --- a/templates/18_delete.tpl +++ b/templates/18_delete.tpl @@ -65,16 +65,16 @@ func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error { } // DeleteAllP deletes all rows, and panics on error. -func (q {{$varNameSingular}}Query) DeleteAllP() { +func (q {{$tableNameSingular}}Query) DeleteAllP() { if err := q.DeleteAll(); err != nil { panic(boil.WrapErr(err)) } } // DeleteAll deletes all matching rows. -func (q {{$varNameSingular}}Query) DeleteAll() error { +func (q {{$tableNameSingular}}Query) DeleteAll() error { if q.Query == nil { - return errors.New("{{.PkgName}}: no {{$varNameSingular}}Query provided for delete all") + return errors.New("{{.PkgName}}: no {{$tableNameSingular}}Query provided for delete all") } queries.SetDelete(q.Query) diff --git a/templates/22_query.tpl b/templates/22_query.tpl new file mode 100644 index 0000000..512c717 --- /dev/null +++ b/templates/22_query.tpl @@ -0,0 +1,33 @@ +{{- $tableNameSingular := .Table.Name | singular | titleCase -}} + +// {{$tableNameSingular}}NewQuery filters query results +func {{$tableNameSingular}}NewQuery(exec boil.Executor) *{{$tableNameSingular}}Query { + return &{{$tableNameSingular}}Query{NewQuery(exec, qm.Select("*"), qm.From("{{.Table.Name | .SchemaTable}}"))} +} + +// {{$tableNameSingular}}NewQuery filters query results +func {{$tableNameSingular}}NewQueryG() *{{$tableNameSingular}}Query { + return {{$tableNameSingular}}NewQuery(boil.GetDB()) +} + +// Where filters query results +func (q *{{$tableNameSingular}}Query) Where(filters {{$tableNameSingular}}Filter) *{{$tableNameSingular}}Query { + r := reflect.ValueOf(filters) + for i := 0; i < r.NumField(); i++ { + f := r.Field(i) + if f.Elem().IsValid() { + if nullable, ok := f.Elem().Interface().(Nullable); ok && nullable.IsZero() { + queries.AppendWhere(q.Query, r.Type().Field(i).Tag.Get("boil")+" IS NULL") + } else { + queries.AppendWhere(q.Query, r.Type().Field(i).Tag.Get("boil")+" = ?", f.Elem().Interface()) + } + } + } + return q +} + +// Limit limits query results +func (q *{{$tableNameSingular}}Query) Limit(limit int) *{{$tableNameSingular}}Query { + queries.SetLimit(q.Query, limit) + return q +} \ No newline at end of file diff --git a/templates/singleton/boil_types.tpl b/templates/singleton/boil_types.tpl index 9bf13e8..85e05d9 100644 --- a/templates/singleton/boil_types.tpl +++ b/templates/singleton/boil_types.tpl @@ -1,6 +1,11 @@ // M type is for providing columns and column values to UpdateAll. 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 +} + // ErrSyncFail occurs during insert when the record could not be retrieved in // order to populate default value information. This usually happens when LastInsertId // fails or there was a primary key configuration that was not resolvable. From b160e5c1f4eddc9ac9e54e87d13da683f3cd1ede Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Wed, 10 May 2017 11:21:29 -0400 Subject: [PATCH 04/35] dont error if no rows found --- templates/03_finishers.tpl | 2 +- templates/14_find.tpl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/03_finishers.tpl b/templates/03_finishers.tpl index 841769b..13ea14d 100644 --- a/templates/03_finishers.tpl +++ b/templates/03_finishers.tpl @@ -19,7 +19,7 @@ func (q {{$tableNameSingular}}Query) One() (*{{$tableNameSingular}}, error) { err := q.Bind(o) if err != nil { if errors.Cause(err) == sql.ErrNoRows { - return nil, sql.ErrNoRows + return nil, nil } return nil, errors.Wrap(err, "{{.PkgName}}: failed to execute a one query for {{.Table.Name}}") } diff --git a/templates/14_find.tpl b/templates/14_find.tpl index e177959..b7f69db 100644 --- a/templates/14_find.tpl +++ b/templates/14_find.tpl @@ -36,7 +36,7 @@ func Find{{$tableNameSingular}}(exec boil.Executor, {{$pkArgs}}, selectCols ...s err := q.Bind({{$varNameSingular}}Obj) if err != nil { if errors.Cause(err) == sql.ErrNoRows { - return nil, sql.ErrNoRows + return nil, nil } return nil, errors.Wrap(err, "{{.PkgName}}: unable to select from {{.Table.Name}}") } @@ -65,7 +65,7 @@ func FindOne{{$tableNameSingular}}(exec boil.Executor, filters {{$tableNameSingu if err != nil { if errors.Cause(err) == sql.ErrNoRows { - return nil, sql.ErrNoRows + return nil, nil } return nil, errors.Wrap(err, "{{.PkgName}}: unable to select from {{.Table.Name}}") } @@ -81,7 +81,7 @@ func FindOne{{$tableNameSingular}}G(filters {{$tableNameSingular}}Filter) (*{{$t // FindOne{{$tableNameSingular}}OrInit retrieves a single record using filters, or initializes a new record if one is not found. func FindOne{{$tableNameSingular}}OrInit(exec boil.Executor, filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) { {{$varNameSingular}}Obj, err := FindOne{{$tableNameSingular}}(exec, filters) - if err != nil && errors.Cause(err) != sql.ErrNoRows { + if err != nil { return nil, err } From 31fe8b6e1d03d29edb3c639575efc75fb2c5a970 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Wed, 10 May 2017 15:29:02 -0400 Subject: [PATCH 05/35] model merging --- boilingcore/imports.go | 7 ++- templates/23_merge.tpl | 84 ++++++++++++++++++++++++++++ templates/singleton/boil_queries.tpl | 54 ++++++++++++++++++ 3 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 templates/23_merge.tpl diff --git a/boilingcore/imports.go b/boilingcore/imports.go index 1fbca14..fc148c7 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -179,11 +179,16 @@ func newImporter() importer { } imp.Singleton = mapImports{ - "boil_queries": { + "boil_queries": imports{ + standard: importList{ + `"database/sql"`, + `"strings"`, + }, thirdParty: importList{ `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, + `"github.com/pkg/errors"`, }, }, "boil_types": { diff --git a/templates/23_merge.tpl b/templates/23_merge.tpl new file mode 100644 index 0000000..c7e27f5 --- /dev/null +++ b/templates/23_merge.tpl @@ -0,0 +1,84 @@ +{{- $tableNamePlural := .Table.Name | plural | titleCase -}} +{{- $tableNameSingular := .Table.Name | singular | titleCase -}} +{{- if .Table.IsJoinTable -}} +{{- else -}} + {{- $dot := . }} +// Merge combines two {{$tableNamePlural}} into one. The primary record will be kept, and the secondary will be deleted. +func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID uint64) error { + txdb, ok := exec.(boil.Beginner) + if !ok { + return errors.New("database does not support transactions") + } + + tx, txErr := txdb.Begin() + if txErr != nil { + return txErr + } + + primary, err := Find{{$tableNameSingular}}(tx, primaryID) + if err != nil { + tx.Rollback() + return err + } + if primary == nil { + return errors.New("Primary {{$tableNameSingular}} not found") + } + + secondary, err := Find{{$tableNameSingular}}(tx, secondaryID) + if err != nil { + tx.Rollback() + return err + } + if secondary == nil { + return errors.New("Secondary {{$tableNameSingular}} not found") + } + + relatedFields := map[string]string{ + {{- range .Tables -}} + {{- range .FKeys -}} + {{- if eq $dot.Table.Name .ForeignTable }} + "{{.Table }}": "{{ .Column}}", + {{- end -}} + {{- end -}} + {{- end }} + } + err = mergeModels(tx, primaryID, secondaryID, relatedFields) + if err != nil { + tx.Rollback() + return err + } + + pr := reflect.ValueOf(primary) + sr := reflect.ValueOf(secondary) + // for any column thats null on the primary and not null on the secondary, copy from secondary to primary + for i := 0; i < sr.Elem().NumField(); i++ { + pf := pr.Elem().Field(i) + sf := sr.Elem().Field(i) + if sf.IsValid() { + if nullable, ok := sf.Interface().(Nullable); ok && !nullable.IsZero() && pf.Interface().(Nullable).IsZero() { + pf.Set(sf) + } + } + } + + err = primary.Update(tx) + if err != nil { + tx.Rollback() + return errors.WithStack(err) + } + + err = secondary.Delete(tx) + if err != nil { + tx.Rollback() + return errors.WithStack(err) + } + + tx.Commit() + return nil +} + +// Merge combines two {{$tableNamePlural}} into one. The primary record will be kept, and the secondary will be deleted. +func Merge{{$tableNamePlural}}G(primaryID uint64, secondaryID uint64) error { + return Merge{{$tableNamePlural}}(boil.GetDB(), primaryID, secondaryID) +} +{{- end -}}{{/* join table */}} \ No newline at end of file diff --git a/templates/singleton/boil_queries.tpl b/templates/singleton/boil_queries.tpl index 3883e8e..d129e43 100644 --- a/templates/singleton/boil_queries.tpl +++ b/templates/singleton/boil_queries.tpl @@ -19,3 +19,57 @@ func NewQuery(exec boil.Executor, mods ...qm.QueryMod) *queries.Query { return q } + +func mergeModels(tx *sql.Tx, primaryID uint64, secondaryID uint64, relatedFields map[string]string) error { + if len(relatedFields) < 1 { + return nil + } + + for table, column := range relatedFields { + // TODO: use NewQuery here, not plain sql + query := "UPDATE " + table + " SET " + column + " = ? WHERE " + column + " = ?" + _, err := tx.Exec(query, primaryID, secondaryID) + if err != nil { + return errors.WithStack(err) + } + } + return checkMerge(tx, relatedFields) +} + +func checkMerge(tx *sql.Tx, fields map[string]string) error { + columns := []interface{}{} + seenColumns := map[string]bool{} + placeholders := []string{} + for _, column := range fields { + if _, ok := seenColumns[column]; !ok { + columns = append(columns, column) + seenColumns[column] = true + placeholders = append(placeholders, "?") + + } + } + + placeholder := strings.Join(placeholders, ", ") + + q := `SELECT table_name, column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND column_name IN (` + placeholder + `)` + rows, err := tx.Query(q, columns...) + defer rows.Close() + if err != nil { + return errors.WithStack(err) + } + + for rows.Next() { + var tableName string + var columnName string + err = rows.Scan(&tableName, &columnName) + if err != nil { + return errors.WithStack(err) + } + + if _, exists := fields[tableName]; !exists { + return errors.New("Missing merge for " + tableName + "." + columnName) + } + } + + return nil +} From 912a689701a945ccd9034c4227b508dfca353095 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Thu, 11 May 2017 17:42:20 -0400 Subject: [PATCH 06/35] added unique key detection (mysql only for now), improved merging --- bdb/drivers/mock.go | 4 + bdb/drivers/mssql.go | 6 +- bdb/drivers/mysql.go | 42 +++++++++- bdb/drivers/postgres.go | 8 +- bdb/interface.go | 5 ++ bdb/keys.go | 7 ++ bdb/table.go | 1 + boilingcore/imports.go | 3 +- boilingcore/templates.go | 2 +- templates/23_merge.tpl | 23 +++++- templates/singleton/boil_queries.tpl | 116 ++++++++++++++++++++------- templates/singleton/boil_types.tpl | 16 ++++ 12 files changed, 195 insertions(+), 38 deletions(-) diff --git a/bdb/drivers/mock.go b/bdb/drivers/mock.go index 7d14f2a..810eb48 100644 --- a/bdb/drivers/mock.go +++ b/bdb/drivers/mock.go @@ -58,6 +58,10 @@ func (m *MockDriver) Columns(schema, tableName string) ([]bdb.Column, error) { }[tableName], nil } +func (m *MockDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, error) { + return []bdb.UniqueKey{}, nil +} + // ForeignKeyInfo returns a list of mock foreignkeys func (m *MockDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { return map[string][]bdb.ForeignKey{ diff --git a/bdb/drivers/mssql.go b/bdb/drivers/mssql.go index e59330b..70b9ed9 100644 --- a/bdb/drivers/mssql.go +++ b/bdb/drivers/mssql.go @@ -7,8 +7,8 @@ import ( "strings" _ "github.com/denisenkom/go-mssqldb" - "github.com/pkg/errors" "github.com/lbryio/sqlboiler/bdb" + "github.com/pkg/errors" ) // MSSQLDriver holds the database connection string and a handle @@ -241,6 +241,10 @@ func (m *MSSQLDriver) PrimaryKeyInfo(schema, tableName string) (*bdb.PrimaryKey, return pkey, nil } +func (m *MSSQLDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, error) { + return []bdb.UniqueKey{}, errors.New("not implemented") +} + // ForeignKeyInfo retrieves the foreign keys for a given table name. func (m *MSSQLDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { var fkeys []bdb.ForeignKey diff --git a/bdb/drivers/mysql.go b/bdb/drivers/mysql.go index bb73574..6a20ba0 100644 --- a/bdb/drivers/mysql.go +++ b/bdb/drivers/mysql.go @@ -7,8 +7,8 @@ import ( "strings" "github.com/go-sql-driver/mysql" - "github.com/pkg/errors" "github.com/lbryio/sqlboiler/bdb" + "github.com/pkg/errors" ) // TinyintAsBool is a global that is set from main.go if a user specifies @@ -232,6 +232,46 @@ func (m *MySQLDriver) PrimaryKeyInfo(schema, tableName string) (*bdb.PrimaryKey, return pkey, nil } +// UniqueKeyInfo retrieves the unique keys for a given table name. +func (m *MySQLDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, error) { + var ukeys []bdb.UniqueKey + + query := ` + select tc.table_name, tc.constraint_name, GROUP_CONCAT(kcu.column_name) + from information_schema.table_constraints tc + left join information_schema.key_column_usage kcu on tc.constraint_name = kcu.constraint_name and tc.table_name = kcu.table_name and tc.table_schema = kcu.table_schema + where tc.table_schema = ? and tc.table_name = ? and tc.constraint_type = "UNIQUE" + group by tc.table_name, tc.constraint_name + ` + + var rows *sql.Rows + var err error + if rows, err = m.dbConn.Query(query, schema, tableName); err != nil { + return nil, err + } + + for rows.Next() { + var ukey bdb.UniqueKey + var columns string + + //ukey.Table = tableName + err = rows.Scan(&ukey.Table, &ukey.Name, &columns) + if err != nil { + return nil, err + } + + ukey.Columns = strings.Split(columns, ",") + + ukeys = append(ukeys, ukey) + } + + if err = rows.Err(); err != nil { + return nil, err + } + + return ukeys, nil +} + // ForeignKeyInfo retrieves the foreign keys for a given table name. func (m *MySQLDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { var fkeys []bdb.ForeignKey diff --git a/bdb/drivers/postgres.go b/bdb/drivers/postgres.go index ad73a2e..4b6a9f4 100644 --- a/bdb/drivers/postgres.go +++ b/bdb/drivers/postgres.go @@ -8,10 +8,10 @@ import ( // Side-effect import sql driver - _ "github.com/lib/pq" - "github.com/pkg/errors" "github.com/lbryio/sqlboiler/bdb" "github.com/lbryio/sqlboiler/strmangle" + _ "github.com/lib/pq" + "github.com/pkg/errors" ) // PostgresDriver holds the database connection string and a handle @@ -266,6 +266,10 @@ func (p *PostgresDriver) PrimaryKeyInfo(schema, tableName string) (*bdb.PrimaryK return pkey, nil } +func (p *PostgresDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, error) { + return []bdb.UniqueKey{}, errors.New("not implemented") +} + // ForeignKeyInfo retrieves the foreign keys for a given table name. func (p *PostgresDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { var fkeys []bdb.ForeignKey diff --git a/bdb/interface.go b/bdb/interface.go index dfb33bc..1fe179a 100644 --- a/bdb/interface.go +++ b/bdb/interface.go @@ -9,6 +9,7 @@ type Interface interface { TableNames(schema string, whitelist, blacklist []string) ([]string, error) Columns(schema, tableName string) ([]Column, error) PrimaryKeyInfo(schema, tableName string) (*PrimaryKey, error) + UniqueKeyInfo(schema, tableName string) ([]UniqueKey, error) ForeignKeyInfo(schema, tableName string) ([]ForeignKey, error) // TranslateColumnType takes a Database column type and returns a go column type. @@ -63,6 +64,10 @@ func Tables(db Interface, schema string, whitelist, blacklist []string) ([]Table return nil, errors.Wrapf(err, "unable to fetch table pkey info (%s)", name) } + if t.UKeys, err = db.UniqueKeyInfo(schema, name); err != nil { + return nil, errors.Wrapf(err, "unable to fetch table ukey info (%s)", name) + } + if t.FKeys, err = db.ForeignKeyInfo(schema, name); err != nil { return nil, errors.Wrapf(err, "unable to fetch table fkey info (%s)", name) } diff --git a/bdb/keys.go b/bdb/keys.go index 909ada2..8007843 100644 --- a/bdb/keys.go +++ b/bdb/keys.go @@ -8,6 +8,13 @@ type PrimaryKey struct { Columns []string } +// UniqueKey represents a unique key constraint in a database +type UniqueKey struct { + Table string + Name string + Columns []string +} + // ForeignKey represents a foreign key constraint in a database type ForeignKey struct { Table string diff --git a/bdb/table.go b/bdb/table.go index 62dcd32..d5cbb50 100644 --- a/bdb/table.go +++ b/bdb/table.go @@ -11,6 +11,7 @@ type Table struct { Columns []Column PKey *PrimaryKey + UKeys []UniqueKey FKeys []ForeignKey IsJoinTable bool diff --git a/boilingcore/imports.go b/boilingcore/imports.go index fc148c7..62b15bb 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -182,12 +182,13 @@ func newImporter() importer { "boil_queries": imports{ standard: importList{ `"database/sql"`, - `"strings"`, + `"fmt"`, }, thirdParty: importList{ `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, + `"github.com/lbryio/sqlboiler/strmangle"`, `"github.com/pkg/errors"`, }, }, diff --git a/boilingcore/templates.go b/boilingcore/templates.go index 62c0ae5..86c78ce 100644 --- a/boilingcore/templates.go +++ b/boilingcore/templates.go @@ -8,10 +8,10 @@ import ( "strings" "text/template" - "github.com/pkg/errors" "github.com/lbryio/sqlboiler/bdb" "github.com/lbryio/sqlboiler/queries" "github.com/lbryio/sqlboiler/strmangle" + "github.com/pkg/errors" ) // templateData for sqlboiler templates diff --git a/templates/23_merge.tpl b/templates/23_merge.tpl index c7e27f5..35ca404 100644 --- a/templates/23_merge.tpl +++ b/templates/23_merge.tpl @@ -33,16 +33,33 @@ func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID return errors.New("Secondary {{$tableNameSingular}} not found") } - relatedFields := map[string]string{ + foreignKeys := []foreignKey{ {{- range .Tables -}} {{- range .FKeys -}} {{- if eq $dot.Table.Name .ForeignTable }} - "{{.Table }}": "{{ .Column}}", + {foreignTable: "{{.Table}}", foreignColumn: "{{.Column}}"}, {{- end -}} {{- end -}} {{- end }} } - err = mergeModels(tx, primaryID, secondaryID, relatedFields) + + conflictingKeys := []conflictingUniqueKey{ + {{- range .Tables -}} + {{- $table := . -}} + {{- range .FKeys -}} + {{- $fk := . -}} + {{- if eq $dot.Table.Name .ForeignTable -}} + {{- range $table.UKeys -}} + {{- if setInclude $fk.Column .Columns }} + {table: "{{$fk.Table}}", objectIdColumn: "{{$fk.Column}}", columns: []string{`{{ .Columns | join "`,`" }}`}}, + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end }} + } + + err = mergeModels(tx, primaryID, secondaryID, foreignKeys, conflictingKeys) if err != nil { tx.Rollback() return err diff --git a/templates/singleton/boil_queries.tpl b/templates/singleton/boil_queries.tpl index d129e43..8ff4edd 100644 --- a/templates/singleton/boil_queries.tpl +++ b/templates/singleton/boil_queries.tpl @@ -20,39 +20,97 @@ func NewQuery(exec boil.Executor, mods ...qm.QueryMod) *queries.Query { return q } -func mergeModels(tx *sql.Tx, primaryID uint64, secondaryID uint64, relatedFields map[string]string) error { - if len(relatedFields) < 1 { - return nil - } - - for table, column := range relatedFields { - // TODO: use NewQuery here, not plain sql - query := "UPDATE " + table + " SET " + column + " = ? WHERE " + column + " = ?" - _, err := tx.Exec(query, primaryID, secondaryID) - if err != nil { - return errors.WithStack(err) - } - } - return checkMerge(tx, relatedFields) -} - -func checkMerge(tx *sql.Tx, fields map[string]string) error { - columns := []interface{}{} - seenColumns := map[string]bool{} - placeholders := []string{} - for _, column := range fields { - if _, ok := seenColumns[column]; !ok { - columns = append(columns, column) - seenColumns[column] = true - placeholders = append(placeholders, "?") +func mergeModels(tx *sql.Tx, primaryID uint64, secondaryID uint64, foreignKeys []foreignKey, conflictingKeys []conflictingUniqueKey) error { + if len(foreignKeys) < 1 { + return nil + } + var err error + for _, conflict := range conflictingKeys { + err = deleteConflictsBeforeMerge(tx, conflict, primaryID, secondaryID) + if err != nil { + return errors.WithStack(err) } } - placeholder := strings.Join(placeholders, ", ") + for _, fk := range foreignKeys { + // TODO: use NewQuery here, not plain sql + query := fmt.Sprintf( + "UPDATE %s SET %s = %s WHERE %s = %s", + fk.foreignTable, fk.foreignColumn, strmangle.Placeholders(dialect.IndexPlaceholders, 1, 1, 1), + fk.foreignColumn, strmangle.Placeholders(dialect.IndexPlaceholders, 1, 2, 1), + ) + _, err = tx.Exec(query, primaryID, secondaryID) + if err != nil { + return errors.WithStack(err) + } + } + return checkMerge(tx, foreignKeys) +} - q := `SELECT table_name, column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND column_name IN (` + placeholder + `)` - rows, err := tx.Query(q, columns...) +func deleteConflictsBeforeMerge(tx *sql.Tx, conflict conflictingUniqueKey, primaryID uint64, secondaryID uint64) error { + conflictingColumns := strmangle.SetComplement(conflict.columns, []string{conflict.objectIdColumn}) + + if len(conflictingColumns) < 1 { + return nil + } else if len(conflictingColumns) > 1 { + return errors.New("this doesnt work for unique keys with more than two columns (yet)") + } + + query := fmt.Sprintf( + "SELECT %s FROM %s WHERE %s IN (%s) GROUP BY %s HAVING count(distinct %s) > 1", + conflictingColumns[0], conflict.table, conflict.objectIdColumn, + strmangle.Placeholders(dialect.IndexPlaceholders, 2, 1, 1), + conflictingColumns[0], conflict.objectIdColumn, + ) + + rows, err := tx.Query(query, primaryID, secondaryID) + defer rows.Close() + if err != nil { + return errors.WithStack(err) + } + + args := []interface{}{secondaryID} + for rows.Next() { + var value string + err = rows.Scan(&value) + if err != nil { + return errors.WithStack(err) + } + args = append(args, value) + } + + query = fmt.Sprintf( + "DELETE FROM %s WHERE %s = %s AND %s IN (%s)", + conflict.table, conflict.objectIdColumn, strmangle.Placeholders(dialect.IndexPlaceholders, 1, 1, 1), + conflictingColumns[0], strmangle.Placeholders(dialect.IndexPlaceholders, len(args)-1, 2, 1), + ) + + _, err = tx.Exec(query, args...) + if err != nil { + return errors.WithStack(err) + } + return nil +} + +func checkMerge(tx *sql.Tx, foreignKeys []foreignKey) error { + uniqueColumns := []interface{}{} + uniqueColumnNames := map[string]bool{} + handledTablesColumns := map[string]bool{} + + for _, fk := range foreignKeys { + handledTablesColumns[fk.foreignTable+"."+fk.foreignColumn] = true + if _, ok := uniqueColumnNames[fk.foreignColumn]; !ok { + uniqueColumns = append(uniqueColumns, fk.foreignColumn) + uniqueColumnNames[fk.foreignColumn] = true + } + } + + q := fmt.Sprintf( + `SELECT table_name, column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND column_name IN (%s)`, + strmangle.Placeholders(dialect.IndexPlaceholders, len(uniqueColumns), 1, 1), + ) + rows, err := tx.Query(q, uniqueColumns...) defer rows.Close() if err != nil { return errors.WithStack(err) @@ -66,7 +124,7 @@ func checkMerge(tx *sql.Tx, fields map[string]string) error { return errors.WithStack(err) } - if _, exists := fields[tableName]; !exists { + if _, exists := handledTablesColumns[tableName+"."+columnName]; !exists { return errors.New("Missing merge for " + tableName + "." + columnName) } } diff --git a/templates/singleton/boil_types.tpl b/templates/singleton/boil_types.tpl index 85e05d9..aa61bf9 100644 --- a/templates/singleton/boil_types.tpl +++ b/templates/singleton/boil_types.tpl @@ -6,6 +6,22 @@ type Nullable interface { IsZero() bool } +// foreignKey connects two tables. When merging records, foreign keys from secondary record must +// be reassigned to primary record. +type foreignKey struct { + foreignTable string + foreignColumn string +} + +// conflictingUniqueKey records a merge conflict. If two rows exist with the same value in the +// conflicting column for two records being merged, one row must be deleted. +type conflictingUniqueKey struct { + table string + objectIdColumn string + columns []string +} + + // ErrSyncFail occurs during insert when the record could not be retrieved in // order to populate default value information. This usually happens when LastInsertId // fails or there was a primary key configuration that was not resolvable. From 09c585cdb1056fc48c59541b0c66f20a81282a25 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Thu, 1 Jun 2017 09:58:50 -0400 Subject: [PATCH 07/35] dont run delete query when there's nothing to delete --- templates/singleton/boil_queries.tpl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/templates/singleton/boil_queries.tpl b/templates/singleton/boil_queries.tpl index 8ff4edd..248fae1 100644 --- a/templates/singleton/boil_queries.tpl +++ b/templates/singleton/boil_queries.tpl @@ -80,6 +80,11 @@ func deleteConflictsBeforeMerge(tx *sql.Tx, conflict conflictingUniqueKey, prima args = append(args, value) } + // if no rows found, no need to delete anything + if len(args) < 2 { + return nil + } + query = fmt.Sprintf( "DELETE FROM %s WHERE %s = %s AND %s IN (%s)", conflict.table, conflict.objectIdColumn, strmangle.Placeholders(dialect.IndexPlaceholders, 1, 1, 1), From ed423a360605cf1d4309cc78d969fce5674d7aea Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Mon, 12 Jun 2017 14:02:04 -0400 Subject: [PATCH 08/35] detect autoincrement column, fix lastID in upsert when update doesnt change anything --- bdb/drivers/mock.go | 4 ++++ bdb/drivers/mssql.go | 4 ++++ bdb/drivers/mysql.go | 32 ++++++++++++++++++++++++++++++++ bdb/drivers/postgres.go | 4 ++++ bdb/interface.go | 5 +++++ bdb/table.go | 4 +++- main.go | 6 +++--- queries/query_builders.go | 7 ++++++- templates/01_types.tpl | 1 + templates/17_upsert.tpl | 2 +- 10 files changed, 63 insertions(+), 6 deletions(-) diff --git a/bdb/drivers/mock.go b/bdb/drivers/mock.go index 810eb48..d8a5aa0 100644 --- a/bdb/drivers/mock.go +++ b/bdb/drivers/mock.go @@ -62,6 +62,10 @@ func (m *MockDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, e return []bdb.UniqueKey{}, nil } +func (m *MockDriver) AutoincrementInfo(schema, tableName string) (string, error) { + return "", nil +} + // ForeignKeyInfo returns a list of mock foreignkeys func (m *MockDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { return map[string][]bdb.ForeignKey{ diff --git a/bdb/drivers/mssql.go b/bdb/drivers/mssql.go index 70b9ed9..79f3010 100644 --- a/bdb/drivers/mssql.go +++ b/bdb/drivers/mssql.go @@ -245,6 +245,10 @@ func (m *MSSQLDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, return []bdb.UniqueKey{}, errors.New("not implemented") } +func (m *MSSQLDriver) AutoincrementInfo(schema, tableName string) (string, error) { + return "", errors.New("not implemented") +} + // ForeignKeyInfo retrieves the foreign keys for a given table name. func (m *MSSQLDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { var fkeys []bdb.ForeignKey diff --git a/bdb/drivers/mysql.go b/bdb/drivers/mysql.go index 6a20ba0..41510ee 100644 --- a/bdb/drivers/mysql.go +++ b/bdb/drivers/mysql.go @@ -272,6 +272,38 @@ func (m *MySQLDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, return ukeys, nil } +// AutoincrementInfo retrieves the autoincrement column for a given table name, if one exists. +func (m *MySQLDriver) AutoincrementInfo(schema, tableName string) (string, error) { + query := ` + select column_name + from information_schema.columns + where table_schema = ? and table_name = ? and extra like "%auto_increment%" + ` + + var rows *sql.Rows + var err error + if rows, err = m.dbConn.Query(query, schema, tableName); err != nil { + return "", err + } + + for rows.Next() { + var column string + + err = rows.Scan(&column) + if err != nil { + return "", err + } + + return column, nil + } + + if err = rows.Err(); err != nil { + return "", err + } + + return "", nil +} + // ForeignKeyInfo retrieves the foreign keys for a given table name. func (m *MySQLDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { var fkeys []bdb.ForeignKey diff --git a/bdb/drivers/postgres.go b/bdb/drivers/postgres.go index 4b6a9f4..9af7edd 100644 --- a/bdb/drivers/postgres.go +++ b/bdb/drivers/postgres.go @@ -270,6 +270,10 @@ func (p *PostgresDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKe return []bdb.UniqueKey{}, errors.New("not implemented") } +func (p *PostgresDriver) AutoincrementInfo(schema, tableName string) (string, error) { + return "", errors.New("not implemented") +} + // ForeignKeyInfo retrieves the foreign keys for a given table name. func (p *PostgresDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { var fkeys []bdb.ForeignKey diff --git a/bdb/interface.go b/bdb/interface.go index 1fe179a..7f4baa5 100644 --- a/bdb/interface.go +++ b/bdb/interface.go @@ -10,6 +10,7 @@ type Interface interface { Columns(schema, tableName string) ([]Column, error) PrimaryKeyInfo(schema, tableName string) (*PrimaryKey, error) UniqueKeyInfo(schema, tableName string) ([]UniqueKey, error) + AutoincrementInfo(schema, tableName string) (string, error) ForeignKeyInfo(schema, tableName string) ([]ForeignKey, error) // TranslateColumnType takes a Database column type and returns a go column type. @@ -72,6 +73,10 @@ func Tables(db Interface, schema string, whitelist, blacklist []string) ([]Table return nil, errors.Wrapf(err, "unable to fetch table fkey info (%s)", name) } + if t.AutoIncrementColumn, err = db.AutoincrementInfo(schema, name); err != nil { + return nil, errors.Wrapf(err, "unable to fetch table autoincrement info (%s)", name) + } + setIsJoinTable(&t) tables = append(tables, t) diff --git a/bdb/table.go b/bdb/table.go index d5cbb50..13355aa 100644 --- a/bdb/table.go +++ b/bdb/table.go @@ -8,7 +8,9 @@ type Table struct { // For dbs with real schemas, like Postgres. // Example value: "schema_name"."table_name" SchemaName string - Columns []Column + + Columns []Column + AutoIncrementColumn string PKey *PrimaryKey UKeys []UniqueKey diff --git a/main.go b/main.go index 5103116..8344e57 100644 --- a/main.go +++ b/main.go @@ -8,13 +8,13 @@ import ( "strings" "github.com/kat-co/vala" - "github.com/spf13/cobra" - "github.com/spf13/viper" "github.com/lbryio/sqlboiler/bdb/drivers" "github.com/lbryio/sqlboiler/boilingcore" + "github.com/spf13/cobra" + "github.com/spf13/viper" ) -const sqlBoilerVersion = "2.3.0" +const sqlBoilerVersion = "2.4.0+lbry" var ( cmdState *boilingcore.State diff --git a/queries/query_builders.go b/queries/query_builders.go index d221aca..f884f91 100644 --- a/queries/query_builders.go +++ b/queries/query_builders.go @@ -190,7 +190,7 @@ func buildUpdateQuery(q *Query) (*bytes.Buffer, []interface{}) { } // BuildUpsertQueryMySQL builds a SQL statement string using the upsertData provided. -func BuildUpsertQueryMySQL(dia Dialect, tableName string, update, whitelist []string) string { +func BuildUpsertQueryMySQL(dia Dialect, tableName string, update, whitelist []string, autoIncrementCol string) string { whitelist = strmangle.IdentQuoteSlice(dia.LQ, dia.RQ, whitelist) buf := strmangle.GetBuffer() @@ -220,6 +220,11 @@ func BuildUpsertQueryMySQL(dia Dialect, tableName string, update, whitelist []st strmangle.Placeholders(dia.IndexPlaceholders, len(whitelist), 1, 1), ) + // https://stackoverflow.com/questions/778534/mysql-on-duplicate-key-last-insert-id + if autoIncrementCol != "" { + buf.WriteString(autoIncrementCol + " = LAST_INSERT_ID(" + autoIncrementCol + "), ") + } + for i, v := range update { if i != 0 { buf.WriteByte(',') diff --git a/templates/01_types.tpl b/templates/01_types.tpl index 9340e42..5aac35f 100644 --- a/templates/01_types.tpl +++ b/templates/01_types.tpl @@ -10,6 +10,7 @@ var ( {{$varNameSingular}}ColumnsWithoutDefault = []string{{"{"}}{{.Table.Columns | filterColumnsByDefault false | columnNames | stringMap .StringFuncs.quoteWrap | join ","}}{{"}"}} {{$varNameSingular}}ColumnsWithDefault = []string{{"{"}}{{.Table.Columns | filterColumnsByDefault true | columnNames | stringMap .StringFuncs.quoteWrap | join ","}}{{"}"}} {{$varNameSingular}}PrimaryKeyColumns = []string{{"{"}}{{.Table.PKey.Columns | stringMap .StringFuncs.quoteWrap | join ", "}}{{"}"}} + {{$varNameSingular}}AutoIncrementColumn = "{{.Table.AutoIncrementColumn }}" ) type ( diff --git a/templates/17_upsert.tpl b/templates/17_upsert.tpl index f3d51e7..dbce58c 100644 --- a/templates/17_upsert.tpl +++ b/templates/17_upsert.tpl @@ -115,7 +115,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName } cache.query = queries.BuildUpsertQueryPostgres(dialect, "{{$schemaTable}}", updateOnConflict, ret, update, conflict, insert) {{else if eq .DriverName "mysql"}} - cache.query = queries.BuildUpsertQueryMySQL(dialect, "{{.Table.Name}}", update, insert) + cache.query = queries.BuildUpsertQueryMySQL(dialect, "{{.Table.Name}}", update, insert, {{$varNameSingular}}AutoIncrementColumn) cache.retQuery = fmt.Sprintf( "SELECT %s FROM {{.LQ}}{{.Table.Name}}{{.RQ}} WHERE {{whereClause .LQ .RQ 0 .Table.PKey.Columns}}", strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, ret), ","), From 05c7f7d06a7f9c1a1c845a91ee04c9020e8e7ba3 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Thu, 6 Jul 2017 15:15:00 -0400 Subject: [PATCH 09/35] switch to more complete null package, implement nicer sql logging --- boilingcore/imports.go | 42 +++++---- boilingcore/imports_test.go | 10 +- queries/helpers_test.go | 2 +- queries/query.go | 94 +++++++++++++++++-- randomize/randomize.go | 2 +- randomize/randomize_test.go | 2 +- templates/07_relationship_to_one_eager.tpl | 6 +- .../08_relationship_one_to_one_eager.tpl | 6 +- templates/09_relationship_to_many_eager.tpl | 6 +- templates/10_relationship_to_one_setops.tpl | 7 +- .../11_relationship_one_to_one_setops.tpl | 7 +- templates/12_relationship_to_many_setops.tpl | 28 ++++-- templates/15_insert.tpl | 14 ++- templates/16_update.tpl | 14 ++- templates/17_upsert.tpl | 14 ++- templates/18_delete.tpl | 40 ++++---- templates/20_exists.tpl | 7 +- templates/22_query.tpl | 2 +- templates/23_merge.tpl | 2 +- templates/singleton/boil_queries.tpl | 66 +++++++++++++ templates/singleton/boil_types.tpl | 5 - 21 files changed, 291 insertions(+), 85 deletions(-) diff --git a/boilingcore/imports.go b/boilingcore/imports.go index 62b15bb..2c31c63 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -170,11 +170,12 @@ func newImporter() importer { `"time"`, }, thirdParty: importList{ - `"github.com/pkg/errors"`, + `"github.com/lbryio/null.go"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, `"github.com/lbryio/sqlboiler/strmangle"`, + `"github.com/pkg/errors"`, }, } @@ -183,6 +184,10 @@ func newImporter() importer { standard: importList{ `"database/sql"`, `"fmt"`, + `"reflect"`, + `"strconv"`, + `"strings"`, + `"time"`, }, thirdParty: importList{ `"github.com/lbryio/sqlboiler/boil"`, @@ -190,6 +195,7 @@ func newImporter() importer { `"github.com/lbryio/sqlboiler/queries/qm"`, `"github.com/lbryio/sqlboiler/strmangle"`, `"github.com/pkg/errors"`, + `"github.com/lbryio/null.go"`, }, }, "boil_types": { @@ -315,55 +321,55 @@ func newImporter() importer { // TranslateColumnType to see the type assignments. imp.BasedOnType = mapImports{ "null.Float32": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Float64": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Int": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Int8": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Int16": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Int32": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Int64": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Uint": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Uint8": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Uint16": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Uint32": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Uint64": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.String": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Bool": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Time": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.JSON": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "null.Bytes": { - thirdParty: importList{`"gopkg.in/nullbio/null.v6"`}, + thirdParty: importList{`"github.com/lbryio/null.go"`}, }, "time.Time": { standard: importList{`"time"`}, diff --git a/boilingcore/imports_test.go b/boilingcore/imports_test.go index ff2362d..b25eece 100644 --- a/boilingcore/imports_test.go +++ b/boilingcore/imports_test.go @@ -246,7 +246,7 @@ func TestCombineTypeImports(t *testing.T) { }, thirdParty: importList{ `"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{ `"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{ 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{ standard: importList{"os"}, @@ -309,8 +309,8 @@ func TestCombineImports(t *testing.T) { if c.standard[0] != "fmt" && c.standard[1] != "os" { 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" { - t.Errorf("Wanted: github.com/lbryio/sqlboiler, gopkg.in/nullbio/null.v6 got: %#v", c.thirdParty) + if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "github.com/lbryio/null.go" { + t.Errorf("Wanted: github.com/lbryio/sqlboiler, github.com/lbryio/null.go got: %#v", c.thirdParty) } } diff --git a/queries/helpers_test.go b/queries/helpers_test.go index d37fcd9..ab4b4ac 100644 --- a/queries/helpers_test.go +++ b/queries/helpers_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - null "gopkg.in/nullbio/null.v6" + null "github.com/lbryio/null.go" ) type testObj struct { diff --git a/queries/query.go b/queries/query.go index be539e5..b3ff830 100644 --- a/queries/query.go +++ b/queries/query.go @@ -3,8 +3,15 @@ package queries import ( "database/sql" "fmt" + "reflect" + "strconv" + "strings" + "time" + "github.com/lbryio/null.go" "github.com/lbryio/sqlboiler/boil" + + "github.com/go-errors/errors" ) // joinKind is the type of join @@ -105,8 +112,11 @@ func RawG(query string, args ...interface{}) *Query { func (q *Query) Exec() (sql.Result, error) { qs, args := buildQuery(q) if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, qs) - fmt.Fprintln(boil.DebugWriter, args) + qStr, err := interpolateParams(qs, args...) + if err != nil { + return nil, err + } + fmt.Fprintln(boil.DebugWriter, qStr) } return q.executor.Exec(qs, args...) } @@ -115,8 +125,11 @@ func (q *Query) Exec() (sql.Result, error) { func (q *Query) QueryRow() *sql.Row { qs, args := buildQuery(q) if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, qs) - fmt.Fprintln(boil.DebugWriter, args) + qStr, err := interpolateParams(qs, args...) + if err != nil { + panic(err) + } + fmt.Fprintln(boil.DebugWriter, qStr) } return q.executor.QueryRow(qs, args...) } @@ -125,8 +138,11 @@ func (q *Query) QueryRow() *sql.Row { func (q *Query) Query() (*sql.Rows, error) { qs, args := buildQuery(q) if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, qs) - fmt.Fprintln(boil.DebugWriter, args) + qStr, err := interpolateParams(qs, args...) + if err != nil { + return nil, err + } + fmt.Fprintln(boil.DebugWriter, qStr) } return q.executor.Query(qs, args...) } @@ -280,3 +296,69 @@ func AppendGroupBy(q *Query, clause string) { func AppendOrderBy(q *Query, clause string) { 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 +} diff --git a/randomize/randomize.go b/randomize/randomize.go index ea99c43..8deb88d 100644 --- a/randomize/randomize.go +++ b/randomize/randomize.go @@ -14,7 +14,7 @@ import ( "sync/atomic" "time" - null "gopkg.in/nullbio/null.v6" + null "github.com/lbryio/null.go" "github.com/pkg/errors" "github.com/satori/go.uuid" diff --git a/randomize/randomize_test.go b/randomize/randomize_test.go index 6f117b7..ccef115 100644 --- a/randomize/randomize_test.go +++ b/randomize/randomize_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - null "gopkg.in/nullbio/null.v6" + null "github.com/lbryio/null.go" ) func TestRandomizeStruct(t *testing.T) { diff --git a/templates/07_relationship_to_one_eager.tpl b/templates/07_relationship_to_one_eager.tpl index 3b24f1a..3bf42f4 100644 --- a/templates/07_relationship_to_one_eager.tpl +++ b/templates/07_relationship_to_one_eager.tpl @@ -40,7 +40,11 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula ) 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...) diff --git a/templates/08_relationship_one_to_one_eager.tpl b/templates/08_relationship_one_to_one_eager.tpl index 37d1af0..1fbf5f7 100644 --- a/templates/08_relationship_one_to_one_eager.tpl +++ b/templates/08_relationship_one_to_one_eager.tpl @@ -40,7 +40,11 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula ) 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...) diff --git a/templates/09_relationship_to_many_eager.tpl b/templates/09_relationship_to_many_eager.tpl index 1603188..3ec5bf9 100644 --- a/templates/09_relationship_to_many_eager.tpl +++ b/templates/09_relationship_to_many_eager.tpl @@ -49,7 +49,11 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula {{end -}} 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...) diff --git a/templates/10_relationship_to_one_setops.tpl b/templates/10_relationship_to_one_setops.tpl index 14f726e..b293b48 100644 --- a/templates/10_relationship_to_one_setops.tpl +++ b/templates/10_relationship_to_one_setops.tpl @@ -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."}}{{"}"}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, updateQuery) - fmt.Fprintln(boil.DebugWriter, values) + qStr, err := interpolateParams(updateQuery, values...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } if _, err = exec.Exec(updateQuery, values...); err != nil { diff --git a/templates/11_relationship_one_to_one_setops.tpl b/templates/11_relationship_one_to_one_setops.tpl index 826eec2..d4583ca 100644 --- a/templates/11_relationship_one_to_one_setops.tpl +++ b/templates/11_relationship_one_to_one_setops.tpl @@ -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."}}{{"}"}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, updateQuery) - fmt.Fprintln(boil.DebugWriter, values) + qStr, err := interpolateParams(updateQuery, values...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } if _, err = exec.Exec(updateQuery, values...); err != nil { diff --git a/templates/12_relationship_to_many_setops.tpl b/templates/12_relationship_to_many_setops.tpl index 06159ee..35a4bd4 100644 --- a/templates/12_relationship_to_many_setops.tpl +++ b/templates/12_relationship_to_many_setops.tpl @@ -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."}}{{"}"}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, updateQuery) - fmt.Fprintln(boil.DebugWriter, values) + qStr, err := interpolateParams(updateQuery, values...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } 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}}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, query) - fmt.Fprintln(boil.DebugWriter, values) + qStr, err := interpolateParams(query, values...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } _, 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}}} {{end -}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, query) - fmt.Fprintln(boil.DebugWriter, values) + qStr, err := interpolateParams(query, values...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } _, err := exec.Exec(query, values...) @@ -260,8 +269,11 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Exec } if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, query) - fmt.Fprintln(boil.DebugWriter, values) + qStr, err := interpolateParams(query, values...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } _, err = exec.Exec(query, values...) diff --git a/templates/15_insert.tpl b/templates/15_insert.tpl index 870e20d..8cd30b9 100644 --- a/templates/15_insert.tpl +++ b/templates/15_insert.tpl @@ -98,8 +98,11 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string vals := queries.ValuesFromMapping(value, cache.valueMapping) if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, cache.query) - fmt.Fprintln(boil.DebugWriter, vals) + qStr, err := interpolateParams(cache.query, vals...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } {{if .UseLastInsertID -}} @@ -144,8 +147,11 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string } if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, cache.retQuery) - fmt.Fprintln(boil.DebugWriter, identifierCols...) + qStr, err := interpolateParams(cache.retQuery, identifierCols...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...) diff --git a/templates/16_update.tpl b/templates/16_update.tpl index bc4a6f5..1ac460b 100644 --- a/templates/16_update.tpl +++ b/templates/16_update.tpl @@ -78,8 +78,11 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping) if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, cache.query) - fmt.Fprintln(boil.DebugWriter, values) + qStr, err := interpolateParams(cache.query, values...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } _, 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))) if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, sql) - fmt.Fprintln(boil.DebugWriter, args...) + qStr, err := interpolateParams(sql, args...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } _, err := exec.Exec(sql, args...) diff --git a/templates/17_upsert.tpl b/templates/17_upsert.tpl index dbce58c..5cf6a14 100644 --- a/templates/17_upsert.tpl +++ b/templates/17_upsert.tpl @@ -147,8 +147,11 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName } if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, cache.query) - fmt.Fprintln(boil.DebugWriter, vals) + qStr, err := interpolateParams(cache.query, vals...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } {{if .UseLastInsertID -}} @@ -193,8 +196,11 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName } if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, cache.retQuery) - fmt.Fprintln(boil.DebugWriter, identifierCols...) + qStr, err := interpolateParams(cache.retQuery, identifierCols...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(returns...) diff --git a/templates/18_delete.tpl b/templates/18_delete.tpl index e9a5177..20e819a 100644 --- a/templates/18_delete.tpl +++ b/templates/18_delete.tpl @@ -6,7 +6,7 @@ // Panics on error. func (o *{{$tableNameSingular}}) DeleteP(exec boil.Executor) { if err := o.Delete(exec); err != nil { - panic(boil.WrapErr(err)) + panic(boil.WrapErr(err)) } } @@ -14,7 +14,7 @@ func (o *{{$tableNameSingular}}) DeleteP(exec boil.Executor) { // DeleteG will match against the primary key column to find the record to delete. func (o *{{$tableNameSingular}}) DeleteG() error { if o == nil { - return errors.New("{{.PkgName}}: no {{$tableNameSingular}} provided for deletion") + return errors.New("{{.PkgName}}: no {{$tableNameSingular}} provided for deletion") } return o.Delete(boil.GetDB()) @@ -25,7 +25,7 @@ func (o *{{$tableNameSingular}}) DeleteG() error { // Panics on error. func (o *{{$tableNameSingular}}) DeleteGP() { if err := o.DeleteG(); err != nil { - panic(boil.WrapErr(err)) + panic(boil.WrapErr(err)) } } @@ -33,12 +33,12 @@ func (o *{{$tableNameSingular}}) DeleteGP() { // Delete will match against the primary key column to find the record to delete. func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error { if o == nil { - return errors.New("{{.PkgName}}: no {{$tableNameSingular}} provided for delete") + return errors.New("{{.PkgName}}: no {{$tableNameSingular}} provided for delete") } {{if not .NoHooks -}} if err := o.doBeforeDeleteHooks(exec); err != nil { - return err + return err } {{- end}} @@ -46,18 +46,21 @@ 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}}" if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, sql) - fmt.Fprintln(boil.DebugWriter, args...) + qStr, err := interpolateParams(sql, args...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } _, err := exec.Exec(sql, args...) if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to delete from {{.Table.Name}}") + return errors.Wrap(err, "{{.PkgName}}: unable to delete from {{.Table.Name}}") } {{if not .NoHooks -}} if err := o.doAfterDeleteHooks(exec); err != nil { - return err + return err } {{- end}} @@ -67,21 +70,21 @@ func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error { // DeleteAllP deletes all rows, and panics on error. func (q {{$tableNameSingular}}Query) DeleteAllP() { if err := q.DeleteAll(); err != nil { - panic(boil.WrapErr(err)) + panic(boil.WrapErr(err)) } } // DeleteAll deletes all matching rows. func (q {{$tableNameSingular}}Query) DeleteAll() error { if q.Query == nil { - return errors.New("{{.PkgName}}: no {{$tableNameSingular}}Query provided for delete all") + return errors.New("{{.PkgName}}: no {{$tableNameSingular}}Query provided for delete all") } queries.SetDelete(q.Query) _, err := q.Query.Exec() if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to delete all from {{.Table.Name}}") + return errors.Wrap(err, "{{.PkgName}}: unable to delete all from {{.Table.Name}}") } return nil @@ -90,14 +93,14 @@ func (q {{$tableNameSingular}}Query) DeleteAll() error { // DeleteAllGP deletes all rows in the slice, and panics on error. func (o {{$tableNameSingular}}Slice) DeleteAllGP() { if err := o.DeleteAllG(); err != nil { - panic(boil.WrapErr(err)) + panic(boil.WrapErr(err)) } } // DeleteAllG deletes all rows in the slice. func (o {{$tableNameSingular}}Slice) DeleteAllG() error { if o == nil { - return errors.New("{{.PkgName}}: no {{$tableNameSingular}} slice provided for delete all") + return errors.New("{{.PkgName}}: no {{$tableNameSingular}} slice provided for delete all") } return o.DeleteAll(boil.GetDB()) } @@ -105,7 +108,7 @@ func (o {{$tableNameSingular}}Slice) DeleteAllG() error { // DeleteAllP deletes all rows in the slice, using an executor, and panics on error. func (o {{$tableNameSingular}}Slice) DeleteAllP(exec boil.Executor) { if err := o.DeleteAll(exec); err != nil { - panic(boil.WrapErr(err)) + panic(boil.WrapErr(err)) } } @@ -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)) if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, sql) - fmt.Fprintln(boil.DebugWriter, args) + qStr, err := interpolateParams(sql, args...) + if err != nil { + return err + } + fmt.Fprintln(boil.DebugWriter, qStr) } _, err := exec.Exec(sql, args...) diff --git a/templates/20_exists.tpl b/templates/20_exists.tpl index 2e20fa6..4c4031a 100644 --- a/templates/20_exists.tpl +++ b/templates/20_exists.tpl @@ -14,8 +14,11 @@ func {{$tableNameSingular}}Exists(exec boil.Executor, {{$pkArgs}}) (bool, error) {{- end}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, sql) - fmt.Fprintln(boil.DebugWriter, {{$pkNames | join ", "}}) + qStr, err := interpolateParams(sql, {{$pkNames | join ", "}}) + if err != nil { + return false, err + } + fmt.Fprintln(boil.DebugWriter, qStr) } row := exec.QueryRow(sql, {{$pkNames | join ", "}}) diff --git a/templates/22_query.tpl b/templates/22_query.tpl index 512c717..2dcf973 100644 --- a/templates/22_query.tpl +++ b/templates/22_query.tpl @@ -16,7 +16,7 @@ func (q *{{$tableNameSingular}}Query) Where(filters {{$tableNameSingular}}Filter for i := 0; i < r.NumField(); i++ { f := r.Field(i) 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") } else { queries.AppendWhere(q.Query, r.Type().Field(i).Tag.Get("boil")+" = ?", f.Elem().Interface()) diff --git a/templates/23_merge.tpl b/templates/23_merge.tpl index 35ca404..6b5cdd2 100644 --- a/templates/23_merge.tpl +++ b/templates/23_merge.tpl @@ -72,7 +72,7 @@ func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID pf := pr.Elem().Field(i) sf := sr.Elem().Field(i) 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) } } diff --git a/templates/singleton/boil_queries.tpl b/templates/singleton/boil_queries.tpl index 248fae1..11f103b 100644 --- a/templates/singleton/boil_queries.tpl +++ b/templates/singleton/boil_queries.tpl @@ -136,3 +136,69 @@ func checkMerge(tx *sql.Tx, foreignKeys []foreignKey) error { 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 +} diff --git a/templates/singleton/boil_types.tpl b/templates/singleton/boil_types.tpl index aa61bf9..547d05d 100644 --- a/templates/singleton/boil_types.tpl +++ b/templates/singleton/boil_types.tpl @@ -1,11 +1,6 @@ // M type is for providing columns and column values to UpdateAll. 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 // be reassigned to primary record. type foreignKey struct { From 9c8262b702a2224d7e437b2e9a405fc698db506d Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Thu, 20 Jul 2017 10:50:55 -0400 Subject: [PATCH 10/35] fix exists() finisher --- templates/03_finishers.tpl | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/03_finishers.tpl b/templates/03_finishers.tpl index 13ea14d..df2081d 100644 --- a/templates/03_finishers.tpl +++ b/templates/03_finishers.tpl @@ -105,6 +105,7 @@ func (q {{$tableNameSingular}}Query) Exists() (bool, error) { var count int64 queries.SetCount(q.Query) + queries.SetSelect(q.Query, []string{}) queries.SetLimit(q.Query, 1) err := q.Query.QueryRow().Scan(&count) From 99a3a1d091d13401cd635e9b376ffec8f72ef156 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Tue, 1 Aug 2017 13:00:14 -0400 Subject: [PATCH 11/35] make merge compatible with an existing transaction --- templates/23_merge.tpl | 47 ++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/templates/23_merge.tpl b/templates/23_merge.tpl index 6b5cdd2..d84ed28 100644 --- a/templates/23_merge.tpl +++ b/templates/23_merge.tpl @@ -4,32 +4,42 @@ {{- else -}} {{- $dot := . }} // Merge combines two {{$tableNamePlural}} into one. The primary record will be kept, and the secondary will be deleted. -func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID uint64) error { - txdb, ok := exec.(boil.Beginner) +func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID uint64) (err error) { + tx, ok := exec.(boil.Transactor) if !ok { - return errors.New("database does not support transactions") - } + txdb, ok := exec.(boil.Beginner) + if !ok { + return errors.New("database does not support transactions") + } - tx, txErr := txdb.Begin() - if txErr != nil { - return txErr + tx, err = txdb.Begin() + if err != nil { + return err + } + + defer func() { + if p := recover(); p != nil { + tx.Rollback() + panic(p) // Rollback, then propagate panic + } else if err != nil { + tx.Rollback() + } else { + err = tx.Commit() + } + }() } primary, err := Find{{$tableNameSingular}}(tx, primaryID) if err != nil { - tx.Rollback() return err - } - if primary == nil { + } else if primary == nil { return errors.New("Primary {{$tableNameSingular}} not found") } secondary, err := Find{{$tableNameSingular}}(tx, secondaryID) if err != nil { - tx.Rollback() return err - } - if secondary == nil { + } else if secondary == nil { return errors.New("Secondary {{$tableNameSingular}} not found") } @@ -59,9 +69,13 @@ func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID {{- end }} } - err = mergeModels(tx, primaryID, secondaryID, foreignKeys, conflictingKeys) + sqlTx, ok := tx.(*sql.Tx) + if !ok { + return errors.New("tx must be an sql.Tx") + } + + err = mergeModels(sqlTx, primaryID, secondaryID, foreignKeys, conflictingKeys) if err != nil { - tx.Rollback() return err } @@ -80,17 +94,14 @@ func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID err = primary.Update(tx) if err != nil { - tx.Rollback() return errors.WithStack(err) } err = secondary.Delete(tx) if err != nil { - tx.Rollback() return errors.WithStack(err) } - tx.Commit() return nil } From 23f245776de75c7d884a2f208702147c417376ea Mon Sep 17 00:00:00 2001 From: Guy Tish <guy@ziprecruiter.com> Date: Mon, 26 Jun 2017 14:14:16 +0300 Subject: [PATCH 12/35] Added table columns and table names as anonymous struct --- templates/00_struct.tpl | 10 ++++++++++ templates/singleton/boil_table_names.tpl | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 templates/singleton/boil_table_names.tpl diff --git a/templates/00_struct.tpl b/templates/00_struct.tpl index f9c3a04..a2608fa 100644 --- a/templates/00_struct.tpl +++ b/templates/00_struct.tpl @@ -17,6 +17,16 @@ type {{$modelName}} struct { {{end -}} } +var {{$modelName}}Columns = struct { + {{range $column := .Table.Columns -}} + {{titleCase $column.Name}} string + {{end -}} +}{ + {{range $column := .Table.Columns -}} + {{titleCase $column.Name}}: "{{$column.Name}}", + {{end -}} +} + // {{$modelName}}Filter allows you to filter on any columns by making them all pointers. type {{$modelName}}Filter struct { {{range $column := .Table.Columns -}} diff --git a/templates/singleton/boil_table_names.tpl b/templates/singleton/boil_table_names.tpl new file mode 100644 index 0000000..062bcad --- /dev/null +++ b/templates/singleton/boil_table_names.tpl @@ -0,0 +1,9 @@ +var TableNames = struct { + {{range $table := .Tables -}} + {{titleCase $table.Name}} string + {{end -}} +}{ + {{range $table := .Tables -}} + {{titleCase $table.Name}}: "{{$table.Name}}", + {{end -}} +} From e3398120275addca81260d0d541abb99f1fa0dae Mon Sep 17 00:00:00 2001 From: Aaron L <aaron@bettercoder.net> Date: Sun, 4 Jun 2017 12:29:04 -0700 Subject: [PATCH 13/35] Stop using aliases in the relationship select - This caused issues with mysql who doesn't understand the syntax: "delete from x as y where y.id = ?" --- templates/06_relationship_to_many.tpl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/templates/06_relationship_to_many.tpl b/templates/06_relationship_to_many.tpl index 10aa842..0e6e634 100644 --- a/templates/06_relationship_to_many.tpl +++ b/templates/06_relationship_to_many.tpl @@ -16,7 +16,7 @@ func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}G(mods ...qm.QueryMod {{- if not (eq $txt.Function.Name $txt.ForeignTable.NamePluralGo)}} via {{.ForeignColumn}} column{{- end}}. func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) {{$tableNameSingular}}Query { queryMods := []qm.QueryMod{ - qm.Select("{{id 0 | $dot.Quotes}}.*"), + qm.Select("{{$schemaForeignTable}}.*"), } if len(mods) != 0 { @@ -25,17 +25,18 @@ func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, {{if .ToJoinTable -}} queryMods = append(queryMods, - qm.InnerJoin("{{.JoinTable | $dot.SchemaTable}} as {{id 1 | $dot.Quotes}} on {{id 0 | $dot.Quotes}}.{{.ForeignColumn | $dot.Quotes}} = {{id 1 | $dot.Quotes}}.{{.JoinForeignColumn | $dot.Quotes}}"), - qm.Where("{{id 1 | $dot.Quotes}}.{{.JoinLocalColumn | $dot.Quotes}}=?", o.{{$txt.LocalTable.ColumnNameGo}}), + {{$schemaJoinTable := .JoinTable | $.SchemaTable -}} + qm.InnerJoin("{{$schemaJoinTable}} on {{$schemaForeignTable}}.{{.ForeignColumn | $dot.Quotes}} = {{$schemaJoinTable}}.{{.JoinForeignColumn | $dot.Quotes}}"), + qm.Where("{{$schemaJoinTable}}.{{.JoinLocalColumn | $dot.Quotes}}=?", o.{{$txt.LocalTable.ColumnNameGo}}), ) {{else -}} queryMods = append(queryMods, - qm.Where("{{id 0 | $dot.Quotes}}.{{.ForeignColumn | $dot.Quotes}}=?", o.{{$txt.LocalTable.ColumnNameGo}}), + qm.Where("{{$schemaForeignTable}}.{{.ForeignColumn | $dot.Quotes}}=?", o.{{$txt.LocalTable.ColumnNameGo}}), ) {{end}} query := {{$txt.ForeignTable.NamePluralGo}}(exec, queryMods...) - queries.SetFrom(query.Query, "{{$schemaForeignTable}} as {{id 0 | $dot.Quotes}}") + queries.SetFrom(query.Query, "{{$schemaForeignTable}}") return query } From ca9f47de8bbab78e3401f818f965825da1425007 Mon Sep 17 00:00:00 2001 From: Aaron L <aaron@bettercoder.net> Date: Wed, 14 Jun 2017 21:14:54 -0700 Subject: [PATCH 14/35] Correct nullability for tests in to_one - Use the nullability of the fkey column in question to determine nullability for the entire struct to make things easy, otherwise we'd have to pluck out one at a time. This makes the tests pass instead of fail sporadically. - Fix #160 --- templates_test/relationship_to_one.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates_test/relationship_to_one.tpl b/templates_test/relationship_to_one.tpl index e95c61a..9211284 100644 --- a/templates_test/relationship_to_one.tpl +++ b/templates_test/relationship_to_one.tpl @@ -13,10 +13,10 @@ func test{{$txt.LocalTable.NameGo}}ToOne{{$txt.ForeignTable.NameGo}}Using{{$txt. var foreign {{$txt.ForeignTable.NameGo}} seed := randomize.NewSeed() - if err := randomize.Struct(seed, &local, {{$varNameSingular}}DBTypes, true, {{$varNameSingular}}ColumnsWithDefault...); err != nil { + if err := randomize.Struct(seed, &local, {{$varNameSingular}}DBTypes, {{if .Nullable}}true{{else}}false{{end}}, {{$varNameSingular}}ColumnsWithDefault...); err != nil { t.Errorf("Unable to randomize {{$txt.LocalTable.NameGo}} struct: %s", err) } - if err := randomize.Struct(seed, &foreign, {{$foreignVarNameSingular}}DBTypes, true, {{$foreignVarNameSingular}}ColumnsWithDefault...); err != nil { + if err := randomize.Struct(seed, &foreign, {{$foreignVarNameSingular}}DBTypes, {{if .ForeignColumnNullable}}true{{else}}false{{end}}, {{$foreignVarNameSingular}}ColumnsWithDefault...); err != nil { t.Errorf("Unable to randomize {{$txt.ForeignTable.NameGo}} struct: %s", err) } From ce9d13abf0492b2bb473f3ee18c00ae7df9559b2 Mon Sep 17 00:00:00 2001 From: Aaron L <aaron@bettercoder.net> Date: Sun, 2 Jul 2017 11:16:21 -0700 Subject: [PATCH 15/35] Fix hook documentation to include error return Fix #171 --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 194fdd8..51b5fbe 100644 --- a/README.md +++ b/README.md @@ -956,15 +956,16 @@ it with the `AddModelHook` method. Here is an example of a before insert hook: ```go // Define my hook function -func myHook(exec boil.Executor, p *Pilot) { +func myHook(exec boil.Executor, p *Pilot) error { // Do stuff + return nil } // Register my before insert hook for pilots models.AddPilotHook(boil.BeforeInsertHook, myHook) ``` -Your `ModelHook` will always be defined as `func(boil.Executor, *Model)` +Your `ModelHook` will always be defined as `func(boil.Executor, *Model) error` ### Transactions From 8837a986eed7e8ddeae1784e14cdc622cbeb03f3 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Wed, 23 Aug 2017 13:36:13 -0400 Subject: [PATCH 16/35] consistent order to unique key columns --- bdb/drivers/mysql.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bdb/drivers/mysql.go b/bdb/drivers/mysql.go index 41510ee..431bad1 100644 --- a/bdb/drivers/mysql.go +++ b/bdb/drivers/mysql.go @@ -3,6 +3,7 @@ package drivers import ( "database/sql" "fmt" + "sort" "strconv" "strings" @@ -261,6 +262,7 @@ func (m *MySQLDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, } ukey.Columns = strings.Split(columns, ",") + sort.Strings(ukey.Columns) ukeys = append(ukeys, ukey) } From 3abac13aeb644da942649b4338d290cfbf2b1227 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Wed, 23 Aug 2017 16:37:33 -0400 Subject: [PATCH 17/35] export InterpolateParams --- templates/07_relationship_to_one_eager.tpl | 2 +- templates/08_relationship_one_to_one_eager.tpl | 2 +- templates/09_relationship_to_many_eager.tpl | 2 +- templates/10_relationship_to_one_setops.tpl | 2 +- templates/11_relationship_one_to_one_setops.tpl | 2 +- templates/12_relationship_to_many_setops.tpl | 8 ++++---- templates/15_insert.tpl | 4 ++-- templates/16_update.tpl | 4 ++-- templates/17_upsert.tpl | 4 ++-- templates/18_delete.tpl | 4 ++-- templates/20_exists.tpl | 2 +- templates/singleton/boil_queries.tpl | 2 +- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/templates/07_relationship_to_one_eager.tpl b/templates/07_relationship_to_one_eager.tpl index 3bf42f4..28010fd 100644 --- a/templates/07_relationship_to_one_eager.tpl +++ b/templates/07_relationship_to_one_eager.tpl @@ -40,7 +40,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula ) if boil.DebugMode { - qStr, err := interpolateParams(query, args...) + qStr, err := InterpolateParams(query, args...) if err != nil { return err } diff --git a/templates/08_relationship_one_to_one_eager.tpl b/templates/08_relationship_one_to_one_eager.tpl index 1fbf5f7..261b30c 100644 --- a/templates/08_relationship_one_to_one_eager.tpl +++ b/templates/08_relationship_one_to_one_eager.tpl @@ -40,7 +40,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula ) if boil.DebugMode { - qStr, err := interpolateParams(query, args...) + qStr, err := InterpolateParams(query, args...) if err != nil { return err } diff --git a/templates/09_relationship_to_many_eager.tpl b/templates/09_relationship_to_many_eager.tpl index 3ec5bf9..8c4159b 100644 --- a/templates/09_relationship_to_many_eager.tpl +++ b/templates/09_relationship_to_many_eager.tpl @@ -49,7 +49,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula {{end -}} if boil.DebugMode { - qStr, err := interpolateParams(query, args...) + qStr, err := InterpolateParams(query, args...) if err != nil { return err } diff --git a/templates/10_relationship_to_one_setops.tpl b/templates/10_relationship_to_one_setops.tpl index b293b48..8362420 100644 --- a/templates/10_relationship_to_one_setops.tpl +++ b/templates/10_relationship_to_one_setops.tpl @@ -53,7 +53,7 @@ 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."}}{{"}"}} if boil.DebugMode { - qStr, err := interpolateParams(updateQuery, values...) + qStr, err := InterpolateParams(updateQuery, values...) if err != nil { return err } diff --git a/templates/11_relationship_one_to_one_setops.tpl b/templates/11_relationship_one_to_one_setops.tpl index d4583ca..7648e23 100644 --- a/templates/11_relationship_one_to_one_setops.tpl +++ b/templates/11_relationship_one_to_one_setops.tpl @@ -59,7 +59,7 @@ 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."}}{{"}"}} if boil.DebugMode { - qStr, err := interpolateParams(updateQuery, values...) + qStr, err := InterpolateParams(updateQuery, values...) if err != nil { return err } diff --git a/templates/12_relationship_to_many_setops.tpl b/templates/12_relationship_to_many_setops.tpl index 35a4bd4..6794889 100644 --- a/templates/12_relationship_to_many_setops.tpl +++ b/templates/12_relationship_to_many_setops.tpl @@ -66,7 +66,7 @@ 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."}}{{"}"}} if boil.DebugMode { - qStr, err := interpolateParams(updateQuery, values...) + qStr, err := InterpolateParams(updateQuery, values...) if err != nil { return err } @@ -90,7 +90,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}(exec boil.Executo values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}, rel.{{$txt.ForeignTable.ColumnNameGo}}} if boil.DebugMode { - qStr, err := interpolateParams(query, values...) + qStr, err := InterpolateParams(query, values...) if err != nil { return err } @@ -190,7 +190,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}} {{end -}} if boil.DebugMode { - qStr, err := interpolateParams(query, values...) + qStr, err := InterpolateParams(query, values...) if err != nil { return err } @@ -269,7 +269,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Exec } if boil.DebugMode { - qStr, err := interpolateParams(query, values...) + qStr, err := InterpolateParams(query, values...) if err != nil { return err } diff --git a/templates/15_insert.tpl b/templates/15_insert.tpl index 8cd30b9..00b6f5b 100644 --- a/templates/15_insert.tpl +++ b/templates/15_insert.tpl @@ -98,7 +98,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string vals := queries.ValuesFromMapping(value, cache.valueMapping) if boil.DebugMode { - qStr, err := interpolateParams(cache.query, vals...) + qStr, err := InterpolateParams(cache.query, vals...) if err != nil { return err } @@ -147,7 +147,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string } if boil.DebugMode { - qStr, err := interpolateParams(cache.retQuery, identifierCols...) + qStr, err := InterpolateParams(cache.retQuery, identifierCols...) if err != nil { return err } diff --git a/templates/16_update.tpl b/templates/16_update.tpl index 1ac460b..1f67234 100644 --- a/templates/16_update.tpl +++ b/templates/16_update.tpl @@ -78,7 +78,7 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping) if boil.DebugMode { - qStr, err := interpolateParams(cache.query, values...) + qStr, err := InterpolateParams(cache.query, values...) if err != nil { return err } @@ -173,7 +173,7 @@ 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))) if boil.DebugMode { - qStr, err := interpolateParams(sql, args...) + qStr, err := InterpolateParams(sql, args...) if err != nil { return err } diff --git a/templates/17_upsert.tpl b/templates/17_upsert.tpl index 5cf6a14..6eef9fe 100644 --- a/templates/17_upsert.tpl +++ b/templates/17_upsert.tpl @@ -147,7 +147,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName } if boil.DebugMode { - qStr, err := interpolateParams(cache.query, vals...) + qStr, err := InterpolateParams(cache.query, vals...) if err != nil { return err } @@ -196,7 +196,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName } if boil.DebugMode { - qStr, err := interpolateParams(cache.retQuery, identifierCols...) + qStr, err := InterpolateParams(cache.retQuery, identifierCols...) if err != nil { return err } diff --git a/templates/18_delete.tpl b/templates/18_delete.tpl index 20e819a..8c63e43 100644 --- a/templates/18_delete.tpl +++ b/templates/18_delete.tpl @@ -46,7 +46,7 @@ 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}}" if boil.DebugMode { - qStr, err := interpolateParams(sql, args...) + qStr, err := InterpolateParams(sql, args...) if err != nil { return err } @@ -142,7 +142,7 @@ 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)) if boil.DebugMode { - qStr, err := interpolateParams(sql, args...) + qStr, err := InterpolateParams(sql, args...) if err != nil { return err } diff --git a/templates/20_exists.tpl b/templates/20_exists.tpl index 4c4031a..7d3dc3d 100644 --- a/templates/20_exists.tpl +++ b/templates/20_exists.tpl @@ -14,7 +14,7 @@ func {{$tableNameSingular}}Exists(exec boil.Executor, {{$pkArgs}}) (bool, error) {{- end}} if boil.DebugMode { - qStr, err := interpolateParams(sql, {{$pkNames | join ", "}}) + qStr, err := InterpolateParams(sql, {{$pkNames | join ", "}}) if err != nil { return false, err } diff --git a/templates/singleton/boil_queries.tpl b/templates/singleton/boil_queries.tpl index 11f103b..0d3c812 100644 --- a/templates/singleton/boil_queries.tpl +++ b/templates/singleton/boil_queries.tpl @@ -138,7 +138,7 @@ func checkMerge(tx *sql.Tx, foreignKeys []foreignKey) error { } // duplicated in queries/query.go -func interpolateParams(query string, args ...interface{}) (string, error) { +func InterpolateParams(query string, args ...interface{}) (string, error) { for i := 0; i < len(args); i++ { field := reflect.ValueOf(args[i]) From faec3464818e1429f49922dec917d7313235a40b Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Wed, 23 Aug 2017 16:59:29 -0400 Subject: [PATCH 18/35] use interface to enable custom Tx types --- boil/db.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boil/db.go b/boil/db.go index 84bc7d3..2d31d38 100644 --- a/boil/db.go +++ b/boil/db.go @@ -19,7 +19,7 @@ type Transactor interface { // Beginner begins transactions. type Beginner interface { - Begin() (*sql.Tx, error) + Begin() (Transactor, error) } // Begin a transaction From 544ff7afdd48696d7659886fc9c3b0e45588fd5f Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Wed, 23 Aug 2017 17:03:24 -0400 Subject: [PATCH 19/35] typo --- bdb/drivers/mysql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bdb/drivers/mysql.go b/bdb/drivers/mysql.go index 431bad1..dec80e0 100644 --- a/bdb/drivers/mysql.go +++ b/bdb/drivers/mysql.go @@ -380,7 +380,7 @@ func (m *MySQLDriver) TranslateColumnType(c bdb.Column) bdb.Column { if unsigned { c.Type = "null.Uint64" } else { - c.Type = "null.Uint64" + c.Type = "null.Int64" } case "float": c.Type = "null.Float32" From 55f42bc03809b788249594b190801485a236431b Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Thu, 24 Aug 2017 11:58:13 -0400 Subject: [PATCH 20/35] just use interfaces --- boilingcore/imports.go | 1 - templates/23_merge.tpl | 7 +------ templates/singleton/boil_queries.tpl | 6 +++--- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/boilingcore/imports.go b/boilingcore/imports.go index 2c31c63..528a946 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -182,7 +182,6 @@ func newImporter() importer { imp.Singleton = mapImports{ "boil_queries": imports{ standard: importList{ - `"database/sql"`, `"fmt"`, `"reflect"`, `"strconv"`, diff --git a/templates/23_merge.tpl b/templates/23_merge.tpl index d84ed28..9f1af10 100644 --- a/templates/23_merge.tpl +++ b/templates/23_merge.tpl @@ -69,12 +69,7 @@ func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID {{- end }} } - sqlTx, ok := tx.(*sql.Tx) - if !ok { - return errors.New("tx must be an sql.Tx") - } - - err = mergeModels(sqlTx, primaryID, secondaryID, foreignKeys, conflictingKeys) + err = mergeModels(tx, primaryID, secondaryID, foreignKeys, conflictingKeys) if err != nil { return err } diff --git a/templates/singleton/boil_queries.tpl b/templates/singleton/boil_queries.tpl index 0d3c812..89b0e74 100644 --- a/templates/singleton/boil_queries.tpl +++ b/templates/singleton/boil_queries.tpl @@ -20,7 +20,7 @@ func NewQuery(exec boil.Executor, mods ...qm.QueryMod) *queries.Query { return q } -func mergeModels(tx *sql.Tx, primaryID uint64, secondaryID uint64, foreignKeys []foreignKey, conflictingKeys []conflictingUniqueKey) error { +func mergeModels(tx boil.Executor, primaryID uint64, secondaryID uint64, foreignKeys []foreignKey, conflictingKeys []conflictingUniqueKey) error { if len(foreignKeys) < 1 { return nil } @@ -48,7 +48,7 @@ func mergeModels(tx *sql.Tx, primaryID uint64, secondaryID uint64, foreignKeys [ return checkMerge(tx, foreignKeys) } -func deleteConflictsBeforeMerge(tx *sql.Tx, conflict conflictingUniqueKey, primaryID uint64, secondaryID uint64) error { +func deleteConflictsBeforeMerge(tx boil.Executor, conflict conflictingUniqueKey, primaryID uint64, secondaryID uint64) error { conflictingColumns := strmangle.SetComplement(conflict.columns, []string{conflict.objectIdColumn}) if len(conflictingColumns) < 1 { @@ -98,7 +98,7 @@ func deleteConflictsBeforeMerge(tx *sql.Tx, conflict conflictingUniqueKey, prima return nil } -func checkMerge(tx *sql.Tx, foreignKeys []foreignKey) error { +func checkMerge(tx boil.Executor, foreignKeys []foreignKey) error { uniqueColumns := []interface{}{} uniqueColumnNames := map[string]bool{} handledTablesColumns := map[string]bool{} From cd445bf2f42346ac3dd5a1398e1f3ccadbe902e8 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Sat, 2 Sep 2017 11:27:27 -0400 Subject: [PATCH 21/35] revert interpolateParams, since we're doing our own logging now --- boilingcore/imports.go | 5 - queries/query.go | 94 ++----------------- templates/07_relationship_to_one_eager.tpl | 6 +- .../08_relationship_one_to_one_eager.tpl | 6 +- templates/09_relationship_to_many_eager.tpl | 6 +- templates/10_relationship_to_one_setops.tpl | 7 +- .../11_relationship_one_to_one_setops.tpl | 7 +- templates/12_relationship_to_many_setops.tpl | 28 ++---- templates/15_insert.tpl | 14 +-- templates/16_update.tpl | 14 +-- templates/17_upsert.tpl | 14 +-- templates/18_delete.tpl | 16 +--- templates/20_exists.tpl | 7 +- templates/singleton/boil_queries.tpl | 66 ------------- 14 files changed, 40 insertions(+), 250 deletions(-) diff --git a/boilingcore/imports.go b/boilingcore/imports.go index 528a946..13ed119 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -183,10 +183,6 @@ func newImporter() importer { "boil_queries": imports{ standard: importList{ `"fmt"`, - `"reflect"`, - `"strconv"`, - `"strings"`, - `"time"`, }, thirdParty: importList{ `"github.com/lbryio/sqlboiler/boil"`, @@ -194,7 +190,6 @@ func newImporter() importer { `"github.com/lbryio/sqlboiler/queries/qm"`, `"github.com/lbryio/sqlboiler/strmangle"`, `"github.com/pkg/errors"`, - `"github.com/lbryio/null.go"`, }, }, "boil_types": { diff --git a/queries/query.go b/queries/query.go index b3ff830..be539e5 100644 --- a/queries/query.go +++ b/queries/query.go @@ -3,15 +3,8 @@ package queries import ( "database/sql" "fmt" - "reflect" - "strconv" - "strings" - "time" - "github.com/lbryio/null.go" "github.com/lbryio/sqlboiler/boil" - - "github.com/go-errors/errors" ) // joinKind is the type of join @@ -112,11 +105,8 @@ func RawG(query string, args ...interface{}) *Query { func (q *Query) Exec() (sql.Result, error) { qs, args := buildQuery(q) if boil.DebugMode { - qStr, err := interpolateParams(qs, args...) - if err != nil { - return nil, err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, qs) + fmt.Fprintln(boil.DebugWriter, args) } return q.executor.Exec(qs, args...) } @@ -125,11 +115,8 @@ func (q *Query) Exec() (sql.Result, error) { func (q *Query) QueryRow() *sql.Row { qs, args := buildQuery(q) if boil.DebugMode { - qStr, err := interpolateParams(qs, args...) - if err != nil { - panic(err) - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, qs) + fmt.Fprintln(boil.DebugWriter, args) } return q.executor.QueryRow(qs, args...) } @@ -138,11 +125,8 @@ func (q *Query) QueryRow() *sql.Row { func (q *Query) Query() (*sql.Rows, error) { qs, args := buildQuery(q) if boil.DebugMode { - qStr, err := interpolateParams(qs, args...) - if err != nil { - return nil, err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, qs) + fmt.Fprintln(boil.DebugWriter, args) } return q.executor.Query(qs, args...) } @@ -296,69 +280,3 @@ func AppendGroupBy(q *Query, clause string) { func AppendOrderBy(q *Query, clause string) { 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 -} diff --git a/templates/07_relationship_to_one_eager.tpl b/templates/07_relationship_to_one_eager.tpl index 28010fd..3b24f1a 100644 --- a/templates/07_relationship_to_one_eager.tpl +++ b/templates/07_relationship_to_one_eager.tpl @@ -40,11 +40,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula ) if boil.DebugMode { - qStr, err := InterpolateParams(query, args...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintf(boil.DebugWriter, "%s\n%v\n", query, args) } results, err := e.Query(query, args...) diff --git a/templates/08_relationship_one_to_one_eager.tpl b/templates/08_relationship_one_to_one_eager.tpl index 261b30c..37d1af0 100644 --- a/templates/08_relationship_one_to_one_eager.tpl +++ b/templates/08_relationship_one_to_one_eager.tpl @@ -40,11 +40,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula ) if boil.DebugMode { - qStr, err := InterpolateParams(query, args...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintf(boil.DebugWriter, "%s\n%v\n", query, args) } results, err := e.Query(query, args...) diff --git a/templates/09_relationship_to_many_eager.tpl b/templates/09_relationship_to_many_eager.tpl index 8c4159b..1603188 100644 --- a/templates/09_relationship_to_many_eager.tpl +++ b/templates/09_relationship_to_many_eager.tpl @@ -49,11 +49,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula {{end -}} if boil.DebugMode { - qStr, err := InterpolateParams(query, args...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintf(boil.DebugWriter, "%s\n%v\n", query, args) } results, err := e.Query(query, args...) diff --git a/templates/10_relationship_to_one_setops.tpl b/templates/10_relationship_to_one_setops.tpl index 8362420..14f726e 100644 --- a/templates/10_relationship_to_one_setops.tpl +++ b/templates/10_relationship_to_one_setops.tpl @@ -53,11 +53,8 @@ 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."}}{{"}"}} if boil.DebugMode { - qStr, err := InterpolateParams(updateQuery, values...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, updateQuery) + fmt.Fprintln(boil.DebugWriter, values) } if _, err = exec.Exec(updateQuery, values...); err != nil { diff --git a/templates/11_relationship_one_to_one_setops.tpl b/templates/11_relationship_one_to_one_setops.tpl index 7648e23..826eec2 100644 --- a/templates/11_relationship_one_to_one_setops.tpl +++ b/templates/11_relationship_one_to_one_setops.tpl @@ -59,11 +59,8 @@ 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."}}{{"}"}} if boil.DebugMode { - qStr, err := InterpolateParams(updateQuery, values...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, updateQuery) + fmt.Fprintln(boil.DebugWriter, values) } if _, err = exec.Exec(updateQuery, values...); err != nil { diff --git a/templates/12_relationship_to_many_setops.tpl b/templates/12_relationship_to_many_setops.tpl index 6794889..06159ee 100644 --- a/templates/12_relationship_to_many_setops.tpl +++ b/templates/12_relationship_to_many_setops.tpl @@ -66,11 +66,8 @@ 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."}}{{"}"}} if boil.DebugMode { - qStr, err := InterpolateParams(updateQuery, values...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, updateQuery) + fmt.Fprintln(boil.DebugWriter, values) } if _, err = exec.Exec(updateQuery, values...); err != nil { @@ -90,11 +87,8 @@ func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}(exec boil.Executo values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}, rel.{{$txt.ForeignTable.ColumnNameGo}}} if boil.DebugMode { - qStr, err := InterpolateParams(query, values...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, query) + fmt.Fprintln(boil.DebugWriter, values) } _, err = exec.Exec(query, values...) @@ -190,11 +184,8 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}} {{end -}} if boil.DebugMode { - qStr, err := InterpolateParams(query, values...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, query) + fmt.Fprintln(boil.DebugWriter, values) } _, err := exec.Exec(query, values...) @@ -269,11 +260,8 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Exec } if boil.DebugMode { - qStr, err := InterpolateParams(query, values...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, query) + fmt.Fprintln(boil.DebugWriter, values) } _, err = exec.Exec(query, values...) diff --git a/templates/15_insert.tpl b/templates/15_insert.tpl index 00b6f5b..870e20d 100644 --- a/templates/15_insert.tpl +++ b/templates/15_insert.tpl @@ -98,11 +98,8 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string vals := queries.ValuesFromMapping(value, cache.valueMapping) if boil.DebugMode { - qStr, err := InterpolateParams(cache.query, vals...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, vals) } {{if .UseLastInsertID -}} @@ -147,11 +144,8 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string } if boil.DebugMode { - qStr, err := InterpolateParams(cache.retQuery, identifierCols...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, cache.retQuery) + fmt.Fprintln(boil.DebugWriter, identifierCols...) } err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...) diff --git a/templates/16_update.tpl b/templates/16_update.tpl index 1f67234..bc4a6f5 100644 --- a/templates/16_update.tpl +++ b/templates/16_update.tpl @@ -78,11 +78,8 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping) if boil.DebugMode { - qStr, err := InterpolateParams(cache.query, values...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, values) } _, err = exec.Exec(cache.query, values...) @@ -173,11 +170,8 @@ 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))) if boil.DebugMode { - qStr, err := InterpolateParams(sql, args...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args...) } _, err := exec.Exec(sql, args...) diff --git a/templates/17_upsert.tpl b/templates/17_upsert.tpl index 6eef9fe..dbce58c 100644 --- a/templates/17_upsert.tpl +++ b/templates/17_upsert.tpl @@ -147,11 +147,8 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName } if boil.DebugMode { - qStr, err := InterpolateParams(cache.query, vals...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, vals) } {{if .UseLastInsertID -}} @@ -196,11 +193,8 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName } if boil.DebugMode { - qStr, err := InterpolateParams(cache.retQuery, identifierCols...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, cache.retQuery) + fmt.Fprintln(boil.DebugWriter, identifierCols...) } err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(returns...) diff --git a/templates/18_delete.tpl b/templates/18_delete.tpl index 8c63e43..aea163e 100644 --- a/templates/18_delete.tpl +++ b/templates/18_delete.tpl @@ -6,7 +6,7 @@ // Panics on error. func (o *{{$tableNameSingular}}) DeleteP(exec boil.Executor) { if err := o.Delete(exec); err != nil { - panic(boil.WrapErr(err)) + panic(boil.WrapErr(err)) } } @@ -46,11 +46,8 @@ 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}}" if boil.DebugMode { - qStr, err := InterpolateParams(sql, args...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args...) } _, err := exec.Exec(sql, args...) @@ -142,11 +139,8 @@ 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)) if boil.DebugMode { - qStr, err := InterpolateParams(sql, args...) - if err != nil { - return err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args) } _, err := exec.Exec(sql, args...) diff --git a/templates/20_exists.tpl b/templates/20_exists.tpl index 7d3dc3d..2e20fa6 100644 --- a/templates/20_exists.tpl +++ b/templates/20_exists.tpl @@ -14,11 +14,8 @@ func {{$tableNameSingular}}Exists(exec boil.Executor, {{$pkArgs}}) (bool, error) {{- end}} if boil.DebugMode { - qStr, err := InterpolateParams(sql, {{$pkNames | join ", "}}) - if err != nil { - return false, err - } - fmt.Fprintln(boil.DebugWriter, qStr) + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, {{$pkNames | join ", "}}) } row := exec.QueryRow(sql, {{$pkNames | join ", "}}) diff --git a/templates/singleton/boil_queries.tpl b/templates/singleton/boil_queries.tpl index 89b0e74..1260dde 100644 --- a/templates/singleton/boil_queries.tpl +++ b/templates/singleton/boil_queries.tpl @@ -136,69 +136,3 @@ func checkMerge(tx boil.Executor, foreignKeys []foreignKey) error { 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 -} From 0b0a1f21c2c3512b0f08441302e5b2e1fce7fc9a Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Sat, 2 Sep 2017 11:52:31 -0400 Subject: [PATCH 22/35] allow generic interface or real sql tx --- boil/db.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/boil/db.go b/boil/db.go index 2d31d38..f3153bc 100644 --- a/boil/db.go +++ b/boil/db.go @@ -22,11 +22,19 @@ type Beginner interface { Begin() (Transactor, error) } +type SQLBeginner interface { + Begin() (*sql.Tx, error) +} + // Begin a transaction func Begin() (Transactor, error) { creator, ok := currentDB.(Beginner) if !ok { - panic("database does not support transactions") + creator2, ok2 := currentDB.(SQLBeginner) + if !ok2 { + panic("database does not support transactions") + } + return creator2.Begin() } return creator.Begin() From e4a52e21b6f0c655dc21b5ba4391bbdf1f3d1abd Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Wed, 7 Feb 2018 09:35:46 -0500 Subject: [PATCH 23/35] switch to our errors package --- boil/errors.go | 23 ------------- boil/errors_test.go | 24 ------------- boilingcore/imports.go | 26 +++++++------- queries/query.go | 5 +-- queries/reflect.go | 6 ++-- templates/02_hooks.tpl | 18 +++++----- templates/03_finishers.tpl | 18 +++++----- templates/07_relationship_to_one_eager.tpl | 6 ++-- .../08_relationship_one_to_one_eager.tpl | 6 ++-- templates/09_relationship_to_many_eager.tpl | 10 +++--- templates/10_relationship_to_one_setops.tpl | 14 ++++---- .../11_relationship_one_to_one_setops.tpl | 14 ++++---- templates/12_relationship_to_many_setops.tpl | 24 ++++++------- templates/14_find.tpl | 12 +++---- templates/15_insert.tpl | 20 +++++------ templates/16_update.tpl | 24 ++++++------- templates/17_upsert.tpl | 24 ++++++------- templates/18_delete.tpl | 34 +++++++++---------- templates/19_reload.tpl | 16 ++++----- templates/20_exists.tpl | 6 ++-- templates/23_merge.tpl | 16 ++++----- templates/singleton/boil_queries.tpl | 18 +++++----- templates/singleton/boil_types.tpl | 2 +- templates_test/main_test/mssql_main.tpl | 14 ++++---- templates_test/main_test/mysql_main.tpl | 22 ++++++------ templates_test/main_test/postgres_main.tpl | 22 ++++++------ templates_test/singleton/boil_main_test.tpl | 2 +- 27 files changed, 190 insertions(+), 236 deletions(-) delete mode 100644 boil/errors.go delete mode 100644 boil/errors_test.go diff --git a/boil/errors.go b/boil/errors.go deleted file mode 100644 index 4d02169..0000000 --- a/boil/errors.go +++ /dev/null @@ -1,23 +0,0 @@ -package boil - -type boilErr struct { - error -} - -// WrapErr wraps err in a boilErr -func WrapErr(err error) error { - return boilErr{ - error: err, - } -} - -// Error returns the underlying error string -func (e boilErr) Error() string { - return e.error.Error() -} - -// IsBoilErr checks if err is a boilErr -func IsBoilErr(err error) bool { - _, ok := err.(boilErr) - return ok -} diff --git a/boil/errors_test.go b/boil/errors_test.go deleted file mode 100644 index 2b2f1a0..0000000 --- a/boil/errors_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package boil - -import ( - "errors" - "testing" -) - -func TestErrors(t *testing.T) { - t.Parallel() - - err := errors.New("test error") - if IsBoilErr(err) == true { - t.Errorf("Expected false") - } - - err = WrapErr(errors.New("test error")) - if err.Error() != "test error" { - t.Errorf(`Expected "test error", got %v`, err.Error()) - } - - if IsBoilErr(err) != true { - t.Errorf("Expected true") - } -} diff --git a/boilingcore/imports.go b/boilingcore/imports.go index 13ed119..b73b429 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -170,12 +170,12 @@ func newImporter() importer { `"time"`, }, thirdParty: importList{ + `"github.com/lbryio/errors.go"`, `"github.com/lbryio/null.go"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, `"github.com/lbryio/sqlboiler/strmangle"`, - `"github.com/pkg/errors"`, }, } @@ -185,16 +185,16 @@ func newImporter() importer { `"fmt"`, }, thirdParty: importList{ + `"github.com/lbryio/errors.go"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, `"github.com/lbryio/sqlboiler/strmangle"`, - `"github.com/pkg/errors"`, }, }, "boil_types": { thirdParty: importList{ - `"github.com/pkg/errors"`, + `"github.com/lbryio/errors.go"`, `"github.com/lbryio/sqlboiler/strmangle"`, }, }, @@ -227,9 +227,9 @@ func newImporter() importer { }, thirdParty: importList{ `"github.com/kat-co/vala"`, - `"github.com/pkg/errors"`, - `"github.com/spf13/viper"`, + `"github.com/lbryio/errors.go"`, `"github.com/lbryio/sqlboiler/boil"`, + `"github.com/spf13/viper"`, }, }, "boil_queries_test": { @@ -265,11 +265,11 @@ func newImporter() importer { `"strings"`, }, thirdParty: importList{ - `"github.com/pkg/errors"`, - `"github.com/spf13/viper"`, + `"github.com/lbryio/errors.go"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, `_ "github.com/lib/pq"`, + `"github.com/spf13/viper"`, }, }, "mysql": { @@ -284,11 +284,11 @@ func newImporter() importer { `"strings"`, }, thirdParty: importList{ - `"github.com/pkg/errors"`, - `"github.com/spf13/viper"`, + `_ "github.com/go-sql-driver/mysql"`, + `"github.com/lbryio/errors.go"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, - `_ "github.com/go-sql-driver/mysql"`, + `"github.com/spf13/viper"`, }, }, "mssql": { @@ -301,11 +301,11 @@ func newImporter() importer { `"strings"`, }, thirdParty: importList{ - `"github.com/pkg/errors"`, - `"github.com/spf13/viper"`, + `_ "github.com/denisenkom/go-mssqldb"`, + `"github.com/lbryio/errors.go"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, - `_ "github.com/denisenkom/go-mssqldb"`, + `"github.com/spf13/viper"`, }, }, } diff --git a/queries/query.go b/queries/query.go index be539e5..a76c046 100644 --- a/queries/query.go +++ b/queries/query.go @@ -4,6 +4,7 @@ import ( "database/sql" "fmt" + "github.com/lbryio/errors.go" "github.com/lbryio/sqlboiler/boil" ) @@ -136,7 +137,7 @@ func (q *Query) Query() (*sql.Rows, error) { func (q *Query) ExecP() sql.Result { res, err := q.Exec() if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } return res @@ -147,7 +148,7 @@ func (q *Query) ExecP() sql.Result { func (q *Query) QueryP() *sql.Rows { rows, err := q.Query() if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } return rows diff --git a/queries/reflect.go b/queries/reflect.go index 8cf8f3d..39eda23 100644 --- a/queries/reflect.go +++ b/queries/reflect.go @@ -7,9 +7,9 @@ import ( "strings" "sync" - "github.com/pkg/errors" - "github.com/lbryio/sqlboiler/boil" "github.com/lbryio/sqlboiler/strmangle" + + "github.com/pkg/errors" ) var ( @@ -41,7 +41,7 @@ const ( // It panics on error. See boil.Bind() documentation. func (q *Query) BindP(obj interface{}) { if err := q.Bind(obj); err != nil { - panic(boil.WrapErr(err)) + panic(errors.WithStack(err)) } } diff --git a/templates/02_hooks.tpl b/templates/02_hooks.tpl index 9815639..d152978 100644 --- a/templates/02_hooks.tpl +++ b/templates/02_hooks.tpl @@ -16,7 +16,7 @@ var {{$varNameSingular}}AfterUpsertHooks []{{$tableNameSingular}}Hook func (o *{{$tableNameSingular}}) doBeforeInsertHooks(exec boil.Executor) (err error) { for _, hook := range {{$varNameSingular}}BeforeInsertHooks { if err := hook(exec, o); err != nil { - return err + return errors.Err(err) } } @@ -27,7 +27,7 @@ func (o *{{$tableNameSingular}}) doBeforeInsertHooks(exec boil.Executor) (err er func (o *{{$tableNameSingular}}) doBeforeUpdateHooks(exec boil.Executor) (err error) { for _, hook := range {{$varNameSingular}}BeforeUpdateHooks { if err := hook(exec, o); err != nil { - return err + return errors.Err(err) } } @@ -38,7 +38,7 @@ func (o *{{$tableNameSingular}}) doBeforeUpdateHooks(exec boil.Executor) (err er func (o *{{$tableNameSingular}}) doBeforeDeleteHooks(exec boil.Executor) (err error) { for _, hook := range {{$varNameSingular}}BeforeDeleteHooks { if err := hook(exec, o); err != nil { - return err + return errors.Err(err) } } @@ -49,7 +49,7 @@ func (o *{{$tableNameSingular}}) doBeforeDeleteHooks(exec boil.Executor) (err er func (o *{{$tableNameSingular}}) doBeforeUpsertHooks(exec boil.Executor) (err error) { for _, hook := range {{$varNameSingular}}BeforeUpsertHooks { if err := hook(exec, o); err != nil { - return err + return errors.Err(err) } } @@ -60,7 +60,7 @@ func (o *{{$tableNameSingular}}) doBeforeUpsertHooks(exec boil.Executor) (err er func (o *{{$tableNameSingular}}) doAfterInsertHooks(exec boil.Executor) (err error) { for _, hook := range {{$varNameSingular}}AfterInsertHooks { if err := hook(exec, o); err != nil { - return err + return errors.Err(err) } } @@ -71,7 +71,7 @@ func (o *{{$tableNameSingular}}) doAfterInsertHooks(exec boil.Executor) (err err func (o *{{$tableNameSingular}}) doAfterSelectHooks(exec boil.Executor) (err error) { for _, hook := range {{$varNameSingular}}AfterSelectHooks { if err := hook(exec, o); err != nil { - return err + return errors.Err(err) } } @@ -82,7 +82,7 @@ func (o *{{$tableNameSingular}}) doAfterSelectHooks(exec boil.Executor) (err err func (o *{{$tableNameSingular}}) doAfterUpdateHooks(exec boil.Executor) (err error) { for _, hook := range {{$varNameSingular}}AfterUpdateHooks { if err := hook(exec, o); err != nil { - return err + return errors.Err(err) } } @@ -93,7 +93,7 @@ func (o *{{$tableNameSingular}}) doAfterUpdateHooks(exec boil.Executor) (err err func (o *{{$tableNameSingular}}) doAfterDeleteHooks(exec boil.Executor) (err error) { for _, hook := range {{$varNameSingular}}AfterDeleteHooks { if err := hook(exec, o); err != nil { - return err + return errors.Err(err) } } @@ -104,7 +104,7 @@ func (o *{{$tableNameSingular}}) doAfterDeleteHooks(exec boil.Executor) (err err func (o *{{$tableNameSingular}}) doAfterUpsertHooks(exec boil.Executor) (err error) { for _, hook := range {{$varNameSingular}}AfterUpsertHooks { if err := hook(exec, o); err != nil { - return err + return errors.Err(err) } } diff --git a/templates/03_finishers.tpl b/templates/03_finishers.tpl index df2081d..473bddd 100644 --- a/templates/03_finishers.tpl +++ b/templates/03_finishers.tpl @@ -4,7 +4,7 @@ func (q {{$tableNameSingular}}Query) OneP() (*{{$tableNameSingular}}) { o, err := q.One() if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } return o @@ -18,10 +18,10 @@ func (q {{$tableNameSingular}}Query) One() (*{{$tableNameSingular}}, error) { err := q.Bind(o) if err != nil { - if errors.Cause(err) == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return nil, nil } - return nil, errors.Wrap(err, "{{.PkgName}}: failed to execute a one query for {{.Table.Name}}") + return nil, errors.Prefix("{{.PkgName}}: failed to execute a one query for {{.Table.Name}}", err) } {{if not .NoHooks -}} @@ -37,7 +37,7 @@ func (q {{$tableNameSingular}}Query) One() (*{{$tableNameSingular}}, error) { func (q {{$tableNameSingular}}Query) AllP() {{$tableNameSingular}}Slice { o, err := q.All() if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } return o @@ -49,7 +49,7 @@ func (q {{$tableNameSingular}}Query) All() ({{$tableNameSingular}}Slice, error) err := q.Bind(&o) if err != nil { - return nil, errors.Wrap(err, "{{.PkgName}}: failed to assign all query results to {{$tableNameSingular}} slice") + return nil, errors.Prefix("{{.PkgName}}: failed to assign all query results to {{$tableNameSingular}} slice", err) } {{if not .NoHooks -}} @@ -69,7 +69,7 @@ func (q {{$tableNameSingular}}Query) All() ({{$tableNameSingular}}Slice, error) func (q {{$tableNameSingular}}Query) CountP() int64 { c, err := q.Count() if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } return c @@ -84,7 +84,7 @@ func (q {{$tableNameSingular}}Query) Count() (int64, error) { err := q.Query.QueryRow().Scan(&count) if err != nil { - return 0, errors.Wrap(err, "{{.PkgName}}: failed to count {{.Table.Name}} rows") + return 0, errors.Prefix("{{.PkgName}}: failed to count {{.Table.Name}} rows", err) } return count, nil @@ -94,7 +94,7 @@ func (q {{$tableNameSingular}}Query) Count() (int64, error) { func (q {{$tableNameSingular}}Query) ExistsP() bool { e, err := q.Exists() if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } return e @@ -110,7 +110,7 @@ func (q {{$tableNameSingular}}Query) Exists() (bool, error) { err := q.Query.QueryRow().Scan(&count) if err != nil { - return false, errors.Wrap(err, "{{.PkgName}}: failed to check if {{.Table.Name}} exists") + return false, errors.Prefix("{{.PkgName}}: failed to check if {{.Table.Name}} exists", err) } return count > 0, nil diff --git a/templates/07_relationship_to_one_eager.tpl b/templates/07_relationship_to_one_eager.tpl index 3b24f1a..f6bba5b 100644 --- a/templates/07_relationship_to_one_eager.tpl +++ b/templates/07_relationship_to_one_eager.tpl @@ -45,20 +45,20 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula results, err := e.Query(query, args...) if err != nil { - return errors.Wrap(err, "failed to eager load {{$txt.ForeignTable.NameGo}}") + return errors.Prefix("failed to eager load {{$txt.ForeignTable.NameGo}}", err) } defer results.Close() var resultSlice []*{{$txt.ForeignTable.NameGo}} if err = queries.Bind(results, &resultSlice); err != nil { - return errors.Wrap(err, "failed to bind eager loaded slice {{$txt.ForeignTable.NameGo}}") + return errors.Prefix("failed to bind eager loaded slice {{$txt.ForeignTable.NameGo}}", err) } {{if not $dot.NoHooks -}} if len({{$varNameSingular}}AfterSelectHooks) != 0 { for _, obj := range resultSlice { if err := obj.doAfterSelectHooks(e); err != nil { - return err + return errors.Err(err) } } } diff --git a/templates/08_relationship_one_to_one_eager.tpl b/templates/08_relationship_one_to_one_eager.tpl index 37d1af0..cd587fc 100644 --- a/templates/08_relationship_one_to_one_eager.tpl +++ b/templates/08_relationship_one_to_one_eager.tpl @@ -45,20 +45,20 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula results, err := e.Query(query, args...) if err != nil { - return errors.Wrap(err, "failed to eager load {{$txt.ForeignTable.NameGo}}") + return errors.Prefix("failed to eager load {{$txt.ForeignTable.NameGo}}", err) } defer results.Close() var resultSlice []*{{$txt.ForeignTable.NameGo}} if err = queries.Bind(results, &resultSlice); err != nil { - return errors.Wrap(err, "failed to bind eager loaded slice {{$txt.ForeignTable.NameGo}}") + return errors.Prefix("failed to bind eager loaded slice {{$txt.ForeignTable.NameGo}}", err) } {{if not $dot.NoHooks -}} if len({{$varNameSingular}}AfterSelectHooks) != 0 { for _, obj := range resultSlice { if err := obj.doAfterSelectHooks(e); err != nil { - return err + return errors.Err(err) } } } diff --git a/templates/09_relationship_to_many_eager.tpl b/templates/09_relationship_to_many_eager.tpl index 1603188..f3fd2c4 100644 --- a/templates/09_relationship_to_many_eager.tpl +++ b/templates/09_relationship_to_many_eager.tpl @@ -54,7 +54,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula results, err := e.Query(query, args...) if err != nil { - return errors.Wrap(err, "failed to eager load {{.ForeignTable}}") + return errors.Prefix("failed to eager load {{.ForeignTable}}", err) } defer results.Close() @@ -70,7 +70,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula err = results.Scan({{$foreignTable.Columns | columnNames | stringMap $dot.StringFuncs.titleCase | prefixStringSlice "&one." | join ", "}}, &localJoinCol) if err = results.Err(); err != nil { - return errors.Wrap(err, "failed to plebian-bind eager loaded slice {{.ForeignTable}}") + return errors.Prefix("failed to plebian-bind eager loaded slice {{.ForeignTable}}", err) } resultSlice = append(resultSlice, one) @@ -78,11 +78,11 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula } if err = results.Err(); err != nil { - return errors.Wrap(err, "failed to plebian-bind eager loaded slice {{.ForeignTable}}") + return errors.Prefix("failed to plebian-bind eager loaded slice {{.ForeignTable}}", err) } {{else -}} if err = queries.Bind(results, &resultSlice); err != nil { - return errors.Wrap(err, "failed to bind eager loaded slice {{.ForeignTable}}") + return errors.Prefix("failed to bind eager loaded slice {{.ForeignTable}}", err) } {{end}} @@ -90,7 +90,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula if len({{.ForeignTable | singular | camelCase}}AfterSelectHooks) != 0 { for _, obj := range resultSlice { if err := obj.doAfterSelectHooks(e); err != nil { - return err + return errors.Err(err) } } } diff --git a/templates/10_relationship_to_one_setops.tpl b/templates/10_relationship_to_one_setops.tpl index 14f726e..200adc3 100644 --- a/templates/10_relationship_to_one_setops.tpl +++ b/templates/10_relationship_to_one_setops.tpl @@ -20,7 +20,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}G(insert bool, rel // Panics on error. func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}P(exec boil.Executor, insert bool, related *{{$txt.ForeignTable.NameGo}}) { if err := o.Set{{$txt.Function.Name}}(exec, insert, related); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -30,7 +30,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}P(exec boil.Execut // Uses the global database handle and panics on error. func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}GP(insert bool, related *{{$txt.ForeignTable.NameGo}}) { if err := o.Set{{$txt.Function.Name}}(boil.GetDB(), insert, related); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -41,7 +41,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo var err error if insert { if err = related.Insert(exec); err != nil { - return errors.Wrap(err, "failed to insert into foreign table") + return errors.Prefix("failed to insert into foreign table", err) } } @@ -58,7 +58,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo } if _, err = exec.Exec(updateQuery, values...); err != nil { - return errors.Wrap(err, "failed to update local table") + return errors.Prefix("failed to update local table", err) } o.{{$txt.Function.LocalAssignment}} = related.{{$txt.Function.ForeignAssignment}} @@ -110,7 +110,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}G(related *{{$t // Panics on error. func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}P(exec boil.Executor, related *{{$txt.ForeignTable.NameGo}}) { if err := o.Remove{{$txt.Function.Name}}(exec, related); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -120,7 +120,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}P(exec boil.Exe // Uses the global database handle and panics on error. func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}GP(related *{{$txt.ForeignTable.NameGo}}) { if err := o.Remove{{$txt.Function.Name}}(boil.GetDB(), related); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -133,7 +133,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Exec o.{{$txt.LocalTable.ColumnNameGo}}.Valid = false if err = o.Update(exec, "{{.Column}}"); err != nil { o.{{$txt.LocalTable.ColumnNameGo}}.Valid = true - return errors.Wrap(err, "failed to update local table") + return errors.Prefix("failed to update local table", err) } o.R.{{$txt.Function.Name}} = nil diff --git a/templates/11_relationship_one_to_one_setops.tpl b/templates/11_relationship_one_to_one_setops.tpl index 826eec2..29ce0a1 100644 --- a/templates/11_relationship_one_to_one_setops.tpl +++ b/templates/11_relationship_one_to_one_setops.tpl @@ -21,7 +21,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}G(insert bool, rel // Panics on error. func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}P(exec boil.Executor, insert bool, related *{{$txt.ForeignTable.NameGo}}) { if err := o.Set{{$txt.Function.Name}}(exec, insert, related); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -31,7 +31,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}P(exec boil.Execut // Uses the global database handle and panics on error. func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}GP(insert bool, related *{{$txt.ForeignTable.NameGo}}) { if err := o.Set{{$txt.Function.Name}}(boil.GetDB(), insert, related); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -48,7 +48,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo {{- end}} if err = related.Insert(exec); err != nil { - return errors.Wrap(err, "failed to insert into foreign table") + return errors.Prefix("failed to insert into foreign table", err) } } else { updateQuery := fmt.Sprintf( @@ -64,7 +64,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo } if _, err = exec.Exec(updateQuery, values...); err != nil { - return errors.Wrap(err, "failed to update foreign table") + return errors.Prefix("failed to update foreign table", err) } related.{{$txt.Function.ForeignAssignment}} = o.{{$txt.Function.LocalAssignment}} @@ -107,7 +107,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}G(related *{{$t // Panics on error. func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}P(exec boil.Executor, related *{{$txt.ForeignTable.NameGo}}) { if err := o.Remove{{$txt.Function.Name}}(exec, related); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -117,7 +117,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}P(exec boil.Exe // Uses the global database handle and panics on error. func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}GP(related *{{$txt.ForeignTable.NameGo}}) { if err := o.Remove{{$txt.Function.Name}}(boil.GetDB(), related); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -130,7 +130,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Exec related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = false if err = related.Update(exec, "{{.ForeignColumn}}"); err != nil { related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = true - return errors.Wrap(err, "failed to update local table") + return errors.Prefix("failed to update local table", err) } o.R.{{$txt.Function.Name}} = nil diff --git a/templates/12_relationship_to_many_setops.tpl b/templates/12_relationship_to_many_setops.tpl index 06159ee..e54c2fd 100644 --- a/templates/12_relationship_to_many_setops.tpl +++ b/templates/12_relationship_to_many_setops.tpl @@ -24,7 +24,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}G(insert bool, rel // Panics on error. func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}P(exec boil.Executor, insert bool, related ...*{{$txt.ForeignTable.NameGo}}) { if err := o.Add{{$txt.Function.Name}}(exec, insert, related...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -35,7 +35,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}P(exec boil.Execut // Uses the global database handle and panics on error. func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}GP(insert bool, related ...*{{$txt.ForeignTable.NameGo}}) { if err := o.Add{{$txt.Function.Name}}(boil.GetDB(), insert, related...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -55,7 +55,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}(exec boil.Executo {{end -}} if err = rel.Insert(exec); err != nil { - return errors.Wrap(err, "failed to insert into foreign table") + return errors.Prefix("failed to insert into foreign table", err) } }{{if not .ToJoinTable}} else { updateQuery := fmt.Sprintf( @@ -71,7 +71,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}(exec boil.Executo } if _, err = exec.Exec(updateQuery, values...); err != nil { - return errors.Wrap(err, "failed to update foreign table") + return errors.Prefix("failed to update foreign table", err) } rel.{{$txt.Function.ForeignAssignment}} = o.{{$txt.Function.LocalAssignment}} @@ -93,7 +93,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}(exec boil.Executo _, err = exec.Exec(query, values...) if err != nil { - return errors.Wrap(err, "failed to insert into join table") + return errors.Prefix("failed to insert into join table", err) } } {{end -}} @@ -152,7 +152,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}G(insert bool, rel // Panics on error. func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}P(exec boil.Executor, insert bool, related ...*{{$txt.ForeignTable.NameGo}}) { if err := o.Set{{$txt.Function.Name}}(exec, insert, related...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -165,7 +165,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}P(exec boil.Execut // Uses the global database handle and panics on error. func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}GP(insert bool, related ...*{{$txt.ForeignTable.NameGo}}) { if err := o.Set{{$txt.Function.Name}}(boil.GetDB(), insert, related...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -190,7 +190,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo _, err := exec.Exec(query, values...) if err != nil { - return errors.Wrap(err, "failed to remove relationships before set") + return errors.Prefix("failed to remove relationships before set", err) } {{if .ToJoinTable -}} @@ -230,7 +230,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}G(related ...*{ // Panics on error. func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}P(exec boil.Executor, related ...*{{$txt.ForeignTable.NameGo}}) { if err := o.Remove{{$txt.Function.Name}}(exec, related...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -240,7 +240,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}P(exec boil.Exe // Uses the global database handle and panics on error. func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}GP(related ...*{{$txt.ForeignTable.NameGo}}) { if err := o.Remove{{$txt.Function.Name}}(boil.GetDB(), related...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -266,7 +266,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Exec _, err = exec.Exec(query, values...) if err != nil { - return errors.Wrap(err, "failed to remove relationships before set") + return errors.Prefix("failed to remove relationships before set", err) } {{else -}} for _, rel := range related { @@ -277,7 +277,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Exec } {{end -}} if err = rel.Update(exec, "{{.ForeignColumn}}"); err != nil { - return err + return errors.Err(err) } } {{end -}} diff --git a/templates/14_find.tpl b/templates/14_find.tpl index b7f69db..f9a88c8 100644 --- a/templates/14_find.tpl +++ b/templates/14_find.tpl @@ -12,7 +12,7 @@ func Find{{$tableNameSingular}}G({{$pkArgs}}, selectCols ...string) (*{{$tableNa func Find{{$tableNameSingular}}GP({{$pkArgs}}, selectCols ...string) *{{$tableNameSingular}} { retobj, err := Find{{$tableNameSingular}}(boil.GetDB(), {{$pkNames | join ", "}}, selectCols...) if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } return retobj @@ -35,10 +35,10 @@ func Find{{$tableNameSingular}}(exec boil.Executor, {{$pkArgs}}, selectCols ...s err := q.Bind({{$varNameSingular}}Obj) if err != nil { - if errors.Cause(err) == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return nil, nil } - return nil, errors.Wrap(err, "{{.PkgName}}: unable to select from {{.Table.Name}}") + return nil, errors.Prefix("{{.PkgName}}: unable to select from {{.Table.Name}}", err) } return {{$varNameSingular}}Obj, nil @@ -48,7 +48,7 @@ func Find{{$tableNameSingular}}(exec boil.Executor, {{$pkArgs}}, selectCols ...s func Find{{$tableNameSingular}}P(exec boil.Executor, {{$pkArgs}}, selectCols ...string) *{{$tableNameSingular}} { retobj, err := Find{{$tableNameSingular}}(exec, {{$pkNames | join ", "}}, selectCols...) if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } return retobj @@ -64,10 +64,10 @@ func FindOne{{$tableNameSingular}}(exec boil.Executor, filters {{$tableNameSingu Bind(obj) if err != nil { - if errors.Cause(err) == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return nil, nil } - return nil, errors.Wrap(err, "{{.PkgName}}: unable to select from {{.Table.Name}}") + return nil, errors.Prefix("{{.PkgName}}: unable to select from {{.Table.Name}}", err) } return obj, nil diff --git a/templates/15_insert.tpl b/templates/15_insert.tpl index 870e20d..20905ac 100644 --- a/templates/15_insert.tpl +++ b/templates/15_insert.tpl @@ -10,7 +10,7 @@ func (o *{{$tableNameSingular}}) InsertG(whitelist ... string) error { // behavior description. func (o *{{$tableNameSingular}}) InsertGP(whitelist ... string) { if err := o.Insert(boil.GetDB(), whitelist...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -18,7 +18,7 @@ func (o *{{$tableNameSingular}}) InsertGP(whitelist ... string) { // for whitelist behavior description. func (o *{{$tableNameSingular}}) InsertP(exec boil.Executor, whitelist ... string) { if err := o.Insert(exec, whitelist...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -29,7 +29,7 @@ func (o *{{$tableNameSingular}}) InsertP(exec boil.Executor, whitelist ... strin // - All columns with a default, but non-zero are included (i.e. health = 75) func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string) error { if o == nil { - return errors.New("{{.PkgName}}: no {{.Table.Name}} provided for insertion") + return errors.Err("{{.PkgName}}: no {{.Table.Name}} provided for insertion") } var err error @@ -37,7 +37,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string {{if not .NoHooks -}} if err := o.doBeforeInsertHooks(exec); err != nil { - return err + return errors.Err(err) } {{- end}} @@ -59,11 +59,11 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string cache.valueMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, wl) if err != nil { - return err + return errors.Err(err) } cache.retMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, returnColumns) if err != nil { - return err + return errors.Err(err) } if len(wl) != 0 { cache.query = fmt.Sprintf("INSERT INTO {{$schemaTable}} ({{.LQ}}%s{{.RQ}}) %%sVALUES (%s)%%s", strings.Join(wl, "{{.RQ}},{{.LQ}}"), strmangle.Placeholders(dialect.IndexPlaceholders, len(wl), 1, 1)) @@ -110,7 +110,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string _, err = exec.Exec(cache.query, vals...) {{- end}} if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to insert into {{.Table.Name}}") + return errors.Prefix("{{.PkgName}}: unable to insert into {{.Table.Name}}", err) } {{if $canLastInsertID -}} @@ -125,7 +125,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string {{if $canLastInsertID -}} lastID, err = result.LastInsertId() if err != nil { - return ErrSyncFail + return errors.Err(ErrSyncFail) } {{$colName := index .Table.PKey.Columns 0 -}} @@ -150,7 +150,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...) if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to populate default values for {{.Table.Name}}") + return errors.Prefix("{{.PkgName}}: unable to populate default values for {{.Table.Name}}", err) } {{else}} if len(cache.retMapping) != 0 { @@ -160,7 +160,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string } if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to insert into {{.Table.Name}}") + return errors.Prefix("{{.PkgName}}: unable to insert into {{.Table.Name}}", err) } {{end}} diff --git a/templates/16_update.tpl b/templates/16_update.tpl index bc4a6f5..eee2036 100644 --- a/templates/16_update.tpl +++ b/templates/16_update.tpl @@ -12,7 +12,7 @@ func (o *{{$tableNameSingular}}) UpdateG(whitelist ...string) error { // Panics on error. See Update for whitelist behavior description. func (o *{{$tableNameSingular}}) UpdateGP(whitelist ...string) { if err := o.Update(boil.GetDB(), whitelist...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -21,7 +21,7 @@ func (o *{{$tableNameSingular}}) UpdateGP(whitelist ...string) { func (o *{{$tableNameSingular}}) UpdateP(exec boil.Executor, whitelist ... string) { err := o.Update(exec, whitelist...) if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -38,7 +38,7 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string var err error {{if not .NoHooks -}} if err = o.doBeforeUpdateHooks(exec); err != nil { - return err + return errors.Err(err) } {{end -}} @@ -62,7 +62,7 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string } {{end -}} if len(wl) == 0 { - return errors.New("{{.PkgName}}: unable to update {{.Table.Name}}, could not build whitelist") + return errors.Err("{{.PkgName}}: unable to update {{.Table.Name}}, could not build whitelist") } cache.query = fmt.Sprintf("UPDATE {{$schemaTable}} SET %s WHERE %s", @@ -71,7 +71,7 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string ) cache.valueMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, append(wl, {{$varNameSingular}}PrimaryKeyColumns...)) if err != nil { - return err + return errors.Err(err) } } @@ -84,7 +84,7 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string _, err = exec.Exec(cache.query, values...) if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to update {{.Table.Name}} row") + return errors.Prefix("{{.PkgName}}: unable to update {{.Table.Name}} row", err) } if !cached { @@ -103,7 +103,7 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string // UpdateAllP updates all rows with matching column names, and panics on error. func (q {{$tableNameSingular}}Query) UpdateAllP(cols M) { if err := q.UpdateAll(cols); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -113,7 +113,7 @@ func (q {{$tableNameSingular}}Query) UpdateAll(cols M) error { _, err := q.Query.Exec() if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to update all for {{.Table.Name}}") + return errors.Prefix("{{.PkgName}}: unable to update all for {{.Table.Name}}", err) } return nil @@ -127,14 +127,14 @@ func (o {{$tableNameSingular}}Slice) UpdateAllG(cols M) error { // UpdateAllGP updates all rows with the specified column values, and panics on error. func (o {{$tableNameSingular}}Slice) UpdateAllGP(cols M) { if err := o.UpdateAll(boil.GetDB(), cols); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } // UpdateAllP updates all rows with the specified column values, and panics on error. func (o {{$tableNameSingular}}Slice) UpdateAllP(exec boil.Executor, cols M) { if err := o.UpdateAll(exec, cols); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -146,7 +146,7 @@ func (o {{$tableNameSingular}}Slice) UpdateAll(exec boil.Executor, cols M) error } if len(cols) == 0 { - return errors.New("{{.PkgName}}: update all requires at least one column argument") + return errors.Err("{{.PkgName}}: update all requires at least one column argument") } colNames := make([]string, len(cols)) @@ -176,7 +176,7 @@ func (o {{$tableNameSingular}}Slice) UpdateAll(exec boil.Executor, cols M) error _, err := exec.Exec(sql, args...) if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to update all in {{$varNameSingular}} slice") + return errors.Prefix("{{.PkgName}}: unable to update all in {{$varNameSingular}} slice", err) } return nil diff --git a/templates/17_upsert.tpl b/templates/17_upsert.tpl index dbce58c..b713243 100644 --- a/templates/17_upsert.tpl +++ b/templates/17_upsert.tpl @@ -9,7 +9,7 @@ func (o *{{$tableNameSingular}}) UpsertG({{if eq .DriverName "postgres"}}updateO // UpsertGP attempts an insert, and does an update or ignore on conflict. Panics on error. func (o *{{$tableNameSingular}}) UpsertGP({{if eq .DriverName "postgres"}}updateOnConflict bool, conflictColumns []string, {{end}}updateColumns []string, whitelist ...string) { if err := o.Upsert(boil.GetDB(), {{if eq .DriverName "postgres"}}updateOnConflict, conflictColumns, {{end}}updateColumns, whitelist...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -17,21 +17,21 @@ func (o *{{$tableNameSingular}}) UpsertGP({{if eq .DriverName "postgres"}}update // UpsertP panics on error. func (o *{{$tableNameSingular}}) UpsertP(exec boil.Executor, {{if eq .DriverName "postgres"}}updateOnConflict bool, conflictColumns []string, {{end}}updateColumns []string, whitelist ...string) { if err := o.Upsert(exec, {{if eq .DriverName "postgres"}}updateOnConflict, conflictColumns, {{end}}updateColumns, whitelist...); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } // Upsert attempts an insert using an executor, and does an update or ignore on conflict. func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName "postgres"}}updateOnConflict bool, conflictColumns []string, {{end}}updateColumns []string, whitelist ...string) error { if o == nil { - return errors.New("{{.PkgName}}: no {{.Table.Name}} provided for upsert") + return errors.Err("{{.PkgName}}: no {{.Table.Name}} provided for upsert") } {{- template "timestamp_upsert_helper" . }} {{if not .NoHooks -}} if err := o.doBeforeUpsertHooks(exec); err != nil { - return err + return errors.Err(err) } {{- end}} @@ -87,7 +87,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName } } if len(insert) == 0 { - return errors.New("{{.PkgName}}: unable to upsert {{.Table.Name}}, could not build insert column list") + return errors.Err("{{.PkgName}}: unable to upsert {{.Table.Name}}, could not build insert column list") } ret = strmangle.SetMerge(ret, {{$varNameSingular}}ColumnsWithAuto) @@ -104,7 +104,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName {{end -}} if len(update) == 0 { - return errors.New("{{.PkgName}}: unable to upsert {{.Table.Name}}, could not build update column list") + return errors.Err("{{.PkgName}}: unable to upsert {{.Table.Name}}, could not build update column list") } {{if eq .DriverName "postgres"}} @@ -129,12 +129,12 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName cache.valueMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, {{if eq .DriverName "mssql"}}whitelist{{else}}insert{{end}}) if err != nil { - return err + return errors.Err(err) } if len(ret) != 0 { cache.retMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, ret) if err != nil { - return err + return errors.Err(err) } } } @@ -159,7 +159,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName _, err = exec.Exec(cache.query, vals...) {{- end}} if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to upsert for {{.Table.Name}}") + return errors.Prefix("{{.PkgName}}: unable to upsert for {{.Table.Name}}", err) } {{if $canLastInsertID -}} @@ -174,7 +174,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName {{if $canLastInsertID -}} lastID, err = result.LastInsertId() if err != nil { - return ErrSyncFail + return errors.Err(ErrSyncFail) } {{$colName := index .Table.PKey.Columns 0 -}} @@ -199,7 +199,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(returns...) if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to populate default values for {{.Table.Name}}") + return errors.Prefix("{{.PkgName}}: unable to populate default values for {{.Table.Name}}", err) } {{- else}} if len(cache.retMapping) != 0 { @@ -211,7 +211,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName _, err = exec.Exec(cache.query, vals...) } if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to upsert {{.Table.Name}}") + return errors.Prefix("{{.PkgName}}: unable to upsert {{.Table.Name}}", err) } {{- end}} diff --git a/templates/18_delete.tpl b/templates/18_delete.tpl index aea163e..1ab82a3 100644 --- a/templates/18_delete.tpl +++ b/templates/18_delete.tpl @@ -6,7 +6,7 @@ // Panics on error. func (o *{{$tableNameSingular}}) DeleteP(exec boil.Executor) { if err := o.Delete(exec); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -14,7 +14,7 @@ func (o *{{$tableNameSingular}}) DeleteP(exec boil.Executor) { // DeleteG will match against the primary key column to find the record to delete. func (o *{{$tableNameSingular}}) DeleteG() error { if o == nil { - return errors.New("{{.PkgName}}: no {{$tableNameSingular}} provided for deletion") + return errors.Err("{{.PkgName}}: no {{$tableNameSingular}} provided for deletion") } return o.Delete(boil.GetDB()) @@ -25,7 +25,7 @@ func (o *{{$tableNameSingular}}) DeleteG() error { // Panics on error. func (o *{{$tableNameSingular}}) DeleteGP() { if err := o.DeleteG(); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -33,12 +33,12 @@ func (o *{{$tableNameSingular}}) DeleteGP() { // Delete will match against the primary key column to find the record to delete. func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error { if o == nil { - return errors.New("{{.PkgName}}: no {{$tableNameSingular}} provided for delete") + return errors.Err("{{.PkgName}}: no {{$tableNameSingular}} provided for delete") } {{if not .NoHooks -}} if err := o.doBeforeDeleteHooks(exec); err != nil { - return err + return errors.Err(err) } {{- end}} @@ -52,12 +52,12 @@ func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error { _, err := exec.Exec(sql, args...) if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to delete from {{.Table.Name}}") + return errors.Prefix("{{.PkgName}}: unable to delete from {{.Table.Name}}", err) } {{if not .NoHooks -}} if err := o.doAfterDeleteHooks(exec); err != nil { - return err + return errors.Err(err) } {{- end}} @@ -67,21 +67,21 @@ func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error { // DeleteAllP deletes all rows, and panics on error. func (q {{$tableNameSingular}}Query) DeleteAllP() { if err := q.DeleteAll(); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } // DeleteAll deletes all matching rows. func (q {{$tableNameSingular}}Query) DeleteAll() error { if q.Query == nil { - return errors.New("{{.PkgName}}: no {{$tableNameSingular}}Query provided for delete all") + return errors.Err("{{.PkgName}}: no {{$tableNameSingular}}Query provided for delete all") } queries.SetDelete(q.Query) _, err := q.Query.Exec() if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to delete all from {{.Table.Name}}") + return errors.Prefix("{{.PkgName}}: unable to delete all from {{.Table.Name}}", err) } return nil @@ -90,14 +90,14 @@ func (q {{$tableNameSingular}}Query) DeleteAll() error { // DeleteAllGP deletes all rows in the slice, and panics on error. func (o {{$tableNameSingular}}Slice) DeleteAllGP() { if err := o.DeleteAllG(); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } // DeleteAllG deletes all rows in the slice. func (o {{$tableNameSingular}}Slice) DeleteAllG() error { if o == nil { - return errors.New("{{.PkgName}}: no {{$tableNameSingular}} slice provided for delete all") + return errors.Err("{{.PkgName}}: no {{$tableNameSingular}} slice provided for delete all") } return o.DeleteAll(boil.GetDB()) } @@ -105,14 +105,14 @@ func (o {{$tableNameSingular}}Slice) DeleteAllG() error { // DeleteAllP deletes all rows in the slice, using an executor, and panics on error. func (o {{$tableNameSingular}}Slice) DeleteAllP(exec boil.Executor) { if err := o.DeleteAll(exec); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } // DeleteAll deletes all rows in the slice, using an executor. func (o {{$tableNameSingular}}Slice) DeleteAll(exec boil.Executor) error { if o == nil { - return errors.New("{{.PkgName}}: no {{$tableNameSingular}} slice provided for delete all") + return errors.Err("{{.PkgName}}: no {{$tableNameSingular}} slice provided for delete all") } if len(o) == 0 { @@ -123,7 +123,7 @@ func (o {{$tableNameSingular}}Slice) DeleteAll(exec boil.Executor) error { if len({{$varNameSingular}}BeforeDeleteHooks) != 0 { for _, obj := range o { if err := obj.doBeforeDeleteHooks(exec); err != nil { - return err + return errors.Err(err) } } } @@ -145,14 +145,14 @@ func (o {{$tableNameSingular}}Slice) DeleteAll(exec boil.Executor) error { _, err := exec.Exec(sql, args...) if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to delete all from {{$varNameSingular}} slice") + return errors.Prefix("{{.PkgName}}: unable to delete all from {{$varNameSingular}} slice", err) } {{if not .NoHooks -}} if len({{$varNameSingular}}AfterDeleteHooks) != 0 { for _, obj := range o { if err := obj.doAfterDeleteHooks(exec); err != nil { - return err + return errors.Err(err) } } } diff --git a/templates/19_reload.tpl b/templates/19_reload.tpl index b1201b8..c7c5273 100644 --- a/templates/19_reload.tpl +++ b/templates/19_reload.tpl @@ -5,21 +5,21 @@ // ReloadGP refetches the object from the database and panics on error. func (o *{{$tableNameSingular}}) ReloadGP() { if err := o.ReloadG(); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } // ReloadP refetches the object from the database with an executor. Panics on error. func (o *{{$tableNameSingular}}) ReloadP(exec boil.Executor) { if err := o.Reload(exec); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } // ReloadG refetches the object from the database using the primary keys. func (o *{{$tableNameSingular}}) ReloadG() error { if o == nil { - return errors.New("{{.PkgName}}: no {{$tableNameSingular}} provided for reload") + return errors.Err("{{.PkgName}}: no {{$tableNameSingular}} provided for reload") } return o.Reload(boil.GetDB()) @@ -30,7 +30,7 @@ func (o *{{$tableNameSingular}}) ReloadG() error { func (o *{{$tableNameSingular}}) Reload(exec boil.Executor) error { ret, err := Find{{$tableNameSingular}}(exec, {{.Table.PKey.Columns | stringMap .StringFuncs.titleCase | prefixStringSlice "o." | join ", "}}) if err != nil { - return err + return errors.Err(err) } *o = *ret @@ -42,7 +42,7 @@ func (o *{{$tableNameSingular}}) Reload(exec boil.Executor) error { // Panics on error. func (o *{{$tableNameSingular}}Slice) ReloadAllGP() { if err := o.ReloadAllG(); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -51,7 +51,7 @@ func (o *{{$tableNameSingular}}Slice) ReloadAllGP() { // Panics on error. func (o *{{$tableNameSingular}}Slice) ReloadAllP(exec boil.Executor) { if err := o.ReloadAll(exec); err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } } @@ -59,7 +59,7 @@ func (o *{{$tableNameSingular}}Slice) ReloadAllP(exec boil.Executor) { // and overwrites the original object slice with the newly updated slice. func (o *{{$tableNameSingular}}Slice) ReloadAllG() error { if o == nil { - return errors.New("{{.PkgName}}: empty {{$tableNameSingular}}Slice provided for reload all") + return errors.Err("{{.PkgName}}: empty {{$tableNameSingular}}Slice provided for reload all") } return o.ReloadAll(boil.GetDB()) @@ -86,7 +86,7 @@ func (o *{{$tableNameSingular}}Slice) ReloadAll(exec boil.Executor) error { err := q.Bind(&{{$varNamePlural}}) if err != nil { - return errors.Wrap(err, "{{.PkgName}}: unable to reload all in {{$tableNameSingular}}Slice") + return errors.Prefix("{{.PkgName}}: unable to reload all in {{$tableNameSingular}}Slice", err) } *o = {{$varNamePlural}} diff --git a/templates/20_exists.tpl b/templates/20_exists.tpl index 2e20fa6..2a36c23 100644 --- a/templates/20_exists.tpl +++ b/templates/20_exists.tpl @@ -22,7 +22,7 @@ func {{$tableNameSingular}}Exists(exec boil.Executor, {{$pkArgs}}) (bool, error) err := row.Scan(&exists) if err != nil { - return false, errors.Wrap(err, "{{.PkgName}}: unable to check if {{.Table.Name}} exists") + return false, errors.Prefix("{{.PkgName}}: unable to check if {{.Table.Name}} exists", err) } return exists, nil @@ -37,7 +37,7 @@ func {{$tableNameSingular}}ExistsG({{$pkArgs}}) (bool, error) { func {{$tableNameSingular}}ExistsGP({{$pkArgs}}) bool { e, err := {{$tableNameSingular}}Exists(boil.GetDB(), {{$pkNames | join ", "}}) if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } return e @@ -47,7 +47,7 @@ func {{$tableNameSingular}}ExistsGP({{$pkArgs}}) bool { func {{$tableNameSingular}}ExistsP(exec boil.Executor, {{$pkArgs}}) bool { e, err := {{$tableNameSingular}}Exists(exec, {{$pkNames | join ", "}}) if err != nil { - panic(boil.WrapErr(err)) + panic(errors.Err(err)) } return e diff --git a/templates/23_merge.tpl b/templates/23_merge.tpl index 9f1af10..16a7b58 100644 --- a/templates/23_merge.tpl +++ b/templates/23_merge.tpl @@ -9,12 +9,12 @@ func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID if !ok { txdb, ok := exec.(boil.Beginner) if !ok { - return errors.New("database does not support transactions") + return errors.Err("database does not support transactions") } tx, err = txdb.Begin() if err != nil { - return err + return errors.Err(err) } defer func() { @@ -31,16 +31,16 @@ func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID primary, err := Find{{$tableNameSingular}}(tx, primaryID) if err != nil { - return err + return errors.Err(err) } else if primary == nil { - return errors.New("Primary {{$tableNameSingular}} not found") + return errors.Err("primary {{$tableNameSingular}} not found") } secondary, err := Find{{$tableNameSingular}}(tx, secondaryID) if err != nil { - return err + return errors.Err(err) } else if secondary == nil { - return errors.New("Secondary {{$tableNameSingular}} not found") + return errors.Err("secondary {{$tableNameSingular}} not found") } foreignKeys := []foreignKey{ @@ -89,12 +89,12 @@ func Merge{{$tableNamePlural}}(exec boil.Executor, primaryID uint64, secondaryID err = primary.Update(tx) if err != nil { - return errors.WithStack(err) + return err } err = secondary.Delete(tx) if err != nil { - return errors.WithStack(err) + return err } return nil diff --git a/templates/singleton/boil_queries.tpl b/templates/singleton/boil_queries.tpl index 1260dde..51ed108 100644 --- a/templates/singleton/boil_queries.tpl +++ b/templates/singleton/boil_queries.tpl @@ -29,7 +29,7 @@ func mergeModels(tx boil.Executor, primaryID uint64, secondaryID uint64, foreign for _, conflict := range conflictingKeys { err = deleteConflictsBeforeMerge(tx, conflict, primaryID, secondaryID) if err != nil { - return errors.WithStack(err) + return err } } @@ -42,7 +42,7 @@ func mergeModels(tx boil.Executor, primaryID uint64, secondaryID uint64, foreign ) _, err = tx.Exec(query, primaryID, secondaryID) if err != nil { - return errors.WithStack(err) + return errors.Err(err) } } return checkMerge(tx, foreignKeys) @@ -54,7 +54,7 @@ func deleteConflictsBeforeMerge(tx boil.Executor, conflict conflictingUniqueKey, if len(conflictingColumns) < 1 { return nil } else if len(conflictingColumns) > 1 { - return errors.New("this doesnt work for unique keys with more than two columns (yet)") + return errors.Err("this doesnt work for unique keys with more than two columns (yet)") } query := fmt.Sprintf( @@ -67,7 +67,7 @@ func deleteConflictsBeforeMerge(tx boil.Executor, conflict conflictingUniqueKey, rows, err := tx.Query(query, primaryID, secondaryID) defer rows.Close() if err != nil { - return errors.WithStack(err) + return errors.Err(err) } args := []interface{}{secondaryID} @@ -75,7 +75,7 @@ func deleteConflictsBeforeMerge(tx boil.Executor, conflict conflictingUniqueKey, var value string err = rows.Scan(&value) if err != nil { - return errors.WithStack(err) + return errors.Err(err) } args = append(args, value) } @@ -93,7 +93,7 @@ func deleteConflictsBeforeMerge(tx boil.Executor, conflict conflictingUniqueKey, _, err = tx.Exec(query, args...) if err != nil { - return errors.WithStack(err) + return errors.Err(err) } return nil } @@ -118,7 +118,7 @@ func checkMerge(tx boil.Executor, foreignKeys []foreignKey) error { rows, err := tx.Query(q, uniqueColumns...) defer rows.Close() if err != nil { - return errors.WithStack(err) + return errors.Err(err) } for rows.Next() { @@ -126,11 +126,11 @@ func checkMerge(tx boil.Executor, foreignKeys []foreignKey) error { var columnName string err = rows.Scan(&tableName, &columnName) if err != nil { - return errors.WithStack(err) + return errors.Err(err) } if _, exists := handledTablesColumns[tableName+"."+columnName]; !exists { - return errors.New("Missing merge for " + tableName + "." + columnName) + return errors.Err("missing merge for " + tableName + "." + columnName) } } diff --git a/templates/singleton/boil_types.tpl b/templates/singleton/boil_types.tpl index 547d05d..48a85e2 100644 --- a/templates/singleton/boil_types.tpl +++ b/templates/singleton/boil_types.tpl @@ -20,7 +20,7 @@ type conflictingUniqueKey struct { // ErrSyncFail occurs during insert when the record could not be retrieved in // order to populate default value information. This usually happens when LastInsertId // fails or there was a primary key configuration that was not resolvable. -var ErrSyncFail = errors.New("{{.PkgName}}: failed to synchronize data after insert") +var ErrSyncFail = errors.Base("{{.PkgName}}: failed to synchronize data after insert") type insertCache struct { query string diff --git a/templates_test/main_test/mssql_main.tpl b/templates_test/main_test/mssql_main.tpl index ba46be7..5b0b5e1 100644 --- a/templates_test/main_test/mssql_main.tpl +++ b/templates_test/main_test/mssql_main.tpl @@ -25,17 +25,17 @@ func (m *mssqlTester) setup() error { m.testDBName = randomize.StableDBName(m.dbName) if err = m.dropTestDB(); err != nil { - return err + return errors.Err(err) } if err = m.createTestDB(); err != nil { - return err + return errors.Err(err) } createCmd := exec.Command("sqlcmd", "-S", m.host, "-U", m.user, "-P", m.pass, "-d", m.testDBName) f, err := os.Open("tables_schema.sql") if err != nil { - return errors.Wrap(err, "failed to open tables_schema.sql file") + return errors.Prefix("failed to open tables_schema.sql file", err) } defer f.Close() @@ -43,12 +43,12 @@ func (m *mssqlTester) setup() error { createCmd.Stdin = newFKeyDestroyer(rgxMSSQLkey, f) if err = createCmd.Start(); err != nil { - return errors.Wrap(err, "failed to start sqlcmd command") + return errors.Prefix("failed to start sqlcmd command", err) } if err = createCmd.Wait(); err != nil { fmt.Println(err) - return errors.Wrap(err, "failed to wait for sqlcmd command") + return errors.Prefix("failed to wait for sqlcmd command", err) } return nil @@ -92,7 +92,7 @@ func (m *mssqlTester) teardown() error { } if err := m.dropTestDB(); err != nil { - return err + return errors.Err(err) } return nil @@ -110,7 +110,7 @@ func (m *mssqlTester) runCmd(stdin, command string, args ...string) error { fmt.Println("failed running:", command, args) fmt.Println(stdout.String()) fmt.Println(stderr.String()) - return err + return errors.Err(err) } return nil diff --git a/templates_test/main_test/mysql_main.tpl b/templates_test/main_test/mysql_main.tpl index b95b32c..ef735e2 100644 --- a/templates_test/main_test/mysql_main.tpl +++ b/templates_test/main_test/mysql_main.tpl @@ -30,14 +30,14 @@ func (m *mysqlTester) setup() error { m.testDBName = randomize.StableDBName(m.dbName) if err = m.makeOptionFile(); err != nil { - return errors.Wrap(err, "couldn't make option file") + return errors.Prefix("couldn't make option file", err) } if err = m.dropTestDB(); err != nil { - return err + return errors.Err(err) } if err = m.createTestDB(); err != nil { - return err + return errors.Err(err) } dumpCmd := exec.Command("mysqldump", m.defaultsFile(), "--no-data", m.dbName) @@ -48,22 +48,22 @@ func (m *mysqlTester) setup() error { createCmd.Stdin = newFKeyDestroyer(rgxMySQLkey, r) if err = dumpCmd.Start(); err != nil { - return errors.Wrap(err, "failed to start mysqldump command") + return errors.Prefix("failed to start mysqldump command", err) } if err = createCmd.Start(); err != nil { - return errors.Wrap(err, "failed to start mysql command") + return errors.Prefix("failed to start mysql command", err) } if err = dumpCmd.Wait(); err != nil { fmt.Println(err) - return errors.Wrap(err, "failed to wait for mysqldump command") + return errors.Prefix("failed to wait for mysqldump command", err) } w.Close() // After dumpCmd is done, close the write end of the pipe if err = createCmd.Wait(); err != nil { fmt.Println(err) - return errors.Wrap(err, "failed to wait for mysql command") + return errors.Prefix("failed to wait for mysql command", err) } return nil @@ -87,7 +87,7 @@ func (m *mysqlTester) defaultsFile() string { func (m *mysqlTester) makeOptionFile() error { tmp, err := ioutil.TempFile("", "optionfile") if err != nil { - return errors.Wrap(err, "failed to create option file") + return errors.Prefix("failed to create option file", err) } isTCP := false @@ -95,7 +95,7 @@ func (m *mysqlTester) makeOptionFile() error { if os.IsNotExist(err) { isTCP = true } else if err != nil { - return errors.Wrap(err, "could not stat m.host") + return errors.Prefix("could not stat m.host", err) } fmt.Fprintln(tmp, "[client]") @@ -139,7 +139,7 @@ func (m *mysqlTester) teardown() error { } if err := m.dropTestDB(); err != nil { - return err + return errors.Err(err) } return os.Remove(m.optionFile) @@ -159,7 +159,7 @@ func (m *mysqlTester) runCmd(stdin, command string, args ...string) error { fmt.Println("failed running:", command, args) fmt.Println(stdout.String()) fmt.Println(stderr.String()) - return err + return errors.Err(err) } return nil diff --git a/templates_test/main_test/postgres_main.tpl b/templates_test/main_test/postgres_main.tpl index 0abcba3..3110325 100644 --- a/templates_test/main_test/postgres_main.tpl +++ b/templates_test/main_test/postgres_main.tpl @@ -33,14 +33,14 @@ func (p *pgTester) setup() error { p.testDBName = randomize.StableDBName(p.dbName) if err = p.makePGPassFile(); err != nil { - return err + return errors.Err(err) } if err = p.dropTestDB(); err != nil { - return err + return errors.Err(err) } if err = p.createTestDB(); err != nil { - return err + return errors.Err(err) } dumpCmd := exec.Command("pg_dump", "--schema-only", p.dbName) @@ -53,22 +53,22 @@ func (p *pgTester) setup() error { createCmd.Stdin = newFKeyDestroyer(rgxPGFkey, r) if err = dumpCmd.Start(); err != nil { - return errors.Wrap(err, "failed to start pg_dump command") + return errors.Prefix("failed to start pg_dump command", err) } if err = createCmd.Start(); err != nil { - return errors.Wrap(err, "failed to start psql command") + return errors.Prefix("failed to start psql command", err) } if err = dumpCmd.Wait(); err != nil { fmt.Println(err) - return errors.Wrap(err, "failed to wait for pg_dump command") + return errors.Prefix("failed to wait for pg_dump command", err) } w.Close() // After dumpCmd is done, close the write end of the pipe if err = createCmd.Wait(); err != nil { fmt.Println(err) - return errors.Wrap(err, "failed to wait for psql command") + return errors.Prefix("failed to wait for psql command", err) } return nil @@ -90,7 +90,7 @@ func (p *pgTester) runCmd(stdin, command string, args ...string) error { fmt.Println("failed running:", command, args) fmt.Println(stdout.String()) fmt.Println(stderr.String()) - return err + return errors.Err(err) } return nil @@ -108,7 +108,7 @@ func (p *pgTester) pgEnv() []string { func (p *pgTester) makePGPassFile() error { tmp, err := ioutil.TempFile("", "pgpass") if err != nil { - return errors.Wrap(err, "failed to create option file") + return errors.Prefix("failed to create option file", err) } fmt.Fprintf(tmp, "%s:%d:postgres:%s", p.host, p.port, p.user) @@ -145,12 +145,12 @@ func (p *pgTester) dropTestDB() error { func (p *pgTester) teardown() error { var err error if err = p.dbConn.Close(); err != nil { - return err + return errors.Err(err) } p.dbConn = nil if err = p.dropTestDB(); err != nil { - return err + return errors.Err(err) } return os.Remove(p.pgPassFile) diff --git a/templates_test/singleton/boil_main_test.tpl b/templates_test/singleton/boil_main_test.tpl index ebb4758..3cf466d 100644 --- a/templates_test/singleton/boil_main_test.tpl +++ b/templates_test/singleton/boil_main_test.tpl @@ -143,5 +143,5 @@ func validateConfig(driverName string) error { ).Check() } - return errors.New("not a valid driver name") + return errors.Err("not a valid driver name") } From 77fc991e7b786a1b1f373a274ff5e6457e43f2df Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Thu, 22 Feb 2018 13:18:41 -0500 Subject: [PATCH 24/35] new location for null.go --- boilingcore/imports.go | 50 ++++++++++++++++++------------------- boilingcore/imports_test.go | 10 ++++---- queries/helpers_test.go | 2 +- queries/query.go | 2 +- randomize/randomize.go | 2 +- randomize/randomize_test.go | 2 +- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/boilingcore/imports.go b/boilingcore/imports.go index b73b429..9a5c656 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -170,8 +170,8 @@ func newImporter() importer { `"time"`, }, thirdParty: importList{ - `"github.com/lbryio/errors.go"`, - `"github.com/lbryio/null.go"`, + `"github.com/lbryio/lbry.go/errors"`, + `"github.com/lbryio/lbry.go/null"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, @@ -185,7 +185,7 @@ func newImporter() importer { `"fmt"`, }, thirdParty: importList{ - `"github.com/lbryio/errors.go"`, + `"github.com/lbryio/lbry.go/errors"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, @@ -194,7 +194,7 @@ func newImporter() importer { }, "boil_types": { thirdParty: importList{ - `"github.com/lbryio/errors.go"`, + `"github.com/lbryio/lbry.go/errors"`, `"github.com/lbryio/sqlboiler/strmangle"`, }, }, @@ -227,7 +227,7 @@ func newImporter() importer { }, thirdParty: importList{ `"github.com/kat-co/vala"`, - `"github.com/lbryio/errors.go"`, + `"github.com/lbryio/lbry.go/errors"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/spf13/viper"`, }, @@ -265,7 +265,7 @@ func newImporter() importer { `"strings"`, }, thirdParty: importList{ - `"github.com/lbryio/errors.go"`, + `"github.com/lbryio/lbry.go/errors"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, `_ "github.com/lib/pq"`, @@ -285,7 +285,7 @@ func newImporter() importer { }, thirdParty: importList{ `_ "github.com/go-sql-driver/mysql"`, - `"github.com/lbryio/errors.go"`, + `"github.com/lbryio/lbry.go/errors"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, `"github.com/spf13/viper"`, @@ -302,7 +302,7 @@ func newImporter() importer { }, thirdParty: importList{ `_ "github.com/denisenkom/go-mssqldb"`, - `"github.com/lbryio/errors.go"`, + `"github.com/lbryio/lbry.go/errors"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, `"github.com/spf13/viper"`, @@ -315,55 +315,55 @@ func newImporter() importer { // TranslateColumnType to see the type assignments. imp.BasedOnType = mapImports{ "null.Float32": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Float64": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Int": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Int8": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Int16": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Int32": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Int64": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Uint": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Uint8": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Uint16": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Uint32": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Uint64": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.String": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Bool": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Time": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.JSON": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "null.Bytes": { - thirdParty: importList{`"github.com/lbryio/null.go"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, }, "time.Time": { standard: importList{`"time"`}, diff --git a/boilingcore/imports_test.go b/boilingcore/imports_test.go index b25eece..693bc10 100644 --- a/boilingcore/imports_test.go +++ b/boilingcore/imports_test.go @@ -246,7 +246,7 @@ func TestCombineTypeImports(t *testing.T) { }, thirdParty: importList{ `"github.com/lbryio/sqlboiler/boil"`, - `"github.com/lbryio/null.go"`, + `"github.com/lbryio/lbry.go/null"`, }, } @@ -281,7 +281,7 @@ func TestCombineTypeImports(t *testing.T) { }, thirdParty: importList{ `"github.com/lbryio/sqlboiler/boil"`, - `"github.com/lbryio/null.go"`, + `"github.com/lbryio/lbry.go/null"`, }, } @@ -297,7 +297,7 @@ func TestCombineImports(t *testing.T) { a := imports{ standard: importList{"fmt"}, - thirdParty: importList{"github.com/lbryio/sqlboiler", "github.com/lbryio/null.go"}, + thirdParty: importList{"github.com/lbryio/sqlboiler", "github.com/lbryio/lbry.go/null"}, } b := imports{ standard: importList{"os"}, @@ -309,8 +309,8 @@ func TestCombineImports(t *testing.T) { if c.standard[0] != "fmt" && c.standard[1] != "os" { t.Errorf("Wanted: fmt, os got: %#v", c.standard) } - if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "github.com/lbryio/null.go" { - t.Errorf("Wanted: github.com/lbryio/sqlboiler, github.com/lbryio/null.go got: %#v", c.thirdParty) + if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "github.com/lbryio/lbry.go/null" { + t.Errorf("Wanted: github.com/lbryio/sqlboiler, github.com/lbryio/lbry.go/null got: %#v", c.thirdParty) } } diff --git a/queries/helpers_test.go b/queries/helpers_test.go index ab4b4ac..b6b757d 100644 --- a/queries/helpers_test.go +++ b/queries/helpers_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - null "github.com/lbryio/null.go" + null "github.com/lbryio/lbry.go/null" ) type testObj struct { diff --git a/queries/query.go b/queries/query.go index a76c046..fdd54b4 100644 --- a/queries/query.go +++ b/queries/query.go @@ -4,7 +4,7 @@ import ( "database/sql" "fmt" - "github.com/lbryio/errors.go" + "github.com/lbryio/lbry.go/errors" "github.com/lbryio/sqlboiler/boil" ) diff --git a/randomize/randomize.go b/randomize/randomize.go index 8deb88d..54c88bf 100644 --- a/randomize/randomize.go +++ b/randomize/randomize.go @@ -14,7 +14,7 @@ import ( "sync/atomic" "time" - null "github.com/lbryio/null.go" + null "github.com/lbryio/lbry.go/null" "github.com/pkg/errors" "github.com/satori/go.uuid" diff --git a/randomize/randomize_test.go b/randomize/randomize_test.go index ccef115..bc7a382 100644 --- a/randomize/randomize_test.go +++ b/randomize/randomize_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - null "github.com/lbryio/null.go" + null "github.com/lbryio/lbry.go/null" ) func TestRandomizeStruct(t *testing.T) { From 396f42bc91eec4d95f3dc1c5180a863175824033 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <git@grin.io> Date: Mon, 16 Apr 2018 12:41:55 -0400 Subject: [PATCH 25/35] never update created_at, updated_at columns --- templates/16_update.tpl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/templates/16_update.tpl b/templates/16_update.tpl index eee2036..a4a688c 100644 --- a/templates/16_update.tpl +++ b/templates/16_update.tpl @@ -56,11 +56,9 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string {{if eq .DriverName "mssql"}} wl = strmangle.SetComplement(wl, {{$varNameSingular}}ColumnsWithAuto) {{end}} - {{if not .NoAutoTimestamps}} if len(whitelist) == 0 { - wl = strmangle.SetComplement(wl, []string{"created_at"}) + wl = strmangle.SetComplement(wl, []string{"created_at","updated_at"}) } - {{end -}} if len(wl) == 0 { return errors.Err("{{.PkgName}}: unable to update {{.Table.Name}}, could not build whitelist") } From 8d4055e3eb1c18919978c53522a64d70139c43d1 Mon Sep 17 00:00:00 2001 From: Mark Beamer Jr <markbeamerjr@gmail.com> Date: Wed, 6 Jun 2018 18:26:33 -0400 Subject: [PATCH 26/35] reverted default to native password authentication. --- bdb/drivers/mysql.go | 1 + 1 file changed, 1 insertion(+) diff --git a/bdb/drivers/mysql.go b/bdb/drivers/mysql.go index dec80e0..19855fb 100644 --- a/bdb/drivers/mysql.go +++ b/bdb/drivers/mysql.go @@ -53,6 +53,7 @@ func MySQLBuildQueryString(user, pass, dbname, host string, port int, sslmode st } config.Addr += ":" + strconv.Itoa(port) config.TLSConfig = sslmode + config.AllowNativePasswords = false // MySQL is a bad, and by default reads date/datetime into a []byte // instead of a time.Time. Tell it to stop being a bad. From 466f2d5b2c6a8f8996b1b2136e5807767625ce6f Mon Sep 17 00:00:00 2001 From: Mark Beamer Jr <markbeamerjr@gmail.com> Date: Wed, 6 Jun 2018 19:03:50 -0400 Subject: [PATCH 27/35] make it true --- bdb/drivers/mysql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bdb/drivers/mysql.go b/bdb/drivers/mysql.go index 19855fb..5523a6b 100644 --- a/bdb/drivers/mysql.go +++ b/bdb/drivers/mysql.go @@ -53,7 +53,7 @@ func MySQLBuildQueryString(user, pass, dbname, host string, port int, sslmode st } config.Addr += ":" + strconv.Itoa(port) config.TLSConfig = sslmode - config.AllowNativePasswords = false + config.AllowNativePasswords = true // MySQL is a bad, and by default reads date/datetime into a []byte // instead of a time.Time. Tell it to stop being a bad. From 3baa9e72ca1cc55c8a8fb870190861ae56d9a8a1 Mon Sep 17 00:00:00 2001 From: Mark Beamer Jr <markbeamerjr@gmail.com> Date: Thu, 10 Jan 2019 20:11:42 -0500 Subject: [PATCH 28/35] Updated to use the latest lbry.go changes --- boilingcore/imports.go | 50 ++++++++++++++++++------------------- boilingcore/imports_test.go | 10 ++++---- queries/helpers_test.go | 2 +- queries/query.go | 2 +- randomize/randomize.go | 2 +- randomize/randomize_test.go | 2 +- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/boilingcore/imports.go b/boilingcore/imports.go index 9a5c656..b5979e3 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -170,8 +170,8 @@ func newImporter() importer { `"time"`, }, thirdParty: importList{ - `"github.com/lbryio/lbry.go/errors"`, - `"github.com/lbryio/lbry.go/null"`, + `"github.com/lbryio/lbry.go/extras/errors"`, + `"github.com/lbryio/lbry.go/extras/null"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, @@ -185,7 +185,7 @@ func newImporter() importer { `"fmt"`, }, thirdParty: importList{ - `"github.com/lbryio/lbry.go/errors"`, + `"github.com/lbryio/lbry.go/extras/errors"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, @@ -194,7 +194,7 @@ func newImporter() importer { }, "boil_types": { thirdParty: importList{ - `"github.com/lbryio/lbry.go/errors"`, + `"github.com/lbryio/lbry.go/extras/errors"`, `"github.com/lbryio/sqlboiler/strmangle"`, }, }, @@ -227,7 +227,7 @@ func newImporter() importer { }, thirdParty: importList{ `"github.com/kat-co/vala"`, - `"github.com/lbryio/lbry.go/errors"`, + `"github.com/lbryio/lbry.go/extras/errors"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/spf13/viper"`, }, @@ -265,7 +265,7 @@ func newImporter() importer { `"strings"`, }, thirdParty: importList{ - `"github.com/lbryio/lbry.go/errors"`, + `"github.com/lbryio/lbry.go/extras/errors"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, `_ "github.com/lib/pq"`, @@ -285,7 +285,7 @@ func newImporter() importer { }, thirdParty: importList{ `_ "github.com/go-sql-driver/mysql"`, - `"github.com/lbryio/lbry.go/errors"`, + `"github.com/lbryio/lbry.go/extras/errors"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, `"github.com/spf13/viper"`, @@ -302,7 +302,7 @@ func newImporter() importer { }, thirdParty: importList{ `_ "github.com/denisenkom/go-mssqldb"`, - `"github.com/lbryio/lbry.go/errors"`, + `"github.com/lbryio/lbry.go/extras/errors"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, `"github.com/spf13/viper"`, @@ -315,55 +315,55 @@ func newImporter() importer { // TranslateColumnType to see the type assignments. imp.BasedOnType = mapImports{ "null.Float32": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Float64": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Int": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Int8": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Int16": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Int32": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Int64": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Uint": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Uint8": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Uint16": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Uint32": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Uint64": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.String": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Bool": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Time": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.JSON": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "null.Bytes": { - thirdParty: importList{`"github.com/lbryio/lbry.go/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, }, "time.Time": { standard: importList{`"time"`}, diff --git a/boilingcore/imports_test.go b/boilingcore/imports_test.go index 693bc10..6d22956 100644 --- a/boilingcore/imports_test.go +++ b/boilingcore/imports_test.go @@ -246,7 +246,7 @@ func TestCombineTypeImports(t *testing.T) { }, thirdParty: importList{ `"github.com/lbryio/sqlboiler/boil"`, - `"github.com/lbryio/lbry.go/null"`, + `"github.com/lbryio/lbry.go/extras/null"`, }, } @@ -281,7 +281,7 @@ func TestCombineTypeImports(t *testing.T) { }, thirdParty: importList{ `"github.com/lbryio/sqlboiler/boil"`, - `"github.com/lbryio/lbry.go/null"`, + `"github.com/lbryio/lbry.go/extras/null"`, }, } @@ -297,7 +297,7 @@ func TestCombineImports(t *testing.T) { a := imports{ standard: importList{"fmt"}, - thirdParty: importList{"github.com/lbryio/sqlboiler", "github.com/lbryio/lbry.go/null"}, + thirdParty: importList{"github.com/lbryio/sqlboiler", "github.com/lbryio/lbry.go/extras/null"}, } b := imports{ standard: importList{"os"}, @@ -309,8 +309,8 @@ func TestCombineImports(t *testing.T) { if c.standard[0] != "fmt" && c.standard[1] != "os" { t.Errorf("Wanted: fmt, os got: %#v", c.standard) } - if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "github.com/lbryio/lbry.go/null" { - t.Errorf("Wanted: github.com/lbryio/sqlboiler, github.com/lbryio/lbry.go/null got: %#v", c.thirdParty) + if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "github.com/lbryio/lbry.go/extras/null" { + t.Errorf("Wanted: github.com/lbryio/sqlboiler, github.com/lbryio/lbry.go/extras/null got: %#v", c.thirdParty) } } diff --git a/queries/helpers_test.go b/queries/helpers_test.go index b6b757d..5a1802a 100644 --- a/queries/helpers_test.go +++ b/queries/helpers_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - null "github.com/lbryio/lbry.go/null" + null "github.com/lbryio/lbry.go/extras/null" ) type testObj struct { diff --git a/queries/query.go b/queries/query.go index fdd54b4..14f2d51 100644 --- a/queries/query.go +++ b/queries/query.go @@ -4,7 +4,7 @@ import ( "database/sql" "fmt" - "github.com/lbryio/lbry.go/errors" + "github.com/lbryio/lbry.go/extras/errors" "github.com/lbryio/sqlboiler/boil" ) diff --git a/randomize/randomize.go b/randomize/randomize.go index 54c88bf..65b2a2b 100644 --- a/randomize/randomize.go +++ b/randomize/randomize.go @@ -14,7 +14,7 @@ import ( "sync/atomic" "time" - null "github.com/lbryio/lbry.go/null" + null "github.com/lbryio/lbry.go/extras/null" "github.com/pkg/errors" "github.com/satori/go.uuid" diff --git a/randomize/randomize_test.go b/randomize/randomize_test.go index bc7a382..45ddf16 100644 --- a/randomize/randomize_test.go +++ b/randomize/randomize_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - null "github.com/lbryio/lbry.go/null" + null "github.com/lbryio/lbry.go/extras/null" ) func TestRandomizeStruct(t *testing.T) { From eea3d349a773e4f5bcfb9a194b78674e5b92fdd5 Mon Sep 17 00:00:00 2001 From: Mark Beamer Jr <markbeamerjr@gmail.com> Date: Mon, 3 Sep 2018 00:51:55 -0400 Subject: [PATCH 29/35] added support for 1 to 1 relations and added support for n unique keys for conflict resolution during merging. split out into two functions. --- templates/singleton/boil_queries.tpl | 118 +++++++++++++++++++-------- 1 file changed, 83 insertions(+), 35 deletions(-) diff --git a/templates/singleton/boil_queries.tpl b/templates/singleton/boil_queries.tpl index 51ed108..a881cda 100644 --- a/templates/singleton/boil_queries.tpl +++ b/templates/singleton/boil_queries.tpl @@ -27,11 +27,15 @@ func mergeModels(tx boil.Executor, primaryID uint64, secondaryID uint64, foreign var err error for _, conflict := range conflictingKeys { - err = deleteConflictsBeforeMerge(tx, conflict, primaryID, secondaryID) - if err != nil { - return err - } - } + if len(conflict.columns) == 1 && conflict.columns[0] == conflict.objectIdColumn { + err = deleteOneToOneConflictsBeforeMerge(tx, conflict, primaryID, secondaryID) + } else { + err = deleteOneToManyConflictsBeforeMerge(tx, conflict, primaryID, secondaryID) + } + if err != nil { + return err + } + } for _, fk := range foreignKeys { // TODO: use NewQuery here, not plain sql @@ -48,53 +52,97 @@ func mergeModels(tx boil.Executor, primaryID uint64, secondaryID uint64, foreign return checkMerge(tx, foreignKeys) } -func deleteConflictsBeforeMerge(tx boil.Executor, conflict conflictingUniqueKey, primaryID uint64, secondaryID uint64) error { - conflictingColumns := strmangle.SetComplement(conflict.columns, []string{conflict.objectIdColumn}) - - if len(conflictingColumns) < 1 { - return nil - } else if len(conflictingColumns) > 1 { - return errors.Err("this doesnt work for unique keys with more than two columns (yet)") - } - +func deleteOneToOneConflictsBeforeMerge(tx boil.Executor, conflict conflictingUniqueKey, primaryID uint64, secondaryID uint64) error { query := fmt.Sprintf( - "SELECT %s FROM %s WHERE %s IN (%s) GROUP BY %s HAVING count(distinct %s) > 1", - conflictingColumns[0], conflict.table, conflict.objectIdColumn, + "SELECT COUNT(*) FROM %s WHERE %s IN (%s)", + conflict.table, conflict.objectIdColumn, strmangle.Placeholders(dialect.IndexPlaceholders, 2, 1, 1), - conflictingColumns[0], conflict.objectIdColumn, ) - rows, err := tx.Query(query, primaryID, secondaryID) - defer rows.Close() + var count int + err := tx.QueryRow(query, primaryID, secondaryID).Scan(&count) if err != nil { return errors.Err(err) } - args := []interface{}{secondaryID} - for rows.Next() { - var value string - err = rows.Scan(&value) - if err != nil { - return errors.Err(err) - } - args = append(args, value) - } - - // if no rows found, no need to delete anything - if len(args) < 2 { - return nil + if count > 2 { + return errors.Err("it should not be possible to have more than two rows here") + } else if count != 2 { + return nil // no conflicting rows } query = fmt.Sprintf( - "DELETE FROM %s WHERE %s = %s AND %s IN (%s)", + "DELETE FROM %s WHERE %s = %s", conflict.table, conflict.objectIdColumn, strmangle.Placeholders(dialect.IndexPlaceholders, 1, 1, 1), - conflictingColumns[0], strmangle.Placeholders(dialect.IndexPlaceholders, len(args)-1, 2, 1), ) - _, err = tx.Exec(query, args...) + _, err = tx.Exec(query, secondaryID) + return errors.Err(err) +} + +func deleteOneToManyConflictsBeforeMerge(tx boil.Executor, conflict conflictingUniqueKey, primaryID uint64, secondaryID uint64) error { + conflictingColumns := strmangle.SetComplement(conflict.columns, []string{conflict.objectIdColumn}) + + query := fmt.Sprintf( + "SELECT %s FROM %s WHERE %s IN (%s) GROUP BY %s HAVING count(distinct %s) > 1", + strings.Join(conflictingColumns, ","), conflict.table, conflict.objectIdColumn, + strmangle.Placeholders(dialect.IndexPlaceholders, 2, 1, 1), + strings.Join(conflictingColumns, ","), conflict.objectIdColumn, + ) + + //The selectParams should be the ObjectIDs to search for regarding the conflict. + rows, err := tx.Query(query, primaryID, secondaryID) if err != nil { return errors.Err(err) } + + //Since we don't don't know if advance how many columns the query returns, we have dynamically assign them to be + // used in the delete query. + colNames, err := rows.Columns() + if err != nil { + log.Fatal(err) + } + //Each row result of the query needs to be removed for being a conflicting row. Store each row's keys in an array. + var rowsToRemove = [][]interface{}(nil) + for rows.Next() { + //Set pointers for dynamic scan + iColPtrs := make([]interface{}, len(colNames)) + for i := 0; i < len(colNames); i++ { + s := string("") + iColPtrs[i] = &s + } + //Dynamically scan n columns + err = rows.Scan(iColPtrs...) + if err != nil { + return errors.Err(err) + } + //Grab scanned values for query arguments + iCol := make([]interface{}, len(colNames)) + for i, col := range iColPtrs { + x := col.(*string) + iCol[i] = *x + } + rowsToRemove = append(rowsToRemove, iCol) + } + defer rows.Close() + + //This query will adjust dynamically depending on the number of conflicting keys, adding AND expressions for each + // key to ensure the right conflicting rows are deleted. + query = fmt.Sprintf( + "DELETE FROM %s %s", + conflict.table, + "WHERE "+strings.Join(conflict.columns, " = ? AND ")+" = ?", + ) + + //There could be multiple conflicting rows between ObjectIDs. In the SELECT query we grab each row and their column + // keys to be deleted here in a loop. + for _, rowToDelete := range rowsToRemove { + rowToDelete = append(rowToDelete, secondaryID) + _, err = tx.Exec(query, rowToDelete...) + if err != nil { + return errors.Err(err) + } + } return nil } From 29172e976b0923c864899a362c4aefe974a168d7 Mon Sep 17 00:00:00 2001 From: Mark Beamer Jr <markbeamerjr@gmail.com> Date: Fri, 7 Sep 2018 20:51:50 -0400 Subject: [PATCH 30/35] changed from Fatal to Error - copy paste mistake. --- templates/singleton/boil_queries.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/singleton/boil_queries.tpl b/templates/singleton/boil_queries.tpl index a881cda..3e9ebb8 100644 --- a/templates/singleton/boil_queries.tpl +++ b/templates/singleton/boil_queries.tpl @@ -100,7 +100,7 @@ func deleteOneToManyConflictsBeforeMerge(tx boil.Executor, conflict conflictingU // used in the delete query. colNames, err := rows.Columns() if err != nil { - log.Fatal(err) + return errors.Err(err) } //Each row result of the query needs to be removed for being a conflicting row. Store each row's keys in an array. var rowsToRemove = [][]interface{}(nil) From f892107dad46b36f3487ffe336d53064c8a053d8 Mon Sep 17 00:00:00 2001 From: Mark Beamer Jr <markbeamerjr@gmail.com> Date: Thu, 7 Feb 2019 20:24:07 -0500 Subject: [PATCH 31/35] missing import --- boilingcore/imports.go | 1 + 1 file changed, 1 insertion(+) diff --git a/boilingcore/imports.go b/boilingcore/imports.go index b5979e3..d37c84b 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -183,6 +183,7 @@ func newImporter() importer { "boil_queries": imports{ standard: importList{ `"fmt"`, + `"strings"`, }, thirdParty: importList{ `"github.com/lbryio/lbry.go/extras/errors"`, From 4e1b83ab3942cc6747e04065aef330b0d9dff56d Mon Sep 17 00:00:00 2001 From: Mark Beamer Jr <markbeamerjr@gmail.com> Date: Sat, 29 Jun 2019 11:30:23 -0400 Subject: [PATCH 32/35] Add force index query mod for select query. Fix eager loading casting for nested levels. --- queries/eager_load.go | 14 ++++++++++++-- queries/qm/query_mods.go | 7 +++++++ queries/query.go | 6 ++++++ queries/query_builders.go | 8 +++++++- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/queries/eager_load.go b/queries/eager_load.go index 081aac4..962d722 100644 --- a/queries/eager_load.go +++ b/queries/eager_load.go @@ -206,9 +206,16 @@ func (l loadRelationshipState) loadRelationshipsRecurse(depth int, obj reflect.V } bkind := kindStruct - if reflect.Indirect(loadedObject).Kind() != reflect.Struct { + if derefed := reflect.Indirect(loadedObject); derefed.Kind() != reflect.Struct { bkind = kindPtrSliceStruct - loadedObject = loadedObject.Addr() + + // Convert away any helper slice types + // elemType is *elem (from []*elem or helperSliceType) + // sliceType is *[]*elem + elemType := derefed.Type().Elem() + sliceType := reflect.PtrTo(reflect.SliceOf(elemType)) + + loadedObject = loadedObject.Addr().Convert(sliceType) } return l.loadRelationships(depth+1, loadedObject.Interface(), bkind) } @@ -241,6 +248,9 @@ func collectLoaded(key string, loadingFrom reflect.Value) (reflect.Value, bindKi if loadedType.Elem().Kind() == reflect.Struct { bkind = kindStruct loadedType = reflect.SliceOf(loadedType) + } else { + // Ensure that we get rid of all the helper "XSlice" types + loadedType = reflect.SliceOf(loadedType.Elem()) } collection := reflect.MakeSlice(loadedType, 0, 0) diff --git a/queries/qm/query_mods.go b/queries/qm/query_mods.go index 89d31d4..6fa6e2f 100644 --- a/queries/qm/query_mods.go +++ b/queries/qm/query_mods.go @@ -123,6 +123,13 @@ func From(from string) QueryMod { } } +func ForceIndex( index string) QueryMod { + return func(q *queries.Query) { + queries.SetForceIndex(q, index) + } +} + + // Limit the number of returned rows func Limit(limit int) QueryMod { return func(q *queries.Query) { diff --git a/queries/query.go b/queries/query.go index 14f2d51..5b0ffbc 100644 --- a/queries/query.go +++ b/queries/query.go @@ -30,6 +30,7 @@ type Query struct { selectCols []string count bool from []string + forceindex string joins []join where []where in []in @@ -263,6 +264,11 @@ func SetLastWhereAsOr(q *Query) { q.where[len(q.where)-1].orSeparator = true } +// SetForceIndex sets the index to be used by the query +func SetForceIndex(q *Query, index string){ + q.forceindex = index +} + // SetLastInAsOr sets the or separator for the tail "IN" in the slice func SetLastInAsOr(q *Query) { if len(q.in) == 0 { diff --git a/queries/query_builders.go b/queries/query_builders.go index f884f91..e682877 100644 --- a/queries/query_builders.go +++ b/queries/query_builders.go @@ -76,7 +76,13 @@ func buildSelectQuery(q *Query) (*bytes.Buffer, []interface{}) { buf.WriteByte(')') } - fmt.Fprintf(buf, " FROM %s", strings.Join(strmangle.IdentQuoteSlice(q.dialect.LQ, q.dialect.RQ, q.from), ", ")) + if len(q.forceindex) > 0 { + fmt.Fprintf(buf, " FROM %s FORCE INDEX (%s)", strings.Join(strmangle.IdentQuoteSlice(q.dialect.LQ, q.dialect.RQ, q.from), ", "),q.forceindex) + + }else{ + fmt.Fprintf(buf, " FROM %s", strings.Join(strmangle.IdentQuoteSlice(q.dialect.LQ, q.dialect.RQ, q.from), ", ")) + + } if len(q.joins) > 0 { argsLen := len(args) From c01b1828391ba95ef3366817aad739e264f46441 Mon Sep 17 00:00:00 2001 From: Mark Beamer Jr <markbeamerjr@gmail.com> Date: Mon, 1 Jul 2019 23:46:37 -0400 Subject: [PATCH 33/35] Allow null query mods for dynamic queries --- queries/qm/query_mods.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/queries/qm/query_mods.go b/queries/qm/query_mods.go index 6fa6e2f..42e881e 100644 --- a/queries/qm/query_mods.go +++ b/queries/qm/query_mods.go @@ -8,7 +8,9 @@ type QueryMod func(q *queries.Query) // Apply the query mods to the Query object func Apply(q *queries.Query, mods ...QueryMod) { for _, mod := range mods { - mod(q) + if mod != nil { + mod(q) + } } } @@ -123,13 +125,12 @@ func From(from string) QueryMod { } } -func ForceIndex( index string) QueryMod { +func ForceIndex(index string) QueryMod { return func(q *queries.Query) { queries.SetForceIndex(q, index) } } - // Limit the number of returned rows func Limit(limit int) QueryMod { return func(q *queries.Query) { From 256a6d4225b70fd17caba555c5b8f035e33db8c9 Mon Sep 17 00:00:00 2001 From: Niko Storni <niko@lbry.io> Date: Mon, 10 Feb 2020 14:49:11 +0100 Subject: [PATCH 34/35] update lbry.go library --- boilingcore/imports.go | 50 ++++++++++++++++++------------------- boilingcore/imports_test.go | 10 ++++---- queries/helpers_test.go | 2 +- queries/query.go | 2 +- randomize/randomize.go | 2 +- randomize/randomize_test.go | 2 +- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/boilingcore/imports.go b/boilingcore/imports.go index d37c84b..e20480b 100644 --- a/boilingcore/imports.go +++ b/boilingcore/imports.go @@ -170,8 +170,8 @@ func newImporter() importer { `"time"`, }, thirdParty: importList{ - `"github.com/lbryio/lbry.go/extras/errors"`, - `"github.com/lbryio/lbry.go/extras/null"`, + `"github.com/lbryio/lbry.go/v2/extras/errors"`, + `"github.com/lbryio/lbry.go/v2/extras/null"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, @@ -186,7 +186,7 @@ func newImporter() importer { `"strings"`, }, thirdParty: importList{ - `"github.com/lbryio/lbry.go/extras/errors"`, + `"github.com/lbryio/lbry.go/v2/extras/errors"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/queries/qm"`, @@ -195,7 +195,7 @@ func newImporter() importer { }, "boil_types": { thirdParty: importList{ - `"github.com/lbryio/lbry.go/extras/errors"`, + `"github.com/lbryio/lbry.go/v2/extras/errors"`, `"github.com/lbryio/sqlboiler/strmangle"`, }, }, @@ -228,7 +228,7 @@ func newImporter() importer { }, thirdParty: importList{ `"github.com/kat-co/vala"`, - `"github.com/lbryio/lbry.go/extras/errors"`, + `"github.com/lbryio/lbry.go/v2/extras/errors"`, `"github.com/lbryio/sqlboiler/boil"`, `"github.com/spf13/viper"`, }, @@ -266,7 +266,7 @@ func newImporter() importer { `"strings"`, }, thirdParty: importList{ - `"github.com/lbryio/lbry.go/extras/errors"`, + `"github.com/lbryio/lbry.go/v2/extras/errors"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, `_ "github.com/lib/pq"`, @@ -286,7 +286,7 @@ func newImporter() importer { }, thirdParty: importList{ `_ "github.com/go-sql-driver/mysql"`, - `"github.com/lbryio/lbry.go/extras/errors"`, + `"github.com/lbryio/lbry.go/v2/extras/errors"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, `"github.com/spf13/viper"`, @@ -303,7 +303,7 @@ func newImporter() importer { }, thirdParty: importList{ `_ "github.com/denisenkom/go-mssqldb"`, - `"github.com/lbryio/lbry.go/extras/errors"`, + `"github.com/lbryio/lbry.go/v2/extras/errors"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`, `"github.com/spf13/viper"`, @@ -316,55 +316,55 @@ func newImporter() importer { // TranslateColumnType to see the type assignments. imp.BasedOnType = mapImports{ "null.Float32": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Float64": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Int": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Int8": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Int16": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Int32": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Int64": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Uint": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Uint8": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Uint16": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Uint32": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Uint64": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.String": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Bool": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Time": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.JSON": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "null.Bytes": { - thirdParty: importList{`"github.com/lbryio/lbry.go/extras/null"`}, + thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`}, }, "time.Time": { standard: importList{`"time"`}, diff --git a/boilingcore/imports_test.go b/boilingcore/imports_test.go index 6d22956..d0043c0 100644 --- a/boilingcore/imports_test.go +++ b/boilingcore/imports_test.go @@ -246,7 +246,7 @@ func TestCombineTypeImports(t *testing.T) { }, thirdParty: importList{ `"github.com/lbryio/sqlboiler/boil"`, - `"github.com/lbryio/lbry.go/extras/null"`, + `"github.com/lbryio/lbry.go/v2/extras/null"`, }, } @@ -281,7 +281,7 @@ func TestCombineTypeImports(t *testing.T) { }, thirdParty: importList{ `"github.com/lbryio/sqlboiler/boil"`, - `"github.com/lbryio/lbry.go/extras/null"`, + `"github.com/lbryio/lbry.go/v2/extras/null"`, }, } @@ -297,7 +297,7 @@ func TestCombineImports(t *testing.T) { a := imports{ standard: importList{"fmt"}, - thirdParty: importList{"github.com/lbryio/sqlboiler", "github.com/lbryio/lbry.go/extras/null"}, + thirdParty: importList{"github.com/lbryio/sqlboiler", "github.com/lbryio/lbry.go/v2/extras/null"}, } b := imports{ standard: importList{"os"}, @@ -309,8 +309,8 @@ func TestCombineImports(t *testing.T) { if c.standard[0] != "fmt" && c.standard[1] != "os" { t.Errorf("Wanted: fmt, os got: %#v", c.standard) } - if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "github.com/lbryio/lbry.go/extras/null" { - t.Errorf("Wanted: github.com/lbryio/sqlboiler, github.com/lbryio/lbry.go/extras/null got: %#v", c.thirdParty) + if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "github.com/lbryio/lbry.go/v2/extras/null" { + t.Errorf("Wanted: github.com/lbryio/sqlboiler, github.com/lbryio/lbry.go/v2/extras/null got: %#v", c.thirdParty) } } diff --git a/queries/helpers_test.go b/queries/helpers_test.go index 5a1802a..fd093e3 100644 --- a/queries/helpers_test.go +++ b/queries/helpers_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - null "github.com/lbryio/lbry.go/extras/null" + null "github.com/lbryio/lbry.go/v2/extras/null" ) type testObj struct { diff --git a/queries/query.go b/queries/query.go index 5b0ffbc..e3a6470 100644 --- a/queries/query.go +++ b/queries/query.go @@ -4,7 +4,7 @@ import ( "database/sql" "fmt" - "github.com/lbryio/lbry.go/extras/errors" + "github.com/lbryio/lbry.go/v2/extras/errors" "github.com/lbryio/sqlboiler/boil" ) diff --git a/randomize/randomize.go b/randomize/randomize.go index 65b2a2b..30592bf 100644 --- a/randomize/randomize.go +++ b/randomize/randomize.go @@ -14,7 +14,7 @@ import ( "sync/atomic" "time" - null "github.com/lbryio/lbry.go/extras/null" + null "github.com/lbryio/lbry.go/v2/extras/null" "github.com/pkg/errors" "github.com/satori/go.uuid" diff --git a/randomize/randomize_test.go b/randomize/randomize_test.go index 45ddf16..71afb55 100644 --- a/randomize/randomize_test.go +++ b/randomize/randomize_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - null "github.com/lbryio/lbry.go/extras/null" + null "github.com/lbryio/lbry.go/v2/extras/null" ) func TestRandomizeStruct(t *testing.T) { From 3db4f30f564e65e40f5467f76692501c21489a46 Mon Sep 17 00:00:00 2001 From: Mark Beamer Jr <markbeamerjr@gmail.com> Date: Wed, 19 Aug 2020 23:43:39 -0400 Subject: [PATCH 35/35] Fix multi-depth eager loading of relationships. If a relationship is nil, do not add it to the collection for checking the next depth level. --- queries/eager_load.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/queries/eager_load.go b/queries/eager_load.go index 962d722..8992290 100644 --- a/queries/eager_load.go +++ b/queries/eager_load.go @@ -5,9 +5,9 @@ import ( "reflect" "strings" - "github.com/pkg/errors" "github.com/lbryio/sqlboiler/boil" "github.com/lbryio/sqlboiler/strmangle" + "github.com/pkg/errors" ) type loadRelationshipState struct { @@ -259,9 +259,13 @@ func collectLoaded(key string, loadingFrom reflect.Value) (reflect.Value, bindKi for { switch bkind { case kindStruct: - collection = reflect.Append(collection, loadedObject) + if !loadedObject.IsNil() { + collection = reflect.Append(collection, loadedObject) + } case kindPtrSliceStruct: - collection = reflect.AppendSlice(collection, loadedObject) + if !loadedObject.IsNil() { + collection = reflect.AppendSlice(collection, loadedObject) + } } i++