mirror of
https://gitee.com/johng/gf.git
synced 2024-12-02 20:28:17 +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
|
**/.DS_Store
|
||||||
.test/
|
.test/
|
||||||
cmd/gf/main
|
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("watchFileDir:", watchFileDir)
|
||||||
mlog.Debug("logicFolderDir:", srcFolderDir)
|
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)
|
mlog.Printf(`ignore watch file "%s", not in source path "%s"`, in.WatchFile, in.SrcFolder)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ import _ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
|||||||
import _ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
|
import _ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
|
||||||
```
|
```
|
||||||
Note:
|
Note:
|
||||||
- It does not support `Save/Replace` features.
|
- It does not support `Save` features.
|
||||||
|
|
||||||
## PostgreSQL
|
## PostgreSQL
|
||||||
```
|
```
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/gogf/gf/v2/errors/gerror"
|
"github.com/gogf/gf/v2/errors/gerror"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Driver is the driver for sqlite database.
|
// Driver is the driver for sqlite database.
|
||||||
@ -35,6 +36,8 @@ type Driver struct {
|
|||||||
var (
|
var (
|
||||||
// tableFieldsMap caches the table information retrieved from database.
|
// tableFieldsMap caches the table information retrieved from database.
|
||||||
tableFieldsMap = gmap.New(true)
|
tableFieldsMap = gmap.New(true)
|
||||||
|
// Error
|
||||||
|
ErrorSave = gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by sqlite driver`)
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -147,10 +150,17 @@ func (d *Driver) TableFields(ctx context.Context, table string, schema ...string
|
|||||||
}
|
}
|
||||||
fields = make(map[string]*gdb.TableField)
|
fields = make(map[string]*gdb.TableField)
|
||||||
for i, m := range result {
|
for i, m := range result {
|
||||||
|
mKey := ""
|
||||||
|
if m["pk"].Bool() {
|
||||||
|
mKey = "pri"
|
||||||
|
}
|
||||||
fields[strings.ToLower(m["name"].String())] = &gdb.TableField{
|
fields[strings.ToLower(m["name"].String())] = &gdb.TableField{
|
||||||
Index: i,
|
Index: i,
|
||||||
Name: strings.ToLower(m["name"].String()),
|
Name: strings.ToLower(m["name"].String()),
|
||||||
Type: strings.ToLower(m["type"].String()),
|
Type: strings.ToLower(m["type"].String()),
|
||||||
|
Key: mKey,
|
||||||
|
Default: m["dflt_value"].Val(),
|
||||||
|
Null: !m["notnull"].Bool(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fields
|
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) {
|
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 {
|
switch option.InsertOption {
|
||||||
case gdb.InsertOptionSave:
|
case gdb.InsertOptionSave:
|
||||||
return nil, gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by sqlite driver`)
|
return nil, ErrorSave
|
||||||
|
case gdb.InsertOptionIgnore, gdb.InsertOptionReplace:
|
||||||
case gdb.InsertOptionReplace:
|
var (
|
||||||
return nil, gerror.NewCode(gcode.CodeNotSupported, `Replace operation is not supported by sqlite driver`)
|
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:
|
default:
|
||||||
return d.Core.DoInsert(ctx, link, table, list, option)
|
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