bool InjectJoinFilters::findExactMinMaxValuesForAttributeHelper( const physical::PhysicalPtr &physical_plan, const expressions::AttributeReferencePtr &attribute, std::int64_t *min_cpp_value, std::int64_t *max_cpp_value) const { bool min_value_is_exact; bool max_value_is_exact; const TypedValue min_value = cost_model_->findMinValueStat(physical_plan, attribute, &min_value_is_exact); const TypedValue max_value = cost_model_->findMaxValueStat(physical_plan, attribute, &max_value_is_exact); if (min_value.isNull() || max_value.isNull() || (!min_value_is_exact) || (!max_value_is_exact)) { return false; } switch (attribute->getValueType().getTypeID()) { case TypeID::kInt: { *min_cpp_value = min_value.getLiteral<int>(); *max_cpp_value = max_value.getLiteral<int>(); return true; } case TypeID::kLong: { *min_cpp_value = min_value.getLiteral<std::int64_t>(); *max_cpp_value = max_value.getLiteral<std::int64_t>(); return true; } default: return false; } }
/** * @brief Overwrite the value at the specified position with the supplied * TypedValue. * @warning You must call prepareForPositionalWrites() BEFORE calling this * method. * @warning Do NOT use positional writes in combination with appends. * @warning It is intended that this and other positional write methods * should be called exactly once for each position (if this is * violated, NULLs may not be tracked properly). * * @param position The position of the value in this NativeColumnVector to * overwrite. * @param value A TypedValue to write into this NativeColumnVector. **/ inline void positionalWriteTypedValue(const std::size_t position, const TypedValue &value) { DCHECK_LT(position, actual_length_); DCHECK(value.isPlausibleInstanceOf(type_.getSignature())); if (null_bitmap_ && value.isNull()) { null_bitmap_->setBit(position, true); } else { DCHECK(!value.isNull()); value.copyInto(static_cast<char*>(values_) + (position * type_length_)); } }
/** * @brief Append a TypedValue to this NativeColumnVector. * * @param value A value to append to this NativeColumnVector. **/ inline void appendTypedValue(const TypedValue &value) { DCHECK_LT(actual_length_, reserved_length_); DCHECK(value.isPlausibleInstanceOf(type_.getSignature())); if (null_bitmap_ && value.isNull()) { null_bitmap_->setBit(actual_length_, true); } else { DCHECK(!value.isNull()); value.copyInto(static_cast<char*>(values_) + (actual_length_ * type_length_)); } ++actual_length_; }
TypedValue applyToTypedValue(const TypedValue &argument) const override { if (source_nullability && argument.isNull()) { return TypedValue(TargetType::kStaticTypeID); } return TypedValue(static_cast<typename TargetType::cpptype>( argument.getLiteral<typename SourceType::cpptype>())); }
inline void iterateUnaryInl(AggregationStateSum *state, const TypedValue &value) const { DCHECK(value.isPlausibleInstanceOf(argument_type_.getSignature())); if (value.isNull()) return; SpinMutexLock lock(state->mutex_); state->sum_ = fast_operator_->applyToTypedValues(state->sum_, value); state->null_ = false; }
/** * @brief Find the first code which is greater than the specified typed * value, similar to std::upper_bound(). * @warning value must not be NULL. * * @param value A typed value, which can be either the exact same Type as * the values in this dictionary, or another Type which is comparable * according to LessComparison. * @param value_type The Type that value belongs to. * @return The first code whose corresponding uncompressed value is greater * than value. May return numberOfCodes() if every value in the * dictionary is less than or equal to value. **/ std::uint32_t getUpperBoundCodeForTypedValue(const TypedValue &value, const Type &value_type) const { DCHECK(!value.isNull()); if (value_type.isSubsumedBy(type_)) { return getUpperBoundCodeForUntypedValue(value.getDataPtr()); } else { return getUpperBoundCodeForDifferentTypedValue(value, value_type); } }
/** * @brief Find the first code which is not less than the specified typed * value, similar to std::lower_bound(). * @warning value must not be NULL. * * @param value A typed value, which can be either the exact same Type as * the values in this dictionary, or another Type which is comparable * according to LessComparison. * @param value_type The Type that value belongs to. * @return The first code whose corresponding uncompressed value is not less * than value. May return numberOfCodes() if every value in the * dictionary is less than value. **/ std::uint32_t getLowerBoundCodeForTypedValue(const TypedValue &value, const Type &value_type, const bool ignore_null_code = false) const { DCHECK(!value.isNull()); if (value_type.isSubsumedBy(type_)) { return getLowerBoundCodeForUntypedValue(value.getDataPtr(), ignore_null_code); } else { return getLowerBoundCodeForDifferentTypedValue(value, value_type, ignore_null_code); } }
void LongType::printValueToFile(const TypedValue &value, FILE *file, const int padding) const { DCHECK(!value.isNull()); std::fprintf(file, "%*" PRId64, static_cast<int>(padding), value.getLiteral<std::int64_t>()); }
void IntType::printValueToFile(const TypedValue &value, FILE *file, const int padding) const { DCHECK(!value.isNull()); std::fprintf(file, "%*d", static_cast<int>(padding), value.getLiteral<int>()); }
/** * @brief Get the compressed code that represents the specified typed value. * @note This uses a binary search to find the appropriate code. It runs in * O(log(n)) time. * * @param value A typed value, which can be either the exact same Type as * the values in this dictionary, or another Type which is comparable * according to LessComparison. * @param value_type The Type that value belongs to. * @return The code for value in this dictionary, or the value of * numberOfCodes() (the maximum code plus one) if value is not * contained in this dictionary. **/ std::uint32_t getCodeForTypedValue(const TypedValue &value, const Type &value_type) const { if (value.isNull()) { return getNullCode() == std::numeric_limits<std::uint32_t>::max() ? number_of_codes_including_null_ : getNullCode(); } else if (value_type.isSubsumedBy(type_)) { return getCodeForUntypedValue(value.getDataPtr()); } else { return getCodeForDifferentTypedValue(value, value_type); } }
/** * @brief Determine the range of codes that match a specified comparison with * a specified typed value. * * @param comp The comparison to evaluate. * @param value A typed value, which can be either the exact same Type as * the values in this dictionary, or another Type which is comparable * according to LessComparison. * @param value_type The Type that value belongs to. * @return The limits of the range of codes which match the predicate * "coded-value comp value". The range is [first, second) (i.e. it * is inclusive of first but not second). **/ std::pair<std::uint32_t, std::uint32_t> getLimitCodesForComparisonTyped( const ComparisonID comp, const TypedValue &value, const Type &value_type) const { if (value_type.isSubsumedBy(type_)) { return getLimitCodesForComparisonUntyped(comp, value.isNull() ? nullptr : value.getDataPtr()); } else { return getLimitCodesForComparisonDifferentTyped(comp, value, value_type); } }
void CharType::printValueToFile(const TypedValue &value, FILE *file, const int padding) const { DCHECK(!value.isNull()); DCHECK_EQ(length_, static_cast<decltype(length_)>(static_cast<int>(length_))) << "Can not convert CHAR Type's maximum length " << length_ << " to int for fprintf()"; std::fprintf(file, "%*.*s", padding, static_cast<int>(length_), static_cast<const char*>(value.getOutOfLineData())); }
/** * @brief Fill this entire ColumnVector with copies of value. * * @param value A value to fill this ColumnVector with. **/ inline void fillWithValue(const TypedValue &value) { DCHECK(value.isPlausibleInstanceOf(type_.getSignature())); if (value.isNull()) { fillWithNulls(); } else { if (null_bitmap_) { null_bitmap_->clear(); } for (std::size_t pos = 0; pos < reserved_length_; ++pos) { value.copyInto(static_cast<char*>(values_) + (pos * type_length_)); } actual_length_ = reserved_length_; } }
TypedValue CharType::coerceValue(const TypedValue &original_value, const Type &original_type) const { DCHECK(isCoercibleFrom(original_type)) << "Can't coerce value of Type " << original_type.getName() << " to Type " << getName(); if (original_value.isNull()) { return makeNullValue(); } const void *original_data = original_value.getOutOfLineData(); const std::size_t original_data_size = original_value.getDataSize(); // VARCHAR always has a null-terminator. CHAR(X) has a null-terminator when // string's length is less than X. const bool null_terminated = (original_type.getTypeID() == kVarChar) || (original_data_size < original_type.maximumByteLength()) || (std::memchr(original_data, '\0', original_data_size) != nullptr); if (original_data_size <= length_) { if (null_terminated || (original_data_size == length_)) { TypedValue value_copy(original_value); value_copy.markType(kChar); return value_copy; } else { // Need to make a new NULL-terminated copy of the string. char *null_terminated_str = static_cast<char*>(std::malloc(original_data_size + 1)); std::memcpy(null_terminated_str, original_data, original_data_size); null_terminated_str[original_data_size] = '\0'; return TypedValue::CreateWithOwnedData(kChar, null_terminated_str, original_data_size + 1); } } else { // Need to truncate. if (original_value.ownsOutOfLineData()) { char *truncated_str = static_cast<char*>(std::malloc(length_)); std::memcpy(truncated_str, original_data, length_); return TypedValue::CreateWithOwnedData(kChar, truncated_str, length_); } else { // Original is a reference, so we will just make a shorter reference. return TypedValue(kChar, original_data, length_); } } }
TypedValue LongType::coerceValue(const TypedValue &original_value, const Type &original_type) const { DCHECK(isCoercibleFrom(original_type)) << "Can't coerce value of Type " << original_type.getName() << " to Type " << getName(); if (original_value.isNull()) { return makeNullValue(); } switch (original_type.getTypeID()) { case kInt: return TypedValue(static_cast<std::int64_t>(original_value.getLiteral<int>())); case kLong: return original_value; case kFloat: return TypedValue(static_cast<std::int64_t>(original_value.getLiteral<float>())); case kDouble: return TypedValue(static_cast<std::int64_t>(original_value.getLiteral<double>())); default: LOG(FATAL) << "Attempted to coerce Type " << original_type.getName() << " (not recognized as a numeric Type) to " << getName(); } }
std::string LongType::printValueToString(const TypedValue &value) const { DCHECK(!value.isNull()); return std::to_string(value.getLiteral<std::int64_t>()); }
std::string CharType::printValueToString(const TypedValue &value) const { DCHECK(!value.isNull()); const char *cstr = static_cast<const char*>(value.getOutOfLineData()); return std::string(cstr, strnlen(cstr, length_)); }
/** * @brief Iterate with count aggregation state. */ inline void iterateUnaryInl(AggregationStateCount *state, const TypedValue &value) const { if ((!nullable_type) || (!value.isNull())) { state->count_.fetch_add(1, std::memory_order_relaxed); } }
inline TypedValue applyToTypedValueInl(const TypedValue &argument) const { if (argument_nullable && argument.isNull()) { return argument; } return TypedValue(-argument.getLiteral<typename ResultType::cpptype>()); }