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++