gnorm-templates/table.gotmpl

170 lines
5.2 KiB
Go Template
Raw Permalink Normal View History

2018-05-04 10:30:44 +02:00
// Code generated by gnorm, DO NOT EDIT!
package {{toLower .Table.Name}}
import (
"{{.Params.RootImport}}"
"{{.Params.RootImport}}/enum"
)
{{$rootPkg := .Params.RootPkg -}}
{{$table := .Table.DBName -}}
{{$schema := .Table.Schema.DBName -}}
// Row represents a row from '{{ $table }}'.
type Row struct {
{{- range .Table.Columns }}
{{ .Name }} {{ .Type }} // {{ .DBName }}{{if .IsPrimaryKey}} (PK){{end}}
{{- end }}
}
// Field values for every column in {{.Table.Name}}.
var (
{{- range .Table.Columns }}
{{- if or (hasPrefix .Type (printf "%s." $rootPkg)) (hasPrefix .Type "enum.")}}
{{.Name}}Col {{ .Type }}Field = "{{ .DBName }}"
{{- else}}
{{.Name}}Col {{$rootPkg}}.{{ title (replace .Type "." "" 1) }}Field = "{{ .DBName }}"
{{- end}}
{{- end}}
)
// Query retrieves rows from '{{ $table }}' as a slice of Row.
func Query(db {{$rootPkg}}.DB, where {{$rootPkg}}.WhereClause) ([]*Row, error) {
const origsqlstr = `SELECT
{{ join .Table.Columns.DBNames ", " }}
FROM {{$schema}}.{{ $table }} WHERE (`
idx := 1
sqlstr := origsqlstr + where.String(&idx) + ") "
var vals []*Row
q, err := db.Query(sqlstr, where.Values()...)
if err != nil {
return nil, err
}
for q.Next() {
r := Row{}
err := q.Scan( {{ join (.Table.Columns.Names.Sprintf "&r.%s") ", " }} )
if err != nil {
return nil, err
}
vals = append(vals, &r)
}
return vals, nil
}
// One retrieve one row from '{{ $table }}'.
func One(db {{$rootPkg}}.DB, where {{$rootPkg}}.WhereClause) (*Row, error) {
const origsqlstr = `SELECT
{{ join .Table.Columns.DBNames ", " }}
FROM {{$schema}}.{{ $table }} WHERE (`
idx := 1
sqlstr := origsqlstr + where.String(&idx) + ") "
row := db.QueryRow(sqlstr, where.Values()...)
r := Row{}
err := row.Scan({{ join (.Table.Columns.Names.Sprintf "&r.%s") ", " }} )
if err != nil {
return nil, err
}
return &r, nil
}
{{- define "values" -}}
{{$nums := numbers 1 . -}}
{{$indices := $nums.Sprintf "$%s" -}}
{{join $indices ", " -}}
{{end}}
// Insert inserts the row into the database, returning the autogenerated
// primary keys. If the primary keys cannot be autogenerated, please use
// InsertExact instead.
func Insert(db {{$rootPkg}}.DB, r *Row) error {
const sqlstr = `INSERT INTO {{ $table }} (
{{ join (.Table.Columns.DBNames.Except .Table.PrimaryKeys.DBNames) ", " }}
) VALUES (
{{template "values" (len (.Table.Columns.Names.Except .Table.PrimaryKeys.Names)) }}
) RETURNING {{join (.Table.PrimaryKeys.DBNames.Sprintf "%s") ", "}}`
err := db.QueryRow(sqlstr, {{join ((.Table.Columns.Names.Except .Table.PrimaryKeys.Names).Sprintf "r.%s") ", "}}).Scan({{join (.Table.PrimaryKeys.Names.Sprintf "&r.%s") ", "}})
return errors.Wrap(err, "insert {{.Table.Name}}")
}
// InsertExact works like Insert, but lets you specify the primary keys.
// For most cases you should consider using Insert.
func InsertExact(db {{$rootPkg}}.DB, r *Row) error {
const sqlstr = `INSERT INTO {{ $table }} (
{{ join .Table.Columns.DBNames ", " }}
) VALUES (
{{template "values" (len .Table.Columns) }}
)`
_, err := db.Exec(sqlstr, {{join (.Table.Columns.Names.Sprintf "r.%s") ", "}})
return errors.Wrap(err, "insert {{.Table.Name}}")
}
{{- if .Table.HasPrimaryKey }}
{{- if gt (len .Table.Columns) (len .Table.PrimaryKeys) }}
{{- $nonPKFields := join ((.Table.Columns.Names.Except .Table.PrimaryKeys.Names).Sprintf "r.%s") ", "}}
{{- $PKFields := join (.Table.PrimaryKeys.Names.Sprintf "r.%s") ", "}}
{{- $nonPKNames := .Table.Columns.DBNames.Except .Table.PrimaryKeys.DBNames}}
{{- $numNonPKs := sub (len .Table.Columns) (len .Table.PrimaryKeys)}}
{{- $updateCols := join (.Table.Columns.DBNames.Except .Table.PrimaryKeys.DBNames) ", " }}
// Update updates the Row in the database.
func Update(db {{$rootPkg}}.DB, r *Row) error {
const sqlstr = `UPDATE {{ $table }} SET (
{{$updateCols}}
) = (
{{ template "values" $numNonPKs }}
) WHERE
{{- $PKnums := numbers (inc $numNonPKs) (len .Table.Columns)}}
{{join .Table.PrimaryKeys.DBNames ", "}} = {{ join ($PKnums.Sprintf "$%s") ", " }}
`
_, err := db.Exec(sqlstr, {{$nonPKFields}}, {{$PKFields}})
return errors.Wrap(err, "update {{.Table.Name}}:")
}
// Upsert performs an upsert for {{ .Table.Name }}.
//
// NOTE: PostgreSQL 9.5+ only
func Upsert(db {{$rootPkg}}.DB, r *Row) error {
const sqlstr = `INSERT INTO {{ $table }} (
{{$updateCols}}, {{join .Table.PrimaryKeys.DBNames ", "}}
) VALUES (
{{template "values" (len .Table.Columns) }}
) ON CONFLICT ({{join .Table.PrimaryKeys.DBNames ", " }}) DO UPDATE SET (
{{$updateCols}}
) = (
{{ template "values" $numNonPKs }}
)`
_, err := db.Exec(sqlstr, {{$nonPKFields}}, {{$PKFields}})
return errors.Wrap(err, "upsert {{.Table.Name}}")
}
{{ else }}
// Update statements omitted due to lack of primary key or lack of updateable fields
{{ end }}
// Delete deletes the Row from the database.
func Delete(
db {{$rootPkg}}.DB,
{{- range .Table.PrimaryKeys}}
{{camel .DBName}} {{.Type}},
{{end -}}
) error {
const sqlstr = `DELETE FROM {{ $table }} WHERE {{join .Table.PrimaryKeys.DBNames ", "}} = {{template "values" (len .Table.PrimaryKeys)}}`
_, err := db.Exec(
sqlstr,
{{- range .Table.PrimaryKeys}}
{{camel .DBName}},
{{end -}}
)
return errors.Wrap(err, "delete {{.Table.Name}}")
}
{{- end }}