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 }