Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
gqcn authored Dec 19, 2023
1 parent 7975e39 commit 645c5ff
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 9 deletions.
95 changes: 94 additions & 1 deletion contrib/drivers/mysql/mysql_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package mysql_test

import (
"context"
"fmt"
"testing"
"time"
Expand Down Expand Up @@ -886,7 +887,8 @@ func Test_Issue3086(t *testing.T) {
func Test_Issue3204(t *testing.T) {
table := createInitTable()
defer dropTable(table)
db.SetDebug(true)

// where
gtest.C(t, func(t *gtest.T) {
type User struct {
g.Meta `orm:"do:true"`
Expand All @@ -905,4 +907,95 @@ func Test_Issue3204(t *testing.T) {
t.Assert(len(all), 1)
t.Assert(all[0]["id"], 2)
})
// data
gtest.C(t, func(t *gtest.T) {
type User struct {
g.Meta `orm:"do:true"`
Id interface{} `orm:"id,omitempty"`
Passport interface{} `orm:"passport,omitempty"`
Password interface{} `orm:"password,omitempty"`
Nickname interface{} `orm:"nickname,omitempty"`
CreateTime interface{} `orm:"create_time,omitempty"`
}
var (
err error
sqlArray []string
insertId int64
data = User{
Id: 20,
Passport: "passport_20",
Password: "",
}
)
sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error {
insertId, err = db.Ctx(ctx).Model(table).Data(data).InsertAndGetId()
return err
})
t.AssertNil(err)
t.Assert(insertId, 20)
t.Assert(
gstr.Contains(sqlArray[len(sqlArray)-1], "(`id`,`passport`) VALUES(20,'passport_20')"),
true,
)
})
// update data
gtest.C(t, func(t *gtest.T) {
type User struct {
g.Meta `orm:"do:true"`
Id interface{} `orm:"id,omitempty"`
Passport interface{} `orm:"passport,omitempty"`
Password interface{} `orm:"password,omitempty"`
Nickname interface{} `orm:"nickname,omitempty"`
CreateTime interface{} `orm:"create_time,omitempty"`
}
var (
err error
sqlArray []string
data = User{
Passport: "passport_1",
Password: "",
Nickname: "",
}
)
sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error {
_, err = db.Ctx(ctx).Model(table).Data(data).WherePri(1).Update()
return err
})
t.AssertNil(err)
t.Assert(
gstr.Contains(sqlArray[len(sqlArray)-1], "SET `passport`='passport_1' WHERE `id`=1"),
true,
)
})
}

// https://github.com/gogf/gf/issues/3218
func Test_Issue3218(t *testing.T) {
table := "issue3218_sys_config"
array := gstr.SplitAndTrim(gtest.DataContent(`issue3218.sql`), ";")
for _, v := range array {
if _, err := db.Exec(ctx, v); err != nil {
gtest.Error(err)
}
}
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type SysConfigInfo struct {
Name string `json:"name"`
Value map[string]string `json:"value"`
}
var configData *SysConfigInfo
err := db.Model(table).Scan(&configData)
t.AssertNil(err)
t.Assert(configData, &SysConfigInfo{
Name: "site",
Value: map[string]string{
"fixed_page": "",
"site_name": "22",
"version": "22",
"banned_ip": "22",
"filings": "2222",
},
})
})
}
14 changes: 14 additions & 0 deletions contrib/drivers/mysql/testdata/issue3218.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CREATE TABLE `issue3218_sys_config` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '配置名称',
`value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '配置值',
`created_at` timestamp NULL DEFAULT NULL COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `name`(`name`(191)) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;

-- ----------------------------
-- Records of sys_config
-- ----------------------------
INSERT INTO `issue3218_sys_config` VALUES (49, 'site', '{\"banned_ip\":\"22\",\"filings\":\"2222\",\"fixed_page\":\"\",\"site_name\":\"22\",\"version\":\"22\"}', '2023-12-19 14:08:25', '2023-12-19 14:08:25');
2 changes: 1 addition & 1 deletion database/gdb/gdb_core_structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (c *Core) GetFieldType(ctx context.Context, fieldName, table, schema string
func (c *Core) ConvertDataForRecord(ctx context.Context, value interface{}, table string) (map[string]interface{}, error) {
var (
err error
data = MapOrStructToMapDeep(value, false)
data = MapOrStructToMapDeep(value, true)
)
for fieldName, fieldValue := range data {
data[fieldName], err = c.db.ConvertValueForField(
Expand Down
14 changes: 10 additions & 4 deletions database/gdb/gdb_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ func DBFromCtx(ctx context.Context) DB {
return nil
}

// ToSQL formats and returns the last one of sql statements in given closure function without truly executing it.
// ToSQL formats and returns the last one of sql statements in given closure function
// WITHOUT TRULY EXECUTING IT.
// Be caution that, all the following sql statements should use the context object passing by function `f`.
func ToSQL(ctx context.Context, f func(ctx context.Context) error) (sql string, err error) {
var manager = &CatchSQLManager{
SQLArray: garray.NewStrArray(),
Expand All @@ -108,7 +110,8 @@ func ToSQL(ctx context.Context, f func(ctx context.Context) error) (sql string,
return
}

// CatchSQL catches and returns all sql statements that are executed in given closure function.
// CatchSQL catches and returns all sql statements that are EXECUTED in given closure function.
// Be caution that, all the following sql statements should use the context object passing by function `f`.
func CatchSQL(ctx context.Context, f func(ctx context.Context) error) (sqlArray []string, err error) {
var manager = &CatchSQLManager{
SQLArray: garray.NewStrArray(),
Expand Down Expand Up @@ -210,12 +213,15 @@ func GetInsertOperationByOption(option InsertOption) string {
}

func anyValueToMapBeforeToRecord(value interface{}) map[string]interface{} {
return gconv.Map(value, gconv.MapOption{Tags: structTagPriority})
return gconv.Map(value, gconv.MapOption{
Tags: structTagPriority,
OmitEmpty: true, // To be compatible with old version from v2.6.0.
})
}

// DaToMapDeep is deprecated, use MapOrStructToMapDeep instead.
func DaToMapDeep(value interface{}) map[string]interface{} {
return MapOrStructToMapDeep(value, false)
return MapOrStructToMapDeep(value, true)
}

// MapOrStructToMapDeep converts `value` to map type recursively(if attribute struct is embedded).
Expand Down
5 changes: 5 additions & 0 deletions util/gconv/gconv_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ package gconv

import "github.com/gogf/gf/v2/os/gtime"

// iVal is used for type assert api for String().
type iVal interface {
Val() interface{}
}

// iString is used for type assert api for String().
type iString interface {
String() string
Expand Down
13 changes: 10 additions & 3 deletions util/gconv/gconv_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type MapOption struct {
// a map[string]interface{} type variable.
Deep bool

// OmitEmpty ignores the attributes that has json omitempty tag.
// OmitEmpty ignores the attributes that has json `omitempty` tag.
OmitEmpty bool

// Tags specifies the converted map key name by struct tag name.
Expand Down Expand Up @@ -64,8 +64,15 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
if value == nil {
return nil
}
var usedOption = getUsedMapOption(option...)
newTags := StructTagPriority
// It redirects to its underlying value if it has implemented interface iVal.
if v, ok := value.(iVal); ok {
value = v.Val()
}

var (
usedOption = getUsedMapOption(option...)
newTags = StructTagPriority
)
switch len(usedOption.Tags) {
case 0:
// No need handling.
Expand Down

0 comments on commit 645c5ff

Please sign in to comment.