Coverage Report

Created: 2026-09-28 17:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/cast/cast_to_timestamptz.h
Line
Count
Source
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
#pragma once
19
20
#include "core/assert_cast.h"
21
#include "core/data_type/data_type_date_or_datetime_v2.h"
22
#include "core/data_type/data_type_timestamp_ns.h"
23
#include "core/data_type/data_type_timestamptz.h"
24
#include "core/data_type/primitive_type.h"
25
#include "core/types.h"
26
#include "core/value/timestamptz_value.h"
27
#include "core/value/vdatetime_value.h"
28
#include "exprs/function/cast/cast_base.h"
29
#include "exprs/function/cast/cast_to_datetimev2_impl.hpp"
30
#include "exprs/function/cast/cast_to_timestamptz_impl.hpp"
31
#include "runtime/runtime_state.h"
32
33
namespace doris {
34
35
template <CastModeType Mode>
36
class CastToImpl<Mode, DataTypeString, DataTypeTimeStampTz> : public CastToBase {
37
public:
38
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
39
                        uint32_t result, size_t input_rows_count,
40
8
                        const NullMap::value_type* null_map = nullptr) const override {
41
8
        const auto& col_from = assert_cast<const DataTypeString::ColumnType&>(
42
8
                *block.get_by_position(arguments[0]).column);
43
44
8
        auto to_type = block.get_by_position(result).type;
45
8
        auto serde = remove_nullable(to_type)->get_serde();
46
8
        MutableColumnPtr column_to;
47
48
8
        DataTypeSerDe::FormatOptions options;
49
8
        options.timezone = &context->state()->timezone_obj();
50
51
8
        if constexpr (Mode == CastModeType::NonStrictMode) {
52
4
            auto to_nullable_type = make_nullable(to_type);
53
4
            column_to = to_nullable_type->create_column();
54
4
            auto& nullable_col_to = assert_cast<ColumnNullable&>(*column_to);
55
4
            RETURN_IF_ERROR(serde->from_string_batch(col_from, nullable_col_to, options));
56
4
        } else if constexpr (Mode == CastModeType::StrictMode) {
57
4
            column_to = to_type->create_column();
58
4
            RETURN_IF_ERROR(
59
4
                    serde->from_string_strict_mode_batch(col_from, *column_to, options, null_map));
60
4
        }
61
62
6
        block.get_by_position(result).column = std::move(column_to);
63
8
        return Status::OK();
64
8
    }
_ZNK5doris10CastToImplILNS_12CastModeTypeE0ENS_14DataTypeStringENS_19DataTypeTimeStampTzEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmPKh
Line
Count
Source
40
4
                        const NullMap::value_type* null_map = nullptr) const override {
41
4
        const auto& col_from = assert_cast<const DataTypeString::ColumnType&>(
42
4
                *block.get_by_position(arguments[0]).column);
43
44
4
        auto to_type = block.get_by_position(result).type;
45
4
        auto serde = remove_nullable(to_type)->get_serde();
46
4
        MutableColumnPtr column_to;
47
48
4
        DataTypeSerDe::FormatOptions options;
49
4
        options.timezone = &context->state()->timezone_obj();
50
51
        if constexpr (Mode == CastModeType::NonStrictMode) {
52
            auto to_nullable_type = make_nullable(to_type);
53
            column_to = to_nullable_type->create_column();
54
            auto& nullable_col_to = assert_cast<ColumnNullable&>(*column_to);
55
            RETURN_IF_ERROR(serde->from_string_batch(col_from, nullable_col_to, options));
56
4
        } else if constexpr (Mode == CastModeType::StrictMode) {
57
4
            column_to = to_type->create_column();
58
4
            RETURN_IF_ERROR(
59
4
                    serde->from_string_strict_mode_batch(col_from, *column_to, options, null_map));
60
4
        }
61
62
2
        block.get_by_position(result).column = std::move(column_to);
63
4
        return Status::OK();
64
4
    }
