mirror of
https://gitee.com/johng/gf.git
synced 2024-12-02 12:17:53 +08:00
Merge branch 'master' of https://github.com/gogf/gf
This commit is contained in:
commit
7d5ab1f8db
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,3 +15,4 @@ cbuild
|
||||
**/.DS_Store
|
||||
.test/
|
||||
cmd/gf/main
|
||||
go.work
|
||||
|
@ -65,7 +65,7 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
|
||||
)
|
||||
mlog.Debug("watchFileDir:", watchFileDir)
|
||||
mlog.Debug("logicFolderDir:", srcFolderDir)
|
||||
if !gstr.HasSuffix(srcFolderDir, in.SrcFolder) {
|
||||
if !gstr.HasSuffix(gstr.Replace(srcFolderDir, `\`, `/`), in.SrcFolder) {
|
||||
mlog.Printf(`ignore watch file "%s", not in source path "%s"`, in.WatchFile, in.SrcFolder)
|
||||
return
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ import _ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
||||
import _ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
|
||||
```
|
||||
Note:
|
||||
- It does not support `Save/Replace` features.
|
||||
- It does not support `Save` features.
|
||||
|
||||
## PostgreSQL
|
||||
```
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
// Driver is the driver for sqlite database.
|
||||
@ -35,6 +36,8 @@ type Driver struct {
|
||||
var (
|
||||
// tableFieldsMap caches the table information retrieved from database.
|
||||
tableFieldsMap = gmap.New(true)
|
||||
// Error
|
||||
ErrorSave = gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by sqlite driver`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -147,10 +150,17 @@ func (d *Driver) TableFields(ctx context.Context, table string, schema ...string
|
||||
}
|
||||
fields = make(map[string]*gdb.TableField)
|
||||
for i, m := range result {
|
||||
mKey := ""
|
||||
if m["pk"].Bool() {
|
||||
mKey = "pri"
|
||||
}
|
||||
fields[strings.ToLower(m["name"].String())] = &gdb.TableField{
|
||||
Index: i,
|
||||
Name: strings.ToLower(m["name"].String()),
|
||||
Type: strings.ToLower(m["type"].String()),
|
||||
Index: i,
|
||||
Name: strings.ToLower(m["name"].String()),
|
||||
Type: strings.ToLower(m["type"].String()),
|
||||
Key: mKey,
|
||||
Default: m["dflt_value"].Val(),
|
||||
Null: !m["notnull"].Bool(),
|
||||
}
|
||||
}
|
||||
return fields
|
||||
@ -166,11 +176,73 @@ func (d *Driver) TableFields(ctx context.Context, table string, schema ...string
|
||||
func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption) (result sql.Result, err error) {
|
||||
switch option.InsertOption {
|
||||
case gdb.InsertOptionSave:
|
||||
return nil, gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by sqlite driver`)
|
||||
|
||||
case gdb.InsertOptionReplace:
|
||||
return nil, gerror.NewCode(gcode.CodeNotSupported, `Replace operation is not supported by sqlite driver`)
|
||||
return nil, ErrorSave
|
||||
case gdb.InsertOptionIgnore, gdb.InsertOptionReplace:
|
||||
var (
|
||||
keys []string // Field names.
|
||||
values []string // Value holder string array, like: (?,?,?)
|
||||
params []interface{} // Values that will be committed to underlying database driver.
|
||||
onDuplicateStr string // onDuplicateStr is used in "ON DUPLICATE KEY UPDATE" statement.
|
||||
)
|
||||
// Handle the field names and placeholders.
|
||||
for k := range list[0] {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
// Prepare the batch result pointer.
|
||||
var (
|
||||
charL, charR = d.GetChars()
|
||||
batchResult = new(gdb.SqlResult)
|
||||
keysStr = charL + strings.Join(keys, charR+","+charL) + charR
|
||||
operation = "INSERT OR IGNORE"
|
||||
)
|
||||
|
||||
if option.InsertOption == gdb.InsertOptionReplace {
|
||||
operation = "INSERT OR REPLACE"
|
||||
}
|
||||
var (
|
||||
listLength = len(list)
|
||||
valueHolder = make([]string, 0)
|
||||
)
|
||||
for i := 0; i < listLength; 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 {
|
||||
if s, ok := list[i][k].(gdb.Raw); ok {
|
||||
values = append(values, gconv.String(s))
|
||||
} else {
|
||||
values = append(values, "?")
|
||||
params = append(params, list[i][k])
|
||||
}
|
||||
}
|
||||
valueHolder = append(valueHolder, "("+gstr.Join(values, ",")+")")
|
||||
// Batch package checks: It meets the batch number, or it is the last element.
|
||||
if len(valueHolder) == option.BatchCount || (i == listLength-1 && len(valueHolder) > 0) {
|
||||
var (
|
||||
stdSqlResult sql.Result
|
||||
affectedRows int64
|
||||
)
|
||||
stdSqlResult, err = d.DoExec(ctx, link, fmt.Sprintf(
|
||||
"%s INTO %s(%s) VALUES%s %s",
|
||||
operation, d.QuotePrefixTableName(table), keysStr,
|
||||
gstr.Join(valueHolder, ","),
|
||||
onDuplicateStr,
|
||||
), params...)
|
||||
if err != nil {
|
||||
return stdSqlResult, err
|
||||
}
|
||||
if affectedRows, err = stdSqlResult.RowsAffected(); err != nil {
|
||||
err = gerror.WrapCode(gcode.CodeDbOperationError, err, `sql.Result.RowsAffected failed`)
|
||||
return stdSqlResult, err
|
||||
} else {
|
||||
batchResult.Result = stdSqlResult
|
||||
batchResult.Affected += affectedRows
|
||||
}
|
||||
params = params[:0]
|
||||
valueHolder = valueHolder[:0]
|
||||
}
|
||||
}
|
||||
return batchResult, nil
|
||||
default:
|
||||
return d.Core.DoInsert(ctx, link, table, list, option)
|
||||
}
|
||||
|
161
contrib/drivers/sqlite/sqlite_0_test.go
Normal file
161
contrib/drivers/sqlite/sqlite_0_test.go
Normal file
@ -0,0 +1,161 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 sqlite_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
)
|
||||
|
||||
var (
|
||||
db gdb.DB
|
||||
dbPrefix gdb.DB
|
||||
dbInvalid gdb.DB
|
||||
configNode gdb.ConfigNode
|
||||
dbDir = gfile.Temp("sqlite")
|
||||
ctx = gctx.New()
|
||||
|
||||
// Error
|
||||
ErrorSave = gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by sqlite driver`)
|
||||
)
|
||||
|
||||
const (
|
||||
TableSize = 10
|
||||
TableName = "user"
|
||||
TestSchema1 = "test1"
|
||||
TestSchema2 = "test2"
|
||||
TableNamePrefix = "gf_"
|
||||
CreateTime = "2018-10-24 10:00:00"
|
||||
DBGroupTest = "test"
|
||||
DBGroupPrefix = "prefix"
|
||||
DBGroupInvalid = "invalid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fmt.Println("init sqlite db start")
|
||||
|
||||
if err := gfile.Mkdir(dbDir); err != nil {
|
||||
gtest.Error(err)
|
||||
}
|
||||
|
||||
fmt.Println("init sqlite db dir: ", dbDir)
|
||||
|
||||
configNode = gdb.ConfigNode{
|
||||
Type: "sqlite",
|
||||
Link: gfile.Join(dbDir, "test.db"),
|
||||
Charset: "utf8",
|
||||
}
|
||||
nodePrefix := configNode
|
||||
nodePrefix.Prefix = TableNamePrefix
|
||||
|
||||
nodeInvalid := configNode
|
||||
|
||||
gdb.AddConfigNode(DBGroupTest, configNode)
|
||||
gdb.AddConfigNode(DBGroupPrefix, nodePrefix)
|
||||
gdb.AddConfigNode(DBGroupInvalid, nodeInvalid)
|
||||
gdb.AddConfigNode(gdb.DefaultGroupName, configNode)
|
||||
|
||||
// Default db.
|
||||
if r, err := gdb.NewByGroup(); err != nil {
|
||||
gtest.Error(err)
|
||||
} else {
|
||||
db = r
|
||||
}
|
||||
|
||||
// Prefix db.
|
||||
if r, err := gdb.NewByGroup(DBGroupPrefix); err != nil {
|
||||
gtest.Error(err)
|
||||
} else {
|
||||
dbPrefix = r
|
||||
}
|
||||
|
||||
// Invalid db.
|
||||
if r, err := gdb.NewByGroup(DBGroupInvalid); err != nil {
|
||||
gtest.Error(err)
|
||||
} else {
|
||||
dbInvalid = r
|
||||
}
|
||||
|
||||
fmt.Println("init sqlite db finish")
|
||||
}
|
||||
|
||||
func createTable(table ...string) string {
|
||||
return createTableWithDb(db, table...)
|
||||
}
|
||||
|
||||
func createInitTable(table ...string) string {
|
||||
return createInitTableWithDb(db, table...)
|
||||
}
|
||||
|
||||
func dropTable(table string) {
|
||||
dropTableWithDb(db, table)
|
||||
}
|
||||
|
||||
func createTableWithDb(db gdb.DB, table ...string) (name string) {
|
||||
if len(table) > 0 {
|
||||
name = table[0]
|
||||
} else {
|
||||
name = fmt.Sprintf(`%s_%d`, TableName, gtime.TimestampNano())
|
||||
}
|
||||
dropTableWithDb(db, name)
|
||||
|
||||
if _, err := db.Exec(ctx, fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT
|
||||
UNIQUE
|
||||
NOT NULL,
|
||||
passport VARCHAR(45) NOT NULL
|
||||
DEFAULT passport,
|
||||
password VARCHAR(128) NOT NULL
|
||||
DEFAULT password,
|
||||
nickname VARCHAR(45),
|
||||
create_time DATETIME
|
||||
);
|
||||
`, name,
|
||||
)); err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func createInitTableWithDb(db gdb.DB, table ...string) (name string) {
|
||||
name = createTableWithDb(db, table...)
|
||||
array := garray.New(true)
|
||||
for i := 1; i <= TableSize; i++ {
|
||||
array.Append(g.Map{
|
||||
"id": i,
|
||||
"passport": fmt.Sprintf(`user_%d`, i),
|
||||
"password": fmt.Sprintf(`pass_%d`, i),
|
||||
"nickname": fmt.Sprintf(`name_%d`, i),
|
||||
"create_time": gtime.NewFromStr(CreateTime).String(),
|
||||
})
|
||||
}
|
||||
|
||||
result, err := db.Insert(ctx, name, array.Slice())
|
||||
gtest.AssertNil(err)
|
||||
|
||||
n, e := result.RowsAffected()
|
||||
gtest.Assert(e, nil)
|
||||
gtest.Assert(n, TableSize)
|
||||
return
|
||||
}
|
||||
|
||||
func dropTableWithDb(db gdb.DB, table string) {
|
||||
if _, err := db.Exec(ctx, fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)); err != nil {
|
||||
gtest.Error(err)
|
||||
}
|
||||
}
|
1551
contrib/drivers/sqlite/sqlite_core_test.go
Normal file
1551
contrib/drivers/sqlite/sqlite_core_test.go
Normal file
File diff suppressed because it is too large
Load Diff
4084
contrib/drivers/sqlite/sqlite_model_test.go
Normal file
4084
contrib/drivers/sqlite/sqlite_model_test.go
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user