Branch data Line data Source code
1 : : #include <mutable/IR/Tuple.hpp> 2 : : 3 : : #include <ctime> 4 : : #include <mutable/catalog/Schema.hpp> 5 : : #include <mutable/catalog/Type.hpp> 6 : : #include <mutable/util/fn.hpp> 7 : : 8 : : 9 : : using namespace m; 10 : : 11 : : 12 : : /*====================================================================================================================== 13 : : Value 14 : : *====================================================================================================================*/ 15 : : 16 : : M_LCOV_EXCL_START 17 : : void Value::print(std::ostream &out, const Type &ty) const 18 : : { 19 : : visit(overloaded { 20 : : [this, &out](const Boolean&) { out << (as_b() ? "TRUE" : "FALSE"); }, 21 : : [this, &out](const CharacterSequence &cs) { out << '"'; out.write(as<const char*>(), cs.length); out << '"'; }, 22 : : [this, &out](const Date&) { 23 : : const int32_t date = as_i(); // signed because year is signed 24 : : const auto oldfill = out.fill('0'); 25 : : const auto oldfmt = out.flags(); 26 : : out << std::internal 27 : : << std::setw(date >> 9 > 0 ? 4 : 5) << (date >> 9) << '-' 28 : : << std::setw(2) << ((date >> 5) & 0xF) << '-' 29 : : << std::setw(2) << (date & 0x1F); 30 : : out.fill(oldfill); 31 : : out.flags(oldfmt); 32 : : }, 33 : : [this, &out](const DateTime&) { 34 : : const time_t time = as_i(); 35 : : std::tm tm; 36 : : gmtime_r(&time, &tm); 37 : : out << put_tm(tm); 38 : : }, 39 : : [this, &out](const Numeric &n) { 40 : : switch (n.kind) { 41 : : case Numeric::N_Int: 42 : : out << as_i(); 43 : : break; 44 : : 45 : : case Numeric::N_Decimal: { 46 : : const int64_t div = powi(10L, n.scale); 47 : : const int64_t pre = as_i() / div; 48 : : const int64_t post = as_i() % div; 49 : : out << pre << '.'; 50 : : auto old_fill = out.fill('0'); 51 : : out << std::setw(n.scale) << post; 52 : : out.fill(old_fill); 53 : : break; 54 : : } 55 : : 56 : : case Numeric::N_Float: 57 : : if (n.size() == 32) 58 : : out << as_f(); 59 : : else 60 : : out << as_d(); 61 : : break; 62 : : } 63 : : }, 64 : : [](auto&&) { M_unreachable("invalid value type"); } 65 : : }, ty); 66 : : } 67 : : 68 : : void Value::dump(std::ostream &out) const { out << *this << std::endl; } 69 : : void Value::dump() const { dump(std::cerr); } 70 : : M_LCOV_EXCL_STOP 71 : : 72 : : 73 : : /*====================================================================================================================== 74 : 1 : Tuple 75 : : *====================================================================================================================*/ 76 : : 77 : 11387 : Tuple::Tuple(const Schema &S) 78 : : #ifdef M_ENABLE_SANITY_FIELDS 79 : : : num_values_(S.num_entries()) 80 : : #endif 81 : : { 82 : 11387 : std::size_t additional_bytes = 0; 83 [ + + ]: 62090 : for (auto &e : S) { 84 [ + + ]: 50703 : if (auto cs = cast<const CharacterSequence>(e.type)) 85 : 3277 : additional_bytes += cs->length + 1; 86 : : } 87 : 11387 : values_ = (Value*) malloc(S.num_entries() * sizeof(Value) + additional_bytes); 88 : 11387 : uint8_t *p = reinterpret_cast<uint8_t*>(values_) + S.num_entries() * sizeof(Value); 89 [ + + ]: 62090 : for (std::size_t i = 0; i != S.num_entries(); ++i) { 90 [ + + ]: 50703 : if (auto cs = cast<const CharacterSequence>(S[i].type)) { 91 : 3277 : new (&values_[i]) Value(p); 92 : 3277 : *p = '\0'; // terminating NUL byte 93 : 3277 : p += cs->length + 1; 94 : 3277 : } else { 95 : 47426 : new (&values_[i]) Value(); 96 : : } 97 : 50703 : } 98 : 11387 : clear(); 99 : 11387 : } 100 : : 101 : 345 : Tuple::Tuple(std::vector<const Type*> types) 102 : : #ifdef M_ENABLE_SANITY_FIELDS 103 : : : num_values_(types.size()) 104 : : #endif 105 : : { 106 : 345 : std::size_t additional_bytes = 0; 107 [ + + ]: 746 : for (auto &ty : types) { 108 [ + + ]: 401 : if (auto cs = cast<const CharacterSequence>(ty)) 109 : 5 : additional_bytes += cs->length + 1; 110 : : } 111 : 345 : values_ = (Value*) malloc(types.size() * sizeof(Value) + additional_bytes); 112 : 345 : uint8_t *p = reinterpret_cast<uint8_t*>(values_) + types.size() * sizeof(Value); 113 [ + + ]: 746 : for (std::size_t i = 0; i != types.size(); ++i) { 114 [ + + ]: 401 : if (auto cs = cast<const CharacterSequence>(types[i])) { 115 : 5 : new (&values_[i]) Value(p); 116 : 5 : p += cs->length + 1; 117 : 5 : } else { 118 : 396 : new (&values_[i]) Value(); 119 : : } 120 : 401 : } 121 : 345 : clear(); 122 : 345 : } 123 : : 124 : 0 : Tuple Tuple::clone(const Schema &S) const 125 : : { 126 : 0 : Tuple cpy(S); 127 [ # # # # ]: 0 : for (std::size_t i = 0; i != S.num_entries(); ++i) { 128 [ # # # # : 0 : if (S[i].type->is_character_sequence()) { # # ] 129 [ # # # # : 0 : strcpy(reinterpret_cast<char*>(cpy[i].as_p()), reinterpret_cast<char*>((*this)[i].as_p())); # # # # ] 130 [ # # ]: 0 : cpy.not_null(i); 131 : 0 : } else { 132 [ # # # # ]: 0 : cpy.set(i, (*this)[i]); 133 : : } 134 : 0 : } 135 : 0 : return cpy; 136 [ # # ]: 0 : } 137 : : 138 : : M_LCOV_EXCL_START 139 : : void Tuple::print(std::ostream &out, const Schema &schema) const 140 : : { 141 : : for (std::size_t i = 0; i != schema.num_entries(); ++i) { 142 : : if (i != 0) out << ','; 143 : : if (is_null(i)) 144 : : out << "NULL"; 145 : : else 146 : : values_[i].print(out, *schema[i].type); 147 : : } 148 : : } 149 : : 150 : : void Tuple::dump(std::ostream &out) const { out << *this << std::endl; } 151 : : void Tuple::dump() const { dump(std::cerr); } 152 : : M_LCOV_EXCL_STOP