Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
二次元的罪恶王冠
beego
提交
41feb3a7
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,发现更多精彩内容 >>
未验证
提交
41feb3a7
编写于
7月 20, 2020
作者:
M
Ming Deng
提交者:
GitHub
7月 20, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #4078 from jianzhiyao/frt/orm_merge
refactor orm
上级
d9c016ed
b6f7d30f
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
337 addition
and
182 deletion
+337
-182
pkg/orm/db_alias.go
pkg/orm/db_alias.go
+53
-0
pkg/orm/orm.go
pkg/orm/orm.go
+159
-95
pkg/orm/orm_object.go
pkg/orm/orm_object.go
+2
-2
pkg/orm/orm_querym2m.go
pkg/orm/orm_querym2m.go
+1
-1
pkg/orm/orm_queryset.go
pkg/orm/orm_queryset.go
+2
-2
pkg/orm/orm_raw.go
pkg/orm/orm_raw.go
+2
-2
pkg/orm/orm_test.go
pkg/orm/orm_test.go
+18
-18
pkg/orm/types.go
pkg/orm/types.go
+100
-62
未找到文件。
pkg/orm/db_alias.go
浏览文件 @
41feb3a7
...
...
@@ -111,6 +111,9 @@ type DB struct {
stmtDecorators
*
lru
.
Cache
}
var
_
dbQuerier
=
new
(
DB
)
var
_
txer
=
new
(
DB
)
func
(
d
*
DB
)
Begin
()
(
*
sql
.
Tx
,
error
)
{
return
d
.
DB
.
Begin
()
}
...
...
@@ -220,6 +223,56 @@ func (d *DB) QueryRowContext(ctx context.Context, query string, args ...interfac
return
stmt
.
QueryRowContext
(
ctx
,
args
)
}
type
TxDB
struct
{
tx
*
sql
.
Tx
}
var
_
dbQuerier
=
new
(
TxDB
)
var
_
txEnder
=
new
(
TxDB
)
func
(
t
*
TxDB
)
Commit
()
error
{
return
t
.
tx
.
Commit
()
}
func
(
t
*
TxDB
)
Rollback
()
error
{
return
t
.
tx
.
Rollback
()
}
var
_
dbQuerier
=
new
(
TxDB
)
var
_
txEnder
=
new
(
TxDB
)
func
(
t
*
TxDB
)
Prepare
(
query
string
)
(
*
sql
.
Stmt
,
error
)
{
return
t
.
PrepareContext
(
context
.
Background
(),
query
)
}
func
(
t
*
TxDB
)
PrepareContext
(
ctx
context
.
Context
,
query
string
)
(
*
sql
.
Stmt
,
error
)
{
return
t
.
tx
.
PrepareContext
(
ctx
,
query
)
}
func
(
t
*
TxDB
)
Exec
(
query
string
,
args
...
interface
{})
(
sql
.
Result
,
error
)
{
return
t
.
ExecContext
(
context
.
Background
(),
query
,
args
...
)
}
func
(
t
*
TxDB
)
ExecContext
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
(
sql
.
Result
,
error
)
{
return
t
.
tx
.
ExecContext
(
ctx
,
query
,
args
...
)
}
func
(
t
*
TxDB
)
Query
(
query
string
,
args
...
interface
{})
(
*
sql
.
Rows
,
error
)
{
return
t
.
QueryContext
(
context
.
Background
(),
query
,
args
...
)
}
func
(
t
*
TxDB
)
QueryContext
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
(
*
sql
.
Rows
,
error
)
{
return
t
.
tx
.
QueryContext
(
ctx
,
query
,
args
...
)
}
func
(
t
*
TxDB
)
QueryRow
(
query
string
,
args
...
interface
{})
*
sql
.
Row
{
return
t
.
QueryRowContext
(
context
.
Background
(),
query
,
args
...
)
}
func
(
t
*
TxDB
)
QueryRowContext
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
*
sql
.
Row
{
return
t
.
tx
.
QueryRowContext
(
ctx
,
query
,
args
...
)
}
type
alias
struct
{
Name
string
Driver
DriverType
...
...
pkg/orm/orm.go
浏览文件 @
41feb3a7
...
...
@@ -62,6 +62,8 @@ import (
"reflect"
"sync"
"time"
"github.com/astaxie/beego/logs"
)
// DebugQueries define the debug
...
...
@@ -76,8 +78,7 @@ var (
DefaultRowsLimit
=
-
1
DefaultRelsDepth
=
2
DefaultTimeLoc
=
time
.
Local
ErrTxHasBegan
=
errors
.
New
(
"<Ormer.Begin> transaction already begin"
)
ErrTxDone
=
errors
.
New
(
"<Ormer.Commit/Rollback> transaction not begin"
)
ErrTxDone
=
errors
.
New
(
"<TxOrmer.Commit/Rollback> transaction already done"
)
ErrMultiRows
=
errors
.
New
(
"<QuerySeter> return multi rows"
)
ErrNoRows
=
errors
.
New
(
"<QuerySeter> no row found"
)
ErrStmtClosed
=
errors
.
New
(
"<QuerySeter> stmt already closed"
)
...
...
@@ -91,16 +92,16 @@ type Params map[string]interface{}
// ParamsList stores paramslist
type
ParamsList
[]
interface
{}
type
orm
struct
{
type
orm
Base
struct
{
alias
*
alias
db
dbQuerier
isTx
bool
}
var
_
Ormer
=
new
(
orm
)
var
_
DQL
=
new
(
ormBase
)
var
_
DML
=
new
(
ormBase
)
// get model info and model reflect value
func
(
o
*
orm
)
getMiInd
(
md
interface
{},
needPtr
bool
)
(
mi
*
modelInfo
,
ind
reflect
.
Value
)
{
func
(
o
*
orm
Base
)
getMiInd
(
md
interface
{},
needPtr
bool
)
(
mi
*
modelInfo
,
ind
reflect
.
Value
)
{
val
:=
reflect
.
ValueOf
(
md
)
ind
=
reflect
.
Indirect
(
val
)
typ
:=
ind
.
Type
()
...
...
@@ -115,7 +116,7 @@ func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect
}
// get field info from model info by given field name
func
(
o
*
orm
)
getFieldInfo
(
mi
*
modelInfo
,
name
string
)
*
fieldInfo
{
func
(
o
*
orm
Base
)
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
))
...
...
@@ -124,33 +125,42 @@ func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo {
}
// read data to model
func
(
o
*
orm
)
Read
(
md
interface
{},
cols
...
string
)
error
{
func
(
o
*
ormBase
)
Read
(
md
interface
{},
cols
...
string
)
error
{
return
o
.
ReadWithCtx
(
context
.
Background
(),
md
,
cols
...
)
}
func
(
o
*
ormBase
)
ReadWithCtx
(
ctx
context
.
Context
,
md
interface
{},
cols
...
string
)
error
{
mi
,
ind
:=
o
.
getMiInd
(
md
,
true
)
return
o
.
alias
.
DbBaser
.
Read
(
o
.
db
,
mi
,
ind
,
o
.
alias
.
TZ
,
cols
,
false
)
}
// read data to model, like Read(), but use "SELECT FOR UPDATE" form
func
(
o
*
orm
)
ReadForUpdate
(
md
interface
{},
cols
...
string
)
error
{
func
(
o
*
ormBase
)
ReadForUpdate
(
md
interface
{},
cols
...
string
)
error
{
return
o
.
ReadForUpdateWithCtx
(
context
.
Background
(),
md
,
cols
...
)
}
func
(
o
*
ormBase
)
ReadForUpdateWithCtx
(
ctx
context
.
Context
,
md
interface
{},
cols
...
string
)
error
{
mi
,
ind
:=
o
.
getMiInd
(
md
,
true
)
return
o
.
alias
.
DbBaser
.
Read
(
o
.
db
,
mi
,
ind
,
o
.
alias
.
TZ
,
cols
,
true
)
}
// Try to read a row from the database, or insert one if it doesn't exist
func
(
o
*
orm
)
ReadOrCreate
(
md
interface
{},
col1
string
,
cols
...
string
)
(
bool
,
int64
,
error
)
{
func
(
o
*
ormBase
)
ReadOrCreate
(
md
interface
{},
col1
string
,
cols
...
string
)
(
bool
,
int64
,
error
)
{
return
o
.
ReadOrCreateWithCtx
(
context
.
Background
(),
md
,
col1
,
cols
...
)
}
func
(
o
*
ormBase
)
ReadOrCreateWithCtx
(
ctx
context
.
Context
,
md
interface
{},
col1
string
,
cols
...
string
)
(
bool
,
int64
,
error
)
{
cols
=
append
([]
string
{
col1
},
cols
...
)
mi
,
ind
:=
o
.
getMiInd
(
md
,
true
)
err
:=
o
.
alias
.
DbBaser
.
Read
(
o
.
db
,
mi
,
ind
,
o
.
alias
.
TZ
,
cols
,
false
)
if
err
==
ErrNoRows
{
// Create
id
,
err
:=
o
.
Insert
(
md
)
return
(
err
==
nil
)
,
id
,
err
id
,
err
:=
o
.
Insert
WithCtx
(
ctx
,
md
)
return
err
==
nil
,
id
,
err
}
id
,
vid
:=
int64
(
0
),
ind
.
FieldByIndex
(
mi
.
fields
.
pk
.
fieldIndex
)
if
mi
.
fields
.
pk
.
fieldType
&
IsPositiveIntegerField
>
0
{
id
=
int64
(
vid
.
Uint
())
}
else
if
mi
.
fields
.
pk
.
rel
{
return
o
.
ReadOrCreate
(
vid
.
Interface
(),
mi
.
fields
.
pk
.
relModelInfo
.
fields
.
pk
.
name
)
return
o
.
ReadOrCreate
WithCtx
(
ctx
,
vid
.
Interface
(),
mi
.
fields
.
pk
.
relModelInfo
.
fields
.
pk
.
name
)
}
else
{
id
=
vid
.
Int
()
}
...
...
@@ -159,7 +169,10 @@ func (o *orm) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, i
}
// insert model data to database
func
(
o
*
orm
)
Insert
(
md
interface
{})
(
int64
,
error
)
{
func
(
o
*
ormBase
)
Insert
(
md
interface
{})
(
int64
,
error
)
{
return
o
.
InsertWithCtx
(
context
.
Background
(),
md
)
}
func
(
o
*
ormBase
)
InsertWithCtx
(
ctx
context
.
Context
,
md
interface
{})
(
int64
,
error
)
{
mi
,
ind
:=
o
.
getMiInd
(
md
,
true
)
id
,
err
:=
o
.
alias
.
DbBaser
.
Insert
(
o
.
db
,
mi
,
ind
,
o
.
alias
.
TZ
)
if
err
!=
nil
{
...
...
@@ -172,7 +185,7 @@ func (o *orm) Insert(md interface{}) (int64, error) {
}
// set auto pk field
func
(
o
*
orm
)
setPk
(
mi
*
modelInfo
,
ind
reflect
.
Value
,
id
int64
)
{
func
(
o
*
orm
Base
)
setPk
(
mi
*
modelInfo
,
ind
reflect
.
Value
,
id
int64
)
{
if
mi
.
fields
.
pk
.
auto
{
if
mi
.
fields
.
pk
.
fieldType
&
IsPositiveIntegerField
>
0
{
ind
.
FieldByIndex
(
mi
.
fields
.
pk
.
fieldIndex
)
.
SetUint
(
uint64
(
id
))
...
...
@@ -183,7 +196,10 @@ func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) {
}
// insert some models to database
func
(
o
*
orm
)
InsertMulti
(
bulk
int
,
mds
interface
{})
(
int64
,
error
)
{
func
(
o
*
ormBase
)
InsertMulti
(
bulk
int
,
mds
interface
{})
(
int64
,
error
)
{
return
o
.
InsertMultiWithCtx
(
context
.
Background
(),
bulk
,
mds
)
}
func
(
o
*
ormBase
)
InsertMultiWithCtx
(
ctx
context
.
Context
,
bulk
int
,
mds
interface
{})
(
int64
,
error
)
{
var
cnt
int64
sind
:=
reflect
.
Indirect
(
reflect
.
ValueOf
(
mds
))
...
...
@@ -218,7 +234,10 @@ func (o *orm) InsertMulti(bulk int, mds interface{}) (int64, error) {
}
// InsertOrUpdate data to database
func
(
o
*
orm
)
InsertOrUpdate
(
md
interface
{},
colConflitAndArgs
...
string
)
(
int64
,
error
)
{
func
(
o
*
ormBase
)
InsertOrUpdate
(
md
interface
{},
colConflictAndArgs
...
string
)
(
int64
,
error
)
{
return
o
.
InsertOrUpdateWithCtx
(
context
.
Background
(),
md
,
colConflictAndArgs
...
)
}
func
(
o
*
ormBase
)
InsertOrUpdateWithCtx
(
ctx
context
.
Context
,
md
interface
{},
colConflitAndArgs
...
string
)
(
int64
,
error
)
{
mi
,
ind
:=
o
.
getMiInd
(
md
,
true
)
id
,
err
:=
o
.
alias
.
DbBaser
.
InsertOrUpdate
(
o
.
db
,
mi
,
ind
,
o
.
alias
,
colConflitAndArgs
...
)
if
err
!=
nil
{
...
...
@@ -232,14 +251,20 @@ func (o *orm) InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64
// update model to database.
// cols set the columns those want to update.
func
(
o
*
orm
)
Update
(
md
interface
{},
cols
...
string
)
(
int64
,
error
)
{
func
(
o
*
ormBase
)
Update
(
md
interface
{},
cols
...
string
)
(
int64
,
error
)
{
return
o
.
UpdateWithCtx
(
context
.
Background
(),
md
,
cols
...
)
}
func
(
o
*
ormBase
)
UpdateWithCtx
(
ctx
context
.
Context
,
md
interface
{},
cols
...
string
)
(
int64
,
error
)
{
mi
,
ind
:=
o
.
getMiInd
(
md
,
true
)
return
o
.
alias
.
DbBaser
.
Update
(
o
.
db
,
mi
,
ind
,
o
.
alias
.
TZ
,
cols
)
}
// delete model in database
// cols shows the delete conditions values read from. default is pk
func
(
o
*
orm
)
Delete
(
md
interface
{},
cols
...
string
)
(
int64
,
error
)
{
func
(
o
*
ormBase
)
Delete
(
md
interface
{},
cols
...
string
)
(
int64
,
error
)
{
return
o
.
DeleteWithCtx
(
context
.
Background
(),
md
,
cols
...
)
}
func
(
o
*
ormBase
)
DeleteWithCtx
(
ctx
context
.
Context
,
md
interface
{},
cols
...
string
)
(
int64
,
error
)
{
mi
,
ind
:=
o
.
getMiInd
(
md
,
true
)
num
,
err
:=
o
.
alias
.
DbBaser
.
Delete
(
o
.
db
,
mi
,
ind
,
o
.
alias
.
TZ
,
cols
)
if
err
!=
nil
{
...
...
@@ -252,7 +277,10 @@ func (o *orm) Delete(md interface{}, cols ...string) (int64, error) {
}
// create a models to models queryer
func
(
o
*
orm
)
QueryM2M
(
md
interface
{},
name
string
)
QueryM2Mer
{
func
(
o
*
ormBase
)
QueryM2M
(
md
interface
{},
name
string
)
QueryM2Mer
{
return
o
.
QueryM2MWithCtx
(
context
.
Background
(),
md
,
name
)
}
func
(
o
*
ormBase
)
QueryM2MWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
)
QueryM2Mer
{
mi
,
ind
:=
o
.
getMiInd
(
md
,
true
)
fi
:=
o
.
getFieldInfo
(
mi
,
name
)
...
...
@@ -274,7 +302,10 @@ func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer {
// for _,tag := range post.Tags{...}
//
// make sure the relation is defined in model struct tags.
func
(
o
*
orm
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
interface
{})
(
int64
,
error
)
{
func
(
o
*
ormBase
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
interface
{})
(
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
)
{
_
,
fi
,
ind
,
qseter
:=
o
.
queryRelated
(
md
,
name
)
qs
:=
qseter
.
(
*
querySet
)
...
...
@@ -341,14 +372,17 @@ func (o *orm) LoadRelated(md interface{}, name string, args ...interface{}) (int
// qs := orm.QueryRelated(post,"Tag")
// qs.All(&[]*Tag{})
//
func
(
o
*
orm
)
QueryRelated
(
md
interface
{},
name
string
)
QuerySeter
{
func
(
o
*
ormBase
)
QueryRelated
(
md
interface
{},
name
string
)
QuerySeter
{
return
o
.
QueryRelatedWithCtx
(
context
.
Background
(),
md
,
name
)
}
func
(
o
*
ormBase
)
QueryRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
)
QuerySeter
{
// is this api needed ?
_
,
_
,
_
,
qs
:=
o
.
queryRelated
(
md
,
name
)
return
qs
}
// get QuerySeter for related models to md model
func
(
o
*
orm
)
queryRelated
(
md
interface
{},
name
string
)
(
*
modelInfo
,
*
fieldInfo
,
reflect
.
Value
,
QuerySeter
)
{
func
(
o
*
orm
Base
)
queryRelated
(
md
interface
{},
name
string
)
(
*
modelInfo
,
*
fieldInfo
,
reflect
.
Value
,
QuerySeter
)
{
mi
,
ind
:=
o
.
getMiInd
(
md
,
true
)
fi
:=
o
.
getFieldInfo
(
mi
,
name
)
...
...
@@ -380,7 +414,7 @@ func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo,
}
// get reverse relation QuerySeter
func
(
o
*
orm
)
getReverseQs
(
md
interface
{},
mi
*
modelInfo
,
fi
*
fieldInfo
)
*
querySet
{
func
(
o
*
orm
Base
)
getReverseQs
(
md
interface
{},
mi
*
modelInfo
,
fi
*
fieldInfo
)
*
querySet
{
switch
fi
.
fieldType
{
case
RelReverseOne
,
RelReverseMany
:
default
:
...
...
@@ -401,7 +435,7 @@ func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *queryS
}
// get relation QuerySeter
func
(
o
*
orm
)
getRelQs
(
md
interface
{},
mi
*
modelInfo
,
fi
*
fieldInfo
)
*
querySet
{
func
(
o
*
orm
Base
)
getRelQs
(
md
interface
{},
mi
*
modelInfo
,
fi
*
fieldInfo
)
*
querySet
{
switch
fi
.
fieldType
{
case
RelOneToOne
,
RelForeignKey
,
RelManyToMany
:
default
:
...
...
@@ -423,7 +457,10 @@ func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet {
// return a QuerySeter for table operations.
// table name can be string or struct.
// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)),
func
(
o
*
orm
)
QueryTable
(
ptrStructOrTableName
interface
{})
(
qs
QuerySeter
)
{
func
(
o
*
ormBase
)
QueryTable
(
ptrStructOrTableName
interface
{})
(
qs
QuerySeter
)
{
return
o
.
QueryTableWithCtx
(
context
.
Background
(),
ptrStructOrTableName
)
}
func
(
o
*
ormBase
)
QueryTableWithCtx
(
ctx
context
.
Context
,
ptrStructOrTableName
interface
{})
(
qs
QuerySeter
)
{
var
name
string
if
table
,
ok
:=
ptrStructOrTableName
.
(
string
);
ok
{
name
=
nameStrategyMap
[
defaultNameStrategy
](
table
)
...
...
@@ -442,94 +479,113 @@ func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) {
return
}
// switch to another registered database driver by given name.
func
(
o
*
orm
)
Using
(
name
string
)
error
{
if
o
.
isTx
{
panic
(
fmt
.
Errorf
(
"<Ormer.Using> transaction has been start, cannot change db"
))
}
if
al
,
ok
:=
dataBaseCache
.
get
(
name
);
ok
{
o
.
alias
=
al
if
Debug
{
o
.
db
=
newDbQueryLog
(
al
,
al
.
DB
)
}
else
{
o
.
db
=
al
.
DB
}
}
else
{
return
fmt
.
Errorf
(
"<Ormer.Using> unknown db alias name `%s`"
,
name
)
// return a raw query seter for raw sql string.
func
(
o
*
ormBase
)
Raw
(
query
string
,
args
...
interface
{})
RawSeter
{
return
o
.
RawWithCtx
(
context
.
Background
(),
query
,
args
...
)
}
func
(
o
*
ormBase
)
RawWithCtx
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
RawSeter
{
return
newRawSet
(
o
,
query
,
args
)
}
// return current using database Driver
func
(
o
*
ormBase
)
Driver
()
Driver
{
return
driver
(
o
.
alias
.
Name
)
}
// return sql.DBStats for current database
func
(
o
*
ormBase
)
DBStats
()
*
sql
.
DBStats
{
if
o
.
alias
!=
nil
&&
o
.
alias
.
DB
!=
nil
{
stats
:=
o
.
alias
.
DB
.
DB
.
Stats
()
return
&
stats
}
return
nil
}
// begin transaction
func
(
o
*
orm
)
Begin
()
error
{
return
o
.
BeginTx
(
context
.
Background
(),
nil
)
type
orm
struct
{
ormBase
}
func
(
o
*
orm
)
BeginTx
(
ctx
context
.
Context
,
opts
*
sql
.
TxOptions
)
error
{
if
o
.
isTx
{
return
ErrTxHasBegan
}
var
tx
*
sql
.
Tx
var
_
Ormer
=
new
(
orm
)
func
(
o
*
orm
)
Begin
()
(
TxOrmer
,
error
)
{
return
o
.
BeginWithCtx
(
context
.
Background
())
}
func
(
o
*
orm
)
BeginWithCtx
(
ctx
context
.
Context
)
(
TxOrmer
,
error
)
{
return
o
.
BeginWithCtxAndOpts
(
ctx
,
nil
)
}
func
(
o
*
orm
)
BeginWithOpts
(
opts
*
sql
.
TxOptions
)
(
TxOrmer
,
error
)
{
return
o
.
BeginWithCtxAndOpts
(
context
.
Background
(),
opts
)
}
func
(
o
*
orm
)
BeginWithCtxAndOpts
(
ctx
context
.
Context
,
opts
*
sql
.
TxOptions
)
(
TxOrmer
,
error
)
{
tx
,
err
:=
o
.
db
.
(
txer
)
.
BeginTx
(
ctx
,
opts
)
if
err
!=
nil
{
return
err
return
nil
,
err
}
o
.
isTx
=
true
if
Debug
{
o
.
db
.
(
*
dbQueryLog
)
.
SetDB
(
tx
)
}
else
{
o
.
db
=
tx
_txOrm
:=
&
txOrm
{
ormBase
:
ormBase
{
alias
:
o
.
alias
,
db
:
&
TxDB
{
tx
:
tx
},
},
}
return
nil
var
taskTxOrm
TxOrmer
=
_txOrm
return
taskTxOrm
,
nil
}
// commit transaction
func
(
o
*
orm
)
Commit
()
error
{
if
!
o
.
isTx
{
return
ErrTxDone
}
err
:=
o
.
db
.
(
txEnder
)
.
Commit
()
if
err
==
nil
{
o
.
isTx
=
false
o
.
Using
(
o
.
alias
.
Name
)
}
else
if
err
==
sql
.
ErrTxDone
{
return
ErrTxDone
}
return
err
func
(
o
*
orm
)
DoTx
(
task
func
(
txOrm
TxOrmer
)
error
)
error
{
return
o
.
DoTxWithCtx
(
context
.
Background
(),
task
)
}
// rollback transaction
func
(
o
*
orm
)
Rollback
()
error
{
if
!
o
.
isTx
{
return
ErrTxDone
}
err
:=
o
.
db
.
(
txEnder
)
.
Rollback
()
if
err
==
nil
{
o
.
isTx
=
false
o
.
Using
(
o
.
alias
.
Name
)
}
else
if
err
==
sql
.
ErrTxDone
{
return
ErrTxDone
func
(
o
*
orm
)
DoTxWithCtx
(
ctx
context
.
Context
,
task
func
(
txOrm
TxOrmer
)
error
)
error
{
return
o
.
DoTxWithCtxAndOpts
(
ctx
,
nil
,
task
)
}
func
(
o
*
orm
)
DoTxWithOpts
(
opts
*
sql
.
TxOptions
,
task
func
(
txOrm
TxOrmer
)
error
)
error
{
return
o
.
DoTxWithCtxAndOpts
(
context
.
Background
(),
opts
,
task
)
}
func
(
o
*
orm
)
DoTxWithCtxAndOpts
(
ctx
context
.
Context
,
opts
*
sql
.
TxOptions
,
task
func
(
txOrm
TxOrmer
)
error
)
error
{
_txOrm
,
err
:=
o
.
BeginWithCtxAndOpts
(
ctx
,
opts
)
if
err
!=
nil
{
return
err
}
panicked
:=
true
defer
func
()
{
if
panicked
||
err
!=
nil
{
e
:=
_txOrm
.
Rollback
()
if
e
!=
nil
{
logs
.
Error
(
"rollback transaction failed: %v,%v"
,
e
,
panicked
)
}
}
else
{
e
:=
_txOrm
.
Commit
()
if
e
!=
nil
{
logs
.
Error
(
"commit transaction failed: %v,%v"
,
e
,
panicked
)
}
}
}()
var
taskTxOrm
=
_txOrm
err
=
task
(
taskTxOrm
)
panicked
=
false
return
err
}
// return a raw query seter for raw sql string.
func
(
o
*
orm
)
Raw
(
query
string
,
args
...
interface
{})
RawSeter
{
return
newRawSet
(
o
,
query
,
args
)
type
txOrm
struct
{
ormBase
}
// return current using database Driver
func
(
o
*
orm
)
Driver
()
Driver
{
return
driver
(
o
.
alias
.
Name
)
var
_
TxOrmer
=
new
(
txOrm
)
func
(
t
*
txOrm
)
Commit
()
error
{
return
t
.
db
.
(
txEnder
)
.
Commit
()
}
// return sql.DBStats for current database
func
(
o
*
orm
)
DBStats
()
*
sql
.
DBStats
{
if
o
.
alias
!=
nil
&&
o
.
alias
.
DB
!=
nil
{
stats
:=
o
.
alias
.
DB
.
DB
.
Stats
()
return
&
stats
}
return
nil
func
(
t
*
txOrm
)
Rollback
()
error
{
return
t
.
db
.
(
txEnder
)
.
Rollback
()
}
// NewOrm create new orm
...
...
@@ -537,10 +593,18 @@ func NewOrm() Ormer {
BootStrap
()
// execute only once
o
:=
new
(
orm
)
err
:=
o
.
Using
(
"default"
)
if
err
!=
nil
{
panic
(
err
)
name
:=
`default`
if
al
,
ok
:=
dataBaseCache
.
get
(
name
);
ok
{
o
.
alias
=
al
if
Debug
{
o
.
db
=
newDbQueryLog
(
al
,
al
.
DB
)
}
else
{
o
.
db
=
al
.
DB
}
}
else
{
panic
(
fmt
.
Errorf
(
"<Ormer.Using> unknown db alias name `%s`"
,
name
))
}
return
o
}
...
...
pkg/orm/orm_object.go
浏览文件 @
41feb3a7
...
...
@@ -22,7 +22,7 @@ import (
// an insert queryer struct
type
insertSet
struct
{
mi
*
modelInfo
orm
*
orm
orm
*
orm
Base
stmt
stmtQuerier
closed
bool
}
...
...
@@ -70,7 +70,7 @@ func (o *insertSet) Close() error {
}
// create new insert queryer.
func
newInsertSet
(
orm
*
orm
,
mi
*
modelInfo
)
(
Inserter
,
error
)
{
func
newInsertSet
(
orm
*
orm
Base
,
mi
*
modelInfo
)
(
Inserter
,
error
)
{
bi
:=
new
(
insertSet
)
bi
.
orm
=
orm
bi
.
mi
=
mi
...
...
pkg/orm/orm_querym2m.go
浏览文件 @
41feb3a7
...
...
@@ -129,7 +129,7 @@ func (o *queryM2M) Count() (int64, error) {
var
_
QueryM2Mer
=
new
(
queryM2M
)
// create new M2M queryer.
func
newQueryM2M
(
md
interface
{},
o
*
orm
,
mi
*
modelInfo
,
fi
*
fieldInfo
,
ind
reflect
.
Value
)
QueryM2Mer
{
func
newQueryM2M
(
md
interface
{},
o
*
orm
Base
,
mi
*
modelInfo
,
fi
*
fieldInfo
,
ind
reflect
.
Value
)
QueryM2Mer
{
qm2m
:=
new
(
queryM2M
)
qm2m
.
md
=
md
qm2m
.
mi
=
mi
...
...
pkg/orm/orm_queryset.go
浏览文件 @
41feb3a7
...
...
@@ -72,7 +72,7 @@ type querySet struct {
orders
[]
string
distinct
bool
forupdate
bool
orm
*
orm
orm
*
orm
Base
ctx
context
.
Context
forContext
bool
}
...
...
@@ -292,7 +292,7 @@ func (o querySet) WithContext(ctx context.Context) QuerySeter {
}
// create new QuerySeter.
func
newQuerySet
(
orm
*
orm
,
mi
*
modelInfo
)
QuerySeter
{
func
newQuerySet
(
orm
*
orm
Base
,
mi
*
modelInfo
)
QuerySeter
{
o
:=
new
(
querySet
)
o
.
mi
=
mi
o
.
orm
=
orm
...
...
pkg/orm/orm_raw.go
浏览文件 @
41feb3a7
...
...
@@ -63,7 +63,7 @@ func newRawPreparer(rs *rawSet) (RawPreparer, error) {
type
rawSet
struct
{
query
string
args
[]
interface
{}
orm
*
orm
orm
*
orm
Base
}
var
_
RawSeter
=
new
(
rawSet
)
...
...
@@ -858,7 +858,7 @@ func (o *rawSet) Prepare() (RawPreparer, error) {
return
newRawPreparer
(
o
)
}
func
newRawSet
(
orm
*
orm
,
query
string
,
args
[]
interface
{})
RawSeter
{
func
newRawSet
(
orm
*
orm
Base
,
query
string
,
args
[]
interface
{})
RawSeter
{
o
:=
new
(
rawSet
)
o
.
query
=
query
o
.
args
=
args
...
...
pkg/orm/orm_test.go
浏览文件 @
41feb3a7
...
...
@@ -2026,24 +2026,24 @@ func TestTransaction(t *testing.T) {
// this test worked when database support transaction
o
:=
NewOrm
()
err
:=
o
.
Begin
()
to
,
err
:=
o
.
Begin
()
throwFail
(
t
,
err
)
var
names
=
[]
string
{
"1"
,
"2"
,
"3"
}
var
tag
Tag
tag
.
Name
=
names
[
0
]
id
,
err
:=
o
.
Insert
(
&
tag
)
id
,
err
:=
t
o
.
Insert
(
&
tag
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
id
>
0
,
true
))
num
,
err
:=
o
.
QueryTable
(
"tag"
)
.
Filter
(
"name"
,
"golang"
)
.
Update
(
Params
{
"name"
:
names
[
1
]})
num
,
err
:=
t
o
.
QueryTable
(
"tag"
)
.
Filter
(
"name"
,
"golang"
)
.
Update
(
Params
{
"name"
:
names
[
1
]})
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
switch
{
case
IsMysql
||
IsSqlite
:
res
,
err
:=
o
.
Raw
(
"INSERT INTO tag (name) VALUES (?)"
,
names
[
2
])
.
Exec
()
res
,
err
:=
t
o
.
Raw
(
"INSERT INTO tag (name) VALUES (?)"
,
names
[
2
])
.
Exec
()
throwFail
(
t
,
err
)
if
err
==
nil
{
id
,
err
=
res
.
LastInsertId
()
...
...
@@ -2052,22 +2052,22 @@ func TestTransaction(t *testing.T) {
}
}
err
=
o
.
Rollback
()
err
=
t
o
.
Rollback
()
throwFail
(
t
,
err
)
num
,
err
=
o
.
QueryTable
(
"tag"
)
.
Filter
(
"name__in"
,
names
)
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
0
))
err
=
o
.
Begin
()
to
,
err
=
o
.
Begin
()
throwFail
(
t
,
err
)
tag
.
Name
=
"commit"
id
,
err
=
o
.
Insert
(
&
tag
)
id
,
err
=
t
o
.
Insert
(
&
tag
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
id
>
0
,
true
))
o
.
Commit
()
t
o
.
Commit
()
throwFail
(
t
,
err
)
num
,
err
=
o
.
QueryTable
(
"tag"
)
.
Filter
(
"name"
,
"commit"
)
.
Delete
()
...
...
@@ -2086,33 +2086,33 @@ func TestTransactionIsolationLevel(t *testing.T) {
o2
:=
NewOrm
()
// start two transaction with isolation level repeatable read
err
:=
o1
.
BeginTx
(
context
.
Background
(),
&
sql
.
TxOptions
{
Isolation
:
sql
.
LevelRepeatableRead
})
to1
,
err
:=
o1
.
BeginWithCtxAndOpts
(
context
.
Background
(),
&
sql
.
TxOptions
{
Isolation
:
sql
.
LevelRepeatableRead
})
throwFail
(
t
,
err
)
err
=
o2
.
BeginTx
(
context
.
Background
(),
&
sql
.
TxOptions
{
Isolation
:
sql
.
LevelRepeatableRead
})
to2
,
err
:=
o2
.
BeginWithCtxAndOpts
(
context
.
Background
(),
&
sql
.
TxOptions
{
Isolation
:
sql
.
LevelRepeatableRead
})
throwFail
(
t
,
err
)
// o1 insert tag
var
tag
Tag
tag
.
Name
=
"test-transaction"
id
,
err
:=
o1
.
Insert
(
&
tag
)
id
,
err
:=
t
o1
.
Insert
(
&
tag
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
id
>
0
,
true
))
// o2 query tag table, no result
num
,
err
:=
o2
.
QueryTable
(
"tag"
)
.
Filter
(
"name"
,
"test-transaction"
)
.
Count
()
num
,
err
:=
t
o2
.
QueryTable
(
"tag"
)
.
Filter
(
"name"
,
"test-transaction"
)
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
0
))
// o1 commit
o1
.
Commit
()
t
o1
.
Commit
()
// o2 query tag table, still no result
num
,
err
=
o2
.
QueryTable
(
"tag"
)
.
Filter
(
"name"
,
"test-transaction"
)
.
Count
()
num
,
err
=
t
o2
.
QueryTable
(
"tag"
)
.
Filter
(
"name"
,
"test-transaction"
)
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
0
))
// o2 commit and query tag table, get the result
o2
.
Commit
()
t
o2
.
Commit
()
num
,
err
=
o2
.
QueryTable
(
"tag"
)
.
Filter
(
"name"
,
"test-transaction"
)
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
1
))
...
...
@@ -2125,14 +2125,14 @@ func TestTransactionIsolationLevel(t *testing.T) {
func
TestBeginTxWithContextCanceled
(
t
*
testing
.
T
)
{
o
:=
NewOrm
()
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
o
.
BeginTx
(
ctx
,
nil
)
id
,
err
:=
o
.
Insert
(
&
Tag
{
Name
:
"test-context"
})
to
,
_
:=
o
.
BeginWithCtx
(
ctx
)
id
,
err
:=
t
o
.
Insert
(
&
Tag
{
Name
:
"test-context"
})
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
id
>
0
,
true
))
// cancel the context before commit to make it error
cancel
()
err
=
o
.
Commit
()
err
=
t
o
.
Commit
()
throwFail
(
t
,
AssertIs
(
err
,
context
.
Canceled
))
}
...
...
pkg/orm/types.go
浏览文件 @
41feb3a7
...
...
@@ -35,35 +35,43 @@ type Fielder interface {
RawValue
()
interface
{}
}
// Ormer define the orm interface
type
Ormer
interface
{
// read data to model
// for example:
// this will find User by Id field
// u = &User{Id: user.Id}
// err = Ormer.Read(u)
// this will find User by UserName field
// u = &User{UserName: "astaxie", Password: "pass"}
// err = Ormer.Read(u, "UserName")
Read
(
md
interface
{},
cols
...
string
)
error
// Like Read(), but with "FOR UPDATE" clause, useful in transaction.
// Some databases are not support this feature.
ReadForUpdate
(
md
interface
{},
cols
...
string
)
error
// Try to read a row from the database, or insert one if it doesn't exist
ReadOrCreate
(
md
interface
{},
col1
string
,
cols
...
string
)
(
bool
,
int64
,
error
)
type
TxBeginner
interface
{
//self control transaction
Begin
()
(
TxOrmer
,
error
)
BeginWithCtx
(
ctx
context
.
Context
)
(
TxOrmer
,
error
)
BeginWithOpts
(
opts
*
sql
.
TxOptions
)
(
TxOrmer
,
error
)
BeginWithCtxAndOpts
(
ctx
context
.
Context
,
opts
*
sql
.
TxOptions
)
(
TxOrmer
,
error
)
//closure control transaction
DoTx
(
task
func
(
txOrm
TxOrmer
)
error
)
error
DoTxWithCtx
(
ctx
context
.
Context
,
task
func
(
txOrm
TxOrmer
)
error
)
error
DoTxWithOpts
(
opts
*
sql
.
TxOptions
,
task
func
(
txOrm
TxOrmer
)
error
)
error
DoTxWithCtxAndOpts
(
ctx
context
.
Context
,
opts
*
sql
.
TxOptions
,
task
func
(
txOrm
TxOrmer
)
error
)
error
}
type
TxCommitter
interface
{
Commit
()
error
Rollback
()
error
}
//Data Manipulation Language
type
DML
interface
{
// insert model data to database
// for example:
// user := new(User)
// id, err = Ormer.Insert(user)
// user must be a pointer and Insert will set user's pk field
Insert
(
interface
{})
(
int64
,
error
)
Insert
(
md
interface
{})
(
int64
,
error
)
InsertWithCtx
(
ctx
context
.
Context
,
md
interface
{})
(
int64
,
error
)
// mysql:InsertOrUpdate(model) or InsertOrUpdate(model,"colu=colu+value")
// if colu type is integer : can use(+-*/), string : convert(colu,"value")
// postgres: InsertOrUpdate(model,"conflictColumnName") or InsertOrUpdate(model,"conflictColumnName","colu=colu+value")
// if colu type is integer : can use(+-*/), string : colu || "value"
InsertOrUpdate
(
md
interface
{},
colConflitAndArgs
...
string
)
(
int64
,
error
)
InsertOrUpdateWithCtx
(
ctx
context
.
Context
,
md
interface
{},
colConflitAndArgs
...
string
)
(
int64
,
error
)
// insert some models to database
InsertMulti
(
bulk
int
,
mds
interface
{})
(
int64
,
error
)
InsertMultiWithCtx
(
ctx
context
.
Context
,
bulk
int
,
mds
interface
{})
(
int64
,
error
)
// update model to database.
// cols set the columns those want to update.
// find model by Id(pk) field and update columns specified by fields, if cols is null then update all columns
...
...
@@ -74,63 +82,93 @@ type Ormer interface {
// user.Extra.Data = "orm"
// num, err = Ormer.Update(&user, "Langs", "Extra")
Update
(
md
interface
{},
cols
...
string
)
(
int64
,
error
)
UpdateWithCtx
(
ctx
context
.
Context
,
md
interface
{},
cols
...
string
)
(
int64
,
error
)
// delete model in database
Delete
(
md
interface
{},
cols
...
string
)
(
int64
,
error
)
DeleteWithCtx
(
ctx
context
.
Context
,
md
interface
{},
cols
...
string
)
(
int64
,
error
)
// return a raw query seter for raw sql string.
// for example:
// ormer.Raw("UPDATE `user` SET `user_name` = ? WHERE `user_name` = ?", "slene", "testing").Exec()
// // update user testing's name to slene
Raw
(
query
string
,
args
...
interface
{})
RawSeter
RawWithCtx
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
RawSeter
}
// Data Query Language
type
DQL
interface
{
// read data to model
// for example:
// this will find User by Id field
// u = &User{Id: user.Id}
// err = Ormer.Read(u)
// this will find User by UserName field
// u = &User{UserName: "astaxie", Password: "pass"}
// err = Ormer.Read(u, "UserName")
Read
(
md
interface
{},
cols
...
string
)
error
ReadWithCtx
(
ctx
context
.
Context
,
md
interface
{},
cols
...
string
)
error
// Like Read(), but with "FOR UPDATE" clause, useful in transaction.
// Some databases are not support this feature.
ReadForUpdate
(
md
interface
{},
cols
...
string
)
error
ReadForUpdateWithCtx
(
ctx
context
.
Context
,
md
interface
{},
cols
...
string
)
error
// Try to read a row from the database, or insert one if it doesn't exist
ReadOrCreate
(
md
interface
{},
col1
string
,
cols
...
string
)
(
bool
,
int64
,
error
)
ReadOrCreateWithCtx
(
ctx
context
.
Context
,
md
interface
{},
col1
string
,
cols
...
string
)
(
bool
,
int64
,
error
)
// load related models to md model.
// args are limit, offset int and order string.
//
// example:
// Ormer.LoadRelated(post,"Tags")
// for _,tag := range post.Tags{...}
//args[0] bool true useDefaultRelsDepth ; false depth 0
//args[0] int loadRelationDepth
//args[1] int limit default limit 1000
//args[2] int offset default offset 0
//args[3] string order for example : "-Id"
//
args[0] bool true useDefaultRelsDepth ; false depth 0
//
args[0] int loadRelationDepth
//
args[1] int limit default limit 1000
//
args[2] int offset default offset 0
//
args[3] string order for example : "-Id"
// make sure the relation is defined in model struct tags.
LoadRelated
(
md
interface
{},
name
string
,
args
...
interface
{})
(
int64
,
error
)
LoadRelated
(
md
interface
{},
name
string
,
args
...
interface
{})
(
int64
,
error
)
LoadRelatedWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
,
args
...
interface
{})
(
int64
,
error
)
// create a models to models queryer
// for example:
// post := Post{Id: 4}
// m2m := Ormer.QueryM2M(&post, "Tags")
QueryM2M
(
md
interface
{},
name
string
)
QueryM2Mer
QueryM2M
(
md
interface
{},
name
string
)
QueryM2Mer
QueryM2MWithCtx
(
ctx
context
.
Context
,
md
interface
{},
name
string
)
QueryM2Mer
// return a QuerySeter for table operations.
// table name can be string or struct.
// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)),
QueryTable
(
ptrStructOrTableName
interface
{})
QuerySeter
QueryTableWithCtx
(
ctx
context
.
Context
,
ptrStructOrTableName
interface
{})
QuerySeter
// switch to another registered database driver by given name.
Using
(
name
string
)
error
// begin transaction
// for example:
// o := NewOrm()
// err := o.Begin()
// ...
// err = o.Rollback()
Begin
()
error
// begin transaction with provided context and option
// the provided context is used until the transaction is committed or rolled back.
// if the context is canceled, the transaction will be rolled back.
// the provided TxOptions is optional and may be nil if defaults should be used.
// if a non-default isolation level is used that the driver doesn't support, an error will be returned.
// for example:
// o := NewOrm()
// err := o.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead})
// ...
// err = o.Rollback()
BeginTx
(
ctx
context
.
Context
,
opts
*
sql
.
TxOptions
)
error
// commit transaction
Commit
()
error
// rollback transaction
Rollback
()
error
// return a raw query seter for raw sql string.
// for example:
// ormer.Raw("UPDATE `user` SET `user_name` = ? WHERE `user_name` = ?", "slene", "testing").Exec()
// // update user testing's name to slene
Raw
(
query
string
,
args
...
interface
{})
RawSeter
Driver
()
Driver
// Using(name string) error
DBStats
()
*
sql
.
DBStats
}
type
DriverGetter
interface
{
Driver
()
Driver
}
type
Ormer
interface
{
DQL
DML
DriverGetter
TxBeginner
}
type
TxOrmer
interface
{
DQL
DML
DriverGetter
TxCommitter
}
// Inserter insert prepared statement
type
Inserter
interface
{
Insert
(
interface
{})
(
int64
,
error
)
...
...
@@ -229,7 +267,7 @@ type QuerySeter interface {
// }) // user slene's name will change to slene2
Update
(
values
Params
)
(
int64
,
error
)
// delete from table
//for example:
//
for example:
// num ,err = qs.Filter("user_name__in", "testing1", "testing2").Delete()
// //delete two user who's name is testing1 or testing2
Delete
()
(
int64
,
error
)
...
...
@@ -314,8 +352,8 @@ type QueryM2Mer interface {
// remove models following the origin model relationship
// only delete rows from m2m table
// for example:
//tag3 := &Tag{Id:5,Name: "TestTag3"}
//num, err = m2m.Remove(tag3)
//
tag3 := &Tag{Id:5,Name: "TestTag3"}
//
num, err = m2m.Remove(tag3)
Remove
(
...
interface
{})
(
int64
,
error
)
// check model is existed in relationship of origin model
Exist
(
interface
{})
bool
...
...
@@ -337,10 +375,10 @@ type RawPreparer interface {
// sql := fmt.Sprintf("SELECT %sid%s,%sname%s FROM %suser%s WHERE id = ?",Q,Q,Q,Q,Q,Q)
// rs := Ormer.Raw(sql, 1)
type
RawSeter
interface
{
//execute sql and get result
//
execute sql and get result
Exec
()
(
sql
.
Result
,
error
)
//query data and map to container
//for example:
//
query data and map to container
//
for example:
// var name string
// var id int
// rs.QueryRow(&id,&name) // id==2 name=="slene"
...
...
@@ -396,11 +434,11 @@ type RawSeter interface {
type
stmtQuerier
interface
{
Close
()
error
Exec
(
args
...
interface
{})
(
sql
.
Result
,
error
)
//ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error)
//
ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error)
Query
(
args
...
interface
{})
(
*
sql
.
Rows
,
error
)
//QueryContext(args ...interface{}) (*sql.Rows, error)
//
QueryContext(args ...interface{}) (*sql.Rows, error)
QueryRow
(
args
...
interface
{})
*
sql
.
Row
//QueryRowContext(ctx context.Context, args ...interface{}) *sql.Row
//
QueryRowContext(ctx context.Context, args ...interface{}) *sql.Row
}
// db querier
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录