blob: 8dd8b60b11b0f4852282695e4a2cbfc14fe970b1 [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.
**/
#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