Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
828a3060
Commit
828a3060
authored
Jan 17, 2014
by
FuXiaoHei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add comments for orm package, done
parent
4c527dde
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
192 additions
and
0 deletions
+192
-0
models.go
orm/models.go
+7
-0
models_boot.go
orm/models_boot.go
+6
-0
models_info_f.go
orm/models_info_f.go
+8
-0
models_info_m.go
orm/models_info_m.go
+4
-0
models_utils.go
orm/models_utils.go
+8
-0
orm.go
orm/orm.go
+37
-0
orm_conds.go
orm/orm_conds.go
+11
-0
orm_log.go
orm/orm_log.go
+5
-0
orm_object.go
orm/orm_object.go
+4
-0
orm_querym2m.go
orm/orm_querym2m.go
+13
-0
orm_queryset.go
orm/orm_queryset.go
+37
-0
orm_raw.go
orm/orm_raw.go
+12
-0
types.go
orm/types.go
+13
-0
utils.go
orm/utils.go
+27
-0
No files found.
orm/models.go
View file @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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 @
828a3060
...
...
@@ -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
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
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 comment