| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| **/ |
| |
| #ifndef __STDC_FORMAT_MACROS |
| #define __STDC_FORMAT_MACROS |
| #endif |
| |
| #include "parser/ParseLiteralValue.hpp" |
| |
| #include <cinttypes> |
| #include <cstdint> |
| #include <cstdio> |
| #include <limits> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "types/DatetimeIntervalType.hpp" |
| #include "types/DoubleType.hpp" |
| #include "types/IntType.hpp" |
| #include "types/LongType.hpp" |
| #include "types/NullType.hpp" |
| #include "types/Type.hpp" |
| #include "types/VarCharType.hpp" |
| #include "types/YearMonthIntervalType.hpp" |
| #include "utility/SqlError.hpp" |
| |
| #include "glog/logging.h" |
| |
| namespace quickstep { |
| |
| TypedValue NullParseLiteralValue::concretize( |
| const Type *type_hint, |
| const Type **concretized_type) const { |
| if (type_hint == nullptr) { |
| *concretized_type = &NullType::InstanceNullable(); |
| } else { |
| *concretized_type = &(type_hint->getNullableVersion()); |
| } |
| return (*concretized_type)->makeNullValue(); |
| } |
| |
| NumericParseLiteralValue::NumericParseLiteralValue(const int line_number, |
| const int column_number, |
| const char *numstring) |
| : ParseLiteralValue(line_number, column_number), |
| numeric_string_(numstring) { |
| float_like_ = (numeric_string_.find('.') != std::string::npos) |
| || (numeric_string_.find('e') != std::string::npos) |
| || (numeric_string_.find('E') != std::string::npos); |
| |
| if (!float_like_) { |
| CHECK_EQ(1, std::sscanf(numeric_string_.c_str(), "%" SCNd64, &long_value_)) |
| << "Failed to parse int64_t from numeric string \"" |
| << numeric_string_ << "\n"; |
| } |
| } |
| |
| void NumericParseLiteralValue::prependMinus() { |
| std::string minused("-"); |
| minused.append(numeric_string_); |
| numeric_string_ = std::move(minused); |
| |
| if (!float_like_) { |
| long_value_ = -long_value_; |
| } |
| } |
| |
| TypedValue NumericParseLiteralValue::concretize( |
| const Type *type_hint, |
| const Type **concretized_type) const { |
| TypedValue parsed_value; |
| if ((type_hint != nullptr) |
| && (type_hint->getSuperTypeID() == Type::kNumeric) |
| && (type_hint->parseValueFromString(numeric_string_, &parsed_value))) { |
| *concretized_type = &(type_hint->getNonNullableVersion()); |
| return parsed_value; |
| } |
| |
| if (float_like_) { |
| *concretized_type = &DoubleType::InstanceNonNullable(); |
| CHECK((*concretized_type)->parseValueFromString(numeric_string_, &parsed_value)) |
| << "Failed to parse double from numeric string \"" |
| << numeric_string_ << "\""; |
| return parsed_value; |
| } else { |
| if ((long_value_ >= std::numeric_limits<int>::min()) |
| && (long_value_ <= std::numeric_limits<int>::max())) { |
| *concretized_type = &IntType::InstanceNonNullable(); |
| return TypedValue(static_cast<int>(long_value_)); |
| } else { |
| *concretized_type = &LongType::InstanceNonNullable(); |
| return TypedValue(long_value_); |
| } |
| } |
| } |
| |
| void NumericParseLiteralValue::getFieldStringItems( |
| std::vector<std::string> *inline_field_names, |
| std::vector<std::string> *inline_field_values, |
| std::vector<std::string> *non_container_child_field_names, |
| std::vector<const ParseTreeNode*> *non_container_child_fields, |
| std::vector<std::string> *container_child_field_names, |
| std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const { |
| inline_field_names->push_back("numeric_string"); |
| inline_field_values->push_back(numeric_string_); |
| |
| inline_field_names->push_back("float_like"); |
| inline_field_values->push_back(float_like_ ? "true" : "false"); |
| } |
| |
| bool StringParseLiteralValue::ParseAmbiguousInterval( |
| ParseString *value, |
| StringParseLiteralValue **output) { |
| *output = new StringParseLiteralValue(value, |
| nullptr); // Initially no explicit type. |
| |
| // Try parsing as DatetimeInterval. |
| (*output)->explicit_type_ = &DatetimeIntervalType::InstanceNonNullable(); |
| if ((*output)->tryExplicitTypeParse()) { |
| return true; |
| } |
| |
| // Try parsing as YearMonthInterval. |
| (*output)->explicit_type_ = &YearMonthIntervalType::InstanceNonNullable(); |
| if ((*output)->tryExplicitTypeParse()) { |
| return true; |
| } |
| |
| delete *output; |
| *output = nullptr; |
| return false; |
| } |
| |
| TypedValue StringParseLiteralValue::concretize(const Type *type_hint, |
| const Type **concretized_type) const { |
| if (explicit_type_ != nullptr) { |
| if ((type_hint != nullptr) && (type_hint->isSafelyCoercibleFrom(*explicit_type_))) { |
| *concretized_type = type_hint; |
| return type_hint->coerceValue(explicit_parsed_value_, *explicit_type_); |
| } else { |
| *concretized_type = explicit_type_; |
| return explicit_parsed_value_; |
| } |
| } else { |
| TypedValue parsed_value; |
| if ((type_hint != nullptr) |
| && (type_hint->parseValueFromString(value_->value(), &parsed_value))) { |
| *concretized_type = &(type_hint->getNonNullableVersion()); |
| return parsed_value; |
| } else { |
| *concretized_type = &VarCharType::InstanceNonNullable(value_->value().length()); |
| CHECK((*concretized_type)->parseValueFromString(value_->value(), &parsed_value)); |
| return parsed_value; |
| } |
| } |
| } |
| |
| std::string StringParseLiteralValue::generateName() const { |
| std::string name; |
| if (explicit_type_ != nullptr) { |
| name.append(explicit_type_->getName()); |
| name.push_back('('); |
| } |
| name.push_back('\''); |
| name.append(value_->value()); |
| name.push_back('\''); |
| if (explicit_type_ != nullptr) { |
| name.push_back(')'); |
| } |
| return name; |
| } |
| |
| bool StringParseLiteralValue::tryExplicitTypeParse() { |
| DCHECK(explicit_type_ != nullptr); |
| return explicit_type_->parseValueFromString(value_->value(), &explicit_parsed_value_); |
| } |
| |
| void StringParseLiteralValue::getFieldStringItems( |
| std::vector<std::string> *inline_field_names, |
| std::vector<std::string> *inline_field_values, |
| std::vector<std::string> *non_container_child_field_names, |
| std::vector<const ParseTreeNode*> *non_container_child_fields, |
| std::vector<std::string> *container_child_field_names, |
| std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const { |
| inline_field_names->push_back("value"); |
| inline_field_values->push_back(value_->value()); |
| |
| if (explicit_type_ != nullptr) { |
| inline_field_names->push_back("explicit_type"); |
| inline_field_values->push_back(explicit_type_->getName()); |
| } |
| } |
| |
| } // namespace quickstep |