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
d043ebcd
Commit
d043ebcd
authored
Oct 14, 2013
by
slene
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
orm support complete m2m operation api / auto load related api
parent
e11c40ee
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
840 additions
and
224 deletions
+840
-224
cmd_utils.go
orm/cmd_utils.go
+5
-1
db.go
orm/db.go
+94
-78
db_tables.go
orm/db_tables.go
+61
-62
models_boot.go
orm/models_boot.go
+47
-10
models_info_f.go
orm/models_info_f.go
+2
-0
models_info_m.go
orm/models_info_m.go
+4
-0
models_test.go
orm/models_test.go
+9
-7
orm.go
orm/orm.go
+151
-13
orm_querym2m.go
orm/orm_querym2m.go
+111
-0
orm_test.go
orm/orm_test.go
+344
-50
types.go
orm/types.go
+12
-3
No files found.
orm/cmd_utils.go
View file @
d043ebcd
...
@@ -151,7 +151,11 @@ func getDbCreateSql(al *alias) (sqls []string, tableIndexes map[string][]dbIndex
...
@@ -151,7 +151,11 @@ func getDbCreateSql(al *alias) (sqls []string, tableIndexes map[string][]dbIndex
}
}
if
mi
.
model
!=
nil
{
if
mi
.
model
!=
nil
{
for
_
,
names
:=
range
getTableUnique
(
mi
.
addrField
)
{
allnames
:=
getTableUnique
(
mi
.
addrField
)
if
!
mi
.
manual
&&
len
(
mi
.
uniques
)
>
0
{
allnames
=
append
(
allnames
,
mi
.
uniques
)
}
for
_
,
names
:=
range
allnames
{
cols
:=
make
([]
string
,
0
,
len
(
names
))
cols
:=
make
([]
string
,
0
,
len
(
names
))
for
_
,
name
:=
range
names
{
for
_
,
name
:=
range
names
{
if
fi
,
ok
:=
mi
.
fields
.
GetByAny
(
name
);
ok
&&
fi
.
dbcol
{
if
fi
,
ok
:=
mi
.
fields
.
GetByAny
(
name
);
ok
&&
fi
.
dbcol
{
...
...
orm/db.go
View file @
d043ebcd
...
@@ -52,7 +52,6 @@ type dbBase struct {
...
@@ -52,7 +52,6 @@ type dbBase struct {
var
_
dbBaser
=
new
(
dbBase
)
var
_
dbBaser
=
new
(
dbBase
)
func
(
d
*
dbBase
)
collectValues
(
mi
*
modelInfo
,
ind
reflect
.
Value
,
cols
[]
string
,
skipAuto
bool
,
insert
bool
,
tz
*
time
.
Location
)
(
columns
[]
string
,
values
[]
interface
{},
err
error
)
{
func
(
d
*
dbBase
)
collectValues
(
mi
*
modelInfo
,
ind
reflect
.
Value
,
cols
[]
string
,
skipAuto
bool
,
insert
bool
,
tz
*
time
.
Location
)
(
columns
[]
string
,
values
[]
interface
{},
err
error
)
{
_
,
pkValue
,
_
:=
getExistPk
(
mi
,
ind
)
for
_
,
column
:=
range
cols
{
for
_
,
column
:=
range
cols
{
var
fi
*
fieldInfo
var
fi
*
fieldInfo
if
fi
,
_
=
mi
.
fields
.
GetByAny
(
column
);
fi
!=
nil
{
if
fi
,
_
=
mi
.
fields
.
GetByAny
(
column
);
fi
!=
nil
{
...
@@ -63,82 +62,90 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string,
...
@@ -63,82 +62,90 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string,
if
fi
.
dbcol
==
false
||
fi
.
auto
&&
skipAuto
{
if
fi
.
dbcol
==
false
||
fi
.
auto
&&
skipAuto
{
continue
continue
}
}
var
value
interface
{}
value
,
err
:=
d
.
collectFieldValue
(
mi
,
fi
,
ind
,
insert
,
tz
)
if
fi
.
pk
{
if
err
!=
nil
{
value
=
pkValue
return
nil
,
nil
,
err
}
columns
=
append
(
columns
,
column
)
values
=
append
(
values
,
value
)
}
return
}
func
(
d
*
dbBase
)
collectFieldValue
(
mi
*
modelInfo
,
fi
*
fieldInfo
,
ind
reflect
.
Value
,
insert
bool
,
tz
*
time
.
Location
)
(
interface
{},
error
)
{
var
value
interface
{}
if
fi
.
pk
{
_
,
value
,
_
=
getExistPk
(
mi
,
ind
)
}
else
{
field
:=
ind
.
Field
(
fi
.
fieldIndex
)
if
fi
.
isFielder
{
f
:=
field
.
Addr
()
.
Interface
()
.
(
Fielder
)
value
=
f
.
RawValue
()
}
else
{
}
else
{
field
:=
ind
.
Field
(
fi
.
fieldIndex
)
switch
fi
.
fieldType
{
if
fi
.
isFielder
{
case
TypeBooleanField
:
f
:=
field
.
Addr
()
.
Interface
()
.
(
Fielder
)
value
=
field
.
Bool
()
value
=
f
.
RawValue
()
case
TypeCharField
,
TypeTextField
:
}
else
{
value
=
field
.
String
()
switch
fi
.
fieldType
{
case
TypeFloatField
,
TypeDecimalField
:
case
TypeBooleanField
:
vu
:=
field
.
Interface
()
value
=
field
.
Bool
()
if
_
,
ok
:=
vu
.
(
float32
);
ok
{
case
TypeCharField
,
TypeTextField
:
value
,
_
=
StrTo
(
ToStr
(
vu
))
.
Float64
()
value
=
field
.
String
()
}
else
{
case
TypeFloatField
,
TypeDecimalField
:
value
=
field
.
Float
()
vu
:=
field
.
Interface
()
}
if
_
,
ok
:=
vu
.
(
float32
);
ok
{
case
TypeDateField
,
TypeDateTimeField
:
value
,
_
=
StrTo
(
ToStr
(
vu
))
.
Float64
()
value
=
field
.
Interface
()
if
t
,
ok
:=
value
.
(
time
.
Time
);
ok
{
if
fi
.
fieldType
==
TypeDateField
{
d
.
ins
.
TimeToDB
(
&
t
,
DefaultTimeLoc
)
}
else
{
}
else
{
value
=
field
.
Float
(
)
d
.
ins
.
TimeToDB
(
&
t
,
tz
)
}
}
case
TypeDateField
,
TypeDateTimeField
:
value
=
t
value
=
field
.
Interface
()
}
if
t
,
ok
:=
value
.
(
time
.
Time
);
ok
{
default
:
if
fi
.
fieldType
==
TypeDateField
{
switch
{
d
.
ins
.
TimeToDB
(
&
t
,
DefaultTimeLoc
)
case
fi
.
fieldType
&
IsPostiveIntegerField
>
0
:
value
=
field
.
Uint
()
case
fi
.
fieldType
&
IsIntegerField
>
0
:
value
=
field
.
Int
()
case
fi
.
fieldType
&
IsRelField
>
0
:
if
field
.
IsNil
()
{
value
=
nil
}
else
{
if
_
,
vu
,
ok
:=
getExistPk
(
fi
.
relModelInfo
,
reflect
.
Indirect
(
field
));
ok
{
value
=
vu
}
else
{
}
else
{
d
.
ins
.
TimeToDB
(
&
t
,
tz
)
}
value
=
t
}
default
:
switch
{
case
fi
.
fieldType
&
IsPostiveIntegerField
>
0
:
value
=
field
.
Uint
()
case
fi
.
fieldType
&
IsIntegerField
>
0
:
value
=
field
.
Int
()
case
fi
.
fieldType
&
IsRelField
>
0
:
if
field
.
IsNil
()
{
value
=
nil
value
=
nil
}
else
{
if
_
,
vu
,
ok
:=
getExistPk
(
fi
.
relModelInfo
,
reflect
.
Indirect
(
field
));
ok
{
value
=
vu
}
else
{
value
=
nil
}
}
if
fi
.
null
==
false
&&
value
==
nil
{
return
nil
,
nil
,
errors
.
New
(
fmt
.
Sprintf
(
"field `%s` cannot be NULL"
,
fi
.
fullName
))
}
}
}
}
if
fi
.
null
==
false
&&
value
==
nil
{
return
nil
,
errors
.
New
(
fmt
.
Sprintf
(
"field `%s` cannot be NULL"
,
fi
.
fullName
))
}
}
}
}
}
switch
fi
.
fieldType
{
}
case
TypeDateField
,
TypeDateTimeField
:
switch
fi
.
fieldType
{
if
fi
.
auto_now
||
fi
.
auto_now_add
&&
insert
{
case
TypeDateField
,
TypeDateTimeField
:
tnow
:=
time
.
Now
()
if
fi
.
auto_now
||
fi
.
auto_now_add
&&
insert
{
if
fi
.
fieldType
==
TypeDateField
{
tnow
:=
time
.
Now
()
d
.
ins
.
TimeToDB
(
&
tnow
,
DefaultTimeLoc
)
if
fi
.
fieldType
==
TypeDateField
{
}
else
{
d
.
ins
.
TimeToDB
(
&
tnow
,
DefaultTimeLoc
)
d
.
ins
.
TimeToDB
(
&
tnow
,
tz
)
}
else
{
}
d
.
ins
.
TimeToDB
(
&
tnow
,
tz
)
value
=
tnow
}
if
fi
.
isFielder
{
value
=
tnow
f
:=
field
.
Addr
()
.
Interface
()
.
(
Fielder
)
if
fi
.
isFielder
{
f
.
SetRaw
(
tnow
.
In
(
DefaultTimeLoc
)
)
f
:=
field
.
Addr
()
.
Interface
()
.
(
Fielder
)
}
else
{
f
.
SetRaw
(
tnow
.
In
(
DefaultTimeLoc
))
field
.
Set
(
reflect
.
ValueOf
(
tnow
.
In
(
DefaultTimeLoc
)))
}
else
{
}
field
.
Set
(
reflect
.
ValueOf
(
tnow
.
In
(
DefaultTimeLoc
)))
}
}
}
}
}
}
columns
=
append
(
columns
,
column
)
values
=
append
(
values
,
value
)
}
}
return
return
value
,
nil
}
}
func
(
d
*
dbBase
)
PrepareInsert
(
q
dbQuerier
,
mi
*
modelInfo
)
(
stmtQuerier
,
string
,
error
)
{
func
(
d
*
dbBase
)
PrepareInsert
(
q
dbQuerier
,
mi
*
modelInfo
)
(
stmtQuerier
,
string
,
error
)
{
...
@@ -250,6 +257,10 @@ func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.
...
@@ -250,6 +257,10 @@ func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.
return
0
,
err
return
0
,
err
}
}
return
d
.
InsertValue
(
q
,
mi
,
names
,
values
)
}
func
(
d
*
dbBase
)
InsertValue
(
q
dbQuerier
,
mi
*
modelInfo
,
names
[]
string
,
values
[]
interface
{})
(
int64
,
error
)
{
Q
:=
d
.
ins
.
TableQuote
()
Q
:=
d
.
ins
.
TableQuote
()
marks
:=
make
([]
string
,
len
(
names
))
marks
:=
make
([]
string
,
len
(
names
))
...
@@ -653,10 +664,12 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
...
@@ -653,10 +664,12 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
trefs
=
refs
[
len
(
tCols
)
:
]
trefs
=
refs
[
len
(
tCols
)
:
]
for
_
,
tbl
:=
range
tables
.
tables
{
for
_
,
tbl
:=
range
tables
.
tables
{
// loop selected tables
if
tbl
.
sel
{
if
tbl
.
sel
{
last
:=
mind
last
:=
mind
names
:=
""
names
:=
""
mmi
:=
mi
mmi
:=
mi
// loop cascade models
for
_
,
name
:=
range
tbl
.
names
{
for
_
,
name
:=
range
tbl
.
names
{
names
+=
name
names
+=
name
if
val
,
ok
:=
cacheV
[
names
];
ok
{
if
val
,
ok
:=
cacheV
[
names
];
ok
{
...
@@ -665,27 +678,30 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
...
@@ -665,27 +678,30 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
}
else
{
}
else
{
fi
:=
mmi
.
fields
.
GetByName
(
name
)
fi
:=
mmi
.
fields
.
GetByName
(
name
)
lastm
:=
mmi
lastm
:=
mmi
mmi
:=
fi
.
relModelInfo
mmi
=
fi
.
relModelInfo
field
:=
reflect
.
Indirect
(
last
.
Field
(
fi
.
fieldIndex
))
field
:=
last
if
field
.
IsValid
()
{
if
last
.
Kind
()
!=
reflect
.
Invalid
{
d
.
setColsValues
(
mmi
,
&
field
,
mmi
.
fields
.
dbcols
,
trefs
[
:
len
(
mmi
.
fields
.
dbcols
)],
tz
)
field
=
reflect
.
Indirect
(
last
.
Field
(
fi
.
fieldIndex
))
for
_
,
fi
:=
range
mmi
.
fields
.
fieldsReverse
{
if
field
.
IsValid
()
{
if
fi
.
inModel
&&
fi
.
reverseFieldInfo
.
mi
==
lastm
{
d
.
setColsValues
(
mmi
,
&
field
,
mmi
.
fields
.
dbcols
,
trefs
[
:
len
(
mmi
.
fields
.
dbcols
)],
tz
)
if
fi
.
reverseFieldInfo
!=
nil
{
for
_
,
fi
:=
range
mmi
.
fields
.
fieldsReverse
{
f
:=
field
.
Field
(
fi
.
fieldIndex
)
if
fi
.
inModel
&&
fi
.
reverseFieldInfo
.
mi
==
lastm
{
if
f
.
Kind
()
==
reflect
.
Ptr
{
if
fi
.
reverseFieldInfo
!=
nil
{
f
.
Set
(
last
.
Addr
())
f
:=
field
.
Field
(
fi
.
fieldIndex
)
if
f
.
Kind
()
==
reflect
.
Ptr
{
f
.
Set
(
last
.
Addr
())
}
}
}
}
}
}
}
last
=
field
}
}
cacheV
[
names
]
=
&
field
cacheM
[
names
]
=
mmi
last
=
field
}
}
trefs
=
trefs
[
len
(
mmi
.
fields
.
dbcols
)
:
]
cacheV
[
names
]
=
&
field
cacheM
[
names
]
=
mmi
}
}
}
}
trefs
=
trefs
[
len
(
mmi
.
fields
.
dbcols
)
:
]
}
}
}
}
...
...
orm/db_tables.go
View file @
d043ebcd
...
@@ -100,22 +100,29 @@ func (t *dbTables) parseRelated(rels []string, depth int) {
...
@@ -100,22 +100,29 @@ func (t *dbTables) parseRelated(rels []string, depth int) {
exs
=
strings
.
Split
(
s
,
ExprSep
)
exs
=
strings
.
Split
(
s
,
ExprSep
)
names
=
make
([]
string
,
0
,
len
(
exs
))
names
=
make
([]
string
,
0
,
len
(
exs
))
mmi
=
t
.
mi
mmi
=
t
.
mi
can
s
el
=
true
can
c
el
=
true
jtl
*
dbTable
jtl
*
dbTable
)
)
inner
:=
true
for
_
,
ex
:=
range
exs
{
for
_
,
ex
:=
range
exs
{
if
fi
,
ok
:=
mmi
.
fields
.
GetByAny
(
ex
);
ok
&&
fi
.
rel
&&
fi
.
fieldType
!=
RelManyToMany
{
if
fi
,
ok
:=
mmi
.
fields
.
GetByAny
(
ex
);
ok
&&
fi
.
rel
&&
fi
.
fieldType
!=
RelManyToMany
{
names
=
append
(
names
,
fi
.
name
)
names
=
append
(
names
,
fi
.
name
)
mmi
=
fi
.
relModelInfo
mmi
=
fi
.
relModelInfo
jt
:=
t
.
set
(
names
,
mmi
,
fi
,
fi
.
null
==
false
)
if
fi
.
null
{
inner
=
false
}
jt
:=
t
.
set
(
names
,
mmi
,
fi
,
inner
)
jt
.
jtl
=
jtl
jt
.
jtl
=
jtl
if
fi
.
reverse
{
if
fi
.
reverse
{
can
s
el
=
false
can
c
el
=
false
}
}
if
can
s
el
{
if
can
c
el
{
jt
.
sel
=
depth
>
0
jt
.
sel
=
depth
>
0
if
i
<
relsNum
{
if
i
<
relsNum
{
...
@@ -178,9 +185,8 @@ func (t *dbTables) getJoinSql() (join string) {
...
@@ -178,9 +185,8 @@ func (t *dbTables) getJoinSql() (join string) {
return
return
}
}
func
(
d
*
dbTables
)
parseExprs
(
mi
*
modelInfo
,
exprs
[]
string
)
(
index
,
name
string
,
info
*
fieldInfo
,
success
bool
)
{
func
(
t
*
dbTables
)
parseExprs
(
mi
*
modelInfo
,
exprs
[]
string
)
(
index
,
name
string
,
info
*
fieldInfo
,
success
bool
)
{
var
(
var
(
ffi
*
fieldInfo
jtl
*
dbTable
jtl
*
dbTable
mmi
=
mi
mmi
=
mi
)
)
...
@@ -188,73 +194,67 @@ func (d *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string
...
@@ -188,73 +194,67 @@ func (d *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string
num
:=
len
(
exprs
)
-
1
num
:=
len
(
exprs
)
-
1
names
:=
make
([]
string
,
0
)
names
:=
make
([]
string
,
0
)
inner
:=
true
for
i
,
ex
:=
range
exprs
{
for
i
,
ex
:=
range
exprs
{
exist
:=
false
check
:
fi
,
ok
:=
mmi
.
fields
.
GetByAny
(
ex
)
fi
,
ok
:=
mmi
.
fields
.
GetByAny
(
ex
)
if
ok
{
if
ok
{
if
num
!=
i
{
isRel
:=
fi
.
rel
||
fi
.
reverse
names
=
append
(
names
,
fi
.
name
)
switch
{
names
=
append
(
names
,
fi
.
name
)
case
fi
.
rel
:
mmi
=
fi
.
relModelInfo
if
fi
.
fieldType
==
RelManyToMany
{
mmi
=
fi
.
relThroughModelInfo
}
case
fi
.
reverse
:
mmi
=
fi
.
reverseFieldInfo
.
mi
if
fi
.
reverseFieldInfo
.
fieldType
==
RelManyToMany
{
mmi
=
fi
.
reverseFieldInfo
.
relThroughModelInfo
}
default
:
return
}
jt
,
_
:=
d
.
add
(
names
,
mmi
,
fi
,
fi
.
null
==
false
)
jt
.
jtl
=
jtl
jtl
=
jt
if
fi
.
rel
&&
fi
.
fieldType
==
RelManyToMany
{
switch
{
ex
=
fi
.
relModelInfo
.
name
case
fi
.
rel
:
goto
check
mmi
=
fi
.
relModelInfo
if
fi
.
fieldType
==
RelManyToMany
{
mmi
=
fi
.
relThroughModelInfo
}
}
case
fi
.
reverse
:
mmi
=
fi
.
reverseFieldInfo
.
mi
}
if
fi
.
reverse
&&
fi
.
reverseFieldInfo
.
fieldType
==
RelManyToMany
{
if
isRel
&&
(
fi
.
mi
.
isThrough
==
false
||
num
!=
i
)
{
ex
=
fi
.
reverseFieldInfo
.
mi
.
name
if
fi
.
null
{
goto
check
inner
=
false
}
}
exist
=
true
jt
,
_
:=
t
.
add
(
names
,
mmi
,
fi
,
inner
)
jt
.
jtl
=
jtl
}
else
{
jtl
=
jt
}
if
ffi
==
nil
{
if
num
==
i
{
if
i
==
0
||
jtl
==
nil
{
index
=
"T0"
index
=
"T0"
}
else
{
}
else
{
index
=
jtl
.
index
index
=
jtl
.
index
}
}
info
=
fi
info
=
fi
if
jtl
!=
nil
{
name
=
jtl
.
name
+
ExprSep
+
fi
.
name
if
jtl
==
nil
{
}
else
{
name
=
fi
.
name
name
=
fi
.
name
}
else
{
name
=
jtl
.
name
+
ExprSep
+
fi
.
name
}
}
switch
fi
.
fieldType
{
switch
{
case
RelManyToMany
,
RelReverseMany
:
case
fi
.
rel
:
default
:
exist
=
true
case
fi
.
reverse
:
switch
fi
.
reverseFieldInfo
.
fieldType
{
case
RelOneToOne
,
RelForeignKey
:
index
=
jtl
.
index
info
=
fi
.
reverseFieldInfo
.
mi
.
fields
.
pk
name
=
info
.
name
}
}
}
}
}
ffi
=
fi
}
else
{
}
if
exist
==
false
{
index
=
""
index
=
""
name
=
""
name
=
""
info
=
nil
info
=
nil
...
@@ -267,16 +267,15 @@ func (d *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string
...
@@ -267,16 +267,15 @@ func (d *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string
return
return
}
}
func
(
d
*
dbTables
)
getCondSql
(
cond
*
Condition
,
sub
bool
,
tz
*
time
.
Location
)
(
where
string
,
params
[]
interface
{})
{
func
(
t
*
dbTables
)
getCondSql
(
cond
*
Condition
,
sub
bool
,
tz
*
time
.
Location
)
(
where
string
,
params
[]
interface
{})
{
if
cond
==
nil
||
cond
.
IsEmpty
()
{
if
cond
==
nil
||
cond
.
IsEmpty
()
{
return
return
}
}
Q
:=
d
.
base
.
TableQuote
()
Q
:=
t
.
base
.
TableQuote
()
mi
:=
d
.
mi
mi
:=
t
.
mi
// outFor:
for
i
,
p
:=
range
cond
.
params
{
for
i
,
p
:=
range
cond
.
params
{
if
i
>
0
{
if
i
>
0
{
if
p
.
isOr
{
if
p
.
isOr
{
...
@@ -289,7 +288,7 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe
...
@@ -289,7 +288,7 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe
where
+=
"NOT "
where
+=
"NOT "
}
}
if
p
.
isCond
{
if
p
.
isCond
{
w
,
ps
:=
d
.
getCondSql
(
p
.
cond
,
true
,
tz
)
w
,
ps
:=
t
.
getCondSql
(
p
.
cond
,
true
,
tz
)
if
w
!=
""
{
if
w
!=
""
{
w
=
fmt
.
Sprintf
(
"( %s) "
,
w
)
w
=
fmt
.
Sprintf
(
"( %s) "
,
w
)
}
}
...
@@ -305,7 +304,7 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe
...
@@ -305,7 +304,7 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe
exprs
=
exprs
[
:
num
]
exprs
=
exprs
[
:
num
]
}
}
index
,
_
,
fi
,
suc
:=
d
.
parseExprs
(
mi
,
exprs
)
index
,
_
,
fi
,
suc
:=
t
.
parseExprs
(
mi
,
exprs
)
if
suc
==
false
{
if
suc
==
false
{
panic
(
fmt
.
Errorf
(
"unknown field/column name `%s`"
,
strings
.
Join
(
p
.
exprs
,
ExprSep
)))
panic
(
fmt
.
Errorf
(
"unknown field/column name `%s`"
,
strings
.
Join
(
p
.
exprs
,
ExprSep
)))
}
}
...
@@ -314,10 +313,10 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe
...
@@ -314,10 +313,10 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe
operator
=
"exact"
operator
=
"exact"
}
}
operSql
,
args
:=
d
.
base
.
GenerateOperatorSql
(
mi
,
fi
,
operator
,
p
.
args
,
tz
)
operSql
,
args
:=
t
.
base
.
GenerateOperatorSql
(
mi
,
fi
,
operator
,
p
.
args
,
tz
)
leftCol
:=
fmt
.
Sprintf
(
"%s.%s%s%s"
,
index
,
Q
,
fi
.
column
,
Q
)
leftCol
:=
fmt
.
Sprintf
(
"%s.%s%s%s"
,
index
,
Q
,
fi
.
column
,
Q
)
d
.
base
.
GenerateOperatorLeftCol
(
fi
,
operator
,
&
leftCol
)
t
.
base
.
GenerateOperatorLeftCol
(
fi
,
operator
,
&
leftCol
)
where
+=
fmt
.
Sprintf
(
"%s %s "
,
leftCol
,
operSql
)
where
+=
fmt
.
Sprintf
(
"%s %s "
,
leftCol
,
operSql
)
params
=
append
(
params
,
args
...
)
params
=
append
(
params
,
args
...
)
...
@@ -332,12 +331,12 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe
...
@@ -332,12 +331,12 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe
return
return
}
}
func
(
d
*
dbTables
)
getOrderSql
(
orders
[]
string
)
(
orderSql
string
)
{
func
(
t
*
dbTables
)
getOrderSql
(
orders
[]
string
)
(
orderSql
string
)
{
if
len
(
orders
)
==
0
{
if
len
(
orders
)
==
0
{
return
return
}
}
Q
:=
d
.
base
.
TableQuote
()
Q
:=
t
.
base
.
TableQuote
()
orderSqls
:=
make
([]
string
,
0
,
len
(
orders
))
orderSqls
:=
make
([]
string
,
0
,
len
(
orders
))
for
_
,
order
:=
range
orders
{
for
_
,
order
:=
range
orders
{
...
@@ -348,7 +347,7 @@ func (d *dbTables) getOrderSql(orders []string) (orderSql string) {
...
@@ -348,7 +347,7 @@ func (d *dbTables) getOrderSql(orders []string) (orderSql string) {
}
}
exprs
:=
strings
.
Split
(
order
,
ExprSep
)
exprs
:=
strings
.
Split
(
order
,
ExprSep
)
index
,
_
,
fi
,
suc
:=
d
.
parseExprs
(
d
.
mi
,
exprs
)
index
,
_
,
fi
,
suc
:=
t
.
parseExprs
(
t
.
mi
,
exprs
)
if
suc
==
false
{
if
suc
==
false
{
panic
(
fmt
.
Errorf
(
"unknown field/column name `%s`"
,
strings
.
Join
(
exprs
,
ExprSep
)))
panic
(
fmt
.
Errorf
(
"unknown field/column name `%s`"
,
strings
.
Join
(
exprs
,
ExprSep
)))
}
}
...
@@ -360,14 +359,14 @@ func (d *dbTables) getOrderSql(orders []string) (orderSql string) {
...
@@ -360,14 +359,14 @@ func (d *dbTables) getOrderSql(orders []string) (orderSql string) {
return
return
}
}
func
(
d
*
dbTables
)
getLimitSql
(
mi
*
modelInfo
,
offset
int64
,
limit
int64
)
(
limits
string
)
{
func
(
t
*
dbTables
)
getLimitSql
(
mi
*
modelInfo
,
offset
int64
,
limit
int64
)
(
limits
string
)
{
if
limit
==
0
{
if
limit
==
0
{
limit
=
int64
(
DefaultRowsLimit
)
limit
=
int64
(
DefaultRowsLimit
)
}
}
if
limit
<
0
{
if
limit
<
0
{
// no limit
// no limit
if
offset
>
0
{
if
offset
>
0
{
maxLimit
:=
d
.
base
.
MaxLimit
()
maxLimit
:=
t
.
base
.
MaxLimit
()
if
maxLimit
==
0
{
if
maxLimit
==
0
{
limits
=
fmt
.
Sprintf
(
"OFFSET %d"
,
offset
)
limits
=
fmt
.
Sprintf
(
"OFFSET %d"
,
offset
)
}
else
{
}
else
{
...
...
orm/models_boot.go
View file @
d043ebcd
...
@@ -121,7 +121,6 @@ func bootStrap() {
...
@@ -121,7 +121,6 @@ func bootStrap() {
err
=
errors
.
New
(
msg
)
err
=
errors
.
New
(
msg
)
goto
end
goto
end
}
}
err
=
nil
}
else
{
}
else
{
i
:=
newM2MModelInfo
(
mi
,
mii
)
i
:=
newM2MModelInfo
(
mi
,
mii
)
if
fi
.
relTable
!=
""
{
if
fi
.
relTable
!=
""
{
...
@@ -135,6 +134,8 @@ func bootStrap() {
...
@@ -135,6 +134,8 @@ func bootStrap() {
fi
.
relTable
=
i
.
table
fi
.
relTable
=
i
.
table
fi
.
relThroughModelInfo
=
i
fi
.
relThroughModelInfo
=
i
}
}
fi
.
relThroughModelInfo
.
isThrough
=
true
}
}
}
}
}
}
...
@@ -152,6 +153,7 @@ func bootStrap() {
...
@@ -152,6 +153,7 @@ func bootStrap() {
break
break
}
}
}
}
if
inModel
==
false
{
if
inModel
==
false
{
rmi
:=
fi
.
relModelInfo
rmi
:=
fi
.
relModelInfo
ffi
:=
new
(
fieldInfo
)
ffi
:=
new
(
fieldInfo
)
...
@@ -185,9 +187,34 @@ func bootStrap() {
...
@@ -185,9 +187,34 @@ func bootStrap() {
}
}
}
}
models
=
modelCache
.
all
()
for
_
,
mi
:=
range
models
{
for
_
,
mi
:=
range
models
{
if
fields
,
ok
:=
mi
.
fields
.
fieldsByType
[
RelReverseOne
];
ok
{
for
_
,
fi
:=
range
mi
.
fields
.
fieldsRel
{
for
_
,
fi
:=
range
fields
{
switch
fi
.
fieldType
{
case
RelManyToMany
:
for
_
,
ffi
:=
range
fi
.
relThroughModelInfo
.
fields
.
fieldsRel
{
switch
ffi
.
fieldType
{
case
RelOneToOne
,
RelForeignKey
:
if
ffi
.
relModelInfo
==
fi
.
relModelInfo
{
fi
.
reverseFieldInfoTwo
=
ffi
}
if
ffi
.
relModelInfo
==
mi
{
fi
.
reverseField
=
ffi
.
name
fi
.
reverseFieldInfo
=
ffi
}
}
}
if
fi
.
reverseFieldInfoTwo
==
nil
{
err
=
fmt
.
Errorf
(
"can not find m2m field for m2m model `%s`, ensure your m2m model defined correct"
,
fi
.
relThroughModelInfo
.
fullName
)
goto
end
}
}
}
for
_
,
fi
:=
range
mi
.
fields
.
fieldsReverse
{
switch
fi
.
fieldType
{
case
RelReverseOne
:
found
:=
false
found
:=
false
mForA
:
mForA
:
for
_
,
ffi
:=
range
fi
.
relModelInfo
.
fields
.
fieldsByType
[
RelOneToOne
]
{
for
_
,
ffi
:=
range
fi
.
relModelInfo
.
fields
.
fieldsByType
[
RelOneToOne
]
{
...
@@ -195,6 +222,9 @@ func bootStrap() {
...
@@ -195,6 +222,9 @@ func bootStrap() {
found
=
true
found
=
true
fi
.
reverseField
=
ffi
.
name
fi
.
reverseField
=
ffi
.
name
fi
.
reverseFieldInfo
=
ffi
fi
.
reverseFieldInfo
=
ffi
ffi
.
reverseField
=
fi
.
name
ffi
.
reverseFieldInfo
=
fi
break
mForA
break
mForA
}
}
}
}
...
@@ -202,10 +232,7 @@ func bootStrap() {
...
@@ -202,10 +232,7 @@ func bootStrap() {
err
=
fmt
.
Errorf
(
"reverse field `%s` not found in model `%s`"
,
fi
.
fullName
,
fi
.
relModelInfo
.
fullName
)
err
=
fmt
.
Errorf
(
"reverse field `%s` not found in model `%s`"
,
fi
.
fullName
,
fi
.
relModelInfo
.
fullName
)
goto
end
goto
end
}
}
}
case
RelReverseMany
:
}
if
fields
,
ok
:=
mi
.
fields
.
fieldsByType
[
RelReverseMany
];
ok
{
for
_
,
fi
:=
range
fields
{
found
:=
false
found
:=
false
mForB
:
mForB
:
for
_
,
ffi
:=
range
fi
.
relModelInfo
.
fields
.
fieldsByType
[
RelForeignKey
]
{
for
_
,
ffi
:=
range
fi
.
relModelInfo
.
fields
.
fieldsByType
[
RelForeignKey
]
{
...
@@ -213,6 +240,10 @@ func bootStrap() {
...
@@ -213,6 +240,10 @@ func bootStrap() {
found
=
true
found
=
true
fi
.
reverseField
=
ffi
.
name
fi
.
reverseField
=
ffi
.
name
fi
.
reverseFieldInfo
=
ffi
fi
.
reverseFieldInfo
=
ffi
ffi
.
reverseField
=
fi
.
name
ffi
.
reverseFieldInfo
=
fi
break
mForB
break
mForB
}
}
}
}
...
@@ -221,14 +252,20 @@ func bootStrap() {
...
@@ -221,14 +252,20 @@ func bootStrap() {
for
_
,
ffi
:=
range
fi
.
relModelInfo
.
fields
.
fieldsByType
[
RelManyToMany
]
{
for
_
,
ffi
:=
range
fi
.
relModelInfo
.
fields
.
fieldsByType
[
RelManyToMany
]
{
if
ffi
.
relModelInfo
==
mi
{
if
ffi
.
relModelInfo
==
mi
{
found
=
true
found
=
true
fi
.
reverseField
=
ffi
.
name
fi
.
reverseFieldInfo
=
ffi
fi
.
reverseField
=
ffi
.
reverseFieldInfoTwo
.
name
fi
.
reverseFieldInfo
=
ffi
.
reverseFieldInfoTwo
fi
.
relThroughModelInfo
=
ffi
.
relThroughModelInfo
fi
.
reverseFieldInfoTwo
=
ffi
.
reverseFieldInfo
fi
.
reverseFieldInfoM2M
=
ffi
ffi
.
reverseFieldInfoM2M
=
fi
break
mForC
break
mForC
}
}
}
}
}
}
if
found
==
false
{
if
found
==
false
{
err
=
fmt
.
Errorf
(
"reverse field `%s` not found in model `%s`"
,
fi
.
fullName
,
fi
.
relModelInfo
.
fullName
)
err
=
fmt
.
Errorf
(
"reverse field
for
`%s` not found in model `%s`"
,
fi
.
fullName
,
fi
.
relModelInfo
.
fullName
)
goto
end
goto
end
}
}
}
}
...
...
orm/models_info_f.go
View file @
d043ebcd
...
@@ -103,6 +103,8 @@ type fieldInfo struct {
...
@@ -103,6 +103,8 @@ type fieldInfo struct {
reverse
bool
reverse
bool
reverseField
string
reverseField
string
reverseFieldInfo
*
fieldInfo
reverseFieldInfo
*
fieldInfo
reverseFieldInfoTwo
*
fieldInfo
reverseFieldInfoM2M
*
fieldInfo
relTable
string
relTable
string
relThrough
string
relThrough
string
relThroughModelInfo
*
modelInfo
relThroughModelInfo
*
modelInfo
...
...
orm/models_info_m.go
View file @
d043ebcd
...
@@ -16,6 +16,8 @@ type modelInfo struct {
...
@@ -16,6 +16,8 @@ type modelInfo struct {
fields
*
fields
fields
*
fields
manual
bool
manual
bool
addrField
reflect
.
Value
addrField
reflect
.
Value
uniques
[]
string
isThrough
bool
}
}
func
newModelInfo
(
val
reflect
.
Value
)
(
info
*
modelInfo
)
{
func
newModelInfo
(
val
reflect
.
Value
)
(
info
*
modelInfo
)
{
...
@@ -118,5 +120,7 @@ func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) {
...
@@ -118,5 +120,7 @@ func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) {
info
.
fields
.
Add
(
f1
)
info
.
fields
.
Add
(
f1
)
info
.
fields
.
Add
(
f2
)
info
.
fields
.
Add
(
f2
)
info
.
fields
.
pk
=
fa
info
.
fields
.
pk
=
fa
info
.
uniques
=
[]
string
{
f1
.
column
,
f2
.
column
}
return
return
}
}
orm/models_test.go
View file @
d043ebcd
...
@@ -99,10 +99,11 @@ func NewUser() *User {
...
@@ -99,10 +99,11 @@ func NewUser() *User {
}
}
type
Profile
struct
{
type
Profile
struct
{
Id
int
Id
int
Age
int16
Age
int16
Money
float64
Money
float64
User
*
User
`orm:"reverse(one)" json:"-"`
User
*
User
`orm:"reverse(one)" json:"-"`
BestPost
*
Post
`orm:"rel(one);null"`
}
}
func
(
u
*
Profile
)
TableName
()
string
{
func
(
u
*
Profile
)
TableName
()
string
{
...
@@ -136,9 +137,10 @@ func NewPost() *Post {
...
@@ -136,9 +137,10 @@ func NewPost() *Post {
}
}
type
Tag
struct
{
type
Tag
struct
{
Id
int
Id
int
Name
string
`orm:"size(30)"`
Name
string
`orm:"size(30)"`
Posts
[]
*
Post
`orm:"reverse(many)" json:"-"`
BestPost
*
Post
`orm:"rel(one);null"`
Posts
[]
*
Post
`orm:"reverse(many)" json:"-"`
}
}
func
NewTag
()
*
Tag
{
func
NewTag
()
*
Tag
{
...
...
orm/orm.go
View file @
d043ebcd
...
@@ -18,7 +18,7 @@ var (
...
@@ -18,7 +18,7 @@ var (
Debug
=
false
Debug
=
false
DebugLog
=
NewLog
(
os
.
Stderr
)
DebugLog
=
NewLog
(
os
.
Stderr
)
DefaultRowsLimit
=
1000
DefaultRowsLimit
=
1000
DefaultRelsDepth
=
5
DefaultRelsDepth
=
2
DefaultTimeLoc
=
time
.
Local
DefaultTimeLoc
=
time
.
Local
ErrTxHasBegan
=
errors
.
New
(
"<Ormer.Begin> transaction already begin"
)
ErrTxHasBegan
=
errors
.
New
(
"<Ormer.Begin> transaction already begin"
)
ErrTxDone
=
errors
.
New
(
"<Ormer.Commit/Rollback> transaction not begin"
)
ErrTxDone
=
errors
.
New
(
"<Ormer.Commit/Rollback> transaction not begin"
)
...
@@ -53,6 +53,14 @@ func (o *orm) getMiInd(md interface{}) (mi *modelInfo, ind reflect.Value) {
...
@@ -53,6 +53,14 @@ func (o *orm) getMiInd(md interface{}) (mi *modelInfo, ind reflect.Value) {
panic
(
fmt
.
Errorf
(
"<Ormer> table: `%s` not found, maybe not RegisterModel"
,
name
))
panic
(
fmt
.
Errorf
(
"<Ormer> table: `%s` not found, maybe not RegisterModel"
,
name
))
}
}
func
(
o
*
orm
)
getFieldInfo
(
mi
*
modelInfo
,
name
string
)
*
fieldInfo
{
fi
,
ok
:=
mi
.
fields
.
GetByAny
(
name
)
if
!
ok
{
panic
(
fmt
.
Errorf
(
"<Ormer> cannot find field `%s` for model `%s`"
,
name
,
mi
.
fullName
))
}
return
fi
}
func
(
o
*
orm
)
Read
(
md
interface
{},
cols
...
string
)
error
{
func
(
o
*
orm
)
Read
(
md
interface
{},
cols
...
string
)
error
{
mi
,
ind
:=
o
.
getMiInd
(
md
)
mi
,
ind
:=
o
.
getMiInd
(
md
)
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
)
...
@@ -107,22 +115,152 @@ func (o *orm) Delete(md interface{}) (int64, error) {
...
@@ -107,22 +115,152 @@ func (o *orm) Delete(md interface{}) (int64, error) {
return
num
,
nil
return
num
,
nil
}
}
func
(
o
*
orm
)
M2mAdd
(
md
interface
{},
name
string
,
mds
...
interface
{})
(
int64
,
error
)
{
func
(
o
*
orm
)
QueryM2M
(
md
interface
{},
name
string
)
QueryM2Mer
{
// TODO
mi
,
ind
:=
o
.
getMiInd
(
md
)
panic
(
ErrNotImplement
)
fi
:=
o
.
getFieldInfo
(
mi
,
name
)
return
0
,
nil
if
fi
.
fieldType
!=
RelManyToMany
{
panic
(
fmt
.
Errorf
(
"<Ormer.QueryM2M> name `%s` for model `%s` is not a m2m field"
,
fi
.
name
,
mi
.
fullName
))
}
return
newQueryM2M
(
md
,
o
,
mi
,
fi
,
ind
)
}
func
(
o
*
orm
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
interface
{})
(
int64
,
error
)
{
_
,
fi
,
ind
,
qseter
:=
o
.
queryRelated
(
md
,
name
)
qs
:=
qseter
.
(
*
querySet
)
var
relDepth
int
var
limit
,
offset
int64
var
order
string
for
i
,
arg
:=
range
args
{
switch
i
{
case
0
:
if
v
,
ok
:=
arg
.
(
bool
);
ok
{
if
v
{
relDepth
=
DefaultRelsDepth
}
}
else
if
v
,
ok
:=
arg
.
(
int
);
ok
{
relDepth
=
v
}
case
1
:
limit
=
ToInt64
(
arg
)
case
2
:
offset
=
ToInt64
(
arg
)
case
3
:
order
,
_
=
arg
.
(
string
)
}
}
switch
fi
.
fieldType
{
case
RelOneToOne
,
RelForeignKey
,
RelReverseOne
:
limit
=
1
offset
=
0
}
qs
.
limit
=
limit
qs
.
offset
=
offset
qs
.
relDepth
=
relDepth
if
len
(
order
)
>
0
{
qs
.
orders
=
[]
string
{
order
}
}
find
:=
ind
.
Field
(
fi
.
fieldIndex
)
var
nums
int64
var
err
error
switch
fi
.
fieldType
{
case
RelOneToOne
,
RelForeignKey
,
RelReverseOne
:
val
:=
reflect
.
New
(
find
.
Type
()
.
Elem
())
container
:=
val
.
Interface
()
err
=
qs
.
One
(
container
)
if
err
==
nil
{
find
.
Set
(
val
)
nums
=
1
}
default
:
nums
,
err
=
qs
.
All
(
find
.
Addr
()
.
Interface
())
}
return
nums
,
err
}
func
(
o
*
orm
)
QueryRelated
(
md
interface
{},
name
string
)
QuerySeter
{
// is this api needed ?
_
,
_
,
_
,
qs
:=
o
.
queryRelated
(
md
,
name
)
return
qs
}
}
func
(
o
*
orm
)
M2mDel
(
md
interface
{},
name
string
,
mds
...
interface
{})
(
int64
,
error
)
{
func
(
o
*
orm
)
queryRelated
(
md
interface
{},
name
string
)
(
*
modelInfo
,
*
fieldInfo
,
reflect
.
Value
,
QuerySeter
)
{
// TODO
mi
,
ind
:=
o
.
getMiInd
(
md
)
panic
(
ErrNotImplement
)
fi
:=
o
.
getFieldInfo
(
mi
,
name
)
return
0
,
nil
_
,
_
,
exist
:=
getExistPk
(
mi
,
ind
)
if
exist
==
false
{
panic
(
ErrMissPK
)
}
var
qs
*
querySet
switch
fi
.
fieldType
{
case
RelOneToOne
,
RelForeignKey
,
RelManyToMany
:
if
!
fi
.
inModel
{
break
}
qs
=
o
.
getRelQs
(
md
,
mi
,
fi
)
case
RelReverseOne
,
RelReverseMany
:
if
!
fi
.
inModel
{
break
}
qs
=
o
.
getReverseQs
(
md
,
mi
,
fi
)
}
if
qs
==
nil
{
panic
(
fmt
.
Errorf
(
"<Ormer> name `%s` for model `%s` is not an available rel/reverse field"
))
}
return
mi
,
fi
,
ind
,
qs
}
func
(
o
*
orm
)
getReverseQs
(
md
interface
{},
mi
*
modelInfo
,
fi
*
fieldInfo
)
*
querySet
{
switch
fi
.
fieldType
{
case
RelReverseOne
,
RelReverseMany
:
default
:
panic
(
fmt
.
Errorf
(
"<Ormer> name `%s` for model `%s` is not an available reverse field"
,
fi
.
name
,
mi
.
fullName
))
}
var
q
*
querySet
if
fi
.
fieldType
==
RelReverseMany
&&
fi
.
reverseFieldInfo
.
mi
.
isThrough
{
q
=
newQuerySet
(
o
,
fi
.
relModelInfo
)
.
(
*
querySet
)
q
.
cond
=
NewCondition
()
.
And
(
fi
.
reverseFieldInfoM2M
.
column
+
ExprSep
+
fi
.
reverseFieldInfo
.
column
,
md
)
}
else
{
q
=
newQuerySet
(
o
,
fi
.
reverseFieldInfo
.
mi
)
.
(
*
querySet
)
q
.
cond
=
NewCondition
()
.
And
(
fi
.
reverseFieldInfo
.
column
,
md
)
}
return
q
}
}
func
(
o
*
orm
)
LoadRel
(
md
interface
{},
name
string
)
(
int64
,
error
)
{
func
(
o
*
orm
)
getRelQs
(
md
interface
{},
mi
*
modelInfo
,
fi
*
fieldInfo
)
*
querySet
{
// TODO
switch
fi
.
fieldType
{
panic
(
ErrNotImplement
)
case
RelOneToOne
,
RelForeignKey
,
RelManyToMany
:
return
0
,
nil
default
:
panic
(
fmt
.
Errorf
(
"<Ormer> name `%s` for model `%s` is not an available rel field"
,
fi
.
name
,
mi
.
fullName
))
}
q
:=
newQuerySet
(
o
,
fi
.
relModelInfo
)
.
(
*
querySet
)
q
.
cond
=
NewCondition
()
if
fi
.
fieldType
==
RelManyToMany
{
q
.
cond
=
q
.
cond
.
And
(
fi
.
reverseFieldInfoM2M
.
column
+
ExprSep
+
fi
.
reverseFieldInfo
.
column
,
md
)
}
else
{
q
.
cond
=
q
.
cond
.
And
(
fi
.
reverseFieldInfo
.
column
,
md
)
}
return
q
}
}
func
(
o
*
orm
)
QueryTable
(
ptrStructOrTableName
interface
{})
(
qs
QuerySeter
)
{
func
(
o
*
orm
)
QueryTable
(
ptrStructOrTableName
interface
{})
(
qs
QuerySeter
)
{
...
...
orm/orm_querym2m.go
0 → 100644
View file @
d043ebcd
package
orm
import
(
"reflect"
)
type
queryM2M
struct
{
md
interface
{}
mi
*
modelInfo
fi
*
fieldInfo
qs
*
querySet
ind
reflect
.
Value
}
func
(
o
*
queryM2M
)
Add
(
mds
...
interface
{})
(
int64
,
error
)
{
fi
:=
o
.
fi
mi
:=
fi
.
relThroughModelInfo
mfi
:=
fi
.
reverseFieldInfo
rfi
:=
fi
.
reverseFieldInfoTwo
orm
:=
o
.
qs
.
orm
dbase
:=
orm
.
alias
.
DbBaser
var
models
[]
interface
{}
for
_
,
md
:=
range
mds
{
val
:=
reflect
.
ValueOf
(
md
)
if
val
.
Kind
()
==
reflect
.
Slice
||
val
.
Kind
()
==
reflect
.
Array
{
for
i
:=
0
;
i
<
val
.
Len
();
i
++
{
v
:=
val
.
Index
(
i
)
if
v
.
CanInterface
()
{
models
=
append
(
models
,
v
.
Interface
())
}
}
}
else
{
models
=
append
(
models
,
md
)
}
}
_
,
v1
,
exist
:=
getExistPk
(
o
.
mi
,
o
.
ind
)
if
exist
==
false
{
panic
(
ErrMissPK
)
}
names
:=
[]
string
{
mfi
.
column
,
rfi
.
column
}
var
nums
int64
for
_
,
md
:=
range
models
{
ind
:=
reflect
.
Indirect
(
reflect
.
ValueOf
(
md
))
var
v2
interface
{}
if
ind
.
Kind
()
!=
reflect
.
Struct
{
v2
=
ind
.
Interface
()
}
else
{
_
,
v2
,
exist
=
getExistPk
(
fi
.
relModelInfo
,
ind
)
if
exist
==
false
{
panic
(
ErrMissPK
)
}
}
values
:=
[]
interface
{}{
v1
,
v2
}
_
,
err
:=
dbase
.
InsertValue
(
orm
.
db
,
mi
,
names
,
values
)
if
err
!=
nil
{
return
nums
,
err
}
nums
+=
1
}
return
nums
,
nil
}
func
(
o
*
queryM2M
)
Remove
(
mds
...
interface
{})
(
int64
,
error
)
{
fi
:=
o
.
fi
qs
:=
o
.
qs
.
Filter
(
fi
.
reverseFieldInfo
.
name
,
o
.
md
)
nums
,
err
:=
qs
.
Filter
(
fi
.
reverseFieldInfoTwo
.
name
+
ExprSep
+
"in"
,
mds
)
.
Delete
()
if
err
!=
nil
{
return
nums
,
err
}
return
nums
,
nil
}
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
()
}
func
(
o
*
queryM2M
)
Clear
()
(
int64
,
error
)
{
fi
:=
o
.
fi
return
o
.
qs
.
Filter
(
fi
.
reverseFieldInfo
.
name
,
o
.
md
)
.
Delete
()
}
func
(
o
*
queryM2M
)
Count
()
(
int64
,
error
)
{
fi
:=
o
.
fi
return
o
.
qs
.
Filter
(
fi
.
reverseFieldInfo
.
name
,
o
.
md
)
.
Count
()
}
var
_
QueryM2Mer
=
new
(
queryM2M
)
func
newQueryM2M
(
md
interface
{},
o
*
orm
,
mi
*
modelInfo
,
fi
*
fieldInfo
,
ind
reflect
.
Value
)
QueryM2Mer
{
qm2m
:=
new
(
queryM2M
)
qm2m
.
md
=
md
qm2m
.
mi
=
mi
qm2m
.
fi
=
fi
qm2m
.
ind
=
ind
qm2m
.
qs
=
newQuerySet
(
o
,
fi
.
relThroughModelInfo
)
.
(
*
querySet
)
return
qm2m
}
orm/orm_test.go
View file @
d043ebcd
...
@@ -48,9 +48,9 @@ func ValuesCompare(is bool, a interface{}, args ...interface{}) (err error, ok b
...
@@ -48,9 +48,9 @@ func ValuesCompare(is bool, a interface{}, args ...interface{}) (err error, ok b
ok
=
is
&&
ok
||
!
is
&&
!
ok
ok
=
is
&&
ok
||
!
is
&&
!
ok
if
!
ok
{
if
!
ok
{
if
is
{
if
is
{
err
=
fmt
.
Errorf
(
"expected:
a ==
`%v`, get `%v`"
,
b
,
a
)
err
=
fmt
.
Errorf
(
"expected: `%v`, get `%v`"
,
b
,
a
)
}
else
{
}
else
{
err
=
fmt
.
Errorf
(
"expected:
a !=
`%v`, get `%v`"
,
b
,
a
)
err
=
fmt
.
Errorf
(
"expected: `%v`, get `%v`"
,
b
,
a
)
}
}
}
}
...
@@ -419,7 +419,7 @@ func TestInsertTestData(t *testing.T) {
...
@@ -419,7 +419,7 @@ func TestInsertTestData(t *testing.T) {
throwFail
(
t
,
AssertIs
(
id
,
4
))
throwFail
(
t
,
AssertIs
(
id
,
4
))
tags
:=
[]
*
Tag
{
tags
:=
[]
*
Tag
{
&
Tag
{
Name
:
"golang"
},
&
Tag
{
Name
:
"golang"
,
BestPost
:
&
Post
{
Id
:
2
}
},
&
Tag
{
Name
:
"example"
},
&
Tag
{
Name
:
"example"
},
&
Tag
{
Name
:
"format"
},
&
Tag
{
Name
:
"format"
},
&
Tag
{
Name
:
"c++"
},
&
Tag
{
Name
:
"c++"
},
...
@@ -454,7 +454,13 @@ The program—and web server—godoc processes Go source files to extract docume
...
@@ -454,7 +454,13 @@ The program—and web server—godoc processes Go source files to extract docume
id
,
err
:=
dORM
.
Insert
(
post
)
id
,
err
:=
dORM
.
Insert
(
post
)
throwFail
(
t
,
err
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
id
>
0
,
true
))
throwFail
(
t
,
AssertIs
(
id
>
0
,
true
))
// dORM.M2mAdd(post, "tags", post.Tags)
num
:=
len
(
post
.
Tags
)
if
num
>
0
{
nums
,
err
:=
dORM
.
QueryM2M
(
post
,
"tags"
)
.
Add
(
post
.
Tags
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
nums
,
num
))
}
}
}
for
_
,
comment
:=
range
comments
{
for
_
,
comment
:=
range
comments
{
...
@@ -590,6 +596,68 @@ func TestOperators(t *testing.T) {
...
@@ -590,6 +596,68 @@ func TestOperators(t *testing.T) {
throwFail
(
t
,
AssertIs
(
num
,
2
))
throwFail
(
t
,
AssertIs
(
num
,
2
))
}
}
func
TestSetCond
(
t
*
testing
.
T
)
{
cond
:=
NewCondition
()
cond1
:=
cond
.
And
(
"profile__isnull"
,
false
)
.
AndNot
(
"status__in"
,
1
)
.
Or
(
"profile__age__gt"
,
2000
)
qs
:=
dORM
.
QueryTable
(
"user"
)
num
,
err
:=
qs
.
SetCond
(
cond1
)
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
cond2
:=
cond
.
AndCond
(
cond1
)
.
OrCond
(
cond
.
And
(
"user_name"
,
"slene"
))
num
,
err
=
qs
.
SetCond
(
cond2
)
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
2
))
}
func
TestLimit
(
t
*
testing
.
T
)
{
var
posts
[]
*
Post
qs
:=
dORM
.
QueryTable
(
"post"
)
num
,
err
:=
qs
.
Limit
(
1
)
.
All
(
&
posts
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
num
,
err
=
qs
.
Limit
(
-
1
)
.
All
(
&
posts
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
4
))
num
,
err
=
qs
.
Limit
(
-
1
,
2
)
.
All
(
&
posts
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
2
))
num
,
err
=
qs
.
Limit
(
0
,
2
)
.
All
(
&
posts
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
2
))
}
func
TestOffset
(
t
*
testing
.
T
)
{
var
posts
[]
*
Post
qs
:=
dORM
.
QueryTable
(
"post"
)
num
,
err
:=
qs
.
Limit
(
1
)
.
Offset
(
2
)
.
All
(
&
posts
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
num
,
err
=
qs
.
Offset
(
2
)
.
All
(
&
posts
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
2
))
}
func
TestOrderBy
(
t
*
testing
.
T
)
{
qs
:=
dORM
.
QueryTable
(
"user"
)
num
,
err
:=
qs
.
OrderBy
(
"-status"
)
.
Filter
(
"user_name"
,
"nobody"
)
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
num
,
err
=
qs
.
OrderBy
(
"status"
)
.
Filter
(
"user_name"
,
"slene"
)
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
num
,
err
=
qs
.
OrderBy
(
"-profile__age"
)
.
Filter
(
"user_name"
,
"astaxie"
)
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
}
func
TestAll
(
t
*
testing
.
T
)
{
func
TestAll
(
t
*
testing
.
T
)
{
var
users
[]
*
User
var
users
[]
*
User
qs
:=
dORM
.
QueryTable
(
"user"
)
qs
:=
dORM
.
QueryTable
(
"user"
)
...
@@ -758,66 +826,292 @@ func TestRelatedSel(t *testing.T) {
...
@@ -758,66 +826,292 @@ func TestRelatedSel(t *testing.T) {
throwFailNow
(
t
,
AssertIs
(
posts
[
3
]
.
User
.
UserName
,
"nobody"
))
throwFailNow
(
t
,
AssertIs
(
posts
[
3
]
.
User
.
UserName
,
"nobody"
))
}
}
func
TestSetCond
(
t
*
testing
.
T
)
{
func
TestReverseQuery
(
t
*
testing
.
T
)
{
cond
:=
NewCondition
()
var
profile
Profile
cond1
:=
cond
.
And
(
"profile__isnull"
,
false
)
.
AndNot
(
"status__in"
,
1
)
.
Or
(
"profile__age__gt"
,
2000
)
err
:=
dORM
.
QueryTable
(
"user_profile"
)
.
Filter
(
"User"
,
3
)
.
One
(
&
profile
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
profile
.
Age
,
30
))
qs
:=
dORM
.
QueryTable
(
"user"
)
profile
=
Profile
{}
num
,
err
:=
qs
.
SetCond
(
cond1
)
.
Count
(
)
err
=
dORM
.
QueryTable
(
"user_profile"
)
.
Filter
(
"User__UserName"
,
"astaxie"
)
.
One
(
&
profile
)
throwFail
(
t
,
err
)
throwFail
Now
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
throwFail
Now
(
t
,
AssertIs
(
profile
.
Age
,
30
))
cond2
:=
cond
.
AndCond
(
cond1
)
.
OrCond
(
cond
.
And
(
"user_name"
,
"slene"
))
var
user
User
num
,
err
=
qs
.
SetCond
(
cond2
)
.
Count
()
err
=
dORM
.
QueryTable
(
"user"
)
.
Filter
(
"Posts__Title"
,
"Examples"
)
.
One
(
&
user
)
throwFail
(
t
,
err
)
throwFailNow
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
2
))
throwFailNow
(
t
,
AssertIs
(
user
.
UserName
,
"astaxie"
))
}
user
=
User
{}
err
=
dORM
.
QueryTable
(
"user"
)
.
Filter
(
"Posts__User__UserName"
,
"astaxie"
)
.
Limit
(
1
)
.
One
(
&
user
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
user
.
UserName
,
"astaxie"
))
user
=
User
{}
err
=
dORM
.
QueryTable
(
"user"
)
.
Filter
(
"Posts__User__UserName"
,
"astaxie"
)
.
RelatedSel
()
.
Limit
(
1
)
.
One
(
&
user
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
user
.
UserName
,
"astaxie"
))
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
.
Age
,
30
))
func
TestLimit
(
t
*
testing
.
T
)
{
var
posts
[]
*
Post
var
posts
[]
*
Post
qs
:=
dORM
.
QueryTable
(
"post"
)
num
,
err
:=
dORM
.
QueryTable
(
"post"
)
.
Filter
(
"Tags__Tag__Name"
,
"golang"
)
.
All
(
&
posts
)
num
,
err
:=
qs
.
Limit
(
1
)
.
All
(
&
posts
)
throwFailNow
(
t
,
err
)
throwFail
(
t
,
err
)
throwFail
Now
(
t
,
AssertIs
(
num
,
3
)
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
throwFail
Now
(
t
,
AssertIs
(
posts
[
0
]
.
Title
,
"Introduction"
))
num
,
err
=
qs
.
Limit
(
-
1
)
.
All
(
&
posts
)
posts
=
[]
*
Post
{}
throwFail
(
t
,
err
)
num
,
err
=
dORM
.
QueryTable
(
"post"
)
.
Filter
(
"Tags__Tag__Name"
,
"golang"
)
.
Filter
(
"User__UserName"
,
"slene"
)
.
All
(
&
posts
)
throwFail
(
t
,
AssertIs
(
num
,
4
))
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
posts
[
0
]
.
Title
,
"Introduction"
))
num
,
err
=
qs
.
Limit
(
-
1
,
2
)
.
All
(
&
posts
)
posts
=
[]
*
Post
{}
throwFail
(
t
,
err
)
num
,
err
=
dORM
.
QueryTable
(
"post"
)
.
Filter
(
"Tags__Tag__Name"
,
"golang"
)
.
throwFail
(
t
,
AssertIs
(
num
,
2
))
Filter
(
"User__UserName"
,
"slene"
)
.
RelatedSel
()
.
All
(
&
posts
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
posts
[
0
]
.
User
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
posts
[
0
]
.
User
.
UserName
,
"slene"
))
num
,
err
=
qs
.
Limit
(
0
,
2
)
.
All
(
&
posts
)
var
tags
[]
*
Tag
throwFail
(
t
,
err
)
num
,
err
=
dORM
.
QueryTable
(
"tag"
)
.
Filter
(
"Posts__Post__Title"
,
"Introduction"
)
.
All
(
&
tags
)
throwFail
(
t
,
AssertIs
(
num
,
2
))
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
tags
[
0
]
.
Name
,
"golang"
))
tags
=
[]
*
Tag
{}
num
,
err
=
dORM
.
QueryTable
(
"tag"
)
.
Filter
(
"Posts__Post__Title"
,
"Introduction"
)
.
Filter
(
"BestPost__User__UserName"
,
"astaxie"
)
.
All
(
&
tags
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
tags
[
0
]
.
Name
,
"golang"
))
tags
=
[]
*
Tag
{}
num
,
err
=
dORM
.
QueryTable
(
"tag"
)
.
Filter
(
"Posts__Post__Title"
,
"Introduction"
)
.
Filter
(
"BestPost__User__UserName"
,
"astaxie"
)
.
RelatedSel
()
.
All
(
&
tags
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
tags
[
0
]
.
Name
,
"golang"
))
throwFailNow
(
t
,
AssertIs
(
tags
[
0
]
.
BestPost
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
tags
[
0
]
.
BestPost
.
Title
,
"Examples"
))
throwFailNow
(
t
,
AssertIs
(
tags
[
0
]
.
BestPost
.
User
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
tags
[
0
]
.
BestPost
.
User
.
UserName
,
"astaxie"
))
}
}
func
TestOffset
(
t
*
testing
.
T
)
{
func
TestLoadRelated
(
t
*
testing
.
T
)
{
var
posts
[]
*
Post
// load reverse foreign key
qs
:=
dORM
.
QueryTable
(
"post"
)
user
:=
User
{
Id
:
3
}
num
,
err
:=
qs
.
Limit
(
1
)
.
Offset
(
2
)
.
All
(
&
posts
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
num
,
err
=
qs
.
Offset
(
2
)
.
All
(
&
posts
)
err
:=
dORM
.
Read
(
&
user
)
throwFail
(
t
,
err
)
throwFailNow
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
2
))
num
,
err
:=
dORM
.
LoadRelated
(
&
user
,
"Posts"
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
2
))
throwFailNow
(
t
,
AssertIs
(
len
(
user
.
Posts
),
2
))
throwFailNow
(
t
,
AssertIs
(
user
.
Posts
[
0
]
.
User
.
Id
,
3
))
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
true
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
len
(
user
.
Posts
),
2
))
throwFailNow
(
t
,
AssertIs
(
user
.
Posts
[
0
]
.
User
.
UserName
,
"astaxie"
))
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
true
,
1
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
len
(
user
.
Posts
),
1
))
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
true
,
0
,
0
,
"-Id"
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
len
(
user
.
Posts
),
2
))
throwFailNow
(
t
,
AssertIs
(
user
.
Posts
[
0
]
.
Title
,
"Formatting"
))
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
true
,
1
,
1
,
"Id"
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
len
(
user
.
Posts
),
1
))
throwFailNow
(
t
,
AssertIs
(
user
.
Posts
[
0
]
.
Title
,
"Formatting"
))
// load reverse one to one
profile
:=
Profile
{
Id
:
3
}
profile
.
BestPost
=
&
Post
{
Id
:
2
}
num
,
err
=
dORM
.
Update
(
&
profile
,
"BestPost"
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
err
=
dORM
.
Read
(
&
profile
)
throwFailNow
(
t
,
err
)
num
,
err
=
dORM
.
LoadRelated
(
&
profile
,
"User"
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
profile
.
User
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
profile
.
User
.
UserName
,
"astaxie"
))
num
,
err
=
dORM
.
LoadRelated
(
&
profile
,
"User"
,
true
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
profile
.
User
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
profile
.
User
.
UserName
,
"astaxie"
))
throwFailNow
(
t
,
AssertIs
(
profile
.
User
.
Profile
.
Age
,
profile
.
Age
))
// load rel one to one
err
=
dORM
.
Read
(
&
user
)
throwFailNow
(
t
,
err
)
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Profile"
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
.
Age
,
30
))
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Profile"
,
true
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
.
Age
,
30
))
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
.
BestPost
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
.
BestPost
.
Title
,
"Examples"
))
post
:=
Post
{
Id
:
2
}
// load rel foreign key
err
=
dORM
.
Read
(
&
post
)
throwFailNow
(
t
,
err
)
num
,
err
=
dORM
.
LoadRelated
(
&
post
,
"User"
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
post
.
User
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
post
.
User
.
UserName
,
"astaxie"
))
num
,
err
=
dORM
.
LoadRelated
(
&
post
,
"User"
,
true
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
post
.
User
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
post
.
User
.
UserName
,
"astaxie"
))
throwFailNow
(
t
,
AssertIs
(
post
.
User
.
Profile
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
post
.
User
.
Profile
.
Age
,
30
))
// load rel m2m
post
=
Post
{
Id
:
2
}
err
=
dORM
.
Read
(
&
post
)
throwFailNow
(
t
,
err
)
num
,
err
=
dORM
.
LoadRelated
(
&
post
,
"Tags"
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
2
))
throwFailNow
(
t
,
AssertIs
(
len
(
post
.
Tags
),
2
))
throwFailNow
(
t
,
AssertIs
(
post
.
Tags
[
0
]
.
Name
,
"golang"
))
num
,
err
=
dORM
.
LoadRelated
(
&
post
,
"Tags"
,
true
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
2
))
throwFailNow
(
t
,
AssertIs
(
len
(
post
.
Tags
),
2
))
throwFailNow
(
t
,
AssertIs
(
post
.
Tags
[
0
]
.
Name
,
"golang"
))
throwFailNow
(
t
,
AssertIs
(
post
.
Tags
[
0
]
.
BestPost
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
post
.
Tags
[
0
]
.
BestPost
.
User
.
UserName
,
"astaxie"
))
// load reverse m2m
tag
:=
Tag
{
Id
:
1
}
err
=
dORM
.
Read
(
&
tag
)
throwFailNow
(
t
,
err
)
num
,
err
=
dORM
.
LoadRelated
(
&
tag
,
"Posts"
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
3
))
throwFailNow
(
t
,
AssertIs
(
tag
.
Posts
[
0
]
.
Title
,
"Introduction"
))
throwFailNow
(
t
,
AssertIs
(
tag
.
Posts
[
0
]
.
User
.
Id
,
2
))
throwFailNow
(
t
,
AssertIs
(
tag
.
Posts
[
0
]
.
User
.
Profile
==
nil
,
true
))
num
,
err
=
dORM
.
LoadRelated
(
&
tag
,
"Posts"
,
true
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
3
))
throwFailNow
(
t
,
AssertIs
(
tag
.
Posts
[
0
]
.
Title
,
"Introduction"
))
throwFailNow
(
t
,
AssertIs
(
tag
.
Posts
[
0
]
.
User
.
Id
,
2
))
throwFailNow
(
t
,
AssertIs
(
tag
.
Posts
[
0
]
.
User
.
UserName
,
"slene"
))
}
}
func
TestOrderBy
(
t
*
testing
.
T
)
{
func
TestQueryM2M
(
t
*
testing
.
T
)
{
qs
:=
dORM
.
QueryTable
(
"user"
)
post
:=
Post
{
Id
:
4
}
num
,
err
:=
qs
.
OrderBy
(
"-status"
)
.
Filter
(
"user_name"
,
"nobody"
)
.
Count
()
m2m
:=
dORM
.
QueryM2M
(
&
post
,
"Tags"
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
num
,
err
=
qs
.
OrderBy
(
"status"
)
.
Filter
(
"user_name"
,
"slene"
)
.
Count
()
tag1
:=
[]
*
Tag
{
&
Tag
{
Name
:
"TestTag1"
},
&
Tag
{
Name
:
"TestTag2"
}}
t
hrowFail
(
t
,
err
)
t
ag2
:=
&
Tag
{
Name
:
"TestTag3"
}
t
hrowFail
(
t
,
AssertIs
(
num
,
1
))
t
ag3
:=
[]
interface
{}{
&
Tag
{
Name
:
"TestTag4"
}}
num
,
err
=
qs
.
OrderBy
(
"-profile__age"
)
.
Filter
(
"user_name"
,
"astaxie"
)
.
Count
()
tags
:=
[]
interface
{}{
tag1
[
0
],
tag1
[
1
],
tag2
,
tag3
[
0
]}
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
for
_
,
tag
:=
range
tags
{
_
,
err
:=
dORM
.
Insert
(
tag
)
throwFailNow
(
t
,
err
)
}
num
,
err
:=
m2m
.
Add
(
tag1
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
2
))
num
,
err
=
m2m
.
Add
(
tag2
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
num
,
err
=
m2m
.
Add
(
tag3
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
num
,
err
=
m2m
.
Count
()
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
5
))
num
,
err
=
m2m
.
Remove
(
tag3
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
num
,
err
=
m2m
.
Count
()
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
4
))
exist
:=
m2m
.
Exist
(
tag2
)
throwFailNow
(
t
,
AssertIs
(
exist
,
true
))
num
,
err
=
m2m
.
Remove
(
tag2
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
exist
=
m2m
.
Exist
(
tag2
)
throwFailNow
(
t
,
AssertIs
(
exist
,
false
))
num
,
err
=
m2m
.
Count
()
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
3
))
num
,
err
=
m2m
.
Clear
()
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
3
))
num
,
err
=
m2m
.
Count
()
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
0
))
}
func
TestQueryRelate
(
t
*
testing
.
T
)
{
// post := &Post{Id: 2}
// qs := dORM.QueryRelate(post, "Tags")
// num, err := qs.Count()
// throwFailNow(t, err)
// throwFailNow(t, AssertIs(num, 2))
// var tags []*Tag
// num, err = qs.All(&tags)
// throwFailNow(t, err)
// throwFailNow(t, AssertIs(num, 2))
// throwFailNow(t, AssertIs(tags[0].Name, "golang"))
// num, err = dORM.QueryTable("Tag").Filter("Posts__Post", 2).Count()
// throwFailNow(t, err)
// throwFailNow(t, AssertIs(num, 2))
}
}
func
TestPrepareInsert
(
t
*
testing
.
T
)
{
func
TestPrepareInsert
(
t
*
testing
.
T
)
{
...
...
orm/types.go
View file @
d043ebcd
...
@@ -24,9 +24,8 @@ type Ormer interface {
...
@@ -24,9 +24,8 @@ type Ormer interface {
Insert
(
interface
{})
(
int64
,
error
)
Insert
(
interface
{})
(
int64
,
error
)
Update
(
interface
{},
...
string
)
(
int64
,
error
)
Update
(
interface
{},
...
string
)
(
int64
,
error
)
Delete
(
interface
{})
(
int64
,
error
)
Delete
(
interface
{})
(
int64
,
error
)
M2mAdd
(
interface
{},
string
,
...
interface
{})
(
int64
,
error
)
LoadRelated
(
interface
{},
string
,
...
interface
{})
(
int64
,
error
)
M2mDel
(
interface
{},
string
,
...
interface
{})
(
int64
,
error
)
QueryM2M
(
interface
{},
string
)
QueryM2Mer
LoadRel
(
interface
{},
string
)
(
int64
,
error
)
QueryTable
(
interface
{})
QuerySeter
QueryTable
(
interface
{})
QuerySeter
Using
(
string
)
error
Using
(
string
)
error
Begin
()
error
Begin
()
error
...
@@ -61,6 +60,14 @@ type QuerySeter interface {
...
@@ -61,6 +60,14 @@ type QuerySeter interface {
ValuesFlat
(
*
ParamsList
,
string
)
(
int64
,
error
)
ValuesFlat
(
*
ParamsList
,
string
)
(
int64
,
error
)
}
}
type
QueryM2Mer
interface
{
Add
(
...
interface
{})
(
int64
,
error
)
Remove
(
...
interface
{})
(
int64
,
error
)
Exist
(
interface
{})
bool
Clear
()
(
int64
,
error
)
Count
()
(
int64
,
error
)
}
type
RawPreparer
interface
{
type
RawPreparer
interface
{
Exec
(
...
interface
{})
(
sql
.
Result
,
error
)
Exec
(
...
interface
{})
(
sql
.
Result
,
error
)
Close
()
error
Close
()
error
...
@@ -114,6 +121,7 @@ type txEnder interface {
...
@@ -114,6 +121,7 @@ type txEnder interface {
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
)
InsertValue
(
dbQuerier
,
*
modelInfo
,
[]
string
,
[]
interface
{})
(
int64
,
error
)
InsertStmt
(
stmtQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
(
int64
,
error
)
InsertStmt
(
stmtQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
(
int64
,
error
)
Update
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
,
[]
string
)
(
int64
,
error
)
Update
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
,
[]
string
)
(
int64
,
error
)
Delete
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
(
int64
,
error
)
Delete
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
(
int64
,
error
)
...
@@ -139,4 +147,5 @@ type dbBaser interface {
...
@@ -139,4 +147,5 @@ type dbBaser interface {
ShowTablesQuery
()
string
ShowTablesQuery
()
string
ShowColumnsQuery
(
string
)
string
ShowColumnsQuery
(
string
)
string
IndexExists
(
dbQuerier
,
string
,
string
)
bool
IndexExists
(
dbQuerier
,
string
,
string
)
bool
collectFieldValue
(
*
modelInfo
,
*
fieldInfo
,
reflect
.
Value
,
bool
,
*
time
.
Location
)
(
interface
{},
error
)
}
}
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