Compare commits

..

43 commits

Author SHA1 Message Date
Mark
6b4e052bed
Merge pull request #10 from lbryio/eagerloading_depth
Fix multi-depth eager loading of relationships. If a relationship is …
2020-09-02 15:59:52 -04:00
Mark Beamer Jr
3db4f30f56
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. 2020-08-19 23:43:39 -04:00
Niko Storni
256a6d4225 update lbry.go library 2020-03-05 16:29:03 -05:00
Mark
3f035a9fe2
Merge pull request #7 from lbryio/guard_null_mod
Allow null query mods for dynamic queries
2019-07-01 23:56:28 -04:00
Mark Beamer Jr
c01b182839
Allow null query mods for dynamic queries 2019-07-01 23:54:54 -04:00
Mark
e3fe976c3c
Merge pull request #6 from lbryio/force_index
Force index
2019-06-30 23:17:36 -04:00
Mark Beamer Jr
4e1b83ab39
Add force index query mod for select query.
Fix eager loading casting for nested levels.
2019-06-30 23:01:24 -04:00
Mark Beamer Jr
f892107dad
missing import 2019-02-07 20:24:07 -05:00
Mark
fadcbfa8b6
Merge pull request #3 from lbryio/merge_changes
added support for 1 to 1 relations and added support for n unique key…
2019-02-07 19:51:35 -05:00
Mark Beamer Jr
29172e976b
changed from Fatal to Error - copy paste mistake. 2019-02-07 18:20:23 -05:00
Mark Beamer Jr
eea3d349a7
added support for 1 to 1 relations and added support for n unique keys for conflict resolution during merging.
split out into two functions.
2019-02-07 18:20:22 -05:00
Mark
d180a095ca
Merge pull request #4 from lbryio/lbrygo_update
Updated to use the latest lbry.go changes
2019-01-10 20:13:22 -05:00
Mark Beamer Jr
3baa9e72ca
Updated to use the latest lbry.go changes 2019-01-10 20:11:42 -05:00
Mark
bc08aa6160
Merge pull request #2 from lbryio/test_authchanges
make it true
2018-06-06 19:05:29 -04:00
Mark Beamer Jr
466f2d5b2c make it true 2018-06-06 19:03:50 -04:00
Mark
45ee5c902f
Merge pull request #1 from lbryio/test_authchanges
reverted default to native password authentication.
2018-06-06 18:57:40 -04:00
Mark Beamer Jr
8d4055e3eb reverted default to native password authentication. 2018-06-06 18:26:33 -04:00
Alex Grintsvayg
396f42bc91 never update created_at, updated_at columns 2018-04-16 12:41:55 -04:00
Alex Grintsvayg
77fc991e7b new location for null.go 2018-02-22 13:41:05 -05:00
Alex Grintsvayg
e4a52e21b6 switch to our errors package 2018-02-07 09:35:46 -05:00
Alex Grintsvayg
0b0a1f21c2 allow generic interface or real sql tx 2017-09-02 11:52:31 -04:00
Alex Grintsvayg
cd445bf2f4 revert interpolateParams, since we're doing our own logging now 2017-09-02 11:31:15 -04:00
Alex Grintsvayg
55f42bc038 just use interfaces 2017-08-24 11:58:13 -04:00
Alex Grintsvayg
544ff7afdd typo 2017-08-23 17:03:24 -04:00
Alex Grintsvayg
faec346481 use interface to enable custom Tx types 2017-08-23 16:59:29 -04:00
Alex Grintsvayg
3abac13aeb export InterpolateParams 2017-08-23 16:37:33 -04:00
Alex Grintsvayg
8837a986ee consistent order to unique key columns 2017-08-23 13:36:13 -04:00
Aaron L
ce9d13abf0 Fix hook documentation to include error return
Fix #171
2017-08-01 14:40:58 -04:00
Aaron L
ca9f47de8b 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
2017-08-01 14:40:38 -04:00
Aaron L
e339812027 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 = ?"
2017-08-01 14:39:10 -04:00
Guy Tish
23f245776d Added table columns and table names as anonymous struct 2017-08-01 14:27:50 -04:00
Alex Grintsvayg
99a3a1d091 make merge compatible with an existing transaction 2017-08-01 13:00:14 -04:00
Alex Grintsvayg
9c8262b702 fix exists() finisher 2017-07-20 10:50:55 -04:00
Alex Grintsvayg
05c7f7d06a switch to more complete null package, implement nicer sql logging 2017-07-06 15:15:00 -04:00
Alex Grintsvayg
ed423a3606 detect autoincrement column, fix lastID in upsert when update doesnt change anything 2017-06-12 14:02:04 -04:00
Alex Grintsvayg
09c585cdb1 dont run delete query when there's nothing to delete 2017-06-01 09:58:50 -04:00
Alex Grintsvayg
912a689701 added unique key detection (mysql only for now), improved merging 2017-05-12 06:56:48 -04:00
Alex Grintsvayg
31fe8b6e1d model merging 2017-05-10 15:35:05 -04:00
Alex Grintsvayg
b160e5c1f4 dont error if no rows found 2017-05-10 11:21:29 -04:00
Alex Grintsvayg
ed43c9078f made query structs public, added IS NULL to filter 2017-05-09 15:30:04 -04:00
Alex Grintsvayg
f863ecb48e add model Filters, FindOrCreate methods, IsNew() 2017-05-08 16:39:16 -04:00
Alex Grintsvayg
451723ccb9 fix imports to point at lbryio repo 2017-05-08 13:25:15 -04:00
Alex Grintsvayg
687b0506db Merge branch 'mysql-uint-fix'
* mysql-uint-fix:
  detect unsigned int columns in mysql
2017-05-08 13:12:48 -04:00
66 changed files with 1018 additions and 500 deletions

View file

@ -13,14 +13,14 @@ jobs:
environment: environment:
MYSQL_ROOT_PASSWORD: mysqlpassword MYSQL_ROOT_PASSWORD: mysqlpassword
# - image: microsoft/mssql-server-linux:ctp2-0 - image: microsoft/mssql-server-linux:ctp1-4
# environment: environment:
# ACCEPT_EULA: 'Y' ACCEPT_EULA: 'Y'
# SA_PASSWORD: 'R@@tr@@t1234' SA_PASSWORD: 'R@@tr@@t1234'
environment: environment:
GOPATH: /go GOPATH: /go
ROOTPATH: /go/src/github.com/volatiletech/sqlboiler ROOTPATH: /go/src/github.com/vattle/sqlboiler
steps: steps:
- run: - run:
@ -72,31 +72,31 @@ jobs:
sleep 1 sleep 1
done done
# - run: - run:
# name: Wait for MSSQL name: Wait for MSSQL
# command: > command: >
# for i in `seq 30`; do for i in `seq 30`; do
# echo "Waiting for mssql" echo "Waiting for mssql"
# set +o errexit set +o errexit
# sqlcmd -H localhost -U sa -P R@@tr@@t1234 -Q "select * from information_schema.tables;" > /dev/null sqlcmd -H localhost -U sa -P R@@tr@@t1234 -Q "select * from information_schema.tables;" > /dev/null
# status=$? status=$?
# set -o errexit set -o errexit
# if [ $status -eq 0 ]; then if [ $status -eq 0 ]; then
# break break
# fi fi
# if [ $i -eq 30 ]; then if [ $i -eq 30 ]; then
# echo "Failed to wait for mssql" echo "Failed to wait for mssql"
# exit 1 exit 1
# fi fi
# sleep 1 sleep 1
# done done
- run: - run:
name: Make GOPATH name: Make GOPATH
command: mkdir -p /go/src/github.com/volatiletech/sqlboiler command: mkdir -p /go/src/github.com/vattle/sqlboiler
- checkout: - checkout:
path: /go/src/github.com/volatiletech/sqlboiler path: /go/src/github.com/vattle/sqlboiler
- run: - run:
name: Create PSQL DB name: Create PSQL DB
@ -108,17 +108,17 @@ jobs:
command: | command: |
mysql --host localhost --execute 'create database sqlboiler;' mysql --host localhost --execute 'create database sqlboiler;'
mysql --host localhost --database sqlboiler < $ROOTPATH/testdata/mysql_test_schema.sql mysql --host localhost --database sqlboiler < $ROOTPATH/testdata/mysql_test_schema.sql
# - run: - run:
# name: Create MSSQL DB name: Create MSSQL DB
# command: | command: |
# sqlcmd -S localhost -U sa -P R@@tr@@t1234 -Q "create database sqlboiler;" sqlcmd -S localhost -U sa -P R@@tr@@t1234 -Q "create database sqlboiler;"
# sqlcmd -S localhost -U sa -P R@@tr@@t1234 -d sqlboiler -i $ROOTPATH/testdata/mssql_test_schema.sql sqlcmd -S localhost -U sa -P R@@tr@@t1234 -d sqlboiler -i $ROOTPATH/testdata/mssql_test_schema.sql
- run: - run:
name: Build SQLBoiler name: Build SQLBoiler
command: | command: |
cd $ROOTPATH; go get -v -t cd $ROOTPATH; go get -v -t
cd $ROOTPATH; go build -v github.com/volatiletech/sqlboiler cd $ROOTPATH; go build -v github.com/vattle/sqlboiler
- run: - run:
name: 'Configure SQLBoiler: PSQL' name: 'Configure SQLBoiler: PSQL'
@ -126,9 +126,9 @@ jobs:
- run: - run:
name: 'Configure SQLBoiler: MySQL' name: 'Configure SQLBoiler: MySQL'
command: echo -e '[mysql]\nhost="localhost"\nport=3306\nuser="root"\npass="mysqlpassword"\ndbname="sqlboiler"\nsslmode="false"\n' >> $ROOTPATH/sqlboiler.toml command: echo -e '[mysql]\nhost="localhost"\nport=3306\nuser="root"\npass="mysqlpassword"\ndbname="sqlboiler"\nsslmode="false"\n' >> $ROOTPATH/sqlboiler.toml
# - run: - run:
# name: 'Configure SQLBoiler: MSSQL' name: 'Configure SQLBoiler: MSSQL'
# command: echo -e '[mssql]\nhost="localhost"\nport=1433\nuser="sa"\npass="R@@tr@@t1234"\ndbname="sqlboiler"\nsslmode="disable"\n' >> $ROOTPATH/sqlboiler.toml command: echo -e '[mssql]\nhost="localhost"\nport=1433\nuser="sa"\npass="R@@tr@@t1234"\ndbname="sqlboiler"\nsslmode="disable"\n' >> $ROOTPATH/sqlboiler.toml
- run: - run:
name: 'Generate: PSQL' name: 'Generate: PSQL'
@ -136,9 +136,9 @@ jobs:
- run: - run:
name: 'Generate: MySQL' name: 'Generate: MySQL'
command: cd $ROOTPATH; ./sqlboiler -o mysql mysql command: cd $ROOTPATH; ./sqlboiler -o mysql mysql
# - run: - run:
# name: 'Generate: MSSQL' name: 'Generate: MSSQL'
# command: cd $ROOTPATH; ./sqlboiler -o mssql mssql command: cd $ROOTPATH; ./sqlboiler -o mssql mssql
- run: - run:
name: Download generated and test deps name: Download generated and test deps
@ -150,7 +150,7 @@ jobs:
name: Run Tests name: Run Tests
command: | command: |
cd $ROOTPATH cd $ROOTPATH
#cp ./testdata/mssql_test_schema.sql mssql/tables_schema.sql cp ./testdata/mssql_test_schema.sql mssql/tables_schema.sql
go test -v -race ./... | tee test_out.txt go test -v -race ./... | tee test_out.txt
- run: - run:
@ -161,3 +161,48 @@ jobs:
- store_test_results: - store_test_results:
path: test_results path: test_results
#test:
# pre:
# - echo -e "[postgres]\nhost=\"localhost\"\nport=5432\nuser=\"ubuntu\"\ndbname=\"sqlboiler\"\n" > sqlboiler.toml
# - createdb -U ubuntu sqlboiler
# - psql -U ubuntu sqlboiler < ./testdata/postgres_test_schema.sql
#
# - echo -e "[mysql]\nhost=\"localhost\"\nport=3306\nuser=\"ubuntu\"\ndbname=\"sqlboiler\"\nsslmode=\"false\"\n" >> sqlboiler.toml
# - echo "create database sqlboiler;" | mysql -u ubuntu
# - mysql -u ubuntu sqlboiler < ./testdata/mysql_test_schema.sql
#
# - echo -e "[mssql]\nhost=\"localhost\"\nport=1433\nuser=\"sa\"\ndbname=\"sqlboiler\"\nsslmode=\"disable\"\n" >> sqlboiler.toml
# - docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=R@@tr@@t1234' -p 1433:1433 -d --name mssql microsoft/mssql-server-linux
# - sqlcmd -S localhost -U sa -P R@@tr@@t1234 -Q "create database sqlboiler;"
# - sqlcmd -S localhost -U sa -P R@@tr@@t1234 -d sqlboiler -i ./testdata/mssql_test_schema.sql
#
# - ./sqlboiler -o postgres postgres
# - ./sqlboiler -o mysql mysql
# - ./sqlboiler -o mssql mssql
# - cp ./testdata/mssql_test_schema.sql mssql/tables_schema.sql
# override:
# - go test -v -race ./... > $CIRCLE_ARTIFACTS/gotest.txt
# post:
# - cat $CIRCLE_ARTIFACTS/gotest.txt | go-junit-report > $CIRCLE_TEST_REPORTS/junit.xml
#
#machine:
# environment:
# GODIST: go1.7.linux-amd64.tar.gz
# PATH: /home/ubuntu/.go_workspace/bin:/usr/local/go/bin:/home/ubuntu/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/mssql-tools/bin
# post:
# - mkdir -p download
# - test -e download/$GODIST || curl -o download/$GODIST https://storage.googleapis.com/golang/$GODIST
# - sudo rm -rf /usr/local/go
# - sudo tar -C /usr/local -xzf download/$GODIST
#
#dependencies:
# pre:
# - mkdir -p /home/ubuntu/.go_workspace/src/github.com/jstemmer
# - go get -u github.com/jstemmer/go-junit-report
#
# - curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
# - curl https://packages.microsoft.com/config/ubuntu/14.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list
# - sudo apt-get update; sudo apt-get install mssql-tools unixodbc-dev
# - docker pull microsoft/mssql-server-linux
# cache_directories:
# - ~/download

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ sqlboiler.toml
models/ models/
testschema.sql testschema.sql
.cover .cover
/.idea

