gou
gou copied to clipboard
some question of soft deletes
here are soft delete implemention, I want to confirm some things:
- the update restore and update data are not in a transaction? But they should in a transaction.
- only string and not null column will be modified, but e.g. if the index only contains non-string && non-null columns, it will be conflict.
func (mod *Model) DeleteWhere(param QueryParam) (int, error) {
// 软删除
if mod.MetaData.Option.SoftDeletes {
// 兼容 SQLite3
if mod.Driver == "sqlite3" {
return mod.sqlite3DeleteWhere(param)
}
data := maps.MapStrAny{}
columns := []string{}
for _, col := range mod.UniqueColumns {
typ := strings.ToLower(col.Type)
if typ == "string" {
data[col.Name] = dbal.Raw(fmt.Sprintf("CONCAT_WS('_', '%d')", time.Now().UnixNano()))
columns = append(
columns,
fmt.Sprintf("CONCAT('\"%s\":\"', `%s`, '\"')", col.Name, col.Name),
)
} else { // 数字, 布尔型等
columns = append(
columns,
fmt.Sprintf("CONCAT('\"%s\":', `%s`)", col.Name, col.Name),
)
}
if col.Nullable {
data[col.Name] = nil
}
}
param.Model = mod.Name
stack := NewQueryStack(param)
qb := stack.FirstQuery()
// 备份唯一数据
if len(columns) > 0 {
restore := dbal.Raw("CONCAT('{'," + strings.Join(columns, ",',',") + ",'}')")
_, err := qb.Update(maps.MapStr{"__restore_data": restore})
if err != nil {
return 0, err
}
}
// 删除数据
field := fmt.Sprintf("%s.%s", mod.MetaData.Table.Name, "deleted_at")
// data["deleted_at"] = dbal.Raw("CURRENT_TIMESTAMP")
data[field] = dbal.Raw("CURRENT_TIMESTAMP")
effect, err := qb.Update(data)
if err != nil {
return 0, err
}
return int(effect), nil
}
return mod.DestroyWhere(param)
}