blob: d4753ab75260c98ffd40d0a2565bf542d8d73a26 [file] [log] [blame]
/**
* 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