mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 11:18:02 +08:00
add gdb.Raw for raw sql instead of prepare argument feature
This commit is contained in:
parent
117eaea720
commit
8978112433
@ -3,7 +3,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/database/gdb"
|
||||
"time"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -18,10 +18,9 @@ func main() {
|
||||
|
||||
db.SetDebug(true)
|
||||
|
||||
type User struct {
|
||||
CreateTime time.Time `orm:"create_time"`
|
||||
}
|
||||
r, e := db.Table("user").Data(User{CreateTime: time.Now()}).Insert()
|
||||
r, e := db.Table("user").Data(g.Map{
|
||||
"create_at": "now()",
|
||||
}).Unscoped().Insert()
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
|
@ -225,21 +225,12 @@ type Counter struct {
|
||||
}
|
||||
|
||||
type (
|
||||
// Value is the field value type.
|
||||
Value = *gvar.Var
|
||||
|
||||
// Record is the row record of the table.
|
||||
Record map[string]Value
|
||||
|
||||
// Result is the row record array.
|
||||
Result []Record
|
||||
|
||||
// Map is alias of map[string]interface{},
|
||||
// which is the most common usage map type.
|
||||
Map = map[string]interface{}
|
||||
|
||||
// List is type of map array.
|
||||
List = []Map
|
||||
Raw string // Raw is a raw sql that will not be treated as argument but as a direct sql part.
|
||||
Value = *gvar.Var // Value is the field value type.
|
||||
Record map[string]Value // Record is the row record of the table.
|
||||
Result []Record // Result is the row record array.
|
||||
Map = map[string]interface{} // Map is alias of map[string]interface{}, which is the most common usage map type.
|
||||
List = []Map // List is type of map array.
|
||||
)
|
||||
|
||||
const (
|
||||
@ -247,10 +238,10 @@ const (
|
||||
insertOptionReplace = 1
|
||||
insertOptionSave = 2
|
||||
insertOptionIgnore = 3
|
||||
defaultBatchNumber = 10 // Per count for batch insert/replace/save.
|
||||
defaultMaxIdleConnCount = 10 // Max idle connection count in pool.
|
||||
defaultMaxOpenConnCount = 100 // Max open connection count in pool.
|
||||
defaultMaxConnLifeTime = 30 // Max life time for per connection in pool in seconds.
|
||||
defaultBatchNumber = 10 // Per count for batch insert/replace/save.
|
||||
defaultMaxIdleConnCount = 10 // Max idle connection count in pool.
|
||||
defaultMaxOpenConnCount = 100 // Max open connection count in pool.
|
||||
defaultMaxConnLifeTime = 30 * time.Second // Max life time for per connection in pool in seconds.
|
||||
)
|
||||
|
||||
var (
|
||||
@ -459,9 +450,13 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
|
||||
}
|
||||
if c.config.MaxIdleConnCount > 0 {
|
||||
sqlDb.SetMaxIdleConns(c.config.MaxIdleConnCount)
|
||||
} else {
|
||||
sqlDb.SetMaxIdleConns(defaultMaxIdleConnCount)
|
||||
}
|
||||
if c.config.MaxOpenConnCount > 0 {
|
||||
sqlDb.SetMaxOpenConns(c.config.MaxOpenConnCount)
|
||||
} else {
|
||||
sqlDb.SetMaxOpenConns(defaultMaxOpenConnCount)
|
||||
}
|
||||
if c.config.MaxConnLifetime > 0 {
|
||||
// Automatically checks whether MaxConnLifetime is configured using string like: "30s", "60s", etc.
|
||||
@ -471,6 +466,8 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
|
||||
} else {
|
||||
sqlDb.SetConnMaxLifetime(c.config.MaxConnLifetime * time.Second)
|
||||
}
|
||||
} else {
|
||||
sqlDb.SetConnMaxLifetime(defaultMaxConnLifeTime)
|
||||
}
|
||||
return sqlDb, nil
|
||||
}, 0)
|
||||
|
@ -479,8 +479,12 @@ func (c *Core) DoInsert(link Link, table string, data interface{}, option int, b
|
||||
)
|
||||
for k, v := range dataMap {
|
||||
fields = append(fields, charL+k+charR)
|
||||
values = append(values, "?")
|
||||
params = append(params, v)
|
||||
if s, ok := v.(Raw); ok {
|
||||
values = append(values, gconv.String(s))
|
||||
} else {
|
||||
values = append(values, "?")
|
||||
params = append(params, v)
|
||||
}
|
||||
}
|
||||
if option == insertOptionSave {
|
||||
for k, _ := range dataMap {
|
||||
@ -615,19 +619,16 @@ func (c *Core) DoBatchInsert(link Link, table string, list interface{}, option i
|
||||
}
|
||||
}
|
||||
// Handle the field names and place holders.
|
||||
holders := []string(nil)
|
||||
for k, _ := range listMap[0] {
|
||||
keys = append(keys, k)
|
||||
holders = append(holders, "?")
|
||||
}
|
||||
// Prepare the batch result pointer.
|
||||
var (
|
||||
charL, charR = c.DB.GetChars()
|
||||
batchResult = new(SqlResult)
|
||||
keysStr = charL + strings.Join(keys, charR+","+charL) + charR
|
||||
valueHolderStr = "(" + strings.Join(holders, ",") + ")"
|
||||
operation = GetInsertOperationByOption(option)
|
||||
updateStr = ""
|
||||
charL, charR = c.DB.GetChars()
|
||||
batchResult = new(SqlResult)
|
||||
keysStr = charL + strings.Join(keys, charR+","+charL) + charR
|
||||
operation = GetInsertOperationByOption(option)
|
||||
updateStr = ""
|
||||
)
|
||||
if option == insertOptionSave {
|
||||
for _, k := range keys {
|
||||
@ -651,23 +652,30 @@ func (c *Core) DoBatchInsert(link Link, table string, list interface{}, option i
|
||||
if len(batch) > 0 && batch[0] > 0 {
|
||||
batchNum = batch[0]
|
||||
}
|
||||
listMapLen := len(listMap)
|
||||
var (
|
||||
listMapLen = len(listMap)
|
||||
valueHolder = make([]string, 0)
|
||||
)
|
||||
for i := 0; i < listMapLen; i++ {
|
||||
values = values[:0]
|
||||
// Note that the map type is unordered,
|
||||
// so it should use slice+key to retrieve the value.
|
||||
for _, k := range keys {
|
||||
params = append(params, listMap[i][k])
|
||||
if s, ok := listMap[i][k].(Raw); ok {
|
||||
values = append(values, gconv.String(s))
|
||||
} else {
|
||||
values = append(values, "?")
|
||||
params = append(params, listMap[i][k])
|
||||
}
|
||||
}
|
||||
values = append(values, valueHolderStr)
|
||||
valueHolder = append(valueHolder, "("+gstr.Join(values, ",")+")")
|
||||
if len(values) == batchNum || (i == listMapLen-1 && len(values) > 0) {
|
||||
r, err := c.DB.DoExec(
|
||||
link,
|
||||
fmt.Sprintf(
|
||||
"%s INTO %s(%s) VALUES%s %s",
|
||||
operation,
|
||||
table,
|
||||
keysStr,
|
||||
strings.Join(values, ","),
|
||||
operation, table, keysStr,
|
||||
gstr.Join(valueHolder, ","),
|
||||
updateStr,
|
||||
),
|
||||
params...,
|
||||
@ -682,7 +690,7 @@ func (c *Core) DoBatchInsert(link Link, table string, list interface{}, option i
|
||||
batchResult.affected += n
|
||||
}
|
||||
params = params[:0]
|
||||
values = values[:0]
|
||||
valueHolder = valueHolder[:0]
|
||||
}
|
||||
}
|
||||
return batchResult, nil
|
||||
@ -743,8 +751,13 @@ func (c *Core) DoUpdate(link Link, table string, data interface{}, condition str
|
||||
params = append(params, value.Value)
|
||||
}
|
||||
default:
|
||||
fields = append(fields, c.DB.QuoteWord(k)+"=?")
|
||||
params = append(params, v)
|
||||
if s, ok := v.(Raw); ok {
|
||||
fields = append(fields, c.DB.QuoteWord(k)+"="+gconv.String(s))
|
||||
} else {
|
||||
fields = append(fields, c.DB.QuoteWord(k)+"=?")
|
||||
params = append(params, v)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
updates = strings.Join(fields, ",")
|
||||
|
@ -501,7 +501,11 @@ func formatWhereInterfaces(db DB, where []interface{}, buffer *bytes.Buffer, new
|
||||
} else {
|
||||
buffer.WriteString(db.QuoteWord(str) + "=?")
|
||||
}
|
||||
newArgs = append(newArgs, where[i+1])
|
||||
if s, ok := where[i+1].(Raw); ok {
|
||||
buffer.WriteString(gconv.String(s))
|
||||
} else {
|
||||
newArgs = append(newArgs, where[i+1])
|
||||
}
|
||||
}
|
||||
return newArgs
|
||||
}
|
||||
@ -569,7 +573,11 @@ func formatWhereKeyValue(db DB, buffer *bytes.Buffer, newArgs []interface{}, key
|
||||
} else {
|
||||
buffer.WriteString(quotedKey)
|
||||
}
|
||||
newArgs = append(newArgs, value)
|
||||
if s, ok := value.(Raw); ok {
|
||||
buffer.WriteString(gconv.String(s))
|
||||
} else {
|
||||
newArgs = append(newArgs, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
return newArgs
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
// Copyright GoFrame gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
|
80
database/gdb/gdb_z_mysql_raw_test.go
Normal file
80
database/gdb/gdb_z_mysql_raw_test.go
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright GoFrame gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gdb_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/database/gdb"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func Test_Insert_Raw(t *testing.T) {
|
||||
table := createTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
user := db.Table(table)
|
||||
result, err := user.Filter().Data(g.Map{
|
||||
"id": gdb.Raw("id+2"),
|
||||
"passport": "port_1",
|
||||
"password": "pass_1",
|
||||
"nickname": "name_1",
|
||||
"create_time": gdb.Raw("now()"),
|
||||
}).Insert()
|
||||
t.Assert(err, nil)
|
||||
n, _ := result.LastInsertId()
|
||||
t.Assert(n, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_BatchInsert_Raw(t *testing.T) {
|
||||
table := createTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
user := db.Table(table)
|
||||
result, err := user.Filter().Data(
|
||||
g.List{
|
||||
g.Map{
|
||||
"id": gdb.Raw("id+2"),
|
||||
"passport": "port_2",
|
||||
"password": "pass_2",
|
||||
"nickname": "name_2",
|
||||
"create_time": gdb.Raw("now()"),
|
||||
},
|
||||
g.Map{
|
||||
"id": gdb.Raw("id+4"),
|
||||
"passport": "port_4",
|
||||
"password": "pass_4",
|
||||
"nickname": "name_4",
|
||||
"create_time": gdb.Raw("now()"),
|
||||
},
|
||||
},
|
||||
).Insert()
|
||||
t.Assert(err, nil)
|
||||
n, _ := result.LastInsertId()
|
||||
t.Assert(n, 4)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Update_Raw(t *testing.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
user := db.Table(table)
|
||||
result, err := user.Data(g.Map{
|
||||
"id": gdb.Raw("id+100"),
|
||||
"create_time": gdb.Raw("now()"),
|
||||
}).Where("id", 1).Insert()
|
||||
t.Assert(err, nil)
|
||||
n, _ := result.RowsAffected()
|
||||
t.Assert(n, 1)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user