Skip to content

Commit f926421

Browse files
authored
[Fix](expr) Fix case when wrong result and relative date types false alarm (#60040)
### What problem does this PR solve? Issue Number: close #xxx Related PR: #xxx Problem Summary: before if there's null return for `case-when` expr and the type is a datelike type. may raise false alarm caused by invalid nested value: ``` ERROR 1105 (HY000): errCode = 2, detailMessage = (10.16.10.3)[INVALID_ARGUMENT]Operation to_date meets invalid data: ``` now fixed it. ### Release note None ### Check List (For Author) - Test <!-- At least one of them must be included. --> - [x] Regression test - [ ] Unit Test - [ ] Manual test (add detailed scripts or steps below) - [ ] No need to test or manual test. Explain why: - [ ] This is a refactor/code format and no logic has been changed. - [ ] Previous test can cover this change. - [ ] No code files have been changed. - [ ] Other reason <!-- Add your reason? --> - Behavior changed: - [x] No. - [ ] Yes. <!-- Explain the behavior change --> - Does this need documentation? - [x] No. - [ ] Yes. <!-- Add document PR link here. eg: apache/doris-website#1214 --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label <!-- Add branch pick label that this PR should merge into -->
1 parent 400ab21 commit f926421

File tree

5 files changed

+220
-7
lines changed

5 files changed

+220
-7
lines changed

be/src/vec/columns/column_const.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,19 @@ class ColumnConst final : public COWHelper<IColumn, ColumnConst> {
290290
"Method replace_column_data is not supported for " + get_name());
291291
}
292292

293+
void replace_column_null_data(const uint8_t* __restrict null_map) override {
294+
// For ColumnConst, the null_map has only 1 element (the const value's null status)
295+
// If the const value is null, replace the nested data with default value
296+
if (null_map[0]) {
297+
data = std::move(*data).mutate();
298+
data->replace_column_null_data(null_map);
299+
}
300+
}
301+
302+
bool support_replace_column_null_data() const override {
303+
return data->support_replace_column_null_data();
304+
}
305+
293306
void finalize() override { data->finalize(); }
294307

