diff --git a/dbcon/execplan/aggregatecolumn.cpp b/dbcon/execplan/aggregatecolumn.cpp index c996dad17..982841e4e 100644 --- a/dbcon/execplan/aggregatecolumn.cpp +++ b/dbcon/execplan/aggregatecolumn.cpp @@ -1,4 +1,5 @@ /* 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 @@ -498,6 +499,14 @@ void AggregateColumn::evaluate(Row& row, bool& isNull) break; + case CalpontSystemCatalog::LONGDOUBLE: + if (row.equals(LONGDOUBLENULL, fInputIndex)) + isNull = true; + else + fResult.longDoubleVal = row.getLongDoubleField(fInputIndex); + + break; + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: switch (fResultType.colWidth) diff --git a/dbcon/execplan/aggregatecolumn.h b/dbcon/execplan/aggregatecolumn.h index 07bbab0b6..79df22e4d 100644 --- a/dbcon/execplan/aggregatecolumn.h +++ b/dbcon/execplan/aggregatecolumn.h @@ -1,4 +1,5 @@ /* 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 @@ -384,6 +385,15 @@ public: return TreeNode::getDoubleVal(); } + /** + * F&E + */ + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + evaluate(row, isNull); + return TreeNode::getLongDoubleVal(); + } + /** * F&E */ diff --git a/dbcon/execplan/arithmeticcolumn.h b/dbcon/execplan/arithmeticcolumn.h index 191416fbf..14d838bad 100644 --- a/dbcon/execplan/arithmeticcolumn.h +++ b/dbcon/execplan/arithmeticcolumn.h @@ -1,4 +1,5 @@ /* 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 @@ -233,6 +234,11 @@ public: return fExpression->getDoubleVal(row, isNull); } + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + return fExpression->getLongDoubleVal(row, isNull); + } + virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull) { return fExpression->getDecimalVal(row, isNull); diff --git a/dbcon/execplan/arithmeticoperator.cpp b/dbcon/execplan/arithmeticoperator.cpp index 73e18b430..71857a8fa 100644 --- a/dbcon/execplan/arithmeticoperator.cpp +++ b/dbcon/execplan/arithmeticoperator.cpp @@ -212,10 +212,10 @@ void ArithmeticOperator::adjustResultType(const CalpontSystemCatalog::ColType& m else { CalpontSystemCatalog::ColType n; - n.colDataType = CalpontSystemCatalog::DOUBLE; + n.colDataType = CalpontSystemCatalog::LONGDOUBLE; n.scale = m.scale; // @bug5736, save the original decimal scale n.precision = -1; // @bug5736, indicate this double is for decimal math - n.colWidth = 8; + n.colWidth = sizeof(long double); fResultType = n; } } diff --git a/dbcon/execplan/arithmeticoperator.h b/dbcon/execplan/arithmeticoperator.h index ca254075b..0f54b1e82 100644 --- a/dbcon/execplan/arithmeticoperator.h +++ b/dbcon/execplan/arithmeticoperator.h @@ -1,4 +1,5 @@ /* 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 @@ -123,6 +124,11 @@ public: evaluate(row, isNull, lop, rop); return TreeNode::getDoubleVal(); } + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull, ParseTree* lop, ParseTree* rop) + { + evaluate(row, isNull, lop, rop); + return TreeNode::getLongDoubleVal(); + } virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull, ParseTree* lop, ParseTree* rop) { evaluate(row, isNull, lop, rop); @@ -194,9 +200,15 @@ inline void ArithmeticOperator::evaluate(rowgroup::Row& row, bool& isNull, Parse case execplan::CalpontSystemCatalog::DOUBLE: case execplan::CalpontSystemCatalog::FLOAT: + case execplan::CalpontSystemCatalog::UDOUBLE: + case execplan::CalpontSystemCatalog::UFLOAT: fResult.doubleVal = execute(lop->getDoubleVal(row, isNull), rop->getDoubleVal(row, isNull), isNull); break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + fResult.longDoubleVal = execute(lop->getLongDoubleVal(row, isNull), rop->getLongDoubleVal(row, isNull), isNull); + break; + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: execute (fResult.decimalVal, lop->getDecimalVal(row, isNull), rop->getDecimalVal(row, isNull), isNull); diff --git a/dbcon/execplan/calpontsystemcatalog.cpp b/dbcon/execplan/calpontsystemcatalog.cpp index 7b75c15a9..119678cf6 100644 --- a/dbcon/execplan/calpontsystemcatalog.cpp +++ b/dbcon/execplan/calpontsystemcatalog.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -155,6 +155,10 @@ const string colDataTypeToString(CalpontSystemCatalog::ColDataType cdt) return "double"; break; + case CalpontSystemCatalog::LONGDOUBLE: + return "long double"; + break; + case CalpontSystemCatalog::DATETIME: return "datetime"; break; diff --git a/dbcon/execplan/calpontsystemcatalog.h b/dbcon/execplan/calpontsystemcatalog.h index debf7dd07..d55ce93fa 100644 --- a/dbcon/execplan/calpontsystemcatalog.h +++ b/dbcon/execplan/calpontsystemcatalog.h @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -80,6 +80,8 @@ const float MAX_FLOAT __attribute__ ((unused)) = std::numeric_limits::ma const float MIN_FLOAT __attribute__ ((unused)) = -std::numeric_limits::max(); const double MAX_DOUBLE __attribute__ ((unused)) = std::numeric_limits::max(); //1.7976931348623157e+308 const double MIN_DOUBLE __attribute__ ((unused)) = -std::numeric_limits::max(); +const long double MAX_LONGDOUBLE __attribute__ ((unused)) = std::numeric_limits::max(); //1.7976931348623157e+308 +const long double MIN_LONGDOUBLE __attribute__ ((unused)) = -std::numeric_limits::max(); const uint64_t AUTOINCR_SATURATED __attribute__ ((unused)) = std::numeric_limits::max(); diff --git a/dbcon/execplan/constantcolumn.cpp b/dbcon/execplan/constantcolumn.cpp index dd112600e..3a816b114 100644 --- a/dbcon/execplan/constantcolumn.cpp +++ b/dbcon/execplan/constantcolumn.cpp @@ -1,4 +1,5 @@ /* 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 @@ -51,7 +52,7 @@ ConstantColumn::ConstantColumn(const string& sql, TYPE type) : fData(sql) { fResult.strVal = sql; - + if (type == LITERAL && sql.length() < 9) { memcpy(tmp, sql.c_str(), sql.length()); @@ -67,6 +68,7 @@ ConstantColumn::ConstantColumn(const string& sql, TYPE type) : fResult.floatVal = atof(sql.c_str()); fResult.doubleVal = atof(sql.c_str()); + fResult.longDoubleVal = strtold(sql.c_str(), NULL); // decimal for constant should be constructed by the caller and call the decimal constructor fResult.decimalVal.value = fResult.intVal; @@ -105,6 +107,27 @@ ConstantColumn::ConstantColumn(const string& sql, const double val) : fResult.intVal = (int64_t)val; fResult.uintVal = (uint64_t)val; fResult.floatVal = (float)val; + fResult.longDoubleVal = val; + // decimal for constant should be constructed by the caller and call the decimal constructor + fResult.decimalVal.value = fResult.intVal; + fResult.decimalVal.scale = 0; + fResult.decimalVal.precision = 18; + fResultType.colDataType = CalpontSystemCatalog::DOUBLE; + fResultType.colWidth = 8; +} + +ConstantColumn::ConstantColumn(const string& sql, const long double val) : + ReturnedColumn(), + fConstval(sql), + fType(NUM), + fData(sql) +{ + fResult.strVal = sql; + fResult.doubleVal = (double)val; + fResult.intVal = (int64_t)val; + fResult.uintVal = (uint64_t)val; + fResult.floatVal = (float)val; + fResult.longDoubleVal = val; // decimal for constant should be constructed by the caller and call the decimal constructor fResult.decimalVal.value = fResult.intVal; fResult.decimalVal.scale = 0; @@ -124,6 +147,7 @@ ConstantColumn::ConstantColumn(const string& sql, const int64_t val, TYPE type) fResult.uintVal = (uint64_t)fResult.intVal; fResult.floatVal = (float)fResult.intVal; fResult.doubleVal = (double)fResult.intVal; + fResult.longDoubleVal = (long double)fResult.intVal; fResult.decimalVal.value = fResult.intVal; fResult.decimalVal.scale = 0; fResultType.colDataType = CalpontSystemCatalog::BIGINT; @@ -141,6 +165,7 @@ ConstantColumn::ConstantColumn(const string& sql, const uint64_t val, TYPE type) fResult.intVal = (int64_t)fResult.uintVal; fResult.floatVal = (float)fResult.uintVal; fResult.doubleVal = (double)fResult.uintVal; + fResult.longDoubleVal = (long double)fResult.uintVal; fResult.decimalVal.value = fResult.uintVal; fResult.decimalVal.scale = 0; fResultType.colDataType = CalpontSystemCatalog::UBIGINT; @@ -158,6 +183,7 @@ ConstantColumn::ConstantColumn(const string& sql, const IDB_Decimal& val) : fResult.uintVal = strtoull(sql.c_str(), NULL, 0); fResult.floatVal = atof(sql.c_str()); fResult.doubleVal = atof(sql.c_str()); + fResult.longDoubleVal = strtold(sql.c_str(), NULL); fResult.decimalVal = val; fResultType.colDataType = CalpontSystemCatalog::DECIMAL; fResultType.colWidth = 8; @@ -201,6 +227,7 @@ ConstantColumn::ConstantColumn(const int64_t val, TYPE type) : fResult.uintVal = (uint64_t)fResult.intVal; fResult.floatVal = (float)fResult.intVal; fResult.doubleVal = (double)fResult.intVal; + fResult.longDoubleVal = (long double)fResult.intVal; fResult.decimalVal.value = fResult.intVal; fResult.decimalVal.scale = 0; fResultType.colDataType = CalpontSystemCatalog::BIGINT; @@ -220,6 +247,7 @@ ConstantColumn::ConstantColumn(const uint64_t val, TYPE type) : fResult.uintVal = val; fResult.floatVal = (float)fResult.uintVal; fResult.doubleVal = (double)fResult.uintVal; + fResult.longDoubleVal = (long double)fResult.uintVal; fResult.decimalVal.value = fResult.uintVal; fResult.decimalVal.scale = 0; fResultType.colDataType = CalpontSystemCatalog::UBIGINT; @@ -281,8 +309,9 @@ void ConstantColumn::serialize(messageqcpp::ByteStream& b) const b << static_cast(fReturnAll); b << (uint64_t)fResult.intVal; b << fResult.uintVal; - b << (*(uint64_t*)(&fResult.doubleVal)); - b << (*(uint32_t*)(&fResult.floatVal)); + b << fResult.doubleVal; + b << fResult.longDoubleVal; + b << fResult.floatVal; b << (uint8_t)fResult.boolVal; b << fResult.strVal; b << (uint64_t)fResult.decimalVal.value; @@ -303,8 +332,9 @@ void ConstantColumn::unserialize(messageqcpp::ByteStream& b) b >> reinterpret_cast< ByteStream::doublebyte&>(fReturnAll); b >> (uint64_t&)fResult.intVal; b >> fResult.uintVal; - b >> (uint64_t&)fResult.doubleVal; - b >> (uint32_t&)fResult.floatVal; + b >> fResult.doubleVal; + b >> fResult.longDoubleVal; + b >> fResult.floatVal; b >> (uint8_t&)fResult.boolVal; b >> fResult.strVal; b >> (uint64_t&)fResult.decimalVal.value; diff --git a/dbcon/execplan/constantcolumn.h b/dbcon/execplan/constantcolumn.h index be0731044..ed8315202 100644 --- a/dbcon/execplan/constantcolumn.h +++ b/dbcon/execplan/constantcolumn.h @@ -1,4 +1,5 @@ /* 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 @@ -200,6 +201,10 @@ public: * ctor */ ConstantColumn(const std::string& sql, const double val); + /** + * ctor + */ + ConstantColumn(const std::string& sql, const long double val); /** * ctor */ diff --git a/dbcon/execplan/functioncolumn.h b/dbcon/execplan/functioncolumn.h index 5a099d1d2..cb4a397fb 100644 --- a/dbcon/execplan/functioncolumn.h +++ b/dbcon/execplan/functioncolumn.h @@ -1,4 +1,5 @@ /* 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 @@ -225,6 +226,10 @@ public: { return fFunctor->getDoubleVal(row, fFunctionParms, isNull, fOperationType); } + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + return fFunctor->getLongDoubleVal(row, fFunctionParms, isNull, fOperationType); + } virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull) { IDB_Decimal decimal = fFunctor->getDecimalVal(row, fFunctionParms, isNull, fOperationType); diff --git a/dbcon/execplan/operator.h b/dbcon/execplan/operator.h index 1a33dcb94..13dea8d38 100644 --- a/dbcon/execplan/operator.h +++ b/dbcon/execplan/operator.h @@ -1,4 +1,5 @@ /* 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 @@ -178,6 +179,10 @@ public: { return fResult.doubleVal; } + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull, ParseTree* lop, ParseTree* rop) + { + return fResult.longDoubleVal; + } virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull, ParseTree* lop, ParseTree* rop) { return fResult.decimalVal; diff --git a/dbcon/execplan/parsetree.h b/dbcon/execplan/parsetree.h index 2ad41b6bb..044d54fd6 100644 --- a/dbcon/execplan/parsetree.h +++ b/dbcon/execplan/parsetree.h @@ -1,4 +1,5 @@ /* 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 @@ -250,6 +251,14 @@ public: return fData->getDoubleVal(row, isNull); } + inline long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + if (fLeft && fRight) + return (reinterpret_cast(fData))->getLongDoubleVal(row, isNull, fLeft, fRight); + else + return fData->getLongDoubleVal(row, isNull); + } + inline IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull) { if (fLeft && fRight) diff --git a/dbcon/execplan/predicateoperator.cpp b/dbcon/execplan/predicateoperator.cpp index 166a8edc0..704ab3a63 100644 --- a/dbcon/execplan/predicateoperator.cpp +++ b/dbcon/execplan/predicateoperator.cpp @@ -1,4 +1,5 @@ /* 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 @@ -317,6 +318,10 @@ void PredicateOperator::setOpType(Type& l, Type& r) fOperationType.colWidth = 8; break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + fOperationType.colDataType = execplan::CalpontSystemCatalog::LONGDOUBLE; + fOperationType.colWidth = sizeof(long double); + break; default: fOperationType.colDataType = execplan::CalpontSystemCatalog::DOUBLE; fOperationType.colWidth = 8; @@ -370,6 +375,12 @@ void PredicateOperator::setOpType(Type& l, Type& r) fOperationType.colWidth = 255; } } + else if (l.colDataType == execplan::CalpontSystemCatalog::LONGDOUBLE || + r.colDataType == execplan::CalpontSystemCatalog::LONGDOUBLE) + { + fOperationType.colDataType = execplan::CalpontSystemCatalog::LONGDOUBLE; + fOperationType.colWidth = sizeof(long double); + } else { fOperationType.colDataType = execplan::CalpontSystemCatalog::DOUBLE; diff --git a/dbcon/execplan/predicateoperator.h b/dbcon/execplan/predicateoperator.h index 6253d9389..b83931394 100644 --- a/dbcon/execplan/predicateoperator.h +++ b/dbcon/execplan/predicateoperator.h @@ -1,4 +1,5 @@ /* 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 @@ -256,6 +257,66 @@ inline bool PredicateOperator::getBoolVal(rowgroup::Row& row, bool& isNull, Retu return numericCompare(val1, rop->getDoubleVal(row, isNull)) && !isNull; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + if (fOp == OP_ISNULL) + { + lop->getLongDoubleVal(row, isNull); + bool ret = isNull; + isNull = false; + return ret; + } + + if (fOp == OP_ISNOTNULL) + { + lop->getLongDoubleVal(row, isNull); + bool ret = isNull; + isNull = false; + return !ret; + } + + if (isNull) + return false; + + long double val1 = lop->getLongDoubleVal(row, isNull); + if (isNull) + return false; + + long double val2 = rop->getLongDoubleVal(row, isNull); + if (isNull) + return false; + + // In many case, rounding error will prevent an eq compare to work + // In these cases, use the largest scale of the two items. + if (fOp == execplan::OP_EQ) + { + // In case a val is a representation of a very large integer, + // we won't want to just multiply by scale, as it may move + // significant digits out of scope. So we break them apart + // and compare each separately + int64_t scale = max(lop->resultType().scale, rop->resultType().scale); + if (scale) + { + long double intpart1; + long double fract1 = modfl(val1, &intpart1); + long double intpart2; + long double fract2 = modfl(val2, &intpart2); + if (numericCompare(intpart1, intpart2)) + { + double factor = pow(10.0, (double)scale); + fract1 = roundl(fract1 * factor); + fract2 = roundl(fract2 * factor); + return numericCompare(fract1, fract2); + } + else + { + return false; + } + } + } + return numericCompare(val1, val2); + } + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { diff --git a/dbcon/execplan/simplecolumn.cpp b/dbcon/execplan/simplecolumn.cpp index 1d7780e33..206194954 100644 --- a/dbcon/execplan/simplecolumn.cpp +++ b/dbcon/execplan/simplecolumn.cpp @@ -1,4 +1,5 @@ /* 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 @@ -592,6 +593,12 @@ void SimpleColumn::evaluate(Row& row, bool& isNull) break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + fResult.longDoubleVal = row.getLongDoubleField(fInputIndex); + break; + } + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { diff --git a/dbcon/execplan/simplecolumn.h b/dbcon/execplan/simplecolumn.h index 60eff939b..6694863d6 100644 --- a/dbcon/execplan/simplecolumn.h +++ b/dbcon/execplan/simplecolumn.h @@ -1,4 +1,5 @@ /* 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 @@ -300,20 +301,36 @@ public: return TreeNode::getDoubleVal(); } + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + evaluate(row, isNull); + return TreeNode::getLongDoubleVal(); + } + virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull) { evaluate(row, isNull); // @bug5736, double type with precision -1 indicates that this type is for decimal math, // the original decimal scale is stored in scale field, which is no use for double. - if (fResultType.colDataType == CalpontSystemCatalog::DOUBLE && fResultType.precision == -1) + if (fResultType.precision == -1) { IDB_Decimal rv; - rv.scale = fResultType.scale; - rv.precision = 15; - rv.value = (int64_t)(TreeNode::getDoubleVal() * IDB_pow[rv.scale]); - - return rv; + if (fResultType.colDataType == CalpontSystemCatalog::DOUBLE) + { + rv.scale = fResultType.scale; + rv.precision = 15; + rv.value = (int64_t)(TreeNode::getDoubleVal() * IDB_pow[rv.scale]); + return rv; + } + else if (fResultType.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + IDB_Decimal rv; + rv.scale = fResultType.scale; + rv.precision = 19; + rv.value = (int64_t)(TreeNode::getLongDoubleVal() * IDB_pow[rv.scale]); + return rv; + } } return TreeNode::getDecimalVal(); diff --git a/dbcon/execplan/simplecolumn_decimal.h b/dbcon/execplan/simplecolumn_decimal.h index 2b7b90cf6..07d451e4b 100644 --- a/dbcon/execplan/simplecolumn_decimal.h +++ b/dbcon/execplan/simplecolumn_decimal.h @@ -1,4 +1,5 @@ /* 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 @@ -76,6 +77,7 @@ public: virtual inline int64_t getIntVal(rowgroup::Row& row, bool& isNull); virtual inline float getFloatVal(rowgroup::Row& row, bool& isNull); virtual inline double getDoubleVal(rowgroup::Row& row, bool& isNull); + virtual inline long double getLongDoubleVal(rowgroup::Row& row, bool& isNull); virtual inline IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull); /** The serialize interface */ @@ -180,6 +182,15 @@ inline double SimpleColumn_Decimal::getDoubleVal(rowgroup::Row& row, bool& return (row.getIntField(fInputIndex) / pow((double)10, fResultType.scale)); } +template +inline long double SimpleColumn_Decimal::getLongDoubleVal(rowgroup::Row& row, bool& isNull) +{ + if (row.equals(fNullVal, fInputIndex)) + isNull = true; + + return (row.getIntField(fInputIndex) / pow((double)10, fResultType.scale)); +} + template inline IDB_Decimal SimpleColumn_Decimal::getDecimalVal(rowgroup::Row& row, bool& isNull) { diff --git a/dbcon/execplan/simplecolumn_int.h b/dbcon/execplan/simplecolumn_int.h index fd171909c..e39ab9953 100644 --- a/dbcon/execplan/simplecolumn_int.h +++ b/dbcon/execplan/simplecolumn_int.h @@ -1,4 +1,5 @@ /* 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 @@ -75,6 +76,7 @@ public: virtual inline uint64_t getUintVal(rowgroup::Row& row, bool& isNull); virtual inline float getFloatVal(rowgroup::Row& row, bool& isNull); virtual inline double getDoubleVal(rowgroup::Row& row, bool& isNull); + virtual inline long double getLongDoubleVal(rowgroup::Row& row, bool& isNull); virtual inline IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull); /** The serialize interface */ @@ -198,6 +200,15 @@ inline double SimpleColumn_INT::getDoubleVal(rowgroup::Row& row, bool& isNu return (double)row.getIntField(fInputIndex); } +template +inline long double SimpleColumn_INT::getLongDoubleVal(rowgroup::Row& row, bool& isNull) +{ + if (row.equals(fNullVal, fInputIndex)) + isNull = true; + + return (long double)row.getIntField(fInputIndex); +} + template inline IDB_Decimal SimpleColumn_INT::getDecimalVal(rowgroup::Row& row, bool& isNull) { diff --git a/dbcon/execplan/simplecolumn_uint.h b/dbcon/execplan/simplecolumn_uint.h index 2bb98cbd4..7c9169f75 100644 --- a/dbcon/execplan/simplecolumn_uint.h +++ b/dbcon/execplan/simplecolumn_uint.h @@ -1,4 +1,5 @@ /* 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 @@ -75,6 +76,7 @@ public: virtual inline uint64_t getUintVal(rowgroup::Row& row, bool& isNull); virtual inline float getFloatVal(rowgroup::Row& row, bool& isNull); virtual inline double getDoubleVal(rowgroup::Row& row, bool& isNull); + virtual inline long double getLongDoubleVal(rowgroup::Row& row, bool& isNull); virtual inline IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull); /** The serialize interface */ @@ -198,6 +200,15 @@ inline double SimpleColumn_UINT::getDoubleVal(rowgroup::Row& row, bool& isN return (double)row.getUintField(fInputIndex); } +template +inline long double SimpleColumn_UINT::getLongDoubleVal(rowgroup::Row& row, bool& isNull) +{ + if (row.equals(fNullVal, fInputIndex)) + isNull = true; + + return (long double)row.getUintField(fInputIndex); +} + template inline IDB_Decimal SimpleColumn_UINT::getDecimalVal(rowgroup::Row& row, bool& isNull) { diff --git a/dbcon/execplan/simplefilter.h b/dbcon/execplan/simplefilter.h index d784aefcd..04afb087a 100644 --- a/dbcon/execplan/simplefilter.h +++ b/dbcon/execplan/simplefilter.h @@ -1,4 +1,5 @@ /* 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 @@ -212,6 +213,7 @@ public: inline virtual bool getBoolVal(rowgroup::Row& row, bool& isNull); inline virtual int64_t getIntVal(rowgroup::Row& row, bool& isNull); inline virtual double getDoubleVal(rowgroup::Row& row, bool& isNull); + inline virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull); // get all simple columns involved in this column const std::vector& simpleColumnList(); @@ -253,6 +255,11 @@ inline double SimpleFilter::getDoubleVal(rowgroup::Row& row, bool& isNull) return getIntVal(row, isNull); } +inline long double SimpleFilter::getLongDoubleVal(rowgroup::Row& row, bool& isNull) +{ + return getIntVal(row, isNull); +} + typedef boost::shared_ptr SSFP; std::ostream& operator<<(std::ostream& output, const SimpleFilter& rhs); diff --git a/dbcon/execplan/treenode.h b/dbcon/execplan/treenode.h index d43239563..91ceb2a11 100644 --- a/dbcon/execplan/treenode.h +++ b/dbcon/execplan/treenode.h @@ -1,4 +1,5 @@ /* 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 @@ -239,7 +240,7 @@ inline std::string removeTrailing0(char* val, uint32_t length) struct Result { Result(): intVal(0), uintVal(0), origIntVal(0), dummy(0), - doubleVal(0), floatVal(0), boolVal(false), + doubleVal(0), longDoubleVal(0), floatVal(0), boolVal(false), strVal(""), decimalVal(IDB_Decimal(0, 0, 0)), valueConverted(false) {} int64_t intVal; @@ -249,6 +250,7 @@ struct Result // when converting origIntVal uint64_t dummy; double doubleVal; + long double longDoubleVal; float floatVal; bool boolVal; std::string strVal; @@ -376,6 +378,10 @@ public: { 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; @@ -404,6 +410,7 @@ public: 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(); @@ -517,6 +524,9 @@ inline bool TreeNode::getBoolVal() 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); @@ -646,6 +656,40 @@ inline const std::string& TreeNode::getStrVal() 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; } @@ -736,6 +780,9 @@ inline int64_t TreeNode::getIntVal() case CalpontSystemCatalog::UDOUBLE: return (int64_t)fResult.doubleVal; + case CalpontSystemCatalog::LONGDOUBLE: + return (int64_t)fResult.longDoubleVal; + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { @@ -779,6 +826,9 @@ inline uint64_t TreeNode::getUintVal() case CalpontSystemCatalog::UDOUBLE: return (uint64_t)fResult.doubleVal; + case CalpontSystemCatalog::LONGDOUBLE: + return (uint64_t)fResult.longDoubleVal; + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { @@ -843,6 +893,9 @@ inline float TreeNode::getFloatVal() 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)); @@ -906,6 +959,9 @@ inline double TreeNode::getDoubleVal() case CalpontSystemCatalog::UDOUBLE: return fResult.doubleVal; + case CalpontSystemCatalog::LONGDOUBLE: + return (double)fResult.longDoubleVal; + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { @@ -924,6 +980,74 @@ inline double TreeNode::getDoubleVal() 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) @@ -942,7 +1066,7 @@ inline IDB_Decimal TreeNode::getDecimalVal() case CalpontSystemCatalog::INT: case CalpontSystemCatalog::SMALLINT: case CalpontSystemCatalog::TINYINT: - fResult.decimalVal.value = (int64_t)(fResult.intVal * pow((double)10, fResultType.scale)); + fResult.decimalVal.value = (int64_t)(fResult.intVal * pow((double)10.0, fResultType.scale)); fResult.decimalVal.scale = fResultType.scale; fResult.decimalVal.precision = fResultType.precision; break; @@ -952,11 +1076,28 @@ inline IDB_Decimal TreeNode::getDecimalVal() case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::USMALLINT: case CalpontSystemCatalog::UTINYINT: - fResult.decimalVal.value = (int64_t)(fResult.uintVal * pow((double)10, fResultType.scale)); + 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."); diff --git a/dbcon/execplan/windowfunctioncolumn.cpp b/dbcon/execplan/windowfunctioncolumn.cpp index b1377880f..e01c5c010 100644 --- a/dbcon/execplan/windowfunctioncolumn.cpp +++ b/dbcon/execplan/windowfunctioncolumn.cpp @@ -1,4 +1,5 @@ /* 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 @@ -378,6 +379,14 @@ void WindowFunctionColumn::adjustResultType() boost::iequals(fFunctionName, "NTH_VALUE")) && !fFunctionParms.empty()) fResultType = fFunctionParms[0]->resultType(); + + if (boost::iequals(fFunctionName, "SUM") || + boost::iequals(fFunctionName, "AVG")) + { + fResultType.colDataType = CalpontSystemCatalog::LONGDOUBLE; + fResultType.colWidth = sizeof(long double); + fResultType.precision = -1; + } } void WindowFunctionColumn::evaluate(Row& row, bool& isNull) @@ -583,6 +592,16 @@ void WindowFunctionColumn::evaluate(Row& row, bool& isNull) break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + if (row.equals(LONGDOUBLENULL, fInputIndex)) + isNull = true; + else + fResult.longDoubleVal = row.getLongDoubleField(fInputIndex); + + break; + } + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { diff --git a/dbcon/execplan/windowfunctioncolumn.h b/dbcon/execplan/windowfunctioncolumn.h index 47c82b805..55f062990 100644 --- a/dbcon/execplan/windowfunctioncolumn.h +++ b/dbcon/execplan/windowfunctioncolumn.h @@ -1,4 +1,5 @@ /* 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 @@ -202,6 +203,12 @@ public: return TreeNode::getDoubleVal(); } + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + evaluate(row, isNull); + return TreeNode::getLongDoubleVal(); + } + virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull) { evaluate(row, isNull); diff --git a/dbcon/joblist/batchprimitiveprocessor-jl.cpp b/dbcon/joblist/batchprimitiveprocessor-jl.cpp index 8adf80e12..d8aab62b4 100644 --- a/dbcon/joblist/batchprimitiveprocessor-jl.cpp +++ b/dbcon/joblist/batchprimitiveprocessor-jl.cpp @@ -1,4 +1,5 @@ /* 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 @@ -1411,12 +1412,19 @@ bool BatchPrimitiveProcessorJL::nextTupleJoinerMsg(ByteStream& bs) } } - bs << (uint8_t) isNull; - if (!isNull) { tlData = makeTypelessKey(r, smallSideKeys[joinerNum], - tlKeyLens[joinerNum], &fa); + tlKeyLens[joinerNum], &fa, + largeSideRG, tJoiners[joinerNum]->getLargeKeyColumns()); + if (tlData.len == 0) + { + isNull = true; + } + } + bs << (uint8_t) isNull; + if (!isNull) + { tlData.serialize(bs); bs << i; } @@ -1442,7 +1450,48 @@ bool BatchPrimitiveProcessorJL::nextTupleJoinerMsg(ByteStream& bs) { r.setPointer((*tSmallSide)[i]); - if (r.isUnsigned(smallKeyCol)) + if ( r.getColType(smallKeyCol)== CalpontSystemCatalog::LONGDOUBLE) + { + // Small side is a long double. Since CS can't store larger than DOUBLE, + // we need to convert to whatever type large side is -- double or int64 + long double smallkeyld = r.getLongDoubleField(smallKeyCol); + switch (largeSideRG.getColType(tJoiners[joinerNum]->getLargeKeyColumns()[0])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + if (smallkeyld > MAX_DOUBLE || smallkeyld < MIN_DOUBLE) + { + smallkey = joblist::UBIGINTEMPTYROW; + } + else + { + double d = (double)smallkeyld; + smallkey = *(int64_t*)&d; + } + break; + } + default: + { + if (r.isUnsigned(smallKeyCol) && smallkeyld > MAX_UBIGINT) + { + smallkey = joblist::UBIGINTEMPTYROW; + } + else if (smallkeyld > MAX_BIGINT || smallkeyld < MIN_BIGINT) + { + smallkey = joblist::UBIGINTEMPTYROW; + } + else + { + smallkey = (int64_t)smallkeyld; + } + break; + } + } + } + else if (r.isUnsigned(smallKeyCol)) smallkey = r.getUintField(smallKeyCol); else smallkey = r.getIntField(smallKeyCol); diff --git a/dbcon/joblist/crossenginestep.h b/dbcon/joblist/crossenginestep.h index 242d00cdf..4ebf2ac9d 100644 --- a/dbcon/joblist/crossenginestep.h +++ b/dbcon/joblist/crossenginestep.h @@ -28,6 +28,7 @@ #include "jobstep.h" #include "primitivestep.h" +#include "threadnaming.h" using namespace std; @@ -192,6 +193,7 @@ protected: Runner(CrossEngineStep* step) : fStep(step) { } void operator()() { + utils::setThreadName("CESRunner"); fStep->execute(); } diff --git a/dbcon/joblist/diskjoinstep.h b/dbcon/joblist/diskjoinstep.h index 154571cdc..fbdda890a 100644 --- a/dbcon/joblist/diskjoinstep.h +++ b/dbcon/joblist/diskjoinstep.h @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (C) 2019 MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -18,6 +19,7 @@ #include "jobstep.h" #include "tuplehashjoin.h" #include "joinpartition.h" +#include "threadnaming.h" #include "../../utils/threadpool/prioritythreadpool.h" #ifndef DISKJOINSTEP_H @@ -65,6 +67,7 @@ private: Runner(DiskJoinStep* d) : djs(d) { } void operator()() { + utils::setThreadName("DJSMainRunner"); djs->mainRunner(); } DiskJoinStep* djs; @@ -92,6 +95,7 @@ private: Loader(DiskJoinStep* d) : djs(d) { } void operator()() { + utils::setThreadName("DJSLoader"); djs->loadFcn(); } DiskJoinStep* djs; @@ -114,6 +118,7 @@ private: Builder(DiskJoinStep* d) : djs(d) { } void operator()() { + utils::setThreadName("DJSBuilder"); djs->buildFcn(); } DiskJoinStep* djs; @@ -126,6 +131,7 @@ private: Joiner(DiskJoinStep* d) : djs(d) { } void operator()() { + utils::setThreadName("DJSJoiner"); djs->joinFcn(); } DiskJoinStep* djs; diff --git a/dbcon/joblist/groupconcat.cpp b/dbcon/joblist/groupconcat.cpp index 11429d053..fe7dd8482 100644 --- a/dbcon/joblist/groupconcat.cpp +++ b/dbcon/joblist/groupconcat.cpp @@ -1,4 +1,5 @@ /* 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 @@ -484,6 +485,12 @@ void GroupConcator::outputRow(std::ostringstream& oss, const rowgroup::Row& row) break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + oss << setprecision(15) << row.getLongDoubleField(*i); + break; + } + case CalpontSystemCatalog::FLOAT: case CalpontSystemCatalog::UFLOAT: { @@ -623,6 +630,7 @@ int64_t GroupConcator::lengthEstimate(const rowgroup::Row& row) case CalpontSystemCatalog::UDOUBLE: case CalpontSystemCatalog::FLOAT: case CalpontSystemCatalog::UFLOAT: + case CalpontSystemCatalog::LONGDOUBLE: { fieldLen = 1; // minimum length break; diff --git a/dbcon/joblist/jlf_common.cpp b/dbcon/joblist/jlf_common.cpp index 4b1980d49..7ce066427 100644 --- a/dbcon/joblist/jlf_common.cpp +++ b/dbcon/joblist/jlf_common.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -838,6 +838,17 @@ bool compatibleColumnTypes(const CalpontSystemCatalog::ColDataType& dt1, uint32_ break; + case CalpontSystemCatalog::LONGDOUBLE: + if (forJoin && (dt2 != CalpontSystemCatalog::LONGDOUBLE)) + return false; + else if (dt2 != CalpontSystemCatalog::FLOAT && + dt2 != CalpontSystemCatalog::DOUBLE && + dt2 != CalpontSystemCatalog::UFLOAT && + dt2 != CalpontSystemCatalog::UDOUBLE && + dt2 != CalpontSystemCatalog::LONGDOUBLE) return false; + + break; + default: return false; break; diff --git a/dbcon/joblist/jlf_common.h b/dbcon/joblist/jlf_common.h index 669a26b4b..18c1ea396 100644 --- a/dbcon/joblist/jlf_common.h +++ b/dbcon/joblist/jlf_common.h @@ -1,4 +1,5 @@ /* 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 @@ -277,10 +278,6 @@ struct JobInfo std::multimap cloneAggregateColMap; std::vector > aggEidIndexList; - // for AVG to support CNX_USE_DECIMAL_SCALE - // map - std::map scaleOfAvg; - // table pairs with incompatible join which is treated as expression std::map incompatibleJoinMap; diff --git a/dbcon/joblist/jlf_subquery.cpp b/dbcon/joblist/jlf_subquery.cpp index 1e4eaeeec..7f2544be8 100644 --- a/dbcon/joblist/jlf_subquery.cpp +++ b/dbcon/joblist/jlf_subquery.cpp @@ -1,4 +1,5 @@ /* 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 @@ -125,6 +126,11 @@ void getColumnValue(ConstantColumn** cc, uint64_t i, const Row& row) *cc = new ConstantColumn(oss.str(), row.getDoubleField(i)); break; + case CalpontSystemCatalog::LONGDOUBLE: + oss << fixed << row.getLongDoubleField(i); + *cc = new ConstantColumn(oss.str(), row.getLongDoubleField(i)); + break; + case CalpontSystemCatalog::DATE: oss << dataconvert::DataConvert::dateToString(row.getUintField<4>(i)); *cc = new ConstantColumn(oss.str()); diff --git a/dbcon/joblist/jlf_tuplejoblist.cpp b/dbcon/joblist/jlf_tuplejoblist.cpp index b006eb90c..5337215d2 100644 --- a/dbcon/joblist/jlf_tuplejoblist.cpp +++ b/dbcon/joblist/jlf_tuplejoblist.cpp @@ -1,4 +1,5 @@ /* 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 @@ -1454,7 +1455,10 @@ bool addFunctionJoin(vector& joinedTables, JobStepVector& joinSteps, TupleInfo ti1 = getTupleInfo(key1, jobInfo); TupleInfo ti2 = getTupleInfo(key2, jobInfo); - if (ti1.dtype == CalpontSystemCatalog::CHAR || ti1.dtype == CalpontSystemCatalog::VARCHAR || ti1.dtype == CalpontSystemCatalog::TEXT) + if (ti1.dtype == CalpontSystemCatalog::CHAR + || ti1.dtype == CalpontSystemCatalog::VARCHAR + || ti1.dtype == CalpontSystemCatalog::TEXT) +// || ti1.dtype == CalpontSystemCatalog::LONGDOUBLE) m1->second.fTypeless = m2->second.fTypeless = true; // ti2 is compatible else m1->second.fTypeless = m2->second.fTypeless = false; @@ -3623,9 +3627,21 @@ void associateTupleJobSteps(JobStepVector& querySteps, JobStepVector& projectSte TupleInfo ti2(getTupleInfo(key2, jobInfo)); if (ti1.width > 8 || ti2.width > 8) - m1->second.fTypeless = m2->second.fTypeless = true; + { + if (ti1.dtype == execplan::CalpontSystemCatalog::LONGDOUBLE + || ti2.dtype == execplan::CalpontSystemCatalog::LONGDOUBLE) + { + m1->second.fTypeless = m2->second.fTypeless = false; + } + else + { + m1->second.fTypeless = m2->second.fTypeless = true; + } + } else + { m1->second.fTypeless = m2->second.fTypeless = false; + } } else { diff --git a/dbcon/joblist/joblistfactory.cpp b/dbcon/joblist/joblistfactory.cpp index 04989e7b7..b0c314364 100644 --- a/dbcon/joblist/joblistfactory.cpp +++ b/dbcon/joblist/joblistfactory.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -695,44 +695,13 @@ void updateAggregateColType(AggregateColumn* ac, const SRCP& srcp, int op, JobIn else if ((fc = dynamic_cast(srcp.get())) != NULL) ct = fc->resultType(); - if (op == AggregateColumn::SUM || op == AggregateColumn::DISTINCT_SUM) - { - if (ct.colDataType == CalpontSystemCatalog::TINYINT || - ct.colDataType == CalpontSystemCatalog::SMALLINT || - ct.colDataType == CalpontSystemCatalog::MEDINT || - ct.colDataType == CalpontSystemCatalog::INT || - ct.colDataType == CalpontSystemCatalog::BIGINT || - ct.colDataType == CalpontSystemCatalog::DECIMAL || - ct.colDataType == CalpontSystemCatalog::UDECIMAL) - { - ct.colWidth = sizeof(int64_t); - - if (ct.scale != 0) - ct.colDataType = CalpontSystemCatalog::DECIMAL; - else - ct.colDataType = CalpontSystemCatalog::BIGINT; - - ct.precision = 19; - } - - if (ct.colDataType == CalpontSystemCatalog::UTINYINT || - ct.colDataType == CalpontSystemCatalog::USMALLINT || - ct.colDataType == CalpontSystemCatalog::UMEDINT || - ct.colDataType == CalpontSystemCatalog::UINT || - ct.colDataType == CalpontSystemCatalog::UBIGINT) - { - ct.colWidth = sizeof(uint64_t); - ct.colDataType = CalpontSystemCatalog::UBIGINT; - ct.precision = 20; - } - } - else if (op == AggregateColumn::STDDEV_POP || op == AggregateColumn::STDDEV_SAMP || - op == AggregateColumn::VAR_POP || op == AggregateColumn::VAR_SAMP) + if (op == AggregateColumn::STDDEV_POP || op == AggregateColumn::STDDEV_SAMP || + op == AggregateColumn::VAR_POP || op == AggregateColumn::VAR_SAMP) { ct.colWidth = sizeof(double); ct.colDataType = CalpontSystemCatalog::DOUBLE; ct.scale = 0; - ct.precision = 0; + ct.precision = -1; } else if (op == AggregateColumn::UDAF) { @@ -1059,7 +1028,11 @@ const JobStepVector doAggProject(const CalpontSelectExecutionPlan* csep, JobInfo // Set the col type based on the single parm. // Changing col type based on a parm if multiple parms // doesn't really make sense. - updateAggregateColType(aggc, srcp, op, jobInfo); + if (op != AggregateColumn::SUM && op != AggregateColumn::DISTINCT_SUM && + op != AggregateColumn::AVG && op != AggregateColumn::DISTINCT_AVG) + { + updateAggregateColType(aggc, srcp, op, jobInfo); + } } aggCt = aggc->resultType(); @@ -1203,9 +1176,6 @@ const JobStepVector doAggProject(const CalpontSelectExecutionPlan* csep, JobInfo // remember the columns to be returned jobInfo.returnedColVec.push_back(make_pair(tupleKey, op)); - if (op == AggregateColumn::AVG || op == AggregateColumn::DISTINCT_AVG) - jobInfo.scaleOfAvg[tupleKey] = (ct.scale << 8) + aggCt.scale; - // bug 1499 distinct processing, save unique distinct columns if (doDistinct && (jobInfo.distinctColVec.end() == @@ -1354,9 +1324,6 @@ const JobStepVector doAggProject(const CalpontSelectExecutionPlan* csep, JobInfo // remember the columns to be returned jobInfo.returnedColVec.push_back(make_pair(tupleKey, op)); - if (op == AggregateColumn::AVG || op == AggregateColumn::DISTINCT_AVG) - jobInfo.scaleOfAvg[tupleKey] = (ct.scale << 8) + aggCt.scale; - // bug 1499 distinct processing, save unique distinct columns if (doDistinct && (jobInfo.distinctColVec.end() == diff --git a/dbcon/joblist/joblisttypes.h b/dbcon/joblist/joblisttypes.h index 37d52f9f4..6fd099330 100644 --- a/dbcon/joblist/joblisttypes.h +++ b/dbcon/joblist/joblisttypes.h @@ -1,4 +1,5 @@ /* 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 @@ -25,6 +26,7 @@ #include #include +#include namespace joblist { @@ -51,6 +53,7 @@ const uint32_t FLOATNULL = 0xFFAAAAAA; const uint32_t FLOATEMPTYROW = 0xFFAAAAAB; const uint64_t DOUBLENULL = 0xFFFAAAAAAAAAAAAAULL; const uint64_t DOUBLEEMPTYROW = 0xFFFAAAAAAAAAAAABULL; +const long double LONGDOUBLENULL = INFINITY; const uint32_t DATENULL = 0xFFFFFFFE; const uint32_t DATEEMPTYROW = 0xFFFFFFFF; diff --git a/dbcon/joblist/limitedorderby.cpp b/dbcon/joblist/limitedorderby.cpp index de7f9bcb6..1b5c307cb 100644 --- a/dbcon/joblist/limitedorderby.cpp +++ b/dbcon/joblist/limitedorderby.cpp @@ -77,8 +77,6 @@ void LimitedOrderBy::initialize(const RowGroup& rg, const JobInfo& jobInfo) map::iterator j = keyToIndexMap.find(i->first); idbassert(j != keyToIndexMap.end()); - // TODO Ordering direction in CSEP differs from - // internal direction representation. This behavior should be fixed fOrderByCond.push_back(IdbSortSpec(j->second, i->second)); } @@ -86,16 +84,14 @@ void LimitedOrderBy::initialize(const RowGroup& rg, const JobInfo& jobInfo) fStart = jobInfo.limitStart; fCount = jobInfo.limitCount; -// fMemSize = (fStart + fCount) * rg.getRowSize(); - IdbOrderBy::initialize(rg); } - +// This must return a proper number of key columns and +// not just a column count. uint64_t LimitedOrderBy::getKeyLength() const { - //return (fRow0.getSize() - 2); - return fRow0.getColumnCount(); + return fOrderByCond.size(); } diff --git a/dbcon/joblist/pdictionaryscan.cpp b/dbcon/joblist/pdictionaryscan.cpp index 47f469723..6c1b7cecd 100644 --- a/dbcon/joblist/pdictionaryscan.cpp +++ b/dbcon/joblist/pdictionaryscan.cpp @@ -63,6 +63,8 @@ using namespace rowgroup; #include "querytele.h" using namespace querytele; +#include "threadnaming.h" + namespace joblist { @@ -75,6 +77,7 @@ struct pDictionaryScanPrimitive { try { + utils::setThreadName("DSSScan"); fPDictScan->sendPrimitiveMessages(); } catch (runtime_error& re) @@ -99,6 +102,7 @@ struct pDictionaryScanAggregator { try { + utils::setThreadName("DSSAgg"); fPDictScan->receivePrimitiveMessages(); } catch (runtime_error& re) diff --git a/dbcon/joblist/primitivestep.h b/dbcon/joblist/primitivestep.h index 8dd02e0e1..588dd49bb 100644 --- a/dbcon/joblist/primitivestep.h +++ b/dbcon/joblist/primitivestep.h @@ -1,4 +1,5 @@ /* 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 @@ -391,7 +392,7 @@ private: boost::condition condvar; boost::condition flushed; SP_LBIDList lbidList; - std::vector scanFlags; // use to keep track of which extents to eliminate from this step + std::vector scanFlags; // use to keep track of which extents to eliminate from this step uint32_t uniqueID; //@bug 2634 diff --git a/dbcon/joblist/subquerystep.h b/dbcon/joblist/subquerystep.h index 2ce6ec579..d69863df5 100644 --- a/dbcon/joblist/subquerystep.h +++ b/dbcon/joblist/subquerystep.h @@ -31,6 +31,7 @@ #include "jobstep.h" #include "joblist.h" #include "funcexpwrapper.h" +#include "threadnaming.h" namespace joblist { @@ -264,6 +265,7 @@ protected: Runner(SubAdapterStep* step) : fStep(step) { } void operator()() { + utils::setThreadName("SQSRunner"); fStep->execute(); } diff --git a/dbcon/joblist/subquerytransformer.cpp b/dbcon/joblist/subquerytransformer.cpp index c212c701d..753438387 100644 --- a/dbcon/joblist/subquerytransformer.cpp +++ b/dbcon/joblist/subquerytransformer.cpp @@ -1,4 +1,5 @@ /* 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 @@ -230,8 +231,15 @@ SJSTEP& SubQueryTransformer::makeSubQueryStep(execplan::CalpontSelectExecutionPl ct.colDataType = row.getColTypes()[i]; ct.scale = row.getScale(i); - if (ct.scale != 0 && ct.precision != -1) - ct.colDataType = CalpontSystemCatalog::DECIMAL; + if (colDataTypeInRg != CalpontSystemCatalog::FLOAT && + colDataTypeInRg != CalpontSystemCatalog::UFLOAT && + colDataTypeInRg != CalpontSystemCatalog::DOUBLE && + colDataTypeInRg != CalpontSystemCatalog::UDOUBLE && + colDataTypeInRg != CalpontSystemCatalog::LONGDOUBLE) + { + if (ct.scale != 0 && ct.precision != -1) + ct.colDataType = CalpontSystemCatalog::DECIMAL; + } ct.precision = row.getPrecision(i); fVtable.columnType(ct, i); diff --git a/dbcon/joblist/tuple-bps.cpp b/dbcon/joblist/tuple-bps.cpp index b42533763..de46f85d0 100644 --- a/dbcon/joblist/tuple-bps.cpp +++ b/dbcon/joblist/tuple-bps.cpp @@ -70,6 +70,8 @@ using namespace BRM; #include "rowgroup.h" using namespace rowgroup; +#include "threadnaming.h" + #include "querytele.h" using namespace querytele; @@ -106,6 +108,7 @@ struct TupleBPSPrimitive { try { + utils::setThreadName("BPSPrimitive"); fBatchPrimitiveStep->sendPrimitiveMessages(); } catch (std::exception& re) @@ -135,6 +138,7 @@ struct TupleBPSAggregators { try { + utils::setThreadName("BPSAggregator"); fBatchPrimitiveStepCols->receiveMultiPrimitiveMessages(fThreadId); } catch (std::exception& re) @@ -276,7 +280,6 @@ TupleBPS::TupleBPS(const pColStep& rhs, const JobInfo& jobInfo) : hasPCFilter = hasPMFilter = hasRIDFilter = hasSegmentFilter = hasDBRootFilter = hasSegmentDirFilter = hasPartitionFilter = hasMaxFilter = hasMinFilter = hasLBIDFilter = hasExtentIDFilter = false; -// cout << "TBPSCount = " << ++TBPSCount << endl; } TupleBPS::TupleBPS(const pColScanStep& rhs, const JobInfo& jobInfo) : @@ -336,8 +339,6 @@ TupleBPS::TupleBPS(const pColScanStep& rhs, const JobInfo& jobInfo) : fBPP->setTxnID(fTxnId); fTraceFlags = rhs.fTraceFlags; fBPP->setTraceFlags(fTraceFlags); -// if (fOid>=3000) -// cout << "BPS:initalized from pColScanStep. fSessionId=" << fSessionId << endl; fBPP->setStepID(fStepId); fBPP->setOutputType(ROW_GROUP); fPhysicalIO = 0; @@ -352,9 +353,6 @@ TupleBPS::TupleBPS(const pColScanStep& rhs, const JobInfo& jobInfo) : hasUMJoin = false; fRunExecuted = false; smallOuterJoiner = -1; - // @1098 initialize scanFlags to be true - //scanFlags.assign(numExtents, true); - //runtimeCPFlags.assign(numExtents, true); bop = BOP_AND; runRan = joinRan = false; @@ -405,9 +403,6 @@ TupleBPS::TupleBPS(const PassThruStep& rhs, const JobInfo& jobInfo) : fTraceFlags = rhs.fTraceFlags; fBPP->setTraceFlags(fTraceFlags); fBPP->setOutputType(ROW_GROUP); -// if (fOid>=3000) -// cout << "BPS:initalized from PassThruStep. fSessionId=" << fSessionId << endl; - finishedSending = sendWaiting = false; fSwallowRows = false; fNumBlksSkipped = 0; @@ -437,7 +432,6 @@ TupleBPS::TupleBPS(const PassThruStep& rhs, const JobInfo& jobInfo) : hasPCFilter = hasPMFilter = hasRIDFilter = hasSegmentFilter = hasDBRootFilter = hasSegmentDirFilter = hasPartitionFilter = hasMaxFilter = hasMinFilter = hasLBIDFilter = hasExtentIDFilter = false; -// cout << "TBPSCount = " << ++TBPSCount << endl; } TupleBPS::TupleBPS(const pDictionaryStep& rhs, const JobInfo& jobInfo) : @@ -463,7 +457,6 @@ TupleBPS::TupleBPS(const pDictionaryStep& rhs, const JobInfo& jobInfo) : fStepCount = 1; fCPEvaluated = false; fEstimatedRows = 0; - //fColType = rhs.colType(); alias(rhs.alias()); view(rhs.view()); name(rhs.name()); @@ -472,8 +465,6 @@ TupleBPS::TupleBPS(const pDictionaryStep& rhs, const JobInfo& jobInfo) : fBPP.reset(new BatchPrimitiveProcessorJL(fRm)); initializeConfigParms(); fBPP->setSessionID(fSessionId); -// if (fOid>=3000) -// cout << "BPS:initalized from DictionaryStep. fSessionId=" << fSessionId << endl; fBPP->setStepID(fStepId); fBPP->setQueryContext(fVerId); fBPP->setTxnID(fTxnId); @@ -506,7 +497,6 @@ TupleBPS::TupleBPS(const pDictionaryStep& rhs, const JobInfo& jobInfo) : hasPCFilter = hasPMFilter = hasRIDFilter = hasSegmentFilter = hasDBRootFilter = hasSegmentDirFilter = hasPartitionFilter = hasMaxFilter = hasMinFilter = hasLBIDFilter = hasExtentIDFilter = false; -// cout << "TBPSCount = " << ++TBPSCount << endl; } TupleBPS::~TupleBPS() @@ -541,7 +531,6 @@ TupleBPS::~TupleBPS() fDec->removeQueue(uniqueID); } -// cout << "~TBPSCount = " << --TBPSCount << endl; } void TupleBPS::setBPP(JobStep* jobStep) @@ -558,7 +547,6 @@ void TupleBPS::setBPP(JobStep* jobStep) if (pseudo) { - //cout << "adding a pseudo col filter" << endl; fBPP->addFilterStep(*pseudo); if (pseudo->filterCount() > 0) @@ -690,8 +678,6 @@ void TupleBPS::setProjectBPP(JobStep* jobStep1, JobStep* jobStep2) colWidth = (pcsp->colType()).colWidth; projectOids.push_back(jobStep1->oid()); -// if (fOid>=3000) -// cout << "Adding project step pColStep and pDictionaryStep to BPS" << endl; } else { @@ -708,8 +694,6 @@ void TupleBPS::setProjectBPP(JobStep* jobStep1, JobStep* jobStep2) projectOids.push_back(jobStep1->oid()); colWidth = (psth->colType()).colWidth; -// if (fOid>=3000) -// cout << "Adding project step PassThruStep and pDictionaryStep to BPS" << endl; } } } @@ -723,7 +707,6 @@ void TupleBPS::setProjectBPP(JobStep* jobStep1, JobStep* jobStep2) if (pseudo) { - //cout << "adding a pseudo col projection" << endl; fBPP->addProjectStep(*pseudo); } else @@ -835,7 +818,6 @@ void TupleBPS::storeCasualPartitionInfo(const bool estimateRowCounts) } } - //cout << "cp column number=" << cpColVec.size() << " 1st col extents size= " << scanFlags.size() << endl; if (cpColVec.size() == 0) return; @@ -900,12 +882,8 @@ void TupleBPS::startAggregationThread() fProducerThreads.push_back(jobstepThreadPool.invoke(TupleBPSAggregators(this, fNumThreads - 1))); } -//#include "boost/date_time/posix_time/posix_time.hpp" - void TupleBPS::serializeJoiner() { -// boost::posix_time::ptime start, stop; -// start = boost::posix_time::microsec_clock::local_time(); ByteStream bs; bool more = true; @@ -925,8 +903,6 @@ void TupleBPS::serializeJoiner() bs.restart(); } -// stop = boost::posix_time::microsec_clock::local_time(); -// cout << "serializing took " << stop-start << endl; } void TupleBPS::serializeJoiner(uint32_t conn) @@ -957,8 +933,6 @@ void TupleBPS::prepCasualPartitioning() { if (fOid >= 3000) { - //if (scanFlags[i] && !runtimeCPFlags[i]) - // cout << "runtime flags eliminated an extent!\n"; scanFlags[i] = scanFlags[i] && runtimeCPFlags[i]; if (scanFlags[i] && lbidList->CasualPartitionDataType(fColType.colDataType, @@ -1209,22 +1183,10 @@ void TupleBPS::run() if (fe2) { - //if (fDelivery) { - // fe2Data.reinit(fe2Output); - // fe2Output.setData(&fe2Data); - //} primRowGroup.initRow(&fe2InRow); fe2Output.initRow(&fe2OutRow); } - /* - if (doJoin) { - for (uint32_t z = 0; z < smallSideCount; z++) - cout << "join #" << z << " " << "0x" << hex << tjoiners[z]->getJoinType() - << std::dec << " typeless: " << (uint32_t) tjoiners[z]->isTypelessJoin() << endl; - } - */ - try { fDec->addDECEventListener(this); @@ -1330,7 +1292,6 @@ void TupleBPS::sendError(uint16_t status) } fBPP->reset(); -// msgsSent++; // not expecting a response from this msg finishedSending = true; condvar.notify_all(); condvarWakeupProducer.notify_all(); @@ -1441,7 +1402,6 @@ void TupleBPS::sendJobs(const vector& jobs) for (i = 0; i < jobs.size() && !cancelled(); i++) { - //cout << "sending a job for dbroot " << jobs[i].dbroot << ", PM " << jobs[i].connectionNum << endl; fDec->write(uniqueID, *(jobs[i].msg)); tplLock.lock(); msgsSent += jobs[i].expectedResponses; @@ -1785,20 +1745,17 @@ void TupleBPS::makeJobs(vector* jobs) if (!inBounds) { - //cout << "out of bounds" << endl; continue; } if (!scanFlags[i]) { - //cout << "CP elimination" << endl; fNumBlksSkipped += lbidsToScan; continue; } if (!processPseudoColFilters(i, dbRootPMMap)) { - //cout << "Skipping an extent due to pseudo-column filter elimination" << endl; fNumBlksSkipped += lbidsToScan; continue; } @@ -1840,8 +1797,6 @@ void TupleBPS::makeJobs(vector* jobs) } } -// cout << " session " << fSessionId << " idx = " << i << " HWM = " << scannedExtents[i].HWM -// << " ... will scan " << lbidsToScan << " lbids\n"; // the # of logical blocks in this extent if (lbidsToScan % fColType.colWidth) @@ -1857,22 +1812,17 @@ void TupleBPS::makeJobs(vector* jobs) #else blocksPerJob = max(blocksToScan / fProcessorThreadsPerScan, 16U); #endif - //cout << "blocks to scan = " << blocksToScan << " blocks per job = " << blocksPerJob << - // " HWM == " << scannedExtents[i].HWM << endl; startingLBID = scannedExtents[i].range.start; while (blocksToScan > 0) { uint32_t blocksThisJob = min(blocksToScan, blocksPerJob); - //cout << "starting LBID = " << startingLBID << " count = " << blocksThisJob << - // " dbroot = " << scannedExtents[i].dbRoot << endl; fBPP->setLBID(startingLBID, scannedExtents[i]); fBPP->setCount(blocksThisJob); bs.reset(new ByteStream()); fBPP->runBPP(*bs, (*dbRootConnectionMap)[scannedExtents[i].dbRoot]); - //cout << "making job for connection # " << (*dbRootConnectionMap)[scannedExtents[i].dbRoot] << endl; jobs->push_back(Job(scannedExtents[i].dbRoot, (*dbRootConnectionMap)[scannedExtents[i].dbRoot], blocksThisJob, bs)); blocksToScan -= blocksThisJob; @@ -1881,7 +1831,6 @@ void TupleBPS::makeJobs(vector* jobs) } } -// cout << "session " << fSessionId << " sees " << extentCounter << " extents" << endl; } void TupleBPS::sendPrimitiveMessages() @@ -1901,19 +1850,16 @@ void TupleBPS::sendPrimitiveMessages() } catch (const IDBExcept& e) { - //cout << "Caught IDBExcept" << e.what() << e.errorCode() << endl; sendError(e.errorCode()); processError(e.what(), e.errorCode(), "TupleBPS::sendPrimitiveMessages()"); } catch (const std::exception& ex) { - //cout << "Caught exception" << endl; sendError(ERR_TUPLE_BPS); processError(ex.what(), ERR_TUPLE_BPS, "TupleBPS::sendPrimitiveMessages()"); } catch (...) { - //cout << "Caught ..." << endl; sendError(ERR_TUPLE_BPS); processError("unknown", ERR_TUPLE_BPS, "TupleBPS::sendPrimitiveMessages()"); } @@ -2189,7 +2135,6 @@ void TupleBPS::receiveMultiPrimitiveMessages(uint32_t threadID) tplLock.unlock(); -// cout << "thread " << threadID << " has " << size << " Bytestreams\n"; for (i = 0; i < size && !cancelled(); i++) { ByteStream* bs = bsv[i].get(); @@ -2244,18 +2189,16 @@ void TupleBPS::receiveMultiPrimitiveMessages(uint32_t threadID) local_outputRG.resetRowGroup(local_primRG.getBaseRid()); local_outputRG.setDBRoot(local_primRG.getDBRoot()); local_primRG.getRow(0, &largeSideRow); - //cout << "large-side raw data: " << local_primRG.toString() << endl; - //cout << "jointype = " << tjoiners[0]->getJoinType() << endl; for (k = 0; k < local_primRG.getRowCount() && !cancelled(); k++, largeSideRow.nextRow()) { - //cout << "TBPS: Large side row: " << largeSideRow.toString() << endl; matchCount = 0; for (j = 0; j < smallSideCount; j++) { tjoiners[j]->match(largeSideRow, k, threadID, &joinerOutput[j]); - /* Debugging code to print the matches +#ifdef JLF_DEBUG + // Debugging code to print the matches Row r; joinerMatchesRGs[j].initRow(&r); cout << joinerOutput[j].size() << " matches: \n"; @@ -2263,7 +2206,7 @@ void TupleBPS::receiveMultiPrimitiveMessages(uint32_t threadID) r.setPointer(joinerOutput[j][z]); cout << " " << r.toString() << endl; } - */ +#endif matchCount = joinerOutput[j].size(); if (tjoiners[j]->inUM()) @@ -2271,7 +2214,6 @@ void TupleBPS::receiveMultiPrimitiveMessages(uint32_t threadID) /* Count the # of rows that pass the join filter */ if (tjoiners[j]->hasFEFilter() && matchCount > 0) { - //cout << "doing FE filter" << endl; vector newJoinerOutput; applyMapping(fergMappings[smallSideCount], largeSideRow, &joinFERow); @@ -2311,10 +2253,6 @@ void TupleBPS::receiveMultiPrimitiveMessages(uint32_t threadID) if (tjoiners[j]->antiJoin()) { matchCount = (matchCount ? 0 : 1); - // if (matchCount) - // cout << "in the result\n"; - // else - // cout << "not in the result\n"; } if (matchCount == 0) @@ -2380,7 +2318,6 @@ void TupleBPS::receiveMultiPrimitiveMessages(uint32_t threadID) } else { -// cout << "TBPS: sending unjoined data\n"; rgDatav.push_back(rgData); } @@ -2488,7 +2425,6 @@ out: { smallSideRows[i].setPointer(unmatched[j]); -// cout << "small side Row: " << smallSideRows[i].toString() << endl; for (k = 0; k < smallSideCount; k++) { if (i == k) @@ -2499,8 +2435,6 @@ out: applyMapping(largeMapping, largeNull, &joinedBaseRow); joinedBaseRow.setRid(0); -// cout << "outer row is " << joinedBaseRow.toString() << endl; -// joinedBaseRow.setRid(largeSideRow.getRelRid()); joinedBaseRow.nextRow(); local_outputRG.incRowCount(); @@ -2785,8 +2719,6 @@ inline bool TupleBPS::scanit(uint64_t rid) fbo = rid >> rpbShift; extentIndex = fbo >> divShift; - //if (scanFlags[extentIndex] && !runtimeCPFlags[extentIndex]) - // cout << "HJ feedback eliminated an extent!\n"; return scanFlags[extentIndex] && runtimeCPFlags[extentIndex]; } @@ -2908,7 +2840,6 @@ void TupleBPS::generateJoinResultSet(const vector >& joiner { smallRow.setPointer(joinerOutput[depth][i]); applyMapping(mappings[depth], smallRow, &baseRow); -// cout << "depth " << depth << ", size " << joinerOutput[depth].size() << ", row " << i << ": " << smallRow.toString() << endl; generateJoinResultSet(joinerOutput, baseRow, mappings, depth + 1, outputRG, rgData, outputData, smallRows, joinedRow); } @@ -2926,7 +2857,6 @@ void TupleBPS::generateJoinResultSet(const vector >& joiner { uint32_t dbRoot = outputRG.getDBRoot(); uint64_t baseRid = outputRG.getBaseRid(); -// cout << "GJRS adding data\n"; outputData->push_back(rgData); rgData = RGData(outputRG); outputRG.setData(&rgData); @@ -2935,11 +2865,8 @@ void TupleBPS::generateJoinResultSet(const vector >& joiner outputRG.getRow(0, &joinedRow); } -// cout << "depth " << depth << ", size " << joinerOutput[depth].size() << ", row " << i << ": " << smallRow.toString() << endl; applyMapping(mappings[depth], smallRow, &baseRow); copyRow(baseRow, &joinedRow); - //memcpy(joinedRow.getData(), baseRow.getData(), joinedRow.getSize()); - //cout << "(step " << fStepId << ") fully joined row is: " << joinedRow.toString() << endl; } } } @@ -3104,7 +3031,6 @@ void TupleBPS::processFE2_oneRG(RowGroup& input, RowGroup& output, Row& inRow, if (ret) { applyMapping(fe2Mapping, inRow, &outRow); - //cout << "fe2 passed row: " << outRow.toString() << endl; outRow.setRid(inRow.getRelRid()); output.incRowCount(); outRow.nextRow(); @@ -3153,7 +3079,6 @@ void TupleBPS::processFE2(RowGroup& input, RowGroup& output, Row& inRow, Row& ou output.getBaseRid() != input.getBaseRid() ) { -// cout << "FE2 produced a full RG\n"; results.push_back(result); result = RGData(output); output.setData(&result); @@ -3167,12 +3092,9 @@ void TupleBPS::processFE2(RowGroup& input, RowGroup& output, Row& inRow, Row& ou if (output.getRowCount() > 0) { -// cout << "FE2 produced " << output.getRowCount() << " rows\n"; results.push_back(result); } -// else -// cout << "no rows from FE2\n"; rgData->swap(results); } diff --git a/dbcon/joblist/tupleaggregatestep.cpp b/dbcon/joblist/tupleaggregatestep.cpp index 4c1893115..b4aec4013 100644 --- a/dbcon/joblist/tupleaggregatestep.cpp +++ b/dbcon/joblist/tupleaggregatestep.cpp @@ -1,4 +1,5 @@ /* 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 @@ -266,6 +267,9 @@ inline string colTypeIdString(CalpontSystemCatalog::ColDataType type) case CalpontSystemCatalog::DOUBLE: return string("DOUBLE"); + case CalpontSystemCatalog::LONGDOUBLE: + return string("LONGDOUBLE"); + case CalpontSystemCatalog::DATETIME: return string("DATETIME"); @@ -735,13 +739,13 @@ void TupleAggregateStep::configDeliveredRowGroup(const JobInfo& jobInfo) // correct the scale vector scale = fRowGroupOut.getScale(); - for (uint64_t i = 0; i < scale.size(); i++) - { +// for (uint64_t i = 0; i < scale.size(); i++) +// { // to support CNX_DECIMAL_SCALE the avg column's scale is coded with two scales: // fe's avg column scale << 8 + original column scale //if ((scale[i] & 0x0000FF00) > 0) - scale[i] = scale[i] & 0x000000FF; - } +// scale[i] = scale[i] & 0x000000FF; +// } size_t retColCount = jobInfo.nonConstDelCols.size(); @@ -1399,43 +1403,10 @@ void TupleAggregateStep::prep1PhaseAggregate( oidsAgg.push_back(oidsProj[colProj]); keysAgg.push_back(key); - - if (typeProj[colProj] == CalpontSystemCatalog::DOUBLE || - typeProj[colProj] == CalpontSystemCatalog::UDOUBLE || - typeProj[colProj] == CalpontSystemCatalog::FLOAT || - typeProj[colProj] == CalpontSystemCatalog::UFLOAT) - { - typeAgg.push_back(typeProj[colProj]); - scaleAgg.push_back(scaleProj[colProj]); - precisionAgg.push_back(precisionProj[colProj]); - widthAgg.push_back(width[colProj]); - } - else if (isUnsigned(typeProj[colProj])) - { - typeAgg.push_back(CalpontSystemCatalog::UBIGINT); - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[key]; // scale += 4; - - scaleAgg.push_back(scale); - precisionAgg.push_back(20); - widthAgg.push_back(bigUintWidth); - } - else - { - typeAgg.push_back(CalpontSystemCatalog::BIGINT); - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[key]; // scale += 4; - - scaleAgg.push_back(scale); - precisionAgg.push_back(19); - widthAgg.push_back(bigIntWidth); - } + typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAgg.push_back(-1); + widthAgg.push_back(sizeof(long double)); + scaleAgg.push_back(scaleProj[colProj]); } break; @@ -1447,16 +1418,7 @@ void TupleAggregateStep::prep1PhaseAggregate( scaleAgg.push_back(0); // work around count() in select subquery precisionAgg.push_back(9999); - - if (isUnsigned(typeProj[colProj])) - { - typeAgg.push_back(CalpontSystemCatalog::UBIGINT); - } - else - { - typeAgg.push_back(CalpontSystemCatalog::BIGINT); - } - + typeAgg.push_back(CalpontSystemCatalog::UBIGINT); widthAgg.push_back(bigIntWidth); } break; @@ -1600,7 +1562,7 @@ void TupleAggregateStep::prep1PhaseAggregate( keysAgg.push_back(k->first); scaleAgg.push_back(0); precisionAgg.push_back(19); - typeAgg.push_back(CalpontSystemCatalog::BIGINT); + typeAgg.push_back(CalpontSystemCatalog::UBIGINT); widthAgg.push_back(bigIntWidth); } } @@ -1640,7 +1602,7 @@ void TupleAggregateStep::prep1PhaseAggregate( oidsAgg.push_back(oidsAgg[j]); keysAgg.push_back(keysAgg[j]); scaleAgg.push_back(0); - precisionAgg.push_back(0); + precisionAgg.push_back(-1); typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAgg.push_back(sizeof(long double)); ++lastCol; @@ -1649,7 +1611,7 @@ void TupleAggregateStep::prep1PhaseAggregate( oidsAgg.push_back(oidsAgg[j]); keysAgg.push_back(keysAgg[j]); scaleAgg.push_back(0); - precisionAgg.push_back(0); + precisionAgg.push_back(-1); typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAgg.push_back(sizeof(long double)); ++lastCol; @@ -1970,47 +1932,19 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAgg.push_back(oidsProj[colProj]); keysAgg.push_back(aggKey); - - if (typeProj[colProj] != CalpontSystemCatalog::DOUBLE && - typeProj[colProj] != CalpontSystemCatalog::FLOAT) - { - if (isUnsigned(typeProj[colProj])) - { - typeAgg.push_back(CalpontSystemCatalog::UBIGINT); - precisionAgg.push_back(20); - } - else - { - typeAgg.push_back(CalpontSystemCatalog::BIGINT); - precisionAgg.push_back(19); - } - - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[aggKey]; // scale += 4; - - scaleAgg.push_back(scale); - widthAgg.push_back(bigIntWidth); - } - else - { - typeAgg.push_back(typeProj[colProj]); - scaleAgg.push_back(scaleProj[colProj]); - precisionAgg.push_back(precisionProj[colProj]); - widthAgg.push_back(widthProj[colProj]); - } - + typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAgg.push_back(-1); + widthAgg.push_back(sizeof(long double)); + scaleAgg.push_back(scaleProj[colProj]); colAgg++; - } - // has distinct step, put the count column for avg next to the sum - // let fall through to add a count column for average function + // has distinct step, put the count column for avg next to the sum + // let fall through to add a count column for average function if (aggOp == ROWAGG_AVG) funct->fAuxColumnIndex = colAgg; else break; + } case ROWAGG_COUNT_ASTERISK: case ROWAGG_COUNT_COL_NAME: @@ -2067,7 +2001,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAgg.push_back(oidsProj[colProj]); keysAgg.push_back(aggKey); scaleAgg.push_back(0); - precisionAgg.push_back(0); + precisionAgg.push_back(-1); typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAgg.push_back(sizeof(long double)); ++colAgg; @@ -2076,7 +2010,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAgg.push_back(oidsProj[colProj]); keysAgg.push_back(aggKey); scaleAgg.push_back(0); - precisionAgg.push_back(0); + precisionAgg.push_back(-1); typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAgg.push_back(sizeof(long double)); ++colAgg; @@ -2318,37 +2252,10 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAggDist.push_back(oidsAgg[colAgg]); keysAggDist.push_back(retKey); - - if (typeAgg[colAgg] != CalpontSystemCatalog::DOUBLE && - typeAgg[colAgg] != CalpontSystemCatalog::FLOAT) - { - if (isUnsigned(typeAgg[colAgg])) - { - typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); - precisionAggDist.push_back(20); - } - else - { - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); - precisionAggDist.push_back(19); - } - - uint32_t scale = scaleProj[colAgg]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_DISTINCT_AVG) - scale = jobInfo.scaleOfAvg[retKey]; // scale += 4; - - scaleAggDist.push_back(scale); - widthAggDist.push_back(bigIntWidth); - } - else - { - typeAggDist.push_back(typeAgg[colAgg]); - scaleAggDist.push_back(scaleAgg[colAgg]); - precisionAggDist.push_back(precisionAgg[colAgg]); - widthAggDist.push_back(widthAgg[colAgg]); - } + typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAggDist.push_back(-1); + widthAggDist.push_back(sizeof(long double)); + scaleAggDist.push_back(scaleProj[colAgg]); } break; @@ -2359,16 +2266,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( scaleAggDist.push_back(0); // work around count() in select subquery precisionAggDist.push_back(9999); - - if (isUnsigned(typeAgg[colAgg])) - { - typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); - } - else - { - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); - } - + typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); widthAggDist.push_back(bigIntWidth); } break; @@ -2656,7 +2554,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( keysAggDist.push_back(k->first); scaleAggDist.push_back(0); precisionAggDist.push_back(19); - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); + typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); widthAggDist.push_back(bigIntWidth); } } @@ -2736,7 +2634,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAggDist.push_back(oidsAggDist[j]); keysAggDist.push_back(keysAggDist[j]); scaleAggDist.push_back(0); - precisionAggDist.push_back(0); + precisionAggDist.push_back(-1); typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggDist.push_back(sizeof(long double)); ++lastCol; @@ -3152,9 +3050,9 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(key); scaleAggPm.push_back(scaleProj[colProj]); - precisionAggPm.push_back(precisionProj[colProj]); typeAggPm.push_back(typeProj[colProj]); widthAggPm.push_back(width[colProj]); + precisionAggPm.push_back(precisionProj[colProj]); aggFuncMap.insert(make_pair(boost::make_tuple(keysAggPm[colAggPm], 0, pUDAFFunc, udafc ? udafc->getContext().getParamKeys() : NULL), colAggPm)); colAggPm++; @@ -3274,49 +3172,15 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); - - if (typeProj[colProj] == CalpontSystemCatalog::DOUBLE || - typeProj[colProj] == CalpontSystemCatalog::UDOUBLE || - typeProj[colProj] == CalpontSystemCatalog::FLOAT || - typeProj[colProj] == CalpontSystemCatalog::UFLOAT) - { - typeAggPm.push_back(typeProj[colProj]); - scaleAggPm.push_back(scaleProj[colProj]); - precisionAggPm.push_back(precisionProj[colProj]); - widthAggPm.push_back(width[colProj]); - } - else if (isUnsigned(typeProj[colProj])) - { - typeAggPm.push_back(CalpontSystemCatalog::UBIGINT); - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[aggKey]; // scale += 4; - - scaleAggPm.push_back(scale); - precisionAggPm.push_back(20); - widthAggPm.push_back(bigUintWidth); - } - else - { - typeAggPm.push_back(CalpontSystemCatalog::BIGINT); - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[aggKey]; // scale += 4; - - scaleAggPm.push_back(scale); - precisionAggPm.push_back(19); - widthAggPm.push_back(bigIntWidth); - } - + typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); + scaleAggPm.push_back(scaleProj[colProj]); + precisionAggPm.push_back(-1); + widthAggPm.push_back(sizeof(long double)); colAggPm++; } - // PM: put the count column for avg next to the sum - // let fall through to add a count column for average function + // PM: put the count column for avg next to the sum + // let fall through to add a count column for average function if (aggOp != ROWAGG_AVG) break; @@ -3328,16 +3192,7 @@ void TupleAggregateStep::prep2PhasesAggregate( scaleAggPm.push_back(0); // work around count() in select subquery precisionAggPm.push_back(9999); - - if (isUnsigned(typeProj[colProj])) - { - typeAggPm.push_back(CalpontSystemCatalog::UBIGINT); - } - else - { - typeAggPm.push_back(CalpontSystemCatalog::BIGINT); - } - + typeAggPm.push_back(CalpontSystemCatalog::UBIGINT); widthAggPm.push_back(bigIntWidth); colAggPm++; } @@ -3375,7 +3230,7 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); scaleAggPm.push_back(0); - precisionAggPm.push_back(0); + precisionAggPm.push_back(-1); typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggPm.push_back(sizeof(long double)); ++colAggPm; @@ -3384,7 +3239,7 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); scaleAggPm.push_back(0); - precisionAggPm.push_back(0); + precisionAggPm.push_back(-1); typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggPm.push_back(sizeof(long double)); ++colAggPm; @@ -3609,7 +3464,7 @@ void TupleAggregateStep::prep2PhasesAggregate( keysAggUm.push_back(retKey); scaleAggUm.push_back(0); precisionAggUm.push_back(19); - typeAggUm.push_back(CalpontSystemCatalog::BIGINT); + typeAggUm.push_back(CalpontSystemCatalog::UBIGINT); widthAggUm.push_back(bigIntWidth); } } @@ -3776,7 +3631,7 @@ void TupleAggregateStep::prep2PhasesAggregate( keysAggUm.push_back(k->first); scaleAggUm.push_back(0); precisionAggUm.push_back(19); - typeAggUm.push_back(CalpontSystemCatalog::BIGINT); + typeAggUm.push_back(CalpontSystemCatalog::UBIGINT); widthAggUm.push_back(bigIntWidth); } } @@ -3815,7 +3670,7 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggUm.push_back(oidsAggUm[j]); keysAggUm.push_back(keysAggUm[j]); scaleAggUm.push_back(0); - precisionAggUm.push_back(0); + precisionAggUm.push_back(-1); typeAggUm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggUm.push_back(sizeof(long double)); ++lastCol; @@ -3824,7 +3679,7 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggUm.push_back(oidsAggUm[j]); keysAggUm.push_back(keysAggUm[j]); scaleAggUm.push_back(0); - precisionAggUm.push_back(0); + precisionAggUm.push_back(-1); typeAggUm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggUm.push_back(sizeof(long double)); ++lastCol; @@ -4042,6 +3897,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( precisionAggPm.push_back(precisionProj[colProj]); typeAggPm.push_back(typeProj[colProj]); widthAggPm.push_back(width[colProj]); + precisionAggPm.push_back(precisionProj[colProj]); aggFuncMap.insert(make_pair(boost::make_tuple(keysAggPm[colAggPm], 0, pUDAFFunc, udafc ? udafc->getContext().getParamKeys() : NULL), colAggPm)); colAggPm++; @@ -4168,43 +4024,15 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); - - if (typeProj[colProj] != CalpontSystemCatalog::DOUBLE && - typeProj[colProj] != CalpontSystemCatalog::FLOAT) - { - if (isUnsigned(typeProj[colProj])) - { - typeAggPm.push_back(CalpontSystemCatalog::UBIGINT); - precisionAggPm.push_back(20); - } - else - { - typeAggPm.push_back(CalpontSystemCatalog::BIGINT); - precisionAggPm.push_back(19); - } - - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[aggKey]; // scale += 4; - - scaleAggPm.push_back(scale); - widthAggPm.push_back(bigIntWidth); - } - else - { - typeAggPm.push_back(typeProj[colProj]); - scaleAggPm.push_back(scaleProj[colProj]); - precisionAggPm.push_back(precisionProj[colProj]); - widthAggPm.push_back(width[colProj]); - } - + typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAggPm.push_back(-1); + widthAggPm.push_back(sizeof(long double)); + scaleAggPm.push_back(scaleProj[colProj]); colAggPm++; } - // PM: put the count column for avg next to the sum - // let fall through to add a count column for average function + // PM: put the count column for avg next to the sum + // let fall through to add a count column for average function if (aggOp == ROWAGG_AVG) funct->fAuxColumnIndex = colAggPm; else @@ -4265,7 +4093,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); scaleAggPm.push_back(0); - precisionAggPm.push_back(0); + precisionAggPm.push_back(-1); typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggPm.push_back(sizeof(long double)); ++colAggPm; @@ -4274,7 +4102,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); scaleAggPm.push_back(0); - precisionAggPm.push_back(0); + precisionAggPm.push_back(-1); typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggPm.push_back(sizeof(long double)); ++colAggPm; @@ -4563,41 +4391,14 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggDist.push_back(oidsAggUm[colUm]); keysAggDist.push_back(retKey); - - if (typeAggUm[colUm] != CalpontSystemCatalog::DOUBLE && - typeAggUm[colUm] != CalpontSystemCatalog::FLOAT) - { - if (isUnsigned(typeAggUm[colUm])) - { - typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); - precisionAggDist.push_back(20); - } - else - { - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); - precisionAggDist.push_back(19); - } - - uint32_t scale = scaleAggUm[colUm]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_DISTINCT_AVG) - scale = jobInfo.scaleOfAvg[retKey]; // scale += 4; - - scaleAggDist.push_back(scale); - widthAggDist.push_back(bigIntWidth); - } - else - { - typeAggDist.push_back(typeAggUm[colUm]); - scaleAggDist.push_back(scaleAggUm[colUm]); - precisionAggDist.push_back(precisionAggUm[colUm]); - widthAggDist.push_back(widthAggUm[colUm]); - } + typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAggDist.push_back(-1); + widthAggDist.push_back(sizeof(long double)); + scaleAggDist.push_back(scaleAggUm[colUm]); } - // PM: put the count column for avg next to the sum - // let fall through to add a count column for average function - //if (aggOp != ROWAGG_DISTINCT_AVG) + // PM: put the count column for avg next to the sum + // let fall through to add a count column for average function + //if (aggOp != ROWAGG_DISTINCT_AVG) break; case ROWAGG_COUNT_DISTINCT_COL_NAME: @@ -4607,22 +4408,13 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( scaleAggDist.push_back(0); // work around count() in select subquery precisionAggDist.push_back(9999); - - if (isUnsigned(typeAggUm[colUm])) - { - typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); - } - else - { - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); - } - + typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); widthAggDist.push_back(bigIntWidth); } break; default: - // cound happen if agg and agg distinct use same column. + // could happen if agg and agg distinct use same column. colUm = -1; break; } // switch @@ -4844,7 +4636,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( keysAggDist.push_back(k->first); scaleAggDist.push_back(0); precisionAggDist.push_back(19); - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); + typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); widthAggDist.push_back(bigIntWidth); } } @@ -4915,7 +4707,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggDist.push_back(oidsAggDist[j]); keysAggDist.push_back(keysAggDist[j]); scaleAggDist.push_back(0); - precisionAggDist.push_back(0); + precisionAggDist.push_back(-1); typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggDist.push_back(sizeof(long double)); ++lastCol; @@ -4924,7 +4716,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggDist.push_back(oidsAggDist[j]); keysAggDist.push_back(keysAggDist[j]); scaleAggDist.push_back(0); - precisionAggDist.push_back(0); + precisionAggDist.push_back(-1); typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggDist.push_back(sizeof(long double)); ++lastCol; diff --git a/dbcon/joblist/tupleaggregatestep.h b/dbcon/joblist/tupleaggregatestep.h index 13a12a8c8..ae356e156 100644 --- a/dbcon/joblist/tupleaggregatestep.h +++ b/dbcon/joblist/tupleaggregatestep.h @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (C) 2019 MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -23,6 +24,7 @@ #include "jobstep.h" #include "rowaggregation.h" +#include "threadnaming.h" #include @@ -138,6 +140,7 @@ private: Aggregator(TupleAggregateStep* step) : fStep(step) { } void operator()() { + utils::setThreadName("TASAggr"); fStep->doAggregate(); } @@ -153,6 +156,7 @@ private: {} void operator()() { + utils::setThreadName("TASThrAggr"); fStep->threadedAggregateRowGroups(fThreadID); } @@ -171,6 +175,7 @@ private: } void operator()() { + utils::setThreadName("TASThr2ndPAggr"); for (uint32_t i = 0; i < bucketCount; i++) fStep->doThreadedSecondPhaseAggregate(fThreadID + i); } diff --git a/dbcon/joblist/tupleannexstep.cpp b/dbcon/joblist/tupleannexstep.cpp index 77a2670d9..c1ef06a4e 100644 --- a/dbcon/joblist/tupleannexstep.cpp +++ b/dbcon/joblist/tupleannexstep.cpp @@ -51,6 +51,7 @@ using namespace rowgroup; #include "hasher.h" #include "stlpoolallocator.h" +#include "threadnaming.h" using namespace utils; #include "querytele.h" @@ -314,6 +315,7 @@ void TupleAnnexStep::execute() void TupleAnnexStep::executeNoOrderBy() { + utils::setThreadName("TASwoOrd"); RGData rgDataIn; RGData rgDataOut; bool more = false; @@ -399,6 +401,7 @@ void TupleAnnexStep::executeNoOrderBy() void TupleAnnexStep::executeNoOrderByWithDistinct() { + utils::setThreadName("TASwoOrdDist"); scoped_ptr distinctMap(new DistinctMap_t(10, TAHasher(this), TAEq(this))); vector dataVec; RGData rgDataIn; @@ -500,6 +503,7 @@ void TupleAnnexStep::executeNoOrderByWithDistinct() void TupleAnnexStep::executeWithOrderBy() { + utils::setThreadName("TASwOrd"); RGData rgDataIn; RGData rgDataOut; bool more = false; diff --git a/dbcon/joblist/tupleconstantstep.cpp b/dbcon/joblist/tupleconstantstep.cpp index 309bb0058..d03996586 100644 --- a/dbcon/joblist/tupleconstantstep.cpp +++ b/dbcon/joblist/tupleconstantstep.cpp @@ -1,4 +1,5 @@ /* 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 @@ -250,6 +251,12 @@ void TupleConstantStep::constructContanstRow(const JobInfo& jobInfo) break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + fRowConst.setLongDoubleField(c.longDoubleVal, *i); + break; + } + case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::VARCHAR: case CalpontSystemCatalog::TEXT: diff --git a/dbcon/joblist/tupleconstantstep.h b/dbcon/joblist/tupleconstantstep.h index 6187f04a6..c98227805 100644 --- a/dbcon/joblist/tupleconstantstep.h +++ b/dbcon/joblist/tupleconstantstep.h @@ -22,6 +22,7 @@ #define JOBLIST_TUPLECONSTANTSTEP_H #include "jobstep.h" +#include "threadnaming.h" namespace joblist { @@ -98,6 +99,7 @@ protected: Runner(TupleConstantStep* step) : fStep(step) { } void operator()() { + utils::setThreadName("TCSRunner"); fStep->execute(); } diff --git a/dbcon/joblist/tuplehashjoin.h b/dbcon/joblist/tuplehashjoin.h index d89e76d2f..27154946f 100644 --- a/dbcon/joblist/tuplehashjoin.h +++ b/dbcon/joblist/tuplehashjoin.h @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (C) 2019 MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -25,6 +26,7 @@ #include "calpontsystemcatalog.h" #include "hasher.h" #include "tuplejoiner.h" +#include "threadnaming.h" #include #include #include @@ -450,6 +452,7 @@ private: HJRunner(TupleHashJoinStep* hj) : HJ(hj) { } void operator()() { + utils::setThreadName("HJSBigSide"); HJ->hjRunner(); } TupleHashJoinStep* HJ; @@ -459,6 +462,7 @@ private: SmallRunner(TupleHashJoinStep* hj, uint32_t i) : HJ(hj), index(i) { } void operator()() { + utils::setThreadName("HJSSmallSide"); HJ->smallRunnerFcn(index); } TupleHashJoinStep* HJ; diff --git a/dbcon/joblist/tuplehavingstep.h b/dbcon/joblist/tuplehavingstep.h index 2624a7e4a..a7fc679ab 100644 --- a/dbcon/joblist/tuplehavingstep.h +++ b/dbcon/joblist/tuplehavingstep.h @@ -23,6 +23,7 @@ #include "jobstep.h" #include "expressionstep.h" +#include "threadnaming.h" // forward reference namespace fucexp @@ -97,6 +98,7 @@ protected: Runner(TupleHavingStep* step) : fStep(step) { } void operator()() { + utils::setThreadName("HVSRunner"); fStep->execute(); } diff --git a/dbcon/joblist/tupleunion.cpp b/dbcon/joblist/tupleunion.cpp index 3b7232c62..0ef83c33b 100644 --- a/dbcon/joblist/tupleunion.cpp +++ b/dbcon/joblist/tupleunion.cpp @@ -1,4 +1,5 @@ /* 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 @@ -510,6 +511,18 @@ void TupleUnion::normalize(const Row& in, Row* out) break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + int scale = in.getScale(i); + long double d = in.getIntField(i); + if (scale != 0) + { + d /= (uint64_t) pow(10.0, scale); + } + out->setLongDoubleField(d, i); + break; + } + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { @@ -620,6 +633,22 @@ dec1: break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + int scale = in.getScale(i); + + if (scale != 0) + { + long double d = in.getUintField(i); + d /= (uint64_t) pow(10.0, scale); + out->setLongDoubleField(d, i); + } + else + out->setLongDoubleField(in.getUintField(i), i); + + break; + } + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { @@ -804,6 +833,10 @@ dec2: out->setDoubleField(val, i); break; + case CalpontSystemCatalog::LONGDOUBLE: + out->setLongDoubleField(val, i); + break; + case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::TEXT: case CalpontSystemCatalog::VARCHAR: @@ -842,6 +875,83 @@ dec3: /* have to pick a scale to use for the double. using 5... */ break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + long double val = in.getLongDoubleField(i); + + switch (out->getColTypes()[i]) + { + case CalpontSystemCatalog::TINYINT: + case CalpontSystemCatalog::SMALLINT: + case CalpontSystemCatalog::MEDINT: + case CalpontSystemCatalog::INT: + case CalpontSystemCatalog::BIGINT: + if (out->getScale(i)) + goto dec4; + + out->setIntField((int64_t) val, i); + break; + + case CalpontSystemCatalog::UTINYINT: + case CalpontSystemCatalog::USMALLINT: + case CalpontSystemCatalog::UMEDINT: + case CalpontSystemCatalog::UINT: + case CalpontSystemCatalog::UBIGINT: + out->setUintField((uint64_t) val, i); + break; + + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + out->setFloatField(val, i); + break; + + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + out->setDoubleField(val, i); + break; + + case CalpontSystemCatalog::LONGDOUBLE: + out->setLongDoubleField(val, i); + break; + + case CalpontSystemCatalog::CHAR: + case CalpontSystemCatalog::TEXT: + case CalpontSystemCatalog::VARCHAR: + { + ostringstream os; + os.precision(15); // to match mysql's output + os << val; + out->setStringField(os.str(), i); + break; + } + + case CalpontSystemCatalog::DECIMAL: + case CalpontSystemCatalog::UDECIMAL: + { +dec4: /* have to pick a scale to use for the double. using 5... */ + uint32_t scale = 5; + uint64_t ival = (uint64_t) (double) (val * pow((double) 10, (double) scale)); + int diff = out->getScale(i) - scale; + + if (diff < 0) + ival /= (uint64_t) pow((double) 10, (double) - diff); + else + ival *= (uint64_t) pow((double) 10, (double) diff); + + out->setIntField((int64_t) val, i); + break; + } + + default: + ostringstream os; + os << "TupleUnion::normalize(): tried an illegal conversion: floating point to " + << out->getColTypes()[i]; + throw logic_error(os.str()); + } + + break; + } + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { @@ -882,12 +992,20 @@ dec3: /* have to pick a scale to use for the double. using 5... */ } case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: { double dval = ((double) val) / IDB_pow[scale]; out->setDoubleField(dval, i); break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + long double dval = ((long double) val) / IDB_pow[scale]; + out->setLongDoubleField(dval, i); + break; + } + case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::TEXT: case CalpontSystemCatalog::VARCHAR: diff --git a/dbcon/joblist/tupleunion.h b/dbcon/joblist/tupleunion.h index 2c54337d3..b6a445da9 100644 --- a/dbcon/joblist/tupleunion.h +++ b/dbcon/joblist/tupleunion.h @@ -35,6 +35,7 @@ #endif #include "stlpoolallocator.h" +#include "threadnaming.h" #ifndef TUPLEUNION2_H_ #define TUPLEUNION2_H_ @@ -155,6 +156,7 @@ private: Runner(TupleUnion* t, uint32_t in) : tu(t), index(in) { } void operator()() { + utils::setThreadName("TUSRunner"); tu->readInput(index); } }; diff --git a/dbcon/joblist/windowfunctionstep.h b/dbcon/joblist/windowfunctionstep.h index 302629c4c..f483c6027 100644 --- a/dbcon/joblist/windowfunctionstep.h +++ b/dbcon/joblist/windowfunctionstep.h @@ -25,6 +25,7 @@ #include "jobstep.h" #include "rowgroup.h" #include "windowfunctioncolumn.h" +#include "threadnaming.h" namespace execplan { @@ -153,6 +154,7 @@ private: Runner(WindowFunctionStep* step) : fStep(step) { } void operator()() { + utils::setThreadName("WFSRunner"); fStep->execute(); } diff --git a/dbcon/mysql/ha_calpont.cpp b/dbcon/mysql/ha_calpont.cpp index 8dc96942f..d4ff366bd 100644 --- a/dbcon/mysql/ha_calpont.cpp +++ b/dbcon/mysql/ha_calpont.cpp @@ -1061,7 +1061,7 @@ void check_walk(const Item* item, void* arg) break; } - case Item::EXPR_CACHE_ITEM: // IN + correlated subquery + case Item::EXPR_CACHE_ITEM: // IN + correlated subquery { const Item_cache_wrapper* icw = static_cast(item); if ( icw->get_orig_item()->type() == Item::FUNC_ITEM ) @@ -1102,11 +1102,14 @@ void check_walk(const Item* item, void* arg) * logical OR in the filter predicates * Impossible WHERE * Impossible HAVING - * Valid queries with the last two crashes the server if processed. + * and there is either GROUP BY or aggregation function + * exists at the top level. + * Valid queries with the last two crashes the server if + * processed. * Details are in server/sql/group_by_handler.h * PARAMETERS: - * thd - THD pointer. - * query - Query structure, that describes the pushdowned query. + * thd - THD pointer + * query - Query structure LFM in group_by_handler.h * RETURN: * group_by_handler if success * NULL in other case @@ -1125,29 +1128,48 @@ create_calpont_group_by_handler(THD* thd, Query* query) && ( query->group_by || select_lex->with_sum_func ) ) { bool unsupported_feature = false; - // Impossible HAVING or WHERE - if ( ( query->having && select_lex->having_value == Item::COND_FALSE ) - || ( select_lex->cond_count > 0 - && select_lex->cond_value == Item::COND_FALSE ) ) + // revisit SELECT_LEX for all units + for(TABLE_LIST* tl = query->from; !unsupported_feature && tl; tl = tl->next_global) { - unsupported_feature = true; - } + select_lex = tl->select_lex; + // Correlation subquery. Comming soon so fail on this yet. + unsupported_feature = select_lex->is_correlated; - // Unsupported conditions check. - if ( !unsupported_feature ) - { - JOIN *join = select_lex->join; - Item_cond *icp = 0; - - if (join != 0) - icp = reinterpret_cast(join->conds); - - if ( unsupported_feature == false - && icp ) + // Impossible HAVING or WHERE + if ( ( !unsupported_feature && query->having && select_lex->having_value == Item::COND_FALSE ) + || ( select_lex->cond_count > 0 + && select_lex->cond_value == Item::COND_FALSE ) ) { - icp->traverse_cond(check_walk, &unsupported_feature, Item::POSTFIX); + unsupported_feature = true; } - } + + // Unsupported JOIN conditions + if ( !unsupported_feature ) + { + JOIN *join = select_lex->join; + Item_cond *icp = 0; + + if (join != 0) + icp = reinterpret_cast(join->conds); + + if ( unsupported_feature == false + && icp ) + { + icp->traverse_cond(check_walk, &unsupported_feature, Item::POSTFIX); + } + + // Optimizer could move some join conditions into where + if (select_lex->where != 0) + icp = reinterpret_cast(select_lex->where); + + if ( unsupported_feature == false + && icp ) + { + icp->traverse_cond(check_walk, &unsupported_feature, Item::POSTFIX); + } + + } + } // unsupported features check ends here if ( !unsupported_feature ) { diff --git a/dbcon/mysql/ha_calpont_ddl.cpp b/dbcon/mysql/ha_calpont_ddl.cpp index 62e372635..a59701e9b 100644 --- a/dbcon/mysql/ha_calpont_ddl.cpp +++ b/dbcon/mysql/ha_calpont_ddl.cpp @@ -39,7 +39,6 @@ #include #endif #include -//#define NDEBUG #include using namespace std; @@ -671,7 +670,7 @@ int ProcessDDLStatement(string& ddlStatement, string& schema, const string& tabl { SqlParser parser; THD* thd = current_thd; -#ifdef INFINIDB_DEBUG +#ifdef MCS_DEBUG cout << "ProcessDDLStatement: " << schema << "." << table << ":" << ddlStatement << endl; #endif @@ -1616,7 +1615,6 @@ int ProcessDDLStatement(string& ddlStatement, string& schema, const string& tabl } else if (ddlpackage::AtaRenameColumn* renameColumnsPtr = dynamic_cast(actionList[i])) { - //cout << "Rename a column" << endl; uint64_t startValue = 1; bool autoIncre = false; //@Bug 3746 Handle compression type @@ -1815,7 +1813,6 @@ int ProcessDDLStatement(string& ddlStatement, string& schema, const string& tabl stmt.fSql = ddlStatement; stmt.fOwner = schema; stmt.fTableWithAutoi = isAnyAutoincreCol; - //cout << "Sending to DDLProc" << endl; ByteStream bytestream; bytestream << stmt.fSessionID; stmt.serialize(bytestream); @@ -1904,30 +1901,6 @@ int ProcessDDLStatement(string& ddlStatement, string& schema, const string& tabl return rc; } -// Fails with `/` sign in table name -pair parseTableName(const string& tn) -{ - string db; - string tb; - typedef boost::tokenizer > tokenizer; -#ifdef _MSC_VER - boost::char_separator sep("\\"); -#else - boost::char_separator sep("/"); -#endif - tokenizer tokens(tn, sep); - tokenizer::iterator tok_iter = tokens.begin(); - ++tok_iter; - idbassert(tok_iter != tokens.end()); - db = *tok_iter; - ++tok_iter; - idbassert(tok_iter != tokens.end()); - tb = *tok_iter; - ++tok_iter; - idbassert(tok_iter == tokens.end()); - return make_pair(db, tb); -} - } // @@ -2005,7 +1978,7 @@ static bool get_field_default_value(THD *thd, Field *field, String *def_value, int ha_calpont_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO* create_info, cal_connection_info& ci) { -#ifdef INFINIDB_DEBUG +#ifdef MCS_DEBUG cout << "ha_calpont_impl_create_: " << name << endl; #endif THD* thd = current_thd; @@ -2077,7 +2050,7 @@ int ha_calpont_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO* if (isCreate) { -#ifdef INFINIDB_DEBUG +#ifdef MCS_DEBUG cout << "ha_calpont_impl_create_: SCHEMA SYNC ONLY found, returning" << endl; #endif return 0; @@ -2108,7 +2081,7 @@ int ha_calpont_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO* { ci.isAlter = true; ci.alterTableState = cal_connection_info::ALTER_FIRST_RENAME; -#ifdef INFINIDB_DEBUG +#ifdef MCS_DEBUG cout << "ha_calpont_impl_create_: now in state ALTER_FIRST_RENAME" << endl; #endif } @@ -2286,7 +2259,7 @@ int ha_calpont_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO* //Bug 1705 reset the flag if error occurs ci.alterTableState = cal_connection_info::NOT_ALTER; ci.isAlter = false; -#ifdef INFINIDB_DEBUG +#ifdef MCS_DEBUG cout << "ha_calpont_impl_create_: ProcessDDL error, now in state NOT_ALTER" << endl; #endif } @@ -2296,7 +2269,7 @@ int ha_calpont_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO* int ha_calpont_impl_delete_table_(const char* db, const char* name, cal_connection_info& ci) { -#ifdef INFINIDB_DEBUG +#ifdef MCS_DEBUG cout << "ha_calpont_impl_delete_table: " << db << name << endl; #endif THD* thd = current_thd; @@ -2312,7 +2285,6 @@ int ha_calpont_impl_delete_table_(const char* db, const char* name, cal_connecti std::string stmt(query); algorithm::to_upper(stmt); -// cout << "ha_calpont_impl_delete_table: " << schema.c_str() << "." << tbl.c_str() << " " << stmt.c_str() << endl; // @bug 4158 allow table name with 'restrict' in it (but not by itself) std::string::size_type fpos; fpos = stmt.rfind(" RESTRICT"); @@ -2351,7 +2323,6 @@ int ha_calpont_impl_delete_table_(const char* db, const char* name, cal_connecti stmt += ";"; int rc = ProcessDDLStatement(stmt, schema, tbl, tid2sid(thd->thread_id), emsg); -// cout << "ProcessDDLStatement rc=" << rc << endl; if (rc != 0) { push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, emsg.c_str()); @@ -2360,6 +2331,7 @@ int ha_calpont_impl_delete_table_(const char* db, const char* name, cal_connecti return rc; } + /** @brief Find and return a pointer to the last slash in the name. @@ -2412,16 +2384,57 @@ void decode_table_name(char *buf, const char *path, size_t pathLen) } } +/** + @brief + Parses the path to extract both database and table names. + + @details + Parses the path to extract both database + and table names. This f() assumes the path format + ./test/d$ + and f() produces a pair of strings 'test' and 'd$'. + This f() looks for a '/' symbols only twice to allow '/' + symbol in table names. The f() supports international + glyphs in db or table names. + + Called from ha_calpont_ddl.cpp by ha_calpont_impl_rename_table_(). +*/ +pair parseTableName(const char *path) +{ + const char *db_pnt = NULL, *tbl_pnt = NULL, *path_cursor = path; + string db, tb; + while (*path_cursor != '/') + { + path_cursor++; + } + path_cursor++; + db_pnt = path_cursor; + while (*path_cursor != '/') + { + path_cursor++; + } + path_cursor++; + tbl_pnt = path_cursor; + db.assign(db_pnt, tbl_pnt - 1 - db_pnt); + tb.assign(tbl_pnt, path + strlen(path) - tbl_pnt); + + return make_pair(db, tb); +} int ha_calpont_impl_rename_table_(const char* from, const char* to, cal_connection_info& ci) { THD* thd = current_thd; string emsg; + // to and from are rewritten after decode_table_name() + // so use a copy of pntrs + const char* from_cpy = from; + const char* to_cpy = to; + pair fromPair; pair toPair; string stmt; - //this is replcated DDL, treat it just like SSO + //this is replicated DDL, treat it just like SSO if (thd->slave_thread) return 0; @@ -2435,16 +2448,18 @@ int ha_calpont_impl_rename_table_(const char* from, const char* to, cal_connecti } // MCOL-1855 Decode the table name if it contains encoded symbols. - // This approach fails when `/` is used in the paths. - size_t pathLen = strlen(from); - char pathCopy[pathLen]; - decode_table_name(pathCopy, from, pathLen); + size_t pathLen = strlen(from_cpy); + char pathCopy[FN_REFLEN]; + decode_table_name(pathCopy, from_cpy, pathLen); fromPair = parseTableName(const_cast(pathCopy)); - pathLen = strlen(to); - decode_table_name(pathCopy, to, pathLen); + pathLen = strlen(to_cpy); + decode_table_name(pathCopy, to_cpy, pathLen); + toPair = parseTableName(const_cast(pathCopy)); + // TBD The next two blocks must be removed to allow different dbnames + // in RENAME statement. if (fromPair.first != toPair.first) { thd->get_stmt_da()->set_overwrite_status(true); diff --git a/dbcon/mysql/ha_calpont_dml.cpp b/dbcon/mysql/ha_calpont_dml.cpp index b5bbe57aa..dd2b09135 100644 --- a/dbcon/mysql/ha_calpont_dml.cpp +++ b/dbcon/mysql/ha_calpont_dml.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -1175,6 +1175,20 @@ int ha_calpont_impl_write_batch_row_(uchar* buf, TABLE* table, cal_impl_if::cal_ break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + if (nullVal && (ci.columnTypes[colpos].constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT)) + fprintf(ci.filePtr, "%c", ci.delimiter); + else + { + fprintf(ci.filePtr, "%.15Lg%c", *((long double*)buf), ci.delimiter); + //printf("%.15g|", *((double*)buf)); + } + + buf += 8; + break; + } + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { diff --git a/dbcon/mysql/ha_calpont_execplan.cpp b/dbcon/mysql/ha_calpont_execplan.cpp index 6e9755707..e553254e3 100644 --- a/dbcon/mysql/ha_calpont_execplan.cpp +++ b/dbcon/mysql/ha_calpont_execplan.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -3373,7 +3373,6 @@ ReturnedColumn* buildFunctionColumn( return ac; } - // comment out for now until case function is fully tested. else if (funcName == "case") { fc = buildCaseFunction(ifp, gwi, nonSupport); @@ -4500,41 +4499,10 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi) isp->sum_func() == Item_sum::AVG_DISTINCT_FUNC) { CalpontSystemCatalog::ColType ct = parm->resultType(); - - switch (ct.colDataType) - { - case CalpontSystemCatalog::TINYINT: - case CalpontSystemCatalog::SMALLINT: - case CalpontSystemCatalog::MEDINT: - case CalpontSystemCatalog::INT: - case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: - case CalpontSystemCatalog::UDECIMAL: - case CalpontSystemCatalog::UTINYINT: - case CalpontSystemCatalog::USMALLINT: - case CalpontSystemCatalog::UMEDINT: - case CalpontSystemCatalog::UINT: - case CalpontSystemCatalog::UBIGINT: - ct.colDataType = CalpontSystemCatalog::DECIMAL; - ct.colWidth = 8; - ct.scale += 4; - break; - -#if PROMOTE_FLOAT_TO_DOUBLE_ON_SUM - - case CalpontSystemCatalog::FLOAT: - case CalpontSystemCatalog::UFLOAT: - case CalpontSystemCatalog::DOUBLE: - case CalpontSystemCatalog::UDOUBLE: - ct.colDataType = CalpontSystemCatalog::DOUBLE; - ct.colWidth = 8; - break; -#endif - - default: - break; - } - + ct.colDataType = CalpontSystemCatalog::LONGDOUBLE; + ct.colWidth = sizeof(long double); + ct.scale += 4; + ct.precision = -1; ac->resultType(ct); } else if (isp->sum_func() == Item_sum::COUNT_FUNC || @@ -4550,47 +4518,9 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi) isp->sum_func() == Item_sum::SUM_DISTINCT_FUNC) { CalpontSystemCatalog::ColType ct = parm->resultType(); - - switch (ct.colDataType) - { - case CalpontSystemCatalog::TINYINT: - case CalpontSystemCatalog::SMALLINT: - case CalpontSystemCatalog::MEDINT: - case CalpontSystemCatalog::INT: - case CalpontSystemCatalog::BIGINT: - ct.colDataType = CalpontSystemCatalog::BIGINT; - - // no break, let fall through - - case CalpontSystemCatalog::DECIMAL: - case CalpontSystemCatalog::UDECIMAL: - ct.colWidth = 8; - break; - - case CalpontSystemCatalog::UTINYINT: - case CalpontSystemCatalog::USMALLINT: - case CalpontSystemCatalog::UMEDINT: - case CalpontSystemCatalog::UINT: - case CalpontSystemCatalog::UBIGINT: - ct.colDataType = CalpontSystemCatalog::UBIGINT; - ct.colWidth = 8; - break; - -#if PROMOTE_FLOAT_TO_DOUBLE_ON_SUM - - case CalpontSystemCatalog::FLOAT: - case CalpontSystemCatalog::UFLOAT: - case CalpontSystemCatalog::DOUBLE: - case CalpontSystemCatalog::UDOUBLE: - ct.colDataType = CalpontSystemCatalog::DOUBLE; - ct.colWidth = 8; - break; -#endif - - default: - break; - } - + ct.colDataType = CalpontSystemCatalog::LONGDOUBLE; + ct.colWidth = sizeof(long double); + ct.precision = -1; ac->resultType(ct); } else if (isp->sum_func() == Item_sum::STD_FUNC || diff --git a/dbcon/mysql/ha_calpont_impl.cpp b/dbcon/mysql/ha_calpont_impl.cpp index b0ef4109c..02164e239 100644 --- a/dbcon/mysql/ha_calpont_impl.cpp +++ b/dbcon/mysql/ha_calpont_impl.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -714,6 +714,61 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, bool h //break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + long double dl = row.getLongDoubleField(s); + if (dl == std::numeric_limits::infinity()) + { + continue; + } + + switch((*f)->type()) + { + case MYSQL_TYPE_NEWDECIMAL: + { + char buf[310]; + Field_new_decimal* f2 = (Field_new_decimal*)*f; + if ((f2->decimals() == DECIMAL_NOT_SPECIFIED && row.getScale(s) > 0) + || f2->decimals() < row.getScale(s)) + { + f2->dec = row.getScale(s); + } +// dl /= pow(10.0, (double)f2->dec); + snprintf(buf, 310, "%.20Lg", dl); + f2->store(buf, strlen(buf), f2->charset()); + if ((*f)->null_ptr) + *(*f)->null_ptr &= ~(*f)->null_bit; + } + break; + case MYSQL_TYPE_DOUBLE: + { + Field_double* f2 = (Field_double*)*f; + + // bug 3483, reserve enough space for the longest double value + // -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and + // 2.2250738585072014E-308 to 1.7976931348623157E+308. + (*f)->field_length = 310; + + if ((f2->decimals() == DECIMAL_NOT_SPECIFIED && row.getScale(s) > 0) + || f2->decimals() < row.getScale(s)) + { + f2->dec = row.getScale(s); + } + + f2->store(static_cast(dl)); + if ((*f)->null_ptr) + *(*f)->null_ptr &= ~(*f)->null_bit; + } + break; + default: + { + continue; // Shouldn't happen. Functions should not return long double to other than double or decimal return type. + } + } + + break; + } + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { diff --git a/dbcon/mysql/ha_calpont_partition.cpp b/dbcon/mysql/ha_calpont_partition.cpp index 038c668c9..61063f2f6 100644 --- a/dbcon/mysql/ha_calpont_partition.cpp +++ b/dbcon/mysql/ha_calpont_partition.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -190,6 +190,9 @@ string name(CalpontSystemCatalog::ColType& ct) case CalpontSystemCatalog::UDOUBLE: return "UDOUBLE"; + case CalpontSystemCatalog::LONGDOUBLE: + return "LONGDOUBLE"; + default: return "Unknown Type"; } diff --git a/dbcon/mysql/ha_window_function.cpp b/dbcon/mysql/ha_window_function.cpp index 84c082bee..417edf61c 100644 --- a/dbcon/mysql/ha_window_function.cpp +++ b/dbcon/mysql/ha_window_function.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -898,7 +898,13 @@ ReturnedColumn* buildWindowFunctionColumn(Item* item, gp_walk_info& gwi, bool& n setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText); return NULL; } - +#if 0 + if (item_sum->sum_func() != Item_sum::UDF_SUM_FUNC && + item_sum->sum_func() != Item_sum::SUM_FUNC && + item_sum->sum_func() != Item_sum::SUM_DISTINCT_FUNC && + item_sum->sum_func() != Item_sum::AVG_FUNC && + item_sum->sum_func() != Item_sum::AVG_DISTINCT_FUNC) +#endif if (item_sum->sum_func() != Item_sum::UDF_SUM_FUNC) { ac->resultType(colType_MysqlToIDB(item_sum)); diff --git a/exemgr/main.cpp b/exemgr/main.cpp index a403360ac..259d1443e 100644 --- a/exemgr/main.cpp +++ b/exemgr/main.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -718,8 +718,7 @@ new_plan: string emsg("NOERROR"); ByteStream emsgBs; ByteStream::quadbyte tflg = 0; - jl = JobListFactory::makeJobList( - &csep, fRm, true, true); + jl = JobListFactory::makeJobList(&csep, fRm, true, true); // assign query stats jl->queryStats(fStats); diff --git a/oamapps/mcsadmin/mcsadmin.cpp b/oamapps/mcsadmin/mcsadmin.cpp index 362fb4b00..d07c67ffb 100644 --- a/oamapps/mcsadmin/mcsadmin.cpp +++ b/oamapps/mcsadmin/mcsadmin.cpp @@ -5404,7 +5404,14 @@ int processCommand(string* arguments) for ( ; pt1 != (*pt).hostConfigList.end() ; pt1++) { - string ipAddr = (*pt1).IPAddr; + /* MCOL-1607. IPAddr may be a host name here b/c it is read straight + from the config file. */ + string tmphost = oam.getIPAddress(pt1->IPAddr); + string ipAddr; + if (tmphost.empty()) + ipAddr = pt1->IPAddr; + else + ipAddr = tmphost; string hostname = (*pt1).HostName; string nicID = oam.itoa((*pt1).NicID); diff --git a/primitives/primproc/batchprimitiveprocessor.cpp b/primitives/primproc/batchprimitiveprocessor.cpp index 019761d39..752c94d9e 100644 --- a/primitives/primproc/batchprimitiveprocessor.cpp +++ b/primitives/primproc/batchprimitiveprocessor.cpp @@ -52,6 +52,7 @@ using namespace boost; #include "fixedallocator.h" #include "blockcacheclient.h" #include "MonitorProcMem.h" +#include "threadnaming.h" #define MAX64 0x7fffffffffffffffLL #define MIN64 0x8000000000000000LL @@ -156,7 +157,6 @@ BatchPrimitiveProcessor::BatchPrimitiveProcessor(ByteStream& b, double prefetch, sendThread = bppst; pthread_mutex_init(&objLock, NULL); initBPP(b); -// cerr << "made a BPP\n"; } #if 0 @@ -1961,6 +1961,7 @@ void BatchPrimitiveProcessor::makeResponse() int BatchPrimitiveProcessor::operator()() { + utils::setThreadName("PPBatchPrimProc"); if (currentBlockOffset == 0) { #ifdef PRIMPROC_STOPWATCH // TODO: needs to be brought up-to-date diff --git a/primitives/primproc/bppseeder.cpp b/primitives/primproc/bppseeder.cpp index 1755135a3..4b94d0c5c 100644 --- a/primitives/primproc/bppseeder.cpp +++ b/primitives/primproc/bppseeder.cpp @@ -142,6 +142,7 @@ int BPPSeeder::operator()() pthread_t tid = 0; boost::mutex::scoped_lock scoped(bppLock, boost::defer_lock_t()); + try { if (firstRun) diff --git a/primitives/primproc/primitiveserver.cpp b/primitives/primproc/primitiveserver.cpp index 227b494de..76ff8ef3c 100644 --- a/primitives/primproc/primitiveserver.cpp +++ b/primitives/primproc/primitiveserver.cpp @@ -91,6 +91,8 @@ using namespace idbdatafile; using namespace threadpool; +#include "threadnaming.h" + #include "atomicops.h" #ifndef O_BINARY @@ -925,6 +927,7 @@ struct AsynchLoader void operator()() { + utils::setThreadName("PPAsyncLoader"); bool cached = false; uint32_t rCount = 0; char buf[BLOCK_SIZE]; @@ -1159,6 +1162,7 @@ void DictScanJob::write(const ByteStream& bs) int DictScanJob::operator()() { + utils::setThreadName("PPDictScanJob"); uint8_t data[DATA_BLOCK_SIZE]; uint32_t output_buf_size = MAX_BUFFER_SIZE; uint32_t session; @@ -1338,6 +1342,7 @@ struct BPPHandler LastJoiner(boost::shared_ptr r, SBS b) : BPPHandlerFunctor(r, b) { } int operator()() { + utils::setThreadName("PPHandLastJoiner"); return rt->lastJoinerMsg(*bs, dieTime); } }; @@ -1347,6 +1352,7 @@ struct BPPHandler Create(boost::shared_ptr r, SBS b) : BPPHandlerFunctor(r, b) { } int operator()() { + utils::setThreadName("PPHandCreate"); rt->createBPP(*bs); return 0; } @@ -1357,6 +1363,7 @@ struct BPPHandler Destroy(boost::shared_ptr r, SBS b) : BPPHandlerFunctor(r, b) { } int operator()() { + utils::setThreadName("PPHandDestroy"); return rt->destroyBPP(*bs, dieTime); } }; @@ -1366,6 +1373,7 @@ struct BPPHandler AddJoiner(boost::shared_ptr r, SBS b) : BPPHandlerFunctor(r, b) { } int operator()() { + utils::setThreadName("PPHandAddJoiner"); return rt->addJoinerToBPP(*bs, dieTime); } }; @@ -1375,6 +1383,7 @@ struct BPPHandler Abort(boost::shared_ptr r, SBS b) : BPPHandlerFunctor(r, b) { } int operator()() { + utils::setThreadName("PPHandAbort"); return rt->doAbort(*bs, dieTime); } }; @@ -1751,6 +1760,7 @@ public: virtual int execute() = 0; int operator()() { + utils::setThreadName("PPDictOp"); int ret; ret = execute(); @@ -1967,6 +1977,7 @@ struct ReadThread void operator()() { + utils::setThreadName("PPReadThread"); boost::shared_ptr procPoolPtr = fPrimitiveServerPtr->getProcessorThreadPool(); SBS bs; @@ -2376,6 +2387,7 @@ struct ServerThread void operator()() { + utils::setThreadName("PPServerThr"); IOSocket ios; try diff --git a/utils/clusterTester/columnstoreClusterTester.sh b/utils/clusterTester/columnstoreClusterTester.sh index 7e507dbff..de050bb70 100755 --- a/utils/clusterTester/columnstoreClusterTester.sh +++ b/utils/clusterTester/columnstoreClusterTester.sh @@ -800,8 +800,7 @@ checkPackages() echo "** Run MariaDB ColumnStore Dependent Package Check" echo "" - - declare -a CENTOS_PKG=("expect" "perl" "perl-DBI" "openssl" "zlib" "file" "libaio" "rsync" "snappy" "net-tools" "numactl-libs") + declare -a CENTOS_PKG=("expect" "perl" "perl-DBI" "openssl" "zlib" "file" "libaio" "rsync" "jemalloc" "snappy" "net-tools" "numactl-libs") declare -a CENTOS_PKG_NOT=("mariadb-libs") if [ "$OS" == "centos6" ] || [ "$OS" == "centos7" ]; then @@ -920,8 +919,7 @@ checkPackages() fi fi - - declare -a SUSE_PKG=("boost-devel" "expect" "perl" "perl-DBI" "openssl" "file" "libaio1" "rsync" "libsnappy1" "net-tools" "libnuma1") + declare -a SUSE_PKG=("boost-devel" "expect" "perl" "perl-DBI" "openssl" "file" "libaio1" "rsync" "jemalloc" "libsnappy1" "net-tools" "libnuma1") declare -a SUSE_PKG_NOT=("mariadb" , "libmariadb18") if [ "$OS" == "suse12" ]; then @@ -1012,7 +1010,7 @@ checkPackages() fi fi - declare -a UBUNTU_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "libreadline-dev" "rsync" "libsnappy1V5" "net-tools" "libnuma1" ) + declare -a UBUNTU_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "libreadline-dev" "rsync" "libjemalloc1" "libsnappy1V5" "net-tools" "libnuma1") declare -a UBUNTU_PKG_NOT=("mariadb-server" "libmariadb18") if [ "$OS" == "ubuntu16" ] || [ "$OS" == "ubuntu18" ]; then @@ -1129,8 +1127,7 @@ checkPackages() fi fi - - declare -a DEBIAN_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "libreadline-dev" "rsync" "libsnappy1" "net-tools" "libnuma1") + declare -a DEBIAN_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "libreadline-dev" "rsync" "libjemalloc1" "libsnappy1" "net-tools" "libnuma1") declare -a DEBIAN_PKG_NOT=("libmariadb18" "mariadb-server") if [ "$OS" == "debian8" ]; then @@ -1247,8 +1244,7 @@ checkPackages() fi fi - - declare -a DEBIAN9_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "libreadline5" "rsync" "libsnappy1V5" "net-tools" "libaio1" "libnuma1") + declare -a DEBIAN9_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "libreadline5" "rsync" "libjemalloc1" "libsnappy1V5" "net-tools" "libaio1") declare -a DEBIAN9_PKG_NOT=("libmariadb18" "mariadb-server") if [ "$OS" == "debian9" ]; then diff --git a/utils/common/CMakeLists.txt b/utils/common/CMakeLists.txt index 54900167e..eff8be12f 100644 --- a/utils/common/CMakeLists.txt +++ b/utils/common/CMakeLists.txt @@ -8,7 +8,8 @@ set(common_LIB_SRCS poolallocator.cpp cgroupconfigurator.cpp MonitorProcMem.cpp - nullvaluemanip.cpp) + nullvaluemanip.cpp + threadnaming.cpp) add_library(common SHARED ${common_LIB_SRCS}) diff --git a/utils/common/common.vpj b/utils/common/common.vpj index ea67e04ba..8b22a4a7a 100755 --- a/utils/common/common.vpj +++ b/utils/common/common.vpj @@ -203,6 +203,7 @@ + + diff --git a/utils/common/nullvaluemanip.cpp b/utils/common/nullvaluemanip.cpp index 475f495cc..a72e8ad00 100644 --- a/utils/common/nullvaluemanip.cpp +++ b/utils/common/nullvaluemanip.cpp @@ -1,4 +1,5 @@ /* 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 @@ -122,9 +123,6 @@ uint64_t getNullValue(CalpontSystemCatalog::ColDataType t, uint32_t colWidth) case CalpontSystemCatalog::UBIGINT: return joblist::UBIGINTNULL; - case CalpontSystemCatalog::LONGDOUBLE: - return -1; // no NULL value for long double yet, this is a nan. - case CalpontSystemCatalog::VARBINARY: default: ostringstream os; @@ -233,7 +231,7 @@ int64_t getSignedNullValue(CalpontSystemCatalog::ColDataType t, uint32_t colWidt return (int64_t)joblist::UBIGINTNULL; case CalpontSystemCatalog::LONGDOUBLE: - return -1; // no NULL value for long double yet, this is a nan. + return (int64_t)joblist::LONGDOUBLENULL; case CalpontSystemCatalog::VARBINARY: default: diff --git a/utils/common/threadnaming.cpp b/utils/common/threadnaming.cpp new file mode 100644 index 000000000..2f4dda91f --- /dev/null +++ b/utils/common/threadnaming.cpp @@ -0,0 +1,26 @@ +/* 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. */ + +#include + +namespace utils +{ + void setThreadName(const char *threadName) + { + prctl(PR_SET_NAME, threadName, 0, 0, 0); + } +} // end of namespace diff --git a/utils/common/threadnaming.h b/utils/common/threadnaming.h new file mode 100644 index 000000000..1682b7045 --- /dev/null +++ b/utils/common/threadnaming.h @@ -0,0 +1,24 @@ +/* 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. */ +#ifndef H_SETTHREADNAME +#define H_SETTHREADNAME + +namespace utils +{ + void setThreadName(const char *threadName); +} // end of namespace +#endif diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index 6566646da..d028bae2f 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -1,4 +1,5 @@ /* 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 @@ -892,7 +893,7 @@ bool mysql_str_to_datetime( const string& input, DateTime& output, bool& isDate bool mysql_str_to_time( const string& input, Time& output, long decimals ) { - int32_t datesepct = 0; +// int32_t datesepct = 0; uint32_t dtend = 0; bool isNeg = false; @@ -3016,6 +3017,7 @@ CalpontSystemCatalog::ColType DataConvert::convertUnionColType(vector unionedType.scale) ? types[i].scale : unionedType.scale; + unionedType.colWidth = sizeof(long double); + unionedType.precision = -1; + break; + + default: + break; + } + + break; + } + case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::VARCHAR: { @@ -3201,6 +3263,7 @@ CalpontSystemCatalog::ColType DataConvert::convertUnionColType(vector 20) ? types[i].colWidth : 20; break; diff --git a/utils/funcexp/func_abs.cpp b/utils/funcexp/func_abs.cpp index 14cb5531a..4cef9a791 100644 --- a/utils/funcexp/func_abs.cpp +++ b/utils/funcexp/func_abs.cpp @@ -1,4 +1,5 @@ /* 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 @@ -78,6 +79,14 @@ double Func_abs::getDoubleVal(Row& row, return fabs(parm[0]->data()->getDoubleVal(row, isNull)); } +long double Func_abs::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + return fabsl(parm[0]->data()->getLongDoubleVal(row, isNull)); +} + } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/func_between.cpp b/utils/funcexp/func_between.cpp index f23d67826..43bde349d 100644 --- a/utils/funcexp/func_between.cpp +++ b/utils/funcexp/func_between.cpp @@ -1,4 +1,5 @@ /* 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 @@ -196,6 +197,24 @@ inline bool getBool(rowgroup::Row& row, numericLE(val, pm[2]->data()->getDoubleVal(row, isNull)); } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double val = pm[0]->data()->getLongDoubleVal(row, isNull); + + if (notBetween) + { + if (!numericGE(val, pm[1]->data()->getLongDoubleVal(row, isNull)) && !isNull) + return true; + + isNull = false; + return (!numericLE(val, pm[2]->data()->getLongDoubleVal(row, isNull)) && !isNull); + } + + return !isNull && + numericGE(val, pm[1]->data()->getLongDoubleVal(row, isNull)) && + numericLE(val, pm[2]->data()->getLongDoubleVal(row, isNull)); + } + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { diff --git a/utils/funcexp/func_case.cpp b/utils/funcexp/func_case.cpp index 03ca241f8..571c66ec7 100644 --- a/utils/funcexp/func_case.cpp +++ b/utils/funcexp/func_case.cpp @@ -1,4 +1,5 @@ /* 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 @@ -243,6 +244,27 @@ inline uint64_t simple_case_cmp(Row& row, break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double ev = parm[n]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getLongDoubleVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + default: { std::ostringstream oss; @@ -510,6 +532,19 @@ double Func_simple_case::getDoubleVal(Row& row, return parm[i]->data()->getDoubleVal(row, isNull); } +long double Func_simple_case::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, operationColType); + + if (isNull) + return doubleNullVal(); + + return parm[i]->data()->getLongDoubleVal(row, isNull); +} + int32_t Func_simple_case::getDateIntVal(rowgroup::Row& row, FunctionParm& parm, @@ -649,6 +684,19 @@ double Func_searched_case::getDoubleVal(Row& row, return parm[i]->data()->getDoubleVal(row, isNull); } +long double Func_searched_case::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + uint64_t i = searched_case_cmp(row, parm, isNull); + + if (isNull) + return longDoubleNullVal(); + + return parm[i]->data()->getLongDoubleVal(row, isNull); +} + int32_t Func_searched_case::getDateIntVal(rowgroup::Row& row, FunctionParm& parm, diff --git a/utils/funcexp/func_cast.cpp b/utils/funcexp/func_cast.cpp index b396c45ea..97c5db075 100644 --- a/utils/funcexp/func_cast.cpp +++ b/utils/funcexp/func_cast.cpp @@ -1,4 +1,5 @@ /* 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 @@ -139,6 +140,26 @@ int64_t Func_cast_signed::getIntVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (value > 0) + value += 0.5; + else if (value < 0) + value -= 0.5; + + int64_t ret = (int64_t) value; + + if (value > (long double) numeric_limits::max()) + ret = numeric_limits::max(); + else if (value < (long double) (numeric_limits::min() + 2)) + ret = numeric_limits::min() + 2; // IDB min for bigint + + return ret; + } + break; + case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::TEXT: @@ -266,6 +287,26 @@ uint64_t Func_cast_unsigned::getUintVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (value > 0) + value += 0.5; + else if (value < 0) + value -= 0.5; + + uint64_t ret = (uint64_t) value; + + if (value > (long double) numeric_limits::max() - 2) + ret = numeric_limits::max(); + else if (value < 0) + ret = 0; + + return ret; + } + break; + case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::TEXT: @@ -391,6 +432,12 @@ string Func_cast_char::getStrVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + return helpers::longDoubleToString(parm[0]->data()->getLongDoubleVal(row, isNull)).substr(0, length); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -526,6 +573,17 @@ double Func_cast_date::getDoubleVal(Row& row, operationColType); } +long double Func_cast_date::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + return (long double) Func_cast_date::getDatetimeIntVal(row, + parm, + isNull, + operationColType); +} + int32_t Func_cast_date::getDateIntVal(rowgroup::Row& row, FunctionParm& parm, @@ -795,6 +853,17 @@ double Func_cast_datetime::getDoubleVal(Row& row, operationColType); } +long double Func_cast_datetime::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + return (long double) Func_cast_datetime::getDatetimeIntVal(row, + parm, + isNull, + operationColType); +} + int64_t Func_cast_datetime::getDatetimeIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, @@ -1099,6 +1168,26 @@ IDB_Decimal Func_cast_decimal::getDecimalVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (value > 0) + decimal.value = (int64_t) (value * helpers::powerOf10_c[decimals] + 0.5); + else if (value < 0) + decimal.value = (int64_t) (value * helpers::powerOf10_c[decimals] - 0.5); + else + decimal.value = 0; + + decimal.scale = decimals; + + if ( value > max_number_decimal ) + decimal.value = max_number_decimal; + else if ( value < -max_number_decimal ) + decimal.value = -max_number_decimal; + } + break; + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { @@ -1426,6 +1515,12 @@ double Func_cast_double::getDoubleVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + dblval = static_cast(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + break; + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { diff --git a/utils/funcexp/func_ceil.cpp b/utils/funcexp/func_ceil.cpp index 7c2f7f571..4cc916b42 100644 --- a/utils/funcexp/func_ceil.cpp +++ b/utils/funcexp/func_ceil.cpp @@ -1,4 +1,5 @@ /* 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 @@ -123,6 +124,12 @@ int64_t Func_ceil::getIntVal(Row& row, } break; + case CalpontSystemCatalog::LONGDOUBLE: + { + ret = (int64_t) ceill(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + break; + case CalpontSystemCatalog::VARCHAR: case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::TEXT: @@ -213,6 +220,12 @@ uint64_t Func_ceil::getUintVal(Row& row, } break; + case CalpontSystemCatalog::LONGDOUBLE: + { + ret = (uint64_t) ceill(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + break; + case CalpontSystemCatalog::VARCHAR: case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::TEXT: @@ -287,6 +300,52 @@ double Func_ceil::getDoubleVal(Row& row, if (!isNull) ret = ceil(strtod(str.c_str(), 0)); } + else if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + ret = (double)ceill(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + else + { + if (isUnsigned(op_ct.colDataType)) + { + ret = (double) getUintVal(row, parm, isNull, op_ct); + } + else + { + ret = (double) getIntVal(row, parm, isNull, op_ct); + } + } + + return ret; +} + +long double Func_ceil::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + long double ret = 0.0; + + if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + ret = ceill(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + else if (op_ct.colDataType == CalpontSystemCatalog::DOUBLE || + op_ct.colDataType == CalpontSystemCatalog::UDOUBLE || + op_ct.colDataType == CalpontSystemCatalog::FLOAT || + op_ct.colDataType == CalpontSystemCatalog::UFLOAT) + { + ret = ceil(parm[0]->data()->getDoubleVal(row, isNull)); + } + else if (op_ct.colDataType == CalpontSystemCatalog::VARCHAR || + op_ct.colDataType == CalpontSystemCatalog::CHAR || + op_ct.colDataType == CalpontSystemCatalog::TEXT) + { + const string& str = parm[0]->data()->getStrVal(row, isNull); + + if (!isNull) + ret = ceil(strtod(str.c_str(), 0)); + } else { if (isUnsigned(op_ct.colDataType)) @@ -328,6 +387,18 @@ string Func_ceil::getStrVal(Row& row, *d = '\0'; } + else if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + snprintf(tmp, 511, "%Lf", getLongDoubleVal(row, parm, isNull, op_ct)); + + // remove the decimals in the oss string. + char* d = tmp; + + while ((*d != '.') && (*d != '\0')) + d++; + + *d = '\0'; + } else if (isUnsigned(op_ct.colDataType)) { #ifndef __LP64__ diff --git a/utils/funcexp/func_coalesce.cpp b/utils/funcexp/func_coalesce.cpp index e03040350..7df883757 100644 --- a/utils/funcexp/func_coalesce.cpp +++ b/utils/funcexp/func_coalesce.cpp @@ -1,4 +1,5 @@ /* 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 @@ -188,6 +189,31 @@ double Func_coalesce::getDoubleVal(rowgroup::Row& row, } +long double Func_coalesce::getLongDoubleVal(rowgroup::Row& row, + FunctionParm& parm, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& ct) +{ + long double d = 0.0; + + for (uint32_t i = 0; i < parm.size(); i++) + { + d = parm[i]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + { + isNull = false; + continue; + } + + return d; + } + + isNull = true; + return d; +} + + execplan::IDB_Decimal Func_coalesce::getDecimalVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, diff --git a/utils/funcexp/func_exp.cpp b/utils/funcexp/func_exp.cpp index 8f1a5bbec..6decbe652 100644 --- a/utils/funcexp/func_exp.cpp +++ b/utils/funcexp/func_exp.cpp @@ -1,4 +1,5 @@ /* 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 @@ -81,6 +82,38 @@ double Func_exp::getDoubleVal(Row& row, return ret; } +long double Func_exp::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + // null value is indicated by isNull + long double x = parm[0]->data()->getLongDoubleVal(row, isNull); + long double ret = 0.0; + + if (!isNull) + { + errno = 0; + ret = expl(x); + + if (errno == ERANGE) // display NULL for out range value + { + if (x > 0) + { + isNull = true; + Message::Args args; + args.add("exp"); + args.add((double)x); + unsigned errcode = ERR_FUNC_OUT_OF_RANGE_RESULT; + throw IDBExcept(IDBErrorInfo::instance()->errorMsg(errcode, args), errcode); + } + else + ret = 0.0; + } + } + + return ret; +} } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/func_floor.cpp b/utils/funcexp/func_floor.cpp index eb05b405f..75954f128 100644 --- a/utils/funcexp/func_floor.cpp +++ b/utils/funcexp/func_floor.cpp @@ -1,4 +1,5 @@ /* 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 @@ -118,6 +119,12 @@ int64_t Func_floor::getIntVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + ret = (int64_t) floorl(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + break; + case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::TEXT: @@ -216,6 +223,12 @@ uint64_t Func_floor::getUintVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + ret = (uint64_t) floorl(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + break; + case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::TEXT: @@ -286,6 +299,10 @@ double Func_floor::getDoubleVal(Row& row, { ret = floor(parm[0]->data()->getDoubleVal(row, isNull)); } + else if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + ret = floorl(parm[0]->data()->getLongDoubleVal(row, isNull)); + } else if (op_ct.colDataType == CalpontSystemCatalog::VARCHAR || op_ct.colDataType == CalpontSystemCatalog::CHAR || op_ct.colDataType == CalpontSystemCatalog::TEXT) @@ -303,6 +320,38 @@ double Func_floor::getDoubleVal(Row& row, return ret; } +long double Func_floor::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + long double ret = 0.0; + + if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE || + op_ct.colDataType == CalpontSystemCatalog::FLOAT) + { + ret = floor(parm[0]->data()->getDoubleVal(row, isNull)); + } + else if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + ret = floorl(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + else if (op_ct.colDataType == CalpontSystemCatalog::VARCHAR || + op_ct.colDataType == CalpontSystemCatalog::CHAR || + op_ct.colDataType == CalpontSystemCatalog::TEXT) + { + const string& str = parm[0]->data()->getStrVal(row, isNull); + + if (!isNull) + ret = floor(strtod(str.c_str(), 0)); + } + else + { + ret = (long double) getIntVal(row, parm, isNull, op_ct); + } + + return ret; +} string Func_floor::getStrVal(Row& row, FunctionParm& parm, @@ -329,6 +378,18 @@ string Func_floor::getStrVal(Row& row, *d = '\0'; } + if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + snprintf(tmp, 511, "%Lf", getLongDoubleVal(row, parm, isNull, op_ct)); + + // remove the decimals in the oss string. + char* d = tmp; + + while ((*d != '.') && (*d != '\0')) + d++; + + *d = '\0'; + } else if (isUnsigned(op_ct.colDataType)) { #ifndef __LP64__ diff --git a/utils/funcexp/func_from_unixtime.cpp b/utils/funcexp/func_from_unixtime.cpp index 9968ba1f0..18dba41c8 100644 --- a/utils/funcexp/func_from_unixtime.cpp +++ b/utils/funcexp/func_from_unixtime.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -209,6 +209,14 @@ double Func_from_unixtime::getDoubleVal(rowgroup::Row& row, return (double) atoi(getStrVal(row, parm, isNull, ct).c_str()); } +long double Func_from_unixtime::getLongDoubleVal(rowgroup::Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& ct) +{ + return (long double) getDoubleVal(row, parm, isNull, ct); +} + } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/func_greatest.cpp b/utils/funcexp/func_greatest.cpp index de63c283e..57c3b82fb 100644 --- a/utils/funcexp/func_greatest.cpp +++ b/utils/funcexp/func_greatest.cpp @@ -1,4 +1,5 @@ /* 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 @@ -121,6 +122,26 @@ double Func_greatest::getDoubleVal(rowgroup::Row& row, return (double) greatestStr; } +long double Func_greatest::getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + long double str = fp[0]->data()->getLongDoubleVal(row, isNull); + + long double greatestStr = str; + + for (uint32_t i = 1; i < fp.size(); i++) + { + long double str1 = fp[i]->data()->getLongDoubleVal(row, isNull); + + if ( greatestStr < str1 ) + greatestStr = str1; + } + + return greatestStr; +} + std::string Func_greatest::getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/func_hex.cpp b/utils/funcexp/func_hex.cpp index 83106a9be..462d8e779 100644 --- a/utils/funcexp/func_hex.cpp +++ b/utils/funcexp/func_hex.cpp @@ -1,4 +1,5 @@ /* 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 @@ -103,6 +104,21 @@ string Func_hex::getStrVal(rowgroup::Row& row, break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + char buf[256]; + long double val = parm[0]->data()->getLongDoubleVal(row, isNull); + +#ifdef _MSC_VER + sprintf(buf, "%llA", val); + +#else + sprintf(buf, "%LA", val); +#endif + retval = buf; + break; + } + case CalpontSystemCatalog::VARBINARY: case CalpontSystemCatalog::BLOB: { diff --git a/utils/funcexp/func_if.cpp b/utils/funcexp/func_if.cpp index ad65d10c9..5da8293e6 100644 --- a/utils/funcexp/func_if.cpp +++ b/utils/funcexp/func_if.cpp @@ -1,4 +1,5 @@ /* 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 @@ -61,6 +62,9 @@ bool boolVal(SPTP& parm, Row& row) case CalpontSystemCatalog::UDOUBLE: ret = (parm->data()->getDoubleVal(row, isNull) != 0); + case CalpontSystemCatalog::LONGDOUBLE: + ret = (parm->data()->getLongDoubleVal(row, isNull) != 0); + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: ret = (parm->data()->getDecimalVal(row, isNull).value != 0); @@ -188,6 +192,21 @@ double Func_if::getDoubleVal(Row& row, } } +long double Func_if::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + if (boolVal(parm[0], row)) + { + return parm[1]->data()->getLongDoubleVal(row, isNull); + } + else + { + return parm[2]->data()->getLongDoubleVal(row, isNull); + } +} + int32_t Func_if::getDateIntVal(Row& row, FunctionParm& parm, diff --git a/utils/funcexp/func_ifnull.cpp b/utils/funcexp/func_ifnull.cpp index 4b8606d4e..00aaa682b 100644 --- a/utils/funcexp/func_ifnull.cpp +++ b/utils/funcexp/func_ifnull.cpp @@ -1,4 +1,5 @@ /* 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 @@ -129,6 +130,25 @@ double Func_ifnull::getDoubleVal(Row& row, return r; } +long double Func_ifnull::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + if (isNull) + return 0.0; + + long double r = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + { + isNull = false; + return parm[1]->data()->getLongDoubleVal(row, isNull); + } + + return r; +} + int32_t Func_ifnull::getDateIntVal(Row& row, FunctionParm& parm, diff --git a/utils/funcexp/func_in.cpp b/utils/funcexp/func_in.cpp index e271fa0f7..966b30ae5 100644 --- a/utils/funcexp/func_in.cpp +++ b/utils/funcexp/func_in.cpp @@ -1,4 +1,5 @@ /* 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 @@ -203,6 +204,27 @@ inline bool getBoolForIn(rowgroup::Row& row, return false; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double val = pm[0]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + return false; + + for (uint32_t i = 1; i < pm.size(); i++) + { + isNull = false; + + if ( val == pm[i]->data()->getLongDoubleVal(row, isNull) && !isNull ) + return true; + + if (isNull && isNotIn) + return true; // will be reversed to false by the caller + } + + return false; + } + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { diff --git a/utils/funcexp/func_isnull.cpp b/utils/funcexp/func_isnull.cpp index 3558f6e30..ebe1c2d88 100644 --- a/utils/funcexp/func_isnull.cpp +++ b/utils/funcexp/func_isnull.cpp @@ -1,4 +1,5 @@ /* 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 @@ -74,6 +75,10 @@ bool Func_isnull::getBoolVal(Row& row, parm[0]->data()->getStrVal(row, isNull); break; + case CalpontSystemCatalog::LONGDOUBLE: + parm[0]->data()->getLongDoubleVal(row, isNull); + break; + default: parm[0]->data()->getIntVal(row, isNull); } diff --git a/utils/funcexp/func_least.cpp b/utils/funcexp/func_least.cpp index 9ba5c98de..cfb590291 100644 --- a/utils/funcexp/func_least.cpp +++ b/utils/funcexp/func_least.cpp @@ -1,4 +1,5 @@ /* 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 @@ -100,6 +101,26 @@ double Func_least::getDoubleVal(rowgroup::Row& row, return (double) leastStr; } +long double Func_least::getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + long double str = fp[0]->data()->getLongDoubleVal(row, isNull); + + long double leastStr = str; + + for (uint32_t i = 1; i < fp.size(); i++) + { + long double str1 = fp[i]->data()->getLongDoubleVal(row, isNull); + + if ( leastStr > str1 ) + leastStr = str1; + } + + return leastStr; +} + std::string Func_least::getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/func_lpad.cpp b/utils/funcexp/func_lpad.cpp index dd25ee191..b5acfd362 100644 --- a/utils/funcexp/func_lpad.cpp +++ b/utils/funcexp/func_lpad.cpp @@ -20,7 +20,7 @@ * * ****************************************************************************/ - +#include "errorids.h" #include using namespace std; @@ -39,6 +39,9 @@ using namespace joblist; namespace funcexp { +const string Func_lpad::fPad = " "; + + CalpontSystemCatalog::ColType Func_lpad::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) { // operation type is not used by this functor @@ -114,17 +117,33 @@ std::string Func_lpad::getStrVal(rowgroup::Row& row, } break; + case execplan::CalpontSystemCatalog::CHAR: + case execplan::CalpontSystemCatalog::VARCHAR: + { + const string& strval = fp[1]->data()->getStrVal(row, isNull); + len = strtol(strval.c_str(), NULL, 10); + break; + } + default: { - len = fp[1]->data()->getIntVal(row, isNull); + std::ostringstream oss; + oss << "lpad parameter 2 must be numeric, not " << execplan::colDataTypeToString(fp[1]->data()->resultType().colDataType); + throw logging::IDBExcept(oss.str(), logging::ERR_DATATYPE_NOT_SUPPORT); + } } if (len < 1) return ""; + // MCOL-2182 As of MariaDB 10.3 the third parameter - pad characters - is optional // The pad characters. - const string& pad = fp[2]->data()->getStrVal(row, isNull); + const string* pad = &fPad; + if (fp.size() > 2) + { + pad = &fp[2]->data()->getStrVal(row, isNull); + } if (isNull) return ""; @@ -172,11 +191,11 @@ std::string Func_lpad::getStrVal(rowgroup::Row& row, // This is the case where there's room to pad. // Convert the pad string to wide - padwclen = pad.length(); // A guess to start. + padwclen = pad->length(); // A guess to start. size_t padbufsize = (padwclen + 1) * sizeof(wchar_t); wchar_t* wcpad = (wchar_t*)alloca(padbufsize); // padwclen+1 is for giving count for the terminating null - size_t padlen = utf8::idb_mbstowcs(wcpad, pad.c_str(), padwclen + 1); + size_t padlen = utf8::idb_mbstowcs(wcpad, pad->c_str(), padwclen + 1); // How many chars do we need? size_t padspace = len - strSize; diff --git a/utils/funcexp/func_math.cpp b/utils/funcexp/func_math.cpp index 8592ec8b0..7af31901a 100644 --- a/utils/funcexp/func_math.cpp +++ b/utils/funcexp/func_math.cpp @@ -1,4 +1,5 @@ /* 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 @@ -1523,6 +1524,26 @@ string Func_format::getStrVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double rawValue = parm[0]->data()->getLongDoubleVal(row, isNull); + + // roundup + if (scale < 0) scale = 0; + + if (rawValue >= 0) + rawValue += 0.5 / pow(10.0, scale); + else + rawValue -= 0.5 / pow(10.0, scale); + + // double's can be *really* long to print out. Max mysql + // is e308 so allow for 308 + 36 decimal places minimum. + char buf[384]; + snprintf(buf, 384, "%0.36Lf", rawValue); + value = buf; + } + break; + default: { std::ostringstream oss; diff --git a/utils/funcexp/func_mod.cpp b/utils/funcexp/func_mod.cpp index c5eb05112..4cbdf23af 100644 --- a/utils/funcexp/func_mod.cpp +++ b/utils/funcexp/func_mod.cpp @@ -1,4 +1,5 @@ /* 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 @@ -142,6 +143,14 @@ double Func_mod::getDoubleVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + mod = (double)fmodl(value, div); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -181,6 +190,110 @@ double Func_mod::getDoubleVal(Row& row, return mod; } +long double Func_mod::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + if ( parm.size() < 2 ) + { + isNull = true; + return 0; + } + + int64_t div = parm[1]->data()->getIntVal(row, isNull); + + if ( div == 0 ) + { + isNull = true; + return 0; + } + + long double mod = 0; + + switch (parm[0]->data()->resultType().colDataType) + { + case execplan::CalpontSystemCatalog::BIGINT: + case execplan::CalpontSystemCatalog::INT: + case execplan::CalpontSystemCatalog::MEDINT: + case execplan::CalpontSystemCatalog::TINYINT: + case execplan::CalpontSystemCatalog::SMALLINT: + { + int64_t value = parm[0]->data()->getIntVal(row, isNull); + + mod = value % div; + } + break; + + case execplan::CalpontSystemCatalog::UBIGINT: + case execplan::CalpontSystemCatalog::UINT: + case execplan::CalpontSystemCatalog::UMEDINT: + case execplan::CalpontSystemCatalog::UTINYINT: + case execplan::CalpontSystemCatalog::USMALLINT: + { + uint64_t udiv = parm[1]->data()->getIntVal(row, isNull); + uint64_t uvalue = parm[0]->data()->getUintVal(row, isNull); + + mod = uvalue % udiv; + } + break; + + case execplan::CalpontSystemCatalog::DOUBLE: + case execplan::CalpontSystemCatalog::UDOUBLE: + { + double value = parm[0]->data()->getDoubleVal(row, isNull); + + mod = fmod(value, div); + } + break; + + case execplan::CalpontSystemCatalog::FLOAT: + case execplan::CalpontSystemCatalog::UFLOAT: + { + float value = parm[0]->data()->getFloatVal(row, isNull); + + mod = fmod(value, div); + } + break; + + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + mod = fmodl(value, div); + } + break; + + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::UDECIMAL: + { + IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); + int64_t value = d.value / helpers::power(d.scale); + + mod = value % div; + } + break; + + case execplan::CalpontSystemCatalog::CHAR: + case execplan::CalpontSystemCatalog::VARCHAR: + case execplan::CalpontSystemCatalog::TEXT: + { + double value = parm[0]->data()->getDoubleVal(row, isNull); + mod = fmod(value, div); + break; + } + + default: + { + std::ostringstream oss; + oss << "mod: datatype of " << execplan::colDataTypeToString(parm[0]->data()->resultType().colDataType); + throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT); + } + } + + return mod; +} + int64_t Func_mod::getIntVal(Row& row, FunctionParm& parm, bool& isNull, @@ -250,6 +363,14 @@ int64_t Func_mod::getIntVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + mod = fmodl(value, div); + } + break; + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { @@ -340,6 +461,14 @@ uint64_t Func_mod::getUIntVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + mod = fmodl(value, div); + } + break; + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { @@ -387,6 +516,10 @@ std::string Func_mod::getStrVal(Row& row, return intToString(getIntVal(row, fp, isNull, op_ct)); break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + return longDoubleToString(getLongDoubleVal(row, fp, isNull, op_ct)); + break; + default: return doubleToString(getDoubleVal(row, fp, isNull, op_ct)); break; diff --git a/utils/funcexp/func_nullif.cpp b/utils/funcexp/func_nullif.cpp index 04a45534a..4bac44c45 100644 --- a/utils/funcexp/func_nullif.cpp +++ b/utils/funcexp/func_nullif.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + 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 @@ -579,6 +579,109 @@ double Func_nullif::getDoubleVal(rowgroup::Row& row, break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + exp2 = (double)parm[1]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + { + isNull = false; + return exp1; + } + + break; + } + + case execplan::CalpontSystemCatalog::DATE: + { + exp2 = parm[1]->data()->getDateIntVal(row, isNull); + + if (isNull) + { + isNull = false; + return exp1; + } + + break; + } + break; + + case execplan::CalpontSystemCatalog::TIME: + case execplan::CalpontSystemCatalog::DATETIME: + { + exp2 = parm[1]->data()->getDatetimeIntVal(row, isNull); + + if (isNull) + { + isNull = false; + return exp1; + } + + break; + } + + default: + { + isNull = true; + } + } + + if ( exp1 == exp2 ) + { + isNull = true; + return 0; + } + + return exp1; +} + + +long double Func_nullif::getLongDoubleVal(rowgroup::Row& row, + FunctionParm& parm, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + long double exp1 = parm[0]->data()->getLongDoubleVal(row, isNull); + long double exp2 = 0; + + switch (parm[1]->data()->resultType().colDataType) + { + case execplan::CalpontSystemCatalog::BIGINT: + case execplan::CalpontSystemCatalog::INT: + case execplan::CalpontSystemCatalog::MEDINT: + case execplan::CalpontSystemCatalog::TINYINT: + case execplan::CalpontSystemCatalog::SMALLINT: + case execplan::CalpontSystemCatalog::DOUBLE: + case execplan::CalpontSystemCatalog::FLOAT: + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::VARCHAR: + case execplan::CalpontSystemCatalog::CHAR: + case execplan::CalpontSystemCatalog::TEXT: + { + exp2 = parm[1]->data()->getDoubleVal(row, isNull); + + if (isNull) + { + isNull = false; + return exp1; + } + + break; + } + + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + exp2 = parm[1]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + { + isNull = false; + return exp1; + } + + break; + } + case execplan::CalpontSystemCatalog::DATE: { exp2 = parm[1]->data()->getDateIntVal(row, isNull); diff --git a/utils/funcexp/func_pow.cpp b/utils/funcexp/func_pow.cpp index c838d174e..f94432b6d 100644 --- a/utils/funcexp/func_pow.cpp +++ b/utils/funcexp/func_pow.cpp @@ -1,4 +1,5 @@ /* 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 @@ -89,6 +90,44 @@ double Func_pow::getDoubleVal(Row& row, return 0.0; } +long double Func_pow::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + // null value is indicated by isNull + long double base = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (!isNull) + { + // Should this be long double? Not sure on usage. + double exponent = parm[1]->data()->getDoubleVal(row, isNull); + + if (!isNull) + { + errno = 0; + long double x = powl(base, (long double)exponent); + + // @bug3490, 4461, rule out domain error, pole error and overflow range error. + if (!isfinite(x)) + { + isNull = true; + Message::Args args; + args.add("pow"); + args.add((double)base); + args.add(exponent); + unsigned errcode = ERR_FUNC_OUT_OF_RANGE_RESULT; + throw IDBExcept(IDBErrorInfo::instance()->errorMsg(errcode, args), errcode); + } + + + return x; + } + } + + return 0.0; +} + } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/func_round.cpp b/utils/funcexp/func_round.cpp index c107fc0fc..2a843f429 100644 --- a/utils/funcexp/func_round.cpp +++ b/utils/funcexp/func_round.cpp @@ -1,4 +1,5 @@ /* 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 @@ -45,7 +46,9 @@ namespace using namespace funcexp; -inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, double& p, Row& row, bool& isNull) +// P should either be double or long double +template +inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, P& p, Row& row, bool& isNull) { s = fp[1]->data()->getIntVal(row, isNull); int64_t d = s; @@ -60,9 +63,9 @@ inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, double& p, Row& row r *= 10; if (d >= 0) - p = (double) r; + p = (P) r; else - p = 1.0 / ((double) r); + p = 1.0 / ((P) r); } } @@ -200,6 +203,67 @@ double Func_round::getDoubleVal(Row& row, return d; } +long double Func_round::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + if (execplan::CalpontSystemCatalog::LONGDOUBLE == op_ct.colDataType) + { + int64_t d = 0; + long double p = 1; + + if (parm.size() > 1) // round(X, D) + decimalPlaceDouble(parm, d, p, row, isNull); + + if (isNull) + return 0.0; + + long double x = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (!isNull) + { + x *= p; + + if (x >= 0) + x = floor(x + 0.5); + else + x = ceil(x - 0.5); + + if (p != 0.0) + x /= p; + else + x = 0.0; + } + + return x; + } + + if (isUnsigned(op_ct.colDataType)) + { + return getUintVal(row, parm, isNull, op_ct); + } + + IDB_Decimal x = getDecimalVal(row, parm, isNull, op_ct); + + if (isNull) + return 0.0; + + double d = x.value; + + if (x.scale > 0) + { + while (x.scale-- > 0) + d /= 10.0; + } + else + { + while (x.scale++ < 0) + d *= 10.0; + } + + return d; +} IDB_Decimal Func_round::getDecimalVal(Row& row, FunctionParm& parm, @@ -330,6 +394,34 @@ IDB_Decimal Func_round::getDecimalVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + int64_t s = 0; + long double p = 1; + + if (parm.size() > 1) // round(X, D) + decimalPlaceDouble(parm, s, p, row, isNull); + + if (isNull) + break; + + long double x = parm[0]->data()->getDoubleVal(row, isNull); + + if (!isNull) + { + x *= p; + + if (x >= 0) + x = floor(x + 0.5); + else + x = ceil(x - 0.5); + + decimal.value = (int64_t) x; + decimal.scale = s; + } + } + break; + case execplan::CalpontSystemCatalog::DATE: { int32_t s = 0; diff --git a/utils/funcexp/func_rpad.cpp b/utils/funcexp/func_rpad.cpp index 7de0dfb78..7a6b94e0c 100644 --- a/utils/funcexp/func_rpad.cpp +++ b/utils/funcexp/func_rpad.cpp @@ -20,7 +20,7 @@ * * ****************************************************************************/ - +#include "errorids.h" #include using namespace std; @@ -39,6 +39,8 @@ using namespace joblist; namespace funcexp { +const string Func_rpad::fPad = " "; + CalpontSystemCatalog::ColType Func_rpad::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) { // operation type is not used by this functor @@ -114,9 +116,19 @@ std::string Func_rpad::getStrVal(rowgroup::Row& row, } break; + case execplan::CalpontSystemCatalog::CHAR: + case execplan::CalpontSystemCatalog::VARCHAR: + { + const string& strval = fp[1]->data()->getStrVal(row, isNull); + len = strtol(strval.c_str(), NULL, 10); + break; + } + default: { - len = fp[1]->data()->getIntVal(row, isNull); + std::ostringstream oss; + oss << "lpad parameter 2 must be numeric, not " << execplan::colDataTypeToString(fp[1]->data()->resultType().colDataType); + throw logging::IDBExcept(oss.str(), logging::ERR_DATATYPE_NOT_SUPPORT); } } @@ -124,7 +136,12 @@ std::string Func_rpad::getStrVal(rowgroup::Row& row, return ""; // The pad characters. - const string& pad = fp[2]->data()->getStrVal(row, isNull); + // MCOL-2182 As of MariaDB 10.3 the third parameter - pad characters - is optional + const string* pad = &fPad; + if (fp.size() > 2) + { + pad = &fp[2]->data()->getStrVal(row, isNull); + } if (isNull) return ""; @@ -172,10 +189,10 @@ std::string Func_rpad::getStrVal(rowgroup::Row& row, // This is the case where there's room to pad. // Convert the pad string to wide - padwclen = pad.length(); // A guess to start. + padwclen = pad->length(); // A guess to start. int padbufsize = (padwclen + 1) * sizeof(wchar_t); wchar_t* wcpad = (wchar_t*)alloca(padbufsize); - size_t padlen = utf8::idb_mbstowcs(wcpad, pad.c_str(), padwclen + 1); + size_t padlen = utf8::idb_mbstowcs(wcpad, pad->c_str(), padwclen + 1); // How many chars do we need? unsigned int padspace = len - strSize; diff --git a/utils/funcexp/func_substring_index.cpp b/utils/funcexp/func_substring_index.cpp index cf1395759..f68679992 100644 --- a/utils/funcexp/func_substring_index.cpp +++ b/utils/funcexp/func_substring_index.cpp @@ -1,4 +1,5 @@ /* 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 @@ -69,9 +70,10 @@ std::string Func_substring_index::getStrVal(rowgroup::Row& row, if ( count == 0 ) return ""; - size_t end = strlen(str.c_str()); + // To avoid comparison b/w int64_t and size_t + int64_t end = strlen(str.c_str()) & 0x7fffffffffffffff; - if ( count > (int64_t) end ) + if ( count > end ) return str; if (( count < 0 ) && ((count * -1) > end)) @@ -83,7 +85,7 @@ std::string Func_substring_index::getStrVal(rowgroup::Row& row, { int pointer = 0; - for ( int i = 0 ; i < count ; i ++ ) + for ( int64_t i = 0 ; i < count ; i ++ ) { string::size_type pos = str.find(delim, pointer); @@ -102,13 +104,13 @@ std::string Func_substring_index::getStrVal(rowgroup::Row& row, int pointer = end; int start = 0; - for ( int i = 0 ; i < count ; i ++ ) + for ( int64_t i = 0 ; i < count ; i ++ ) { string::size_type pos = str.rfind(delim, pointer); if (pos != string::npos) { - if ( count > (int64_t) end ) + if ( count > end ) return ""; pointer = pos - 1; diff --git a/utils/funcexp/func_truncate.cpp b/utils/funcexp/func_truncate.cpp index 2da482ab8..1b8383b28 100644 --- a/utils/funcexp/func_truncate.cpp +++ b/utils/funcexp/func_truncate.cpp @@ -1,4 +1,5 @@ /* 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 @@ -42,7 +43,9 @@ namespace using namespace funcexp; -inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, double& p, Row& row, bool& isNull) +// P should be double or long double +template +inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, P& p, Row& row, bool& isNull) { s = fp[1]->data()->getIntVal(row, isNull); int64_t d = s; @@ -57,9 +60,9 @@ inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, double& p, Row& row r *= 10; if (d >= 0) - p = (double) r; + p = (P) r; else - p = 1.0 / ((double) r); + p = 1.0 / ((P) r); } } @@ -223,6 +226,60 @@ double Func_truncate::getDoubleVal(Row& row, return d; } +long double Func_truncate::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + if (execplan::CalpontSystemCatalog::LONGDOUBLE == op_ct.colDataType) + { + int64_t d = 0; + long double p = 1; + decimalPlaceDouble(parm, d, p, row, isNull); + + if (isNull) + return 0.0; + + long double x = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (!isNull) + { + x *= p; + + if (x > 0) + x = floor(x); + else + x = ceil(x); + + if (p != 0.0) + x /= p; + else + x = 0.0; + } + + return x; + } + + IDB_Decimal x = getDecimalVal(row, parm, isNull, op_ct); + + if (isNull) + return 0.0; + + double d = x.value; + + if (x.scale > 0) + { + while (x.scale-- > 0) + d /= 10.0; + } + else + { + while (x.scale++ < 0) + d *= 10.0; + } + + return d; +} IDB_Decimal Func_truncate::getDecimalVal(Row& row, FunctionParm& parm, @@ -325,6 +382,26 @@ IDB_Decimal Func_truncate::getDecimalVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + int64_t s = 0; + long double p = 1; + decimalPlaceDouble(parm, s, p, row, isNull); + + if (isNull) + break; + + long double x = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (!isNull) + { + x *= p; + decimal.value = (int64_t) x; + decimal.scale = s; + } + } + break; + case execplan::CalpontSystemCatalog::DATE: { int32_t s = 0; diff --git a/utils/funcexp/funcexp.cpp b/utils/funcexp/funcexp.cpp index 53f7da595..d933474f7 100644 --- a/utils/funcexp/funcexp.cpp +++ b/utils/funcexp/funcexp.cpp @@ -1,4 +1,5 @@ /* 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 @@ -439,6 +440,18 @@ void FuncExp::evaluate(rowgroup::Row& row, std::vector& expressi break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + long double val = expression[i]->getLongDoubleVal(row, isNull); + + if (isNull) + row.setLongDoubleField(LONGDOUBLENULL, expression[i]->outputIndex()); + else + row.setLongDoubleField(val, expression[i]->outputIndex()); + + break; + } + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { diff --git a/utils/funcexp/funchelpers.h b/utils/funcexp/funchelpers.h index ebb78f8cc..e1290d230 100644 --- a/utils/funcexp/funchelpers.h +++ b/utils/funcexp/funchelpers.h @@ -1,4 +1,5 @@ /* 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 @@ -751,6 +752,16 @@ string doubleToString(double d) return buf; } +inline +string longDoubleToString(long double ld) +{ + // long double's can be *really* long to print out. Max mysql + // is e308 so allow for 308 + 36 decimal places minimum. + char buf[384]; + snprintf(buf, 384, "%Lf", ld); + return buf; +} + //@bug6146, remove duplicate function with incorrect impl. Use the DataConvert::decimalToString() //string decimalToString( execplan::IDB_Decimal x, int p ) diff --git a/utils/funcexp/functor.cpp b/utils/funcexp/functor.cpp index 1e50ea1fc..54060d74b 100644 --- a/utils/funcexp/functor.cpp +++ b/utils/funcexp/functor.cpp @@ -1,4 +1,5 @@ /* 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 @@ -60,6 +61,7 @@ void Func::init() double* dp = reinterpret_cast(&dni); fDoubleNullVal = *dp; + fDoubleNullVal = joblist::LONGDOUBLENULL; } @@ -341,6 +343,11 @@ string Func::doubleToString(double d) return helpers::doubleToString(d); } +string Func::longDoubleToString(long double ld) +{ + return helpers::longDoubleToString(ld); +} + } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/functor.h b/utils/funcexp/functor.h index 20914e99e..9904c6831 100644 --- a/utils/funcexp/functor.h +++ b/utils/funcexp/functor.h @@ -1,4 +1,5 @@ /* 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 @@ -90,6 +91,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) = 0; + virtual long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) = 0; + virtual std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -152,6 +158,11 @@ public: { return fDoubleNullVal; } + const long double longDoubleNullVal() const + { + return fLongDoubleNullVal; + } + protected: virtual uint32_t stringToDate(std::string); @@ -164,6 +175,7 @@ protected: virtual std::string intToString(int64_t); virtual std::string doubleToString(double); + virtual std::string longDoubleToString(long double); virtual int64_t nowDatetime(); virtual int64_t addTime(DateTime& dt1, dataconvert::Time& dt2); @@ -180,6 +192,7 @@ private: float fFloatNullVal; double fDoubleNullVal; + long double fLongDoubleNullVal; }; diff --git a/utils/funcexp/functor_all.h b/utils/funcexp/functor_all.h index 553abc40f..71d857132 100644 --- a/utils/funcexp/functor_all.h +++ b/utils/funcexp/functor_all.h @@ -1,4 +1,5 @@ /* 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 @@ -85,6 +86,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -137,6 +143,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -185,6 +196,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -232,6 +248,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -289,6 +310,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -337,6 +363,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -384,6 +415,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -456,6 +492,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + execplan::IDB_Decimal getDecimalVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_bool.h b/utils/funcexp/functor_bool.h index b7b85106b..27e32fbbc 100644 --- a/utils/funcexp/functor_bool.h +++ b/utils/funcexp/functor_bool.h @@ -64,6 +64,14 @@ public: return (getBoolVal(row, fp, isNull, op_ct) ? 1.0 : 0.0); } + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return (getBoolVal(row, fp, isNull, op_ct) ? 1.0 : 0.0); + } + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_dtm.h b/utils/funcexp/functor_dtm.h index bcff47854..bddd78202 100644 --- a/utils/funcexp/functor_dtm.h +++ b/utils/funcexp/functor_dtm.h @@ -1,4 +1,5 @@ /* 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 @@ -57,6 +58,14 @@ public: return (double) getIntVal(row, fp, isNull, op_ct); } + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return (long double) getIntVal(row, fp, isNull, op_ct); + } + /* std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, @@ -196,6 +205,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -238,6 +252,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -423,6 +442,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_export.h b/utils/funcexp/functor_export.h index a58293f98..af7ca6cee 100644 --- a/utils/funcexp/functor_export.h +++ b/utils/funcexp/functor_export.h @@ -1,4 +1,5 @@ /* 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 @@ -58,6 +59,14 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return (long double)getDoubleVal(row, fp, isNull, op_ct); + } + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_int.h b/utils/funcexp/functor_int.h index 2eb7cc63e..e5b0093a9 100644 --- a/utils/funcexp/functor_int.h +++ b/utils/funcexp/functor_int.h @@ -1,4 +1,5 @@ /* 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 @@ -55,6 +56,14 @@ public: return ((double) getIntVal(row, fp, isNull, op_ct)); } + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return ((long double) getIntVal(row, fp, isNull, op_ct)); + } + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_real.h b/utils/funcexp/functor_real.h index 5d40ce589..a12759333 100644 --- a/utils/funcexp/functor_real.h +++ b/utils/funcexp/functor_real.h @@ -1,4 +1,5 @@ /* 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 @@ -57,12 +58,14 @@ public: { return ((uint64_t) getDoubleVal(row, fp, isNull, op_ct)); } - /* - double getDoubleVal(rowgroup::Row& row, - FunctionParm& fp, - bool& isNull, - execplan::CalpontSystemCatalog::ColType& op_ct) = 0; - */ + + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return ((long double) getDoubleVal(row, fp, isNull, op_ct)); + } std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, @@ -99,6 +102,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + execplan::IDB_Decimal getDecimalVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -120,6 +128,11 @@ public: FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); }; @@ -137,6 +150,11 @@ public: FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); }; @@ -165,6 +183,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + execplan::IDB_Decimal getDecimalVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -202,6 +225,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -239,6 +267,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -271,6 +304,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -350,6 +388,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + execplan::IDB_Decimal getDecimalVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_str.h b/utils/funcexp/functor_str.h index 8b6c10404..5402cc646 100644 --- a/utils/funcexp/functor_str.h +++ b/utils/funcexp/functor_str.h @@ -1,4 +1,5 @@ /* 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 @@ -57,6 +58,14 @@ public: return strtod(getStrVal(row, fp, isNull, op_ct).c_str(), NULL); } + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return strtold(getStrVal(row, fp, isNull, op_ct).c_str(), NULL); + } + #if 0 std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, @@ -105,12 +114,16 @@ protected: // Bug3788, use the shorter of fixed or scientific notation for floating point values. // [ the default format in treenode.h is fixed-point notation ] char buf[20]; - double floatVal; - int exponent; - double base; + long double floatVal; + int64_t exponent; + long double base; switch (fp->data()->resultType().colDataType) { + case execplan::CalpontSystemCatalog::LONGDOUBLE: + floatVal = fp->data()->getLongDoubleVal(row, isNull); + break; + case execplan::CalpontSystemCatalog::DOUBLE: floatVal = fp->data()->getDoubleVal(row, isNull); break; @@ -125,19 +138,19 @@ protected: break; } - exponent = (int)floor(log10( fabs(floatVal))); + exponent = (int)floor(log10( fabsl(floatVal))); base = floatVal * pow(10, -1.0 * exponent); if (isnan(exponent) || isnan(base)) { - snprintf(buf, 20, "%f", floatVal); + snprintf(buf, 20, "%Lf", floatVal); fFloatStr = execplan::removeTrailing0(buf, 20); } else { - snprintf(buf, 20, "%.5f", base); + snprintf(buf, 20, "%.5Lf", base); fFloatStr = execplan::removeTrailing0(buf, 20); - snprintf(buf, 20, "e%02d", exponent); + snprintf(buf, 20, "e%02ld", exponent); fFloatStr += buf; } @@ -312,6 +325,7 @@ public: */ class Func_lpad : public Func_Str { + static const string fPad; public: Func_lpad() : Func_Str("lpad") {} virtual ~Func_lpad() {} @@ -329,6 +343,7 @@ public: */ class Func_rpad : public Func_Str { + static const string fPad; public: Func_rpad() : Func_Str("rpad") {} virtual ~Func_rpad() {} diff --git a/utils/joiner/joinpartition.cpp b/utils/joiner/joinpartition.cpp index 962143aac..4982ed750 100644 --- a/utils/joiner/joinpartition.cpp +++ b/utils/joiner/joinpartition.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2018 MariaDB Corporation + 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 @@ -118,7 +118,6 @@ JoinPartition::JoinPartition(const JoinPartition& jp, bool splitMode) : totalBytesWritten(0), maxLargeSize(0), maxSmallSize(0), nextSmallOffset(0), nextLargeOffset(0) { - config::Config* config = config::Config::makeConfig(); boost::posix_time::ptime t; ostringstream os; diff --git a/utils/joiner/tuplejoiner.cpp b/utils/joiner/tuplejoiner.cpp index edc94b067..ff64b8283 100644 --- a/utils/joiner/tuplejoiner.cpp +++ b/utils/joiner/tuplejoiner.cpp @@ -1,4 +1,5 @@ /* 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 @@ -45,7 +46,14 @@ TupleJoiner::TupleJoiner( smallRG(smallInput), largeRG(largeInput), joinAlg(INSERTING), joinType(jt), threadCount(1), typelessJoin(false), bSignedUnsignedJoin(false), uniqueLimit(100), finished(false) { - if (smallRG.usesStringTable()) + if (smallRG.getColTypes()[smallJoinColumn] == CalpontSystemCatalog::LONGDOUBLE) + { + STLPoolAllocator > alloc(64 * 1024 * 1024 + 1); + _pool = alloc.getPoolAllocator(); + + ld.reset(new ldhash_t(10, hasher(), ldhash_t::key_equal(), alloc)); + } + else if (smallRG.usesStringTable()) { STLPoolAllocator > alloc(64 * 1024 * 1024 + 1); _pool = alloc.getPoolAllocator(); @@ -131,8 +139,14 @@ TupleJoiner::TupleJoiner( if (keyLength > 65536) keyLength = 65536; } + else if (smallRG.getColTypes()[smallKeyColumns[i]] == CalpontSystemCatalog::LONGDOUBLE) + { + keyLength += sizeof(long double); + } else + { keyLength += 8; + } // Set bSignedUnsignedJoin if one or more join columns are signed to unsigned compares. if (smallRG.isUnsigned(smallKeyColumns[i]) != largeRG.isUnsigned(largeKeyColumns[i])) @@ -198,9 +212,20 @@ void TupleJoiner::insert(Row& r, bool zeroTheRid) { if (typelessJoin) { - ht->insert(pair - (makeTypelessKey(r, smallKeyColumns, keyLength, &storedKeyAlloc), - r.getPointer())); + TypelessData td = makeTypelessKey(r, smallKeyColumns, keyLength, &storedKeyAlloc, + largeRG, largeKeyColumns); + if (td.len > 0) + { + ht->insert(pair(td, r.getPointer())); + } + } + else if (r.getColType(smallKeyColumns[0]) == execplan::CalpontSystemCatalog::LONGDOUBLE) + { + long double smallKey = r.getLongDoubleField(smallKeyColumns[0]); + if (UNLIKELY(smallKey == joblist::LONGDOUBLENULL)) + ld->insert(pair(joblist::LONGDOUBLENULL, r.getPointer())); + else + ld->insert(pair(smallKey, r.getPointer())); } else if (!smallRG.usesStringTable()) { @@ -260,9 +285,16 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin thIterator it; pair range; - largeKey = makeTypelessKey(largeSideRow, largeKeyColumns, keyLength, &tmpKeyAlloc[threadID]); - it = ht->find(largeKey); - + largeKey = makeTypelessKey(largeSideRow, largeKeyColumns, keyLength, &tmpKeyAlloc[threadID], smallRG, smallKeyColumns); + if (largeKey.len > 0) + { + it = ht->find(largeKey); + } + else + { + return; + } + if (it == ht->end() && !(joinType & (LARGEOUTER | MATCHNULLS))) return; @@ -271,6 +303,28 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin for (; range.first != range.second; ++range.first) matches->push_back(range.first->second); } + else if (largeSideRow.getColType(largeKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE + && ld) + { + // This is a compare of two long double + long double largeKey; + ldIterator it; + pair range; + Row r; + + largeKey = largeSideRow.getLongDoubleField(largeKeyColumns[0]); + it = ld->find(largeKey); + + if (it == ld->end() && !(joinType & (LARGEOUTER | MATCHNULLS))) + return; + + range = ld->equal_range(largeKey); + + for (; range.first != range.second; ++range.first) + { + matches->push_back(range.first->second); + } + } else if (!smallRG.usesStringTable()) { int64_t largeKey; @@ -278,7 +332,11 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin pair range; Row r; - if (largeSideRow.isUnsigned(largeKeyColumns[0])) + if (largeSideRow.getColType(largeKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + { + largeKey = (int64_t)largeSideRow.getLongDoubleField(largeKeyColumns[0]); + } + else if (largeSideRow.isUnsigned(largeKeyColumns[0])) { largeKey = (int64_t)largeSideRow.getUintField(largeKeyColumns[0]); } @@ -287,19 +345,41 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin largeKey = largeSideRow.getIntField(largeKeyColumns[0]); } - it = h->find(largeKey); - - if (it == end() && !(joinType & (LARGEOUTER | MATCHNULLS))) - return; - - range = h->equal_range(largeKey); - - //smallRG.initRow(&r); - for (; range.first != range.second; ++range.first) + if (ld) { - //r.setData(range.first->second); - //cerr << "matched small side row: " << r.toString() << endl; - matches->push_back(range.first->second); + // Compare against long double + ldIterator it; + pair range; + long double ldKey = largeKey; +// ldKey = 6920; + it = ld->find(ldKey); + + if (it == ld->end() && !(joinType & (LARGEOUTER | MATCHNULLS))) + return; + + range = ld->equal_range(ldKey); + + for (; range.first != range.second; ++range.first) + { + matches->push_back(range.first->second); + } + } + else + { + it = h->find(largeKey); + + if (it == h->end() && !(joinType & (LARGEOUTER | MATCHNULLS))) + return; + + range = h->equal_range(largeKey); + + //smallRG.initRow(&r); + for (; range.first != range.second; ++range.first) + { + //r.setData(range.first->second); + //cerr << "matched small side row: " << r.toString() << endl; + matches->push_back(range.first->second); + } } } else @@ -335,7 +415,14 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin if (UNLIKELY(inUM() && (joinType & MATCHNULLS) && !isNull && !typelessJoin)) { - if (!smallRG.usesStringTable()) + if (smallRG.getColType(largeKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + { + pair range = ld->equal_range(joblist::LONGDOUBLENULL); + + for (; range.first != range.second; ++range.first) + matches->push_back(range.first->second); + } + else if (!smallRG.usesStringTable()) { pair range = h->equal_range(getJoinNullValue()); @@ -357,7 +444,14 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin { if (!typelessJoin) { - if (!smallRG.usesStringTable()) + if (smallRG.getColType(smallKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + { + ldIterator it; + + for (it = ld->begin(); it != ld->end(); ++it) + matches->push_back(it->second); + } + else if (!smallRG.usesStringTable()) { iterator it; @@ -410,6 +504,7 @@ void TupleJoiner::doneInserting() tr1::unordered_set::iterator uit; sthash_t::iterator sthit; hash_t::iterator hit; + ldhash_t::iterator ldit; typelesshash_t::iterator thit; uint32_t i, pmpos = 0, rowCount; Row smallRow; @@ -425,6 +520,8 @@ void TupleJoiner::doneInserting() pmpos = 0; else if (typelessJoin) thit = ht->begin(); + else if (smallRG.getColType(smallKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + ldit = ld->begin(); else if (!smallRG.usesStringTable()) hit = h->begin(); else @@ -439,6 +536,11 @@ void TupleJoiner::doneInserting() smallRow.setPointer(thit->second); ++thit; } + else if (smallRG.getColType(smallKeyColumns[col]) == CalpontSystemCatalog::LONGDOUBLE) + { + smallRow.setPointer(ldit->second); + ++ldit; + } else if (!smallRG.usesStringTable()) { smallRow.setPointer(hit->second); @@ -450,6 +552,25 @@ void TupleJoiner::doneInserting() ++sthit; } + if (smallRow.getColType(smallKeyColumns[col]) == CalpontSystemCatalog::LONGDOUBLE) + { + double dval = (double)roundl(smallRow.getLongDoubleField(smallKeyColumns[col])); + switch (largeRG.getColType(largeKeyColumns[col])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + uniquer.insert(*(int64_t*)&dval); + } + default: + { + uniquer.insert((int64_t)dval); + } + } + } + else if (smallRow.isUnsigned(smallKeyColumns[col])) { uniquer.insert((int64_t)smallRow.getUintField(smallKeyColumns[col])); @@ -614,11 +735,23 @@ void TupleJoiner::getUnmarkedRows(vector* out) out->push_back(it->second); } } + else if (smallRG.getColType(smallKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + { + ldIterator it; + + for (it = ld->begin(); it != ld->end(); ++it) + { + smallR.setPointer(it->second); + + if (!smallR.isMarked()) + out->push_back(it->second); + } + } else if (!smallRG.usesStringTable()) { iterator it; - for (it = begin(); it != end(); ++it) + for (it = h->begin(); it != h->end(); ++it) { smallR.setPointer(it->second); @@ -670,8 +803,9 @@ void TupleJoiner::updateCPData(const Row& r) for (col = 0; col < smallKeyColumns.size(); col++) { +// if (r.getColumnWidth(smallKeyColumns[col]) > 8) if (r.isLongString(smallKeyColumns[col])) - continue; + continue; int64_t& min = cpValues[col][0], &max = cpValues[col][1]; @@ -693,7 +827,29 @@ void TupleJoiner::updateCPData(const Row& r) } else if (r.isUnsigned(smallKeyColumns[col])) { - uint64_t uval = r.getUintField(smallKeyColumns[col]); + uint64_t uval; + if (r.getColType(smallKeyColumns[col]) == CalpontSystemCatalog::LONGDOUBLE) + { + double dval = (double)roundl(r.getLongDoubleField(smallKeyColumns[col])); + switch (largeRG.getColType(largeKeyColumns[col])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + uval = *(uint64_t*)&dval; + } + default: + { + uval = (uint64_t)dval; + } + } + } + else + { + uval = r.getUintField(smallKeyColumns[col]); + } if (uval > static_cast(max)) max = static_cast(uval); @@ -703,7 +859,29 @@ void TupleJoiner::updateCPData(const Row& r) } else { - int64_t val = r.getIntField(smallKeyColumns[col]); + int64_t val; + if (r.getColType(smallKeyColumns[col]) == CalpontSystemCatalog::LONGDOUBLE) + { + double dval = (double)roundl(r.getLongDoubleField(smallKeyColumns[col])); + switch (largeRG.getColType(largeKeyColumns[col])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + val = *(int64_t*)&dval; + } + default: + { + val = (int64_t)dval; + } + } + } + else + { + val = r.getIntField(smallKeyColumns[col]); + } if (val > max) max = val; @@ -720,6 +898,8 @@ size_t TupleJoiner::size() const { if (UNLIKELY(typelessJoin)) return ht->size(); + else if (smallRG.getColType(smallKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + return ld->size(); else if (!smallRG.usesStringTable()) return h->size(); else @@ -768,20 +948,18 @@ TypelessData makeTypelessKey(const Row& r, const vector& keyCols, ret.data[off++] = 0; } + else if (r.isUnsigned(keyCols[i])) + { + if (off + 8 > keylen) + goto toolong; + *((uint64_t*) &ret.data[off]) = r.getUintField(keyCols[i]); + off += 8; + } else { if (off + 8 > keylen) goto toolong; - - if (r.isUnsigned(keyCols[i])) - { - *((uint64_t*) &ret.data[off]) = r.getUintField(keyCols[i]); - } - else - { - *((int64_t*) &ret.data[off]) = r.getIntField(keyCols[i]); - } - + *((int64_t*) &ret.data[off]) = r.getIntField(keyCols[i]); off += 8; } } @@ -795,7 +973,132 @@ toolong: return ret; } -TypelessData makeTypelessKey(const Row& r, const vector& keyCols, PoolAllocator* fa) +TypelessData makeTypelessKey(const Row& r, const vector& keyCols, + uint32_t keylen, FixedAllocator* fa, + const rowgroup::RowGroup& otherSideRG, const std::vector& otherKeyCols) +{ + TypelessData ret; + uint32_t off = 0, i, j; + execplan::CalpontSystemCatalog::ColDataType type; + + ret.data = (uint8_t*) fa->allocate(); + + for (i = 0; i < keyCols.size(); i++) + { + type = r.getColTypes()[keyCols[i]]; + + if (type == CalpontSystemCatalog::VARCHAR || + type == CalpontSystemCatalog::CHAR || + type == CalpontSystemCatalog::TEXT) + { + // this is a string, copy a normalized version + const uint8_t* str = r.getStringPointer(keyCols[i]); + uint32_t width = r.getStringLength(keyCols[i]); + + if (width > 65536) + { + throw runtime_error("Cannot join strings greater than 64KB"); + } + + for (j = 0; j < width && str[j] != 0; j++) + { + if (off >= keylen) + goto toolong; + + ret.data[off++] = str[j]; + } + + if (off >= keylen) + goto toolong; + + ret.data[off++] = 0; + } + else if (r.getColType(keyCols[i]) == CalpontSystemCatalog::LONGDOUBLE) + { + if (off + sizeof(long double) > keylen) + goto toolong; + // Small side is a long double. Since CS can't store larger than DOUBLE, + // we need to convert to whatever type large side is -- double or int64 + long double keyld = r.getLongDoubleField(keyCols[i]); + switch (otherSideRG.getColType(otherKeyCols[i])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + if (off + 8 > keylen) + goto toolong; + if (keyld > MAX_DOUBLE || keyld < MIN_DOUBLE) + { + ret.len = 0; + return ret; + } + else + { + double d = (double)keyld; + *((int64_t*) &ret.data[off]) = *(int64_t*)&d; + } + break; + } + case CalpontSystemCatalog::LONGDOUBLE: + { + if (off + sizeof(long double) > keylen) + goto toolong; + *((long double*) &ret.data[off]) = keyld; + off += sizeof(long double); + break; + } + default: + { + if (off + 8 > keylen) + goto toolong; + if (r.isUnsigned(keyCols[i]) && keyld > MAX_UBIGINT) + { + ret.len = 0; + return ret; + } + else if (keyld > MAX_BIGINT || keyld < MIN_BIGINT) + { + ret.len = 0; + return ret; + } + else + { + *((int64_t*) &ret.data[off]) = (int64_t)keyld; + off += 8; + } + break; + } + } + } + else if (r.isUnsigned(keyCols[i])) + { + if (off + 8 > keylen) + goto toolong; + *((uint64_t*) &ret.data[off]) = r.getUintField(keyCols[i]); + off += 8; + } + else + { + if (off + 8 > keylen) + goto toolong; + *((int64_t*) &ret.data[off]) = r.getIntField(keyCols[i]); + off += 8; + } + } + + ret.len = off; + fa->truncateBy(keylen - off); + return ret; +toolong: + fa->truncateBy(keylen); + ret.len = 0; + return ret; +} + +TypelessData makeTypelessKey(const Row& r, const vector& keyCols, PoolAllocator* fa, + const rowgroup::RowGroup& otherSideRG, const std::vector& otherKeyCols) { TypelessData ret; uint32_t off = 0, i, j; @@ -808,7 +1111,12 @@ TypelessData makeTypelessKey(const Row& r, const vector& keyCols, Pool { type = r.getColTypes()[keyCols[i]]; - if (r.isCharType(keyCols[i])) + if (r.getColType(keyCols[i]) == CalpontSystemCatalog::LONGDOUBLE + && otherSideRG.getColType(otherKeyCols[i]) == CalpontSystemCatalog::LONGDOUBLE) + { + keylen += sizeof(long double); + } + else if (r.isCharType(keyCols[i])) keylen += r.getStringLength(keyCols[i]) + 1; else keylen += 8; @@ -838,17 +1146,66 @@ TypelessData makeTypelessKey(const Row& r, const vector& keyCols, Pool ret.data[off++] = 0; } + else if (type == CalpontSystemCatalog::LONGDOUBLE) + { + // Small side is a long double. Since CS can't store larger than DOUBLE, + // we need to convert to whatever type large side is -- double or int64 + long double keyld = r.getLongDoubleField(keyCols[i]); + switch (otherSideRG.getColType(otherKeyCols[i])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + if (keyld > MAX_DOUBLE || keyld < MIN_DOUBLE) + { + ret.len = 0; + return ret; + } + else + { + double d = (double)keyld; + *((int64_t*) &ret.data[off]) = *(int64_t*)&d; + off += 8; + } + break; + } + case CalpontSystemCatalog::LONGDOUBLE: + { + *((long double*) &ret.data[off]) = keyld; + off += sizeof(long double); + break; + } + default: + { + if (r.isUnsigned(keyCols[i]) && keyld > MAX_UBIGINT) + { + ret.len = 0; + return ret; + } + else if (keyld > MAX_BIGINT || keyld < MIN_BIGINT) + { + ret.len = 0; + return ret; + } + else + { + *((int64_t*) &ret.data[off]) = (int64_t)keyld; + off += 8; + } + break; + } + } + } + else if (r.isUnsigned(keyCols[i])) + { + *((uint64_t*)&ret.data[off]) = r.getUintField(keyCols[i]); + off += 8; + } else { - if (r.isUnsigned(keyCols[i])) - { - *((uint64_t*)&ret.data[off]) = r.getUintField(keyCols[i]); - } - else - { - *((int64_t*)&ret.data[off]) = r.getIntField(keyCols[i]); - } - + *((int64_t*)&ret.data[off]) = r.getIntField(keyCols[i]); off += 8; } } @@ -881,25 +1238,29 @@ uint64_t getHashOfTypelessKey(const Row& r, const vector& keyCols, uin ret = hasher((const char*) str, len, ret); /* for (uint32_t j = 0; j < width && str[j] != 0; j++) - ret.data[off++] = str[j]; + ret.data[off++] = str[j]; */ ret = hasher(&nullChar, 1, ret); width += len + 1; } + else if (r.getColType(keyCols[i]) == CalpontSystemCatalog::LONGDOUBLE) + { + long double tmp = r.getLongDoubleField(keyCols[i]); + ret = hasher((char*) &tmp, sizeof(long double), ret); + width += sizeof(long double); + } + else + if (r.isUnsigned(keyCols[i])) + { + tmp = r.getUintField(keyCols[i]); + ret = hasher((char*) &tmp, 8, ret); + width += 8; + } else { + tmp = r.getIntField(keyCols[i]); + ret = hasher((char*) &tmp, 8, ret); width += 8; - - if (r.isUnsigned(keyCols[i])) - { - tmp = r.getUintField(keyCols[i]); - ret = hasher((char*) &tmp, 8, ret); - } - else - { - tmp = r.getIntField(keyCols[i]); - ret = hasher((char*) &tmp, 8, ret); - } } } diff --git a/utils/joiner/tuplejoiner.h b/utils/joiner/tuplejoiner.h index 0391e7cdf..7302876e0 100644 --- a/utils/joiner/tuplejoiner.h +++ b/utils/joiner/tuplejoiner.h @@ -1,4 +1,5 @@ /* 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 @@ -78,14 +79,30 @@ inline bool TypelessData::operator==(const TypelessData& t) const return (memcmp(data, t.data, len) == 0); } +// Comparator for long double in the hash +class LongDoubleEq +{ +public: + LongDoubleEq(){}; + inline bool operator()(const long double& pos1, const long double& pos2) const + { + return pos1 == pos2; + } +}; + /* This function makes the keys for string & compound joins. The length of the * key is limited by keylen. Keys that are longer are assigned a length of 0 on return, * signifying that it shouldn't match anything. */ extern TypelessData makeTypelessKey(const rowgroup::Row&, const std::vector&, uint32_t keylen, utils::FixedAllocator* fa); +// MCOL-1822 SUM/AVG as long double: pass in RG and col so we can determine type conversion extern TypelessData makeTypelessKey(const rowgroup::Row&, - const std::vector&, utils::PoolAllocator* fa); + const std::vector&, uint32_t keylen, utils::FixedAllocator* fa, + const rowgroup::RowGroup&, const std::vector&); +extern TypelessData makeTypelessKey(const rowgroup::Row&, + const std::vector&, utils::PoolAllocator* fa, + const rowgroup::RowGroup&, const std::vector&); extern uint64_t getHashOfTypelessKey(const rowgroup::Row&, const std::vector&, uint32_t seed = 0); @@ -99,10 +116,26 @@ public: { return fHasher((char*) &val, 8); } + inline size_t operator()(uint64_t val) const + { + return fHasher((char*) &val, 8); + } inline size_t operator()(const TypelessData& e) const { return fHasher((char*) e.data, e.len); } + inline size_t operator()(long double val) const + { + if (sizeof(long double) == 8) // Probably just MSC, but you never know. + { + return fHasher((char*) &val, sizeof(long double)); + } + else + { + // For Linux x86_64, long double is stored in 128 bits, but only 80 are significant + return fHasher((char*) &val, 10); + } + } private: utils::Hasher fHasher; @@ -300,29 +333,24 @@ private: utils::STLPoolAllocator > > sthash_t; typedef std::tr1::unordered_multimap, utils::STLPoolAllocator > > typelesshash_t; + // MCOL-1822 Add support for Long Double AVG/SUM small side + typedef std::tr1::unordered_multimap > > ldhash_t; typedef hash_t::iterator iterator; typedef typelesshash_t::iterator thIterator; + typedef ldhash_t::iterator ldIterator; TupleJoiner(); TupleJoiner(const TupleJoiner&); TupleJoiner& operator=(const TupleJoiner&); - iterator begin() - { - return h->begin(); - } - iterator end() - { - return h->end(); - } - - rowgroup::RGData smallNullMemory; boost::scoped_ptr h; // used for UM joins on ints boost::scoped_ptr sth; // used for UM join on ints where the backing table uses a string table + boost::scoped_ptr ld; // used for UM join on long double std::vector rows; // used for PM join /* This struct is rough. The BPP-JL stores the parsed results for diff --git a/utils/messageqcpp/bytestream.cpp b/utils/messageqcpp/bytestream.cpp index ec471be8f..003c35fd4 100644 --- a/utils/messageqcpp/bytestream.cpp +++ b/utils/messageqcpp/bytestream.cpp @@ -1,6 +1,6 @@ /* - Copyright (c) 2017, MariaDB 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 @@ -636,6 +636,18 @@ ByteStream& ByteStream::operator<<(const double d) return *this; } +ByteStream& ByteStream::operator<<(const long double d) +{ + int sz = sizeof(long double); + + if (fBuf == 0 || (fCurInPtr - fBuf + sz > fMaxLen + ISSOverhead)) + growBuf(fMaxLen + BlockSize); + + *((long double*) fCurInPtr) = d; + fCurInPtr += sz; + + return *this; +} ByteStream& ByteStream::operator>>(float& f) { peek(f); @@ -648,6 +660,12 @@ ByteStream& ByteStream::operator>>(double& d) fCurOutPtr += sizeof(double); return *this; } +ByteStream& ByteStream::operator>>(long double& d) +{ + peek(d); + fCurOutPtr += sizeof(long double); + return *this; +} void ByteStream::peek(float& f) const { if (length() < sizeof(float)) @@ -663,6 +681,14 @@ void ByteStream::peek(double& d) const d = *((double*) fCurOutPtr); } +void ByteStream::peek(long double& d) const +{ + if (length() < sizeof(long double)) + throw underflow_error("ByteStream>int64_t: not enough data in stream to fill datatype"); + + d = *((long double*) fCurOutPtr); +} + }//namespace messageqcpp diff --git a/utils/messageqcpp/bytestream.h b/utils/messageqcpp/bytestream.h index f8453843e..cf3eb2057 100644 --- a/utils/messageqcpp/bytestream.h +++ b/utils/messageqcpp/bytestream.h @@ -1,6 +1,6 @@ /* - Copyright (c) 2017, MariaDB 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 @@ -153,6 +153,11 @@ public: * whatever the native byte order is. */ EXPORT ByteStream& operator<<(const double d); + /** + * push a long double onto the end of the stream. The byte + * order is whatever the native byte order is. + */ + EXPORT ByteStream& operator<<(const long double d); /** * push a std::string onto the end of the stream. */ @@ -212,6 +217,11 @@ public: * order is whatever the native byte order is. */ EXPORT ByteStream& operator>>(double& d); + /** + * extract a long double from the front of the stream. The byte + * order is whatever the native byte order is. + */ + EXPORT ByteStream& operator>>(long double& d); /** * extract a std::string from the front of the stream. */ @@ -277,6 +287,11 @@ public: * order is whatever the native byte order is. */ EXPORT void peek(double& f) const; + /** + * Peek at a long double from the front of the stream. The byte + * order is whatever the native byte order is. + */ + EXPORT void peek(long double& f) const; /** * Peek at a std::string from the front of the stream. */ diff --git a/utils/rowgroup/rowaggregation.cpp b/utils/rowgroup/rowaggregation.cpp index d6aa253a6..4bfbf87b6 100644 --- a/utils/rowgroup/rowaggregation.cpp +++ b/utils/rowgroup/rowaggregation.cpp @@ -1,6 +1,6 @@ /* - Copyright (c) 2017, MariaDB Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -203,6 +203,10 @@ inline float getFloatNullValue() return *y; } +inline long double getLongDoubleNullValue() +{ + return joblist::LONGDOUBLENULL; +} inline string getStringNullValue() { @@ -229,6 +233,7 @@ const static_any::any& RowAggregation::ulongTypeId((unsigned long)1); const static_any::any& RowAggregation::ullTypeId((unsigned long long)1); const static_any::any& RowAggregation::floatTypeId((float)1); const static_any::any& RowAggregation::doubleTypeId((double)1); +const static_any::any& RowAggregation::longdoubleTypeId((long double)1); const static_any::any& RowAggregation::strTypeId(typeStr); KeyStorage::KeyStorage(const RowGroup& keys, Row** tRow) : tmpRow(tRow), rg(keys) @@ -357,6 +362,15 @@ inline void RowAggregation::updateDoubleMinMax(double val1, double val2, int64_t } +inline void RowAggregation::updateLongDoubleMinMax(long double val1, long double val2, int64_t col, int func) +{ + if (isNull(fRowGroupOut, fRow, col)) + fRow.setLongDoubleField(val1, col); + else if (minMax(val1, val2, func)) + fRow.setLongDoubleField(val1, col); +} + + inline void RowAggregation::updateFloatMinMax(float val1, float val2, int64_t col, int func) { if (isNull(fRowGroupOut, fRow, col)) @@ -396,124 +410,6 @@ void RowAggregation::updateStringMinMax(string val1, string val2, int64_t col, i #endif } - -inline void RowAggregation::updateIntSum(int64_t val1, int64_t val2, int64_t col) -{ - if (isNull(fRowGroupOut, fRow, col)) - { - fRow.setIntField(val1, col); - } - else - { -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - - if (((val2 >= 0) && ((numeric_limits::max() - val2) >= val1)) || - ((val2 < 0) && ((numeric_limits::min() - val2) <= val1))) - fRow.setIntField(val1 + val2, col); - -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - - if (fRow.getColTypes()[col] != execplan::CalpontSystemCatalog::DOUBLE && - fRow.getColTypes()[col] != execplan::CalpontSystemCatalog::UDOUBLE) - { - if (((val2 >= 0) && ((numeric_limits::max() - val2) >= val1)) || - ((val2 < 0) && ((numeric_limits::min() - val2) <= val1))) - { - fRow.setIntField(val1 + val2, col); - } - else - { - execplan::CalpontSystemCatalog::ColDataType* cdtp = fRow.getColTypes(); - cdtp += col; - *cdtp = execplan::CalpontSystemCatalog::DOUBLE; - updateDoubleSum((double)val1, (double)val2, col); - } - } - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - else - { -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - ostringstream oss; - oss << overflowMsg << ": " << val2 << "+" << val1; - - if (val2 > 0) - oss << " > " << numeric_limits::max(); - else - oss << " < " << numeric_limits::min(); - - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - double* dp2 = (double*)&val2; - updateDoubleSum((double)val1, *dp2, col); -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - } - } -} - -inline void RowAggregation::updateUintSum(uint64_t val1, uint64_t val2, int64_t col) -{ - if (isNull(fRowGroupOut, fRow, col)) - { - fRow.setUintField(val1, col); - } - else - { -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - - if ((numeric_limits::max() - val2) >= val1) - fRow.setUintField(val1 + val2, col); - else - { - ostringstream oss; - oss << overflowMsg << ": " << val2 << "+" << val1 << " > " << numeric_limits::max(); - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); - } - -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - - if (fRow.getColTypes()[col] != execplan::CalpontSystemCatalog::DOUBLE && - fRow.getColTypes()[col] != execplan::CalpontSystemCatalog::UDOUBLE) - { - if ((numeric_limits::max() - val2) >= val1) - { - fRow.setUintField(val1 + val2, col); - } - else - { - execplan::CalpontSystemCatalog::ColDataType* cdtp = fRow.getColTypes(); - cdtp += col; - *cdtp = execplan::CalpontSystemCatalog::DOUBLE; - updateDoubleSum((double)val1, (double)val2, col); - } - } - else - { - double* dp2 = (double*)&val2; - updateDoubleSum((double)val1, *dp2, col); - } - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - } -} - -inline void RowAggregation::updateDoubleSum(double val1, double val2, int64_t col) -{ - if (isNull(fRowGroupOut, fRow, col)) - fRow.setDoubleField(val1, col); - else - fRow.setDoubleField(val1 + val2, col); -} - - -inline void RowAggregation::updateFloatSum(float val1, float val2, int64_t col) -{ - if (isNull(fRowGroupOut, fRow, col)) - fRow.setFloatField(val1, col); - else - fRow.setFloatField(val1 + val2, col); -} - //------------------------------------------------------------------------------ // Verify if the column value is NULL // row(in) - Row to be included in aggregation. @@ -598,6 +494,12 @@ inline bool RowAggregation::isNull(const RowGroup* pRowGroup, const Row& row, in break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + ret = (row.getLongDoubleField(col) == joblist::LONGDOUBLENULL); + break; + } + case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::INT: { @@ -1134,6 +1036,12 @@ void RowAggregation::initMapData(const Row& rowIn) break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + fRow.setLongDoubleField(rowIn.getLongDoubleField(colIn), colOut); + break; + } + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -1265,6 +1173,12 @@ void RowAggregation::makeAggFieldsNull(Row& row) break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + row.setLongDoubleField(getLongDoubleNullValue(), colOut); + break; + } + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -1290,7 +1204,7 @@ void RowAggregation::makeAggFieldsNull(Row& row) //------------------------------------------------------------------------------ -// Update the min/max/sum fields if input is not null. +// Update the min/max fields if input is not null. // rowIn(in) - Row to be included in aggregation. // colIn(in) - column in the input row group // colOut(in) - column in the output row group @@ -1298,7 +1212,7 @@ void RowAggregation::makeAggFieldsNull(Row& row) // Note: NULL value check must be done on UM & PM // UM may receive NULL values, too. //------------------------------------------------------------------------------ -void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut, int funcType) +void RowAggregation::doMinMax(const Row& rowIn, int64_t colIn, int64_t colOut, int funcType) { int colDataType = (fRowGroupIn.getColTypes())[colIn]; @@ -1317,12 +1231,7 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut { int64_t valIn = rowIn.getIntField(colIn); int64_t valOut = fRow.getIntField(colOut); - - if (funcType == ROWAGG_SUM || funcType == ROWAGG_DISTINCT_SUM) - updateIntSum(valIn, valOut, colOut); - else - updateIntMinMax(valIn, valOut, colOut, funcType); - + updateIntMinMax(valIn, valOut, colOut, funcType); break; } @@ -1334,12 +1243,7 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut { uint64_t valIn = rowIn.getUintField(colIn); uint64_t valOut = fRow.getUintField(colOut); - - if (funcType == ROWAGG_SUM || funcType == ROWAGG_DISTINCT_SUM) - updateUintSum(valIn, valOut, colOut); - else - updateUintMinMax(valIn, valOut, colOut, funcType); - + updateUintMinMax(valIn, valOut, colOut, funcType); break; } @@ -1347,16 +1251,7 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::TEXT: { - if (funcType == ROWAGG_SUM) - { - std::ostringstream errmsg; - errmsg << "RowAggregation: sum(CHAR[]) is not supported."; - cerr << errmsg.str() << endl; - throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr); - } - int colWidth = fRowGroupIn.getColumnWidth(colIn); - if (colWidth <= 8) { uint64_t valIn = rowIn.getUintField(colIn); @@ -1369,7 +1264,6 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut string valOut = fRow.getStringField(colOut); updateStringMinMax(valIn, valOut, colOut, funcType); } - break; } @@ -1378,12 +1272,7 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut { double valIn = rowIn.getDoubleField(colIn); double valOut = fRow.getDoubleField(colOut); - - if (funcType == ROWAGG_SUM) - updateDoubleSum(valIn, valOut, colOut); - else - updateDoubleMinMax(valIn, valOut, colOut, funcType); - + updateDoubleMinMax(valIn, valOut, colOut, funcType); break; } @@ -1392,12 +1281,7 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut { float valIn = rowIn.getFloatField(colIn); float valOut = fRow.getFloatField(colOut); - - if (funcType == ROWAGG_SUM) - updateFloatSum(valIn, valOut, colOut); - else - updateFloatMinMax(valIn, valOut, colOut, funcType); - + updateFloatMinMax(valIn, valOut, colOut, funcType); break; } @@ -1405,20 +1289,20 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut case execplan::CalpontSystemCatalog::DATETIME: case execplan::CalpontSystemCatalog::TIME: { - if (funcType == ROWAGG_SUM) - { - std::ostringstream errmsg; - errmsg << "RowAggregation: sum(date|date time) is not supported."; - cerr << errmsg.str() << endl; - throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr); - } - uint64_t valIn = rowIn.getUintField(colIn); uint64_t valOut = fRow.getUintField(colOut); updateUintMinMax(valIn, valOut, colOut, funcType); break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double valIn = rowIn.getLongDoubleField(colIn); + long double valOut = fRow.getLongDoubleField(colOut); + updateLongDoubleMinMax(valIn, valOut, colOut, funcType); + break; + } + default: { break; @@ -1426,6 +1310,113 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut } } +//------------------------------------------------------------------------------ +// Update the sum fields if input is not null. +// rowIn(in) - Row to be included in aggregation. +// colIn(in) - column in the input row group +// colOut(in) - column in the output row group +// funcType(in) - aggregation function type +// Note: NULL value check must be done on UM & PM +// UM may receive NULL values, too. +//------------------------------------------------------------------------------ +void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int funcType) +{ + int colDataType = (fRowGroupIn.getColTypes())[colIn]; + long double valIn = 0; + long double valOut = fRow.getLongDoubleField(colOut); + if (isNull(&fRowGroupIn, rowIn, colIn) == true) + return; + + switch (colDataType) + { + case execplan::CalpontSystemCatalog::TINYINT: + case execplan::CalpontSystemCatalog::SMALLINT: + case execplan::CalpontSystemCatalog::MEDINT: + case execplan::CalpontSystemCatalog::INT: + case execplan::CalpontSystemCatalog::BIGINT: + { + valIn = rowIn.getIntField(colIn); + break; + } + + case execplan::CalpontSystemCatalog::UTINYINT: + case execplan::CalpontSystemCatalog::USMALLINT: + case execplan::CalpontSystemCatalog::UMEDINT: + case execplan::CalpontSystemCatalog::UINT: + case execplan::CalpontSystemCatalog::UBIGINT: + { + valIn = rowIn.getUintField(colIn); + break; + } + + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::UDECIMAL: + { + valIn = rowIn.getIntField(colIn); + double scale = (double)(fRowGroupIn.getScale())[colIn]; + if (valIn != 0 && scale > 0) + { + valIn /= pow(10.0, scale); + } + break; + } + + case execplan::CalpontSystemCatalog::CHAR: + case execplan::CalpontSystemCatalog::VARCHAR: + case execplan::CalpontSystemCatalog::TEXT: + { + std::ostringstream errmsg; + errmsg << "RowAggregation: sum(CHAR[]) is not supported."; + cerr << errmsg.str() << endl; + throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr); + break; + } + + case execplan::CalpontSystemCatalog::DOUBLE: + case execplan::CalpontSystemCatalog::UDOUBLE: + { + valIn = rowIn.getDoubleField(colIn); + break; + } + + case execplan::CalpontSystemCatalog::FLOAT: + case execplan::CalpontSystemCatalog::UFLOAT: + { + valIn = rowIn.getFloatField(colIn); + break; + } + + case execplan::CalpontSystemCatalog::DATE: + case execplan::CalpontSystemCatalog::DATETIME: + case execplan::CalpontSystemCatalog::TIME: + { + std::ostringstream errmsg; + errmsg << "RowAggregation: sum(date|date time) is not supported."; + cerr << errmsg.str() << endl; + throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr); + break; + } + + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + valIn = rowIn.getLongDoubleField(colIn); + break; + } + + default: + { + break; + } + } + if (isNull(fRowGroupOut, fRow, colOut)) + { + fRow.setLongDoubleField(valIn, colOut); + } + else + { + fRow.setLongDoubleField(valIn+valOut, colOut); + } +} //------------------------------------------------------------------------------ // Update the and/or/xor fields if input is not null. @@ -1507,12 +1498,15 @@ void RowAggregation::doBitOp(const Row& rowIn, int64_t colIn, int64_t colOut, in case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UDOUBLE: case execplan::CalpontSystemCatalog::UFLOAT: + case execplan::CalpontSystemCatalog::LONGDOUBLE: { double dbl = 0.0; if (colDataType == execplan::CalpontSystemCatalog::DOUBLE || colDataType == execplan::CalpontSystemCatalog::UDOUBLE) dbl = rowIn.getDoubleField(colIn); + else if (colDataType == execplan::CalpontSystemCatalog::LONGDOUBLE) + dbl = (double)rowIn.getLongDoubleField(colIn); else dbl = rowIn.getFloatField(colIn); @@ -1684,13 +1678,16 @@ void RowAggregation::updateEntry(const Row& rowIn) if (isNull(&fRowGroupIn, rowIn, colIn) == true) break; case ROWAGG_COUNT_ASTERISK: - fRow.setIntField<8>(fRow.getIntField<8>(colOut) + 1, colOut); + fRow.setUintField<8>(fRow.getUintField<8>(colOut) + 1, colOut); break; case ROWAGG_MIN: case ROWAGG_MAX: + doMinMax(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + break; + case ROWAGG_SUM: - doMinMaxSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + doSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); break; case ROWAGG_AVG: @@ -1749,11 +1746,13 @@ void RowAggregation::updateEntry(const Row& rowIn) //------------------------------------------------------------------------------ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int64_t colAux) { - int colDataType = (fRowGroupIn.getColTypes())[colIn]; - if (isNull(&fRowGroupIn, rowIn, colIn) == true) return; + int colDataType = (fRowGroupIn.getColTypes())[colIn]; + long double valIn = 0; + long double valOut = fRow.getLongDoubleField(colOut); + switch (colDataType) { case execplan::CalpontSystemCatalog::TINYINT: @@ -1761,70 +1760,9 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6 case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::INT: case execplan::CalpontSystemCatalog::BIGINT: - case execplan::CalpontSystemCatalog::DECIMAL: - case execplan::CalpontSystemCatalog::UDECIMAL: { - int64_t valIn = rowIn.getIntField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setIntField(valIn, colOut); - fRow.setIntField(1, colAux); - } - else - { - int64_t valOut = fRow.getIntField(colOut); -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - - if (((valOut >= 0) && ((numeric_limits::max() - valOut) >= valIn)) || - ((valOut < 0) && ((numeric_limits::min() - valOut) <= valIn))) - fRow.setIntField(valIn + valOut, colOut); - -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - - if (fRow.getColTypes()[colOut] != execplan::CalpontSystemCatalog::DOUBLE) - { - if (((valOut >= 0) && ((numeric_limits::max() - valOut) >= valIn)) || - ((valOut < 0) && ((numeric_limits::min() - valOut) <= valIn))) - { - fRow.setIntField(valIn + valOut, colOut); - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); - } - else - { - execplan::CalpontSystemCatalog::ColDataType* cdtp = fRow.getColTypes(); - cdtp += colOut; - *cdtp = execplan::CalpontSystemCatalog::DOUBLE; - fRow.setDoubleField((double)valIn + (double)valOut, colOut); - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); - } - } - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - else -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - { - ostringstream oss; - oss << overflowMsg << ": " << valOut << "+" << valIn; - - if (valOut > 0) - oss << " > " << numeric_limits::max(); - else - oss << " < " << numeric_limits::min(); - - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); - } - - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - { - double* dp = (double*)&valOut; - fRow.setDoubleField((double)valIn + *dp, colOut); - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); - } -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - } - + valIn = rowIn.getIntField(colIn); + break; break; } @@ -1834,98 +1772,39 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6 case execplan::CalpontSystemCatalog::UINT: case execplan::CalpontSystemCatalog::UBIGINT: { - uint64_t valIn = rowIn.getUintField(colIn); + valIn = rowIn.getUintField(colIn); + break; + } - if (fRow.getUintField(colAux) == 0) + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::UDECIMAL: + { + valIn = rowIn.getIntField(colIn); + double scale = (double)(fRowGroupIn.getScale())[colIn]; + if (valIn != 0 && scale > 0) { - fRow.setUintField(valIn, colOut); - fRow.setUintField(1, colAux); + valIn /= pow(10.0, scale); } - else - { - uint64_t valOut = fRow.getUintField(colOut); -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - - if ((numeric_limits::max() - valOut) >= valIn) - { - fRow.setUintField(valIn + valOut, colOut); - fRow.setUintField(fRow.getUintField(colAux) + 1, colAux); - } - else - { - ostringstream oss; - oss << overflowMsg << ": " << valOut << "+" << valIn << " > " << numeric_limits::max(); - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); - } - -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - - if (fRow.getColTypes()[colOut] != execplan::CalpontSystemCatalog::DOUBLE) - { - if ((numeric_limits::max() - valOut) >= valIn) - { - fRow.setUintField(valIn + valOut, colOut); - fRow.setUintField(fRow.getUintField(colAux) + 1, colAux); - } - else - { - execplan::CalpontSystemCatalog::ColDataType* cdtp = fRow.getColTypes(); - cdtp += colOut; - *cdtp = execplan::CalpontSystemCatalog::DOUBLE; - fRow.setDoubleField((double)valIn + (double)valOut, colOut); - fRow.setUintField(fRow.getUintField(colAux) + 1, colAux); - } - } - else - { - double* dp = (double*)&valOut; - fRow.setDoubleField((double)valIn + *dp, colOut); - fRow.setUintField(fRow.getUintField(colAux) + 1, colAux); - } - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - } - break; } case execplan::CalpontSystemCatalog::DOUBLE: case execplan::CalpontSystemCatalog::UDOUBLE: { - double valIn = rowIn.getDoubleField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setDoubleField(valIn, colOut); - fRow.setIntField(1, colAux); - } - else - { - double valOut = fRow.getDoubleField(colOut); - fRow.setDoubleField(valIn + valOut, colOut); - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); - } - + valIn = rowIn.getDoubleField(colIn); break; } case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { - float valIn = rowIn.getFloatField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setFloatField(valIn, colOut); - fRow.setIntField(1, colAux); - } - else - { - float valOut = fRow.getFloatField(colOut); - fRow.setFloatField(valIn + valOut, colOut); - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); - } + valIn = rowIn.getFloatField(colIn); + break; + } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + valIn = rowIn.getLongDoubleField(colIn); break; } @@ -1938,6 +1817,18 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6 break; } } + + if (fRow.getUintField(colAux) == 0) + { + // This is the first value + fRow.setLongDoubleField(valIn, colOut); + fRow.setUintField(1, colAux); + } + else + { + fRow.setLongDoubleField(valIn + valOut, colOut); + fRow.setUintField(fRow.getUintField(colAux) + 1, colAux); + } } @@ -1988,6 +1879,10 @@ void RowAggregation::doStatistics(const Row& rowIn, int64_t colIn, int64_t colOu valIn = (long double) rowIn.getFloatField(colIn); break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + valIn = rowIn.getLongDoubleField(colIn); + break; + default: std::ostringstream errmsg; errmsg << "RowAggregation: no average for data type: " << colDataType; @@ -2137,6 +2032,22 @@ void RowAggregation::doUDAF(const Row& rowIn, int64_t colIn, int64_t colOut, break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + datum.dataType = execplan::CalpontSystemCatalog::LONGDOUBLE; + + if (cc) + { + datum.columnData = cc->getLongDoubleVal(const_cast(rowIn), bIsNull); + } + else + { + datum.columnData = rowIn.getLongDoubleField(colIn); + } + + break; + } + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -2509,13 +2420,16 @@ void RowAggregationUM::updateEntry(const Row& rowIn) if (isNull(&fRowGroupIn, rowIn, colIn) == true) break; case ROWAGG_COUNT_ASTERISK: - fRow.setIntField<8>(fRow.getIntField<8>(colOut) + 1, colOut); + fRow.setUintField<8>(fRow.getUintField<8>(colOut) + 1, colOut); break; case ROWAGG_MIN: case ROWAGG_MAX: + doMinMax(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + break; + case ROWAGG_SUM: - doMinMaxSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + doSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); break; case ROWAGG_AVG: @@ -2600,12 +2514,11 @@ void RowAggregationUM::calculateAvgColumns() { int64_t colOut = fFunctionCols[i]->fOutputColumnIndex; int64_t colAux = fFunctionCols[i]->fAuxColumnIndex; - int colDataType = (fRowGroupOut->getColTypes())[colOut]; - int scale = fRowGroupOut->getScale()[colOut]; - int scale1 = scale >> 8; - int scale2 = scale & 0x000000FF; - long double factor = pow(10.0, scale2 - scale1); +// int scale = fRowGroupOut->getScale()[colOut]; +// int scale1 = scale >> 8; +// int scale2 = scale & 0x000000FF; +// long double factor = pow(10.0, scale2 - scale1); for (uint64_t j = 0; j < fRowGroupOut->getRowCount(); j++) { @@ -2618,97 +2531,11 @@ void RowAggregationUM::calculateAvgColumns() long double sum = 0.0; long double avg = 0.0; - switch (colDataType) - { - case execplan::CalpontSystemCatalog::DOUBLE: - case execplan::CalpontSystemCatalog::UDOUBLE: - sum = fRow.getDoubleField(colOut); - avg = sum / cnt; - fRow.setDoubleField(avg, colOut); - break; - - case execplan::CalpontSystemCatalog::FLOAT: - case execplan::CalpontSystemCatalog::UFLOAT: - sum = fRow.getFloatField(colOut); - avg = sum / cnt; - fRow.setFloatField(avg, colOut); - break; - - case execplan::CalpontSystemCatalog::TINYINT: - case execplan::CalpontSystemCatalog::SMALLINT: - case execplan::CalpontSystemCatalog::MEDINT: - case execplan::CalpontSystemCatalog::INT: - case execplan::CalpontSystemCatalog::BIGINT: - case execplan::CalpontSystemCatalog::DECIMAL: - case execplan::CalpontSystemCatalog::UDECIMAL: - sum = static_cast(fRow.getIntField(colOut)); - avg = sum / cnt; - avg *= factor; - avg += (avg < 0) ? (-0.5) : (0.5); - - if (avg > (long double) numeric_limits::max() || - avg < (long double) numeric_limits::min()) -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - { - ostringstream oss; - oss << overflowMsg << ": " << avg << "(incl factor " << factor; - - if (avg > 0) - oss << ") > " << numeric_limits::max(); - else - oss << ") < " << numeric_limits::min(); - - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); - } - - fRow.setIntField((int64_t) avg, colOut); -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - { - sum = fRow.getDoubleField(colOut); - avg = sum / cnt; - avg += (avg < 0) ? (-0.5) : (0.5); - fRow.getColTypes()[colOut] = execplan::CalpontSystemCatalog::DOUBLE; - fRow.setDoubleField(avg, colOut); - } - else - fRow.setIntField((int64_t)avg, colOut); - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - break; - - case execplan::CalpontSystemCatalog::UTINYINT: - case execplan::CalpontSystemCatalog::USMALLINT: - case execplan::CalpontSystemCatalog::UMEDINT: - case execplan::CalpontSystemCatalog::UINT: - case execplan::CalpontSystemCatalog::UBIGINT: - sum = static_cast(fRow.getUintField(colOut)); - avg = sum / cnt; - avg *= factor; - avg += (avg < 0) ? (-0.5) : (0.5); - - if (avg > (long double) numeric_limits::max()) -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - { - ostringstream oss; - oss << overflowMsg << ": " << avg << "(incl factor " << factor << ") > " << numeric_limits::max(); - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); - } - - fRow.setUintField((uint64_t) avg, colOut); -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - { - sum = fRow.getDoubleField(colOut); - avg = sum / cnt; - avg += 0.5; - fRow.getColTypes()[colOut] = execplan::CalpontSystemCatalog::DOUBLE; - fRow.setDoubleField(avg, colOut); - } - else - fRow.setUintField((uint64_t)avg, colOut); - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - break; - } + // MCOL-1822 Always long double + sum = fRow.getLongDoubleField(colOut); + avg = sum / cnt; +// avg *= factor; + fRow.setLongDoubleField(avg, colOut); } } } @@ -2729,6 +2556,7 @@ void RowAggregationUM::SetUDAFValue(static_any::any& valOut, int64_t colOut) uint64_t uintOut = 0; float floatOut = 0.0; double doubleOut = 0.0; + long double longdoubleOut = 0.0; ostringstream oss; std::string strOut; @@ -2896,6 +2724,16 @@ void RowAggregationUM::SetUDAFValue(static_any::any& valOut, int64_t colOut) break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + if (valOut.compatible(doubleTypeId)) + { + longdoubleOut = valOut.cast(); + fRow.setLongDoubleField(longdoubleOut, colOut); + bSetSuccess = true; + } + + break; + default: { std::ostringstream errmsg; @@ -2919,10 +2757,12 @@ void RowAggregationUM::SetUDAFAnyValue(static_any::any& valOut, int64_t colOut) // that they didn't set in mcsv1_UDAF::init(), but this // handles whatever return type is given and casts // it to whatever they said to return. + // TODO: Save cpu cycles here. int64_t intOut = 0; uint64_t uintOut = 0; float floatOut = 0.0; double doubleOut = 0.0; + long double longdoubleOut = 0.0; ostringstream oss; std::string strOut; @@ -2996,12 +2836,24 @@ void RowAggregationUM::SetUDAFAnyValue(static_any::any& valOut, int64_t colOut) { floatOut = valOut.cast(); doubleOut = floatOut; + longdoubleOut = doubleOut; intOut = uintOut = floatOut; oss << floatOut; } else if (valOut.compatible(doubleTypeId)) { doubleOut = valOut.cast(); + longdoubleOut = doubleOut; + floatOut = (float)doubleOut; + uintOut = (uint64_t)doubleOut; + intOut = (int64_t)doubleOut; + oss << doubleOut; + } + + else if (valOut.compatible(longdoubleTypeId)) + { + longdoubleOut = valOut.cast(); + doubleOut = (double)longdoubleOut; floatOut = (float)doubleOut; uintOut = (uint64_t)doubleOut; intOut = (int64_t)doubleOut; @@ -3015,6 +2867,7 @@ void RowAggregationUM::SetUDAFAnyValue(static_any::any& valOut, int64_t colOut) intOut = atol(strOut.c_str()); uintOut = strtoul(strOut.c_str(), NULL, 10); doubleOut = strtod(strOut.c_str(), NULL); + longdoubleOut = strtold(strOut.c_str(), NULL); floatOut = (float)doubleOut; } else @@ -3094,6 +2947,10 @@ void RowAggregationUM::SetUDAFAnyValue(static_any::any& valOut, int64_t colOut) fRow.setVarBinaryField(strOut, colOut); break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + fRow.setLongDoubleField(longdoubleOut, colOut); + break; + default: { std::ostringstream errmsg; @@ -3394,6 +3251,13 @@ void RowAggregationUM::doNullConstantAggregate(const ConstantAggData& aggData, u fRow.setStringField("", colOut); } break; + + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + fRow.setLongDoubleField(getLongDoubleNullValue(), colOut); + } + break; + } } break; @@ -3401,7 +3265,7 @@ void RowAggregationUM::doNullConstantAggregate(const ConstantAggData& aggData, u case ROWAGG_COUNT_COL_NAME: case ROWAGG_COUNT_DISTINCT_COL_NAME: { - fRow.setIntField(0, colOut); + fRow.setUintField(0, colOut); } break; @@ -3548,6 +3412,12 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + fRow.setLongDoubleField(strtold(aggData.fConstValue.c_str(), 0), colOut); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -3650,6 +3520,13 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double dbl = strtold(aggData.fConstValue.c_str(), 0) * rowCnt; + fRow.setLongDoubleField(dbl, colOut); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -3712,6 +3589,12 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + fRow.setLongDoubleField(0.0, colOut); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -3746,13 +3629,13 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData case ROWAGG_COUNT_COL_NAME: { - fRow.setIntField(rowCnt, colOut); + fRow.setUintField(rowCnt, colOut); } break; case ROWAGG_COUNT_DISTINCT_COL_NAME: { - fRow.setIntField(1, colOut); + fRow.setUintField(1, colOut); } break; @@ -3839,6 +3722,12 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + datum.columnData = strtold(aggData.fConstValue.c_str(), 0); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -4065,15 +3954,18 @@ void RowAggregationUMP2::updateEntry(const Row& rowIn) case ROWAGG_COUNT_ASTERISK: case ROWAGG_COUNT_COL_NAME: { - int64_t count = fRow.getIntField<8>(colOut) + rowIn.getIntField<8>(colIn); - fRow.setIntField<8>(count, colOut); + uint64_t count = fRow.getUintField<8>(colOut) + rowIn.getUintField<8>(colIn); + fRow.setUintField<8>(count, colOut); break; } case ROWAGG_MIN: case ROWAGG_MAX: + doMinMax(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + break; + case ROWAGG_SUM: - doMinMaxSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + doSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); break; case ROWAGG_AVG: @@ -4142,11 +4034,13 @@ void RowAggregationUMP2::updateEntry(const Row& rowIn) //------------------------------------------------------------------------------ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int64_t colAux) { - int colDataType = (fRowGroupIn.getColTypes())[colIn]; - if (isNull(&fRowGroupIn, rowIn, colIn) == true) return; + int colDataType = (fRowGroupIn.getColTypes())[colIn]; + long double valIn = 0; + long double valOut = fRow.getLongDoubleField(colOut); + switch (colDataType) { case execplan::CalpontSystemCatalog::TINYINT: @@ -4154,23 +4048,8 @@ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::INT: case execplan::CalpontSystemCatalog::BIGINT: - case execplan::CalpontSystemCatalog::DECIMAL: - case execplan::CalpontSystemCatalog::UDECIMAL: { - int64_t valIn = rowIn.getIntField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setIntField(valIn, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1), colAux); - } - else - { - int64_t valOut = fRow.getIntField(colOut); - fRow.setIntField(valIn + valOut, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1) + fRow.getIntField(colAux), colAux); - } - + valIn = rowIn.getIntField(colIn); break; } @@ -4180,60 +4059,40 @@ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, case execplan::CalpontSystemCatalog::UINT: case execplan::CalpontSystemCatalog::UBIGINT: { - uint64_t valIn = rowIn.getUintField(colIn); + valIn = rowIn.getUintField(colIn); + break; + } - if (fRow.getUintField(colAux) == 0) + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::UDECIMAL: + { + valIn = rowIn.getIntField(colIn); + break; + double scale = (double)(fRowGroupIn.getScale())[colIn]; + if (valIn != 0 && scale > 0) { - fRow.setUintField(valIn, colOut); - fRow.setUintField(rowIn.getUintField(colIn + 1), colAux); + valIn /= pow(10.0, scale); } - else - { - uint64_t valOut = fRow.getUintField(colOut); - fRow.setUintField(valIn + valOut, colOut); - fRow.setUintField(rowIn.getUintField(colIn + 1) + fRow.getUintField(colAux), colAux); - } - break; } case execplan::CalpontSystemCatalog::DOUBLE: case execplan::CalpontSystemCatalog::UDOUBLE: { - double valIn = rowIn.getDoubleField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setDoubleField(valIn, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1), colAux); - } - else - { - double valOut = fRow.getDoubleField(colOut); - fRow.setDoubleField(valIn + valOut, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1) + fRow.getIntField(colAux), colAux); - } - + valIn = rowIn.getDoubleField(colIn); break; } case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { - float valIn = rowIn.getFloatField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setFloatField(valIn, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1), colAux); - } - else - { - float valOut = fRow.getFloatField(colOut); - fRow.setFloatField(valIn + valOut, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1) + fRow.getIntField(colAux), colAux); - } + valIn = rowIn.getFloatField(colIn); + break; + } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + valIn = rowIn.getLongDoubleField(colIn); break; } @@ -4246,8 +4105,19 @@ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, break; } } -} + int64_t cnt = fRow.getUintField(colAux); + if (cnt == 0) + { + fRow.setLongDoubleField(valIn, colOut); + fRow.setUintField(rowIn.getUintField(colIn + 1), colAux); + } + else + { + fRow.setLongDoubleField(valIn + valOut, colOut); + fRow.setUintField(rowIn.getUintField(colIn + 1) + cnt, colAux); + } +} //------------------------------------------------------------------------------ // Update the sum and count fields for stattistics if input is not null. @@ -4478,23 +4348,25 @@ void RowAggregationDistinct::updateEntry(const Row& rowIn) case ROWAGG_COUNT_ASTERISK: case ROWAGG_COUNT_COL_NAME: { - int64_t count = fRow.getIntField<8>(colOut) + rowIn.getIntField<8>(colIn); - fRow.setIntField<8>(count, colOut); + uint64_t count = fRow.getUintField<8>(colOut) + rowIn.getUintField<8>(colIn); + fRow.setUintField<8>(count, colOut); break; } case ROWAGG_COUNT_DISTINCT_COL_NAME: if (isNull(&fRowGroupIn, rowIn, colIn) != true) - fRow.setIntField<8>(fRow.getIntField<8>(colOut) + 1, colOut); + fRow.setUintField<8>(fRow.getUintField<8>(colOut) + 1, colOut); break; case ROWAGG_MIN: case ROWAGG_MAX: + doMinMax(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + break; + case ROWAGG_SUM: case ROWAGG_DISTINCT_SUM: - - doMinMaxSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + doSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); break; case ROWAGG_AVG: diff --git a/utils/rowgroup/rowaggregation.h b/utils/rowgroup/rowaggregation.h index e039d5c2a..4817ed476 100644 --- a/utils/rowgroup/rowaggregation.h +++ b/utils/rowgroup/rowaggregation.h @@ -1,6 +1,6 @@ /* - Copyright (c) 2017, MariaDB Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -612,14 +612,15 @@ protected: virtual void attachGroupConcatAg(); virtual void updateEntry(const Row& row); - virtual void doMinMaxSum(const Row&, int64_t, int64_t, int); + virtual void doMinMax(const Row&, int64_t, int64_t, int); + virtual void doSum(const Row&, int64_t, int64_t, int); virtual void doAvg(const Row&, int64_t, int64_t, int64_t); virtual void doStatistics(const Row&, int64_t, int64_t, int64_t); virtual void doBitOp(const Row&, int64_t, int64_t, int); virtual void doUDAF(const Row&, int64_t, int64_t, int64_t, uint64_t& funcColsIdx); virtual bool countSpecial(const RowGroup* pRG) { - fRow.setIntField<8>(fRow.getIntField<8>(0) + pRG->getRowCount(), 0); + fRow.setUintField<8>(fRow.getUintField<8>(0) + pRG->getRowCount(), 0); return true; } @@ -642,13 +643,9 @@ protected: inline void updateUintMinMax(uint64_t val1, uint64_t val2, int64_t col, int func); inline void updateCharMinMax(uint64_t val1, uint64_t val2, int64_t col, int func); inline void updateDoubleMinMax(double val1, double val2, int64_t col, int func); + inline void updateLongDoubleMinMax(long double val1, long double val2, int64_t col, int func); inline void updateFloatMinMax(float val1, float val2, int64_t col, int func); inline void updateStringMinMax(std::string val1, std::string val2, int64_t col, int func); - inline void updateIntSum(int64_t val1, int64_t val2, int64_t col); - inline void updateUintSum(uint64_t val1, uint64_t val2, int64_t col); - inline void updateDoubleSum(double val1, double val2, int64_t col); - inline void updateFloatSum(float val1, float val2, int64_t col); - std::vector fGroupByCols; std::vector fFunctionCols; RowAggMap_t* fAggMapPtr; @@ -711,6 +708,7 @@ protected: static const static_any::any& ullTypeId; static const static_any::any& floatTypeId; static const static_any::any& doubleTypeId; + static const static_any::any& longdoubleTypeId; static const static_any::any& strTypeId; }; diff --git a/utils/rowgroup/rowgroup.cpp b/utils/rowgroup/rowgroup.cpp index 3ecb4998f..b4ab56ff1 100644 --- a/utils/rowgroup/rowgroup.cpp +++ b/utils/rowgroup/rowgroup.cpp @@ -1,6 +1,6 @@ /* - Copyright (c) 2017, MariaDB Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -702,6 +702,9 @@ void Row::initToNull() *((uint64_t*) &data[offsets[i]]) = joblist::DOUBLENULL; break; + case CalpontSystemCatalog::LONGDOUBLE: + *((long double*) &data[offsets[i]]) = joblist::LONGDOUBLENULL; + case CalpontSystemCatalog::DATETIME: *((uint64_t*) &data[offsets[i]]) = joblist::DATETIMENULL; break; @@ -804,13 +807,6 @@ void Row::initToNull() *((uint64_t*) &data[offsets[i]]) = joblist::UBIGINTNULL; break; - case CalpontSystemCatalog::LONGDOUBLE: - { - // no NULL value for long double yet, this is a nan. - memset(&data[offsets[i]], 0xFF, getColumnWidth(i)); - break; - } - default: ostringstream os; os << "Row::initToNull(): got bad column type (" << types[i] << @@ -956,7 +952,7 @@ bool Row::isNullValue(uint32_t colIndex) const return (*((uint64_t*) &data[offsets[colIndex]]) == joblist::UBIGINTNULL); case CalpontSystemCatalog::LONGDOUBLE: - // return false; // no NULL value for long double yet + return (*((long double*) &data[offsets[colIndex]]) == joblist::LONGDOUBLENULL); break; default: diff --git a/utils/rowgroup/rowgroup.h b/utils/rowgroup/rowgroup.h index ca05360c2..27f0b98a4 100644 --- a/utils/rowgroup/rowgroup.h +++ b/utils/rowgroup/rowgroup.h @@ -1,6 +1,6 @@ /* - Copyright (c) 2017, MariaDB Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -330,6 +330,7 @@ public: template inline int64_t getIntField(uint32_t colIndex) const; inline int64_t getIntField(uint32_t colIndex) const; template inline bool equals(uint64_t val, uint32_t colIndex) const; + inline bool equals(long double val, uint32_t colIndex) const; inline bool equals(const std::string& val, uint32_t colIndex) const; inline double getDoubleField(uint32_t colIndex) const; @@ -616,6 +617,11 @@ inline bool Row::equals(uint64_t val, uint32_t colIndex) const } } +inline bool Row::equals(long double val, uint32_t colIndex) const +{ + return *((long double*) &data[offsets[colIndex]]) == val; +} + inline bool Row::equals(const std::string& val, uint32_t colIndex) const { if (inStringTable(colIndex)) @@ -1030,6 +1036,11 @@ inline void Row::setFloatField(float val, uint32_t colIndex) inline void Row::setLongDoubleField(long double val, uint32_t colIndex) { + if (sizeof(long double) == 16) + { + // zero out the unused portion as there may be garbage there. + *((uint64_t*)&val+1) &= 0x000000000000FFFFULL; + } *((long double*) &data[offsets[colIndex]]) = val; } diff --git a/utils/udfsdk/docs/README b/utils/udfsdk/docs/README new file mode 100644 index 000000000..3fa3f0f3c --- /dev/null +++ b/utils/udfsdk/docs/README @@ -0,0 +1,8 @@ +To Build PDF: + + +[root@me docs]# sphinx-build -b latex source build +[root@me docs]# cd build +[root@me docs]# make + +The UDAF.pdf file will be in the build directory \ No newline at end of file diff --git a/utils/udfsdk/docs/build/Makefile b/utils/udfsdk/docs/build/Makefile new file mode 100644 index 000000000..c561680ad --- /dev/null +++ b/utils/udfsdk/docs/build/Makefile @@ -0,0 +1,68 @@ +# Makefile for Sphinx LaTeX output + +ALLDOCS = $(basename $(wildcard *.tex)) +ALLPDF = $(addsuffix .pdf,$(ALLDOCS)) +ALLDVI = $(addsuffix .dvi,$(ALLDOCS)) +ALLXDV = +ALLPS = $(addsuffix .ps,$(ALLDOCS)) +ALLIMGS = $(wildcard *.png *.gif *.jpg *.jpeg) + +# Prefix for archive names +ARCHIVEPREFIX = +# Additional LaTeX options (passed via variables in latexmkrc/latexmkjarc file) +export LATEXOPTS = +# Additional latexmk options +LATEXMKOPTS = +# format: pdf or dvi (used only by archive targets) +FMT = pdf + +LATEX = latexmk -dvi +PDFLATEX = latexmk -pdf -dvi- -ps- + + +%.png %.gif %.jpg %.jpeg: FORCE_MAKE + extractbb '$@' + +%.dvi: %.tex FORCE_MAKE + $(LATEX) $(LATEXMKOPTS) '$<' + +%.ps: %.dvi + dvips '$<' + +%.pdf: %.tex FORCE_MAKE + $(PDFLATEX) $(LATEXMKOPTS) '$<' + +all: $(ALLPDF) + +all-dvi: $(ALLDVI) + +all-ps: $(ALLPS) + +all-pdf: $(ALLPDF) + +zip: all-$(FMT) + mkdir $(ARCHIVEPREFIX)docs-$(FMT) + cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT) + zip -q -r -9 $(ARCHIVEPREFIX)docs-$(FMT).zip $(ARCHIVEPREFIX)docs-$(FMT) + rm -r $(ARCHIVEPREFIX)docs-$(FMT) + +tar: all-$(FMT) + mkdir $(ARCHIVEPREFIX)docs-$(FMT) + cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT) + tar cf $(ARCHIVEPREFIX)docs-$(FMT).tar $(ARCHIVEPREFIX)docs-$(FMT) + rm -r $(ARCHIVEPREFIX)docs-$(FMT) + +gz: tar + gzip -9 < $(ARCHIVEPREFIX)docs-$(FMT).tar > $(ARCHIVEPREFIX)docs-$(FMT).tar.gz + +bz2: tar + bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar + +xz: tar + xz -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar + +clean: + rm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ps *.tar *.tar.gz *.tar.bz2 *.tar.xz $(ALLPDF) $(ALLDVI) $(ALLXDV) *.fls *.fdb_latexmk + +.PHONY: all all-pdf all-dvi all-ps clean zip tar gz bz2 xz +.PHONY: FORCE_MAKE \ No newline at end of file diff --git a/utils/udfsdk/docs/build/latex/UDAF.pdf b/utils/udfsdk/docs/build/UDAF.pdf similarity index 51% rename from utils/udfsdk/docs/build/latex/UDAF.pdf rename to utils/udfsdk/docs/build/UDAF.pdf index eb5011f33..780d4024c 100644 Binary files a/utils/udfsdk/docs/build/latex/UDAF.pdf and b/utils/udfsdk/docs/build/UDAF.pdf differ diff --git a/utils/udfsdk/docs/source/changelog.rst b/utils/udfsdk/docs/source/changelog.rst index 1a7c749f9..84688fad8 100644 --- a/utils/udfsdk/docs/source/changelog.rst +++ b/utils/udfsdk/docs/source/changelog.rst @@ -5,5 +5,6 @@ Version History | Version | Date | Changes | +=========+============+=============================+ | 1.1.0α | 2017-08-25 | - First alpha release | ++---------+------------+-----------------------------+ | 1.2.0α | 2016-05-18 | - Add multi parm support | +---------+------------+-----------------------------+ diff --git a/utils/udfsdk/docs/source/conf.py b/utils/udfsdk/docs/source/conf.py index 3bd11a000..9e86ebc84 100644 --- a/utils/udfsdk/docs/source/conf.py +++ b/utils/udfsdk/docs/source/conf.py @@ -49,7 +49,7 @@ master_doc = 'index' # General information about the project. project = u'UDAF' -copyright = u'2017, MariaDB Corporation' +copyright = u'2019, MariaDB Corporation' author = u'MariaDB Corporation' # The version info for the project you're documenting, acts as replacement for @@ -57,9 +57,9 @@ author = u'MariaDB Corporation' # built documents. # # The short X.Y version. -version = u'1.1' +version = u'1.2' # The full version, including alpha/beta/rc tags. -release = u'1.1' +release = u'1.2' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/utils/udfsdk/docs/source/reference/UDAFMap.rst b/utils/udfsdk/docs/source/reference/UDAFMap.rst index d3cda63f4..7c3b7c7c5 100644 --- a/utils/udfsdk/docs/source/reference/UDAFMap.rst +++ b/utils/udfsdk/docs/source/reference/UDAFMap.rst @@ -34,3 +34,24 @@ The UDAFMap is where we tell the system about our function. For Columnstore 1.2, return fm; } +An alternative method added for 1.2 is to put the following in your .cpp file. +replace "median" with the name of your function: + +:: + + class Add_median_ToUDAFMap + { + public: + Add_median_ToUDAFMap() + { + UDAFMap::getMap()["median"] = new median(); + } + }; + + static Add_median_ToUDAFMap addToMap; + +This defines an object whose constructor adds the entry to the UDAFMap. The +static declaration instatiates an object at runtime, thus adding the entry +at startup. + + diff --git a/utils/udfsdk/docs/source/usage/memoryallocation.rst b/utils/udfsdk/docs/source/usage/memoryallocation.rst index 1ca5f74a5..6c62f9e25 100644 --- a/utils/udfsdk/docs/source/usage/memoryallocation.rst +++ b/utils/udfsdk/docs/source/usage/memoryallocation.rst @@ -77,7 +77,7 @@ The serialize method leverages Columnstore's :ref:`ByteStream ` clas For MEDIAN, serialize() iterates over the set and streams the values to the :ref:`ByteStream ` and unserialze unstreams them back into the set: .. literalinclude:: ../../../median.cpp - :lines: 290-305 + :lines: 194-208 :language: cpp .. rubric:: createUserData() @@ -93,6 +93,6 @@ This function may be called many times from different modules. Do not expect you The implementation of the createUserData() method() in MEDIAN: .. literalinclude:: ../../../median.cpp - :lines: 283-288 + :lines: 187-192 :language: cpp diff --git a/utils/udfsdk/docs/source/usage/sourcefile.rst b/utils/udfsdk/docs/source/usage/sourcefile.rst old mode 100755 new mode 100644 diff --git a/utils/udfsdk/udfsdk.cpp b/utils/udfsdk/udfsdk.cpp index 9a8973232..f8885a977 100644 --- a/utils/udfsdk/udfsdk.cpp +++ b/utils/udfsdk/udfsdk.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -201,6 +201,14 @@ double MCS_add::getDoubleVal(Row& row, return 0; } +long double MCS_add::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + return getDoubleVal(row, parm, isNull, op_ct); +} + float MCS_add::getFloatVal(Row& row, FunctionParm& parm, bool& isNull, @@ -349,6 +357,14 @@ double MCS_isnull::getDoubleVal(Row& row, return (getBoolVal(row, parm, isNull, op_ct) ? 1 : 0); } +long double MCS_isnull::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + return (getBoolVal(row, parm, isNull, op_ct) ? 1 : 0); +} + float MCS_isnull::getFloatVal(Row& row, FunctionParm& parm, bool& isNull, diff --git a/utils/udfsdk/udfsdk.h b/utils/udfsdk/udfsdk.h index 2160d552b..4587d067d 100644 --- a/utils/udfsdk/udfsdk.h +++ b/utils/udfsdk/udfsdk.h @@ -1,5 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. - Copyright (C) 2016 MariaDB Corporaton + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -170,6 +170,14 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + /** + * Returns a long double result of this function. + */ + + virtual long double getLongDoubleVal(rowgroup::Row& row, + funcexp::FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); /** * Returns a float result of this function. */ @@ -266,6 +274,14 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + /** + * Returns a double result of this function. + */ + virtual long double getLongDoubleVal(rowgroup::Row& row, + funcexp::FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + /** * Returns a float result of this function. */ diff --git a/utils/windowfunction/frameboundrange.cpp b/utils/windowfunction/frameboundrange.cpp index cdb65f5f9..21323f823 100644 --- a/utils/windowfunction/frameboundrange.cpp +++ b/utils/windowfunction/frameboundrange.cpp @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -313,6 +314,20 @@ void FrameBoundExpressionRange::validate() break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double tmp = this->fRow.getLongDoubleField(this->fIndex[1]); + this->fIsZero = (tmp == 0.0); + + if (tmp < 0) + { + invalid = true; + oss << tmp; + } + + break; + } + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { diff --git a/utils/windowfunction/idborderby.cpp b/utils/windowfunction/idborderby.cpp index db5cdf1c1..0cc39017c 100644 --- a/utils/windowfunction/idborderby.cpp +++ b/utils/windowfunction/idborderby.cpp @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (C) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -19,7 +20,6 @@ #include -//#define NDEBUG #include #include #include @@ -174,7 +174,6 @@ int DoubleCompare::operator()(IdbCompare* l, Row::Pointer r1, Row::Pointer r2) return ret; } - int FloatCompare::operator()(IdbCompare* l, Row::Pointer r1, Row::Pointer r2) { l->row1().setData(r1); @@ -206,6 +205,37 @@ int FloatCompare::operator()(IdbCompare* l, Row::Pointer r1, Row::Pointer r2) return ret; } +int LongDoubleCompare::operator()(IdbCompare* l, Row::Pointer r1, Row::Pointer r2) +{ + l->row1().setData(r1); + l->row2().setData(r2); + + bool b1 = l->row1().isNullValue(fSpec.fIndex); + bool b2 = l->row2().isNullValue(fSpec.fIndex); + + int ret = 0; + + if (b1 == true || b2 == true) + { + if (b1 == false && b2 == true) + ret = fSpec.fNf; + else if (b1 == true && b2 == false) + ret = -fSpec.fNf; + } + else + { + long double v1 = l->row1().getLongDoubleField(fSpec.fIndex); + long double v2 = l->row2().getLongDoubleField(fSpec.fIndex); + + if (v1 > v2) + ret = fSpec.fAsc; + else if (v1 < v2) + ret = -fSpec.fAsc; + } + + return ret; +} + bool CompareRule::less(Row::Pointer r1, Row::Pointer r2) { @@ -279,6 +309,13 @@ void CompareRule::compileRules(const std::vector& spec, const rowgr break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + Compare* c = new LongDoubleCompare(*i); + fCompares.push_back(c); + break; + } + case CalpontSystemCatalog::DATE: case CalpontSystemCatalog::DATETIME: case CalpontSystemCatalog::TIME: @@ -442,6 +479,12 @@ bool EqualCompData::operator()(Row::Pointer a, Row::Pointer b) break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + eq = (fRow1.getLongDoubleField(*i) == fRow2.getLongDoubleField(*i)); + break; + } + default: { eq = false; @@ -463,7 +506,6 @@ uint64_t IdbOrderBy::Hasher::operator()(const Row::Pointer& p) const row.setPointer(p); // MCOL-1829 Row::h uses colcount as an array idx down a callstack. uint64_t ret = row.hash(); - //cout << "hash(): returning " << ret << " for row: " << row.toString() << endl; return ret; } @@ -472,11 +514,8 @@ bool IdbOrderBy::Eq::operator()(const Row::Pointer& d1, const Row::Pointer& d2) Row& r1 = ts->row1, &r2 = ts->row2; r1.setPointer(d1); r2.setPointer(d2); - // MCOL-1829 Row::equals uses 2nd argument as container size boundary - // so it must be column count - 1. - bool ret = r1.equals(r2, colCount - 1); - //cout << "equals(): returning " << (int) ret << " for r1: " << r1.toString() << " r2: " << r2.toString() - // << endl; + // MCOL-1829 Row::equals uses 2nd argument as key columns container size boundary + bool ret = r1.equals(r2, colCount); return ret; } diff --git a/utils/windowfunction/idborderby.h b/utils/windowfunction/idborderby.h index a432fdc31..4453828ba 100644 --- a/utils/windowfunction/idborderby.h +++ b/utils/windowfunction/idborderby.h @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -119,6 +120,14 @@ public: int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer); }; +class LongDoubleCompare : public Compare +{ +public: + LongDoubleCompare(const IdbSortSpec& spec) : Compare(spec) {} + + int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer); +}; + class FloatCompare : public Compare { diff --git a/utils/windowfunction/wf_lead_lag.cpp b/utils/windowfunction/wf_lead_lag.cpp index 5160b75bf..c720e9db2 100644 --- a/utils/windowfunction/wf_lead_lag.cpp +++ b/utils/windowfunction/wf_lead_lag.cpp @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -90,6 +91,12 @@ boost::shared_ptr WF_lead_lag::makeFunction(int id, const break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + func.reset(new WF_lead_lag(id, name)); + break; + } + case CalpontSystemCatalog::FLOAT: case CalpontSystemCatalog::UFLOAT: { diff --git a/utils/windowfunction/wf_min_max.cpp b/utils/windowfunction/wf_min_max.cpp index b0c1fe033..511fbb4eb 100644 --- a/utils/windowfunction/wf_min_max.cpp +++ b/utils/windowfunction/wf_min_max.cpp @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -96,6 +97,12 @@ boost::shared_ptr WF_min_max::makeFunction(int id, const break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + func.reset(new WF_min_max(id, name)); + break; + } + default: { func.reset(new WF_min_max(id, name)); diff --git a/utils/windowfunction/wf_nth_value.cpp b/utils/windowfunction/wf_nth_value.cpp index eacd1202a..c6eea0ace 100644 --- a/utils/windowfunction/wf_nth_value.cpp +++ b/utils/windowfunction/wf_nth_value.cpp @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -97,6 +98,12 @@ boost::shared_ptr WF_nth_value::makeFunction(int id, cons break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + func.reset(new WF_nth_value(id, name)); + break; + } + default: { func.reset(new WF_nth_value(id, name)); diff --git a/utils/windowfunction/wf_percentile.cpp b/utils/windowfunction/wf_percentile.cpp index 83d6f57d8..acf137c2e 100644 --- a/utils/windowfunction/wf_percentile.cpp +++ b/utils/windowfunction/wf_percentile.cpp @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -102,6 +103,12 @@ boost::shared_ptr WF_percentile::makeFunction(int id, con break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + func.reset(new WF_percentile(id, name)); + break; + } + default: { if (id == WF__PERCENTILE_DISC) @@ -145,6 +152,12 @@ boost::shared_ptr WF_percentile::makeFunction(int id, con break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + func.reset(new WF_percentile(id, name)); + break; + } + default: { string errStr = name + "(" + colType2String[ct] + ")"; diff --git a/utils/windowfunction/wf_stats.cpp b/utils/windowfunction/wf_stats.cpp index 3599271d4..db4b107ee 100644 --- a/utils/windowfunction/wf_stats.cpp +++ b/utils/windowfunction/wf_stats.cpp @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -96,6 +97,12 @@ boost::shared_ptr WF_stats::makeFunction(int id, const st break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + func.reset(new WF_stats(id, name)); + break; + } + default: { string errStr = name + "(" + colType2String[ct] + ")"; diff --git a/utils/windowfunction/wf_sum_avg.cpp b/utils/windowfunction/wf_sum_avg.cpp index 15586da3b..4632496df 100644 --- a/utils/windowfunction/wf_sum_avg.cpp +++ b/utils/windowfunction/wf_sum_avg.cpp @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -49,10 +50,10 @@ using namespace joblist; #include "wf_sum_avg.h" +#if 0 namespace { - template void checkSumLimit(T sum, T val) { @@ -102,14 +103,12 @@ void checkSumLimit(uint64_t sum, uint64_t val) } -template -T calculateAvg(T sum, uint64_t count, int s) +template<> +long double calculateAvg(long double sum, uint64_t count, int s) { - T avg = ((long double) sum) / count; - return avg; + return sum / count; } - long double avgWithLimit(long double sum, uint64_t count, int scale, long double u, long double l) { long double factor = pow(10.0, scale); @@ -149,8 +148,8 @@ uint64_t calculateAvg(uint64_t sum, uint64_t count, int scale) return t; } - } +#endif namespace windowfunction { @@ -159,7 +158,6 @@ template boost::shared_ptr WF_sum_avg::makeFunction(int id, const string& name, int ct) { boost::shared_ptr func; - switch (ct) { case CalpontSystemCatalog::TINYINT: @@ -198,6 +196,11 @@ boost::shared_ptr WF_sum_avg::makeFunction(int id, const break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + func.reset(new WF_sum_avg(id, name)); + break; + } default: { string errStr = name + "(" + colType2String[ct] + ")"; @@ -248,7 +251,7 @@ void WF_sum_avg::operator()(int64_t b, int64_t e, int64_t c) e = c; uint64_t colIn = fFieldIndex[1]; - int scale = fRow.getScale(colOut) - fRow.getScale(colIn); + double scale = fRow.getScale(colIn); for (int64_t i = b; i <= e; i++) { @@ -262,11 +265,16 @@ void WF_sum_avg::operator()(int64_t b, int64_t e, int64_t c) T valIn; getValue(colIn, valIn); - checkSumLimit(fSum, valIn); +// checkSumLimit(fSum, valIn); if ((!fDistinct) || (fSet.find(valIn) == fSet.end())) { - fSum += valIn; + long double val = valIn; + if (scale) + { + val /= pow(10.0, scale); + } + fSum += val; fCount++; if (fDistinct) @@ -275,10 +283,12 @@ void WF_sum_avg::operator()(int64_t b, int64_t e, int64_t c) } if ((fCount > 0) && (fFunctionId == WF__AVG || fFunctionId == WF__AVG_DISTINCT)) - fAvg = (T) calculateAvg(fSum, fCount, scale); + { + fAvg = fSum / fCount; + } } - T* v = NULL; + long double* v = NULL; if (fCount > 0) { diff --git a/utils/windowfunction/wf_sum_avg.h b/utils/windowfunction/wf_sum_avg.h index c96166fba..48d46453b 100644 --- a/utils/windowfunction/wf_sum_avg.h +++ b/utils/windowfunction/wf_sum_avg.h @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -47,8 +48,8 @@ public: static boost::shared_ptr makeFunction(int, const string&, int); protected: - T fAvg; - T fSum; + long double fAvg; + long double fSum; uint64_t fCount; bool fDistinct; std::set fSet; diff --git a/utils/windowfunction/wf_udaf.cpp b/utils/windowfunction/wf_udaf.cpp index 91ae5f9b2..903dda613 100644 --- a/utils/windowfunction/wf_udaf.cpp +++ b/utils/windowfunction/wf_udaf.cpp @@ -1,5 +1,5 @@ /************************************************************************************ - Copyright (C) 2017 MariaDB Corporation AB + Copyright (c) 2019 MariaDB Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -398,6 +398,48 @@ bool WF_udaf::dropValues(int64_t b, int64_t e) break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + double valIn; + + if (cc) + { + valIn = cc->getLongDoubleVal(fRow, isNull); + } + else + { + getValue(colIn, valIn); + } + + // Check for distinct, if turned on. + // Currently, distinct only works on the first parameter. + if (k == 0) + { + if (fDistinct) + { + DistinctMap::iterator distinct; + distinct = fDistinctMap.find(valIn); + if (distinct != fDistinctMap.end()) + { + // This is a duplicate: decrement the count + --(*distinct).second; + if ((*distinct).second > 0) // still more of these + { + bSkipIt = true; + continue; + } + else + { + fDistinctMap.erase(distinct); + } + } + } + } + + datum.columnData = valIn; + break; + } + case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::VARCHAR: case CalpontSystemCatalog::VARBINARY: @@ -515,6 +557,7 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, uint64_t uintOut = 0; float floatOut = 0.0; double doubleOut = 0.0; + long double longdoubleOut = 0.0; ostringstream oss; std::string strOut; @@ -588,12 +631,14 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, { floatOut = valOut.cast(); doubleOut = floatOut; + longdoubleOut = floatOut; intOut = uintOut = floatOut; oss << floatOut; } else if (valOut.compatible(doubleTypeId)) { doubleOut = valOut.cast(); + longdoubleOut = doubleOut; floatOut = (float)doubleOut; uintOut = (uint64_t)doubleOut; intOut = (int64_t)doubleOut; @@ -607,6 +652,7 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, intOut = atol(strOut.c_str()); uintOut = strtoul(strOut.c_str(), NULL, 10); doubleOut = strtod(strOut.c_str(), NULL); + longdoubleOut = doubleOut; floatOut = (float)doubleOut; } else @@ -676,6 +722,17 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + if (valOut.empty()) + { + setValue(colDataType, b, e, c, (long double*)NULL); + } + else + { + setValue(colDataType, b, e, c, &longdoubleOut); + } + break; + case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::TEXT: @@ -971,6 +1028,38 @@ void WF_udaf::operator()(int64_t b, int64_t e, int64_t c) break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + long double valIn; + + if (cc) + { + valIn = cc->getLongDoubleVal(fRow, isNull); + } + else + { + getValue(colIn, valIn); + } + + // Check for distinct, if turned on. + // Currently, distinct only works on the first parameter. + if (k == 0 && fDistinct) + { + std::pair val = make_pair(valIn, 1); + std::pair distinct; + distinct = fDistinctMap.insert(val); + if (distinct.second == false) + { + ++(*distinct.first).second; + bSkipIt = true; + continue; + } + } + + datum.columnData = valIn; + break; + } + case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::VARCHAR: case CalpontSystemCatalog::VARBINARY: diff --git a/utils/windowfunction/windowfunctiontype.cpp b/utils/windowfunction/windowfunctiontype.cpp index 68015d120..776e63c73 100644 --- a/utils/windowfunction/windowfunctiontype.cpp +++ b/utils/windowfunction/windowfunctiontype.cpp @@ -1,6 +1,6 @@ /* - Copyright (c) 2017, MariaDB Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -290,6 +290,16 @@ template<> void WindowFunctionType::getValue(uint64_t i, float& t, CDT* c } } +template<> void WindowFunctionType::getValue(uint64_t i, long double& t, CDT* cdt) +{ + t = fRow.getLongDoubleField(i); + + if (cdt) + { + *cdt = execplan::CalpontSystemCatalog::LONGDOUBLE; + } +} + template<> void WindowFunctionType::getValue(uint64_t i, string& t, CDT* cdt) { t = fRow.getStringField(i); @@ -320,6 +330,11 @@ template<> void WindowFunctionType::setValue(uint64_t i, float& t) fRow.setFloatField(t, i); } +template<> void WindowFunctionType::setValue(uint64_t i, long double& t) +{ + fRow.setLongDoubleField(t, i); +} + template<> void WindowFunctionType::setValue(uint64_t i, string& t) { fRow.setStringField(t, i); @@ -406,6 +421,14 @@ void WindowFunctionType::setValue(int ct, int64_t b, int64_t e, int64_t c, T* v) setValue(i, fv); break; } + + case CalpontSystemCatalog::LONGDOUBLE: + { + long double dv = *v; + setValue(i, dv); + break; + } + default: { setValue(i, *v); @@ -480,6 +503,16 @@ void WindowFunctionType::implicit2T(uint64_t i, T& t, int s) break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + if (s == 0) + t = (T) fRow.getLongDoubleField(i); + else + t = (T) (fRow.getLongDoubleField(i) * IDB_pow[s]); // s is scale, [0, 18] + + break; + } + case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::VARCHAR: default: @@ -523,6 +556,12 @@ void WindowFunctionType::getConstValue(ConstantColumn* cc, double& t, bo t = cc->getDoubleVal(fRow, b); } +template<> +void WindowFunctionType::getConstValue(ConstantColumn* cc, long double& t, bool& b) +{ + t = cc->getLongDoubleVal(fRow, b); +} + template<> void WindowFunctionType::getConstValue(ConstantColumn* cc, float& t, bool& b) { @@ -539,11 +578,13 @@ template void WindowFunctionType::implicit2T(uint64_t, int64_t&, int); template void WindowFunctionType::implicit2T(uint64_t, uint64_t&, int); template void WindowFunctionType::implicit2T(uint64_t, float&, int); template void WindowFunctionType::implicit2T(uint64_t, double&, int); +template void WindowFunctionType::implicit2T(uint64_t, long double&, int); template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, int64_t*); template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, uint64_t*); template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, float*); template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, double*); +template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, long double*); void* WindowFunctionType::getNullValueByType(int ct, int pos) { @@ -557,6 +598,7 @@ void* WindowFunctionType::getNullValueByType(int ct, int pos) static uint64_t utinyIntNull = joblist::UTINYINTNULL; static uint64_t floatNull = joblist::FLOATNULL; static uint64_t doubleNull = joblist::DOUBLENULL; + static long double longDoubleNull= joblist::LONGDOUBLENULL; static uint64_t dateNull = joblist::DATENULL; static uint64_t datetimeNull = joblist::DATETIMENULL; static uint64_t timeNull = joblist::TIMENULL; @@ -691,6 +733,9 @@ void* WindowFunctionType::getNullValueByType(int ct, int pos) break; case CalpontSystemCatalog::LONGDOUBLE: + v = &longDoubleNull; + break; + case CalpontSystemCatalog::VARBINARY: default: std::ostringstream oss; diff --git a/utils/windowfunction/windowfunctiontype.h b/utils/windowfunction/windowfunctiontype.h index 5c2f43db0..e0a1aa832 100644 --- a/utils/windowfunction/windowfunctiontype.h +++ b/utils/windowfunction/windowfunctiontype.h @@ -1,4 +1,5 @@ /* Copyright (C) 2014 InfiniDB, Inc. + Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -223,6 +224,10 @@ protected: { return fRow.getDoubleField(i); } + long double getLongDoubleValue(uint64_t i) + { + return fRow.getLongDoubleField(i); + } void setIntValue(int64_t i, int64_t v) { fRow.setIntField(v, i); @@ -231,7 +236,10 @@ protected: { fRow.setDoubleField(v, i); } - + void setLongDoubleValue(int64_t i, long double v) + { + fRow.setLongDoubleField(v, i); + } // for string table rowgroup::Row::Pointer getPointer(joblist::RowPosition& r)