1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-06-12 05:01:56 +03:00
Files
mariadb-columnstore-engine/dbcon/execplan/treenode.h
2019-04-17 17:28:47 -05:00

1203 lines
36 KiB
C++

/* Copyright (C) 2014 InfiniDB, Inc.
Copyright (C) 2019 MariaDB Corporaton
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
// $Id: treenode.h 9635 2013-06-19 21:42:30Z bwilkinson $
/** @file */
#ifndef CALPONT_TREENODE_H
#define CALPONT_TREENODE_H
#include <string>
#include <iostream>
#include <cmath>
#include <boost/shared_ptr.hpp>
#ifdef _MSC_VER
#include <boost/regex.hpp>
#else
#include <regex.h>
#endif
#include <stdlib.h>
#include <unistd.h>
#include "calpontsystemcatalog.h"
#include "exceptclasses.h"
#include "dataconvert.h"
// Workaround for my_global.h #define of isnan(X) causing a std::std namespace
using namespace std;
namespace messageqcpp
{
class ByteStream;
}
namespace rowgroup
{
class Row;
}
/**
* Namespace
*/
namespace execplan
{
typedef execplan::CalpontSystemCatalog::ColType Type;
/**
* @brief IDB_Decimal type
*
*/
struct IDB_Decimal
{
IDB_Decimal(): value(0), scale(0), precision(0) {}
IDB_Decimal(int64_t val, int8_t s, uint8_t p) :
value (val),
scale(s),
precision(p) {}
int decimalComp(const IDB_Decimal& d) const
{
lldiv_t d1 = lldiv(value, IDB_pow[scale]);
lldiv_t d2 = lldiv(d.value, IDB_pow[d.scale]);
int ret = 0;
if (d1.quot > d2.quot)
{
ret = 1;
}
else if (d1.quot < d2.quot)
{
ret = -1;
}
else
{
// rem carries the value's sign, but needs to be normalized.
int64_t s = scale - d.scale;
if (s < 0)
{
if ((d1.rem * IDB_pow[-s]) > d2.rem)
ret = 1;
else if ((d1.rem * IDB_pow[-s]) < d2.rem)
ret = -1;
}
else
{
if (d1.rem > (d2.rem * IDB_pow[s]))
ret = 1;
else if (d1.rem < (d2.rem * IDB_pow[s]))
ret = -1;
}
}
return ret;
}
bool operator==(const IDB_Decimal& rhs) const
{
if (scale == rhs.scale)
return value == rhs.value;
else
return (decimalComp(rhs) == 0);
}
bool operator>(const IDB_Decimal& rhs) const
{
if (scale == rhs.scale)
return value > rhs.value;
else
return (decimalComp(rhs) > 0);
}
bool operator<(const IDB_Decimal& rhs) const
{
if (scale == rhs.scale)
return value < rhs.value;
else
return (decimalComp(rhs) < 0);
}
bool operator>=(const IDB_Decimal& rhs) const
{
if (scale == rhs.scale)
return value >= rhs.value;
else
return (decimalComp(rhs) >= 0);
}
bool operator<=(const IDB_Decimal& rhs) const
{
if (scale == rhs.scale)
return value <= rhs.value;
else
return (decimalComp(rhs) <= 0);
}
bool operator!=(const IDB_Decimal& rhs) const
{
if (scale == rhs.scale)
return value != rhs.value;
else
return (decimalComp(rhs) != 0);
}
int64_t value;
int8_t scale; // 0~18
uint8_t precision; // 1~18
};
typedef IDB_Decimal CNX_Decimal;
/**
* @brief IDB_Regex struct
*
*/
#ifdef _MSC_VER
typedef boost::regex IDB_Regex;
#else
typedef regex_t IDB_Regex;
#endif
typedef IDB_Regex CNX_Regex;
typedef boost::shared_ptr<IDB_Regex> SP_IDB_Regex;
typedef SP_IDB_Regex SP_CNX_Regex;
/** Trim trailing 0 from val. All insignificant zeroes to the right of the
* decimal point are removed. Also, the decimal point is not included on
* whole numbers. It works like %g flag with printf, but always print
* double value in fixed-point notation.
*
* @parm val valid double value in fixed-point notation from printf %f.
* No format validation is perfomed in this function.
* @parm length length of the buffer val
*/
inline std::string removeTrailing0(char* val, uint32_t length)
{
char* ptr = val;
uint32_t i = 0;
bool decimal_point = false;
for (; i < length; i++, ptr++)
{
if (*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9'))
{
continue;
}
if (*ptr == '.')
{
decimal_point = true;
continue;
}
*ptr = 0;
break;
}
if (decimal_point)
{
for (i = i - 1; i >= 0; i--)
{
if (val[i] == '0')
{
val[i] = 0;
}
else if (val[i] == '.')
{
val[i] = 0;
break;
}
else
{
break;
}
}
}
return std::string(val);
}
/**
* @brief Result type added for F&E framework
*
*/
struct Result
{
Result(): intVal(0), uintVal(0), origIntVal(0), dummy(0),
doubleVal(0), longDoubleVal(0), floatVal(0), boolVal(false),
strVal(""), decimalVal(IDB_Decimal(0, 0, 0)),
valueConverted(false) {}
int64_t intVal;
uint64_t uintVal;
uint64_t origIntVal;
// clear up the memory following origIntVal to make sure null terminated string
// when converting origIntVal
uint64_t dummy;
double doubleVal;
long double longDoubleVal;
float floatVal;
bool boolVal;
std::string strVal;
IDB_Decimal decimalVal;
bool valueConverted;
};
/**
* @brief An abstract class to represent a node data on the expression tree
*
*/
class TreeNode
{
public:
TreeNode();
TreeNode(const TreeNode& rhs);
virtual ~TreeNode();
virtual const std::string data() const = 0;
virtual void data(const std::string data) = 0;
virtual const std::string toString() const = 0;
virtual TreeNode* clone() const = 0;
/**
* Interface for serialization
*/
/** @brief Convert *this to a stream of bytes
*
* Convert *this to a stream of bytes.
* @param b The ByteStream to add *this to.
*/
virtual void serialize(messageqcpp::ByteStream& b) const = 0;
/** @brief Construct a TreeNode from a stream of bytes
*
* Construct a TreeNode from a stream of bytes.
* @param b The ByteStream to parse
* @return The newly allocated TreeNode
*/
virtual void unserialize(messageqcpp::ByteStream& b) = 0;
/** @brief Do a deep, strict (as opposed to semantic) equivalence test
*
* Do a deep, strict (as opposed to semantic) equivalence test.
* @return true iff every member of t is a duplicate copy of every member of this; false otherwise
*/
virtual bool operator==(const TreeNode* t) const = 0;
/** @brief Do a deep, strict (as opposed to semantic) equivalence test
*
* Do a deep, strict (as opposed to semantic) equivalence test.
* @return false iff every member of t is a duplicate copy of every member of this; true otherwise
*/
virtual bool operator!=(const TreeNode* t) const = 0;
// derivedTable mutator and accessor
virtual const std::string& derivedTable() const
{
return fDerivedTable;
}
virtual void derivedTable(const std::string& derivedTable)
{
fDerivedTable = derivedTable;
}
// must to be implented by treenode that could potentially belong to
// one single derived table
virtual void setDerivedTable()
{
fDerivedTable = "";
}
virtual TreeNode* derivedRefCol() const
{
return fDerivedRefCol;
}
virtual void derivedRefCol(TreeNode* derivedRefCol)
{
fDerivedRefCol = derivedRefCol;
}
virtual uint64_t refCount() const
{
return fRefCount;
}
virtual void refCount (const uint64_t refCount)
{
fRefCount = refCount;
}
// the inc and dec functions are used by connector single thread.
virtual void decRefCount()
{
fRefCount--;
}
virtual void incRefCount()
{
fRefCount++;
}
/***********************************************************************
* F&E framework *
***********************************************************************/
virtual const std::string& getStrVal(rowgroup::Row& row, bool& isNull)
{
return fResult.strVal;
}
virtual int64_t getIntVal(rowgroup::Row& row, bool& isNull)
{
return fResult.intVal;
}
virtual uint64_t getUintVal(rowgroup::Row& row, bool& isNull)
{
return fResult.uintVal;
}
virtual float getFloatVal(rowgroup::Row& row, bool& isNull)
{
return fResult.floatVal;
}
virtual double getDoubleVal(rowgroup::Row& row, bool& isNull)
{
return fResult.doubleVal;
}
virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull)
{
return fResult.longDoubleVal;
}
virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull)
{
return fResult.decimalVal;
}
virtual bool getBoolVal(rowgroup::Row& row, bool& isNull)
{
return fResult.boolVal;
}
virtual int32_t getDateIntVal(rowgroup::Row& row, bool& isNull)
{
return fResult.intVal;
}
virtual int64_t getDatetimeIntVal(rowgroup::Row& row, bool& isNull)
{
return fResult.intVal;
}
virtual int64_t getTimeIntVal(rowgroup::Row& row, bool& isNull)
{
return fResult.intVal;
}
virtual void evaluate(rowgroup::Row& row, bool& isNull) {}
inline bool getBoolVal();
inline const std::string& getStrVal();
inline int64_t getIntVal();
inline uint64_t getUintVal();
inline float getFloatVal();
inline double getDoubleVal();
inline long double getLongDoubleVal();
inline IDB_Decimal getDecimalVal();
inline int32_t getDateIntVal();
inline int64_t getDatetimeIntVal();
inline int64_t getTimeIntVal();
virtual const execplan::CalpontSystemCatalog::ColType& resultType() const
{
return fResultType;
}
virtual execplan::CalpontSystemCatalog::ColType& resultType()
{
return fResultType;
}
virtual void resultType ( const execplan::CalpontSystemCatalog::ColType& resultType ) ;
virtual void operationType(const Type& type)
{
fOperationType = type;
}
virtual const execplan::CalpontSystemCatalog::ColType& operationType() const
{
return fOperationType;
}
// result mutator and accessor. for speical functor to set for optimization.
virtual void result(const Result& result)
{
fResult = result;
}
virtual const Result& result() const
{
return fResult;
}
// regex mutator and accessor
virtual void regex(SP_IDB_Regex regex)
{
fRegex = regex;
}
virtual SP_IDB_Regex regex() const
{
return fRegex;
}
protected:
Result fResult;
execplan::CalpontSystemCatalog::ColType fResultType; // mapped from mysql data type
execplan::CalpontSystemCatalog::ColType fOperationType; // operator type, could be different from the result type
SP_IDB_Regex fRegex;
// double's range is +/-1.7E308 with at least 15 digits of precision
char tmp[312]; // for conversion use
// @bug5635 If any item involved in this filter belongs to a derived table,
// the derived table alias is added to the reference vector.
std::string fDerivedTable;
uint64_t fRefCount;
TreeNode* fDerivedRefCol;
private:
//default okay
//TreeNode& operator=(const TreeNode& rhs);
};
inline bool TreeNode::getBoolVal()
{
switch (fResultType.colDataType)
{
case CalpontSystemCatalog::CHAR:
if (fResultType.colWidth <= 8)
return (atoi((char*)(&fResult.origIntVal)) != 0);
return (atoi(fResult.strVal.c_str()) != 0);
case CalpontSystemCatalog::VARCHAR:
if (fResultType.colWidth <= 7)
return (atoi((char*)(&fResult.origIntVal)) != 0);
return (atoi(fResult.strVal.c_str()) != 0);
//FIXME: Huh???
case CalpontSystemCatalog::VARBINARY:
case CalpontSystemCatalog::BLOB:
case CalpontSystemCatalog::TEXT:
if (fResultType.colWidth <= 7)
return (atoi((char*)(&fResult.origIntVal)) != 0);
return (atoi(fResult.strVal.c_str()) != 0);
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
case CalpontSystemCatalog::TIME:
return (fResult.intVal != 0);
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::UINT:
return (fResult.uintVal != 0);
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
return (fResult.floatVal != 0);
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
return (fResult.doubleVal != 0);
case CalpontSystemCatalog::LONGDOUBLE:
return (fResult.longDoubleVal != 0);
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
return (fResult.decimalVal.value != 0);
default:
throw logging::InvalidConversionExcept("TreeNode::getBoolVal: Invalid conversion.");
}
return fResult.boolVal;
}
inline const std::string& TreeNode::getStrVal()
{
switch (fResultType.colDataType)
{
case CalpontSystemCatalog::CHAR:
if (fResultType.colWidth <= 8)
fResult.strVal = (char*)(&fResult.origIntVal);
break;
case CalpontSystemCatalog::VARCHAR:
if (fResultType.colWidth <= 7)
fResult.strVal = (char*)(&fResult.origIntVal);
break;
//FIXME: ???
case CalpontSystemCatalog::VARBINARY:
case CalpontSystemCatalog::BLOB:
case CalpontSystemCatalog::TEXT:
if (fResultType.colWidth <= 7)
fResult.strVal = (char*)(&fResult.origIntVal);
break;
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::INT:
{
#ifndef __LP64__
snprintf(tmp, 20, "%lld", fResult.intVal);
#else
snprintf(tmp, 20, "%ld", fResult.intVal);
#endif
fResult.strVal = std::string(tmp);
break;
}
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::UINT:
{
#ifndef __LP64__
snprintf(tmp, 20, "%llu", fResult.uintVal);
#else
snprintf(tmp, 20, "%lu", fResult.uintVal);
#endif
fResult.strVal = std::string(tmp);
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
if ((fabs(fResult.floatVal) > (1.0 / IDB_pow[4])) &&
(fabs(fResult.floatVal) < (float) IDB_pow[6]))
{
snprintf(tmp, 312, "%f", fResult.floatVal);
fResult.strVal = removeTrailing0(tmp, 312);
}
else
{
// MCOL-299 Print scientific with 5 mantissa and no + sign for exponent
int exponent = (int)floor(log10( fabs(fResult.floatVal))); // This will round down the exponent
double base = fResult.floatVal * pow(10, -1.0 * exponent);
if (isnan(exponent) || std::isnan(base))
{
snprintf(tmp, 312, "%f", fResult.floatVal);
fResult.strVal = removeTrailing0(tmp, 312);
}
else
{
snprintf(tmp, 312, "%.5f", base);
fResult.strVal = removeTrailing0(tmp, 312);
snprintf(tmp, 312, "e%02d", exponent);
fResult.strVal += tmp;
}
// snprintf(tmp, 312, "%e.5", fResult.floatVal);
// fResult.strVal = tmp;
}
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
if ((fabs(fResult.doubleVal) > (1.0 / IDB_pow[13])) &&
(fabs(fResult.doubleVal) < (float) IDB_pow[15]))
{
snprintf(tmp, 312, "%f", fResult.doubleVal);
fResult.strVal = removeTrailing0(tmp, 312);
}
else
{
// MCOL-299 Print scientific with 9 mantissa and no + sign for exponent
int exponent = (int)floor(log10( fabs(fResult.doubleVal))); // This will round down the exponent
double base = fResult.doubleVal * pow(10, -1.0 * exponent);
if (isnan(exponent) || std::isnan(base))
{
snprintf(tmp, 312, "%f", fResult.doubleVal);
fResult.strVal = removeTrailing0(tmp, 312);
}
else
{
snprintf(tmp, 312, "%.9f", base);
fResult.strVal = removeTrailing0(tmp, 312);
snprintf(tmp, 312, "e%02d", exponent);
fResult.strVal += tmp;
}
// snprintf(tmp, 312, "%e", fResult.doubleVal);
// fResult.strVal = tmp;
}
break;
}
case CalpontSystemCatalog::LONGDOUBLE:
{
if ((fabsl(fResult.longDoubleVal) > (1.0 / IDB_pow[13])) &&
(fabsl(fResult.longDoubleVal) < (float) IDB_pow[15]))
{
snprintf(tmp, 312, "%Lf", fResult.longDoubleVal);
fResult.strVal = removeTrailing0(tmp, 312);
}
else
{
// MCOL-299 Print scientific with 9 mantissa and no + sign for exponent
int exponent = (int)floorl(log10( fabsl(fResult.longDoubleVal))); // This will round down the exponent
long double base = fResult.longDoubleVal * pow(10, -1.0 * exponent);
if (isnan(exponent) || isnan(base))
{
snprintf(tmp, 312, "%Lf", fResult.longDoubleVal);
fResult.strVal = removeTrailing0(tmp, 312);
}
else
{
snprintf(tmp, 312, "%.14Lf", base);
fResult.strVal = removeTrailing0(tmp, 312);
snprintf(tmp, 312, "e%02d", exponent);
fResult.strVal += tmp;
}
// snprintf(tmp, 312, "%e", fResult.doubleVal);
// fResult.strVal = tmp;
}
break;
}
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
dataconvert::DataConvert::decimalToString(fResult.decimalVal.value, fResult.decimalVal.scale, tmp, 22, fResultType.colDataType);
fResult.strVal = std::string(tmp);
break;
}
case CalpontSystemCatalog::DATE:
{
dataconvert::DataConvert::dateToString(fResult.intVal, tmp, 255);
fResult.strVal = std::string(tmp);
break;
}
case CalpontSystemCatalog::DATETIME:
{
dataconvert::DataConvert::datetimeToString(fResult.intVal, tmp, 255, fResultType.precision);
fResult.strVal = std::string(tmp);
break;
}
case CalpontSystemCatalog::TIME:
{
dataconvert::DataConvert::timeToString(fResult.intVal, tmp, 255, fResultType.precision);
fResult.strVal = std::string(tmp);
break;
}
default:
throw logging::InvalidConversionExcept("TreeNode::getStrVal: Invalid conversion.");
}
return fResult.strVal;
}
inline int64_t TreeNode::getIntVal()
{
switch (fResultType.colDataType)
{
case CalpontSystemCatalog::CHAR:
if (fResultType.colWidth <= 8)
return fResult.intVal;
return atoll(fResult.strVal.c_str());
case CalpontSystemCatalog::VARCHAR:
if (fResultType.colWidth <= 7)
return fResult.intVal;
return atoll(fResult.strVal.c_str());
//FIXME: ???
case CalpontSystemCatalog::VARBINARY:
case CalpontSystemCatalog::BLOB:
case CalpontSystemCatalog::TEXT:
if (fResultType.colWidth <= 7)
return fResult.intVal;
return atoll(fResult.strVal.c_str());
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
return fResult.intVal;
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
return fResult.uintVal;
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
return (int64_t)fResult.floatVal;
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
return (int64_t)fResult.doubleVal;
case CalpontSystemCatalog::LONGDOUBLE:
return (int64_t)fResult.longDoubleVal;
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
return (int64_t)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
}
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
case CalpontSystemCatalog::TIME:
return fResult.intVal;
default:
throw logging::InvalidConversionExcept("TreeNode::getIntVal: Invalid conversion.");
}
return fResult.intVal;
}
inline uint64_t TreeNode::getUintVal()
{
switch (fResultType.colDataType)
{
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
return fResult.intVal;
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
return fResult.uintVal;
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
return (uint64_t)fResult.floatVal;
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
return (uint64_t)fResult.doubleVal;
case CalpontSystemCatalog::LONGDOUBLE:
return (uint64_t)fResult.longDoubleVal;
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
return (uint64_t)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
}
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
case CalpontSystemCatalog::TIME:
return fResult.intVal;
default:
throw logging::InvalidConversionExcept("TreeNode::getIntVal: Invalid conversion.");
}
return fResult.intVal;
}
inline float TreeNode::getFloatVal()
{
switch (fResultType.colDataType)
{
case CalpontSystemCatalog::CHAR:
if (fResultType.colWidth <= 8)
return atof((char*)(&fResult.origIntVal));
return atof(fResult.strVal.c_str());
case CalpontSystemCatalog::VARCHAR:
if (fResultType.colWidth <= 7)
return atof((char*)(&fResult.origIntVal));
return atof(fResult.strVal.c_str());
//FIXME: ???
case CalpontSystemCatalog::VARBINARY:
case CalpontSystemCatalog::BLOB:
case CalpontSystemCatalog::TEXT:
if (fResultType.colWidth <= 7)
return atof((char*)(&fResult.origIntVal));
return atof(fResult.strVal.c_str());
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
return (float)fResult.intVal;
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
return (float)fResult.uintVal;
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
return fResult.floatVal;
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
return (float)fResult.doubleVal;
case CalpontSystemCatalog::LONGDOUBLE:
return (float)fResult.doubleVal;
case CalpontSystemCatalog::DECIMAL:
{
return (fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
}
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
case CalpontSystemCatalog::TIME:
return (float)fResult.intVal;
default:
throw logging::InvalidConversionExcept("TreeNode::getFloatVal: Invalid conversion.");
}
return fResult.floatVal;
}
inline double TreeNode::getDoubleVal()
{
switch (fResultType.colDataType)
{
case CalpontSystemCatalog::CHAR:
if (fResultType.colWidth <= 8)
return strtod((char*)(&fResult.origIntVal), NULL);
return strtod(fResult.strVal.c_str(), NULL);
case CalpontSystemCatalog::VARCHAR:
if (fResultType.colWidth <= 7)
return strtod((char*)(&fResult.origIntVal), NULL);
return strtod(fResult.strVal.c_str(), NULL);
//FIXME: ???
case CalpontSystemCatalog::VARBINARY:
case CalpontSystemCatalog::BLOB:
case CalpontSystemCatalog::TEXT:
if (fResultType.colWidth <= 7)
return strtod((char*)(&fResult.origIntVal), NULL);
return strtod(fResult.strVal.c_str(), NULL);
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
return (double)fResult.intVal;
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
return (double)fResult.uintVal;
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
return (double)fResult.floatVal;
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
return fResult.doubleVal;
case CalpontSystemCatalog::LONGDOUBLE:
return (double)fResult.longDoubleVal;
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
// this may not be accurate. if this is problematic, change to pre-calculated power array.
return (double)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
}
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
case CalpontSystemCatalog::TIME:
return (double)fResult.intVal;
default:
throw logging::InvalidConversionExcept("TreeNode::getDoubleVal: Invalid conversion.");
}
return fResult.doubleVal;
}
inline long double TreeNode::getLongDoubleVal()
{
switch (fResultType.colDataType)
{
case CalpontSystemCatalog::CHAR:
if (fResultType.colWidth <= 8)
return strtold((char*)(&fResult.origIntVal), NULL);
return strtold(fResult.strVal.c_str(), NULL);
case CalpontSystemCatalog::VARCHAR:
if (fResultType.colWidth <= 7)
return strtold((char*)(&fResult.origIntVal), NULL);
return strtold(fResult.strVal.c_str(), NULL);
//FIXME: ???
case CalpontSystemCatalog::VARBINARY:
case CalpontSystemCatalog::BLOB:
case CalpontSystemCatalog::TEXT:
if (fResultType.colWidth <= 7)
return strtold((char*)(&fResult.origIntVal), NULL);
return strtold(fResult.strVal.c_str(), NULL);
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
return (long double)fResult.intVal;
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
return (long double)fResult.uintVal;
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
return (long double)fResult.floatVal;
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
return (long double)fResult.doubleVal;
case CalpontSystemCatalog::LONGDOUBLE:
return (long double)fResult.longDoubleVal;
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
// this may not be accurate. if this is problematic, change to pre-calculated power array.
return (long double)(fResult.decimalVal.value / pow((long double)10, fResult.decimalVal.scale));
}
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
case CalpontSystemCatalog::TIME:
return (long double)fResult.intVal;
default:
throw logging::InvalidConversionExcept("TreeNode::getDoubleVal: Invalid conversion.");
}
return fResult.doubleVal;
}
inline IDB_Decimal TreeNode::getDecimalVal()
{
switch (fResultType.colDataType)
{
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
case CalpontSystemCatalog::TEXT:
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from string");
case CalpontSystemCatalog::VARBINARY:
case CalpontSystemCatalog::BLOB:
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from binary string");
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::TINYINT:
fResult.decimalVal.value = (int64_t)(fResult.intVal * pow((double)10.0, fResultType.scale));
fResult.decimalVal.scale = fResultType.scale;
fResult.decimalVal.precision = fResultType.precision;
break;
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UTINYINT:
fResult.decimalVal.value = (int64_t)(fResult.uintVal * pow((double)10.0, fResultType.scale));
fResult.decimalVal.scale = fResultType.scale;
fResult.decimalVal.precision = fResultType.precision;
break;
case CalpontSystemCatalog::LONGDOUBLE:
{
long double dlScaled = fResult.longDoubleVal;
if (fResultType.scale > 0)
{
dlScaled= fResult.longDoubleVal * pow((double)10.0, fResultType.scale);
}
if (dlScaled > (double)MAX_BIGINT)
{
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: decimal overflow.");
}
fResult.decimalVal.value = (int64_t)roundl((fResult.longDoubleVal * pow((double)10.0, fResultType.scale)));
fResult.decimalVal.scale = fResultType.scale;
fResult.decimalVal.precision = fResultType.precision;
}
break;
case CalpontSystemCatalog::DATE:
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion from date.");
case CalpontSystemCatalog::DATETIME:
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion from datetime.");
case CalpontSystemCatalog::TIME:
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion from time.");
case CalpontSystemCatalog::FLOAT:
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from float");
case CalpontSystemCatalog::UFLOAT:
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from float unsigned");
case CalpontSystemCatalog::DOUBLE:
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from double");
case CalpontSystemCatalog::UDOUBLE:
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from double unsigned");
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
return fResult.decimalVal;
default:
throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion.");
}
return fResult.decimalVal;
}
inline int64_t TreeNode::getDatetimeIntVal()
{
if (fResultType.colDataType == execplan::CalpontSystemCatalog::DATE)
return (fResult.intVal & 0x00000000FFFFFFC0LL) << 32;
else if (fResultType.colDataType == execplan::CalpontSystemCatalog::TIME)
{
dataconvert::Time tt;
int day = 0;
memcpy(&tt, &fResult.intVal, 8);
// Note, this should probably be current date +/- time
if ((tt.hour > 23) && (!tt.is_neg))
{
day = tt.hour / 24;
tt.hour = tt.hour % 24;
}
else if ((tt.hour < 0) || (tt.is_neg))
{
tt.hour = 0;
}
dataconvert::DateTime dt(0, 0, day, tt.hour, tt.minute, tt.second, tt.msecond);
memcpy(&fResult.intVal, &dt, 8);
return fResult.intVal;
}
else if (fResultType.colDataType == execplan::CalpontSystemCatalog::DATETIME)
//return (fResult.intVal & 0xFFFFFFFFFFF00000LL);
return (fResult.intVal);
else
return getIntVal();
}
inline int64_t TreeNode::getTimeIntVal()
{
if (fResultType.colDataType == execplan::CalpontSystemCatalog::DATETIME)
{
dataconvert::DateTime dt;
memcpy(&dt, &fResult.intVal, 8);
dataconvert::Time tt(0, dt.hour, dt.minute, dt.second, dt.msecond, false);
memcpy(&fResult.intVal, &tt, 8);
return fResult.intVal;
}
else if (fResultType.colDataType == execplan::CalpontSystemCatalog::TIME)
return (fResult.intVal);
else
return getIntVal();
}
inline int32_t TreeNode::getDateIntVal()
{
if (fResultType.colDataType == execplan::CalpontSystemCatalog::DATETIME)
return (((int32_t)(fResult.intVal >> 32) & 0xFFFFFFC0) | 0x3E);
else if (fResultType.colDataType == execplan::CalpontSystemCatalog::DATE)
return ((fResult.intVal & 0xFFFFFFC0) | 0x3E);
else
return getIntVal();
}
typedef boost::shared_ptr<TreeNode> STNP;
/**
* Operations
*/
std::ostream& operator<<(std::ostream& output, const TreeNode& rhs);
}
#endif