github.com/astaxie/beego@v1.12.3/orm/orm_queryset.go (about)

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