| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 | 
							- package om
 
- import (
 
- 	"fmt"
 
- 	"reflect"
 
- 	"strings"
 
- 	"golib/v4/features/sdb"
 
- )
 
- type Builder struct {
 
- 	table   string
 
- 	query   []Condition
 
- 	limit   int64
 
- 	offset  int64
 
- 	orders  []string
 
- 	groupBy string
 
- }
 
- func (b *Builder) Table(table string) {
 
- 	b.table = table
 
- }
 
- func (b *Builder) Query(params Params) error {
 
- 	for k, v := range params {
 
- 		if err := b.addQueryCondition(k, v); err != nil {
 
- 			return err
 
- 		}
 
- 	}
 
- 	return nil
 
- }
 
- func (b *Builder) GroupBy(groupBy string) {
 
- 	b.groupBy = groupBy
 
- }
 
- func (b *Builder) Limit(params LimitParams) {
 
- 	b.limit = params.Limit
 
- 	b.offset = params.Offset
 
- }
 
- func (b *Builder) OrderBy(orderBy OrderBy) {
 
- 	for k, v := range orderBy {
 
- 		b.orders = append(b.orders, k+" "+string(v))
 
- 	}
 
- }
 
- func (b *Builder) addQueryCondition(key string, value any) error {
 
- 	switch key[:1] {
 
- 	case "-":
 
- 		b.query = append(b.query, NewCondition(key[1:], value, Like))
 
- 	case "%":
 
- 		if v, ok := value.(string); ok {
 
- 			b.query = append(b.query, NewCondition(key[1:], "%"+v+"%", Like))
 
- 		} else {
 
- 			return fmt.Errorf("addQueryCondition: add filter err: startswith not string key: %s val: %v", key, value)
 
- 		}
 
- 	case ">":
 
- 		b.query = append(b.query, NewCondition(key[1:], value, Ge))
 
- 	case "<":
 
- 		b.query = append(b.query, NewCondition(key[1:], value, Le))
 
- 	case "|":
 
- 		// only slice/array params supported
 
- 		rvk := reflect.ValueOf(value).Kind()
 
- 		if rvk != reflect.Slice && rvk != reflect.Array {
 
- 			return fmt.Errorf("addQueryCondition: only slice/array params supported: key: %s val: %v", key, value)
 
- 		}
 
- 		b.query = append(b.query, NewCondition(key[1:], value, Equ))
 
- 	case "!":
 
- 		// single or slice/array params supported
 
- 		b.query = append(b.query, NewCondition(key[1:], value, UnEqu))
 
- 	default:
 
- 		b.query = append(b.query, NewCondition(key, value))
 
- 	}
 
- 	return nil
 
- }
 
- func (b *Builder) GetConditionSQLs() string {
 
- 	var sql string
 
- 	if len(b.query) > 0 {
 
- 		for _, cond := range b.query {
 
- 			if len(sql) > 0 {
 
- 				sql = sql + AND + " "
 
- 			}
 
- 			rv := reflect.ValueOf(cond.Value)
 
- 			switch rv.Kind() {
 
- 			case reflect.Slice, reflect.Array:
 
- 				sql = fmt.Sprintf("%s ( %s %s ? ", sql, cond.FieldName, cond.Opt)
 
- 				// start with 1
 
- 				for i := 1; i < rv.Len(); i++ {
 
- 					sql = fmt.Sprintf("%s OR %s %s ? ", sql, cond.FieldName, cond.Opt)
 
- 				}
 
- 				sql = sql + ")" + " "
 
- 			default:
 
- 				// sql + AND table.sec opt ?
 
- 				sql = sql + cond.FieldName + " " + cond.Opt + " ? "
 
- 			}
 
- 		}
 
- 	}
 
- 	return sql
 
- }
 
