github.com/gogf/gf@v1.16.9/database/gdb/gdb_model_condition.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gdb
     8  
     9  import (
    10  	"fmt"
    11  	"github.com/gogf/gf/text/gstr"
    12  	"github.com/gogf/gf/util/gconv"
    13  	"strings"
    14  )
    15  
    16  // Where sets the condition statement for the model. The parameter `where` can be type of
    17  // string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
    18  // multiple conditions will be joined into where statement using "AND".
    19  // Eg:
    20  // Where("uid=10000")
    21  // Where("uid", 10000)
    22  // Where("money>? AND name like ?", 99999, "vip_%")
    23  // Where("uid", 1).Where("name", "john")
    24  // Where("status IN (?)", g.Slice{1,2,3})
    25  // Where("age IN(?,?)", 18, 50)
    26  // Where(User{ Id : 1, UserName : "john"})
    27  func (m *Model) Where(where interface{}, args ...interface{}) *Model {
    28  	model := m.getModel()
    29  	if model.whereHolder == nil {
    30  		model.whereHolder = make([]ModelWhereHolder, 0)
    31  	}
    32  	model.whereHolder = append(model.whereHolder, ModelWhereHolder{
    33  		Operator: whereHolderOperatorWhere,
    34  		Where:    where,
    35  		Args:     args,
    36  	})
    37  	return model
    38  }
    39  
    40  // Having sets the having statement for the model.
    41  // The parameters of this function usage are as the same as function Where.
    42  // See Where.
    43  func (m *Model) Having(having interface{}, args ...interface{}) *Model {
    44  	model := m.getModel()
    45  	model.having = []interface{}{
    46  		having, args,
    47  	}
    48  	return model
    49  }
    50  
    51  // WherePri does the same logic as Model.Where except that if the parameter `where`
    52  // is a single condition like int/string/float/slice, it treats the condition as the primary
    53  // key value. That is, if primary key is "id" and given `where` parameter as "123", the
    54  // WherePri function treats the condition as "id=123", but Model.Where treats the condition
    55  // as string "123".
    56  func (m *Model) WherePri(where interface{}, args ...interface{}) *Model {
    57  	if len(args) > 0 {
    58  		return m.Where(where, args...)
    59  	}
    60  	newWhere := GetPrimaryKeyCondition(m.getPrimaryKey(), where)
    61  	return m.Where(newWhere[0], newWhere[1:]...)
    62  }
    63  
    64  // Wheref builds condition string using fmt.Sprintf and arguments.
    65  // Note that if the number of `args` is more than the place holder in `format`,
    66  // the extra `args` will be used as the where condition arguments of the Model.
    67  func (m *Model) Wheref(format string, args ...interface{}) *Model {
    68  	var (
    69  		placeHolderCount = gstr.Count(format, "?")
    70  		conditionStr     = fmt.Sprintf(format, args[:len(args)-placeHolderCount]...)
    71  	)
    72  	return m.Where(conditionStr, args[len(args)-placeHolderCount:]...)
    73  }
    74  
    75  // WhereLT builds `column < value` statement.
    76  func (m *Model) WhereLT(column string, value interface{}) *Model {
    77  	return m.Wheref(`%s < ?`, column, value)
    78  }
    79  
    80  // WhereLTE builds `column <= value` statement.
    81  func (m *Model) WhereLTE(column string, value interface{}) *Model {
    82  	return m.Wheref(`%s <= ?`, column, value)
    83  }
    84  
    85  // WhereGT builds `column > value` statement.
    86  func (m *Model) WhereGT(column string, value interface{}) *Model {
    87  	return m.Wheref(`%s > ?`, column, value)
    88  }
    89  
    90  // WhereGTE builds `column >= value` statement.
    91  func (m *Model) WhereGTE(column string, value interface{}) *Model {
    92  	return m.Wheref(`%s >= ?`, column, value)
    93  }
    94  
    95  // WhereBetween builds `column BETWEEN min AND max` statement.
    96  func (m *Model) WhereBetween(column string, min, max interface{}) *Model {
    97  	return m.Wheref(`%s BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
    98  }
    99  
   100  // WhereLike builds `column LIKE like` statement.
   101  func (m *Model) WhereLike(column string, like interface{}) *Model {
   102  	return m.Wheref(`%s LIKE ?`, m.db.GetCore().QuoteWord(column), like)
   103  }
   104  
   105  // WhereIn builds `column IN (in)` statement.
   106  func (m *Model) WhereIn(column string, in interface{}) *Model {
   107  	return m.Wheref(`%s IN (?)`, m.db.GetCore().QuoteWord(column), in)
   108  }
   109  
   110  // WhereNull builds `columns[0] IS NULL AND columns[1] IS NULL ...` statement.
   111  func (m *Model) WhereNull(columns ...string) *Model {
   112  	model := m
   113  	for _, column := range columns {
   114  		model = m.Wheref(`%s IS NULL`, m.db.GetCore().QuoteWord(column))
   115  	}
   116  	return model
   117  }
   118  
   119  // WhereNotBetween builds `column NOT BETWEEN min AND max` statement.
   120  func (m *Model) WhereNotBetween(column string, min, max interface{}) *Model {
   121  	return m.Wheref(`%s NOT BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
   122  }
   123  
   124  // WhereNotLike builds `column NOT LIKE like` statement.
   125  func (m *Model) WhereNotLike(column string, like interface{}) *Model {
   126  	return m.Wheref(`%s NOT LIKE ?`, m.db.GetCore().QuoteWord(column), like)
   127  }
   128  
   129  // WhereNot builds `column != value` statement.
   130  func (m *Model) WhereNot(column string, value interface{}) *Model {
   131  	return m.Wheref(`%s != ?`, m.db.GetCore().QuoteWord(column), value)
   132  }
   133  
   134  // WhereNotIn builds `column NOT IN (in)` statement.
   135  func (m *Model) WhereNotIn(column string, in interface{}) *Model {
   136  	return m.Wheref(`%s NOT IN (?)`, m.db.GetCore().QuoteWord(column), in)
   137  }
   138  
   139  // WhereNotNull builds `columns[0] IS NOT NULL AND columns[1] IS NOT NULL ...` statement.
   140  func (m *Model) WhereNotNull(columns ...string) *Model {
   141  	model := m
   142  	for _, column := range columns {
   143  		model = m.Wheref(`%s IS NOT NULL`, m.db.GetCore().QuoteWord(column))
   144  	}
   145  	return model
   146  }
   147  
   148  // WhereOr adds "OR" condition to the where statement.
   149  func (m *Model) WhereOr(where interface{}, args ...interface{}) *Model {
   150  	model := m.getModel()
   151  	if model.whereHolder == nil {
   152  		model.whereHolder = make([]ModelWhereHolder, 0)
   153  	}
   154  	model.whereHolder = append(model.whereHolder, ModelWhereHolder{
   155  		Operator: whereHolderOperatorOr,
   156  		Where:    where,
   157  		Args:     args,
   158  	})
   159  	return model
   160  }
   161  
   162  // WhereOrf builds `OR` condition string using fmt.Sprintf and arguments.
   163  func (m *Model) WhereOrf(format string, args ...interface{}) *Model {
   164  	var (
   165  		placeHolderCount = gstr.Count(format, "?")
   166  		conditionStr     = fmt.Sprintf(format, args[:len(args)-placeHolderCount]...)
   167  	)
   168  	return m.WhereOr(conditionStr, args[len(args)-placeHolderCount:]...)
   169  }
   170  
   171  // WhereOrLT builds `column < value` statement in `OR` conditions..
   172  func (m *Model) WhereOrLT(column string, value interface{}) *Model {
   173  	return m.WhereOrf(`%s < ?`, column, value)
   174  }
   175  
   176  // WhereOrLTE builds `column <= value` statement in `OR` conditions..
   177  func (m *Model) WhereOrLTE(column string, value interface{}) *Model {
   178  	return m.WhereOrf(`%s <= ?`, column, value)
   179  }
   180  
   181  // WhereOrGT builds `column > value` statement in `OR` conditions..
   182  func (m *Model) WhereOrGT(column string, value interface{}) *Model {
   183  	return m.WhereOrf(`%s > ?`, column, value)
   184  }
   185  
   186  // WhereOrGTE builds `column >= value` statement in `OR` conditions..
   187  func (m *Model) WhereOrGTE(column string, value interface{}) *Model {
   188  	return m.WhereOrf(`%s >= ?`, column, value)
   189  }
   190  
   191  // WhereOrBetween builds `column BETWEEN min AND max` statement in `OR` conditions.
   192  func (m *Model) WhereOrBetween(column string, min, max interface{}) *Model {
   193  	return m.WhereOrf(`%s BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
   194  }
   195  
   196  // WhereOrLike builds `column LIKE like` statement in `OR` conditions.
   197  func (m *Model) WhereOrLike(column string, like interface{}) *Model {
   198  	return m.WhereOrf(`%s LIKE ?`, m.db.GetCore().QuoteWord(column), like)
   199  }
   200  
   201  // WhereOrIn builds `column IN (in)` statement in `OR` conditions.
   202  func (m *Model) WhereOrIn(column string, in interface{}) *Model {
   203  	return m.WhereOrf(`%s IN (?)`, m.db.GetCore().QuoteWord(column), in)
   204  }
   205  
   206  // WhereOrNull builds `columns[0] IS NULL OR columns[1] IS NULL ...` statement in `OR` conditions.
   207  func (m *Model) WhereOrNull(columns ...string) *Model {
   208  	model := m
   209  	for _, column := range columns {
   210  		model = m.WhereOrf(`%s IS NULL`, m.db.GetCore().QuoteWord(column))
   211  	}
   212  	return model
   213  }
   214  
   215  // WhereOrNotBetween builds `column NOT BETWEEN min AND max` statement in `OR` conditions.
   216  func (m *Model) WhereOrNotBetween(column string, min, max interface{}) *Model {
   217  	return m.WhereOrf(`%s NOT BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
   218  }
   219  
   220  // WhereOrNotLike builds `column NOT LIKE like` statement in `OR` conditions.
   221  func (m *Model) WhereOrNotLike(column string, like interface{}) *Model {
   222  	return m.WhereOrf(`%s NOT LIKE ?`, m.db.GetCore().QuoteWord(column), like)
   223  }
   224  
   225  // WhereOrNotIn builds `column NOT IN (in)` statement.
   226  func (m *Model) WhereOrNotIn(column string, in interface{}) *Model {
   227  	return m.WhereOrf(`%s NOT IN (?)`, m.db.GetCore().QuoteWord(column), in)
   228  }
   229  
   230  // WhereOrNotNull builds `columns[0] IS NOT NULL OR columns[1] IS NOT NULL ...` statement in `OR` conditions.
   231  func (m *Model) WhereOrNotNull(columns ...string) *Model {
   232  	model := m
   233  	for _, column := range columns {
   234  		model = m.WhereOrf(`%s IS NOT NULL`, m.db.GetCore().QuoteWord(column))
   235  	}
   236  	return model
   237  }
   238  
   239  // Group sets the "GROUP BY" statement for the model.
   240  func (m *Model) Group(groupBy ...string) *Model {
   241  	if len(groupBy) > 0 {
   242  		model := m.getModel()
   243  		model.groupBy = m.db.GetCore().QuoteString(gstr.Join(groupBy, ","))
   244  		return model
   245  	}
   246  	return m
   247  }
   248  
   249  // And adds "AND" condition to the where statement.
   250  // Deprecated, use Where instead.
   251  func (m *Model) And(where interface{}, args ...interface{}) *Model {
   252  	model := m.getModel()
   253  	if model.whereHolder == nil {
   254  		model.whereHolder = make([]ModelWhereHolder, 0)
   255  	}
   256  	model.whereHolder = append(model.whereHolder, ModelWhereHolder{
   257  		Operator: whereHolderOperatorAnd,
   258  		Where:    where,
   259  		Args:     args,
   260  	})
   261  	return model
   262  }
   263  
   264  // Or adds "OR" condition to the where statement.
   265  // Deprecated, use WhereOr instead.
   266  func (m *Model) Or(where interface{}, args ...interface{}) *Model {
   267  	return m.WhereOr(where, args...)
   268  }
   269  
   270  // GroupBy is alias of Model.Group.
   271  // See Model.Group.
   272  // Deprecated, use Group instead.
   273  func (m *Model) GroupBy(groupBy string) *Model {
   274  	return m.Group(groupBy)
   275  }
   276  
   277  // Order sets the "ORDER BY" statement for the model.
   278  func (m *Model) Order(orderBy ...string) *Model {
   279  	if len(orderBy) == 0 {
   280  		return m
   281  	}
   282  	model := m.getModel()
   283  	if model.orderBy != "" {
   284  		model.orderBy += ","
   285  	}
   286  	model.orderBy = m.db.GetCore().QuoteString(strings.Join(orderBy, " "))
   287  	return model
   288  }
   289  
   290  // OrderAsc sets the "ORDER BY xxx ASC" statement for the model.
   291  func (m *Model) OrderAsc(column string) *Model {
   292  	if len(column) == 0 {
   293  		return m
   294  	}
   295  	model := m.getModel()
   296  	if model.orderBy != "" {
   297  		model.orderBy += ","
   298  	}
   299  	model.orderBy = m.db.GetCore().QuoteWord(column) + " ASC"
   300  	return model
   301  }
   302  
   303  // OrderDesc sets the "ORDER BY xxx DESC" statement for the model.
   304  func (m *Model) OrderDesc(column string) *Model {
   305  	if len(column) == 0 {
   306  		return m
   307  	}
   308  	model := m.getModel()
   309  	if model.orderBy != "" {
   310  		model.orderBy += ","
   311  	}
   312  	model.orderBy = m.db.GetCore().QuoteWord(column) + " DESC"
   313  	return model
   314  }
   315  
   316  // OrderRandom sets the "ORDER BY RANDOM()" statement for the model.
   317  func (m *Model) OrderRandom() *Model {
   318  	model := m.getModel()
   319  	model.orderBy = "RAND()"
   320  	return model
   321  }
   322  
   323  // OrderBy is alias of Model.Order.
   324  // See Model.Order.
   325  // Deprecated, use Order instead.
   326  func (m *Model) OrderBy(orderBy string) *Model {
   327  	return m.Order(orderBy)
   328  }
   329  
   330  // Limit sets the "LIMIT" statement for the model.
   331  // The parameter `limit` can be either one or two number, if passed two number is passed,
   332  // it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
   333  // statement.
   334  func (m *Model) Limit(limit ...int) *Model {
   335  	model := m.getModel()
   336  	switch len(limit) {
   337  	case 1:
   338  		model.limit = limit[0]
   339  	case 2:
   340  		model.start = limit[0]
   341  		model.limit = limit[1]
   342  	}
   343  	return model
   344  }
   345  
   346  // Offset sets the "OFFSET" statement for the model.
   347  // It only makes sense for some databases like SQLServer, PostgreSQL, etc.
   348  func (m *Model) Offset(offset int) *Model {
   349  	model := m.getModel()
   350  	model.offset = offset
   351  	return model
   352  }
   353  
   354  // Distinct forces the query to only return distinct results.
   355  func (m *Model) Distinct() *Model {
   356  	model := m.getModel()
   357  	model.distinct = "DISTINCT "
   358  	return model
   359  }
   360  
   361  // Page sets the paging number for the model.
   362  // The parameter `page` is started from 1 for paging.
   363  // Note that, it differs that the Limit function starts from 0 for "LIMIT" statement.
   364  func (m *Model) Page(page, limit int) *Model {
   365  	model := m.getModel()
   366  	if page <= 0 {
   367  		page = 1
   368  	}
   369  	model.start = (page - 1) * limit
   370  	model.limit = limit
   371  	return model
   372  }
   373  
   374  // ForPage is alias of Model.Page.
   375  // See Model.Page.
   376  // Deprecated, use Page instead.
   377  func (m *Model) ForPage(page, limit int) *Model {
   378  	return m.Page(page, limit)
   379  }
   380  
   381  // formatCondition formats where arguments of the model and returns a new condition sql and its arguments.
   382  // Note that this function does not change any attribute value of the `m`.
   383  //
   384  // The parameter `limit1` specifies whether limits querying only one record if m.limit is not set.
   385  func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWhere string, conditionExtra string, conditionArgs []interface{}) {
   386  	if len(m.whereHolder) > 0 {
   387  		for _, v := range m.whereHolder {
   388  			switch v.Operator {
   389  			case whereHolderOperatorWhere:
   390  				if conditionWhere == "" {
   391  					newWhere, newArgs := formatWhere(m.db, formatWhereInput{
   392  						Where:     v.Where,
   393  						Args:      v.Args,
   394  						OmitNil:   m.option&optionOmitNilWhere > 0,
   395  						OmitEmpty: m.option&optionOmitEmptyWhere > 0,
   396  						Schema:    m.schema,
   397  						Table:     m.tables,
   398  					})
   399  					if len(newWhere) > 0 {
   400  						conditionWhere = newWhere
   401  						conditionArgs = newArgs
   402  					}
   403  					continue
   404  				}
   405  				fallthrough
   406  
   407  			case whereHolderOperatorAnd:
   408  				newWhere, newArgs := formatWhere(m.db, formatWhereInput{
   409  					Where:     v.Where,
   410  					Args:      v.Args,
   411  					OmitNil:   m.option&optionOmitNilWhere > 0,
   412  					OmitEmpty: m.option&optionOmitEmptyWhere > 0,
   413  					Schema:    m.schema,
   414  					Table:     m.tables,
   415  				})
   416  				if len(newWhere) > 0 {
   417  					if len(conditionWhere) == 0 {
   418  						conditionWhere = newWhere
   419  					} else if conditionWhere[0] == '(' {
   420  						conditionWhere = fmt.Sprintf(`%s AND (%s)`, conditionWhere, newWhere)
   421  					} else {
   422  						conditionWhere = fmt.Sprintf(`(%s) AND (%s)`, conditionWhere, newWhere)
   423  					}
   424  					conditionArgs = append(conditionArgs, newArgs...)
   425  				}
   426  
   427  			case whereHolderOperatorOr:
   428  				newWhere, newArgs := formatWhere(m.db, formatWhereInput{
   429  					Where:     v.Where,
   430  					Args:      v.Args,
   431  					OmitNil:   m.option&optionOmitNilWhere > 0,
   432  					OmitEmpty: m.option&optionOmitEmptyWhere > 0,
   433  					Schema:    m.schema,
   434  					Table:     m.tables,
   435  				})
   436  				if len(newWhere) > 0 {
   437  					if len(conditionWhere) == 0 {
   438  						conditionWhere = newWhere
   439  					} else if conditionWhere[0] == '(' {
   440  						conditionWhere = fmt.Sprintf(`%s OR (%s)`, conditionWhere, newWhere)
   441  					} else {
   442  						conditionWhere = fmt.Sprintf(`(%s) OR (%s)`, conditionWhere, newWhere)
   443  					}
   444  					conditionArgs = append(conditionArgs, newArgs...)
   445  				}
   446  			}
   447  		}
   448  	}
   449  	// Soft deletion.
   450  	softDeletingCondition := m.getConditionForSoftDeleting()
   451  	if m.rawSql != "" && conditionWhere != "" {
   452  		if gstr.ContainsI(m.rawSql, " WHERE ") {
   453  			conditionWhere = " AND " + conditionWhere
   454  		} else {
   455  			conditionWhere = " WHERE " + conditionWhere
   456  		}
   457  	} else if !m.unscoped && softDeletingCondition != "" {
   458  		if conditionWhere == "" {
   459  			conditionWhere = fmt.Sprintf(` WHERE %s`, softDeletingCondition)
   460  		} else {
   461  			conditionWhere = fmt.Sprintf(` WHERE (%s) AND %s`, conditionWhere, softDeletingCondition)
   462  		}
   463  	} else {
   464  		if conditionWhere != "" {
   465  			conditionWhere = " WHERE " + conditionWhere
   466  		}
   467  	}
   468  
   469  	// GROUP BY.
   470  	if m.groupBy != "" {
   471  		conditionExtra += " GROUP BY " + m.groupBy
   472  	}
   473  	// HAVING.
   474  	if len(m.having) > 0 {
   475  		havingStr, havingArgs := formatWhere(m.db, formatWhereInput{
   476  			Where:     m.having[0],
   477  			Args:      gconv.Interfaces(m.having[1]),
   478  			OmitNil:   m.option&optionOmitNilWhere > 0,
   479  			OmitEmpty: m.option&optionOmitEmptyWhere > 0,
   480  			Schema:    m.schema,
   481  			Table:     m.tables,
   482  		})
   483  		if len(havingStr) > 0 {
   484  			conditionExtra += " HAVING " + havingStr
   485  			conditionArgs = append(conditionArgs, havingArgs...)
   486  		}
   487  	}
   488  	// ORDER BY.
   489  	if m.orderBy != "" {
   490  		conditionExtra += " ORDER BY " + m.orderBy
   491  	}
   492  	// LIMIT.
   493  	if !isCountStatement {
   494  		if m.limit != 0 {
   495  			if m.start >= 0 {
   496  				conditionExtra += fmt.Sprintf(" LIMIT %d,%d", m.start, m.limit)
   497  			} else {
   498  				conditionExtra += fmt.Sprintf(" LIMIT %d", m.limit)
   499  			}
   500  		} else if limit1 {
   501  			conditionExtra += " LIMIT 1"
   502  		}
   503  
   504  		if m.offset >= 0 {
   505  			conditionExtra += fmt.Sprintf(" OFFSET %d", m.offset)
   506  		}
   507  	}
   508  
   509  	if m.lockInfo != "" {
   510  		conditionExtra += " " + m.lockInfo
   511  	}
   512  	return
   513  }