github.com/astaxie/beego@v1.12.3/orm/types.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  	"database/sql"
    20  	"reflect"
    21  	"time"
    22  )
    23  
    24  // Driver define database driver
    25  type Driver interface {
    26  	Name() string
    27  	Type() DriverType
    28  }
    29  
    30  // Fielder define field info
    31  type Fielder interface {
    32  	String() string
    33  	FieldType() int
    34  	SetRaw(interface{}) error
    35  	RawValue() interface{}
    36  }
    37  
    38  // Ormer define the orm interface
    39  type Ormer interface {
    40  	// read data to model
    41  	// for example:
    42  	//	this will find User by Id field
    43  	// 	u = &User{Id: user.Id}
    44  	// 	err = Ormer.Read(u)
    45  	//	this will find User by UserName field
    46  	// 	u = &User{UserName: "astaxie", Password: "pass"}
    47  	//	err = Ormer.Read(u, "UserName")
    48  	Read(md interface{}, cols ...string) error
    49  	// Like Read(), but with "FOR UPDATE" clause, useful in transaction.
    50  	// Some databases are not support this feature.
    51  	ReadForUpdate(md interface{}, cols ...string) error
    52  	// Try to read a row from the database, or insert one if it doesn't exist
    53  	ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error)
    54  	// insert model data to database
    55  	// for example:
    56  	//  user := new(User)
    57  	//  id, err = Ormer.Insert(user)
    58  	//  user must be a pointer and Insert will set user's pk field
    59  	Insert(interface{}) (int64, error)
    60  	// mysql:InsertOrUpdate(model) or InsertOrUpdate(model,"colu=colu+value")
    61  	// if colu type is integer : can use(+-*/), string : convert(colu,"value")
    62  	// postgres: InsertOrUpdate(model,"conflictColumnName") or InsertOrUpdate(model,"conflictColumnName","colu=colu+value")
    63  	// if colu type is integer : can use(+-*/), string : colu || "value"
    64  	InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error)
    65  	// insert some models to database
    66  	InsertMulti(bulk int, mds interface{}) (int64, error)
    67  	// update model to database.
    68  	// cols set the columns those want to update.
    69  	// find model by Id(pk) field and update columns specified by fields, if cols is null then update all columns
    70  	// for example:
    71  	// user := User{Id: 2}
    72  	//	user.Langs = append(user.Langs, "zh-CN", "en-US")
    73  	//	user.Extra.Name = "beego"
    74  	//	user.Extra.Data = "orm"
    75  	//	num, err = Ormer.Update(&user, "Langs", "Extra")
    76  	Update(md interface{}, cols ...string) (int64, error)
    77  	// delete model in database
    78  	Delete(md interface{}, cols ...string) (int64, error)
    79  	// load related models to md model.
    80  	// args are limit, offset int and order string.
    81  	//
    82  	// example:
    83  	// 	Ormer.LoadRelated(post,"Tags")
    84  	// 	for _,tag := range post.Tags{...}
    85  	//args[0] bool true useDefaultRelsDepth ; false  depth 0
    86  	//args[0] int  loadRelationDepth
    87  	//args[1] int limit default limit 1000
    88  	//args[2] int offset default offset 0
    89  	//args[3] string order  for example : "-Id"
    90  	// make sure the relation is defined in model struct tags.
    91  	LoadRelated(md interface{}, name string, args ...interface{}) (int64, error)
    92  	// create a models to models queryer
    93  	// for example:
    94  	// 	post := Post{Id: 4}
    95  	// 	m2m := Ormer.QueryM2M(&post, "Tags")
    96  	QueryM2M(md interface{}, name string) QueryM2Mer
    97  	// return a QuerySeter for table operations.
    98  	// table name can be string or struct.
    99  	// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)),
   100  	QueryTable(ptrStructOrTableName interface{}) QuerySeter
   101  	// switch to another registered database driver by given name.
   102  	Using(name string) error
   103  	// begin transaction
   104  	// for example:
   105  	// 	o := NewOrm()
   106  	// 	err := o.Begin()
   107  	// 	...
   108  	// 	err = o.Rollback()
   109  	Begin() error
   110  	// begin transaction with provided context and option
   111  	// the provided context is used until the transaction is committed or rolled back.
   112  	// if the context is canceled, the transaction will be rolled back.
   113  	// the provided TxOptions is optional and may be nil if defaults should be used.
   114  	// if a non-default isolation level is used that the driver doesn't support, an error will be returned.
   115  	// for example:
   116  	//  o := NewOrm()
   117  	// 	err := o.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead})
   118  	//  ...
   119  	//  err = o.Rollback()
   120  	BeginTx(ctx context.Context, opts *sql.TxOptions) error
   121  	// commit transaction
   122  	Commit() error
   123  	// rollback transaction
   124  	Rollback() error
   125  	// return a raw query seter for raw sql string.
   126  	// for example:
   127  	//	 ormer.Raw("UPDATE `user` SET `user_name` = ? WHERE `user_name` = ?", "slene", "testing").Exec()
   128  	//	// update user testing's name to slene
   129  	Raw(query string, args ...interface{}) RawSeter
   130  	Driver() Driver
   131  	DBStats() *sql.DBStats
   132  }
   133  
   134  // Inserter insert prepared statement
   135  type Inserter interface {
   136  	Insert(interface{}) (int64, error)
   137  	Close() error
   138  }
   139  
   140  // QuerySeter query seter
   141  type QuerySeter interface {
   142  	// add condition expression to QuerySeter.
   143  	// for example:
   144  	//	filter by UserName == 'slene'
   145  	//	qs.Filter("UserName", "slene")
   146  	//	sql : left outer join profile on t0.id1==t1.id2 where t1.age == 28
   147  	//	Filter("profile__Age", 28)
   148  	// 	 // time compare
   149  	//	qs.Filter("created", time.Now())
   150  	Filter(string, ...interface{}) QuerySeter
   151  	// add raw sql to querySeter.
   152  	// for example:
   153  	// qs.FilterRaw("user_id IN (SELECT id FROM profile WHERE age>=18)")
   154  	// //sql-> WHERE user_id IN (SELECT id FROM profile WHERE age>=18)
   155  	FilterRaw(string, string) QuerySeter
   156  	// add NOT condition to querySeter.
   157  	// have the same usage as Filter
   158  	Exclude(string, ...interface{}) QuerySeter
   159  	// set condition to QuerySeter.
   160  	// sql's where condition
   161  	//	cond := orm.NewCondition()
   162  	//	cond1 := cond.And("profile__isnull", false).AndNot("status__in", 1).Or("profile__age__gt", 2000)
   163  	//	//sql-> WHERE T0.`profile_id` IS NOT NULL AND NOT T0.`Status` IN (?) OR T1.`age` >  2000
   164  	//	num, err := qs.SetCond(cond1).Count()
   165  	SetCond(*Condition) QuerySeter
   166  	// get condition from QuerySeter.
   167  	// sql's where condition
   168  	//  cond := orm.NewCondition()
   169  	//  cond = cond.And("profile__isnull", false).AndNot("status__in", 1)
   170  	//  qs = qs.SetCond(cond)
   171  	//  cond = qs.GetCond()
   172  	//  cond := cond.Or("profile__age__gt", 2000)
   173  	//  //sql-> WHERE T0.`profile_id` IS NOT NULL AND NOT T0.`Status` IN (?) OR T1.`age` >  2000
   174  	//  num, err := qs.SetCond(cond).Count()
   175  	GetCond() *Condition
   176  	// add LIMIT value.
   177  	// args[0] means offset, e.g. LIMIT num,offset.
   178  	// if Limit <= 0 then Limit will be set to default limit ,eg 1000
   179  	// if QuerySeter doesn't call Limit, the sql's Limit will be set to default limit, eg 1000
   180  	//  for example:
   181  	//	qs.Limit(10, 2)
   182  	//	// sql-> limit 10 offset 2
   183  	Limit(limit interface{}, args ...interface{}) QuerySeter
   184  	// add OFFSET value
   185  	// same as Limit function's args[0]
   186  	Offset(offset interface{}) QuerySeter
   187  	// add GROUP BY expression
   188  	// for example:
   189  	//	qs.GroupBy("id")
   190  	GroupBy(exprs ...string) QuerySeter
   191  	// add ORDER expression.
   192  	// "column" means ASC, "-column" means DESC.
   193  	// for example:
   194  	//	qs.OrderBy("-status")
   195  	OrderBy(exprs ...string) QuerySeter
   196  	// set relation model to query together.
   197  	// it will query relation models and assign to parent model.
   198  	// for example:
   199  	//	// will load all related fields use left join .
   200  	// 	qs.RelatedSel().One(&user)
   201  	//	// will  load related field only profile
   202  	//	qs.RelatedSel("profile").One(&user)
   203  	//	user.Profile.Age = 32
   204  	RelatedSel(params ...interface{}) QuerySeter
   205  	// Set Distinct
   206  	// for example:
   207  	//  o.QueryTable("policy").Filter("Groups__Group__Users__User", user).
   208  	//    Distinct().
   209  	//    All(&permissions)
   210  	Distinct() QuerySeter
   211  	// set FOR UPDATE to query.
   212  	// for example:
   213  	//  o.QueryTable("user").Filter("uid", uid).ForUpdate().All(&users)
   214  	ForUpdate() QuerySeter
   215  	// return QuerySeter execution result number
   216  	// for example:
   217  	//	num, err = qs.Filter("profile__age__gt", 28).Count()
   218  	Count() (int64, error)
   219  	// check result empty or not after QuerySeter executed
   220  	// the same as QuerySeter.Count > 0
   221  	Exist() bool
   222  	// execute update with parameters
   223  	// for example:
   224  	//	num, err = qs.Filter("user_name", "slene").Update(Params{
   225  	//		"Nums": ColValue(Col_Minus, 50),
   226  	//	}) // user slene's Nums will minus 50
   227  	//	num, err = qs.Filter("UserName", "slene").Update(Params{
   228  	//		"user_name": "slene2"
   229  	//	}) // user slene's  name will change to slene2
   230  	Update(values Params) (int64, error)
   231  	// delete from table
   232  	//for example:
   233  	//	num ,err = qs.Filter("user_name__in", "testing1", "testing2").Delete()
   234  	// 	//delete two user  who's name is testing1 or testing2
   235  	Delete() (int64, error)
   236  	// return a insert queryer.
   237  	// it can be used in times.
   238  	// example:
   239  	// 	i,err := sq.PrepareInsert()
   240  	// 	num, err = i.Insert(&user1) // user table will add one record user1 at once
   241  	//	num, err = i.Insert(&user2) // user table will add one record user2 at once
   242  	//	err = i.Close() //don't forget call Close
   243  	PrepareInsert() (Inserter, error)
   244  	// query all data and map to containers.
   245  	// cols means the columns when querying.
   246  	// for example:
   247  	//	var users []*User
   248  	//	qs.All(&users) // users[0],users[1],users[2] ...
   249  	All(container interface{}, cols ...string) (int64, error)
   250  	// query one row data and map to containers.
   251  	// cols means the columns when querying.
   252  	// for example:
   253  	//	var user User
   254  	//	qs.One(&user) //user.UserName == "slene"
   255  	One(container interface{}, cols ...string) error
   256  	// query all data and map to []map[string]interface.
   257  	// expres means condition expression.
   258  	// it converts data to []map[column]value.
   259  	// for example:
   260  	//	var maps []Params
   261  	//	qs.Values(&maps) //maps[0]["UserName"]=="slene"
   262  	Values(results *[]Params, exprs ...string) (int64, error)
   263  	// query all data and map to [][]interface
   264  	// it converts data to [][column_index]value
   265  	// for example:
   266  	//	var list []ParamsList
   267  	//	qs.ValuesList(&list) // list[0][1] == "slene"
   268  	ValuesList(results *[]ParamsList, exprs ...string) (int64, error)
   269  	// query all data and map to []interface.
   270  	// it's designed for one column record set, auto change to []value, not [][column]value.
   271  	// for example:
   272  	//	var list ParamsList
   273  	//	qs.ValuesFlat(&list, "UserName") // list[0] == "slene"
   274  	ValuesFlat(result *ParamsList, expr string) (int64, error)
   275  	// query all rows into map[string]interface with specify key and value column name.
   276  	// keyCol = "name", valueCol = "value"
   277  	// table data
   278  	// name  | value
   279  	// total | 100
   280  	// found | 200
   281  	// to map[string]interface{}{
   282  	// 	"total": 100,
   283  	// 	"found": 200,
   284  	// }
   285  	RowsToMap(result *Params, keyCol, valueCol string) (int64, error)
   286  	// query all rows into struct with specify key and value column name.
   287  	// keyCol = "name", valueCol = "value"
   288  	// table data
   289  	// name  | value
   290  	// total | 100
   291  	// found | 200
   292  	// to struct {
   293  	// 	Total int
   294  	// 	Found int
   295  	// }
   296  	RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error)
   297  }
   298  
   299  // QueryM2Mer model to model query struct
   300  // all operations are on the m2m table only, will not affect the origin model table
   301  type QueryM2Mer interface {
   302  	// add models to origin models when creating queryM2M.
   303  	// example:
   304  	// 	m2m := orm.QueryM2M(post,"Tag")
   305  	// 	m2m.Add(&Tag1{},&Tag2{})
   306  	//  	for _,tag := range post.Tags{}{ ... }
   307  	// param could also be any of the follow
   308  	// 	[]*Tag{{Id:3,Name: "TestTag1"}, {Id:4,Name: "TestTag2"}}
   309  	//	&Tag{Id:5,Name: "TestTag3"}
   310  	//	[]interface{}{&Tag{Id:6,Name: "TestTag4"}}
   311  	// insert one or more rows to m2m table
   312  	// make sure the relation is defined in post model struct tag.
   313  	Add(...interface{}) (int64, error)
   314  	// remove models following the origin model relationship
   315  	// only delete rows from m2m table
   316  	// for example:
   317  	//tag3 := &Tag{Id:5,Name: "TestTag3"}
   318  	//num, err = m2m.Remove(tag3)
   319  	Remove(...interface{}) (int64, error)
   320  	// check model is existed in relationship of origin model
   321  	Exist(interface{}) bool
   322  	// clean all models in related of origin model
   323  	Clear() (int64, error)
   324  	// count all related models of origin model
   325  	Count() (int64, error)
   326  }
   327  
   328  // RawPreparer raw query statement
   329  type RawPreparer interface {
   330  	Exec(...interface{}) (sql.Result, error)
   331  	Close() error
   332  }
   333  
   334  // RawSeter raw query seter
   335  // create From Ormer.Raw
   336  // for example:
   337  //  sql := fmt.Sprintf("SELECT %sid%s,%sname%s FROM %suser%s WHERE id = ?",Q,Q,Q,Q,Q,Q)
   338  //  rs := Ormer.Raw(sql, 1)
   339  type RawSeter interface {
   340  	//execute sql and get result
   341  	Exec() (sql.Result, error)
   342  	//query data and map to container
   343  	//for example:
   344  	//	var name string
   345  	//	var id int
   346  	//	rs.QueryRow(&id,&name) // id==2 name=="slene"
   347  	QueryRow(containers ...interface{}) error
   348  
   349  	// query data rows and map to container
   350  	//	var ids []int
   351  	//	var names []int
   352  	//	query = fmt.Sprintf("SELECT 'id','name' FROM %suser%s", Q, Q)
   353  	//	num, err = dORM.Raw(query).QueryRows(&ids,&names) // ids=>{1,2},names=>{"nobody","slene"}
   354  	QueryRows(containers ...interface{}) (int64, error)
   355  	SetArgs(...interface{}) RawSeter
   356  	// query data to []map[string]interface
   357  	// see QuerySeter's Values
   358  	Values(container *[]Params, cols ...string) (int64, error)
   359  	// query data to [][]interface
   360  	// see QuerySeter's ValuesList
   361  	ValuesList(container *[]ParamsList, cols ...string) (int64, error)
   362  	// query data to []interface
   363  	// see QuerySeter's ValuesFlat
   364  	ValuesFlat(container *ParamsList, cols ...string) (int64, error)
   365  	// query all rows into map[string]interface with specify key and value column name.
   366  	// keyCol = "name", valueCol = "value"
   367  	// table data
   368  	// name  | value
   369  	// total | 100
   370  	// found | 200
   371  	// to map[string]interface{}{
   372  	// 	"total": 100,
   373  	// 	"found": 200,
   374  	// }
   375  	RowsToMap(result *Params, keyCol, valueCol string) (int64, error)
   376  	// query all rows into struct with specify key and value column name.
   377  	// keyCol = "name", valueCol = "value"
   378  	// table data
   379  	// name  | value
   380  	// total | 100
   381  	// found | 200
   382  	// to struct {
   383  	// 	Total int
   384  	// 	Found int
   385  	// }
   386  	RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error)
   387  
   388  	// return prepared raw statement for used in times.
   389  	// for example:
   390  	// 	pre, err := dORM.Raw("INSERT INTO tag (name) VALUES (?)").Prepare()
   391  	// 	r, err := pre.Exec("name1") // INSERT INTO tag (name) VALUES (`name1`)
   392  	Prepare() (RawPreparer, error)
   393  }
   394  
   395  // stmtQuerier statement querier
   396  type stmtQuerier interface {
   397  	Close() error
   398  	Exec(args ...interface{}) (sql.Result, error)
   399  	//ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error)
   400  	Query(args ...interface{}) (*sql.Rows, error)
   401  	//QueryContext(args ...interface{}) (*sql.Rows, error)
   402  	QueryRow(args ...interface{}) *sql.Row
   403  	//QueryRowContext(ctx context.Context, args ...interface{}) *sql.Row
   404  }
   405  
   406  // db querier
   407  type dbQuerier interface {
   408  	Prepare(query string) (*sql.Stmt, error)
   409  	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
   410  	Exec(query string, args ...interface{}) (sql.Result, error)
   411  	ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
   412  	Query(query string, args ...interface{}) (*sql.Rows, error)
   413  	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
   414  	QueryRow(query string, args ...interface{}) *sql.Row
   415  	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
   416  }
   417  
   418  // type DB interface {
   419  // 	Begin() (*sql.Tx, error)
   420  // 	Prepare(query string) (stmtQuerier, error)
   421  // 	Exec(query string, args ...interface{}) (sql.Result, error)
   422  // 	Query(query string, args ...interface{}) (*sql.Rows, error)
   423  // 	QueryRow(query string, args ...interface{}) *sql.Row
   424  // }
   425  
   426  // transaction beginner
   427  type txer interface {
   428  	Begin() (*sql.Tx, error)
   429  	BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
   430  }
   431  
   432  // transaction ending
   433  type txEnder interface {
   434  	Commit() error
   435  	Rollback() error
   436  }
   437  
   438  // base database struct
   439  type dbBaser interface {
   440  	Read(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string, bool) error
   441  	Insert(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
   442  	InsertOrUpdate(dbQuerier, *modelInfo, reflect.Value, *alias, ...string) (int64, error)
   443  	InsertMulti(dbQuerier, *modelInfo, reflect.Value, int, *time.Location) (int64, error)
   444  	InsertValue(dbQuerier, *modelInfo, bool, []string, []interface{}) (int64, error)
   445  	InsertStmt(stmtQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
   446  	Update(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) (int64, error)
   447  	Delete(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) (int64, error)
   448  	ReadBatch(dbQuerier, *querySet, *modelInfo, *Condition, interface{}, *time.Location, []string) (int64, error)
   449  	SupportUpdateJoin() bool
   450  	UpdateBatch(dbQuerier, *querySet, *modelInfo, *Condition, Params, *time.Location) (int64, error)
   451  	DeleteBatch(dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error)
   452  	Count(dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error)
   453  	OperatorSQL(string) string
   454  	GenerateOperatorSQL(*modelInfo, *fieldInfo, string, []interface{}, *time.Location) (string, []interface{})
   455  	GenerateOperatorLeftCol(*fieldInfo, string, *string)
   456  	PrepareInsert(dbQuerier, *modelInfo) (stmtQuerier, string, error)
   457  	ReadValues(dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}, *time.Location) (int64, error)
   458  	RowsTo(dbQuerier, *querySet, *modelInfo, *Condition, interface{}, string, string, *time.Location) (int64, error)
   459  	MaxLimit() uint64
   460  	TableQuote() string
   461  	ReplaceMarks(*string)
   462  	HasReturningID(*modelInfo, *string) bool
   463  	TimeFromDB(*time.Time, *time.Location)
   464  	TimeToDB(*time.Time, *time.Location)
   465  	DbTypes() map[string]string
   466  	GetTables(dbQuerier) (map[string]bool, error)
   467  	GetColumns(dbQuerier, string) (map[string][3]string, error)
   468  	ShowTablesQuery() string
   469  	ShowColumnsQuery(string) string
   470  	IndexExists(dbQuerier, string, string) bool
   471  	collectFieldValue(*modelInfo, *fieldInfo, reflect.Value, bool, *time.Location) (interface{}, error)
   472  	setval(dbQuerier, *modelInfo, []string) error
   473  }