diff --git a/contrib/drivers/mysql/mysql_z_unit_issue_test.go b/contrib/drivers/mysql/mysql_z_unit_issue_test.go index 265ac50f3..72c7185de 100644 --- a/contrib/drivers/mysql/mysql_z_unit_issue_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_issue_test.go @@ -1983,3 +1983,86 @@ func Test_Issue4697(t *testing.T) { t.AssertNE(result[0]["nickname"], nil) }) } + +// https://github.com/gogf/gf/issues/4698 +func Test_Issue4698(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + // Test 1: AllAndCount with multiple fields should generate valid COUNT SQL + gtest.C(t, func(t *gtest.T) { + result, count, err := db.Model(table).Fields("id, nickname").AllAndCount(true) + t.AssertNil(err) + t.Assert(count, TableSize) + t.Assert(len(result), TableSize) + t.AssertNE(result[0]["id"], nil) + t.AssertNE(result[0]["nickname"], nil) + t.Assert(result[0]["passport"], nil) + }) + + // Test 2: AllAndCount(false) with multiple fields + gtest.C(t, func(t *gtest.T) { + result, count, err := db.Model(table).Fields("id, nickname").AllAndCount(false) + t.AssertNil(err) + t.Assert(count, TableSize) + t.Assert(len(result), TableSize) + }) + + // Test 3: ScanAndCount with multiple fields + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Nickname string + } + var users []User + var total int + err := db.Model(table).Fields("id, nickname").ScanAndCount(&users, &total, true) + t.AssertNil(err) + t.Assert(total, TableSize) + t.Assert(len(users), TableSize) + t.AssertGT(users[0].Id, 0) + t.AssertNE(users[0].Nickname, "") + }) + + // Test 4: AllAndCount with single field and useFieldForCount=true + gtest.C(t, func(t *gtest.T) { + result, count, err := db.Model(table).Fields("id").AllAndCount(true) + t.AssertNil(err) + t.Assert(count, TableSize) + t.Assert(len(result), TableSize) + t.Assert(len(result[0]), 1) + }) + + // Test 5: AllAndCount with Where condition + gtest.C(t, func(t *gtest.T) { + result, count, err := db.Model(table).Fields("id, nickname").Where("id 0 { countModel = countModel.Cache(m.pageCacheOption[0]) @@ -341,9 +348,16 @@ func (m *Model) Scan(pointer any, where ...any) error { func (m *Model) ScanAndCount(pointer any, totalCount *int, useFieldForCount bool) (err error) { // support Fields with *, example: .Fields("a.*, b.name"). Count sql is select count(1) from xxx countModel := m.Clone() - // If useFieldForCount is false, set the fields to a constant value of 1 for counting - if !useFieldForCount { - countModel.fields = []any{Raw("1")} + // Decide how to build the COUNT() expression: + // - If caller explicitly wants to use the single field expression for counting, + // honor it (e.g. Fields("DISTINCT col") with useFieldForCount = true). + // - Otherwise, clear fields to let Count() use its default COUNT(1), + // avoiding invalid COUNT(field1, field2, ...) with multiple fields, + // or incorrect COUNT(DISTINCT 1) when Distinct() is set. + if useFieldForCount && len(m.fields) == 1 { + countModel.fields = m.fields + } else { + countModel.fields = nil } if len(m.pageCacheOption) > 0 { countModel = countModel.Cache(m.pageCacheOption[0])