codegen: implement auto-timestamps for created_at and updated_at
This commit is contained in:
parent
75b7662c34
commit
5973a2a4b7
@ -40,7 +40,9 @@ create table item_flavor (rowid integer primary key, name text not null) strict;
|
||||
create table items (
|
||||
rowid integer primary key,
|
||||
description text not null default '',
|
||||
flavor integer references item_flavor(rowid)
|
||||
flavor integer references item_flavor(rowid),
|
||||
created_at integer not null,
|
||||
updated_at integer not null
|
||||
) strict;
|
||||
EOF
|
||||
|
||||
|
||||
@ -97,6 +97,9 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
insertVals := make([]string, 0, len(tbl.Columns))
|
||||
updatePairs := make([]string, 0, len(tbl.Columns))
|
||||
|
||||
hasCreatedAt, hasUpdatedAt := tbl.HasAutoTimestamps()
|
||||
|
||||
// Assemble data for building SQL "insert" and "update" strings
|
||||
for _, col := range tbl.Columns {
|
||||
if col.Name == "rowid" {
|
||||
continue
|
||||
@ -107,8 +110,14 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
val = fmt.Sprintf("nullif(%s, 0)", val)
|
||||
}
|
||||
insertVals = append(insertVals, val)
|
||||
// created_at should not be updated after creation
|
||||
if col.Name == "created_at" && hasCreatedAt {
|
||||
continue
|
||||
}
|
||||
updatePairs = append(updatePairs, col.Name+"="+val)
|
||||
}
|
||||
insertStmt := fmt.Sprintf("\n\t\t insert into %s (%s)\n\t\t values (%s)\n\t\t", tbl.TableName, strings.Join(insertCols, ", "), strings.Join(insertVals, ", "))
|
||||
updateStmt := fmt.Sprintf("\n\t\t update %s\n\t\t set %s\n\t\t where rowid = :rowid\n\t\t", tbl.TableName, strings.Join(updatePairs, ",\n\t\t "))
|
||||
|
||||
hasFks := false
|
||||
checkForeignKeyFailuresAssignment := &ast.AssignStmt{
|
||||
@ -235,15 +244,20 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
},
|
||||
}
|
||||
|
||||
insertStmt := fmt.Sprintf("\n\t\t insert into %s (%s)\n\t\t values (%s)\n\t\t", tbl.TableName, strings.Join(insertCols, ", "), strings.Join(insertVals, ", "))
|
||||
updateStmt := fmt.Sprintf("\n\t\t update %s\n\t\t set %s\n\t\t where rowid = :rowid\n\t\t", tbl.TableName, strings.Join(updatePairs, ",\n\t\t "))
|
||||
|
||||
funcBody := &ast.BlockStmt{
|
||||
List: func() []ast.Stmt {
|
||||
ret := []ast.Stmt{}
|
||||
if hasFks {
|
||||
ret = append(ret, checkForeignKeyFailuresAssignment)
|
||||
}
|
||||
if hasUpdatedAt {
|
||||
// Auto-timestamps: updated_at
|
||||
ret = append(ret, &ast.AssignStmt{
|
||||
Lhs: []ast.Expr{&ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent("UpdatedAt")}},
|
||||
Tok: token.ASSIGN,
|
||||
Rhs: []ast.Expr{&ast.CallExpr{Fun: ast.NewIdent("TimestampNow"), Args: []ast.Expr{}}},
|
||||
})
|
||||
}
|
||||
// if item.ID == 0 {...} else {...}
|
||||
ret = append(ret, &ast.IfStmt{
|
||||
Cond: &ast.BinaryExpr{
|
||||
@ -255,6 +269,15 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
// Do create
|
||||
List: append(
|
||||
func() []ast.Stmt {
|
||||
ret := []ast.Stmt{}
|
||||
if hasCreatedAt {
|
||||
// Auto-timestamps: created_at
|
||||
ret = append(ret, &ast.AssignStmt{
|
||||
Lhs: []ast.Expr{&ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent("CreatedAt")}},
|
||||
Tok: token.ASSIGN,
|
||||
Rhs: []ast.Expr{&ast.CallExpr{Fun: ast.NewIdent("TimestampNow"), Args: []ast.Expr{}}},
|
||||
})
|
||||
}
|
||||
namedExecStmt := &ast.CallExpr{
|
||||
Fun: &ast.SelectorExpr{X: ast.NewIdent("db.DB"), Sel: ast.NewIdent("NamedExec")},
|
||||
Args: []ast.Expr{
|
||||
@ -264,19 +287,17 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
}
|
||||
if !hasFks {
|
||||
// No foreign key checking needed; just use `Must` for brevity
|
||||
return []ast.Stmt{
|
||||
&ast.AssignStmt{
|
||||
Lhs: []ast.Expr{ast.NewIdent("result")},
|
||||
Tok: token.DEFINE,
|
||||
Rhs: []ast.Expr{&ast.CallExpr{
|
||||
Fun: ast.NewIdent("Must"),
|
||||
Args: []ast.Expr{namedExecStmt},
|
||||
}},
|
||||
},
|
||||
}
|
||||
return append(ret, &ast.AssignStmt{
|
||||
Lhs: []ast.Expr{ast.NewIdent("result")},
|
||||
Tok: token.DEFINE,
|
||||
Rhs: []ast.Expr{&ast.CallExpr{
|
||||
Fun: ast.NewIdent("Must"),
|
||||
Args: []ast.Expr{namedExecStmt},
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
return []ast.Stmt{
|
||||
return append(ret,
|
||||
// result, err := db.DB.NamedExec(`...`, u)
|
||||
&ast.AssignStmt{
|
||||
Lhs: []ast.Expr{
|
||||
@ -329,7 +350,7 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
}(),
|
||||
&ast.AssignStmt{
|
||||
Lhs: []ast.Expr{&ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent("ID")}},
|
||||
|
||||
@ -46,6 +46,18 @@ type Table struct {
|
||||
GoTypeName string
|
||||
}
|
||||
|
||||
func (t Table) HasAutoTimestamps() (hasCreatedAt bool, hasUpdatedAt bool) {
|
||||
for _, c := range t.Columns {
|
||||
if c.Name == "created_at" && c.Type == "integer" {
|
||||
hasCreatedAt = true
|
||||
}
|
||||
if c.Name == "updated_at" && c.Type == "integer" {
|
||||
hasUpdatedAt = true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Index struct {
|
||||
Name string `db:"index_name"`
|
||||
TableName string `db:"table_name"`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user