- func (b *Builder) GetCountSQL() string {
 
- 	sql := fmt.Sprintf("SELECT COUNT(sn) as count FROM %s ", b.table)
 
- 	if len(b.query) > 0 {
 
- 		sql = sql + "WHERE " + b.GetConditionSQLs()
 
- 	}
 
- 	if b.groupBy != "" {
 
- 		sql = sql + " GROUP BY " + b.groupBy
 
- 	}
 
- 	return sql
 
- }
 
- func (b *Builder) GetSumSQL() string {
 
- 	sql := fmt.Sprintf("SELECT ROUND(SUM(%s),2) FROM %s ", b.groupBy, b.table)
 
- 	if len(b.query) > 0 {
 
- 		sql = sql + "WHERE " + b.GetConditionSQLs()
 
- 	}
 
- 	return sql
 
- }
 
- func (b *Builder) GetDeleteSQL() string {
 
- 	sql := fmt.Sprintf("DELETE FROM %s ", b.table)
 
- 	if len(b.query) > 0 {
 
- 		sql = sql + "WHERE " + b.GetConditionSQLs()
 
- 		return sql
 
- 	}
 
- 	return b.GetCustomerSQL(sql)
 
- }
 
- func (b *Builder) GetSelectSQL() string {
 
- 	sql := fmt.Sprintf("SELECT * FROM %s ", b.table)
 
- 	return b.GetCustomerSQL(sql)
 
- }
 
- func (b *Builder) GetCustomerSQL(sql string) string {
 
- 	if !strings.HasSuffix(sql, " ") {
 
- 		sql = sql + " "
 
- 	}
 
- 	if len(b.query) > 0 {
 
- 		if strings.Contains(strings.ToUpper(sql), "WHERE") {
 
- 			sql = sql + "AND "
 
- 		} else {
 
- 			sql = sql + "WHERE "
 
- 		}
 
- 		sql = sql + b.GetConditionSQLs()
 
- 	}
 
- 	if b.groupBy != "" {
 
- 		sql = sql + " GROUP BY " + b.groupBy + " "
 
- 	}
 
- 	if len(b.orders) > 0 {
 
- 		sql = sql + "ORDER BY "
 
- 		for idx, v := range b.orders {
 
- 			if idx > 0 {
 
- 				sql = sql + ", "
 
- 			}
 
- 			sql = sql + v + " "
 
- 		}
 
- 	}
 
- 	if b.limit > 0 {
 
- 		sql = sql + fmt.Sprintf("LIMIT %d ", b.limit)
 
- 	}
 
- 	if b.offset > 0 {
 
- 		if b.limit == 0 {
 
- 			sql = sql + "LIMIT -1 " // SQLte3 also requires Limit to exist if OFFSET exists
 
- 		}
 
- 		sql = sql + fmt.Sprintf("OFFSET %d ", b.offset)
 
- 	}
 
- 	return sql
 
- }
 
- func (b *Builder) GetValues() []any {
 
- 	values := make([]any, 0)
 
- 	for _, cond := range b.query {
 
- 		rv := reflect.ValueOf(cond.Value)
 
- 		switch rv.Kind() {
 
- 		case reflect.Slice, reflect.Array:
 
- 			for i := 0; i < rv.Len(); i++ {
 
- 				values = append(values, rv.Index(i).Interface())
 
- 			}
 
- 		default:
 
- 			values = append(values, cond.Value)
 
- 		}
 
- 	}
 
- 	return values
 
- }
 
- func NewBuilder() *Builder {
 
- 	o := &Builder{}
 
- 	return o
 
- }
 
- func CreateUpdateSql(table string, valueFields []string, idFields ...string) string {
 
- 	sep := fmt.Sprintf("%s = ?, %s", Q, Q)
 
- 	columns := strings.Join(valueFields, sep)
 
- 	sql := fmt.Sprintf("UPDATE %s%s%s SET %s%s%s = ?", Q, table, Q, Q, columns, Q)
 
- 	if len(idFields) > 0 {
 
- 		idColumns := strings.Join(idFields, " = ? AND ")
 
- 		sql = fmt.Sprintf("%s WHERE %s = ?", sql, idColumns)
 
- 	} else {
 
- 		// 如果不存在更新条件, 则更新所有数据
 
- 		// realIdFields = []string{defaultQueryField}
 
- 	}
 
- 	return sql
 
- }
 
