int IR_ALWAYS_INLINE RawValue::Compare()

in be/src/runtime/raw-value-ir.cc [30:115]


int IR_ALWAYS_INLINE RawValue::Compare(
    const void* v1, const void* v2, const ColumnType& type) noexcept {
  const StringValue* string_value1;
  const StringValue* string_value2;
  const TimestampValue* ts_value1;
  const TimestampValue* ts_value2;
  const DateValue* date_value1;
  const DateValue* date_value2;
  float f1, f2;
  double d1, d2;
  int32_t i1, i2;
  int64_t b1, b2;
  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_DATE:
      date_value1 = reinterpret_cast<const DateValue*>(v1);
      date_value2 = reinterpret_cast<const DateValue*>(v2);
      return *date_value1 > *date_value2 ? 1 : (*date_value1 < *date_value2 ? -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);
      if (UNLIKELY(std::isnan(f1) && std::isnan(f2))) return 0;
      if (UNLIKELY(std::isnan(f1))) return -1;
      if (UNLIKELY(std::isnan(f2))) return 1;
      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);
      if (std::isnan(d1) && std::isnan(d2)) return 0;
      if (std::isnan(d1)) return -1;
      if (std::isnan(d2)) return 1;
      return d1 > d2 ? 1 : (d1 < d2 ? -1 : 0);
    case TYPE_STRING:
    case TYPE_VARCHAR:
      string_value1 = reinterpret_cast<const StringValue*>(v1);
      string_value2 = reinterpret_cast<const StringValue*>(v2);
      return string_value1->Compare(*string_value2);
    case TYPE_TIMESTAMP:
      ts_value1 = reinterpret_cast<const TimestampValue*>(v1);
      ts_value2 = reinterpret_cast<const TimestampValue*>(v2);
      return *ts_value1 > *ts_value2 ? 1 : (*ts_value1 < *ts_value2 ? -1 : 0);
    case TYPE_CHAR: {
      const char* v1ptr = reinterpret_cast<const char*>(v1);
      const char* v2ptr = reinterpret_cast<const char*>(v2);
      int64_t l1 = StringValue::UnpaddedCharLength(v1ptr, type.len);
      int64_t l2 = StringValue::UnpaddedCharLength(v2ptr, type.len);
      return StringCompare(v1ptr, l1, v2ptr, l2, std::min(l1, l2));
    }
    case TYPE_DECIMAL:
      switch (type.GetByteSize()) {
        case 4:
          return reinterpret_cast<const Decimal4Value*>(v1)->Compare(
                 *reinterpret_cast<const Decimal4Value*>(v2));
        case 8:
          return reinterpret_cast<const Decimal8Value*>(v1)->Compare(
                 *reinterpret_cast<const Decimal8Value*>(v2));
        case 16:
          return reinterpret_cast<const Decimal16Value*>(v1)->Compare(
                 *reinterpret_cast<const Decimal16Value*>(v2));
        default:
          DCHECK(false) << type;
          return 0;
      }
    default:
      DCHECK(false) << "invalid type: " << type.DebugString();
      return 0;
  };
}