<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// value.cpp
//
// Identification: src/backend/common/value.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "backend/common/value.h"
#include "backend/common/logger.h"

#include <cstdio>
#include <cstring>
#include <sstream>
#include <iostream>

namespace peloton {

// For x <op> y where x is an integer,
// promote x and y to s_intPromotionTable[y]
ValueType Value::IntPromotionTable[] = {
    VALUE_TYPE_INVALID,  // 0 invalid
    VALUE_TYPE_NULL,     // 1 null
    VALUE_TYPE_INVALID,  // 2 <unused>
    VALUE_TYPE_BIGINT,   // 3 tinyint
    VALUE_TYPE_BIGINT,   // 4 smallint
    VALUE_TYPE_BIGINT,   // 5 integer
    VALUE_TYPE_BIGINT,   // 6 bigint
    VALUE_TYPE_INVALID,  // 7 <unused>
    VALUE_TYPE_DOUBLE,   // 8 double
    VALUE_TYPE_INVALID,  // 9 varchar
    VALUE_TYPE_INVALID,  // 10 <unused>
    VALUE_TYPE_BIGINT,   // 11 timestamp

    // 12 - 21 unused
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID,

    VALUE_TYPE_DECIMAL,  // 22 decimal
    VALUE_TYPE_INVALID,  // 23 boolean
    VALUE_TYPE_INVALID,  // 24 address
};

// For x <op> y where x is a double
// promote x and y to s_doublePromotionTable[y]
ValueType Value::DoublePromotionTable[] = {
    VALUE_TYPE_INVALID,  // 0 invalid
    VALUE_TYPE_NULL,     // 1 null
    VALUE_TYPE_INVALID,  // 2 <unused>
    VALUE_TYPE_DOUBLE,   // 3 tinyint
    VALUE_TYPE_DOUBLE,   // 4 smallint
    VALUE_TYPE_DOUBLE,   // 5 integer
    VALUE_TYPE_DOUBLE,   // 6 bigint
    VALUE_TYPE_INVALID,  // 7 <unused>
    VALUE_TYPE_DOUBLE,   // 8 double
    VALUE_TYPE_INVALID,  // 9 varchar
    VALUE_TYPE_INVALID,  // 10 <unused>
    VALUE_TYPE_DOUBLE,   // 11 timestamp

    // 12 - 21 unused.
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID,

    VALUE_TYPE_INVALID,  // 22 decimal  (todo)
    VALUE_TYPE_INVALID,  // 23 boolean
    VALUE_TYPE_INVALID,  // 24 address
};

// for x <op> y where x is a decimal
// promote x and y to s_decimalPromotionTable[y]
ValueType Value::DecimalPromotionTable[] = {
    VALUE_TYPE_INVALID,  // 0 invalid
    VALUE_TYPE_NULL,     // 1 null
    VALUE_TYPE_INVALID,  // 2 <unused>
    VALUE_TYPE_DECIMAL,  // 3 tinyint
    VALUE_TYPE_DECIMAL,  // 4 smallint
    VALUE_TYPE_DECIMAL,  // 5 integer
    VALUE_TYPE_DECIMAL,  // 6 bigint
    VALUE_TYPE_INVALID,  // 7 <unused>
    VALUE_TYPE_INVALID,  // 8 double (todo)
    VALUE_TYPE_INVALID,  // 9 varchar
    VALUE_TYPE_INVALID,  // 10 <unused>
    VALUE_TYPE_DECIMAL,  // 11 timestamp

    // 12 - 21 unused. ick.
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID,

    VALUE_TYPE_DECIMAL,  // 22 decimal
    VALUE_TYPE_INVALID,  // 23 boolean
    VALUE_TYPE_INVALID,  // 24 address
};

TTInt Value::MaxDecimal(
    "9999999999"  // 10 digits
    "9999999999"  // 20 digits
    "9999999999"  // 30 digits
    "99999999");  // 38 digits

TTInt Value::MinDecimal(
    "-9999999999"  // 10 digits
    "9999999999"   // 20 digits
    "9999999999"   // 30 digits
    "99999999");   // 38 digits

//===--------------------------------------------------------------------===//
// Type Cast and Getters
//===--------------------------------------------------------------------===//

int64_t Value::CastAsBigIntAndGetValue() const {
  const ValueType type = GetValueType();
  if (IsNull()) {
    return INT64_NULL;
  }

  switch (type) {
    case VALUE_TYPE_NULL:
      return INT64_NULL;
    case VALUE_TYPE_TINYINT:
      return static_cast<int64_t>(GetTinyInt());
    case VALUE_TYPE_SMALLINT:
      return static_cast<int64_t>(GetSmallInt());
    case VALUE_TYPE_INTEGER:
      return static_cast<int64_t>(GetInteger());
    case VALUE_TYPE_ADDRESS:
      return GetBigInt();
    case VALUE_TYPE_BIGINT:
      return GetBigInt();
    case VALUE_TYPE_TIMESTAMP:
      return GetTimestamp();
    case VALUE_TYPE_DOUBLE:
      if (GetDouble() > (double)INT64_MAX || GetDouble() < (double)INT64_MIN) {
        throw ValueOutOfRangeException(GetDouble(), VALUE_TYPE_DOUBLE,
                                       VALUE_TYPE_BIGINT);
      }
      return static_cast<int64_t>(GetDouble());
    default:
      throw CastException(type, VALUE_TYPE_BIGINT);
      return 0;  // NOT REACHED
  }
}

int64_t Value::CastAsRawInt64AndGetValue() const {
  const ValueType type = GetValueType();

  switch (type) {
    case VALUE_TYPE_TINYINT:
      return static_cast<int64_t>(GetTinyInt());
    case VALUE_TYPE_SMALLINT:
      return static_cast<int64_t>(GetSmallInt());
    case VALUE_TYPE_INTEGER:
      return static_cast<int64_t>(GetInteger());
    case VALUE_TYPE_BIGINT:
      return GetBigInt();
    case VALUE_TYPE_TIMESTAMP:
      return GetTimestamp();
    default:
      throw CastException(type, VALUE_TYPE_BIGINT);
      return 0;  // NOT REACHED
  }
}

double Value::CastAsDoubleAndGetValue() const {
  const ValueType type = GetValueType();
  if (IsNull()) {
    return DOUBLE_MIN;
  }

  switch (type) {
    case VALUE_TYPE_NULL:
      return DOUBLE_MIN;
    case VALUE_TYPE_TINYINT:
      return static_cast<double>(GetTinyInt());
    case VALUE_TYPE_SMALLINT:
      return static_cast<double>(GetSmallInt());
    case VALUE_TYPE_INTEGER:
      return static_cast<double>(GetInteger());
    case VALUE_TYPE_ADDRESS:
      return static_cast<double>(GetBigInt());
    case VALUE_TYPE_BIGINT:
      return static_cast<double>(GetBigInt());
    case VALUE_TYPE_TIMESTAMP:
      return static_cast<double>(GetTimestamp());
    case VALUE_TYPE_DOUBLE:
      return GetDouble();
    case VALUE_TYPE_VARCHAR:
    case VALUE_TYPE_VARBINARY:
    case VALUE_TYPE_DECIMAL:
    default:
      throw CastException(type, VALUE_TYPE_DOUBLE);
      return 0;  // NOT REACHED
  }
}

TTInt Value::CastAsDecimalAndGetValue() const {
  const ValueType type = GetValueType();
  if (IsNull()) {
    TTInt retval;
    retval.SetMin();
    return retval;
  }

  switch (type) {
    case VALUE_TYPE_TINYINT:
    case VALUE_TYPE_SMALLINT:
    case VALUE_TYPE_INTEGER:
    case VALUE_TYPE_BIGINT:
    case VALUE_TYPE_TIMESTAMP: {
      int64_t value = CastAsBigIntAndGetValue();
      TTInt retval(value);
      retval *= Value::max_decimal_scale_factor;
      return retval;
    }
    case VALUE_TYPE_DECIMAL:
      return GetDecimal();
    case VALUE_TYPE_VARCHAR:
    case VALUE_TYPE_VARBINARY:
    default:
      throw CastException(type, VALUE_TYPE_DOUBLE);
      return 0;  // NOT REACHED
  }
}

Value Value::CastAsBigInt() const {
  Value retval(VALUE_TYPE_BIGINT);
  const ValueType type = GetValueType();
  if (IsNull()) {<commit_msg>add support for decimal and double promotion<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// value.cpp
//
// Identification: src/backend/common/value.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "backend/common/value.h"
#include "backend/common/logger.h"

#include <cstdio>
#include <cstring>
#include <sstream>
#include <iostream>

namespace peloton {

// For x <op> y where x is an integer,
// promote x and y to s_intPromotionTable[y]
ValueType Value::IntPromotionTable[] = {
    VALUE_TYPE_INVALID,  // 0 invalid
    VALUE_TYPE_NULL,     // 1 null
    VALUE_TYPE_INVALID,  // 2 <unused>
    VALUE_TYPE_BIGINT,   // 3 tinyint
    VALUE_TYPE_BIGINT,   // 4 smallint
    VALUE_TYPE_BIGINT,   // 5 integer
    VALUE_TYPE_BIGINT,   // 6 bigint
    VALUE_TYPE_INVALID,  // 7 <unused>
    VALUE_TYPE_DOUBLE,   // 8 double
    VALUE_TYPE_INVALID,  // 9 varchar
    VALUE_TYPE_INVALID,  // 10 <unused>
    VALUE_TYPE_BIGINT,   // 11 timestamp

    // 12 - 21 unused
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID,

    VALUE_TYPE_DECIMAL,  // 22 decimal
    VALUE_TYPE_INVALID,  // 23 boolean
    VALUE_TYPE_INVALID,  // 24 address
};

// For x <op> y where x is a double
// promote x and y to s_doublePromotionTable[y]
ValueType Value::DoublePromotionTable[] = {
    VALUE_TYPE_INVALID,  // 0 invalid
    VALUE_TYPE_NULL,     // 1 null
    VALUE_TYPE_INVALID,  // 2 <unused>
    VALUE_TYPE_DOUBLE,   // 3 tinyint
    VALUE_TYPE_DOUBLE,   // 4 smallint
    VALUE_TYPE_DOUBLE,   // 5 integer
    VALUE_TYPE_DOUBLE,   // 6 bigint
    VALUE_TYPE_INVALID,  // 7 <unused>
    VALUE_TYPE_DOUBLE,   // 8 double
    VALUE_TYPE_INVALID,  // 9 varchar
    VALUE_TYPE_INVALID,  // 10 <unused>
    VALUE_TYPE_DOUBLE,   // 11 timestamp

    // 12 - 21 unused.
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID,

    VALUE_TYPE_DOUBLE,  // 22 decimal  (todo)
    VALUE_TYPE_INVALID,  // 23 boolean
    VALUE_TYPE_INVALID,  // 24 address
};

// for x <op> y where x is a decimal
// promote x and y to s_decimalPromotionTable[y]
ValueType Value::DecimalPromotionTable[] = {
    VALUE_TYPE_INVALID,  // 0 invalid
    VALUE_TYPE_NULL,     // 1 null
    VALUE_TYPE_INVALID,  // 2 <unused>
    VALUE_TYPE_DECIMAL,  // 3 tinyint
    VALUE_TYPE_DECIMAL,  // 4 smallint
    VALUE_TYPE_DECIMAL,  // 5 integer
    VALUE_TYPE_DECIMAL,  // 6 bigint
    VALUE_TYPE_INVALID,  // 7 <unused>
    VALUE_TYPE_DECIMAL,  // 8 double (todo)
    VALUE_TYPE_INVALID,  // 9 varchar
    VALUE_TYPE_INVALID,  // 10 <unused>
    VALUE_TYPE_DECIMAL,  // 11 timestamp

    // 12 - 21 unused. ick.
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID, VALUE_TYPE_INVALID, VALUE_TYPE_INVALID,
    VALUE_TYPE_INVALID,

    VALUE_TYPE_DECIMAL,  // 22 decimal
    VALUE_TYPE_INVALID,  // 23 boolean
    VALUE_TYPE_INVALID,  // 24 address
};

TTInt Value::MaxDecimal(
    "9999999999"  // 10 digits
    "9999999999"  // 20 digits
    "9999999999"  // 30 digits
    "99999999");  // 38 digits

TTInt Value::MinDecimal(
    "-9999999999"  // 10 digits
    "9999999999"   // 20 digits
    "9999999999"   // 30 digits
    "99999999");   // 38 digits

//===--------------------------------------------------------------------===//
// Type Cast and Getters
//===--------------------------------------------------------------------===//

int64_t Value::CastAsBigIntAndGetValue() const {
  const ValueType type = GetValueType();
  if (IsNull()) {
    return INT64_NULL;
  }

  switch (type) {
    case VALUE_TYPE_NULL:
      return INT64_NULL;
    case VALUE_TYPE_TINYINT:
      return static_cast<int64_t>(GetTinyInt());
    case VALUE_TYPE_SMALLINT:
      return static_cast<int64_t>(GetSmallInt());
    case VALUE_TYPE_INTEGER:
      return static_cast<int64_t>(GetInteger());
    case VALUE_TYPE_ADDRESS:
      return GetBigInt();
    case VALUE_TYPE_BIGINT:
      return GetBigInt();
    case VALUE_TYPE_TIMESTAMP:
      return GetTimestamp();
    case VALUE_TYPE_DOUBLE:
      if (GetDouble() > (double)INT64_MAX || GetDouble() < (double)INT64_MIN) {
        throw ValueOutOfRangeException(GetDouble(), VALUE_TYPE_DOUBLE,
                                       VALUE_TYPE_BIGINT);
      }
      return static_cast<int64_t>(GetDouble());
    default:
      throw CastException(type, VALUE_TYPE_BIGINT);
      return 0;  // NOT REACHED
  }
}

int64_t Value::CastAsRawInt64AndGetValue() const {
  const ValueType type = GetValueType();

  switch (type) {
    case VALUE_TYPE_TINYINT:
      return static_cast<int64_t>(GetTinyInt());
    case VALUE_TYPE_SMALLINT:
      return static_cast<int64_t>(GetSmallInt());
    case VALUE_TYPE_INTEGER:
      return static_cast<int64_t>(GetInteger());
    case VALUE_TYPE_BIGINT:
      return GetBigInt();
    case VALUE_TYPE_TIMESTAMP:
      return GetTimestamp();
    default:
      throw CastException(type, VALUE_TYPE_BIGINT);
      return 0;  // NOT REACHED
  }
}

double Value::CastAsDoubleAndGetValue() const {
  const ValueType type = GetValueType();
  if (IsNull()) {
    return DOUBLE_MIN;
  }

  switch (type) {
    case VALUE_TYPE_NULL:
      return DOUBLE_MIN;
    case VALUE_TYPE_TINYINT:
      return static_cast<double>(GetTinyInt());
    case VALUE_TYPE_SMALLINT:
      return static_cast<double>(GetSmallInt());
    case VALUE_TYPE_INTEGER:
      return static_cast<double>(GetInteger());
    case VALUE_TYPE_ADDRESS:
      return static_cast<double>(GetBigInt());
    case VALUE_TYPE_BIGINT:
      return static_cast<double>(GetBigInt());
    case VALUE_TYPE_TIMESTAMP:
      return static_cast<double>(GetTimestamp());
    case VALUE_TYPE_DOUBLE:
      return GetDouble();
    case VALUE_TYPE_VARCHAR:
    case VALUE_TYPE_VARBINARY:
    case VALUE_TYPE_DECIMAL: {
      std::string str_decimal = CreateStringFromDecimal();
      return std::stod(str_decimal);
    }
    default:
      throw CastException(type, VALUE_TYPE_DOUBLE);
      return 0;  // NOT REACHED
  }
}

TTInt Value::CastAsDecimalAndGetValue() const {
  const ValueType type = GetValueType();
  if (IsNull()) {
    TTInt retval;
    retval.SetMin();
    return retval;
  }

  switch (type) {
    case VALUE_TYPE_TINYINT:
    case VALUE_TYPE_SMALLINT:
    case VALUE_TYPE_INTEGER:
    case VALUE_TYPE_BIGINT:
    case VALUE_TYPE_TIMESTAMP: {
      int64_t value = CastAsBigIntAndGetValue();
      TTInt retval(value);
      retval *= Value::max_decimal_scale_factor;
      return retval;
    }
    case VALUE_TYPE_DECIMAL:
      return GetDecimal();
    case VALUE_TYPE_DOUBLE: {
      auto d = GetDouble();
      std::string str_double = std::to_string(d);
      Value decimal = GetDecimalValueFromString(str_double);
      return decimal.GetDecimal();
    }
    case VALUE_TYPE_VARCHAR:
    case VALUE_TYPE_VARBINARY:
    default:
      throw CastException(type, VALUE_TYPE_DOUBLE);
      return 0;  // NOT REACHED
  }
}

Value Value::CastAsBigInt() const {
  Value retval(VALUE_TYPE_BIGINT);
  const ValueType type = GetValueType();
  if (IsNull()) {
{'fraction_non_alphanumeric': 0.13493030179997292, 'fraction_numerical': 0.027337934767898225, 'mean_word_length': 2.6672456575682384, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 16, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4796239', 'n_tokens_mistral': 5311, 'n_tokens_neox': 4849, 'n_words': 1038}