Begin the pain
This commit is contained in:
parent
1875bac7cf
commit
160c6ff0f0
6 changed files with 34 additions and 112 deletions
26
bdb/keys.go
26
bdb/keys.go
|
@ -3,7 +3,6 @@ package bdb
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var rgxAutoIncColumn = regexp.MustCompile(`^nextval\(.*\)`)
|
var rgxAutoIncColumn = regexp.MustCompile(`^nextval\(.*\)`)
|
||||||
|
@ -90,28 +89,3 @@ func SQLColDefStrings(defs []SQLColumnDef) []string {
|
||||||
|
|
||||||
return strs
|
return strs
|
||||||
}
|
}
|
||||||
|
|
||||||
// AutoIncPrimaryKey returns the auto-increment primary key column name or an
|
|
||||||
// empty string.
|
|
||||||
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 !rgxAutoIncColumn.MatchString(c.Default) || c.Nullable ||
|
|
||||||
!(strings.HasPrefix(c.Type, "int") || strings.HasPrefix(c.Type, "uint")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return &c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -50,55 +50,3 @@ func TestSQLDefStrings(t *testing.T) {
|
||||||
t.Error("wrong str:", got)
|
t.Error("wrong str:", got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAutoIncPrimaryKey(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tests := map[string]struct {
|
|
||||||
Ok bool
|
|
||||||
Expect Column
|
|
||||||
Pkey *PrimaryKey
|
|
||||||
Columns []Column
|
|
||||||
}{
|
|
||||||
"nillcase": {
|
|
||||||
Ok: false,
|
|
||||||
Pkey: nil,
|
|
||||||
Columns: nil,
|
|
||||||
},
|
|
||||||
"easycase": {
|
|
||||||
Ok: true,
|
|
||||||
Expect: Column{Name: "one", Type: "int32", Nullable: false, Default: `nextval('abc'::regclass)`},
|
|
||||||
Pkey: &PrimaryKey{Name: "pkey", Columns: []string{"one"}},
|
|
||||||
Columns: []Column{{Name: "one", Type: "int32", Nullable: false, Default: `nextval('abc'::regclass)`}},
|
|
||||||
},
|
|
||||||
"missingcase": {
|
|
||||||
Ok: false,
|
|
||||||
Pkey: &PrimaryKey{Name: "pkey", Columns: []string{"two"}},
|
|
||||||
Columns: []Column{{Name: "one", Type: "int32", Nullable: false, Default: `nextval('abc'::regclass)`}},
|
|
||||||
},
|
|
||||||
"wrongtype": {
|
|
||||||
Ok: false,
|
|
||||||
Pkey: &PrimaryKey{Name: "pkey", Columns: []string{"one"}},
|
|
||||||
Columns: []Column{{Name: "one", Type: "string", Nullable: false, Default: `nextval('abc'::regclass)`}},
|
|
||||||
},
|
|
||||||
"nodefault": {
|
|
||||||
Ok: false,
|
|
||||||
Pkey: &PrimaryKey{Name: "pkey", Columns: []string{"one"}},
|
|
||||||
Columns: []Column{{Name: "one", Type: "string", Nullable: false, Default: ``}},
|
|
||||||
},
|
|
||||||
"nullable": {
|
|
||||||
Ok: false,
|
|
||||||
Pkey: &PrimaryKey{Name: "pkey", Columns: []string{"one"}},
|
|
||||||
Columns: []Column{{Name: "one", Type: "string", Nullable: true, Default: `nextval('abc'::regclass)`}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for testName, test := range tests {
|
|
||||||
pkey := AutoIncPrimaryKey(test.Columns, test.Pkey)
|
|
||||||
if ok := (pkey != nil); ok != test.Ok {
|
|
||||||
t.Errorf("%s) found state was wrong, want: %t, got: %t", testName, test.Ok, ok)
|
|
||||||
} else if test.Ok && *pkey != test.Expect {
|
|
||||||
t.Errorf("%s) wrong primary key, want: %#v, got %#v", testName, test.Expect, pkey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -172,7 +172,6 @@ var templateFunctions = template.FuncMap{
|
||||||
"filterColumnsByAutoIncrement": bdb.FilterColumnsByAutoIncrement,
|
"filterColumnsByAutoIncrement": bdb.FilterColumnsByAutoIncrement,
|
||||||
"filterColumnsByValidated": bdb.FilterColumnsByValidated,
|
"filterColumnsByValidated": bdb.FilterColumnsByValidated,
|
||||||
"filterColumnsByUnique": bdb.FilterColumnsByUnique,
|
"filterColumnsByUnique": bdb.FilterColumnsByUnique,
|
||||||
"autoIncPrimaryKey": bdb.AutoIncPrimaryKey,
|
|
||||||
"sqlColDefinitions": bdb.SQLColDefinitions,
|
"sqlColDefinitions": bdb.SQLColDefinitions,
|
||||||
"sqlColDefStrings": bdb.SQLColDefStrings,
|
"sqlColDefStrings": bdb.SQLColDefStrings,
|
||||||
"columnNames": bdb.ColumnNames,
|
"columnNames": bdb.ColumnNames,
|
||||||
|
|
|
@ -9,7 +9,7 @@ var (
|
||||||
{{$varNameSingular}}UniqueColumns = []string{{"{"}}{{.Table.Columns | filterColumnsByUnique | columnNames | stringMap .StringFuncs.quoteWrap | join ", "}}{{"}"}}
|
{{$varNameSingular}}UniqueColumns = []string{{"{"}}{{.Table.Columns | filterColumnsByUnique | columnNames | stringMap .StringFuncs.quoteWrap | join ", "}}{{"}"}}
|
||||||
{{$varNameSingular}}PrimaryKeyColumns = []string{{"{"}}{{.Table.PKey.Columns | stringMap .StringFuncs.quoteWrap | join ", "}}{{"}"}}
|
{{$varNameSingular}}PrimaryKeyColumns = []string{{"{"}}{{.Table.PKey.Columns | stringMap .StringFuncs.quoteWrap | join ", "}}{{"}"}}
|
||||||
{{$varNameSingular}}AutoIncrementColumns = []string{{"{"}}{{.Table.Columns | filterColumnsByAutoIncrement true | columnNames | stringMap .StringFuncs.quoteWrap | join "," }}{{"}"}}
|
{{$varNameSingular}}AutoIncrementColumns = []string{{"{"}}{{.Table.Columns | filterColumnsByAutoIncrement true | columnNames | stringMap .StringFuncs.quoteWrap | join "," }}{{"}"}}
|
||||||
{{$varNameSingular}}AutoIncPrimaryKey = "{{- with autoIncPrimaryKey .Table.Columns .Table.PKey -}}{{.Name}}{{- end -}}"
|
{{$varNameSingular}}AutoIncPrimaryKeys = []string{{"{"}}{{.Table.Columns | filterColumnsByPrimaryKey .Table.PKey | filterColumnsByDefault true | columnNames | join ", "}}{{"}"}}
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|
|
@ -41,34 +41,34 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
||||||
ins := fmt.Sprintf(`INSERT INTO {{.Table.Name}} ("%s") VALUES (%s)`, strings.Join(wl, `","`), strmangle.Placeholders(len(wl), 1, 1))
|
ins := fmt.Sprintf(`INSERT INTO {{.Table.Name}} ("%s") VALUES (%s)`, strings.Join(wl, `","`), strmangle.Placeholders(len(wl), 1, 1))
|
||||||
|
|
||||||
{{if driverUsesLastInsertID .DriverName}}
|
{{if driverUsesLastInsertID .DriverName}}
|
||||||
if len(returnColumns) != 0 {
|
if boil.DebugMode {
|
||||||
result, err := exec.Exec(ins, boil.GetStructValues(o, wl...)...)
|
fmt.Fprintln(boil.DebugWriter, ins)
|
||||||
if err != nil {
|
fmt.Fprintln(boil.DebugWriter, boil.GetStructValues(o, wl...))
|
||||||
return errors.Wrap(err, "{{.PkgName}}: unable to insert into {{.Table.Name}}")
|
}
|
||||||
}
|
|
||||||
|
|
||||||
lastId, err := result.lastInsertId()
|
result, err := exec.Exec(ins, boil.GetStructValues(o, wl...)...)
|
||||||
if err != nil || lastId == 0 {
|
if err != nil {
|
||||||
sel := fmt.Sprintf(`SELECT %s FROM {{.Table.Name}} WHERE %s`, strings.Join(returnColumns, `","`), strmangle.WhereClause(1, wl))
|
return errors.Wrap(err, "{{.PkgName}}: unable to insert into {{.Table.Name}}")
|
||||||
rows, err := exec.Query(sel, boil.GetStructValues(o, wl...)...)
|
}
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "{{.PkgName}}: unable to insert into {{.Table.Name}}")
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
i := 0
|
if len(returnColumns) == 0 {
|
||||||
ptrs := boil.GetStructPointers(o, returnColumns...)
|
return o.doAfterCreateHooks()
|
||||||
for rows.Next() {
|
}
|
||||||
if err := rows.Scan(ptrs[i]); err != nil {
|
|
||||||
return errors.Wrapf(err, "{{.PkgName}}: unable to get result of insert, scan failed for column %s index %d\n\n%#v", returnColumns[i], i, ptrs)
|
lastId, err := result.lastInsertId()
|
||||||
}
|
if err != nil || lastId == 0 {
|
||||||
i++
|
return ErrSyncFail
|
||||||
}
|
}
|
||||||
} else if {{$varNameSingular}}AutoIncPrimKey != "" {
|
|
||||||
sel := fmt.Sprintf(`SELECT %s FROM {{.Table.Name}} WHERE %s=$1`, strings.Join(returnColumns, ","), {{$varNameSingular}}AutoIncPrimaryKey, lastId)
|
if len({{$varNameSingular}}AutoIncPrimaryKeys) != 1 {
|
||||||
}
|
return ErrSyncFail
|
||||||
} else {
|
}
|
||||||
_, err = exec.Exec(ins, boil.GetStructValues(o, wl...)...)
|
|
||||||
|
pkey := {{$varNameSingular}}AutoIncPrimaryKeys[0]
|
||||||
|
sel := fmt.Sprintf(`SELECT %s FROM {{.Table.Name}} WHERE %s`, strings.Join(returnColumns, `","`), strmangle.WhereClause(1, pkey))
|
||||||
|
err := exec.QueryRow(sel, lastId).Scan(boil.GetStructPointers(o, returnColumns...))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "{{.PkgName}}: unable to populate default values for {{.Table.Name}}")
|
||||||
}
|
}
|
||||||
{{else}}
|
{{else}}
|
||||||
if len(returnColumns) != 0 {
|
if len(returnColumns) != 0 {
|
||||||
|
@ -77,7 +77,6 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
||||||
} else {
|
} else {
|
||||||
_, err = exec.Exec(ins, boil.GetStructValues(o, wl...)...)
|
_, err = exec.Exec(ins, boil.GetStructValues(o, wl...)...)
|
||||||
}
|
}
|
||||||
{{end}}
|
|
||||||
|
|
||||||
if boil.DebugMode {
|
if boil.DebugMode {
|
||||||
fmt.Fprintln(boil.DebugWriter, ins)
|
fmt.Fprintln(boil.DebugWriter, ins)
|
||||||
|
@ -87,12 +86,9 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "{{.PkgName}}: unable to insert into {{.Table.Name}}")
|
return errors.Wrap(err, "{{.PkgName}}: unable to insert into {{.Table.Name}}")
|
||||||
}
|
}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
if err := o.doAfterCreateHooks(); err != nil {
|
return o.doAfterCreateHooks()
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateInsertColumns generates the whitelist columns and return columns for an insert statement
|
// generateInsertColumns generates the whitelist columns and return columns for an insert statement
|
||||||
|
|
|
@ -7,3 +7,8 @@ type upsertData struct {
|
||||||
whitelist []string
|
whitelist []string
|
||||||
returning []string
|
returning []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrSyncFail occurs during insert when the record could not be retrieved in
|
||||||
|
// order to populate default value information. This usually happens when LastInsertId
|
||||||
|
// fails or there was a primary key configuration that was not resolvable.
|
||||||
|
var ErrSyncFail = errors.New("{{.PkgName}}: failed to synchronize data after insert")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue