Merge branch 'dev'
This commit is contained in:
commit
05d901865a
33 changed files with 812 additions and 531 deletions
|
@ -85,7 +85,7 @@ func Tables(db Interface, schema string, whitelist, blacklist []string) ([]Table
|
|||
// A composite primary key involving two columns
|
||||
// Both primary key columns are also foreign keys
|
||||
func setIsJoinTable(t *Table) {
|
||||
if t.PKey == nil || len(t.PKey.Columns) != 2 || len(t.FKeys) < 2 {
|
||||
if t.PKey == nil || len(t.PKey.Columns) != 2 || len(t.FKeys) < 2 || len(t.Columns) > 2 {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
35
bdb/keys.go
35
bdb/keys.go
|
@ -1,12 +1,6 @@
|
|||
package bdb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var rgxAutoIncColumn = regexp.MustCompile(`^nextval\(.*\)`)
|
||||
import "fmt"
|
||||
|
||||
// PrimaryKey represents a primary key constraint in a database
|
||||
type PrimaryKey struct {
|
||||
|
@ -80,30 +74,3 @@ func SQLColDefinitions(cols []Column, names []string) SQLColumnDefs {
|
|||
|
||||
return ret
|
||||
}
|
||||
|
||||
// AutoIncPrimaryKey returns the auto-increment primary key column name or an
|
||||
// empty string. Primary key columns with default values are presumed
|
||||
// to be auto-increment, because pkeys need to be unique and a static
|
||||
// default value would cause collisions.
|
||||
func AutoIncPrimaryKey(cols []Column, pkey *PrimaryKey) *Column {
|
||||
if pkey == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, pkeyColumn := range pkey.Columns {
|
||||
for _, c := range cols {
|
||||
if c.Name != pkeyColumn {
|
||||
continue
|
||||
}
|
||||
|
||||
if c.Default != "auto_increment" || c.Nullable ||
|
||||
!(strings.HasPrefix(c.Type, "int") || strings.HasPrefix(c.Type, "uint")) {
|
||||
continue
|
||||
}
|
||||
|
||||
return &c
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ func toManyRelationships(table Table, tables []Table) []ToManyRelationship {
|
|||
|
||||
for _, t := range tables {
|
||||
for _, f := range t.FKeys {
|
||||
if f.ForeignTable == table.Name && !f.Unique {
|
||||
if f.ForeignTable == table.Name && (t.IsJoinTable || !f.Unique) {
|
||||
relationships = append(relationships, buildToManyRelationship(table, f, t, tables))
|
||||
}
|
||||
}
|
||||
|
@ -101,12 +101,11 @@ func buildToOneRelationship(localTable Table, foreignKey ForeignKey, foreignTabl
|
|||
|
||||
func buildToManyRelationship(localTable Table, foreignKey ForeignKey, foreignTable Table, tables []Table) ToManyRelationship {
|
||||
if !foreignTable.IsJoinTable {
|
||||
col := localTable.GetColumn(foreignKey.ForeignColumn)
|
||||
return ToManyRelationship{
|
||||
Table: localTable.Name,
|
||||
Column: foreignKey.ForeignColumn,
|
||||
Nullable: col.Nullable,
|
||||
Unique: col.Unique,
|
||||
Nullable: foreignKey.ForeignColumnNullable,
|
||||
Unique: foreignKey.ForeignColumnUnique,
|
||||
ForeignTable: foreignTable.Name,
|
||||
ForeignColumn: foreignKey.Column,
|
||||
ForeignColumnNullable: foreignKey.Nullable,
|
||||
|
@ -115,33 +114,33 @@ func buildToManyRelationship(localTable Table, foreignKey ForeignKey, foreignTab
|
|||
}
|
||||
}
|
||||
|
||||
col := foreignTable.GetColumn(foreignKey.Column)
|
||||
relationship := ToManyRelationship{
|
||||
Table: localTable.Name,
|
||||
Column: foreignKey.ForeignColumn,
|
||||
Nullable: col.Nullable,
|
||||
Unique: col.Unique,
|
||||
Table: localTable.Name,
|
||||
Column: foreignKey.ForeignColumn,
|
||||
Nullable: foreignKey.ForeignColumnNullable,
|
||||
Unique: foreignKey.ForeignColumnUnique,
|
||||
|
||||
ToJoinTable: true,
|
||||
JoinTable: foreignTable.Name,
|
||||
|
||||
JoinLocalColumn: foreignKey.Column,
|
||||
JoinLocalColumnNullable: foreignKey.Nullable,
|
||||
JoinLocalColumnUnique: foreignKey.Unique,
|
||||
}
|
||||
|
||||
for _, fk := range foreignTable.FKeys {
|
||||
if fk.ForeignTable != localTable.Name {
|
||||
relationship.JoinForeignColumn = fk.Column
|
||||
relationship.JoinForeignColumnNullable = fk.Nullable
|
||||
relationship.JoinForeignColumnUnique = fk.Unique
|
||||
|
||||
foreignTable := GetTable(tables, fk.ForeignTable)
|
||||
foreignCol := foreignTable.GetColumn(fk.ForeignColumn)
|
||||
relationship.ForeignTable = fk.ForeignTable
|
||||
relationship.ForeignColumn = fk.ForeignColumn
|
||||
relationship.ForeignColumnNullable = foreignCol.Nullable
|
||||
relationship.ForeignColumnUnique = foreignCol.Unique
|
||||
} else {
|
||||
relationship.JoinLocalColumn = fk.Column
|
||||
relationship.JoinLocalColumnNullable = fk.Nullable
|
||||
relationship.JoinLocalColumnUnique = fk.Unique
|
||||
if fk.Name == foreignKey.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
relationship.JoinForeignColumn = fk.Column
|
||||
relationship.JoinForeignColumnNullable = fk.Nullable
|
||||
relationship.JoinForeignColumnUnique = fk.Unique
|
||||
|
||||
relationship.ForeignTable = fk.ForeignTable
|
||||
relationship.ForeignColumn = fk.ForeignColumn
|
||||
relationship.ForeignColumnNullable = fk.ForeignColumnNullable
|
||||
relationship.ForeignColumnUnique = fk.ForeignColumnUnique
|
||||
}
|
||||
|
||||
return relationship
|
||||
|
|
|
@ -213,15 +213,15 @@ func TestToManyRelationshipsNull(t *testing.T) {
|
|||
Name: "jets",
|
||||
Columns: []Column{{Name: "id", Nullable: true}, {Name: "pilot_id", Nullable: true}, {Name: "airport_id", Nullable: true}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "jets_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true},
|
||||
{Name: "jets_airport_id_fk", Column: "airport_id", ForeignTable: "airports", ForeignColumn: "id", Nullable: true},
|
||||
{Name: "jets_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true, ForeignColumnNullable: true},
|
||||
{Name: "jets_airport_id_fk", Column: "airport_id", ForeignTable: "airports", ForeignColumn: "id", Nullable: true, ForeignColumnNullable: true},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "licenses",
|
||||
Columns: []Column{{Name: "id", Nullable: true}, {Name: "pilot_id", Nullable: true}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "licenses_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true},
|
||||
{Name: "licenses_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true, ForeignColumnNullable: true},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -237,8 +237,8 @@ func TestToManyRelationshipsNull(t *testing.T) {
|
|||
IsJoinTable: true,
|
||||
Columns: []Column{{Name: "pilot_id", Nullable: true}, {Name: "language_id", Nullable: true}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true},
|
||||
{Name: "language_id_fk", Column: "language_id", ForeignTable: "languages", ForeignColumn: "id", Nullable: true},
|
||||
{Name: "pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true, ForeignColumnNullable: true},
|
||||
{Name: "language_id_fk", Column: "language_id", ForeignTable: "languages", ForeignColumn: "id", Nullable: true, ForeignColumnNullable: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
24
bdb/table.go
24
bdb/table.go
|
@ -40,3 +40,27 @@ func (t Table) GetColumn(name string) (col Column) {
|
|||
|
||||
panic(fmt.Sprintf("could not find column name: %s", name))
|
||||
}
|
||||
|
||||
// CanLastInsertID checks the following:
|
||||
// 1. Is there only one primary key?
|
||||
// 2. Does the primary key column have a default value?
|
||||
// 3. Is the primary key column type one of uintX/intX?
|
||||
// If the above is all true, this table can use LastInsertId
|
||||
func (t Table) CanLastInsertID() bool {
|
||||
if t.PKey == nil || len(t.PKey.Columns) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
col := t.GetColumn(t.PKey.Columns[0])
|
||||
if len(col.Default) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
switch col.Type {
|
||||
case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64":
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -65,3 +65,56 @@ func TestGetColumnMissing(t *testing.T) {
|
|||
|
||||
table.GetColumn("missing")
|
||||
}
|
||||
|
||||
func TestCanLastInsertID(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
Can bool
|
||||
PKeys []Column
|
||||
}{
|
||||
{true, []Column{
|
||||
{Name: "id", Type: "int64", Default: "a"},
|
||||
}},
|
||||
{true, []Column{
|
||||
{Name: "id", Type: "uint64", Default: "a"},
|
||||
}},
|
||||
{true, []Column{
|
||||
{Name: "id", Type: "int", Default: "a"},
|
||||
}},
|
||||
{true, []Column{
|
||||
{Name: "id", Type: "uint", Default: "a"},
|
||||
}},
|
||||
{true, []Column{
|
||||
{Name: "id", Type: "uint", Default: "a"},
|
||||
}},
|
||||
{false, []Column{
|
||||
{Name: "id", Type: "uint", Default: "a"},
|
||||
{Name: "id2", Type: "uint", Default: "a"},
|
||||
}},
|
||||
{false, []Column{
|
||||
{Name: "id", Type: "string", Default: "a"},
|
||||
}},
|
||||
{false, []Column{
|
||||
{Name: "id", Type: "int", Default: ""},
|
||||
}},
|
||||
{false, nil},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
table := Table{
|
||||
Columns: test.PKeys,
|
||||
PKey: &PrimaryKey{},
|
||||
}
|
||||
|
||||
var pkeyNames []string
|
||||
for _, pk := range test.PKeys {
|
||||
pkeyNames = append(pkeyNames, pk.Name)
|
||||
}
|
||||
table.PKey.Columns = pkeyNames
|
||||
|
||||
if got := table.CanLastInsertID(); got != test.Can {
|
||||
t.Errorf("%d) wrong: %t", i, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
205
output.go
205
output.go
|
@ -5,8 +5,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
@ -15,11 +14,17 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var testHarnessStdout io.Writer = os.Stdout
|
||||
var testHarnessFileOpen = func(filename string) (io.WriteCloser, error) {
|
||||
file, err := os.Create(filename)
|
||||
return file, err
|
||||
}
|
||||
var (
|
||||
// templateByteBuffer is re-used by all template construction to avoid
|
||||
// allocating more memory than is needed. This will later be a problem for
|
||||
// concurrency, address it then.
|
||||
templateByteBuffer = &bytes.Buffer{}
|
||||
|
||||
rgxRemoveNumberedPrefix = regexp.MustCompile(`[0-9]+_`)
|
||||
rgxSyntaxError = regexp.MustCompile(`(\d+):\d+: `)
|
||||
|
||||
testHarnessWriteFile = ioutil.WriteFile
|
||||
)
|
||||
|
||||
// generateOutput builds the file output and sends it to outHandler for saving
|
||||
func generateOutput(state *State, data *templateData) error {
|
||||
|
@ -88,26 +93,27 @@ func executeTemplates(e executeTemplateData) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
var out [][]byte
|
||||
var imps imports
|
||||
out := templateByteBuffer
|
||||
out.Reset()
|
||||
|
||||
var imps imports
|
||||
imps.standard = e.importSet.standard
|
||||
imps.thirdParty = e.importSet.thirdParty
|
||||
for _, tplName := range e.templates.Templates() {
|
||||
if e.combineImportsOnType {
|
||||
imps = combineTypeImports(imps, importsBasedOnType, e.data.Table.Columns)
|
||||
}
|
||||
if e.combineImportsOnType {
|
||||
imps = combineTypeImports(imps, importsBasedOnType, e.data.Table.Columns)
|
||||
}
|
||||
|
||||
resp, err := executeTemplate(e.templates.Template, tplName, e.data)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Error generating template %s", tplName)
|
||||
writePackageName(out, e.state.Config.PkgName)
|
||||
writeImports(out, imps)
|
||||
|
||||
for _, tplName := range e.templates.Templates() {
|
||||
if err := executeTemplate(out, e.templates.Template, tplName, e.data); err != nil {
|
||||
return err
|
||||
}
|
||||
out = append(out, resp)
|
||||
}
|
||||
|
||||
fName := e.data.Table.Name + e.fileSuffix
|
||||
err := outHandler(e.state.Config.OutFolder, fName, e.state.Config.PkgName, imps, out)
|
||||
if err != nil {
|
||||
if err := writeFile(e.state.Config.OutFolder, fName, out); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -119,31 +125,27 @@ func executeSingletonTemplates(e executeTemplateData) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
rgxRemove := regexp.MustCompile(`[0-9]+_`)
|
||||
|
||||
out := templateByteBuffer
|
||||
for _, tplName := range e.templates.Templates() {
|
||||
resp, err := executeTemplate(e.templates.Template, tplName, e.data)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Error generating template %s", tplName)
|
||||
}
|
||||
out.Reset()
|
||||
|
||||
fName := tplName
|
||||
ext := filepath.Ext(fName)
|
||||
fName = rgxRemove.ReplaceAllString(fName[:len(fName)-len(ext)], "")
|
||||
fName = rgxRemoveNumberedPrefix.ReplaceAllString(fName[:len(fName)-len(ext)], "")
|
||||
|
||||
imps := imports{
|
||||
standard: e.importNamedSet[fName].standard,
|
||||
thirdParty: e.importNamedSet[fName].thirdParty,
|
||||
}
|
||||
|
||||
err = outHandler(
|
||||
e.state.Config.OutFolder,
|
||||
fName+e.fileSuffix,
|
||||
e.state.Config.PkgName,
|
||||
imps,
|
||||
[][]byte{resp},
|
||||
)
|
||||
if err != nil {
|
||||
writePackageName(out, e.state.Config.PkgName)
|
||||
writeImports(out, imps)
|
||||
|
||||
if err := executeTemplate(out, e.templates.Template, tplName, e.data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := writeFile(e.state.Config.OutFolder, fName+e.fileSuffix, out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -156,95 +158,94 @@ func generateTestMainOutput(state *State, data *templateData) error {
|
|||
return errors.New("No TestMain template located for generation")
|
||||
}
|
||||
|
||||
var out [][]byte
|
||||
var imps imports
|
||||
out := templateByteBuffer
|
||||
out.Reset()
|
||||
|
||||
var imps imports
|
||||
imps.standard = defaultTestMainImports[state.Config.DriverName].standard
|
||||
imps.thirdParty = defaultTestMainImports[state.Config.DriverName].thirdParty
|
||||
|
||||
resp, err := executeTemplate(state.TestMainTemplate, state.TestMainTemplate.Name(), data)
|
||||
if err != nil {
|
||||
writePackageName(out, state.Config.PkgName)
|
||||
writeImports(out, imps)
|
||||
|
||||
if err := executeTemplate(out, state.TestMainTemplate, state.TestMainTemplate.Name(), data); err != nil {
|
||||
return err
|
||||
}
|
||||
out = append(out, resp)
|
||||
|
||||
err = outHandler(state.Config.OutFolder, "main_test.go", state.Config.PkgName, imps, out)
|
||||
if err != nil {
|
||||
if err := writeFile(state.Config.OutFolder, "main_test.go", out); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func outHandler(outFolder string, fileName string, pkgName string, imps imports, contents [][]byte) error {
|
||||
out := testHarnessStdout
|
||||
// writePackageName writes the package name correctly, ignores errors
|
||||
// since it's to the concrete buffer type which produces none
|
||||
func writePackageName(out *bytes.Buffer, pkgName string) {
|
||||
_, _ = fmt.Fprintf(out, "package %s\n\n", pkgName)
|
||||
}
|
||||
|
||||
// writeImports writes the package imports correctly, ignores errors
|
||||
// since it's to the concrete buffer type which produces none
|
||||
func writeImports(out *bytes.Buffer, imps imports) {
|
||||
if impStr := buildImportString(imps); len(impStr) > 0 {
|
||||
_, _ = fmt.Fprintf(out, "%s\n", impStr)
|
||||
}
|
||||
}
|
||||
|
||||
// writeFile writes to the given folder and filename, formatting the buffer
|
||||
// given.
|
||||
func writeFile(outFolder string, fileName string, input *bytes.Buffer) error {
|
||||
byt, err := formatBuffer(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path := filepath.Join(outFolder, fileName)
|
||||
|
||||
outFile, err := testHarnessFileOpen(path)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Unable to create output file %s", path)
|
||||
}
|
||||
defer outFile.Close()
|
||||
out = outFile
|
||||
|
||||
if _, err := fmt.Fprintf(out, "package %s\n\n", pkgName); err != nil {
|
||||
return errors.Errorf("Unable to write package name %s to file: %s", pkgName, path)
|
||||
}
|
||||
|
||||
impStr := buildImportString(imps)
|
||||
if len(impStr) > 0 {
|
||||
if _, err := fmt.Fprintf(out, "%s\n", impStr); err != nil {
|
||||
return errors.Wrap(err, "Unable to write imports to file handle")
|
||||
}
|
||||
}
|
||||
|
||||
for _, templateOutput := range contents {
|
||||
if _, err := fmt.Fprintf(out, "%s\n", templateOutput); err != nil {
|
||||
return errors.Wrap(err, "Unable to write template output to file handle")
|
||||
}
|
||||
if err = testHarnessWriteFile(path, byt, 0666); err != nil {
|
||||
return errors.Wrapf(err, "failed to write output file %s", path)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxSyntaxError = regexp.MustCompile(`(\d+):\d+: `)
|
||||
|
||||
// executeTemplate takes a template and returns the output of the template
|
||||
// execution.
|
||||
func executeTemplate(t *template.Template, name string, data *templateData) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := t.ExecuteTemplate(&buf, name, data); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to execute template")
|
||||
func executeTemplate(buf *bytes.Buffer, t *template.Template, name string, data *templateData) error {
|
||||
if err := t.ExecuteTemplate(buf, name, data); err != nil {
|
||||
return errors.Wrapf(err, "failed to execute template: %s", name)
|
||||
}
|
||||
|
||||
output, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
matches := rgxSyntaxError.FindStringSubmatch(err.Error())
|
||||
if matches == nil {
|
||||
return nil, errors.Wrap(err, "failed to format template")
|
||||
}
|
||||
|
||||
lineNum, _ := strconv.Atoi(matches[1])
|
||||
scanner := bufio.NewScanner(&buf)
|
||||
errBuf := &bytes.Buffer{}
|
||||
line := 0
|
||||
for ; scanner.Scan(); line++ {
|
||||
if delta := line - lineNum; delta < -5 || delta > 5 {
|
||||
continue
|
||||
}
|
||||
|
||||
if line == lineNum {
|
||||
errBuf.WriteString(">>> ")
|
||||
} else {
|
||||
fmt.Fprintf(errBuf, "% 3d ", line)
|
||||
}
|
||||
errBuf.Write(scanner.Bytes())
|
||||
errBuf.WriteByte('\n')
|
||||
}
|
||||
|
||||
return nil, errors.Wrapf(err, "failed to format template\n\n%s\n", errBuf.Bytes())
|
||||
}
|
||||
|
||||
return output, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatBuffer(buf *bytes.Buffer) ([]byte, error) {
|
||||
output, err := format.Source(buf.Bytes())
|
||||
if err == nil {
|
||||
return output, nil
|
||||
}
|
||||
|
||||
matches := rgxSyntaxError.FindStringSubmatch(err.Error())
|
||||
if matches == nil {
|
||||
return nil, errors.Wrap(err, "failed to format template")
|
||||
}
|
||||
|
||||
lineNum, _ := strconv.Atoi(matches[1])
|
||||
scanner := bufio.NewScanner(buf)
|
||||
errBuf := &bytes.Buffer{}
|
||||
line := 1
|
||||
for ; scanner.Scan(); line++ {
|
||||
if delta := line - lineNum; delta < -5 || delta > 5 {
|
||||
continue
|
||||
}
|
||||
|
||||
if line == lineNum {
|
||||
errBuf.WriteString(">>>> ")
|
||||
} else {
|
||||
fmt.Fprintf(errBuf, "% 4d ", line)
|
||||
}
|
||||
errBuf.Write(scanner.Bytes())
|
||||
errBuf.WriteByte('\n')
|
||||
}
|
||||
|
||||
return nil, errors.Wrapf(err, "failed to format template\n\n%s\n", errBuf.Bytes())
|
||||
}
|
||||
|
|
125
output_test.go
125
output_test.go
|
@ -2,8 +2,10 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -19,120 +21,49 @@ func nopCloser(w io.Writer) io.WriteCloser {
|
|||
return NopWriteCloser{w}
|
||||
}
|
||||
|
||||
func TestOutHandler(t *testing.T) {
|
||||
func TestWriteFile(t *testing.T) {
|
||||
// t.Parallel() cannot be used
|
||||
|
||||
// set the function pointer back to its original value
|
||||
// after we modify it for the test
|
||||
saveTestHarnessFileOpen := testHarnessFileOpen
|
||||
saveTestHarnessWriteFile := testHarnessWriteFile
|
||||
defer func() {
|
||||
testHarnessFileOpen = saveTestHarnessFileOpen
|
||||
testHarnessWriteFile = saveTestHarnessWriteFile
|
||||
}()
|
||||
|
||||
var output []byte
|
||||
testHarnessWriteFile = func(_ string, in []byte, _ os.FileMode) error {
|
||||
output = in
|
||||
return nil
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
testHarnessFileOpen = func(path string) (io.WriteCloser, error) {
|
||||
return nopCloser(buf), nil
|
||||
}
|
||||
writePackageName(buf, "pkg")
|
||||
fmt.Fprintf(buf, "func hello() {}\n\n\nfunc world() {\nreturn\n}\n\n\n\n")
|
||||
|
||||
templateOutputs := [][]byte{[]byte("hello world"), []byte("patrick's dreams")}
|
||||
|
||||
if err := outHandler("", "file.go", "patrick", imports{}, templateOutputs); err != nil {
|
||||
if err := writeFile("", "", buf); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if out := buf.String(); out != "package patrick\n\nhello world\npatrick's dreams\n" {
|
||||
t.Errorf("Wrong output: %q", out)
|
||||
if string(output) != "package pkg\n\nfunc hello() {}\n\nfunc world() {\n\treturn\n}\n" {
|
||||
t.Errorf("Wrong output: %q", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOutHandlerFiles(t *testing.T) {
|
||||
// t.Parallel() cannot be used
|
||||
func TestFormatBuffer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
saveTestHarnessFileOpen := testHarnessFileOpen
|
||||
defer func() {
|
||||
testHarnessFileOpen = saveTestHarnessFileOpen
|
||||
}()
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
file := &bytes.Buffer{}
|
||||
testHarnessFileOpen = func(path string) (io.WriteCloser, error) {
|
||||
return nopCloser(file), nil
|
||||
fmt.Fprintf(buf, "package pkg\n\nfunc() {a}\n")
|
||||
|
||||
// Only test error case - happy case is taken care of by template test
|
||||
_, err := formatBuffer(buf)
|
||||
if err == nil {
|
||||
t.Error("want an error")
|
||||
}
|
||||
|
||||
templateOutputs := [][]byte{[]byte("hello world"), []byte("patrick's dreams")}
|
||||
|
||||
if err := outHandler("folder", "file.go", "patrick", imports{}, templateOutputs); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if out := file.String(); out != "package patrick\n\nhello world\npatrick's dreams\n" {
|
||||
t.Errorf("Wrong output: %q", out)
|
||||
}
|
||||
|
||||
a1 := imports{
|
||||
standard: importList{
|
||||
`"fmt"`,
|
||||
},
|
||||
}
|
||||
file = &bytes.Buffer{}
|
||||
|
||||
if err := outHandler("folder", "file.go", "patrick", a1, templateOutputs); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if out := file.String(); out != "package patrick\n\nimport \"fmt\"\nhello world\npatrick's dreams\n" {
|
||||
t.Errorf("Wrong output: %q", out)
|
||||
}
|
||||
|
||||
a2 := imports{
|
||||
thirdParty: []string{
|
||||
`"github.com/spf13/cobra"`,
|
||||
},
|
||||
}
|
||||
file = &bytes.Buffer{}
|
||||
|
||||
if err := outHandler("folder", "file.go", "patrick", a2, templateOutputs); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if out := file.String(); out != "package patrick\n\nimport \"github.com/spf13/cobra\"\nhello world\npatrick's dreams\n" {
|
||||
t.Errorf("Wrong output: %q", out)
|
||||
}
|
||||
|
||||
a3 := imports{
|
||||
standard: importList{
|
||||
`"fmt"`,
|
||||
`"errors"`,
|
||||
},
|
||||
thirdParty: importList{
|
||||
`_ "github.com/lib/pq"`,
|
||||
`_ "github.com/gorilla/n"`,
|
||||
`"github.com/gorilla/mux"`,
|
||||
`"github.com/gorilla/websocket"`,
|
||||
},
|
||||
}
|
||||
file = &bytes.Buffer{}
|
||||
|
||||
sort.Sort(a3.standard)
|
||||
sort.Sort(a3.thirdParty)
|
||||
|
||||
if err := outHandler("folder", "file.go", "patrick", a3, templateOutputs); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
expectedOut := `package patrick
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
_ "github.com/gorilla/n"
|
||||
"github.com/gorilla/websocket"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
hello world
|
||||
patrick's dreams
|
||||
`
|
||||
|
||||
if out := file.String(); out != expectedOut {
|
||||
t.Errorf("Wrong output (len %d, len %d): \n\n%q\n\n%q", len(out), len(expectedOut), out, expectedOut)
|
||||
if txt := err.Error(); !strings.Contains(txt, ">>>> func() {a}") {
|
||||
t.Error("got:\n", txt)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,7 +173,6 @@ var templateFunctions = template.FuncMap{
|
|||
|
||||
// dbdrivers ops
|
||||
"filterColumnsByDefault": bdb.FilterColumnsByDefault,
|
||||
"autoIncPrimaryKey": bdb.AutoIncPrimaryKey,
|
||||
"sqlColDefinitions": bdb.SQLColDefinitions,
|
||||
"columnNames": bdb.ColumnNames,
|
||||
"columnDBTypes": bdb.ColumnDBTypes,
|
||||
|
|
|
@ -4,17 +4,17 @@
|
|||
{{- $table := .Table -}}
|
||||
{{- range .Table.ToManyRelationships -}}
|
||||
{{- $varNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $rel := txtsFromToMany $dot.Tables $table . -}}
|
||||
{{- $schemaForeignTable := .ForeignTable | $dot.SchemaTable -}}
|
||||
// {{$rel.Function.Name}}G retrieves all the {{$rel.LocalTable.NameSingular}}'s {{$rel.ForeignTable.NameHumanReadable}}
|
||||
{{- if not (eq $rel.Function.Name $rel.ForeignTable.NamePluralGo)}} via {{.ForeignColumn}} column{{- end}}.
|
||||
func (o *{{$rel.LocalTable.NameGo}}) {{$rel.Function.Name}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query {
|
||||
return o.{{$rel.Function.Name}}(boil.GetDB(), mods...)
|
||||
{{- $txt := txtsFromToMany $dot.Tables $table . -}}
|
||||
{{- $schemaForeignTable := .ForeignTable | $dot.SchemaTable}}
|
||||
// {{$txt.Function.Name}}G retrieves all the {{.ForeignTable | singular}}'s {{$txt.ForeignTable.NameHumanReadable}}
|
||||
{{- if not (eq $txt.Function.Name $txt.ForeignTable.NamePluralGo)}} via {{.ForeignColumn}} column{{- end}}.
|
||||
func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query {
|
||||
return o.{{$txt.Function.Name}}(boil.GetDB(), mods...)
|
||||
}
|
||||
|
||||
// {{$rel.Function.Name}} retrieves all the {{$rel.LocalTable.NameSingular}}'s {{$rel.ForeignTable.NameHumanReadable}} with an executor
|
||||
{{- if not (eq $rel.Function.Name $rel.ForeignTable.NamePluralGo)}} via {{.ForeignColumn}} column{{- end}}.
|
||||
func (o *{{$rel.LocalTable.NameGo}}) {{$rel.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) {{$varNameSingular}}Query {
|
||||
// {{$txt.Function.Name}} retrieves all the {{.ForeignTable | singular}}'s {{$txt.ForeignTable.NameHumanReadable}} with an executor
|
||||
{{- if not (eq $txt.Function.Name $txt.ForeignTable.NamePluralGo)}} via {{.ForeignColumn}} column{{- end}}.
|
||||
func (o *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) {{$varNameSingular}}Query {
|
||||
queryMods := []qm.QueryMod{
|
||||
qm.Select("{{id 0 | $dot.Quotes}}.*"),
|
||||
}
|
||||
|
@ -26,15 +26,15 @@ func (o *{{$rel.LocalTable.NameGo}}) {{$rel.Function.Name}}(exec boil.Executor,
|
|||
{{if .ToJoinTable -}}
|
||||
queryMods = append(queryMods,
|
||||
qm.InnerJoin("{{.JoinTable | $dot.SchemaTable}} as {{id 1 | $dot.Quotes}} on {{id 0 | $dot.Quotes}}.{{.ForeignColumn | $dot.Quotes}} = {{id 1 | $dot.Quotes}}.{{.JoinForeignColumn | $dot.Quotes}}"),
|
||||
qm.Where("{{id 1 | $dot.Quotes}}.{{.JoinLocalColumn | $dot.Quotes}}={{if $dot.Dialect.IndexPlaceholders}}$1{{else}}?{{end}}", o.{{$rel.LocalTable.ColumnNameGo}}),
|
||||
qm.Where("{{id 1 | $dot.Quotes}}.{{.JoinLocalColumn | $dot.Quotes}}={{if $dot.Dialect.IndexPlaceholders}}$1{{else}}?{{end}}", o.{{$txt.LocalTable.ColumnNameGo}}),
|
||||
)
|
||||
{{else -}}
|
||||
queryMods = append(queryMods,
|
||||
qm.Where("{{id 0 | $dot.Quotes}}.{{.ForeignColumn | $dot.Quotes}}={{if $dot.Dialect.IndexPlaceholders}}$1{{else}}?{{end}}", o.{{$rel.LocalTable.ColumnNameGo}}),
|
||||
qm.Where("{{id 0 | $dot.Quotes}}.{{.ForeignColumn | $dot.Quotes}}={{if $dot.Dialect.IndexPlaceholders}}$1{{else}}?{{end}}", o.{{$txt.LocalTable.ColumnNameGo}}),
|
||||
)
|
||||
{{end}}
|
||||
|
||||
query := {{$rel.ForeignTable.NamePluralGo}}(exec, queryMods...)
|
||||
query := {{$txt.ForeignTable.NamePluralGo}}(exec, queryMods...)
|
||||
queries.SetFrom(query.Query, "{{$schemaForeignTable}} as {{id 0 | $dot.Quotes}}")
|
||||
return query
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
{{- /* Begin execution of template for many-to-one or many-to-many eager load */ -}}
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
{{- /* Begin execution of template for one-to-one setops */ -}}
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.FKeys -}}
|
||||
{{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $localNameSingular := .Table | singular | camelCase}}
|
||||
{{- $foreignNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase}}
|
||||
{{- $schemaTable := .Table | $dot.SchemaTable}}
|
||||
// Set{{$txt.Function.Name}} of the {{.Table | singular}} to the related item.
|
||||
// Sets o.R.{{$txt.Function.Name}} to related.
|
||||
// Adds o to related.R.{{$txt.Function.ForeignName}}.
|
||||
|
@ -17,21 +17,29 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo
|
|||
}
|
||||
}
|
||||
|
||||
oldVal := o.{{$txt.Function.LocalAssignment}}
|
||||
updateQuery := fmt.Sprintf(
|
||||
"UPDATE {{$schemaTable}} SET %s WHERE %s",
|
||||
strmangle.SetParamNames("{{$dot.LQ}}", "{{$dot.RQ}}", {{if $dot.Dialect.IndexPlaceholders}}1{{else}}0{{end}}, []string{{"{"}}"{{.Column}}"{{"}"}}),
|
||||
strmangle.WhereClause("{{$dot.LQ}}", "{{$dot.RQ}}", {{if $dot.Dialect.IndexPlaceholders}}2{{else}}0{{end}}, {{$varNameSingular}}PrimaryKeyColumns),
|
||||
)
|
||||
values := []interface{}{related.{{$txt.ForeignTable.ColumnNameGo}}, o.{{$dot.Table.PKey.Columns | stringMap $dot.StringFuncs.titleCase | join ", o."}}{{"}"}}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, updateQuery)
|
||||
fmt.Fprintln(boil.DebugWriter, values)
|
||||
}
|
||||
|
||||
if _, err = exec.Exec(updateQuery, values...); err != nil {
|
||||
return errors.Wrap(err, "failed to update local table")
|
||||
}
|
||||
|
||||
o.{{$txt.Function.LocalAssignment}} = related.{{$txt.Function.ForeignAssignment}}
|
||||
{{if .Nullable -}}
|
||||
o.{{$txt.LocalTable.ColumnNameGo}}.Valid = true
|
||||
{{- end}}
|
||||
if err = o.Update(exec, "{{.Column}}"); err != nil {
|
||||
o.{{$txt.Function.LocalAssignment}} = oldVal
|
||||
{{if .Nullable -}}
|
||||
o.{{$txt.LocalTable.ColumnNameGo}}.Valid = false
|
||||
{{- end}}
|
||||
return errors.Wrap(err, "failed to update local table")
|
||||
}
|
||||
|
||||
if o.R == nil {
|
||||
o.R = &{{$localNameSingular}}R{
|
||||
o.R = &{{$varNameSingular}}R{
|
||||
{{$txt.Function.Name}}: related,
|
||||
}
|
||||
} else {
|
||||
|
@ -40,7 +48,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo
|
|||
|
||||
{{if .Unique -}}
|
||||
if related.R == nil {
|
||||
related.R = &{{$varNameSingular}}R{
|
||||
related.R = &{{$foreignNameSingular}}R{
|
||||
{{$txt.Function.ForeignName}}: o,
|
||||
}
|
||||
} else {
|
||||
|
@ -48,7 +56,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo
|
|||
}
|
||||
{{else -}}
|
||||
if related.R == nil {
|
||||
related.R = &{{$varNameSingular}}R{
|
||||
related.R = &{{$foreignNameSingular}}R{
|
||||
{{$txt.Function.ForeignName}}: {{$txt.LocalTable.NameGo}}Slice{{"{"}}o{{"}"}},
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -3,40 +3,51 @@
|
|||
{{- $dot := . -}}
|
||||
{{- range .Table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $localNameSingular := .Table | singular | camelCase}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $foreignPKeyCols := (getTable $dot.Tables .ForeignTable).PKey.Columns -}}
|
||||
{{- $foreignSchemaTable := .ForeignTable | $dot.SchemaTable}}
|
||||
// Set{{$txt.Function.Name}} of the {{.Table | singular}} to the related item.
|
||||
// Sets o.R.{{$txt.Function.Name}} to related.
|
||||
// Adds o to related.R.{{$txt.Function.ForeignName}}.
|
||||
func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executor, insert bool, related *{{$txt.ForeignTable.NameGo}}) error {
|
||||
var err error
|
||||
|
||||
oldVal := related.{{$txt.Function.ForeignAssignment}}
|
||||
related.{{$txt.Function.ForeignAssignment}} = o.{{$txt.Function.LocalAssignment}}
|
||||
{{if .ForeignColumnNullable -}}
|
||||
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = true
|
||||
{{- end}}
|
||||
|
||||
if insert {
|
||||
related.{{$txt.Function.ForeignAssignment}} = o.{{$txt.Function.LocalAssignment}}
|
||||
{{if .ForeignColumnNullable -}}
|
||||
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = true
|
||||
{{- end}}
|
||||
|
||||
if err = related.Insert(exec); err != nil {
|
||||
related.{{$txt.Function.ForeignAssignment}} = oldVal
|
||||
{{if .ForeignColumnNullable -}}
|
||||
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = false
|
||||
{{- end}}
|
||||
return errors.Wrap(err, "failed to insert into foreign table")
|
||||
}
|
||||
} else {
|
||||
if err = related.Update(exec, "{{.ForeignColumn}}"); err != nil {
|
||||
related.{{$txt.Function.ForeignAssignment}} = oldVal
|
||||
{{if .ForeignColumnNullable -}}
|
||||
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = false
|
||||
{{- end}}
|
||||
updateQuery := fmt.Sprintf(
|
||||
"UPDATE {{$foreignSchemaTable}} SET %s WHERE %s",
|
||||
strmangle.SetParamNames("{{$dot.LQ}}", "{{$dot.RQ}}", {{if $dot.Dialect.IndexPlaceholders}}1{{else}}0{{end}}, []string{{"{"}}"{{.ForeignColumn}}"{{"}"}}),
|
||||
strmangle.WhereClause("{{$dot.LQ}}", "{{$dot.RQ}}", {{if $dot.Dialect.IndexPlaceholders}}2{{else}}0{{end}}, {{$foreignVarNameSingular}}PrimaryKeyColumns),
|
||||
)
|
||||
values := []interface{}{o.{{$txt.LocalTable.ColumnNameGo}}, related.{{$foreignPKeyCols | stringMap $dot.StringFuncs.titleCase | join ", related."}}{{"}"}}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, updateQuery)
|
||||
fmt.Fprintln(boil.DebugWriter, values)
|
||||
}
|
||||
|
||||
if _, err = exec.Exec(updateQuery, values...); err != nil {
|
||||
return errors.Wrap(err, "failed to update foreign table")
|
||||
}
|
||||
|
||||
related.{{$txt.Function.ForeignAssignment}} = o.{{$txt.Function.LocalAssignment}}
|
||||
{{if .ForeignColumnNullable -}}
|
||||
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = true
|
||||
{{- end}}
|
||||
}
|
||||
|
||||
|
||||
if o.R == nil {
|
||||
o.R = &{{$localNameSingular}}R{
|
||||
o.R = &{{$varNameSingular}}R{
|
||||
{{$txt.Function.Name}}: related,
|
||||
}
|
||||
} else {
|
||||
|
@ -44,7 +55,7 @@ func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executo
|
|||
}
|
||||
|
||||
if related.R == nil {
|
||||
related.R = &{{$varNameSingular}}R{
|
||||
related.R = &{{$foreignVarNameSingular}}R{
|
||||
{{$txt.Function.ForeignName}}: o,
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
{{- /* Begin execution of template for many-to-one or many-to-many setops */ -}}
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- $table := .Table -}}
|
||||
{{- range .Table.ToManyRelationships -}}
|
||||
{{- $rel := txtsFromToMany $dot.Tables $table . -}}
|
||||
{{- $txt := txtsFromToMany $dot.Tables $table . -}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase}}
|
||||
// Add{{$rel.Function.Name}} adds the given related objects to the existing relationships
|
||||
// Add{{$txt.Function.Name}} adds the given related objects to the existing relationships
|
||||
// of the {{$table.Name | singular}}, optionally inserting them as new records.
|
||||
// Appends related to o.R.{{$rel.Function.Name}}.
|
||||
// Sets related.R.{{$rel.Function.ForeignName}} appropriately.
|
||||
func (o *{{$rel.LocalTable.NameGo}}) Add{{$rel.Function.Name}}(exec boil.Executor, insert bool, related ...*{{$rel.ForeignTable.NameGo}}) error {
|
||||
// Appends related to o.R.{{$txt.Function.Name}}.
|
||||
// Sets related.R.{{$txt.Function.ForeignName}} appropriately.
|
||||
func (o *{{$txt.LocalTable.NameGo}}) Add{{$txt.Function.Name}}(exec boil.Executor, insert bool, related ...*{{$txt.ForeignTable.NameGo}}) error {
|
||||
var err error
|
||||
for _, rel := range related {
|
||||
{{if not .ToJoinTable -}}
|
||||
rel.{{$rel.Function.ForeignAssignment}} = o.{{$rel.Function.LocalAssignment}}
|
||||
rel.{{$txt.Function.ForeignAssignment}} = o.{{$txt.Function.LocalAssignment}}
|
||||
{{if .ForeignColumnNullable -}}
|
||||
rel.{{$rel.ForeignTable.ColumnNameGo}}.Valid = true
|
||||
rel.{{$txt.ForeignTable.ColumnNameGo}}.Valid = true
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
if insert {
|
||||
|
@ -34,7 +33,7 @@ func (o *{{$rel.LocalTable.NameGo}}) Add{{$rel.Function.Name}}(exec boil.Executo
|
|||
{{if .ToJoinTable -}}
|
||||
for _, rel := range related {
|
||||
query := "insert into {{.JoinTable | $dot.SchemaTable}} ({{.JoinLocalColumn | $dot.Quotes}}, {{.JoinForeignColumn | $dot.Quotes}}) values {{if $dot.Dialect.IndexPlaceholders}}($1, $2){{else}}(?, ?){{end}}"
|
||||
values := []interface{}{{"{"}}o.{{$rel.LocalTable.ColumnNameGo}}, rel.{{$rel.ForeignTable.ColumnNameGo}}}
|
||||
values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}, rel.{{$txt.ForeignTable.ColumnNameGo}}}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, query)
|
||||
|
@ -50,30 +49,30 @@ func (o *{{$rel.LocalTable.NameGo}}) Add{{$rel.Function.Name}}(exec boil.Executo
|
|||
|
||||
if o.R == nil {
|
||||
o.R = &{{$varNameSingular}}R{
|
||||
{{$rel.Function.Name}}: related,
|
||||
{{$txt.Function.Name}}: related,
|
||||
}
|
||||
} else {
|
||||
o.R.{{$rel.Function.Name}} = append(o.R.{{$rel.Function.Name}}, related...)
|
||||
o.R.{{$txt.Function.Name}} = append(o.R.{{$txt.Function.Name}}, related...)
|
||||
}
|
||||
|
||||
{{if .ToJoinTable -}}
|
||||
for _, rel := range related {
|
||||
if rel.R == nil {
|
||||
rel.R = &{{$foreignVarNameSingular}}R{
|
||||
{{$rel.Function.ForeignName}}: {{$rel.LocalTable.NameGo}}Slice{{"{"}}o{{"}"}},
|
||||
{{$txt.Function.ForeignName}}: {{$txt.LocalTable.NameGo}}Slice{{"{"}}o{{"}"}},
|
||||
}
|
||||
} else {
|
||||
rel.R.{{$rel.Function.ForeignName}} = append(rel.R.{{$rel.Function.ForeignName}}, o)
|
||||
rel.R.{{$txt.Function.ForeignName}} = append(rel.R.{{$txt.Function.ForeignName}}, o)
|
||||
}
|
||||
}
|
||||
{{else -}}
|
||||
for _, rel := range related {
|
||||
if rel.R == nil {
|
||||
rel.R = &{{$foreignVarNameSingular}}R{
|
||||
{{$rel.Function.ForeignName}}: o,
|
||||
{{$txt.Function.ForeignName}}: o,
|
||||
}
|
||||
} else {
|
||||
rel.R.{{$rel.Function.ForeignName}} = o
|
||||
rel.R.{{$txt.Function.ForeignName}} = o
|
||||
}
|
||||
}
|
||||
{{end -}}
|
||||
|
@ -82,19 +81,19 @@ func (o *{{$rel.LocalTable.NameGo}}) Add{{$rel.Function.Name}}(exec boil.Executo
|
|||
}
|
||||
|
||||
{{- if (or .ForeignColumnNullable .ToJoinTable)}}
|
||||
// Set{{$rel.Function.Name}} removes all previously related items of the
|
||||
// Set{{$txt.Function.Name}} removes all previously related items of the
|
||||
// {{$table.Name | singular}} replacing them completely with the passed
|
||||
// in related items, optionally inserting them as new records.
|
||||
// Sets o.R.{{$rel.Function.ForeignName}}'s {{$rel.Function.Name}} accordingly.
|
||||
// Replaces o.R.{{$rel.Function.Name}} with related.
|
||||
// Sets related.R.{{$rel.Function.ForeignName}}'s {{$rel.Function.Name}} accordingly.
|
||||
func (o *{{$rel.LocalTable.NameGo}}) Set{{$rel.Function.Name}}(exec boil.Executor, insert bool, related ...*{{$rel.ForeignTable.NameGo}}) error {
|
||||
// Sets o.R.{{$txt.Function.ForeignName}}'s {{$txt.Function.Name}} accordingly.
|
||||
// Replaces o.R.{{$txt.Function.Name}} with related.
|
||||
// Sets related.R.{{$txt.Function.ForeignName}}'s {{$txt.Function.Name}} accordingly.
|
||||
func (o *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executor, insert bool, related ...*{{$txt.ForeignTable.NameGo}}) error {
|
||||
{{if .ToJoinTable -}}
|
||||
query := "delete from {{.JoinTable | $dot.SchemaTable}} where {{.JoinLocalColumn | $dot.Quotes}} = {{if $dot.Dialect.IndexPlaceholders}}$1{{else}}?{{end}}"
|
||||
values := []interface{}{{"{"}}o.{{$rel.LocalTable.ColumnNameGo}}}
|
||||
values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}}
|
||||
{{else -}}
|
||||
query := "update {{.ForeignTable | $dot.SchemaTable}} set {{.ForeignColumn | $dot.Quotes}} = null where {{.ForeignColumn | $dot.Quotes}} = {{if $dot.Dialect.IndexPlaceholders}}$1{{else}}?{{end}}"
|
||||
values := []interface{}{{"{"}}o.{{$rel.LocalTable.ColumnNameGo}}}
|
||||
values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}}
|
||||
{{end -}}
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, query)
|
||||
|
@ -107,37 +106,37 @@ func (o *{{$rel.LocalTable.NameGo}}) Set{{$rel.Function.Name}}(exec boil.Executo
|
|||
}
|
||||
|
||||
{{if .ToJoinTable -}}
|
||||
remove{{$rel.LocalTable.NameGo}}From{{$rel.ForeignTable.NameGo}}Slice(o, related)
|
||||
o.R.{{$rel.Function.Name}} = nil
|
||||
remove{{$txt.Function.Name}}From{{$txt.Function.ForeignName}}Slice(o, related)
|
||||
o.R.{{$txt.Function.Name}} = nil
|
||||
{{else -}}
|
||||
if o.R != nil {
|
||||
for _, rel := range o.R.{{$rel.Function.Name}} {
|
||||
rel.{{$rel.ForeignTable.ColumnNameGo}}.Valid = false
|
||||
for _, rel := range o.R.{{$txt.Function.Name}} {
|
||||
rel.{{$txt.ForeignTable.ColumnNameGo}}.Valid = false
|
||||
if rel.R == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
rel.R.{{$rel.Function.ForeignName}} = nil
|
||||
rel.R.{{$txt.Function.ForeignName}} = nil
|
||||
}
|
||||
|
||||
o.R.{{$rel.Function.Name}} = nil
|
||||
o.R.{{$txt.Function.Name}} = nil
|
||||
}
|
||||
{{end -}}
|
||||
|
||||
return o.Add{{$rel.Function.Name}}(exec, insert, related...)
|
||||
return o.Add{{$txt.Function.Name}}(exec, insert, related...)
|
||||
}
|
||||
|
||||
// Remove{{$rel.Function.Name}} relationships from objects passed in.
|
||||
// Removes related items from R.{{$rel.Function.Name}} (uses pointer comparison, removal does not keep order)
|
||||
// Sets related.R.{{$rel.Function.ForeignName}}.
|
||||
func (o *{{$rel.LocalTable.NameGo}}) Remove{{$rel.Function.Name}}(exec boil.Executor, related ...*{{$rel.ForeignTable.NameGo}}) error {
|
||||
// Remove{{$txt.Function.Name}} relationships from objects passed in.
|
||||
// Removes related items from R.{{$txt.Function.Name}} (uses pointer comparison, removal does not keep order)
|
||||
// Sets related.R.{{$txt.Function.ForeignName}}.
|
||||
func (o *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Executor, related ...*{{$txt.ForeignTable.NameGo}}) error {
|
||||
var err error
|
||||
{{if .ToJoinTable -}}
|
||||
query := fmt.Sprintf(
|
||||
"delete from {{.JoinTable | $dot.SchemaTable}} where {{.JoinLocalColumn | $dot.Quotes}} = {{if $dot.Dialect.IndexPlaceholders}}$1{{else}}?{{end}} and {{.JoinForeignColumn | $dot.Quotes}} in (%s)",
|
||||
strmangle.Placeholders(dialect.IndexPlaceholders, len(related), 1, 1),
|
||||
)
|
||||
values := []interface{}{{"{"}}o.{{$rel.LocalTable.ColumnNameGo}}}
|
||||
values := []interface{}{{"{"}}o.{{$txt.LocalTable.ColumnNameGo}}}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, query)
|
||||
|
@ -150,10 +149,10 @@ func (o *{{$rel.LocalTable.NameGo}}) Remove{{$rel.Function.Name}}(exec boil.Exec
|
|||
}
|
||||
{{else -}}
|
||||
for _, rel := range related {
|
||||
rel.{{$rel.ForeignTable.ColumnNameGo}}.Valid = false
|
||||
rel.{{$txt.ForeignTable.ColumnNameGo}}.Valid = false
|
||||
{{if not .ToJoinTable -}}
|
||||
if rel.R != nil {
|
||||
rel.R.{{$rel.Function.ForeignName}} = nil
|
||||
rel.R.{{$txt.Function.ForeignName}} = nil
|
||||
}
|
||||
{{end -}}
|
||||
if err = rel.Update(exec, "{{.ForeignColumn}}"); err != nil {
|
||||
|
@ -163,23 +162,23 @@ func (o *{{$rel.LocalTable.NameGo}}) Remove{{$rel.Function.Name}}(exec boil.Exec
|
|||
{{end -}}
|
||||
|
||||
{{if .ToJoinTable -}}
|
||||
remove{{$rel.LocalTable.NameGo}}From{{$rel.ForeignTable.NameGo}}Slice(o, related)
|
||||
remove{{$txt.Function.Name}}From{{$txt.Function.ForeignName}}Slice(o, related)
|
||||
{{end -}}
|
||||
if o.R == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, rel := range related {
|
||||
for i, ri := range o.R.{{$rel.Function.Name}} {
|
||||
for i, ri := range o.R.{{$txt.Function.Name}} {
|
||||
if rel != ri {
|
||||
continue
|
||||
}
|
||||
|
||||
ln := len(o.R.{{$rel.Function.Name}})
|
||||
ln := len(o.R.{{$txt.Function.Name}})
|
||||
if ln > 1 && i < ln-1 {
|
||||
o.R.{{$rel.Function.Name}}[i] = o.R.{{$rel.Function.Name}}[ln-1]
|
||||
o.R.{{$txt.Function.Name}}[i] = o.R.{{$txt.Function.Name}}[ln-1]
|
||||
}
|
||||
o.R.{{$rel.Function.Name}} = o.R.{{$rel.Function.Name}}[:ln-1]
|
||||
o.R.{{$txt.Function.Name}} = o.R.{{$txt.Function.Name}}[:ln-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -188,25 +187,25 @@ func (o *{{$rel.LocalTable.NameGo}}) Remove{{$rel.Function.Name}}(exec boil.Exec
|
|||
}
|
||||
|
||||
{{if .ToJoinTable -}}
|
||||
func remove{{$rel.LocalTable.NameGo}}From{{$rel.ForeignTable.NameGo}}Slice(o *{{$rel.LocalTable.NameGo}}, related []*{{$rel.ForeignTable.NameGo}}) {
|
||||
func remove{{$txt.Function.Name}}From{{$txt.Function.ForeignName}}Slice(o *{{$txt.LocalTable.NameGo}}, related []*{{$txt.ForeignTable.NameGo}}) {
|
||||
for _, rel := range related {
|
||||
if rel.R == nil {
|
||||
continue
|
||||
}
|
||||
for i, ri := range rel.R.{{$rel.Function.ForeignName}} {
|
||||
{{if $rel.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(o.{{$rel.Function.LocalAssignment}}, ri.{{$rel.Function.LocalAssignment}}) {
|
||||
for i, ri := range rel.R.{{$txt.Function.ForeignName}} {
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(o.{{$txt.Function.LocalAssignment}}, ri.{{$txt.Function.LocalAssignment}}) {
|
||||
{{else -}}
|
||||
if o.{{$rel.Function.LocalAssignment}} != ri.{{$rel.Function.LocalAssignment}} {
|
||||
if o.{{$txt.Function.LocalAssignment}} != ri.{{$txt.Function.LocalAssignment}} {
|
||||
{{end -}}
|
||||
continue
|
||||
}
|
||||
|
||||
ln := len(rel.R.{{$rel.Function.ForeignName}})
|
||||
ln := len(rel.R.{{$txt.Function.ForeignName}})
|
||||
if ln > 1 && i < ln-1 {
|
||||
rel.R.{{$rel.Function.ForeignName}}[i] = rel.R.{{$rel.Function.ForeignName}}[ln-1]
|
||||
rel.R.{{$txt.Function.ForeignName}}[i] = rel.R.{{$txt.Function.ForeignName}}[ln-1]
|
||||
}
|
||||
rel.R.{{$rel.Function.ForeignName}} = rel.R.{{$rel.Function.ForeignName}}[:ln-1]
|
||||
rel.R.{{$txt.Function.ForeignName}} = rel.R.{{$txt.Function.ForeignName}}[:ln-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{{- $tableNamePlural := .Table.Name | plural | titleCase -}}
|
||||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
{{- $varNameSingular := .Table.Name | singular | camelCase}}
|
||||
// {{$tableNamePlural}}G retrieves all records.
|
||||
func {{$tableNamePlural}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query {
|
||||
return {{$tableNamePlural}}(boil.GetDB(), mods...)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
{{- $colDefs := sqlColDefinitions .Table.Columns .Table.PKey.Columns -}}
|
||||
{{- $pkNames := $colDefs.Names | stringMap .StringFuncs.camelCase -}}
|
||||
{{- $pkArgs := joinSlices " " $pkNames $colDefs.Types | join ", " -}}
|
||||
{{- $pkArgs := joinSlices " " $pkNames $colDefs.Types | join ", "}}
|
||||
// Find{{$tableNameSingular}}G retrieves a single record by ID.
|
||||
func Find{{$tableNameSingular}}G({{$pkArgs}}, selectCols ...string) (*{{$tableNameSingular}}, error) {
|
||||
return Find{{$tableNameSingular}}(boil.GetDB(), {{$pkNames | join ", "}}, selectCols...)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{- $tableNameSingular := .Table.Name | singular | titleCase -}}
|
||||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable}}
|
||||
// InsertG a single record. See Insert for whitelist behavior description.
|
||||
func (o *{{$tableNameSingular}}) InsertG(whitelist ... string) error {
|
||||
return o.Insert(boil.GetDB(), whitelist...)
|
||||
|
@ -78,56 +78,61 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
|||
|
||||
value := reflect.Indirect(reflect.ValueOf(o))
|
||||
vals := queries.ValuesFromMapping(value, cache.valueMapping)
|
||||
{{if .UseLastInsertID}}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.query)
|
||||
fmt.Fprintln(boil.DebugWriter, vals)
|
||||
}
|
||||
|
||||
{{if .UseLastInsertID -}}
|
||||
{{- $canLastInsertID := .Table.CanLastInsertID -}}
|
||||
{{if $canLastInsertID -}}
|
||||
result, err := exec.Exec(cache.query, vals...)
|
||||
{{else -}}
|
||||
_, err = exec.Exec(cache.query, vals...)
|
||||
{{- end}}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to insert into {{.Table.Name}}")
|
||||
}
|
||||
|
||||
var lastID int64
|
||||
{{if $canLastInsertID -}}
|
||||
var lastID int64
|
||||
{{- end}}
|
||||
var identifierCols []interface{}
|
||||
|
||||
if len(cache.retMapping) == 0 {
|
||||
goto CacheNoHooks
|
||||
}
|
||||
|
||||
{{if $canLastInsertID -}}
|
||||
lastID, err = result.LastInsertId()
|
||||
if err != nil {
|
||||
return ErrSyncFail
|
||||
}
|
||||
|
||||
{{- $colName := index .Table.PKey.Columns 0 -}}
|
||||
|
||||
{{$colName := index .Table.PKey.Columns 0 -}}
|
||||
{{- $col := .Table.GetColumn $colName -}}
|
||||
{{- $colTitled := $colName | singular | titleCase}}
|
||||
{{if eq 1 (len .Table.PKey.Columns)}}
|
||||
{{$cnames := .Table.Columns | filterColumnsByDefault true | columnNames}}
|
||||
{{if setInclude $colName $cnames}}
|
||||
{{- $colTitled := $colName | titleCase}}
|
||||
o.{{$colTitled}} = {{$col.Type}}(lastID)
|
||||
identifierCols = []interface{}{lastID}
|
||||
{{end}}
|
||||
{{else}}
|
||||
if lastID != 0 && len(cache.retMapping) == 1 && cache.retMapping[0] == {{$varNameSingular}}Mapping["{{$colTitled}}"] {
|
||||
goto CacheNoHooks
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
identifierCols = []interface{}{
|
||||
{{range .Table.PKey.Columns -}}
|
||||
o.{{. | singular | titleCase}},
|
||||
o.{{. | titleCase}},
|
||||
{{end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
if lastID == 0 || len(cache.retMapping) != 1 || cache.retMapping[0] == {{$varNameSingular}}Mapping["{{$colTitled}}"] {
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.retQuery)
|
||||
fmt.Fprintln(boil.DebugWriter, identifierCols...)
|
||||
}
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.retQuery)
|
||||
fmt.Fprintln(boil.DebugWriter, identifierCols...)
|
||||
}
|
||||
|
||||
err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to populate default values for {{.Table.Name}}")
|
||||
}
|
||||
err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to populate default values for {{.Table.Name}}")
|
||||
}
|
||||
{{else}}
|
||||
if len(cache.retMapping) != 0 {
|
||||
|
@ -136,15 +141,11 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
|||
_, err = exec.Exec(cache.query, vals...)
|
||||
}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.query)
|
||||
fmt.Fprintln(boil.DebugWriter, vals)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to insert into {{.Table.Name}}")
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .UseLastInsertID -}}
|
||||
CacheNoHooks:
|
||||
{{- end}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{- $tableNameSingular := .Table.Name | singular | titleCase -}}
|
||||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable}}
|
||||
// UpdateG a single {{$tableNameSingular}} record. See Update for
|
||||
// whitelist behavior description.
|
||||
func (o *{{$tableNameSingular}}) UpdateG(whitelist ...string) error {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{- $tableNameSingular := .Table.Name | singular | titleCase -}}
|
||||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable}}
|
||||
// UpsertG attempts an insert, and does an update or ignore on conflict.
|
||||
func (o *{{$tableNameSingular}}) UpsertG({{if ne .DriverName "mysql"}}updateOnConflict bool, conflictColumns []string, {{end}}updateColumns []string, whitelist ...string) error {
|
||||
return o.Upsert(boil.GetDB(), {{if ne .DriverName "mysql"}}updateOnConflict, conflictColumns, {{end}}updateColumns, whitelist...)
|
||||
|
@ -117,7 +117,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if ne .DriverName
|
|||
}
|
||||
|
||||
value := reflect.Indirect(reflect.ValueOf(o))
|
||||
values := queries.ValuesFromMapping(value, cache.valueMapping)
|
||||
vals := queries.ValuesFromMapping(value, cache.valueMapping)
|
||||
var returns []interface{}
|
||||
if len(cache.retMapping) != 0 {
|
||||
returns = queries.PtrsFromMapping(value, cache.retMapping)
|
||||
|
@ -125,59 +125,64 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if ne .DriverName
|
|||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.query)
|
||||
fmt.Fprintln(boil.DebugWriter, values)
|
||||
fmt.Fprintln(boil.DebugWriter, vals)
|
||||
}
|
||||
|
||||
{{- if .UseLastInsertID}}
|
||||
result, err := exec.Exec(cache.query, values...)
|
||||
{{if .UseLastInsertID -}}
|
||||
{{- $canLastInsertID := .Table.CanLastInsertID -}}
|
||||
{{if $canLastInsertID -}}
|
||||
result, err := exec.Exec(cache.query, vals...)
|
||||
{{else -}}
|
||||
_, err = exec.Exec(cache.query, vals...)
|
||||
{{- end}}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to upsert for {{.Table.Name}}")
|
||||
}
|
||||
|
||||
{{if $canLastInsertID -}}
|
||||
var lastID int64
|
||||
{{- end}}
|
||||
var identifierCols []interface{}
|
||||
|
||||
if len(cache.retMapping) == 0 {
|
||||
goto CacheNoHooks
|
||||
}
|
||||
|
||||
{{if $canLastInsertID -}}
|
||||
lastID, err = result.LastInsertId()
|
||||
if err != nil {
|
||||
return ErrSyncFail
|
||||
}
|
||||
|
||||
{{- $colName := index .Table.PKey.Columns 0 -}}
|
||||
{{$colName := index .Table.PKey.Columns 0 -}}
|
||||
{{- $col := .Table.GetColumn $colName -}}
|
||||
{{- $colTitled := $colName | singular | titleCase}}
|
||||
{{if eq 1 (len .Table.PKey.Columns)}}
|
||||
{{$cnames := .Table.Columns | filterColumnsByDefault true | columnNames}}
|
||||
{{if setInclude $colName $cnames}}
|
||||
{{- $colTitled := $colName | titleCase}}
|
||||
o.{{$colTitled}} = {{$col.Type}}(lastID)
|
||||
identifierCols = []interface{}{lastID}
|
||||
{{end}}
|
||||
{{else}}
|
||||
if lastID != 0 && len(cache.retMapping) == 1 && cache.retMapping[0] == {{$varNameSingular}}Mapping["{{$colTitled}}"] {
|
||||
goto CacheNoHooks
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
identifierCols = []interface{}{
|
||||
{{range .Table.PKey.Columns -}}
|
||||
o.{{. | singular | titleCase}},
|
||||
o.{{. | titleCase}},
|
||||
{{end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
if lastID == 0 || len(cache.retMapping) != 1 || cache.retMapping[0] == {{$varNameSingular}}Mapping["{{$colTitled}}"] {
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.retQuery)
|
||||
fmt.Fprintln(boil.DebugWriter, identifierCols...)
|
||||
}
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.retQuery)
|
||||
fmt.Fprintln(boil.DebugWriter, identifierCols...)
|
||||
}
|
||||
|
||||
err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(returns...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to populate default values for {{.Table.Name}}")
|
||||
}
|
||||
err = exec.QueryRow(cache.retQuery, identifierCols...).Scan(returns...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to populate default values for {{.Table.Name}}")
|
||||
}
|
||||
{{- else}}
|
||||
if len(cache.retMapping) != 0 {
|
||||
err = exec.QueryRow(cache.query, values...).Scan(returns...)
|
||||
err = exec.QueryRow(cache.query, vals...).Scan(returns...)
|
||||
} else {
|
||||
_, err = exec.Exec(cache.query, values...)
|
||||
_, err = exec.Exec(cache.query, vals...)
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to upsert for {{.Table.Name}}")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{- $tableNameSingular := .Table.Name | singular | titleCase -}}
|
||||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable}}
|
||||
// DeleteP deletes a single {{$tableNameSingular}} record with an executor.
|
||||
// DeleteP will match against the primary key column to find the record to delete.
|
||||
// Panics on error.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{- $tableNameSingular := .Table.Name | singular | titleCase -}}
|
||||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
{{- $varNamePlural := .Table.Name | plural | camelCase -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable}}
|
||||
// ReloadGP refetches the object from the database and panics on error.
|
||||
func (o *{{$tableNameSingular}}) ReloadGP() {
|
||||
if err := o.ReloadG(); err != nil {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{{- $colDefs := sqlColDefinitions .Table.Columns .Table.PKey.Columns -}}
|
||||
{{- $pkNames := $colDefs.Names | stringMap .StringFuncs.camelCase -}}
|
||||
{{- $pkArgs := joinSlices " " $pkNames $colDefs.Types | join ", " -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable -}}
|
||||
{{- $schemaTable := .Table.Name | .SchemaTable}}
|
||||
// {{$tableNameSingular}}Exists checks if the {{$tableNameSingular}} row exists.
|
||||
func {{$tableNameSingular}}Exists(exec boil.Executor, {{$pkArgs}}) (bool, error) {
|
||||
var exists bool
|
||||
|
|
|
@ -101,7 +101,7 @@ func (p *pgTester) pgEnv() []string {
|
|||
fmt.Sprintf("PGHOST=%s", p.host),
|
||||
fmt.Sprintf("PGPORT=%d", p.port),
|
||||
fmt.Sprintf("PGUSER=%s", p.user),
|
||||
fmt.Sprintf("PGPASS=%s", p.pgPassFile),
|
||||
fmt.Sprintf("PGPASSFILE=%s", p.pgPassFile),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,12 @@ func (p *pgTester) makePGPassFile() error {
|
|||
return errors.Wrap(err, "failed to create option file")
|
||||
}
|
||||
|
||||
fmt.Fprintf(tmp, "%s:%d:postgres:%s", p.host, p.port, p.user)
|
||||
if len(p.pass) != 0 {
|
||||
fmt.Fprintf(tmp, ":%s", p.pass)
|
||||
}
|
||||
fmt.Fprintln(tmp)
|
||||
|
||||
fmt.Fprintf(tmp, "%s:%d:%s:%s", p.host, p.port, p.dbName, p.user)
|
||||
if len(p.pass) != 0 {
|
||||
fmt.Fprintf(tmp, ":%s", p.pass)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{{- range .Table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase}}
|
||||
func test{{$txt.LocalTable.NameGo}}OneToOne{{$txt.ForeignTable.NameGo}}Using{{$txt.Function.Name}}(t *testing.T) {
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
@ -65,5 +65,6 @@ func test{{$txt.LocalTable.NameGo}}OneToOne{{$txt.ForeignTable.NameGo}}Using{{$t
|
|||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
}
|
||||
|
||||
{{end -}}{{/* range */}}
|
||||
{{- end -}}{{/* join table */}}
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
{{- range .Table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $dot.Table .}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $foreignPKeyCols := (getTable $dot.Tables .ForeignTable).PKey.Columns}}
|
||||
func test{{$txt.LocalTable.NameGo}}OneToOneSetOp{{$txt.ForeignTable.NameGo}}Using{{$txt.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
|
||||
|
@ -53,12 +54,20 @@ func test{{$txt.LocalTable.NameGo}}OneToOneSetOp{{$txt.ForeignTable.NameGo}}Usin
|
|||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}})
|
||||
}
|
||||
|
||||
{{if setInclude .ForeignColumn $foreignPKeyCols -}}
|
||||
if exists, err := {{$txt.ForeignTable.NameGo}}Exists(tx, x.{{$foreignPKeyCols | stringMap $dot.StringFuncs.titleCase | join ", x."}}); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !exists {
|
||||
t.Error("want 'x' to exist")
|
||||
}
|
||||
{{else -}}
|
||||
zero := reflect.Zero(reflect.TypeOf(x.{{$txt.Function.ForeignAssignment}}))
|
||||
reflect.Indirect(reflect.ValueOf(&x.{{$txt.Function.ForeignAssignment}})).Set(zero)
|
||||
|
||||
if err = x.Reload(tx); err != nil {
|
||||
t.Fatal("failed to reload", err)
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$txt.Function.LocalAssignment}}, x.{{$txt.Function.ForeignAssignment}}) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
{{- range .Table.ToManyRelationships -}}
|
||||
{{- $txt := txtsFromToMany $dot.Tables $table .}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
func test{{$txt.LocalTable.NameGo}}ToMany{{$txt.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
tx := MustTx(boil.Begin())
|
||||
|
@ -22,8 +23,8 @@ func test{{$txt.LocalTable.NameGo}}ToMany{{$txt.Function.Name}}(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
randomize.Struct(seed, &b, {{$txt.ForeignTable.NameSingular | camelCase}}DBTypes, false{{if not $txt.Function.UsesBytes}}, "{{.ForeignColumn}}"{{end}})
|
||||
randomize.Struct(seed, &c, {{$txt.ForeignTable.NameSingular | camelCase}}DBTypes, false{{if not $txt.Function.UsesBytes}}, "{{.ForeignColumn}}"{{end}})
|
||||
randomize.Struct(seed, &b, {{$foreignVarNameSingular}}DBTypes, false, {{$foreignVarNameSingular}}ColumnsWithDefault...)
|
||||
randomize.Struct(seed, &c, {{$foreignVarNameSingular}}DBTypes, false, {{$foreignVarNameSingular}}ColumnsWithDefault...)
|
||||
{{if .Nullable -}}
|
||||
a.{{.Column | titleCase}}.Valid = true
|
||||
{{- end}}
|
||||
|
|
|
@ -5,21 +5,21 @@
|
|||
{{- range .Table.ToManyRelationships -}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $rel := txtsFromToMany $dot.Tables $table .}}
|
||||
func test{{$rel.LocalTable.NameGo}}ToManyAddOp{{$rel.Function.Name}}(t *testing.T) {
|
||||
{{- $txt := txtsFromToMany $dot.Tables $table .}}
|
||||
func test{{$txt.LocalTable.NameGo}}ToManyAddOp{{$txt.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var a {{$rel.LocalTable.NameGo}}
|
||||
var b, c, d, e {{$rel.ForeignTable.NameGo}}
|
||||
var a {{$txt.LocalTable.NameGo}}
|
||||
var b, c, d, e {{$txt.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
foreigners := []*{{$rel.ForeignTable.NameGo}}{&b, &c, &d, &e}
|
||||
foreigners := []*{{$txt.ForeignTable.NameGo}}{&b, &c, &d, &e}
|
||||
for _, x := range foreigners {
|
||||
if err = randomize.Struct(seed, x, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -36,13 +36,13 @@ func test{{$rel.LocalTable.NameGo}}ToManyAddOp{{$rel.Function.Name}}(t *testing.
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
foreignersSplitByInsertion := [][]*{{$rel.ForeignTable.NameGo}}{
|
||||
foreignersSplitByInsertion := [][]*{{$txt.ForeignTable.NameGo}}{
|
||||
{&b, &c},
|
||||
{&d, &e},
|
||||
}
|
||||
|
||||
for i, x := range foreignersSplitByInsertion {
|
||||
err = a.Add{{$rel.Function.Name}}(tx, i != 0, x...)
|
||||
err = a.Add{{$txt.Function.Name}}(tx, i != 0, x...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -51,46 +51,46 @@ func test{{$rel.LocalTable.NameGo}}ToManyAddOp{{$rel.Function.Name}}(t *testing.
|
|||
second := x[1]
|
||||
{{- if .ToJoinTable}}
|
||||
|
||||
if first.R.{{$rel.Function.ForeignName}}[0] != &a {
|
||||
if first.R.{{$txt.Function.ForeignName}}[0] != &a {
|
||||
t.Error("relationship was not added properly to the slice")
|
||||
}
|
||||
if second.R.{{$rel.Function.ForeignName}}[0] != &a {
|
||||
if second.R.{{$txt.Function.ForeignName}}[0] != &a {
|
||||
t.Error("relationship was not added properly to the slice")
|
||||
}
|
||||
{{- else}}
|
||||
|
||||
{{if $rel.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$rel.Function.LocalAssignment}}, first.{{$rel.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, first.{{$rel.Function.ForeignAssignment}})
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$txt.Function.LocalAssignment}}, first.{{$txt.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, first.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
if 0 != bytes.Compare(a.{{$rel.Function.LocalAssignment}}, second.{{$rel.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, second.{{$rel.Function.ForeignAssignment}})
|
||||
if 0 != bytes.Compare(a.{{$txt.Function.LocalAssignment}}, second.{{$txt.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, second.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
{{else -}}
|
||||
if a.{{$rel.Function.LocalAssignment}} != first.{{$rel.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, first.{{$rel.Function.ForeignAssignment}})
|
||||
if a.{{$txt.Function.LocalAssignment}} != first.{{$txt.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, first.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
if a.{{$rel.Function.LocalAssignment}} != second.{{$rel.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, second.{{$rel.Function.ForeignAssignment}})
|
||||
if a.{{$txt.Function.LocalAssignment}} != second.{{$txt.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, second.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
if first.R.{{$rel.Function.ForeignName}} != &a {
|
||||
if first.R.{{$txt.Function.ForeignName}} != &a {
|
||||
t.Error("relationship was not added properly to the foreign slice")
|
||||
}
|
||||
if second.R.{{$rel.Function.ForeignName}} != &a {
|
||||
if second.R.{{$txt.Function.ForeignName}} != &a {
|
||||
t.Error("relationship was not added properly to the foreign slice")
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
if a.R.{{$rel.Function.Name}}[i*2] != first {
|
||||
if a.R.{{$txt.Function.Name}}[i*2] != first {
|
||||
t.Error("relationship struct slice not set to correct value")
|
||||
}
|
||||
if a.R.{{$rel.Function.Name}}[i*2+1] != second {
|
||||
if a.R.{{$txt.Function.Name}}[i*2+1] != second {
|
||||
t.Error("relationship struct slice not set to correct value")
|
||||
}
|
||||
|
||||
count, err := a.{{$rel.Function.Name}}(tx).Count()
|
||||
count, err := a.{{$txt.Function.Name}}(tx).Count()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -101,20 +101,20 @@ func test{{$rel.LocalTable.NameGo}}ToManyAddOp{{$rel.Function.Name}}(t *testing.
|
|||
}
|
||||
{{- if (or .ForeignColumnNullable .ToJoinTable)}}
|
||||
|
||||
func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.T) {
|
||||
func test{{$txt.LocalTable.NameGo}}ToManySetOp{{$txt.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var a {{$rel.LocalTable.NameGo}}
|
||||
var b, c, d, e {{$rel.ForeignTable.NameGo}}
|
||||
var a {{$txt.LocalTable.NameGo}}
|
||||
var b, c, d, e {{$txt.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
foreigners := []*{{$rel.ForeignTable.NameGo}}{&b, &c, &d, &e}
|
||||
foreigners := []*{{$txt.ForeignTable.NameGo}}{&b, &c, &d, &e}
|
||||
for _, x := range foreigners {
|
||||
if err = randomize.Struct(seed, x, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -131,12 +131,12 @@ func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = a.Set{{$rel.Function.Name}}(tx, false, &b, &c)
|
||||
err = a.Set{{$txt.Function.Name}}(tx, false, &b, &c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
count, err := a.{{$rel.Function.Name}}(tx).Count()
|
||||
count, err := a.{{$txt.Function.Name}}(tx).Count()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -144,12 +144,12 @@ func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.
|
|||
t.Error("count was wrong:", count)
|
||||
}
|
||||
|
||||
err = a.Set{{$rel.Function.Name}}(tx, true, &d, &e)
|
||||
err = a.Set{{$txt.Function.Name}}(tx, true, &d, &e)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
count, err = a.{{$rel.Function.Name}}(tx).Count()
|
||||
count, err = a.{{$txt.Function.Name}}(tx).Count()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -159,78 +159,78 @@ func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.
|
|||
|
||||
{{- if .ToJoinTable}}
|
||||
|
||||
if len(b.R.{{$rel.Function.ForeignName}}) != 0 {
|
||||
if len(b.R.{{$txt.Function.ForeignName}}) != 0 {
|
||||
t.Error("relationship was not removed properly from the slice")
|
||||
}
|
||||
if len(c.R.{{$rel.Function.ForeignName}}) != 0 {
|
||||
if len(c.R.{{$txt.Function.ForeignName}}) != 0 {
|
||||
t.Error("relationship was not removed properly from the slice")
|
||||
}
|
||||
if d.R.{{$rel.Function.ForeignName}}[0] != &a {
|
||||
if d.R.{{$txt.Function.ForeignName}}[0] != &a {
|
||||
t.Error("relationship was not added properly to the slice")
|
||||
}
|
||||
if e.R.{{$rel.Function.ForeignName}}[0] != &a {
|
||||
if e.R.{{$txt.Function.ForeignName}}[0] != &a {
|
||||
t.Error("relationship was not added properly to the slice")
|
||||
}
|
||||
{{- else}}
|
||||
|
||||
if b.{{$rel.ForeignTable.ColumnNameGo}}.Valid {
|
||||
if b.{{$txt.ForeignTable.ColumnNameGo}}.Valid {
|
||||
t.Error("want b's foreign key value to be nil")
|
||||
}
|
||||
if c.{{$rel.ForeignTable.ColumnNameGo}}.Valid {
|
||||
if c.{{$txt.ForeignTable.ColumnNameGo}}.Valid {
|
||||
t.Error("want c's foreign key value to be nil")
|
||||
}
|
||||
{{if $rel.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$rel.Function.LocalAssignment}}, d.{{$rel.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, d.{{$rel.Function.ForeignAssignment}})
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$txt.Function.LocalAssignment}}, d.{{$txt.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, d.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
if 0 != bytes.Compare(a.{{$rel.Function.LocalAssignment}}, e.{{$rel.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, e.{{$rel.Function.ForeignAssignment}})
|
||||
if 0 != bytes.Compare(a.{{$txt.Function.LocalAssignment}}, e.{{$txt.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, e.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
{{else -}}
|
||||
if a.{{$rel.Function.LocalAssignment}} != d.{{$rel.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, d.{{$rel.Function.ForeignAssignment}})
|
||||
if a.{{$txt.Function.LocalAssignment}} != d.{{$txt.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, d.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
if a.{{$rel.Function.LocalAssignment}} != e.{{$rel.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, e.{{$rel.Function.ForeignAssignment}})
|
||||
if a.{{$txt.Function.LocalAssignment}} != e.{{$txt.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, e.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
if b.R.{{$rel.Function.ForeignName}} != nil {
|
||||
if b.R.{{$txt.Function.ForeignName}} != nil {
|
||||
t.Error("relationship was not removed properly from the foreign struct")
|
||||
}
|
||||
if c.R.{{$rel.Function.ForeignName}} != nil {
|
||||
if c.R.{{$txt.Function.ForeignName}} != nil {
|
||||
t.Error("relationship was not removed properly from the foreign struct")
|
||||
}
|
||||
if d.R.{{$rel.Function.ForeignName}} != &a {
|
||||
if d.R.{{$txt.Function.ForeignName}} != &a {
|
||||
t.Error("relationship was not added properly to the foreign struct")
|
||||
}
|
||||
if e.R.{{$rel.Function.ForeignName}} != &a {
|
||||
if e.R.{{$txt.Function.ForeignName}} != &a {
|
||||
t.Error("relationship was not added properly to the foreign struct")
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
if a.R.{{$rel.Function.Name}}[0] != &d {
|
||||
if a.R.{{$txt.Function.Name}}[0] != &d {
|
||||
t.Error("relationship struct slice not set to correct value")
|
||||
}
|
||||
if a.R.{{$rel.Function.Name}}[1] != &e {
|
||||
if a.R.{{$txt.Function.Name}}[1] != &e {
|
||||
t.Error("relationship struct slice not set to correct value")
|
||||
}
|
||||
}
|
||||
|
||||
func test{{$rel.LocalTable.NameGo}}ToManyRemoveOp{{$rel.Function.Name}}(t *testing.T) {
|
||||
func test{{$txt.LocalTable.NameGo}}ToManyRemoveOp{{$txt.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var a {{$rel.LocalTable.NameGo}}
|
||||
var b, c, d, e {{$rel.ForeignTable.NameGo}}
|
||||
var a {{$txt.LocalTable.NameGo}}
|
||||
var b, c, d, e {{$txt.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
foreigners := []*{{$rel.ForeignTable.NameGo}}{&b, &c, &d, &e}
|
||||
foreigners := []*{{$txt.ForeignTable.NameGo}}{&b, &c, &d, &e}
|
||||
for _, x := range foreigners {
|
||||
if err = randomize.Struct(seed, x, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -241,12 +241,12 @@ func test{{$rel.LocalTable.NameGo}}ToManyRemoveOp{{$rel.Function.Name}}(t *testi
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = a.Add{{$rel.Function.Name}}(tx, true, foreigners...)
|
||||
err = a.Add{{$txt.Function.Name}}(tx, true, foreigners...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
count, err := a.{{$rel.Function.Name}}(tx).Count()
|
||||
count, err := a.{{$txt.Function.Name}}(tx).Count()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -254,12 +254,12 @@ func test{{$rel.LocalTable.NameGo}}ToManyRemoveOp{{$rel.Function.Name}}(t *testi
|
|||
t.Error("count was wrong:", count)
|
||||
}
|
||||
|
||||
err = a.Remove{{$rel.Function.Name}}(tx, foreigners[:2]...)
|
||||
err = a.Remove{{$txt.Function.Name}}(tx, foreigners[:2]...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
count, err = a.{{$rel.Function.Name}}(tx).Count()
|
||||
count, err = a.{{$txt.Function.Name}}(tx).Count()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -269,50 +269,50 @@ func test{{$rel.LocalTable.NameGo}}ToManyRemoveOp{{$rel.Function.Name}}(t *testi
|
|||
|
||||
{{- if .ToJoinTable}}
|
||||
|
||||
if len(b.R.{{$rel.Function.ForeignName}}) != 0 {
|
||||
if len(b.R.{{$txt.Function.ForeignName}}) != 0 {
|
||||
t.Error("relationship was not removed properly from the slice")
|
||||
}
|
||||
if len(c.R.{{$rel.Function.ForeignName}}) != 0 {
|
||||
if len(c.R.{{$txt.Function.ForeignName}}) != 0 {
|
||||
t.Error("relationship was not removed properly from the slice")
|
||||
}
|
||||
if d.R.{{$rel.Function.ForeignName}}[0] != &a {
|
||||
if d.R.{{$txt.Function.ForeignName}}[0] != &a {
|
||||
t.Error("relationship was not added properly to the foreign struct")
|
||||
}
|
||||
if e.R.{{$rel.Function.ForeignName}}[0] != &a {
|
||||
if e.R.{{$txt.Function.ForeignName}}[0] != &a {
|
||||
t.Error("relationship was not added properly to the foreign struct")
|
||||
}
|
||||
{{- else}}
|
||||
|
||||
if b.{{$rel.ForeignTable.ColumnNameGo}}.Valid {
|
||||
if b.{{$txt.ForeignTable.ColumnNameGo}}.Valid {
|
||||
t.Error("want b's foreign key value to be nil")
|
||||
}
|
||||
if c.{{$rel.ForeignTable.ColumnNameGo}}.Valid {
|
||||
if c.{{$txt.ForeignTable.ColumnNameGo}}.Valid {
|
||||
t.Error("want c's foreign key value to be nil")
|
||||
}
|
||||
|
||||
if b.R.{{$rel.Function.ForeignName}} != nil {
|
||||
if b.R.{{$txt.Function.ForeignName}} != nil {
|
||||
t.Error("relationship was not removed properly from the foreign struct")
|
||||
}
|
||||
if c.R.{{$rel.Function.ForeignName}} != nil {
|
||||
if c.R.{{$txt.Function.ForeignName}} != nil {
|
||||
t.Error("relationship was not removed properly from the foreign struct")
|
||||
}
|
||||
if d.R.{{$rel.Function.ForeignName}} != &a {
|
||||
if d.R.{{$txt.Function.ForeignName}} != &a {
|
||||
t.Error("relationship to a should have been preserved")
|
||||
}
|
||||
if e.R.{{$rel.Function.ForeignName}} != &a {
|
||||
if e.R.{{$txt.Function.ForeignName}} != &a {
|
||||
t.Error("relationship to a should have been preserved")
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
if len(a.R.{{$rel.Function.Name}}) != 2 {
|
||||
if len(a.R.{{$txt.Function.Name}}) != 2 {
|
||||
t.Error("should have preserved two relationships")
|
||||
}
|
||||
|
||||
// Removal doesn't do a stable deletion for performance so we have to flip the order
|
||||
if a.R.{{$rel.Function.Name}}[1] != &d {
|
||||
if a.R.{{$txt.Function.Name}}[1] != &d {
|
||||
t.Error("relationship to d should have been preserved")
|
||||
}
|
||||
if a.R.{{$rel.Function.Name}}[0] != &e {
|
||||
if a.R.{{$txt.Function.Name}}[0] != &e {
|
||||
t.Error("relationship to e should have been preserved")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{{- range .Table.FKeys -}}
|
||||
{{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase}}
|
||||
func test{{$txt.LocalTable.NameGo}}ToOne{{$txt.ForeignTable.NameGo}}Using{{$txt.Function.Name}}(t *testing.T) {
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
@ -65,5 +65,6 @@ func test{{$txt.LocalTable.NameGo}}ToOne{{$txt.ForeignTable.NameGo}}Using{{$txt.
|
|||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
}
|
||||
|
||||
{{end -}}{{/* range */}}
|
||||
{{- end -}}{{/* join table */}}
|
||||
|
|
|
@ -60,6 +60,13 @@ func test{{$txt.LocalTable.NameGo}}ToOneSetOp{{$txt.ForeignTable.NameGo}}Using{{
|
|||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}})
|
||||
}
|
||||
|
||||
{{if setInclude .Column $dot.Table.PKey.Columns -}}
|
||||
if exists, err := {{$txt.LocalTable.NameGo}}Exists(tx, a.{{$dot.Table.PKey.Columns | stringMap $dot.StringFuncs.titleCase | join ", a."}}); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !exists {
|
||||
t.Error("want 'a' to exist")
|
||||
}
|
||||
{{else -}}
|
||||
zero := reflect.Zero(reflect.TypeOf(a.{{$txt.Function.LocalAssignment}}))
|
||||
reflect.Indirect(reflect.ValueOf(&a.{{$txt.Function.LocalAssignment}})).Set(zero)
|
||||
|
||||
|
@ -74,6 +81,7 @@ func test{{$txt.LocalTable.NameGo}}ToOneSetOp{{$txt.ForeignTable.NameGo}}Using{{
|
|||
{{end -}}
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, x.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
{{- end}}
|
||||
}
|
||||
}
|
||||
{{- if .Nullable}}
|
||||
|
|
44
testdata/mysql_test_schema.sql
vendored
44
testdata/mysql_test_schema.sql
vendored
|
@ -285,3 +285,47 @@ create table byte_pilot_languages (
|
|||
foreign key (byte_pilot_id) references byte_pilots (id),
|
||||
foreign key (byte_language_id) references byte_languages (id)
|
||||
);
|
||||
|
||||
create table cars (
|
||||
id integer not null,
|
||||
name text,
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
create table car_cars (
|
||||
car_id integer not null,
|
||||
awesome_car_id integer not null,
|
||||
relation text not null,
|
||||
primary key (car_id, awesome_car_id),
|
||||
foreign key (car_id) references cars(id),
|
||||
foreign key (awesome_car_id) references cars(id)
|
||||
);
|
||||
|
||||
create table trucks (
|
||||
id integer not null,
|
||||
parent_id integer,
|
||||
name text,
|
||||
primary key (id),
|
||||
foreign key (parent_id) references trucks(id)
|
||||
);
|
||||
|
||||
CREATE TABLE race (
|
||||
id integer PRIMARY KEY NOT NULL,
|
||||
race_date timestamp,
|
||||
track text
|
||||
);
|
||||
|
||||
CREATE TABLE race_results (
|
||||
id integer PRIMARY KEY NOT NULL,
|
||||
race_id integer,
|
||||
name text,
|
||||
foreign key (race_id) references race(id)
|
||||
);
|
||||
|
||||
CREATE TABLE race_result_scratchings (
|
||||
id integer PRIMARY KEY NOT NULL,
|
||||
results_id integer NOT NULL,
|
||||
name text NOT NULL,
|
||||
foreign key (results_id) references race_results(id)
|
||||
);
|
||||
|
||||
|
|
43
testdata/postgres_test_schema.sql
vendored
43
testdata/postgres_test_schema.sql
vendored
|
@ -326,3 +326,46 @@ create table byte_pilot_languages (
|
|||
foreign key (byte_pilot_id) references byte_pilots (id),
|
||||
foreign key (byte_language_id) references byte_languages (id)
|
||||
);
|
||||
|
||||
create table cars (
|
||||
id integer not null,
|
||||
name text,
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
create table car_cars (
|
||||
car_id integer not null,
|
||||
awesome_car_id integer not null,
|
||||
relation text not null,
|
||||
primary key (car_id, awesome_car_id),
|
||||
foreign key (car_id) references cars(id),
|
||||
foreign key (awesome_car_id) references cars(id)
|
||||
);
|
||||
|
||||
create table trucks (
|
||||
id integer not null,
|
||||
parent_id integer,
|
||||
name text,
|
||||
primary key (id),
|
||||
foreign key (parent_id) references trucks(id)
|
||||
);
|
||||
|
||||
CREATE TABLE race (
|
||||
id integer PRIMARY KEY NOT NULL,
|
||||
race_date timestamp,
|
||||
track text
|
||||
);
|
||||
|
||||
CREATE TABLE race_results (
|
||||
id integer PRIMARY KEY NOT NULL,
|
||||
race_id integer,
|
||||
name text,
|
||||
foreign key (race_id) references race(id)
|
||||
);
|
||||
|
||||
CREATE TABLE race_result_scratchings (
|
||||
id integer PRIMARY KEY NOT NULL,
|
||||
results_id integer NOT NULL,
|
||||
name text NOT NULL,
|
||||
foreign key (results_id) references race_results(id)
|
||||
);
|
||||
|
|
132
text_helpers.go
132
text_helpers.go
|
@ -29,7 +29,6 @@ type TxtToOne struct {
|
|||
Name string
|
||||
ForeignName string
|
||||
|
||||
Varname string
|
||||
UsesBytes bool
|
||||
|
||||
LocalAssignment string
|
||||
|
@ -50,13 +49,7 @@ func txtsFromFKey(tables []bdb.Table, table bdb.Table, fkey bdb.ForeignKey) TxtT
|
|||
r.ForeignTable.ColumnName = fkey.ForeignColumn
|
||||
r.ForeignTable.ColumnNameGo = strmangle.TitleCase(strmangle.Singular(fkey.ForeignColumn))
|
||||
|
||||
r.Function.Name = strmangle.TitleCase(strmangle.Singular(trimSuffixes(fkey.Column)))
|
||||
plurality := strmangle.Plural
|
||||
if fkey.Unique {
|
||||
plurality = strmangle.Singular
|
||||
}
|
||||
r.Function.ForeignName = mkFunctionName(strmangle.Singular(fkey.ForeignTable), strmangle.TitleCase(plurality(fkey.Table)), fkey.Column, false)
|
||||
r.Function.Varname = strmangle.CamelCase(strmangle.Singular(fkey.ForeignTable))
|
||||
r.Function.Name, r.Function.ForeignName = txtNameToOne(fkey)
|
||||
|
||||
if fkey.Nullable {
|
||||
col := table.GetColumn(fkey.Column)
|
||||
|
@ -101,10 +94,14 @@ func txtsFromOneToOne(tables []bdb.Table, table bdb.Table, oneToOne bdb.ToOneRel
|
|||
rel.ForeignKey.Column, rel.ForeignKey.ForeignColumn = rel.ForeignKey.ForeignColumn, rel.ForeignKey.Column
|
||||
rel.ForeignKey.Nullable, rel.ForeignKey.ForeignColumnNullable = rel.ForeignKey.ForeignColumnNullable, rel.ForeignKey.Nullable
|
||||
rel.ForeignKey.Unique, rel.ForeignKey.ForeignColumnUnique = rel.ForeignKey.ForeignColumnUnique, rel.ForeignKey.Unique
|
||||
|
||||
rel.Function.Name = strmangle.TitleCase(strmangle.Singular(oneToOne.ForeignTable))
|
||||
rel.Function.ForeignName = mkFunctionName(strmangle.Singular(oneToOne.Table), strmangle.TitleCase(strmangle.Singular(oneToOne.Table)), oneToOne.ForeignColumn, false)
|
||||
rel.Function.UsesBytes = col.Type == "[]byte"
|
||||
rel.Function.ForeignName, rel.Function.Name = txtNameToOne(bdb.ForeignKey{
|
||||
Table: oneToOne.ForeignTable,
|
||||
Column: oneToOne.ForeignColumn,
|
||||
Unique: true,
|
||||
ForeignTable: oneToOne.Table,
|
||||
ForeignColumn: oneToOne.Column,
|
||||
})
|
||||
return rel
|
||||
}
|
||||
|
||||
|
@ -112,13 +109,11 @@ func txtsFromOneToOne(tables []bdb.Table, table bdb.Table, oneToOne bdb.ToOneRel
|
|||
type TxtToMany struct {
|
||||
LocalTable struct {
|
||||
NameGo string
|
||||
NameSingular string
|
||||
ColumnNameGo string
|
||||
}
|
||||
|
||||
ForeignTable struct {
|
||||
NameGo string
|
||||
NameSingular string
|
||||
NamePluralGo string
|
||||
NameHumanReadable string
|
||||
ColumnNameGo string
|
||||
|
@ -140,25 +135,17 @@ type TxtToMany struct {
|
|||
// transformation in advance for a given relationship.
|
||||
func txtsFromToMany(tables []bdb.Table, table bdb.Table, rel bdb.ToManyRelationship) TxtToMany {
|
||||
r := TxtToMany{}
|
||||
r.LocalTable.NameSingular = strmangle.Singular(table.Name)
|
||||
r.LocalTable.NameGo = strmangle.TitleCase(r.LocalTable.NameSingular)
|
||||
r.LocalTable.NameGo = strmangle.TitleCase(strmangle.Singular(table.Name))
|
||||
r.LocalTable.ColumnNameGo = strmangle.TitleCase(rel.Column)
|
||||
|
||||
r.ForeignTable.NameSingular = strmangle.Singular(rel.ForeignTable)
|
||||
foreignNameSingular := strmangle.Singular(rel.ForeignTable)
|
||||
r.ForeignTable.NamePluralGo = strmangle.TitleCase(strmangle.Plural(rel.ForeignTable))
|
||||
r.ForeignTable.NameGo = strmangle.TitleCase(r.ForeignTable.NameSingular)
|
||||
r.ForeignTable.NameGo = strmangle.TitleCase(foreignNameSingular)
|
||||
r.ForeignTable.ColumnNameGo = strmangle.TitleCase(rel.ForeignColumn)
|
||||
r.ForeignTable.Slice = fmt.Sprintf("%sSlice", strmangle.TitleCase(r.ForeignTable.NameSingular))
|
||||
r.ForeignTable.Slice = fmt.Sprintf("%sSlice", strmangle.TitleCase(foreignNameSingular))
|
||||
r.ForeignTable.NameHumanReadable = strings.Replace(rel.ForeignTable, "_", " ", -1)
|
||||
|
||||
r.Function.Name = mkFunctionName(r.LocalTable.NameSingular, r.ForeignTable.NamePluralGo, rel.ForeignColumn, rel.ToJoinTable)
|
||||
plurality := strmangle.Singular
|
||||
foreignNamingColumn := rel.ForeignColumn
|
||||
if rel.ToJoinTable {
|
||||
plurality = strmangle.Plural
|
||||
foreignNamingColumn = rel.JoinLocalColumn
|
||||
}
|
||||
r.Function.ForeignName = strmangle.TitleCase(plurality(trimSuffixes(foreignNamingColumn)))
|
||||
r.Function.Name, r.Function.ForeignName = txtNameToMany(rel)
|
||||
|
||||
col := table.GetColumn(rel.Column)
|
||||
if rel.Nullable {
|
||||
|
@ -180,6 +167,99 @@ func txtsFromToMany(tables []bdb.Table, table bdb.Table, rel bdb.ToManyRelations
|
|||
return r
|
||||
}
|
||||
|
||||
// txtNameToOne creates the local and foreign function names for
|
||||
// one-to-many and one-to-one relationships, where local == lhs (one).
|
||||
//
|
||||
// = many-to-one
|
||||
// users - videos : user_id
|
||||
// users - videos : producer_id
|
||||
//
|
||||
// fk == table = user.Videos | video.User
|
||||
// fk != table = user.ProducerVideos | video.Producer
|
||||
//
|
||||
// = many-to-one
|
||||
// industries - industries : parent_id
|
||||
//
|
||||
// fk == table = industry.Industries | industry.Industry
|
||||
// fk != table = industry.ParentIndustries | industry.Parent
|
||||
//
|
||||
// = one-to-one
|
||||
// users - videos : user_id
|
||||
// users - videos : producer_id
|
||||
//
|
||||
// fk == table = user.Video | video.User
|
||||
// fk != table = user.ProducerVideo | video.Producer
|
||||
//
|
||||
// = one-to-one
|
||||
// industries - industries : parent_id
|
||||
//
|
||||
// fk == table = industry.Industry | industry.Industry
|
||||
// fk != table = industry.ParentIndustry | industry.Industry
|
||||
func txtNameToOne(fk bdb.ForeignKey) (localFn, foreignFn string) {
|
||||
localFn = strmangle.Singular(trimSuffixes(fk.Column))
|
||||
fkeyIsTableName := localFn != strmangle.Singular(fk.ForeignTable)
|
||||
localFn = strmangle.TitleCase(localFn)
|
||||
|
||||
if fkeyIsTableName {
|
||||
foreignFn = localFn
|
||||
}
|
||||
|
||||
plurality := strmangle.Plural
|
||||
if fk.Unique {
|
||||
plurality = strmangle.Singular
|
||||
}
|
||||
foreignFn += strmangle.TitleCase(plurality(fk.Table))
|
||||
|
||||
return localFn, foreignFn
|
||||
}
|
||||
|
||||
// txtNameToMany creates the local and foreign function names for
|
||||
// many-to-one and many-to-many relationship, where local == lhs (many)
|
||||
//
|
||||
// cases:
|
||||
// = many-to-many
|
||||
// sponsors - constests
|
||||
// sponsor_id contest_id
|
||||
// fk == table = sponsor.Contests | contest.Sponsors
|
||||
//
|
||||
// = many-to-many
|
||||
// sponsors - constests
|
||||
// wiggle_id jiggle_id
|
||||
// fk != table = sponsor.JiggleSponsors | contest.WiggleContests
|
||||
//
|
||||
// = many-to-many
|
||||
// industries - industries
|
||||
// industry_id mapped_industry_id
|
||||
//
|
||||
// fk == table = industry.Industries
|
||||
// fk != table = industry.MappedIndustryIndustry
|
||||
func txtNameToMany(toMany bdb.ToManyRelationship) (localFn, foreignFn string) {
|
||||
if toMany.ToJoinTable {
|
||||
localFkey := strmangle.Singular(trimSuffixes(toMany.JoinLocalColumn))
|
||||
foreignFkey := strmangle.Singular(trimSuffixes(toMany.JoinForeignColumn))
|
||||
|
||||
if localFkey != strmangle.Singular(toMany.Table) {
|
||||
foreignFn = strmangle.TitleCase(localFkey)
|
||||
}
|
||||
foreignFn += strmangle.TitleCase(strmangle.Plural(toMany.Table))
|
||||
|
||||
if foreignFkey != strmangle.Singular(toMany.ForeignTable) {
|
||||
localFn = strmangle.TitleCase(foreignFkey)
|
||||
}
|
||||
localFn += strmangle.TitleCase(strmangle.Plural(toMany.ForeignTable))
|
||||
|
||||
return localFn, foreignFn
|
||||
}
|
||||
|
||||
fkeyName := strmangle.Singular(trimSuffixes(toMany.ForeignColumn))
|
||||
if fkeyName != strmangle.Singular(toMany.Table) {
|
||||
localFn = strmangle.TitleCase(fkeyName)
|
||||
}
|
||||
localFn += strmangle.TitleCase(strmangle.Plural(toMany.ForeignTable))
|
||||
foreignFn = strmangle.TitleCase(strmangle.Singular(fkeyName))
|
||||
return localFn, foreignFn
|
||||
}
|
||||
|
||||
// mkFunctionName checks to see if the foreign key name is the same as the local table name (minus _id suffix)
|
||||
// Simple case: yes - we can name the function the same as the plural table name
|
||||
// Not simple case: We have to name the function based off the foreign key and the foreign table name
|
||||
|
|
|
@ -33,7 +33,6 @@ func TestTxtsFromOne(t *testing.T) {
|
|||
|
||||
expect.Function.Name = "Pilot"
|
||||
expect.Function.ForeignName = "Jet"
|
||||
expect.Function.Varname = "pilot"
|
||||
|
||||
expect.Function.LocalAssignment = "PilotID.Int"
|
||||
expect.Function.ForeignAssignment = "ID"
|
||||
|
@ -56,7 +55,6 @@ func TestTxtsFromOne(t *testing.T) {
|
|||
|
||||
expect.Function.Name = "Airport"
|
||||
expect.Function.ForeignName = "Jets"
|
||||
expect.Function.Varname = "airport"
|
||||
|
||||
expect.Function.LocalAssignment = "AirportID"
|
||||
expect.Function.ForeignAssignment = "ID"
|
||||
|
@ -106,7 +104,6 @@ func TestTxtsFromOneToOne(t *testing.T) {
|
|||
|
||||
expect.Function.Name = "Jet"
|
||||
expect.Function.ForeignName = "Pilot"
|
||||
expect.Function.Varname = "jet"
|
||||
|
||||
expect.Function.LocalAssignment = "ID"
|
||||
expect.Function.ForeignAssignment = "PilotID.Int"
|
||||
|
@ -128,11 +125,9 @@ func TestTxtsFromMany(t *testing.T) {
|
|||
texts := txtsFromToMany(tables, pilots, pilots.ToManyRelationships[0])
|
||||
expect := TxtToMany{}
|
||||
expect.LocalTable.NameGo = "Pilot"
|
||||
expect.LocalTable.NameSingular = "pilot"
|
||||
expect.LocalTable.ColumnNameGo = "ID"
|
||||
|
||||
expect.ForeignTable.NameGo = "License"
|
||||
expect.ForeignTable.NameSingular = "license"
|
||||
expect.ForeignTable.NamePluralGo = "Licenses"
|
||||
expect.ForeignTable.NameHumanReadable = "licenses"
|
||||
expect.ForeignTable.ColumnNameGo = "PilotID"
|
||||
|
@ -150,11 +145,9 @@ func TestTxtsFromMany(t *testing.T) {
|
|||
texts = txtsFromToMany(tables, pilots, pilots.ToManyRelationships[1])
|
||||
expect = TxtToMany{}
|
||||
expect.LocalTable.NameGo = "Pilot"
|
||||
expect.LocalTable.NameSingular = "pilot"
|
||||
expect.LocalTable.ColumnNameGo = "ID"
|
||||
|
||||
expect.ForeignTable.NameGo = "Language"
|
||||
expect.ForeignTable.NameSingular = "language"
|
||||
expect.ForeignTable.NamePluralGo = "Languages"
|
||||
expect.ForeignTable.NameHumanReadable = "languages"
|
||||
expect.ForeignTable.ColumnNameGo = "ID"
|
||||
|
@ -170,6 +163,104 @@ func TestTxtsFromMany(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTxtNameToOne(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
Table string
|
||||
Column string
|
||||
Unique bool
|
||||
ForeignTable string
|
||||
ForeignColumn string
|
||||
ForeignColumnUnique bool
|
||||
|
||||
LocalFn string
|
||||
ForeignFn string
|
||||
}{
|
||||
{"jets", "airport_id", false, "airports", "id", true, "Airport", "Jets"},
|
||||
{"jets", "airport_id", true, "airports", "id", true, "Airport", "Jet"},
|
||||
|
||||
{"jets", "holiday_id", false, "airports", "id", true, "Holiday", "HolidayJets"},
|
||||
{"jets", "holiday_id", true, "airports", "id", true, "Holiday", "HolidayJet"},
|
||||
|
||||
{"jets", "holiday_airport_id", false, "airports", "id", true, "HolidayAirport", "HolidayAirportJets"},
|
||||
{"jets", "holiday_airport_id", true, "airports", "id", true, "HolidayAirport", "HolidayAirportJet"},
|
||||
|
||||
{"jets", "jet_id", false, "jets", "id", true, "Jet", "Jets"},
|
||||
{"jets", "jet_id", true, "jets", "id", true, "Jet", "Jet"},
|
||||
{"jets", "plane_id", false, "jets", "id", true, "Plane", "PlaneJets"},
|
||||
{"jets", "plane_id", true, "jets", "id", true, "Plane", "PlaneJet"},
|
||||
|
||||
{"race_result_scratchings", "results_id", false, "race_results", "id", true, "Result", "ResultRaceResultScratchings"},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
fk := bdb.ForeignKey{
|
||||
Table: test.Table, Column: test.Column, Unique: test.Unique,
|
||||
ForeignTable: test.ForeignTable, ForeignColumn: test.ForeignColumn, ForeignColumnUnique: test.ForeignColumnUnique,
|
||||
}
|
||||
|
||||
local, foreign := txtNameToOne(fk)
|
||||
if local != test.LocalFn {
|
||||
t.Error(i, "local wrong:", local, "want:", test.LocalFn)
|
||||
}
|
||||
if foreign != test.ForeignFn {
|
||||
t.Error(i, "foreign wrong:", foreign, "want:", test.ForeignFn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTxtNameToMany(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
Table string
|
||||
Column string
|
||||
|
||||
ForeignTable string
|
||||
ForeignColumn string
|
||||
|
||||
ToJoinTable bool
|
||||
JoinLocalColumn string
|
||||
JoinForeignColumn string
|
||||
|
||||
LocalFn string
|
||||
ForeignFn string
|
||||
}{
|
||||
{"airports", "id", "jets", "airport_id", false, "", "", "Jets", "Airport"},
|
||||
{"airports", "id", "jets", "holiday_airport_id", false, "", "", "HolidayAirportJets", "HolidayAirport"},
|
||||
|
||||
{"jets", "id", "jets", "jet_id", false, "", "", "Jets", "Jet"},
|
||||
{"jets", "id", "jets", "plane_id", false, "", "", "PlaneJets", "Plane"},
|
||||
|
||||
{"pilots", "id", "languages", "id", true, "pilot_id", "language_id", "Languages", "Pilots"},
|
||||
{"pilots", "id", "languages", "id", true, "captain_id", "lingo_id", "LingoLanguages", "CaptainPilots"},
|
||||
|
||||
{"pilots", "id", "pilots", "id", true, "pilot_id", "mentor_id", "MentorPilots", "Pilots"},
|
||||
{"pilots", "id", "pilots", "id", true, "mentor_id", "pilot_id", "Pilots", "MentorPilots"},
|
||||
{"pilots", "id", "pilots", "id", true, "captain_id", "mentor_id", "MentorPilots", "CaptainPilots"},
|
||||
|
||||
{"race_results", "id", "race_result_scratchings", "results_id", false, "", "", "ResultRaceResultScratchings", "Result"},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
fk := bdb.ToManyRelationship{
|
||||
Table: test.Table, Column: test.Column,
|
||||
ForeignTable: test.ForeignTable, ForeignColumn: test.ForeignColumn,
|
||||
ToJoinTable: test.ToJoinTable,
|
||||
JoinLocalColumn: test.JoinLocalColumn, JoinForeignColumn: test.JoinForeignColumn,
|
||||
}
|
||||
|
||||
local, foreign := txtNameToMany(fk)
|
||||
if local != test.LocalFn {
|
||||
t.Error(i, "local wrong:", local, "want:", test.LocalFn)
|
||||
}
|
||||
if foreign != test.ForeignFn {
|
||||
t.Error(i, "foreign wrong:", foreign, "want:", test.ForeignFn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrimSuffixes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue