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