github.com/goravel/framework@v1.13.9/database/gorm/query.go (about)

     1  package gorm
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"errors"
     7  	"fmt"
     8  	"reflect"
     9  
    10  	"github.com/google/wire"
    11  	"github.com/spf13/cast"
    12  	"gorm.io/driver/mysql"
    13  	"gorm.io/driver/postgres"
    14  	"gorm.io/driver/sqlserver"
    15  	gormio "gorm.io/gorm"
    16  	"gorm.io/gorm/clause"
    17  
    18  	"github.com/goravel/framework/contracts/config"
    19  	ormcontract "github.com/goravel/framework/contracts/database/orm"
    20  	"github.com/goravel/framework/database/gorm/hints"
    21  	"github.com/goravel/framework/database/orm"
    22  	"github.com/goravel/framework/support/database"
    23  )
    24  
    25  var QuerySet = wire.NewSet(BuildQueryImpl, wire.Bind(new(ormcontract.Query), new(*QueryImpl)))
    26  var _ ormcontract.Query = &QueryImpl{}
    27  
    28  type QueryImpl struct {
    29  	conditions Conditions
    30  	config     config.Config
    31  	connection string
    32  	ctx        context.Context
    33  	instance   *gormio.DB
    34  	queries    map[string]*QueryImpl
    35  }
    36  
    37  func NewQueryImpl(ctx context.Context, config config.Config, connection string, db *gormio.DB, conditions *Conditions) *QueryImpl {
    38  	queryImpl := &QueryImpl{
    39  		config:     config,
    40  		connection: connection,
    41  		ctx:        ctx,
    42  		instance:   db,
    43  		queries:    make(map[string]*QueryImpl),
    44  	}
    45  
    46  	if conditions != nil {
    47  		queryImpl.conditions = *conditions
    48  	}
    49  
    50  	return queryImpl
    51  }
    52  
    53  func BuildQueryImpl(ctx context.Context, config config.Config, connection string, gorm Gorm) (*QueryImpl, error) {
    54  	db, err := gorm.Make()
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	if ctx != nil {
    59  		db = db.WithContext(ctx)
    60  	}
    61  
    62  	return NewQueryImpl(ctx, config, connection, db, nil), nil
    63  }
    64  
    65  func (r *QueryImpl) Association(association string) ormcontract.Association {
    66  	query := r.buildConditions()
    67  
    68  	return query.instance.Association(association)
    69  }
    70  
    71  func (r *QueryImpl) Begin() (ormcontract.Transaction, error) {
    72  	tx := r.instance.Begin()
    73  
    74  	return NewTransaction(tx, r.config, r.connection), tx.Error
    75  }
    76  
    77  func (r *QueryImpl) Driver() ormcontract.Driver {
    78  	return ormcontract.Driver(r.instance.Dialector.Name())
    79  }
    80  
    81  func (r *QueryImpl) Count(count *int64) error {
    82  	query := r.buildConditions()
    83  
    84  	return query.instance.Count(count).Error
    85  }
    86  
    87  func (r *QueryImpl) Create(value any) error {
    88  	query, err := r.refreshConnection(value)
    89  	if err != nil {
    90  		return err
    91  	}
    92  	query = query.buildConditions()
    93  
    94  	if len(query.instance.Statement.Selects) > 0 && len(query.instance.Statement.Omits) > 0 {
    95  		return errors.New("cannot set Select and Omits at the same time")
    96  	}
    97  
    98  	if len(query.instance.Statement.Selects) > 0 {
    99  		return query.selectCreate(value)
   100  	}
   101  
   102  	if len(query.instance.Statement.Omits) > 0 {
   103  		return query.omitCreate(value)
   104  	}
   105  
   106  	return query.create(value)
   107  }
   108  
   109  func (r *QueryImpl) Cursor() (chan ormcontract.Cursor, error) {
   110  	with := r.conditions.with
   111  	query := r.buildConditions()
   112  	r.conditions.with = with
   113  
   114  	var err error
   115  	cursorChan := make(chan ormcontract.Cursor)
   116  	go func() {
   117  		var rows *sql.Rows
   118  		rows, err = query.instance.Rows()
   119  		if err != nil {
   120  			return
   121  		}
   122  		defer rows.Close()
   123  
   124  		for rows.Next() {
   125  			val := make(map[string]any)
   126  			err = query.instance.ScanRows(rows, val)
   127  			if err != nil {
   128  				return
   129  			}
   130  			cursorChan <- &CursorImpl{query: r, row: val}
   131  		}
   132  		close(cursorChan)
   133  	}()
   134  	return cursorChan, err
   135  }
   136  
   137  func (r *QueryImpl) Delete(dest any, conds ...any) (*ormcontract.Result, error) {
   138  	query, err := r.refreshConnection(dest)
   139  	if err != nil {
   140  		return nil, err
   141  	}
   142  	query = query.buildConditions()
   143  
   144  	if err := query.deleting(dest); err != nil {
   145  		return nil, err
   146  	}
   147  
   148  	res := query.instance.Delete(dest, conds...)
   149  	if res.Error != nil {
   150  		return nil, res.Error
   151  	}
   152  
   153  	if err := query.deleted(dest); err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	return &ormcontract.Result{
   158  		RowsAffected: res.RowsAffected,
   159  	}, nil
   160  }
   161  
   162  func (r *QueryImpl) Distinct(args ...any) ormcontract.Query {
   163  	conditions := r.conditions
   164  	conditions.distinct = append(conditions.distinct, args...)
   165  
   166  	return r.setConditions(conditions)
   167  }
   168  
   169  func (r *QueryImpl) Exec(sql string, values ...any) (*ormcontract.Result, error) {
   170  	query := r.buildConditions()
   171  	result := query.instance.Exec(sql, values...)
   172  
   173  	return &ormcontract.Result{
   174  		RowsAffected: result.RowsAffected,
   175  	}, result.Error
   176  }
   177  
   178  func (r *QueryImpl) Find(dest any, conds ...any) error {
   179  	query, err := r.refreshConnection(dest)
   180  	if err != nil {
   181  		return err
   182  	}
   183  
   184  	query = query.buildConditions()
   185  
   186  	if err := filterFindConditions(conds...); err != nil {
   187  		return err
   188  	}
   189  	if err := query.instance.Find(dest, conds...).Error; err != nil {
   190  		return err
   191  	}
   192  
   193  	return query.retrieved(dest)
   194  }
   195  
   196  func (r *QueryImpl) FindOrFail(dest any, conds ...any) error {
   197  	query, err := r.refreshConnection(dest)
   198  	if err != nil {
   199  		return err
   200  	}
   201  
   202  	query = query.buildConditions()
   203  
   204  	if err := filterFindConditions(conds...); err != nil {
   205  		return err
   206  	}
   207  
   208  	res := query.instance.Find(dest, conds...)
   209  	if err := res.Error; err != nil {
   210  		return err
   211  	}
   212  
   213  	if res.RowsAffected == 0 {
   214  		return orm.ErrRecordNotFound
   215  	}
   216  
   217  	return query.retrieved(dest)
   218  }
   219  
   220  func (r *QueryImpl) First(dest any) error {
   221  	query, err := r.refreshConnection(dest)
   222  	if err != nil {
   223  		return err
   224  	}
   225  
   226  	query = query.buildConditions()
   227  
   228  	res := query.instance.First(dest)
   229  	if res.Error != nil {
   230  		if errors.Is(res.Error, gormio.ErrRecordNotFound) {
   231  			return nil
   232  		}
   233  
   234  		return res.Error
   235  	}
   236  
   237  	return query.retrieved(dest)
   238  }
   239  
   240  func (r *QueryImpl) FirstOr(dest any, callback func() error) error {
   241  	query, err := r.refreshConnection(dest)
   242  	if err != nil {
   243  		return err
   244  	}
   245  
   246  	query = query.buildConditions()
   247  
   248  	if err := query.instance.First(dest).Error; err != nil {
   249  		if errors.Is(err, gormio.ErrRecordNotFound) {
   250  			return callback()
   251  		}
   252  
   253  		return err
   254  	}
   255  
   256  	return query.retrieved(dest)
   257  }
   258  
   259  func (r *QueryImpl) FirstOrCreate(dest any, conds ...any) error {
   260  	query, err := r.refreshConnection(dest)
   261  	if err != nil {
   262  		return err
   263  	}
   264  
   265  	query = query.buildConditions()
   266  
   267  	if len(conds) == 0 {
   268  		return errors.New("query condition is require")
   269  	}
   270  
   271  	var res *gormio.DB
   272  	if len(conds) > 1 {
   273  		res = query.instance.Attrs(conds[1]).FirstOrInit(dest, conds[0])
   274  	} else {
   275  		res = query.instance.FirstOrInit(dest, conds[0])
   276  	}
   277  
   278  	if res.Error != nil {
   279  		return res.Error
   280  	}
   281  	if res.RowsAffected > 0 {
   282  		return query.retrieved(dest)
   283  	}
   284  
   285  	return query.Create(dest)
   286  }
   287  
   288  func (r *QueryImpl) FirstOrFail(dest any) error {
   289  	query, err := r.refreshConnection(dest)
   290  	if err != nil {
   291  		return err
   292  	}
   293  
   294  	query = query.buildConditions()
   295  
   296  	if err := query.instance.First(dest).Error; err != nil {
   297  		if errors.Is(err, gormio.ErrRecordNotFound) {
   298  			return orm.ErrRecordNotFound
   299  		}
   300  
   301  		return err
   302  	}
   303  
   304  	return query.retrieved(dest)
   305  }
   306  
   307  func (r *QueryImpl) FirstOrNew(dest any, attributes any, values ...any) error {
   308  	query, err := r.refreshConnection(dest)
   309  	if err != nil {
   310  		return err
   311  	}
   312  
   313  	query = query.buildConditions()
   314  
   315  	var res *gormio.DB
   316  	if len(values) > 0 {
   317  		res = query.instance.Attrs(values[0]).FirstOrInit(dest, attributes)
   318  	} else {
   319  		res = query.instance.FirstOrInit(dest, attributes)
   320  	}
   321  
   322  	if res.Error != nil {
   323  		return res.Error
   324  	}
   325  	if res.RowsAffected > 0 {
   326  		return query.retrieved(dest)
   327  	}
   328  
   329  	return nil
   330  }
   331  
   332  func (r *QueryImpl) ForceDelete(value any, conds ...any) (*ormcontract.Result, error) {
   333  	query, err := r.refreshConnection(value)
   334  	if err != nil {
   335  		return nil, err
   336  	}
   337  
   338  	query = query.buildConditions()
   339  
   340  	if err := query.forceDeleting(value); err != nil {
   341  		return nil, err
   342  	}
   343  
   344  	res := query.instance.Unscoped().Delete(value, conds...)
   345  	if res.Error != nil {
   346  		return nil, res.Error
   347  	}
   348  
   349  	if res.RowsAffected > 0 {
   350  		if err := query.forceDeleted(value); err != nil {
   351  			return nil, err
   352  		}
   353  	}
   354  
   355  	return &ormcontract.Result{
   356  		RowsAffected: res.RowsAffected,
   357  	}, res.Error
   358  }
   359  
   360  func (r *QueryImpl) Get(dest any) error {
   361  	return r.Find(dest)
   362  }
   363  
   364  func (r *QueryImpl) Group(name string) ormcontract.Query {
   365  	conditions := r.conditions
   366  	conditions.group = name
   367  
   368  	return r.setConditions(conditions)
   369  }
   370  
   371  func (r *QueryImpl) Having(query any, args ...any) ormcontract.Query {
   372  	conditions := r.conditions
   373  	conditions.having = &Having{
   374  		query: query,
   375  		args:  args,
   376  	}
   377  
   378  	return r.setConditions(conditions)
   379  }
   380  
   381  func (r *QueryImpl) Instance() *gormio.DB {
   382  	return r.instance
   383  }
   384  
   385  func (r *QueryImpl) Join(query string, args ...any) ormcontract.Query {
   386  	conditions := r.conditions
   387  	conditions.join = append(conditions.join, Join{
   388  		query: query,
   389  		args:  args,
   390  	})
   391  
   392  	return r.setConditions(conditions)
   393  }
   394  
   395  func (r *QueryImpl) Limit(limit int) ormcontract.Query {
   396  	conditions := r.conditions
   397  	conditions.limit = &limit
   398  
   399  	return r.setConditions(conditions)
   400  }
   401  
   402  func (r *QueryImpl) Load(model any, relation string, args ...any) error {
   403  	if relation == "" {
   404  		return errors.New("relation cannot be empty")
   405  	}
   406  
   407  	destType := reflect.TypeOf(model)
   408  	if destType.Kind() != reflect.Pointer {
   409  		return errors.New("model must be pointer")
   410  	}
   411  
   412  	if id := database.GetID(model); id == nil {
   413  		return errors.New("id cannot be empty")
   414  	}
   415  
   416  	copyDest := copyStruct(model)
   417  	err := r.With(relation, args...).Find(model)
   418  
   419  	t := destType.Elem()
   420  	v := reflect.ValueOf(model).Elem()
   421  	for i := 0; i < t.NumField(); i++ {
   422  		if !t.Field(i).IsExported() {
   423  			continue
   424  		}
   425  		if t.Field(i).Name != relation {
   426  			v.Field(i).Set(copyDest.Field(i))
   427  		}
   428  	}
   429  
   430  	return err
   431  }
   432  
   433  func (r *QueryImpl) LoadMissing(model any, relation string, args ...any) error {
   434  	destType := reflect.TypeOf(model)
   435  	if destType.Kind() != reflect.Pointer {
   436  		return errors.New("model must be pointer")
   437  	}
   438  
   439  	t := reflect.TypeOf(model).Elem()
   440  	v := reflect.ValueOf(model).Elem()
   441  	for i := 0; i < t.NumField(); i++ {
   442  		if !t.Field(i).IsExported() {
   443  			continue
   444  		}
   445  		if t.Field(i).Name == relation {
   446  			var id any
   447  			if v.Field(i).Kind() == reflect.Pointer {
   448  				if !v.Field(i).IsNil() {
   449  					id = database.GetIDByReflect(v.Field(i).Type().Elem(), v.Field(i).Elem())
   450  				}
   451  			} else if v.Field(i).Kind() == reflect.Slice {
   452  				if v.Field(i).Len() > 0 {
   453  					return nil
   454  				}
   455  			} else {
   456  				id = database.GetIDByReflect(v.Field(i).Type(), v.Field(i))
   457  			}
   458  			if cast.ToString(id) != "" {
   459  				return nil
   460  			}
   461  		}
   462  	}
   463  
   464  	return r.Load(model, relation, args...)
   465  }
   466  
   467  func (r *QueryImpl) LockForUpdate() ormcontract.Query {
   468  	conditions := r.conditions
   469  	conditions.lockForUpdate = true
   470  
   471  	return r.setConditions(conditions)
   472  }
   473  
   474  func (r *QueryImpl) Model(value any) ormcontract.Query {
   475  	conditions := r.conditions
   476  	conditions.model = value
   477  
   478  	return r.setConditions(conditions)
   479  }
   480  
   481  func (r *QueryImpl) Offset(offset int) ormcontract.Query {
   482  	conditions := r.conditions
   483  	conditions.offset = &offset
   484  
   485  	return r.setConditions(conditions)
   486  }
   487  
   488  func (r *QueryImpl) Omit(columns ...string) ormcontract.Query {
   489  	conditions := r.conditions
   490  	conditions.omit = columns
   491  
   492  	return r.setConditions(conditions)
   493  }
   494  
   495  func (r *QueryImpl) Order(value any) ormcontract.Query {
   496  	conditions := r.conditions
   497  	conditions.order = append(r.conditions.order, value)
   498  
   499  	return r.setConditions(conditions)
   500  }
   501  
   502  func (r *QueryImpl) OrWhere(query any, args ...any) ormcontract.Query {
   503  	conditions := r.conditions
   504  	conditions.where = append(r.conditions.where, Where{
   505  		query: query,
   506  		args:  args,
   507  		or:    true,
   508  	})
   509  
   510  	return r.setConditions(conditions)
   511  }
   512  
   513  func (r *QueryImpl) Paginate(page, limit int, dest any, total *int64) error {
   514  	query, err := r.refreshConnection(dest)
   515  	if err != nil {
   516  		return err
   517  	}
   518  
   519  	query = query.buildConditions()
   520  
   521  	offset := (page - 1) * limit
   522  	if total != nil {
   523  		if query.conditions.table == nil && query.conditions.model == nil {
   524  			if err := query.Model(dest).Count(total); err != nil {
   525  				return err
   526  			}
   527  		} else {
   528  			if err := query.Count(total); err != nil {
   529  				return err
   530  			}
   531  		}
   532  	}
   533  
   534  	return query.Offset(offset).Limit(limit).Find(dest)
   535  }
   536  
   537  func (r *QueryImpl) Pluck(column string, dest any) error {
   538  	query := r.buildConditions()
   539  
   540  	return query.instance.Pluck(column, dest).Error
   541  }
   542  
   543  func (r *QueryImpl) Raw(sql string, values ...any) ormcontract.Query {
   544  	return r.new(r.instance.Raw(sql, values...))
   545  }
   546  
   547  func (r *QueryImpl) Save(value any) error {
   548  	query, err := r.refreshConnection(value)
   549  	if err != nil {
   550  		return err
   551  	}
   552  
   553  	query = query.buildConditions()
   554  
   555  	if len(query.instance.Statement.Selects) > 0 && len(query.instance.Statement.Omits) > 0 {
   556  		return errors.New("cannot set Select and Omits at the same time")
   557  	}
   558  
   559  	model := query.instance.Statement.Model
   560  	id := database.GetID(value)
   561  	update := id != nil
   562  
   563  	if err := query.saving(model, value); err != nil {
   564  		return err
   565  	}
   566  	if update {
   567  		if err := query.updating(model, value); err != nil {
   568  			return err
   569  		}
   570  	} else {
   571  		if err := query.creating(value); err != nil {
   572  			return err
   573  		}
   574  	}
   575  
   576  	if len(query.instance.Statement.Selects) > 0 {
   577  		if err := query.selectSave(value); err != nil {
   578  			return err
   579  		}
   580  	} else if len(query.instance.Statement.Omits) > 0 {
   581  		if err := query.omitSave(value); err != nil {
   582  			return err
   583  		}
   584  	} else {
   585  		if err := query.save(value); err != nil {
   586  			return err
   587  		}
   588  	}
   589  
   590  	if update {
   591  		if err := query.updated(model, value); err != nil {
   592  			return err
   593  		}
   594  	} else {
   595  		if err := query.created(value); err != nil {
   596  			return err
   597  		}
   598  	}
   599  	if err := query.saved(model, value); err != nil {
   600  		return err
   601  	}
   602  
   603  	return nil
   604  }
   605  
   606  func (r *QueryImpl) SaveQuietly(value any) error {
   607  	return r.WithoutEvents().Save(value)
   608  }
   609  
   610  func (r *QueryImpl) Scan(dest any) error {
   611  	query, err := r.refreshConnection(dest)
   612  	if err != nil {
   613  		return err
   614  	}
   615  
   616  	query = query.buildConditions()
   617  
   618  	return query.instance.Scan(dest).Error
   619  }
   620  
   621  func (r *QueryImpl) Scopes(funcs ...func(ormcontract.Query) ormcontract.Query) ormcontract.Query {
   622  	conditions := r.conditions
   623  	conditions.scopes = append(r.conditions.scopes, funcs...)
   624  
   625  	return r.setConditions(conditions)
   626  }
   627  
   628  func (r *QueryImpl) Select(query any, args ...any) ormcontract.Query {
   629  	conditions := r.conditions
   630  	conditions.selectColumns = &Select{
   631  		query: query,
   632  		args:  args,
   633  	}
   634  
   635  	return r.setConditions(conditions)
   636  }
   637  
   638  func (r *QueryImpl) SetContext(ctx context.Context) {
   639  	r.ctx = ctx
   640  	r.instance.Statement.Context = ctx
   641  }
   642  
   643  func (r *QueryImpl) SharedLock() ormcontract.Query {
   644  	conditions := r.conditions
   645  	conditions.sharedLock = true
   646  
   647  	return r.setConditions(conditions)
   648  }
   649  
   650  func (r *QueryImpl) Sum(column string, dest any) error {
   651  	query := r.buildConditions()
   652  
   653  	return query.instance.Select("SUM(" + column + ")").Row().Scan(dest)
   654  }
   655  
   656  func (r *QueryImpl) Table(name string, args ...any) ormcontract.Query {
   657  	conditions := r.conditions
   658  	conditions.table = &Table{
   659  		name: name,
   660  		args: args,
   661  	}
   662  
   663  	return r.setConditions(conditions)
   664  }
   665  
   666  func (r *QueryImpl) Update(column any, value ...any) (*ormcontract.Result, error) {
   667  	query := r.buildConditions()
   668  
   669  	if _, ok := column.(string); !ok && len(value) > 0 {
   670  		return nil, errors.New("parameter error, please check the document")
   671  	}
   672  
   673  	var singleUpdate bool
   674  	model := query.instance.Statement.Model
   675  	if model != nil {
   676  		id := database.GetID(model)
   677  		singleUpdate = id != nil
   678  	}
   679  
   680  	if c, ok := column.(string); ok && len(value) > 0 {
   681  		query.instance.Statement.Dest = map[string]any{c: value[0]}
   682  	}
   683  	if len(value) == 0 {
   684  		query.instance.Statement.Dest = column
   685  	}
   686  
   687  	if singleUpdate {
   688  		if err := query.saving(model, query.instance.Statement.Dest); err != nil {
   689  			return nil, err
   690  		}
   691  		if err := query.updating(model, query.instance.Statement.Dest); err != nil {
   692  			return nil, err
   693  		}
   694  	}
   695  
   696  	res, err := query.updates(query.instance.Statement.Dest)
   697  
   698  	if singleUpdate && err == nil {
   699  		if err := query.updated(model, query.instance.Statement.Dest); err != nil {
   700  			return nil, err
   701  		}
   702  		if err := query.saved(model, query.instance.Statement.Dest); err != nil {
   703  			return nil, err
   704  		}
   705  	}
   706  
   707  	return res, err
   708  }
   709  
   710  func (r *QueryImpl) UpdateOrCreate(dest any, attributes any, values any) error {
   711  	query, err := r.refreshConnection(dest)
   712  	if err != nil {
   713  		return err
   714  	}
   715  
   716  	query = query.buildConditions()
   717  
   718  	res := query.instance.Assign(values).FirstOrInit(dest, attributes)
   719  	if res.Error != nil {
   720  		return res.Error
   721  	}
   722  	if res.RowsAffected > 0 {
   723  		return query.Save(dest)
   724  	}
   725  
   726  	return query.Create(dest)
   727  }
   728  
   729  func (r *QueryImpl) Where(query any, args ...any) ormcontract.Query {
   730  	conditions := r.conditions
   731  	conditions.where = append(r.conditions.where, Where{
   732  		query: query,
   733  		args:  args,
   734  	})
   735  
   736  	return r.setConditions(conditions)
   737  }
   738  
   739  func (r *QueryImpl) With(query string, args ...any) ormcontract.Query {
   740  	conditions := r.conditions
   741  	conditions.with = append(r.conditions.with, With{
   742  		query: query,
   743  		args:  args,
   744  	})
   745  
   746  	return r.setConditions(conditions)
   747  }
   748  
   749  func (r *QueryImpl) WithoutEvents() ormcontract.Query {
   750  	conditions := r.conditions
   751  	conditions.withoutEvents = true
   752  
   753  	return r.setConditions(conditions)
   754  }
   755  
   756  func (r *QueryImpl) WithTrashed() ormcontract.Query {
   757  	conditions := r.conditions
   758  	conditions.withTrashed = true
   759  
   760  	return r.setConditions(conditions)
   761  }
   762  
   763  func (r *QueryImpl) buildConditions() *QueryImpl {
   764  	query := r.buildModel()
   765  	db := query.instance
   766  	db = query.buildDistinct(db)
   767  	db = query.buildGroup(db)
   768  	db = query.buildHaving(db)
   769  	db = query.buildJoin(db)
   770  	db = query.buildLockForUpdate(db)
   771  	db = query.buildLimit(db)
   772  	db = query.buildOrder(db)
   773  	db = query.buildOffset(db)
   774  	db = query.buildOmit(db)
   775  	db = query.buildScopes(db)
   776  	db = query.buildSelectColumns(db)
   777  	db = query.buildSharedLock(db)
   778  	db = query.buildTable(db)
   779  	db = query.buildWith(db)
   780  	db = query.buildWithTrashed(db)
   781  	db = query.buildWhere(db)
   782  
   783  	return query.new(db)
   784  }
   785  
   786  func (r *QueryImpl) buildDistinct(db *gormio.DB) *gormio.DB {
   787  	if len(r.conditions.distinct) == 0 {
   788  		return db
   789  	}
   790  
   791  	db = db.Distinct(r.conditions.distinct...)
   792  	r.conditions.distinct = nil
   793  
   794  	return db
   795  }
   796  
   797  func (r *QueryImpl) buildGroup(db *gormio.DB) *gormio.DB {
   798  	if r.conditions.group == "" {
   799  		return db
   800  	}
   801  
   802  	db = db.Group(r.conditions.group)
   803  	r.conditions.group = ""
   804  
   805  	return db
   806  }
   807  
   808  func (r *QueryImpl) buildHaving(db *gormio.DB) *gormio.DB {
   809  	if r.conditions.having == nil {
   810  		return db
   811  	}
   812  
   813  	db = db.Having(r.conditions.having.query, r.conditions.having.args...)
   814  	r.conditions.having = nil
   815  
   816  	return db
   817  }
   818  
   819  func (r *QueryImpl) buildJoin(db *gormio.DB) *gormio.DB {
   820  	if r.conditions.join == nil {
   821  		return db
   822  	}
   823  
   824  	for _, item := range r.conditions.join {
   825  		db = db.Joins(item.query, item.args...)
   826  	}
   827  
   828  	r.conditions.join = nil
   829  
   830  	return db
   831  }
   832  
   833  func (r *QueryImpl) buildLimit(db *gormio.DB) *gormio.DB {
   834  	if r.conditions.limit == nil {
   835  		return db
   836  	}
   837  
   838  	db = db.Limit(*r.conditions.limit)
   839  	r.conditions.limit = nil
   840  
   841  	return db
   842  }
   843  
   844  func (r *QueryImpl) buildLockForUpdate(db *gormio.DB) *gormio.DB {
   845  	if !r.conditions.lockForUpdate {
   846  		return db
   847  	}
   848  
   849  	driver := r.instance.Name()
   850  	mysqlDialector := mysql.Dialector{}
   851  	postgresqlDialector := postgres.Dialector{}
   852  	sqlserverDialector := sqlserver.Dialector{}
   853  
   854  	if driver == mysqlDialector.Name() || driver == postgresqlDialector.Name() {
   855  		return db.Clauses(clause.Locking{Strength: "UPDATE"})
   856  	} else if driver == sqlserverDialector.Name() {
   857  		return db.Clauses(hints.With("rowlock", "updlock", "holdlock"))
   858  	}
   859  
   860  	r.conditions.lockForUpdate = false
   861  
   862  	return db
   863  }
   864  
   865  func (r *QueryImpl) buildModel() *QueryImpl {
   866  	if r.conditions.model == nil {
   867  		return r
   868  	}
   869  
   870  	query, err := r.refreshConnection(r.conditions.model)
   871  	if err != nil {
   872  		return nil
   873  	}
   874  
   875  	return query.new(query.instance.Model(r.conditions.model))
   876  }
   877  
   878  func (r *QueryImpl) buildOffset(db *gormio.DB) *gormio.DB {
   879  	if r.conditions.offset == nil {
   880  		return db
   881  	}
   882  
   883  	db = db.Offset(*r.conditions.offset)
   884  	r.conditions.offset = nil
   885  
   886  	return db
   887  }
   888  
   889  func (r *QueryImpl) buildOmit(db *gormio.DB) *gormio.DB {
   890  	if len(r.conditions.omit) == 0 {
   891  		return db
   892  	}
   893  
   894  	db = db.Omit(r.conditions.omit...)
   895  	r.conditions.omit = nil
   896  
   897  	return db
   898  }
   899  
   900  func (r *QueryImpl) buildOrder(db *gormio.DB) *gormio.DB {
   901  	if len(r.conditions.order) == 0 {
   902  		return db
   903  	}
   904  
   905  	for _, order := range r.conditions.order {
   906  		db = db.Order(order)
   907  	}
   908  
   909  	r.conditions.order = nil
   910  
   911  	return db
   912  }
   913  
   914  func (r *QueryImpl) buildSelectColumns(db *gormio.DB) *gormio.DB {
   915  	if r.conditions.selectColumns == nil {
   916  		return db
   917  	}
   918  
   919  	db = db.Select(r.conditions.selectColumns.query, r.conditions.selectColumns.args...)
   920  	r.conditions.selectColumns = nil
   921  
   922  	return db
   923  }
   924  
   925  func (r *QueryImpl) buildScopes(db *gormio.DB) *gormio.DB {
   926  	if len(r.conditions.scopes) == 0 {
   927  		return db
   928  	}
   929  
   930  	var gormFuncs []func(*gormio.DB) *gormio.DB
   931  	for _, scope := range r.conditions.scopes {
   932  		gormFuncs = append(gormFuncs, func(tx *gormio.DB) *gormio.DB {
   933  			queryImpl := r.new(tx)
   934  			query := scope(queryImpl)
   935  			queryImpl = query.(*QueryImpl)
   936  			queryImpl = queryImpl.buildConditions()
   937  
   938  			return queryImpl.instance
   939  		})
   940  	}
   941  
   942  	db = db.Scopes(gormFuncs...)
   943  	r.conditions.scopes = nil
   944  
   945  	return db
   946  }
   947  
   948  func (r *QueryImpl) buildSharedLock(db *gormio.DB) *gormio.DB {
   949  	if !r.conditions.sharedLock {
   950  		return db
   951  	}
   952  
   953  	driver := r.instance.Name()
   954  	mysqlDialector := mysql.Dialector{}
   955  	postgresqlDialector := postgres.Dialector{}
   956  	sqlserverDialector := sqlserver.Dialector{}
   957  
   958  	if driver == mysqlDialector.Name() || driver == postgresqlDialector.Name() {
   959  		return db.Clauses(clause.Locking{Strength: "SHARE"})
   960  	} else if driver == sqlserverDialector.Name() {
   961  		return db.Clauses(hints.With("rowlock", "holdlock"))
   962  	}
   963  
   964  	r.conditions.sharedLock = false
   965  
   966  	return db
   967  }
   968  
   969  func (r *QueryImpl) buildTable(db *gormio.DB) *gormio.DB {
   970  	if r.conditions.table == nil {
   971  		return db
   972  	}
   973  
   974  	db = db.Table(r.conditions.table.name, r.conditions.table.args...)
   975  	r.conditions.table = nil
   976  
   977  	return db
   978  }
   979  
   980  func (r *QueryImpl) buildWhere(db *gormio.DB) *gormio.DB {
   981  	if len(r.conditions.where) == 0 {
   982  		return db
   983  	}
   984  
   985  	for _, item := range r.conditions.where {
   986  		if item.or {
   987  			db = db.Or(item.query, item.args...)
   988  		} else {
   989  			db = db.Where(item.query, item.args...)
   990  		}
   991  	}
   992  
   993  	r.conditions.where = nil
   994  
   995  	return db
   996  }
   997  
   998  func (r *QueryImpl) buildWith(db *gormio.DB) *gormio.DB {
   999  	if len(r.conditions.with) == 0 {
  1000  		return db
  1001  	}
  1002  
  1003  	for _, item := range r.conditions.with {
  1004  		isSet := false
  1005  		if len(item.args) == 1 {
  1006  			if arg, ok := item.args[0].(func(ormcontract.Query) ormcontract.Query); ok {
  1007  				newArgs := []any{
  1008  					func(tx *gormio.DB) *gormio.DB {
  1009  						queryImpl := NewQueryImpl(r.ctx, r.config, r.connection, tx, nil)
  1010  						query := arg(queryImpl)
  1011  						queryImpl = query.(*QueryImpl)
  1012  						queryImpl = queryImpl.buildConditions()
  1013  
  1014  						return queryImpl.instance
  1015  					},
  1016  				}
  1017  
  1018  				db = db.Preload(item.query, newArgs...)
  1019  				isSet = true
  1020  			}
  1021  		}
  1022  
  1023  		if !isSet {
  1024  			db = db.Preload(item.query, item.args...)
  1025  		}
  1026  	}
  1027  
  1028  	r.conditions.with = nil
  1029  
  1030  	return db
  1031  }
  1032  
  1033  func (r *QueryImpl) buildWithTrashed(db *gormio.DB) *gormio.DB {
  1034  	if !r.conditions.withTrashed {
  1035  		return db
  1036  	}
  1037  
  1038  	db = db.Unscoped()
  1039  	r.conditions.withTrashed = false
  1040  
  1041  	return db
  1042  }
  1043  
  1044  func (r *QueryImpl) clearConditions() {
  1045  	r.conditions = Conditions{}
  1046  }
  1047  
  1048  func (r *QueryImpl) create(value any) error {
  1049  	if err := r.saving(nil, value); err != nil {
  1050  		return err
  1051  	}
  1052  	if err := r.creating(value); err != nil {
  1053  		return err
  1054  	}
  1055  
  1056  	if err := r.instance.Omit(orm.Associations).Create(value).Error; err != nil {
  1057  		return err
  1058  	}
  1059  
  1060  	if err := r.created(value); err != nil {
  1061  		return err
  1062  	}
  1063  	if err := r.saved(nil, value); err != nil {
  1064  		return err
  1065  	}
  1066  
  1067  	return nil
  1068  }
  1069  
  1070  func (r *QueryImpl) created(dest any) error {
  1071  	return r.event(ormcontract.EventCreated, nil, dest)
  1072  }
  1073  
  1074  func (r *QueryImpl) creating(dest any) error {
  1075  	return r.event(ormcontract.EventCreating, nil, dest)
  1076  }
  1077  
  1078  func (r *QueryImpl) deleting(dest any) error {
  1079  	return r.event(ormcontract.EventDeleting, nil, dest)
  1080  }
  1081  
  1082  func (r *QueryImpl) deleted(dest any) error {
  1083  	return r.event(ormcontract.EventDeleted, nil, dest)
  1084  }
  1085  
  1086  func (r *QueryImpl) forceDeleting(dest any) error {
  1087  	return r.event(ormcontract.EventForceDeleting, nil, dest)
  1088  }
  1089  
  1090  func (r *QueryImpl) forceDeleted(dest any) error {
  1091  	return r.event(ormcontract.EventForceDeleted, nil, dest)
  1092  }
  1093  
  1094  func (r *QueryImpl) event(event ormcontract.EventType, model, dest any) error {
  1095  	if r.conditions.withoutEvents {
  1096  		return nil
  1097  	}
  1098  
  1099  	instance := NewEvent(r, model, dest)
  1100  
  1101  	if dispatchesEvents, exist := dest.(ormcontract.DispatchesEvents); exist {
  1102  		if event, exist := dispatchesEvents.DispatchesEvents()[event]; exist {
  1103  			return event(instance)
  1104  		}
  1105  
  1106  		return nil
  1107  	}
  1108  	if model != nil {
  1109  		if dispatchesEvents, exist := model.(ormcontract.DispatchesEvents); exist {
  1110  			if event, exist := dispatchesEvents.DispatchesEvents()[event]; exist {
  1111  				return event(instance)
  1112  			}
  1113  		}
  1114  
  1115  		return nil
  1116  	}
  1117  
  1118  	if observer := observer(dest); observer != nil {
  1119  		if observerEvent := observerEvent(event, observer); observerEvent != nil {
  1120  			return observerEvent(instance)
  1121  		}
  1122  
  1123  		return nil
  1124  	}
  1125  
  1126  	if model != nil {
  1127  		if observer := observer(model); observer != nil {
  1128  			if observerEvent := observerEvent(event, observer); observerEvent != nil {
  1129  				return observerEvent(instance)
  1130  			}
  1131  
  1132  			return nil
  1133  		}
  1134  	}
  1135  
  1136  	return nil
  1137  }
  1138  
  1139  func (r *QueryImpl) new(db *gormio.DB) *QueryImpl {
  1140  	query := NewQueryImpl(r.ctx, r.config, r.connection, db, &r.conditions)
  1141  
  1142  	return query
  1143  }
  1144  
  1145  func (r *QueryImpl) omitCreate(value any) error {
  1146  	if len(r.instance.Statement.Omits) > 1 {
  1147  		for _, val := range r.instance.Statement.Omits {
  1148  			if val == orm.Associations {
  1149  				return errors.New("cannot set orm.Associations and other fields at the same time")
  1150  			}
  1151  		}
  1152  	}
  1153  
  1154  	if len(r.instance.Statement.Omits) == 1 && r.instance.Statement.Omits[0] == orm.Associations {
  1155  		r.instance.Statement.Selects = []string{}
  1156  	}
  1157  
  1158  	if err := r.saving(nil, value); err != nil {
  1159  		return err
  1160  	}
  1161  	if err := r.creating(value); err != nil {
  1162  		return err
  1163  	}
  1164  
  1165  	if len(r.instance.Statement.Omits) == 1 && r.instance.Statement.Omits[0] == orm.Associations {
  1166  		if err := r.instance.Omit(orm.Associations).Create(value).Error; err != nil {
  1167  			return err
  1168  		}
  1169  	} else {
  1170  		if err := r.instance.Create(value).Error; err != nil {
  1171  			return err
  1172  		}
  1173  	}
  1174  
  1175  	if err := r.created(value); err != nil {
  1176  		return err
  1177  	}
  1178  	if err := r.saved(nil, value); err != nil {
  1179  		return err
  1180  	}
  1181  
  1182  	return nil
  1183  }
  1184  
  1185  func (r *QueryImpl) omitSave(value any) error {
  1186  	for _, val := range r.instance.Statement.Omits {
  1187  		if val == orm.Associations {
  1188  			return r.instance.Omit(orm.Associations).Save(value).Error
  1189  		}
  1190  	}
  1191  
  1192  	return r.instance.Save(value).Error
  1193  }
  1194  
  1195  func (r *QueryImpl) refreshConnection(model any) (*QueryImpl, error) {
  1196  	connection, err := getModelConnection(model)
  1197  	if err != nil {
  1198  		return nil, err
  1199  	}
  1200  	if connection == "" || connection == r.connection {
  1201  		return r, nil
  1202  	}
  1203  
  1204  	query, ok := r.queries[connection]
  1205  	if !ok {
  1206  		var err error
  1207  		query, err = InitializeQuery(r.ctx, r.config, connection)
  1208  		if err != nil {
  1209  			return nil, err
  1210  		}
  1211  
  1212  		if r.queries == nil {
  1213  			r.queries = make(map[string]*QueryImpl)
  1214  		}
  1215  		r.queries[connection] = query
  1216  	}
  1217  
  1218  	query.conditions = r.conditions
  1219  
  1220  	return query, nil
  1221  }
  1222  
  1223  func (r *QueryImpl) retrieved(dest any) error {
  1224  	return r.event(ormcontract.EventRetrieved, nil, dest)
  1225  }
  1226  
  1227  func (r *QueryImpl) save(value any) error {
  1228  	return r.instance.Omit(orm.Associations).Save(value).Error
  1229  }
  1230  
  1231  func (r *QueryImpl) saved(model, dest any) error {
  1232  	return r.event(ormcontract.EventSaved, model, dest)
  1233  }
  1234  
  1235  func (r *QueryImpl) saving(model, dest any) error {
  1236  	return r.event(ormcontract.EventSaving, model, dest)
  1237  }
  1238  
  1239  func (r *QueryImpl) selectCreate(value any) error {
  1240  	if len(r.instance.Statement.Selects) > 1 {
  1241  		for _, val := range r.instance.Statement.Selects {
  1242  			if val == orm.Associations {
  1243  				return errors.New("cannot set orm.Associations and other fields at the same time")
  1244  			}
  1245  		}
  1246  	}
  1247  
  1248  	if len(r.instance.Statement.Selects) == 1 && r.instance.Statement.Selects[0] == orm.Associations {
  1249  		r.instance.Statement.Selects = []string{}
  1250  	}
  1251  
  1252  	if err := r.saving(nil, value); err != nil {
  1253  		return err
  1254  	}
  1255  	if err := r.creating(value); err != nil {
  1256  		return err
  1257  	}
  1258  
  1259  	if err := r.instance.Create(value).Error; err != nil {
  1260  		return err
  1261  	}
  1262  
  1263  	if err := r.created(value); err != nil {
  1264  		return err
  1265  	}
  1266  	if err := r.saved(nil, value); err != nil {
  1267  		return err
  1268  	}
  1269  
  1270  	return nil
  1271  }
  1272  
  1273  func (r *QueryImpl) selectSave(value any) error {
  1274  	for _, val := range r.instance.Statement.Selects {
  1275  		if val == orm.Associations {
  1276  			return r.instance.Session(&gormio.Session{FullSaveAssociations: true}).Save(value).Error
  1277  		}
  1278  	}
  1279  
  1280  	if err := r.instance.Save(value).Error; err != nil {
  1281  		return err
  1282  	}
  1283  
  1284  	return nil
  1285  }
  1286  
  1287  func (r *QueryImpl) setConditions(conditions Conditions) *QueryImpl {
  1288  	query := r.new(r.instance)
  1289  	query.conditions = conditions
  1290  
  1291  	return query
  1292  }
  1293  
  1294  func (r *QueryImpl) updating(model, dest any) error {
  1295  	return r.event(ormcontract.EventUpdating, model, dest)
  1296  }
  1297  
  1298  func (r *QueryImpl) updated(model, dest any) error {
  1299  	return r.event(ormcontract.EventUpdated, model, dest)
  1300  }
  1301  
  1302  func (r *QueryImpl) updates(values any) (*ormcontract.Result, error) {
  1303  	if len(r.instance.Statement.Selects) > 0 && len(r.instance.Statement.Omits) > 0 {
  1304  		return nil, errors.New("cannot set Select and Omits at the same time")
  1305  	}
  1306  
  1307  	if len(r.instance.Statement.Selects) > 0 {
  1308  		for _, val := range r.instance.Statement.Selects {
  1309  			if val == orm.Associations {
  1310  				result := r.instance.Session(&gormio.Session{FullSaveAssociations: true}).Updates(values)
  1311  				return &ormcontract.Result{
  1312  					RowsAffected: result.RowsAffected,
  1313  				}, result.Error
  1314  			}
  1315  		}
  1316  
  1317  		result := r.instance.Updates(values)
  1318  
  1319  		return &ormcontract.Result{
  1320  			RowsAffected: result.RowsAffected,
  1321  		}, result.Error
  1322  	}
  1323  
  1324  	if len(r.instance.Statement.Omits) > 0 {
  1325  		for _, val := range r.instance.Statement.Omits {
  1326  			if val == orm.Associations {
  1327  				result := r.instance.Omit(orm.Associations).Updates(values)
  1328  
  1329  				return &ormcontract.Result{
  1330  					RowsAffected: result.RowsAffected,
  1331  				}, result.Error
  1332  			}
  1333  		}
  1334  		result := r.instance.Updates(values)
  1335  
  1336  		return &ormcontract.Result{
  1337  			RowsAffected: result.RowsAffected,
  1338  		}, result.Error
  1339  	}
  1340  	result := r.instance.Omit(orm.Associations).Updates(values)
  1341  
  1342  	return &ormcontract.Result{
  1343  		RowsAffected: result.RowsAffected,
  1344  	}, result.Error
  1345  }
  1346  
  1347  func filterFindConditions(conds ...any) error {
  1348  	if len(conds) > 0 {
  1349  		switch cond := conds[0].(type) {
  1350  		case string:
  1351  			if cond == "" {
  1352  				return ErrorMissingWhereClause
  1353  			}
  1354  		default:
  1355  			reflectValue := reflect.Indirect(reflect.ValueOf(cond))
  1356  			switch reflectValue.Kind() {
  1357  			case reflect.Slice, reflect.Array:
  1358  				if reflectValue.Len() == 0 {
  1359  					return ErrorMissingWhereClause
  1360  				}
  1361  			}
  1362  		}
  1363  	}
  1364  
  1365  	return nil
  1366  }
  1367  
  1368  func getModelConnection(model any) (string, error) {
  1369  	value1 := reflect.ValueOf(model)
  1370  	if value1.Kind() == reflect.Ptr && value1.IsNil() {
  1371  		value1 = reflect.New(value1.Type().Elem())
  1372  	}
  1373  	modelType := reflect.Indirect(value1).Type()
  1374  
  1375  	if modelType.Kind() == reflect.Interface {
  1376  		modelType = reflect.Indirect(reflect.ValueOf(model)).Elem().Type()
  1377  	}
  1378  
  1379  	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
  1380  		modelType = modelType.Elem()
  1381  	}
  1382  
  1383  	if modelType.Kind() != reflect.Struct {
  1384  		if modelType.PkgPath() == "" {
  1385  			return "", errors.New("invalid model")
  1386  		}
  1387  		return "", fmt.Errorf("%s: %s.%s", "invalid model", modelType.PkgPath(), modelType.Name())
  1388  	}
  1389  
  1390  	modelValue := reflect.New(modelType)
  1391  	connectionModel, ok := modelValue.Interface().(ormcontract.ConnectionModel)
  1392  	if !ok {
  1393  		return "", nil
  1394  	}
  1395  
  1396  	return connectionModel.Connection(), nil
  1397  }
  1398  
  1399  func observer(dest any) ormcontract.Observer {
  1400  	destType := reflect.TypeOf(dest)
  1401  	if destType.Kind() == reflect.Pointer {
  1402  		destType = destType.Elem()
  1403  	}
  1404  
  1405  	for _, observer := range orm.Observers {
  1406  		modelType := reflect.TypeOf(observer.Model)
  1407  		if modelType.Kind() == reflect.Pointer {
  1408  			modelType = modelType.Elem()
  1409  		}
  1410  		if destType.Name() == modelType.Name() {
  1411  			return observer.Observer
  1412  		}
  1413  	}
  1414  
  1415  	return nil
  1416  }
  1417  
  1418  func observerEvent(event ormcontract.EventType, observer ormcontract.Observer) func(ormcontract.Event) error {
  1419  	switch event {
  1420  	case ormcontract.EventRetrieved:
  1421  		return observer.Retrieved
  1422  	case ormcontract.EventCreating:
  1423  		return observer.Creating
  1424  	case ormcontract.EventCreated:
  1425  		return observer.Created
  1426  	case ormcontract.EventUpdating:
  1427  		return observer.Updating
  1428  	case ormcontract.EventUpdated:
  1429  		return observer.Updated
  1430  	case ormcontract.EventSaving:
  1431  		return observer.Saving
  1432  	case ormcontract.EventSaved:
  1433  		return observer.Saved
  1434  	case ormcontract.EventDeleting:
  1435  		return observer.Deleting
  1436  	case ormcontract.EventDeleted:
  1437  		return observer.Deleted
  1438  	case ormcontract.EventForceDeleting:
  1439  		return observer.ForceDeleting
  1440  	case ormcontract.EventForceDeleted:
  1441  		return observer.ForceDeleted
  1442  	}
  1443  
  1444  	return nil
  1445  }