gou icon indicating copy to clipboard operation
gou copied to clipboard

some question of soft deletes

Open yflau opened this issue 6 months ago • 0 comments

here are soft delete implemention, I want to confirm some things:

  1. the update restore and update data are not in a transaction? But they should in a transaction.
  2. 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)
}

yflau avatar Jul 29 '24 07:07 yflau