query_in_test.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package DB
  2. import (
  3. "path/filepath"
  4. "testing"
  5. )
  6. // 钉住 ORM Where 的 "in" 操作符行为 (docs/OPERATION_TUTORIAL.md §7.3 的承诺):
  7. // - 切片/数组值 → field IN (...)
  8. // - 空集合 → 恒假 (0 行), 不能退化成查全表
  9. // - 单值 (非切片) → 容忍为等值
  10. // - 分量按列类型归一 (int 字面量 vs int64 列)
  11. func TestWhereIn(t *testing.T) {
  12. db, err := Open(filepath.Join(t.TempDir(), "in_test.db"))
  13. if err != nil {
  14. t.Fatal(err)
  15. }
  16. defer db.Close()
  17. type Emp struct {
  18. BaseModel
  19. Name string `vrtx:"maxlen:16"`
  20. Dept string `vrtx:"maxlen:16"`
  21. Age int64 `vrtx:"index:idx_age"`
  22. }
  23. et, err := UseTable[Emp](db, "in_test")
  24. if err != nil {
  25. t.Fatal(err)
  26. }
  27. for i, dept := range []string{"工程部", "技术部", "销售部", "工程部"} {
  28. if err := et.Insert(&Emp{Name: "e", Dept: dept, Age: int64(20 + i)}); err != nil {
  29. t.Fatal(err)
  30. }
  31. }
  32. if err := db.Commit(); err != nil {
  33. t.Fatal(err)
  34. }
  35. // 基本形态: 字符串集合
  36. rows, err := et.Where("Dept", "in", []string{"工程部", "技术部"}).Find()
  37. if err != nil {
  38. t.Fatal(err)
  39. }
  40. if len(rows) != 3 {
  41. t.Fatalf("in [工程部,技术部] 期望 3 行, 实际 %d", len(rows))
  42. }
  43. // 整数集合: int 分量对 int64 列自动归一
  44. rows, err = et.Where("Age", "in", []int{20, 22}).Find()
  45. if err != nil {
  46. t.Fatal(err)
  47. }
  48. if len(rows) != 2 {
  49. t.Fatalf("in [20,22] 期望 2 行, 实际 %d", len(rows))
  50. }
  51. // 数组载体
  52. rows, err = et.Where("Age", "in", [1]int64{23}).Find()
  53. if err != nil {
  54. t.Fatal(err)
  55. }
  56. if len(rows) != 1 {
  57. t.Fatalf("in [24] 期望 1 行, 实际 %d", len(rows))
  58. }
  59. // 空集合恒假: 0 行, 而不是退化成全表
  60. rows, err = et.Where("Dept", "in", []string{}).Find()
  61. if err != nil {
  62. t.Fatal(err)
  63. }
  64. if len(rows) != 0 {
  65. t.Fatalf("in 空集期望 0 行, 实际 %d (退化成全表了)", len(rows))
  66. }
  67. cnt, err := et.Where("Age", "in", []int64{}).Count()
  68. if err != nil {
  69. t.Fatal(err)
  70. }
  71. if cnt != 0 {
  72. t.Fatalf("in 空集 Count 期望 0, 实际 %d", cnt)
  73. }
  74. // 与其它条件 AND 组合
  75. rows, err = et.Where("Dept", "in", []string{"工程部", "技术部"}).
  76. Where("Age", ">", int64(21)).Find()
  77. if err != nil {
  78. t.Fatal(err)
  79. }
  80. if len(rows) != 1 {
  81. t.Fatalf("in + > 组合期望 1 行, 实际 %d", len(rows))
  82. }
  83. // 集合外无一行命中
  84. rows, err = et.Where("Dept", "in", []string{"人事部"}).Find()
  85. if err != nil {
  86. t.Fatal(err)
  87. }
  88. if len(rows) != 0 {
  89. t.Fatalf("in [人事部] 期望 0 行, 实际 %d", len(rows))
  90. }
  91. // 单值容忍: ≡ 等值
  92. rows, err = et.Where("Age", "in", int64(20)).Find()
  93. if err != nil {
  94. t.Fatal(err)
  95. }
  96. if len(rows) != 1 {
  97. t.Fatalf("in 单值期望 1 行, 实际 %d", len(rows))
  98. }
  99. }