678 lines
22 KiB
C++
678 lines
22 KiB
C++
// 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.
|
|
// This file is copied from
|
|
// https://github.com/apache/impala/blob/branch-2.9.0/be/src/runtime/raw-value.cpp
|
|
// and modified by Doris
|
|
|
|
#include "runtime/raw_value.h"
|
|
|
|
#include <sstream>
|
|
|
|
#include "common/consts.h"
|
|
#include "runtime/collection_value.h"
|
|
#include "runtime/large_int_value.h"
|
|
#include "runtime/tuple.h"
|
|
#include "util/types.h"
|
|
#include "vec/io/io_helper.h"
|
|
|
|
namespace doris {
|
|
|
|
const int RawValue::ASCII_PRECISION = 16; // print 16 digits for double/float
|
|
|
|
void RawValue::print_value_as_bytes(const void* value, const TypeDescriptor& type,
|
|
std::stringstream* stream) {
|
|
if (value == nullptr) {
|
|
return;
|
|
}
|
|
|
|
const char* chars = reinterpret_cast<const char*>(value);
|
|
const StringValue* string_val = nullptr;
|
|
|
|
switch (type.type) {
|
|
case TYPE_NULL:
|
|
break;
|
|
case TYPE_BOOLEAN:
|
|
stream->write(chars, sizeof(bool));
|
|
return;
|
|
|
|
case TYPE_TINYINT:
|
|
stream->write(chars, sizeof(int8_t));
|
|
break;
|
|
|
|
case TYPE_SMALLINT:
|
|
stream->write(chars, sizeof(int16_t));
|
|
break;
|
|
|
|
case TYPE_INT:
|
|
stream->write(chars, sizeof(int32_t));
|
|
break;
|
|
|
|
case TYPE_BIGINT:
|
|
stream->write(chars, sizeof(int64_t));
|
|
break;
|
|
|
|
case TYPE_FLOAT:
|
|
stream->write(chars, sizeof(float));
|
|
break;
|
|
|
|
case TYPE_DOUBLE:
|
|
stream->write(chars, sizeof(double));
|
|
break;
|
|
|
|
case TYPE_VARCHAR:
|
|
case TYPE_HLL:
|
|
case TYPE_CHAR:
|
|
case TYPE_STRING:
|
|
string_val = reinterpret_cast<const StringValue*>(value);
|
|
stream->write(static_cast<char*>(string_val->ptr), string_val->len);
|
|
return;
|
|
|
|
case TYPE_DATE:
|
|
case TYPE_DATETIME:
|
|
stream->write(chars, sizeof(DateTimeValue));
|
|
break;
|
|
|
|
case TYPE_DATEV2:
|
|
stream->write(chars,
|
|
sizeof(doris::vectorized::DateV2Value<doris::vectorized::DateV2ValueType>));
|
|
break;
|
|
|
|
case TYPE_DATETIMEV2:
|
|
stream->write(
|
|
chars,
|
|
sizeof(doris::vectorized::DateV2Value<doris::vectorized::DateTimeV2ValueType>));
|
|
break;
|
|
|
|
case TYPE_DECIMALV2:
|
|
stream->write(chars, sizeof(DecimalV2Value));
|
|
break;
|
|
|
|
case TYPE_DECIMAL32:
|
|
stream->write(chars, 4);
|
|
break;
|
|
|
|
case TYPE_DECIMAL64:
|
|
stream->write(chars, 8);
|
|
break;
|
|
|
|
case TYPE_DECIMAL128:
|
|
stream->write(chars, 16);
|
|
break;
|
|
|
|
case TYPE_LARGEINT:
|
|
stream->write(chars, sizeof(__int128));
|
|
break;
|
|
|
|
default:
|
|
DCHECK(false) << "bad RawValue::print_value() type: " << type;
|
|
}
|
|
}
|
|
|
|
void RawValue::print_value(const void* value, const TypeDescriptor& type, int scale,
|
|
std::stringstream* stream) {
|
|
if (value == nullptr) {
|
|
*stream << "NULL";
|
|
return;
|
|
}
|
|
|
|
int old_precision = stream->precision();
|
|
std::ios_base::fmtflags old_flags = stream->flags();
|
|
|
|
if (scale > -1) {
|
|
stream->precision(scale);
|
|
// Setting 'fixed' causes precision to set the number of digits printed after the
|
|
// decimal (by default it sets the maximum number of digits total).
|
|
*stream << std::fixed;
|
|
}
|
|
|
|
std::string tmp;
|
|
const StringValue* string_val = nullptr;
|
|
|
|
switch (type.type) {
|
|
case TYPE_BOOLEAN: {
|
|
bool val = *reinterpret_cast<const bool*>(value);
|
|
*stream << (val ? "true" : "false");
|
|
return;
|
|
}
|
|
|
|
case TYPE_TINYINT:
|
|
// Extra casting for chars since they should not be interpreted as ASCII.
|
|
*stream << static_cast<int>(*reinterpret_cast<const int8_t*>(value));
|
|
break;
|
|
|
|
case TYPE_SMALLINT:
|
|
*stream << *reinterpret_cast<const int16_t*>(value);
|
|
break;
|
|
|
|
case TYPE_INT:
|
|
*stream << *reinterpret_cast<const int32_t*>(value);
|
|
break;
|
|
|
|
case TYPE_BIGINT:
|
|
*stream << *reinterpret_cast<const int64_t*>(value);
|
|
break;
|
|
|
|
case TYPE_FLOAT:
|
|
*stream << *reinterpret_cast<const float*>(value);
|
|
break;
|
|
|
|
case TYPE_DOUBLE:
|
|
*stream << *reinterpret_cast<const double*>(value);
|
|
break;
|
|
case TYPE_HLL:
|
|
case TYPE_CHAR:
|
|
case TYPE_VARCHAR:
|
|
case TYPE_STRING:
|
|
string_val = reinterpret_cast<const StringValue*>(value);
|
|
tmp.assign(static_cast<char*>(string_val->ptr), string_val->len);
|
|
*stream << tmp;
|
|
return;
|
|
|
|
case TYPE_DATE:
|
|
case TYPE_DATETIME:
|
|
*stream << *reinterpret_cast<const DateTimeValue*>(value);
|
|
break;
|
|
|
|
case TYPE_DATEV2:
|
|
*stream << *reinterpret_cast<
|
|
const doris::vectorized::DateV2Value<doris::vectorized::DateV2ValueType>*>(value);
|
|
break;
|
|
|
|
case TYPE_DATETIMEV2:
|
|
*stream << *reinterpret_cast<
|
|
const doris::vectorized::DateV2Value<doris::vectorized::DateTimeV2ValueType>*>(
|
|
value);
|
|
break;
|
|
|
|
case TYPE_DECIMALV2:
|
|
*stream << DecimalV2Value(reinterpret_cast<const PackedInt128*>(value)->value).to_string();
|
|
break;
|
|
|
|
case TYPE_DECIMAL32: {
|
|
auto decimal_val = reinterpret_cast<const doris::vectorized::Decimal32*>(value);
|
|
write_text(*decimal_val, type.scale, *stream);
|
|
break;
|
|
}
|
|
|
|
case TYPE_DECIMAL64: {
|
|
auto decimal_val = reinterpret_cast<const doris::vectorized::Decimal64*>(value);
|
|
write_text(*decimal_val, type.scale, *stream);
|
|
break;
|
|
}
|
|
|
|
case TYPE_DECIMAL128: {
|
|
auto decimal_val = reinterpret_cast<const doris::vectorized::Decimal128*>(value);
|
|
write_text(*decimal_val, type.scale, *stream);
|
|
break;
|
|
}
|
|
|
|
case TYPE_LARGEINT:
|
|
*stream << reinterpret_cast<const PackedInt128*>(value)->value;
|
|
break;
|
|
|
|
case TYPE_ARRAY: {
|
|
auto child_type = type.children[0];
|
|
auto array_value = (const CollectionValue*)(value);
|
|
|
|
ArrayIterator iter = array_value->iterator(child_type.type);
|
|
*stream << "[";
|
|
|
|
int begin = 0;
|
|
while (iter.has_next()) {
|
|
if (begin != 0) {
|
|
*stream << ", ";
|
|
}
|
|
if (!iter.get()) {
|
|
*stream << "NULL";
|
|
} else {
|
|
if (child_type.is_string_type()) {
|
|
*stream << "'";
|
|
print_value(iter.get(), child_type, scale, stream);
|
|
*stream << "'";
|
|
} else if (child_type.is_date_type()) {
|
|
DateTimeVal data;
|
|
iter.get(&data);
|
|
auto datetime_value = DateTimeValue::from_datetime_val(data);
|
|
print_value(&datetime_value, child_type, scale, stream);
|
|
} else if (child_type.is_decimal_type()) {
|
|
DecimalV2Val data;
|
|
iter.get(&data);
|
|
auto decimal_value = DecimalV2Value::from_decimal_val(data);
|
|
print_value(&decimal_value, child_type, scale, stream);
|
|
} else if (child_type.type == TYPE_DOUBLE) {
|
|
// Note: the default precision is 6, here should be reset to 15.
|
|
// Otherwise, there is a risk of losing precision.
|
|
stream->precision(15);
|
|
print_value(iter.get(), child_type, scale, stream);
|
|
} else {
|
|
print_value(iter.get(), child_type, scale, stream);
|
|
}
|
|
}
|
|
|
|
iter.next();
|
|
begin++;
|
|
}
|
|
*stream << "]";
|
|
break;
|
|
}
|
|
|
|
default:
|
|
DCHECK(false) << "bad RawValue::print_value() type: " << type;
|
|
}
|
|
|
|
stream->precision(old_precision);
|
|
// Undo setting stream to fixed
|
|
stream->flags(old_flags);
|
|
}
|
|
|
|
void RawValue::print_value(const void* value, const TypeDescriptor& type, int scale,
|
|
std::string* str) {
|
|
if (value == nullptr) {
|
|
*str = "NULL";
|
|
return;
|
|
}
|
|
|
|
std::stringstream out;
|
|
out.precision(ASCII_PRECISION);
|
|
const StringValue* string_val = nullptr;
|
|
std::string tmp;
|
|
bool val = false;
|
|
|
|
// Special case types that we can print more efficiently without using a std::stringstream
|
|
switch (type.type) {
|
|
case TYPE_BOOLEAN:
|
|
val = *reinterpret_cast<const bool*>(value);
|
|
*str = (val ? "true" : "false");
|
|
return;
|
|
|
|
case TYPE_CHAR:
|
|
case TYPE_VARCHAR:
|
|
case TYPE_OBJECT:
|
|
case TYPE_HLL:
|
|
case TYPE_QUANTILE_STATE:
|
|
case TYPE_STRING: {
|
|
string_val = reinterpret_cast<const StringValue*>(value);
|
|
std::stringstream ss;
|
|
ss << "ptr:" << (void*)string_val->ptr << " len:" << string_val->len;
|
|
tmp = ss.str();
|
|
if (string_val->len <= 1000) {
|
|
tmp.assign(static_cast<char*>(string_val->ptr), string_val->len);
|
|
}
|
|
str->swap(tmp);
|
|
return;
|
|
}
|
|
case TYPE_NULL: {
|
|
*str = "NULL";
|
|
return;
|
|
}
|
|
default:
|
|
print_value(value, type, scale, &out);
|
|
}
|
|
|
|
*str = out.str();
|
|
}
|
|
|
|
void RawValue::write(const void* value, void* dst, const TypeDescriptor& type, MemPool* pool) {
|
|
DCHECK(value != nullptr);
|
|
|
|
switch (type.type) {
|
|
case TYPE_NULL:
|
|
break;
|
|
case TYPE_BOOLEAN: {
|
|
*reinterpret_cast<bool*>(dst) = *reinterpret_cast<const bool*>(value);
|
|
break;
|
|
}
|
|
|
|
case TYPE_TINYINT: {
|
|
*reinterpret_cast<int8_t*>(dst) = *reinterpret_cast<const int8_t*>(value);
|
|
break;
|
|
}
|
|
|
|
case TYPE_SMALLINT: {
|
|
*reinterpret_cast<int16_t*>(dst) = *reinterpret_cast<const int16_t*>(value);
|
|
break;
|
|
}
|
|
|
|
case TYPE_INT: {
|
|
*reinterpret_cast<int32_t*>(dst) = *reinterpret_cast<const int32_t*>(value);
|
|
break;
|
|
}
|
|
|
|
case TYPE_BIGINT: {
|
|
*reinterpret_cast<int64_t*>(dst) = *reinterpret_cast<const int64_t*>(value);
|
|
break;
|
|
}
|
|
|
|
case TYPE_LARGEINT: {
|
|
*reinterpret_cast<PackedInt128*>(dst) = *reinterpret_cast<const PackedInt128*>(value);
|
|
break;
|
|
}
|
|
|
|
case TYPE_FLOAT: {
|
|
*reinterpret_cast<float*>(dst) = *reinterpret_cast<const float*>(value);
|
|
break;
|
|
}
|
|
|
|
case TYPE_TIME:
|
|
case TYPE_DOUBLE: {
|
|
*reinterpret_cast<double*>(dst) = *reinterpret_cast<const double*>(value);
|
|
break;
|
|
}
|
|
|
|
case TYPE_DATE:
|
|
case TYPE_DATETIME:
|
|
*reinterpret_cast<DateTimeValue*>(dst) = *reinterpret_cast<const DateTimeValue*>(value);
|
|
break;
|
|
|
|
case TYPE_DATEV2:
|
|
*reinterpret_cast<doris::vectorized::DateV2Value<doris::vectorized::DateV2ValueType>*>(
|
|
dst) =
|
|
*reinterpret_cast<
|
|
const doris::vectorized::DateV2Value<doris::vectorized::DateV2ValueType>*>(
|
|
value);
|
|
break;
|
|
|
|
case TYPE_DATETIMEV2:
|
|
*reinterpret_cast<doris::vectorized::DateV2Value<doris::vectorized::DateTimeV2ValueType>*>(
|
|
dst) =
|
|
*reinterpret_cast<const doris::vectorized::DateV2Value<
|
|
doris::vectorized::DateTimeV2ValueType>*>(value);
|
|
break;
|
|
|
|
case TYPE_DECIMALV2:
|
|
*reinterpret_cast<PackedInt128*>(dst) = *reinterpret_cast<const PackedInt128*>(value);
|
|
break;
|
|
|
|
case TYPE_DECIMAL32:
|
|
*reinterpret_cast<doris::vectorized::Decimal32*>(dst) =
|
|
*reinterpret_cast<const doris::vectorized::Decimal32*>(value);
|
|
break;
|
|
case TYPE_DECIMAL64:
|
|
*reinterpret_cast<doris::vectorized::Decimal64*>(dst) =
|
|
*reinterpret_cast<const doris::vectorized::Decimal64*>(value);
|
|
break;
|
|
case TYPE_DECIMAL128:
|
|
*reinterpret_cast<doris::vectorized::Decimal128*>(dst) =
|
|
*reinterpret_cast<const doris::vectorized::Decimal128*>(value);
|
|
break;
|
|
|
|
case TYPE_OBJECT:
|
|
case TYPE_HLL:
|
|
case TYPE_QUANTILE_STATE:
|
|
case TYPE_VARCHAR:
|
|
case TYPE_CHAR:
|
|
case TYPE_STRING: {
|
|
const StringValue* src = reinterpret_cast<const StringValue*>(value);
|
|
StringValue* dest = reinterpret_cast<StringValue*>(dst);
|
|
dest->len = src->len;
|
|
|
|
if (pool != nullptr) {
|
|
dest->ptr = reinterpret_cast<char*>(pool->allocate(dest->len));
|
|
memcpy(dest->ptr, src->ptr, dest->len);
|
|
} else {
|
|
dest->ptr = src->ptr;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case TYPE_ARRAY: {
|
|
DCHECK_EQ(type.children.size(), 1);
|
|
|
|
const CollectionValue* src = reinterpret_cast<const CollectionValue*>(value);
|
|
CollectionValue* val = reinterpret_cast<CollectionValue*>(dst);
|
|
|
|
if (pool != nullptr) {
|
|
const auto& item_type = type.children[0];
|
|
CollectionValue::init_collection(pool, src->size(), item_type.type, val);
|
|
ArrayIterator src_iter = src->iterator(item_type.type);
|
|
ArrayIterator val_iter = val->iterator(item_type.type);
|
|
|
|
val->set_has_null(src->has_null());
|
|
val->copy_null_signs(src);
|
|
|
|
while (src_iter.has_next() && val_iter.has_next()) {
|
|
val_iter.raw_value_write(src_iter.get(), item_type, pool);
|
|
src_iter.next();
|
|
val_iter.next();
|
|
}
|
|
} else {
|
|
val->shallow_copy(src);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
DCHECK(false) << "RawValue::write(): bad type: " << type;
|
|
}
|
|
}
|
|
|
|
// TODO: can we remove some of this code duplication? Templated allocator?
|
|
void RawValue::write(const void* value, const TypeDescriptor& type, void* dst, uint8_t** buf) {
|
|
DCHECK(value != nullptr);
|
|
switch (type.type) {
|
|
case TYPE_BOOLEAN:
|
|
*reinterpret_cast<bool*>(dst) = *reinterpret_cast<const bool*>(value);
|
|
break;
|
|
case TYPE_TINYINT:
|
|
*reinterpret_cast<int8_t*>(dst) = *reinterpret_cast<const int8_t*>(value);
|
|
break;
|
|
case TYPE_SMALLINT:
|
|
*reinterpret_cast<int16_t*>(dst) = *reinterpret_cast<const int16_t*>(value);
|
|
break;
|
|
case TYPE_INT:
|
|
*reinterpret_cast<int32_t*>(dst) = *reinterpret_cast<const int32_t*>(value);
|
|
break;
|
|
case TYPE_BIGINT:
|
|
*reinterpret_cast<int64_t*>(dst) = *reinterpret_cast<const int64_t*>(value);
|
|
break;
|
|
case TYPE_LARGEINT:
|
|
*reinterpret_cast<PackedInt128*>(dst) = *reinterpret_cast<const PackedInt128*>(value);
|
|
break;
|
|
case TYPE_FLOAT:
|
|
*reinterpret_cast<float*>(dst) = *reinterpret_cast<const float*>(value);
|
|
break;
|
|
case TYPE_DOUBLE:
|
|
*reinterpret_cast<double*>(dst) = *reinterpret_cast<const double*>(value);
|
|
break;
|
|
case TYPE_DATE:
|
|
case TYPE_DATETIME:
|
|
*reinterpret_cast<DateTimeValue*>(dst) = *reinterpret_cast<const DateTimeValue*>(value);
|
|
break;
|
|
case TYPE_DATEV2:
|
|
*reinterpret_cast<doris::vectorized::DateV2Value<doris::vectorized::DateV2ValueType>*>(
|
|
dst) =
|
|
*reinterpret_cast<
|
|
const doris::vectorized::DateV2Value<doris::vectorized::DateV2ValueType>*>(
|
|
value);
|
|
break;
|
|
case TYPE_DATETIMEV2:
|
|
*reinterpret_cast<doris::vectorized::DateV2Value<doris::vectorized::DateTimeV2ValueType>*>(
|
|
dst) =
|
|
*reinterpret_cast<const doris::vectorized::DateV2Value<
|
|
doris::vectorized::DateTimeV2ValueType>*>(value);
|
|
break;
|
|
case TYPE_VARCHAR:
|
|
case TYPE_CHAR:
|
|
case TYPE_STRING: {
|
|
DCHECK(buf != nullptr);
|
|
const StringValue* src = reinterpret_cast<const StringValue*>(value);
|
|
StringValue* dest = reinterpret_cast<StringValue*>(dst);
|
|
dest->len = src->len;
|
|
dest->ptr = reinterpret_cast<char*>(*buf);
|
|
memcpy(dest->ptr, src->ptr, dest->len);
|
|
*buf += dest->len;
|
|
break;
|
|
}
|
|
|
|
case TYPE_DECIMALV2:
|
|
*reinterpret_cast<PackedInt128*>(dst) = *reinterpret_cast<const PackedInt128*>(value);
|
|
break;
|
|
|
|
case TYPE_DECIMAL32:
|
|
*reinterpret_cast<doris::vectorized::Decimal32*>(dst) =
|
|
*reinterpret_cast<const doris::vectorized::Decimal32*>(value);
|
|
break;
|
|
case TYPE_DECIMAL64:
|
|
*reinterpret_cast<doris::vectorized::Decimal64*>(dst) =
|
|
*reinterpret_cast<const doris::vectorized::Decimal64*>(value);
|
|
break;
|
|
case TYPE_DECIMAL128:
|
|
*reinterpret_cast<doris::vectorized::Decimal128*>(dst) =
|
|
*reinterpret_cast<const doris::vectorized::Decimal128*>(value);
|
|
break;
|
|
|
|
default:
|
|
DCHECK(false) << "RawValue::write(): bad type: " << type.debug_string();
|
|
}
|
|
}
|
|
|
|
void RawValue::write(const void* value, Tuple* tuple, const SlotDescriptor* slot_desc,
|
|
MemPool* pool) {
|
|
if (value == nullptr) {
|
|
tuple->set_null(slot_desc->null_indicator_offset());
|
|
} else {
|
|
void* slot = tuple->get_slot(slot_desc->tuple_offset());
|
|
RawValue::write(value, slot, slot_desc->type(), pool);
|
|
}
|
|
}
|
|
|
|
int RawValue::compare(const void* v1, const void* v2, const TypeDescriptor& type) {
|
|
const StringValue* string_value1;
|
|
const StringValue* string_value2;
|
|
const DateTimeValue* ts_value1;
|
|
const DateTimeValue* ts_value2;
|
|
float f1 = 0;
|
|
float f2 = 0;
|
|
double d1 = 0;
|
|
double d2 = 0;
|
|
int32_t i1;
|
|
int32_t i2;
|
|
int64_t b1;
|
|
int64_t b2;
|
|
|
|
if (nullptr == v1 && nullptr == v2) {
|
|
return 0;
|
|
} else if (nullptr == v1 && nullptr != v2) {
|
|
return -1;
|
|
} else if (nullptr != v1 && nullptr == v2) {
|
|
return 1;
|
|
}
|
|
|
|
switch (type.type) {
|
|
case TYPE_NULL:
|
|
return 0;
|
|
|
|
case TYPE_BOOLEAN:
|
|
return *reinterpret_cast<const bool*>(v1) - *reinterpret_cast<const bool*>(v2);
|
|
|
|
case TYPE_TINYINT:
|
|
return *reinterpret_cast<const int8_t*>(v1) - *reinterpret_cast<const int8_t*>(v2);
|
|
|
|
case TYPE_SMALLINT:
|
|
return *reinterpret_cast<const int16_t*>(v1) - *reinterpret_cast<const int16_t*>(v2);
|
|
|
|
case TYPE_INT:
|
|
i1 = *reinterpret_cast<const int32_t*>(v1);
|
|
i2 = *reinterpret_cast<const int32_t*>(v2);
|
|
return i1 > i2 ? 1 : (i1 < i2 ? -1 : 0);
|
|
|
|
case TYPE_BIGINT:
|
|
b1 = *reinterpret_cast<const int64_t*>(v1);
|
|
b2 = *reinterpret_cast<const int64_t*>(v2);
|
|
return b1 > b2 ? 1 : (b1 < b2 ? -1 : 0);
|
|
|
|
case TYPE_FLOAT:
|
|
// TODO: can this be faster? (just returning the difference has underflow problems)
|
|
f1 = *reinterpret_cast<const float*>(v1);
|
|
f2 = *reinterpret_cast<const float*>(v2);
|
|
return f1 > f2 ? 1 : (f1 < f2 ? -1 : 0);
|
|
|
|
case TYPE_DOUBLE:
|
|
// TODO: can this be faster?
|
|
d1 = *reinterpret_cast<const double*>(v1);
|
|
d2 = *reinterpret_cast<const double*>(v2);
|
|
return d1 > d2 ? 1 : (d1 < d2 ? -1 : 0);
|
|
|
|
case TYPE_CHAR:
|
|
case TYPE_VARCHAR:
|
|
case TYPE_HLL:
|
|
case TYPE_STRING:
|
|
string_value1 = reinterpret_cast<const StringValue*>(v1);
|
|
string_value2 = reinterpret_cast<const StringValue*>(v2);
|
|
return string_value1->compare(*string_value2);
|
|
|
|
case TYPE_DATE:
|
|
case TYPE_DATETIME:
|
|
ts_value1 = reinterpret_cast<const DateTimeValue*>(v1);
|
|
ts_value2 = reinterpret_cast<const DateTimeValue*>(v2);
|
|
return *ts_value1 > *ts_value2 ? 1 : (*ts_value1 < *ts_value2 ? -1 : 0);
|
|
|
|
case TYPE_DATEV2: {
|
|
auto date_v2_value1 = reinterpret_cast<
|
|
const doris::vectorized::DateV2Value<doris::vectorized::DateV2ValueType>*>(v1);
|
|
auto date_v2_value2 = reinterpret_cast<
|
|
const doris::vectorized::DateV2Value<doris::vectorized::DateV2ValueType>*>(v2);
|
|
return *date_v2_value1 > *date_v2_value2 ? 1 : (*date_v2_value1 < *date_v2_value2 ? -1 : 0);
|
|
}
|
|
|
|
case TYPE_DATETIMEV2: {
|
|
auto date_v2_value1 = reinterpret_cast<
|
|
const doris::vectorized::DateV2Value<doris::vectorized::DateTimeV2ValueType>*>(v1);
|
|
auto date_v2_value2 = reinterpret_cast<
|
|
const doris::vectorized::DateV2Value<doris::vectorized::DateTimeV2ValueType>*>(v2);
|
|
return *date_v2_value1 > *date_v2_value2 ? 1 : (*date_v2_value1 < *date_v2_value2 ? -1 : 0);
|
|
}
|
|
|
|
case TYPE_DECIMALV2: {
|
|
DecimalV2Value decimal_value1(reinterpret_cast<const PackedInt128*>(v1)->value);
|
|
DecimalV2Value decimal_value2(reinterpret_cast<const PackedInt128*>(v2)->value);
|
|
return (decimal_value1 > decimal_value2) ? 1 : (decimal_value1 < decimal_value2 ? -1 : 0);
|
|
}
|
|
|
|
case TYPE_DECIMAL32: {
|
|
i1 = *reinterpret_cast<const int32_t*>(v1);
|
|
i2 = *reinterpret_cast<const int32_t*>(v2);
|
|
return i1 > i2 ? 1 : (i1 < i2 ? -1 : 0);
|
|
}
|
|
|
|
case TYPE_DECIMAL64: {
|
|
b1 = *reinterpret_cast<const int64_t*>(v1);
|
|
b2 = *reinterpret_cast<const int64_t*>(v2);
|
|
return b1 > b2 ? 1 : (b1 < b2 ? -1 : 0);
|
|
}
|
|
|
|
case TYPE_DECIMAL128: {
|
|
__int128 large_int_value1 = reinterpret_cast<const PackedInt128*>(v1)->value;
|
|
__int128 large_int_value2 = reinterpret_cast<const PackedInt128*>(v2)->value;
|
|
return large_int_value1 > large_int_value2 ? 1
|
|
: (large_int_value1 < large_int_value2 ? -1 : 0);
|
|
}
|
|
|
|
case TYPE_LARGEINT: {
|
|
__int128 large_int_value1 = reinterpret_cast<const PackedInt128*>(v1)->value;
|
|
__int128 large_int_value2 = reinterpret_cast<const PackedInt128*>(v2)->value;
|
|
return large_int_value1 > large_int_value2 ? 1
|
|
: (large_int_value1 < large_int_value2 ? -1 : 0);
|
|
}
|
|
|
|
default:
|
|
DCHECK(false) << "invalid type: " << type.type;
|
|
return 0;
|
|
};
|
|
}
|
|
|
|
} // namespace doris
|