github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/databases/orm/types.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  	"database/sql"
    23  	"reflect"
    24  	"time"
    25  
    26  	"github.com/mdaxf/iac/databases/orm/clauses"
    27  	"github.com/mdaxf/iac/framework/utils"
    28  )
    29  
    30  // TableNaming is usually used by model
    31  // when you custom your table name, please implement this interfaces
    32  // for example:
    33  //
    34  //	type User struct {
    35  //	  ...
    36  //	}
    37  //
    38  //	func (u *User) TableName() string {
    39  //	   return "USER_TABLE"
    40  //	}
    41  type TableNameI interface {
    42  	TableName() string
    43  }
    44  
    45  // TableEngineI is usually used by model
    46  // when you want to use specific engine, like myisam, you can implement this interface
    47  // for example:
    48  //
    49  //	type User struct {
    50  //	  ...
    51  //	}
    52  //
    53  //	func (u *User) TableEngine() string {
    54  //	   return "myisam"
    55  //	}
    56  type TableEngineI interface {
    57  	TableEngine() string
    58  }
    59  
    60  // TableIndexI is usually used by model
    61  // when you want to create indexes, you can implement this interface
    62  // for example:
    63  //
    64  //	type User struct {
    65  //	  ...
    66  //	}
    67  //
    68  //	func (u *User) TableIndex() [][]string {
    69  //	   return [][]string{{"Name"}}
    70  //	}
    71  type TableIndexI interface {
    72  	TableIndex() [][]string
    73  }
    74  
    75  // TableUniqueI is usually used by model
    76  // when you want to create unique indexes, you can implement this interface
    77  // for example:
    78  //
    79  //	type User struct {
    80  //	  ...
    81  //	}
    82  //
    83  //	func (u *User) TableUnique() [][]string {
    84  //	   return [][]string{{"Email"}}
    85  //	}
    86  type TableUniqueI interface {
    87  	TableUnique() [][]string
    88  }
    89  
    90  // IsApplicableTableForDB if return false, we won't create table to this db
    91  type IsApplicableTableForDB interface {
    92  	IsApplicableTableForDB(db string) bool
    93  }
    94  
    95  // Driver define database driver
    96  type Driver interface {
    97  	Name() string
    98  	Type() DriverType
    99  }
   100  
   101  // Fielder define field info
   102  type Fielder interface {
   103  	String() string
   104  	FieldType() int
   105  	SetRaw(interface{}) error
   106  	RawValue() interface{}
   107  }
   108  
   109  type TxBeginner interface {
   110  	// self control transaction
   111  	Begin() (TxOrmer, error)
   112  	BeginWithCtx(ctx context.Context) (TxOrmer, error)
   113  	BeginWithOpts(opts *sql.TxOptions) (TxOrmer, error)
   114  	BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxOrmer, error)
   115  
   116  	// closure control transaction
   117  	DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error
   118  	DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error
   119  	DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error
   120  	DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error
   121  }
   122  
   123  type TxCommitter interface {
   124  	txEnder
   125  }
   126  
   127  // transaction beginner
   128  type txer interface {
   129  	Begin() (*sql.Tx, error)
   130  	BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
   131  }
   132  
   133  // transaction ending
   134  type txEnder interface {
   135  	Commit() error
   136  	Rollback() error
   137  
   138  	// RollbackUnlessCommit if the transaction has been committed, do nothing, or transaction will be rollback
   139  	// For example:
   140  	// ```go
   141  	//    txOrm := orm.Begin()
   142  	//    defer txOrm.RollbackUnlessCommit()
   143  	//    err := txOrm.Insert() // do something
   144  	//    if err != nil {
   145  	//       return err
   146  	//    }
   147  	//    txOrm.Commit()
   148  	// ```
   149  	RollbackUnlessCommit() error
   150  }
   151  
   152  // Data Manipulation Language
   153  type DML interface {
   154  	// insert model data to database
   155  	// for example:
   156  	//  user := new(User)
   157  	//  id, err = Ormer.Insert(user)
   158  	//  user must be a pointer and Insert will set user's pk field
   159  	Insert(md interface{}) (int64, error)
   160  	InsertWithCtx(ctx context.Context, md interface{}) (int64, error)
   161  	// mysql:InsertOrUpdate(model) or InsertOrUpdate(model,"colu=colu+value")
   162  	// if colu type is integer : can use(+-*/), string : convert(colu,"value")
   163  	// postgres: InsertOrUpdate(model,"conflictColumnName") or InsertOrUpdate(model,"conflictColumnName","colu=colu+value")
   164  	// if colu type is integer : can use(+-*/), string : colu || "value"
   165  	InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error)
   166  	InsertOrUpdateWithCtx(ctx context.Context, md interface{}, colConflitAndArgs ...string) (int64, error)
   167  	// insert some models to database
   168  	InsertMulti(bulk int, mds interface{}) (int64, error)
   169  	InsertMultiWithCtx(ctx context.Context, bulk int, mds interface{}) (int64, error)
   170  	// update model to database.
   171  	// cols set the columns those want to update.
   172  	// find model by Id(pk) field and update columns specified by fields, if cols is null then update all columns
   173  	// for example:
   174  	// user := User{Id: 2}
   175  	//	user.Langs = append(user.Langs, "zh-CN", "en-US")
   176  	//	user.Extra.Name = "beego"
   177  	//	user.Extra.Data = "orm"
   178  	//	num, err = Ormer.Update(&user, "Langs", "Extra")
   179  	Update(md interface{}, cols ...string) (int64, error)
   180  	UpdateWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)
   181  	// delete model in database
   182  	Delete(md interface{}, cols ...string) (int64, error)
   183  	DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)
   184  
   185  	// return a raw query seter for raw sql string.
   186  	// for example:
   187  	//	 ormer.Raw("UPDATE `user` SET `user_name` = ? WHERE `user_name` = ?", "slene", "testing").Exec()
   188  	//	// update user testing's name to slene
   189  	Raw(query string, args ...interface{}) RawSeter
   190  	RawWithCtx(ctx context.Context, query string, args ...interface{}) RawSeter
   191  }
   192  
   193  // Data Query Language
   194  type DQL interface {
   195  	// read data to model
   196  	// for example:
   197  	//	this will find User by Id field
   198  	// 	u = &User{Id: user.Id}
   199  	// 	err = Ormer.Read(u)
   200  	//	this will find User by UserName field
   201  	// 	u = &User{UserName: "astaxie", Password: "pass"}
   202  	//	err = Ormer.Read(u, "UserName")
   203  	Read(md interface{}, cols ...string) error
   204  	ReadWithCtx(ctx context.Context, md interface{}, cols ...string) error
   205  
   206  	// Like Read(), but with "FOR UPDATE" clause, useful in transaction.
   207  	// Some databases are not support this feature.
   208  	ReadForUpdate(md interface{}, cols ...string) error
   209  	ReadForUpdateWithCtx(ctx context.Context, md interface{}, cols ...string) error
   210  
   211  	// Try to read a row from the database, or insert one if it doesn't exist
   212  	ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error)
   213  	ReadOrCreateWithCtx(ctx context.Context, md interface{}, col1 string, cols ...string) (bool, int64, error)
   214  
   215  	// load related models to md model.
   216  	// args are limit, offset int and order string.
   217  	//
   218  	// example:
   219  	// 	Ormer.LoadRelated(post,"Tags")
   220  	// 	for _,tag := range post.Tags{...}
   221  	// hints.DefaultRelDepth useDefaultRelsDepth ; or depth 0
   222  	// hints.RelDepth loadRelationDepth
   223  	// hints.Limit limit default limit 1000
   224  	// hints.Offset int offset default offset 0
   225  	// hints.OrderBy string order  for example : "-Id"
   226  	// make sure the relation is defined in model struct tags.
   227  	LoadRelated(md interface{}, name string, args ...utils.KV) (int64, error)
   228  	LoadRelatedWithCtx(ctx context.Context, md interface{}, name string, args ...utils.KV) (int64, error)
   229  
   230  	// create a models to models queryer
   231  	// for example:
   232  	// 	post := Post{Id: 4}
   233  	// 	m2m := Ormer.QueryM2M(&post, "Tags")
   234  	QueryM2M(md interface{}, name string) QueryM2Mer
   235  	// NOTE: this method is deprecated, context parameter will not take effect.
   236  	// Use context.Context directly on methods with `WithCtx` suffix such as InsertWithCtx/UpdateWithCtx
   237  	QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer
   238  
   239  	// return a QuerySeter for table operations.
   240  	// table name can be string or struct.
   241  	// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)),
   242  	QueryTable(ptrStructOrTableName interface{}) QuerySeter
   243  	// NOTE: this method is deprecated, context parameter will not take effect.
   244  	// Use context.Context directly on methods with `WithCtx` suffix such as InsertWithCtx/UpdateWithCtx
   245  	QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter
   246  
   247  	DBStats() *sql.DBStats
   248  }
   249  
   250  type DriverGetter interface {
   251  	Driver() Driver
   252  }
   253  
   254  type ormer interface {
   255  	DQL
   256  	DML
   257  	DriverGetter
   258  }
   259  
   260  // QueryExecutor wrapping for ormer
   261  type QueryExecutor interface {
   262  	ormer
   263  }
   264  
   265  type Ormer interface {
   266  	QueryExecutor
   267  	TxBeginner
   268  }
   269  
   270  type TxOrmer interface {
   271  	QueryExecutor
   272  	TxCommitter
   273  }
   274  
   275  // Inserter insert prepared statement
   276  type Inserter interface {
   277  	Insert(interface{}) (int64, error)
   278  	InsertWithCtx(context.Context, interface{}) (int64, error)
   279  	Close() error
   280  }
   281  
   282  // QuerySeter query seter
   283  type QuerySeter interface {
   284  	// add condition expression to QuerySeter.
   285  	// for example:
   286  	//	filter by UserName == 'slene'
   287  	//	qs.Filter("UserName", "slene")
   288  	//	sql : left outer join profile on t0.id1==t1.id2 where t1.age == 28
   289  	//	Filter("profile__Age", 28)
   290  	// 	 // time compare
   291  	//	qs.Filter("created", time.Now())
   292  	Filter(string, ...interface{}) QuerySeter
   293  	// add raw sql to querySeter.
   294  	// for example:
   295  	// qs.FilterRaw("user_id IN (SELECT id FROM profile WHERE age>=18)")
   296  	// //sql-> WHERE user_id IN (SELECT id FROM profile WHERE age>=18)
   297  	FilterRaw(string, string) QuerySeter
   298  	// add NOT condition to querySeter.
   299  	// have the same usage as Filter
   300  	Exclude(string, ...interface{}) QuerySeter
   301  	// set condition to QuerySeter.
   302  	// sql's where condition
   303  	//	cond := orm.NewCondition()
   304  	//	cond1 := cond.And("profile__isnull", false).AndNot("status__in", 1).Or("profile__age__gt", 2000)
   305  	//	//sql-> WHERE T0.`profile_id` IS NOT NULL AND NOT T0.`Status` IN (?) OR T1.`age` >  2000
   306  	//	num, err := qs.SetCond(cond1).Count()
   307  	SetCond(*Condition) QuerySeter
   308  	// get condition from QuerySeter.
   309  	// sql's where condition
   310  	//  cond := orm.NewCondition()
   311  	//  cond = cond.And("profile__isnull", false).AndNot("status__in", 1)
   312  	//  qs = qs.SetCond(cond)
   313  	//  cond = qs.GetCond()
   314  	//  cond := cond.Or("profile__age__gt", 2000)
   315  	//  //sql-> WHERE T0.`profile_id` IS NOT NULL AND NOT T0.`Status` IN (?) OR T1.`age` >  2000
   316  	//  num, err := qs.SetCond(cond).Count()
   317  	GetCond() *Condition
   318  	// add LIMIT value.
   319  	// args[0] means offset, e.g. LIMIT num,offset.
   320  	// if Limit <= 0 then Limit will be set to default limit ,eg 1000
   321  	// if QuerySeter doesn't call Limit, the sql's Limit will be set to default limit, eg 1000
   322  	//  for example:
   323  	//	qs.Limit(10, 2)
   324  	//	// sql-> limit 10 offset 2
   325  	Limit(limit interface{}, args ...interface{}) QuerySeter
   326  	// add OFFSET value
   327  	// same as Limit function's args[0]
   328  	Offset(offset interface{}) QuerySeter
   329  	// add GROUP BY expression
   330  	// for example:
   331  	//	qs.GroupBy("id")
   332  	GroupBy(exprs ...string) QuerySeter
   333  	// add ORDER expression.
   334  	// "column" means ASC, "-column" means DESC.
   335  	// for example:
   336  	//	qs.OrderBy("-status")
   337  	OrderBy(exprs ...string) QuerySeter
   338  	// add ORDER expression by order clauses
   339  	// for example:
   340  	//	OrderClauses(
   341  	//		order_clause.Clause(
   342  	//			order.Column("Id"),
   343  	//			order.SortAscending(),
   344  	//		),
   345  	//		order_clause.Clause(
   346  	//			order.Column("status"),
   347  	//			order.SortDescending(),
   348  	//		),
   349  	//	)
   350  	//	OrderClauses(order_clause.Clause(
   351  	//		order_clause.Column(`user__status`),
   352  	//		order_clause.SortDescending(),//default None
   353  	//	))
   354  	//	OrderClauses(order_clause.Clause(
   355  	//		order_clause.Column(`random()`),
   356  	//		order_clause.SortNone(),//default None
   357  	//		order_clause.Raw(),//default false.if true, do not check field is valid or not
   358  	//	))
   359  	OrderClauses(orders ...*clauses.Order) QuerySeter
   360  	// add FORCE INDEX expression.
   361  	// for example:
   362  	//	qs.ForceIndex(`idx_name1`,`idx_name2`)
   363  	// ForceIndex, UseIndex , IgnoreIndex are mutually exclusive
   364  	ForceIndex(indexes ...string) QuerySeter
   365  	// add USE INDEX expression.
   366  	// for example:
   367  	//	qs.UseIndex(`idx_name1`,`idx_name2`)
   368  	// ForceIndex, UseIndex , IgnoreIndex are mutually exclusive
   369  	UseIndex(indexes ...string) QuerySeter
   370  	// add IGNORE INDEX expression.
   371  	// for example:
   372  	//	qs.IgnoreIndex(`idx_name1`,`idx_name2`)
   373  	// ForceIndex, UseIndex , IgnoreIndex are mutually exclusive
   374  	IgnoreIndex(indexes ...string) QuerySeter
   375  	// set relation model to query together.
   376  	// it will query relation models and assign to parent model.
   377  	// for example:
   378  	//	// will load all related fields use left join .
   379  	// 	qs.RelatedSel().One(&user)
   380  	//	// will  load related field only profile
   381  	//	qs.RelatedSel("profile").One(&user)
   382  	//	user.Profile.Age = 32
   383  	RelatedSel(params ...interface{}) QuerySeter
   384  	// Set Distinct
   385  	// for example:
   386  	//  o.QueryTable("policy").Filter("Groups__Group__Users__User", user).
   387  	//    Distinct().
   388  	//    All(&permissions)
   389  	Distinct() QuerySeter
   390  	// set FOR UPDATE to query.
   391  	// for example:
   392  	//  o.QueryTable("user").Filter("uid", uid).ForUpdate().All(&users)
   393  	ForUpdate() QuerySeter
   394  	// return QuerySeter execution result number
   395  	// for example:
   396  	//	num, err = qs.Filter("profile__age__gt", 28).Count()
   397  	Count() (int64, error)
   398  	CountWithCtx(context.Context) (int64, error)
   399  	// check result empty or not after QuerySeter executed
   400  	// the same as QuerySeter.Count > 0
   401  	Exist() bool
   402  	ExistWithCtx(context.Context) bool
   403  	// execute update with parameters
   404  	// for example:
   405  	//	num, err = qs.Filter("user_name", "slene").Update(Params{
   406  	//		"Nums": ColValue(Col_Minus, 50),
   407  	//	}) // user slene's Nums will minus 50
   408  	//	num, err = qs.Filter("UserName", "slene").Update(Params{
   409  	//		"user_name": "slene2"
   410  	//	}) // user slene's  name will change to slene2
   411  	Update(values Params) (int64, error)
   412  	UpdateWithCtx(ctx context.Context, values Params) (int64, error)
   413  	// delete from table
   414  	// for example:
   415  	//	num ,err = qs.Filter("user_name__in", "testing1", "testing2").Delete()
   416  	// 	//delete two user  who's name is testing1 or testing2
   417  	Delete() (int64, error)
   418  	DeleteWithCtx(context.Context) (int64, error)
   419  	// return an insert queryer.
   420  	// it can be used in times.
   421  	// example:
   422  	// 	i,err := sq.PrepareInsert()
   423  	// 	num, err = i.Insert(&user1) // user table will add one record user1 at once
   424  	//	num, err = i.Insert(&user2) // user table will add one record user2 at once
   425  	//	err = i.Close() //don't forget call Close
   426  	PrepareInsert() (Inserter, error)
   427  	PrepareInsertWithCtx(context.Context) (Inserter, error)
   428  	// query all data and map to containers.
   429  	// cols means the columns when querying.
   430  	// for example:
   431  	//	var users []*User
   432  	//	qs.All(&users) // users[0],users[1],users[2] ...
   433  	All(container interface{}, cols ...string) (int64, error)
   434  	AllWithCtx(ctx context.Context, container interface{}, cols ...string) (int64, error)
   435  	// query one row data and map to containers.
   436  	// cols means the columns when querying.
   437  	// for example:
   438  	//	var user User
   439  	//	qs.One(&user) //user.UserName == "slene"
   440  	One(container interface{}, cols ...string) error
   441  	OneWithCtx(ctx context.Context, container interface{}, cols ...string) error
   442  	// query all data and map to []map[string]interface.
   443  	// expres means condition expression.
   444  	// it converts data to []map[column]value.
   445  	// for example:
   446  	//	var maps []Params
   447  	//	qs.Values(&maps) //maps[0]["UserName"]=="slene"
   448  	Values(results *[]Params, exprs ...string) (int64, error)
   449  	ValuesWithCtx(ctx context.Context, results *[]Params, exprs ...string) (int64, error)
   450  	// query all data and map to [][]interface
   451  	// it converts data to [][column_index]value
   452  	// for example:
   453  	//	var list []ParamsList
   454  	//	qs.ValuesList(&list) // list[0][1] == "slene"
   455  	ValuesList(results *[]ParamsList, exprs ...string) (int64, error)
   456  	ValuesListWithCtx(ctx context.Context, results *[]ParamsList, exprs ...string) (int64, error)
   457  	// query all data and map to []interface.
   458  	// it's designed for one column record set, auto change to []value, not [][column]value.
   459  	// for example:
   460  	//	var list ParamsList
   461  	//	qs.ValuesFlat(&list, "UserName") // list[0] == "slene"
   462  	ValuesFlat(result *ParamsList, expr string) (int64, error)
   463  	ValuesFlatWithCtx(ctx context.Context, result *ParamsList, expr string) (int64, error)
   464  	// query all rows into map[string]interface with specify key and value column name.
   465  	// keyCol = "name", valueCol = "value"
   466  	// table data
   467  	// name  | value
   468  	// total | 100
   469  	// found | 200
   470  	// to map[string]interface{}{
   471  	// 	"total": 100,
   472  	// 	"found": 200,
   473  	// }
   474  	RowsToMap(result *Params, keyCol, valueCol string) (int64, error)
   475  	// query all rows into struct with specify key and value column name.
   476  	// keyCol = "name", valueCol = "value"
   477  	// table data
   478  	// name  | value
   479  	// total | 100
   480  	// found | 200
   481  	// to struct {
   482  	// 	Total int
   483  	// 	Found int
   484  	// }
   485  	RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error)
   486  	// aggregate func.
   487  	// for example:
   488  	// type result struct {
   489  	//  DeptName string
   490  	//	Total    int
   491  	// }
   492  	// var res []result
   493  	//  o.QueryTable("dept_info").Aggregate("dept_name,sum(salary) as total").GroupBy("dept_name").All(&res)
   494  	Aggregate(s string) QuerySeter
   495  }
   496  
   497  // QueryM2Mer model to model query struct
   498  // all operations are on the m2m table only, will not affect the origin model table
   499  type QueryM2Mer interface {
   500  	// add models to origin models when creating queryM2M.
   501  	// example:
   502  	// 	m2m := orm.QueryM2M(post,"Tag")
   503  	// 	m2m.Add(&Tag1{},&Tag2{})
   504  	//  	for _,tag := range post.Tags{}{ ... }
   505  	// param could also be any of the follow
   506  	// 	[]*Tag{{Id:3,Name: "TestTag1"}, {Id:4,Name: "TestTag2"}}
   507  	//	&Tag{Id:5,Name: "TestTag3"}
   508  	//	[]interface{}{&Tag{Id:6,Name: "TestTag4"}}
   509  	// insert one or more rows to m2m table
   510  	// make sure the relation is defined in post model struct tag.
   511  	Add(...interface{}) (int64, error)
   512  	AddWithCtx(context.Context, ...interface{}) (int64, error)
   513  	// remove models following the origin model relationship
   514  	// only delete rows from m2m table
   515  	// for example:
   516  	// tag3 := &Tag{Id:5,Name: "TestTag3"}
   517  	// num, err = m2m.Remove(tag3)
   518  	Remove(...interface{}) (int64, error)
   519  	RemoveWithCtx(context.Context, ...interface{}) (int64, error)
   520  	// check model is existed in relationship of origin model
   521  	Exist(interface{}) bool
   522  	ExistWithCtx(context.Context, interface{}) bool
   523  	// clean all models in related of origin model
   524  	Clear() (int64, error)
   525  	ClearWithCtx(context.Context) (int64, error)
   526  	// count all related models of origin model
   527  	Count() (int64, error)
   528  	CountWithCtx(context.Context) (int64, error)
   529  }
   530  
   531  // RawPreparer raw query statement
   532  type RawPreparer interface {
   533  	Exec(...interface{}) (sql.Result, error)
   534  	Close() error
   535  }
   536  
   537  // RawSeter raw query seter
   538  // create From Ormer.Raw
   539  // for example:
   540  //
   541  //	sql := fmt.Sprintf("SELECT %sid%s,%sname%s FROM %suser%s WHERE id = ?",Q,Q,Q,Q,Q,Q)
   542  //	rs := Ormer.Raw(sql, 1)
   543  type RawSeter interface {
   544  	// execute sql and get result
   545  	Exec() (sql.Result, error)
   546  	// query data and map to container
   547  	// for example:
   548  	//	var name string
   549  	//	var id int
   550  	//	rs.QueryRow(&id,&name) // id==2 name=="slene"
   551  	QueryRow(containers ...interface{}) error
   552  
   553  	// query data rows and map to container
   554  	//	var ids []int
   555  	//	var names []int
   556  	//	query = fmt.Sprintf("SELECT 'id','name' FROM %suser%s", Q, Q)
   557  	//	num, err = dORM.Raw(query).QueryRows(&ids,&names) // ids=>{1,2},names=>{"nobody","slene"}
   558  	QueryRows(containers ...interface{}) (int64, error)
   559  	SetArgs(...interface{}) RawSeter
   560  	// query data to []map[string]interface
   561  	// see QuerySeter's Values
   562  	Values(container *[]Params, cols ...string) (int64, error)
   563  	// query data to [][]interface
   564  	// see QuerySeter's ValuesList
   565  	ValuesList(container *[]ParamsList, cols ...string) (int64, error)
   566  	// query data to []interface
   567  	// see QuerySeter's ValuesFlat
   568  	ValuesFlat(container *ParamsList, cols ...string) (int64, error)
   569  	// query all rows into map[string]interface with specify key and value column name.
   570  	// keyCol = "name", valueCol = "value"
   571  	// table data
   572  	// name  | value
   573  	// total | 100
   574  	// found | 200
   575  	// to map[string]interface{}{
   576  	// 	"total": 100,
   577  	// 	"found": 200,
   578  	// }
   579  	RowsToMap(result *Params, keyCol, valueCol string) (int64, error)
   580  	// query all rows into struct with specify key and value column name.
   581  	// keyCol = "name", valueCol = "value"
   582  	// table data
   583  	// name  | value
   584  	// total | 100
   585  	// found | 200
   586  	// to struct {
   587  	// 	Total int
   588  	// 	Found int
   589  	// }
   590  	RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error)
   591  
   592  	// return prepared raw statement for used in times.
   593  	// for example:
   594  	// 	pre, err := dORM.Raw("INSERT INTO tag (name) VALUES (?)").Prepare()
   595  	// 	r, err := pre.Exec("name1") // INSERT INTO tag (name) VALUES (`name1`)
   596  	Prepare() (RawPreparer, error)
   597  }
   598  
   599  // stmtQuerier statement querier
   600  type stmtQuerier interface {
   601  	Close() error
   602  	Exec(args ...interface{}) (sql.Result, error)
   603  	ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error)
   604  	Query(args ...interface{}) (*sql.Rows, error)
   605  	QueryContext(ctx context.Context, args ...interface{}) (*sql.Rows, error)
   606  	QueryRow(args ...interface{}) *sql.Row
   607  	QueryRowContext(ctx context.Context, args ...interface{}) *sql.Row
   608  }
   609  
   610  // db querier
   611  type dbQuerier interface {
   612  	Prepare(query string) (*sql.Stmt, error)
   613  	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
   614  	Exec(query string, args ...interface{}) (sql.Result, error)
   615  	ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
   616  	Query(query string, args ...interface{}) (*sql.Rows, error)
   617  	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
   618  	QueryRow(query string, args ...interface{}) *sql.Row
   619  	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
   620  }
   621  
   622  // type DB interface {
   623  // 	Begin() (*sql.Tx, error)
   624  // 	Prepare(query string) (stmtQuerier, error)
   625  // 	Exec(query string, args ...interface{}) (sql.Result, error)
   626  // 	Query(query string, args ...interface{}) (*sql.Rows, error)
   627  // 	QueryRow(query string, args ...interface{}) *sql.Row
   628  // }
   629  
   630  // base database struct
   631  type dbBaser interface {
   632  	Read(context.Context, dbQuerier, *modelInfo, reflect.Value, *time.Location, []string, bool) error
   633  	ReadBatch(context.Context, dbQuerier, *querySet, *modelInfo, *Condition, interface{}, *time.Location, []string) (int64, error)
   634  	Count(context.Context, dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error)
   635  	ReadValues(context.Context, dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}, *time.Location) (int64, error)
   636  
   637  	Insert(context.Context, dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
   638  	InsertOrUpdate(context.Context, dbQuerier, *modelInfo, reflect.Value, *alias, ...string) (int64, error)
   639  	InsertMulti(context.Context, dbQuerier, *modelInfo, reflect.Value, int, *time.Location) (int64, error)
   640  	InsertValue(context.Context, dbQuerier, *modelInfo, bool, []string, []interface{}) (int64, error)
   641  	InsertStmt(context.Context, stmtQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
   642  
   643  	Update(context.Context, dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) (int64, error)
   644  	UpdateBatch(context.Context, dbQuerier, *querySet, *modelInfo, *Condition, Params, *time.Location) (int64, error)
   645  
   646  	Delete(context.Context, dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) (int64, error)
   647  	DeleteBatch(context.Context, dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error)
   648  
   649  	SupportUpdateJoin() bool
   650  	OperatorSQL(string) string
   651  	GenerateOperatorSQL(*modelInfo, *fieldInfo, string, []interface{}, *time.Location) (string, []interface{})
   652  	GenerateOperatorLeftCol(*fieldInfo, string, *string)
   653  	PrepareInsert(context.Context, dbQuerier, *modelInfo) (stmtQuerier, string, error)
   654  	MaxLimit() uint64
   655  	TableQuote() string
   656  	ReplaceMarks(*string)
   657  	HasReturningID(*modelInfo, *string) bool
   658  	TimeFromDB(*time.Time, *time.Location)
   659  	TimeToDB(*time.Time, *time.Location)
   660  	DbTypes() map[string]string
   661  	GetTables(dbQuerier) (map[string]bool, error)
   662  	GetColumns(context.Context, dbQuerier, string) (map[string][3]string, error)
   663  	ShowTablesQuery() string
   664  	ShowColumnsQuery(string) string
   665  	IndexExists(context.Context, dbQuerier, string, string) bool
   666  	collectFieldValue(*modelInfo, *fieldInfo, reflect.Value, bool, *time.Location) (interface{}, error)
   667  	setval(context.Context, dbQuerier, *modelInfo, []string) error
   668  
   669  	GenerateSpecifyIndex(tableName string, useIndex int, indexes []string) string
   670  }