This commit is contained in:
John Guo 2024-02-06 10:21:44 +08:00 committed by GitHub
parent 2acdf4bb47
commit 72014689e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 76 additions and 16 deletions

View File

@ -1091,3 +1091,37 @@ func Test_Issue2552_ClearTableFields(t *testing.T) {
t.Assert(gstr.Contains(gstr.Join(sqlArray, "|"), showTableKey), true)
})
}
// https://github.com/gogf/gf/issues/2643
func Test_Issue2643(t *testing.T) {
table := "issue2643"
array := gstr.SplitAndTrim(gtest.DataContent(`issue2643.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) {
var (
expectKey1 = "SELECT s.name,replace(concat_ws(',',lpad(s.id, 6, '0'),s.name),',','') `code` FROM `issue2643` AS s"
expectKey2 = "SELECT CASE WHEN dept='物资部' THEN '物资部' ELSE '其他' END dept,sum(s.value) FROM `issue2643` AS s GROUP BY CASE WHEN dept='物资部' THEN '物资部' ELSE '其他' END"
)
sqlArray, err := gdb.CatchSQL(ctx, func(ctx context.Context) error {
db.Ctx(ctx).Model(table).As("s").Fields(
"s.name",
"replace(concat_ws(',',lpad(s.id, 6, '0'),s.name),',','') `code`",
).All()
db.Ctx(ctx).Model(table).As("s").Fields(
"CASE WHEN dept='物资部' THEN '物资部' ELSE '其他' END dept",
"sum(s.value)",
).Group("CASE WHEN dept='物资部' THEN '物资部' ELSE '其他' END").All()
return nil
})
t.AssertNil(err)
sqlContent := gstr.Join(sqlArray, "\n")
t.Assert(gstr.Contains(sqlContent, expectKey1), true)
t.Assert(gstr.Contains(sqlContent, expectKey2), true)
})
}

View File

@ -2286,7 +2286,7 @@ func Test_Model_Option_Where(t *testing.T) {
n, _ := r.RowsAffected()
t.Assert(n, TableSize)
})
return
gtest.C(t, func(t *gtest.T) {
table := createInitTable()
defer dropTable(table)

View File

@ -0,0 +1,7 @@
CREATE TABLE `issue2643` (
`id` INT(10) NULL DEFAULT NULL,
`name` VARCHAR(50) NULL DEFAULT NULL,
`value` INT(10) NULL DEFAULT NULL,
`dept` VARCHAR(50) NULL DEFAULT NULL
)
ENGINE=InnoDB

View File

@ -495,6 +495,10 @@ var (
// which is a regular field name of table.
regularFieldNameRegPattern = `^[\w\.\-]+$`
// regularFieldNameWithCommaRegPattern is the regular expression pattern for one or more strings
// which are regular field names of table, multiple field names joined with char ','.
regularFieldNameWithCommaRegPattern = `^[\w\.\-,\s]+$`
// regularFieldNameWithoutDotRegPattern is similar to regularFieldNameRegPattern but not allows '.'.
// Note that, although some databases allow char '.' in the field name, but it here does not allow '.'
// in the field name as it conflicts with "db.table.field" pattern in SOME situations.

View File

@ -767,6 +767,8 @@ func (c *Core) HasTable(name string) (bool, error) {
if err != nil {
return false, err
}
charL, charR := c.db.GetChars()
name = gstr.Trim(name, charL+charR)
for _, table := range tables {
if table == name {
return true, nil

View File

@ -93,6 +93,9 @@ func (c *Core) QuoteWord(s string) string {
//
// The meaning of a `string` can be considered as part of a statement string including columns.
func (c *Core) QuoteString(s string) string {
if !gregex.IsMatchString(regularFieldNameWithCommaRegPattern, s) {
return s
}
charLeft, charRight := c.db.GetChars()
return doQuoteString(s, charLeft, charRight)
}

View File

@ -68,30 +68,40 @@ func (m *Model) mappingAndFilterToTableFields(table string, fields []string, fil
if len(fieldsMap) == 0 {
return fields
}
var (
inputFieldsArray = gstr.SplitAndTrim(gstr.Join(fields, ","), ",")
outputFieldsArray = make([]string, 0, len(inputFieldsArray))
)
var outputFieldsArray = make([]string, 0)
fieldsKeyMap := make(map[string]interface{}, len(fieldsMap))
for k := range fieldsMap {
fieldsKeyMap[k] = nil
}
for _, field := range inputFieldsArray {
if _, ok := fieldsKeyMap[field]; !ok {
if !gregex.IsMatchString(regularFieldNameWithoutDotRegPattern, field) {
// Eg: user.id, user.name
outputFieldsArray = append(outputFieldsArray, field)
for _, field := range fields {
var inputFieldsArray []string
if gregex.IsMatchString(regularFieldNameWithoutDotRegPattern, field) {
inputFieldsArray = append(inputFieldsArray, field)
} else if gregex.IsMatchString(regularFieldNameWithCommaRegPattern, field) {
inputFieldsArray = gstr.SplitAndTrim(field, ",")
} else {
// Example:
// user.id, user.name
// replace(concat_ws(',',lpad(s.id, 6, '0'),s.name),',','') `code`
outputFieldsArray = append(outputFieldsArray, field)
continue
}
for _, inputField := range inputFieldsArray {
if !gregex.IsMatchString(regularFieldNameWithoutDotRegPattern, inputField) {
outputFieldsArray = append(outputFieldsArray, inputField)
continue
} else {
// Eg: id, name
if foundKey, _ := gutil.MapPossibleItemByKey(fieldsKeyMap, field); foundKey != "" {
}
if _, ok := fieldsKeyMap[inputField]; !ok {
// Example:
// id, name
if foundKey, _ := gutil.MapPossibleItemByKey(fieldsKeyMap, inputField); foundKey != "" {
outputFieldsArray = append(outputFieldsArray, foundKey)
} else if !filter {
outputFieldsArray = append(outputFieldsArray, field)
outputFieldsArray = append(outputFieldsArray, inputField)
}
} else {
outputFieldsArray = append(outputFieldsArray, inputField)
}
} else {
outputFieldsArray = append(outputFieldsArray, field)
}
}
return outputFieldsArray