Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix issue #2427 #2442

Merged
merged 7 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/gf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ jobs:
- 1521:1521

# dm8 server
# docker run -d --name dm -p 5236:5236 loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
dm-server:
image: loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
ports:
Expand Down
4 changes: 2 additions & 2 deletions contrib/drivers/dm/dm.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,9 @@ func (d *Driver) DoFilter(ctx context.Context, link gdb.Link, sql string, args [
// There should be no need to capitalize, because it has been done from field processing before
newSql, err = gregex.ReplaceString(`["\n\t]`, "", sql)
newSql = gstr.ReplaceI(newSql, "GROUP_CONCAT", "WM_CONCAT")
// g.Dump("Driver.DoFilter()::newSql", newSql)
// gutil.Dump("Driver.DoFilter()::newSql", newSql)
newArgs = args
// g.Dump("Driver.DoFilter()::newArgs", newArgs)
// gutil.Dump("Driver.DoFilter()::newArgs", newArgs)
return
}

Expand Down
122 changes: 0 additions & 122 deletions contrib/drivers/dm/dm_z_basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -582,125 +582,3 @@ func Test_Empty_Slice_Argument(t *testing.T) {
t.Assert(len(result), 0)
})
}

// func Test_GROUP_CONCAT(t *testing.T) {
// gtest.C(t, func(t *gtest.T) {
// type GroupIdAndUserIDsInfo struct {
// GroupID int64
// UserIDs string
// }
// result := make([]GroupIdAndUserIDsInfo, 0)

// model := db.Model("t_inf_group", "groupinfo").Fields("groupinfo.id as group_id", "GROUP_CONCAT(userinfo.id) as user_ids")
// model.InnerJoin("t_lin_user_group", "lin", "groupinfo.id = lin.group_id")
// model.InnerJoin("t_inf_user", "userinfo", "lin.user_id = userinfo.id")
// model.Where("groupinfo.enabled", 1).Where("groupinfo.deleted", 0)
// model.Where("userinfo.enabled", 1).Where("userinfo.deleted", 0)
// model.Group("groupinfo.id")

// err := model.Scan(&result)
// gtest.Assert(err, nil)
// g.Dump(result)
// })
// }

// func TestGroup(t *testing.T) {
// gtest.C(t, func(t *gtest.T) {
// type GroupListResult struct {
// ID int64 `json:"group_id"`
// GroupName string `json:"group_name"`
// CategoryName string `json:"category_name"`
// Description string `json:"description"`
// RoleName string `json:"role_name"`
// UserIDs []string `json:"user_ids"`
// Enabled int64 `json:"enabled"`
// CreatedTime string `json:"created_time"`
// UpdateTime string `json:"updated_time"`
// }
// result := make([]GroupListResult, 0)

// model := db.Model("t_inf_group", "groupinfo")
// model.LeftJoin("t_inf_group_category", "category", "groupinfo.category_id=category.id and (category.enabled = 1) and (category.deleted = 0)").
// Where("groupinfo.deleted", 0).
// Where("groupinfo.enabled", 1)

// total, err := model.Count()
// gtest.Assert(err, nil)
// model.Fields("distinct groupinfo.id, groupinfo.group_name, groupinfo.enabled, ifnull(category.category_name,'') as category_name", "groupinfo.created_time", "groupinfo.updated_time", "groupinfo.description")
// err = model.Order("groupinfo.updated_time desc").Page(1, 100).Scan(&result)
// gtest.Assert(err, nil)
// g.Dump(result)
// g.Dump(total)
// })

// gtest.C(t, func(t *gtest.T) {
// type GroupListByUserIdResult struct {
// ID int64 `json:"group_id"`
// GroupName string `json:"group_name"`
// CategoryName string `json:"category_name"`
// RoleName string `json:"role_name"`
// }
// result := make([]*GroupListByUserIdResult, 0)

// model := db.Model("t_inf_group", "groupinfo").Fields("distinct groupinfo.id, groupinfo.group_name, groupinfo.enabled, category.category_name,groupinfo.updated_time")

// model.LeftJoin("t_inf_group_category", "category", "groupinfo.category_id=category.id and (category.enabled = 1) and (category.deleted = 0)")

// // if userId != 0 {
// // model.InnerJoin(grouptype.TLINUSERGROUP, "ug", "groupinfo.id=ug.group_id")
// // model.InnerJoin(grouptype.TINFUSER, "u", "u.id=ug.user_id")
// // model.Where("u.id = ?", userId).Where("u.deleted", consts.DataDeletedFalse)
// // }

// model.Where("groupinfo.enabled", 1).Where("groupinfo.deleted", 0)

// err := model.Order("groupinfo.updated_time desc").Scan(&result)
// //
// gtest.Assert(err, nil)
// g.Dump(result)
// })
// gtest.C(t, func(t *gtest.T) {

