Added primary key flag to column data

* Added delete method attached to object
* Added primary key related template helper functions
This commit is contained in:
Patrick O'brien 2016-03-19 01:27:55 +10:00
parent 2f9c936c6a
commit 54f6e43370
6 changed files with 83 additions and 20 deletions

View file

@ -75,6 +75,8 @@ var sqlBoilerTemplateFuncs = template.FuncMap{
"insertParamFlags": insertParamFlags,
"insertParamVariables": insertParamVariables,
"scanParamNames": scanParamNames,
"hasPrimaryKey": hasPrimaryKey,
"getPrimaryKey": getPrimaryKey,
}
/* Struct commands */

View file

@ -48,15 +48,22 @@ func defaultRun(cmd *cobra.Command, args []string) {
PkgName: cmdData.PkgName,
}
// outHandler takes a slice of byte slices, so append the Template
// execution output to a [][]byte before sending it to outHandler.
out := [][]byte{generateTemplate(cmd.Name(), &data)}
templater(cmd, &data)
}
}
imps := combineImports(sqlBoilerDefaultImports, sqlBoilerCustomImports[cmd.Name()])
err := outHandler(cmdData.OutFolder, out, &data, &imps)
if err != nil {
errorQuit(fmt.Errorf("Unable to generate the template for command %s: %s", cmd.Name(), err))
}
// templater generates the template by passing it the tplData object.
// Once the template is generated, it will add the imports to the output stream
// and output the contents of the template with the added bits (imports and package declaration).
func templater(cmd *cobra.Command, data *tplData) {
// outHandler takes a slice of byte slices, so append the Template
// execution output to a [][]byte before sending it to outHandler.
out := [][]byte{generateTemplate(cmd.Name(), data)}
imps := combineImports(sqlBoilerDefaultImports, sqlBoilerCustomImports[cmd.Name()])
err := outHandler(cmdData.OutFolder, out, data, &imps)
if err != nil {
errorQuit(fmt.Errorf("Unable to generate the template for command %s: %s", cmd.Name(), err))
}
}

View file

@ -211,3 +211,25 @@ func scanParamNames(object string, columns []dbdrivers.DBColumn) string {
return strings.Join(scans, ", ")
}
// hasPrimaryKey returns true if one of the columns passed in is a primary key
func hasPrimaryKey(columns []dbdrivers.DBColumn) bool {
for _, c := range columns {
if c.IsPrimaryKey {
return true
}
}
return false
}
// getPrimaryKey returns the primary key column name if one is present
func getPrimaryKey(columns []dbdrivers.DBColumn) string {
for _, c := range columns {
if c.IsPrimaryKey {
return c.Name
}
}
return ""
}

View file

@ -12,3 +12,17 @@ func {{$tableNameSingular}}Delete(db boil.DB, id int) error {
return nil
}
{{if hasPrimaryKey .Columns -}}
// Delete deletes a single {{$tableNameSingular}} record.
// Delete will match against the primary key column to find the record to delete.
func (o *{{$tableNameSingular}}) Delete(db *sqlx.DB) error {
{{- $pkeyName := getPrimaryKey .Columns -}}
err := db.Exec("DELETE FROM {{.Table}} WHERE {{$pkeyName}}=$1", o.{{titleCase $pkeyName}})
if err != nil {
return errors.New("{{.PkgName}}: unable to delete from {{.Table}}: %s", err)
}
return nil
}
{{- end}}

View file

@ -17,7 +17,7 @@ type DBDriver interface {
// ParseTableInfo builds a DBColumn out of a column name and column type.
// Its main responsibility is to convert database types to Go types, for example
// "varchar" to "string".
ParseTableInfo(name, colType string, isNullable bool) DBColumn
ParseTableInfo(name, colType string, isNullable bool, isPrimary bool) DBColumn
// Open the database connection
Open() error
@ -29,7 +29,8 @@ type DBDriver interface {
// DBColumn holds information about a database column name.
// Column types are Go types, converted by ParseTableInfo.
type DBColumn struct {
Name string
Type string
IsNullable bool
Name string
Type string
IsPrimaryKey bool
IsNullable bool
}

View file

@ -76,10 +76,23 @@ func (d *PostgresDriver) GetAllTables() ([]string, error) {
// and column types and returns those as a []DBColumn after ParseTableInfo()
// converts the SQL types to Go types, for example: "varchar" to "string"
func (d *PostgresDriver) GetTableInfo(tableName string) ([]DBColumn, error) {
var tableInfo []DBColumn
var table []DBColumn
rows, err := d.dbConn.Query(`select column_name, data_type, is_nullable from
information_schema.columns where table_name=$1`, tableName)
rows, err := d.dbConn.Query(`
SELECT c.column_name, c.data_type, c.is_nullable,
CASE WHEN pk.column_name IS NOT NULL THEN 'PRIMARY KEY' ELSE '' END AS KeyType
FROM information_schema.columns c
LEFT JOIN (
SELECT ku.table_name, ku.column_name
FROM information_schema.table_constraints AS tc
INNER JOIN information_schema.key_column_usage AS ku
ON tc.constraint_type = 'PRIMARY KEY'
AND tc.constraint_name = ku.constraint_name
) pk
ON c.table_name = pk.table_name
AND c.column_name = pk.column_name
WHERE c.table_name=$1
`, tableName)
if err != nil {
return nil, err
@ -87,23 +100,27 @@ func (d *PostgresDriver) GetTableInfo(tableName string) ([]DBColumn, error) {
defer rows.Close()
for rows.Next() {
var colName, colType, isNullable string
if err := rows.Scan(&colName, &colType, &isNullable); err != nil {
var colName, colType, isNullable, isPrimary string
if err := rows.Scan(&colName, &colType, &isNullable, &isPrimary); err != nil {
return nil, err
}
tableInfo = append(tableInfo, d.ParseTableInfo(colName, colType, "YES" == isNullable))
t := d.ParseTableInfo(colName, colType, isNullable == "YES", isPrimary == "PRIMARY KEY")
table = append(table, t)
}
return tableInfo, nil
return table, nil
}
// ParseTableInfo converts postgres database types to Go types, for example
// "varchar" to "string" and "bigint" to "int64". It returns this parsed data
// as a DBColumn object.
func (d *PostgresDriver) ParseTableInfo(colName, colType string, isNullable bool) DBColumn {
func (d *PostgresDriver) ParseTableInfo(colName, colType string, isNullable bool, isPrimary bool) DBColumn {
var t DBColumn
t.Name = colName
t.IsPrimaryKey = isPrimary
t.IsNullable = isNullable
if isNullable {
switch colType {
case "bigint", "bigserial", "integer", "smallint", "smallserial", "serial":