1 /* Copyright (C) 2014 InfiniDB, Inc.
2 Copyright (C) 2019 MariaDB Corporation
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; version 2 of
7 the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 MA 02110-1301, USA. */
18
19 // $Id: treenode.h 9635 2013-06-19 21:42:30Z bwilkinson $
20
21
22 /** @file */
23
24 #ifndef CALPONT_TREENODE_H
25 #define CALPONT_TREENODE_H
26
27 #include <string>
28 #include <iostream>
29 #include <cmath>
30 #include <boost/shared_ptr.hpp>
31
32 #include <stdlib.h>
33 #include <unistd.h>
34
35 #include "calpontsystemcatalog.h"
36 #include "exceptclasses.h"
37 #include "dataconvert.h"
38
39 namespace messageqcpp
40 {
41 class ByteStream;
42 }
43
44 namespace rowgroup
45 {
46 class Row;
47 }
48
49 /**
50 * Namespace
51 */
52 namespace execplan
53 {
54
55 typedef execplan::CalpontSystemCatalog::ColType Type;
56
57
58 /**
59 * @brief IDB_Decimal type
60 *
61 */
62 struct IDB_Decimal
63 {
IDB_DecimalIDB_Decimal64 IDB_Decimal(): value(0), scale(0), precision(0) {}
IDB_DecimalIDB_Decimal65 IDB_Decimal(int64_t val, int8_t s, uint8_t p) :
66 value (val),
67 scale(s),
68 precision(p) {}
69
decimalCompIDB_Decimal70 int decimalComp(const IDB_Decimal& d) const
71 {
72 lldiv_t d1 = lldiv(value, IDB_pow[scale]);
73 lldiv_t d2 = lldiv(d.value, IDB_pow[d.scale]);
74
75 int ret = 0;
76
77 if (d1.quot > d2.quot)
78 {
79 ret = 1;
80 }
81 else if (d1.quot < d2.quot)
82 {
83 ret = -1;
84 }
85 else
86 {
87 // rem carries the value's sign, but needs to be normalized.
88 int64_t s = scale - d.scale;
89
90 if (s < 0)
91 {
92 if ((d1.rem * IDB_pow[-s]) > d2.rem)
93 ret = 1;
94 else if ((d1.rem * IDB_pow[-s]) < d2.rem)
95 ret = -1;
96 }
97 else
98 {
99 if (d1.rem > (d2.rem * IDB_pow[s]))
100 ret = 1;
101 else if (d1.rem < (d2.rem * IDB_pow[s]))
102 ret = -1;
103 }
104 }
105
106 return ret;
107 }
108
109 bool operator==(const IDB_Decimal& rhs) const
110 {
111 if (scale == rhs.scale)
112 return value == rhs.value;
113 else
114 return (decimalComp(rhs) == 0);
115 }
116 bool operator>(const IDB_Decimal& rhs) const
117 {
118 if (scale == rhs.scale)
119 return value > rhs.value;
120 else
121 return (decimalComp(rhs) > 0);
122 }
123 bool operator<(const IDB_Decimal& rhs) const
124 {
125 if (scale == rhs.scale)
126 return value < rhs.value;
127 else
128 return (decimalComp(rhs) < 0);
129 }
130 bool operator>=(const IDB_Decimal& rhs) const
131 {
132 if (scale == rhs.scale)
133 return value >= rhs.value;
134 else
135 return (decimalComp(rhs) >= 0);
136 }
137 bool operator<=(const IDB_Decimal& rhs) const
138 {
139 if (scale == rhs.scale)
140 return value <= rhs.value;
141 else
142 return (decimalComp(rhs) <= 0);
143 }
144 bool operator!=(const IDB_Decimal& rhs) const
145 {
146 if (scale == rhs.scale)
147 return value != rhs.value;
148 else
149 return (decimalComp(rhs) != 0);
150 }
151
152 int64_t value;
153 int8_t scale; // 0~18
154 uint8_t precision; // 1~18
155 };
156 typedef IDB_Decimal CNX_Decimal;
157
158 /**
159 * @brief IDB_Regex struct
160 *
161 */
162 #ifdef POSIX_REGEX
163 typedef regex_t IDB_Regex;
164 #else
165 typedef boost::regex IDB_Regex;
166 #endif
167
168 typedef IDB_Regex CNX_Regex;
169
170 typedef boost::shared_ptr<IDB_Regex> SP_IDB_Regex;
171 typedef SP_IDB_Regex SP_CNX_Regex;
172
173 /** Trim trailing 0 from val. All insignificant zeroes to the right of the
174 * decimal point are removed. Also, the decimal point is not included on
175 * whole numbers. It works like %g flag with printf, but always print
176 * double value in fixed-point notation.
177 *
178 * @parm val valid double value in fixed-point notation from printf %f.
179 * No format validation is perfomed in this function.
180 * @parm length length of the buffer val
181 */
removeTrailing0(char * val,uint32_t length)182 inline std::string removeTrailing0(char* val, uint32_t length)
183 {
184 char* ptr = val;
185 int64_t i = 0;
186 bool decimal_point = false;
187
188 for (; i < length; i++, ptr++)
189 {
190 if (*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9'))
191 {
192 continue;
193 }
194
195 if (*ptr == '.')
196 {
197 decimal_point = true;
198 continue;
199 }
200
201 *ptr = 0;
202 break;
203 }
204
205 if (decimal_point)
206 {
207 for (i = i - 1; i >= 0; i--)
208 {
209 if (val[i] == '0')
210 {
211 val[i] = 0;
212 }
213 else if (val[i] == '.')
214 {
215 val[i] = 0;
216 break;
217 }
218 else
219 {
220 break;
221 }
222 }
223 }
224
225 return std::string(val);
226 }
227
228 /**
229 * @brief Result type added for F&E framework
230 *
231 */
232 struct Result
233 {
ResultResult234 Result(): intVal(0), uintVal(0), origIntVal(0), dummy(0),
235 doubleVal(0), longDoubleVal(0), floatVal(0), boolVal(false),
236 strVal(""), decimalVal(IDB_Decimal(0, 0, 0)),
237 valueConverted(false) {}
238 int64_t intVal;
239 uint64_t uintVal;
240 uint64_t origIntVal;
241 // clear up the memory following origIntVal to make sure null terminated string
242 // when converting origIntVal
243 uint64_t dummy;
244 double doubleVal;
245 long double longDoubleVal;
246 float floatVal;
247 bool boolVal;
248 std::string strVal;
249 IDB_Decimal decimalVal;
250 bool valueConverted;
251 };
252
253 /**
254 * @brief An abstract class to represent a node data on the expression tree
255 *
256 */
257 class TreeNode
258 {
259 public:
260 TreeNode();
261 TreeNode(const TreeNode& rhs);
262 virtual ~TreeNode();
263 virtual const std::string data() const = 0;
264 virtual void data(const std::string data) = 0;
265 virtual const std::string toString() const = 0;
266 virtual TreeNode* clone() const = 0;
267
268 /**
269 * Interface for serialization
270 */
271
272 /** @brief Convert *this to a stream of bytes
273 *
274 * Convert *this to a stream of bytes.
275 * @param b The ByteStream to add *this to.
276 */
277 virtual void serialize(messageqcpp::ByteStream& b) const = 0;
278
279 /** @brief Construct a TreeNode from a stream of bytes
280 *
281 * Construct a TreeNode from a stream of bytes.
282 * @param b The ByteStream to parse
283 * @return The newly allocated TreeNode
284 */
285 virtual void unserialize(messageqcpp::ByteStream& b) = 0;
286
287 /** @brief Do a deep, strict (as opposed to semantic) equivalence test
288 *
289 * Do a deep, strict (as opposed to semantic) equivalence test.
290 * @return true iff every member of t is a duplicate copy of every member of this; false otherwise
291 */
292 virtual bool operator==(const TreeNode* t) const = 0;
293
294 /** @brief Do a deep, strict (as opposed to semantic) equivalence test
295 *
296 * Do a deep, strict (as opposed to semantic) equivalence test.
297 * @return false iff every member of t is a duplicate copy of every member of this; true otherwise
298 */
299 virtual bool operator!=(const TreeNode* t) const = 0;
300
301 // derivedTable mutator and accessor
derivedTable()302 virtual const std::string& derivedTable() const
303 {
304 return fDerivedTable;
305 }
306
derivedTable(const std::string & derivedTable)307 virtual void derivedTable(const std::string& derivedTable)
308 {
309 fDerivedTable = derivedTable;
310 }
311
312 // must to be implented by treenode that could potentially belong to
313 // one single derived table
setDerivedTable()314 virtual void setDerivedTable()
315 {
316 fDerivedTable = "";
317 }
318
derivedRefCol()319 virtual TreeNode* derivedRefCol() const
320 {
321 return fDerivedRefCol;
322 }
323
derivedRefCol(TreeNode * derivedRefCol)324 virtual void derivedRefCol(TreeNode* derivedRefCol)
325 {
326 fDerivedRefCol = derivedRefCol;
327 }
328
refCount()329 virtual uint64_t refCount() const
330 {
331 return fRefCount;
332 }
333
refCount(const uint64_t refCount)334 virtual void refCount (const uint64_t refCount)
335 {
336 fRefCount = refCount;
337 }
338
339 // the inc and dec functions areparm[n]->data() used by connector single thread.
decRefCount()340 virtual void decRefCount()
341 {
342 fRefCount--;
343 }
344
incRefCount()345 virtual void incRefCount()
346 {
347 fRefCount++;
348 }
349
350 /***********************************************************************
351 * F&E framework *
352 ***********************************************************************/
getStrVal(rowgroup::Row & row,bool & isNull)353 virtual const std::string& getStrVal(rowgroup::Row& row, bool& isNull)
354 {
355 return fResult.strVal;
356 }
getIntVal(rowgroup::Row & row,bool & isNull)357 virtual int64_t getIntVal(rowgroup::Row& row, bool& isNull)
358 {
359 return fResult.intVal;
360 }
getUintVal(rowgroup::Row & row,bool & isNull)361 virtual uint64_t getUintVal(rowgroup::Row& row, bool& isNull)
362 {
363 return fResult.uintVal;
364 }
getFloatVal(rowgroup::Row & row,bool & isNull)365 virtual float getFloatVal(rowgroup::Row& row, bool& isNull)
366 {
367 return fResult.floatVal;
368 }
getDoubleVal(rowgroup::Row & row,bool & isNull)369 virtual double getDoubleVal(rowgroup::Row& row, bool& isNull)
370 {
371 return fResult.doubleVal;
372 }
getLongDoubleVal(rowgroup::Row & row,bool & isNull)373 virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull)
374 {
375 return fResult.longDoubleVal;
376 }
getDecimalVal(rowgroup::Row & row,bool & isNull)377 virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull)
378 {
379 return fResult.decimalVal;
380 }
getBoolVal(rowgroup::Row & row,bool & isNull)381 virtual bool getBoolVal(rowgroup::Row& row, bool& isNull)
382 {
383 return fResult.boolVal;
384 }
getDateIntVal(rowgroup::Row & row,bool & isNull)385 virtual int32_t getDateIntVal(rowgroup::Row& row, bool& isNull)
386 {
387 return fResult.intVal;
388 }
getDatetimeIntVal(rowgroup::Row & row,bool & isNull)389 virtual int64_t getDatetimeIntVal(rowgroup::Row& row, bool& isNull)
390 {
391 return fResult.intVal;
392 }
getTimestampIntVal(rowgroup::Row & row,bool & isNull)393 virtual int64_t getTimestampIntVal(rowgroup::Row& row, bool& isNull)
394 {
395 return fResult.intVal;
396 }
getTimeIntVal(rowgroup::Row & row,bool & isNull)397 virtual int64_t getTimeIntVal(rowgroup::Row& row, bool& isNull)
398 {
399 return fResult.intVal;
400 }
evaluate(rowgroup::Row & row,bool & isNull)401 virtual void evaluate(rowgroup::Row& row, bool& isNull) {}
402
403 inline bool getBoolVal();
404 inline const std::string& getStrVal(const std::string& timeZone);
405 inline int64_t getIntVal();
406 inline uint64_t getUintVal();
407 inline float getFloatVal();
408 inline double getDoubleVal();
409 inline long double getLongDoubleVal();
410 inline IDB_Decimal getDecimalVal();
411 inline int32_t getDateIntVal();
412 inline int64_t getDatetimeIntVal();
413 inline int64_t getTimestampIntVal();
414 inline int64_t getTimeIntVal();
415
resultType()416 virtual const execplan::CalpontSystemCatalog::ColType& resultType() const
417 {
418 return fResultType;
419 }
resultType()420 virtual execplan::CalpontSystemCatalog::ColType& resultType()
421 {
422 return fResultType;
423 }
424 virtual void resultType ( const execplan::CalpontSystemCatalog::ColType& resultType ) ;
operationType(const Type & type)425 virtual void operationType(const Type& type)
426 {
427 fOperationType = type;
428 }
operationType()429 virtual const execplan::CalpontSystemCatalog::ColType& operationType() const
430 {
431 return fOperationType;
432 }
433
434 // result mutator and accessor. for speical functor to set for optimization.
result(const Result & result)435 virtual void result(const Result& result)
436 {
437 fResult = result;
438 }
result()439 virtual const Result& result() const
440 {
441 return fResult;
442 }
443
charsetNumber()444 uint32_t charsetNumber() const
445 {
446 return fResultType.charsetNumber;
447 }
charsetNumber(uint32_t cnum)448 void charsetNumber(uint32_t cnum)
449 {
450 fResultType.charsetNumber = cnum;
451 fOperationType.charsetNumber = cnum;
452 }
453
454 protected:
455 Result fResult;
456 execplan::CalpontSystemCatalog::ColType fResultType; // mapped from mysql data type
457 execplan::CalpontSystemCatalog::ColType fOperationType; // operator type, could be different from the result type
458
459 // double's range is +/-1.7E308 with at least 15 digits of precision
460 char tmp[312]; // for conversion use
461
462 // @bug5635 If any item involved in this filter belongs to a derived table,
463 // the derived table alias is added to the reference vector.
464 std::string fDerivedTable;
465 uint64_t fRefCount;
466 TreeNode* fDerivedRefCol;
467
468 private:
469 //default okay
470 //TreeNode& operator=(const TreeNode& rhs);
471 };
472
getBoolVal()473 inline bool TreeNode::getBoolVal()
474 {
475 switch (fResultType.colDataType)
476 {
477 case CalpontSystemCatalog::CHAR:
478 if (fResultType.colWidth <= 8)
479 return (atoi((char*)(&fResult.origIntVal)) != 0);
480
481 return (atoi(fResult.strVal.c_str()) != 0);
482
483 case CalpontSystemCatalog::VARCHAR:
484 if (fResultType.colWidth <= 7)
485 return (atoi((char*)(&fResult.origIntVal)) != 0);
486
487 return (atoi(fResult.strVal.c_str()) != 0);
488
489 //FIXME: Huh???
490 case CalpontSystemCatalog::VARBINARY:
491 case CalpontSystemCatalog::BLOB:
492 case CalpontSystemCatalog::TEXT:
493 if (fResultType.colWidth <= 7)
494 return (atoi((char*)(&fResult.origIntVal)) != 0);
495
496 return (atoi(fResult.strVal.c_str()) != 0);
497
498 case CalpontSystemCatalog::BIGINT:
499 case CalpontSystemCatalog::SMALLINT:
500 case CalpontSystemCatalog::MEDINT:
501 case CalpontSystemCatalog::TINYINT:
502 case CalpontSystemCatalog::INT:
503 case CalpontSystemCatalog::DATE:
504 case CalpontSystemCatalog::DATETIME:
505 case CalpontSystemCatalog::TIMESTAMP:
506 case CalpontSystemCatalog::TIME:
507 return (fResult.intVal != 0);
508
509 case CalpontSystemCatalog::UBIGINT:
510 case CalpontSystemCatalog::USMALLINT:
511 case CalpontSystemCatalog::UMEDINT:
512 case CalpontSystemCatalog::UTINYINT:
513 case CalpontSystemCatalog::UINT:
514 return (fResult.uintVal != 0);
515
516 case CalpontSystemCatalog::FLOAT:
517 case CalpontSystemCatalog::UFLOAT:
518 return (fResult.floatVal != 0);
519
520 case CalpontSystemCatalog::DOUBLE:
521 case CalpontSystemCatalog::UDOUBLE:
522 return (fResult.doubleVal != 0);
523
524 case CalpontSystemCatalog::LONGDOUBLE:
525 return (fResult.longDoubleVal != 0);
526
527 case CalpontSystemCatalog::DECIMAL:
528 case CalpontSystemCatalog::UDECIMAL:
529 return (fResult.decimalVal.value != 0);
530
531 default:
532 throw logging::InvalidConversionExcept("TreeNode::getBoolVal: Invalid conversion.");
533 }
534
535 return fResult.boolVal;
536 }
537
getStrVal(const std::string & timeZone)538 inline const std::string& TreeNode::getStrVal(const std::string& timeZone)
539 {
540 switch (fResultType.colDataType)
541 {
542 case CalpontSystemCatalog::CHAR:
543 if (fResultType.colWidth <= 8)
544 fResult.strVal = (char*)(&fResult.origIntVal);
545
546 break;
547
548 case CalpontSystemCatalog::VARCHAR:
549 if (fResultType.colWidth <= 7)
550 fResult.strVal = (char*)(&fResult.origIntVal);
551
552 break;
553
554 //FIXME: ???
555 case CalpontSystemCatalog::VARBINARY:
556 case CalpontSystemCatalog::BLOB:
557 case CalpontSystemCatalog::TEXT:
558 if (fResultType.colWidth <= 7)
559 fResult.strVal = (char*)(&fResult.origIntVal);
560
561 break;
562
563 case CalpontSystemCatalog::BIGINT:
564 case CalpontSystemCatalog::SMALLINT:
565 case CalpontSystemCatalog::MEDINT:
566 case CalpontSystemCatalog::TINYINT:
567 case CalpontSystemCatalog::INT:
568 {
569 #ifndef __LP64__
570 snprintf(tmp, 20, "%lld", fResult.intVal);
571 #else
572 snprintf(tmp, 20, "%ld", fResult.intVal);
573 #endif
574 fResult.strVal = std::string(tmp);
575 break;
576 }
577
578 case CalpontSystemCatalog::UBIGINT:
579 case CalpontSystemCatalog::USMALLINT:
580 case CalpontSystemCatalog::UMEDINT:
581 case CalpontSystemCatalog::UTINYINT:
582 case CalpontSystemCatalog::UINT:
583 {
584 #ifndef __LP64__
585 snprintf(tmp, 20, "%llu", fResult.uintVal);
586 #else
587 snprintf(tmp, 20, "%lu", fResult.uintVal);
588 #endif
589 fResult.strVal = std::string(tmp);
590 break;
591 }
592
593 case CalpontSystemCatalog::FLOAT:
594 case CalpontSystemCatalog::UFLOAT:
595 {
596 if ((fabs(fResult.floatVal) > (1.0 / IDB_pow[4])) &&
597 (fabs(fResult.floatVal) < (float) IDB_pow[6]))
598 {
599 snprintf(tmp, 312, "%f", fResult.floatVal);
600 fResult.strVal = removeTrailing0(tmp, 312);
601 }
602 else
603 {
604 // MCOL-299 Print scientific with 5 mantissa and no + sign for exponent
605 int exponent = (int)floor(log10( fabs(fResult.floatVal))); // This will round down the exponent
606 double base = fResult.floatVal * pow(10, -1.0 * exponent);
607
608 if (std::isnan(exponent) || std::isnan(base))
609 {
610 snprintf(tmp, 312, "%f", fResult.floatVal);
611 fResult.strVal = removeTrailing0(tmp, 312);
612 }
613 else
614 {
615 snprintf(tmp, 312, "%.5f", base);
616 fResult.strVal = removeTrailing0(tmp, 312);
617 snprintf(tmp, 312, "e%02d", exponent);
618 fResult.strVal += tmp;
619 }
620
621 // snprintf(tmp, 312, "%e.5", fResult.floatVal);
622 // fResult.strVal = tmp;
623 }
624
625 break;
626 }
627
628 case CalpontSystemCatalog::DOUBLE:
629 case CalpontSystemCatalog::UDOUBLE:
630 {
631 if ((fabs(fResult.doubleVal) > (1.0 / IDB_pow[13])) &&
632 (fabs(fResult.doubleVal) < (float) IDB_pow[15]))
633 {
634 snprintf(tmp, 312, "%f", fResult.doubleVal);
635 fResult.strVal = removeTrailing0(tmp, 312);
636 }
637 else
638 {
639 // MCOL-299 Print scientific with 9 mantissa and no + sign for exponent
640 int exponent = (int)floor(log10( fabs(fResult.doubleVal))); // This will round down the exponent
641 double base = fResult.doubleVal * pow(10, -1.0 * exponent);
642
643 if (std::isnan(exponent) || std::isnan(base))
644 {
645 snprintf(tmp, 312, "%f", fResult.doubleVal);
646 fResult.strVal = removeTrailing0(tmp, 312);
647 }
648 else
649 {
650 snprintf(tmp, 312, "%.9f", base);
651 fResult.strVal = removeTrailing0(tmp, 312);
652 snprintf(tmp, 312, "e%02d", exponent);
653 fResult.strVal += tmp;
654 }
655
656 // snprintf(tmp, 312, "%e", fResult.doubleVal);
657 // fResult.strVal = tmp;
658 }
659
660 break;
661 }
662
663 case CalpontSystemCatalog::LONGDOUBLE:
664 {
665 if ((fabsl(fResult.longDoubleVal) > (1.0 / IDB_pow[13])) &&
666 (fabsl(fResult.longDoubleVal) < (float) IDB_pow[15]))
667 {
668 snprintf(tmp, 312, "%Lf", fResult.longDoubleVal);
669 fResult.strVal = removeTrailing0(tmp, 312);
670 }
671 else
672 {
673 // MCOL-299 Print scientific with 9 mantissa and no + sign for exponent
674 int exponent = (int)floorl(log10( fabsl(fResult.longDoubleVal))); // This will round down the exponent
675 long double base = fResult.longDoubleVal * pow(10, -1.0 * exponent);
676
677 if (std::isnan(exponent) || std::isnan(base))
678 {
679 snprintf(tmp, 312, "%Lf", fResult.longDoubleVal);
680 fResult.strVal = removeTrailing0(tmp, 312);
681 }
682 else
683 {
684 snprintf(tmp, 312, "%.14Lf", base);
685 fResult.strVal = removeTrailing0(tmp, 312);
686 snprintf(tmp, 312, "e%02d", exponent);
687 fResult.strVal += tmp;
688 }
689
690 // snprintf(tmp, 312, "%e", fResult.doubleVal);
691 // fResult.strVal = tmp;
692 }
693
694 break;
695 }
696
697 case CalpontSystemCatalog::DECIMAL:
698 case CalpontSystemCatalog::UDECIMAL:
699 {
700 dataconvert::DataConvert::decimalToString(fResult.decimalVal.value, fResult.decimalVal.scale, tmp, 22, fResultType.colDataType);
701 fResult.strVal = std::string(tmp);
702 break;
703 }
704
705 case CalpontSystemCatalog::DATE:
706 {
707 dataconvert::DataConvert::dateToString(fResult.intVal, tmp, 255);
708 fResult.strVal = std::string(tmp);
709 break;
710 }
711
712 case CalpontSystemCatalog::DATETIME:
713 {
714 dataconvert::DataConvert::datetimeToString(fResult.intVal, tmp, 255, fResultType.precision);
715 fResult.strVal = std::string(tmp);
716 break;
717 }
718
719 case CalpontSystemCatalog::TIMESTAMP:
720 {
721 dataconvert::DataConvert::timestampToString(fResult.intVal, tmp, 255, timeZone, fResultType.precision);
722 fResult.strVal = std::string(tmp);
723 break;
724 }
725
726 case CalpontSystemCatalog::TIME:
727 {
728 dataconvert::DataConvert::timeToString(fResult.intVal, tmp, 255, fResultType.precision);
729 fResult.strVal = std::string(tmp);
730 break;
731 }
732
733 default:
734 throw logging::InvalidConversionExcept("TreeNode::getStrVal: Invalid conversion.");
735 }
736
737 return fResult.strVal;
738 }
739
getIntVal()740 inline int64_t TreeNode::getIntVal()
741 {
742 switch (fResultType.colDataType)
743 {
744 case CalpontSystemCatalog::CHAR:
745 if (fResultType.colWidth <= 8)
746 return fResult.intVal;
747
748 return atoll(fResult.strVal.c_str());
749
750 case CalpontSystemCatalog::VARCHAR:
751 if (fResultType.colWidth <= 7)
752 return fResult.intVal;
753
754 return atoll(fResult.strVal.c_str());
755
756 //FIXME: ???
757 case CalpontSystemCatalog::VARBINARY:
758 case CalpontSystemCatalog::BLOB:
759 case CalpontSystemCatalog::TEXT:
760 if (fResultType.colWidth <= 7)
761 return fResult.intVal;
762
763 return atoll(fResult.strVal.c_str());
764
765 case CalpontSystemCatalog::BIGINT:
766 case CalpontSystemCatalog::TINYINT:
767 case CalpontSystemCatalog::SMALLINT:
768 case CalpontSystemCatalog::MEDINT:
769 case CalpontSystemCatalog::INT:
770 return fResult.intVal;
771
772 case CalpontSystemCatalog::UBIGINT:
773 case CalpontSystemCatalog::UTINYINT:
774 case CalpontSystemCatalog::USMALLINT:
775 case CalpontSystemCatalog::UMEDINT:
776 case CalpontSystemCatalog::UINT:
777 return fResult.uintVal;
778
779 case CalpontSystemCatalog::FLOAT:
780 case CalpontSystemCatalog::UFLOAT:
781 return (int64_t)fResult.floatVal;
782
783 case CalpontSystemCatalog::DOUBLE:
784 case CalpontSystemCatalog::UDOUBLE:
785 return (int64_t)fResult.doubleVal;
786
787 case CalpontSystemCatalog::LONGDOUBLE:
788 return (int64_t)fResult.longDoubleVal;
789
790 case CalpontSystemCatalog::DECIMAL:
791 case CalpontSystemCatalog::UDECIMAL:
792 {
793 return (int64_t)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
794 }
795
796 case CalpontSystemCatalog::DATE:
797 case CalpontSystemCatalog::DATETIME:
798 case CalpontSystemCatalog::TIMESTAMP:
799 case CalpontSystemCatalog::TIME:
800 return fResult.intVal;
801
802 default:
803 throw logging::InvalidConversionExcept("TreeNode::getIntVal: Invalid conversion.");
804 }
805
806 return fResult.intVal;
807 }
getUintVal()808 inline uint64_t TreeNode::getUintVal()
809 {
810 switch (fResultType.colDataType)
811 {
812 case CalpontSystemCatalog::BIGINT:
813 case CalpontSystemCatalog::TINYINT:
814 case CalpontSystemCatalog::SMALLINT:
815 case CalpontSystemCatalog::MEDINT:
816 case CalpontSystemCatalog::INT:
817 return fResult.intVal;
818
819 case CalpontSystemCatalog::UBIGINT:
820 case CalpontSystemCatalog::UTINYINT:
821 case CalpontSystemCatalog::USMALLINT:
822 case CalpontSystemCatalog::UMEDINT:
823 case CalpontSystemCatalog::UINT:
824 return fResult.uintVal;
825
826 case CalpontSystemCatalog::FLOAT:
827 case CalpontSystemCatalog::UFLOAT:
828 return (uint64_t)fResult.floatVal;
829
830 case CalpontSystemCatalog::DOUBLE:
831 case CalpontSystemCatalog::UDOUBLE:
832 return (uint64_t)fResult.doubleVal;
833
834 case CalpontSystemCatalog::LONGDOUBLE:
835 return (uint64_t)fResult.longDoubleVal;
836
837 case CalpontSystemCatalog::DECIMAL:
838 case CalpontSystemCatalog::UDECIMAL:
839 {
840 return (uint64_t)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
841 }
842
843 case CalpontSystemCatalog::DATE:
844 case CalpontSystemCatalog::DATETIME:
845 case CalpontSystemCatalog::TIMESTAMP:
846 case CalpontSystemCatalog::TIME:
847 return fResult.intVal;
848
849 default:
850 throw logging::InvalidConversionExcept("TreeNode::getIntVal: Invalid conversion.");
851 }
852
853 return fResult.intVal;
854 }
getFloatVal()855 inline float TreeNode::getFloatVal()
856 {
857 switch (fResultType.colDataType)
858 {
859 case CalpontSystemCatalog::CHAR:
860 if (fResultType.colWidth <= 8)
861 return atof((char*)(&fResult.origIntVal));
862
863 return atof(fResult.strVal.c_str());
864
865 case CalpontSystemCatalog::VARCHAR:
866 if (fResultType.colWidth <= 7)
867 return atof((char*)(&fResult.origIntVal));
868
869 return atof(fResult.strVal.c_str());
870
871 //FIXME: ???
872 case CalpontSystemCatalog::VARBINARY:
873 case CalpontSystemCatalog::BLOB:
874 case CalpontSystemCatalog::TEXT:
875 if (fResultType.colWidth <= 7)
876 return atof((char*)(&fResult.origIntVal));
877
878 return atof(fResult.strVal.c_str());
879
880 case CalpontSystemCatalog::BIGINT:
881 case CalpontSystemCatalog::TINYINT:
882 case CalpontSystemCatalog::SMALLINT:
883 case CalpontSystemCatalog::MEDINT:
884 case CalpontSystemCatalog::INT:
885 return (float)fResult.intVal;
886
887 case CalpontSystemCatalog::UBIGINT:
888 case CalpontSystemCatalog::UTINYINT:
889 case CalpontSystemCatalog::USMALLINT:
890 case CalpontSystemCatalog::UMEDINT:
891 case CalpontSystemCatalog::UINT:
892 return (float)fResult.uintVal;
893
894 case CalpontSystemCatalog::FLOAT:
895 case CalpontSystemCatalog::UFLOAT:
896 return fResult.floatVal;
897
898 case CalpontSystemCatalog::DOUBLE:
899 case CalpontSystemCatalog::UDOUBLE:
900 return (float)fResult.doubleVal;
901
902 case CalpontSystemCatalog::LONGDOUBLE:
903 return (float)fResult.doubleVal;
904
905 case CalpontSystemCatalog::DECIMAL:
906 {
907 return (fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
908 }
909
910 case CalpontSystemCatalog::DATE:
911 case CalpontSystemCatalog::DATETIME:
912 case CalpontSystemCatalog::TIMESTAMP:
913 case CalpontSystemCatalog::TIME:
914 return (float)fResult.intVal;
915
916 default:
917 throw logging::InvalidConversionExcept("TreeNode::getFloatVal: Invalid conversion.");
918 }
919
920 return fResult.floatVal;
921 }
getDoubleVal()922 inline double TreeNode::getDoubleVal()
923 {
924 switch (fResultType.colDataType)
925 {
926 case CalpontSystemCatalog::CHAR:
927 if (fResultType.colWidth <= 8)
928 return strtod((char*)(&fResult.origIntVal), NULL);
929
930 return strtod(fResult.strVal.c_str(), NULL);
931
932 case CalpontSystemCatalog::VARCHAR:
933 if (fResultType.colWidth <= 7)
934 return strtod((char*)(&fResult.origIntVal), NULL);
935
936 return strtod(fResult.strVal.c_str(), NULL);
937
938 //FIXME: ???
939 case CalpontSystemCatalog::VARBINARY:
940 case CalpontSystemCatalog::BLOB:
941 case CalpontSystemCatalog::TEXT:
942 if (fResultType.colWidth <= 7)
943 return strtod((char*)(&fResult.origIntVal), NULL);
944
945 return strtod(fResult.strVal.c_str(), NULL);
946
947 case CalpontSystemCatalog::BIGINT:
948 case CalpontSystemCatalog::TINYINT:
949 case CalpontSystemCatalog::SMALLINT:
950 case CalpontSystemCatalog::MEDINT:
951 case CalpontSystemCatalog::INT:
952 return (double)fResult.intVal;
953
954 case CalpontSystemCatalog::UBIGINT:
955 case CalpontSystemCatalog::UTINYINT:
956 case CalpontSystemCatalog::USMALLINT:
957 case CalpontSystemCatalog::UMEDINT:
958 case CalpontSystemCatalog::UINT:
959 return (double)fResult.uintVal;
960
961 case CalpontSystemCatalog::FLOAT:
962 case CalpontSystemCatalog::UFLOAT:
963 return (double)fResult.floatVal;
964
965 case CalpontSystemCatalog::DOUBLE:
966 case CalpontSystemCatalog::UDOUBLE:
967 return fResult.doubleVal;
968
969 case CalpontSystemCatalog::LONGDOUBLE:
970 return (double)fResult.longDoubleVal;
971
972 case CalpontSystemCatalog::DECIMAL:
973 case CalpontSystemCatalog::UDECIMAL:
974 {
975 // this may not be accurate. if this is problematic, change to pre-calculated power array.
976 return (double)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
977 }
978
979 case CalpontSystemCatalog::DATE:
980 case CalpontSystemCatalog::DATETIME:
981 case CalpontSystemCatalog::TIMESTAMP:
982 case CalpontSystemCatalog::TIME:
983 return (double)fResult.intVal;
984
985 default:
986 throw logging::InvalidConversionExcept("TreeNode::getDoubleVal: Invalid conversion.");
987 }
988
989 return fResult.doubleVal;
990 }
getLongDoubleVal()991 inline long double TreeNode::getLongDoubleVal()
992 {
993 switch (fResultType.colDataType)
994 {
995 case CalpontSystemCatalog::CHAR:
996 if (fResultType.colWidth <= 8)
997 return strtold((char*)(&fResult.origIntVal), NULL);
998
999 return strtold(fResult.strVal.c_str(), NULL);
1000
1001 case CalpontSystemCatalog::VARCHAR:
1002 if (fResultType.colWidth <= 7)
1003 return strtold((char*)(&fResult.origIntVal), NULL);
1004
1005 return strtold(fResult.strVal.c_str(), NULL);
1006
1007 //FIXME: ???
1008 case CalpontSystemCatalog::VARBINARY:
1009 case CalpontSystemCatalog::BLOB:
1010 case CalpontSystemCatalog::TEXT:
1011 if (fResultType.colWidth <= 7)
1012 return strtold((char*)(&fResult.origIntVal), NULL);
1013
1014 return strtold(fResult.strVal.c_str(), NULL);
1015
1016 case CalpontSystemCatalog::BIGINT:
1017 case CalpontSystemCatalog::TINYINT:
1018 case CalpontSystemCatalog::SMALLINT:
1019 case CalpontSystemCatalog::MEDINT:
1020 case CalpontSystemCatalog::INT:
1021 return (long double)fResult.intVal;
1022
1023 case CalpontSystemCatalog::UBIGINT:
1024 case CalpontSystemCatalog::UTINYINT:
1025 case CalpontSystemCatalog::USMALLINT:
1026 case CalpontSystemCatalog::UMEDINT:
1027 case CalpontSystemCatalog::UINT:
1028 return (long double)fResult.uintVal;
1029
1030 case CalpontSystemCatalog::FLOAT:
1031 case CalpontSystemCatalog::UFLOAT:
1032 return (long double)fResult.floatVal;
1033
1034 case CalpontSystemCatalog::DOUBLE:
1035 case CalpontSystemCatalog::UDOUBLE:
1036 return (long double)fResult.doubleVal;
1037
1038 case CalpontSystemCatalog::LONGDOUBLE:
1039 return (long double)fResult.longDoubleVal;
1040
1041 case CalpontSystemCatalog::DECIMAL:
1042 case CalpontSystemCatalog::UDECIMAL:
1043 {
1044 // this may not be accurate. if this is problematic, change to pre-calculated power array.
1045 return (long double)(fResult.decimalVal.value / pow((long double)10, fResult.decimalVal.scale));
1046 }
1047
1048 case CalpontSystemCatalog::DATE:
1049 case CalpontSystemCatalog::DATETIME:
1050 case CalpontSystemCatalog::TIME:
1051 return (long double)fResult.intVal;
1052
1053 default:
1054 throw logging::InvalidConversionExcept("TreeNode::getDoubleVal: Invalid conversion.");
1055 }
1056
1057 return fResult.doubleVal;
1058 }
getDecimalVal()1059 inline IDB_Decimal TreeNode::getDecimalVal()
1060 {
1061 switch (fResultType.colDataType)
1062 {
1063 case CalpontSystemCatalog::CHAR:
1064 case CalpontSystemCatalog::VARCHAR:
1065 case CalpontSystemCatalog::TEXT:
1066 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from string");
1067
1068 case CalpontSystemCatalog::VARBINARY:
1069 case CalpontSystemCatalog::BLOB:
1070 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from binary string");
1071
1072 case CalpontSystemCatalog::BIGINT:
1073 case CalpontSystemCatalog::MEDINT:
1074 case CalpontSystemCatalog::INT:
1075 case CalpontSystemCatalog::SMALLINT:
1076 case CalpontSystemCatalog::TINYINT:
1077 fResult.decimalVal.value = (int64_t)(fResult.intVal * pow((double)10.0, fResultType.scale));
1078 fResult.decimalVal.scale = fResultType.scale;
1079 fResult.decimalVal.precision = fResultType.precision;
1080 break;
1081
1082 case CalpontSystemCatalog::UBIGINT:
1083 case CalpontSystemCatalog::UMEDINT:
1084 case CalpontSystemCatalog::UINT:
1085 case CalpontSystemCatalog::USMALLINT:
1086 case CalpontSystemCatalog::UTINYINT:
1087 fResult.decimalVal.value = (int64_t)(fResult.uintVal * pow((double)10.0, fResultType.scale));
1088 fResult.decimalVal.scale = fResultType.scale;
1089 fResult.decimalVal.precision = fResultType.precision;
1090 break;
1091
1092 case CalpontSystemCatalog::LONGDOUBLE:
1093 {
1094 long double dlScaled = fResult.longDoubleVal;
1095 if (fResultType.scale > 0)
1096 {
1097 dlScaled= fResult.longDoubleVal * pow((double)10.0, fResultType.scale);
1098 }
1099 if (dlScaled > (double)MAX_BIGINT)
1100 {
1101 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: decimal overflow.");
1102 }
1103 fResult.decimalVal.value = (int64_t)roundl((fResult.longDoubleVal * pow((double)10.0, fResultType.scale)));
1104 fResult.decimalVal.scale = fResultType.scale;
1105 fResult.decimalVal.precision = fResultType.precision;
1106 }
1107 break;
1108
1109 case CalpontSystemCatalog::DATE:
1110 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion from date.");
1111
1112 case CalpontSystemCatalog::DATETIME:
1113 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion from datetime.");
1114
1115 case CalpontSystemCatalog::TIMESTAMP:
1116 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion from timestamp.");
1117
1118 case CalpontSystemCatalog::TIME:
1119 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion from time.");
1120
1121 case CalpontSystemCatalog::FLOAT:
1122 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from float");
1123
1124 case CalpontSystemCatalog::UFLOAT:
1125 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from float unsigned");
1126
1127 case CalpontSystemCatalog::DOUBLE:
1128 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from double");
1129
1130 case CalpontSystemCatalog::UDOUBLE:
1131 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from double unsigned");
1132
1133 case CalpontSystemCatalog::DECIMAL:
1134 case CalpontSystemCatalog::UDECIMAL:
1135 return fResult.decimalVal;
1136
1137 default:
1138 throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion.");
1139 }
1140
1141 return fResult.decimalVal;
1142 }
1143
getDatetimeIntVal()1144 inline int64_t TreeNode::getDatetimeIntVal()
1145 {
1146 if (fResultType.colDataType == execplan::CalpontSystemCatalog::DATE)
1147 return (fResult.intVal & 0x00000000FFFFFFC0LL) << 32;
1148 else if (fResultType.colDataType == execplan::CalpontSystemCatalog::TIME)
1149 {
1150 dataconvert::Time tt;
1151 int day = 0;
1152
1153 void *ttp = static_cast<void*>(&tt);
1154
1155 memcpy(ttp, &fResult.intVal, 8);
1156
1157 // Note, this should probably be current date +/- time
1158 if ((tt.hour > 23) && (!tt.is_neg))
1159 {
1160 day = tt.hour / 24;
1161 tt.hour = tt.hour % 24;
1162 }
1163 else if ((tt.hour < 0) || (tt.is_neg))
1164 {
1165 tt.hour = 0;
1166 }
1167
1168 dataconvert::DateTime dt(0, 0, day, tt.hour, tt.minute, tt.second, tt.msecond);
1169 memcpy(&fResult.intVal, &dt, 8);
1170 return fResult.intVal;
1171 }
1172 else if (fResultType.colDataType == execplan::CalpontSystemCatalog::DATETIME)
1173 //return (fResult.intVal & 0xFFFFFFFFFFF00000LL);
1174 return (fResult.intVal);
1175 else
1176 return getIntVal();
1177 }
1178
getTimestampIntVal()1179 inline int64_t TreeNode::getTimestampIntVal()
1180 {
1181 if (fResultType.colDataType == execplan::CalpontSystemCatalog::TIMESTAMP)
1182 return fResult.intVal;
1183 else
1184 return getIntVal();
1185 }
1186
getTimeIntVal()1187 inline int64_t TreeNode::getTimeIntVal()
1188 {
1189 if (fResultType.colDataType == execplan::CalpontSystemCatalog::DATETIME)
1190 {
1191 dataconvert::DateTime dt;
1192
1193 memcpy((int64_t*)(&dt), &fResult.intVal, 8);
1194 dataconvert::Time tt(0, dt.hour, dt.minute, dt.second, dt.msecond, false);
1195 memcpy(&fResult.intVal, &tt, 8);
1196 return fResult.intVal;
1197 }
1198 else if (fResultType.colDataType == execplan::CalpontSystemCatalog::TIME)
1199 return (fResult.intVal);
1200 else
1201 return getIntVal();
1202 }
1203
getDateIntVal()1204 inline int32_t TreeNode::getDateIntVal()
1205 {
1206 if (fResultType.colDataType == execplan::CalpontSystemCatalog::DATETIME)
1207 return (((int32_t)(fResult.intVal >> 32) & 0xFFFFFFC0) | 0x3E);
1208 else if (fResultType.colDataType == execplan::CalpontSystemCatalog::DATE)
1209 return ((fResult.intVal & 0xFFFFFFC0) | 0x3E);
1210 else
1211 return getIntVal();
1212 }
1213
1214 typedef boost::shared_ptr<TreeNode> STNP;
1215
1216 /**
1217 * Operations
1218 */
1219 std::ostream& operator<<(std::ostream& output, const TreeNode& rhs);
1220
1221 }
1222
1223 #endif
1224