| /** |
| * 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. |
| **/ |
| |
| #include "types/TypedValue.hpp" |
| |
| #include <cstddef> |
| #include <cstring> |
| |
| #include "types/DatetimeLit.hpp" |
| #include "types/IntervalLit.hpp" |
| #include "types/Type.pb.h" |
| #include "types/TypeID.hpp" |
| #include "types/TypedValue.pb.h" |
| #include "utility/Macros.hpp" |
| |
| #include "glog/logging.h" |
| |
| using std::memchr; |
| using std::size_t; |
| |
| namespace quickstep { |
| |
| bool TypedValue::isPlausibleInstanceOf(const TypeSignature type) const { |
| TypeID type_id = getTypeID(); |
| if (type_id != type.id) { |
| return false; |
| } |
| |
| if (isNull()) { |
| return type.nullable; |
| } |
| |
| switch (type_id) { |
| case kInt: |
| case kLong: |
| case kFloat: |
| case kDouble: |
| case kDate: |
| case kDatetime: |
| case kDatetimeInterval: |
| case kYearMonthInterval: |
| return true; |
| case kChar: { |
| size_t data_size = getDataSize(); |
| if (data_size == type.length) { |
| return true; |
| } else if (data_size < type.length) { |
| // If the data is shorter than the max size for a CHAR type, make sure |
| // it is null-terminated. |
| return (memchr(value_union_.out_of_line_data, '\0', data_size) != nullptr); |
| } else { |
| return false; |
| } |
| } |
| case kVarChar: |
| return getDataSize() <= (type.length + 1); |
| default: { |
| size_t data_size = getDataSize(); |
| return (data_size <= type.length); |
| } |
| } |
| } |
| |
| serialization::TypedValue TypedValue::getProto() const { |
| serialization::TypedValue proto; |
| |
| // NOTE(chasseur): To represent a NULL value, only the 'type_id' field of the |
| // proto is filled in, and all the optional value fields are omitted. |
| switch (getTypeID()) { |
| case kInt: |
| proto.set_type_id(serialization::Type::INT); |
| if (!isNull()) { |
| proto.set_int_value(getLiteral<int>()); |
| } |
| break; |
| case kLong: |
| proto.set_type_id(serialization::Type::LONG); |
| if (!isNull()) { |
| proto.set_long_value(getLiteral<std::int64_t>()); |
| } |
| break; |
| case kFloat: |
| proto.set_type_id(serialization::Type::FLOAT); |
| if (!isNull()) { |
| proto.set_float_value(getLiteral<float>()); |
| } |
| break; |
| case kDouble: |
| proto.set_type_id(serialization::Type::DOUBLE); |
| if (!isNull()) { |
| proto.set_double_value(getLiteral<double>()); |
| } |
| break; |
| case kDate: |
| proto.set_type_id(serialization::Type::DATE); |
| if (!isNull()) { |
| serialization::TypedValue::DateLit *literal_date_proto = proto.mutable_date_value(); |
| literal_date_proto->set_year(value_union_.date_value.year); |
| literal_date_proto->set_month(value_union_.date_value.month); |
| literal_date_proto->set_day(value_union_.date_value.day); |
| } |
| break; |
| case kDatetime: |
| proto.set_type_id(serialization::Type::DATETIME); |
| if (!isNull()) { |
| proto.set_datetime_value(value_union_.datetime_value.ticks); |
| } |
| break; |
| case kDatetimeInterval: |
| proto.set_type_id(serialization::Type::DATETIME_INTERVAL); |
| if (!isNull()) { |
| proto.set_datetime_interval_value(value_union_.datetime_interval_value.interval_ticks); |
| } |
| break; |
| case kYearMonthInterval: |
| proto.set_type_id(serialization::Type::YEAR_MONTH_INTERVAL); |
| if (!isNull()) { |
| proto.set_year_month_interval_value(value_union_.year_month_interval_value.months); |
| } |
| break; |
| case kChar: |
| proto.set_type_id(serialization::Type::CHAR); |
| if (!isNull()) { |
| proto.set_out_of_line_data(static_cast<const char*>(getOutOfLineData()), getDataSize()); |
| } |
| break; |
| case kVarChar: |
| proto.set_type_id(serialization::Type::VAR_CHAR); |
| if (!isNull()) { |
| proto.set_out_of_line_data(static_cast<const char*>(getOutOfLineData()), getDataSize()); |
| } |
| break; |
| case kNullType: |
| proto.set_type_id(serialization::Type::NULL_TYPE); |
| DCHECK(isNull()); |
| break; |
| default: |
| FATAL_ERROR("Unrecognized TypeID in TypedValue::getProto"); |
| } |
| |
| return proto; |
| } |
| |
| bool TypedValue::ProtoIsValid(const serialization::TypedValue &proto) { |
| return proto.IsInitialized(); |
| } |
| |
| TypedValue TypedValue::ReconstructFromProto(const serialization::TypedValue &proto) { |
| DCHECK(ProtoIsValid(proto)) |
| << "Attempted to create TypedValue from an invalid proto description:\n" |
| << proto.DebugString(); |
| |
| switch (proto.type_id()) { |
| case serialization::Type::INT: |
| return proto.has_int_value() ? |
| TypedValue(static_cast<int>(proto.int_value())) : |
| TypedValue(kInt); |
| case serialization::Type::LONG: |
| return proto.has_long_value() ? |
| TypedValue(static_cast<std::int64_t>(proto.long_value())) : |
| TypedValue(kLong); |
| case serialization::Type::FLOAT: |
| return proto.has_float_value() ? |
| TypedValue(static_cast<float>(proto.float_value())) : |
| TypedValue(kFloat); |
| case serialization::Type::DOUBLE: |
| return proto.has_double_value() ? |
| TypedValue(static_cast<double>(proto.double_value())) : |
| TypedValue(kDouble); |
| case serialization::Type::DATE: |
| if (proto.has_date_value()) { |
| return TypedValue(DateLit::Create(proto.date_value().year(), |
| proto.date_value().month(), |
| proto.date_value().day())); |
| } else { |
| return TypedValue(kDate); |
| } |
| case serialization::Type::DATETIME: |
| if (proto.has_datetime_value()) { |
| DatetimeLit datetime; |
| datetime.ticks = proto.datetime_value(); |
| return TypedValue(datetime); |
| } else { |
| return TypedValue(kDatetime); |
| } |
| case serialization::Type::DATETIME_INTERVAL: |
| if (proto.has_datetime_interval_value()) { |
| DatetimeIntervalLit interval; |
| interval.interval_ticks = proto.datetime_interval_value(); |
| return TypedValue(interval); |
| } else { |
| return TypedValue(kDatetimeInterval); |
| } |
| case serialization::Type::YEAR_MONTH_INTERVAL: |
| if (proto.has_year_month_interval_value()) { |
| YearMonthIntervalLit interval; |
| interval.months = proto.year_month_interval_value(); |
| return TypedValue(interval); |
| } else { |
| return TypedValue(kYearMonthInterval); |
| } |
| case serialization::Type::CHAR: |
| return proto.has_out_of_line_data() ? |
| TypedValue(kChar, |
| static_cast<const void*>(proto.out_of_line_data().c_str()), |
| proto.out_of_line_data().size()).ensureNotReference() : |
| TypedValue(kChar); |
| case serialization::Type::VAR_CHAR: |
| return proto.has_out_of_line_data() ? |
| TypedValue(kVarChar, |
| static_cast<const void*>(proto.out_of_line_data().c_str()), |
| proto.out_of_line_data().size()).ensureNotReference() : |
| TypedValue(kVarChar); |
| case serialization::Type::NULL_TYPE: |
| return TypedValue(kNullType); |
| default: |
| FATAL_ERROR("Unrecognized TypeID in TypedValue::ReconstructFromProto"); |
| } |
| } |
| |
| } // namespace quickstep |