Added Update commands

This commit is contained in:
Patrick O'brien 2016-03-19 16:22:10 +10:00
parent 54f6e43370
commit 9d41861e90
5 changed files with 130 additions and 2 deletions

View file

@ -10,6 +10,7 @@ import (
) )
// SelectNames returns the column names for a select statement // SelectNames returns the column names for a select statement
// Eg: col1, col2, col3
func SelectNames(results interface{}) string { func SelectNames(results interface{}) string {
var names []string var names []string
@ -36,6 +37,7 @@ func SelectNames(results interface{}) string {
} }
// Where returns the where clause for an sql statement // Where returns the where clause for an sql statement
// eg: col1=$1 AND col2=$2 AND col3=$3
func Where(columns map[string]interface{}) string { func Where(columns map[string]interface{}) string {
names := make([]string, 0, len(columns)) names := make([]string, 0, len(columns))
@ -52,6 +54,24 @@ func Where(columns map[string]interface{}) string {
return strings.Join(names, " AND ") return strings.Join(names, " AND ")
} }
// Update returns the column list for an update statement SET clause
// eg: col1=$1,col2=$2,col3=$3
func Update(columns map[string]interface{}) string {
names := make([]string, 0, len(columns))
for c := range columns {
names = append(names, c)
}
sort.Strings(names)
for i, c := range names {
names[i] = fmt.Sprintf("%s=$%d", c, i+1)
}
return strings.Join(names, ",")
}
// WhereParams returns a list of sql parameter values for the query // WhereParams returns a list of sql parameter values for the query
func WhereParams(columns map[string]interface{}) []interface{} { func WhereParams(columns map[string]interface{}) []interface{} {
names := make([]string, 0, len(columns)) names := make([]string, 0, len(columns))

View file

@ -50,6 +50,8 @@ var sqlBoilerCommands = map[string]*cobra.Command{
"findselect": findSelectCmd, "findselect": findSelectCmd,
// Delete commands // Delete commands
"delete": deleteCmd, "delete": deleteCmd,
// Update commands
"update": updateCmd,
} }
// sqlBoilerCommandRuns points each command to its custom run function. // sqlBoilerCommandRuns points each command to its custom run function.
@ -77,6 +79,8 @@ var sqlBoilerTemplateFuncs = template.FuncMap{
"scanParamNames": scanParamNames, "scanParamNames": scanParamNames,
"hasPrimaryKey": hasPrimaryKey, "hasPrimaryKey": hasPrimaryKey,
"getPrimaryKey": getPrimaryKey, "getPrimaryKey": getPrimaryKey,
"updateParamNames": updateParamNames,
"updateParamVariables": updateParamVariables,
} }
/* Struct commands */ /* Struct commands */
@ -131,3 +135,10 @@ var deleteCmd = &cobra.Command{
Use: "delete", Use: "delete",
Short: "Generate delete statement helpers from table definitions", Short: "Generate delete statement helpers from table definitions",
} }
/* Update commands */
var updateCmd = &cobra.Command{
Use: "update",
Short: "Generate update statement helpers from table definitions",
}

View file

@ -152,6 +152,41 @@ func makeDBName(tableName, colName string) string {
return tableName + "_" + colName return tableName + "_" + colName
} }
// updateParamNames takes a []DBColumn and returns a comma seperated
// list of parameter names for the update statement template SET clause.
// eg: col1=$1,col2=$2,col3=$3
// Note: updateParamNames will exclude the PRIMARY KEY column.
func updateParamNames(columns []dbdrivers.DBColumn) string {
names := make([]string, 0, len(columns))
counter := 0
for _, c := range columns {
if c.IsPrimaryKey {
continue
}
counter++
names = append(names, fmt.Sprintf("%s=$%d", c.Name, counter))
}
return strings.Join(names, ",")
}
// updateParamVariables takes a prefix and a []DBColumns and returns a
// comma seperated list of parameter variable names for the update statement.
// eg: prefix("o."), column("name_id") -> "o.NameID, ..."
// Note: updateParamVariables will exclude the PRIMARY KEY column.
func updateParamVariables(prefix string, columns []dbdrivers.DBColumn) string {
names := make([]string, 0, len(columns))
for _, c := range columns {
if c.IsPrimaryKey {
continue
}
n := prefix + titleCase(c.Name)
names = append(names, n)
}
return strings.Join(names, ", ")
}
// insertParamNames takes a []DBColumn and returns a comma seperated // insertParamNames takes a []DBColumn and returns a comma seperated
// list of parameter names for the insert statement template. // list of parameter names for the insert statement template.
func insertParamNames(columns []dbdrivers.DBColumn) string { func insertParamNames(columns []dbdrivers.DBColumn) string {

View file

@ -7,8 +7,8 @@ import (
) )
var testColumns = []dbdrivers.DBColumn{ var testColumns = []dbdrivers.DBColumn{
{Name: "friend_column", Type: "int", IsNullable: false}, {Name: "friend_column", Type: "int", IsNullable: false, IsPrimaryKey: false},
{Name: "enemy_column_thing", Type: "string", IsNullable: true}, {Name: "enemy_column_thing", Type: "string", IsNullable: true, IsPrimaryKey: false},
} }
func TestSingular(t *testing.T) { func TestSingular(t *testing.T) {
@ -95,6 +95,36 @@ func TestMakeDBName(t *testing.T) {
} }
} }
func TestUpdateParamNames(t *testing.T) {
t.Parallel()
var testCols = []dbdrivers.DBColumn{
{Name: "id", Type: "int", IsNullable: false, IsPrimaryKey: true},
{Name: "friend_column", Type: "int", IsNullable: false, IsPrimaryKey: false},
{Name: "enemy_column_thing", Type: "string", IsNullable: true, IsPrimaryKey: false},
}
out := updateParamNames(testCols)
if out != "friend_column=$1,enemy_column_thing=$2" {
t.Error("Wrong output:", out)
}
}
func TestUpdateParamVariables(t *testing.T) {
t.Parallel()
var testCols = []dbdrivers.DBColumn{
{Name: "id", Type: "int", IsNullable: false, IsPrimaryKey: true},
{Name: "friend_column", Type: "int", IsNullable: false, IsPrimaryKey: false},
{Name: "enemy_column_thing", Type: "string", IsNullable: true, IsPrimaryKey: false},
}
out := updateParamVariables("o.", testCols)
if out != "o.FriendColumn, o.EnemyColumnThing" {
t.Error("Wrong output:", out)
}
}
func TestInsertParamNames(t *testing.T) { func TestInsertParamNames(t *testing.T) {
t.Parallel() t.Parallel()

32
cmds/templates/update.tpl Normal file
View file

@ -0,0 +1,32 @@
{{- $tableNameSingular := titleCaseSingular .Table -}}
// {{$tableNameSingular}}Update updates a single record.
func {{$tableNameSingular}}Update(db boil.DB, id int, columns map[string]interface{}) error {
if id == 0 {
return nil, errors.New("{{.PkgName}}: no id provided for {{.Table}} update")
}
query := fmt.Sprintf(`UPDATE {{.Table}} SET %s WHERE id=$%d`, boil.Update(columns), len(columns))
err := db.Exec(query, id, boil.WhereParams(columns))
if err != nil {
return errors.New("{{.PkgName}}: unable to update row with ID %d in {{.Table}}: %s", id, err)
}
return nil
}
{{if hasPrimaryKey .Columns -}}
// Update updates a single {{$tableNameSingular}} record.
// Update will match against the primary key column to find the record to update.
// WARNING: This Update method will NOT ignore nil members.
// If you pass in nil members, those columnns will be set to null.
func (o *{{$tableNameSingular}}) Update(db *sqlx.DB) error {
{{- $pkeyName := getPrimaryKey .Columns -}}
err := db.Exec("UPDATE {{.Table}} SET {{updateParamNames .Columns}} WHERE {{$pkeyName}}=${{len .Columns}}", {{updateParamVariables "o." .Columns}}, o.{{titleCase $pkeyName}})
if err != nil {
return errors.New("{{.PkgName}}: unable to update {{.Table}} row using primary key {{$pkeyName}}: %s", err)
}
return nil
}
{{- end}}