github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/databases/orm/orm_queryset.go (about) 1 // The original package is migrated from beego and modified, you can find orignal from following link: 2 // "github.com/beego/beego/" 3 // 4 // Copyright 2023 IAC. All Rights Reserved. 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 package orm 19 20 import ( 21 "context" 22 "fmt" 23 24 "github.com/mdaxf/iac/databases/orm/clauses" 25 "github.com/mdaxf/iac/databases/orm/hints" 26 ) 27 28 type colValue struct { 29 value int64 30 opt operator 31 } 32 33 type operator int 34 35 // define Col operations 36 const ( 37 ColAdd operator = iota 38 ColMinus 39 ColMultiply 40 ColExcept 41 ColBitAnd 42 ColBitRShift 43 ColBitLShift 44 ColBitXOR 45 ColBitOr 46 ) 47 48 // ColValue do the field raw changes. e.g Nums = Nums + 10. usage: 49 // 50 // Params{ 51 // "Nums": ColValue(Col_Add, 10), 52 // } 53 func ColValue(opt operator, value interface{}) interface{} { 54 switch opt { 55 case ColAdd, ColMinus, ColMultiply, ColExcept, ColBitAnd, ColBitRShift, 56 ColBitLShift, ColBitXOR, ColBitOr: 57 default: 58 panic(fmt.Errorf("orm.ColValue wrong operator")) 59 } 60 v, err := StrTo(ToStr(value)).Int64() 61 if err != nil { 62 panic(fmt.Errorf("orm.ColValue doesn't support non string/numeric type, %s", err)) 63 } 64 var val colValue 65 val.value = v 66 val.opt = opt 67 return val 68 } 69 70 // real query struct 71 type querySet struct { 72 mi *modelInfo 73 cond *Condition 74 related []string 75 relDepth int 76 limit int64 77 offset int64 78 groups []string 79 orders []*clauses.Order 80 distinct bool 81 forUpdate bool 82 useIndex int 83 indexes []string 84 orm *ormBase 85 aggregate string 86 } 87 88 var _ QuerySeter = new(querySet) 89 90 // add condition expression to QuerySeter. 91 func (o querySet) Filter(expr string, args ...interface{}) QuerySeter { 92 if o.cond == nil { 93 o.cond = NewCondition() 94 } 95 o.cond = o.cond.And(expr, args...) 96 return &o 97 } 98 99 // add raw sql to querySeter. 100 func (o querySet) FilterRaw(expr string, sql string) QuerySeter { 101 if o.cond == nil { 102 o.cond = NewCondition() 103 } 104 o.cond = o.cond.Raw(expr, sql) 105 return &o 106 } 107 108 // add NOT condition to querySeter. 109 func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { 110 if o.cond == nil { 111 o.cond = NewCondition() 112 } 113 o.cond = o.cond.AndNot(expr, args...) 114 return &o 115 } 116 117 // set offset number 118 func (o *querySet) setOffset(num interface{}) { 119 o.offset = ToInt64(num) 120 } 121 122 // add LIMIT value. 123 // args[0] means offset, e.g. LIMIT num,offset. 124 func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter { 125 o.limit = ToInt64(limit) 126 if len(args) > 0 { 127 o.setOffset(args[0]) 128 } 129 return &o 130 } 131 132 // add OFFSET value 133 func (o querySet) Offset(offset interface{}) QuerySeter { 134 o.setOffset(offset) 135 return &o 136 } 137 138 // add GROUP expression 139 func (o querySet) GroupBy(exprs ...string) QuerySeter { 140 o.groups = exprs 141 return &o 142 } 143 144 // add ORDER expression. 145 // "column" means ASC, "-column" means DESC. 146 func (o querySet) OrderBy(expressions ...string) QuerySeter { 147 if len(expressions) <= 0 { 148 return &o 149 } 150 o.orders = clauses.ParseOrder(expressions...) 151 return &o 152 } 153 154 // add ORDER expression. 155 func (o querySet) OrderClauses(orders ...*clauses.Order) QuerySeter { 156 if len(orders) <= 0 { 157 return &o 158 } 159 o.orders = orders 160 return &o 161 } 162 163 // add DISTINCT to SELECT 164 func (o querySet) Distinct() QuerySeter { 165 o.distinct = true 166 return &o 167 } 168 169 // add FOR UPDATE to SELECT 170 func (o querySet) ForUpdate() QuerySeter { 171 o.forUpdate = true 172 return &o 173 } 174 175 // ForceIndex force index for query 176 func (o querySet) ForceIndex(indexes ...string) QuerySeter { 177 o.useIndex = hints.KeyForceIndex 178 o.indexes = indexes 179 return &o 180 } 181 182 // UseIndex use index for query 183 func (o querySet) UseIndex(indexes ...string) QuerySeter { 184 o.useIndex = hints.KeyUseIndex 185 o.indexes = indexes 186 return &o 187 } 188 189 // IgnoreIndex ignore index for query 190 func (o querySet) IgnoreIndex(indexes ...string) QuerySeter { 191 o.useIndex = hints.KeyIgnoreIndex 192 o.indexes = indexes 193 return &o 194 } 195 196 // set relation model to query together. 197 // it will query relation models and assign to parent model. 198 func (o querySet) RelatedSel(params ...interface{}) QuerySeter { 199 if len(params) == 0 { 200 o.relDepth = DefaultRelsDepth 201 } else { 202 for _, p := range params { 203 switch val := p.(type) { 204 case string: 205 o.related = append(o.related, val) 206 case int: 207 o.relDepth = val 208 default: 209 panic(fmt.Errorf("<QuerySeter.RelatedSel> wrong param kind: %v", val)) 210 } 211 } 212 } 213 return &o 214 } 215 216 // set condition to QuerySeter. 217 func (o querySet) SetCond(cond *Condition) QuerySeter { 218 o.cond = cond 219 return &o 220 } 221 222 // get condition from QuerySeter 223 func (o querySet) GetCond() *Condition { 224 return o.cond 225 } 226 227 // return QuerySeter execution result number 228 func (o *querySet) Count() (int64, error) { 229 return o.CountWithCtx(context.Background()) 230 } 231 232 func (o *querySet) CountWithCtx(ctx context.Context) (int64, error) { 233 return o.orm.alias.DbBaser.Count(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) 234 } 235 236 // check result empty or not after QuerySeter executed 237 func (o *querySet) Exist() bool { 238 return o.ExistWithCtx(context.Background()) 239 } 240 241 func (o *querySet) ExistWithCtx(ctx context.Context) bool { 242 cnt, _ := o.orm.alias.DbBaser.Count(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) 243 return cnt > 0 244 } 245 246 // execute update with parameters 247 func (o *querySet) Update(values Params) (int64, error) { 248 return o.UpdateWithCtx(context.Background(), values) 249 } 250 251 func (o *querySet) UpdateWithCtx(ctx context.Context, values Params) (int64, error) { 252 return o.orm.alias.DbBaser.UpdateBatch(ctx, o.orm.db, o, o.mi, o.cond, values, o.orm.alias.TZ) 253 } 254 255 // execute delete 256 func (o *querySet) Delete() (int64, error) { 257 return o.DeleteWithCtx(context.Background()) 258 } 259 260 func (o *querySet) DeleteWithCtx(ctx context.Context) (int64, error) { 261 return o.orm.alias.DbBaser.DeleteBatch(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) 262 } 263 264 // return an insert queryer. 265 // it can be used in times. 266 // example: 267 // 268 // i,err := sq.PrepareInsert() 269 // i.Add(&user1{},&user2{}) 270 func (o *querySet) PrepareInsert() (Inserter, error) { 271 return o.PrepareInsertWithCtx(context.Background()) 272 } 273 274 func (o *querySet) PrepareInsertWithCtx(ctx context.Context) (Inserter, error) { 275 return newInsertSet(ctx, o.orm, o.mi) 276 } 277 278 // query all data and map to containers. 279 // cols means the columns when querying. 280 func (o *querySet) All(container interface{}, cols ...string) (int64, error) { 281 return o.AllWithCtx(context.Background(), container, cols...) 282 } 283 284 func (o *querySet) AllWithCtx(ctx context.Context, container interface{}, cols ...string) (int64, error) { 285 return o.orm.alias.DbBaser.ReadBatch(ctx, o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols) 286 } 287 288 // query one row data and map to containers. 289 // cols means the columns when querying. 290 func (o *querySet) One(container interface{}, cols ...string) error { 291 return o.OneWithCtx(context.Background(), container, cols...) 292 } 293 294 func (o *querySet) OneWithCtx(ctx context.Context, container interface{}, cols ...string) error { 295 o.limit = 1 296 num, err := o.orm.alias.DbBaser.ReadBatch(ctx, o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols) 297 if err != nil { 298 return err 299 } 300 if num == 0 { 301 return ErrNoRows 302 } 303 304 if num > 1 { 305 return ErrMultiRows 306 } 307 return nil 308 } 309 310 // query all data and map to []map[string]interface. 311 // expres means condition expression. 312 // it converts data to []map[column]value. 313 func (o *querySet) Values(results *[]Params, exprs ...string) (int64, error) { 314 return o.ValuesWithCtx(context.Background(), results, exprs...) 315 } 316 317 func (o *querySet) ValuesWithCtx(ctx context.Context, results *[]Params, exprs ...string) (int64, error) { 318 return o.orm.alias.DbBaser.ReadValues(ctx, o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ) 319 } 320 321 // query all data and map to [][]interface 322 // it converts data to [][column_index]value 323 func (o *querySet) ValuesList(results *[]ParamsList, exprs ...string) (int64, error) { 324 return o.ValuesListWithCtx(context.Background(), results, exprs...) 325 } 326 327 func (o *querySet) ValuesListWithCtx(ctx context.Context, results *[]ParamsList, exprs ...string) (int64, error) { 328 return o.orm.alias.DbBaser.ReadValues(ctx, o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ) 329 } 330 331 // query all data and map to []interface. 332 // it's designed for one row record set, auto change to []value, not [][column]value. 333 func (o *querySet) ValuesFlat(result *ParamsList, expr string) (int64, error) { 334 return o.ValuesFlatWithCtx(context.Background(), result, expr) 335 } 336 337 func (o *querySet) ValuesFlatWithCtx(ctx context.Context, result *ParamsList, expr string) (int64, error) { 338 return o.orm.alias.DbBaser.ReadValues(ctx, o.orm.db, o, o.mi, o.cond, []string{expr}, result, o.orm.alias.TZ) 339 } 340 341 // query all rows into map[string]interface with specify key and value column name. 342 // keyCol = "name", valueCol = "value" 343 // table data 344 // name | value 345 // total | 100 346 // found | 200 347 // 348 // to map[string]interface{}{ 349 // "total": 100, 350 // "found": 200, 351 // } 352 func (o *querySet) RowsToMap(result *Params, keyCol, valueCol string) (int64, error) { 353 panic(ErrNotImplement) 354 } 355 356 // query all rows into struct with specify key and value column name. 357 // keyCol = "name", valueCol = "value" 358 // table data 359 // name | value 360 // total | 100 361 // found | 200 362 // 363 // to struct { 364 // Total int 365 // Found int 366 // } 367 func (o *querySet) RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error) { 368 panic(ErrNotImplement) 369 } 370 371 // create new QuerySeter. 372 func newQuerySet(orm *ormBase, mi *modelInfo) QuerySeter { 373 o := new(querySet) 374 o.mi = mi 375 o.orm = orm 376 return o 377 } 378 379 // aggregate func 380 func (o querySet) Aggregate(s string) QuerySeter { 381 o.aggregate = s 382 return &o 383 }