295308
void erase(size_t start, size_t length) override {

be/src/vec/columns/column_vector.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,6 @@ class ColumnVector final : public COWHelper<IColumn, ColumnVector<T>> {
382382
size_t serialize_impl(char* pos, const size_t row) const override;
383383
size_t deserialize_impl(const char* pos) override;
384384
size_t serialize_size_at(size_t row) const override { return sizeof(value_type); }
385-
386-
protected:
387-
uint32_t _crc32c_hash(uint32_t hash, size_t idx) const;
388385
// when run function which need_replace_null_data_to_default, use the value far from 0 to avoid
389386
// raise errors for null cell.
390387
static value_type default_value() {
@@ -395,6 +392,8 @@ class ColumnVector final : public COWHelper<IColumn, ColumnVector<T>> {
395392
}
396393
}
397394

395+
protected:
396+
uint32_t _crc32c_hash(uint32_t hash, size_t idx) const;
398397
Container data;
399398
};
400399

be/src/vec/exprs/vcase_expr.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,15 @@ class VCaseExpr final : public VExpr {
204204

205205
// set default value
206206
for (int i = 0; i < rows_count; i++) {
207-
result_raw_data[i] = {};
207+
if constexpr (std::is_same_v<ColumnType, ColumnDate> ||
208+
std::is_same_v<ColumnType, ColumnDateTime> ||
209+
std::is_same_v<ColumnType, ColumnDateV2> ||
210+
std::is_same_v<ColumnType, ColumnDateTimeV2> ||
211+
std::is_same_v<ColumnType, ColumnTimeStampTz>) {
212+
result_raw_data[i] = ColumnType::default_value();
213+
} else {
214+
result_raw_data[i] = {};
215+
}
208216
}
209217

210218
for (IndexType i = 0; i < then_columns.size(); i++) {
@@ -222,9 +230,8 @@ class VCaseExpr final : public VExpr {
222230
std::is_same_v<ColumnType, ColumnDateTimeV2> ||
223231
std::is_same_v<ColumnType, ColumnTimeStampTz>) {
224232
for (int row_idx = 0; row_idx < rows_count; row_idx++) {
225-
result_raw_data[row_idx] =
226-
(then_idx[row_idx] == i ? column_raw_data[row_idx]
227-
: typename ColumnType::value_type());
233+
result_raw_data[row_idx] = (then_idx[row_idx] == i) ? column_raw_data[row_idx]
234+
: result_raw_data[row_idx];
228235
}
229236
} else {
230237
for (int row_idx = 0; row_idx < rows_count; row_idx++) {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
-- This file is automatically generated. You should know what you did if you want to edit this
2+
-- !case_when_to_date --
3+
1 2023-01-01
4+
2 2023-02-15
5+
3 2023-03-20
6+
4 2023-04-11
7+
5 2023-05-26
8+
9+
-- !case_when_date_3branches --
10+
1 2023-01-01
11+
2 2023-02-25
12+
3 2023-03-20
13+
4 2023-04-10
14+
5 2023-05-25
15+
16+
-- !case_when_month --
17+
1 1
18+
2 2
19+
3 3
20+
4 4
21+
5 5
22+
23+
-- !case_when_dayofmonth --
24+
1 1
25+
2 15
26+
3 20
27+
4 10
28+
5 25
29+
30+
-- !case_when_datetime --
31+
1 2023-01-01T10:00
32+
2 2023-02-15T12:30
33+
3 2023-03-20T15:45
34+
4 2023-04-10T08:00
35+
5 2023-05-25T20:00
36+
37+
-- !case_when_datetimev2_to_date --
38+
1 2023-01-01
39+
2 2023-02-15
40+
3 2023-03-20
41+
4 2023-04-10
42+
5 2023-05-25
43+
44+
-- !case_when_nested --
45+
1 2023-01-01
46+
2 2023-02-15
47+
3 2023-03-20
48+
4 2023-04-10
49+
5 2023-05-25
50+
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
suite("test_case_when_date") {
19+
sql """ DROP TABLE IF EXISTS test_case_when_date_tbl """
20+
sql """
21+
CREATE TABLE test_case_when_date_tbl
22+
(
23+
id INT NOT NULL,
24+
col_date DATE NULL,
25+
col_date_not_null DATE NOT NULL,
26+
col_datev2 DATEV2 NULL,
27+
col_datev2_not_null DATEV2 NOT NULL,
28+
col_datetime DATETIME NULL,
29+
col_datetime_not_null DATETIME NOT NULL,
30+
col_datetimev2 DATETIMEV2 NULL,
31+
col_datetimev2_not_null DATETIMEV2 NOT NULL
32+
)
33+
DISTRIBUTED BY HASH(id) BUCKETS 1
34+
PROPERTIES("replication_num" = "1");
35+
"""
36+
37+
// Insert test data with various date values
38+
sql """
39+
INSERT INTO test_case_when_date_tbl VALUES
40+
(1, '2023-01-01', '2023-01-01', '2023-01-01', '2023-01-01', '2023-01-01 10:00:00', '2023-01-01 10:00:00', '2023-01-01 10:00:00', '2023-01-01 10:00:00'),
41+
(2, '2023-02-15', '2023-02-15', '2023-02-15', '2023-02-15', '2023-02-15 12:30:00', '2023-02-15 12:30:00', '2023-02-15 12:30:00', '2023-02-15 12:30:00'),
42+
(3, '2023-03-20', '2023-03-20', '2023-03-20', '2023-03-20', '2023-03-20 15:45:00', '2023-03-20 15:45:00', '2023-03-20 15:45:00', '2023-03-20 15:45:00'),
43+
(4, NULL, '2023-04-10', NULL, '2023-04-10', NULL, '2023-04-10 08:00:00', NULL, '2023-04-10 08:00:00'),
44+
(5, '2023-05-25', '2023-05-25', '2023-05-25', '2023-05-25', '2023-05-25 20:00:00', '2023-05-25 20:00:00', '2023-05-25 20:00:00', '2023-05-25 20:00:00');
45+
"""
46+
47+
// Test 1: CASE WHEN with multiple branches on DATEV2, applying TO_DATE function
48+
// This was the original failing case - multi-branch CASE WHEN with date functions
49+
qt_case_when_to_date """
50+
SELECT id,
51+
TO_DATE(
52+
CASE
53+
WHEN col_datev2 IN ('2023-01-01', '2023-02-15') THEN col_datev2_not_null
54+
WHEN col_datev2 = '2023-03-20' THEN col_datev2_not_null
55+
ELSE DATE_ADD(col_datev2_not_null, INTERVAL 1 DAY)
56+
END
57+
) AS result
58+
FROM test_case_when_date_tbl
59+
ORDER BY id;
60+
"""
61+
62+
// Test 2: CASE WHEN with 3 branches on DATE type
63+
qt_case_when_date_3branches """
64+
SELECT id,
65+
CASE
66+
WHEN id = 1 THEN col_date_not_null
67+
WHEN id = 2 THEN DATE_ADD(col_date_not_null, INTERVAL 10 DAY)
68+
ELSE col_date_not_null
69+
END AS result
70+
FROM test_case_when_date_tbl
71+
ORDER BY id;
72+
"""
73+
74+
// Test 3: CASE WHEN with MONTH function on result
75+
qt_case_when_month """
76+
SELECT id,
77+
MONTH(
78+
CASE
79+
WHEN id <= 2 THEN col_datev2_not_null
80+
WHEN id = 3 THEN col_datev2_not_null
81+
ELSE col_datev2_not_null
82+
END
83+
) AS result
84+
FROM test_case_when_date_tbl
85+
ORDER BY id;
86+
"""
87+
88+
// Test 4: CASE WHEN with DAYOFMONTH function
89+
qt_case_when_dayofmonth """
90+
SELECT id,
91+
DAYOFMONTH(
92+
CASE
93+
WHEN id = 1 THEN col_datev2_not_null
94+
WHEN id IN (2, 3) THEN col_datev2_not_null
95+
ELSE col_datev2_not_null
96+
END
97+
) AS result
98+
FROM test_case_when_date_tbl
99+
ORDER BY id;
100+
"""
101+
102+
// Test 5: CASE WHEN on DATETIME type with multiple branches
103+
qt_case_when_datetime """
104+
SELECT id,
105+
CASE
106+
WHEN id = 1 THEN col_datetime_not_null
107+
WHEN id = 2 THEN col_datetime_not_null
108+
WHEN id = 3 THEN col_datetime_not_null
109+
ELSE col_datetime_not_null
110+
END AS result
111+
FROM test_case_when_date_tbl
112+
ORDER BY id;
113+
"""
114+
115+
// Test 6: CASE WHEN on DATETIMEV2 with date functions
116+
qt_case_when_datetimev2_to_date """
117+
SELECT id,
118+
TO_DATE(
119+
CASE
120+
WHEN id <= 2 THEN col_datetimev2_not_null
121+
WHEN id = 3 THEN col_datetimev2_not_null
122+
ELSE col_datetimev2_not_null
123+
END
124+
) AS result
125+
FROM test_case_when_date_tbl
126+
ORDER BY id;
127+
"""
128+
129+
// Test 7: Nested CASE WHEN with date types
130+
qt_case_when_nested """
131+
SELECT id,
132+
CASE
133+
WHEN id = 1 THEN
134+
CASE
135+
WHEN col_datev2 IS NOT NULL THEN col_datev2_not_null
136+
ELSE col_datev2_not_null
137+
END
138+
WHEN id = 2 THEN col_datev2_not_null
139+
ELSE col_datev2_not_null
140+
END AS result
141+
FROM test_case_when_date_tbl
142+
ORDER BY id;
143+
"""
144+
}

0 commit comments

Comments
 (0)