Skip to content

Commit 294396e

Browse files
authored
fix(query): domain calc for int64 to timestamp is incorrect (#18597)
If timestamp is not in a valid socpe will cast it into timestamp::MIN or timestamp::MIN
1 parent 1584469 commit 294396e

File tree

3 files changed

+46
-6
lines changed

3 files changed

+46
-6
lines changed

src/query/functions/src/scalars/timestamp/src/datetime.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,27 +141,40 @@ pub fn int64_to_timestamp(mut n: i64) -> i64 {
141141
}
142142
}
143143

144+
/// calc int64 domain to timestamp domain
144145
#[inline]
145-
pub fn int32_to_timestamp(n: i32) -> i64 {
146+
pub fn calc_int64_to_timestamp_domain(n: i64) -> i64 {
147+
if -31536000000 < n && n < 31536000000 {
148+
n * MICROS_PER_SEC
149+
} else if -31536000000000 < n && n < 31536000000000 {
150+
n * MICROS_PER_MILLI
151+
} else {
152+
n.clamp(TIMESTAMP_MIN, TIMESTAMP_MAX)
153+
}
154+
}
155+
156+
/// calc int32 domain to timestamp domain
157+
#[inline]
158+
pub fn calc_int32_to_timestamp_domain(n: i32) -> i64 {
146159
let n = n as i64 * 24 * 3600 * MICROS_PER_SEC;
147-
int64_to_timestamp(n)
160+
calc_int64_to_timestamp_domain(n)
148161
}
149162

150163
fn int32_domain_to_timestamp_domain<T: AsPrimitive<i32>>(
151164
domain: &SimpleDomain<T>,
152165
) -> Option<SimpleDomain<i64>> {
153166
Some(SimpleDomain {
154-
min: int32_to_timestamp(domain.min.as_()),
155-
max: int32_to_timestamp(domain.max.as_()),
167+
min: calc_int32_to_timestamp_domain(domain.min.as_()),
168+
max: calc_int32_to_timestamp_domain(domain.max.as_()),
156169
})
157170
}
158171

159172
fn int64_domain_to_timestamp_domain<T: AsPrimitive<i64>>(
160173
domain: &SimpleDomain<T>,
161174
) -> Option<SimpleDomain<i64>> {
162175
Some(SimpleDomain {
163-
min: int64_to_timestamp(domain.min.as_()),
164-
max: int64_to_timestamp(domain.max.as_()),
176+
min: calc_int64_to_timestamp_domain(domain.min.as_()),
177+
max: calc_int64_to_timestamp_domain(domain.max.as_()),
165178
})
166179
}
167180

src/query/functions/tests/it/scalars/datetime.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ fn test_to_timestamp(file: &mut impl Write) {
6464
]),
6565
)]);
6666

67+
run_ast(file, "to_timestamp(a) > '2020-01-01'", &[(
68+
"a",
69+
Int64Type::from_data(vec![i64::MIN, i64::MAX]),
70+
)]);
71+
6772
run_ast(file, "to_timestamp(b)", &[(
6873
"b",
6974
StringType::from_data(vec!["2020-01-01", "2020-01-02", "2020-01-03", "2029-01-01"]),

src/query/functions/tests/it/scalars/testdata/datetime.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,28 @@ evaluation (internal):
132132
+--------+------------------------------------------------------------------------------------------------------------+
133133

134134

135+
ast : to_timestamp(a) > '2020-01-01'
136+
raw expr : gt(to_timestamp(a::Int64), '2020-01-01')
137+
checked expr : gt<Timestamp, Timestamp>(CAST<Int64>(a AS Timestamp), CAST<String>("2020-01-01" AS Timestamp))
138+
optimized expr : gt<Timestamp, Timestamp>(CAST<Int64>(a AS Timestamp), 1577836800000000)
139+
evaluation:
140+
+--------+----------------------------------------------+---------------+
141+
| | a | Output |
142+
+--------+----------------------------------------------+---------------+
143+
| Type | Int64 | Boolean |
144+
| Domain | {-9223372036854775808..=9223372036854775807} | {FALSE, TRUE} |
145+
| Row 0 | -9223372036854775808 | false |
146+
| Row 1 | 9223372036854775807 | false |
147+
+--------+----------------------------------------------+---------------+
148+
evaluation (internal):
149+
+--------+----------------------------------------------------+
150+
| Column | Data |
151+
+--------+----------------------------------------------------+
152+
| a | Int64([-9223372036854775808, 9223372036854775807]) |
153+
| Output | Boolean([0b______00]) |
154+
+--------+----------------------------------------------------+
155+
156+
135157
ast : to_timestamp(b)
136158
raw expr : to_timestamp(b::String)
137159
checked expr : CAST<String>(b AS Timestamp)

0 commit comments

Comments
 (0)