1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-22 14:30:56 +00:00

add comments for orm package, done

This commit is contained in:
FuXiaoHei 2014-01-17 23:28:54 +08:00
parent 4c527dde65
commit 828a306069
14 changed files with 192 additions and 0 deletions

View File

@ -41,6 +41,7 @@ var (
} }
) )
// model info collection
type _modelCache struct { type _modelCache struct {
sync.RWMutex sync.RWMutex
orders []string orders []string
@ -49,6 +50,7 @@ type _modelCache struct {
done bool done bool
} }
// get all model info
func (mc *_modelCache) all() map[string]*modelInfo { func (mc *_modelCache) all() map[string]*modelInfo {
m := make(map[string]*modelInfo, len(mc.cache)) m := make(map[string]*modelInfo, len(mc.cache))
for k, v := range mc.cache { for k, v := range mc.cache {
@ -57,6 +59,7 @@ func (mc *_modelCache) all() map[string]*modelInfo {
return m return m
} }
// get orderd model info
func (mc *_modelCache) allOrdered() []*modelInfo { func (mc *_modelCache) allOrdered() []*modelInfo {
m := make([]*modelInfo, 0, len(mc.orders)) m := make([]*modelInfo, 0, len(mc.orders))
for _, table := range mc.orders { for _, table := range mc.orders {
@ -65,16 +68,19 @@ func (mc *_modelCache) allOrdered() []*modelInfo {
return m return m
} }
// get model info by table name
func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) { func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) {
mi, ok = mc.cache[table] mi, ok = mc.cache[table]
return return
} }
// get model info by field name
func (mc *_modelCache) getByFN(name string) (mi *modelInfo, ok bool) { func (mc *_modelCache) getByFN(name string) (mi *modelInfo, ok bool) {
mi, ok = mc.cacheByFN[name] mi, ok = mc.cacheByFN[name]
return return
} }
// set model info to collection
func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo { func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo {
mii := mc.cache[table] mii := mc.cache[table]
mc.cache[table] = mi mc.cache[table] = mi
@ -85,6 +91,7 @@ func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo {
return mii return mii
} }
// clean all model info.
func (mc *_modelCache) clean() { func (mc *_modelCache) clean() {
mc.orders = make([]string, 0) mc.orders = make([]string, 0)
mc.cache = make(map[string]*modelInfo) mc.cache = make(map[string]*modelInfo)

View File

@ -8,6 +8,8 @@ import (
"strings" "strings"
) )
// register models.
// prefix means table name prefix.
func registerModel(model interface{}, prefix string) { func registerModel(model interface{}, prefix string) {
val := reflect.ValueOf(model) val := reflect.ValueOf(model)
ind := reflect.Indirect(val) ind := reflect.Indirect(val)
@ -67,6 +69,7 @@ func registerModel(model interface{}, prefix string) {
modelCache.set(table, info) modelCache.set(table, info)
} }
// boostrap models
func bootStrap() { func bootStrap() {
if modelCache.done { if modelCache.done {
return return
@ -281,6 +284,7 @@ end:
} }
} }
// register models
func RegisterModel(models ...interface{}) { func RegisterModel(models ...interface{}) {
if modelCache.done { if modelCache.done {
panic(fmt.Errorf("RegisterModel must be run before BootStrap")) 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() { func BootStrap() {
if modelCache.done { if modelCache.done {
return return

View File

@ -9,6 +9,7 @@ import (
var errSkipField = errors.New("skip field") var errSkipField = errors.New("skip field")
// field info collection
type fields struct { type fields struct {
pk *fieldInfo pk *fieldInfo
columns map[string]*fieldInfo columns map[string]*fieldInfo
@ -23,6 +24,7 @@ type fields struct {
dbcols []string dbcols []string
} }
// add field info
func (f *fields) Add(fi *fieldInfo) (added bool) { func (f *fields) Add(fi *fieldInfo) (added bool) {
if f.fields[fi.name] == nil && f.columns[fi.column] == nil { if f.fields[fi.name] == nil && f.columns[fi.column] == nil {
f.columns[fi.column] = fi f.columns[fi.column] = fi
@ -49,14 +51,17 @@ func (f *fields) Add(fi *fieldInfo) (added bool) {
return true return true
} }
// get field info by name
func (f *fields) GetByName(name string) *fieldInfo { func (f *fields) GetByName(name string) *fieldInfo {
return f.fields[name] return f.fields[name]
} }
// get field info by column name
func (f *fields) GetByColumn(column string) *fieldInfo { func (f *fields) GetByColumn(column string) *fieldInfo {
return f.columns[column] return f.columns[column]
} }
// get field info by string, name is prior
func (f *fields) GetByAny(name string) (*fieldInfo, bool) { func (f *fields) GetByAny(name string) (*fieldInfo, bool) {
if fi, ok := f.fields[name]; ok { if fi, ok := f.fields[name]; ok {
return fi, ok return fi, ok
@ -70,6 +75,7 @@ func (f *fields) GetByAny(name string) (*fieldInfo, bool) {
return nil, false return nil, false
} }
// create new field info collection
func newFields() *fields { func newFields() *fields {
f := new(fields) f := new(fields)
f.fields = make(map[string]*fieldInfo) f.fields = make(map[string]*fieldInfo)
@ -79,6 +85,7 @@ func newFields() *fields {
return f return f
} }
// single field info
type fieldInfo struct { type fieldInfo struct {
mi *modelInfo mi *modelInfo
fieldIndex int fieldIndex int
@ -115,6 +122,7 @@ type fieldInfo struct {
onDelete string onDelete string
} }
// new field info
func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField) (fi *fieldInfo, err error) { func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField) (fi *fieldInfo, err error) {
var ( var (
tag string tag string

View File

@ -7,6 +7,7 @@ import (
"reflect" "reflect"
) )
// single model info
type modelInfo struct { type modelInfo struct {
pkg string pkg string
name string name string
@ -20,6 +21,7 @@ type modelInfo struct {
isThrough bool isThrough bool
} }
// new model info
func newModelInfo(val reflect.Value) (info *modelInfo) { func newModelInfo(val reflect.Value) (info *modelInfo) {
var ( var (
err error err error
@ -79,6 +81,8 @@ func newModelInfo(val reflect.Value) (info *modelInfo) {
return return
} }
// combine related model info to new model info.
// prepare for relation models query.
func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) { func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) {
info = new(modelInfo) info = new(modelInfo)
info.fields = newFields() info.fields = newFields()

View File

@ -7,10 +7,12 @@ import (
"time" "time"
) )
// get reflect.Type name with package path.
func getFullName(typ reflect.Type) string { func getFullName(typ reflect.Type) string {
return typ.PkgPath() + "." + typ.Name() return typ.PkgPath() + "." + typ.Name()
} }
// get table name. method, or field name. auto snaked.
func getTableName(val reflect.Value) string { func getTableName(val reflect.Value) string {
ind := reflect.Indirect(val) ind := reflect.Indirect(val)
fun := val.MethodByName("TableName") fun := val.MethodByName("TableName")
@ -26,6 +28,7 @@ func getTableName(val reflect.Value) string {
return snakeString(ind.Type().Name()) return snakeString(ind.Type().Name())
} }
// get table engine, mysiam or innodb.
func getTableEngine(val reflect.Value) string { func getTableEngine(val reflect.Value) string {
fun := val.MethodByName("TableEngine") fun := val.MethodByName("TableEngine")
if fun.IsValid() { if fun.IsValid() {
@ -40,6 +43,7 @@ func getTableEngine(val reflect.Value) string {
return "" return ""
} }
// get table index from method.
func getTableIndex(val reflect.Value) [][]string { func getTableIndex(val reflect.Value) [][]string {
fun := val.MethodByName("TableIndex") fun := val.MethodByName("TableIndex")
if fun.IsValid() { if fun.IsValid() {
@ -56,6 +60,7 @@ func getTableIndex(val reflect.Value) [][]string {
return nil return nil
} }
// get table unique from method
func getTableUnique(val reflect.Value) [][]string { func getTableUnique(val reflect.Value) [][]string {
fun := val.MethodByName("TableUnique") fun := val.MethodByName("TableUnique")
if fun.IsValid() { if fun.IsValid() {
@ -72,6 +77,7 @@ func getTableUnique(val reflect.Value) [][]string {
return nil return nil
} }
// get snaked column name
func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col string) string { func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col string) string {
col = strings.ToLower(col) col = strings.ToLower(col)
column := col column := col
@ -89,6 +95,7 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col
return column return column
} }
// return field type as type constant from reflect.Value
func getFieldType(val reflect.Value) (ft int, err error) { func getFieldType(val reflect.Value) (ft int, err error) {
elm := reflect.Indirect(val) elm := reflect.Indirect(val)
switch elm.Kind() { switch elm.Kind() {
@ -128,6 +135,7 @@ func getFieldType(val reflect.Value) (ft int, err error) {
return return
} }
// parse struct tag string
func parseStructTag(data string, attrs *map[string]bool, tags *map[string]string) { func parseStructTag(data string, attrs *map[string]bool, tags *map[string]string) {
attr := make(map[string]bool) attr := make(map[string]bool)
tag := make(map[string]string) tag := make(map[string]string)

View File

@ -40,6 +40,7 @@ type orm struct {
var _ Ormer = new(orm) var _ Ormer = new(orm)
// get model info and model reflect value
func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect.Value) { func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect.Value) {
val := reflect.ValueOf(md) val := reflect.ValueOf(md)
ind = reflect.Indirect(val) ind = reflect.Indirect(val)
@ -54,6 +55,7 @@ func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect
panic(fmt.Errorf("<Ormer> table: `%s` not found, maybe not RegisterModel", name)) panic(fmt.Errorf("<Ormer> 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 { func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo {
fi, ok := mi.fields.GetByAny(name) fi, ok := mi.fields.GetByAny(name)
if !ok { if !ok {
@ -62,6 +64,7 @@ func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo {
return fi return fi
} }
// read data to model
func (o *orm) Read(md interface{}, cols ...string) error { func (o *orm) Read(md interface{}, cols ...string) error {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
err := o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols) 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 return nil
} }
// insert model data to database
func (o *orm) Insert(md interface{}) (int64, error) { func (o *orm) Insert(md interface{}) (int64, error) {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
id, err := o.alias.DbBaser.Insert(o.db, mi, ind, o.alias.TZ) 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 return id, nil
} }
// set auto pk field
func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) { func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) {
if mi.fields.pk.auto { if mi.fields.pk.auto {
if mi.fields.pk.fieldType&IsPostiveIntegerField > 0 { 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) { func (o *orm) InsertMulti(bulk int, mds interface{}) (int64, error) {
var cnt int64 var cnt int64
@ -127,6 +133,8 @@ func (o *orm) InsertMulti(bulk int, mds interface{}) (int64, error) {
return cnt, nil 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) { func (o *orm) Update(md interface{}, cols ...string) (int64, error) {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
num, err := o.alias.DbBaser.Update(o.db, mi, ind, o.alias.TZ, cols) 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 return num, nil
} }
// delete model in database
func (o *orm) Delete(md interface{}) (int64, error) { func (o *orm) Delete(md interface{}) (int64, error) {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
num, err := o.alias.DbBaser.Delete(o.db, mi, ind, o.alias.TZ) 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 return num, nil
} }
// create a models to models queryer
func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer { func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
fi := o.getFieldInfo(mi, name) 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) 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) { func (o *orm) LoadRelated(md interface{}, name string, args ...interface{}) (int64, error) {
_, fi, ind, qseter := o.queryRelated(md, name) _, 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 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 { func (o *orm) QueryRelated(md interface{}, name string) QuerySeter {
// is this api needed ? // is this api needed ?
_, _, _, qs := o.queryRelated(md, name) _, _, _, qs := o.queryRelated(md, name)
return qs return qs
} }
// get QuerySeter for related models to md model
func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, reflect.Value, QuerySeter) { func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, reflect.Value, QuerySeter) {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
fi := o.getFieldInfo(mi, name) fi := o.getFieldInfo(mi, name)
@ -260,6 +285,7 @@ func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo,
return mi, fi, ind, qs return mi, fi, ind, qs
} }
// get reverse relation QuerySeter
func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet {
switch fi.fieldType { switch fi.fieldType {
case RelReverseOne, RelReverseMany: case RelReverseOne, RelReverseMany:
@ -280,6 +306,7 @@ func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *queryS
return q return q
} }
// get relation QuerySeter
func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet {
switch fi.fieldType { switch fi.fieldType {
case RelOneToOne, RelForeignKey, RelManyToMany: case RelOneToOne, RelForeignKey, RelManyToMany:
@ -299,6 +326,9 @@ func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet {
return q 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) { func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) {
name := "" name := ""
if table, ok := ptrStructOrTableName.(string); ok { if table, ok := ptrStructOrTableName.(string); ok {
@ -318,6 +348,7 @@ func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) {
return return
} }
// switch to another registered database driver by given name.
func (o *orm) Using(name string) error { func (o *orm) Using(name string) error {
if o.isTx { if o.isTx {
panic(fmt.Errorf("<Ormer.Using> transaction has been start, cannot change db")) panic(fmt.Errorf("<Ormer.Using> transaction has been start, cannot change db"))
@ -335,6 +366,7 @@ func (o *orm) Using(name string) error {
return nil return nil
} }
// begin transaction
func (o *orm) Begin() error { func (o *orm) Begin() error {
if o.isTx { if o.isTx {
return ErrTxHasBegan return ErrTxHasBegan
@ -353,6 +385,7 @@ func (o *orm) Begin() error {
return nil return nil
} }
// commit transaction
func (o *orm) Commit() error { func (o *orm) Commit() error {
if o.isTx == false { if o.isTx == false {
return ErrTxDone return ErrTxDone
@ -367,6 +400,7 @@ func (o *orm) Commit() error {
return err return err
} }
// rollback transaction
func (o *orm) Rollback() error { func (o *orm) Rollback() error {
if o.isTx == false { if o.isTx == false {
return ErrTxDone return ErrTxDone
@ -381,14 +415,17 @@ func (o *orm) Rollback() error {
return err return err
} }
// return a raw query seter for raw sql string.
func (o *orm) Raw(query string, args ...interface{}) RawSeter { func (o *orm) Raw(query string, args ...interface{}) RawSeter {
return newRawSet(o, query, args) return newRawSet(o, query, args)
} }
// return current using database Driver
func (o *orm) Driver() Driver { func (o *orm) Driver() Driver {
return driver(o.alias.Name) return driver(o.alias.Name)
} }
// create new orm
func NewOrm() Ormer { func NewOrm() Ormer {
BootStrap() // execute only once BootStrap() // execute only once

View File

@ -18,15 +18,19 @@ type condValue struct {
isCond bool isCond bool
} }
// condition struct.
// work for WHERE conditions.
type Condition struct { type Condition struct {
params []condValue params []condValue
} }
// return new condition struct
func NewCondition() *Condition { func NewCondition() *Condition {
c := &Condition{} c := &Condition{}
return c return c
} }
// add expression to condition
func (c Condition) And(expr string, args ...interface{}) *Condition { func (c Condition) And(expr string, args ...interface{}) *Condition {
if expr == "" || len(args) == 0 { if expr == "" || len(args) == 0 {
panic(fmt.Errorf("<Condition.And> args cannot empty")) panic(fmt.Errorf("<Condition.And> args cannot empty"))
@ -35,6 +39,7 @@ func (c Condition) And(expr string, args ...interface{}) *Condition {
return &c return &c
} }
// add NOT expression to condition
func (c Condition) AndNot(expr string, args ...interface{}) *Condition { func (c Condition) AndNot(expr string, args ...interface{}) *Condition {
if expr == "" || len(args) == 0 { if expr == "" || len(args) == 0 {
panic(fmt.Errorf("<Condition.AndNot> args cannot empty")) panic(fmt.Errorf("<Condition.AndNot> args cannot empty"))
@ -43,6 +48,7 @@ func (c Condition) AndNot(expr string, args ...interface{}) *Condition {
return &c return &c
} }
// combine a condition to current condition
func (c *Condition) AndCond(cond *Condition) *Condition { func (c *Condition) AndCond(cond *Condition) *Condition {
c = c.clone() c = c.clone()
if c == cond { if c == cond {
@ -54,6 +60,7 @@ func (c *Condition) AndCond(cond *Condition) *Condition {
return c return c
} }
// add OR expression to condition
func (c Condition) Or(expr string, args ...interface{}) *Condition { func (c Condition) Or(expr string, args ...interface{}) *Condition {
if expr == "" || len(args) == 0 { if expr == "" || len(args) == 0 {
panic(fmt.Errorf("<Condition.Or> args cannot empty")) panic(fmt.Errorf("<Condition.Or> args cannot empty"))
@ -62,6 +69,7 @@ func (c Condition) Or(expr string, args ...interface{}) *Condition {
return &c return &c
} }
// add OR NOT expression to condition
func (c Condition) OrNot(expr string, args ...interface{}) *Condition { func (c Condition) OrNot(expr string, args ...interface{}) *Condition {
if expr == "" || len(args) == 0 { if expr == "" || len(args) == 0 {
panic(fmt.Errorf("<Condition.OrNot> args cannot empty")) panic(fmt.Errorf("<Condition.OrNot> args cannot empty"))
@ -70,6 +78,7 @@ func (c Condition) OrNot(expr string, args ...interface{}) *Condition {
return &c return &c
} }
// combine a OR condition to current condition
func (c *Condition) OrCond(cond *Condition) *Condition { func (c *Condition) OrCond(cond *Condition) *Condition {
c = c.clone() c = c.clone()
if c == cond { if c == cond {
@ -81,10 +90,12 @@ func (c *Condition) OrCond(cond *Condition) *Condition {
return c return c
} }
// check the condition arguments are empty or not.
func (c *Condition) IsEmpty() bool { func (c *Condition) IsEmpty() bool {
return len(c.params) == 0 return len(c.params) == 0
} }
// clone a condition
func (c Condition) clone() *Condition { func (c Condition) clone() *Condition {
return &c return &c
} }

View File

@ -13,6 +13,7 @@ type Log struct {
*log.Logger *log.Logger
} }
// set io.Writer to create a Logger.
func NewLog(out io.Writer) *Log { func NewLog(out io.Writer) *Log {
d := new(Log) d := new(Log)
d.Logger = log.New(out, "[ORM]", 1e9) 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) DebugLog.Println(con)
} }
// statement query logger struct.
// if dev mode, use stmtQueryLog, or use stmtQuerier.
type stmtQueryLog struct { type stmtQueryLog struct {
alias *alias alias *alias
query string query string
@ -84,6 +87,8 @@ func newStmtQueryLog(alias *alias, stmt stmtQuerier, query string) stmtQuerier {
return d return d
} }
// database query logger struct.
// if dev mode, use dbQueryLog, or use dbQuerier.
type dbQueryLog struct { type dbQueryLog struct {
alias *alias alias *alias
db dbQuerier db dbQuerier

View File

@ -5,6 +5,7 @@ import (
"reflect" "reflect"
) )
// an insert queryer struct
type insertSet struct { type insertSet struct {
mi *modelInfo mi *modelInfo
orm *orm orm *orm
@ -14,6 +15,7 @@ type insertSet struct {
var _ Inserter = new(insertSet) var _ Inserter = new(insertSet)
// insert model ignore it's registered or not.
func (o *insertSet) Insert(md interface{}) (int64, error) { func (o *insertSet) Insert(md interface{}) (int64, error) {
if o.closed { if o.closed {
return 0, ErrStmtClosed return 0, ErrStmtClosed
@ -44,6 +46,7 @@ func (o *insertSet) Insert(md interface{}) (int64, error) {
return id, nil return id, nil
} }
// close insert queryer statement
func (o *insertSet) Close() error { func (o *insertSet) Close() error {
if o.closed { if o.closed {
return ErrStmtClosed return ErrStmtClosed
@ -52,6 +55,7 @@ func (o *insertSet) Close() error {
return o.stmt.Close() return o.stmt.Close()
} }
// create new insert queryer.
func newInsertSet(orm *orm, mi *modelInfo) (Inserter, error) { func newInsertSet(orm *orm, mi *modelInfo) (Inserter, error) {
bi := new(insertSet) bi := new(insertSet)
bi.orm = orm bi.orm = orm

View File

@ -4,6 +4,7 @@ import (
"reflect" "reflect"
) )
// model to model struct
type queryM2M struct { type queryM2M struct {
md interface{} md interface{}
mi *modelInfo mi *modelInfo
@ -12,6 +13,13 @@ type queryM2M struct {
ind reflect.Value 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) { func (o *queryM2M) Add(mds ...interface{}) (int64, error) {
fi := o.fi fi := o.fi
mi := fi.relThroughModelInfo mi := fi.relThroughModelInfo
@ -67,6 +75,7 @@ func (o *queryM2M) Add(mds ...interface{}) (int64, error) {
return dbase.InsertValue(orm.db, mi, true, names, values) return dbase.InsertValue(orm.db, mi, true, names, values)
} }
// remove models following the origin model relationship
func (o *queryM2M) Remove(mds ...interface{}) (int64, error) { func (o *queryM2M) Remove(mds ...interface{}) (int64, error) {
fi := o.fi fi := o.fi
qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md) qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md)
@ -78,17 +87,20 @@ func (o *queryM2M) Remove(mds ...interface{}) (int64, error) {
return nums, nil return nums, nil
} }
// check model is existed in relationship of origin model
func (o *queryM2M) Exist(md interface{}) bool { func (o *queryM2M) Exist(md interface{}) bool {
fi := o.fi fi := o.fi
return o.qs.Filter(fi.reverseFieldInfo.name, o.md). return o.qs.Filter(fi.reverseFieldInfo.name, o.md).
Filter(fi.reverseFieldInfoTwo.name, md).Exist() Filter(fi.reverseFieldInfoTwo.name, md).Exist()
} }
// clean all models in related of origin model
func (o *queryM2M) Clear() (int64, error) { func (o *queryM2M) Clear() (int64, error) {
fi := o.fi fi := o.fi
return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Delete() return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Delete()
} }
// count all related models of origin model
func (o *queryM2M) Count() (int64, error) { func (o *queryM2M) Count() (int64, error) {
fi := o.fi fi := o.fi
return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Count() return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Count()
@ -96,6 +108,7 @@ func (o *queryM2M) Count() (int64, error) {
var _ QueryM2Mer = new(queryM2M) var _ QueryM2Mer = new(queryM2M)
// create new M2M queryer.
func newQueryM2M(md interface{}, o *orm, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer { func newQueryM2M(md interface{}, o *orm, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer {
qm2m := new(queryM2M) qm2m := new(queryM2M)
qm2m.md = md qm2m.md = md

View File

@ -18,6 +18,10 @@ const (
Col_Except 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{} { func ColValue(opt operator, value interface{}) interface{} {
switch opt { switch opt {
case Col_Add, Col_Minus, Col_Multiply, Col_Except: case Col_Add, Col_Minus, Col_Multiply, Col_Except:
@ -34,6 +38,7 @@ func ColValue(opt operator, value interface{}) interface{} {
return val return val
} }
// real query struct
type querySet struct { type querySet struct {
mi *modelInfo mi *modelInfo
cond *Condition cond *Condition
@ -47,6 +52,7 @@ type querySet struct {
var _ QuerySeter = new(querySet) var _ QuerySeter = new(querySet)
// add condition expression to QuerySeter.
func (o querySet) Filter(expr string, args ...interface{}) QuerySeter { func (o querySet) Filter(expr string, args ...interface{}) QuerySeter {
if o.cond == nil { if o.cond == nil {
o.cond = NewCondition() o.cond = NewCondition()
@ -55,6 +61,7 @@ func (o querySet) Filter(expr string, args ...interface{}) QuerySeter {
return &o return &o
} }
// add NOT condition to querySeter.
func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter {
if o.cond == nil { if o.cond == nil {
o.cond = NewCondition() o.cond = NewCondition()
@ -63,10 +70,13 @@ func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter {
return &o return &o
} }
// set offset number
func (o *querySet) setOffset(num interface{}) { func (o *querySet) setOffset(num interface{}) {
o.offset = ToInt64(num) 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 { func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter {
o.limit = ToInt64(limit) o.limit = ToInt64(limit)
if len(args) > 0 { if len(args) > 0 {
@ -75,16 +85,21 @@ func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter {
return &o return &o
} }
// add OFFSET value
func (o querySet) Offset(offset interface{}) QuerySeter { func (o querySet) Offset(offset interface{}) QuerySeter {
o.setOffset(offset) o.setOffset(offset)
return &o return &o
} }
// add ORDER expression.
// "column" means ASC, "-column" means DESC.
func (o querySet) OrderBy(exprs ...string) QuerySeter { func (o querySet) OrderBy(exprs ...string) QuerySeter {
o.orders = exprs o.orders = exprs
return &o 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 { func (o querySet) RelatedSel(params ...interface{}) QuerySeter {
var related []string var related []string
if len(params) == 0 { if len(params) == 0 {
@ -105,36 +120,50 @@ func (o querySet) RelatedSel(params ...interface{}) QuerySeter {
return &o return &o
} }
// set condition to QuerySeter.
func (o querySet) SetCond(cond *Condition) QuerySeter { func (o querySet) SetCond(cond *Condition) QuerySeter {
o.cond = cond o.cond = cond
return &o return &o
} }
// return QuerySeter execution result number
func (o *querySet) Count() (int64, error) { func (o *querySet) Count() (int64, error) {
return o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) 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 { func (o *querySet) Exist() bool {
cnt, _ := o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) cnt, _ := o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ)
return cnt > 0 return cnt > 0
} }
// execute update with parameters
func (o *querySet) Update(values Params) (int64, error) { 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) 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) { 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 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) { func (o *querySet) PrepareInsert() (Inserter, error) {
return newInsertSet(o.orm, o.mi) 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) { 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) 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 { 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) num, err := o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols)
if err != nil { if err != nil {
@ -149,18 +178,26 @@ func (o *querySet) One(container interface{}, cols ...string) error {
return nil 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) { 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) 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) { 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) 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) { 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) 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 { func newQuerySet(orm *orm, mi *modelInfo) QuerySeter {
o := new(querySet) o := new(querySet)
o.mi = mi o.mi = mi

View File

@ -7,6 +7,7 @@ import (
"time" "time"
) )
// raw sql string prepared statement
type rawPrepare struct { type rawPrepare struct {
rs *rawSet rs *rawSet
stmt stmtQuerier stmt stmtQuerier
@ -44,6 +45,7 @@ func newRawPreparer(rs *rawSet) (RawPreparer, error) {
return o, nil return o, nil
} }
// raw query seter
type rawSet struct { type rawSet struct {
query string query string
args []interface{} args []interface{}
@ -52,11 +54,13 @@ type rawSet struct {
var _ RawSeter = new(rawSet) var _ RawSeter = new(rawSet)
// set args for every query
func (o rawSet) SetArgs(args ...interface{}) RawSeter { func (o rawSet) SetArgs(args ...interface{}) RawSeter {
o.args = args o.args = args
return &o return &o
} }
// execute raw sql and return sql.Result
func (o *rawSet) Exec() (sql.Result, error) { func (o *rawSet) Exec() (sql.Result, error) {
query := o.query query := o.query
o.orm.alias.DbBaser.ReplaceMarks(&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...) return o.orm.db.Exec(query, args...)
} }
// set field value to row container
func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) {
switch ind.Kind() { switch ind.Kind() {
case reflect.Bool: 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) { func (o *rawSet) loopSetRefs(refs []interface{}, sInds []reflect.Value, nIndsPtr *[]reflect.Value, eTyps []reflect.Type, init bool) {
nInds := *nIndsPtr 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 { func (o *rawSet) QueryRow(containers ...interface{}) error {
refs := make([]interface{}, 0, len(containers)) refs := make([]interface{}, 0, len(containers))
sInds := make([]reflect.Value, 0) sInds := make([]reflect.Value, 0)
@ -362,6 +369,7 @@ func (o *rawSet) QueryRow(containers ...interface{}) error {
return nil return nil
} }
// query data rows and map to container
func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) {
refs := make([]interface{}, 0, len(containers)) refs := make([]interface{}, 0, len(containers))
sInds := make([]reflect.Value, 0) sInds := make([]reflect.Value, 0)
@ -615,18 +623,22 @@ func (o *rawSet) readValues(container interface{}) (int64, error) {
return cnt, nil return cnt, nil
} }
// query data to []map[string]interface
func (o *rawSet) Values(container *[]Params) (int64, error) { func (o *rawSet) Values(container *[]Params) (int64, error) {
return o.readValues(container) return o.readValues(container)
} }
// query data to [][]interface
func (o *rawSet) ValuesList(container *[]ParamsList) (int64, error) { func (o *rawSet) ValuesList(container *[]ParamsList) (int64, error) {
return o.readValues(container) return o.readValues(container)
} }
// query data to []interface
func (o *rawSet) ValuesFlat(container *ParamsList) (int64, error) { func (o *rawSet) ValuesFlat(container *ParamsList) (int64, error) {
return o.readValues(container) return o.readValues(container)
} }
// return prepared raw statement for used in times.
func (o *rawSet) Prepare() (RawPreparer, error) { func (o *rawSet) Prepare() (RawPreparer, error) {
return newRawPreparer(o) return newRawPreparer(o)
} }

View File

@ -6,11 +6,13 @@ import (
"time" "time"
) )
// database driver
type Driver interface { type Driver interface {
Name() string Name() string
Type() DriverType Type() DriverType
} }
// field info
type Fielder interface { type Fielder interface {
String() string String() string
FieldType() int FieldType() int
@ -18,6 +20,7 @@ type Fielder interface {
RawValue() interface{} RawValue() interface{}
} }
// orm struct
type Ormer interface { type Ormer interface {
Read(interface{}, ...string) error Read(interface{}, ...string) error
Insert(interface{}) (int64, error) Insert(interface{}) (int64, error)
@ -35,11 +38,13 @@ type Ormer interface {
Driver() Driver Driver() Driver
} }
// insert prepared statement
type Inserter interface { type Inserter interface {
Insert(interface{}) (int64, error) Insert(interface{}) (int64, error)
Close() error Close() error
} }
// query seter
type QuerySeter interface { type QuerySeter interface {
Filter(string, ...interface{}) QuerySeter Filter(string, ...interface{}) QuerySeter
Exclude(string, ...interface{}) QuerySeter Exclude(string, ...interface{}) QuerySeter
@ -60,6 +65,7 @@ type QuerySeter interface {
ValuesFlat(*ParamsList, string) (int64, error) ValuesFlat(*ParamsList, string) (int64, error)
} }
// model to model query struct
type QueryM2Mer interface { type QueryM2Mer interface {
Add(...interface{}) (int64, error) Add(...interface{}) (int64, error)
Remove(...interface{}) (int64, error) Remove(...interface{}) (int64, error)
@ -68,11 +74,13 @@ type QueryM2Mer interface {
Count() (int64, error) Count() (int64, error)
} }
// raw query statement
type RawPreparer interface { type RawPreparer interface {
Exec(...interface{}) (sql.Result, error) Exec(...interface{}) (sql.Result, error)
Close() error Close() error
} }
// raw query seter
type RawSeter interface { type RawSeter interface {
Exec() (sql.Result, error) Exec() (sql.Result, error)
QueryRow(...interface{}) error QueryRow(...interface{}) error
@ -84,6 +92,7 @@ type RawSeter interface {
Prepare() (RawPreparer, error) Prepare() (RawPreparer, error)
} }
// statement querier
type stmtQuerier interface { type stmtQuerier interface {
Close() error Close() error
Exec(args ...interface{}) (sql.Result, error) Exec(args ...interface{}) (sql.Result, error)
@ -91,6 +100,7 @@ type stmtQuerier interface {
QueryRow(args ...interface{}) *sql.Row QueryRow(args ...interface{}) *sql.Row
} }
// db querier
type dbQuerier interface { type dbQuerier interface {
Prepare(query string) (*sql.Stmt, error) Prepare(query string) (*sql.Stmt, error)
Exec(query string, args ...interface{}) (sql.Result, error) Exec(query string, args ...interface{}) (sql.Result, error)
@ -98,15 +108,18 @@ type dbQuerier interface {
QueryRow(query string, args ...interface{}) *sql.Row QueryRow(query string, args ...interface{}) *sql.Row
} }
// transaction beginner
type txer interface { type txer interface {
Begin() (*sql.Tx, error) Begin() (*sql.Tx, error)
} }
// transaction ending
type txEnder interface { type txEnder interface {
Commit() error Commit() error
Rollback() error Rollback() error
} }
// base database struct
type dbBaser interface { type dbBaser interface {
Read(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) error Read(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) error
Insert(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error) Insert(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)

View File

@ -10,6 +10,7 @@ import (
type StrTo string type StrTo string
// set string
func (f *StrTo) Set(v string) { func (f *StrTo) Set(v string) {
if v != "" { if v != "" {
*f = StrTo(v) *f = StrTo(v)
@ -18,77 +19,93 @@ func (f *StrTo) Set(v string) {
} }
} }
// clean string
func (f *StrTo) Clear() { func (f *StrTo) Clear() {
*f = StrTo(0x1E) *f = StrTo(0x1E)
} }
// check string exist
func (f StrTo) Exist() bool { func (f StrTo) Exist() bool {
return string(f) != string(0x1E) return string(f) != string(0x1E)
} }
// string to bool
func (f StrTo) Bool() (bool, error) { func (f StrTo) Bool() (bool, error) {
return strconv.ParseBool(f.String()) return strconv.ParseBool(f.String())
} }
// string to float32
func (f StrTo) Float32() (float32, error) { func (f StrTo) Float32() (float32, error) {
v, err := strconv.ParseFloat(f.String(), 32) v, err := strconv.ParseFloat(f.String(), 32)
return float32(v), err return float32(v), err
} }
// string to float64
func (f StrTo) Float64() (float64, error) { func (f StrTo) Float64() (float64, error) {
return strconv.ParseFloat(f.String(), 64) return strconv.ParseFloat(f.String(), 64)
} }
// string to int
func (f StrTo) Int() (int, error) { func (f StrTo) Int() (int, error) {
v, err := strconv.ParseInt(f.String(), 10, 32) v, err := strconv.ParseInt(f.String(), 10, 32)
return int(v), err return int(v), err
} }
// string to int8
func (f StrTo) Int8() (int8, error) { func (f StrTo) Int8() (int8, error) {
v, err := strconv.ParseInt(f.String(), 10, 8) v, err := strconv.ParseInt(f.String(), 10, 8)
return int8(v), err return int8(v), err
} }
// string to int16
func (f StrTo) Int16() (int16, error) { func (f StrTo) Int16() (int16, error) {
v, err := strconv.ParseInt(f.String(), 10, 16) v, err := strconv.ParseInt(f.String(), 10, 16)
return int16(v), err return int16(v), err
} }
// string to int32
func (f StrTo) Int32() (int32, error) { func (f StrTo) Int32() (int32, error) {
v, err := strconv.ParseInt(f.String(), 10, 32) v, err := strconv.ParseInt(f.String(), 10, 32)
return int32(v), err return int32(v), err
} }
// string to int64
func (f StrTo) Int64() (int64, error) { func (f StrTo) Int64() (int64, error) {
v, err := strconv.ParseInt(f.String(), 10, 64) v, err := strconv.ParseInt(f.String(), 10, 64)
return int64(v), err return int64(v), err
} }
// string to uint
func (f StrTo) Uint() (uint, error) { func (f StrTo) Uint() (uint, error) {
v, err := strconv.ParseUint(f.String(), 10, 32) v, err := strconv.ParseUint(f.String(), 10, 32)
return uint(v), err return uint(v), err
} }
// string to uint8
func (f StrTo) Uint8() (uint8, error) { func (f StrTo) Uint8() (uint8, error) {
v, err := strconv.ParseUint(f.String(), 10, 8) v, err := strconv.ParseUint(f.String(), 10, 8)
return uint8(v), err return uint8(v), err
} }
// string to uint16
func (f StrTo) Uint16() (uint16, error) { func (f StrTo) Uint16() (uint16, error) {
v, err := strconv.ParseUint(f.String(), 10, 16) v, err := strconv.ParseUint(f.String(), 10, 16)
return uint16(v), err return uint16(v), err
} }
// string to uint31
func (f StrTo) Uint32() (uint32, error) { func (f StrTo) Uint32() (uint32, error) {
v, err := strconv.ParseUint(f.String(), 10, 32) v, err := strconv.ParseUint(f.String(), 10, 32)
return uint32(v), err return uint32(v), err
} }
// string to uint64
func (f StrTo) Uint64() (uint64, error) { func (f StrTo) Uint64() (uint64, error) {
v, err := strconv.ParseUint(f.String(), 10, 64) v, err := strconv.ParseUint(f.String(), 10, 64)
return uint64(v), err return uint64(v), err
} }
// string to string
func (f StrTo) String() string { func (f StrTo) String() string {
if f.Exist() { if f.Exist() {
return string(f) return string(f)
@ -96,6 +113,7 @@ func (f StrTo) String() string {
return "" return ""
} }
// interface to string
func ToStr(value interface{}, args ...int) (s string) { func ToStr(value interface{}, args ...int) (s string) {
switch v := value.(type) { switch v := value.(type) {
case bool: case bool:
@ -134,6 +152,7 @@ func ToStr(value interface{}, args ...int) (s string) {
return s return s
} }
// interface to int64
func ToInt64(value interface{}) (d int64) { func ToInt64(value interface{}) (d int64) {
val := reflect.ValueOf(value) val := reflect.ValueOf(value)
switch value.(type) { switch value.(type) {
@ -147,6 +166,7 @@ func ToInt64(value interface{}) (d int64) {
return return
} }
// snake string, XxYy to xx_yy
func snakeString(s string) string { func snakeString(s string) string {
data := make([]byte, 0, len(s)*2) data := make([]byte, 0, len(s)*2)
j := false j := false
@ -164,6 +184,7 @@ func snakeString(s string) string {
return strings.ToLower(string(data[:len(data)])) return strings.ToLower(string(data[:len(data)]))
} }
// camel string, xx_yy to XxYy
func camelString(s string) string { func camelString(s string) string {
data := make([]byte, 0, len(s)) data := make([]byte, 0, len(s))
j := false j := false
@ -190,6 +211,7 @@ func camelString(s string) string {
type argString []string type argString []string
// get string by index from string slice
func (a argString) Get(i int, args ...string) (r string) { func (a argString) Get(i int, args ...string) (r string) {
if i >= 0 && i < len(a) { if i >= 0 && i < len(a) {
r = a[i] r = a[i]
@ -201,6 +223,7 @@ func (a argString) Get(i int, args ...string) (r string) {
type argInt []int type argInt []int
// get int by index from int slice
func (a argInt) Get(i int, args ...int) (r int) { func (a argInt) Get(i int, args ...int) (r int) {
if i >= 0 && i < len(a) { if i >= 0 && i < len(a) {
r = a[i] r = a[i]
@ -213,6 +236,7 @@ func (a argInt) Get(i int, args ...int) (r int) {
type argAny []interface{} type argAny []interface{}
// get interface by index from interface slice
func (a argAny) Get(i int, args ...interface{}) (r interface{}) { func (a argAny) Get(i int, args ...interface{}) (r interface{}) {
if i >= 0 && i < len(a) { if i >= 0 && i < len(a) {
r = a[i] r = a[i]
@ -223,15 +247,18 @@ func (a argAny) Get(i int, args ...interface{}) (r interface{}) {
return return
} }
// parse time to string with location
func timeParse(dateString, format string) (time.Time, error) { func timeParse(dateString, format string) (time.Time, error) {
tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc)
return tp, err return tp, err
} }
// format time string
func timeFormat(t time.Time, format string) string { func timeFormat(t time.Time, format string) string {
return t.Format(format) return t.Format(format)
} }
// get pointer indirect type
func indirectType(v reflect.Type) reflect.Type { func indirectType(v reflect.Type) reflect.Type {
switch v.Kind() { switch v.Kind() {
case reflect.Ptr: case reflect.Ptr: