gitee.com/h79/goutils@v1.22.10/dao/wrapper/condition.go (about) 1 package wrapper 2 3 import ( 4 commonoption "gitee.com/h79/goutils/common/option" 5 "gitee.com/h79/goutils/dao/option" 6 "reflect" 7 "strings" 8 ) 9 10 var _ IQuery = (*Condition)(nil) 11 12 // Operate 13 const ( 14 And = "AND " 15 Or = "OR " 16 Eq = "= ?" 17 Neq = "<> ?" 18 Lt = "< ?" 19 Lte = "<= ?" 20 Gt = "> ?" 21 Gte = ">= ?" 22 NotIn = "NOT IN ?" 23 In = "IN ?" 24 Between = "BETWEEN ? AND ?" 25 Like = "LIKE ?" 26 Exists = "EXISTS ?" 27 NotExists = "NOT EXISTS ?" 28 ) 29 30 func Compose[T ComposeType](op []string, cond *Condition, column string, size int, values []T) { 31 if len(values) <= 0 { 32 return 33 } 34 if len(values) == 1 { 35 cond.And(column, op[0], values[0]) 36 } else if len(values) >= size { 37 cond.Compose(column, op[1], values) 38 } else { 39 for i := range values { 40 cond.Or(column, op[0], values[i]) 41 } 42 } 43 } 44 45 func OrCompose[T ComposeType](op []string, cond *Condition, column string, size int, values []T) { 46 if len(values) <= 0 { 47 return 48 } 49 if len(values) == 1 { 50 cond.Or(column, op[0], values[0]) 51 } else if len(values) >= size { 52 cond.Or(column, op[1], values) 53 } else { 54 for i := range values { 55 cond.Or(column, op[0], values[i]) 56 } 57 } 58 } 59 60 func AndCompose[T ComposeType](op []string, cond *Condition, column string, size int, values []T) { 61 if len(values) <= 0 { 62 return 63 } 64 if len(values) == 1 { 65 cond.And(column, op[0], values[0]) 66 } else { 67 cs := Condition{} 68 if len(values) >= size { 69 cs.Compose(column, op[1], values) 70 } else { 71 for i := range values { 72 cs.Or(column, op[0], values[i]) 73 } 74 } 75 cond.From(&cs, true, And) 76 } 77 } 78 79 var InOp = []string{Eq, In} 80 81 func IN[T ComposeType](cond *Condition, column string, size int, values []T) { 82 Compose(InOp, cond, column, size, values) 83 } 84 85 var NotInOp = []string{Neq, NotIn} 86 87 func NIN[T ComposeType](cond *Condition, column string, size int, values []T) { 88 Compose(NotInOp, cond, column, size, values) 89 } 90 91 func OR[T ComposeType](cond *Condition, column string, size int, values []T) { 92 OrCompose(InOp, cond, column, size, values) 93 } 94 95 func AND[T ComposeType](cond *Condition, column string, size int, values []T) { 96 AndCompose(InOp, cond, column, size, values) 97 } 98 99 type ComposeType interface { 100 ~string | bool | ~int8 | ~int16 | ~int | ~int32 | ~int64 | ~uint8 | ~uint16 | ~uint | ~uint32 | ~uint64 | ~float32 | ~float64 101 } 102 103 type Condition struct { 104 sql strings.Builder 105 vars []any 106 hasOp bool 107 } 108 109 // And 110 /* @param column 111 * @param operator "=、<小于、>大于、>=大于等于、<=小于等于、<>以及不等于" 112 */ 113 func (sq *Condition) And(column, operator string, value any) *Condition { 114 if sq.hasOp { 115 sq.Operate(And) 116 } 117 return sq.Compose(column, operator, value) 118 } 119 120 func (sq *Condition) AndEq(column string, value any) *Condition { 121 return sq.And(column, Eq, value) 122 } 123 124 func (sq *Condition) AndNEq(column string, value any) *Condition { 125 return sq.And(column, Neq, value) 126 } 127 128 func (sq *Condition) AndLt(column string, value any) *Condition { 129 return sq.And(column, Lt, value) 130 } 131 132 func (sq *Condition) AndLte(column string, value any) *Condition { 133 return sq.And(column, Lte, value) 134 } 135 136 func (sq *Condition) AndGt(column string, value any) *Condition { 137 return sq.And(column, Gt, value) 138 } 139 140 func (sq *Condition) AndGte(column string, value any) *Condition { 141 return sq.And(column, Gte, value) 142 } 143 144 func (sq *Condition) Or(column, operator string, value any) *Condition { 145 if sq.hasOp { 146 sq.Operate(Or) 147 } 148 return sq.Compose(column, operator, value) 149 } 150 151 func (sq *Condition) OrEq(column string, value any) *Condition { 152 return sq.Or(column, Eq, value) 153 } 154 155 func (sq *Condition) OrNEq(column string, value any) *Condition { 156 return sq.Or(column, Neq, value) 157 } 158 159 func (sq *Condition) OrLt(column string, value any) *Condition { 160 return sq.Or(column, Lt, value) 161 } 162 163 func (sq *Condition) OrLte(column string, value any) *Condition { 164 return sq.Or(column, Lte, value) 165 } 166 167 func (sq *Condition) OrGt(column string, value any) *Condition { 168 return sq.Or(column, Gt, value) 169 } 170 171 func (sq *Condition) OrGte(column string, value any) *Condition { 172 return sq.Or(column, Gte, value) 173 } 174 175 func (sq *Condition) In(column string, value any) *Condition { 176 return sq.Compose(column, In, value) 177 } 178 179 func (sq *Condition) NotIn(column string, value any) *Condition { 180 return sq.Compose(column, NotIn, value) 181 } 182 183 // Like 184 /* @example db.Where("name LIKE ?", "%jin%").Find(&users) 185 * Condition.Like("name","jin") 186 */ 187 func (sq *Condition) Like(column string, value any) *Condition { 188 return sq.Compose(column, Like, value) 189 } 190 191 // PLike %? 192 func PLike(value string) string { 193 return "%" + value 194 } 195 func (sq *Condition) PLike(column string, value string) *Condition { 196 return sq.Compose(column, Like, "%"+value) 197 } 198 199 // SLike ?% 200 func SLike(value string) string { 201 return value + "%" 202 } 203 func (sq *Condition) SLike(column string, value string) *Condition { 204 return sq.Compose(column, Like, value+"%") 205 } 206 207 // MLike %?% 208 func MLike(value string) string { 209 return "%" + value + "%" 210 } 211 func (sq *Condition) MLike(column string, value string) *Condition { 212 return sq.Compose(column, Like, "%"+value+"%") 213 } 214 215 func (sq *Condition) Between(column string, value1, value2 any) *Condition { 216 return sq.AndBetween(column, value1, value2) 217 } 218 219 func (sq *Condition) AndBetween(column string, value1, value2 any) *Condition { 220 if sq.hasOp { 221 sq.Operate(And) 222 } 223 return sq.Compose(column, Between, value1, value2) 224 } 225 226 func (sq *Condition) OrBetween(column string, value1, value2 any) *Condition { 227 if sq.hasOp { 228 sq.Operate(Or) 229 } 230 return sq.Compose(column, Between, value1, value2) 231 } 232 233 func (sq *Condition) Eq(column string, value any) *Condition { 234 return sq.Compose(column, Eq, value) 235 } 236 237 func (sq *Condition) NEq(column string, value any) *Condition { 238 return sq.Compose(column, Neq, value) 239 } 240 func (sq *Condition) Neq(column string, value any) *Condition { 241 return sq.Compose(column, Neq, value) 242 } 243 244 func (sq *Condition) Lt(column string, value any) *Condition { 245 return sq.Compose(column, Lt, value) 246 } 247 248 func (sq *Condition) LtEq(column string, value any) *Condition { 249 return sq.Compose(column, Lte, value) 250 } 251 func (sq *Condition) Lte(column string, value any) *Condition { 252 return sq.Compose(column, Lte, value) 253 } 254 255 func (sq *Condition) Gt(column string, value any) *Condition { 256 return sq.Compose(column, Gt, value) 257 } 258 259 func (sq *Condition) GtEq(column string, value any) *Condition { 260 return sq.Compose(column, Gte, value) 261 } 262 func (sq *Condition) Gte(column string, value any) *Condition { 263 return sq.Compose(column, Gte, value) 264 } 265 266 // Column 267 /* 268 * example db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users) 269 */ 270 func (sq *Condition) Column(column string) *Condition { 271 SqlColumn(&sq.sql, column) 272 return sq 273 } 274 275 // Operate 276 /* @param operator 277 * @example created_at BETWEEN ? AND ? 278 * Condition.Column("created_at").Operate("BETWEEN").Operate("AND").Values(11333,34444) 279 */ 280 func (sq *Condition) Operate(operator string) *Condition { 281 if !sq.hasOp { 282 sq.hasOp = true 283 } 284 sq.sql.WriteByte(' ') 285 sq.sql.WriteString(operator) 286 return sq 287 } 288 289 func (sq *Condition) Values(value ...interface{}) *Condition { 290 sq.vars = append(sq.vars, value...) 291 return sq 292 } 293 294 func (sq *Condition) Compose(column string, operator string, value ...any) *Condition { 295 sq.Column(column) 296 sq.Operate(operator) 297 sq.vars = append(sq.vars, value...) 298 return sq 299 } 300 301 // Modifier 修饰符,比如 () 302 func (sq *Condition) Modifier(m string) *Condition { 303 sq.sql.WriteString(m) 304 return sq 305 } 306 307 // ComposeFrom 组合 308 // Deprecated: please use Condition.From 309 func (sq *Condition) ComposeFrom(src *Condition, operator string) *Condition { 310 return sq.From(src, true, operator) 311 } 312 313 // From 组合 组合 314 // brackets 是否需要用 () 把语句 315 func (sq *Condition) From(src *Condition, brackets bool, operator string) *Condition { 316 if !sq.hasOp { 317 sq.hasOp = src.hasOp 318 } else { 319 sq.Operate(operator) 320 } 321 if brackets { 322 sq.sql.WriteByte('(') 323 sq.sql.WriteString(strings.Trim(src.Query(), " ")) 324 sq.sql.WriteByte(')') 325 } else { 326 sq.sql.WriteString(src.Query()) 327 } 328 sq.Values(src.Value()...) 329 return sq 330 } 331 332 func (sq *Condition) IsFirst() bool { 333 return sq.hasOp 334 } 335 336 func (sq *Condition) Is() bool { 337 if sq == nil { 338 return false 339 } 340 return sq.sql.Len() > 0 && len(sq.vars) > 0 341 } 342 343 func (sq *Condition) Cond() string { 344 return sq.sql.String() 345 } 346 347 func (sq *Condition) Query() string { 348 return sq.sql.String() 349 } 350 351 func (sq *Condition) Value() []interface{} { 352 return sq.vars 353 } 354 355 func (sq *Condition) Reset() *Condition { 356 sq.hasOp = false 357 sq.sql.Reset() 358 sq.vars = nil 359 return sq 360 } 361 362 func (sq *Condition) Build(opts ...commonoption.Option) string { 363 return sq.build(option.FullSqlExist(opts...)) 364 } 365 366 func (sq *Condition) build(full bool) string { 367 var ( 368 idx int 369 ) 370 var sql = sq.Query() 371 builder := strings.Builder{} 372 for i, v := range []byte(sql) { 373 if i == 0 && full { 374 builder.WriteString(" WHERE ") 375 } 376 if v == '?' && len(sq.vars) > idx { 377 switch rv := reflect.ValueOf(sq.vars[idx]); rv.Kind() { 378 case reflect.Slice, reflect.Array: 379 if rv.Len() == 0 { 380 builder.WriteString("(NULL)") 381 AddVar(&builder, nil) 382 } else { 383 builder.WriteByte('(') 384 for j := 0; j < rv.Len(); j++ { 385 if j > 0 { 386 builder.WriteByte(',') 387 } 388 AddVar(&builder, rv.Index(j).Interface()) 389 } 390 builder.WriteByte(')') 391 } 392 default: 393 AddVar(&builder, sq.vars[idx]) 394 } 395 idx++ 396 } else { 397 builder.WriteByte(v) 398 } 399 } 400 return builder.String() 401 }