123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
- //
- // This Source Code Form is subject to the terms of the MIT License.
- // If a copy of the MIT was not distributed with this file,
- // You can obtain one at https://github.com/gogf/gf.
- package gdb
- import (
- "fmt"
- "github.com/gogf/gf/text/gstr"
- "github.com/gogf/gf/util/gconv"
- "strings"
- )
- // Where sets the condition statement for the model. The parameter `where` can be type of
- // string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
- // multiple conditions will be joined into where statement using "AND".
- // Eg:
- // Where("uid=10000")
- // Where("uid", 10000)
- // Where("money>? AND name like ?", 99999, "vip_%")
- // Where("uid", 1).Where("name", "john")
- // Where("status IN (?)", g.Slice{1,2,3})
- // Where("age IN(?,?)", 18, 50)
- // Where(User{ Id : 1, UserName : "john"})
- func (m *Model) Where(where interface{}, args ...interface{}) *Model {
- model := m.getModel()
- if model.whereHolder == nil {
- model.whereHolder = make([]ModelWhereHolder, 0)
- }
- model.whereHolder = append(model.whereHolder, ModelWhereHolder{
- Operator: whereHolderOperatorWhere,
- Where: where,
- Args: args,
- })
- return model
- }
- // Having sets the having statement for the model.
- // The parameters of this function usage are as the same as function Where.
- // See Where.
- func (m *Model) Having(having interface{}, args ...interface{}) *Model {
- model := m.getModel()
- model.having = []interface{}{
- having, args,
- }
- return model
- }
- // WherePri does the same logic as Model.Where except that if the parameter `where`
- // is a single condition like int/string/float/slice, it treats the condition as the primary
- // key value. That is, if primary key is "id" and given `where` parameter as "123", the
- // WherePri function treats the condition as "id=123", but Model.Where treats the condition
- // as string "123".
- func (m *Model) WherePri(where interface{}, args ...interface{}) *Model {
- if len(args) > 0 {
- return m.Where(where, args...)
- }
- newWhere := GetPrimaryKeyCondition(m.getPrimaryKey(), where)
- return m.Where(newWhere[0], newWhere[1:]...)
- }
- // Wheref builds condition string using fmt.Sprintf and arguments.
- // Note that if the number of `args` is more than the place holder in `format`,
- // the extra `args` will be used as the where condition arguments of the Model.
- func (m *Model) Wheref(format string, args ...interface{}) *Model {
- var (
- placeHolderCount = gstr.Count(format, "?")
- conditionStr = fmt.Sprintf(format, args[:len(args)-placeHolderCount]...)
- )
- return m.Where(conditionStr, args[len(args)-placeHolderCount:]...)
- }
- // WhereLT builds `column < value` statement.
- func (m *Model) WhereLT(column string, value interface{}) *Model {
- return m.Wheref(`%s < ?`, column, value)
- }
- // WhereLTE builds `column <= value` statement.
- func (m *Model) WhereLTE(column string, value interface{}) *Model {
- return m.Wheref(`%s <= ?`, column, value)
- }
- // WhereGT builds `column > value` statement.
- func (m *Model) WhereGT(column string, value interface{}) *Model {
- return m.Wheref(`%s > ?`, column, value)
- }
- // WhereGTE builds `column >= value` statement.
- func (m *Model) WhereGTE(column string, value interface{}) *Model {
- return m.Wheref(`%s >= ?`, column, value)
- }
- // WhereBetween builds `column BETWEEN min AND max` statement.
- func (m *Model) WhereBetween(column string, min, max interface{}) *Model {
- return m.Wheref(`%s BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
- }
- // WhereLike builds `column LIKE like` statement.
- func (m *Model) WhereLike(column string, like interface{}) *Model {
- return m.Wheref(`%s LIKE ?`, m.db.GetCore().QuoteWord(column), like)
- }
- // WhereIn builds `column IN (in)` statement.
- func (m *Model) WhereIn(column string, in interface{}) *Model {
- return m.Wheref(`%s IN (?)`, m.db.GetCore().QuoteWord(column), in)
- }
- // WhereNull builds `columns[0] IS NULL AND columns[1] IS NULL ...` statement.
- func (m *Model) WhereNull(columns ...string) *Model {
- model := m
- for _, column := range columns {
- model = m.Wheref(`%s IS NULL`, m.db.GetCore().QuoteWord(column))
- }
- return model
- }
- // WhereNotBetween builds `column NOT BETWEEN min AND max` statement.
- func (m *Model) WhereNotBetween(column string, min, max interface{}) *Model {
- return m.Wheref(`%s NOT BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
- }
- // WhereNotLike builds `column NOT LIKE like` statement.
- func (m *Model) WhereNotLike(column string, like interface{}) *Model {
- return m.Wheref(`%s NOT LIKE ?`, m.db.GetCore().QuoteWord(column), like)
- }
- // WhereNot builds `column != value` statement.
- func (m *Model) WhereNot(column string, value interface{}) *Model {
- return m.Wheref(`%s != ?`, m.db.GetCore().QuoteWord(column), value)
- }
- // WhereNotIn builds `column NOT IN (in)` statement.
- func (m *Model) WhereNotIn(column string, in interface{}) *Model {
- return m.Wheref(`%s NOT IN (?)`, m.db.GetCore().QuoteWord(column), in)
- }
- // WhereNotNull builds `columns[0] IS NOT NULL AND columns[1] IS NOT NULL ...` statement.
- func (m *Model) WhereNotNull(columns ...string) *Model {
- model := m
- for _, column := range columns {
- model = m.Wheref(`%s IS NOT NULL`, m.db.GetCore().QuoteWord(column))
- }
- return model
- }
- // WhereOr adds "OR" condition to the where statement.
- func (m *Model) WhereOr(where interface{}, args ...interface{}) *Model {
- model := m.getModel()
- if model.whereHolder == nil {
- model.whereHolder = make([]ModelWhereHolder, 0)
- }
- model.whereHolder = append(model.whereHolder, ModelWhereHolder{
- Operator: whereHolderOperatorOr,
- Where: where,
- Args: args,
- })
- return model
- }
- // WhereOrf builds `OR` condition string using fmt.Sprintf and arguments.
- func (m *Model) WhereOrf(format string, args ...interface{}) *Model {
- var (
- placeHolderCount = gstr.Count(format, "?")
- conditionStr = fmt.Sprintf(format, args[:len(args)-placeHolderCount]...)
- )
- return m.WhereOr(conditionStr, args[len(args)-placeHolderCount:]...)
- }
- // WhereOrLT builds `column < value` statement in `OR` conditions..
- func (m *Model) WhereOrLT(column string, value interface{}) *Model {
- return m.WhereOrf(`%s < ?`, column, value)
- }
- // WhereOrLTE builds `column <= value` statement in `OR` conditions..
- func (m *Model) WhereOrLTE(column string, value interface{}) *Model {
- return m.WhereOrf(`%s <= ?`, column, value)
- }
- // WhereOrGT builds `column > value` statement in `OR` conditions..
- func (m *Model) WhereOrGT(column string, value interface{}) *Model {
- return m.WhereOrf(`%s > ?`, column, value)
- }
- // WhereOrGTE builds `column >= value` statement in `OR` conditions..
- func (m *Model) WhereOrGTE(column string, value interface{}) *Model {
- return m.WhereOrf(`%s >= ?`, column, value)
- }
- // WhereOrBetween builds `column BETWEEN min AND max` statement in `OR` conditions.
- func (m *Model) WhereOrBetween(column string, min, max interface{}) *Model {
- return m.WhereOrf(`%s BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
- }
- // WhereOrLike builds `column LIKE like` statement in `OR` conditions.
- func (m *Model) WhereOrLike(column string, like interface{}) *Model {
- return m.WhereOrf(`%s LIKE ?`, m.db.GetCore().QuoteWord(column), like)
- }
- // WhereOrIn builds `column IN (in)` statement in `OR` conditions.
- func (m *Model) WhereOrIn(column string, in interface{}) *Model {
- return m.WhereOrf(`%s IN (?)`, m.db.GetCore().QuoteWord(column), in)
- }
- // WhereOrNull builds `columns[0] IS NULL OR columns[1] IS NULL ...` statement in `OR` conditions.
- func (m *Model) WhereOrNull(columns ...string) *Model {
- model := m
- for _, column := range columns {
- model = m.WhereOrf(`%s IS NULL`, m.db.GetCore().QuoteWord(column))
- }
- return model
- }
- // WhereOrNotBetween builds `column NOT BETWEEN min AND max` statement in `OR` conditions.
- func (m *Model) WhereOrNotBetween(column string, min, max interface{}) *Model {
- return m.WhereOrf(`%s NOT BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
- }
- // WhereOrNotLike builds `column NOT LIKE like` statement in `OR` conditions.
- func (m *Model) WhereOrNotLike(column string, like interface{}) *Model {
- return m.WhereOrf(`%s NOT LIKE ?`, m.db.GetCore().QuoteWord(column), like)
- }
- // WhereOrNotIn builds `column NOT IN (in)` statement.
- func (m *Model) WhereOrNotIn(column string, in interface{}) *Model {
- return m.WhereOrf(`%s NOT IN (?)`, m.db.GetCore().QuoteWord(column), in)
- }
- // WhereOrNotNull builds `columns[0] IS NOT NULL OR columns[1] IS NOT NULL ...` statement in `OR` conditions.
- func (m *Model) WhereOrNotNull(columns ...string) *Model {
- model := m
- for _, column := range columns {
- model = m.WhereOrf(`%s IS NOT NULL`, m.db.GetCore().QuoteWord(column))
- }
- return model
- }
- // Group sets the "GROUP BY" statement for the model.
- func (m *Model) Group(groupBy ...string) *Model {
- if len(groupBy) > 0 {
- model := m.getModel()
- model.groupBy = m.db.GetCore().QuoteString(gstr.Join(groupBy, ","))
- return model
- }
- return m
- }
- // And adds "AND" condition to the where statement.
- // Deprecated, use Where instead.
- func (m *Model) And(where interface{}, args ...interface{}) *Model {
- model := m.getModel()
- if model.whereHolder == nil {
- model.whereHolder = make([]ModelWhereHolder, 0)
- }
- model.whereHolder = append(model.whereHolder, ModelWhereHolder{
- Operator: whereHolderOperatorAnd,
- Where: where,
- Args: args,
- })
- return model
- }
- // Or adds "OR" condition to the where statement.
- // Deprecated, use WhereOr instead.
- func (m *Model) Or(where interface{}, args ...interface{}) *Model {
- return m.WhereOr(where, args...)
- }
- // GroupBy is alias of Model.Group.
- // See Model.Group.
- // Deprecated, use Group instead.
- func (m *Model) GroupBy(groupBy string) *Model {
- return m.Group(groupBy)
- }
- // Order sets the "ORDER BY" statement for the model.
- func (m *Model) Order(orderBy ...string) *Model {
- if len(orderBy) == 0 {
- return m
- }
- model := m.getModel()
- if model.orderBy != "" {
- model.orderBy += ","
- }
- model.orderBy = m.db.GetCore().QuoteString(strings.Join(orderBy, " "))
- return model
- }
- // OrderAsc sets the "ORDER BY xxx ASC" statement for the model.
- func (m *Model) OrderAsc(column string) *Model {
- if len(column) == 0 {
- return m
- }
- model := m.getModel()
- if model.orderBy != "" {
- model.orderBy += ","
- }
- model.orderBy = m.db.GetCore().QuoteWord(column) + " ASC"
- return model
- }
- // OrderDesc sets the "ORDER BY xxx DESC" statement for the model.
- func (m *Model) OrderDesc(column string) *Model {
- if len(column) == 0 {
- return m
- }
- model := m.getModel()
- if model.orderBy != "" {
- model.orderBy += ","
- }
- model.orderBy = m.db.GetCore().QuoteWord(column) + " DESC"
- return model
- }
- // OrderRandom sets the "ORDER BY RANDOM()" statement for the model.
- func (m *Model) OrderRandom() *Model {
- model := m.getModel()
- model.orderBy = "RAND()"
- return model
- }
- // OrderBy is alias of Model.Order.
- // See Model.Order.
- // Deprecated, use Order instead.
- func (m *Model) OrderBy(orderBy string) *Model {
- return m.Order(orderBy)
- }
- // Limit sets the "LIMIT" statement for the model.
- // The parameter `limit` can be either one or two number, if passed two number is passed,
- // it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
- // statement.
- func (m *Model) Limit(limit ...int) *Model {
- model := m.getModel()
- switch len(limit) {
- case 1:
- model.limit = limit[0]
- case 2:
- model.start = limit[0]
- model.limit = limit[1]
- }
- return model
- }
- // Offset sets the "OFFSET" statement for the model.
- // It only makes sense for some databases like SQLServer, PostgreSQL, etc.
- func (m *Model) Offset(offset int) *Model {
- model := m.getModel()
- model.offset = offset
- return model
- }
- // Distinct forces the query to only return distinct results.
- func (m *Model) Distinct() *Model {
- model := m.getModel()
- model.distinct = "DISTINCT "
- return model
- }
- // Page sets the paging number for the model.
- // The parameter `page` is started from 1 for paging.
- // Note that, it differs that the Limit function starts from 0 for "LIMIT" statement.
- func (m *Model) Page(page, limit int) *Model {
- model := m.getModel()
- if page <= 0 {
- page = 1
- }
- model.start = (page - 1) * limit
- model.limit = limit
- return model
- }
- // ForPage is alias of Model.Page.
- // See Model.Page.
- // Deprecated, use Page instead.
- func (m *Model) ForPage(page, limit int) *Model {
- return m.Page(page, limit)
- }
- // formatCondition formats where arguments of the model and returns a new condition sql and its arguments.
- // Note that this function does not change any attribute value of the `m`.
- //
- // The parameter `limit1` specifies whether limits querying only one record if m.limit is not set.
- func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWhere string, conditionExtra string, conditionArgs []interface{}) {
- if len(m.whereHolder) > 0 {
- for _, v := range m.whereHolder {
- switch v.Operator {
- case whereHolderOperatorWhere:
- if conditionWhere == "" {
- newWhere, newArgs := formatWhere(m.db, formatWhereInput{
- Where: v.Where,
- Args: v.Args,
- OmitNil: m.option&optionOmitNilWhere > 0,
- OmitEmpty: m.option&optionOmitEmptyWhere > 0,
- Schema: m.schema,
- Table: m.tables,
- })
- if len(newWhere) > 0 {
- conditionWhere = newWhere
- conditionArgs = newArgs
- }
- continue
- }
- fallthrough
- case whereHolderOperatorAnd:
- newWhere, newArgs := formatWhere(m.db, formatWhereInput{
- Where: v.Where,
- Args: v.Args,
- OmitNil: m.option&optionOmitNilWhere > 0,
- OmitEmpty: m.option&optionOmitEmptyWhere > 0,
- Schema: m.schema,
- Table: m.tables,
- })
- if len(newWhere) > 0 {
- if len(conditionWhere) == 0 {
- conditionWhere = newWhere
- } else if conditionWhere[0] == '(' {
- conditionWhere = fmt.Sprintf(`%s AND (%s)`, conditionWhere, newWhere)
- } else {
- conditionWhere = fmt.Sprintf(`(%s) AND (%s)`, conditionWhere, newWhere)
- }
- conditionArgs = append(conditionArgs, newArgs...)
- }
- case whereHolderOperatorOr:
- newWhere, newArgs := formatWhere(m.db, formatWhereInput{
- Where: v.Where,
- Args: v.Args,
- OmitNil: m.option&optionOmitNilWhere > 0,
- OmitEmpty: m.option&optionOmitEmptyWhere > 0,
- Schema: m.schema,
- Table: m.tables,
- })
- if len(newWhere) > 0 {
- if len(conditionWhere) == 0 {
- conditionWhere = newWhere
- } else if conditionWhere[0] == '(' {
- conditionWhere = fmt.Sprintf(`%s OR (%s)`, conditionWhere, newWhere)
- } else {
- conditionWhere = fmt.Sprintf(`(%s) OR (%s)`, conditionWhere, newWhere)
- }
- conditionArgs = append(conditionArgs, newArgs...)
- }
- }
- }
- }
- // Soft deletion.
- softDeletingCondition := m.getConditionForSoftDeleting()
- if m.rawSql != "" && conditionWhere != "" {
- if gstr.ContainsI(m.rawSql, " WHERE ") {
- conditionWhere = " AND " + conditionWhere
- } else {
- conditionWhere = " WHERE " + conditionWhere
- }
- } else if !m.unscoped && softDeletingCondition != "" {
- if conditionWhere == "" {
- conditionWhere = fmt.Sprintf(` WHERE %s`, softDeletingCondition)
- } else {
- conditionWhere = fmt.Sprintf(` WHERE (%s) AND %s`, conditionWhere, softDeletingCondition)
- }
- } else {
- if conditionWhere != "" {
- conditionWhere = " WHERE " + conditionWhere
- }
- }
- // GROUP BY.
- if m.groupBy != "" {
- conditionExtra += " GROUP BY " + m.groupBy
- }
- // HAVING.
- if len(m.having) > 0 {
- havingStr, havingArgs := formatWhere(m.db, formatWhereInput{
- Where: m.having[0],
- Args: gconv.Interfaces(m.having[1]),
- OmitNil: m.option&optionOmitNilWhere > 0,
- OmitEmpty: m.option&optionOmitEmptyWhere > 0,
- Schema: m.schema,
- Table: m.tables,
- })
- if len(havingStr) > 0 {
- conditionExtra += " HAVING " + havingStr
- conditionArgs = append(conditionArgs, havingArgs...)
- }
- }
- // ORDER BY.
- if m.orderBy != "" {
- conditionExtra += " ORDER BY " + m.orderBy
- }
- // LIMIT.
- if !isCountStatement {
- if m.limit != 0 {
- if m.start >= 0 {
- conditionExtra += fmt.Sprintf(" LIMIT %d,%d", m.start, m.limit)
- } else {
- conditionExtra += fmt.Sprintf(" LIMIT %d", m.limit)
- }
- } else if limit1 {
- conditionExtra += " LIMIT 1"
- }
- if m.offset >= 0 {
- conditionExtra += fmt.Sprintf(" OFFSET %d", m.offset)
- }
- }
- if m.lockInfo != "" {
- conditionExtra += " " + m.lockInfo
- }
- return
- }
|