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 (
|
create table items (
|
||||||
rowid integer primary key,
|
rowid integer primary key,
|
||||||
description text not null default '',
|
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;
|
) strict;
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|||||||
@ -97,6 +97,9 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
insertVals := make([]string, 0, len(tbl.Columns))
|
insertVals := make([]string, 0, len(tbl.Columns))
|
||||||
updatePairs := 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 {
|
for _, col := range tbl.Columns {
|
||||||
if col.Name == "rowid" {
|
if col.Name == "rowid" {
|
||||||
continue
|
continue
|
||||||
@ -107,8 +110,14 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
val = fmt.Sprintf("nullif(%s, 0)", val)
|
val = fmt.Sprintf("nullif(%s, 0)", val)
|
||||||
}
|
}
|
||||||
insertVals = append(insertVals, 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)
|
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
|
hasFks := false
|
||||||
checkForeignKeyFailuresAssignment := &ast.AssignStmt{
|
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{
|
funcBody := &ast.BlockStmt{
|
||||||
List: func() []ast.Stmt {
|
List: func() []ast.Stmt {
|
||||||
ret := []ast.Stmt{}
|
ret := []ast.Stmt{}
|
||||||
if hasFks {
|
if hasFks {
|
||||||
ret = append(ret, checkForeignKeyFailuresAssignment)
|
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 {...}
|
// if item.ID == 0 {...} else {...}
|
||||||
ret = append(ret, &ast.IfStmt{
|
ret = append(ret, &ast.IfStmt{
|
||||||
Cond: &ast.BinaryExpr{
|
Cond: &ast.BinaryExpr{
|
||||||
@ -255,6 +269,15 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
// Do create
|
// Do create
|
||||||
List: append(
|
List: append(
|
||||||
func() []ast.Stmt {
|
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{
|
namedExecStmt := &ast.CallExpr{
|
||||||
Fun: &ast.SelectorExpr{X: ast.NewIdent("db.DB"), Sel: ast.NewIdent("NamedExec")},
|
Fun: &ast.SelectorExpr{X: ast.NewIdent("db.DB"), Sel: ast.NewIdent("NamedExec")},
|
||||||
Args: []ast.Expr{
|
Args: []ast.Expr{
|
||||||
@ -264,19 +287,17 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
}
|
}
|
||||||
if !hasFks {
|
if !hasFks {
|
||||||
// No foreign key checking needed; just use `Must` for brevity
|
// No foreign key checking needed; just use `Must` for brevity
|
||||||
return []ast.Stmt{
|
return append(ret, &ast.AssignStmt{
|
||||||
&ast.AssignStmt{
|
|
||||||
Lhs: []ast.Expr{ast.NewIdent("result")},
|
Lhs: []ast.Expr{ast.NewIdent("result")},
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
Rhs: []ast.Expr{&ast.CallExpr{
|
Rhs: []ast.Expr{&ast.CallExpr{
|
||||||
Fun: ast.NewIdent("Must"),
|
Fun: ast.NewIdent("Must"),
|
||||||
Args: []ast.Expr{namedExecStmt},
|
Args: []ast.Expr{namedExecStmt},
|
||||||
}},
|
}},
|
||||||
},
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return []ast.Stmt{
|
return append(ret,
|
||||||
// result, err := db.DB.NamedExec(`...`, u)
|
// result, err := db.DB.NamedExec(`...`, u)
|
||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{
|
Lhs: []ast.Expr{
|
||||||
@ -329,7 +350,7 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
)
|
||||||
}(),
|
}(),
|
||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{&ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent("ID")}},
|
Lhs: []ast.Expr{&ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent("ID")}},
|
||||||
|
|||||||
@ -46,6 +46,18 @@ type Table struct {
|
|||||||
GoTypeName string
|
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 {
|
type Index struct {
|
||||||
Name string `db:"index_name"`
|
Name string `db:"index_name"`
|
||||||
TableName string `db:"table_name"`
|
TableName string `db:"table_name"`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user