Skip to content

Commit 56fa073

Browse files
author
linxiaotao
committed
test(mysql): Add comprehensive type compatibility test cases for RuleSQLE00112
- Introduced new test cases to validate behavior of various data types (e.g., BIGINT, INT, FLOAT, CHAR, DATE) in SQL queries. - Enhanced coverage for implicit conversion scenarios, ensuring accurate detection of type mismatches. - Organized tests into categories for better clarity and maintainability, addressing edge cases and boundary conditions. These additions aim to strengthen the robustness of type compatibility checks in SQL queries.
1 parent 3315659 commit 56fa073

File tree

1 file changed

+278
-0
lines changed

1 file changed

+278
-0
lines changed

sqle/driver/mysql/rule_00112_test.go

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,284 @@ func TestRuleSQLE00112(t *testing.T) {
185185
session.NewAIMockContext().WithSQL("CREATE TABLE orders (c_id VARCHAR(100), order_date DATE);").
186186
WithSQL("CREATE TABLE customers (c_id INT, name VARCHAR(100));"),
187187
nil, newTestResult().addResult(ruleName))
188+
189+
// 新增测试用例:验证修复效果
190+
runAIRuleCase(rule, t, "case 33: UPDATE with BIGINT UNSIGNED and int constant (should pass)",
191+
"UPDATE t1 SET name = 'jack' WHERE id = 2838923;",
192+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (id BIGINT UNSIGNED NOT NULL, name VARCHAR(100));"),
193+
nil, newTestResult())
194+
195+
runAIRuleCase(rule, t, "case 34: UPDATE with BIGINT and int constant (should pass)",
196+
"UPDATE t1 SET name = 'jack' WHERE id = 2838923;",
197+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (id BIGINT NOT NULL, name VARCHAR(100));"),
198+
nil, newTestResult())
199+
200+
runAIRuleCase(rule, t, "case 35: UPDATE with INT and int constant (should pass)",
201+
"UPDATE t1 SET name = 'jack' WHERE id = 100;",
202+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (id INT NOT NULL, name VARCHAR(100));"),
203+
nil, newTestResult())
204+
205+
runAIRuleCase(rule, t, "case 36: UPDATE with BIGINT UNSIGNED and string constant (should fail)",
206+
"UPDATE t1 SET name = 'jack' WHERE id = '2838923';",
207+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (id BIGINT UNSIGNED NOT NULL, name VARCHAR(100));"),
208+
nil, newTestResult().addResult(ruleName))
209+
210+
runAIRuleCase(rule, t, "case 37: SELECT with BIGINT UNSIGNED and large constant (should pass)",
211+
"SELECT * FROM t1 WHERE id = 18446744073709551615;",
212+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (id BIGINT UNSIGNED NOT NULL, name VARCHAR(100));"),
213+
nil, newTestResult())
214+
215+
// ==== 测试用例分类:数值类型大类匹配 ====
216+
// 测试目标:验证数值类型之间的匹配,确保不会导致隐式转换
217+
// 测试范围:cases 38-43
218+
219+
// 整数类型匹配测试
220+
runAIRuleCase(rule, t, "case 38: TINYINT with INT constant (should pass - 数值在范围内)",
221+
"SELECT * FROM t1 WHERE age = 25;",
222+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (age TINYINT, name VARCHAR(100));"),
223+
nil, newTestResult())
224+
225+
runAIRuleCase(rule, t, "case 39: SMALLINT with INT constant (should pass - 数值在范围内)",
226+
"SELECT * FROM t1 WHERE score = 1000;",
227+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (score SMALLINT, name VARCHAR(100));"),
228+
nil, newTestResult())
229+
230+
runAIRuleCase(rule, t, "case 40: INT with INT constant (should pass)",
231+
"SELECT * FROM t1 WHERE id = 2147483647;",
232+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (id INT, name VARCHAR(100));"),
233+
nil, newTestResult())
234+
235+
// 浮点数与整数匹配测试
236+
runAIRuleCase(rule, t, "case 41: FLOAT with INT constant (should fail - 隐式转换)",
237+
"SELECT * FROM t1 WHERE price = 100;",
238+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (price FLOAT, name VARCHAR(100));"),
239+
nil, newTestResult().addResult(ruleName))
240+
241+
runAIRuleCase(rule, t, "case 42: DOUBLE with FLOAT constant (should fail - 隐式转换)",
242+
"SELECT * FROM t1 WHERE rate = 3.14;",
243+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (rate DOUBLE, name VARCHAR(100));"),
244+
nil, newTestResult().addResult(ruleName))
245+
246+
// 精确数值类型匹配测试
247+
runAIRuleCase(rule, t, "case 43: DECIMAL with INT constant (should fail - 隐式转换)",
248+
"SELECT * FROM t1 WHERE amount = 100;",
249+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (amount DECIMAL(10,2), name VARCHAR(100));"),
250+
nil, newTestResult().addResult(ruleName))
251+
252+
// ==== 测试用例分类:字符串类型大类匹配 ====
253+
// 测试目标:验证字符串类型之间的匹配,确保不会导致隐式转换
254+
// 测试范围:cases 44-47
255+
256+
// 基础字符串类型匹配测试
257+
runAIRuleCase(rule, t, "case 44: CHAR with VARCHAR constant (should pass - 字符串类型兼容)",
258+
"SELECT * FROM t1 WHERE code = 'ABC';",
259+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (code CHAR(10), name VARCHAR(100));"),
260+
nil, newTestResult())
261+
262+
runAIRuleCase(rule, t, "case 45: VARCHAR with CHAR constant (should pass - 字符串类型兼容)",
263+
"SELECT * FROM t1 WHERE name = 'John';",
264+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (name VARCHAR(100), code CHAR(10));"),
265+
nil, newTestResult())
266+
267+
// 二进制字符串类型匹配测试
268+
runAIRuleCase(rule, t, "case 46: BLOB with BLOB constant (should pass)",
269+
"SELECT * FROM t1 WHERE data = 0x48656C6C6F;",
270+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (data BLOB, name VARCHAR(100));"),
271+
nil, newTestResult())
272+
273+
// 枚举类型匹配测试
274+
runAIRuleCase(rule, t, "case 47: ENUM with ENUM constant (should fail - 隐式转换)",
275+
"SELECT * FROM t1 WHERE status = 'active';",
276+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (status ENUM('active', 'inactive'), name VARCHAR(100));"),
277+
nil, newTestResult().addResult(ruleName))
278+
279+
// ==== 测试用例分类:日期时间类型大类匹配 ====
280+
// 测试目标:验证日期时间类型的匹配,检测隐式转换风险
281+
// 测试范围:cases 48-50B
282+
// 注意:虽然 MySQL 会自动转换字符串为日期,但隐式转换可能导致索引失效
283+
// 正确的做法:应该使用显式转换,如 CAST('1990-01-01' AS DATE) 或 DATE('1990-01-01')
284+
285+
// 日期时间类型与字符串常量不匹配测试(应该报错)
286+
runAIRuleCase(rule, t, "case 48: DATE with string constant (should fail - 隐式转换风险)",
287+
"SELECT * FROM t1 WHERE birth_date = '1990-01-01';",
288+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (birth_date DATE, name VARCHAR(100));"),
289+
nil, newTestResult().addResult(ruleName))
290+
291+
runAIRuleCase(rule, t, "case 49: DATETIME with string constant (should fail - 隐式转换风险)",
292+
"SELECT * FROM t1 WHERE created_at = '2023-01-01 12:00:00';",
293+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (created_at DATETIME, name VARCHAR(100));"),
294+
nil, newTestResult().addResult(ruleName))
295+
296+
runAIRuleCase(rule, t, "case 50: TIMESTAMP with string constant (should fail - 隐式转换风险)",
297+
"SELECT * FROM t1 WHERE updated_at = '2023-01-01 12:00:00';",
298+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (updated_at TIMESTAMP, name VARCHAR(100));"),
299+
nil, newTestResult().addResult(ruleName))
300+
301+
// 日期时间类型与日期时间类型列匹配测试(应该通过)
302+
runAIRuleCase(rule, t, "case 50A: DATE with DATE column (should pass)",
303+
"SELECT * FROM t1 WHERE birth_date = created_date;",
304+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (birth_date DATE, created_date DATE, name VARCHAR(100));"),
305+
nil, newTestResult())
306+
307+
runAIRuleCase(rule, t, "case 50B: DATETIME with DATETIME column (should pass)",
308+
"SELECT * FROM t1 WHERE created_at = updated_at;",
309+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (created_at DATETIME, updated_at DATETIME, name VARCHAR(100));"),
310+
nil, newTestResult())
311+
312+
// ==== 测试用例分类:跨大类不匹配 ====
313+
// 测试目标:验证不同大类类型之间的不匹配,确保检测到隐式转换风险
314+
// 测试范围:cases 51-54
315+
316+
// 数值与字符串类型不匹配测试(应该报错)
317+
runAIRuleCase(rule, t, "case 51: INT with VARCHAR constant (should fail)",
318+
"SELECT * FROM t1 WHERE id = '123';",
319+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (id INT, name VARCHAR(100));"),
320+
nil, newTestResult().addResult(ruleName))
321+
322+
runAIRuleCase(rule, t, "case 52: VARCHAR with INT constant (should fail)",
323+
"SELECT * FROM t1 WHERE name = 123;",
324+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (name VARCHAR(100), id INT);"),
325+
nil, newTestResult().addResult(ruleName))
326+
327+
// 日期时间与字符串类型不匹配测试(应该报错)
328+
// 正确的做法:使用 CAST('1990-01-01' AS DATE) 或 DATE('1990-01-01')
329+
runAIRuleCase(rule, t, "case 53: DATE with VARCHAR constant (should fail - 隐式转换风险)",
330+
"SELECT * FROM t1 WHERE birth_date = '1990-01-01';",
331+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (birth_date DATE, name VARCHAR(100));"),
332+
nil, newTestResult().addResult(ruleName))
333+
334+
// 日期时间与数值类型不匹配测试(应该报错)
335+
// 正确的做法:使用 CAST(19900101 AS DATE) 或 DATE(19900101)
336+
runAIRuleCase(rule, t, "case 54: DATE with INT constant (should fail - 隐式转换风险)",
337+
"SELECT * FROM t1 WHERE birth_date = 19900101;",
338+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (birth_date DATE, name VARCHAR(100));"),
339+
nil, newTestResult().addResult(ruleName))
340+
341+
// ==== 测试用例分类:边界情况 ====
342+
// 测试目标:验证特殊类型和边界情况的匹配
343+
// 测试范围:cases 55-57
344+
345+
// 位类型匹配测试
346+
runAIRuleCase(rule, t, "case 55: BIT with INT constant (should fail - 隐式转换)",
347+
"SELECT * FROM t1 WHERE flag = 1;",
348+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (flag BIT(1), name VARCHAR(100));"),
349+
nil, newTestResult().addResult(ruleName))
350+
351+
// 年份类型匹配测试
352+
runAIRuleCase(rule, t, "case 56: YEAR with INT constant (should fail - 隐式转换)",
353+
"SELECT * FROM t1 WHERE year_col = 2023;",
354+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (year_col YEAR, name VARCHAR(100));"),
355+
nil, newTestResult().addResult(ruleName))
356+
357+
// 集合类型匹配测试
358+
runAIRuleCase(rule, t, "case 57: SET with SET constant (should fail - 隐式转换)",
359+
"SELECT * FROM t1 WHERE tags = 'tag1,tag2';",
360+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (tags SET('tag1', 'tag2', 'tag3'), name VARCHAR(100));"),
361+
nil, newTestResult().addResult(ruleName))
362+
363+
// ==== 新增测试用例:时间转换函数 ====
364+
365+
// 测试使用时间函数与时间列的比较(应该通过)
366+
runAIRuleCase(rule, t, "case 58: DATE with CURRENT_DATE function (should pass)",
367+
"SELECT * FROM t1 WHERE birth_date = CURRENT_DATE();",
368+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (birth_date DATE, name VARCHAR(100));"),
369+
nil, newTestResult())
370+
371+
runAIRuleCase(rule, t, "case 59: DATETIME with NOW function (should pass)",
372+
"SELECT * FROM t1 WHERE created_at = NOW();",
373+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (created_at DATETIME, name VARCHAR(100));"),
374+
nil, newTestResult())
375+
376+
// ==== 测试用例分类:列与值大类相同但会隐式转换的情况 ====
377+
// 测试目标:验证列与值在大类相同但具体类型不同时的隐式转换检测
378+
// 这些情况虽然大类相同,但会导致隐式转换,影响性能
379+
380+
// 数值类型内部的隐式转换测试(应该报错)
381+
runAIRuleCase(rule, t, "case 60: TINYINT column with BIGINT constant (should fail - 隐式转换)",
382+
"SELECT * FROM t1 WHERE age = 9223372036854775807;",
383+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (age TINYINT, name VARCHAR(100));"),
384+
nil, newTestResult().addResult(ruleName))
385+
386+
runAIRuleCase(rule, t, "case 61: INT column with BIGINT constant (should fail - 隐式转换)",
387+
"SELECT * FROM t1 WHERE id = 9223372036854775807;",
388+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (id INT, name VARCHAR(100));"),
389+
nil, newTestResult().addResult(ruleName))
390+
391+
runAIRuleCase(rule, t, "case 62: FLOAT column with DOUBLE constant (should fail - 隐式转换)",
392+
"SELECT * FROM t1 WHERE price = 3.141592653589793;",
393+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (price FLOAT, name VARCHAR(100));"),
394+
nil, newTestResult().addResult(ruleName))
395+
396+
runAIRuleCase(rule, t, "case 63: DECIMAL(5,2) column with DECIMAL(10,4) constant (should pass - DECIMAL类型兼容)",
397+
"SELECT * FROM t1 WHERE amount = 123456.7890;",
398+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (amount DECIMAL(5,2), name VARCHAR(100));"),
399+
nil, newTestResult())
400+
401+
// 字符串类型内部的兼容性测试
402+
runAIRuleCase(rule, t, "case 64: CHAR(10) column with long VARCHAR constant (should pass - MySQL转换值)",
403+
"SELECT * FROM t1 WHERE code = 'This is a very long string that exceeds CHAR(10) limit';",
404+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (code CHAR(10), name VARCHAR(100));"),
405+
nil, newTestResult())
406+
407+
runAIRuleCase(rule, t, "case 65: VARCHAR(50) column with TEXT constant (should pass - 字符串类型兼容)",
408+
"SELECT * FROM t1 WHERE description = 'This is a very long text that would be stored in TEXT type';",
409+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (description VARCHAR(50), name VARCHAR(100));"),
410+
nil, newTestResult())
411+
412+
runAIRuleCase(rule, t, "case 66: BLOB column with BLOB constant (should pass - BLOB类型兼容)",
413+
"SELECT * FROM t1 WHERE data = 0x48656C6C6F576F726C64;",
414+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (data BLOB, name VARCHAR(100));"),
415+
nil, newTestResult())
416+
417+
// 日期时间类型内部的隐式转换测试(应该报错)
418+
runAIRuleCase(rule, t, "case 67: DATE column with DATETIME constant (should fail - 隐式转换)",
419+
"SELECT * FROM t1 WHERE birth_date = '2023-01-01 12:00:00';",
420+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (birth_date DATE, name VARCHAR(100));"),
421+
nil, newTestResult().addResult(ruleName))
422+
423+
runAIRuleCase(rule, t, "case 68: DATETIME column with TIMESTAMP constant (should fail - 隐式转换)",
424+
"SELECT * FROM t1 WHERE created_at = '2023-01-01 12:00:00';",
425+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (created_at DATETIME, name VARCHAR(100));"),
426+
nil, newTestResult().addResult(ruleName))
427+
428+
runAIRuleCase(rule, t, "case 69: TIMESTAMP column with DATE constant (should fail - 隐式转换)",
429+
"SELECT * FROM t1 WHERE updated_at = '2023-01-01';",
430+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (updated_at TIMESTAMP, name VARCHAR(100));"),
431+
nil, newTestResult().addResult(ruleName))
432+
433+
// 特殊数值类型的隐式转换测试(应该报错)
434+
runAIRuleCase(rule, t, "case 70: TINYINT UNSIGNED column with overflow constant (should fail - 超出范围)",
435+
"SELECT * FROM t1 WHERE status = 256;",
436+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (status TINYINT UNSIGNED, name VARCHAR(100));"),
437+
nil, newTestResult().addResult(ruleName))
438+
439+
runAIRuleCase(rule, t, "case 71: INT UNSIGNED column with BIGINT constant (should fail - 隐式转换)",
440+
"SELECT * FROM t1 WHERE count = 9223372036854775807;",
441+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (count INT UNSIGNED, name VARCHAR(100));"),
442+
nil, newTestResult().addResult(ruleName))
443+
444+
// 枚举和集合类型的隐式转换测试(应该报错)
445+
runAIRuleCase(rule, t, "case 72: ENUM column with invalid ENUM constant (should fail - 隐式转换)",
446+
"SELECT * FROM t1 WHERE status = 'invalid_status';",
447+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (status ENUM('active', 'inactive'), name VARCHAR(100));"),
448+
nil, newTestResult().addResult(ruleName))
449+
450+
runAIRuleCase(rule, t, "case 73: SET column with invalid SET constant (should fail - 隐式转换)",
451+
"SELECT * FROM t1 WHERE tags = 'invalid_tag,another_invalid';",
452+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (tags SET('tag1', 'tag2', 'tag3'), name VARCHAR(100));"),
453+
nil, newTestResult().addResult(ruleName))
454+
455+
// 边界值隐式转换测试(应该报错)
456+
runAIRuleCase(rule, t, "case 74: SMALLINT column with INT overflow constant (should fail - 隐式转换)",
457+
"SELECT * FROM t1 WHERE score = 32768;",
458+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (score SMALLINT, name VARCHAR(100));"),
459+
nil, newTestResult().addResult(ruleName))
460+
461+
runAIRuleCase(rule, t, "case 75: MEDIUMINT column with BIGINT constant (should fail - 隐式转换)",
462+
"SELECT * FROM t1 WHERE id = 2147483648;",
463+
session.NewAIMockContext().WithSQL("CREATE TABLE t1 (id MEDIUMINT, name VARCHAR(100));"),
464+
nil, newTestResult().addResult(ruleName))
465+
188466
}
189467

190468
// ==== Rule test code end ====

0 commit comments

Comments
 (0)