LCOV - code coverage report
Current view: top level - src/catalog - Type.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 121 142 85.2 %
Date: 2025-03-25 01:19:55 Functions: 48 65 73.8 %
Branches: 76 142 53.5 %

           Branch data     Line data    Source code
       1                 :            : #include <mutable/catalog/Type.hpp>
       2                 :            : 
       3                 :            : 
       4                 :            : using namespace m;
       5                 :            : 
       6                 :            : 
       7                 :            : 
       8                 :            : constexpr const char * Numeric::KIND_TO_STR_[]; ///> declaration for constexpr static field, see C++17 inline variables
       9                 :            : 
      10                 :            : /*======================================================================================================================
      11                 :            :  * SQL Types
      12                 :            :  *====================================================================================================================*/
      13                 :            : 
      14                 :            : constexpr const char *Type::CATEGORY_TO_STR_[];
      15                 :            : 
      16                 :      28036 : uint64_t std::hash<m::Type>::operator()(const m::Type &type) const { return type.hash(); }
      17                 :            : 
      18                 :          1 : Pool<Type> Type::types_;
      19                 :            : 
      20                 :            : M_LCOV_EXCL_START
      21                 :            : void Type::dump() const { dump(std::cerr); }
      22                 :            : M_LCOV_EXCL_STOP
      23                 :            : 
      24                 :        519 : const Numeric * m::arithmetic_join(const Numeric *lhs, const Numeric *rhs)
      25                 :            : {
      26                 :            :     ///> factor to convert count of decimal digits to binary digits
      27                 :            :     static constexpr double LOG_2_OF_10 = 3.321928094887362;
      28                 :            : 
      29                 :            :     /* Combining a vector with a scalar yields a vector. */
      30                 :        519 :     Type::category_t category = std::max(lhs->category, rhs->category);
      31                 :            : 
      32                 :            :     /* N_Decimal is always "more precise" than N_Float.  N_Float is always more precise than N_Int.  */
      33                 :        519 :     Numeric::kind_t kind = std::max(lhs->kind, rhs->kind);
      34                 :            : 
      35                 :            :     /* Compute the precision in bits. */
      36                 :            :     unsigned precision_lhs, precision_rhs;
      37   [ +  -  +  + ]:        519 :     switch (lhs->kind) {
      38                 :        424 :         case Numeric::N_Int:     precision_lhs = 8 * lhs->precision; break;
      39                 :         67 :         case Numeric::N_Float:   precision_lhs = lhs->precision; break;
      40                 :         28 :         case Numeric::N_Decimal: precision_lhs = std::ceil(LOG_2_OF_10 * lhs->precision); break;
      41                 :            :     }
      42   [ +  -  +  + ]:        519 :     switch (rhs->kind) {
      43                 :        467 :         case Numeric::N_Int:     precision_rhs = 8 * rhs->precision; break;
      44                 :         32 :         case Numeric::N_Float:   precision_rhs = rhs->precision; break;
      45                 :         20 :         case Numeric::N_Decimal: precision_rhs = std::ceil(LOG_2_OF_10 * rhs->precision); break;
      46                 :            :     }
      47                 :        519 :     int precision = std::max(precision_lhs, precision_rhs);
      48                 :        519 :     int scale = std::max(lhs->scale, rhs->scale);
      49                 :            : 
      50   [ +  +  +  - ]:        519 :     switch (kind) {
      51         [ +  - ]:        405 :         case Numeric::N_Int: return Type::Get_Integer(category, precision / 8);
      52                 :            :         case Numeric::N_Float: {
      53   [ +  +  -  + ]:         70 :             if (precision == 32) return Type::Get_Float(category);
      54                 :         54 :             M_insist(precision == 64, "Illegal floating-point precision");
      55         [ -  + ]:         54 :             return Type::Get_Double(category);
      56                 :            :         }
      57                 :            : 
      58         [ +  - ]:         44 :         case Numeric::N_Decimal: return Type::Get_Decimal(category, precision / LOG_2_OF_10, scale);
      59                 :          0 :     }
      60                 :        519 : }
      61                 :            : 
      62                 :            : /*===== Factory Methods ==============================================================================================*/
      63                 :            : 
      64         [ +  - ]:       6350 : Type::Pooled<ErrorType> Type::Get_Error() { return types_(ErrorType{}); }
      65                 :            : 
      66         [ +  - ]:       4109 : Type::Pooled<NoneType> Type::Get_None() { return types_(NoneType{}); }
      67                 :            : 
      68         [ +  - ]:       1891 : Type::Pooled<Boolean> Type::Get_Boolean(category_t category) { return types_(Boolean{category}); }
      69                 :            : 
      70                 :        344 : Type::Pooled<Bitmap> Type::Get_Bitmap(category_t category, std::size_t length)
      71                 :            : {
      72         [ +  - ]:        344 :     return types_(Bitmap{category, length});
      73                 :          0 : }
      74                 :          1 : 
      75                 :        406 : Type::Pooled<CharacterSequence> Type::Get_Char(category_t category, std::size_t length)
      76                 :            : {
      77         [ +  - ]:        406 :     return types_(CharacterSequence{category, length, false});
      78                 :          0 : }
      79                 :            : 
      80                 :         47 : Type::Pooled<CharacterSequence> Type::Get_Varchar(category_t category, std::size_t length)
      81                 :            : {
      82         [ +  - ]:         47 :     return types_(CharacterSequence{category, length, true});
      83                 :          0 : }
      84                 :            : 
      85         [ +  - ]:         32 : Type::Pooled<Date> Type::Get_Date(category_t category) { return types_(Date{category}); }
      86                 :            : 
      87         [ +  - ]:         22 : Type::Pooled<DateTime> Type::Get_Datetime(category_t category) { return types_(DateTime{category}); }
      88                 :            : 
      89                 :        272 : Type::Pooled<Numeric> Type::Get_Decimal(category_t category, unsigned digits, unsigned scale)
      90                 :            : {
      91         [ +  - ]:        272 :     return types_(Numeric{category, Numeric::N_Decimal, digits, scale});
      92                 :          0 : }
      93                 :            : 
      94                 :       5149 : Type::Pooled<Numeric> Type::Get_Integer(category_t category, unsigned num_bytes)
      95                 :            : {
      96         [ +  - ]:       5149 :     return types_(Numeric{category, Numeric::N_Int, num_bytes, 0});
      97                 :          0 : }
      98                 :            : 
      99                 :        327 : Type::Pooled<Numeric> Type::Get_Float(category_t category)
     100                 :            : {
     101         [ +  - ]:        327 :     return types_(Numeric{category, Numeric::N_Float, 32, 0});
     102                 :          0 : }
     103                 :            : 
     104                 :        385 : Type::Pooled<Numeric> Type::Get_Double(category_t category)
     105                 :            : {
     106         [ +  - ]:        385 :     return types_(Numeric{category, Numeric::N_Float, 64, 0});
     107                 :          0 : }
     108                 :            : 
     109                 :         88 : Type::Pooled<FnType> Type::Get_Function(const Type *return_type, std::vector<const Type*> parameter_types)
     110                 :            : {
     111   [ +  -  -  + ]:         88 :     return types_(FnType{return_type, parameter_types});
     112                 :          0 : }
     113                 :            : 
     114                 :            : /*===== Type visitor =================================================================================================*/
     115                 :            : 
     116                 :            : #define ACCEPT(TYPE) \
     117                 :            :     void TYPE::accept(TypeVisitor &v) { v(*this); } \
     118                 :            :     void TYPE::accept(ConstTypeVisitor &v) const { v(*this); }
     119                 :        258 : M_TYPE_LIST(ACCEPT)
     120                 :            : #undef ACCEPT
     121                 :            : 
     122                 :            : /*===== Comparison ===================================================================================================*/
     123                 :            : 
     124                 :       7056 : bool ErrorType::operator==(const Type &other) const { return is<const ErrorType>(&other); }
     125                 :            : 
     126                 :       4108 : bool NoneType::operator==(const Type &other) const { return is<const NoneType>(&other); }
     127                 :            : 
     128                 :       2671 : bool Boolean::operator==(const Type &other) const
     129                 :            : {
     130         [ +  + ]:       2671 :     if (auto o = cast<const Boolean>(&other))
     131                 :       1949 :         return this->category == o->category;
     132                 :        722 :     return false;
     133                 :       2671 : }
     134                 :            : 
     135                 :        468 : bool Bitmap::operator==(const Type &other) const
     136                 :            : {
     137         [ +  + ]:        468 :     if (auto o = cast<const Bitmap>(&other))
     138         [ +  - ]:        335 :         return this->category == o->category and this->length == o->length;
     139                 :        133 :     return false;
     140                 :        468 : }
     141                 :            : 
     142                 :        657 : bool CharacterSequence::operator==(const Type &other) const
     143                 :            : {
     144         [ +  + ]:        657 :     if (auto o = cast<const CharacterSequence>(&other))
     145   [ +  -  +  - ]:        501 :         return this->category == o->category and this->is_varying == o->is_varying and this->length == o->length;
     146                 :        156 :     return false;
     147                 :        657 : }
     148                 :            : 
     149                 :         34 : bool Date::operator==(const Type &other) const
     150                 :            : {
     151         [ +  + ]:         34 :     if (auto o = cast<const Date>(&other))
     152                 :         30 :         return this->category == o->category;
     153                 :          4 :     return false;
     154                 :         34 : }
     155                 :            : 
     156                 :         24 : bool DateTime::operator==(const Type &other) const
     157                 :            : {
     158         [ +  + ]:         24 :     if (auto o = cast<const DateTime>(&other))
     159                 :         20 :         return this->category == o->category;
     160                 :          4 :     return false;
     161                 :         24 : }
     162                 :            : 
     163                 :      14689 : bool Numeric::operator==(const Type &other) const
     164                 :            : {
     165         [ +  + ]:      14689 :     if (auto o = cast<const Numeric>(&other)) {
     166         [ +  - ]:      29320 :         return this->category == o->category and
     167         [ +  - ]:      14660 :                this->kind == o->kind and
     168         [ +  - ]:      14660 :                this->precision == o->precision and
     169                 :      14660 :                this->scale == o->scale;
     170                 :            :     }
     171                 :         29 :     return false;
     172                 :      14689 : }
     173                 :            : 
     174                 :         80 : bool FnType::operator==(const Type &other) const
     175                 :            : {
     176         [ +  + ]:         80 :     if (auto o = cast<const FnType>(&other)) {
     177         [ -  + ]:         78 :         if (this->return_type != o->return_type) return false; // return types must match
     178         [ -  + ]:         78 :         if (this->parameter_types.size() != o->parameter_types.size()) return false; // parameter count must match
     179         [ +  + ]:        136 :         for (std::size_t i = 0, end = parameter_types.size(); i != end; ++i)
     180         [ +  - ]:         58 :             if (this->parameter_types[i] != o->parameter_types[i]) return false; // parameters must have same type
     181                 :         78 :         return true;
     182                 :            :     }
     183                 :          2 :     return false;
     184                 :         80 : }
     185                 :            : 
     186                 :            : /*===== Hash =========================================================================================================*/
     187                 :            : 
     188                 :       6351 : uint64_t ErrorType::hash() const { return 0; }
     189                 :            : 
     190                 :       4110 : uint64_t NoneType::hash() const { return -1UL; }
     191                 :            : 
     192                 :       1901 : uint64_t Boolean::hash() const { return 0b10UL | uint64_t(category); }
     193                 :            : 
     194                 :        353 : uint64_t Bitmap::hash() const
     195                 :            : {
     196                 :        353 :     return uint64_t(length) << 1 | uint64_t(category);
     197                 :            : }
     198                 :            : 
     199                 :        535 : uint64_t CharacterSequence::hash() const
     200                 :            : {
     201                 :        535 :     return uint64_t(length) << 2 | uint64_t(is_varying) << 1 | uint64_t(category);
     202                 :            : }
     203                 :            : 
     204                 :         34 : uint64_t Date::hash() const { return 0b100UL | uint64_t(category); }
     205                 :            : 
     206                 :         24 : uint64_t DateTime::hash() const { return 0b1000UL | uint64_t(category); }
     207                 :            : 
     208                 :      14804 : uint64_t Numeric::hash() const
     209                 :            : {
     210                 :      14804 :     return ((uint64_t(precision) << 32) ^ (uint64_t(scale) << 3) ^ (uint64_t(kind) << 1)) | uint64_t(category);
     211                 :            : }
     212                 :            : 
     213                 :         98 : uint64_t FnType::hash() const
     214                 :            : {
     215                 :         98 :     auto h = return_type->hash();
     216         [ +  + ]:        174 :     for (auto p : parameter_types)
     217                 :         76 :         h = (h << 7) ^ p->hash();
     218                 :         98 :     return h;
     219                 :            : }
     220                 :            : 
     221                 :            : /*===== Scalar & Vector Conversion ===================================================================================*/
     222                 :            : 
     223         [ +  - ]:          5 : const PrimitiveType * Boolean::as_scalar() const { return Type::Get_Boolean(TY_Scalar); }
     224                 :            : 
     225         [ +  - ]:        456 : const PrimitiveType * Boolean::as_vectorial() const { return Type::Get_Boolean(TY_Vector); }
     226                 :            : 
     227                 :          0 : const PrimitiveType * Bitmap::as_scalar() const
     228                 :            : {
     229         [ #  # ]:          0 :     if (is_scalar()) return this;
     230   [ #  #  #  #  :          0 :     return as<const Bitmap>(&*types_(Bitmap(TY_Scalar, length)));
                   #  # ]
     231                 :          0 : }
     232                 :          0 : const PrimitiveType * Bitmap::as_vectorial() const
     233                 :            : {
     234         [ #  # ]:          0 :     if (is_vectorial()) return this;
     235   [ #  #  #  #  :          0 :     return as<const Bitmap>(&*types_(Bitmap(TY_Vector, length)));
                   #  # ]
     236                 :          0 : }
     237                 :            : 
     238                 :          2 : const PrimitiveType * CharacterSequence::as_scalar() const
     239                 :            : {
     240         [ +  + ]:          2 :     if (is_scalar()) return this;
     241   [ +  -  +  -  :          1 :     return as<const CharacterSequence>(&*types_(CharacterSequence(TY_Scalar, length, is_varying)));
                   +  - ]
     242                 :          2 : }
     243                 :        128 : const PrimitiveType * CharacterSequence::as_vectorial() const
     244                 :            : {
     245         [ +  + ]:        128 :     if (is_vectorial()) return this;
     246   [ +  -  +  -  :         49 :     return as<const CharacterSequence>(&*types_(CharacterSequence(TY_Vector, length, is_varying)));
                   +  - ]
     247                 :        128 : }
     248                 :            : 
     249         [ #  # ]:          0 : const PrimitiveType * Date::as_scalar() const { return Type::Get_Date(TY_Scalar); }
     250                 :            : 
     251         [ +  - ]:          2 : const PrimitiveType * Date::as_vectorial() const { return Type::Get_Date(TY_Vector); }
     252                 :            : 
     253         [ #  # ]:          0 : const PrimitiveType * DateTime::as_scalar() const { return Type::Get_Datetime(TY_Scalar); }
     254                 :            : 
     255         [ +  - ]:          2 : const PrimitiveType * DateTime::as_vectorial() const { return Type::Get_Datetime(TY_Vector); }
     256                 :            : 
     257                 :        147 : const PrimitiveType * Numeric::as_scalar() const
     258                 :            : {
     259   [ +  -  +  -  :        147 :     return as<const Numeric>(&*types_(Numeric(TY_Scalar, kind, precision, scale)));
                   +  - ]
     260                 :          0 : }
     261                 :       8322 : const PrimitiveType * Numeric::as_vectorial() const
     262                 :            : {
     263   [ +  -  +  -  :       8322 :     return as<const Numeric>(&*types_(Numeric(TY_Vector, kind, precision, scale)));
                   +  - ]
     264                 :          0 : }
     265                 :            : 
     266                 :            : /*===== Pretty Printing ==============================================================================================*/
     267                 :            : 
     268                 :            : M_LCOV_EXCL_START
     269                 :            : void ErrorType::print(std::ostream &out) const { out << "[ErrorType]"; }
     270                 :            : 
     271                 :            : void NoneType::print(std::ostream &out) const { out << "[none]"; }
     272                 :            : 
     273                 :            : void Boolean::print(std::ostream &out) const { out << "BOOL"; }
     274                 :            : 
     275                 :            : void Bitmap::print(std::ostream &out) const { out << "BITMAP" << '(' << length << ')'; }
     276                 :            : 
     277                 :            : void CharacterSequence::print(std::ostream &out) const
     278                 :            : {
     279                 :            :     out << ( is_varying ? "VARCHAR" : "CHAR" ) << '(' << length << ')';
     280                 :            : }
     281                 :            : 
     282                 :            : void Date::print(std::ostream &out) const { out << "DATE"; }
     283                 :            : 
     284                 :            : void DateTime::print(std::ostream &out) const { out << "DATETIME"; }
     285                 :            : 
     286                 :            : void Numeric::print(std::ostream &out) const
     287                 :            : {
     288                 :            :     switch (kind) {
     289                 :            :         case N_Int:
     290                 :            :             out << "INT(" << precision << ')';
     291                 :            :             break;
     292                 :            : 
     293                 :            :         case N_Float:
     294                 :            :             if (precision == 32) out << "FLOAT";
     295                 :            :             else if (precision == 64) out << "DOUBLE";
     296                 :            :             else out << "[IllegalFloatingPoint]";
     297                 :            :             break;
     298                 :            : 
     299                 :            :         case N_Decimal: {
     300                 :            :             out << "DECIMAL(" << precision << ", " << scale << ')';
     301                 :            :             break;
     302                 :            :         }
     303                 :            :     }
     304                 :            : }
     305                 :            : 
     306                 :            : void FnType::print(std::ostream &out) const
     307                 :            : {
     308                 :            :     out << '(';
     309                 :            :     for (auto it = parameter_types.cbegin(), end = parameter_types.cend(); it != end; ++it) {
     310                 :            :         if (it != parameter_types.cbegin()) out << ", ";
     311                 :            :         out << **it;
     312                 :            :     }
     313                 :            :     out << ") -> " << *return_type;
     314                 :            : }
     315                 :            : M_LCOV_EXCL_STOP
     316                 :            : 
     317                 :            : /*===== Dump =========================================================================================================*/
     318                 :            : 
     319                 :            : M_LCOV_EXCL_START
     320                 :            : void ErrorType::dump(std::ostream &out) const { out << "[ErrorType]" << std::endl; }
     321                 :            : 
     322                 :            : void NoneType::dump(std::ostream &out) const { out << "[NoneType]" << std::endl; }
     323                 :            : 
     324                 :            : void Boolean::dump(std::ostream &out) const
     325                 :            : {
     326                 :            :     out << "Boolean{ category = " << CATEGORY_TO_STR_[category] << " }" << std::endl;
     327                 :            : }
     328                 :            : 
     329                 :            : void Bitmap::dump(std::ostream &out) const
     330                 :            : {
     331                 :            :     out << "Bitmap{ category = " << CATEGORY_TO_STR_[category] << ", length = " << length << " }" << std::endl;
     332                 :            : }
     333                 :            : 
     334                 :            : void CharacterSequence::dump(std::ostream &out) const
     335                 :            : {
     336                 :            :     out << "CharacterSequence{ category = " << CATEGORY_TO_STR_[category] << ", is_varying = "
     337                 :            :         << (is_varying ? "true" : "false") << ", length = " << length << " }" << std::endl;
     338                 :            : }
     339                 :            : 
     340                 :            : void Date::dump(std::ostream &out) const
     341                 :            : {
     342                 :            :     out << "Date{ category = " << CATEGORY_TO_STR_[category] << " }" << std::endl;
     343                 :            : }
     344                 :            : 
     345                 :            : void DateTime::dump(std::ostream &out) const
     346                 :            : {
     347                 :            :     out << "DateTime{ category = " << CATEGORY_TO_STR_[category] << " }" << std::endl;
     348                 :            : }
     349                 :            : 
     350                 :            : void Numeric::dump(std::ostream &out) const
     351                 :            : {
     352                 :            :     out << "Numeric{ category = " << CATEGORY_TO_STR_[category] << ", kind = " << Numeric::KIND_TO_STR_[kind]
     353                 :            :         << ", precision = " << precision << ", scale = " << scale << " }" << std::endl;
     354                 :            : }
     355                 :            : 
     356                 :            : void FnType::dump(std::ostream &out) const
     357                 :            : {
     358                 :            :     out << "FnType{\n    return_type: ";
     359                 :            :     return_type->dump(out);
     360                 :            :     out << "    parameter_types: {\n";
     361                 :            :     for (auto p :parameter_types) {
     362                 :            :         out << "        ";
     363                 :            :         p->dump(out);
     364                 :            :     }
     365                 :            :     out << '}' << std::endl;
     366                 :            : }
     367                 :            : M_LCOV_EXCL_STOP

Generated by: LCOV version 1.16