]>
Commit | Line | Data |
---|---|---|
1d09f67e TL |
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 | #include "gandiva/to_date_holder.h" | |
19 | ||
20 | #include <algorithm> | |
21 | #include <string> | |
22 | ||
23 | #include "arrow/util/value_parsing.h" | |
24 | #include "arrow/vendored/datetime.h" | |
25 | #include "gandiva/date_utils.h" | |
26 | #include "gandiva/execution_context.h" | |
27 | #include "gandiva/node.h" | |
28 | ||
29 | namespace gandiva { | |
30 | ||
31 | Status ToDateHolder::Make(const FunctionNode& node, | |
32 | std::shared_ptr<ToDateHolder>* holder) { | |
33 | if (node.children().size() != 2 && node.children().size() != 3) { | |
34 | return Status::Invalid("'to_date' function requires two or three parameters"); | |
35 | } | |
36 | ||
37 | auto literal_pattern = dynamic_cast<LiteralNode*>(node.children().at(1).get()); | |
38 | if (literal_pattern == nullptr) { | |
39 | return Status::Invalid( | |
40 | "'to_date' function requires a literal as the second parameter"); | |
41 | } | |
42 | ||
43 | auto literal_type = literal_pattern->return_type()->id(); | |
44 | if (literal_type != arrow::Type::STRING && literal_type != arrow::Type::BINARY) { | |
45 | return Status::Invalid( | |
46 | "'to_date' function requires a string literal as the second parameter"); | |
47 | } | |
48 | auto pattern = arrow::util::get<std::string>(literal_pattern->holder()); | |
49 | ||
50 | int suppress_errors = 0; | |
51 | if (node.children().size() == 3) { | |
52 | auto literal_suppress_errors = | |
53 | dynamic_cast<LiteralNode*>(node.children().at(2).get()); | |
54 | if (literal_pattern == nullptr) { | |
55 | return Status::Invalid( | |
56 | "The (optional) third parameter to 'to_date' function needs to an integer " | |
57 | "literal to indicate whether to suppress the error"); | |
58 | } | |
59 | ||
60 | literal_type = literal_suppress_errors->return_type()->id(); | |
61 | if (literal_type != arrow::Type::INT32) { | |
62 | return Status::Invalid( | |
63 | "The (optional) third parameter to 'to_date' function needs to an integer " | |
64 | "literal to indicate whether to suppress the error"); | |
65 | } | |
66 | suppress_errors = arrow::util::get<int>(literal_suppress_errors->holder()); | |
67 | } | |
68 | ||
69 | return Make(pattern, suppress_errors, holder); | |
70 | } | |
71 | ||
72 | Status ToDateHolder::Make(const std::string& sql_pattern, int32_t suppress_errors, | |
73 | std::shared_ptr<ToDateHolder>* holder) { | |
74 | std::shared_ptr<std::string> transformed_pattern; | |
75 | ARROW_RETURN_NOT_OK(DateUtils::ToInternalFormat(sql_pattern, &transformed_pattern)); | |
76 | auto lholder = std::shared_ptr<ToDateHolder>( | |
77 | new ToDateHolder(*(transformed_pattern.get()), suppress_errors)); | |
78 | *holder = lholder; | |
79 | return Status::OK(); | |
80 | } | |
81 | ||
82 | int64_t ToDateHolder::operator()(ExecutionContext* context, const char* data, | |
83 | int data_len, bool in_valid, bool* out_valid) { | |
84 | *out_valid = false; | |
85 | if (!in_valid) { | |
86 | return 0; | |
87 | } | |
88 | ||
89 | // Issues | |
90 | // 1. processes date that do not match the format. | |
91 | // 2. does not process time in format +08:00 (or) id. | |
92 | int64_t seconds_since_epoch = 0; | |
93 | if (!::arrow::internal::ParseTimestampStrptime( | |
94 | data, data_len, pattern_.c_str(), | |
95 | /*ignore_time_in_day=*/true, /*allow_trailing_chars=*/true, | |
96 | ::arrow::TimeUnit::SECOND, &seconds_since_epoch)) { | |
97 | return_error(context, data, data_len); | |
98 | return 0; | |
99 | } | |
100 | ||
101 | *out_valid = true; | |
102 | return seconds_since_epoch * 1000; | |
103 | } | |
104 | ||
105 | void ToDateHolder::return_error(ExecutionContext* context, const char* data, | |
106 | int data_len) { | |
107 | if (suppress_errors_ == 1) { | |
108 | return; | |
109 | } | |
110 | ||
111 | std::string err_msg = | |
112 | "Error parsing value " + std::string(data, data_len) + " for given format."; | |
113 | context->set_error_msg(err_msg.c_str()); | |
114 | } | |
115 | ||
116 | } // namespace gandiva |