From e0c032d1b191b7d542f59b3d263da711ddcefc3a Mon Sep 17 00:00:00 2001 From: Jack Ling <34231795+lingcoder@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:27:00 +0800 Subject: [PATCH] fix(database/gdb): handle empty string in Fields() gracefully (#4700) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Fix bug where `Fields("")` with empty string generates invalid SQL `SELECT FROM table`. ## Root Cause `mappingAndFilterToTableFields` method doesn't skip empty strings when processing fields: - `gstr.SplitAndTrim("", ",")` returns empty array - No fields added to query - Results in invalid SQL: `SELECT FROM table` ## Fix Skip empty string fields in `mappingAndFilterToTableFields` (line 97-100): ```go // Skip empty string fields if fieldStr == "" { continue } ``` ## Behavior Changes - `Fields("")` → SELECT * FROM table (uses default) - `Fields("", "id")` → SELECT id FROM table (ignores empty string) - `Fields("id", "", "nickname")` → SELECT id, nickname FROM table ## Tests Added `Test_Issue4697` with 3 scenarios covering all cases above. ## Related Fixes #4697 Ref #4703 (discovered during pagination test development) --- .../drivers/mysql/mysql_z_unit_issue_test.go | 34 +++++++++++++++++++ database/gdb/gdb_model_utility.go | 4 +++ 2 files changed, 38 insertions(+) diff --git a/contrib/drivers/mysql/mysql_z_unit_issue_test.go b/contrib/drivers/mysql/mysql_z_unit_issue_test.go index edb4b2a18..265ac50f3 100644 --- a/contrib/drivers/mysql/mysql_z_unit_issue_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_issue_test.go @@ -1949,3 +1949,37 @@ func Test_Issue4500(t *testing.T) { t.Assert(len(all), 3) }) } + +// https://github.com/gogf/gf/issues/4697 +func Test_Issue4697(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + // Fields("") should be treated as Fields() and select all fields + result, err := db.Model(table).Fields("").Limit(1).All() + t.AssertNil(err) + t.AssertGT(len(result), 0) + // Should have all fields (id, passport, password, nickname, create_time, create_date) + t.Assert(len(result[0]), 6) + }) + + gtest.C(t, func(t *gtest.T) { + // Fields("", "id") should ignore empty string and only select "id" + result, err := db.Model(table).Fields("", "id").Limit(1).All() + t.AssertNil(err) + t.AssertGT(len(result), 0) + t.Assert(len(result[0]), 1) + t.AssertNE(result[0]["id"], nil) + }) + + gtest.C(t, func(t *gtest.T) { + // Fields("id", "", "nickname") should ignore empty string + result, err := db.Model(table).Fields("id", "", "nickname").Limit(1).All() + t.AssertNil(err) + t.AssertGT(len(result), 0) + t.Assert(len(result[0]), 2) + t.AssertNE(result[0]["id"], nil) + t.AssertNE(result[0]["nickname"], nil) + }) +} diff --git a/database/gdb/gdb_model_utility.go b/database/gdb/gdb_model_utility.go index 1ced41c39..48e6e974e 100644 --- a/database/gdb/gdb_model_utility.go +++ b/database/gdb/gdb_model_utility.go @@ -94,6 +94,10 @@ func (m *Model) mappingAndFilterToTableFields(table string, fields []any, filter fieldStr = gconv.String(field) inputFieldsArray []string ) + // Skip empty string fields. + if fieldStr == "" { + continue + } switch { case gregex.IsMatchString(regularFieldNameWithoutDotRegPattern, fieldStr): inputFieldsArray = append(inputFieldsArray, fieldStr)