_ZNK5doris10CastToImplILNS_12CastModeTypeE1ENS_14DataTypeStringENS_19DataTypeTimeStampTzEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmPKh
Line
Count
Source
40
4
                        const NullMap::value_type* null_map = nullptr) const override {
41
4
        const auto& col_from = assert_cast<const DataTypeString::ColumnType&>(
42
4
                *block.get_by_position(arguments[0]).column);
43
44
4
        auto to_type = block.get_by_position(result).type;
45
4
        auto serde = remove_nullable(to_type)->get_serde();
46
4
        MutableColumnPtr column_to;
47
48
4
        DataTypeSerDe::FormatOptions options;
49
4
        options.timezone = &context->state()->timezone_obj();
50
51
4
        if constexpr (Mode == CastModeType::NonStrictMode) {
52
4
            auto to_nullable_type = make_nullable(to_type);
53
4
            column_to = to_nullable_type->create_column();
54
4
            auto& nullable_col_to = assert_cast<ColumnNullable&>(*column_to);
55
4
            RETURN_IF_ERROR(serde->from_string_batch(col_from, nullable_col_to, options));
56
        } else if constexpr (Mode == CastModeType::StrictMode) {
57
            column_to = to_type->create_column();
58
            RETURN_IF_ERROR(
59
                    serde->from_string_strict_mode_batch(col_from, *column_to, options, null_map));
60
        }
61
62
4
        block.get_by_position(result).column = std::move(column_to);
63
4
        return Status::OK();
64
4
    }
65
};
66
67
template <>
68
class CastToImpl<CastModeType::StrictMode, DataTypeDateTimeV2, DataTypeTimeStampTz>
69
        : public CastToBase {
70
public:
71
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
72
                        uint32_t result, size_t input_rows_count,
73
12
                        const NullMap::value_type* null_map = nullptr) const override {
74
12
        const auto& col_from =
75
12
                assert_cast<const ColumnDateTimeV2&>(*block.get_by_position(arguments[0]).column)
76
12
                        .get_data();
77
78
12
        auto col_to = ColumnTimeStampTz::create(input_rows_count);
79
12
        auto& col_to_data = col_to->get_data();
80
12
        const auto& local_time_zone = context->state()->timezone_obj();
81
82
12
        const auto dt_scale = block.get_by_position(arguments[0]).type->get_scale();
83
12
        const auto tz_scale = block.get_by_position(result).type->get_scale();
84
85
26
        for (int i = 0; i < input_rows_count; ++i) {
86
20
            if (null_map && null_map[i]) {
87
2
                continue;
88
2
            }
89
90
18
            DateV2Value<DateTimeV2ValueType> from_dt {col_from[i]};
91
18
            TimestampTzValue tz_value;
92
93
18
            if (!tz_value.from_datetime(from_dt, local_time_zone, dt_scale, tz_scale)) {
94
6
                return Status::InvalidArgument(
95
6
                        "can not cast from  datetime : {} to timestamptz in timezone : {}",
96
6
                        from_dt.to_string(), context->state()->timezone());
97
6
            }
98
99
12
            col_to_data[i] = tz_value;
100
12
        }
101
6
        block.get_by_position(result).column = std::move(col_to);
102
6
        return Status::OK();
103
12
    }
104
};
105
106
template <>
107
class CastToImpl<CastModeType::NonStrictMode, DataTypeDateTimeV2, DataTypeTimeStampTz>
108
        : public CastToBase {
109
public:
110
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
111
                        uint32_t result, size_t input_rows_count,
112
6
                        const NullMap::value_type*) const override {
113
6
        const auto& col_from =
114
6
                assert_cast<const ColumnDateTimeV2&>(*block.get_by_position(arguments[0]).column)
115
6
                        .get_data();
116
117
6
        auto col_to = ColumnTimeStampTz::create(input_rows_count);
118
6
        auto& col_to_data = col_to->get_data();
119
6
        auto col_null = ColumnBool::create(input_rows_count, 0);
120
6
        auto& col_null_map = col_null->get_data();
121
6
        const auto& local_time_zone = context->state()->timezone_obj();
122
123
6
        const auto dt_scale = block.get_by_position(arguments[0]).type->get_scale();
124
6
        const auto tz_scale = block.get_by_position(result).type->get_scale();
125
126
28
        for (int i = 0; i < input_rows_count; ++i) {
127
22
            DateV2Value<DateTimeV2ValueType> from_dt {col_from[i]};
128
22
            TimestampTzValue tz_value {};
129
130
22
            if (tz_value.from_datetime(from_dt, local_time_zone, dt_scale, tz_scale)) {
131
18
                col_to_data[i] = tz_value;
132
18
            } else {
133
4
                col_null_map[i] = true;
134
4
            }
135
22
        }
136
137
6
        block.get_by_position(result).column =
138
6
                ColumnNullable::create(std::move(col_to), std::move(col_null));
139
6
        return Status::OK();
140
6
    }
