Skip to content

Commit 82edf74

Browse files
yihong0618JaySon-Huang
authored andcommitted
types: fix CASE WHEN wrong result when prepare value is NULL (pingcap#62568)
close pingcap#62564
1 parent 3ee5568 commit 82edf74

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

pkg/types/field_type.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,14 @@ func InferParamTypeFromDatum(d *Datum, tp *FieldType) {
194194
func InferParamTypeFromUnderlyingValue(value any, tp *FieldType) {
195195
switch value.(type) {
196196
case nil:
197-
tp.SetType(mysql.TypeVarString)
198-
tp.SetFlen(UnspecifiedLength)
199-
tp.SetDecimal(UnspecifiedLength)
200-
// Also set the `charset` and `collation` for it, because some function (e.g. `json_object`) will return error
201-
// if the argument collation is `binary`.
197+
// For NULL parameters, use TypeNull to ensure consistent behavior with literal NULL values
198+
// in control flow functions like CASE WHEN. Previously using TypeVarString caused incorrect
199+
// type inference in prepared statements (issue #62564).
200+
tp.SetType(mysql.TypeNull)
201+
tp.SetFlen(0)
202+
tp.SetDecimal(0)
203+
// Set default charset and collation instead of binary charset to avoid breaking JSON functions
204+
// (see PR #54145 which fixed JSON function argument verification issues).
202205
tp.SetCharset(mysql.DefaultCharset)
203206
tp.SetCollate(mysql.DefaultCollationName)
204207
default:

tests/integrationtest/r/planner/core/casetest/integration.result

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,3 +1838,13 @@ Update N/A root N/A
18381838
└─TableReader(Probe) 0.00 root data:Selection
18391839
└─Selection 0.00 cop[tikv] or(or(and(eq(test.tt.c, 11), eq(test.tt.d, 111)), and(eq(test.tt.c, 22), eq(test.tt.d, 222))), or(and(eq(test.tt.c, 33), eq(test.tt.d, 333)), and(eq(test.tt.c, 44), eq(test.tt.d, 444)))), or(or(eq(test.tt.c, 11), eq(test.tt.c, 22)), or(eq(test.tt.c, 33), eq(test.tt.c, 44))), or(or(eq(test.tt.d, 111), eq(test.tt.d, 222)), or(eq(test.tt.d, 333), eq(test.tt.d, 444)))
18401840
└─TableRangeScan 0.00 cop[tikv] table:tt range: decided by [eq(test.tt.c, Column#20) eq(test.tt.d, Column#21)], keep order:false, stats:pseudo
1841+
CREATE TABLE test_62564(c0 DECIMAL);
1842+
INSERT INTO test_62564 VALUES (0);
1843+
SELECT * FROM test_62564 WHERE CAST((CASE test_62564.c0 WHEN test_62564.c0 THEN CAST(test_62564.c0 AS TIME) ELSE NULL END ) AS DATE);
1844+
c0
1845+
0
1846+
SET @b = NULL;
1847+
PREPARE prepare_query FROM 'SELECT * FROM test_62564 WHERE CAST((CASE test_62564.c0 WHEN test_62564.c0 THEN CAST(test_62564.c0 AS TIME) ELSE ? END ) AS DATE)';
1848+
EXECUTE prepare_query USING @b;
1849+
c0
1850+
0

tests/integrationtest/t/planner/core/casetest/integration.test

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,3 +732,11 @@ use test;
732732
drop table if exists tt;
733733
create table tt(a bigint, b bigint, c bigint, d bigint, e bigint, primary key(c,d));
734734
explain format = brief update tt, (select 1 as c1 ,2 as c2 ,3 as c3, 4 as c4 union all select 2,3,4,5 union all select 3,4,5,6) tmp set tt.a=tmp.c1, tt.b=tmp.c2 where tt.c=tmp.c3 and tt.d=tmp.c4 and (tt.c,tt.d) in ((11,111),(22,222),(33,333),(44,444));
735+
736+
# TestIssue62564
737+
CREATE TABLE test_62564(c0 DECIMAL);
738+
INSERT INTO test_62564 VALUES (0);
739+
SELECT * FROM test_62564 WHERE CAST((CASE test_62564.c0 WHEN test_62564.c0 THEN CAST(test_62564.c0 AS TIME) ELSE NULL END ) AS DATE);
740+
SET @b = NULL;
741+
PREPARE prepare_query FROM 'SELECT * FROM test_62564 WHERE CAST((CASE test_62564.c0 WHEN test_62564.c0 THEN CAST(test_62564.c0 AS TIME) ELSE ? END ) AS DATE)';
742+
EXECUTE prepare_query USING @b;

0 commit comments

Comments
 (0)