1package gorm
2
3import (
4	"bytes"
5	"database/sql"
6	"database/sql/driver"
7	"errors"
8	"fmt"
9	"reflect"
10	"regexp"
11	"strings"
12	"time"
13)
14
15// Scope contain current operation's information when you perform any operation on the database
16type Scope struct {
17	Search          *search
18	Value           interface{}
19	SQL             string
20	SQLVars         []interface{}
21	db              *DB
22	instanceID      string
23	primaryKeyField *Field
24	skipLeft        bool
25	fields          *[]*Field
26	selectAttrs     *[]string
27}
28
29// IndirectValue return scope's reflect value's indirect value
30func (scope *Scope) IndirectValue() reflect.Value {
31	return indirect(reflect.ValueOf(scope.Value))
32}
33
34// New create a new Scope without search information
35func (scope *Scope) New(value interface{}) *Scope {
36	return &Scope{db: scope.NewDB(), Search: &search{}, Value: value}
37}
38
39////////////////////////////////////////////////////////////////////////////////
40// Scope DB
41////////////////////////////////////////////////////////////////////////////////
42
43// DB return scope's DB connection
44func (scope *Scope) DB() *DB {
45	return scope.db
46}
47
48// NewDB create a new DB without search information
49func (scope *Scope) NewDB() *DB {
50	if scope.db != nil {
51		db := scope.db.clone()
52		db.search = nil
53		db.Value = nil
54		return db
55	}
56	return nil
57}
58
59// SQLDB return *sql.DB
60func (scope *Scope) SQLDB() SQLCommon {
61	return scope.db.db
62}
63
64// Dialect get dialect
65func (scope *Scope) Dialect() Dialect {
66	return scope.db.dialect
67}
68
69// Quote used to quote string to escape them for database
70func (scope *Scope) Quote(str string) string {
71	if strings.Contains(str, ".") {
72		newStrs := []string{}
73		for _, str := range strings.Split(str, ".") {
74			newStrs = append(newStrs, scope.Dialect().Quote(str))
75		}
76		return strings.Join(newStrs, ".")
77	}
78
79	return scope.Dialect().Quote(str)
80}
81
82// Err add error to Scope
83func (scope *Scope) Err(err error) error {
84	if err != nil {
85		scope.db.AddError(err)
86	}
87	return err
88}
89
90// HasError check if there are any error
91func (scope *Scope) HasError() bool {
92	return scope.db.Error != nil
93}
94
95// Log print log message
96func (scope *Scope) Log(v ...interface{}) {
97	scope.db.log(v...)
98}
99
100// SkipLeft skip remaining callbacks
101func (scope *Scope) SkipLeft() {
102	scope.skipLeft = true
103}
104
105// Fields get value's fields
106func (scope *Scope) Fields() []*Field {
107	if scope.fields == nil {
108		var (
109			fields             []*Field
110			indirectScopeValue = scope.IndirectValue()
111			isStruct           = indirectScopeValue.Kind() == reflect.Struct
112		)
113
114		for _, structField := range scope.GetModelStruct().StructFields {
115			if isStruct {
116				fieldValue := indirectScopeValue
117				for _, name := range structField.Names {
118					if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
119						fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
120					}
121					fieldValue = reflect.Indirect(fieldValue).FieldByName(name)
122				}
123				fields = append(fields, &Field{StructField: structField, Field: fieldValue, IsBlank: isBlank(fieldValue)})
124			} else {
125				fields = append(fields, &Field{StructField: structField, IsBlank: true})
126			}
127		}
128		scope.fields = &fields
129	}
130
131	return *scope.fields
132}
133
134// FieldByName find `gorm.Field` with field name or db name
135func (scope *Scope) FieldByName(name string) (field *Field, ok bool) {
136	var (
137		dbName           = ToColumnName(name)
138		mostMatchedField *Field
139	)
140
141	for _, field := range scope.Fields() {
142		if field.Name == name || field.DBName == name {
143			return field, true
144		}
145		if field.DBName == dbName {
146			mostMatchedField = field
147		}
148	}
149	return mostMatchedField, mostMatchedField != nil
150}
151
152// PrimaryFields return scope's primary fields
153func (scope *Scope) PrimaryFields() (fields []*Field) {
154	for _, field := range scope.Fields() {
155		if field.IsPrimaryKey {
156			fields = append(fields, field)
157		}
158	}
159	return fields
160}
161
162// PrimaryField return scope's main primary field, if defined more that one primary fields, will return the one having column name `id` or the first one
163func (scope *Scope) PrimaryField() *Field {
164	if primaryFields := scope.GetModelStruct().PrimaryFields; len(primaryFields) > 0 {
165		if len(primaryFields) > 1 {
166			if field, ok := scope.FieldByName("id"); ok {
167				return field
168			}
169		}
170		return scope.PrimaryFields()[0]
171	}
172	return nil
173}
174
175// PrimaryKey get main primary field's db name
176func (scope *Scope) PrimaryKey() string {
177	if field := scope.PrimaryField(); field != nil {
178		return field.DBName
179	}
180	return ""
181}
182
183// PrimaryKeyZero check main primary field's value is blank or not
184func (scope *Scope) PrimaryKeyZero() bool {
185	field := scope.PrimaryField()
186	return field == nil || field.IsBlank
187}
188
189// PrimaryKeyValue get the primary key's value
190func (scope *Scope) PrimaryKeyValue() interface{} {
191	if field := scope.PrimaryField(); field != nil && field.Field.IsValid() {
192		return field.Field.Interface()
193	}
194	return 0
195}
196
197// HasColumn to check if has column
198func (scope *Scope) HasColumn(column string) bool {
199	for _, field := range scope.GetStructFields() {
200		if field.IsNormal && (field.Name == column || field.DBName == column) {
201			return true
202		}
203	}
204	return false
205}
206
207// SetColumn to set the column's value, column could be field or field's name/dbname
208func (scope *Scope) SetColumn(column interface{}, value interface{}) error {
209	var updateAttrs = map[string]interface{}{}
210	if attrs, ok := scope.InstanceGet("gorm:update_attrs"); ok {
211		updateAttrs = attrs.(map[string]interface{})
212		defer scope.InstanceSet("gorm:update_attrs", updateAttrs)
213	}
214
215	if field, ok := column.(*Field); ok {
216		updateAttrs[field.DBName] = value
217		return field.Set(value)
218	} else if name, ok := column.(string); ok {
219		var (
220			dbName           = ToDBName(name)
221			mostMatchedField *Field
222		)
223		for _, field := range scope.Fields() {
224			if field.DBName == value {
225				updateAttrs[field.DBName] = value
226				return field.Set(value)
227			}
228			if !field.IsIgnored && ((field.DBName == dbName) || (field.Name == name && mostMatchedField == nil)) {
229				mostMatchedField = field
230			}
231		}
232
233		if mostMatchedField != nil {
234			updateAttrs[mostMatchedField.DBName] = value
235			return mostMatchedField.Set(value)
236		}
237	}
238	return errors.New("could not convert column to field")
239}
240
241// CallMethod call scope value's method, if it is a slice, will call its element's method one by one
242func (scope *Scope) CallMethod(methodName string) {
243	if scope.Value == nil {
244		return
245	}
246
247	if indirectScopeValue := scope.IndirectValue(); indirectScopeValue.Kind() == reflect.Slice {
248		for i := 0; i < indirectScopeValue.Len(); i++ {
249			scope.callMethod(methodName, indirectScopeValue.Index(i))
250		}
251	} else {
252		scope.callMethod(methodName, indirectScopeValue)
253	}
254}
255
256// AddToVars add value as sql's vars, used to prevent SQL injection
257func (scope *Scope) AddToVars(value interface{}) string {
258	_, skipBindVar := scope.InstanceGet("skip_bindvar")
259
260	if expr, ok := value.(*SqlExpr); ok {
261		exp := expr.expr
262		for _, arg := range expr.args {
263			if skipBindVar {
264				scope.AddToVars(arg)
265			} else {
266				exp = strings.Replace(exp, "?", scope.AddToVars(arg), 1)
267			}
268		}
269		return exp
270	}
271
272	scope.SQLVars = append(scope.SQLVars, value)
273
274	if skipBindVar {
275		return "?"
276	}
277	return scope.Dialect().BindVar(len(scope.SQLVars))
278}
279
280// SelectAttrs return selected attributes
281func (scope *Scope) SelectAttrs() []string {
282	if scope.selectAttrs == nil {
283		attrs := []string{}
284		for _, value := range scope.Search.selects {
285			if str, ok := value.(string); ok {
286				attrs = append(attrs, str)
287			} else if strs, ok := value.([]string); ok {
288				attrs = append(attrs, strs...)
289			} else if strs, ok := value.([]interface{}); ok {
290				for _, str := range strs {
291					attrs = append(attrs, fmt.Sprintf("%v", str))
292				}
293			}
294		}
295		scope.selectAttrs = &attrs
296	}
297	return *scope.selectAttrs
298}
299
300// OmitAttrs return omitted attributes
301func (scope *Scope) OmitAttrs() []string {
302	return scope.Search.omits
303}
304
305type tabler interface {
306	TableName() string
307}
308
309type dbTabler interface {
310	TableName(*DB) string
311}
312
313// TableName return table name
314func (scope *Scope) TableName() string {
315	if scope.Search != nil && len(scope.Search.tableName) > 0 {
316		return scope.Search.tableName
317	}
318
319	if tabler, ok := scope.Value.(tabler); ok {
320		return tabler.TableName()
321	}
322
323	if tabler, ok := scope.Value.(dbTabler); ok {
324		return tabler.TableName(scope.db)
325	}
326
327	return scope.GetModelStruct().TableName(scope.db.Model(scope.Value))
328}
329
330// QuotedTableName return quoted table name
331func (scope *Scope) QuotedTableName() (name string) {
332	if scope.Search != nil && len(scope.Search.tableName) > 0 {
333		if strings.Contains(scope.Search.tableName, " ") {
334			return scope.Search.tableName
335		}
336		return scope.Quote(scope.Search.tableName)
337	}
338
339	return scope.Quote(scope.TableName())
340}
341
342// CombinedConditionSql return combined condition sql
343func (scope *Scope) CombinedConditionSql() string {
344	joinSQL := scope.joinsSQL()
345	whereSQL := scope.whereSQL()
346	if scope.Search.raw {
347		whereSQL = strings.TrimSuffix(strings.TrimPrefix(whereSQL, "WHERE ("), ")")
348	}
349	return joinSQL + whereSQL + scope.groupSQL() +
350		scope.havingSQL() + scope.orderSQL() + scope.limitAndOffsetSQL()
351}
352
353// Raw set raw sql
354func (scope *Scope) Raw(sql string) *Scope {
355	scope.SQL = strings.Replace(sql, "$$$", "?", -1)
356	return scope
357}
358
359// Exec perform generated SQL
360func (scope *Scope) Exec() *Scope {
361	defer scope.trace(NowFunc())
362
363	if !scope.HasError() {
364		if result, err := scope.SQLDB().Exec(scope.SQL, scope.SQLVars...); scope.Err(err) == nil {
365			if count, err := result.RowsAffected(); scope.Err(err) == nil {
366				scope.db.RowsAffected = count
367			}
368		}
369	}
370	return scope
371}
372
373// Set set value by name
374func (scope *Scope) Set(name string, value interface{}) *Scope {
375	scope.db.InstantSet(name, value)
376	return scope
377}
378
379// Get get setting by name
380func (scope *Scope) Get(name string) (interface{}, bool) {
381	return scope.db.Get(name)
382}
383
384// InstanceID get InstanceID for scope
385func (scope *Scope) InstanceID() string {
386	if scope.instanceID == "" {
387		scope.instanceID = fmt.Sprintf("%v%v", &scope, &scope.db)
388	}
389	return scope.instanceID
390}
391
392// InstanceSet set instance setting for current operation, but not for operations in callbacks, like saving associations callback
393func (scope *Scope) InstanceSet(name string, value interface{}) *Scope {
394	return scope.Set(name+scope.InstanceID(), value)
395}
396
397// InstanceGet get instance setting from current operation
398func (scope *Scope) InstanceGet(name string) (interface{}, bool) {
399	return scope.Get(name + scope.InstanceID())
400}
401
402// Begin start a transaction
403func (scope *Scope) Begin() *Scope {
404	if db, ok := scope.SQLDB().(sqlDb); ok {
405		if tx, err := db.Begin(); scope.Err(err) == nil {
406			scope.db.db = interface{}(tx).(SQLCommon)
407			scope.InstanceSet("gorm:started_transaction", true)
408		}
409	}
410	return scope
411}
412
413// CommitOrRollback commit current transaction if no error happened, otherwise will rollback it
414func (scope *Scope) CommitOrRollback() *Scope {
415	if _, ok := scope.InstanceGet("gorm:started_transaction"); ok {
416		if db, ok := scope.db.db.(sqlTx); ok {
417			if scope.HasError() {
418				db.Rollback()
419			} else {
420				scope.Err(db.Commit())
421			}
422			scope.db.db = scope.db.parent.db
423		}
424	}
425	return scope
426}
427
428////////////////////////////////////////////////////////////////////////////////
429// Private Methods For *gorm.Scope
430////////////////////////////////////////////////////////////////////////////////
431
432func (scope *Scope) callMethod(methodName string, reflectValue reflect.Value) {
433	// Only get address from non-pointer
434	if reflectValue.CanAddr() && reflectValue.Kind() != reflect.Ptr {
435		reflectValue = reflectValue.Addr()
436	}
437
438	if methodValue := reflectValue.MethodByName(methodName); methodValue.IsValid() {
439		switch method := methodValue.Interface().(type) {
440		case func():
441			method()
442		case func(*Scope):
443			method(scope)
444		case func(*DB):
445			newDB := scope.NewDB()
446			method(newDB)
447			scope.Err(newDB.Error)
448		case func() error:
449			scope.Err(method())
450		case func(*Scope) error:
451			scope.Err(method(scope))
452		case func(*DB) error:
453			newDB := scope.NewDB()
454			scope.Err(method(newDB))
455			scope.Err(newDB.Error)
456		default:
457			scope.Err(fmt.Errorf("unsupported function %v", methodName))
458		}
459	}
460}
461
462var (
463	columnRegexp        = regexp.MustCompile("^[a-zA-Z\\d]+(\\.[a-zA-Z\\d]+)*$") // only match string like `name`, `users.name`
464	isNumberRegexp      = regexp.MustCompile("^\\s*\\d+\\s*$")                   // match if string is number
465	comparisonRegexp    = regexp.MustCompile("(?i) (=|<>|(>|<)(=?)|LIKE|IS|IN) ")
466	countingQueryRegexp = regexp.MustCompile("(?i)^count(.+)$")
467)
468
469func (scope *Scope) quoteIfPossible(str string) string {
470	if columnRegexp.MatchString(str) {
471		return scope.Quote(str)
472	}
473	return str
474}
475
476func (scope *Scope) scan(rows *sql.Rows, columns []string, fields []*Field) {
477	var (
478		ignored            interface{}
479		values             = make([]interface{}, len(columns))
480		selectFields       []*Field
481		selectedColumnsMap = map[string]int{}
482		resetFields        = map[int]*Field{}
483	)
484
485	for index, column := range columns {
486		values[index] = &ignored
487
488		selectFields = fields
489		offset := 0
490		if idx, ok := selectedColumnsMap[column]; ok {
491			offset = idx + 1
492			selectFields = selectFields[offset:]
493		}
494
495		for fieldIndex, field := range selectFields {
496			if field.DBName == column {
497				if field.Field.Kind() == reflect.Ptr {
498					values[index] = field.Field.Addr().Interface()
499				} else {
500					reflectValue := reflect.New(reflect.PtrTo(field.Struct.Type))
501					reflectValue.Elem().Set(field.Field.Addr())
502					values[index] = reflectValue.Interface()
503					resetFields[index] = field
504				}
505
506				selectedColumnsMap[column] = offset + fieldIndex
507
508				if field.IsNormal {
509					break
510				}
511			}
512		}
513	}
514
515	scope.Err(rows.Scan(values...))
516
517	for index, field := range resetFields {
518		if v := reflect.ValueOf(values[index]).Elem().Elem(); v.IsValid() {
519			field.Field.Set(v)
520		}
521	}
522}
523
524func (scope *Scope) primaryCondition(value interface{}) string {
525	return fmt.Sprintf("(%v.%v = %v)", scope.QuotedTableName(), scope.Quote(scope.PrimaryKey()), value)
526}
527
528func (scope *Scope) buildCondition(clause map[string]interface{}, include bool) (str string) {
529	var (
530		quotedTableName  = scope.QuotedTableName()
531		quotedPrimaryKey = scope.Quote(scope.PrimaryKey())
532		equalSQL         = "="
533		inSQL            = "IN"
534	)
535
536	// If building not conditions
537	if !include {
538		equalSQL = "<>"
539		inSQL = "NOT IN"
540	}
541
542	switch value := clause["query"].(type) {
543	case sql.NullInt64:
544		return fmt.Sprintf("(%v.%v %s %v)", quotedTableName, quotedPrimaryKey, equalSQL, value.Int64)
545	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
546		return fmt.Sprintf("(%v.%v %s %v)", quotedTableName, quotedPrimaryKey, equalSQL, value)
547	case []int, []int8, []int16, []int32, []int64, []uint, []uint8, []uint16, []uint32, []uint64, []string, []interface{}:
548		if !include && reflect.ValueOf(value).Len() == 0 {
549			return
550		}
551		str = fmt.Sprintf("(%v.%v %s (?))", quotedTableName, quotedPrimaryKey, inSQL)
552		clause["args"] = []interface{}{value}
553	case string:
554		if isNumberRegexp.MatchString(value) {
555			return fmt.Sprintf("(%v.%v %s %v)", quotedTableName, quotedPrimaryKey, equalSQL, scope.AddToVars(value))
556		}
557
558		if value != "" {
559			if !include {
560				if comparisonRegexp.MatchString(value) {
561					str = fmt.Sprintf("NOT (%v)", value)
562				} else {
563					str = fmt.Sprintf("(%v.%v NOT IN (?))", quotedTableName, scope.Quote(value))
564				}
565			} else {
566				str = fmt.Sprintf("(%v)", value)
567			}
568		}
569	case map[string]interface{}:
570		var sqls []string
571		for key, value := range value {
572			if value != nil {
573				sqls = append(sqls, fmt.Sprintf("(%v.%v %s %v)", quotedTableName, scope.Quote(key), equalSQL, scope.AddToVars(value)))
574			} else {
575				if !include {
576					sqls = append(sqls, fmt.Sprintf("(%v.%v IS NOT NULL)", quotedTableName, scope.Quote(key)))
577				} else {
578					sqls = append(sqls, fmt.Sprintf("(%v.%v IS NULL)", quotedTableName, scope.Quote(key)))
579				}
580			}
581		}
582		return strings.Join(sqls, " AND ")
583	case interface{}:
584		var sqls []string
585		newScope := scope.New(value)
586
587		if len(newScope.Fields()) == 0 {
588			scope.Err(fmt.Errorf("invalid query condition: %v", value))
589			return
590		}
591		scopeQuotedTableName := newScope.QuotedTableName()
592		for _, field := range newScope.Fields() {
593			if !field.IsIgnored && !field.IsBlank && field.Relationship == nil {
594				sqls = append(sqls, fmt.Sprintf("(%v.%v %s %v)", scopeQuotedTableName, scope.Quote(field.DBName), equalSQL, scope.AddToVars(field.Field.Interface())))
595			}
596		}
597		return strings.Join(sqls, " AND ")
598	default:
599		scope.Err(fmt.Errorf("invalid query condition: %v", value))
600		return
601	}
602
603	replacements := []string{}
604	args := clause["args"].([]interface{})
605	for _, arg := range args {
606		var err error
607		switch reflect.ValueOf(arg).Kind() {
608		case reflect.Slice: // For where("id in (?)", []int64{1,2})
609			if scanner, ok := interface{}(arg).(driver.Valuer); ok {
610				arg, err = scanner.Value()
611				replacements = append(replacements, scope.AddToVars(arg))
612			} else if b, ok := arg.([]byte); ok {
613				replacements = append(replacements, scope.AddToVars(b))
614			} else if as, ok := arg.([][]interface{}); ok {
615				var tempMarks []string
616				for _, a := range as {
617					var arrayMarks []string
618					for _, v := range a {
619						arrayMarks = append(arrayMarks, scope.AddToVars(v))
620					}
621
622					if len(arrayMarks) > 0 {
623						tempMarks = append(tempMarks, fmt.Sprintf("(%v)", strings.Join(arrayMarks, ",")))
624					}
625				}
626
627				if len(tempMarks) > 0 {
628					replacements = append(replacements, strings.Join(tempMarks, ","))
629				}
630			} else if values := reflect.ValueOf(arg); values.Len() > 0 {
631				var tempMarks []string
632				for i := 0; i < values.Len(); i++ {
633					tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface()))
634				}
635				replacements = append(replacements, strings.Join(tempMarks, ","))
636			} else {
637				replacements = append(replacements, scope.AddToVars(Expr("NULL")))
638			}
639		default:
640			if valuer, ok := interface{}(arg).(driver.Valuer); ok {
641				arg, err = valuer.Value()
642			}
643
644			replacements = append(replacements, scope.AddToVars(arg))
645		}
646
647		if err != nil {
648			scope.Err(err)
649		}
650	}
651
652	buff := bytes.NewBuffer([]byte{})
653	i := 0
654	for _, s := range str {
655		if s == '?' && len(replacements) > i {
656			buff.WriteString(replacements[i])
657			i++
658		} else {
659			buff.WriteRune(s)
660		}
661	}
662
663	str = buff.String()
664
665	return
666}
667
668func (scope *Scope) buildSelectQuery(clause map[string]interface{}) (str string) {
669	switch value := clause["query"].(type) {
670	case string:
671		str = value
672	case []string:
673		str = strings.Join(value, ", ")
674	}
675
676	args := clause["args"].([]interface{})
677	replacements := []string{}
678	for _, arg := range args {
679		switch reflect.ValueOf(arg).Kind() {
680		case reflect.Slice:
681			values := reflect.ValueOf(arg)
682			var tempMarks []string
683			for i := 0; i < values.Len(); i++ {
684				tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface()))
685			}
686			replacements = append(replacements, strings.Join(tempMarks, ","))
687		default:
688			if valuer, ok := interface{}(arg).(driver.Valuer); ok {
689				arg, _ = valuer.Value()
690			}
691			replacements = append(replacements, scope.AddToVars(arg))
692		}
693	}
694
695	buff := bytes.NewBuffer([]byte{})
696	i := 0
697	for pos, char := range str {
698		if str[pos] == '?' {
699			buff.WriteString(replacements[i])
700			i++
701		} else {
702			buff.WriteRune(char)
703		}
704	}
705
706	str = buff.String()
707
708	return
709}
710
711func (scope *Scope) whereSQL() (sql string) {
712	var (
713		quotedTableName                                = scope.QuotedTableName()
714		deletedAtField, hasDeletedAtField              = scope.FieldByName("DeletedAt")
715		primaryConditions, andConditions, orConditions []string
716	)
717
718	if !scope.Search.Unscoped && hasDeletedAtField {
719		sql := fmt.Sprintf("%v.%v IS NULL", quotedTableName, scope.Quote(deletedAtField.DBName))
720		primaryConditions = append(primaryConditions, sql)
721	}
722
723	if !scope.PrimaryKeyZero() {
724		for _, field := range scope.PrimaryFields() {
725			sql := fmt.Sprintf("%v.%v = %v", quotedTableName, scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface()))
726			primaryConditions = append(primaryConditions, sql)
727		}
728	}
729
730	for _, clause := range scope.Search.whereConditions {
731		if sql := scope.buildCondition(clause, true); sql != "" {
732			andConditions = append(andConditions, sql)
733		}
734	}
735
736	for _, clause := range scope.Search.orConditions {
737		if sql := scope.buildCondition(clause, true); sql != "" {
738			orConditions = append(orConditions, sql)
739		}
740	}
741
742	for _, clause := range scope.Search.notConditions {
743		if sql := scope.buildCondition(clause, false); sql != "" {
744			andConditions = append(andConditions, sql)
745		}
746	}
747
748	orSQL := strings.Join(orConditions, " OR ")
749	combinedSQL := strings.Join(andConditions, " AND ")
750	if len(combinedSQL) > 0 {
751		if len(orSQL) > 0 {
752			combinedSQL = combinedSQL + " OR " + orSQL
753		}
754	} else {
755		combinedSQL = orSQL
756	}
757
758	if len(primaryConditions) > 0 {
759		sql = "WHERE " + strings.Join(primaryConditions, " AND ")
760		if len(combinedSQL) > 0 {
761			sql = sql + " AND (" + combinedSQL + ")"
762		}
763	} else if len(combinedSQL) > 0 {
764		sql = "WHERE " + combinedSQL
765	}
766	return
767}
768
769func (scope *Scope) selectSQL() string {
770	if len(scope.Search.selects) == 0 {
771		if len(scope.Search.joinConditions) > 0 {
772			return fmt.Sprintf("%v.*", scope.QuotedTableName())
773		}
774		return "*"
775	}
776	return scope.buildSelectQuery(scope.Search.selects)
777}
778
779func (scope *Scope) orderSQL() string {
780	if len(scope.Search.orders) == 0 || scope.Search.ignoreOrderQuery {
781		return ""
782	}
783
784	var orders []string
785	for _, order := range scope.Search.orders {
786		if str, ok := order.(string); ok {
787			orders = append(orders, scope.quoteIfPossible(str))
788		} else if expr, ok := order.(*SqlExpr); ok {
789			exp := expr.expr
790			for _, arg := range expr.args {
791				exp = strings.Replace(exp, "?", scope.AddToVars(arg), 1)
792			}
793			orders = append(orders, exp)
794		}
795	}
796	return " ORDER BY " + strings.Join(orders, ",")
797}
798
799func (scope *Scope) limitAndOffsetSQL() string {
800	sql, err := scope.Dialect().LimitAndOffsetSQL(scope.Search.limit, scope.Search.offset)
801	scope.Err(err)
802	return sql
803}
804
805func (scope *Scope) groupSQL() string {
806	if len(scope.Search.group) == 0 {
807		return ""
808	}
809	return " GROUP BY " + scope.Search.group
810}
811
812func (scope *Scope) havingSQL() string {
813	if len(scope.Search.havingConditions) == 0 {
814		return ""
815	}
816
817	var andConditions []string
818	for _, clause := range scope.Search.havingConditions {
819		if sql := scope.buildCondition(clause, true); sql != "" {
820			andConditions = append(andConditions, sql)
821		}
822	}
823
824	combinedSQL := strings.Join(andConditions, " AND ")
825	if len(combinedSQL) == 0 {
826		return ""
827	}
828
829	return " HAVING " + combinedSQL
830}
831
832func (scope *Scope) joinsSQL() string {
833	var joinConditions []string
834	for _, clause := range scope.Search.joinConditions {
835		if sql := scope.buildCondition(clause, true); sql != "" {
836			joinConditions = append(joinConditions, strings.TrimSuffix(strings.TrimPrefix(sql, "("), ")"))
837		}
838	}
839
840	return strings.Join(joinConditions, " ") + " "
841}
842
843func (scope *Scope) prepareQuerySQL() {
844	if scope.Search.raw {
845		scope.Raw(scope.CombinedConditionSql())
846	} else {
847		scope.Raw(fmt.Sprintf("SELECT %v FROM %v %v", scope.selectSQL(), scope.QuotedTableName(), scope.CombinedConditionSql()))
848	}
849	return
850}
851
852func (scope *Scope) inlineCondition(values ...interface{}) *Scope {
853	if len(values) > 0 {
854		scope.Search.Where(values[0], values[1:]...)
855	}
856	return scope
857}
858
859func (scope *Scope) callCallbacks(funcs []*func(s *Scope)) *Scope {
860	defer func() {
861		if err := recover(); err != nil {
862			if db, ok := scope.db.db.(sqlTx); ok {
863				db.Rollback()
864			}
865			panic(err)
866		}
867	}()
868	for _, f := range funcs {
869		(*f)(scope)
870		if scope.skipLeft {
871			break
872		}
873	}
874	return scope
875}
876
877func convertInterfaceToMap(values interface{}, withIgnoredField bool, db *DB) map[string]interface{} {
878	var attrs = map[string]interface{}{}
879
880	switch value := values.(type) {
881	case map[string]interface{}:
882		return value
883	case []interface{}:
884		for _, v := range value {
885			for key, value := range convertInterfaceToMap(v, withIgnoredField, db) {
886				attrs[key] = value
887			}
888		}
889	case interface{}:
890		reflectValue := reflect.ValueOf(values)
891
892		switch reflectValue.Kind() {
893		case reflect.Map:
894			for _, key := range reflectValue.MapKeys() {
895				attrs[ToColumnName(key.Interface().(string))] = reflectValue.MapIndex(key).Interface()
896			}
897		default:
898			for _, field := range (&Scope{Value: values, db: db}).Fields() {
899				if !field.IsBlank && (withIgnoredField || !field.IsIgnored) {
900					attrs[field.DBName] = field.Field.Interface()
901				}
902			}
903		}
904	}
905	return attrs
906}
907
908func (scope *Scope) updatedAttrsWithValues(value interface{}) (results map[string]interface{}, hasUpdate bool) {
909	if scope.IndirectValue().Kind() != reflect.Struct {
910		return convertInterfaceToMap(value, false, scope.db), true
911	}
912
913	results = map[string]interface{}{}
914
915	for key, value := range convertInterfaceToMap(value, true, scope.db) {
916		if field, ok := scope.FieldByName(key); ok {
917			if scope.changeableField(field) {
918				if _, ok := value.(*SqlExpr); ok {
919					hasUpdate = true
920					results[field.DBName] = value
921				} else {
922					err := field.Set(value)
923					if field.IsNormal && !field.IsIgnored {
924						hasUpdate = true
925						if err == ErrUnaddressable {
926							results[field.DBName] = value
927						} else {
928							results[field.DBName] = field.Field.Interface()
929						}
930					}
931				}
932			}
933		} else {
934			results[key] = value
935		}
936	}
937	return
938}
939
940func (scope *Scope) row() *sql.Row {
941	defer scope.trace(NowFunc())
942
943	result := &RowQueryResult{}
944	scope.InstanceSet("row_query_result", result)
945	scope.callCallbacks(scope.db.parent.callbacks.rowQueries)
946
947	return result.Row
948}
949
950func (scope *Scope) rows() (*sql.Rows, error) {
951	defer scope.trace(NowFunc())
952
953	result := &RowsQueryResult{}
954	scope.InstanceSet("row_query_result", result)
955	scope.callCallbacks(scope.db.parent.callbacks.rowQueries)
956
957	return result.Rows, result.Error
958}
959
960func (scope *Scope) initialize() *Scope {
961	for _, clause := range scope.Search.whereConditions {
962		scope.updatedAttrsWithValues(clause["query"])
963	}
964	scope.updatedAttrsWithValues(scope.Search.initAttrs)
965	scope.updatedAttrsWithValues(scope.Search.assignAttrs)
966	return scope
967}
968
969func (scope *Scope) isQueryForColumn(query interface{}, column string) bool {
970	queryStr := strings.ToLower(fmt.Sprint(query))
971	if queryStr == column {
972		return true
973	}
974
975	if strings.HasSuffix(queryStr, "as "+column) {
976		return true
977	}
978
979	if strings.HasSuffix(queryStr, "as "+scope.Quote(column)) {
980		return true
981	}
982
983	return false
984}
985
986func (scope *Scope) pluck(column string, value interface{}) *Scope {
987	dest := reflect.Indirect(reflect.ValueOf(value))
988	if dest.Kind() != reflect.Slice {
989		scope.Err(fmt.Errorf("results should be a slice, not %s", dest.Kind()))
990		return scope
991	}
992
993	if dest.Len() > 0 {
994		dest.Set(reflect.Zero(dest.Type()))
995	}
996
997	if query, ok := scope.Search.selects["query"]; !ok || !scope.isQueryForColumn(query, column) {
998		scope.Search.Select(column)
999	}
1000
1001	rows, err := scope.rows()
1002	if scope.Err(err) == nil {
1003		defer rows.Close()
1004		for rows.Next() {
1005			elem := reflect.New(dest.Type().Elem()).Interface()
1006			scope.Err(rows.Scan(elem))
1007			dest.Set(reflect.Append(dest, reflect.ValueOf(elem).Elem()))
1008		}
1009
1010		if err := rows.Err(); err != nil {
1011			scope.Err(err)
1012		}
1013	}
1014	return scope
1015}
1016
1017func (scope *Scope) count(value interface{}) *Scope {
1018	if query, ok := scope.Search.selects["query"]; !ok || !countingQueryRegexp.MatchString(fmt.Sprint(query)) {
1019		if len(scope.Search.group) != 0 {
1020			if len(scope.Search.havingConditions) != 0 {
1021				scope.prepareQuerySQL()
1022				scope.Search = &search{}
1023				scope.Search.Select("count(*)")
1024				scope.Search.Table(fmt.Sprintf("( %s ) AS count_table", scope.SQL))
1025			} else {
1026				scope.Search.Select("count(*) FROM ( SELECT count(*) as name ")
1027				scope.Search.group += " ) AS count_table"
1028			}
1029		} else {
1030			scope.Search.Select("count(*)")
1031		}
1032	}
1033	scope.Search.ignoreOrderQuery = true
1034	scope.Err(scope.row().Scan(value))
1035	return scope
1036}
1037
1038func (scope *Scope) typeName() string {
1039	typ := scope.IndirectValue().Type()
1040
1041	for typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr {
1042		typ = typ.Elem()
1043	}
1044
1045	return typ.Name()
1046}
1047
1048// trace print sql log
1049func (scope *Scope) trace(t time.Time) {
1050	if len(scope.SQL) > 0 {
1051		scope.db.slog(scope.SQL, t, scope.SQLVars...)
1052	}
1053}
1054
1055func (scope *Scope) changeableField(field *Field) bool {
1056	if selectAttrs := scope.SelectAttrs(); len(selectAttrs) > 0 {
1057		for _, attr := range selectAttrs {
1058			if field.Name == attr || field.DBName == attr {
1059				return true
1060			}
1061		}
1062		return false
1063	}
1064
1065	for _, attr := range scope.OmitAttrs() {
1066		if field.Name == attr || field.DBName == attr {
1067			return false
1068		}
1069	}
1070
1071	return true
1072}
1073
1074func (scope *Scope) related(value interface{}, foreignKeys ...string) *Scope {
1075	toScope := scope.db.NewScope(value)
1076	tx := scope.db.Set("gorm:association:source", scope.Value)
1077
1078	for _, foreignKey := range append(foreignKeys, toScope.typeName()+"Id", scope.typeName()+"Id") {
1079		fromField, _ := scope.FieldByName(foreignKey)
1080		toField, _ := toScope.FieldByName(foreignKey)
1081
1082		if fromField != nil {
1083			if relationship := fromField.Relationship; relationship != nil {
1084				if relationship.Kind == "many_to_many" {
1085					joinTableHandler := relationship.JoinTableHandler
1086					scope.Err(joinTableHandler.JoinWith(joinTableHandler, tx, scope.Value).Find(value).Error)
1087				} else if relationship.Kind == "belongs_to" {
1088					for idx, foreignKey := range relationship.ForeignDBNames {
1089						if field, ok := scope.FieldByName(foreignKey); ok {
1090							tx = tx.Where(fmt.Sprintf("%v = ?", scope.Quote(relationship.AssociationForeignDBNames[idx])), field.Field.Interface())
1091						}
1092					}
1093					scope.Err(tx.Find(value).Error)
1094				} else if relationship.Kind == "has_many" || relationship.Kind == "has_one" {
1095					for idx, foreignKey := range relationship.ForeignDBNames {
1096						if field, ok := scope.FieldByName(relationship.AssociationForeignDBNames[idx]); ok {
1097							tx = tx.Where(fmt.Sprintf("%v = ?", scope.Quote(foreignKey)), field.Field.Interface())
1098						}
1099					}
1100
1101					if relationship.PolymorphicType != "" {
1102						tx = tx.Where(fmt.Sprintf("%v = ?", scope.Quote(relationship.PolymorphicDBName)), relationship.PolymorphicValue)
1103					}
1104					scope.Err(tx.Find(value).Error)
1105				}
1106			} else {
1107				sql := fmt.Sprintf("%v = ?", scope.Quote(toScope.PrimaryKey()))
1108				scope.Err(tx.Where(sql, fromField.Field.Interface()).Find(value).Error)
1109			}
1110			return scope
1111		} else if toField != nil {
1112			sql := fmt.Sprintf("%v = ?", scope.Quote(toField.DBName))
1113			scope.Err(tx.Where(sql, scope.PrimaryKeyValue()).Find(value).Error)
1114			return scope
1115		}
1116	}
1117
1118	scope.Err(fmt.Errorf("invalid association %v", foreignKeys))
1119	return scope
1120}
1121
1122// getTableOptions return the table options string or an empty string if the table options does not exist
1123func (scope *Scope) getTableOptions() string {
1124	tableOptions, ok := scope.Get("gorm:table_options")
1125	if !ok {
1126		return ""
1127	}
1128	return " " + tableOptions.(string)
1129}
1130
1131func (scope *Scope) createJoinTable(field *StructField) {
1132	if relationship := field.Relationship; relationship != nil && relationship.JoinTableHandler != nil {
1133		joinTableHandler := relationship.JoinTableHandler
1134		joinTable := joinTableHandler.Table(scope.db)
1135		if !scope.Dialect().HasTable(joinTable) {
1136			toScope := &Scope{Value: reflect.New(field.Struct.Type).Interface()}
1137
1138			var sqlTypes, primaryKeys []string
1139			for idx, fieldName := range relationship.ForeignFieldNames {
1140				if field, ok := scope.FieldByName(fieldName); ok {
1141					foreignKeyStruct := field.clone()
1142					foreignKeyStruct.IsPrimaryKey = false
1143					foreignKeyStruct.TagSettingsSet("IS_JOINTABLE_FOREIGNKEY", "true")
1144					foreignKeyStruct.TagSettingsDelete("AUTO_INCREMENT")
1145					sqlTypes = append(sqlTypes, scope.Quote(relationship.ForeignDBNames[idx])+" "+scope.Dialect().DataTypeOf(foreignKeyStruct))
1146					primaryKeys = append(primaryKeys, scope.Quote(relationship.ForeignDBNames[idx]))
1147				}
1148			}
1149
1150			for idx, fieldName := range relationship.AssociationForeignFieldNames {
1151				if field, ok := toScope.FieldByName(fieldName); ok {
1152					foreignKeyStruct := field.clone()
1153					foreignKeyStruct.IsPrimaryKey = false
1154					foreignKeyStruct.TagSettingsSet("IS_JOINTABLE_FOREIGNKEY", "true")
1155					foreignKeyStruct.TagSettingsDelete("AUTO_INCREMENT")
1156					sqlTypes = append(sqlTypes, scope.Quote(relationship.AssociationForeignDBNames[idx])+" "+scope.Dialect().DataTypeOf(foreignKeyStruct))
1157					primaryKeys = append(primaryKeys, scope.Quote(relationship.AssociationForeignDBNames[idx]))
1158				}
1159			}
1160
1161			scope.Err(scope.NewDB().Exec(fmt.Sprintf("CREATE TABLE %v (%v, PRIMARY KEY (%v))%s", scope.Quote(joinTable), strings.Join(sqlTypes, ","), strings.Join(primaryKeys, ","), scope.getTableOptions())).Error)
1162		}
1163		scope.NewDB().Table(joinTable).AutoMigrate(joinTableHandler)
1164	}
1165}
1166
1167func (scope *Scope) createTable() *Scope {
1168	var tags []string
1169	var primaryKeys []string
1170	var primaryKeyInColumnType = false
1171	for _, field := range scope.GetModelStruct().StructFields {
1172		if field.IsNormal {
1173			sqlTag := scope.Dialect().DataTypeOf(field)
1174
1175			// Check if the primary key constraint was specified as
1176			// part of the column type. If so, we can only support
1177			// one column as the primary key.
1178			if strings.Contains(strings.ToLower(sqlTag), "primary key") {
1179				primaryKeyInColumnType = true
1180			}
1181
1182			tags = append(tags, scope.Quote(field.DBName)+" "+sqlTag)
1183		}
1184
1185		if field.IsPrimaryKey {
1186			primaryKeys = append(primaryKeys, scope.Quote(field.DBName))
1187		}
1188		scope.createJoinTable(field)
1189	}
1190
1191	var primaryKeyStr string
1192	if len(primaryKeys) > 0 && !primaryKeyInColumnType {
1193		primaryKeyStr = fmt.Sprintf(", PRIMARY KEY (%v)", strings.Join(primaryKeys, ","))
1194	}
1195
1196	scope.Raw(fmt.Sprintf("CREATE TABLE %v (%v %v)%s", scope.QuotedTableName(), strings.Join(tags, ","), primaryKeyStr, scope.getTableOptions())).Exec()
1197
1198	scope.autoIndex()
1199	return scope
1200}
1201
1202func (scope *Scope) dropTable() *Scope {
1203	scope.Raw(fmt.Sprintf("DROP TABLE %v", scope.QuotedTableName())).Exec()
1204	return scope
1205}
1206
1207func (scope *Scope) modifyColumn(column string, typ string) {
1208	scope.db.AddError(scope.Dialect().ModifyColumn(scope.QuotedTableName(), scope.Quote(column), typ))
1209}
1210
1211func (scope *Scope) dropColumn(column string) {
1212	scope.Raw(fmt.Sprintf("ALTER TABLE %v DROP COLUMN %v", scope.QuotedTableName(), scope.Quote(column))).Exec()
1213}
1214
1215func (scope *Scope) addIndex(unique bool, indexName string, column ...string) {
1216	if scope.Dialect().HasIndex(scope.TableName(), indexName) {
1217		return
1218	}
1219
1220	var columns []string
1221	for _, name := range column {
1222		columns = append(columns, scope.quoteIfPossible(name))
1223	}
1224
1225	sqlCreate := "CREATE INDEX"
1226	if unique {
1227		sqlCreate = "CREATE UNIQUE INDEX"
1228	}
1229
1230	scope.Raw(fmt.Sprintf("%s %v ON %v(%v) %v", sqlCreate, indexName, scope.QuotedTableName(), strings.Join(columns, ", "), scope.whereSQL())).Exec()
1231}
1232
1233func (scope *Scope) addForeignKey(field string, dest string, onDelete string, onUpdate string) {
1234	// Compatible with old generated key
1235	keyName := scope.Dialect().BuildKeyName(scope.TableName(), field, dest, "foreign")
1236
1237	if scope.Dialect().HasForeignKey(scope.TableName(), keyName) {
1238		return
1239	}
1240	var query = `ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s ON DELETE %s ON UPDATE %s;`
1241	scope.Raw(fmt.Sprintf(query, scope.QuotedTableName(), scope.quoteIfPossible(keyName), scope.quoteIfPossible(field), dest, onDelete, onUpdate)).Exec()
1242}
1243
1244func (scope *Scope) removeForeignKey(field string, dest string) {
1245	keyName := scope.Dialect().BuildKeyName(scope.TableName(), field, dest, "foreign")
1246	if !scope.Dialect().HasForeignKey(scope.TableName(), keyName) {
1247		return
1248	}
1249	var mysql mysql
1250	var query string
1251	if scope.Dialect().GetName() == mysql.GetName() {
1252		query = `ALTER TABLE %s DROP FOREIGN KEY %s;`
1253	} else {
1254		query = `ALTER TABLE %s DROP CONSTRAINT %s;`
1255	}
1256
1257	scope.Raw(fmt.Sprintf(query, scope.QuotedTableName(), scope.quoteIfPossible(keyName))).Exec()
1258}
1259
1260func (scope *Scope) removeIndex(indexName string) {
1261	scope.Dialect().RemoveIndex(scope.TableName(), indexName)
1262}
1263
1264func (scope *Scope) autoMigrate() *Scope {
1265	tableName := scope.TableName()
1266	quotedTableName := scope.QuotedTableName()
1267
1268	if !scope.Dialect().HasTable(tableName) {
1269		scope.createTable()
1270	} else {
1271		for _, field := range scope.GetModelStruct().StructFields {
1272			if !scope.Dialect().HasColumn(tableName, field.DBName) {
1273				if field.IsNormal {
1274					sqlTag := scope.Dialect().DataTypeOf(field)
1275					scope.Raw(fmt.Sprintf("ALTER TABLE %v ADD %v %v;", quotedTableName, scope.Quote(field.DBName), sqlTag)).Exec()
1276				}
1277			}
1278			scope.createJoinTable(field)
1279		}
1280		scope.autoIndex()
1281	}
1282	return scope
1283}
1284
1285func (scope *Scope) autoIndex() *Scope {
1286	var indexes = map[string][]string{}
1287	var uniqueIndexes = map[string][]string{}
1288
1289	for _, field := range scope.GetStructFields() {
1290		if name, ok := field.TagSettingsGet("INDEX"); ok {
1291			names := strings.Split(name, ",")
1292
1293			for _, name := range names {
1294				if name == "INDEX" || name == "" {
1295					name = scope.Dialect().BuildKeyName("idx", scope.TableName(), field.DBName)
1296				}
1297				name, column := scope.Dialect().NormalizeIndexAndColumn(name, field.DBName)
1298				indexes[name] = append(indexes[name], column)
1299			}
1300		}
1301
1302		if name, ok := field.TagSettingsGet("UNIQUE_INDEX"); ok {
1303			names := strings.Split(name, ",")
1304
1305			for _, name := range names {
1306				if name == "UNIQUE_INDEX" || name == "" {
1307					name = scope.Dialect().BuildKeyName("uix", scope.TableName(), field.DBName)
1308				}
1309				name, column := scope.Dialect().NormalizeIndexAndColumn(name, field.DBName)
1310				uniqueIndexes[name] = append(uniqueIndexes[name], column)
1311			}
1312		}
1313	}
1314
1315	for name, columns := range indexes {
1316		if db := scope.NewDB().Table(scope.TableName()).Model(scope.Value).AddIndex(name, columns...); db.Error != nil {
1317			scope.db.AddError(db.Error)
1318		}
1319	}
1320
1321	for name, columns := range uniqueIndexes {
1322		if db := scope.NewDB().Table(scope.TableName()).Model(scope.Value).AddUniqueIndex(name, columns...); db.Error != nil {
1323			scope.db.AddError(db.Error)
1324		}
1325	}
1326
1327	return scope
1328}
1329
1330func (scope *Scope) getColumnAsArray(columns []string, values ...interface{}) (results [][]interface{}) {
1331	resultMap := make(map[string][]interface{})
1332	for _, value := range values {
1333		indirectValue := indirect(reflect.ValueOf(value))
1334
1335		switch indirectValue.Kind() {
1336		case reflect.Slice:
1337			for i := 0; i < indirectValue.Len(); i++ {
1338				var result []interface{}
1339				var object = indirect(indirectValue.Index(i))
1340				var hasValue = false
1341				for _, column := range columns {
1342					field := object.FieldByName(column)
1343					if hasValue || !isBlank(field) {
1344						hasValue = true
1345					}
1346					result = append(result, field.Interface())
1347				}
1348
1349				if hasValue {
1350					h := fmt.Sprint(result...)
1351					if _, exist := resultMap[h]; !exist {
1352						resultMap[h] = result
1353					}
1354				}
1355			}
1356		case reflect.Struct:
1357			var result []interface{}
1358			var hasValue = false
1359			for _, column := range columns {
1360				field := indirectValue.FieldByName(column)
1361				if hasValue || !isBlank(field) {
1362					hasValue = true
1363				}
1364				result = append(result, field.Interface())
1365			}
1366
1367			if hasValue {
1368				h := fmt.Sprint(result...)
1369				if _, exist := resultMap[h]; !exist {
1370					resultMap[h] = result
1371				}
1372			}
1373		}
1374	}
1375	for _, v := range resultMap {
1376		results = append(results, v)
1377	}
1378	return
1379}
1380
1381func (scope *Scope) getColumnAsScope(column string) *Scope {
1382	indirectScopeValue := scope.IndirectValue()
1383
1384	switch indirectScopeValue.Kind() {
1385	case reflect.Slice:
1386		if fieldStruct, ok := scope.GetModelStruct().ModelType.FieldByName(column); ok {
1387			fieldType := fieldStruct.Type
1388			if fieldType.Kind() == reflect.Slice || fieldType.Kind() == reflect.Ptr {
1389				fieldType = fieldType.Elem()
1390			}
1391
1392			resultsMap := map[interface{}]bool{}
1393			results := reflect.New(reflect.SliceOf(reflect.PtrTo(fieldType))).Elem()
1394
1395			for i := 0; i < indirectScopeValue.Len(); i++ {
1396				result := indirect(indirect(indirectScopeValue.Index(i)).FieldByName(column))
1397
1398				if result.Kind() == reflect.Slice {
1399					for j := 0; j < result.Len(); j++ {
1400						if elem := result.Index(j); elem.CanAddr() && resultsMap[elem.Addr()] != true {
1401							resultsMap[elem.Addr()] = true
1402							results = reflect.Append(results, elem.Addr())
1403						}
1404					}
1405				} else if result.CanAddr() && resultsMap[result.Addr()] != true {
1406					resultsMap[result.Addr()] = true
1407					results = reflect.Append(results, result.Addr())
1408				}
1409			}
1410			return scope.New(results.Interface())
1411		}
1412	case reflect.Struct:
1413		if field := indirectScopeValue.FieldByName(column); field.CanAddr() {
1414			return scope.New(field.Addr().Interface())
1415		}
1416	}
1417	return nil
1418}
1419
1420func (scope *Scope) hasConditions() bool {
1421	return !scope.PrimaryKeyZero() ||
1422		len(scope.Search.whereConditions) > 0 ||
1423		len(scope.Search.orConditions) > 0 ||
1424		len(scope.Search.notConditions) > 0
1425}
1426