141
};
142
143
template <CastModeType CastMode>
144
class CastToImpl<CastMode, DataTypeTimeStampNs, DataTypeTimeStampTz> : public CastToBase {
145
public:
146
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
147
                        uint32_t result, size_t input_rows_count,
148
2
                        const NullMap::value_type* null_map = nullptr) const override {
149
2
        const auto& col_from =
150
2
                assert_cast<const ColumnTimeStampNs&>(*block.get_by_position(arguments[0]).column)
151
2
                        .get_data();
152
2
        auto col_to = ColumnTimeStampTz::create(input_rows_count);
153
2
        auto col_null = ColumnBool::create(input_rows_count, 0);
154
2
        const auto& local_time_zone = context->state()->timezone_obj();
155
2
        const auto target_scale = block.get_by_position(result).type->get_scale();
156
157
12
        for (size_t i = 0; i < input_rows_count; ++i) {
158
10
            if (null_map && null_map[i]) {
159
0
                continue;
160
0
            }
161
10
            DateV2Value<DateTimeV2ValueType> rounded_datetime;
162
10
            TimestampTzValue target;
163
10
            const bool converted =
164
10
                    transform_date_scale(target_scale, TimeStampNsValue::FRACTIONAL_DIGITS,
165
10
                                         rounded_datetime, col_from[i]) &&
166
10
                    target.from_datetime(rounded_datetime, local_time_zone, target_scale,
167
10
                                         target_scale);
168
10
            if (!converted) {
169
0
                if constexpr (CastMode == CastModeType::StrictMode) {
170
0
                    return Status::InvalidArgument(
171
0
                            "can not cast TIMESTAMP_NS {} to timestamptz in timezone {}",
172
0
                            col_from[i].to_string(), context->state()->timezone());
173
0
                }
174
0
                col_null->get_data()[i] = true;
175
0
                continue;
176
0
            }
177
10
            col_to->get_data()[i] = target;
178
10
        }
179
180
2
        if constexpr (CastMode == CastModeType::StrictMode) {
181
0
            block.get_by_position(result).column = std::move(col_to);
182
2
        } else {
183
2
            block.get_by_position(result).column =
184
2
                    ColumnNullable::create(std::move(col_to), std::move(col_null));
185
2
        }
186
2
        return Status::OK();
187
2
    }
Unexecuted instantiation: _ZNK5doris10CastToImplILNS_12CastModeTypeE0ENS_19DataTypeTimeStampNsENS_19DataTypeTimeStampTzEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmPKh
_ZNK5doris10CastToImplILNS_12CastModeTypeE1ENS_19DataTypeTimeStampNsENS_19DataTypeTimeStampTzEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmPKh
Line
Count
Source
148
2
                        const NullMap::value_type* null_map = nullptr) const override {
149
2
        const auto& col_from =
150
2
                assert_cast<const ColumnTimeStampNs&>(*block.get_by_position(arguments[0]).column)
151
2
                        .get_data();
152
2
        auto col_to = ColumnTimeStampTz::create(input_rows_count);
153
2
        auto col_null = ColumnBool::create(input_rows_count, 0);
154
2
        const auto& local_time_zone = context->state()->timezone_obj();
155
2
        const auto target_scale = block.get_by_position(result).type->get_scale();
156
157
12
        for (size_t i = 0; i < input_rows_count; ++i) {
158
10
            if (null_map && null_map[i]) {
159
0
                continue;
160
0
            }
161
10
            DateV2Value<DateTimeV2ValueType> rounded_datetime;
162
10
            TimestampTzValue target;
163
10
            const bool converted =
164
10
                    transform_date_scale(target_scale, TimeStampNsValue::FRACTIONAL_DIGITS,
165
10
                                         rounded_datetime, col_from[i]) &&
166
10
                    target.from_datetime(rounded_datetime, local_time_zone, target_scale,
167
10
                                         target_scale);
168
10
            if (!converted) {
169
                if constexpr (CastMode == CastModeType::StrictMode) {
170
                    return Status::InvalidArgument(
171
                            "can not cast TIMESTAMP_NS {} to timestamptz in timezone {}",
172
                            col_from[i].to_string(), context->state()->timezone());
173
                }
174
0
                col_null->get_data()[i] = true;
175
0
                continue;
176
0
            }
177
10
            col_to->get_data()[i] = target;
178
10
        }
179
180
        if constexpr (CastMode == CastModeType::StrictMode) {
181
            block.get_by_position(result).column = std::move(col_to);
182
2
        } else {
183
2
            block.get_by_position(result).column =
184
2
                    ColumnNullable::create(std::move(col_to), std::move(col_null));
185
2
        }
186
2
        return Status::OK();
187
2
    }
