| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 | package omimport (	"errors"	"fmt"	"reflect"	"strings"	"git.simanc.com/software/golib/v4/features/sdb")var (	ErrRowNotFound = errors.New("row not found"))type ORM struct {	TableName string	DB        *sdb.DB}func (o *ORM) Find(query Params, limit LimitParams, order OrderBy) ([]sdb.M, error) {	builder := NewBuilder()	builder.Table(o.TableName)	if err := builder.Query(query); err != nil {		return nil, err	}	builder.Limit(limit)	builder.OrderBy(order)	sql := builder.GetSelectSQL()	values := builder.GetValues()	return o.DB.Query(sql, values...)}func (o *ORM) FindOne(query Params) (sdb.M, error) {	return o.FindOneByOrder(query, OrderBy{})}func (o *ORM) FindOneByOrder(query Params, order OrderBy) (sdb.M, error) {	rows, err := o.Find(query, LimitParams{Limit: 1}, order)	if err != nil {		return nil, err	}	if len(rows) == 0 {		return nil, ErrRowNotFound	}	return rows[0], nil}func (o *ORM) InsertOne(row sdb.M) error {	k, v := o.splitMap(row)	query := CreateInsertSQL(o.TableName, k)	return o.DB.Exec(query, v...)}func (o *ORM) InsertMany(rows []sdb.M) error {	if len(rows) == 0 {		return nil	}	if len(rows) == 1 {		return o.InsertOne(rows[0])	}	k := make([]string, 0, len(rows))	for key := range rows[0] {		k = append(k, key)	}	args := make([][]any, len(rows))	for i, row := range rows {		arg := make([]any, len(k))		for j, key := range k {			if val, ok := row[key]; ok {				arg[j] = val			} else {				return fmt.Errorf("idx:%d key: %s not found", i, key)			}		}		args[i] = arg	}	query := CreateInsertSQL(o.TableName, k)	return o.DB.Execs(query, args...)}func (o *ORM) InsertAny(v any) error {	if row, ok := v.(sdb.M); ok {		return o.InsertOne(row)	}	if rows, ok := v.([]sdb.M); ok {		return o.InsertMany(rows)	}	rk := reflect.ValueOf(v).Kind()	switch rk {	case reflect.Struct:		row, err := sdb.Encode(v)		if err != nil {			return err		}		return o.InsertOne(row)	case reflect.Slice, reflect.Array:		rows, err := sdb.Encodes(v)		if err != nil {			return err		}		return o.InsertMany(rows)	default:		return fmt.Errorf("unsupported value type: %s", rk.String())	}}func (o *ORM) Delete(query Params) error {	builder := NewBuilder()	builder.Table(o.TableName)	if err := builder.Query(query); err != nil {		return err	}	sql := builder.GetDeleteSQL()	value := builder.GetValues()	return o.DB.Exec(sql, value...)}func (o *ORM) Update(query Params, update sdb.M) error {	qk, qv := o.splitMap(query)	k, v := o.splitMap(update)	v = append(v, qv...)	sql := CreateUpdateSql(o.TableName, k, qk...)	return o.DB.Exec(sql, v...)}func (o *ORM) UpdateBySn(sn string, update sdb.M) error {	delete(update, defaultQueryField)	k, v := o.splitMap(update)	v = append(v, sn)	sql := CreateUpdateSql(o.TableName, k, defaultQueryField)	return o.DB.Exec(sql, v...)}func (o *ORM) ListWithParams(query Params, limit LimitParams, orderBy OrderBy) ([]sdb.M, int64, error) {	var total int64 = 0	if limit.Limit > 0 {		total, _ = o.Count(query)		if total <= 0 {			return []sdb.M{}, 0, nil		}	}	retMaps, err := o.Find(query, limit, orderBy)	if err != nil {		return nil, 0, err	}	if limit.Limit == 0 {		total = int64(len(retMaps))	}	return retMaps, total, nil}func (o *ORM) Count(query Params) (int64, error) {	builder := NewBuilder()	builder.Table(o.TableName)	if err := builder.Query(query); err != nil {		return 0, err	}	sql := builder.GetCountSQL()	values := builder.GetValues()	counts, err := o.DB.Count(1, sql, values...)	if err != nil {		return 0, err	}	return counts[0], nil}func (o *ORM) BatchUpdate(update sdb.M, idField string, ids []string) error {	k, v := o.splitMap(update)	sep := `' = ?, '`	columns := strings.Join(k, sep)	ins := func() string {		mark := make([]string, len(ids))		for i := 0; i < len(ids); i++ {			mark[i] = "?"			v = append(v, ids[i])		}		return strings.Join(mark, ", ")	}()	query := fmt.Sprintf(`UPDATE '%s' SET '%s' = ? WHERE %s IN (%s)`, o.TableName, columns, idField, ins)	return o.DB.Exec(query, v...)}func (o *ORM) splitMap(param map[string]any) ([]string, []any) {	var k []string	var v []any	for key, val := range param {		v = append(v, val)		k = append(k, key)	}	return k, v}
 |