blob: c0cdd62201b4172a48aaa23fb0b99a4ee808a00f [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) {
mType = type;
mValue.DecimalVal = 0;
mSize = 0;
mIsNull = true;
mPrecision = 0;
mScale = 0;
mHashCode = 0;
}
Literal::Literal(int64_t val) {
mType = PredicateDataType::LONG;
mValue.IntVal = val;
mSize = sizeof(val);
mIsNull = false;
mPrecision = 0;
mScale = 0;
mHashCode = hashCode();
}
Literal::Literal(double val) {
mType = PredicateDataType::FLOAT;
mValue.DoubleVal = val;
mSize = sizeof(val);
mIsNull = false;
mPrecision = 0;
mScale = 0;
mHashCode = hashCode();
}
Literal::Literal(bool val) {
mType = PredicateDataType::BOOLEAN;
mValue.BooleanVal = val;
mSize = sizeof(val);
mIsNull = false;
mPrecision = 0;
mScale = 0;
mHashCode = hashCode();
}
Literal::Literal(PredicateDataType type, int64_t val) {
if (type != PredicateDataType::DATE) {
throw std::invalid_argument("only DATE is supported here!");
}
mType = type;
mValue.IntVal = val;
mSize = sizeof(val);
mIsNull = false;
mPrecision = 0;
mScale = 0;
mHashCode = hashCode();
}
Literal::Literal(const char* str, size_t size) {
mType = PredicateDataType::STRING;
mValue.Buffer = new char[size];
memcpy(mValue.Buffer, str, size);
mSize = size;
mIsNull = false;
mPrecision = 0;
mScale = 0;
mHashCode = hashCode();
}
Literal::Literal(Int128 val, int32_t precision, int32_t scale) {
mType = PredicateDataType::DECIMAL;
mValue.DecimalVal = val;
mPrecision = precision;
mScale = scale;
mSize = sizeof(Int128);
mIsNull = false;
mHashCode = hashCode();
}
Literal::Literal(int64_t second, int32_t nanos) {
mType = PredicateDataType::TIMESTAMP;
mValue.TimeStampVal.second = second;
mValue.TimeStampVal.nanos = nanos;
mPrecision = 0;
mScale = 0;
mSize = sizeof(Timestamp);
mIsNull = false;
mHashCode = hashCode();
}
Literal::Literal(const Literal& r)
: mType(r.mType), mSize(r.mSize), mIsNull(r.mIsNull), mHashCode(r.mHashCode) {
if (mType == PredicateDataType::STRING) {
mValue.Buffer = new char[r.mSize];
memcpy(mValue.Buffer, r.mValue.Buffer, r.mSize);
mPrecision = 0;
mScale = 0;
} else if (mType == PredicateDataType::DECIMAL) {
mPrecision = r.mPrecision;
mScale = r.mScale;
mValue = r.mValue;
} else if (mType == PredicateDataType::TIMESTAMP) {
mValue.TimeStampVal = r.mValue.TimeStampVal;
} else {
mValue = r.mValue;
mPrecision = 0;
mScale = 0;
}
}
Literal::~Literal() {
if (mType == PredicateDataType::STRING && mValue.Buffer) {
delete[] mValue.Buffer;
mValue.Buffer = nullptr;
}
}
Literal& Literal::operator=(const Literal& r) {
if (this != &r) {
if (mType == PredicateDataType::STRING && mValue.Buffer) {
delete[] mValue.Buffer;
mValue.Buffer = nullptr;
}
mType = r.mType;
mSize = r.mSize;
mIsNull = r.mIsNull;
mPrecision = r.mPrecision;
mScale = r.mScale;
if (mType == PredicateDataType::STRING) {
mValue.Buffer = new char[r.mSize];
memcpy(mValue.Buffer, r.mValue.Buffer, r.mSize);
} else if (mType == PredicateDataType::TIMESTAMP) {
mValue.TimeStampVal = r.mValue.TimeStampVal;
} else {
mValue = r.mValue;
}
mHashCode = r.mHashCode;
}
return *this;
}
std::string Literal::toString() const {
if (mIsNull) {
return "null";
}
std::ostringstream sstream;
switch (mType) {
case PredicateDataType::LONG:
sstream << mValue.IntVal;
break;
case PredicateDataType::DATE:
sstream << mValue.DateVal;
break;
case PredicateDataType::TIMESTAMP:
sstream << mValue.TimeStampVal.second << "." << mValue.TimeStampVal.nanos;
break;
case PredicateDataType::FLOAT:
sstream << mValue.DoubleVal;
break;
case PredicateDataType::BOOLEAN:
sstream << (mValue.BooleanVal ? "true" : "false");
break;
case PredicateDataType::STRING:
sstream << std::string(mValue.Buffer, mSize);
break;
case PredicateDataType::DECIMAL:
sstream << mValue.DecimalVal.toDecimalString(mScale);
break;
}
return sstream.str();
}
size_t Literal::hashCode() const {
if (mIsNull) {
return 0;
}
switch (mType) {
case PredicateDataType::LONG:
return std::hash<int64_t>{}(mValue.IntVal);
case PredicateDataType::DATE:
return std::hash<int64_t>{}(mValue.DateVal);
case PredicateDataType::TIMESTAMP:
return std::hash<int64_t>{}(mValue.TimeStampVal.second) * 17 +
std::hash<int32_t>{}(mValue.TimeStampVal.nanos);
case PredicateDataType::FLOAT:
return std::hash<double>{}(mValue.DoubleVal);
case PredicateDataType::BOOLEAN:
return std::hash<bool>{}(mValue.BooleanVal);
case PredicateDataType::STRING:
return std::hash<std::string>{}(std::string(mValue.Buffer, mSize));
case PredicateDataType::DECIMAL:
// current glibc does not support hash<int128_t>
return std::hash<int64_t>{}(mValue.IntVal);
default:
return 0;
}
}
bool Literal::operator==(const Literal& r) const {
if (this == &r) {
return true;
}
if (mHashCode != r.mHashCode || mType != r.mType || mIsNull != r.mIsNull) {
return false;
}
if (mIsNull) {
return true;
}
switch (mType) {
case PredicateDataType::LONG:
return mValue.IntVal == r.mValue.IntVal;
case PredicateDataType::DATE:
return mValue.DateVal == r.mValue.DateVal;
case PredicateDataType::TIMESTAMP:
return mValue.TimeStampVal == r.mValue.TimeStampVal;
case PredicateDataType::FLOAT:
return std::fabs(mValue.DoubleVal - r.mValue.DoubleVal) <
std::numeric_limits<double>::epsilon();
case PredicateDataType::BOOLEAN:
return mValue.BooleanVal == r.mValue.BooleanVal;
case PredicateDataType::STRING:
return mSize == r.mSize && memcmp(mValue.Buffer, r.mValue.Buffer, mSize) == 0;
case PredicateDataType::DECIMAL:
return mValue.DecimalVal == r.mValue.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(mIsNull, mType, PredicateDataType::LONG);
return mValue.IntVal;
}
int64_t Literal::getDate() const {
validate(mIsNull, mType, PredicateDataType::DATE);
return mValue.DateVal;
}
Literal::Timestamp Literal::getTimestamp() const {
validate(mIsNull, mType, PredicateDataType::TIMESTAMP);
return mValue.TimeStampVal;
}
double Literal::getFloat() const {
validate(mIsNull, mType, PredicateDataType::FLOAT);
return mValue.DoubleVal;
}
std::string Literal::getString() const {
validate(mIsNull, mType, PredicateDataType::STRING);
return std::string(mValue.Buffer, mSize);
}
bool Literal::getBool() const {
validate(mIsNull, mType, PredicateDataType::BOOLEAN);
return mValue.BooleanVal;
}
Decimal Literal::getDecimal() const {
validate(mIsNull, mType, PredicateDataType::DECIMAL);
return Decimal(mValue.DecimalVal, mScale);
}
} // namespace orc