where_clause_debug_test.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. package engine
  2. import (
  3. "context"
  4. "strconv"
  5. "testing"
  6. "github.com/seaweedfs/seaweedfs/weed/pb/schema_pb"
  7. )
  8. // TestWhereParsing tests if WHERE clauses are parsed correctly by CockroachDB parser
  9. func TestWhereParsing(t *testing.T) {
  10. testCases := []struct {
  11. name string
  12. sql string
  13. expectError bool
  14. desc string
  15. }{
  16. {
  17. name: "Simple_Equals",
  18. sql: "SELECT id FROM user_events WHERE id = 82460",
  19. expectError: false,
  20. desc: "Simple equality WHERE clause",
  21. },
  22. {
  23. name: "Greater_Than",
  24. sql: "SELECT id FROM user_events WHERE id > 10000000",
  25. expectError: false,
  26. desc: "Greater than WHERE clause",
  27. },
  28. {
  29. name: "String_Equals",
  30. sql: "SELECT id FROM user_events WHERE status = 'active'",
  31. expectError: false,
  32. desc: "String equality WHERE clause",
  33. },
  34. {
  35. name: "Impossible_Condition",
  36. sql: "SELECT id FROM user_events WHERE 1 = 0",
  37. expectError: false,
  38. desc: "Impossible WHERE condition (should parse but return no rows)",
  39. },
  40. }
  41. for _, tc := range testCases {
  42. t.Run(tc.name, func(t *testing.T) {
  43. // Test parsing first
  44. parsedStmt, parseErr := ParseSQL(tc.sql)
  45. if tc.expectError {
  46. if parseErr == nil {
  47. t.Errorf("Expected parse error but got none for: %s", tc.desc)
  48. } else {
  49. t.Logf("PASS: Expected parse error: %v", parseErr)
  50. }
  51. return
  52. }
  53. if parseErr != nil {
  54. t.Errorf("Unexpected parse error for %s: %v", tc.desc, parseErr)
  55. return
  56. }
  57. // Check if it's a SELECT statement
  58. selectStmt, ok := parsedStmt.(*SelectStatement)
  59. if !ok {
  60. t.Errorf("Expected SelectStatement, got %T", parsedStmt)
  61. return
  62. }
  63. // Check if WHERE clause exists
  64. if selectStmt.Where == nil {
  65. t.Errorf("WHERE clause not parsed for: %s", tc.desc)
  66. return
  67. }
  68. t.Logf("PASS: WHERE clause parsed successfully for: %s", tc.desc)
  69. t.Logf(" WHERE expression type: %T", selectStmt.Where.Expr)
  70. })
  71. }
  72. }
  73. // TestPredicateBuilding tests if buildPredicate can handle CockroachDB AST nodes
  74. func TestPredicateBuilding(t *testing.T) {
  75. engine := NewTestSQLEngine()
  76. testCases := []struct {
  77. name string
  78. sql string
  79. desc string
  80. testRecord *schema_pb.RecordValue
  81. shouldMatch bool
  82. }{
  83. {
  84. name: "Simple_Equals_Match",
  85. sql: "SELECT id FROM user_events WHERE id = 82460",
  86. desc: "Simple equality - should match",
  87. testRecord: createTestRecord("82460", "active"),
  88. shouldMatch: true,
  89. },
  90. {
  91. name: "Simple_Equals_NoMatch",
  92. sql: "SELECT id FROM user_events WHERE id = 82460",
  93. desc: "Simple equality - should not match",
  94. testRecord: createTestRecord("999999", "active"),
  95. shouldMatch: false,
  96. },
  97. {
  98. name: "Greater_Than_Match",
  99. sql: "SELECT id FROM user_events WHERE id > 100000",
  100. desc: "Greater than - should match",
  101. testRecord: createTestRecord("841256", "active"),
  102. shouldMatch: true,
  103. },
  104. {
  105. name: "Greater_Than_NoMatch",
  106. sql: "SELECT id FROM user_events WHERE id > 100000",
  107. desc: "Greater than - should not match",
  108. testRecord: createTestRecord("82460", "active"),
  109. shouldMatch: false,
  110. },
  111. {
  112. name: "String_Equals_Match",
  113. sql: "SELECT id FROM user_events WHERE status = 'active'",
  114. desc: "String equality - should match",
  115. testRecord: createTestRecord("82460", "active"),
  116. shouldMatch: true,
  117. },
  118. {
  119. name: "String_Equals_NoMatch",
  120. sql: "SELECT id FROM user_events WHERE status = 'active'",
  121. desc: "String equality - should not match",
  122. testRecord: createTestRecord("82460", "inactive"),
  123. shouldMatch: false,
  124. },
  125. {
  126. name: "Impossible_Condition",
  127. sql: "SELECT id FROM user_events WHERE 1 = 0",
  128. desc: "Impossible condition - should never match",
  129. testRecord: createTestRecord("82460", "active"),
  130. shouldMatch: false,
  131. },
  132. }
  133. for _, tc := range testCases {
  134. t.Run(tc.name, func(t *testing.T) {
  135. // Parse the SQL
  136. parsedStmt, parseErr := ParseSQL(tc.sql)
  137. if parseErr != nil {
  138. t.Fatalf("Parse error: %v", parseErr)
  139. }
  140. selectStmt, ok := parsedStmt.(*SelectStatement)
  141. if !ok || selectStmt.Where == nil {
  142. t.Fatalf("No WHERE clause found")
  143. }
  144. // Try to build the predicate
  145. predicate, buildErr := engine.buildPredicate(selectStmt.Where.Expr)
  146. if buildErr != nil {
  147. t.Errorf("PREDICATE BUILD ERROR: %v", buildErr)
  148. t.Errorf("This might be the root cause of WHERE clause not working!")
  149. t.Errorf("WHERE expression type: %T", selectStmt.Where.Expr)
  150. return
  151. }
  152. // Test the predicate against our test record
  153. actualMatch := predicate(tc.testRecord)
  154. if actualMatch == tc.shouldMatch {
  155. t.Logf("PASS: %s - Predicate worked correctly (match=%v)", tc.desc, actualMatch)
  156. } else {
  157. t.Errorf("FAIL: %s - Expected match=%v, got match=%v", tc.desc, tc.shouldMatch, actualMatch)
  158. t.Errorf("This confirms the predicate logic is incorrect!")
  159. }
  160. })
  161. }
  162. }
  163. // TestWhereClauseEndToEnd tests complete WHERE clause functionality
  164. func TestWhereClauseEndToEnd(t *testing.T) {
  165. engine := NewTestSQLEngine()
  166. t.Log("END-TO-END WHERE CLAUSE VALIDATION")
  167. t.Log("===================================")
  168. // Test 1: Baseline (no WHERE clause)
  169. baselineResult, err := engine.ExecuteSQL(context.Background(), "SELECT id FROM user_events")
  170. if err != nil {
  171. t.Fatalf("Baseline query failed: %v", err)
  172. }
  173. baselineCount := len(baselineResult.Rows)
  174. t.Logf("Baseline (no WHERE): %d rows", baselineCount)
  175. // Test 2: Impossible condition
  176. impossibleResult, err := engine.ExecuteSQL(context.Background(), "SELECT id FROM user_events WHERE 1 = 0")
  177. if err != nil {
  178. t.Fatalf("Impossible WHERE query failed: %v", err)
  179. }
  180. impossibleCount := len(impossibleResult.Rows)
  181. t.Logf("WHERE 1 = 0: %d rows", impossibleCount)
  182. // CRITICAL TEST: This should detect the WHERE clause bug
  183. if impossibleCount == baselineCount {
  184. t.Errorf("❌ WHERE CLAUSE BUG CONFIRMED:")
  185. t.Errorf(" Impossible condition returned same row count as no WHERE clause")
  186. t.Errorf(" This proves WHERE filtering is not being applied")
  187. } else if impossibleCount == 0 {
  188. t.Logf("✅ Impossible WHERE condition correctly returns 0 rows")
  189. }
  190. // Test 3: Specific ID filtering
  191. if baselineCount > 0 {
  192. firstId := baselineResult.Rows[0][0].ToString()
  193. specificResult, err := engine.ExecuteSQL(context.Background(),
  194. "SELECT id FROM user_events WHERE id = "+firstId)
  195. if err != nil {
  196. t.Fatalf("Specific ID WHERE query failed: %v", err)
  197. }
  198. specificCount := len(specificResult.Rows)
  199. t.Logf("WHERE id = %s: %d rows", firstId, specificCount)
  200. if specificCount == baselineCount {
  201. t.Errorf("❌ WHERE clause bug: Specific ID filter returned all rows")
  202. } else if specificCount == 1 {
  203. t.Logf("✅ Specific ID WHERE clause working correctly")
  204. } else {
  205. t.Logf("❓ Unexpected: Specific ID returned %d rows", specificCount)
  206. }
  207. }
  208. // Test 4: Range filtering with actual data validation
  209. rangeResult, err := engine.ExecuteSQL(context.Background(), "SELECT id FROM user_events WHERE id > 10000000")
  210. if err != nil {
  211. t.Fatalf("Range WHERE query failed: %v", err)
  212. }
  213. rangeCount := len(rangeResult.Rows)
  214. t.Logf("WHERE id > 10000000: %d rows", rangeCount)
  215. // Check if the filtering actually worked by examining the data
  216. nonMatchingCount := 0
  217. for _, row := range rangeResult.Rows {
  218. idStr := row[0].ToString()
  219. if idVal, parseErr := strconv.ParseInt(idStr, 10, 64); parseErr == nil {
  220. if idVal <= 10000000 {
  221. nonMatchingCount++
  222. }
  223. }
  224. }
  225. if nonMatchingCount > 0 {
  226. t.Errorf("❌ WHERE clause bug: %d rows have id <= 10,000,000 but should be filtered out", nonMatchingCount)
  227. t.Errorf(" Sample IDs that should be filtered: %v", getSampleIds(rangeResult, 3))
  228. } else {
  229. t.Logf("✅ WHERE id > 10000000 correctly filtered results")
  230. }
  231. }
  232. // Helper function to create test records for predicate testing
  233. func createTestRecord(id string, status string) *schema_pb.RecordValue {
  234. record := &schema_pb.RecordValue{
  235. Fields: make(map[string]*schema_pb.Value),
  236. }
  237. // Add id field (as int64)
  238. if idVal, err := strconv.ParseInt(id, 10, 64); err == nil {
  239. record.Fields["id"] = &schema_pb.Value{
  240. Kind: &schema_pb.Value_Int64Value{Int64Value: idVal},
  241. }
  242. } else {
  243. record.Fields["id"] = &schema_pb.Value{
  244. Kind: &schema_pb.Value_StringValue{StringValue: id},
  245. }
  246. }
  247. // Add status field (as string)
  248. record.Fields["status"] = &schema_pb.Value{
  249. Kind: &schema_pb.Value_StringValue{StringValue: status},
  250. }
  251. return record
  252. }
  253. // Helper function to get sample IDs from result
  254. func getSampleIds(result *QueryResult, count int) []string {
  255. var ids []string
  256. for i := 0; i < count && i < len(result.Rows); i++ {
  257. ids = append(ids, result.Rows[i][0].ToString())
  258. }
  259. return ids
  260. }
  261. // TestSpecificWhereClauseBug reproduces the exact issue from real usage
  262. func TestSpecificWhereClauseBug(t *testing.T) {
  263. engine := NewTestSQLEngine()
  264. t.Log("REPRODUCING EXACT WHERE CLAUSE BUG")
  265. t.Log("==================================")
  266. // The exact query that was failing: WHERE id > 10000000
  267. sql := "SELECT id FROM user_events WHERE id > 10000000 LIMIT 10 OFFSET 5"
  268. result, err := engine.ExecuteSQL(context.Background(), sql)
  269. if err != nil {
  270. t.Fatalf("Query failed: %v", err)
  271. }
  272. t.Logf("Query: %s", sql)
  273. t.Logf("Returned %d rows:", len(result.Rows))
  274. // Check each returned ID
  275. bugDetected := false
  276. for i, row := range result.Rows {
  277. idStr := row[0].ToString()
  278. if idVal, parseErr := strconv.ParseInt(idStr, 10, 64); parseErr == nil {
  279. t.Logf("Row %d: id = %d", i+1, idVal)
  280. if idVal <= 10000000 {
  281. bugDetected = true
  282. t.Errorf("❌ BUG: id %d should be filtered out (≤ 10,000,000)", idVal)
  283. }
  284. }
  285. }
  286. if !bugDetected {
  287. t.Log("✅ WHERE clause working correctly - all IDs > 10,000,000")
  288. } else {
  289. t.Error("❌ WHERE clause bug confirmed: Returned IDs that should be filtered out")
  290. }
  291. }