github.com/wangyougui/gf/v2@v2.6.5/database/gdb/gdb_model_builder.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/wangyougui/gf. 6 7 package gdb 8 9 import ( 10 "fmt" 11 ) 12 13 // WhereBuilder holds multiple where conditions in a group. 14 type WhereBuilder struct { 15 model *Model // A WhereBuilder should be bound to certain Model. 16 whereHolder []WhereHolder // Condition strings for where operation. 17 } 18 19 // WhereHolder is the holder for where condition preparing. 20 type WhereHolder struct { 21 Type string // Type of this holder. 22 Operator int // Operator for this holder. 23 Where interface{} // Where parameter, which can commonly be type of string/map/struct. 24 Args []interface{} // Arguments for where parameter. 25 Prefix string // Field prefix, eg: "user.", "order.". 26 } 27 28 // Builder creates and returns a WhereBuilder. Please note that the builder is chain-safe. 29 func (m *Model) Builder() *WhereBuilder { 30 b := &WhereBuilder{ 31 model: m, 32 whereHolder: make([]WhereHolder, 0), 33 } 34 return b 35 } 36 37 // getBuilder creates and returns a cloned WhereBuilder of current WhereBuilder 38 func (b *WhereBuilder) getBuilder() *WhereBuilder { 39 return b.Clone() 40 } 41 42 // Clone clones and returns a WhereBuilder that is a copy of current one. 43 func (b *WhereBuilder) Clone() *WhereBuilder { 44 newBuilder := b.model.Builder() 45 newBuilder.whereHolder = make([]WhereHolder, len(b.whereHolder)) 46 copy(newBuilder.whereHolder, b.whereHolder) 47 return newBuilder 48 } 49 50 // Build builds current WhereBuilder and returns the condition string and parameters. 51 func (b *WhereBuilder) Build() (conditionWhere string, conditionArgs []interface{}) { 52 var ( 53 ctx = b.model.GetCtx() 54 autoPrefix = b.model.getAutoPrefix() 55 tableForMappingAndFiltering = b.model.tables 56 ) 57 if len(b.whereHolder) > 0 { 58 for _, holder := range b.whereHolder { 59 if holder.Prefix == "" { 60 holder.Prefix = autoPrefix 61 } 62 switch holder.Operator { 63 case whereHolderOperatorWhere, whereHolderOperatorAnd: 64 newWhere, newArgs := formatWhereHolder(ctx, b.model.db, formatWhereHolderInput{ 65 WhereHolder: holder, 66 OmitNil: b.model.option&optionOmitNilWhere > 0, 67 OmitEmpty: b.model.option&optionOmitEmptyWhere > 0, 68 Schema: b.model.schema, 69 Table: tableForMappingAndFiltering, 70 }) 71 if len(newWhere) > 0 { 72 if len(conditionWhere) == 0 { 73 conditionWhere = newWhere 74 } else if conditionWhere[0] == '(' { 75 conditionWhere = fmt.Sprintf(`%s AND (%s)`, conditionWhere, newWhere) 76 } else { 77 conditionWhere = fmt.Sprintf(`(%s) AND (%s)`, conditionWhere, newWhere) 78 } 79 conditionArgs = append(conditionArgs, newArgs...) 80 } 81 82 case whereHolderOperatorOr: 83 newWhere, newArgs := formatWhereHolder(ctx, b.model.db, formatWhereHolderInput{ 84 WhereHolder: holder, 85 OmitNil: b.model.option&optionOmitNilWhere > 0, 86 OmitEmpty: b.model.option&optionOmitEmptyWhere > 0, 87 Schema: b.model.schema, 88 Table: tableForMappingAndFiltering, 89 }) 90 if len(newWhere) > 0 { 91 if len(conditionWhere) == 0 { 92 conditionWhere = newWhere 93 } else if conditionWhere[0] == '(' { 94 conditionWhere = fmt.Sprintf(`%s OR (%s)`, conditionWhere, newWhere) 95 } else { 96 conditionWhere = fmt.Sprintf(`(%s) OR (%s)`, conditionWhere, newWhere) 97 } 98 conditionArgs = append(conditionArgs, newArgs...) 99 } 100 } 101 } 102 } 103 return 104 } 105 106 // convertWhereBuilder converts parameter `where` to condition string and parameters if `where` is also a WhereBuilder. 107 func (b *WhereBuilder) convertWhereBuilder(where interface{}, args []interface{}) (newWhere interface{}, newArgs []interface{}) { 108 var builder *WhereBuilder 109 switch v := where.(type) { 110 case WhereBuilder: 111 builder = &v 112 113 case *WhereBuilder: 114 builder = v 115 } 116 if builder != nil { 117 conditionWhere, conditionArgs := builder.Build() 118 if conditionWhere != "" && (len(b.whereHolder) == 0 || len(builder.whereHolder) > 1) { 119 conditionWhere = "(" + conditionWhere + ")" 120 } 121 return conditionWhere, conditionArgs 122 } 123 return where, args 124 }