mirror of
https://github.com/astaxie/beego.git
synced 2024-11-25 19:50:55 +00:00
Merge pull request #2158 from simpleelegant/develop
Add support "SELECT FOR UPDATE" to orm. Resolve issue #2157
This commit is contained in:
commit
d5fb74aa94
@ -310,7 +310,7 @@ func (d *dbBase) InsertStmt(stmt stmtQuerier, mi *modelInfo, ind reflect.Value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// query sql ,read records and persist in dbBaser.
|
// query sql ,read records and persist in dbBaser.
|
||||||
func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) error {
|
func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string, isForUpdate bool) error {
|
||||||
var whereCols []string
|
var whereCols []string
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
|
|
||||||
@ -341,7 +341,12 @@ func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Lo
|
|||||||
sep = fmt.Sprintf("%s = ? AND %s", Q, Q)
|
sep = fmt.Sprintf("%s = ? AND %s", Q, Q)
|
||||||
wheres := strings.Join(whereCols, sep)
|
wheres := strings.Join(whereCols, sep)
|
||||||
|
|
||||||
query := fmt.Sprintf("SELECT %s%s%s FROM %s%s%s WHERE %s%s%s = ?", Q, sels, Q, Q, mi.table, Q, Q, wheres, Q)
|
forUpdate := ""
|
||||||
|
if isForUpdate {
|
||||||
|
forUpdate = "FOR UPDATE"
|
||||||
|
}
|
||||||
|
|
||||||
|
query := fmt.Sprintf("SELECT %s%s%s FROM %s%s%s WHERE %s%s%s = ? %s", Q, sels, Q, Q, mi.table, Q, Q, wheres, Q, forUpdate)
|
||||||
|
|
||||||
refs := make([]interface{}, colsNum)
|
refs := make([]interface{}, colsNum)
|
||||||
for i := range refs {
|
for i := range refs {
|
||||||
|
14
orm/orm.go
14
orm/orm.go
@ -122,7 +122,17 @@ func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo {
|
|||||||
// read data to model
|
// read data to model
|
||||||
func (o *orm) Read(md interface{}, cols ...string) error {
|
func (o *orm) Read(md interface{}, cols ...string) error {
|
||||||
mi, ind := o.getMiInd(md, true)
|
mi, ind := o.getMiInd(md, true)
|
||||||
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, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// read data to model, like Read(), but use "SELECT FOR UPDATE" form
|
||||||
|
func (o *orm) ReadForUpdate(md interface{}, cols ...string) error {
|
||||||
|
mi, ind := o.getMiInd(md, true)
|
||||||
|
err := o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -133,7 +143,7 @@ func (o *orm) Read(md interface{}, cols ...string) error {
|
|||||||
func (o *orm) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) {
|
func (o *orm) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) {
|
||||||
cols = append([]string{col1}, cols...)
|
cols = append([]string{col1}, cols...)
|
||||||
mi, ind := o.getMiInd(md, true)
|
mi, ind := o.getMiInd(md, true)
|
||||||
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, false)
|
||||||
if err == ErrNoRows {
|
if err == ErrNoRows {
|
||||||
// Create
|
// Create
|
||||||
id, err := o.Insert(md)
|
id, err := o.Insert(md)
|
||||||
|
@ -19,6 +19,7 @@ import "errors"
|
|||||||
// QueryBuilder is the Query builder interface
|
// QueryBuilder is the Query builder interface
|
||||||
type QueryBuilder interface {
|
type QueryBuilder interface {
|
||||||
Select(fields ...string) QueryBuilder
|
Select(fields ...string) QueryBuilder
|
||||||
|
ForUpdate() QueryBuilder
|
||||||
From(tables ...string) QueryBuilder
|
From(tables ...string) QueryBuilder
|
||||||
InnerJoin(table string) QueryBuilder
|
InnerJoin(table string) QueryBuilder
|
||||||
LeftJoin(table string) QueryBuilder
|
LeftJoin(table string) QueryBuilder
|
||||||
|
@ -34,6 +34,12 @@ func (qb *MySQLQueryBuilder) Select(fields ...string) QueryBuilder {
|
|||||||
return qb
|
return qb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForUpdate add the FOR UPDATE clause
|
||||||
|
func (qb *MySQLQueryBuilder) ForUpdate() QueryBuilder {
|
||||||
|
qb.Tokens = append(qb.Tokens, "FOR UPDATE")
|
||||||
|
return qb
|
||||||
|
}
|
||||||
|
|
||||||
// From join the tables
|
// From join the tables
|
||||||
func (qb *MySQLQueryBuilder) From(tables ...string) QueryBuilder {
|
func (qb *MySQLQueryBuilder) From(tables ...string) QueryBuilder {
|
||||||
qb.Tokens = append(qb.Tokens, "FROM", strings.Join(tables, CommaSpace))
|
qb.Tokens = append(qb.Tokens, "FROM", strings.Join(tables, CommaSpace))
|
||||||
|
@ -31,6 +31,12 @@ func (qb *TiDBQueryBuilder) Select(fields ...string) QueryBuilder {
|
|||||||
return qb
|
return qb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForUpdate add the FOR UPDATE clause
|
||||||
|
func (qb *TiDBQueryBuilder) ForUpdate() QueryBuilder {
|
||||||
|
qb.Tokens = append(qb.Tokens, "FOR UPDATE")
|
||||||
|
return qb
|
||||||
|
}
|
||||||
|
|
||||||
// From join the tables
|
// From join the tables
|
||||||
func (qb *TiDBQueryBuilder) From(tables ...string) QueryBuilder {
|
func (qb *TiDBQueryBuilder) From(tables ...string) QueryBuilder {
|
||||||
qb.Tokens = append(qb.Tokens, "FROM", strings.Join(tables, CommaSpace))
|
qb.Tokens = append(qb.Tokens, "FROM", strings.Join(tables, CommaSpace))
|
||||||
|
@ -45,6 +45,9 @@ type Ormer interface {
|
|||||||
// u = &User{UserName: "astaxie", Password: "pass"}
|
// u = &User{UserName: "astaxie", Password: "pass"}
|
||||||
// err = Ormer.Read(u, "UserName")
|
// err = Ormer.Read(u, "UserName")
|
||||||
Read(md interface{}, cols ...string) error
|
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
|
// 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)
|
ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error)
|
||||||
// insert model data to database
|
// insert model data to database
|
||||||
@ -394,7 +397,7 @@ type txEnder interface {
|
|||||||
|
|
||||||
// base database struct
|
// base database struct
|
||||||
type dbBaser interface {
|
type dbBaser interface {
|
||||||
Read(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) error
|
Read(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string, bool) error
|
||||||
Insert(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
|
Insert(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
|
||||||
InsertOrUpdate(dbQuerier, *modelInfo, reflect.Value, *alias, ...string) (int64, error)
|
InsertOrUpdate(dbQuerier, *modelInfo, reflect.Value, *alias, ...string) (int64, error)
|
||||||
InsertMulti(dbQuerier, *modelInfo, reflect.Value, int, *time.Location) (int64, error)
|
InsertMulti(dbQuerier, *modelInfo, reflect.Value, int, *time.Location) (int64, error)
|
||||||
|
Loading…
Reference in New Issue
Block a user