- func CreateInsertSQL(table string, cols []string) string {
 
- 	mark := make([]string, len(cols))
 
- 	for i := range mark {
 
- 		mark[i] = "?"
 
- 	}
 
- 	sep := fmt.Sprintf("%s, %s", Q, Q)
 
- 	columns := strings.Join(cols, sep)
 
- 	qMarks := strings.Join(mark, ", ")
 
- 	return fmt.Sprintf(`INSERT INTO '%s' ('%s') VALUES (%s)`, table, columns, qMarks)
 
- }
 
- func CreateInsertSqlWithNum(table string, cols []string, max int) string {
 
- 	mark := make([]string, len(cols))
 
- 	for i := range mark {
 
- 		mark[i] = "?"
 
- 	}
 
- 	sep := fmt.Sprintf("%s, %s", Q, Q)
 
- 	qMarks := strings.Join(mark, ", ")
 
- 	columns := strings.Join(cols, sep)
 
- 	header := fmt.Sprintf(`INSERT INTO '%s' ('%s') `, table, columns)
 
- 	vl := make([]string, max)
 
- 	for i := 0; i < max; i++ {
 
- 		vl[i] = fmt.Sprintf("(%s)", qMarks)
 
- 	}
 
- 	header += fmt.Sprintf("VALUES %s", strings.Join(vl, ", "))
 
- 	return header
 
- }
 
- type TableColumn struct {
 
- 	Key     string
 
- 	Type    string
 
- 	Default any
 
- 	Notnull bool
 
- 	Unique  bool
 
- }
 
- func (t TableColumn) SQL() string {
 
- 	notNull := func() string {
 
- 		if t.Notnull {
 
- 			return "NOT NULL "
 
- 		}
 
- 		return "NULL "
 
- 	}
 
- 	value := func() string {
 
- 		if t.Default == nil {
 
- 			return ""
 
- 		}
 
- 		switch t.Type {
 
- 		case sdb.TypeINTEGER, sdb.TypeREAL, sdb.TypeUINT:
 
- 			return fmt.Sprintf(`DEFAULT %v `, t.Default)
 
- 		case sdb.TypeTEXT:
 
- 			return fmt.Sprintf(`DEFAULT '%v' `, t.Default)
 
- 		case sdb.TypeBOOLEAN:
 
- 			if t.Default == true {
 
- 				return `DEFAULT 1 `
 
- 			} else {
 
- 				return `DEFAULT 0 `
 
- 			}
 
- 		default:
 
- 			return ""
 
- 		}
 
- 	}
 
- 	unique := func() string {
 
- 		if t.Unique {
 
- 			return "UNIQUE "
 
- 		}
 
- 		return ""
 
- 	}
 
- 	return fmt.Sprintf(`%s %s %s%s%s`, t.Key, t.Type, notNull(), unique(), value())
 
- }
 
- func CreateTableSQL(name string, column []TableColumn) string {
 
- 	column = append(column,
 
- 		TableColumn{Key: "sn", Type: sdb.TypeTEXT, Notnull: true, Unique: true},
 
- 	)
 
- 	str := make([]string, len(column))
 
- 	for i, col := range column {
 
- 		str[i] = col.SQL()
 
- 	}
 
- 	sql := `CREATE TABLE %s (id INTEGER PRIMARY KEY Autoincrement NOT NULL, %s, creationTime INTEGER DEFAULT CURRENT_TIMESTAMP)`
 
- 	return fmt.Sprintf(sql, name, strings.Join(str, ", "))
 
- }
 
 
  |