20
LICENSE
View file

@ -1,18 +1,18 @@
Copyright (c) 2017 Volatile Technologies Inc. All rights reserved. Copyright (c) 2016 The SQLBoiler Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are
met: met:
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the in the documentation and/or other materials provided with the
distribution. distribution.
* Neither the name of Vattle or Volatile Technologies Inc. nor the * Neither the name of Vattle nor the names of its
names of its contributors may be used to endorse or promote products contributors may be used to endorse or promote products derived from
derived from this software without specific prior written permission. this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

View file

@ -1,12 +1,12 @@
![sqlboiler logo](http://i.imgur.com/ilkv0r9.png) ![sqlboiler logo](http://i.imgur.com/NJtCT7y.png)
[![License](https://img.shields.io/badge/license-BSD-blue.svg)](https://github.com/volatiletech/sqlboiler/blob/master/LICENSE) [![License](https://img.shields.io/badge/license-BSD-blue.svg)](https://github.com/vattle/sqlboiler/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/volatiletech/sqlboiler?status.svg)](https://godoc.org/github.com/volatiletech/sqlboiler) [![GoDoc](https://godoc.org/github.com/vattle/sqlboiler?status.svg)](https://godoc.org/github.com/vattle/sqlboiler)
[![Mail](https://img.shields.io/badge/mail%20list-sqlboiler-lightgrey.svg)](https://groups.google.com/a/volatile.tech/forum/#!forum/sqlboiler) [![Mail](https://img.shields.io/badge/mail%20list-sqlboiler-lightgrey.svg)](https://groups.google.com/a/volatile.tech/forum/#!forum/sqlboiler)
[![Mail-Annc](https://img.shields.io/badge/mail%20list-sqlboiler--announce-lightgrey.svg)](https://groups.google.com/a/volatile.tech/forum/#!forum/sqlboiler-announce) [![Mail-Annc](https://img.shields.io/badge/mail%20list-sqlboiler--announce-lightgrey.svg)](https://groups.google.com/a/volatile.tech/forum/#!forum/sqlboiler-announce)
[![Slack](https://img.shields.io/badge/slack-%23general-lightgrey.svg)](https://sqlboiler.from-the.cloud) [![Slack](https://img.shields.io/badge/slack-%23general-lightgrey.svg)](https://sqlboiler.from-the.cloud)
[![CircleCI](https://circleci.com/gh/volatiletech/sqlboiler.svg?style=shield)](https://circleci.com/gh/volatiletech/sqlboiler) [![CircleCI](https://circleci.com/gh/vattle/sqlboiler.svg?style=shield)](https://circleci.com/gh/vattle/sqlboiler)
[![Go Report Card](https://goreportcard.com/badge/volatiletech/sqlboiler)](http://goreportcard.com/report/volatiletech/sqlboiler) [![Go Report Card](https://goreportcard.com/badge/vattle/sqlboiler)](http://goreportcard.com/report/vattle/sqlboiler)
SQLBoiler is a tool to generate a Go ORM tailored to your database schema. SQLBoiler is a tool to generate a Go ORM tailored to your database schema.
@ -76,7 +76,6 @@ Table of Contents
* [Reload](#reload) * [Reload](#reload)
* [Exists](#exists) * [Exists](#exists)
* [Enums](#enums) * [Enums](#enums)
* [Constants](#constants)
* [FAQ](#faq) * [FAQ](#faq)
* [Won't compiling models for a huge database be very slow?](#wont-compiling-models-for-a-huge-database-be-very-slow) * [Won't compiling models for a huge database be very slow?](#wont-compiling-models-for-a-huge-database-be-very-slow)
* [Missing imports for generated package](#missing-imports-for-generated-package) * [Missing imports for generated package](#missing-imports-for-generated-package)
@ -123,7 +122,7 @@ For a comprehensive list of available operations and examples please see [Featur
```go ```go
import ( import (
// Import this so we don't have to use qm.Limit etc. // Import this so we don't have to use qm.Limit etc.
. "github.com/volatiletech/sqlboiler/queries/qm" . "github.com/vattle/sqlboiler/queries/qm"
) )
// Open handle to database like normal // Open handle to database like normal
@ -215,12 +214,12 @@ fmt.Println(len(users.R.FavoriteMovies))
#### Download #### Download
```shell ```shell
go get -u -t github.com/volatiletech/sqlboiler go get -u -t github.com/vattle/sqlboiler
``` ```
#### Configuration #### Configuration
Create a configuration file. Because the project uses [viper](https://github.com/spf13/viper), TOML, JSON and YAML Create a configuration file. Because the project uses [viper](github.com/spf13/viper), TOML, JSON and YAML
are all supported. Environment variables are also able to be used. are all supported. Environment variables are also able to be used.
We will assume TOML for the rest of the documentation. We will assume TOML for the rest of the documentation.
@ -296,7 +295,7 @@ generate models for, we can invoke the sqlboiler command line utility.
```text ```text
SQL Boiler generates a Go ORM from template files, tailored to your database schema. SQL Boiler generates a Go ORM from template files, tailored to your database schema.
Complete documentation is available at http://github.com/volatiletech/sqlboiler Complete documentation is available at http://github.com/vattle/sqlboiler
Usage: Usage:
sqlboiler [flags] <driver> sqlboiler [flags] <driver>
@ -626,7 +625,7 @@ when performing query building. Here is a list of all of your generated query mo
```go ```go
// Dot import so we can access query mods directly instead of prefixing with "qm." // Dot import so we can access query mods directly instead of prefixing with "qm."
import . "github.com/volatiletech/sqlboiler/queries/qm" import . "github.com/vattle/sqlboiler/queries/qm"
// Use a raw query against a generated struct (Pilot in this example) // Use a raw query against a generated struct (Pilot in this example)
// If this query mod exists in your call, it will override the others. // If this query mod exists in your call, it will override the others.
@ -737,7 +736,7 @@ in combination with your own custom, non-generated model.
### Binding ### Binding
For a comprehensive ruleset for `Bind()` you can refer to our [godoc](https://godoc.org/github.com/volatiletech/sqlboiler/queries#Bind). For a comprehensive ruleset for `Bind()` you can refer to our [godoc](https://godoc.org/github.com/vattle/sqlboiler/queries#Bind).
The `Bind()` [Finisher](#finisher) allows the results of a query built with The `Bind()` [Finisher](#finisher) allows the results of a query built with
the [Raw SQL](#raw-query) method or the [Query Builder](#query-building) methods to be bound the [Raw SQL](#raw-query) method or the [Query Builder](#query-building) methods to be bound
@ -991,7 +990,7 @@ tx.Rollback()
``` ```
It's also worth noting that there's a way to take advantage of `boil.SetDB()` It's also worth noting that there's a way to take advantage of `boil.SetDB()`
by using the [boil.Begin()](https://godoc.org/github.com/volatiletech/sqlboiler/boil#Begin) function. by using the [boil.Begin()](https://godoc.org/github.com/vattle/sqlboiler/boil#Begin) function.
This opens a transaction using the globally stored database. This opens a transaction using the globally stored database.
### Debug Logging ### Debug Logging
@ -1027,10 +1026,10 @@ Find is used to find a single row by primary key:
```go ```go
// Retrieve pilot with all columns filled // Retrieve pilot with all columns filled
pilot, err := models.FindPilot(db, 1) pilot, err := models.PilotFind(db, 1)
// Retrieve a subset of column values // Retrieve a subset of column values
jet, err := models.FindJet(db, 1, "name", "color") jet, err := models.JetFind(db, 1, "name", "color")
``` ```
### Insert ### Insert
@ -1193,7 +1192,7 @@ exists, err := models.Pilots(db, Where("id=?", 5)).Exists()
If your MySQL or Postgres tables use enums we will generate constants that hold their values If your MySQL or Postgres tables use enums we will generate constants that hold their values
that you can use in your queries. For example: that you can use in your queries. For example:
```sql ```
CREATE TYPE workday AS ENUM('monday', 'tuesday', 'wednesday', 'thursday', 'friday'); CREATE TYPE workday AS ENUM('monday', 'tuesday', 'wednesday', 'thursday', 'friday');
CREATE TABLE event_one ( CREATE TABLE event_one (
@ -1225,41 +1224,6 @@ still be able to use your generated library, and it will still work as expected,
to get the tests to pass in this event is to either use a parsable enum value or use a regular column to get the tests to pass in this event is to either use a parsable enum value or use a regular column
instead of an enum. instead of an enum.
### Constants
The models package will also contain some structs that contain all of the table and column
names harvested from the database at generation time.
For table names they're generated under `models.TableNames`:
```go
// Generated code from models package
var TableNames = struct {
Messages string
Purchases string
}{
Messages: "messages",
Purchases: "purchases",
}
// Usage example:
fmt.Println(models.TableNames.Messages)
```
```go
// Generated code from models package
var MessageColumns = struct {
ID string
PurchaseID string
}{
ID: "id",
PurchaseID: "purchase_id",
}
// Usage example:
fmt.Println(models.MessageColumns.ID)
```
## FAQ ## FAQ
#### Won't compiling models for a huge database be very slow? #### Won't compiling models for a huge database be very slow?
@ -1298,12 +1262,12 @@ You *must* use a DSN flag in MySQL connections, see: [Requirements](#requirement
#### Where is the homepage? #### Where is the homepage?
The homepage for the [SQLBoiler](https://github.com/volatiletech/sqlboiler) [Golang ORM](https://github.com/volatiletech/sqlboiler) The homepage for the [SQLBoiler](https://github.com/vattle/sqlboiler) [Golang ORM](https://github.com/vattle/sqlboiler)
generator is located at: https://github.com/volatiletech/sqlboiler generator is located at: https://github.com/vattle/sqlboiler
## Benchmarks ## Benchmarks
If you'd like to run the benchmarks yourself check out our [boilbench](https://github.com/volatiletech/boilbench) repo. If you'd like to run the benchmarks yourself check out our [boilbench](https://github.com/vattle/boilbench) repo.
```bash ```bash
go test -bench . -benchmem go test -bench . -benchmem

View file

@ -3,7 +3,7 @@ package bdb
import ( import (
"strings" "strings"
"github.com/volatiletech/sqlboiler/strmangle" "github.com/lbryio/sqlboiler/strmangle"
) )
// Column holds information about a database column. // Column holds information about a database column.

View file

@ -1,8 +1,8 @@
package drivers package drivers
import ( import (
"github.com/volatiletech/sqlboiler/bdb" "github.com/lbryio/sqlboiler/bdb"
"github.com/volatiletech/sqlboiler/strmangle" "github.com/lbryio/sqlboiler/strmangle"
) )
// MockDriver is a mock implementation of the bdb driver Interface // MockDriver is a mock implementation of the bdb driver Interface
@ -58,6 +58,14 @@ func (m *MockDriver) Columns(schema, tableName string) ([]bdb.Column, error) {
}[tableName], nil }[tableName], nil
} }
func (m *MockDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, error) {
return []bdb.UniqueKey{}, nil
}
func (m *MockDriver) AutoincrementInfo(schema, tableName string) (string, error) {
return "", nil
}
// ForeignKeyInfo returns a list of mock foreignkeys // ForeignKeyInfo returns a list of mock foreignkeys
func (m *MockDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { func (m *MockDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) {
return map[string][]bdb.ForeignKey{ return map[string][]bdb.ForeignKey{

View file

@ -7,8 +7,8 @@ import (
"strings" "strings"
_ "github.com/denisenkom/go-mssqldb" _ "github.com/denisenkom/go-mssqldb"
"github.com/lbryio/sqlboiler/bdb"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/volatiletech/sqlboiler/bdb"
) )
// MSSQLDriver holds the database connection string and a handle // MSSQLDriver holds the database connection string and a handle
@ -241,6 +241,14 @@ func (m *MSSQLDriver) PrimaryKeyInfo(schema, tableName string) (*bdb.PrimaryKey,
return pkey, nil return pkey, nil
} }
func (m *MSSQLDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, error) {
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. // ForeignKeyInfo retrieves the foreign keys for a given table name.
func (m *MSSQLDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { func (m *MSSQLDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) {
var fkeys []bdb.ForeignKey var fkeys []bdb.ForeignKey

View file

@ -3,12 +3,13 @@ package drivers
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"sort"
"strconv" "strconv"
"strings" "strings"
"github.com/go-sql-driver/mysql" "github.com/go-sql-driver/mysql"
"github.com/lbryio/sqlboiler/bdb"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/volatiletech/sqlboiler/bdb"
) )
// TinyintAsBool is a global that is set from main.go if a user specifies // TinyintAsBool is a global that is set from main.go if a user specifies
@ -52,6 +53,7 @@ func MySQLBuildQueryString(user, pass, dbname, host string, port int, sslmode st
} }
config.Addr += ":" + strconv.Itoa(port) config.Addr += ":" + strconv.Itoa(port)
config.TLSConfig = sslmode config.TLSConfig = sslmode
config.AllowNativePasswords = true
// MySQL is a bad, and by default reads date/datetime into a []byte // 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. // instead of a time.Time. Tell it to stop being a bad.
@ -232,6 +234,79 @@ func (m *MySQLDriver) PrimaryKeyInfo(schema, tableName string) (*bdb.PrimaryKey,
return pkey, nil 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, ",")
sort.Strings(ukey.Columns)
ukeys = append(ukeys, ukey)
}
if err = rows.Err(); err != nil {
return nil, err
}
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. // ForeignKeyInfo retrieves the foreign keys for a given table name.
func (m *MySQLDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { func (m *MySQLDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) {
var fkeys []bdb.ForeignKey var fkeys []bdb.ForeignKey

View file

@ -8,10 +8,10 @@ import (
// Side-effect import sql driver // Side-effect import sql driver
"github.com/lbryio/sqlboiler/bdb"
"github.com/lbryio/sqlboiler/strmangle"
_ "github.com/lib/pq" _ "github.com/lib/pq"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/volatiletech/sqlboiler/bdb"
"github.com/volatiletech/sqlboiler/strmangle"
) )
// PostgresDriver holds the database connection string and a handle // PostgresDriver holds the database connection string and a handle
@ -266,6 +266,14 @@ func (p *PostgresDriver) PrimaryKeyInfo(schema, tableName string) (*bdb.PrimaryK
return pkey, nil return pkey, nil
} }
func (p *PostgresDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, error) {
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. // ForeignKeyInfo retrieves the foreign keys for a given table name.
func (p *PostgresDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) { func (p *PostgresDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) {
var fkeys []bdb.ForeignKey var fkeys []bdb.ForeignKey

View file

@ -1,11 +1,7 @@
// Package bdb supplies the sql(b)oiler (d)ata(b)ase abstractions. // Package bdb supplies the sql(b)oiler (d)ata(b)ase abstractions.
package bdb package bdb
import ( import "github.com/pkg/errors"
"sort"
"github.com/pkg/errors"
)
// Interface for a database driver. Functionality required to support a specific // Interface for a database driver. Functionality required to support a specific
// database type (eg, MySQL, Postgres etc.) // database type (eg, MySQL, Postgres etc.)
@ -13,6 +9,8 @@ type Interface interface {
TableNames(schema string, whitelist, blacklist []string) ([]string, error) TableNames(schema string, whitelist, blacklist []string) ([]string, error)
Columns(schema, tableName string) ([]Column, error) Columns(schema, tableName string) ([]Column, error)
PrimaryKeyInfo(schema, tableName string) (*PrimaryKey, 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) ForeignKeyInfo(schema, tableName string) ([]ForeignKey, error)
// TranslateColumnType takes a Database column type and returns a go column type. // TranslateColumnType takes a Database column type and returns a go column type.
@ -49,8 +47,6 @@ func Tables(db Interface, schema string, whitelist, blacklist []string) ([]Table
return nil, errors.Wrap(err, "unable to get table names") return nil, errors.Wrap(err, "unable to get table names")
} }
sort.Strings(names)
var tables []Table var tables []Table
for _, name := range names { for _, name := range names {
t := Table{ t := Table{
@ -69,10 +65,18 @@ func Tables(db Interface, schema string, whitelist, blacklist []string) ([]Table
return nil, errors.Wrapf(err, "unable to fetch table pkey info (%s)", name) 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 { if t.FKeys, err = db.ForeignKeyInfo(schema, name); err != nil {
return nil, errors.Wrapf(err, "unable to fetch table fkey info (%s)", name) 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) setIsJoinTable(&t)
tables = append(tables, t) tables = append(tables, t)

View file

@ -3,7 +3,7 @@ package bdb
import ( import (
"testing" "testing"
"github.com/volatiletech/sqlboiler/strmangle" "github.com/lbryio/sqlboiler/strmangle"
) )
type testMockDriver struct{} type testMockDriver struct{}
@ -124,14 +124,6 @@ func TestTables(t *testing.T) {
t.Errorf("Expected len 7, got: %d\n", len(tables)) t.Errorf("Expected len 7, got: %d\n", len(tables))
} }
prev := ""
for i := range tables {
if prev >= tables[i].Name {
t.Error("tables are not sorted")
}
prev = tables[i].Name
}
pilots := GetTable(tables, "pilots") pilots := GetTable(tables, "pilots")
if len(pilots.Columns) != 2 { if len(pilots.Columns) != 2 {
t.Error() t.Error()

View file

@ -8,6 +8,13 @@ type PrimaryKey struct {
Columns []string 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 // ForeignKey represents a foreign key constraint in a database
type ForeignKey struct { type ForeignKey struct {
Table string Table string

View file

@ -8,9 +8,12 @@ type Table struct {
// For dbs with real schemas, like Postgres. // For dbs with real schemas, like Postgres.
// Example value: "schema_name"."table_name" // Example value: "schema_name"."table_name"
SchemaName string SchemaName string
Columns []Column
Columns []Column
AutoIncrementColumn string
PKey *PrimaryKey PKey *PrimaryKey
UKeys []UniqueKey
FKeys []ForeignKey FKeys []ForeignKey
IsJoinTable bool IsJoinTable bool

View file

@ -22,7 +22,6 @@ type Beginner interface {
Begin() (Transactor, error) Begin() (Transactor, error)
} }
// SQLBeginner begins transactions (non-interface return type)
type SQLBeginner interface { type SQLBeginner interface {
Begin() (*sql.Tx, error) Begin() (*sql.Tx, error)
} }

View file

@ -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
}

View file

@ -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")
}
}

View file

@ -13,10 +13,10 @@ import (
"text/template" "text/template"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/volatiletech/sqlboiler/bdb" "github.com/lbryio/sqlboiler/bdb"
"github.com/volatiletech/sqlboiler/bdb/drivers" "github.com/lbryio/sqlboiler/bdb/drivers"
"github.com/volatiletech/sqlboiler/queries" "github.com/lbryio/sqlboiler/queries"
"github.com/volatiletech/sqlboiler/strmangle" "github.com/lbryio/sqlboiler/strmangle"
) )
const ( const (
@ -267,7 +267,7 @@ func (s *State) processReplacements() error {
return nil return nil
} }
var basePackage = "github.com/volatiletech/sqlboiler" var basePackage = "github.com/lbryio/sqlboiler"
func getBasePath(baseDirConfig string) (string, error) { func getBasePath(baseDirConfig string) (string, error) {
if len(baseDirConfig) > 0 { if len(baseDirConfig) > 0 {

View file

@ -6,7 +6,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/volatiletech/sqlboiler/bdb" "github.com/lbryio/sqlboiler/bdb"
) )
// imports defines the optional standard imports and // imports defines the optional standard imports and
@ -170,26 +170,33 @@ func newImporter() importer {
`"time"`, `"time"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/pkg/errors"`, `"github.com/lbryio/lbry.go/v2/extras/errors"`,
`"github.com/volatiletech/sqlboiler/boil"`, `"github.com/lbryio/lbry.go/v2/extras/null"`,
`"github.com/volatiletech/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/boil"`,
`"github.com/volatiletech/sqlboiler/queries/qm"`, `"github.com/lbryio/sqlboiler/queries"`,
`"github.com/volatiletech/sqlboiler/strmangle"`, `"github.com/lbryio/sqlboiler/queries/qm"`,
`"github.com/lbryio/sqlboiler/strmangle"`,
}, },
} }
imp.Singleton = mapImports{ imp.Singleton = mapImports{
"boil_queries": { "boil_queries": imports{
standard: importList{
`"fmt"`,
`"strings"`,
},
thirdParty: importList{ thirdParty: importList{
`"github.com/volatiletech/sqlboiler/boil"`, `"github.com/lbryio/lbry.go/v2/extras/errors"`,
`"github.com/volatiletech/sqlboiler/queries"`, `"github.com/lbryio/sqlboiler/boil"`,
`"github.com/volatiletech/sqlboiler/queries/qm"`, `"github.com/lbryio/sqlboiler/queries"`,
`"github.com/lbryio/sqlboiler/queries/qm"`,
`"github.com/lbryio/sqlboiler/strmangle"`,
}, },
}, },
"boil_types": { "boil_types": {
thirdParty: importList{ thirdParty: importList{
`"github.com/pkg/errors"`, `"github.com/lbryio/lbry.go/v2/extras/errors"`,
`"github.com/volatiletech/sqlboiler/strmangle"`, `"github.com/lbryio/sqlboiler/strmangle"`,
}, },
}, },
} }
@ -201,9 +208,9 @@ func newImporter() importer {
`"testing"`, `"testing"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/volatiletech/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/boil"`,
`"github.com/volatiletech/sqlboiler/randomize"`, `"github.com/lbryio/sqlboiler/randomize"`,
`"github.com/volatiletech/sqlboiler/strmangle"`, `"github.com/lbryio/sqlboiler/strmangle"`,
}, },
} }
@ -221,9 +228,9 @@ func newImporter() importer {
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/kat-co/vala"`, `"github.com/kat-co/vala"`,
`"github.com/pkg/errors"`, `"github.com/lbryio/lbry.go/v2/extras/errors"`,
`"github.com/lbryio/sqlboiler/boil"`,
`"github.com/spf13/viper"`, `"github.com/spf13/viper"`,
`"github.com/volatiletech/sqlboiler/boil"`,
}, },
}, },
"boil_queries_test": { "boil_queries_test": {
@ -236,7 +243,7 @@ func newImporter() importer {
`"regexp"`, `"regexp"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/volatiletech/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/boil"`,
}, },
}, },
"boil_suites_test": { "boil_suites_test": {
@ -259,11 +266,11 @@ func newImporter() importer {
`"strings"`, `"strings"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/pkg/errors"`, `"github.com/lbryio/lbry.go/v2/extras/errors"`,
`"github.com/spf13/viper"`, `"github.com/lbryio/sqlboiler/bdb/drivers"`,
`"github.com/volatiletech/sqlboiler/bdb/drivers"`, `"github.com/lbryio/sqlboiler/randomize"`,
`"github.com/volatiletech/sqlboiler/randomize"`,
`_ "github.com/lib/pq"`, `_ "github.com/lib/pq"`,
`"github.com/spf13/viper"`,
}, },
}, },
"mysql": { "mysql": {
@ -278,11 +285,11 @@ func newImporter() importer {
`"strings"`, `"strings"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/pkg/errors"`,
`"github.com/spf13/viper"`,
`"github.com/volatiletech/sqlboiler/bdb/drivers"`,
`"github.com/volatiletech/sqlboiler/randomize"`,
`_ "github.com/go-sql-driver/mysql"`, `_ "github.com/go-sql-driver/mysql"`,
`"github.com/lbryio/lbry.go/v2/extras/errors"`,
`"github.com/lbryio/sqlboiler/bdb/drivers"`,
`"github.com/lbryio/sqlboiler/randomize"`,
`"github.com/spf13/viper"`,
}, },
}, },
"mssql": { "mssql": {
@ -295,11 +302,11 @@ func newImporter() importer {
`"strings"`, `"strings"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/pkg/errors"`,
`"github.com/spf13/viper"`,
`"github.com/volatiletech/sqlboiler/bdb/drivers"`,
`"github.com/volatiletech/sqlboiler/randomize"`,
`_ "github.com/denisenkom/go-mssqldb"`, `_ "github.com/denisenkom/go-mssqldb"`,
`"github.com/lbryio/lbry.go/v2/extras/errors"`,
`"github.com/lbryio/sqlboiler/bdb/drivers"`,
`"github.com/lbryio/sqlboiler/randomize"`,
`"github.com/spf13/viper"`,
}, },
}, },
} }
@ -309,79 +316,79 @@ func newImporter() importer {
// TranslateColumnType to see the type assignments. // TranslateColumnType to see the type assignments.
imp.BasedOnType = mapImports{ imp.BasedOnType = mapImports{
"null.Float32": { "null.Float32": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Float64": { "null.Float64": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Int": { "null.Int": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Int8": { "null.Int8": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Int16": { "null.Int16": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Int32": { "null.Int32": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Int64": { "null.Int64": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Uint": { "null.Uint": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Uint8": { "null.Uint8": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Uint16": { "null.Uint16": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Uint32": { "null.Uint32": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Uint64": { "null.Uint64": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.String": { "null.String": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Bool": { "null.Bool": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Time": { "null.Time": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.JSON": { "null.JSON": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"null.Bytes": { "null.Bytes": {
thirdParty: importList{`"gopkg.in/volatiletech/null.v6"`}, thirdParty: importList{`"github.com/lbryio/lbry.go/v2/extras/null"`},
}, },
"time.Time": { "time.Time": {
standard: importList{`"time"`}, standard: importList{`"time"`},
}, },
"types.JSON": { "types.JSON": {
thirdParty: importList{`"github.com/volatiletech/sqlboiler/types"`}, thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`},
}, },
"types.BytesArray": { "types.BytesArray": {
thirdParty: importList{`"github.com/volatiletech/sqlboiler/types"`}, thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`},
}, },
"types.Int64Array": { "types.Int64Array": {
thirdParty: importList{`"github.com/volatiletech/sqlboiler/types"`}, thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`},
}, },
"types.Float64Array": { "types.Float64Array": {
thirdParty: importList{`"github.com/volatiletech/sqlboiler/types"`}, thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`},
}, },
"types.BoolArray": { "types.BoolArray": {
thirdParty: importList{`"github.com/volatiletech/sqlboiler/types"`}, thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`},
}, },
"types.StringArray": { "types.StringArray": {
thirdParty: importList{`"github.com/volatiletech/sqlboiler/types"`}, thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`},
}, },
"types.Hstore": { "types.Hstore": {
thirdParty: importList{`"github.com/volatiletech/sqlboiler/types"`}, thirdParty: importList{`"github.com/lbryio/sqlboiler/types"`},
}, },
} }

View file

@ -6,7 +6,7 @@ import (
"testing" "testing"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/volatiletech/sqlboiler/bdb" "github.com/lbryio/sqlboiler/bdb"
) )
func TestImportsSort(t *testing.T) { func TestImportsSort(t *testing.T) {
@ -234,7 +234,7 @@ func TestCombineTypeImports(t *testing.T) {
`"fmt"`, `"fmt"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/volatiletech/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/boil"`,
}, },
} }
@ -245,8 +245,8 @@ func TestCombineTypeImports(t *testing.T) {
`"time"`, `"time"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/volatiletech/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/boil"`,
`"gopkg.in/volatiletech/null.v6"`, `"github.com/lbryio/lbry.go/v2/extras/null"`,
}, },
} }
@ -280,8 +280,8 @@ func TestCombineTypeImports(t *testing.T) {
`"time"`, `"time"`,
}, },
thirdParty: importList{ thirdParty: importList{
`"github.com/volatiletech/sqlboiler/boil"`, `"github.com/lbryio/sqlboiler/boil"`,
`"gopkg.in/volatiletech/null.v6"`, `"github.com/lbryio/lbry.go/v2/extras/null"`,
}, },
} }
@ -297,11 +297,11 @@ func TestCombineImports(t *testing.T) {
a := imports{ a := imports{
standard: importList{"fmt"}, standard: importList{"fmt"},
thirdParty: importList{"github.com/volatiletech/sqlboiler", "gopkg.in/volatiletech/null.v6"}, thirdParty: importList{"github.com/lbryio/sqlboiler", "github.com/lbryio/lbry.go/v2/extras/null"},
} }
b := imports{ b := imports{
standard: importList{"os"}, standard: importList{"os"},
thirdParty: importList{"github.com/volatiletech/sqlboiler"}, thirdParty: importList{"github.com/lbryio/sqlboiler"},
} }
c := combineImports(a, b) c := combineImports(a, b)
@ -309,8 +309,8 @@ func TestCombineImports(t *testing.T) {
if c.standard[0] != "fmt" && c.standard[1] != "os" { if c.standard[0] != "fmt" && c.standard[1] != "os" {
t.Errorf("Wanted: fmt, os got: %#v", c.standard) t.Errorf("Wanted: fmt, os got: %#v", c.standard)
} }
if c.thirdParty[0] != "github.com/volatiletech/sqlboiler" && c.thirdParty[1] != "gopkg.in/volatiletech/null.v6" { if c.thirdParty[0] != "github.com/lbryio/sqlboiler" && c.thirdParty[1] != "github.com/lbryio/lbry.go/v2/extras/null" {
t.Errorf("Wanted: github.com/volatiletech/sqlboiler, gopkg.in/volatiletech/null.v6 got: %#v", c.thirdParty) t.Errorf("Wanted: github.com/lbryio/sqlboiler, github.com/lbryio/lbry.go/v2/extras/null got: %#v", c.thirdParty)
} }
} }

View file

@ -14,7 +14,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
var noEditDisclaimer = []byte(`// This file is generated by SQLBoiler (https://github.com/volatiletech/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. // and is meant to be re-generated in place and/or deleted at any time.
// DO NOT EDIT // DO NOT EDIT

View file

@ -8,10 +8,10 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/lbryio/sqlboiler/bdb"
"github.com/lbryio/sqlboiler/queries"
"github.com/lbryio/sqlboiler/strmangle"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/volatiletech/sqlboiler/bdb"
"github.com/volatiletech/sqlboiler/queries"
"github.com/volatiletech/sqlboiler/strmangle"
) )
// templateData for sqlboiler templates // templateData for sqlboiler templates

View file

@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/volatiletech/sqlboiler/bdb" "github.com/lbryio/sqlboiler/bdb"
"github.com/volatiletech/sqlboiler/strmangle" "github.com/lbryio/sqlboiler/strmangle"
) )
// TxtToOne contains text that will be used by templates for a one-to-many or // TxtToOne contains text that will be used by templates for a one-to-many or

View file

@ -5,8 +5,8 @@ import (
"testing" "testing"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/volatiletech/sqlboiler/bdb" "github.com/lbryio/sqlboiler/bdb"
"github.com/volatiletech/sqlboiler/bdb/drivers" "github.com/lbryio/sqlboiler/bdb/drivers"
) )
func TestTxtsFromOne(t *testing.T) { func TestTxtsFromOne(t *testing.T) {

View file

@ -8,13 +8,13 @@ import (
"strings" "strings"
"github.com/kat-co/vala" "github.com/kat-co/vala"
"github.com/lbryio/sqlboiler/bdb/drivers"
"github.com/lbryio/sqlboiler/boilingcore"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/volatiletech/sqlboiler/bdb/drivers"
"github.com/volatiletech/sqlboiler/boilingcore"
) )
const sqlBoilerVersion = "2.5.1" const sqlBoilerVersion = "2.4.0+lbry"
var ( var (
cmdState *boilingcore.State cmdState *boilingcore.State
@ -62,7 +62,7 @@ func main() {
Use: "sqlboiler [flags] <driver>", Use: "sqlboiler [flags] <driver>",
Short: "SQL Boiler generates an ORM tailored to your database schema.", 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" + Long: "SQL Boiler generates a Go ORM from template files, tailored to your database schema.\n" +
`Complete documentation is available at http://github.com/volatiletech/sqlboiler`, `Complete documentation is available at http://github.com/lbryio/sqlboiler`,
Example: `sqlboiler postgres`, Example: `sqlboiler postgres`,
PreRunE: preRun, PreRunE: preRun,
RunE: run, RunE: run,

View file

@ -5,9 +5,9 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/lbryio/sqlboiler/boil"
"github.com/lbryio/sqlboiler/strmangle"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/volatiletech/sqlboiler/boil"
"github.com/volatiletech/sqlboiler/strmangle"
) )
type loadRelationshipState struct { type loadRelationshipState struct {
@ -259,9 +259,13 @@ func collectLoaded(key string, loadingFrom reflect.Value) (reflect.Value, bindKi
for { for {
switch bkind { switch bkind {
case kindStruct: case kindStruct:
collection = reflect.Append(collection, loadedObject) if !loadedObject.IsNil() {
collection = reflect.Append(collection, loadedObject)
}
case kindPtrSliceStruct: case kindPtrSliceStruct:
collection = reflect.AppendSlice(collection, loadedObject) if !loadedObject.IsNil() {
collection = reflect.AppendSlice(collection, loadedObject)
}
} }
i++ i++

View file

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/volatiletech/sqlboiler/boil" "github.com/lbryio/sqlboiler/boil"
) )
var testEagerCounters struct { var testEagerCounters struct {

View file

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/volatiletech/sqlboiler/strmangle" "github.com/lbryio/sqlboiler/strmangle"
) )
// NonZeroDefaultSet returns the fields included in the // NonZeroDefaultSet returns the fields included in the

View file

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

View file

@ -1,6 +1,6 @@
package qm package qm
import "github.com/volatiletech/sqlboiler/queries" import "github.com/lbryio/sqlboiler/queries"
// QueryMod to modify the query object // QueryMod to modify the query object
type QueryMod func(q *queries.Query) type QueryMod func(q *queries.Query)
@ -8,7 +8,9 @@ type QueryMod func(q *queries.Query)
// Apply the query mods to the Query object // Apply the query mods to the Query object
func Apply(q *queries.Query, mods ...QueryMod) { func Apply(q *queries.Query, mods ...QueryMod) {
for _, mod := range mods { for _, mod := range mods {
mod(q) if mod != nil {
mod(q)
}
} }
} }
@ -123,6 +125,12 @@ 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 // Limit the number of returned rows
func Limit(limit int) QueryMod { func Limit(limit int) QueryMod {
return func(q *queries.Query) { return func(q *queries.Query) {

View file

@ -4,7 +4,8 @@ import (
"database/sql" "database/sql"
"fmt" "fmt"
"github.com/volatiletech/sqlboiler/boil" "github.com/lbryio/lbry.go/v2/extras/errors"
"github.com/lbryio/sqlboiler/boil"
) )
// joinKind is the type of join // joinKind is the type of join
@ -29,6 +30,7 @@ type Query struct {
selectCols []string selectCols []string
count bool count bool
from []string from []string
forceindex string
joins []join joins []join
where []where where []where
in []in in []in
@ -136,7 +138,7 @@ func (q *Query) Query() (*sql.Rows, error) {
func (q *Query) ExecP() sql.Result { func (q *Query) ExecP() sql.Result {
res, err := q.Exec() res, err := q.Exec()
if err != nil { if err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
return res return res
@ -147,7 +149,7 @@ func (q *Query) ExecP() sql.Result {
func (q *Query) QueryP() *sql.Rows { func (q *Query) QueryP() *sql.Rows {
rows, err := q.Query() rows, err := q.Query()
if err != nil { if err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
return rows return rows
@ -188,11 +190,6 @@ func SetSelect(q *Query, sel []string) {
q.selectCols = sel q.selectCols = sel
} }
// GetSelect from the query
func GetSelect(q *Query) []string {
return q.selectCols
}
// SetCount on the query. // SetCount on the query.
func SetCount(q *Query) { func SetCount(q *Query) {
q.count = true q.count = true
@ -267,6 +264,11 @@ func SetLastWhereAsOr(q *Query) {
q.where[len(q.where)-1].orSeparator = true 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 // SetLastInAsOr sets the or separator for the tail "IN" in the slice
func SetLastInAsOr(q *Query) { func SetLastInAsOr(q *Query) {
if len(q.in) == 0 { if len(q.in) == 0 {

View file

@ -7,7 +7,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/volatiletech/sqlboiler/strmangle" "github.com/lbryio/sqlboiler/strmangle"
) )
var ( var (
@ -76,7 +76,13 @@ func buildSelectQuery(q *Query) (*bytes.Buffer, []interface{}) {
buf.WriteByte(')') 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 { if len(q.joins) > 0 {
argsLen := len(args) argsLen := len(args)
@ -190,7 +196,7 @@ func buildUpdateQuery(q *Query) (*bytes.Buffer, []interface{}) {
} }
// BuildUpsertQueryMySQL builds a SQL statement string using the upsertData provided. // 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) whitelist = strmangle.IdentQuoteSlice(dia.LQ, dia.RQ, whitelist)
buf := strmangle.GetBuffer() buf := strmangle.GetBuffer()
@ -220,6 +226,11 @@ func BuildUpsertQueryMySQL(dia Dialect, tableName string, update, whitelist []st
strmangle.Placeholders(dia.IndexPlaceholders, len(whitelist), 1, 1), 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 { for i, v := range update {
if i != 0 { if i != 0 {
buf.WriteByte(',') buf.WriteByte(',')

View file

@ -7,9 +7,9 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/lbryio/sqlboiler/strmangle"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/volatiletech/sqlboiler/boil"
"github.com/volatiletech/sqlboiler/strmangle"
) )
var ( var (
@ -41,7 +41,7 @@ const (
// It panics on error. See boil.Bind() documentation. // It panics on error. See boil.Bind() documentation.
func (q *Query) BindP(obj interface{}) { func (q *Query) BindP(obj interface{}) {
if err := q.Bind(obj); err != nil { if err := q.Bind(obj); err != nil {
panic(boil.WrapErr(err)) panic(errors.WithStack(err))
} }
} }

View file

@ -14,12 +14,12 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
null "gopkg.in/volatiletech/null.v6" null "github.com/lbryio/lbry.go/v2/extras/null"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/satori/go.uuid" "github.com/satori/go.uuid"
"github.com/volatiletech/sqlboiler/strmangle" "github.com/lbryio/sqlboiler/strmangle"
"github.com/volatiletech/sqlboiler/types" "github.com/lbryio/sqlboiler/types"
) )
var ( var (
@ -159,17 +159,18 @@ func randDate(s *Seed) time.Time {
// If canBeNull is true: // If canBeNull is true:
// The value has the possibility of being null or non-zero at random. // The value has the possibility of being null or non-zero at random.
func randomizeField(s *Seed, field reflect.Value, fieldType string, canBeNull bool) error { func randomizeField(s *Seed, field reflect.Value, fieldType string, canBeNull bool) error {
kind := field.Kind() kind := field.Kind()
typ := field.Type() typ := field.Type()
if strings.HasPrefix(fieldType, "enum") { if strings.HasPrefix(fieldType, "enum") {
enum, err := randEnumValue(s, fieldType) enum, err := randEnumValue(fieldType)
if err != nil { if err != nil {
return err return err
} }
if kind == reflect.Struct { if kind == reflect.Struct {
val := null.NewString(enum, s.nextInt()%2 == 0) val := null.NewString(enum, rand.Intn(1) == 0)
field.Set(reflect.ValueOf(val)) field.Set(reflect.ValueOf(val))
} else { } else {
field.Set(reflect.ValueOf(enum)) field.Set(reflect.ValueOf(enum))
@ -622,11 +623,11 @@ func getVariableRandValue(s *Seed, kind reflect.Kind, typ reflect.Type) interfac
return nil return nil
} }
func randEnumValue(s *Seed, enum string) (string, error) { func randEnumValue(enum string) (string, error) {
vals := strmangle.ParseEnumVals(enum) vals := strmangle.ParseEnumVals(enum)
if vals == nil || len(vals) == 0 { if vals == nil || len(vals) == 0 {
return "", fmt.Errorf("unable to parse enum string: %s", enum) return "", fmt.Errorf("unable to parse enum string: %s", enum)
} }
return vals[s.nextInt()%len(vals)], nil return vals[rand.Intn(len(vals)-1)], nil
} }

View file

@ -5,7 +5,7 @@ import (
"testing" "testing"
"time" "time"
null "gopkg.in/volatiletech/null.v6" null "github.com/lbryio/lbry.go/v2/extras/null"
) )
func TestRandomizeStruct(t *testing.T) { func TestRandomizeStruct(t *testing.T) {
@ -148,36 +148,24 @@ func TestRandomizeField(t *testing.T) {
func TestRandEnumValue(t *testing.T) { func TestRandEnumValue(t *testing.T) {
t.Parallel() t.Parallel()
s := NewSeed()
enum1 := "enum.workday('monday','tuesday')" enum1 := "enum.workday('monday','tuesday')"
enum2 := "enum('monday','tuesday')" enum2 := "enum('monday','tuesday')"
enum3 := "enum('monday')"
r1, err := randEnumValue(s, enum1) r1, err := randEnumValue(enum1)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
if r1 != "monday" && r1 != "tuesday" { if r1 != "monday" && r1 != "tuesday" {
t.Errorf("Expected monday or tuesday, got: %q", r1) t.Errorf("Expected monday or tueday, got: %q", r1)
} }
r2, err := randEnumValue(s, enum2) r2, err := randEnumValue(enum2)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
if r2 != "monday" && r2 != "tuesday" { if r2 != "monday" && r2 != "tuesday" {
t.Errorf("Expected monday or tuesday, got: %q", r2) t.Errorf("Expected monday or tueday, got: %q", r2)
}
r3, err := randEnumValue(s, enum3)
if err != nil {
t.Error(err)
}
if r3 != "monday" {
t.Errorf("Expected monday got: %q", r3)
} }
} }

View file

@ -1,6 +1,6 @@
package strmangle package strmangle
import "github.com/volatiletech/inflect" import "github.com/nullbio/inflect"
var boilRuleset *inflect.Ruleset var boilRuleset *inflect.Ruleset
@ -193,7 +193,6 @@ func newBoilRuleset() *inflect.Ruleset {
rs.AddSingularExact("is", "is", true) rs.AddSingularExact("is", "is", true)
rs.AddSingularExact("us", "us", true) rs.AddSingularExact("us", "us", true)
rs.AddSingularExact("as", "as", true) rs.AddSingularExact("as", "as", true)
rs.AddSingularExact("areas", "area", true)
rs.AddPluralExact("a", "a", true) rs.AddPluralExact("a", "a", true)
rs.AddPluralExact("i", "i", true) rs.AddPluralExact("i", "i", true)
rs.AddPluralExact("is", "is", true) rs.AddPluralExact("is", "is", true)

View file

@ -93,7 +93,7 @@ func SchemaTable(lq, rq string, driver string, schema string, table string) stri
return fmt.Sprintf(`%s%s%s`, lq, table, rq) return fmt.Sprintf(`%s%s%s`, lq, table, rq)
} }
// IdentQuote attempts to quote simple identifiers in SQL statements // IdentQuote attempts to quote simple identifiers in SQL tatements
func IdentQuote(lq byte, rq byte, s string) string { func IdentQuote(lq byte, rq byte, s string) string {
if strings.ToLower(s) == "null" || s == "?" { if strings.ToLower(s) == "null" || s == "?" {
return s return s

View file

@ -139,7 +139,6 @@ func TestSingular(t *testing.T) {
{"hello_people", "hello_person"}, {"hello_people", "hello_person"},
{"hello_person", "hello_person"}, {"hello_person", "hello_person"},
{"friends", "friend"}, {"friends", "friend"},
{"areas", "area"},
{"hello_there_people", "hello_there_person"}, {"hello_there_people", "hello_there_person"},
} }
@ -160,7 +159,6 @@ func TestPlural(t *testing.T) {
{"hello_person", "hello_people"}, {"hello_person", "hello_people"},
{"friend", "friends"}, {"friend", "friends"},
{"friends", "friends"}, {"friends", "friends"},
{"area", "areas"},
{"hello_there_person", "hello_there_people"}, {"hello_there_person", "hello_there_people"},
} }

View file

@ -27,6 +27,13 @@ var {{$modelName}}Columns = struct {
{{end -}} {{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 -}} {{- if .Table.IsJoinTable -}}
{{- else}} {{- else}}
// {{$modelNameCamel}}R is where relationships are stored. // {{$modelNameCamel}}R is where relationships are stored.

View file

@ -10,6 +10,7 @@ var (
{{$varNameSingular}}ColumnsWithoutDefault = []string{{"{"}}{{.Table.Columns | filterColumnsByDefault false | columnNames | stringMap .StringFuncs.quoteWrap | join ","}}{{"}"}} {{$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}}ColumnsWithDefault = []string{{"{"}}{{.Table.Columns | filterColumnsByDefault true | columnNames | stringMap .StringFuncs.quoteWrap | join ","}}{{"}"}}
{{$varNameSingular}}PrimaryKeyColumns = []string{{"{"}}{{.Table.PKey.Columns | stringMap .StringFuncs.quoteWrap | join ", "}}{{"}"}} {{$varNameSingular}}PrimaryKeyColumns = []string{{"{"}}{{.Table.PKey.Columns | stringMap .StringFuncs.quoteWrap | join ", "}}{{"}"}}
{{$varNameSingular}}AutoIncrementColumn = "{{.Table.AutoIncrementColumn }}"
) )
type ( type (
@ -21,7 +22,7 @@ type (
{{$tableNameSingular}}Hook func(boil.Executor, *{{$tableNameSingular}}) error {{$tableNameSingular}}Hook func(boil.Executor, *{{$tableNameSingular}}) error
{{- end}} {{- end}}
{{$varNameSingular}}Query struct { {{$tableNameSingular}}Query struct {
*queries.Query *queries.Query
} }
) )

View file

@ -16,7 +16,7 @@ var {{$varNameSingular}}AfterUpsertHooks []{{$tableNameSingular}}Hook
func (o *{{$tableNameSingular}}) doBeforeInsertHooks(exec boil.Executor) (err error) { func (o *{{$tableNameSingular}}) doBeforeInsertHooks(exec boil.Executor) (err error) {
for _, hook := range {{$varNameSingular}}BeforeInsertHooks { for _, hook := range {{$varNameSingular}}BeforeInsertHooks {
if err := hook(exec, o); err != nil { 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) { func (o *{{$tableNameSingular}}) doBeforeUpdateHooks(exec boil.Executor) (err error) {
for _, hook := range {{$varNameSingular}}BeforeUpdateHooks { for _, hook := range {{$varNameSingular}}BeforeUpdateHooks {
if err := hook(exec, o); err != nil { 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) { func (o *{{$tableNameSingular}}) doBeforeDeleteHooks(exec boil.Executor) (err error) {
for _, hook := range {{$varNameSingular}}BeforeDeleteHooks { for _, hook := range {{$varNameSingular}}BeforeDeleteHooks {
if err := hook(exec, o); err != nil { 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) { func (o *{{$tableNameSingular}}) doBeforeUpsertHooks(exec boil.Executor) (err error) {
for _, hook := range {{$varNameSingular}}BeforeUpsertHooks { for _, hook := range {{$varNameSingular}}BeforeUpsertHooks {
if err := hook(exec, o); err != nil { 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) { func (o *{{$tableNameSingular}}) doAfterInsertHooks(exec boil.Executor) (err error) {
for _, hook := range {{$varNameSingular}}AfterInsertHooks { for _, hook := range {{$varNameSingular}}AfterInsertHooks {
if err := hook(exec, o); err != nil { 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) { func (o *{{$tableNameSingular}}) doAfterSelectHooks(exec boil.Executor) (err error) {
for _, hook := range {{$varNameSingular}}AfterSelectHooks { for _, hook := range {{$varNameSingular}}AfterSelectHooks {
if err := hook(exec, o); err != nil { 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) { func (o *{{$tableNameSingular}}) doAfterUpdateHooks(exec boil.Executor) (err error) {
for _, hook := range {{$varNameSingular}}AfterUpdateHooks { for _, hook := range {{$varNameSingular}}AfterUpdateHooks {
if err := hook(exec, o); err != nil { 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) { func (o *{{$tableNameSingular}}) doAfterDeleteHooks(exec boil.Executor) (err error) {
for _, hook := range {{$varNameSingular}}AfterDeleteHooks { for _, hook := range {{$varNameSingular}}AfterDeleteHooks {
if err := hook(exec, o); err != nil { 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) { func (o *{{$tableNameSingular}}) doAfterUpsertHooks(exec boil.Executor) (err error) {
for _, hook := range {{$varNameSingular}}AfterUpsertHooks { for _, hook := range {{$varNameSingular}}AfterUpsertHooks {
if err := hook(exec, o); err != nil { if err := hook(exec, o); err != nil {
return err return errors.Err(err)
} }
} }

View file

@ -1,27 +1,27 @@
{{- $tableNameSingular := .Table.Name | singular | titleCase -}} {{- $tableNameSingular := .Table.Name | singular | titleCase -}}
{{- $varNameSingular := .Table.Name | singular | camelCase -}} {{- $varNameSingular := .Table.Name | singular | camelCase -}}
// OneP returns a single {{$varNameSingular}} record from the query, and panics on error. // OneP returns a single {{$tableNameSingular}} record from the query, and panics on error.
func (q {{$varNameSingular}}Query) OneP() (*{{$tableNameSingular}}) { func (q {{$tableNameSingular}}Query) OneP() (*{{$tableNameSingular}}) {
o, err := q.One() o, err := q.One()
if err != nil { if err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
return o return o
} }
// One returns a single {{$varNameSingular}} record from the query. // One returns a single {{$tableNameSingular}} record from the query.
func (q {{$varNameSingular}}Query) One() (*{{$tableNameSingular}}, error) { func (q {{$tableNameSingular}}Query) One() (*{{$tableNameSingular}}, error) {
o := &{{$tableNameSingular}}{} o := &{{$tableNameSingular}}{}
queries.SetLimit(q.Query, 1) queries.SetLimit(q.Query, 1)
err := q.Bind(o) err := q.Bind(o)
if err != nil { if err != nil {
if errors.Cause(err) == sql.ErrNoRows { if errors.Is(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}}") return nil, errors.Prefix("{{.PkgName}}: failed to execute a one query for {{.Table.Name}}", err)
} }
{{if not .NoHooks -}} {{if not .NoHooks -}}
@ -34,22 +34,22 @@ func (q {{$varNameSingular}}Query) One() (*{{$tableNameSingular}}, error) {
} }
// AllP returns all {{$tableNameSingular}} records from the query, and panics on 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() o, err := q.All()
if err != nil { if err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
return o return o
} }
// All returns all {{$tableNameSingular}} records from the query. // 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}} var o []*{{$tableNameSingular}}
err := q.Bind(&o) err := q.Bind(&o)
if err != nil { 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 -}} {{if not .NoHooks -}}
@ -66,17 +66,17 @@ func (q {{$varNameSingular}}Query) All() ({{$tableNameSingular}}Slice, error) {
} }
// CountP returns the count of all {{$tableNameSingular}} records in the query, and panics on 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() c, err := q.Count()
if err != nil { if err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
return c return c
} }
// Count returns the count of all {{$tableNameSingular}} records in the query. // 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 var count int64
queries.SetSelect(q.Query, nil) queries.SetSelect(q.Query, nil)
@ -84,32 +84,33 @@ func (q {{$varNameSingular}}Query) Count() (int64, error) {
err := q.Query.QueryRow().Scan(&count) err := q.Query.QueryRow().Scan(&count)
if err != nil { 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 return count, nil
} }
// Exists checks if the row exists in the table, and panics on 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() e, err := q.Exists()
if err != nil { if err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
return e return e
} }
// Exists checks if the row exists in the table. // 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 var count int64
queries.SetCount(q.Query) queries.SetCount(q.Query)
queries.SetSelect(q.Query, []string{})
queries.SetLimit(q.Query, 1) queries.SetLimit(q.Query, 1)
err := q.Query.QueryRow().Scan(&count) err := q.Query.QueryRow().Scan(&count)
if err != nil { 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 return count > 0, nil

View file

@ -3,14 +3,14 @@
{{- $dot := . -}} {{- $dot := . -}}
{{- range .Table.FKeys -}} {{- range .Table.FKeys -}}
{{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}} {{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}}
{{- $varNameSingular := .ForeignTable | singular | camelCase}} {{- $tableNameSingular := .ForeignTable | singular | titleCase}}
// {{$txt.Function.Name}}G pointed to by the foreign key. // {{$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...) return o.{{$txt.Function.Name}}(boil.GetDB(), mods...)
} }
// {{$txt.Function.Name}} pointed to by the foreign key. // {{$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{ queryMods := []qm.QueryMod{
qm.Where("{{$txt.ForeignTable.ColumnName}}=?", o.{{$txt.LocalTable.ColumnNameGo}}), qm.Where("{{$txt.ForeignTable.ColumnName}}=?", o.{{$txt.LocalTable.ColumnNameGo}}),
} }

View file

@ -3,14 +3,14 @@
{{- $dot := . -}} {{- $dot := . -}}
{{- range .Table.ToOneRelationships -}} {{- range .Table.ToOneRelationships -}}
{{- $txt := txtsFromOneToOne $dot.Tables $dot.Table . -}} {{- $txt := txtsFromOneToOne $dot.Tables $dot.Table . -}}
{{- $varNameSingular := .ForeignTable | singular | camelCase}} {{- $tableNameSingular := .ForeignTable | singular | titleCase}}
// {{$txt.Function.Name}}G pointed to by the foreign key. // {{$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...) return o.{{$txt.Function.Name}}(boil.GetDB(), mods...)
} }
// {{$txt.Function.Name}} pointed to by the foreign key. // {{$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{ queryMods := []qm.QueryMod{
qm.Where("{{$txt.ForeignTable.ColumnName}}=?", o.{{$txt.LocalTable.ColumnNameGo}}), qm.Where("{{$txt.ForeignTable.ColumnName}}=?", o.{{$txt.LocalTable.ColumnNameGo}}),
} }

View file

@ -3,19 +3,22 @@
{{- $dot := . -}} {{- $dot := . -}}
{{- $table := .Table -}} {{- $table := .Table -}}
{{- range .Table.ToManyRelationships -}} {{- range .Table.ToManyRelationships -}}
{{- $varNameSingular := .ForeignTable | singular | camelCase -}} {{- $tableNameSingular := .ForeignTable | singular | titleCase -}}
{{- $txt := txtsFromToMany $dot.Tables $table . -}} {{- $txt := txtsFromToMany $dot.Tables $table . -}}
{{- $schemaForeignTable := .ForeignTable | $dot.SchemaTable}} {{- $schemaForeignTable := .ForeignTable | $dot.SchemaTable}}
// {{$txt.Function.Name}}G retrieves all the {{.ForeignTable | singular}}'s {{$txt.ForeignTable.NameHumanReadable}} // {{$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}}. {{- 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...) return o.{{$txt.Function.Name}}(boil.GetDB(), mods...)
} }
// {{$txt.Function.Name}} retrieves all the {{.ForeignTable | singular}}'s {{$txt.ForeignTable.NameHumanReadable}} with an executor // {{$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}}. {{- 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 {
var queryMods []qm.QueryMod queryMods := []qm.QueryMod{
qm.Select("{{$schemaForeignTable}}.*"),
}
if len(mods) != 0 { if len(mods) != 0 {
queryMods = append(queryMods, mods...) queryMods = append(queryMods, mods...)
} }
@ -34,11 +37,6 @@ func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor,
query := {{$txt.ForeignTable.NamePluralGo}}(exec, queryMods...) query := {{$txt.ForeignTable.NamePluralGo}}(exec, queryMods...)
queries.SetFrom(query.Query, "{{$schemaForeignTable}}") queries.SetFrom(query.Query, "{{$schemaForeignTable}}")
if len(queries.GetSelect(query.Query)) == 0 {
queries.SetSelect(query.Query, []string{"{{$schemaForeignTable}}.*"})
}
return query return query
} }

View file

@ -4,7 +4,7 @@
{{- range .Table.FKeys -}} {{- range .Table.FKeys -}}
{{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}} {{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}}
{{- $varNameSingular := $dot.Table.Name | singular | camelCase -}} {{- $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 // Load{{$txt.Function.Name}} allows an eager lookup of values, cached into the
// loaded structs of the objects. // loaded structs of the objects.
func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singular bool, {{$arg}} interface{}) error { func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singular bool, {{$arg}} interface{}) error {
@ -45,20 +45,20 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
results, err := e.Query(query, args...) results, err := e.Query(query, args...)
if err != nil { 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() defer results.Close()
var resultSlice []*{{$txt.ForeignTable.NameGo}} var resultSlice []*{{$txt.ForeignTable.NameGo}}
if err = queries.Bind(results, &resultSlice); err != nil { 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 not $dot.NoHooks -}}
if len({{$varNameSingular}}AfterSelectHooks) != 0 { if len({{$varNameSingular}}AfterSelectHooks) != 0 {
for _, obj := range resultSlice { for _, obj := range resultSlice {
if err := obj.doAfterSelectHooks(e); err != nil { if err := obj.doAfterSelectHooks(e); err != nil {
return err return errors.Err(err)
} }
} }
} }

View file

@ -45,20 +45,20 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
results, err := e.Query(query, args...) results, err := e.Query(query, args...)
if err != nil { 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() defer results.Close()
var resultSlice []*{{$txt.ForeignTable.NameGo}} var resultSlice []*{{$txt.ForeignTable.NameGo}}
if err = queries.Bind(results, &resultSlice); err != nil { 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 not $dot.NoHooks -}}
if len({{$varNameSingular}}AfterSelectHooks) != 0 { if len({{$varNameSingular}}AfterSelectHooks) != 0 {
for _, obj := range resultSlice { for _, obj := range resultSlice {
if err := obj.doAfterSelectHooks(e); err != nil { if err := obj.doAfterSelectHooks(e); err != nil {
return err return errors.Err(err)
} }
} }
} }

View file

@ -54,7 +54,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
results, err := e.Query(query, args...) results, err := e.Query(query, args...)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to eager load {{.ForeignTable}}") return errors.Prefix("failed to eager load {{.ForeignTable}}", err)
} }
defer results.Close() 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) err = results.Scan({{$foreignTable.Columns | columnNames | stringMap $dot.StringFuncs.titleCase | prefixStringSlice "&one." | join ", "}}, &localJoinCol)
if err = results.Err(); err != nil { 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) 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 { 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 -}} {{else -}}
if err = queries.Bind(results, &resultSlice); err != nil { 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}} {{end}}
@ -90,7 +90,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
if len({{.ForeignTable | singular | camelCase}}AfterSelectHooks) != 0 { if len({{.ForeignTable | singular | camelCase}}AfterSelectHooks) != 0 {
for _, obj := range resultSlice { for _, obj := range resultSlice {
if err := obj.doAfterSelectHooks(e); err != nil { if err := obj.doAfterSelectHooks(e); err != nil {
return err return errors.Err(err)
} }
} }
} }

View file

@ -20,7 +20,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}G(insert bool, rel
// Panics on error. // Panics on error.
func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}P(exec boil.Executor, insert bool, related *{{$txt.ForeignTable.NameGo}}) { 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 { 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. // 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}}) { 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 { 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 var err error
if insert { if insert {
if err = related.Insert(exec); err != nil { 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 { 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}} 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. // Panics on error.
func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}P(exec boil.Executor, related *{{$txt.ForeignTable.NameGo}}) { 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 { 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. // Uses the global database handle and panics on error.
func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}GP(related *{{$txt.ForeignTable.NameGo}}) { 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 { 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 o.{{$txt.LocalTable.ColumnNameGo}}.Valid = false
if err = o.Update(exec, "{{.Column}}"); err != nil { if err = o.Update(exec, "{{.Column}}"); err != nil {
o.{{$txt.LocalTable.ColumnNameGo}}.Valid = true 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 o.R.{{$txt.Function.Name}} = nil

View file

@ -21,7 +21,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}G(insert bool, rel
// Panics on error. // Panics on error.
func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}P(exec boil.Executor, insert bool, related *{{$txt.ForeignTable.NameGo}}) { 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 { 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. // 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}}) { 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 { 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}} {{- end}}
if err = related.Insert(exec); err != nil { 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 { } else {
updateQuery := fmt.Sprintf( 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 { 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}} 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. // Panics on error.
func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}P(exec boil.Executor, related *{{$txt.ForeignTable.NameGo}}) { 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 { 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. // Uses the global database handle and panics on error.
func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}GP(related *{{$txt.ForeignTable.NameGo}}) { 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 { 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 related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = false
if err = related.Update(exec, "{{.ForeignColumn}}"); err != nil { if err = related.Update(exec, "{{.ForeignColumn}}"); err != nil {
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = true 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 o.R.{{$txt.Function.Name}} = nil

View file

@ -24,7 +24,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}G(insert bool, rel
// Panics on error. // Panics on error.
func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}P(exec boil.Executor, insert bool, related ...*{{$txt.ForeignTable.NameGo}}) { 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 { 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. // 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}}) { 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 { 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 -}} {{end -}}
if err = rel.Insert(exec); err != nil { 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 { }{{if not .ToJoinTable}} else {
updateQuery := fmt.Sprintf( 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 { 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}} 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...) _, err = exec.Exec(query, values...)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to insert into join table") return errors.Prefix("failed to insert into join table", err)
} }
} }
{{end -}} {{end -}}
@ -152,7 +152,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}G(insert bool, rel
// Panics on error. // Panics on error.
func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}P(exec boil.Executor, insert bool, related ...*{{$txt.ForeignTable.NameGo}}) { 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 { 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. // 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}}) { 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 { 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...) _, err := exec.Exec(query, values...)
if err != nil { 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 -}} {{if .ToJoinTable -}}
@ -230,7 +230,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}G(related ...*{
// Panics on error. // Panics on error.
func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}P(exec boil.Executor, related ...*{{$txt.ForeignTable.NameGo}}) { 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 { 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. // Uses the global database handle and panics on error.
func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}GP(related ...*{{$txt.ForeignTable.NameGo}}) { 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 { 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...) _, err = exec.Exec(query, values...)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to remove relationships before set") return errors.Prefix("failed to remove relationships before set", err)
} }
{{else -}} {{else -}}
for _, rel := range related { for _, rel := range related {
@ -277,7 +277,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Exec
} }
{{end -}} {{end -}}
if err = rel.Update(exec, "{{.ForeignColumn}}"); err != nil { if err = rel.Update(exec, "{{.ForeignColumn}}"); err != nil {
return err return errors.Err(err)
} }
} }
{{end -}} {{end -}}

View file

@ -1,12 +1,12 @@
{{- $tableNamePlural := .Table.Name | plural | titleCase -}} {{- $tableNamePlural := .Table.Name | plural | titleCase -}}
{{- $varNameSingular := .Table.Name | singular | camelCase}} {{- $tableNameSingular := .Table.Name | singular | titleCase}}
// {{$tableNamePlural}}G retrieves all records. // {{$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...) return {{$tableNamePlural}}(boil.GetDB(), mods...)
} }
// {{$tableNamePlural}} retrieves all the records using an executor. // {{$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}}")) mods = append(mods, qm.From("{{.Table.Name | .SchemaTable}}"))
return {{$varNameSingular}}Query{NewQuery(exec, mods...)} return {{$tableNameSingular}}Query{NewQuery(exec, mods...)}
} }

View file

@ -12,7 +12,7 @@ func Find{{$tableNameSingular}}G({{$pkArgs}}, selectCols ...string) (*{{$tableNa
func Find{{$tableNameSingular}}GP({{$pkArgs}}, selectCols ...string) *{{$tableNameSingular}} { func Find{{$tableNameSingular}}GP({{$pkArgs}}, selectCols ...string) *{{$tableNameSingular}} {
retobj, err := Find{{$tableNameSingular}}(boil.GetDB(), {{$pkNames | join ", "}}, selectCols...) retobj, err := Find{{$tableNameSingular}}(boil.GetDB(), {{$pkNames | join ", "}}, selectCols...)
if err != nil { if err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
return retobj return retobj
@ -35,10 +35,10 @@ func Find{{$tableNameSingular}}(exec boil.Executor, {{$pkArgs}}, selectCols ...s
err := q.Bind({{$varNameSingular}}Obj) err := q.Bind({{$varNameSingular}}Obj)
if err != nil { if err != nil {
if errors.Cause(err) == sql.ErrNoRows { if errors.Is(err, sql.ErrNoRows) {
return nil, 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 return {{$varNameSingular}}Obj, nil
@ -48,8 +48,79 @@ func Find{{$tableNameSingular}}(exec boil.Executor, {{$pkArgs}}, selectCols ...s
func Find{{$tableNameSingular}}P(exec boil.Executor, {{$pkArgs}}, selectCols ...string) *{{$tableNameSingular}} { func Find{{$tableNameSingular}}P(exec boil.Executor, {{$pkArgs}}, selectCols ...string) *{{$tableNameSingular}} {
retobj, err := Find{{$tableNameSingular}}(exec, {{$pkNames | join ", "}}, selectCols...) retobj, err := Find{{$tableNameSingular}}(exec, {{$pkNames | join ", "}}, selectCols...)
if err != nil { if err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
return retobj return retobj
} }
// FindOne{{$tableNameSingular}} retrieves a single record using filters.
func FindOne{{$tableNameSingular}}(exec boil.Executor, filters {{$tableNameSingular}}Filter) (*{{$tableNameSingular}}, error) {
obj := &{{$tableNameSingular}}{}
err := {{$tableNameSingular}}NewQuery(exec).
Where(filters).
Limit(1).
Bind(obj)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, errors.Prefix("{{.PkgName}}: unable to select from {{.Table.Name}}", err)
}
return 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 {
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)
}

View file

@ -10,7 +10,7 @@ func (o *{{$tableNameSingular}}) InsertG(whitelist ... string) error {
// behavior description. // behavior description.
func (o *{{$tableNameSingular}}) InsertGP(whitelist ... string) { func (o *{{$tableNameSingular}}) InsertGP(whitelist ... string) {
if err := o.Insert(boil.GetDB(), whitelist...); err != nil { 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. // for whitelist behavior description.
func (o *{{$tableNameSingular}}) InsertP(exec boil.Executor, whitelist ... string) { func (o *{{$tableNameSingular}}) InsertP(exec boil.Executor, whitelist ... string) {
if err := o.Insert(exec, whitelist...); err != nil { 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) // - All columns with a default, but non-zero are included (i.e. health = 75)
func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string) error { func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string) error {
if o == nil { 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 var err error
@ -37,7 +37,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
{{if not .NoHooks -}} {{if not .NoHooks -}}
if err := o.doBeforeInsertHooks(exec); err != nil { if err := o.doBeforeInsertHooks(exec); err != nil {
return err return errors.Err(err)
} }
{{- end}} {{- end}}
@ -59,11 +59,11 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
cache.valueMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, wl) cache.valueMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, wl)
if err != nil { if err != nil {
return err return errors.Err(err)
} }
cache.retMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, returnColumns) cache.retMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, returnColumns)
if err != nil { if err != nil {
return err return errors.Err(err)
} }
if len(wl) != 0 { 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)) 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...) _, err = exec.Exec(cache.query, vals...)
{{- end}} {{- end}}
if err != nil { 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 -}} {{if $canLastInsertID -}}
@ -125,7 +125,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
{{if $canLastInsertID -}} {{if $canLastInsertID -}}
lastID, err = result.LastInsertId() lastID, err = result.LastInsertId()
if err != nil { if err != nil {
return ErrSyncFail return errors.Err(ErrSyncFail)
} }
{{$colName := index .Table.PKey.Columns 0 -}} {{$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)...) err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...)
if err != nil { 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}} {{else}}
if len(cache.retMapping) != 0 { if len(cache.retMapping) != 0 {
@ -160,7 +160,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
} }
if err != nil { 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}} {{end}}

View file

@ -12,7 +12,7 @@ func (o *{{$tableNameSingular}}) UpdateG(whitelist ...string) error {
// Panics on error. See Update for whitelist behavior description. // Panics on error. See Update for whitelist behavior description.
func (o *{{$tableNameSingular}}) UpdateGP(whitelist ...string) { func (o *{{$tableNameSingular}}) UpdateGP(whitelist ...string) {
if err := o.Update(boil.GetDB(), whitelist...); err != nil { 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) { func (o *{{$tableNameSingular}}) UpdateP(exec boil.Executor, whitelist ... string) {
err := o.Update(exec, whitelist...) err := o.Update(exec, whitelist...)
if err != nil { 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 var err error
{{if not .NoHooks -}} {{if not .NoHooks -}}
if err = o.doBeforeUpdateHooks(exec); err != nil { if err = o.doBeforeUpdateHooks(exec); err != nil {
return err return errors.Err(err)
} }
{{end -}} {{end -}}
@ -56,13 +56,11 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string
{{if eq .DriverName "mssql"}} {{if eq .DriverName "mssql"}}
wl = strmangle.SetComplement(wl, {{$varNameSingular}}ColumnsWithAuto) wl = strmangle.SetComplement(wl, {{$varNameSingular}}ColumnsWithAuto)
{{end}} {{end}}
{{if not .NoAutoTimestamps}}
if len(whitelist) == 0 { 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 { 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", cache.query = fmt.Sprintf("UPDATE {{$schemaTable}} SET %s WHERE %s",
@ -71,7 +69,7 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string
) )
cache.valueMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, append(wl, {{$varNameSingular}}PrimaryKeyColumns...)) cache.valueMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, append(wl, {{$varNameSingular}}PrimaryKeyColumns...))
if err != nil { if err != nil {
return err return errors.Err(err)
} }
} }
@ -84,7 +82,7 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string
_, err = exec.Exec(cache.query, values...) _, err = exec.Exec(cache.query, values...)
if err != nil { 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 { if !cached {
@ -101,19 +99,19 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string
} }
// UpdateAllP updates all rows with matching column names, and panics on error. // 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 { if err := q.UpdateAll(cols); err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
} }
// UpdateAll updates all rows with the specified column values. // 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) queries.SetUpdate(q.Query, cols)
_, err := q.Query.Exec() _, err := q.Query.Exec()
if err != nil { 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 return nil
@ -127,14 +125,14 @@ func (o {{$tableNameSingular}}Slice) UpdateAllG(cols M) error {
// UpdateAllGP updates all rows with the specified column values, and panics on error. // UpdateAllGP updates all rows with the specified column values, and panics on error.
func (o {{$tableNameSingular}}Slice) UpdateAllGP(cols M) { func (o {{$tableNameSingular}}Slice) UpdateAllGP(cols M) {
if err := o.UpdateAll(boil.GetDB(), cols); err != nil { 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. // UpdateAllP updates all rows with the specified column values, and panics on error.
func (o {{$tableNameSingular}}Slice) UpdateAllP(exec boil.Executor, cols M) { func (o {{$tableNameSingular}}Slice) UpdateAllP(exec boil.Executor, cols M) {
if err := o.UpdateAll(exec, cols); err != nil { if err := o.UpdateAll(exec, cols); err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
} }
@ -146,7 +144,7 @@ func (o {{$tableNameSingular}}Slice) UpdateAll(exec boil.Executor, cols M) error
} }
if len(cols) == 0 { 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)) colNames := make([]string, len(cols))
@ -176,7 +174,7 @@ func (o {{$tableNameSingular}}Slice) UpdateAll(exec boil.Executor, cols M) error
_, err := exec.Exec(sql, args...) _, err := exec.Exec(sql, args...)
if err != nil { 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 return nil

View file

@ -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. // 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) { 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 { 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. // UpsertP panics on error.
func (o *{{$tableNameSingular}}) UpsertP(exec boil.Executor, {{if eq .DriverName "postgres"}}updateOnConflict bool, conflictColumns []string, {{end}}updateColumns []string, whitelist ...string) { 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 { 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. // 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 { func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName "postgres"}}updateOnConflict bool, conflictColumns []string, {{end}}updateColumns []string, whitelist ...string) error {
if o == nil { 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" . }} {{- template "timestamp_upsert_helper" . }}
{{if not .NoHooks -}} {{if not .NoHooks -}}
if err := o.doBeforeUpsertHooks(exec); err != nil { if err := o.doBeforeUpsertHooks(exec); err != nil {
return err return errors.Err(err)
} }
{{- end}} {{- end}}
@ -87,7 +87,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName
} }
} }
if len(insert) == 0 { 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) ret = strmangle.SetMerge(ret, {{$varNameSingular}}ColumnsWithAuto)
@ -104,7 +104,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName
{{end -}} {{end -}}
if len(update) == 0 { 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"}} {{if eq .DriverName "postgres"}}
@ -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) cache.query = queries.BuildUpsertQueryPostgres(dialect, "{{$schemaTable}}", updateOnConflict, ret, update, conflict, insert)
{{else if eq .DriverName "mysql"}} {{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( cache.retQuery = fmt.Sprintf(
"SELECT %s FROM {{.LQ}}{{.Table.Name}}{{.RQ}} WHERE {{whereClause .LQ .RQ 0 .Table.PKey.Columns}}", "SELECT %s FROM {{.LQ}}{{.Table.Name}}{{.RQ}} WHERE {{whereClause .LQ .RQ 0 .Table.PKey.Columns}}",
strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, ret), ","), strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, ret), ","),
@ -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}}) cache.valueMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, {{if eq .DriverName "mssql"}}whitelist{{else}}insert{{end}})
if err != nil { if err != nil {
return err return errors.Err(err)
} }
if len(ret) != 0 { if len(ret) != 0 {
cache.retMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, ret) cache.retMapping, err = queries.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, ret)
if err != nil { 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...) _, err = exec.Exec(cache.query, vals...)
{{- end}} {{- end}}
if err != nil { 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 -}} {{if $canLastInsertID -}}
@ -174,7 +174,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName
{{if $canLastInsertID -}} {{if $canLastInsertID -}}
lastID, err = result.LastInsertId() lastID, err = result.LastInsertId()
if err != nil { if err != nil {
return ErrSyncFail return errors.Err(ErrSyncFail)
} }
{{$colName := index .Table.PKey.Columns 0 -}} {{$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...) err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(returns...)
if err != nil { 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}} {{- else}}
if len(cache.retMapping) != 0 { 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...) _, err = exec.Exec(cache.query, vals...)
} }
if err != nil { if err != nil {
return errors.Wrap(err, "{{.PkgName}}: unable to upsert {{.Table.Name}}") return errors.Prefix("{{.PkgName}}: unable to upsert {{.Table.Name}}", err)
} }
{{- end}} {{- end}}

View file

@ -6,7 +6,7 @@
// Panics on error. // Panics on error.
func (o *{{$tableNameSingular}}) DeleteP(exec boil.Executor) { func (o *{{$tableNameSingular}}) DeleteP(exec boil.Executor) {
if err := o.Delete(exec); err != nil { 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. // DeleteG will match against the primary key column to find the record to delete.
func (o *{{$tableNameSingular}}) DeleteG() error { func (o *{{$tableNameSingular}}) DeleteG() error {
if o == nil { 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()) return o.Delete(boil.GetDB())
@ -25,7 +25,7 @@ func (o *{{$tableNameSingular}}) DeleteG() error {
// Panics on error. // Panics on error.
func (o *{{$tableNameSingular}}) DeleteGP() { func (o *{{$tableNameSingular}}) DeleteGP() {
if err := o.DeleteG(); err != nil { 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. // Delete will match against the primary key column to find the record to delete.
func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error { func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error {
if o == nil { 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 not .NoHooks -}}
if err := o.doBeforeDeleteHooks(exec); err != nil { if err := o.doBeforeDeleteHooks(exec); err != nil {
return err return errors.Err(err)
} }
{{- end}} {{- end}}
@ -52,12 +52,12 @@ func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error {
_, err := exec.Exec(sql, args...) _, err := exec.Exec(sql, args...)
if err != nil { 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 not .NoHooks -}}
if err := o.doAfterDeleteHooks(exec); err != nil { if err := o.doAfterDeleteHooks(exec); err != nil {
return err return errors.Err(err)
} }
{{- end}} {{- end}}
@ -65,23 +65,23 @@ func (o *{{$tableNameSingular}}) Delete(exec boil.Executor) error {
} }
// DeleteAllP deletes all rows, and panics on 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 { if err := q.DeleteAll(); err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
} }
// DeleteAll deletes all matching rows. // DeleteAll deletes all matching rows.
func (q {{$varNameSingular}}Query) DeleteAll() error { func (q {{$tableNameSingular}}Query) DeleteAll() error {
if q.Query == nil { if q.Query == nil {
return errors.New("{{.PkgName}}: no {{$varNameSingular}}Query provided for delete all") return errors.Err("{{.PkgName}}: no {{$tableNameSingular}}Query provided for delete all")
} }
queries.SetDelete(q.Query) queries.SetDelete(q.Query)
_, err := q.Query.Exec() _, err := q.Query.Exec()
if err != nil { 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 return nil
@ -90,14 +90,14 @@ func (q {{$varNameSingular}}Query) DeleteAll() error {
// DeleteAllGP deletes all rows in the slice, and panics on error. // DeleteAllGP deletes all rows in the slice, and panics on error.
func (o {{$tableNameSingular}}Slice) DeleteAllGP() { func (o {{$tableNameSingular}}Slice) DeleteAllGP() {
if err := o.DeleteAllG(); err != nil { if err := o.DeleteAllG(); err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
} }
// DeleteAllG deletes all rows in the slice. // DeleteAllG deletes all rows in the slice.
func (o {{$tableNameSingular}}Slice) DeleteAllG() error { func (o {{$tableNameSingular}}Slice) DeleteAllG() error {
if o == nil { 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()) 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. // DeleteAllP deletes all rows in the slice, using an executor, and panics on error.
func (o {{$tableNameSingular}}Slice) DeleteAllP(exec boil.Executor) { func (o {{$tableNameSingular}}Slice) DeleteAllP(exec boil.Executor) {
if err := o.DeleteAll(exec); err != nil { 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. // DeleteAll deletes all rows in the slice, using an executor.
func (o {{$tableNameSingular}}Slice) DeleteAll(exec boil.Executor) error { func (o {{$tableNameSingular}}Slice) DeleteAll(exec boil.Executor) error {
if o == nil { 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 { if len(o) == 0 {
@ -123,7 +123,7 @@ func (o {{$tableNameSingular}}Slice) DeleteAll(exec boil.Executor) error {
if len({{$varNameSingular}}BeforeDeleteHooks) != 0 { if len({{$varNameSingular}}BeforeDeleteHooks) != 0 {
for _, obj := range o { for _, obj := range o {
if err := obj.doBeforeDeleteHooks(exec); err != nil { 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...) _, err := exec.Exec(sql, args...)
if err != nil { 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 not .NoHooks -}}
if len({{$varNameSingular}}AfterDeleteHooks) != 0 { if len({{$varNameSingular}}AfterDeleteHooks) != 0 {
for _, obj := range o { for _, obj := range o {
if err := obj.doAfterDeleteHooks(exec); err != nil { if err := obj.doAfterDeleteHooks(exec); err != nil {
return err return errors.Err(err)
} }
} }
} }

View file

@ -5,21 +5,21 @@
// ReloadGP refetches the object from the database and panics on error. // ReloadGP refetches the object from the database and panics on error.
func (o *{{$tableNameSingular}}) ReloadGP() { func (o *{{$tableNameSingular}}) ReloadGP() {
if err := o.ReloadG(); err != nil { 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. // ReloadP refetches the object from the database with an executor. Panics on error.
func (o *{{$tableNameSingular}}) ReloadP(exec boil.Executor) { func (o *{{$tableNameSingular}}) ReloadP(exec boil.Executor) {
if err := o.Reload(exec); err != nil { 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. // ReloadG refetches the object from the database using the primary keys.
func (o *{{$tableNameSingular}}) ReloadG() error { func (o *{{$tableNameSingular}}) ReloadG() error {
if o == nil { 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()) return o.Reload(boil.GetDB())
@ -30,7 +30,7 @@ func (o *{{$tableNameSingular}}) ReloadG() error {
func (o *{{$tableNameSingular}}) Reload(exec boil.Executor) error { func (o *{{$tableNameSingular}}) Reload(exec boil.Executor) error {
ret, err := Find{{$tableNameSingular}}(exec, {{.Table.PKey.Columns | stringMap .StringFuncs.titleCase | prefixStringSlice "o." | join ", "}}) ret, err := Find{{$tableNameSingular}}(exec, {{.Table.PKey.Columns | stringMap .StringFuncs.titleCase | prefixStringSlice "o." | join ", "}})
if err != nil { if err != nil {
return err return errors.Err(err)
} }
*o = *ret *o = *ret
@ -42,7 +42,7 @@ func (o *{{$tableNameSingular}}) Reload(exec boil.Executor) error {
// Panics on error. // Panics on error.
func (o *{{$tableNameSingular}}Slice) ReloadAllGP() { func (o *{{$tableNameSingular}}Slice) ReloadAllGP() {
if err := o.ReloadAllG(); err != nil { 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. // Panics on error.
func (o *{{$tableNameSingular}}Slice) ReloadAllP(exec boil.Executor) { func (o *{{$tableNameSingular}}Slice) ReloadAllP(exec boil.Executor) {
if err := o.ReloadAll(exec); err != nil { 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. // and overwrites the original object slice with the newly updated slice.
func (o *{{$tableNameSingular}}Slice) ReloadAllG() error { func (o *{{$tableNameSingular}}Slice) ReloadAllG() error {
if o == nil { 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()) return o.ReloadAll(boil.GetDB())
@ -86,7 +86,7 @@ func (o *{{$tableNameSingular}}Slice) ReloadAll(exec boil.Executor) error {
err := q.Bind(&{{$varNamePlural}}) err := q.Bind(&{{$varNamePlural}})
if err != nil { 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}} *o = {{$varNamePlural}}

View file

@ -1,4 +1,5 @@
{{- $tableNameSingular := .Table.Name | singular | titleCase -}} {{- $tableNameSingular := .Table.Name | singular | titleCase -}}
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
{{- $colDefs := sqlColDefinitions .Table.Columns .Table.PKey.Columns -}} {{- $colDefs := sqlColDefinitions .Table.Columns .Table.PKey.Columns -}}
{{- $pkNames := $colDefs.Names | stringMap .StringFuncs.camelCase | stringMap .StringFuncs.replaceReserved -}} {{- $pkNames := $colDefs.Names | stringMap .StringFuncs.camelCase | stringMap .StringFuncs.replaceReserved -}}
{{- $pkArgs := joinSlices " " $pkNames $colDefs.Types | join ", " -}} {{- $pkArgs := joinSlices " " $pkNames $colDefs.Types | join ", " -}}
@ -21,7 +22,7 @@ func {{$tableNameSingular}}Exists(exec boil.Executor, {{$pkArgs}}) (bool, error)
err := row.Scan(&exists) err := row.Scan(&exists)
if err != nil { 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 return exists, nil
@ -36,7 +37,7 @@ func {{$tableNameSingular}}ExistsG({{$pkArgs}}) (bool, error) {
func {{$tableNameSingular}}ExistsGP({{$pkArgs}}) bool { func {{$tableNameSingular}}ExistsGP({{$pkArgs}}) bool {
e, err := {{$tableNameSingular}}Exists(boil.GetDB(), {{$pkNames | join ", "}}) e, err := {{$tableNameSingular}}Exists(boil.GetDB(), {{$pkNames | join ", "}})
if err != nil { if err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
return e return e
@ -46,8 +47,43 @@ func {{$tableNameSingular}}ExistsGP({{$pkArgs}}) bool {
func {{$tableNameSingular}}ExistsP(exec boil.Executor, {{$pkArgs}}) bool { func {{$tableNameSingular}}ExistsP(exec boil.Executor, {{$pkArgs}}) bool {
e, err := {{$tableNameSingular}}Exists(exec, {{$pkNames | join ", "}}) e, err := {{$tableNameSingular}}Exists(exec, {{$pkNames | join ", "}})
if err != nil { if err != nil {
panic(boil.WrapErr(err)) panic(errors.Err(err))
} }
return e 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...)
}
}

33
templates/22_query.tpl Normal file
View file

@ -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().(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())
}
}
}
return q
}
// Limit limits query results
func (q *{{$tableNameSingular}}Query) Limit(limit int) *{{$tableNameSingular}}Query {
queries.SetLimit(q.Query, limit)
return q
}

107
templates/23_merge.tpl Normal file
View file

@ -0,0 +1,107 @@
{{- $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) (err error) {
tx, ok := exec.(boil.Transactor)
if !ok {
txdb, ok := exec.(boil.Beginner)
if !ok {
return errors.Err("database does not support transactions")
}
tx, err = txdb.Begin()
if err != nil {
return errors.Err(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 {
return errors.Err(err)
} else if primary == nil {
return errors.Err("primary {{$tableNameSingular}} not found")
}
secondary, err := Find{{$tableNameSingular}}(tx, secondaryID)
if err != nil {
return errors.Err(err)
} else if secondary == nil {
return errors.Err("secondary {{$tableNameSingular}} not found")
}
foreignKeys := []foreignKey{
{{- range .Tables -}}
{{- range .FKeys -}}
{{- if eq $dot.Table.Name .ForeignTable }}
{foreignTable: "{{.Table}}", foreignColumn: "{{.Column}}"},
{{- end -}}
{{- end -}}
{{- end }}
}
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 {
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().(null.Nullable); ok && !nullable.IsNull() && pf.Interface().(null.Nullable).IsNull() {
pf.Set(sf)
}
}
}
err = primary.Update(tx)
if err != nil {
return err
}
err = secondary.Delete(tx)
if err != nil {
return err
}
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 */}}

View file

@ -19,3 +19,168 @@ func NewQuery(exec boil.Executor, mods ...qm.QueryMod) *queries.Query {
return q return q
} }
func mergeModels(tx boil.Executor, primaryID uint64, secondaryID uint64, foreignKeys []foreignKey, conflictingKeys []conflictingUniqueKey) error {
if len(foreignKeys) < 1 {
return nil
}
var err error
for _, conflict := range conflictingKeys {
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
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.Err(err)
}
}
return checkMerge(tx, foreignKeys)
}
func deleteOneToOneConflictsBeforeMerge(tx boil.Executor, conflict conflictingUniqueKey, primaryID uint64, secondaryID uint64) error {
query := fmt.Sprintf(
"SELECT COUNT(*) FROM %s WHERE %s IN (%s)",
conflict.table, conflict.objectIdColumn,
strmangle.Placeholders(dialect.IndexPlaceholders, 2, 1, 1),
)
var count int
err := tx.QueryRow(query, primaryID, secondaryID).Scan(&count)
if err != nil {
return errors.Err(err)
}
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",
conflict.table, conflict.objectIdColumn, strmangle.Placeholders(dialect.IndexPlaceholders, 1, 1, 1),
)
_, 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 {
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)
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
}
func checkMerge(tx boil.Executor, 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.Err(err)
}
for rows.Next() {
var tableName string
var columnName string
err = rows.Scan(&tableName, &columnName)
if err != nil {
return errors.Err(err)
}
if _, exists := handledTablesColumns[tableName+"."+columnName]; !exists {
return errors.Err("missing merge for " + tableName + "." + columnName)
}
}
return nil
}

View file

@ -1,10 +1,26 @@
// M type is for providing columns and column values to UpdateAll. // M type is for providing columns and column values to UpdateAll.
type M map[string]interface{} type M map[string]interface{}
// 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 // ErrSyncFail occurs during insert when the record could not be retrieved in
// order to populate default value information. This usually happens when LastInsertId // order to populate default value information. This usually happens when LastInsertId
// fails or there was a primary key configuration that was not resolvable. // 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 { type insertCache struct {
query string query string

View file

@ -25,17 +25,17 @@ func (m *mssqlTester) setup() error {
m.testDBName = randomize.StableDBName(m.dbName) m.testDBName = randomize.StableDBName(m.dbName)
if err = m.dropTestDB(); err != nil { if err = m.dropTestDB(); err != nil {
return err return errors.Err(err)
} }
if err = m.createTestDB(); err != nil { 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) createCmd := exec.Command("sqlcmd", "-S", m.host, "-U", m.user, "-P", m.pass, "-d", m.testDBName)
f, err := os.Open("tables_schema.sql") f, err := os.Open("tables_schema.sql")
if err != nil { 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() defer f.Close()
@ -43,12 +43,12 @@ func (m *mssqlTester) setup() error {
createCmd.Stdin = newFKeyDestroyer(rgxMSSQLkey, f) createCmd.Stdin = newFKeyDestroyer(rgxMSSQLkey, f)
if err = createCmd.Start(); err != nil { 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 { if err = createCmd.Wait(); err != nil {
fmt.Println(err) 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 return nil
@ -92,7 +92,7 @@ func (m *mssqlTester) teardown() error {
} }
if err := m.dropTestDB(); err != nil { if err := m.dropTestDB(); err != nil {
return err return errors.Err(err)
} }
return nil return nil
@ -110,7 +110,7 @@ func (m *mssqlTester) runCmd(stdin, command string, args ...string) error {
fmt.Println("failed running:", command, args) fmt.Println("failed running:", command, args)
fmt.Println(stdout.String()) fmt.Println(stdout.String())
fmt.Println(stderr.String()) fmt.Println(stderr.String())
return err return errors.Err(err)
} }
return nil return nil

View file

@ -30,14 +30,14 @@ func (m *mysqlTester) setup() error {
m.testDBName = randomize.StableDBName(m.dbName) m.testDBName = randomize.StableDBName(m.dbName)
if err = m.makeOptionFile(); err != nil { 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 { if err = m.dropTestDB(); err != nil {
return err return errors.Err(err)
} }
if err = m.createTestDB(); err != nil { if err = m.createTestDB(); err != nil {
return err return errors.Err(err)
} }
dumpCmd := exec.Command("mysqldump", m.defaultsFile(), "--no-data", m.dbName) dumpCmd := exec.Command("mysqldump", m.defaultsFile(), "--no-data", m.dbName)
@ -48,22 +48,22 @@ func (m *mysqlTester) setup() error {
createCmd.Stdin = newFKeyDestroyer(rgxMySQLkey, r) createCmd.Stdin = newFKeyDestroyer(rgxMySQLkey, r)
if err = dumpCmd.Start(); err != nil { 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 { 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 { if err = dumpCmd.Wait(); err != nil {
fmt.Println(err) 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 w.Close() // After dumpCmd is done, close the write end of the pipe
if err = createCmd.Wait(); err != nil { if err = createCmd.Wait(); err != nil {
fmt.Println(err) 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 return nil
@ -87,7 +87,7 @@ func (m *mysqlTester) defaultsFile() string {
func (m *mysqlTester) makeOptionFile() error { func (m *mysqlTester) makeOptionFile() error {
tmp, err := ioutil.TempFile("", "optionfile") tmp, err := ioutil.TempFile("", "optionfile")
if err != nil { if err != nil {
return errors.Wrap(err, "failed to create option file") return errors.Prefix("failed to create option file", err)
} }
isTCP := false isTCP := false
@ -95,7 +95,7 @@ func (m *mysqlTester) makeOptionFile() error {
if os.IsNotExist(err) { if os.IsNotExist(err) {
isTCP = true isTCP = true
} else if err != nil { } 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]") fmt.Fprintln(tmp, "[client]")
@ -139,7 +139,7 @@ func (m *mysqlTester) teardown() error {
} }
if err := m.dropTestDB(); err != nil { if err := m.dropTestDB(); err != nil {
return err return errors.Err(err)
} }
return os.Remove(m.optionFile) 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("failed running:", command, args)
fmt.Println(stdout.String()) fmt.Println(stdout.String())
fmt.Println(stderr.String()) fmt.Println(stderr.String())
return err return errors.Err(err)
} }
return nil return nil

View file

@ -33,14 +33,14 @@ func (p *pgTester) setup() error {
p.testDBName = randomize.StableDBName(p.dbName) p.testDBName = randomize.StableDBName(p.dbName)
if err = p.makePGPassFile(); err != nil { if err = p.makePGPassFile(); err != nil {
return err return errors.Err(err)
} }
if err = p.dropTestDB(); err != nil { if err = p.dropTestDB(); err != nil {
return err return errors.Err(err)
} }
if err = p.createTestDB(); err != nil { if err = p.createTestDB(); err != nil {
return err return errors.Err(err)
} }
dumpCmd := exec.Command("pg_dump", "--schema-only", p.dbName) dumpCmd := exec.Command("pg_dump", "--schema-only", p.dbName)
@ -53,22 +53,22 @@ func (p *pgTester) setup() error {
createCmd.Stdin = newFKeyDestroyer(rgxPGFkey, r) createCmd.Stdin = newFKeyDestroyer(rgxPGFkey, r)
if err = dumpCmd.Start(); err != nil { 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 { 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 { if err = dumpCmd.Wait(); err != nil {
fmt.Println(err) 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 w.Close() // After dumpCmd is done, close the write end of the pipe
if err = createCmd.Wait(); err != nil { if err = createCmd.Wait(); err != nil {
fmt.Println(err) 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 return nil
@ -90,7 +90,7 @@ func (p *pgTester) runCmd(stdin, command string, args ...string) error {
fmt.Println("failed running:", command, args) fmt.Println("failed running:", command, args)
fmt.Println(stdout.String()) fmt.Println(stdout.String())
fmt.Println(stderr.String()) fmt.Println(stderr.String())
return err return errors.Err(err)
} }
return nil return nil
@ -108,7 +108,7 @@ func (p *pgTester) pgEnv() []string {
func (p *pgTester) makePGPassFile() error { func (p *pgTester) makePGPassFile() error {
tmp, err := ioutil.TempFile("", "pgpass") tmp, err := ioutil.TempFile("", "pgpass")
if err != nil { 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) 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 { func (p *pgTester) teardown() error {
var err error var err error
if err = p.dbConn.Close(); err != nil { if err = p.dbConn.Close(); err != nil {
return err return errors.Err(err)
} }
p.dbConn = nil p.dbConn = nil
if err = p.dropTestDB(); err != nil { if err = p.dropTestDB(); err != nil {
return err return errors.Err(err)
} }
return os.Remove(p.pgPassFile) return os.Remove(p.pgPassFile)

View file

@ -143,5 +143,5 @@ func validateConfig(driverName string) error {
).Check() ).Check()
} }
return errors.New("not a valid driver name") return errors.Err("not a valid driver name")
} }