From 828a30606999e2e5fa2cac11327bb11378f50190 Mon Sep 17 00:00:00 2001 From: FuXiaoHei Date: Fri, 17 Jan 2014 23:28:54 +0800 Subject: [PATCH] add comments for orm package, done --- orm/models.go | 7 +++++++ orm/models_boot.go | 6 ++++++ orm/models_info_f.go | 8 ++++++++ orm/models_info_m.go | 4 ++++ orm/models_utils.go | 8 ++++++++ orm/orm.go | 37 +++++++++++++++++++++++++++++++++++++ orm/orm_conds.go | 11 +++++++++++ orm/orm_log.go | 5 +++++ orm/orm_object.go | 4 ++++ orm/orm_querym2m.go | 13 +++++++++++++ orm/orm_queryset.go | 37 +++++++++++++++++++++++++++++++++++++ orm/orm_raw.go | 12 ++++++++++++ orm/types.go | 13 +++++++++++++ orm/utils.go | 27 +++++++++++++++++++++++++++ 14 files changed, 192 insertions(+) diff --git a/orm/models.go b/orm/models.go index 1cb25c4c..5744d865 100644 --- a/orm/models.go +++ b/orm/models.go @@ -41,6 +41,7 @@ var ( } ) +// model info collection type _modelCache struct { sync.RWMutex orders []string @@ -49,6 +50,7 @@ type _modelCache struct { done bool } +// get all model info func (mc *_modelCache) all() map[string]*modelInfo { m := make(map[string]*modelInfo, len(mc.cache)) for k, v := range mc.cache { @@ -57,6 +59,7 @@ func (mc *_modelCache) all() map[string]*modelInfo { return m } +// get orderd model info func (mc *_modelCache) allOrdered() []*modelInfo { m := make([]*modelInfo, 0, len(mc.orders)) for _, table := range mc.orders { @@ -65,16 +68,19 @@ func (mc *_modelCache) allOrdered() []*modelInfo { return m } +// get model info by table name func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) { mi, ok = mc.cache[table] return } +// get model info by field name func (mc *_modelCache) getByFN(name string) (mi *modelInfo, ok bool) { mi, ok = mc.cacheByFN[name] return } +// set model info to collection func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo { mii := mc.cache[table] mc.cache[table] = mi @@ -85,6 +91,7 @@ func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo { return mii } +// clean all model info. func (mc *_modelCache) clean() { mc.orders = make([]string, 0) mc.cache = make(map[string]*modelInfo) diff --git a/orm/models_boot.go b/orm/models_boot.go index 3274b187..03caeb62 100644 --- a/orm/models_boot.go +++ b/orm/models_boot.go @@ -8,6 +8,8 @@ import ( "strings" ) +// register models. +// prefix means table name prefix. func registerModel(model interface{}, prefix string) { val := reflect.ValueOf(model) ind := reflect.Indirect(val) @@ -67,6 +69,7 @@ func registerModel(model interface{}, prefix string) { modelCache.set(table, info) } +// boostrap models func bootStrap() { if modelCache.done { return @@ -281,6 +284,7 @@ end: } } +// register models func RegisterModel(models ...interface{}) { if modelCache.done { panic(fmt.Errorf("RegisterModel must be run before BootStrap")) @@ -302,6 +306,8 @@ func RegisterModelWithPrefix(prefix string, models ...interface{}) { } } +// bootrap models. +// make all model parsed and can not add more models func BootStrap() { if modelCache.done { return diff --git a/orm/models_info_f.go b/orm/models_info_f.go index 03736091..fadbb335 100644 --- a/orm/models_info_f.go +++ b/orm/models_info_f.go @@ -9,6 +9,7 @@ import ( var errSkipField = errors.New("skip field") +// field info collection type fields struct { pk *fieldInfo columns map[string]*fieldInfo @@ -23,6 +24,7 @@ type fields struct { dbcols []string } +// add field info func (f *fields) Add(fi *fieldInfo) (added bool) { if f.fields[fi.name] == nil && f.columns[fi.column] == nil { f.columns[fi.column] = fi @@ -49,14 +51,17 @@ func (f *fields) Add(fi *fieldInfo) (added bool) { return true } +// get field info by name func (f *fields) GetByName(name string) *fieldInfo { return f.fields[name] } +// get field info by column name func (f *fields) GetByColumn(column string) *fieldInfo { return f.columns[column] } +// get field info by string, name is prior func (f *fields) GetByAny(name string) (*fieldInfo, bool) { if fi, ok := f.fields[name]; ok { return fi, ok @@ -70,6 +75,7 @@ func (f *fields) GetByAny(name string) (*fieldInfo, bool) { return nil, false } +// create new field info collection func newFields() *fields { f := new(fields) f.fields = make(map[string]*fieldInfo) @@ -79,6 +85,7 @@ func newFields() *fields { return f } +// single field info type fieldInfo struct { mi *modelInfo fieldIndex int @@ -115,6 +122,7 @@ type fieldInfo struct { onDelete string } +// new field info func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField) (fi *fieldInfo, err error) { var ( tag string diff --git a/orm/models_info_m.go b/orm/models_info_m.go index 7a173781..b596fc6a 100644 --- a/orm/models_info_m.go +++ b/orm/models_info_m.go @@ -7,6 +7,7 @@ import ( "reflect" ) +// single model info type modelInfo struct { pkg string name string @@ -20,6 +21,7 @@ type modelInfo struct { isThrough bool } +// new model info func newModelInfo(val reflect.Value) (info *modelInfo) { var ( err error @@ -79,6 +81,8 @@ func newModelInfo(val reflect.Value) (info *modelInfo) { return } +// combine related model info to new model info. +// prepare for relation models query. func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) { info = new(modelInfo) info.fields = newFields() diff --git a/orm/models_utils.go b/orm/models_utils.go index 38095b7e..1466a724 100644 --- a/orm/models_utils.go +++ b/orm/models_utils.go @@ -7,10 +7,12 @@ import ( "time" ) +// get reflect.Type name with package path. func getFullName(typ reflect.Type) string { return typ.PkgPath() + "." + typ.Name() } +// get table name. method, or field name. auto snaked. func getTableName(val reflect.Value) string { ind := reflect.Indirect(val) fun := val.MethodByName("TableName") @@ -26,6 +28,7 @@ func getTableName(val reflect.Value) string { return snakeString(ind.Type().Name()) } +// get table engine, mysiam or innodb. func getTableEngine(val reflect.Value) string { fun := val.MethodByName("TableEngine") if fun.IsValid() { @@ -40,6 +43,7 @@ func getTableEngine(val reflect.Value) string { return "" } +// get table index from method. func getTableIndex(val reflect.Value) [][]string { fun := val.MethodByName("TableIndex") if fun.IsValid() { @@ -56,6 +60,7 @@ func getTableIndex(val reflect.Value) [][]string { return nil } +// get table unique from method func getTableUnique(val reflect.Value) [][]string { fun := val.MethodByName("TableUnique") if fun.IsValid() { @@ -72,6 +77,7 @@ func getTableUnique(val reflect.Value) [][]string { return nil } +// get snaked column name func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col string) string { col = strings.ToLower(col) column := col @@ -89,6 +95,7 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col return column } +// return field type as type constant from reflect.Value func getFieldType(val reflect.Value) (ft int, err error) { elm := reflect.Indirect(val) switch elm.Kind() { @@ -128,6 +135,7 @@ func getFieldType(val reflect.Value) (ft int, err error) { return } +// parse struct tag string func parseStructTag(data string, attrs *map[string]bool, tags *map[string]string) { attr := make(map[string]bool) tag := make(map[string]string) diff --git a/orm/orm.go b/orm/orm.go index 9e3c3565..71b4daa4 100644 --- a/orm/orm.go +++ b/orm/orm.go @@ -40,6 +40,7 @@ type orm struct { var _ Ormer = new(orm) +// get model info and model reflect value func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect.Value) { val := reflect.ValueOf(md) ind = reflect.Indirect(val) @@ -54,6 +55,7 @@ func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect panic(fmt.Errorf(" table: `%s` not found, maybe not RegisterModel", name)) } +// get field info from model info by given field name func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo { fi, ok := mi.fields.GetByAny(name) if !ok { @@ -62,6 +64,7 @@ func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo { return fi } +// read data to model func (o *orm) Read(md interface{}, cols ...string) error { mi, ind := o.getMiInd(md, true) err := o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols) @@ -71,6 +74,7 @@ func (o *orm) Read(md interface{}, cols ...string) error { return nil } +// insert model data to database func (o *orm) Insert(md interface{}) (int64, error) { mi, ind := o.getMiInd(md, true) id, err := o.alias.DbBaser.Insert(o.db, mi, ind, o.alias.TZ) @@ -83,6 +87,7 @@ func (o *orm) Insert(md interface{}) (int64, error) { return id, nil } +// set auto pk field func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) { if mi.fields.pk.auto { if mi.fields.pk.fieldType&IsPostiveIntegerField > 0 { @@ -93,6 +98,7 @@ func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) { } } +// insert some models to database func (o *orm) InsertMulti(bulk int, mds interface{}) (int64, error) { var cnt int64 @@ -127,6 +133,8 @@ func (o *orm) InsertMulti(bulk int, mds interface{}) (int64, error) { return cnt, nil } +// update model to database. +// cols set the columns those want to update. func (o *orm) Update(md interface{}, cols ...string) (int64, error) { mi, ind := o.getMiInd(md, true) num, err := o.alias.DbBaser.Update(o.db, mi, ind, o.alias.TZ, cols) @@ -136,6 +144,7 @@ func (o *orm) Update(md interface{}, cols ...string) (int64, error) { return num, nil } +// delete model in database func (o *orm) Delete(md interface{}) (int64, error) { mi, ind := o.getMiInd(md, true) num, err := o.alias.DbBaser.Delete(o.db, mi, ind, o.alias.TZ) @@ -148,6 +157,7 @@ func (o *orm) Delete(md interface{}) (int64, error) { return num, nil } +// create a models to models queryer func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer { mi, ind := o.getMiInd(md, true) fi := o.getFieldInfo(mi, name) @@ -162,6 +172,14 @@ func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer { return newQueryM2M(md, o, mi, fi, ind) } +// load related models to md model. +// args are limit, offset int and order string. +// +// example: +// orm.LoadRelated(post,"Tags") +// for _,tag := range post.Tags{...} +// +// make sure the relation is defined in model struct tags. func (o *orm) LoadRelated(md interface{}, name string, args ...interface{}) (int64, error) { _, fi, ind, qseter := o.queryRelated(md, name) @@ -223,12 +241,19 @@ func (o *orm) LoadRelated(md interface{}, name string, args ...interface{}) (int return nums, err } +// return a QuerySeter for related models to md model. +// it can do all, update, delete in QuerySeter. +// example: +// qs := orm.QueryRelated(post,"Tag") +// qs.All(&[]*Tag{}) +// func (o *orm) QueryRelated(md interface{}, name string) QuerySeter { // is this api needed ? _, _, _, qs := o.queryRelated(md, name) return qs } +// get QuerySeter for related models to md model func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, reflect.Value, QuerySeter) { mi, ind := o.getMiInd(md, true) fi := o.getFieldInfo(mi, name) @@ -260,6 +285,7 @@ func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, return mi, fi, ind, qs } +// get reverse relation QuerySeter func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { switch fi.fieldType { case RelReverseOne, RelReverseMany: @@ -280,6 +306,7 @@ func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *queryS return q } +// get relation QuerySeter func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { switch fi.fieldType { case RelOneToOne, RelForeignKey, RelManyToMany: @@ -299,6 +326,9 @@ func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { return q } +// return a QuerySeter for table operations. +// table name can be string or struct. +// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)), func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { name := "" if table, ok := ptrStructOrTableName.(string); ok { @@ -318,6 +348,7 @@ func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { return } +// switch to another registered database driver by given name. func (o *orm) Using(name string) error { if o.isTx { panic(fmt.Errorf(" transaction has been start, cannot change db")) @@ -335,6 +366,7 @@ func (o *orm) Using(name string) error { return nil } +// begin transaction func (o *orm) Begin() error { if o.isTx { return ErrTxHasBegan @@ -353,6 +385,7 @@ func (o *orm) Begin() error { return nil } +// commit transaction func (o *orm) Commit() error { if o.isTx == false { return ErrTxDone @@ -367,6 +400,7 @@ func (o *orm) Commit() error { return err } +// rollback transaction func (o *orm) Rollback() error { if o.isTx == false { return ErrTxDone @@ -381,14 +415,17 @@ func (o *orm) Rollback() error { return err } +// return a raw query seter for raw sql string. func (o *orm) Raw(query string, args ...interface{}) RawSeter { return newRawSet(o, query, args) } +// return current using database Driver func (o *orm) Driver() Driver { return driver(o.alias.Name) } +// create new orm func NewOrm() Ormer { BootStrap() // execute only once diff --git a/orm/orm_conds.go b/orm/orm_conds.go index 91d69986..5b1151e2 100644 --- a/orm/orm_conds.go +++ b/orm/orm_conds.go @@ -18,15 +18,19 @@ type condValue struct { isCond bool } +// condition struct. +// work for WHERE conditions. type Condition struct { params []condValue } +// return new condition struct func NewCondition() *Condition { c := &Condition{} return c } +// add expression to condition func (c Condition) And(expr string, args ...interface{}) *Condition { if expr == "" || len(args) == 0 { panic(fmt.Errorf(" args cannot empty")) @@ -35,6 +39,7 @@ func (c Condition) And(expr string, args ...interface{}) *Condition { return &c } +// add NOT expression to condition func (c Condition) AndNot(expr string, args ...interface{}) *Condition { if expr == "" || len(args) == 0 { panic(fmt.Errorf(" args cannot empty")) @@ -43,6 +48,7 @@ func (c Condition) AndNot(expr string, args ...interface{}) *Condition { return &c } +// combine a condition to current condition func (c *Condition) AndCond(cond *Condition) *Condition { c = c.clone() if c == cond { @@ -54,6 +60,7 @@ func (c *Condition) AndCond(cond *Condition) *Condition { return c } +// add OR expression to condition func (c Condition) Or(expr string, args ...interface{}) *Condition { if expr == "" || len(args) == 0 { panic(fmt.Errorf(" args cannot empty")) @@ -62,6 +69,7 @@ func (c Condition) Or(expr string, args ...interface{}) *Condition { return &c } +// add OR NOT expression to condition func (c Condition) OrNot(expr string, args ...interface{}) *Condition { if expr == "" || len(args) == 0 { panic(fmt.Errorf(" args cannot empty")) @@ -70,6 +78,7 @@ func (c Condition) OrNot(expr string, args ...interface{}) *Condition { return &c } +// combine a OR condition to current condition func (c *Condition) OrCond(cond *Condition) *Condition { c = c.clone() if c == cond { @@ -81,10 +90,12 @@ func (c *Condition) OrCond(cond *Condition) *Condition { return c } +// check the condition arguments are empty or not. func (c *Condition) IsEmpty() bool { return len(c.params) == 0 } +// clone a condition func (c Condition) clone() *Condition { return &c } diff --git a/orm/orm_log.go b/orm/orm_log.go index 0bb5d6f9..e6df797a 100644 --- a/orm/orm_log.go +++ b/orm/orm_log.go @@ -13,6 +13,7 @@ type Log struct { *log.Logger } +// set io.Writer to create a Logger. func NewLog(out io.Writer) *Log { d := new(Log) d.Logger = log.New(out, "[ORM]", 1e9) @@ -40,6 +41,8 @@ func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error DebugLog.Println(con) } +// statement query logger struct. +// if dev mode, use stmtQueryLog, or use stmtQuerier. type stmtQueryLog struct { alias *alias query string @@ -84,6 +87,8 @@ func newStmtQueryLog(alias *alias, stmt stmtQuerier, query string) stmtQuerier { return d } +// database query logger struct. +// if dev mode, use dbQueryLog, or use dbQuerier. type dbQueryLog struct { alias *alias db dbQuerier diff --git a/orm/orm_object.go b/orm/orm_object.go index 3c6d1f0e..fa644349 100644 --- a/orm/orm_object.go +++ b/orm/orm_object.go @@ -5,6 +5,7 @@ import ( "reflect" ) +// an insert queryer struct type insertSet struct { mi *modelInfo orm *orm @@ -14,6 +15,7 @@ type insertSet struct { var _ Inserter = new(insertSet) +// insert model ignore it's registered or not. func (o *insertSet) Insert(md interface{}) (int64, error) { if o.closed { return 0, ErrStmtClosed @@ -44,6 +46,7 @@ func (o *insertSet) Insert(md interface{}) (int64, error) { return id, nil } +// close insert queryer statement func (o *insertSet) Close() error { if o.closed { return ErrStmtClosed @@ -52,6 +55,7 @@ func (o *insertSet) Close() error { return o.stmt.Close() } +// create new insert queryer. func newInsertSet(orm *orm, mi *modelInfo) (Inserter, error) { bi := new(insertSet) bi.orm = orm diff --git a/orm/orm_querym2m.go b/orm/orm_querym2m.go index 6f0544d0..f0bc94b7 100644 --- a/orm/orm_querym2m.go +++ b/orm/orm_querym2m.go @@ -4,6 +4,7 @@ import ( "reflect" ) +// model to model struct type queryM2M struct { md interface{} mi *modelInfo @@ -12,6 +13,13 @@ type queryM2M struct { ind reflect.Value } +// add models to origin models when creating queryM2M. +// example: +// m2m := orm.QueryM2M(post,"Tag") +// m2m.Add(&Tag1{},&Tag2{}) +// for _,tag := range post.Tags{} +// +// make sure the relation is defined in post model struct tag. func (o *queryM2M) Add(mds ...interface{}) (int64, error) { fi := o.fi mi := fi.relThroughModelInfo @@ -67,6 +75,7 @@ func (o *queryM2M) Add(mds ...interface{}) (int64, error) { return dbase.InsertValue(orm.db, mi, true, names, values) } +// remove models following the origin model relationship func (o *queryM2M) Remove(mds ...interface{}) (int64, error) { fi := o.fi qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md) @@ -78,17 +87,20 @@ func (o *queryM2M) Remove(mds ...interface{}) (int64, error) { return nums, nil } +// check model is existed in relationship of origin model func (o *queryM2M) Exist(md interface{}) bool { fi := o.fi return o.qs.Filter(fi.reverseFieldInfo.name, o.md). Filter(fi.reverseFieldInfoTwo.name, md).Exist() } +// clean all models in related of origin model func (o *queryM2M) Clear() (int64, error) { fi := o.fi return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Delete() } +// count all related models of origin model func (o *queryM2M) Count() (int64, error) { fi := o.fi return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Count() @@ -96,6 +108,7 @@ func (o *queryM2M) Count() (int64, error) { var _ QueryM2Mer = new(queryM2M) +// create new M2M queryer. func newQueryM2M(md interface{}, o *orm, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer { qm2m := new(queryM2M) qm2m.md = md diff --git a/orm/orm_queryset.go b/orm/orm_queryset.go index b25d0542..ad8a9374 100644 --- a/orm/orm_queryset.go +++ b/orm/orm_queryset.go @@ -18,6 +18,10 @@ const ( Col_Except ) +// ColValue do the field raw changes. e.g Nums = Nums + 10. usage: +// Params{ +// "Nums": ColValue(Col_Add, 10), +// } func ColValue(opt operator, value interface{}) interface{} { switch opt { case Col_Add, Col_Minus, Col_Multiply, Col_Except: @@ -34,6 +38,7 @@ func ColValue(opt operator, value interface{}) interface{} { return val } +// real query struct type querySet struct { mi *modelInfo cond *Condition @@ -47,6 +52,7 @@ type querySet struct { var _ QuerySeter = new(querySet) +// add condition expression to QuerySeter. func (o querySet) Filter(expr string, args ...interface{}) QuerySeter { if o.cond == nil { o.cond = NewCondition() @@ -55,6 +61,7 @@ func (o querySet) Filter(expr string, args ...interface{}) QuerySeter { return &o } +// add NOT condition to querySeter. func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { if o.cond == nil { o.cond = NewCondition() @@ -63,10 +70,13 @@ func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { return &o } +// set offset number func (o *querySet) setOffset(num interface{}) { o.offset = ToInt64(num) } +// add LIMIT value. +// args[0] means offset, e.g. LIMIT num,offset. func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter { o.limit = ToInt64(limit) if len(args) > 0 { @@ -75,16 +85,21 @@ func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter { return &o } +// add OFFSET value func (o querySet) Offset(offset interface{}) QuerySeter { o.setOffset(offset) return &o } +// add ORDER expression. +// "column" means ASC, "-column" means DESC. func (o querySet) OrderBy(exprs ...string) QuerySeter { o.orders = exprs return &o } +// set relation model to query together. +// it will query relation models and assign to parent model. func (o querySet) RelatedSel(params ...interface{}) QuerySeter { var related []string if len(params) == 0 { @@ -105,36 +120,50 @@ func (o querySet) RelatedSel(params ...interface{}) QuerySeter { return &o } +// set condition to QuerySeter. func (o querySet) SetCond(cond *Condition) QuerySeter { o.cond = cond return &o } +// return QuerySeter execution result number func (o *querySet) Count() (int64, error) { return o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) } +// check result empty or not after QuerySeter executed func (o *querySet) Exist() bool { cnt, _ := o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) return cnt > 0 } +// execute update with parameters func (o *querySet) Update(values Params) (int64, error) { return o.orm.alias.DbBaser.UpdateBatch(o.orm.db, o, o.mi, o.cond, values, o.orm.alias.TZ) } +// execute delete func (o *querySet) Delete() (int64, error) { return o.orm.alias.DbBaser.DeleteBatch(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) } +// return a insert queryer. +// it can be used in times. +// example: +// i,err := sq.PrepareInsert() +// i.Add(&user1{},&user2{}) func (o *querySet) PrepareInsert() (Inserter, error) { return newInsertSet(o.orm, o.mi) } +// query all data and map to containers. +// cols means the columns when querying. func (o *querySet) All(container interface{}, cols ...string) (int64, error) { return o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols) } +// query one row data and map to containers. +// cols means the columns when querying. func (o *querySet) One(container interface{}, cols ...string) error { num, err := o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols) if err != nil { @@ -149,18 +178,26 @@ func (o *querySet) One(container interface{}, cols ...string) error { return nil } +// query all data and map to []map[string]interface. +// expres means condition expression. +// it converts data to []map[column]value. func (o *querySet) Values(results *[]Params, exprs ...string) (int64, error) { return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ) } +// query all data and map to [][]interface +// it converts data to [][column_index]value func (o *querySet) ValuesList(results *[]ParamsList, exprs ...string) (int64, error) { return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ) } +// query all data and map to []interface. +// it's designed for one row record set, auto change to []value, not [][column]value. func (o *querySet) ValuesFlat(result *ParamsList, expr string) (int64, error) { return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, []string{expr}, result, o.orm.alias.TZ) } +// create new QuerySeter. func newQuerySet(orm *orm, mi *modelInfo) QuerySeter { o := new(querySet) o.mi = mi diff --git a/orm/orm_raw.go b/orm/orm_raw.go index a713dbac..3f5fb162 100644 --- a/orm/orm_raw.go +++ b/orm/orm_raw.go @@ -7,6 +7,7 @@ import ( "time" ) +// raw sql string prepared statement type rawPrepare struct { rs *rawSet stmt stmtQuerier @@ -44,6 +45,7 @@ func newRawPreparer(rs *rawSet) (RawPreparer, error) { return o, nil } +// raw query seter type rawSet struct { query string args []interface{} @@ -52,11 +54,13 @@ type rawSet struct { var _ RawSeter = new(rawSet) +// set args for every query func (o rawSet) SetArgs(args ...interface{}) RawSeter { o.args = args return &o } +// execute raw sql and return sql.Result func (o *rawSet) Exec() (sql.Result, error) { query := o.query o.orm.alias.DbBaser.ReplaceMarks(&query) @@ -65,6 +69,7 @@ func (o *rawSet) Exec() (sql.Result, error) { return o.orm.db.Exec(query, args...) } +// set field value to row container func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { switch ind.Kind() { case reflect.Bool: @@ -163,6 +168,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { } } +// set field value in loop for slice container func (o *rawSet) loopSetRefs(refs []interface{}, sInds []reflect.Value, nIndsPtr *[]reflect.Value, eTyps []reflect.Type, init bool) { nInds := *nIndsPtr @@ -233,6 +239,7 @@ func (o *rawSet) loopSetRefs(refs []interface{}, sInds []reflect.Value, nIndsPtr } } +// query data and map to container func (o *rawSet) QueryRow(containers ...interface{}) error { refs := make([]interface{}, 0, len(containers)) sInds := make([]reflect.Value, 0) @@ -362,6 +369,7 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { return nil } +// query data rows and map to container func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { refs := make([]interface{}, 0, len(containers)) sInds := make([]reflect.Value, 0) @@ -615,18 +623,22 @@ func (o *rawSet) readValues(container interface{}) (int64, error) { return cnt, nil } +// query data to []map[string]interface func (o *rawSet) Values(container *[]Params) (int64, error) { return o.readValues(container) } +// query data to [][]interface func (o *rawSet) ValuesList(container *[]ParamsList) (int64, error) { return o.readValues(container) } +// query data to []interface func (o *rawSet) ValuesFlat(container *ParamsList) (int64, error) { return o.readValues(container) } +// return prepared raw statement for used in times. func (o *rawSet) Prepare() (RawPreparer, error) { return newRawPreparer(o) } diff --git a/orm/types.go b/orm/types.go index a6487fc0..6f13ed67 100644 --- a/orm/types.go +++ b/orm/types.go @@ -6,11 +6,13 @@ import ( "time" ) +// database driver type Driver interface { Name() string Type() DriverType } +// field info type Fielder interface { String() string FieldType() int @@ -18,6 +20,7 @@ type Fielder interface { RawValue() interface{} } +// orm struct type Ormer interface { Read(interface{}, ...string) error Insert(interface{}) (int64, error) @@ -35,11 +38,13 @@ type Ormer interface { Driver() Driver } +// insert prepared statement type Inserter interface { Insert(interface{}) (int64, error) Close() error } +// query seter type QuerySeter interface { Filter(string, ...interface{}) QuerySeter Exclude(string, ...interface{}) QuerySeter @@ -60,6 +65,7 @@ type QuerySeter interface { ValuesFlat(*ParamsList, string) (int64, error) } +// model to model query struct type QueryM2Mer interface { Add(...interface{}) (int64, error) Remove(...interface{}) (int64, error) @@ -68,11 +74,13 @@ type QueryM2Mer interface { Count() (int64, error) } +// raw query statement type RawPreparer interface { Exec(...interface{}) (sql.Result, error) Close() error } +// raw query seter type RawSeter interface { Exec() (sql.Result, error) QueryRow(...interface{}) error @@ -84,6 +92,7 @@ type RawSeter interface { Prepare() (RawPreparer, error) } +// statement querier type stmtQuerier interface { Close() error Exec(args ...interface{}) (sql.Result, error) @@ -91,6 +100,7 @@ type stmtQuerier interface { QueryRow(args ...interface{}) *sql.Row } +// db querier type dbQuerier interface { Prepare(query string) (*sql.Stmt, error) Exec(query string, args ...interface{}) (sql.Result, error) @@ -98,15 +108,18 @@ type dbQuerier interface { QueryRow(query string, args ...interface{}) *sql.Row } +// transaction beginner type txer interface { Begin() (*sql.Tx, error) } +// transaction ending type txEnder interface { Commit() error Rollback() error } +// base database struct type dbBaser interface { Read(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) error Insert(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error) diff --git a/orm/utils.go b/orm/utils.go index 237b3edf..2e347278 100644 --- a/orm/utils.go +++ b/orm/utils.go @@ -10,6 +10,7 @@ import ( type StrTo string +// set string func (f *StrTo) Set(v string) { if v != "" { *f = StrTo(v) @@ -18,77 +19,93 @@ func (f *StrTo) Set(v string) { } } +// clean string func (f *StrTo) Clear() { *f = StrTo(0x1E) } +// check string exist func (f StrTo) Exist() bool { return string(f) != string(0x1E) } +// string to bool func (f StrTo) Bool() (bool, error) { return strconv.ParseBool(f.String()) } +// string to float32 func (f StrTo) Float32() (float32, error) { v, err := strconv.ParseFloat(f.String(), 32) return float32(v), err } +// string to float64 func (f StrTo) Float64() (float64, error) { return strconv.ParseFloat(f.String(), 64) } +// string to int func (f StrTo) Int() (int, error) { v, err := strconv.ParseInt(f.String(), 10, 32) return int(v), err } +// string to int8 func (f StrTo) Int8() (int8, error) { v, err := strconv.ParseInt(f.String(), 10, 8) return int8(v), err } +// string to int16 func (f StrTo) Int16() (int16, error) { v, err := strconv.ParseInt(f.String(), 10, 16) return int16(v), err } +// string to int32 func (f StrTo) Int32() (int32, error) { v, err := strconv.ParseInt(f.String(), 10, 32) return int32(v), err } +// string to int64 func (f StrTo) Int64() (int64, error) { v, err := strconv.ParseInt(f.String(), 10, 64) return int64(v), err } +// string to uint func (f StrTo) Uint() (uint, error) { v, err := strconv.ParseUint(f.String(), 10, 32) return uint(v), err } +// string to uint8 func (f StrTo) Uint8() (uint8, error) { v, err := strconv.ParseUint(f.String(), 10, 8) return uint8(v), err } +// string to uint16 func (f StrTo) Uint16() (uint16, error) { v, err := strconv.ParseUint(f.String(), 10, 16) return uint16(v), err } +// string to uint31 func (f StrTo) Uint32() (uint32, error) { v, err := strconv.ParseUint(f.String(), 10, 32) return uint32(v), err } +// string to uint64 func (f StrTo) Uint64() (uint64, error) { v, err := strconv.ParseUint(f.String(), 10, 64) return uint64(v), err } +// string to string func (f StrTo) String() string { if f.Exist() { return string(f) @@ -96,6 +113,7 @@ func (f StrTo) String() string { return "" } +// interface to string func ToStr(value interface{}, args ...int) (s string) { switch v := value.(type) { case bool: @@ -134,6 +152,7 @@ func ToStr(value interface{}, args ...int) (s string) { return s } +// interface to int64 func ToInt64(value interface{}) (d int64) { val := reflect.ValueOf(value) switch value.(type) { @@ -147,6 +166,7 @@ func ToInt64(value interface{}) (d int64) { return } +// snake string, XxYy to xx_yy func snakeString(s string) string { data := make([]byte, 0, len(s)*2) j := false @@ -164,6 +184,7 @@ func snakeString(s string) string { return strings.ToLower(string(data[:len(data)])) } +// camel string, xx_yy to XxYy func camelString(s string) string { data := make([]byte, 0, len(s)) j := false @@ -190,6 +211,7 @@ func camelString(s string) string { type argString []string +// get string by index from string slice func (a argString) Get(i int, args ...string) (r string) { if i >= 0 && i < len(a) { r = a[i] @@ -201,6 +223,7 @@ func (a argString) Get(i int, args ...string) (r string) { type argInt []int +// get int by index from int slice func (a argInt) Get(i int, args ...int) (r int) { if i >= 0 && i < len(a) { r = a[i] @@ -213,6 +236,7 @@ func (a argInt) Get(i int, args ...int) (r int) { type argAny []interface{} +// get interface by index from interface slice func (a argAny) Get(i int, args ...interface{}) (r interface{}) { if i >= 0 && i < len(a) { r = a[i] @@ -223,15 +247,18 @@ func (a argAny) Get(i int, args ...interface{}) (r interface{}) { return } +// parse time to string with location func timeParse(dateString, format string) (time.Time, error) { tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) return tp, err } +// format time string func timeFormat(t time.Time, format string) string { return t.Format(format) } +// get pointer indirect type func indirectType(v reflect.Type) reflect.Type { switch v.Kind() { case reflect.Ptr: