blob: f36db7943729b59686ee3ae16a9b51ad6acef7a5 [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 "orc/sargs/Literal.hh"
#include <cmath>
#include <functional>
#include <limits>
#include <sstream>
namespace orc {
Literal::Literal(PredicateDataType type) {
type_ = type;
value_.DecimalVal = 0;
size_ = 0;
isNull_ = true;
precision_ = 0;
scale_ = 0;
hashCode_ = 0;
}
Literal::Literal(int64_t val) {
type_ = PredicateDataType::LONG;
value_.IntVal = val;
size_ = sizeof(val);
isNull_ = false;
precision_ = 0;
scale_ = 0;
hashCode_ = hashCode();
}
Literal::Literal(double val) {
type_ = PredicateDataType::FLOAT;
value_.DoubleVal = val;
size_ = sizeof(val);
isNull_ = false;
precision_ = 0;
scale_ = 0;
hashCode_ = hashCode();
}
Literal::Literal(bool val) {
type_ = PredicateDataType::BOOLEAN;
value_.BooleanVal = val;
size_ = sizeof(val);
isNull_ = false;
precision_ = 0;
scale_ = 0;
hashCode_ = hashCode();
}
Literal::Literal(PredicateDataType type, int64_t val) {
if (type != PredicateDataType::DATE) {
throw std::invalid_argument("only DATE is supported here!");
}
type_ = type;
value_.IntVal = val;
size_ = sizeof(val);
isNull_ = false;
precision_ = 0;
scale_ = 0;
hashCode_ = hashCode();
}
Literal::Literal(const char* str, size_t size) {
type_ = PredicateDataType::STRING;
value_.Buffer = new char[size];
memcpy(value_.Buffer, str, size);
size_ = size;
isNull_ = false;
precision_ = 0;
scale_ = 0;
hashCode_ = hashCode();
}
Literal::Literal(Int128 val, int32_t precision, int32_t scale) {
type_ = PredicateDataType::DECIMAL;
value_.DecimalVal = val;
precision_ = precision;
scale_ = scale;
size_ = sizeof(Int128);
isNull_ = false;
hashCode_ = hashCode();
}
Literal::Literal(int64_t second, int32_t nanos) {
type_ = PredicateDataType::TIMESTAMP;
value_.TimeStampVal.second = second;
value_.TimeStampVal.nanos = nanos;
precision_ = 0;
scale_ = 0;
size_ = sizeof(Timestamp);
isNull_ = false;
hashCode_ = hashCode();
}
Literal::Literal(const Literal& r)
: type_(r.type_), size_(r.size_), isNull_(r.isNull_), hashCode_(r.hashCode_) {
if (type_ == PredicateDataType::STRING) {
value_.Buffer = new char[r.size_];
memcpy(value_.Buffer, r.value_.Buffer, r.size_);
precision_ = 0;
scale_ = 0;
} else if (type_ == PredicateDataType::DECIMAL) {
precision_ = r.precision_;
scale_ = r.scale_;
value_ = r.value_;
} else if (type_ == PredicateDataType::TIMESTAMP) {
value_.TimeStampVal = r.value_.TimeStampVal;
} else {
value_ = r.value_;
precision_ = 0;
scale_ = 0;
}
}
Literal::~Literal() {
if (type_ == PredicateDataType::STRING && value_.Buffer) {
delete[] value_.Buffer;
value_.Buffer = nullptr;
}
}
Literal& Literal::operator=(const Literal& r) {
if (this != &r) {
if (type_ == PredicateDataType::STRING && value_.Buffer) {
delete[] value_.Buffer;
value_.Buffer = nullptr;
}
type_ = r.type_;
size_ = r.size_;
isNull_ = r.isNull_;
precision_ = r.precision_;
scale_ = r.scale_;
if (type_ == PredicateDataType::STRING) {
value_.Buffer = new char[r.size_];
memcpy(value_.Buffer, r.value_.Buffer, r.size_);
} else if (type_ == PredicateDataType::TIMESTAMP) {
value_.TimeStampVal = r.value_.TimeStampVal;
} else {
value_ = r.value_;
}
hashCode_ = r.hashCode_;
}
return *this;
}
std::string Literal::toString() const {
if (isNull_) {
return "null";
}
std::ostringstream sstream;
switch (type_) {
case PredicateDataType::LONG:
sstream << value_.IntVal;
break;
case PredicateDataType::DATE:
sstream << value_.DateVal;
break;
case PredicateDataType::TIMESTAMP:
sstream << value_.TimeStampVal.second << "." << value_.TimeStampVal.nanos;
break;
case PredicateDataType::FLOAT:
sstream << value_.DoubleVal;
break;
case PredicateDataType::BOOLEAN:
sstream << (value_.BooleanVal ? "true" : "false");
break;
case PredicateDataType::STRING:
sstream << std::string(value_.Buffer, size_);
break;
case PredicateDataType::DECIMAL:
sstream << value_.DecimalVal.toDecimalString(scale_);
break;
}
return sstream.str();
}
size_t Literal::hashCode() const {
if (isNull_) {
return 0;
}
switch (type_) {
case PredicateDataType::LONG:
return std::hash<int64_t>{}(value_.IntVal);
case PredicateDataType::DATE:
return std::hash<int64_t>{}(value_.DateVal);
case PredicateDataType::TIMESTAMP:
return std::hash<int64_t>{}(value_.TimeStampVal.second) * 17 +
std::hash<int32_t>{}(value_.TimeStampVal.nanos);
case PredicateDataType::FLOAT:
return std::hash<double>{}(value_.DoubleVal);
case PredicateDataType::BOOLEAN:
return std::hash<bool>{}(value_.BooleanVal);
case PredicateDataType::STRING:
return std::hash<std::string>{}(std::string(value_.Buffer, size_));
case PredicateDataType::DECIMAL:
// current glibc does not support hash<int128_t>
return std::hash<int64_t>{}(value_.IntVal);
default:
return 0;
}
}
bool Literal::operator==(const Literal& r) const {
if (this == &r) {
return true;
}
if (hashCode_ != r.hashCode_ || type_ != r.type_ || isNull_ != r.isNull_) {
return false;
}
if (isNull_) {
return true;
}
switch (type_) {
case PredicateDataType::LONG:
return value_.IntVal == r.value_.IntVal;
case PredicateDataType::DATE:
return value_.DateVal == r.value_.DateVal;
case PredicateDataType::TIMESTAMP:
return value_.TimeStampVal == r.value_.TimeStampVal;
case PredicateDataType::FLOAT:
return std::fabs(value_.DoubleVal - r.value_.DoubleVal) <
std::numeric_limits<double>::epsilon();
case PredicateDataType::BOOLEAN:
return value_.BooleanVal == r.value_.BooleanVal;
case PredicateDataType::STRING:
return size_ == r.size_ && memcmp(value_.Buffer, r.value_.Buffer, size_) == 0;
case PredicateDataType::DECIMAL:
return value_.DecimalVal == r.value_.DecimalVal;
default:
return true;
}
}
bool Literal::operator!=(const Literal& r) const {
return !(*this == r);
}
inline void validate(const bool& isNull, const PredicateDataType& type,
const PredicateDataType& expected) {
if (isNull) {
throw std::logic_error("cannot get value when it is null!");
}
if (type != expected) {
throw std::logic_error("predicate type mismatch");
}
}
int64_t Literal::getLong() const {
validate(isNull_, type_, PredicateDataType::LONG);
return value_.IntVal;
}
int64_t Literal::getDate() const {
validate(isNull_, type_, PredicateDataType::DATE);
return value_.DateVal;
}
Literal::Timestamp Literal::getTimestamp() const {
validate(isNull_, type_, PredicateDataType::TIMESTAMP);
return value_.TimeStampVal;
}
double Literal::getFloat() const {
validate(isNull_, type_, PredicateDataType::FLOAT);
return value_.DoubleVal;
}
std::string Literal::getString() const {
validate(isNull_, type_, PredicateDataType::STRING);
return std::string(value_.Buffer, size_);
}
bool Literal::getBool() const {
validate(isNull_, type_, PredicateDataType::BOOLEAN);
return value_.BooleanVal;
}
Decimal Literal::getDecimal() const {
validate(isNull_, type_, PredicateDataType::DECIMAL);
return Decimal(value_.DecimalVal, scale_);
}
} // namespace orc