Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
张磊
/
FileStorageBeego
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
828a3060
authored
2014-01-17 23:28:54 +0800
by
FuXiaoHei
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
add comments for orm package, done
1 parent
4c527dde
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
192 additions
and
0 deletions
orm/models.go
orm/models_boot.go
orm/models_info_f.go
orm/models_info_m.go
orm/models_utils.go
orm/orm.go
orm/orm_conds.go
orm/orm_log.go
orm/orm_object.go
orm/orm_querym2m.go
orm/orm_queryset.go
orm/orm_raw.go
orm/types.go
orm/utils.go
orm/models.go
View file @
828a306
...
...
@@ -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
)
...
...
orm/models_boot.go
View file @
828a306
...
...
@@ -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
...
...
orm/models_info_f.go
View file @
828a306
...
...
@@ -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
...
...
orm/models_info_m.go
View file @
828a306
...
...
@@ -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
()
...
...
orm/models_utils.go
View file @
828a306
...
...
@@ -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
)
...
...
orm/orm.go
View file @
828a306
...
...
@@ -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
(
"<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
{
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
(
"<Ormer.Using> 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
...
...
orm/orm_conds.go
View file @
828a306
...
...
@@ -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
(
"<Condition.And> 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
(
"<Condition.AndNot> 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
(
"<Condition.Or> 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
(
"<Condition.OrNot> 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
}
...
...
orm/orm_log.go
View file @
828a306
...
...
@@ -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
...
...
orm/orm_object.go
View file @
828a306
...
...
@@ -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
...
...
orm/orm_querym2m.go
View file @
828a306
...
...
@@ -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
...
...
orm/orm_queryset.go
View file @
828a306
...
...
@@ -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
...
...
orm/orm_raw.go
View file @
828a306
...
...
@@ -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
)
}
...
...
orm/types.go
View file @
828a306
...
...
@@ -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
)
...
...
orm/utils.go
View file @
828a306
...
...
@@ -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
:
...
...
Write
Preview
Styling with
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment