From d1b905b7800187040bc56c223d19cac4b3437a19 Mon Sep 17 00:00:00 2001 From: hoteas <925970985@qq.com> Date: Fri, 23 Jan 2026 01:51:35 +0800 Subject: [PATCH] =?UTF-8?q?test(db):=20=E6=B7=BB=E5=8A=A0=20OR=20=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6=E5=A4=84=E7=90=86=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=B9=B6=E4=BF=AE=E5=A4=8D=20WHERE=20=E5=AD=90?= =?UTF-8?q?=E5=8F=A5=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加了 TestWhereWithORCondition 测试函数验证 OR 条件的括号包裹 - 修复了 where.go 中条件计数变量名称从 normalCondCount 改为 condCount - 实现了 OR/AND 组条件的括号包裹逻辑确保 SQL 语法正确 - 添加了空条件检查避免生成无效的 SQL 片段 - 更新了 .gitignore 文件添加日志文件忽略规则 --- .gitignore | 3 +- db/dialect_test.go | 165 +++++++++++++++++++++++++++++++++++++++++++++ db/where.go | 28 +++++--- 3 files changed, 185 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 668562c..7360a18 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .idea /example/tpt/demo/ *.exe -/example/config \ No newline at end of file +/example/config +/.cursor/*.log diff --git a/db/dialect_test.go b/db/dialect_test.go index 9d5892d..989f943 100644 --- a/db/dialect_test.go +++ b/db/dialect_test.go @@ -1,6 +1,7 @@ package db import ( + . "code.hoteas.com/golang/hotime/common" "fmt" "strings" "testing" @@ -248,6 +249,170 @@ func TestHoTimeDBHelperMethods(t *testing.T) { }) } +// TestWhereWithORCondition 测试 OR 条件处理是否正确添加括号 +func TestWhereWithORCondition(t *testing.T) { + // 创建 MySQL 数据库实例 + mysqlDB := &HoTimeDB{ + Type: "mysql", + Prefix: "", + } + mysqlDB.initDialect() + + // 测试 OR 与普通条件组合 (假设 A: 顺序问题) + t.Run("OR with normal condition", func(t *testing.T) { + data := Map{ + "OR": Map{ + "username": "test", + "phone": "123", + }, + "state": 0, + } + + where, params := mysqlDB.where(data) + fmt.Println("Test 1 - OR with normal condition:") + fmt.Println(" Generated WHERE:", where) + fmt.Println(" Params count:", len(params)) + + // 检查 OR 条件是否被括号包裹 + if !strings.Contains(where, "(") || !strings.Contains(where, ")") { + t.Errorf("OR condition should be wrapped with parentheses, got: %s", where) + } + + // 检查是否有 AND 连接 + if !strings.Contains(where, "AND") { + t.Errorf("OR condition and normal condition should be connected with AND, got: %s", where) + } + }) + + // 测试纯 OR 条件(无其他普通条件) + t.Run("Pure OR condition", func(t *testing.T) { + data := Map{ + "OR": Map{ + "username": "test", + "phone": "123", + }, + } + + where, params := mysqlDB.where(data) + fmt.Println("Test 2 - Pure OR condition:") + fmt.Println(" Generated WHERE:", where) + fmt.Println(" Params count:", len(params)) + + // 检查 OR 条件内部应该用 OR 连接 + if !strings.Contains(where, "OR") { + t.Errorf("OR condition should contain OR keyword, got: %s", where) + } + }) + + // 测试多个普通条件与 OR 组合 (假设 A) + t.Run("OR with multiple normal conditions", func(t *testing.T) { + data := Map{ + "OR": Map{ + "username": "test", + "phone": "123", + }, + "state": 0, + "status": 1, + } + + where, params := mysqlDB.where(data) + fmt.Println("Test 3 - OR with multiple normal conditions:") + fmt.Println(" Generated WHERE:", where) + fmt.Println(" Params count:", len(params)) + + // 应该有括号 + if !strings.Contains(where, "(") { + t.Errorf("OR condition should be wrapped with parentheses, got: %s", where) + } + }) + + // 测试嵌套 AND/OR 条件 (假设 B, E) + t.Run("Nested AND/OR conditions", func(t *testing.T) { + data := Map{ + "OR": Map{ + "username": "test", + "AND": Map{ + "phone": "123", + "status": 1, + }, + }, + "state": 0, + } + + where, params := mysqlDB.where(data) + fmt.Println("Test 4 - Nested AND/OR conditions:") + fmt.Println(" Generated WHERE:", where) + fmt.Println(" Params count:", len(params)) + }) + + // 测试空 OR 条件 (假设 C) + t.Run("Empty OR condition", func(t *testing.T) { + data := Map{ + "OR": Map{}, + "state": 0, + } + + where, params := mysqlDB.where(data) + fmt.Println("Test 5 - Empty OR condition:") + fmt.Println(" Generated WHERE:", where) + fmt.Println(" Params count:", len(params)) + }) + + // 测试 OR 与 LIMIT, ORDER 组合 (假设 D) + t.Run("OR with LIMIT and ORDER", func(t *testing.T) { + data := Map{ + "OR": Map{ + "username": "test", + "phone": "123", + }, + "state": 0, + "ORDER": "id DESC", + "LIMIT": 10, + } + + where, params := mysqlDB.where(data) + fmt.Println("Test 6 - OR with LIMIT and ORDER:") + fmt.Println(" Generated WHERE:", where) + fmt.Println(" Params count:", len(params)) + }) + + // 测试同时有 OR 和 AND 关键字 (假设 E) + t.Run("Both OR and AND keywords", func(t *testing.T) { + data := Map{ + "OR": Map{ + "username": "test", + "phone": "123", + }, + "AND": Map{ + "type": 1, + "source": "web", + }, + "state": 0, + } + + where, params := mysqlDB.where(data) + fmt.Println("Test 7 - Both OR and AND keywords:") + fmt.Println(" Generated WHERE:", where) + fmt.Println(" Params count:", len(params)) + }) + + // 测试普通条件在 OR 之前(排序后)(假设 A) + t.Run("Normal condition before OR alphabetically", func(t *testing.T) { + data := Map{ + "OR": Map{ + "username": "test", + "phone": "123", + }, + "active": 1, // 'a' 在 'O' 之前 + } + + where, params := mysqlDB.where(data) + fmt.Println("Test 8 - Normal condition before OR (alphabetically):") + fmt.Println(" Generated WHERE:", where) + fmt.Println(" Params count:", len(params)) + }) +} + // 打印测试结果(用于调试) func ExampleIdentifierProcessor() { // MySQL 示例 diff --git a/db/where.go b/db/where.go index 050ab76..572d1b6 100644 --- a/db/where.go +++ b/db/where.go @@ -70,8 +70,8 @@ func (that *HoTimeDB) where(data Map) (string, []interface{}) { } sort.Strings(testQu) - // 追踪普通条件数量,用于自动添加 AND - normalCondCount := 0 + // 追踪条件数量,用于自动添加 AND + condCount := 0 for _, k := range testQu { v := data[k] @@ -79,8 +79,16 @@ func (that *HoTimeDB) where(data Map) (string, []interface{}) { // 检查是否是 AND/OR 条件关键字 if isConditionKey(k) { tw, ts := that.cond(strings.ToUpper(k), v.(Map)) - where += tw - res = append(res, ts...) + if tw != "" && strings.TrimSpace(tw) != "" { + // 与前面的条件用 AND 连接 + if condCount > 0 { + where += " AND " + } + // 用括号包裹 OR/AND 组条件 + where += "(" + strings.TrimSpace(tw) + ")" + condCount++ + res = append(res, ts...) + } continue } @@ -95,11 +103,11 @@ func (that *HoTimeDB) where(data Map) (string, []interface{}) { // 检查是否是 NOT IN(带 [!] 后缀)- NOT IN 空数组永真,跳过即可 if !strings.HasSuffix(k, "[!]") { // IN 空数组 -> 生成永假条件 - if normalCondCount > 0 { + if condCount > 0 { where += " AND " } where += "1=0 " - normalCondCount++ + condCount++ } continue } @@ -107,11 +115,11 @@ func (that *HoTimeDB) where(data Map) (string, []interface{}) { // 检查是否是 NOT IN(带 [!] 后缀)- NOT IN 空数组永真,跳过即可 if !strings.HasSuffix(k, "[!]") { // IN 空数组 -> 生成永假条件 - if normalCondCount > 0 { + if condCount > 0 { where += " AND " } where += "1=0 " - normalCondCount++ + condCount++ } continue } @@ -119,11 +127,11 @@ func (that *HoTimeDB) where(data Map) (string, []interface{}) { tv, vv := that.varCond(k, v) if tv != "" { // 自动添加 AND 连接符 - if normalCondCount > 0 { + if condCount > 0 { where += " AND " } where += tv - normalCondCount++ + condCount++ res = append(res, vv...) } }