]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/cpp/src/gandiva/to_date_holder.cc
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / gandiva / to_date_holder.cc
CommitLineData
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
29namespace gandiva {
30
31Status 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
72Status 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
82int64_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
105void 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