codegen: add generator for soft-deletion
This commit is contained in:
@@ -296,6 +296,7 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
updatePairs := make([]string, 0, len(tbl.Columns))
|
||||
|
||||
hasCreatedAt, hasUpdatedAt := tbl.HasAutoTimestamps()
|
||||
hasSoftDelete := tbl.HasSoftDelete()
|
||||
|
||||
// Assemble data for building SQL "insert" and "update" strings
|
||||
for _, col := range tbl.Columns {
|
||||
@@ -312,6 +313,10 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
if col.Name == "created_at" && hasCreatedAt {
|
||||
continue
|
||||
}
|
||||
// Soft-delete state is managed by SoftDeleteXyz(), not by updates
|
||||
if hasSoftDelete && (col.Name == "is_deleted" || col.Name == "deleted_at") {
|
||||
continue
|
||||
}
|
||||
if !col.IsPrimaryKey { // Don't try to update primary key columns (mainly for w/o rowid tables)
|
||||
updatePairs = append(updatePairs, col.Name+"="+val)
|
||||
}
|
||||
@@ -828,6 +833,66 @@ func GenerateDeleteItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
return funcDecl
|
||||
}
|
||||
|
||||
// GenerateSoftDeleteItemFunc produces an AST for the `SoftDeleteXyz()` function, which is only
|
||||
// generated for tables that have both an "is_deleted" and a "deleted_at" column.
|
||||
// E.g., a table with `table.TypeName = "foods"` will produce a "SoftDeleteFood()" function.
|
||||
func GenerateSoftDeleteItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
whereClauses := []string{}
|
||||
for _, c := range tbl.PrimaryKeyColumns() {
|
||||
whereClauses = append(whereClauses, fmt.Sprintf("%s = :%s", c.Name, c.Name))
|
||||
}
|
||||
setPairs := []string{"is_deleted = :is_deleted", "deleted_at = :deleted_at"}
|
||||
|
||||
updateStmt := fmt.Sprintf("\n\t update %s\n\t set %s\n\t where %s\n\t",
|
||||
tbl.TableName,
|
||||
strings.Join(setPairs, ",\n\t "),
|
||||
strings.Join(whereClauses, " and "),
|
||||
)
|
||||
|
||||
funcBody := &ast.BlockStmt{
|
||||
List: []ast.Stmt{
|
||||
// item.IsDeleted = true
|
||||
&ast.AssignStmt{
|
||||
Lhs: []ast.Expr{&ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent(tbl.GetColumnByName("is_deleted").GoFieldName())}},
|
||||
Tok: token.ASSIGN,
|
||||
Rhs: []ast.Expr{ast.NewIdent("true")},
|
||||
},
|
||||
// item.DeletedAt = TimestampNow()
|
||||
&ast.AssignStmt{
|
||||
Lhs: []ast.Expr{&ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent(tbl.GetColumnByName("deleted_at").GoFieldName())}},
|
||||
Tok: token.ASSIGN,
|
||||
Rhs: []ast.Expr{&ast.CallExpr{Fun: ast.NewIdent("TimestampNow"), Args: []ast.Expr{}}},
|
||||
},
|
||||
// result := must.Get(db.DB.NamedExec(...))
|
||||
&ast.AssignStmt{
|
||||
Lhs: []ast.Expr{ast.NewIdent("result")},
|
||||
Tok: token.DEFINE,
|
||||
Rhs: []ast.Expr{mustCall(&ast.CallExpr{
|
||||
Fun: &ast.SelectorExpr{X: dbDB, Sel: ast.NewIdent("NamedExec")},
|
||||
Args: []ast.Expr{
|
||||
&ast.BasicLit{Kind: token.STRING, Value: "`" + updateStmt + "`"},
|
||||
ast.NewIdent(tbl.VarName),
|
||||
},
|
||||
})},
|
||||
},
|
||||
MustBeRowsAffected(tbl),
|
||||
},
|
||||
}
|
||||
|
||||
return &ast.FuncDecl{
|
||||
Doc: &ast.CommentGroup{List: []*ast.Comment{
|
||||
{Text: fmt.Sprintf("// SoftDelete%s sets deleted-at and marks the item as deleted.", tbl.GoTypeName)},
|
||||
}},
|
||||
Recv: dbRecv,
|
||||
Name: ast.NewIdent("SoftDelete" + tbl.GoTypeName),
|
||||
Type: &ast.FuncType{Params: &ast.FieldList{List: []*ast.Field{{
|
||||
Names: []*ast.Ident{ast.NewIdent(tbl.VarName)},
|
||||
Type: &ast.StarExpr{X: ast.NewIdent(tbl.GoTypeName)},
|
||||
}}}, Results: nil},
|
||||
Body: funcBody,
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateSQLFieldsConst produces an AST for the `const xyzSQLFields = ...` string.
|
||||
func GenerateSQLFieldsConst(tbl schema.Table) *ast.GenDecl {
|
||||
columns := make([]string, 0, len(tbl.Columns))
|
||||
|
||||
Reference in New Issue
Block a user