188
};
189
190
template <>
191
class CastToImpl<CastModeType::StrictMode, DataTypeTimeStampTz, DataTypeTimeStampTz>
192
        : public CastToBase {
193
public:
194
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
195
                        uint32_t result, size_t input_rows_count,
196
10
                        const NullMap::value_type* null_map = nullptr) const override {
197
10
        const auto& col_from =
198
10
                assert_cast<const ColumnTimeStampTz&>(*block.get_by_position(arguments[0]).column)
199
10
                        .get_data();
200
201
10
        auto col_to = ColumnTimeStampTz::create(input_rows_count);
202
10
        auto& col_to_data = col_to->get_data();
203
204
10
        const auto from_scale = block.get_by_position(arguments[0]).type->get_scale();
205
10
        const auto to_scale = block.get_by_position(result).type->get_scale();
206
207
16
        for (int i = 0; i < input_rows_count; ++i) {
208
12
            if (null_map && null_map[i]) {
209
2
                continue;
210
2
            }
211
212
10
            const auto& from_tz = col_from[i];
213
10
            auto& to_tz = col_to_data[i];
214
215
10
            if (!transform_date_scale(to_scale, from_scale, to_tz, from_tz)) {
216
                // Error reporting must not format an overflowing timestamp in a session
217
                // timezone whose local year may itself be outside the supported range.
218
6
                return Status::InvalidArgument(
219
6
                        "can not cast from  timestamptz : {} UTC to timestamptz in timezone : {}",
220
6
                        from_tz.utc_dt().to_string(from_scale), context->state()->timezone());
221
6
            }
222
10
        }
223
4
        block.get_by_position(result).column = std::move(col_to);
224
4
        return Status::OK();
225
10
    }
226
};
227
228
template <>
229
class CastToImpl<CastModeType::NonStrictMode, DataTypeTimeStampTz, DataTypeTimeStampTz>
230
        : public CastToBase {
231
public:
232
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
233
                        uint32_t result, size_t input_rows_count,
234
4
                        const NullMap::value_type*) const override {
235
4
        const auto& col_from =
236
4
                assert_cast<const ColumnTimeStampTz&>(*block.get_by_position(arguments[0]).column)
237
4
                        .get_data();
238
239
4
        auto col_to = ColumnTimeStampTz::create(input_rows_count);
240
4
        auto& col_to_data = col_to->get_data();
241
4
        auto col_null = ColumnBool::create(input_rows_count, 0);
242
4
        auto& col_null_map = col_null->get_data();
243
244
4
        const auto from_scale = block.get_by_position(arguments[0]).type->get_scale();
245
4
        const auto to_scale = block.get_by_position(result).type->get_scale();
246
247
12
        for (int i = 0; i < input_rows_count; ++i) {
248
8
            const auto& from_tz = col_from[i];
249
8
            auto& to_tz = col_to_data[i];
250
251
8
            if (!transform_date_scale(to_scale, from_scale, to_tz, from_tz)) {
252
4
                col_null_map[i] = true;
253
4
                to_tz = TimestampTzValue(MIN_DATETIME_V2);
254
4
            }
255
8
        }
256
257
4
        block.get_by_position(result).column =
258
4
                ColumnNullable::create(std::move(col_to), std::move(col_null));
259
4
        return Status::OK();
260
4
    }
261
};
262
263
} // namespace doris