// model := db.Model("t_inf_role", "role").Fields("role.role_name", "role.id")
// model.RightJoin("t_lin_group_role", "link", "link.role_id=role.id")
// // model.Where("link.group_id", gid)
// model.Where("role.deleted", 0)

// record, err := model.One()
// gtest.Assert(err, nil)
// g.Dump(record)

// })
// gtest.C(t, func(t *gtest.T) {
// type GroupInfos struct {
// RoleName string `orm:"role_name"`
// RoleID int64 `orm:"id"`
// GroupID int64 `orm:"group_id"`
// }
// result := make([]GroupInfos, 0)

// model := db.Model("t_inf_role", "role").Fields("role.id", "role.role_name", "link.group_id")
// model.RightJoin("t_lin_group_role", "link", "link.role_id=role.id")
// model.Where("role.enabled", 1).Where("role.deleted", 0)
// err := model.Scan(&result)
// gtest.Assert(err, nil)
// g.Dump(result)
// })
// gtest.C(t, func(t *gtest.T) {
// type GroupIdAndRoleNameInfo struct {
// GroupID int64
// RoleID int64
// RoleName string
// }
// result := make([]GroupIdAndRoleNameInfo, 0)
// model := db.Model("t_inf_group", "groupinfo").Fields("groupinfo.id as group_id", "lin.role_id", "role.role_name")
// model.InnerJoin("t_lin_group_role", "lin", "groupinfo.id = lin.group_id")
// model.InnerJoin("t_inf_role", "role", "lin.role_id = role.id")
// model.Where("groupinfo.enabled", 1).Where("groupinfo.deleted", 0)
// model.Where("role.enabled", 1).Where("role.deleted", 0)

// err2 := model.Scan(&result)
// gtest.Assert(err2, nil)
// g.Dump(result)
// })
// }
2 changes: 1 addition & 1 deletion contrib/drivers/dm/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ go 1.15
replace github.com/gogf/gf/v2 => ../../../

require (
gitee.com/chunanyong/dm v1.8.6
gitee.com/chunanyong/dm v1.8.11
github.com/gogf/gf/v2 v2.0.0
)
4 changes: 2 additions & 2 deletions contrib/drivers/dm/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
gitee.com/chunanyong/dm v1.8.6 h1:5UnOCW1f2+LYiSQvuHiloS6OTMnZAtjRQ4woi9i6QY4=
gitee.com/chunanyong/dm v1.8.6/go.mod h1:EPRJnuPFgbyOFgJ0TRYCTGzhq+ZT4wdyaj/GW/LLcNg=
gitee.com/chunanyong/dm v1.8.11 h1:JPwiS1PqHObo4QFodruLR8WOhLP+7Y/EKGGu2BJ5SJI=
gitee.com/chunanyong/dm v1.8.11/go.mod h1:EPRJnuPFgbyOFgJ0TRYCTGzhq+ZT4wdyaj/GW/LLcNg=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
Expand Down
2 changes: 1 addition & 1 deletion contrib/drivers/mysql/mysql_feature_time_maintain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ CREATE TABLE %s (
t.Assert(one["name"], "name_1")

// Soft deleting.
r, err = db.Model(table1).Delete()
r, err = db.Model(table1).Where(1).Delete()
t.AssertNil(err)
n, _ = r.RowsAffected()
t.Assert(n, 1)
Expand Down
31 changes: 31 additions & 0 deletions contrib/drivers/mysql/mysql_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -633,3 +633,34 @@ CREATE TABLE %s (
t.Assert(all[0]["nickname"], "name_2")
})
}

