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
|