| /** |
| * 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 |