github.com/godaddy-x/freego@v1.0.156/ormx/sqld/base_manager.go (about)

     1  package sqld
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"database/sql"
     7  	"github.com/godaddy-x/freego/cache"
     8  	DIC "github.com/godaddy-x/freego/common"
     9  	"github.com/godaddy-x/freego/ormx/sqlc"
    10  	"github.com/godaddy-x/freego/ormx/sqld/dialect"
    11  	"github.com/godaddy-x/freego/utils"
    12  	"github.com/godaddy-x/freego/zlog"
    13  	"reflect"
    14  	"time"
    15  )
    16  
    17  var (
    18  	ZERO  = int64(0)
    19  	TRUE  = true
    20  	FALSE = false
    21  	rdbs  = map[string]*RDBManager{}
    22  )
    23  
    24  const (
    25  	SAVE          = 1
    26  	UPDATE        = 2
    27  	DELETE        = 3
    28  	UPDATE_BY_CND = 4
    29  )
    30  
    31  /********************************** 数据库配置参数 **********************************/
    32  
    33  // 数据库配置
    34  type DBConfig struct {
    35  	Option
    36  	Host        string // 地址IP
    37  	Port        int    // 数据库端口
    38  	Username    string // 账号
    39  	Password    string // 密码
    40  	SlowQuery   int64  // 0.不开启筛选 >0开启筛选查询 毫秒
    41  	SlowLogPath string // 慢查询写入地址
    42  }
    43  
    44  // 数据选项
    45  type Option struct {
    46  	DsName      string // 数据源,分库时使用
    47  	Database    string // 数据库名称
    48  	Charset     string // 连接字符集,默认utf8mb4
    49  	OpenTx      bool   // 是否开启事务 true.是 false.否
    50  	AutoID      bool   // 是否自增ID
    51  	MongoSync   bool   // 是否自动同步mongo数据库写入
    52  	Timeout     int64  // 请求超时设置/毫秒,默认10000
    53  	SlowQuery   int64  // 0.不开启筛选 >0开启筛选查询 毫秒
    54  	SlowLogPath string // 慢查询写入地址
    55  }
    56  
    57  type MGOSyncData struct {
    58  	CacheOption int           // 1.save 2.update 3.delete
    59  	CacheModel  sqlc.Object   // 对象模型
    60  	CacheCnd    *sqlc.Cnd     // 需要缓存的数据 CacheSync为true时有效
    61  	CacheObject []sqlc.Object // 需要缓存的数据 CacheSync为true时有效
    62  }
    63  
    64  // 数据库管理器
    65  type DBManager struct {
    66  	Option
    67  	CacheManager cache.Cache    // 缓存管理器
    68  	MGOSyncData  []*MGOSyncData // 同步数据对象
    69  	Errors       []error        // 错误异常记录
    70  }
    71  
    72  /********************************** 数据库ORM实现 **********************************/
    73  
    74  // orm数据库接口
    75  type IDBase interface {
    76  	// 初始化数据库配置
    77  	InitConfig(input interface{}) error
    78  	// 获取数据库管理器
    79  	GetDB(option ...Option) error
    80  	// 保存数据
    81  	Save(datas ...sqlc.Object) error
    82  	// 更新数据
    83  	Update(datas ...sqlc.Object) error
    84  	// 按条件更新数据
    85  	UpdateByCnd(cnd *sqlc.Cnd) (int64, error)
    86  	// 删除数据
    87  	Delete(datas ...sqlc.Object) error
    88  	// 删除数据
    89  	DeleteById(object sqlc.Object, data ...interface{}) (int64, error)
    90  	// 按条件删除数据
    91  	DeleteByCnd(cnd *sqlc.Cnd) (int64, error)
    92  	// 统计数据
    93  	Count(cnd *sqlc.Cnd) (int64, error)
    94  	// 检测是否存在
    95  	Exists(cnd *sqlc.Cnd) (bool, error)
    96  	// 按ID查询单条数据
    97  	FindById(data sqlc.Object) error
    98  	// 按条件查询单条数据
    99  	FindOne(cnd *sqlc.Cnd, data sqlc.Object) error
   100  	// 按条件查询数据
   101  	FindList(cnd *sqlc.Cnd, data interface{}) error
   102  	// 按复杂条件查询数据
   103  	FindOneComplex(cnd *sqlc.Cnd, data sqlc.Object) error
   104  	// 按复杂条件查询数据列表
   105  	FindListComplex(cnd *sqlc.Cnd, data interface{}) error
   106  	// 构建数据表别名
   107  	BuildCondKey(cnd *sqlc.Cnd, key string) []byte
   108  	// 构建逻辑条件
   109  	BuildWhereCase(cnd *sqlc.Cnd) (*bytes.Buffer, []interface{})
   110  	// 构建分组条件
   111  	BuildGroupBy(cnd *sqlc.Cnd) string
   112  	// 构建排序条件
   113  	BuildSortBy(cnd *sqlc.Cnd) string
   114  	// 构建分页条件
   115  	BuildPagination(cnd *sqlc.Cnd, sql string, values []interface{}) (string, error)
   116  	// 数据库操作缓存异常
   117  	Error(data ...interface{}) error
   118  }
   119  
   120  func (self *DBManager) InitConfig(input interface{}) error {
   121  	return utils.Error("No implementation method [InitConfig] was found")
   122  }
   123  
   124  func (self *DBManager) GetDB(option ...Option) error {
   125  	return utils.Error("No implementation method [GetDB] was found")
   126  }
   127  
   128  func (self *DBManager) Save(datas ...sqlc.Object) error {
   129  	return utils.Error("No implementation method [Save] was found")
   130  }
   131  
   132  func (self *DBManager) Update(datas ...sqlc.Object) error {
   133  	return utils.Error("No implementation method [Update] was found")
   134  }
   135  
   136  func (self *DBManager) UpdateByCnd(cnd *sqlc.Cnd) (int64, error) {
   137  	return 0, utils.Error("No implementation method [UpdateByCnd] was found")
   138  }
   139  
   140  func (self *DBManager) Delete(datas ...sqlc.Object) error {
   141  	return utils.Error("No implementation method [Delete] was found")
   142  }
   143  
   144  func (self *DBManager) DeleteById(object sqlc.Object, data ...interface{}) (int64, error) {
   145  	return 0, utils.Error("No implementation method [DeleteById] was found")
   146  }
   147  
   148  func (self *DBManager) DeleteByCnd(cnd *sqlc.Cnd) (int64, error) {
   149  	return 0, utils.Error("No implementation method [DeleteByCnd] was found")
   150  }
   151  
   152  func (self *DBManager) Count(cnd *sqlc.Cnd) (int64, error) {
   153  	return 0, utils.Error("No implementation method [Count] was found")
   154  }
   155  
   156  func (self *DBManager) Exists(cnd *sqlc.Cnd) (bool, error) {
   157  	return false, utils.Error("No implementation method [Exists] was found")
   158  }
   159  
   160  func (self *DBManager) FindById(data sqlc.Object) error {
   161  	return utils.Error("No implementation method [FindById] was found")
   162  }
   163  
   164  func (self *DBManager) FindOne(cnd *sqlc.Cnd, data sqlc.Object) error {
   165  	return utils.Error("No implementation method [FindOne] was found")
   166  }
   167  
   168  func (self *DBManager) FindList(cnd *sqlc.Cnd, data interface{}) error {
   169  	return utils.Error("No implementation method [FindList] was found")
   170  }
   171  
   172  func (self *DBManager) FindOneComplex(cnd *sqlc.Cnd, data sqlc.Object) error {
   173  	return utils.Error("No implementation method [FindOneComplexOne] was found")
   174  }
   175  
   176  func (self *DBManager) FindListComplex(cnd *sqlc.Cnd, data interface{}) error {
   177  	return utils.Error("No implementation method [FindListComplex] was found")
   178  }
   179  
   180  func (self *DBManager) Close() error {
   181  	return utils.Error("No implementation method [Close] was found")
   182  }
   183  
   184  func (self *DBManager) BuildCondKey(cnd *sqlc.Cnd, key string) []byte {
   185  	zlog.Warn("No implementation method [BuildCondKey] was found", 0)
   186  	return nil
   187  }
   188  
   189  func (self *DBManager) BuildWhereCase(cnd *sqlc.Cnd) (*bytes.Buffer, []interface{}) {
   190  	zlog.Warn("No implementation method [BuildWhereCase] was found", 0)
   191  	return nil, nil
   192  }
   193  
   194  func (self *DBManager) BuildGroupBy(cnd *sqlc.Cnd) string {
   195  	zlog.Warn("No implementation method [BuilGroupBy] was found", 0)
   196  	return ""
   197  }
   198  
   199  func (self *DBManager) BuildSortBy(cnd *sqlc.Cnd) string {
   200  	zlog.Warn("No implementation method [BuilSortBy] was found", 0)
   201  	return ""
   202  }
   203  
   204  func (self *DBManager) BuildPagination(cnd *sqlc.Cnd, sql string, values []interface{}) (string, error) {
   205  	return "", utils.Error("No implementation method [BuildPagination] was found")
   206  }
   207  
   208  func (self *DBManager) Error(data ...interface{}) error {
   209  	if data == nil || len(data) == 0 {
   210  		return nil
   211  	}
   212  	err := utils.Error(data...)
   213  	self.Errors = append(self.Errors, err)
   214  	return err
   215  }
   216  
   217  /********************************** 关系数据库ORM默认实现 -> MySQL(如需实现其他类型数据库则自行实现IDBase接口) **********************************/
   218  
   219  // 关系数据库连接管理器
   220  type RDBManager struct {
   221  	DBManager
   222  	Db *sql.DB
   223  	Tx *sql.Tx
   224  }
   225  
   226  func (self *RDBManager) GetDB(options ...Option) error {
   227  	dsName := DIC.MASTER
   228  	var option Option
   229  	if len(options) > 0 {
   230  		option = options[0]
   231  		if len(option.DsName) > 0 {
   232  			dsName = option.DsName
   233  		} else {
   234  			option.DsName = dsName
   235  		}
   236  	}
   237  	rdb := rdbs[dsName]
   238  	if rdb == nil {
   239  		return self.Error("datasource [", dsName, "] not found...")
   240  	}
   241  	self.Db = rdb.Db
   242  	self.DsName = rdb.DsName
   243  	self.Database = rdb.Database
   244  	self.Timeout = 10000
   245  	self.MongoSync = rdb.MongoSync
   246  	self.CacheManager = rdb.CacheManager
   247  	self.OpenTx = false
   248  	self.Option.AutoID = option.AutoID
   249  	if len(option.DsName) > 0 {
   250  		if len(option.DsName) > 0 {
   251  			self.DsName = option.DsName
   252  		}
   253  		if option.OpenTx {
   254  			self.OpenTx = option.OpenTx
   255  		}
   256  		if option.MongoSync {
   257  			self.MongoSync = option.MongoSync
   258  		}
   259  		if option.Timeout > 0 {
   260  			self.Timeout = option.Timeout
   261  		}
   262  		if len(option.Database) > 0 {
   263  			self.Database = option.Database
   264  		}
   265  		if option.OpenTx {
   266  			if txv, err := self.Db.Begin(); err != nil {
   267  				return self.Error("database open transaction failed: ", err)
   268  			} else {
   269  				self.Tx = txv
   270  			}
   271  		}
   272  	}
   273  	return nil
   274  }
   275  
   276  func (self *RDBManager) Save(data ...sqlc.Object) error {
   277  	if data == nil || len(data) == 0 {
   278  		return self.Error("[Mysql.Save] data is nil")
   279  	}
   280  	if len(data) > 2000 {
   281  		return self.Error("[Mysql.Save] data length > 2000")
   282  	}
   283  	obv, ok := modelDrivers[data[0].GetTable()]
   284  	if !ok {
   285  		return self.Error("[Mysql.Save] registration object type not found [", data[0].GetTable(), "]")
   286  	}
   287  	var fready bool
   288  	parameter := make([]interface{}, 0, len(obv.FieldElem)*len(data))
   289  	fpart := bytes.NewBuffer(make([]byte, 0, 14*len(obv.FieldElem)))
   290  	vpart := bytes.NewBuffer(make([]byte, 0, 64*len(data)))
   291  	for _, v := range data {
   292  		vpart_ := bytes.NewBuffer(make([]byte, 0, 64))
   293  		vpart_.WriteString(" (")
   294  		for _, vv := range obv.FieldElem {
   295  			if vv.Ignore {
   296  				continue
   297  			}
   298  			if vv.Primary {
   299  				if self.AutoID {
   300  					continue
   301  				}
   302  				if vv.FieldKind == reflect.Int64 {
   303  					lastInsertId := utils.GetInt64(utils.GetPtr(v, obv.PkOffset))
   304  					if lastInsertId == 0 {
   305  						if obv.AutoId {
   306  							continue
   307  						}
   308  						lastInsertId = utils.NextIID()
   309  						utils.SetInt64(utils.GetPtr(v, vv.FieldOffset), lastInsertId)
   310  					}
   311  					parameter = append(parameter, lastInsertId)
   312  				} else if vv.FieldKind == reflect.String {
   313  					lastInsertId := utils.GetString(utils.GetPtr(v, obv.PkOffset))
   314  					if len(lastInsertId) == 0 {
   315  						if obv.AutoId {
   316  							continue
   317  						}
   318  						lastInsertId := utils.NextSID()
   319  						utils.SetString(utils.GetPtr(v, vv.FieldOffset), lastInsertId)
   320  					}
   321  					parameter = append(parameter, lastInsertId)
   322  				} else {
   323  					return utils.Error("only Int64 and string type IDs are supported")
   324  				}
   325  			} else {
   326  				fval, err := GetValue(v, vv)
   327  				if err != nil {
   328  					zlog.Error("[Mysql.Save] parameter value acquisition failed", 0, zlog.String("field", vv.FieldName), zlog.AddError(err))
   329  					continue
   330  				}
   331  				if vv.IsDate && fval == "" { // time = 0
   332  					fval = utils.Time2Str(utils.UnixMilli())
   333  				}
   334  				parameter = append(parameter, fval)
   335  			}
   336  			if !fready {
   337  				fpart.WriteString("`")
   338  				fpart.WriteString(vv.FieldJsonName)
   339  				fpart.WriteString("`")
   340  				fpart.WriteString(",")
   341  			}
   342  			vpart_.WriteString("?,")
   343  		}
   344  		if !fready {
   345  			fready = true
   346  		}
   347  		vstr := utils.Bytes2Str(vpart_.Bytes())
   348  		vpart.WriteString(utils.Substr(vstr, 0, len(vstr)-1))
   349  		vpart.WriteString("),")
   350  	}
   351  	str1 := utils.Bytes2Str(fpart.Bytes())
   352  	str2 := utils.Bytes2Str(vpart.Bytes())
   353  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str1)+len(str2)+64))
   354  	sqlbuf.WriteString("insert into ")
   355  	sqlbuf.WriteString(obv.TableName)
   356  	sqlbuf.WriteString(" (")
   357  	sqlbuf.WriteString(utils.Substr(str1, 0, len(str1)-1))
   358  	sqlbuf.WriteString(")")
   359  	sqlbuf.WriteString(" values ")
   360  	if len(str2) > 0 {
   361  		sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
   362  	}
   363  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
   364  	if zlog.IsDebug() {
   365  		defer zlog.Debug("[Mysql.Save] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
   366  	}
   367  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
   368  	defer cancel()
   369  	var err error
   370  	var stmt *sql.Stmt
   371  	if self.OpenTx {
   372  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
   373  	} else {
   374  		stmt, err = self.Db.PrepareContext(ctx, prepare)
   375  	}
   376  	if err != nil {
   377  		return self.Error("[Mysql.Save] [ ", prepare, " ] prepare failed: ", err)
   378  	}
   379  	defer stmt.Close()
   380  	if ret, err := stmt.ExecContext(ctx, parameter...); err != nil {
   381  		return self.Error("[Mysql.Save] save failed: ", err)
   382  	} else if rowsAffected, err := ret.RowsAffected(); err != nil {
   383  		return self.Error("[Mysql.Save] affected rows failed: ", err)
   384  	} else if rowsAffected <= 0 {
   385  		return self.Error("[Mysql.Save] affected rows <= 0: ", rowsAffected)
   386  	}
   387  	if self.MongoSync && obv.ToMongo {
   388  		self.MGOSyncData = append(self.MGOSyncData, &MGOSyncData{SAVE, data[0], nil, data})
   389  	}
   390  	return nil
   391  }
   392  
   393  func (self *RDBManager) Update(data ...sqlc.Object) error {
   394  	if data == nil || len(data) == 0 {
   395  		return self.Error("[Mysql.Update] data is nil")
   396  	}
   397  	if len(data) > 1 {
   398  		return self.Error("[Mysql.Update] data length must 1")
   399  	}
   400  	oneData := data[0]
   401  	obv, ok := modelDrivers[oneData.GetTable()]
   402  	if !ok {
   403  		return self.Error("[Mysql.Update] registration object type not found [", data[0].GetTable(), "]")
   404  	}
   405  
   406  	parameter := make([]interface{}, 0, len(obv.FieldElem))
   407  	fpart := bytes.NewBuffer(make([]byte, 0, 96))
   408  	var lastInsertId interface{}
   409  	for _, v := range obv.FieldElem { // 遍历对象字段
   410  		if v.Ignore {
   411  			continue
   412  		}
   413  		if v.Primary {
   414  			if obv.PkKind == reflect.Int64 {
   415  				lastInsertId = utils.GetInt64(utils.GetPtr(oneData, obv.PkOffset))
   416  				if lastInsertId == 0 {
   417  					return self.Error("[Mysql.Update] data object id is nil")
   418  				}
   419  			} else if obv.PkKind == reflect.String {
   420  				lastInsertId = utils.GetString(utils.GetPtr(oneData, obv.PkOffset))
   421  				if lastInsertId == "" {
   422  					return self.Error("[Mysql.Update] data object id is nil")
   423  				}
   424  			} else {
   425  				return utils.Error("only Int64 and string type IDs are supported")
   426  			}
   427  			continue
   428  		}
   429  		fval, err := GetValue(oneData, v)
   430  		if err != nil {
   431  			zlog.Error("[Mysql.update] parameter value acquisition failed", 0, zlog.String("field", v.FieldName), zlog.AddError(err))
   432  			return utils.Error(err)
   433  		}
   434  		if v.IsDate && fval == "" {
   435  			continue
   436  		}
   437  		fpart.WriteString(" ")
   438  		fpart.WriteString("`")
   439  		fpart.WriteString(v.FieldJsonName)
   440  		fpart.WriteString("`")
   441  		fpart.WriteString(" = ?,")
   442  		parameter = append(parameter, fval)
   443  	}
   444  	parameter = append(parameter, lastInsertId)
   445  	str1 := utils.Bytes2Str(fpart.Bytes())
   446  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str1)))
   447  	sqlbuf.WriteString("update ")
   448  	sqlbuf.WriteString(obv.TableName)
   449  	sqlbuf.WriteString(" set ")
   450  	sqlbuf.WriteString(utils.Substr(str1, 0, len(str1)-1))
   451  	sqlbuf.WriteString(" where ")
   452  	sqlbuf.WriteString("`")
   453  	sqlbuf.WriteString(obv.PkName)
   454  	sqlbuf.WriteString("`")
   455  	sqlbuf.WriteString(" = ?")
   456  
   457  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
   458  	if zlog.IsDebug() {
   459  		defer zlog.Debug("[Mysql.Update] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
   460  	}
   461  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
   462  	defer cancel()
   463  	var err error
   464  	var stmt *sql.Stmt
   465  	if self.OpenTx {
   466  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
   467  	} else {
   468  		stmt, err = self.Db.PrepareContext(ctx, prepare)
   469  	}
   470  	if err != nil {
   471  		return self.Error("[Mysql.Update] [ ", prepare, " ] prepare failed: ", err)
   472  	}
   473  	defer stmt.Close()
   474  	if ret, err := stmt.ExecContext(ctx, parameter...); err != nil {
   475  		return self.Error("[Mysql.Update] update failed: ", err)
   476  	} else if rowsAffected, err := ret.RowsAffected(); err != nil {
   477  		return self.Error("[Mysql.Update] affected rows failed: ", err)
   478  	} else if rowsAffected <= 0 {
   479  		zlog.Warn(utils.AddStr("[Mysql.Update] affected rows <= 0 -> ", rowsAffected), 0, zlog.String("sql", prepare))
   480  		return nil
   481  	}
   482  	if self.MongoSync && obv.ToMongo {
   483  		self.MGOSyncData = append(self.MGOSyncData, &MGOSyncData{UPDATE, oneData, nil, nil})
   484  	}
   485  	return nil
   486  }
   487  
   488  func (self *RDBManager) UpdateByCnd(cnd *sqlc.Cnd) (int64, error) {
   489  	if cnd.Model == nil {
   490  		return 0, self.Error("[Mysql.UpdateByCnd] data is nil")
   491  	}
   492  	if cnd.Upsets == nil || len(cnd.Upsets) == 0 {
   493  		return 0, self.Error("[Mysql.UpdateByCnd] upset fields is nil")
   494  	}
   495  	obv, ok := modelDrivers[cnd.Model.GetTable()]
   496  	if !ok {
   497  		return 0, self.Error("[Mysql.UpdateByCnd] registration object type not found [", cnd.Model.GetTable(), "]")
   498  	}
   499  	case_part, case_arg := self.BuildWhereCase(cnd)
   500  	if case_part.Len() == 0 || len(case_arg) == 0 {
   501  		return 0, self.Error("[Mysql.UpdateByCnd] update WhereCase is nil")
   502  	}
   503  	parameter := make([]interface{}, 0, len(cnd.Upsets)+len(case_arg))
   504  	fpart := bytes.NewBuffer(make([]byte, 0, 96))
   505  	for k, v := range cnd.Upsets { // 遍历对象字段
   506  		if cnd.Escape {
   507  			fpart.WriteString(" ")
   508  			fpart.WriteString("`")
   509  			fpart.WriteString(k)
   510  			fpart.WriteString("`")
   511  			fpart.WriteString(" = ?,")
   512  		} else {
   513  			fpart.WriteString(" ")
   514  			fpart.WriteString(k)
   515  			fpart.WriteString(" = ?,")
   516  		}
   517  		parameter = append(parameter, v)
   518  	}
   519  	for _, v := range case_arg {
   520  		parameter = append(parameter, v)
   521  	}
   522  	vpart := bytes.NewBuffer(make([]byte, 0, case_part.Len()+16))
   523  	vpart.WriteString("where")
   524  	str := case_part.String()
   525  	vpart.WriteString(utils.Substr(str, 0, len(str)-3))
   526  	str1 := utils.Bytes2Str(fpart.Bytes())
   527  	str2 := utils.Bytes2Str(vpart.Bytes())
   528  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str1)+len(str2)+64))
   529  	sqlbuf.WriteString("update ")
   530  	sqlbuf.WriteString(obv.TableName)
   531  	sqlbuf.WriteString(" set ")
   532  	sqlbuf.WriteString(utils.Substr(str1, 0, len(str1)-1))
   533  	sqlbuf.WriteString(" ")
   534  	if len(str2) > 0 {
   535  		sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
   536  	}
   537  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
   538  	if zlog.IsDebug() {
   539  		defer zlog.Debug("[Mysql.UpdateByCnd] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
   540  	}
   541  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
   542  	defer cancel()
   543  	var err error
   544  	var stmt *sql.Stmt
   545  	if self.OpenTx {
   546  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
   547  	} else {
   548  		stmt, err = self.Db.PrepareContext(ctx, prepare)
   549  	}
   550  	if err != nil {
   551  		return 0, self.Error("[Mysql.UpdateByCnd] [ ", prepare, " ] prepare failed: ", err)
   552  	}
   553  	defer stmt.Close()
   554  	ret, err := stmt.ExecContext(ctx, parameter...)
   555  	if err != nil {
   556  		return 0, self.Error("[Mysql.UpdateByCnd] update failed: ", err)
   557  	}
   558  	rowsAffected, err := ret.RowsAffected()
   559  	if err != nil {
   560  		return 0, self.Error("[Mysql.UpdateByCnd] affected rows failed: ", err)
   561  	}
   562  	if rowsAffected <= 0 {
   563  		zlog.Warn(utils.AddStr("[Mysql.UpdateByCnd] affected rows <= 0 -> ", rowsAffected), 0, zlog.String("sql", prepare))
   564  		return 0, nil
   565  	}
   566  	if self.MongoSync && obv.ToMongo {
   567  		self.MGOSyncData = append(self.MGOSyncData, &MGOSyncData{UPDATE_BY_CND, cnd.Model, cnd, nil})
   568  	}
   569  	return rowsAffected, nil
   570  }
   571  
   572  func (self *RDBManager) Delete(data ...sqlc.Object) error {
   573  	if data == nil || len(data) == 0 {
   574  		return self.Error("[Mysql.Delete] data is nil")
   575  	}
   576  	if len(data) > 2000 {
   577  		return self.Error("[Mysql.Delete] data length > 2000")
   578  	}
   579  	obv, ok := modelDrivers[data[0].GetTable()]
   580  	if !ok {
   581  		return self.Error("[Mysql.Delete] registration object type not found [", data[0].GetTable(), "]")
   582  	}
   583  	parameter := make([]interface{}, 0, len(data))
   584  	vpart := bytes.NewBuffer(make([]byte, 0, 2*len(data)))
   585  	for _, v := range data {
   586  		if obv.PkKind == reflect.Int64 {
   587  			lastInsertId := utils.GetInt64(utils.GetPtr(v, obv.PkOffset))
   588  			if lastInsertId == 0 {
   589  				return self.Error("[Mysql.Delete] data object id is nil")
   590  			}
   591  			parameter = append(parameter, lastInsertId)
   592  		} else if obv.PkKind == reflect.String {
   593  			lastInsertId := utils.GetString(utils.GetPtr(v, obv.PkOffset))
   594  			if len(lastInsertId) == 0 {
   595  				return self.Error("[Mysql.Delete] data object id is nil")
   596  			}
   597  			parameter = append(parameter, lastInsertId)
   598  		}
   599  		vpart.WriteString("?,")
   600  	}
   601  	str2 := utils.Bytes2Str(vpart.Bytes())
   602  	if len(str2) == 0 {
   603  		return self.Error("where case is nil")
   604  	}
   605  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str2)+64))
   606  	sqlbuf.WriteString("delete from ")
   607  	sqlbuf.WriteString(obv.TableName)
   608  	sqlbuf.WriteString(" where ")
   609  	sqlbuf.WriteString("`")
   610  	sqlbuf.WriteString(obv.PkName)
   611  	sqlbuf.WriteString("`")
   612  	sqlbuf.WriteString(" in (")
   613  	sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
   614  	sqlbuf.WriteString(")")
   615  
   616  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
   617  	if zlog.IsDebug() {
   618  		defer zlog.Debug("[Mysql.Delete] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
   619  	}
   620  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
   621  	defer cancel()
   622  	var err error
   623  	var stmt *sql.Stmt
   624  	if self.OpenTx {
   625  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
   626  	} else {
   627  		stmt, err = self.Db.PrepareContext(ctx, prepare)
   628  	}
   629  	if err != nil {
   630  		return self.Error("[Mysql.Delete] [ ", prepare, " ] prepare failed: ", err)
   631  	}
   632  	defer stmt.Close()
   633  	if ret, err := stmt.ExecContext(ctx, parameter...); err != nil {
   634  		return self.Error("[Mysql.Delete] delete failed: ", err)
   635  	} else if rowsAffected, err := ret.RowsAffected(); err != nil {
   636  		return self.Error("[Mysql.Delete] affected rows failed: ", err)
   637  	} else if rowsAffected <= 0 {
   638  		zlog.Warn(utils.AddStr("[Mysql.Delete] affected rows <= 0 -> ", rowsAffected), 0, zlog.String("sql", prepare))
   639  		return nil
   640  	}
   641  	if self.MongoSync && obv.ToMongo {
   642  		self.MGOSyncData = append(self.MGOSyncData, &MGOSyncData{DELETE, data[0], nil, data})
   643  	}
   644  	return nil
   645  }
   646  
   647  func (self *RDBManager) DeleteById(object sqlc.Object, data ...interface{}) (int64, error) {
   648  	if data == nil || len(data) == 0 {
   649  		return 0, self.Error("[Mysql.DeleteById] data is nil")
   650  	}
   651  	if len(data) > 2000 {
   652  		return 0, self.Error("[Mysql.DeleteById] data length > 2000")
   653  	}
   654  	obv, ok := modelDrivers[object.GetTable()]
   655  	if !ok {
   656  		return 0, self.Error("[Mysql.DeleteById] registration object type not found [", object.GetTable(), "]")
   657  	}
   658  	parameter := make([]interface{}, 0, len(data))
   659  	vpart := bytes.NewBuffer(make([]byte, 0, 2*len(data)))
   660  	for _, v := range data {
   661  		vpart.WriteString("?,")
   662  		parameter = append(parameter, v)
   663  	}
   664  	str2 := utils.Bytes2Str(vpart.Bytes())
   665  	if len(str2) == 0 {
   666  		return 0, self.Error("where case is nil")
   667  	}
   668  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str2)+64))
   669  	sqlbuf.WriteString("delete from ")
   670  	sqlbuf.WriteString(obv.TableName)
   671  	sqlbuf.WriteString(" where ")
   672  	sqlbuf.WriteString("`")
   673  	sqlbuf.WriteString(obv.PkName)
   674  	sqlbuf.WriteString("`")
   675  	sqlbuf.WriteString(" in (")
   676  	sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
   677  	sqlbuf.WriteString(")")
   678  
   679  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
   680  	if zlog.IsDebug() {
   681  		defer zlog.Debug("[Mysql.DeleteById] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
   682  	}
   683  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
   684  	defer cancel()
   685  	var err error
   686  	var stmt *sql.Stmt
   687  	if self.OpenTx {
   688  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
   689  	} else {
   690  		stmt, err = self.Db.PrepareContext(ctx, prepare)
   691  	}
   692  	if err != nil {
   693  		return 0, self.Error("[Mysql.DeleteById] [ ", prepare, " ] prepare failed: ", err)
   694  	}
   695  	defer stmt.Close()
   696  	ret, err := stmt.ExecContext(ctx, parameter...)
   697  	if err != nil {
   698  		return 0, self.Error("[Mysql.DeleteById] delete failed: ", err)
   699  	}
   700  	rowsAffected, err := ret.RowsAffected()
   701  	if err != nil {
   702  		return 0, self.Error("[Mysql.DeleteById] affected rows failed: ", err)
   703  	}
   704  	if rowsAffected <= 0 {
   705  		zlog.Warn(utils.AddStr("[Mysql.DeleteById] affected rows <= 0 -> ", rowsAffected), 0, zlog.String("sql", prepare))
   706  		return 0, nil
   707  	}
   708  	return rowsAffected, nil
   709  }
   710  
   711  func (self *RDBManager) DeleteByCnd(cnd *sqlc.Cnd) (int64, error) {
   712  	if cnd.Model == nil {
   713  		return 0, self.Error("[Mysql.DeleteByCnd] data is nil")
   714  	}
   715  	obv, ok := modelDrivers[cnd.Model.GetTable()]
   716  	if !ok {
   717  		return 0, self.Error("[Mysql.DeleteByCnd] registration object type not found [", cnd.Model.GetTable(), "]")
   718  	}
   719  	case_part, case_arg := self.BuildWhereCase(cnd)
   720  	if case_part.Len() == 0 || len(case_arg) == 0 {
   721  		return 0, self.Error("[Mysql.DeleteByCnd] update WhereCase is nil")
   722  	}
   723  	parameter := make([]interface{}, 0, len(case_arg))
   724  	//fpart := bytes.NewBuffer(make([]byte, 0, 96))
   725  	//for k, v := range cnd.Upsets { // 遍历对象字段
   726  	//	if cnd.Escape {
   727  	//		fpart.WriteString(" ")
   728  	//		fpart.WriteString("`")
   729  	//		fpart.WriteString(k)
   730  	//		fpart.WriteString("`")
   731  	//		fpart.WriteString(" = ?,")
   732  	//	} else {
   733  	//		fpart.WriteString(" ")
   734  	//		fpart.WriteString(k)
   735  	//		fpart.WriteString(" = ?,")
   736  	//	}
   737  	//	parameter = append(parameter, v)
   738  	//}
   739  	for _, v := range case_arg {
   740  		parameter = append(parameter, v)
   741  	}
   742  	vpart := bytes.NewBuffer(make([]byte, 0, case_part.Len()+16))
   743  	vpart.WriteString(" where")
   744  	str := case_part.String()
   745  	vpart.WriteString(utils.Substr(str, 0, len(str)-3))
   746  	//str1 := utils.Bytes2Str(fpart.Bytes())
   747  	str2 := utils.Bytes2Str(vpart.Bytes())
   748  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str2)+64))
   749  	sqlbuf.WriteString("delete from ")
   750  	sqlbuf.WriteString(obv.TableName)
   751  	//sqlbuf.WriteString(" set ")
   752  	//sqlbuf.WriteString(utils.Substr(str1, 0, len(str1)-1))
   753  	//sqlbuf.WriteString(" ")
   754  	if len(str2) > 0 {
   755  		sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
   756  	}
   757  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
   758  	if zlog.IsDebug() {
   759  		defer zlog.Debug("[Mysql.DeleteByCnd] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
   760  	}
   761  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
   762  	defer cancel()
   763  	var err error
   764  	var stmt *sql.Stmt
   765  	if self.OpenTx {
   766  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
   767  	} else {
   768  		stmt, err = self.Db.PrepareContext(ctx, prepare)
   769  	}
   770  	if err != nil {
   771  		return 0, self.Error("[Mysql.DeleteByCnd] [ ", prepare, " ] prepare failed: ", err)
   772  	}
   773  	defer stmt.Close()
   774  	ret, err := stmt.ExecContext(ctx, parameter...)
   775  	if err != nil {
   776  		return 0, self.Error("[Mysql.DeleteByCnd] update failed: ", err)
   777  	}
   778  	rowsAffected, err := ret.RowsAffected()
   779  	if err != nil {
   780  		return 0, self.Error("[Mysql.DeleteByCnd] affected rows failed: ", err)
   781  	}
   782  	if rowsAffected <= 0 {
   783  		zlog.Warn(utils.AddStr("[Mysql.DeleteByCnd] affected rows <= 0 -> ", rowsAffected), 0, zlog.String("sql", prepare))
   784  		return 0, nil
   785  	}
   786  	if self.MongoSync && obv.ToMongo {
   787  		self.MGOSyncData = append(self.MGOSyncData, &MGOSyncData{DELETE, cnd.Model, cnd, nil})
   788  	}
   789  	return rowsAffected, nil
   790  }
   791  
   792  func (self *RDBManager) FindById(data sqlc.Object) error {
   793  	if data == nil {
   794  		return self.Error("[Mysql.FindById] data is nil")
   795  	}
   796  	obv, ok := modelDrivers[data.GetTable()]
   797  	if !ok {
   798  		return self.Error("[Mysql.FindById] registration object type not found [", data.GetTable(), "]")
   799  	}
   800  	var parameter []interface{}
   801  	if obv.PkKind == reflect.Int64 {
   802  		lastInsertId := utils.GetInt64(utils.GetPtr(data, obv.PkOffset))
   803  		if lastInsertId == 0 {
   804  			return self.Error("[Mysql.FindById] data object id is nil")
   805  		}
   806  		parameter = append(parameter, lastInsertId)
   807  	} else if obv.PkKind == reflect.String {
   808  		lastInsertId := utils.GetString(utils.GetPtr(data, obv.PkOffset))
   809  		if len(lastInsertId) == 0 {
   810  			return self.Error("[Mysql.FindById] data object id is nil")
   811  		}
   812  		parameter = append(parameter, lastInsertId)
   813  	}
   814  	fpart := bytes.NewBuffer(make([]byte, 0, 14*len(obv.FieldElem)))
   815  	for _, vv := range obv.FieldElem {
   816  		if vv.Ignore {
   817  			continue
   818  		}
   819  		fpart.WriteString("`")
   820  		fpart.WriteString(vv.FieldJsonName)
   821  		fpart.WriteString("`")
   822  		fpart.WriteString(",")
   823  	}
   824  	str1 := utils.Bytes2Str(fpart.Bytes())
   825  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str1)+64))
   826  	sqlbuf.WriteString("select ")
   827  	sqlbuf.WriteString(utils.Substr(str1, 0, len(str1)-1))
   828  	sqlbuf.WriteString(" from ")
   829  	sqlbuf.WriteString(obv.TableName)
   830  	sqlbuf.WriteString(" where ")
   831  	sqlbuf.WriteString("`")
   832  	sqlbuf.WriteString(obv.PkName)
   833  	sqlbuf.WriteString("`")
   834  	sqlbuf.WriteString(" = ?")
   835  	sqlbuf.WriteString(" limit 1")
   836  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
   837  	if zlog.IsDebug() {
   838  		defer zlog.Debug("[Mysql.FindById] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
   839  	}
   840  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
   841  	defer cancel()
   842  	var err error
   843  	var stmt *sql.Stmt
   844  	var rows *sql.Rows
   845  	if self.OpenTx {
   846  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
   847  	} else {
   848  		stmt, err = self.Db.PrepareContext(ctx, prepare)
   849  	}
   850  	if err != nil {
   851  		return self.Error("[Mysql.FindById] [", prepare, "] prepare failed: ", err)
   852  	}
   853  	defer stmt.Close()
   854  	rows, err = stmt.QueryContext(ctx, parameter...)
   855  	if err != nil {
   856  		return self.Error("[Mysql.FindById] query failed: ", err)
   857  	}
   858  	defer rows.Close()
   859  	cols, err := rows.Columns()
   860  	if err != nil {
   861  		return self.Error("[Mysql.FindById] read columns failed: ", err)
   862  	}
   863  	var first [][]byte
   864  	if out, err := OutDest(rows, len(cols)); err != nil {
   865  		return self.Error("[Mysql.FindById] read result failed: ", err)
   866  	} else if len(out) == 0 {
   867  		return nil
   868  	} else {
   869  		first = out[0]
   870  	}
   871  	for i, vv := range obv.FieldElem {
   872  		if vv.Ignore {
   873  			continue
   874  		}
   875  		if err := SetValue(data, vv, first[i]); err != nil {
   876  			return self.Error(err)
   877  		}
   878  	}
   879  	return nil
   880  }
   881  
   882  func (self *RDBManager) FindOne(cnd *sqlc.Cnd, data sqlc.Object) error {
   883  	if data == nil {
   884  		return self.Error("[Mysql.FindOne] data is nil")
   885  	}
   886  	obv, ok := modelDrivers[data.GetTable()]
   887  	if !ok {
   888  		return self.Error("[Mysql.FindOne] registration object type not found [", data.GetTable(), "]")
   889  	}
   890  	var parameter []interface{}
   891  	fpart := bytes.NewBuffer(make([]byte, 0, 14*len(obv.FieldElem)))
   892  	for _, vv := range obv.FieldElem {
   893  		if vv.Ignore {
   894  			continue
   895  		}
   896  		fpart.WriteString("`")
   897  		fpart.WriteString(vv.FieldJsonName)
   898  		fpart.WriteString("`")
   899  		fpart.WriteString(",")
   900  	}
   901  	case_part, case_arg := self.BuildWhereCase(cnd.Offset(0, 1))
   902  	for _, v := range case_arg {
   903  		parameter = append(parameter, v)
   904  	}
   905  	var vpart *bytes.Buffer
   906  	if case_part.Len() > 0 {
   907  		vpart = bytes.NewBuffer(make([]byte, 0, case_part.Len()+16))
   908  		vpart.WriteString("where")
   909  		str := case_part.String()
   910  		vpart.WriteString(utils.Substr(str, 0, len(str)-3))
   911  	}
   912  	str1 := utils.Bytes2Str(fpart.Bytes())
   913  	str2 := ""
   914  	if vpart != nil {
   915  		str2 = utils.Bytes2Str(vpart.Bytes())
   916  	}
   917  	sortby := self.BuildSortBy(cnd)
   918  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str1)+len(str2)+len(sortby)+32))
   919  	sqlbuf.WriteString("select ")
   920  	sqlbuf.WriteString(utils.Substr(str1, 0, len(str1)-1))
   921  	sqlbuf.WriteString(" from ")
   922  	sqlbuf.WriteString(obv.TableName)
   923  	sqlbuf.WriteString(" ")
   924  	if len(str2) > 0 {
   925  		sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
   926  	}
   927  	if len(sortby) > 0 {
   928  		sqlbuf.WriteString(sortby)
   929  	}
   930  	sqlbuf.WriteString(" limit 1")
   931  	// cnd.Pagination = dialect.Dialect{PageNo: 1, PageSize: 1}
   932  	// prepare, err := self.BuildPagination(cnd, utils.Bytes2Str(sqlbuf.Bytes()), parameter)
   933  	// if err != nil {
   934  	//	 return self.Error(err)
   935  	// }
   936  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
   937  	if zlog.IsDebug() {
   938  		defer zlog.Debug("[Mysql.FindOne] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
   939  	}
   940  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
   941  	defer cancel()
   942  	var err error
   943  	var stmt *sql.Stmt
   944  	var rows *sql.Rows
   945  	if self.OpenTx {
   946  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
   947  	} else {
   948  		stmt, err = self.Db.PrepareContext(ctx, prepare)
   949  	}
   950  	if err != nil {
   951  		return self.Error("[Mysql.FindOne] [ ", prepare, " ] prepare failed: ", err)
   952  	}
   953  	defer stmt.Close()
   954  	rows, err = stmt.QueryContext(ctx, parameter...)
   955  	if err != nil {
   956  		return self.Error("[Mysql.FindOne] query failed: ", err)
   957  	}
   958  	defer rows.Close()
   959  	cols, err := rows.Columns()
   960  	if err != nil {
   961  		return self.Error("[Mysql.FindOne] read columns failed: ", err)
   962  	}
   963  	var first [][]byte
   964  	if out, err := OutDest(rows, len(cols)); err != nil {
   965  		return self.Error("[Mysql.FindOne] read result failed: ", err)
   966  	} else if len(out) == 0 {
   967  		return nil
   968  	} else {
   969  		first = out[0]
   970  	}
   971  	for i, vv := range obv.FieldElem {
   972  		if vv.Ignore {
   973  			continue
   974  		}
   975  		if err := SetValue(data, vv, first[i]); err != nil {
   976  			return self.Error(err)
   977  		}
   978  	}
   979  	return nil
   980  }
   981  
   982  func (self *RDBManager) FindList(cnd *sqlc.Cnd, data interface{}) error {
   983  	if data == nil {
   984  		return self.Error("[Mysql.FindList] data is nil")
   985  	}
   986  	if cnd.Model == nil {
   987  		return self.Error("[Mysql.FindList] model is nil")
   988  	}
   989  	obv, ok := modelDrivers[cnd.Model.GetTable()]
   990  	if !ok {
   991  		return self.Error("[Mysql.FindList] registration object type not found [", cnd.Model.GetTable(), "]")
   992  	}
   993  	fpart := bytes.NewBuffer(make([]byte, 0, 14*len(obv.FieldElem)))
   994  	for _, vv := range obv.FieldElem {
   995  		if vv.Ignore {
   996  			continue
   997  		}
   998  		fpart.WriteString("`")
   999  		fpart.WriteString(vv.FieldJsonName)
  1000  		fpart.WriteString("`")
  1001  		fpart.WriteString(",")
  1002  	}
  1003  	case_part, case_arg := self.BuildWhereCase(cnd)
  1004  	parameter := make([]interface{}, 0, len(case_arg))
  1005  	for _, v := range case_arg {
  1006  		parameter = append(parameter, v)
  1007  	}
  1008  	var vpart *bytes.Buffer
  1009  	if case_part.Len() > 0 {
  1010  		vpart = bytes.NewBuffer(make([]byte, 0, case_part.Len()+16))
  1011  		vpart.WriteString("where")
  1012  		str := case_part.String()
  1013  		vpart.WriteString(utils.Substr(str, 0, len(str)-3))
  1014  	}
  1015  	str1 := utils.Bytes2Str(fpart.Bytes())
  1016  	str2 := ""
  1017  	if vpart != nil {
  1018  		str2 = utils.Bytes2Str(vpart.Bytes())
  1019  	}
  1020  	groupby := self.BuildGroupBy(cnd)
  1021  	sortby := self.BuildSortBy(cnd)
  1022  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str1)+len(str2)+len(groupby)+len(sortby)+32))
  1023  	sqlbuf.WriteString("select ")
  1024  	sqlbuf.WriteString(utils.Substr(str1, 0, len(str1)-1))
  1025  	sqlbuf.WriteString(" from ")
  1026  	sqlbuf.WriteString(obv.TableName)
  1027  	sqlbuf.WriteString(" ")
  1028  	if len(str2) > 0 {
  1029  		sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
  1030  	}
  1031  	if len(groupby) > 0 {
  1032  		sqlbuf.WriteString(groupby)
  1033  	}
  1034  	if len(sortby) > 0 {
  1035  		sqlbuf.WriteString(sortby)
  1036  	}
  1037  	prepare, err := self.BuildPagination(cnd, utils.Bytes2Str(sqlbuf.Bytes()), parameter)
  1038  	if err != nil {
  1039  		return self.Error(err)
  1040  	}
  1041  	if zlog.IsDebug() {
  1042  		defer zlog.Debug("[Mysql.FindList] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
  1043  	}
  1044  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
  1045  	defer cancel()
  1046  	var stmt *sql.Stmt
  1047  	var rows *sql.Rows
  1048  	if self.OpenTx {
  1049  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
  1050  	} else {
  1051  		stmt, err = self.Db.PrepareContext(ctx, prepare)
  1052  	}
  1053  	if err != nil {
  1054  		return self.Error("[Mysql.FindList] [ ", prepare, " ] prepare failed: ", err)
  1055  	}
  1056  	defer stmt.Close()
  1057  	rows, err = stmt.QueryContext(ctx, parameter...)
  1058  	if err != nil {
  1059  		return self.Error("[Mysql.FindList] query failed: ", err)
  1060  	}
  1061  	defer rows.Close()
  1062  	cols, err := rows.Columns()
  1063  	if err != nil {
  1064  		return self.Error("[Mysql.FindList] read columns failed: ", err)
  1065  	}
  1066  	out, err := OutDest(rows, len(cols))
  1067  	if err != nil {
  1068  		return self.Error("[Mysql.FindList] read result failed: ", err)
  1069  	} else if len(out) == 0 {
  1070  		if cnd.Pagination.IsPage {
  1071  			cnd.Pagination.PageCount = 0
  1072  			cnd.Pagination.PageTotal = 0
  1073  		}
  1074  		return nil
  1075  	}
  1076  	resultv := reflect.ValueOf(data)
  1077  	if resultv.Kind() != reflect.Ptr {
  1078  		return self.Error("[Mysql.FindList] target value kind not ptr")
  1079  	}
  1080  	slicev := resultv.Elem()
  1081  	if slicev.Kind() != reflect.Slice {
  1082  		return self.Error("[Mysql.FindList] target value kind not slice")
  1083  	}
  1084  	slicev = slicev.Slice(0, slicev.Cap())
  1085  	for _, v := range out {
  1086  		model := cnd.Model.NewObject()
  1087  		for i := 0; i < len(obv.FieldElem); i++ {
  1088  			vv := obv.FieldElem[i]
  1089  			if vv.Ignore {
  1090  				continue
  1091  			}
  1092  			if vv.IsDate && v[i] == nil {
  1093  				continue
  1094  			}
  1095  			if err := SetValue(model, vv, v[i]); err != nil {
  1096  				return self.Error(err)
  1097  			}
  1098  		}
  1099  		slicev = reflect.Append(slicev, reflect.ValueOf(model))
  1100  	}
  1101  	slicev = slicev.Slice(0, slicev.Cap())
  1102  	resultv.Elem().Set(slicev.Slice(0, len(out)))
  1103  	return nil
  1104  }
  1105  
  1106  func (self *RDBManager) Count(cnd *sqlc.Cnd) (int64, error) {
  1107  	if cnd.Model == nil {
  1108  		return 0, self.Error("[Mysql.Count] data is nil")
  1109  	}
  1110  	obv, ok := modelDrivers[cnd.Model.GetTable()]
  1111  	if !ok {
  1112  		return 0, self.Error("[Mysql.Count] registration object type not found [", cnd.Model.GetTable(), "]")
  1113  	}
  1114  	fpart := bytes.NewBuffer(make([]byte, 0, 32))
  1115  	fpart.WriteString("count(1)")
  1116  	case_part, case_arg := self.BuildWhereCase(cnd)
  1117  	parameter := make([]interface{}, 0, len(case_arg))
  1118  	for _, v := range case_arg {
  1119  		parameter = append(parameter, v)
  1120  	}
  1121  	var vpart *bytes.Buffer
  1122  	if case_part.Len() > 0 {
  1123  		vpart = bytes.NewBuffer(make([]byte, 0, case_part.Len()+16))
  1124  		vpart.WriteString("where")
  1125  		str := case_part.String()
  1126  		vpart.WriteString(utils.Substr(str, 0, len(str)-3))
  1127  	}
  1128  	str1 := utils.Bytes2Str(fpart.Bytes())
  1129  	str2 := ""
  1130  	if vpart != nil {
  1131  		str2 = utils.Bytes2Str(vpart.Bytes())
  1132  	}
  1133  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str1)+len(str2)+32))
  1134  	sqlbuf.WriteString("select ")
  1135  	sqlbuf.WriteString(str1)
  1136  	sqlbuf.WriteString(" from ")
  1137  	sqlbuf.WriteString(obv.TableName)
  1138  	sqlbuf.WriteString(" ")
  1139  	if len(str2) > 0 {
  1140  		sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
  1141  	}
  1142  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
  1143  	if zlog.IsDebug() {
  1144  		defer zlog.Debug("[Mysql.Count] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
  1145  	}
  1146  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
  1147  	defer cancel()
  1148  	var err error
  1149  	var rows *sql.Rows
  1150  	var stmt *sql.Stmt
  1151  	if self.OpenTx {
  1152  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
  1153  	} else {
  1154  		stmt, err = self.Db.PrepareContext(ctx, prepare)
  1155  	}
  1156  	if err != nil {
  1157  		return 0, self.Error("[Mysql.Count] [ ", prepare, " ] prepare failed: ", err)
  1158  	}
  1159  	defer stmt.Close()
  1160  	rows, err = stmt.QueryContext(ctx, parameter...)
  1161  	if err != nil {
  1162  		return 0, utils.Error("[Mysql.Count] query failed: ", err)
  1163  	}
  1164  	defer rows.Close()
  1165  	var pageTotal int64
  1166  	for rows.Next() {
  1167  		if err := rows.Scan(&pageTotal); err != nil {
  1168  			return 0, self.Error("[Mysql.Count] read total failed: ", err)
  1169  		}
  1170  	}
  1171  	if err := rows.Err(); err != nil {
  1172  		return 0, self.Error("[Mysql.Count] read result failed: ", err)
  1173  	}
  1174  	if pageTotal > 0 && cnd.Pagination.PageSize > 0 {
  1175  		var pageCount int64
  1176  		if pageTotal%cnd.Pagination.PageSize == 0 {
  1177  			pageCount = pageTotal / cnd.Pagination.PageSize
  1178  		} else {
  1179  			pageCount = pageTotal/cnd.Pagination.PageSize + 1
  1180  		}
  1181  		cnd.Pagination.PageCount = pageCount
  1182  	} else {
  1183  		cnd.Pagination.PageCount = 0
  1184  	}
  1185  	cnd.Pagination.PageTotal = pageTotal
  1186  	return pageTotal, nil
  1187  }
  1188  
  1189  func (self *RDBManager) Exists(cnd *sqlc.Cnd) (bool, error) {
  1190  	if cnd.Model == nil {
  1191  		return false, self.Error("[Mysql.Exists] data is nil")
  1192  	}
  1193  	obv, ok := modelDrivers[cnd.Model.GetTable()]
  1194  	if !ok {
  1195  		return false, self.Error("[Mysql.Exists] registration object type not found [", cnd.Model.GetTable(), "]")
  1196  	}
  1197  	fpart := bytes.NewBuffer(make([]byte, 0, 32))
  1198  	fpart.WriteString("1")
  1199  	case_part, case_arg := self.BuildWhereCase(cnd)
  1200  	parameter := make([]interface{}, 0, len(case_arg))
  1201  	for _, v := range case_arg {
  1202  		parameter = append(parameter, v)
  1203  	}
  1204  	var vpart *bytes.Buffer
  1205  	if case_part.Len() > 0 {
  1206  		vpart = bytes.NewBuffer(make([]byte, 0, case_part.Len()+16))
  1207  		vpart.WriteString("where")
  1208  		str := case_part.String()
  1209  		vpart.WriteString(utils.Substr(str, 0, len(str)-3))
  1210  	}
  1211  	str1 := utils.Bytes2Str(fpart.Bytes())
  1212  	str2 := ""
  1213  	if vpart != nil {
  1214  		str2 = utils.Bytes2Str(vpart.Bytes())
  1215  	}
  1216  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str1)+len(str2)+64))
  1217  	sqlbuf.WriteString("select exists(")
  1218  	sqlbuf.WriteString("select ")
  1219  	sqlbuf.WriteString(str1)
  1220  	sqlbuf.WriteString(" from ")
  1221  	sqlbuf.WriteString(obv.TableName)
  1222  	sqlbuf.WriteString(" ")
  1223  	if len(str2) > 0 {
  1224  		sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
  1225  	}
  1226  	sqlbuf.WriteString(" limit 1 ")
  1227  	sqlbuf.WriteString(" ) as pub_exists")
  1228  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
  1229  	if zlog.IsDebug() {
  1230  		defer zlog.Debug("[Mysql.Exists] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
  1231  	}
  1232  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
  1233  	defer cancel()
  1234  	var err error
  1235  	var rows *sql.Rows
  1236  	var stmt *sql.Stmt
  1237  	if self.OpenTx {
  1238  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
  1239  	} else {
  1240  		stmt, err = self.Db.PrepareContext(ctx, prepare)
  1241  	}
  1242  	if err != nil {
  1243  		return false, self.Error("[Mysql.Exists] [ ", prepare, " ] prepare failed: ", err)
  1244  	}
  1245  	defer stmt.Close()
  1246  	rows, err = stmt.QueryContext(ctx, parameter...)
  1247  	if err != nil {
  1248  		return false, utils.Error("[Mysql.Exists] query failed: ", err)
  1249  	}
  1250  	defer rows.Close()
  1251  	var exists int64
  1252  	for rows.Next() {
  1253  		if err := rows.Scan(&exists); err != nil {
  1254  			return false, self.Error("[Mysql.Exists] read total failed: ", err)
  1255  		}
  1256  	}
  1257  	if err := rows.Err(); err != nil {
  1258  		return false, self.Error("[Mysql.Exists] read result failed: ", err)
  1259  	}
  1260  	return exists > 0, nil
  1261  }
  1262  
  1263  func (self *RDBManager) FindListComplex(cnd *sqlc.Cnd, data interface{}) error {
  1264  	if data == nil {
  1265  		return self.Error("[Mysql.FindListComplex] data is nil")
  1266  	}
  1267  	if cnd.Model == nil {
  1268  		return self.Error("[Mysql.FindListComplex] model is nil")
  1269  	}
  1270  	if cnd.FromCond == nil || len(cnd.FromCond.Table) == 0 {
  1271  		return self.Error("[Mysql.FindListComplex] from table is nil")
  1272  	}
  1273  	if cnd.AnyFields == nil || len(cnd.AnyFields) == 0 {
  1274  		return self.Error("[Mysql.FindListComplex] any fields is nil")
  1275  	}
  1276  	obv, ok := modelDrivers[cnd.Model.GetTable()]
  1277  	if !ok {
  1278  		return self.Error("[Mysql.FindListComplex] registration object type not found [", cnd.Model.GetTable(), "]")
  1279  	}
  1280  	fpart := bytes.NewBuffer(make([]byte, 0, 32*len(cnd.AnyFields)))
  1281  	for _, vv := range cnd.AnyFields {
  1282  		if cnd.Escape {
  1283  			fpart.WriteString("`")
  1284  			fpart.WriteString(vv)
  1285  			fpart.WriteString("`")
  1286  			fpart.WriteString(",")
  1287  		} else {
  1288  			fpart.WriteString(vv)
  1289  			fpart.WriteString(",")
  1290  		}
  1291  	}
  1292  	case_part, case_arg := self.BuildWhereCase(cnd)
  1293  	parameter := make([]interface{}, 0, len(case_arg))
  1294  	for _, v := range case_arg {
  1295  		parameter = append(parameter, v)
  1296  	}
  1297  	var vpart *bytes.Buffer
  1298  	if case_part.Len() > 0 {
  1299  		vpart = bytes.NewBuffer(make([]byte, 0, case_part.Len()+16))
  1300  		vpart.WriteString("where")
  1301  		str := case_part.String()
  1302  		vpart.WriteString(utils.Substr(str, 0, len(str)-3))
  1303  	}
  1304  	str1 := utils.Bytes2Str(fpart.Bytes())
  1305  	str2 := ""
  1306  	if vpart != nil {
  1307  		str2 = utils.Bytes2Str(vpart.Bytes())
  1308  	}
  1309  	groupby := self.BuildGroupBy(cnd)
  1310  	sortby := self.BuildSortBy(cnd)
  1311  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str1)+len(str2)+len(groupby)+len(sortby)+32))
  1312  	sqlbuf.WriteString("select ")
  1313  	sqlbuf.WriteString(utils.Substr(str1, 0, len(str1)-1))
  1314  	sqlbuf.WriteString(" from ")
  1315  	sqlbuf.WriteString(cnd.FromCond.Table)
  1316  	sqlbuf.WriteString(" ")
  1317  	sqlbuf.WriteString(cnd.FromCond.Alias)
  1318  	sqlbuf.WriteString(" ")
  1319  	if len(cnd.JoinCond) > 0 {
  1320  		for _, v := range cnd.JoinCond {
  1321  			if len(v.Table) == 0 || len(v.On) == 0 {
  1322  				continue
  1323  			}
  1324  			if v.Type == sqlc.LEFT_ {
  1325  				sqlbuf.WriteString(" left join ")
  1326  			} else if v.Type == sqlc.RIGHT_ {
  1327  				sqlbuf.WriteString(" right join ")
  1328  			} else if v.Type == sqlc.INNER_ {
  1329  				sqlbuf.WriteString(" inner join ")
  1330  			} else {
  1331  				continue
  1332  			}
  1333  			sqlbuf.WriteString(v.Table)
  1334  			sqlbuf.WriteString(" on ")
  1335  			sqlbuf.WriteString(v.On)
  1336  			sqlbuf.WriteString(" ")
  1337  		}
  1338  	}
  1339  	if len(str2) > 0 {
  1340  		sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
  1341  	}
  1342  	if len(groupby) > 0 {
  1343  		sqlbuf.WriteString(groupby)
  1344  	}
  1345  	if len(sortby) > 0 {
  1346  		sqlbuf.WriteString(sortby)
  1347  	}
  1348  
  1349  	prepare, err := self.BuildPagination(cnd, utils.Bytes2Str(sqlbuf.Bytes()), parameter)
  1350  	if err != nil {
  1351  		return self.Error(err)
  1352  	}
  1353  	if zlog.IsDebug() {
  1354  		defer zlog.Debug("[Mysql.FindListComplex] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
  1355  	}
  1356  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
  1357  	defer cancel()
  1358  	var stmt *sql.Stmt
  1359  	var rows *sql.Rows
  1360  	if self.OpenTx {
  1361  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
  1362  	} else {
  1363  		stmt, err = self.Db.PrepareContext(ctx, prepare)
  1364  	}
  1365  	if err != nil {
  1366  		return self.Error("[Mysql.FindListComplex] [ ", prepare, " ] prepare failed: ", err)
  1367  	}
  1368  	defer stmt.Close()
  1369  	rows, err = stmt.QueryContext(ctx, parameter...)
  1370  	if err != nil {
  1371  		return self.Error("[Mysql.FindListComplex] query failed: ", err)
  1372  	}
  1373  	defer rows.Close()
  1374  	cols, err := rows.Columns()
  1375  	if err != nil {
  1376  		return self.Error("[Mysql.FindListComplex] read columns failed: ", err)
  1377  	}
  1378  	if len(cols) != len(cnd.AnyFields) {
  1379  		return self.Error("[Mysql.FindListComplex] read columns length invalid")
  1380  	}
  1381  	out, err := OutDest(rows, len(cols))
  1382  	if err != nil {
  1383  		return self.Error("[Mysql.FindListComplex] read result failed: ", err)
  1384  	} else if len(out) == 0 {
  1385  		if cnd.Pagination.IsPage {
  1386  			cnd.Pagination.PageCount = 0
  1387  			cnd.Pagination.PageTotal = 0
  1388  		}
  1389  		return nil
  1390  	}
  1391  	resultv := reflect.ValueOf(data)
  1392  	if resultv.Kind() != reflect.Ptr {
  1393  		return self.Error("[Mysql.FindList] target value kind not ptr")
  1394  	}
  1395  	slicev := resultv.Elem()
  1396  	if slicev.Kind() != reflect.Slice {
  1397  		return self.Error("[Mysql.FindList] target value kind not slice")
  1398  	}
  1399  	slicev = slicev.Slice(0, slicev.Cap())
  1400  	for _, v := range out {
  1401  		model := cnd.Model.NewObject()
  1402  		for i := 0; i < len(cols); i++ {
  1403  			for _, vv := range obv.FieldElem {
  1404  				if vv.FieldJsonName == cols[i] {
  1405  					if err := SetValue(model, vv, v[i]); err != nil {
  1406  						return self.Error(err)
  1407  					}
  1408  					break
  1409  				}
  1410  			}
  1411  		}
  1412  		slicev = reflect.Append(slicev, reflect.ValueOf(model))
  1413  	}
  1414  	slicev = slicev.Slice(0, slicev.Cap())
  1415  	resultv.Elem().Set(slicev.Slice(0, len(out)))
  1416  	return nil
  1417  }
  1418  
  1419  func (self *RDBManager) FindOneComplex(cnd *sqlc.Cnd, data sqlc.Object) error {
  1420  	if data == nil {
  1421  		return self.Error("[Mysql.FindOneComplex] data is nil")
  1422  	}
  1423  	if cnd.FromCond == nil || len(cnd.FromCond.Table) == 0 {
  1424  		return self.Error("[Mysql.FindOneComplex] from table is nil")
  1425  	}
  1426  	if cnd.AnyFields == nil || len(cnd.AnyFields) == 0 {
  1427  		return self.Error("[Mysql.FindOneComplex] any fields is nil")
  1428  	}
  1429  	obv, ok := modelDrivers[data.GetTable()]
  1430  	if !ok {
  1431  		return self.Error("[Mysql.FindOneComplex] registration object type not found [", data.GetTable(), "]")
  1432  	}
  1433  	fpart := bytes.NewBuffer(make([]byte, 0, 32*len(cnd.AnyFields)))
  1434  	for _, vv := range cnd.AnyFields {
  1435  		if cnd.Escape {
  1436  			fpart.WriteString("`")
  1437  			fpart.WriteString(vv)
  1438  			fpart.WriteString("`")
  1439  			fpart.WriteString(",")
  1440  		} else {
  1441  			fpart.WriteString(vv)
  1442  			fpart.WriteString(",")
  1443  		}
  1444  	}
  1445  	case_part, case_arg := self.BuildWhereCase(cnd.Offset(0, 1))
  1446  	parameter := make([]interface{}, 0, len(case_arg))
  1447  	for _, v := range case_arg {
  1448  		parameter = append(parameter, v)
  1449  	}
  1450  	var vpart *bytes.Buffer
  1451  	if case_part.Len() > 0 {
  1452  		vpart = bytes.NewBuffer(make([]byte, 0, case_part.Len()+16))
  1453  		vpart.WriteString("where")
  1454  		str := case_part.String()
  1455  		vpart.WriteString(utils.Substr(str, 0, len(str)-3))
  1456  	}
  1457  	str1 := utils.Bytes2Str(fpart.Bytes())
  1458  	str2 := ""
  1459  	if vpart != nil {
  1460  		str2 = utils.Bytes2Str(vpart.Bytes())
  1461  	}
  1462  	groupby := self.BuildGroupBy(cnd)
  1463  	sortby := self.BuildSortBy(cnd)
  1464  	sqlbuf := bytes.NewBuffer(make([]byte, 0, len(str1)+len(str2)+len(groupby)+len(sortby)+32))
  1465  	sqlbuf.WriteString("select ")
  1466  	sqlbuf.WriteString(utils.Substr(str1, 0, len(str1)-1))
  1467  	sqlbuf.WriteString(" from ")
  1468  	sqlbuf.WriteString(cnd.FromCond.Table)
  1469  	sqlbuf.WriteString(" ")
  1470  	sqlbuf.WriteString(cnd.FromCond.Alias)
  1471  	sqlbuf.WriteString(" ")
  1472  	if len(cnd.JoinCond) > 0 {
  1473  		for _, v := range cnd.JoinCond {
  1474  			if len(v.Table) == 0 || len(v.On) == 0 {
  1475  				continue
  1476  			}
  1477  			if v.Type == sqlc.LEFT_ {
  1478  				sqlbuf.WriteString(" left join ")
  1479  			} else if v.Type == sqlc.RIGHT_ {
  1480  				sqlbuf.WriteString(" right join ")
  1481  			} else if v.Type == sqlc.INNER_ {
  1482  				sqlbuf.WriteString(" inner join ")
  1483  			} else {
  1484  				continue
  1485  			}
  1486  			sqlbuf.WriteString(v.Table)
  1487  			sqlbuf.WriteString(" on ")
  1488  			sqlbuf.WriteString(v.On)
  1489  			sqlbuf.WriteString(" ")
  1490  		}
  1491  	}
  1492  	if len(str2) > 0 {
  1493  		sqlbuf.WriteString(utils.Substr(str2, 0, len(str2)-1))
  1494  	}
  1495  	if len(groupby) > 0 {
  1496  		sqlbuf.WriteString(groupby)
  1497  	}
  1498  	if len(sortby) > 0 {
  1499  		sqlbuf.WriteString(sortby)
  1500  	}
  1501  	sqlbuf.WriteString(" limit 1")
  1502  	// prepare, err := self.BuildPagination(cnd, utils.Bytes2Str(sqlbuf.Bytes()), parameter)
  1503  	// if err != nil {
  1504  	//	 return self.Error(err)
  1505  	// }
  1506  	prepare := utils.Bytes2Str(sqlbuf.Bytes())
  1507  	if zlog.IsDebug() {
  1508  		defer zlog.Debug("[Mysql.FindOneComplex] sql log", utils.UnixMilli(), zlog.String("sql", prepare), zlog.Any("values", parameter))
  1509  	}
  1510  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
  1511  	defer cancel()
  1512  	var err error
  1513  	var stmt *sql.Stmt
  1514  	var rows *sql.Rows
  1515  	if self.OpenTx {
  1516  		stmt, err = self.Tx.PrepareContext(ctx, prepare)
  1517  	} else {
  1518  		stmt, err = self.Db.PrepareContext(ctx, prepare)
  1519  	}
  1520  	if err != nil {
  1521  		return self.Error("[Mysql.FindOneComplex] [ ", prepare, " ] prepare failed: ", err)
  1522  	}
  1523  	defer stmt.Close()
  1524  	rows, err = stmt.QueryContext(ctx, parameter...)
  1525  	if err != nil {
  1526  		return self.Error("[Mysql.FindOneComplex] query failed: ", err)
  1527  	}
  1528  	defer rows.Close()
  1529  	cols, err := rows.Columns()
  1530  	if err != nil {
  1531  		return self.Error("[Mysql.FindOneComplex] read columns failed: ", err)
  1532  	}
  1533  	if len(cols) != len(cnd.AnyFields) {
  1534  		return self.Error("[Mysql.FindOneComplex] read columns length invalid")
  1535  	}
  1536  	var first [][]byte
  1537  	if out, err := OutDest(rows, len(cols)); err != nil {
  1538  		return self.Error("[Mysql.FindOneComplex] read result failed: ", err)
  1539  	} else if len(out) == 0 {
  1540  		return nil
  1541  	} else {
  1542  		first = out[0]
  1543  	}
  1544  	for i := 0; i < len(cols); i++ {
  1545  		for _, vv := range obv.FieldElem {
  1546  			if vv.FieldJsonName == cols[i] {
  1547  				if err := SetValue(data, vv, first[i]); err != nil {
  1548  					return self.Error(err)
  1549  				}
  1550  				break
  1551  			}
  1552  		}
  1553  	}
  1554  	return nil
  1555  }
  1556  
  1557  func (self *RDBManager) Close() error {
  1558  	if self.OpenTx && self.Tx != nil {
  1559  		if self.Errors == nil && len(self.Errors) == 0 {
  1560  			if err := self.Tx.Commit(); err != nil {
  1561  				zlog.Error("transaction commit failed", 0, zlog.AddError(err))
  1562  				return nil
  1563  			}
  1564  		} else {
  1565  			if err := self.Tx.Rollback(); err != nil {
  1566  				zlog.Error("transaction rollback failed", 0, zlog.AddError(err))
  1567  			}
  1568  			return nil
  1569  		}
  1570  	}
  1571  	if self.Errors == nil && len(self.Errors) == 0 && self.MongoSync && len(self.MGOSyncData) > 0 {
  1572  		for _, v := range self.MGOSyncData {
  1573  			if len(v.CacheObject) > 0 {
  1574  				if err := self.mongoSyncData(v.CacheOption, v.CacheModel, v.CacheCnd, v.CacheObject...); err != nil {
  1575  					zlog.Error("MySQL data synchronization Mongo failed", 0, zlog.Any("data", v), zlog.AddError(err))
  1576  				}
  1577  			}
  1578  		}
  1579  	}
  1580  	return nil
  1581  }
  1582  
  1583  // mongo同步数据
  1584  func (self *RDBManager) mongoSyncData(option int, model sqlc.Object, cnd *sqlc.Cnd, data ...sqlc.Object) error {
  1585  	mongo, err := new(MGOManager).Get(self.Option)
  1586  	if err != nil {
  1587  		return utils.Error("failed to get Mongo connection: ", err)
  1588  	}
  1589  	defer mongo.Close()
  1590  	mongo.MGOSyncData = []*MGOSyncData{
  1591  		{option, model, cnd, data},
  1592  	}
  1593  	switch option {
  1594  	case SAVE:
  1595  		return mongo.Save(data...)
  1596  	case UPDATE:
  1597  		return mongo.Update(data...)
  1598  	case DELETE:
  1599  		return mongo.Delete(data...)
  1600  	case UPDATE_BY_CND:
  1601  		if cnd == nil {
  1602  			return utils.Error("synchronization condition object is nil")
  1603  		}
  1604  		_, err = mongo.UpdateByCnd(cnd)
  1605  		if err != nil {
  1606  			return err
  1607  		}
  1608  		return nil
  1609  	}
  1610  	return nil
  1611  }
  1612  
  1613  // 输出查询结果集
  1614  func OutDest(rows *sql.Rows, flen int) ([][][]byte, error) {
  1615  	out := make([][][]byte, 0)
  1616  	for rows.Next() {
  1617  		rets := make([][]byte, flen)
  1618  		dest := make([]interface{}, flen)
  1619  		for i, _ := range rets {
  1620  			dest[i] = &rets[i]
  1621  		}
  1622  		if err := rows.Scan(dest...); err != nil {
  1623  			return nil, utils.Error("rows scan failed: ", err)
  1624  		}
  1625  		out = append(out, rets)
  1626  	}
  1627  	if err := rows.Err(); err != nil {
  1628  		return nil, utils.Error("rows.Err(): ", err)
  1629  	}
  1630  	return out, nil
  1631  }
  1632  
  1633  func (self *RDBManager) BuildCondKey(cnd *sqlc.Cnd, key string) []byte {
  1634  	fieldPart := bytes.NewBuffer(make([]byte, 0, 16))
  1635  	if cnd.Escape {
  1636  		fieldPart.WriteString(" ")
  1637  		fieldPart.WriteString("`")
  1638  		fieldPart.WriteString(key)
  1639  		fieldPart.WriteString("`")
  1640  	} else {
  1641  		fieldPart.WriteString(" ")
  1642  		fieldPart.WriteString(key)
  1643  	}
  1644  	return fieldPart.Bytes()
  1645  }
  1646  
  1647  // 构建where条件
  1648  func (self *RDBManager) BuildWhereCase(cnd *sqlc.Cnd) (*bytes.Buffer, []interface{}) {
  1649  	var case_arg []interface{}
  1650  	if cnd == nil {
  1651  		return bytes.NewBuffer(make([]byte, 0, 64)), case_arg
  1652  	}
  1653  	case_part := bytes.NewBuffer(make([]byte, 0, 128))
  1654  	for _, v := range cnd.Conditions {
  1655  		key := v.Key
  1656  		value := v.Value
  1657  		values := v.Values
  1658  		switch v.Logic {
  1659  		// case condition
  1660  		case sqlc.EQ_:
  1661  			case_part.Write(self.BuildCondKey(cnd, key))
  1662  			case_part.WriteString(" = ? and")
  1663  			case_arg = append(case_arg, value)
  1664  		case sqlc.NOT_EQ_:
  1665  			case_part.Write(self.BuildCondKey(cnd, key))
  1666  			case_part.WriteString(" <> ? and")
  1667  			case_arg = append(case_arg, value)
  1668  		case sqlc.LT_:
  1669  			case_part.Write(self.BuildCondKey(cnd, key))
  1670  			case_part.WriteString(" < ? and")
  1671  			case_arg = append(case_arg, value)
  1672  		case sqlc.LTE_:
  1673  			case_part.Write(self.BuildCondKey(cnd, key))
  1674  			case_part.WriteString(" <= ? and")
  1675  			case_arg = append(case_arg, value)
  1676  		case sqlc.GT_:
  1677  			case_part.Write(self.BuildCondKey(cnd, key))
  1678  			case_part.WriteString(" > ? and")
  1679  			case_arg = append(case_arg, value)
  1680  		case sqlc.GTE_:
  1681  			case_part.Write(self.BuildCondKey(cnd, key))
  1682  			case_part.WriteString(" >= ? and")
  1683  			case_arg = append(case_arg, value)
  1684  		case sqlc.IS_NULL_:
  1685  			case_part.Write(self.BuildCondKey(cnd, key))
  1686  			case_part.WriteString(" is null and")
  1687  		case sqlc.IS_NOT_NULL_:
  1688  			case_part.Write(self.BuildCondKey(cnd, key))
  1689  			case_part.WriteString(" is not null and")
  1690  		case sqlc.BETWEEN_:
  1691  			case_part.Write(self.BuildCondKey(cnd, key))
  1692  			case_part.WriteString(" between ? and ? and")
  1693  			case_arg = append(case_arg, values[0])
  1694  			case_arg = append(case_arg, values[1])
  1695  		case sqlc.NOT_BETWEEN_:
  1696  			case_part.Write(self.BuildCondKey(cnd, key))
  1697  			case_part.WriteString(" not between ? and ? and")
  1698  			case_arg = append(case_arg, values[0])
  1699  			case_arg = append(case_arg, values[1])
  1700  		case sqlc.IN_:
  1701  			case_part.Write(self.BuildCondKey(cnd, key))
  1702  			case_part.WriteString(" in(")
  1703  			var buf bytes.Buffer
  1704  			for _, v := range values {
  1705  				buf.WriteString("?,")
  1706  				case_arg = append(case_arg, v)
  1707  			}
  1708  			s := buf.String()
  1709  			case_part.WriteString(utils.Substr(s, 0, len(s)-1))
  1710  			case_part.WriteString(") and")
  1711  		case sqlc.NOT_IN_:
  1712  			case_part.Write(self.BuildCondKey(cnd, key))
  1713  			case_part.WriteString(" not in(")
  1714  			var buf bytes.Buffer
  1715  			for _, v := range values {
  1716  				buf.WriteString("?,")
  1717  				case_arg = append(case_arg, v)
  1718  			}
  1719  			s := buf.String()
  1720  			case_part.WriteString(utils.Substr(s, 0, len(s)-1))
  1721  			case_part.WriteString(") and")
  1722  		case sqlc.LIKE_:
  1723  			case_part.Write(self.BuildCondKey(cnd, key))
  1724  			case_part.WriteString(" like concat('%',?,'%') and")
  1725  			case_arg = append(case_arg, value)
  1726  		case sqlc.NOT_LIKE_:
  1727  			case_part.Write(self.BuildCondKey(cnd, key))
  1728  			case_part.WriteString(" not like concat('%',?,'%') and")
  1729  			case_arg = append(case_arg, value)
  1730  		case sqlc.OR_:
  1731  			var orpart bytes.Buffer
  1732  			var args []interface{}
  1733  			for _, v := range values {
  1734  				cnd, ok := v.(*sqlc.Cnd)
  1735  				if !ok {
  1736  					continue
  1737  				}
  1738  				buf, arg := self.BuildWhereCase(cnd)
  1739  				s := buf.String()
  1740  				s = utils.Substr(s, 0, len(s)-3)
  1741  				orpart.WriteString(s)
  1742  				orpart.WriteString(" or")
  1743  				for _, v := range arg {
  1744  					args = append(args, v)
  1745  				}
  1746  			}
  1747  			s := orpart.String()
  1748  			s = utils.Substr(s, 0, len(s)-3)
  1749  			case_part.WriteString(" (")
  1750  			case_part.WriteString(s)
  1751  			case_part.WriteString(") and")
  1752  			for _, v := range args {
  1753  				case_arg = append(case_arg, v)
  1754  			}
  1755  		}
  1756  	}
  1757  	return case_part, case_arg
  1758  }
  1759  
  1760  // 构建分组命令
  1761  func (self *RDBManager) BuildGroupBy(cnd *sqlc.Cnd) string {
  1762  	if cnd == nil || len(cnd.Groupbys) <= 0 {
  1763  		return ""
  1764  	}
  1765  	groupby := bytes.NewBuffer(make([]byte, 0, 64))
  1766  	groupby.WriteString(" group by")
  1767  	for _, v := range cnd.Groupbys {
  1768  		if len(v) == 0 {
  1769  			continue
  1770  		}
  1771  		if cnd.Escape {
  1772  			groupby.WriteString(" ")
  1773  			groupby.WriteString("`")
  1774  			groupby.WriteString(v)
  1775  			groupby.WriteString("`")
  1776  			groupby.WriteString(",")
  1777  		} else {
  1778  			groupby.WriteString(" ")
  1779  			groupby.WriteString(v)
  1780  			groupby.WriteString(",")
  1781  		}
  1782  	}
  1783  	s := utils.Bytes2Str(groupby.Bytes())
  1784  	return utils.Substr(s, 0, len(s)-1)
  1785  }
  1786  
  1787  // 构建排序命令
  1788  func (self *RDBManager) BuildSortBy(cnd *sqlc.Cnd) string {
  1789  	if cnd == nil || len(cnd.Orderbys) <= 0 {
  1790  		return ""
  1791  	}
  1792  	var sortby = bytes.Buffer{}
  1793  	sortby.WriteString(" order by")
  1794  	for _, v := range cnd.Orderbys {
  1795  		if cnd.Escape {
  1796  			sortby.WriteString(" ")
  1797  			sortby.WriteString("`")
  1798  			sortby.WriteString(v.Key)
  1799  			sortby.WriteString("`")
  1800  		} else {
  1801  			sortby.WriteString(" ")
  1802  			sortby.WriteString(v.Key)
  1803  		}
  1804  		if v.Value == sqlc.DESC_ {
  1805  			sortby.WriteString(" desc,")
  1806  		} else if v.Value == sqlc.ASC_ {
  1807  			sortby.WriteString(" asc,")
  1808  		}
  1809  	}
  1810  	s := utils.Bytes2Str(sortby.Bytes())
  1811  	return utils.Substr(s, 0, len(s)-1)
  1812  }
  1813  
  1814  // 构建分页命令
  1815  func (self *RDBManager) BuildPagination(cnd *sqlc.Cnd, sqlbuf string, values []interface{}) (string, error) {
  1816  	if cnd == nil {
  1817  		return sqlbuf, nil
  1818  	}
  1819  	pagination := cnd.Pagination
  1820  	if pagination.PageNo == 0 && pagination.PageSize == 0 {
  1821  		return sqlbuf, nil
  1822  	}
  1823  	if pagination.PageSize <= 0 {
  1824  		pagination.PageSize = 10
  1825  	}
  1826  	dialect := dialect.MysqlDialect{Dialect: pagination}
  1827  	limitSql, err := dialect.GetLimitSql(sqlbuf)
  1828  	if err != nil {
  1829  		return "", err
  1830  	}
  1831  	if !dialect.IsPage {
  1832  		return limitSql, nil
  1833  	}
  1834  	if !dialect.IsOffset {
  1835  		countSql, err := dialect.GetCountSql(sqlbuf)
  1836  		if err != nil {
  1837  			return "", err
  1838  		}
  1839  		ctx, cancel := context.WithTimeout(context.Background(), time.Duration(self.Timeout)*time.Millisecond)
  1840  		defer cancel()
  1841  		var rows *sql.Rows
  1842  		if self.OpenTx {
  1843  			rows, err = self.Tx.QueryContext(ctx, countSql, values...)
  1844  		} else {
  1845  			rows, err = self.Db.QueryContext(ctx, countSql, values...)
  1846  		}
  1847  		if err != nil {
  1848  			return "", self.Error("count query failed: ", err)
  1849  		}
  1850  		defer rows.Close()
  1851  		var pageTotal int64
  1852  		for rows.Next() {
  1853  			if err := rows.Scan(&pageTotal); err != nil {
  1854  				return "", self.Error("rows scan failed: ", err)
  1855  			}
  1856  		}
  1857  		if err := rows.Err(); err != nil {
  1858  			return "", self.Error("rows.Err(): ", err)
  1859  		}
  1860  		var pageCount int64
  1861  		if pageTotal%cnd.Pagination.PageSize == 0 {
  1862  			pageCount = pageTotal / cnd.Pagination.PageSize
  1863  		} else {
  1864  			pageCount = pageTotal/cnd.Pagination.PageSize + 1
  1865  		}
  1866  		cnd.Pagination.PageTotal = pageTotal
  1867  		cnd.Pagination.PageCount = pageCount
  1868  	}
  1869  	return limitSql, nil
  1870  }