Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
二次元的罪恶王冠
beego
提交
5a1fa4e1
B
beego
项目概览
二次元的罪恶王冠
/
beego
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
B
beego
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5a1fa4e1
编写于
8月 10, 2020
作者:
J
jianzhiyao
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
specify index
上级
d0546023
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
499 addition
and
113 deletion
+499
-113
pkg/common/kv.go
pkg/common/kv.go
+30
-8
pkg/orm/db.go
pkg/orm/db.go
+53
-11
pkg/orm/db_alias.go
pkg/orm/db_alias.go
+7
-6
pkg/orm/db_alias_test.go
pkg/orm/db_alias_test.go
+8
-7
pkg/orm/db_oracle.go
pkg/orm/db_oracle.go
+24
-0
pkg/orm/db_postgres.go
pkg/orm/db_postgres.go
+7
-0
pkg/orm/db_sqlite.go
pkg/orm/db_sqlite.go
+21
-0
pkg/orm/db_tables.go
pkg/orm/db_tables.go
+9
-0
pkg/orm/do_nothing_orm.go
pkg/orm/do_nothing_orm.go
+3
-2
pkg/orm/filter_orm_decorator.go
pkg/orm/filter_orm_decorator.go
+3
-2
pkg/orm/filter_orm_decorator_test.go
pkg/orm/filter_orm_decorator_test.go
+2
-1
pkg/orm/hints/db_hints.go
pkg/orm/hints/db_hints.go
+68
-12
pkg/orm/hints/db_hints_test.go
pkg/orm/hints/db_hints_test.go
+154
-0
pkg/orm/models_test.go
pkg/orm/models_test.go
+2
-1
pkg/orm/orm.go
pkg/orm/orm.go
+25
-19
pkg/orm/orm_log.go
pkg/orm/orm_log.go
+5
-20
pkg/orm/orm_queryset.go
pkg/orm/orm_queryset.go
+26
-2
pkg/orm/orm_test.go
pkg/orm/orm_test.go
+18
-9
pkg/orm/types.go
pkg/orm/types.go
+34
-13
未找到文件。
pkg/common/kv.go
浏览文件 @
5a1fa4e1
...
...
@@ -36,14 +36,25 @@ func (s *SimpleKV) GetValue() interface{} {
return
s
.
Value
}
// KVs will store SimpleKV collection as map
type
KVs
struct
{
// KVs interface
type
KVs
interface
{
GetValueOr
(
key
interface
{},
defValue
interface
{})
interface
{}
Contains
(
key
interface
{})
bool
IfContains
(
key
interface
{},
action
func
(
value
interface
{}))
KVs
Put
(
key
interface
{},
value
interface
{})
KVs
Clone
()
KVs
}
// SimpleKVs will store SimpleKV collection as map
type
SimpleKVs
struct
{
kvs
map
[
interface
{}]
interface
{}
}
var
_
KVs
=
new
(
SimpleKVs
)
// GetValueOr returns the value for a given key, if non-existant
// it returns defValue
func
(
kvs
*
KVs
)
GetValueOr
(
key
interface
{},
defValue
interface
{})
interface
{}
{
func
(
kvs
*
Simple
KVs
)
GetValueOr
(
key
interface
{},
defValue
interface
{})
interface
{}
{
v
,
ok
:=
kvs
.
kvs
[
key
]
if
ok
{
return
v
...
...
@@ -52,13 +63,13 @@ func (kvs *KVs) GetValueOr(key interface{}, defValue interface{}) interface{} {
}
// Contains checks if a key exists
func
(
kvs
*
KVs
)
Contains
(
key
interface
{})
bool
{
func
(
kvs
*
Simple
KVs
)
Contains
(
key
interface
{})
bool
{
_
,
ok
:=
kvs
.
kvs
[
key
]
return
ok
}
// IfContains invokes the action on a key if it exists
func
(
kvs
*
KVs
)
IfContains
(
key
interface
{},
action
func
(
value
interface
{}))
*
KVs
{
func
(
kvs
*
SimpleKVs
)
IfContains
(
key
interface
{},
action
func
(
value
interface
{}))
KVs
{
v
,
ok
:=
kvs
.
kvs
[
key
]
if
ok
{
action
(
v
)
...
...
@@ -67,14 +78,25 @@ func (kvs *KVs) IfContains(key interface{}, action func(value interface{})) *KVs
}
// Put stores the value
func
(
kvs
*
KVs
)
Put
(
key
interface
{},
value
interface
{})
*
KVs
{
func
(
kvs
*
SimpleKVs
)
Put
(
key
interface
{},
value
interface
{})
KVs
{
kvs
.
kvs
[
key
]
=
value
return
kvs
}
// Clone
func
(
kvs
*
SimpleKVs
)
Clone
()
KVs
{
newKVs
:=
new
(
SimpleKVs
)
for
key
,
value
:=
range
kvs
.
kvs
{
newKVs
.
Put
(
key
,
value
)
}
return
newKVs
}
// NewKVs creates the *KVs instance
func
NewKVs
(
kvs
...
KV
)
*
KVs
{
res
:=
&
KVs
{
func
NewKVs
(
kvs
...
KV
)
KVs
{
res
:=
&
Simple
KVs
{
kvs
:
make
(
map
[
interface
{}]
interface
{},
len
(
kvs
)),
}
for
_
,
kv
:=
range
kvs
{
...
...
pkg/orm/db.go
浏览文件 @
5a1fa4e1
...
...
@@ -18,6 +18,7 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"reflect"
"strings"
"time"
...
...
@@ -738,8 +739,10 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
}
tables
:=
newDbTables
(
mi
,
d
.
ins
)
var
specifyIndexes
string
if
qs
!=
nil
{
tables
.
parseRelated
(
qs
.
related
,
qs
.
relDepth
)
specifyIndexes
=
tables
.
getIndexSql
(
mi
.
table
,
qs
.
useIndex
,
qs
.
indexes
)
}
where
,
args
:=
tables
.
getCondSQL
(
cond
,
false
,
tz
)
...
...
@@ -790,9 +793,12 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
sets
:=
strings
.
Join
(
cols
,
", "
)
+
" "
if
d
.
ins
.
SupportUpdateJoin
()
{
query
=
fmt
.
Sprintf
(
"UPDATE %s%s%s T0 %s
SET %s%s"
,
Q
,
mi
.
table
,
Q
,
join
,
sets
,
where
)
query
=
fmt
.
Sprintf
(
"UPDATE %s%s%s T0 %s
%sSET %s%s"
,
Q
,
mi
.
table
,
Q
,
specifyIndexes
,
join
,
sets
,
where
)
}
else
{
supQuery
:=
fmt
.
Sprintf
(
"SELECT T0.%s%s%s FROM %s%s%s T0 %s%s"
,
Q
,
mi
.
fields
.
pk
.
column
,
Q
,
Q
,
mi
.
table
,
Q
,
join
,
where
)
supQuery
:=
fmt
.
Sprintf
(
"SELECT T0.%s%s%s FROM %s%s%s T0 %s%s%s"
,
Q
,
mi
.
fields
.
pk
.
column
,
Q
,
Q
,
mi
.
table
,
Q
,
specifyIndexes
,
join
,
where
)
query
=
fmt
.
Sprintf
(
"UPDATE %s%s%s SET %sWHERE %s%s%s IN ( %s )"
,
Q
,
mi
.
table
,
Q
,
sets
,
Q
,
mi
.
fields
.
pk
.
column
,
Q
,
supQuery
)
}
...
...
@@ -843,8 +849,10 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
tables
:=
newDbTables
(
mi
,
d
.
ins
)
tables
.
skipEnd
=
true
var
specifyIndexes
string
if
qs
!=
nil
{
tables
.
parseRelated
(
qs
.
related
,
qs
.
relDepth
)
specifyIndexes
=
tables
.
getIndexSql
(
mi
.
table
,
qs
.
useIndex
,
qs
.
indexes
)
}
if
cond
==
nil
||
cond
.
IsEmpty
()
{
...
...
@@ -857,7 +865,7 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
join
:=
tables
.
getJoinSQL
()
cols
:=
fmt
.
Sprintf
(
"T0.%s%s%s"
,
Q
,
mi
.
fields
.
pk
.
column
,
Q
)
query
:=
fmt
.
Sprintf
(
"SELECT %s FROM %s%s%s T0 %s%s
"
,
cols
,
Q
,
mi
.
table
,
Q
,
join
,
where
)
query
:=
fmt
.
Sprintf
(
"SELECT %s FROM %s%s%s T0 %s%s
%s"
,
cols
,
Q
,
mi
.
table
,
Q
,
specifyIndexes
,
join
,
where
)
d
.
ins
.
ReplaceMarks
(
&
query
)
...
...
@@ -1002,6 +1010,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
orderBy
:=
tables
.
getOrderSQL
(
qs
.
orders
)
limit
:=
tables
.
getLimitSQL
(
mi
,
offset
,
rlimit
)
join
:=
tables
.
getJoinSQL
()
specifyIndexes
:=
tables
.
getIndexSql
(
mi
.
table
,
qs
.
useIndex
,
qs
.
indexes
)
for
_
,
tbl
:=
range
tables
.
tables
{
if
tbl
.
sel
{
...
...
@@ -1015,9 +1024,11 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
if
qs
.
distinct
{
sqlSelect
+=
" DISTINCT"
}
query
:=
fmt
.
Sprintf
(
"%s %s FROM %s%s%s T0 %s%s%s%s%s"
,
sqlSelect
,
sels
,
Q
,
mi
.
table
,
Q
,
join
,
where
,
groupBy
,
orderBy
,
limit
)
query
:=
fmt
.
Sprintf
(
"%s %s FROM %s%s%s T0 %s%s%s%s%s%s"
,
sqlSelect
,
sels
,
Q
,
mi
.
table
,
Q
,
specifyIndexes
,
join
,
where
,
groupBy
,
orderBy
,
limit
)
if
qs
.
for
u
pdate
{
if
qs
.
for
U
pdate
{
query
+=
" FOR UPDATE"
}
...
...
@@ -1153,10 +1164,13 @@ func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition
groupBy
:=
tables
.
getGroupSQL
(
qs
.
groups
)
tables
.
getOrderSQL
(
qs
.
orders
)
join
:=
tables
.
getJoinSQL
()
specifyIndexes
:=
tables
.
getIndexSql
(
mi
.
table
,
qs
.
useIndex
,
qs
.
indexes
)
Q
:=
d
.
ins
.
TableQuote
()
query
:=
fmt
.
Sprintf
(
"SELECT COUNT(*) FROM %s%s%s T0 %s%s%s"
,
Q
,
mi
.
table
,
Q
,
join
,
where
,
groupBy
)
query
:=
fmt
.
Sprintf
(
"SELECT COUNT(*) FROM %s%s%s T0 %s%s%s%s"
,
Q
,
mi
.
table
,
Q
,
specifyIndexes
,
join
,
where
,
groupBy
)
if
groupBy
!=
""
{
query
=
fmt
.
Sprintf
(
"SELECT COUNT(*) FROM (%s) AS T"
,
query
)
...
...
@@ -1680,6 +1694,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
orderBy
:=
tables
.
getOrderSQL
(
qs
.
orders
)
limit
:=
tables
.
getLimitSQL
(
mi
,
qs
.
offset
,
qs
.
limit
)
join
:=
tables
.
getJoinSQL
()
specifyIndexes
:=
tables
.
getIndexSql
(
mi
.
table
,
qs
.
useIndex
,
qs
.
indexes
)
sels
:=
strings
.
Join
(
cols
,
", "
)
...
...
@@ -1687,7 +1702,10 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
if
qs
.
distinct
{
sqlSelect
+=
" DISTINCT"
}
query
:=
fmt
.
Sprintf
(
"%s %s FROM %s%s%s T0 %s%s%s%s%s"
,
sqlSelect
,
sels
,
Q
,
mi
.
table
,
Q
,
join
,
where
,
groupBy
,
orderBy
,
limit
)
query
:=
fmt
.
Sprintf
(
"%s %s FROM %s%s%s T0 %s%s%s%s%s%s"
,
sqlSelect
,
sels
,
Q
,
mi
.
table
,
Q
,
specifyIndexes
,
join
,
where
,
groupBy
,
orderBy
,
limit
)
d
.
ins
.
ReplaceMarks
(
&
query
)
...
...
@@ -1781,10 +1799,6 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
return
cnt
,
nil
}
func
(
d
*
dbBase
)
RowsTo
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
interface
{},
string
,
string
,
*
time
.
Location
)
(
int64
,
error
)
{
return
0
,
nil
}
// flag of update joined record.
func
(
d
*
dbBase
)
SupportUpdateJoin
()
bool
{
return
true
...
...
@@ -1900,3 +1914,31 @@ func (d *dbBase) ShowColumnsQuery(table string) string {
func
(
d
*
dbBase
)
IndexExists
(
dbQuerier
,
string
,
string
)
bool
{
panic
(
ErrNotImplement
)
}
// GenerateSpecifyIndex return a specifying index clause
func
(
d
*
dbBase
)
GenerateSpecifyIndex
(
tableName
string
,
useIndex
int
,
indexes
[]
string
)
string
{
var
s
[]
string
Q
:=
d
.
TableQuote
()
for
_
,
index
:=
range
indexes
{
tmp
:=
fmt
.
Sprintf
(
`%s%s%s`
,
Q
,
index
,
Q
)
s
=
append
(
s
,
tmp
)
}
var
useWay
string
switch
useIndex
{
case
hints
.
KeyUseIndex
:
useWay
=
`USE`
case
hints
.
KeyForceIndex
:
useWay
=
`FORCE`
case
hints
.
KeyIgnoreIndex
:
useWay
=
`IGNORE`
default
:
DebugLog
.
Println
(
"[WARN] Not a valid specifying action, so that action is ignored"
)
return
``
}
return
fmt
.
Sprintf
(
` %s INDEX(%s) `
,
useWay
,
strings
.
Join
(
s
,
`,`
))
}
pkg/orm/db_alias.go
浏览文件 @
5a1fa4e1
...
...
@@ -18,6 +18,7 @@ import (
"context"
"database/sql"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"sync"
"time"
...
...
@@ -363,7 +364,7 @@ func newAliasWithDb(aliasName, driverName string, db *sql.DB, params ...common.K
var
stmtCache
*
lru
.
Cache
var
stmtCacheSize
int
maxStmtCacheSize
:=
kvs
.
GetValueOr
(
maxStmtCacheSizeKey
,
0
)
.
(
int
)
maxStmtCacheSize
:=
kvs
.
GetValueOr
(
hints
.
KeyMaxStmtCacheSize
,
0
)
.
(
int
)
if
maxStmtCacheSize
>
0
{
_stmtCache
,
errC
:=
newStmtDecoratorLruWithEvict
(
maxStmtCacheSize
)
if
errC
!=
nil
{
...
...
@@ -398,15 +399,15 @@ func newAliasWithDb(aliasName, driverName string, db *sql.DB, params ...common.K
detectTZ
(
al
)
kvs
.
IfContains
(
maxIdleConnectionsKey
,
func
(
value
interface
{})
{
kvs
.
IfContains
(
hints
.
KeyMaxIdleConnections
,
func
(
value
interface
{})
{
if
m
,
ok
:=
value
.
(
int
);
ok
{
SetMaxIdleConns
(
al
,
m
)
}
})
.
IfContains
(
maxOpenConnectionsKey
,
func
(
value
interface
{})
{
})
.
IfContains
(
hints
.
KeyMaxOpenConnections
,
func
(
value
interface
{})
{
if
m
,
ok
:=
value
.
(
int
);
ok
{
SetMaxOpenConns
(
al
,
m
)
}
})
.
IfContains
(
connMaxLifetimeKey
,
func
(
value
interface
{})
{
})
.
IfContains
(
hints
.
KeyConnMaxLifetime
,
func
(
value
interface
{})
{
if
m
,
ok
:=
value
.
(
time
.
Duration
);
ok
{
SetConnMaxLifetime
(
al
,
m
)
}
...
...
@@ -422,7 +423,7 @@ func AddAliasWthDB(aliasName, driverName string, db *sql.DB, params ...common.KV
}
// RegisterDataBase Setting the database connect params. Use the database driver self dataSource args.
func
RegisterDataBase
(
aliasName
,
driverName
,
dataSource
string
,
hint
s
...
common
.
KV
)
error
{
func
RegisterDataBase
(
aliasName
,
driverName
,
dataSource
string
,
param
s
...
common
.
KV
)
error
{
var
(
err
error
db
*
sql
.
DB
...
...
@@ -436,7 +437,7 @@ func RegisterDataBase(aliasName, driverName, dataSource string, hints ...common.
goto
end
}
al
,
err
=
addAliasWthDB
(
aliasName
,
driverName
,
db
,
hint
s
...
)
al
,
err
=
addAliasWthDB
(
aliasName
,
driverName
,
db
,
param
s
...
)
if
err
!=
nil
{
goto
end
}
...
...
pkg/orm/db_alias_test.go
浏览文件 @
5a1fa4e1
...
...
@@ -15,6 +15,7 @@
package
orm
import
(
"github.com/astaxie/beego/pkg/orm/hints"
"testing"
"time"
...
...
@@ -23,9 +24,9 @@ import (
func
TestRegisterDataBase
(
t
*
testing
.
T
)
{
err
:=
RegisterDataBase
(
"test-params"
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
MaxIdleConnections
(
20
),
MaxOpenConnections
(
300
),
ConnMaxLifetime
(
time
.
Minute
))
hints
.
MaxIdleConnections
(
20
),
hints
.
MaxOpenConnections
(
300
),
hints
.
ConnMaxLifetime
(
time
.
Minute
))
assert
.
Nil
(
t
,
err
)
al
:=
getDbAlias
(
"test-params"
)
...
...
@@ -37,7 +38,7 @@ func TestRegisterDataBase(t *testing.T) {
func
TestRegisterDataBase_MaxStmtCacheSizeNegative1
(
t
*
testing
.
T
)
{
aliasName
:=
"TestRegisterDataBase_MaxStmtCacheSizeNegative1"
err
:=
RegisterDataBase
(
aliasName
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
MaxStmtCacheSize
(
-
1
))
err
:=
RegisterDataBase
(
aliasName
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
hints
.
MaxStmtCacheSize
(
-
1
))
assert
.
Nil
(
t
,
err
)
al
:=
getDbAlias
(
aliasName
)
...
...
@@ -47,7 +48,7 @@ func TestRegisterDataBase_MaxStmtCacheSizeNegative1(t *testing.T) {
func
TestRegisterDataBase_MaxStmtCacheSize0
(
t
*
testing
.
T
)
{
aliasName
:=
"TestRegisterDataBase_MaxStmtCacheSize0"
err
:=
RegisterDataBase
(
aliasName
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
MaxStmtCacheSize
(
0
))
err
:=
RegisterDataBase
(
aliasName
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
hints
.
MaxStmtCacheSize
(
0
))
assert
.
Nil
(
t
,
err
)
al
:=
getDbAlias
(
aliasName
)
...
...
@@ -57,7 +58,7 @@ func TestRegisterDataBase_MaxStmtCacheSize0(t *testing.T) {
func
TestRegisterDataBase_MaxStmtCacheSize1
(
t
*
testing
.
T
)
{
aliasName
:=
"TestRegisterDataBase_MaxStmtCacheSize1"
err
:=
RegisterDataBase
(
aliasName
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
MaxStmtCacheSize
(
1
))
err
:=
RegisterDataBase
(
aliasName
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
hints
.
MaxStmtCacheSize
(
1
))
assert
.
Nil
(
t
,
err
)
al
:=
getDbAlias
(
aliasName
)
...
...
@@ -67,7 +68,7 @@ func TestRegisterDataBase_MaxStmtCacheSize1(t *testing.T) {
func
TestRegisterDataBase_MaxStmtCacheSize841
(
t
*
testing
.
T
)
{
aliasName
:=
"TestRegisterDataBase_MaxStmtCacheSize841"
err
:=
RegisterDataBase
(
aliasName
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
MaxStmtCacheSize
(
841
))
err
:=
RegisterDataBase
(
aliasName
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
hints
.
MaxStmtCacheSize
(
841
))
assert
.
Nil
(
t
,
err
)
al
:=
getDbAlias
(
aliasName
)
...
...
pkg/orm/db_oracle.go
浏览文件 @
5a1fa4e1
...
...
@@ -16,6 +16,7 @@ package orm
import
(
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"strings"
)
...
...
@@ -96,6 +97,29 @@ func (d *dbBaseOracle) IndexExists(db dbQuerier, table string, name string) bool
return
cnt
>
0
}
func
(
d
*
dbBaseOracle
)
GenerateSpecifyIndex
(
tableName
string
,
useIndex
int
,
indexes
[]
string
)
string
{
var
s
[]
string
Q
:=
d
.
TableQuote
()
for
_
,
index
:=
range
indexes
{
tmp
:=
fmt
.
Sprintf
(
`%s%s%s`
,
Q
,
index
,
Q
)
s
=
append
(
s
,
tmp
)
}
var
hint
string
switch
useIndex
{
case
hints
.
KeyUseIndex
,
hints
.
KeyForceIndex
:
hint
=
`INDEX`
case
hints
.
KeyIgnoreIndex
:
hint
=
`NO_INDEX`
default
:
DebugLog
.
Println
(
"[WARN] Not a valid specifying action, so that action is ignored"
)
return
``
}
return
fmt
.
Sprintf
(
` /*+ %s(%s %s)*/ `
,
hint
,
tableName
,
strings
.
Join
(
s
,
`,`
))
}
// execute insert sql with given struct and given values.
// insert the given values, not the field values in struct.
func
(
d
*
dbBaseOracle
)
InsertValue
(
q
dbQuerier
,
mi
*
modelInfo
,
isMulti
bool
,
names
[]
string
,
values
[]
interface
{})
(
int64
,
error
)
{
...
...
pkg/orm/db_postgres.go
浏览文件 @
5a1fa4e1
...
...
@@ -92,6 +92,7 @@ func (d *dbBasePostgres) MaxLimit() uint64 {
return
0
}
// postgresql quote is ".
func
(
d
*
dbBasePostgres
)
TableQuote
()
string
{
return
`"`
...
...
@@ -181,6 +182,12 @@ func (d *dbBasePostgres) IndexExists(db dbQuerier, table string, name string) bo
return
cnt
>
0
}
// GenerateSpecifyIndex return a specifying index clause
func
(
d
*
dbBasePostgres
)
GenerateSpecifyIndex
(
tableName
string
,
useIndex
int
,
indexes
[]
string
)
string
{
DebugLog
.
Println
(
"[WARN] Not support any specifying index action, so that action is ignored"
)
return
``
}
// create new postgresql dbBaser.
func
newdbBasePostgres
()
dbBaser
{
b
:=
new
(
dbBasePostgres
)
...
...
pkg/orm/db_sqlite.go
浏览文件 @
5a1fa4e1
...
...
@@ -17,7 +17,9 @@ package orm
import
(
"database/sql"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"reflect"
"strings"
"time"
)
...
...
@@ -153,6 +155,25 @@ func (d *dbBaseSqlite) IndexExists(db dbQuerier, table string, name string) bool
return
false
}
// GenerateSpecifyIndex return a specifying index clause
func
(
d
*
dbBaseSqlite
)
GenerateSpecifyIndex
(
tableName
string
,
useIndex
int
,
indexes
[]
string
)
string
{
var
s
[]
string
Q
:=
d
.
TableQuote
()
for
_
,
index
:=
range
indexes
{
tmp
:=
fmt
.
Sprintf
(
`%s%s%s`
,
Q
,
index
,
Q
)
s
=
append
(
s
,
tmp
)
}
switch
useIndex
{
case
hints
.
KeyUseIndex
,
hints
.
KeyForceIndex
:
return
fmt
.
Sprintf
(
` INDEXED BY %s `
,
strings
.
Join
(
s
,
`,`
))
default
:
DebugLog
.
Println
(
"[WARN] Not a valid specifying action, so that action is ignored"
)
return
``
}
}
// create new sqlite dbBaser.
func
newdbBaseSqlite
()
dbBaser
{
b
:=
new
(
dbBaseSqlite
)
...
...
pkg/orm/db_tables.go
浏览文件 @
5a1fa4e1
...
...
@@ -472,6 +472,15 @@ func (t *dbTables) getLimitSQL(mi *modelInfo, offset int64, limit int64) (limits
return
}
// getIndexSql generate index sql.
func
(
t
*
dbTables
)
getIndexSql
(
tableName
string
,
useIndex
int
,
indexes
[]
string
)
(
clause
string
)
{
if
len
(
indexes
)
==
0
{
return
}
return
t
.
base
.
GenerateSpecifyIndex
(
tableName
,
useIndex
,
indexes
)
}
// crete new tables collection.
func
newDbTables
(
mi
*
modelInfo
,
base
dbBaser
)
*
dbTables
{
tables
:=
&
dbTables
{}
...
...
pkg/orm/do_nothing_orm.go
浏览文件 @
5a1fa4e1
...
...
@@ -17,6 +17,7 @@ package orm
import
(
"context"
"database/sql"
"github.com/astaxie/beego/pkg/common"
)
// DoNothingOrm won't do anything, usually you use this to custom your mock Ormer implementation
...
...
@@ -52,11 +53,11 @@ func (d *DoNothingOrm) ReadOrCreateWithCtx(ctx context.Context, md interface{},
return
false
,
0
,
nil
}
func
(
d
*
DoNothingOrm
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
interface
{}
)
(
int64
,
error
)
{
func
(
d
*
DoNothingOrm
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
common
.
KV
)
(
int64
,
error
)
{
return
0
,
nil
}
func
(
d
*
DoNothingOrm
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
interface
{}
)
(
int64
,
error
)
{
func
(
d
*
DoNothingOrm
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
common
.
KV
)
(
int64
,
error
)
{
return
0
,
nil
}
...
...
pkg/orm/filter_orm_decorator.go
浏览文件 @
5a1fa4e1
...
...
@@ -17,6 +17,7 @@ package orm
import
(
"context"
"database/sql"
"github.com/astaxie/beego/pkg/common"
"reflect"
"time"
)
...
...
@@ -133,11 +134,11 @@ func (f *filterOrmDecorator) ReadOrCreateWithCtx(ctx context.Context, md interfa
return
ok
,
res
,
err
}
func
(
f
*
filterOrmDecorator
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
interface
{}
)
(
int64
,
error
)
{
func
(
f
*
filterOrmDecorator
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
common
.
KV
)
(
int64
,
error
)
{
return
f
.
LoadRelatedWithCtx
(
context
.
Background
(),
md
,
name
,
args
...
)
}
func
(
f
*
filterOrmDecorator
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
interface
{}
)
(
int64
,
error
)
{
func
(
f
*
filterOrmDecorator
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
common
.
KV
)
(
int64
,
error
)
{
var
(
res
int64
err
error
...
...
pkg/orm/filter_orm_decorator_test.go
浏览文件 @
5a1fa4e1
...
...
@@ -18,6 +18,7 @@ import (
"context"
"database/sql"
"errors"
"github.com/astaxie/beego/pkg/common"
"sync"
"testing"
...
...
@@ -360,7 +361,7 @@ func (f *filterMockOrm) ReadForUpdateWithCtx(ctx context.Context, md interface{}
return
errors
.
New
(
"read for update error"
)
}
func
(
f
*
filterMockOrm
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
interface
{}
)
(
int64
,
error
)
{
func
(
f
*
filterMockOrm
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
common
.
KV
)
(
int64
,
error
)
{
return
99
,
errors
.
New
(
"load related error"
)
}
...
...
pkg/orm/db_hints.go
→
pkg/orm/
hints/
db_hints.go
浏览文件 @
5a1fa4e1
...
...
@@ -12,13 +12,31 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package
orm
package
hints
import
(
"github.com/astaxie/beego/pkg/common"
"time"
)
const
(
//db level
KeyMaxIdleConnections
=
iota
KeyMaxOpenConnections
KeyConnMaxLifetime
KeyMaxStmtCacheSize
//query level
KeyForceIndex
KeyUseIndex
KeyIgnoreIndex
KeyForUpdate
KeyLimit
KeyOffset
KeyOrderBy
KeyRelDepth
)
type
Hint
struct
{
key
interface
{}
value
interface
{}
...
...
@@ -36,33 +54,71 @@ func (s *Hint) GetValue() interface{} {
return
s
.
value
}
const
(
maxIdleConnectionsKey
=
"MaxIdleConnections"
maxOpenConnectionsKey
=
"MaxOpenConnections"
connMaxLifetimeKey
=
"ConnMaxLifetime"
maxStmtCacheSizeKey
=
"MaxStmtCacheSize"
)
var
_
common
.
KV
=
new
(
Hint
)
// MaxIdleConnections return a hint about MaxIdleConnections
func
MaxIdleConnections
(
v
int
)
*
Hint
{
return
NewHint
(
maxIdleConnectionsKey
,
v
)
return
NewHint
(
KeyMaxIdleConnections
,
v
)
}
// MaxOpenConnections return a hint about MaxOpenConnections
func
MaxOpenConnections
(
v
int
)
*
Hint
{
return
NewHint
(
maxOpenConnectionsKey
,
v
)
return
NewHint
(
KeyMaxOpenConnections
,
v
)
}
// ConnMaxLifetime return a hint about ConnMaxLifetime
func
ConnMaxLifetime
(
v
time
.
Duration
)
*
Hint
{
return
NewHint
(
connMaxLifetimeKey
,
v
)
return
NewHint
(
KeyConnMaxLifetime
,
v
)
}
// MaxStmtCacheSize return a hint about MaxStmtCacheSize
func
MaxStmtCacheSize
(
v
int
)
*
Hint
{
return
NewHint
(
maxStmtCacheSizeKey
,
v
)
return
NewHint
(
KeyMaxStmtCacheSize
,
v
)
}
// ForceIndex return a hint about ForceIndex
func
ForceIndex
(
indexes
...
string
)
*
Hint
{
return
NewHint
(
KeyForceIndex
,
indexes
)
}
// UseIndex return a hint about UseIndex
func
UseIndex
(
indexes
...
string
)
*
Hint
{
return
NewHint
(
KeyUseIndex
,
indexes
)
}
// IgnoreIndex return a hint about IgnoreIndex
func
IgnoreIndex
(
indexes
...
string
)
*
Hint
{
return
NewHint
(
KeyIgnoreIndex
,
indexes
)
}
// ForUpdate return a hint about ForUpdate
func
ForUpdate
()
*
Hint
{
return
NewHint
(
KeyForUpdate
,
true
)
}
// DefaultRelDepth return a hint about DefaultRelDepth
func
DefaultRelDepth
()
*
Hint
{
return
NewHint
(
KeyRelDepth
,
true
)
}
// RelDepth return a hint about RelDepth
func
RelDepth
(
d
int
)
*
Hint
{
return
NewHint
(
KeyRelDepth
,
d
)
}
// Limit return a hint about Limit
func
Limit
(
d
int64
)
*
Hint
{
return
NewHint
(
KeyLimit
,
d
)
}
// Offset return a hint about Offset
func
Offset
(
d
int64
)
*
Hint
{
return
NewHint
(
KeyOffset
,
d
)
}
// OrderBy return a hint about OrderBy
func
OrderBy
(
s
string
)
*
Hint
{
return
NewHint
(
KeyOrderBy
,
s
)
}
// NewHint return a hint
...
...
pkg/orm/db_hints_test.go
→
pkg/orm/
hints/
db_hints_test.go
浏览文件 @
5a1fa4e1
...
...
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package
orm
package
hints
import
(
"github.com/stretchr/testify/assert"
...
...
@@ -51,26 +51,104 @@ func TestMaxOpenConnections(t *testing.T) {
i
:=
887423
hint
:=
MaxOpenConnections
(
i
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
i
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
maxOpenConnectionsKey
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyMaxOpenConnections
)
}
func
TestConnMaxLifetime
(
t
*
testing
.
T
)
{
i
:=
time
.
Hour
hint
:=
ConnMaxLifetime
(
i
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
i
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
connMaxLifetimeKey
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyConnMaxLifetime
)
}
func
TestMaxIdleConnections
(
t
*
testing
.
T
)
{
i
:=
42316
hint
:=
MaxIdleConnections
(
i
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
i
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
maxIdleConnectionsKey
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyMaxIdleConnections
)
}
func
TestMaxStmtCacheSize
(
t
*
testing
.
T
)
{
i
:=
94157
hint
:=
MaxStmtCacheSize
(
i
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
i
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
maxStmtCacheSizeKey
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyMaxStmtCacheSize
)
}
func
TestForceIndex
(
t
*
testing
.
T
)
{
s
:=
[]
string
{
`f_index1`
,
`f_index2`
,
`f_index3`
}
hint
:=
ForceIndex
(
s
...
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
s
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyForceIndex
)
}
func
TestForceIndex_0
(
t
*
testing
.
T
)
{
var
s
[]
string
hint
:=
ForceIndex
(
s
...
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
s
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyForceIndex
)
}
func
TestIgnoreIndex
(
t
*
testing
.
T
)
{
s
:=
[]
string
{
`i_index1`
,
`i_index2`
,
`i_index3`
}
hint
:=
IgnoreIndex
(
s
...
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
s
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyIgnoreIndex
)
}
func
TestIgnoreIndex_0
(
t
*
testing
.
T
)
{
var
s
[]
string
hint
:=
IgnoreIndex
(
s
...
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
s
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyIgnoreIndex
)
}
func
TestUseIndex
(
t
*
testing
.
T
)
{
s
:=
[]
string
{
`u_index1`
,
`u_index2`
,
`u_index3`
}
hint
:=
UseIndex
(
s
...
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
s
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyUseIndex
)
}
func
TestUseIndex_0
(
t
*
testing
.
T
)
{
var
s
[]
string
hint
:=
UseIndex
(
s
...
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
s
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyUseIndex
)
}
func
TestForUpdate
(
t
*
testing
.
T
)
{
hint
:=
ForUpdate
()
assert
.
Equal
(
t
,
hint
.
GetValue
(),
true
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyForUpdate
)
}
func
TestDefaultRelDepth
(
t
*
testing
.
T
)
{
hint
:=
DefaultRelDepth
()
assert
.
Equal
(
t
,
hint
.
GetValue
(),
true
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyRelDepth
)
}
func
TestRelDepth
(
t
*
testing
.
T
)
{
hint
:=
RelDepth
(
157965
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
157965
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyRelDepth
)
}
func
TestLimit
(
t
*
testing
.
T
)
{
hint
:=
Limit
(
1579625
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
int64
(
1579625
))
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyLimit
)
}
func
TestOffset
(
t
*
testing
.
T
)
{
hint
:=
Offset
(
int64
(
1572123965
))
assert
.
Equal
(
t
,
hint
.
GetValue
(),
int64
(
1572123965
))
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyOffset
)
}
func
TestOrderBy
(
t
*
testing
.
T
)
{
hint
:=
OrderBy
(
`-ID`
)
assert
.
Equal
(
t
,
hint
.
GetValue
(),
`-ID`
)
assert
.
Equal
(
t
,
hint
.
GetKey
(),
KeyOrderBy
)
}
\ No newline at end of file
pkg/orm/models_test.go
浏览文件 @
5a1fa4e1
...
...
@@ -18,6 +18,7 @@ import (
"database/sql"
"encoding/json"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"os"
"strings"
"time"
...
...
@@ -488,7 +489,7 @@ func init() {
os
.
Exit
(
2
)
}
err
:=
RegisterDataBase
(
"default"
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
MaxIdleConnections
(
20
))
err
:=
RegisterDataBase
(
"default"
,
DBARGS
.
Driver
,
DBARGS
.
Source
,
hints
.
MaxIdleConnections
(
20
))
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"can not register database: %v"
,
err
))
...
...
pkg/orm/orm.go
浏览文件 @
5a1fa4e1
...
...
@@ -59,6 +59,7 @@ import (
"errors"
"fmt"
"github.com/astaxie/beego/pkg/common"
"github.com/astaxie/beego/pkg/orm/hints"
"os"
"reflect"
"time"
...
...
@@ -99,6 +100,7 @@ type ormBase struct {
var
_
DQL
=
new
(
ormBase
)
var
_
DML
=
new
(
ormBase
)
var
_
DriverGetter
=
new
(
ormBase
)
// get model info and model reflect value
func
(
o
*
ormBase
)
getMiInd
(
md
interface
{},
needPtr
bool
)
(
mi
*
modelInfo
,
ind
reflect
.
Value
)
{
...
...
@@ -302,11 +304,10 @@ func (o *ormBase) QueryM2MWithCtx(ctx context.Context, md interface{}, name stri
// for _,tag := range post.Tags{...}
//
// make sure the relation is defined in model struct tags.
func
(
o
*
ormBase
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
interface
{}
)
(
int64
,
error
)
{
func
(
o
*
ormBase
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
common
.
KV
)
(
int64
,
error
)
{
return
o
.
LoadRelatedWithCtx
(
context
.
Background
(),
md
,
name
,
args
...
)
}
func
(
o
*
ormBase
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
interface
{})
(
int64
,
error
)
{
func
(
o
*
ormBase
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
common
.
KV
)
(
int64
,
error
)
{
_
,
fi
,
ind
,
qseter
:=
o
.
queryRelated
(
md
,
name
)
qs
:=
qseter
.
(
*
querySet
)
...
...
@@ -314,24 +315,29 @@ func (o *ormBase) LoadRelatedWithCtx(ctx context.Context, md interface{}, name s
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
kvs
:=
common
.
NewKVs
(
args
...
)
kvs
.
IfContains
(
hints
.
KeyRelDepth
,
func
(
value
interface
{})
{
if
v
,
ok
:=
value
.
(
bool
);
ok
{
if
v
{
relDepth
=
DefaultRelsDepth
}
case
1
:
limit
=
ToInt64
(
arg
)
case
2
:
offset
=
ToInt64
(
arg
)
case
3
:
order
,
_
=
arg
.
(
string
)
}
else
if
v
,
ok
:=
value
.
(
int
);
ok
{
relDepth
=
v
}
}
})
.
IfContains
(
hints
.
KeyLimit
,
func
(
value
interface
{})
{
if
v
,
ok
:=
value
.
(
int64
);
ok
{
limit
=
v
}
})
.
IfContains
(
hints
.
KeyOffset
,
func
(
value
interface
{})
{
if
v
,
ok
:=
value
.
(
int64
);
ok
{
offset
=
v
}
})
.
IfContains
(
hints
.
KeyOrderBy
,
func
(
value
interface
{})
{
if
v
,
ok
:=
value
.
(
string
);
ok
{
order
=
v
}
})
switch
fi
.
fieldType
{
case
RelOneToOne
,
RelForeignKey
,
RelReverseOne
:
...
...
pkg/orm/orm_log.go
浏览文件 @
5a1fa4e1
...
...
@@ -127,10 +127,7 @@ var _ txer = new(dbQueryLog)
var
_
txEnder
=
new
(
dbQueryLog
)
func
(
d
*
dbQueryLog
)
Prepare
(
query
string
)
(
*
sql
.
Stmt
,
error
)
{
a
:=
time
.
Now
()
stmt
,
err
:=
d
.
db
.
Prepare
(
query
)
debugLogQueies
(
d
.
alias
,
"db.Prepare"
,
query
,
a
,
err
)
return
stmt
,
err
return
d
.
PrepareContext
(
context
.
Background
(),
query
)
}
func
(
d
*
dbQueryLog
)
PrepareContext
(
ctx
context
.
Context
,
query
string
)
(
*
sql
.
Stmt
,
error
)
{
...
...
@@ -141,10 +138,7 @@ func (d *dbQueryLog) PrepareContext(ctx context.Context, query string) (*sql.Stm
}
func
(
d
*
dbQueryLog
)
Exec
(
query
string
,
args
...
interface
{})
(
sql
.
Result
,
error
)
{
a
:=
time
.
Now
()
res
,
err
:=
d
.
db
.
Exec
(
query
,
args
...
)
debugLogQueies
(
d
.
alias
,
"db.Exec"
,
query
,
a
,
err
,
args
...
)
return
res
,
err
return
d
.
ExecContext
(
context
.
Background
(),
query
,
args
...
)
}
func
(
d
*
dbQueryLog
)
ExecContext
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
(
sql
.
Result
,
error
)
{
...
...
@@ -155,10 +149,7 @@ func (d *dbQueryLog) ExecContext(ctx context.Context, query string, args ...inte
}
func
(
d
*
dbQueryLog
)
Query
(
query
string
,
args
...
interface
{})
(
*
sql
.
Rows
,
error
)
{
a
:=
time
.
Now
()
res
,
err
:=
d
.
db
.
Query
(
query
,
args
...
)
debugLogQueies
(
d
.
alias
,
"db.Query"
,
query
,
a
,
err
,
args
...
)
return
res
,
err
return
d
.
QueryContext
(
context
.
Background
(),
query
,
args
...
)
}
func
(
d
*
dbQueryLog
)
QueryContext
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
(
*
sql
.
Rows
,
error
)
{
...
...
@@ -169,10 +160,7 @@ func (d *dbQueryLog) QueryContext(ctx context.Context, query string, args ...int
}
func
(
d
*
dbQueryLog
)
QueryRow
(
query
string
,
args
...
interface
{})
*
sql
.
Row
{
a
:=
time
.
Now
()
res
:=
d
.
db
.
QueryRow
(
query
,
args
...
)
debugLogQueies
(
d
.
alias
,
"db.QueryRow"
,
query
,
a
,
nil
,
args
...
)
return
res
return
d
.
QueryRowContext
(
context
.
Background
(),
query
,
args
...
)
}
func
(
d
*
dbQueryLog
)
QueryRowContext
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
*
sql
.
Row
{
...
...
@@ -183,10 +171,7 @@ func (d *dbQueryLog) QueryRowContext(ctx context.Context, query string, args ...
}
func
(
d
*
dbQueryLog
)
Begin
()
(
*
sql
.
Tx
,
error
)
{
a
:=
time
.
Now
()
tx
,
err
:=
d
.
db
.
(
txer
)
.
Begin
()
debugLogQueies
(
d
.
alias
,
"db.Begin"
,
"START TRANSACTION"
,
a
,
err
)
return
tx
,
err
return
d
.
BeginTx
(
context
.
Background
(),
nil
)
}
func
(
d
*
dbQueryLog
)
BeginTx
(
ctx
context
.
Context
,
opts
*
sql
.
TxOptions
)
(
*
sql
.
Tx
,
error
)
{
...
...
pkg/orm/orm_queryset.go
浏览文件 @
5a1fa4e1
...
...
@@ -17,6 +17,7 @@ package orm
import
(
"context"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
)
type
colValue
struct
{
...
...
@@ -71,7 +72,9 @@ type querySet struct {
groups
[]
string
orders
[]
string
distinct
bool
forupdate
bool
forUpdate
bool
useIndex
int
indexes
[]
string
orm
*
ormBase
ctx
context
.
Context
forContext
bool
...
...
@@ -148,7 +151,28 @@ func (o querySet) Distinct() QuerySeter {
// add FOR UPDATE to SELECT
func
(
o
querySet
)
ForUpdate
()
QuerySeter
{
o
.
forupdate
=
true
o
.
forUpdate
=
true
return
&
o
}
// ForceIndex force index for query
func
(
o
querySet
)
ForceIndex
(
indexes
...
string
)
QuerySeter
{
o
.
useIndex
=
hints
.
KeyForceIndex
o
.
indexes
=
indexes
return
&
o
}
// UseIndex use index for query
func
(
o
querySet
)
UseIndex
(
indexes
...
string
)
QuerySeter
{
o
.
useIndex
=
hints
.
KeyUseIndex
o
.
indexes
=
indexes
return
&
o
}
// IgnoreIndex ignore index for query
func
(
o
querySet
)
IgnoreIndex
(
indexes
...
string
)
QuerySeter
{
o
.
useIndex
=
hints
.
KeyIgnoreIndex
o
.
indexes
=
indexes
return
&
o
}
...
...
pkg/orm/orm_test.go
浏览文件 @
5a1fa4e1
...
...
@@ -21,6 +21,7 @@ import (
"context"
"database/sql"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"io/ioutil"
"math"
"os"
...
...
@@ -1279,24 +1280,32 @@ func TestLoadRelated(t *testing.T) {
throwFailNow
(
t
,
AssertIs
(
len
(
user
.
Posts
),
2
))
throwFailNow
(
t
,
AssertIs
(
user
.
Posts
[
0
]
.
User
.
ID
,
3
))
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
true
)
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
hints
.
DefaultRelDepth
()
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
2
))
throwFailNow
(
t
,
AssertIs
(
len
(
user
.
Posts
),
2
))
throwFailNow
(
t
,
AssertIs
(
user
.
Posts
[
0
]
.
User
.
UserName
,
"astaxie"
))
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
true
,
1
)
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
hints
.
DefaultRelDepth
(),
hints
.
Limit
(
1
))
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
len
(
user
.
Posts
),
1
))
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
true
,
0
,
0
,
"-Id"
)
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
hints
.
DefaultRelDepth
(),
hints
.
OrderBy
(
"-Id"
))
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
2
))
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"
)
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Posts"
,
hints
.
DefaultRelDepth
(),
hints
.
Limit
(
1
),
hints
.
Offset
(
1
),
hints
.
OrderBy
(
"Id"
))
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
len
(
user
.
Posts
),
1
))
...
...
@@ -1318,7 +1327,7 @@ func TestLoadRelated(t *testing.T) {
throwFailNow
(
t
,
AssertIs
(
profile
.
User
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
profile
.
User
.
UserName
,
"astaxie"
))
num
,
err
=
dORM
.
LoadRelated
(
&
profile
,
"User"
,
true
)
num
,
err
=
dORM
.
LoadRelated
(
&
profile
,
"User"
,
hints
.
DefaultRelDepth
()
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
profile
.
User
==
nil
,
false
))
...
...
@@ -1335,7 +1344,7 @@ func TestLoadRelated(t *testing.T) {
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
.
Age
,
30
))
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Profile"
,
true
)
num
,
err
=
dORM
.
LoadRelated
(
&
user
,
"Profile"
,
hints
.
DefaultRelDepth
()
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
user
.
Profile
==
nil
,
false
))
...
...
@@ -1355,7 +1364,7 @@ func TestLoadRelated(t *testing.T) {
throwFailNow
(
t
,
AssertIs
(
post
.
User
==
nil
,
false
))
throwFailNow
(
t
,
AssertIs
(
post
.
User
.
UserName
,
"astaxie"
))
num
,
err
=
dORM
.
LoadRelated
(
&
post
,
"User"
,
true
)
num
,
err
=
dORM
.
LoadRelated
(
&
post
,
"User"
,
hints
.
DefaultRelDepth
()
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
1
))
throwFailNow
(
t
,
AssertIs
(
post
.
User
==
nil
,
false
))
...
...
@@ -1375,7 +1384,7 @@ func TestLoadRelated(t *testing.T) {
throwFailNow
(
t
,
AssertIs
(
len
(
post
.
Tags
),
2
))
throwFailNow
(
t
,
AssertIs
(
post
.
Tags
[
0
]
.
Name
,
"golang"
))
num
,
err
=
dORM
.
LoadRelated
(
&
post
,
"Tags"
,
true
)
num
,
err
=
dORM
.
LoadRelated
(
&
post
,
"Tags"
,
hints
.
DefaultRelDepth
()
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
2
))
throwFailNow
(
t
,
AssertIs
(
len
(
post
.
Tags
),
2
))
...
...
@@ -1396,7 +1405,7 @@ func TestLoadRelated(t *testing.T) {
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
)
num
,
err
=
dORM
.
LoadRelated
(
&
tag
,
"Posts"
,
hints
.
DefaultRelDepth
()
)
throwFailNow
(
t
,
err
)
throwFailNow
(
t
,
AssertIs
(
num
,
3
))
throwFailNow
(
t
,
AssertIs
(
tag
.
Posts
[
0
]
.
Title
,
"Introduction"
))
...
...
pkg/orm/types.go
浏览文件 @
5a1fa4e1
...
...
@@ -17,6 +17,7 @@ package orm
import
(
"context"
"database/sql"
"github.com/astaxie/beego/pkg/common"
"reflect"
"time"
)
...
...
@@ -175,14 +176,14 @@ type DQL interface {
// example:
// Ormer.LoadRelated(post,"Tags")
// for _,tag := range post.Tags{...}
//
args[0] bool true useDefaultRelsDepth ; false
depth 0
//
args[0] int
loadRelationDepth
//
args[1] in
t limit default limit 1000
//
args[2]
int offset default offset 0
//
args[3]
string order for example : "-Id"
//
hints.DefaultRelDepth useDefaultRelsDepth ; or
depth 0
//
hints.RelDepth
loadRelationDepth
//
hints.Limi
t limit default limit 1000
//
hints.Offset
int offset default offset 0
//
hints.OrderBy
string order for example : "-Id"
// make sure the relation is defined in model struct tags.
LoadRelated
(
md
interface
{},
name
string
,
args
...
interface
{}
)
(
int64
,
error
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
interface
{}
)
(
int64
,
error
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
common
.
KV
)
(
int64
,
error
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
common
.
KV
)
(
int64
,
error
)
// create a models to models queryer
// for example:
...
...
@@ -282,6 +283,21 @@ type QuerySeter interface {
// for example:
// qs.OrderBy("-status")
OrderBy
(
exprs
...
string
)
QuerySeter
// add FORCE INDEX expression.
// for example:
// qs.ForceIndex(`idx_name1`,`idx_name2`)
// ForceIndex, UseIndex , IgnoreIndex are mutually exclusive
ForceIndex
(
indexes
...
string
)
QuerySeter
// add USE INDEX expression.
// for example:
// qs.UseIndex(`idx_name1`,`idx_name2`)
// ForceIndex, UseIndex , IgnoreIndex are mutually exclusive
UseIndex
(
indexes
...
string
)
QuerySeter
// add IGNORE INDEX expression.
// for example:
// qs.IgnoreIndex(`idx_name1`,`idx_name2`)
// ForceIndex, UseIndex , IgnoreIndex are mutually exclusive
IgnoreIndex
(
indexes
...
string
)
QuerySeter
// set relation model to query together.
// it will query relation models and assign to parent model.
// for example:
...
...
@@ -527,24 +543,27 @@ type txEnder interface {
// base database struct
type
dbBaser
interface
{
Read
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
,
[]
string
,
bool
)
error
ReadBatch
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
interface
{},
*
time
.
Location
,
[]
string
)
(
int64
,
error
)
Count
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
*
time
.
Location
)
(
int64
,
error
)
ReadValues
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
[]
string
,
interface
{},
*
time
.
Location
)
(
int64
,
error
)
Insert
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
(
int64
,
error
)
InsertOrUpdate
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
alias
,
...
string
)
(
int64
,
error
)
InsertMulti
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
int
,
*
time
.
Location
)
(
int64
,
error
)
InsertValue
(
dbQuerier
,
*
modelInfo
,
bool
,
[]
string
,
[]
interface
{})
(
int64
,
error
)
InsertStmt
(
stmtQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
(
int64
,
error
)
Update
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
,
[]
string
)
(
int64
,
error
)
Delete
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
,
[]
string
)
(
int64
,
error
)
ReadBatch
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
interface
{},
*
time
.
Location
,
[]
string
)
(
int64
,
error
)
SupportUpdateJoin
()
bool
UpdateBatch
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
Params
,
*
time
.
Location
)
(
int64
,
error
)
Delete
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
,
[]
string
)
(
int64
,
error
)
DeleteBatch
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
*
time
.
Location
)
(
int64
,
error
)
Count
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
*
time
.
Location
)
(
int64
,
error
)
SupportUpdateJoin
()
bool
OperatorSQL
(
string
)
string
GenerateOperatorSQL
(
*
modelInfo
,
*
fieldInfo
,
string
,
[]
interface
{},
*
time
.
Location
)
(
string
,
[]
interface
{})
GenerateOperatorLeftCol
(
*
fieldInfo
,
string
,
*
string
)
PrepareInsert
(
dbQuerier
,
*
modelInfo
)
(
stmtQuerier
,
string
,
error
)
ReadValues
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
[]
string
,
interface
{},
*
time
.
Location
)
(
int64
,
error
)
RowsTo
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
interface
{},
string
,
string
,
*
time
.
Location
)
(
int64
,
error
)
MaxLimit
()
uint64
TableQuote
()
string
ReplaceMarks
(
*
string
)
...
...
@@ -559,4 +578,6 @@ type dbBaser interface {
IndexExists
(
dbQuerier
,
string
,
string
)
bool
collectFieldValue
(
*
modelInfo
,
*
fieldInfo
,
reflect
.
Value
,
bool
,
*
time
.
Location
)
(
interface
{},
error
)
setval
(
dbQuerier
,
*
modelInfo
,
[]
string
)
error
GenerateSpecifyIndex
(
tableName
string
,
useIndex
int
,
indexes
[]
string
)
string
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录