// https://github.com/gogf/gf/issues/2427
func Test_Issue2427(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
table := "demo_" + guid.S()
if _, err := db.Exec(ctx, fmt.Sprintf(`
CREATE TABLE %s (
id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID',
passport varchar(45) NOT NULL COMMENT 'User Passport',
password varchar(45) NOT NULL COMMENT 'User Password',
nickname varchar(45) NOT NULL COMMENT 'User Nickname',
create_at datetime DEFAULT NULL COMMENT 'Created Time',
update_at datetime DEFAULT NULL COMMENT 'Updated Time',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
`, table,
)); err != nil {
t.AssertNil(err)
}
defer dropTable(table)

_, err1 := db.Model(table).Delete()
t.Assert(err1, `there should be WHERE condition statement for DELETE operation`)

_, err2 := db.Model(table).Where(g.Map{}).Delete()
t.Assert(err2, `there should be WHERE condition statement for DELETE operation`)

_, err3 := db.Model(table).Where(1).Delete()
t.AssertNil(err3)
})
}
32 changes: 21 additions & 11 deletions database/gdb/gdb_model_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ package gdb
import (
"database/sql"
"fmt"

"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/internal/intlog"
"github.com/gogf/gf/v2/text/gstr"

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

// Delete does "DELETE FROM ... " statement for the model.
Expand All @@ -32,9 +33,25 @@ func (m *Model) Delete(where ...interface{}) (result sql.Result, err error) {
var (
fieldNameDelete = m.getSoftFieldNameDeleted("", m.tablesInit)
conditionWhere, conditionExtra, conditionArgs = m.formatCondition(ctx, false, false)
conditionStr = conditionWhere + conditionExtra
)
if m.unscoped {
fieldNameDelete = ""
}
if !gstr.ContainsI(conditionStr, " WHERE ") || (fieldNameDelete != "" && !gstr.ContainsI(conditionStr, " AND ")) {
intlog.Printf(
ctx,
`sql condition string "%s" has no WHERE for DELETE operation, fieldNameDelete: %s`,
conditionStr, fieldNameDelete,
)
return nil, gerror.NewCode(
gcode.CodeMissingParameter,
"there should be WHERE condition statement for DELETE operation",
)
}

// Soft deleting.
if !m.unscoped && fieldNameDelete != "" {
if fieldNameDelete != "" {
in := &HookUpdateInput{
internalParamHookUpdate: internalParamHookUpdate{
internalParamHook: internalParamHook{
Expand All @@ -45,18 +62,11 @@ func (m *Model) Delete(where ...interface{}) (result sql.Result, err error) {
Model: m,
Table: m.tables,
Data: fmt.Sprintf(`%s=?`, m.db.GetCore().QuoteString(fieldNameDelete)),
Condition: conditionWhere + conditionExtra,
Condition: conditionStr,
Args: append([]interface{}{gtime.Now().String()}, conditionArgs...),
}
return in.Next(ctx)
}
conditionStr := conditionWhere + conditionExtra
if !gstr.ContainsI(conditionStr, " WHERE ") {
return nil, gerror.NewCode(
gcode.CodeMissingParameter,
"there should be WHERE condition statement for DELETE operation",
)
}

in := &HookDeleteInput{
internalParamHookDelete: internalParamHookDelete{
Expand Down
4 changes: 3 additions & 1 deletion database/gdb/gdb_model_select.go
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,9 @@ func (m *Model) getFieldsFiltered() string {
// Note that this function does not change any attribute value of the `m`.
//
// The parameter `limit1` specifies whether limits querying only one record if m.limit is not set.
func (m *Model) formatCondition(ctx context.Context, limit1 bool, isCountStatement bool) (conditionWhere string, conditionExtra string, conditionArgs []interface{}) {
func (m *Model) formatCondition(
ctx context.Context, limit1 bool, isCountStatement bool,
) (conditionWhere string, conditionExtra string, conditionArgs []interface{}) {
var autoPrefix = m.getAutoPrefix()
// GROUP BY.
if m.groupBy != "" {
Expand Down
22 changes: 18 additions & 4 deletions database/gdb/gdb_model_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package gdb
import (
"database/sql"
"fmt"
"github.com/gogf/gf/v2/internal/intlog"
"reflect"

"github.com/gogf/gf/v2/errors/gcode"
Expand Down Expand Up @@ -48,7 +49,12 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro
reflectInfo = reflection.OriginTypeAndKind(updateData)
fieldNameUpdate = m.getSoftFieldNameUpdated("", m.tablesInit)
conditionWhere, conditionExtra, conditionArgs = m.formatCondition(ctx, false, false)
conditionStr = conditionWhere + conditionExtra
)
if m.unscoped {
fieldNameUpdate = ""
}

switch reflectInfo.OriginKind {
case reflect.Map, reflect.Struct:
var dataMap map[string]interface{}
Expand All @@ -57,15 +63,15 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro
return nil, err
}
// Automatically update the record updating time.
if !m.unscoped && fieldNameUpdate != "" {
if fieldNameUpdate != "" {
dataMap[fieldNameUpdate] = gtime.Now().String()
}
updateData = dataMap

default:
updates := gconv.String(m.data)
// Automatically update the record updating time.
if !m.unscoped && fieldNameUpdate != "" {
if fieldNameUpdate != "" {
if fieldNameUpdate != "" && !gstr.Contains(updates, fieldNameUpdate) {
updates += fmt.Sprintf(`,%s='%s'`, fieldNameUpdate, gtime.Now().String())
}
Expand All @@ -76,9 +82,17 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro
if err != nil {
return nil, err
}
conditionStr := conditionWhere + conditionExtra

if !gstr.ContainsI(conditionStr, " WHERE ") {
return nil, gerror.NewCode(gcode.CodeMissingParameter, "there should be WHERE condition statement for UPDATE operation")
intlog.Printf(
ctx,
`sql condition string "%s" has no WHERE for UPDATE operation, fieldNameUpdate: %s`,
conditionStr, fieldNameUpdate,
)
return nil, gerror.NewCode(
gcode.CodeMissingParameter,
"there should be WHERE condition statement for UPDATE operation",
)
}

in := &HookUpdateInput{
Expand Down
2 changes: 1 addition & 1 deletion version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package gf

const (
// VERSION is the current GoFrame version.
VERSION = "v2.3.1"
VERSION = "v2.3.2"
)