diff --git a/CMakeLists.txt b/CMakeLists.txt index 7379cd23c..94fdde894 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,17 @@ if (NOT SNAPPY_FOUND) MESSAGE(FATAL_ERROR "Snappy not found please install snappy-devel for CentOS/RedHat or libsnappy-dev for Ubuntu/Debian") endif() +# Jemalloc has issues with SLES 12, so disable for now +IF (EXISTS "/etc/SuSE-release") + SET(JEMALLOC_LIBRARIES "") +ELSE () + INCLUDE (FindJeMalloc.cmake) + if (NOT JEMALLOC_FOUND) + message(FATAL_ERROR "jemalloc not found!") + SET(JEMALLOC_LIBRARIES "") + endif() +ENDIF () + FIND_PROGRAM(AWK_EXECUTABLE awk DOC "path to the awk executable") if(NOT AWK_EXECUTABLE) message(FATAL_ERROR "awk not found!") @@ -163,7 +174,7 @@ SET (ENGINE_LOCALDIR "${INSTALL_ENGINE}/local") SET (ENGINE_MYSQLDIR "${INSTALL_ENGINE}/mysql") SET (ENGINE_TOOLSDIR "${INSTALL_ENGINE}/tools") -SET (ENGINE_COMMON_LIBS messageqcpp loggingcpp configcpp idbboot ${Boost_LIBRARIES} xml2 pthread rt libmysql_client) +SET (ENGINE_COMMON_LIBS messageqcpp loggingcpp configcpp idbboot ${Boost_LIBRARIES} xml2 pthread rt libmysql_client ${JEMALLOC_LIBRARIES}) SET (ENGINE_OAM_LIBS oamcpp alarmmanager) SET (ENGINE_BRM_LIBS brm idbdatafile cacheutils rwlock ${ENGINE_OAM_LIBS} ${ENGINE_COMMON_LIBS}) SET (ENGINE_EXEC_LIBS joblist execplan windowfunction joiner rowgroup funcexp udfsdk regr dataconvert common compress querystats querytele thrift threadpool ${ENGINE_BRM_LIBS}) diff --git a/FindJeMalloc.cmake b/FindJeMalloc.cmake new file mode 100644 index 000000000..c97bb1b9f --- /dev/null +++ b/FindJeMalloc.cmake @@ -0,0 +1,44 @@ +# - Try to find jemalloc headers and libraries. +# +# Usage of this module as follows: +# +# find_package(JeMalloc) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# JEMALLOC_ROOT_DIR Set this variable to the root installation of +# jemalloc if the module has problems finding +# the proper installation path. +# +# Variables defined by this module: +# +# JEMALLOC_FOUND System has jemalloc libs/headers +# JEMALLOC_LIBRARIES The jemalloc library/libraries +# JEMALLOC_INCLUDE_DIR The location of jemalloc headers + +find_path(JEMALLOC_ROOT_DIR + NAMES include/jemalloc/jemalloc.h +) + +find_library(JEMALLOC_LIBRARIES + NAMES jemalloc + HINTS ${JEMALLOC_ROOT_DIR}/lib +) + +find_path(JEMALLOC_INCLUDE_DIR + NAMES jemalloc/jemalloc.h + HINTS ${JEMALLOC_ROOT_DIR}/include +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(JeMalloc DEFAULT_MSG + JEMALLOC_LIBRARIES + JEMALLOC_INCLUDE_DIR +) + +mark_as_advanced( + JEMALLOC_ROOT_DIR + JEMALLOC_LIBRARIES + JEMALLOC_INCLUDE_DIR +) diff --git a/VERSION b/VERSION index ebe283cd3..f5d54e457 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ COLUMNSTORE_VERSION_MAJOR=1 -COLUMNSTORE_VERSION_MINOR=2 -COLUMNSTORE_VERSION_PATCH=3 +COLUMNSTORE_VERSION_MINOR=3 +COLUMNSTORE_VERSION_PATCH=0 COLUMNSTORE_VERSION_RELEASE=1 diff --git a/cpackEngineDEB.cmake b/cpackEngineDEB.cmake index 549e0d53a..4cae76f6a 100644 --- a/cpackEngineDEB.cmake +++ b/cpackEngineDEB.cmake @@ -65,11 +65,11 @@ if (EXISTS "/etc/debian_version") set(DEBIAN_VERSION_NUMBER "${CMAKE_MATCH_1}") endif () if ("${DEBIAN_VERSION_NUMBER}" EQUAL "8") - SET(CPACK_DEBIAN_PLATFORM_PACKAGE_DEPENDS "expect, perl, openssl, file, libdbi-perl, libreadline-dev, rsync, net-tools, libboost-all-dev, mariadb-columnstore-libs, mariadb-columnstore-server, libsnappy1") + SET(CPACK_DEBIAN_PLATFORM_PACKAGE_DEPENDS "expect, perl, openssl, file, libdbi-perl, libreadline-dev, rsync, net-tools, libboost-all-dev, mariadb-columnstore-libs, mariadb-columnstore-server, libsnappy1, libjemalloc1") elseif ("${DEBIAN_VERSION_NUMBER}" EQUAL "9") - SET(CPACK_DEBIAN_PLATFORM_PACKAGE_DEPENDS "expect, perl, openssl, file, libdbi-perl, libreadline-dev, rsync, net-tools, libboost-all-dev, mariadb-columnstore-libs, mariadb-columnstore-server, libsnappy1v5, libreadline5") + SET(CPACK_DEBIAN_PLATFORM_PACKAGE_DEPENDS "expect, perl, openssl, file, libdbi-perl, libreadline-dev, rsync, net-tools, libboost-all-dev, mariadb-columnstore-libs, mariadb-columnstore-server, libsnappy1v5, libreadline5, libjemalloc1") else() - SET(CPACK_DEBIAN_PLATFORM_PACKAGE_DEPENDS "expect, perl, openssl, file, libdbi-perl, libboost-all-dev, libreadline-dev, rsync, libsnappy1v5, net-tools") + SET(CPACK_DEBIAN_PLATFORM_PACKAGE_DEPENDS "expect, perl, openssl, file, libdbi-perl, libboost-all-dev, libreadline-dev, rsync, libsnappy1v5, net-tools, libjemalloc1") endif () SET(CPACK_DEBIAN_STORAGE-ENGINE_PACKAGE_DEPENDS "mariadb-columnstore-libs") diff --git a/cpackEngineRPM.cmake b/cpackEngineRPM.cmake index c4fc765cc..83a707dbd 100644 --- a/cpackEngineRPM.cmake +++ b/cpackEngineRPM.cmake @@ -91,9 +91,9 @@ if (${REDHAT_VERSION_NUMBER} EQUAL 6) # Disable auto require as this will also try to pull Boost via RPM SET(CPACK_RPM_PACKAGE_AUTOREQPROV " no") elseif (${SUSE_VERSION_NUMBER} EQUAL 12) - SETA(CPACK_RPM_platform_PACKAGE_REQUIRES "expect" "boost-devel >= 1.54.0" "mariadb-columnstore-libs" "libsnappy1") + SETA(CPACK_RPM_platform_PACKAGE_REQUIRES "expect" "boost-devel >= 1.54.0" "mariadb-columnstore-libs" "libsnappy1" "jemalloc") else () - SETA(CPACK_RPM_platform_PACKAGE_REQUIRES "expect" "boost >= 1.53.0" "mariadb-columnstore-libs" "snappy") + SETA(CPACK_RPM_platform_PACKAGE_REQUIRES "expect" "boost >= 1.53.0" "mariadb-columnstore-libs" "snappy" "jemalloc") endif() SETA(CPACK_RPM_storage-engine_PACKAGE_REQUIRES "mariadb-columnstore-libs") diff --git a/dbcon/ddlpackage/ddl.l b/dbcon/ddlpackage/ddl.l index bb65715da..edc962a10 100644 --- a/dbcon/ddlpackage/ddl.l +++ b/dbcon/ddlpackage/ddl.l @@ -187,6 +187,7 @@ MEDIUMTEXT {return MEDIUMTEXT;} LONGTEXT {return LONGTEXT;} BOOL {return BOOL;} BOOLEAN {return BOOLEAN;} +MEDIUMINT {return MEDIUMINT;} \n { lineno++;} diff --git a/dbcon/ddlpackage/ddl.y b/dbcon/ddlpackage/ddl.y index 2b35c8392..cdd439927 100644 --- a/dbcon/ddlpackage/ddl.y +++ b/dbcon/ddlpackage/ddl.y @@ -112,7 +112,7 @@ MIN_ROWS MODIFY NO NOT NULL_TOK NUMBER NUMERIC ON PARTIAL PRECISION PRIMARY REFERENCES RENAME RESTRICT SET SMALLINT TABLE TEXT TINYBLOB TINYTEXT TINYINT TO UNIQUE UNSIGNED UPDATE USER SESSION_USER SYSTEM_USER VARCHAR VARBINARY VARYING WITH ZONE DOUBLE IDB_FLOAT REAL CHARSET IDB_IF EXISTS CHANGE TRUNCATE -BOOL BOOLEAN +BOOL BOOLEAN MEDIUMINT %token DQ_IDENT IDENT FCONST SCONST CP_SEARCH_CONDITION_TEXT ICONST DATE TIME @@ -1054,6 +1054,16 @@ exact_numeric_type: $$->fLength = DDLDatatypeLength[DDL_TINYINT]; $$->fPrecision = 1; } + | MEDIUMINT opt_display_width + { + $$ = new ColumnType(DDL_MEDINT); + $$->fLength = DDLDatatypeLength[DDL_MEDINT]; + } + | MEDIUMINT opt_display_width UNSIGNED + { + $$ = new ColumnType(DDL_UNSIGNED_MEDINT); + $$->fLength = DDLDatatypeLength[DDL_UNSIGNED_MEDINT]; + } ; /* Bug 1570, change default scale to 0 from -1 */ opt_precision_scale: diff --git a/dbcon/ddlpackage/ddlpkg.cpp b/dbcon/ddlpackage/ddlpkg.cpp index 1edb909ad..03794a304 100644 --- a/dbcon/ddlpackage/ddlpkg.cpp +++ b/dbcon/ddlpackage/ddlpkg.cpp @@ -115,9 +115,16 @@ ColumnType::ColumnType(int type) : fPrecision = 5; break; + case DDL_MEDINT: + fPrecision = 7; + break; + + case DDL_UNSIGNED_MEDINT: + fPrecision = 8; + break; + case DDL_INT: case DDL_UNSIGNED_INT: - case DDL_MEDINT: fPrecision = 10; break; @@ -202,7 +209,12 @@ void ColumnDef::convertDecimal() fType->fType = DDL_SMALLINT; fType->fLength = 2; } - else if (fType->fPrecision > 4 && fType->fPrecision < 10) + else if (fType->fPrecision > 4 && fType->fPrecision < 7) + { + fType->fType = DDL_MEDINT; + fType->fLength = 4; + } + else if (fType->fPrecision > 6 && fType->fPrecision < 10) { //dataType = CalpontSystemCatalog::INT; fType->fType = DDL_INT; diff --git a/dbcon/ddlpackageproc/altertableprocessor.cpp b/dbcon/ddlpackageproc/altertableprocessor.cpp index a398e656f..cc14424e2 100644 --- a/dbcon/ddlpackageproc/altertableprocessor.cpp +++ b/dbcon/ddlpackageproc/altertableprocessor.cpp @@ -139,7 +139,6 @@ bool typesAreSame(const CalpontSystemCatalog::ColType& colType, const ColumnType break; - // Don't think there can be such a type in syscat right now... case (CalpontSystemCatalog::MEDINT): if (newType.fType == DDL_MEDINT && colType.precision == newType.fPrecision && colType.scale == newType.fScale) return true; @@ -149,6 +148,12 @@ bool typesAreSame(const CalpontSystemCatalog::ColType& colType, const ColumnType // colType.scale == newType.fScale) return true; break; + case (CalpontSystemCatalog::UMEDINT): + if (newType.fType == DDL_UNSIGNED_MEDINT && colType.precision == newType.fPrecision && + colType.scale == newType.fScale) return true; + + break; + case (CalpontSystemCatalog::INT): if (newType.fType == DDL_INT && colType.precision == newType.fPrecision && colType.scale == newType.fScale) return true; @@ -2103,7 +2108,6 @@ void AlterTableProcessor::tableComment(uint32_t sessionID, execplan::CalpontSyst break; case CalpontSystemCatalog::INT: - case CalpontSystemCatalog::MEDINT: if (static_cast(nextVal) > MAX_INT) validated = false; @@ -2113,12 +2117,26 @@ void AlterTableProcessor::tableComment(uint32_t sessionID, execplan::CalpontSyst break; case CalpontSystemCatalog::UINT: - case CalpontSystemCatalog::UMEDINT: if (nextVal > MAX_UINT) validated = false; break; + case CalpontSystemCatalog::MEDINT: + if (static_cast(nextVal) > MAX_MEDINT) + validated = false; + + if (static_cast(nextVal) < 1) + negative = true; + + break; + + case CalpontSystemCatalog::UMEDINT: + if (nextVal > MAX_UMEDINT) + validated = false; + + break; + case CalpontSystemCatalog::SMALLINT: if (static_cast(nextVal) > MAX_SMALLINT) validated = false; 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 7b828a297..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 @@ -58,6 +58,8 @@ const int64_t MIN_TINYINT __attribute__ ((unused)) = std::numeric_limits const int64_t MAX_TINYINT __attribute__ ((unused)) = std::numeric_limits::max(); //127; const int64_t MIN_SMALLINT __attribute__ ((unused)) = std::numeric_limits::min() + 2; //-32766; const int64_t MAX_SMALLINT __attribute__ ((unused)) = std::numeric_limits::max(); //32767; +const int64_t MIN_MEDINT __attribute__ ((unused)) = -(1ULL << 23); //-8388608; +const int64_t MAX_MEDINT __attribute__ ((unused)) = (1ULL << 23) - 1; //8388607; const int64_t MIN_INT __attribute__ ((unused)) = std::numeric_limits::min() + 2; //-2147483646; const int64_t MAX_INT __attribute__ ((unused)) = std::numeric_limits::max(); //2147483647; const int64_t MIN_BIGINT __attribute__ ((unused)) = std::numeric_limits::min() + 2; //-9223372036854775806LL; @@ -66,16 +68,20 @@ const int64_t MAX_BIGINT __attribute__ ((unused)) = std::numeric_limits::max() - 2; //4294967293 const uint64_t MAX_UTINYINT __attribute__ ((unused)) = std::numeric_limits::max() - 2; //253; const uint64_t MAX_USMALLINT __attribute__ ((unused)) = std::numeric_limits::max() - 2; //65533; +const uint64_t MAX_UMEDINT __attribute__ ((unused)) = (1ULL << 24) - 1; //16777215 const uint64_t MAX_UBIGINT __attribute__ ((unused)) = std::numeric_limits::max() - 2; //18446744073709551613 const float MAX_FLOAT __attribute__ ((unused)) = std::numeric_limits::max(); //3.402823466385289e+38 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(); @@ -969,8 +975,8 @@ inline bool isCharType(const execplan::CalpontSystemCatalog::ColDataType type) execplan::CalpontSystemCatalog::TEXT == type); } -/** convenience function to determine if column type is an - * unsigned type +/** convenience function to determine if column type is a + * numeric type */ inline bool isNumeric(const execplan::CalpontSystemCatalog::ColDataType type) { @@ -999,6 +1005,9 @@ inline bool isNumeric(const execplan::CalpontSystemCatalog::ColDataType type) } } +/** convenience function to determine if column type is an + * unsigned type + */ inline bool isUnsigned(const execplan::CalpontSystemCatalog::ColDataType type) { switch (type) 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 d0892e45f..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: @@ -1068,6 +1186,7 @@ void TupleUnion::writeNull(Row* out, uint32_t col) out->setUintField<4>(joblist::INTNULL, col); break; + case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::UINT: out->setUintField<4>(joblist::UINTNULL, col); break; 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/CMakeLists.txt b/dbcon/mysql/CMakeLists.txt index ae8f30622..fa2df6eaa 100644 --- a/dbcon/mysql/CMakeLists.txt +++ b/dbcon/mysql/CMakeLists.txt @@ -4,6 +4,8 @@ include_directories( ${ENGINE_COMMON_INCLUDES} SET ( libcalmysql_SRCS + ha_mcs_sysvars.cpp + ha_mcs_client_udfs.cpp ha_calpont.cpp ha_calpont_impl.cpp ha_calpont_dml.cpp diff --git a/dbcon/mysql/ha_calpont.cpp b/dbcon/mysql/ha_calpont.cpp index 6ea5f85a6..d4ff366bd 100644 --- a/dbcon/mysql/ha_calpont.cpp +++ b/dbcon/mysql/ha_calpont.cpp @@ -16,97 +16,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// $Id: ha_calpont.cpp 9642 2013-06-24 14:57:42Z rdempsey $ - -/* Copyright (C) 2003 MySQL AB - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/** - @file ha_example.cc - - @brief - The ha_example engine is a stubbed storage engine for example purposes only; - it does nothing at this point. Its purpose is to provide a source - code illustration of how to begin writing new storage engines; see also - /storage/example/ha_example.h. - - @details - ha_example will let you create/open/delete tables, but - nothing further (for example, indexes are not supported nor can data - be stored in the table). Use this example as a template for - implementing the same functionality in your own storage engine. You - can enable the example storage engine in your build by doing the - following during your build process:
./configure - --with-example-storage-engine - - Once this is done, MySQL will let you create tables with:
- CREATE TABLE (...) ENGINE=EXAMPLE; - - The example storage engine is set up to use table locks. It - implements an example "SHARE" that is inserted into a hash by table - name. You can use this to store information of state that any - example handler object will be able to see when it is using that - table. - - Please read the object definition in ha_example.h before reading the rest - of this file. - - @note - When you create an EXAMPLE table, the MySQL Server creates a table .frm - (format) file in the database directory, using the table name as the file - name as is customary with MySQL. No other files are created. To get an idea - of what occurs, here is an example select that would do a scan of an entire - table: - - @code - ha_example::store_lock - ha_example::external_lock - ha_example::info - ha_example::rnd_init - ha_example::extra - ENUM HA_EXTRA_CACHE Cache record in HA_rrnd() - ha_example::rnd_next - ha_example::rnd_next - ha_example::rnd_next - ha_example::rnd_next - ha_example::rnd_next - ha_example::rnd_next - ha_example::rnd_next - ha_example::rnd_next - ha_example::rnd_next - ha_example::extra - ENUM HA_EXTRA_NO_CACHE End caching of records (def) - ha_example::external_lock - ha_example::extra - ENUM HA_EXTRA_RESET Reset database to after open - @endcode - - Here you see that the example storage engine has 9 rows called before - rnd_next signals that it has reached the end of its data. Also note that - the table in question was already opened; had it not been open, a call to - ha_example::open() would also have been necessary. Calls to - ha_example::extra() are hints as to what will be occuring to the request. - - A Longer Example can be found called the "Skeleton Engine" which can be - found on TangentOrg. It has both an engine and a full build environment - for building a pluggable storage engine. - - Happy coding!
- -Brian -*/ - #include "ha_calpont.h" #include "columnstoreversion.h" @@ -1101,44 +1010,6 @@ struct st_mysql_storage_engine columnstore_storage_engine = struct st_mysql_storage_engine infinidb_storage_engine = { MYSQL_HANDLERTON_INTERFACE_VERSION }; -#if 0 -static ulong srv_enum_var = 0; -static ulong srv_ulong_var = 0; - -const char* enum_var_names[] = -{ - "e1", "e2", NullS -}; - -TYPELIB enum_var_typelib = -{ - array_elements(enum_var_names) - 1, "enum_var_typelib", - enum_var_names, NULL -}; - -static MYSQL_SYSVAR_ENUM( - enum_var, // name - srv_enum_var, // varname - PLUGIN_VAR_RQCMDARG, // opt - "Sample ENUM system variable.", // comment - NULL, // check - NULL, // update - 0, // def - &enum_var_typelib); // typelib - -static MYSQL_SYSVAR_ULONG( - ulong_var, - srv_ulong_var, - PLUGIN_VAR_RQCMDARG, - "0..1000", - NULL, - NULL, - 8, - 0, - 1000, - 0); -#endif - /*@brief check_walk - It traverses filter conditions*/ /************************************************************ * DESCRIPTION: @@ -1190,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 ) @@ -1231,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 @@ -1254,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 ) { @@ -1368,14 +1261,6 @@ int ha_calpont_group_by_handler::end_scan() DBUG_RETURN(rc); } - -static struct st_mysql_sys_var* calpont_system_variables[] = -{ -// MYSQL_SYSVAR(enum_var), -// MYSQL_SYSVAR(ulong_var), - NULL -}; - mysql_declare_plugin(columnstore) { MYSQL_STORAGE_ENGINE_PLUGIN, @@ -1388,7 +1273,7 @@ mysql_declare_plugin(columnstore) columnstore_done_func, /* Plugin Deinit */ 0x0100 /* 1.0 */, NULL, /* status variables */ - calpont_system_variables, /* system variables */ + mcs_system_variables, /* system variables */ NULL, /* reserved */ 0 /* config flags */ }, @@ -1403,7 +1288,7 @@ mysql_declare_plugin(columnstore) infinidb_done_func, /* Plugin Deinit */ 0x0100 /* 1.0 */, NULL, /* status variables */ - calpont_system_variables, /* system variables */ + mcs_system_variables, /* system variables */ NULL, /* reserved */ 0 /* config flags */ } @@ -1419,9 +1304,9 @@ maria_declare_plugin(columnstore) columnstore_init_func, columnstore_done_func, 0x0100, /* 1.0 */ - NULL, /* status variables */ - calpont_system_variables, /* system variables */ - "1.0", /* string version */ + NULL, /* status variables */ + mcs_system_variables, /* system variables */ + "1.0", /* string version */ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ }, { @@ -1434,10 +1319,10 @@ maria_declare_plugin(columnstore) infinidb_init_func, infinidb_done_func, 0x0100, /* 1.0 */ - NULL, /* status variables */ - calpont_system_variables, /* system variables */ - "1.0", /* string version */ - MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ + NULL, /* status variables */ + mcs_system_variables, /* system variables */ + "1.0", /* string version */ + MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ } maria_declare_plugin_end; diff --git a/dbcon/mysql/ha_calpont.h b/dbcon/mysql/ha_calpont.h index e618ed4f0..bab756851 100644 --- a/dbcon/mysql/ha_calpont.h +++ b/dbcon/mysql/ha_calpont.h @@ -15,35 +15,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/** @file ha_example.h - - @brief - The ha_example engine is a stubbed storage engine for example purposes only; - it does nothing at this point. Its purpose is to provide a source - code illustration of how to begin writing new storage engines; see also - /storage/example/ha_example.cc. - - @note - Please read ha_example.cc before reading this file. - Reminder: The example storage engine implements all methods that are *required* - to be implemented. For a full list of all methods that you can implement, see - handler.h. - - @see - /sql/handler.h and /storage/example/ha_example.cc -*/ - -// $Id: ha_calpont.h 9210 2013-01-21 14:10:42Z rdempsey $ - #ifndef HA_CALPONT_H__ #define HA_CALPONT_H__ #include #include "idb_mysql.h" +#include "ha_mcs_sysvars.h" extern handlerton* calpont_hton; /** @brief - EXAMPLE_SHARE is a structure that will be shared among all open handlers. + This structure will be shared among all open handlers. This example implements the minimum of what you will probably need. */ typedef struct st_calpont_share diff --git a/dbcon/mysql/ha_calpont_ddl.cpp b/dbcon/mysql/ha_calpont_ddl.cpp index 487e0d4f8..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; @@ -49,6 +48,7 @@ using namespace std; #include using namespace boost; +#include "ha_mcs_sysvars.h" #include "idb_mysql.h" #include "ha_calpont_impl_if.h" @@ -198,6 +198,10 @@ uint32_t convertDataType(int dataType) calpontDataType = CalpontSystemCatalog::USMALLINT; break; + case ddlpackage::DDL_UNSIGNED_MEDINT: + calpontDataType = CalpontSystemCatalog::UMEDINT; + break; + case ddlpackage::DDL_UNSIGNED_INT: calpontDataType = CalpontSystemCatalog::UINT; break; @@ -323,21 +327,33 @@ bool validateNextValue( int type, int64_t value ) case ddlpackage::DDL_INT: case ddlpackage::DDL_INTEGER: - case ddlpackage::DDL_MEDINT: { if (value > MAX_INT) validValue = false; } break; + case ddlpackage::DDL_MEDINT: + { + if (value > MAX_MEDINT) + validValue = false; + } + break; + case ddlpackage::DDL_UNSIGNED_INT: - case ddlpackage::DDL_UNSIGNED_MEDINT: { if (static_cast(value) > MAX_UINT) validValue = false; } break; + case ddlpackage::DDL_UNSIGNED_MEDINT: + { + if (static_cast(value) > MAX_UMEDINT) + validValue = false; + } + break; + case ddlpackage::DDL_SMALLINT: { if (value > MAX_SMALLINT) @@ -654,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 @@ -663,10 +679,10 @@ int ProcessDDLStatement(string& ddlStatement, string& schema, const string& tabl IDBCompressInterface idbCompress; parser.Parse(ddlStatement.c_str()); - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); if (parser.Good()) { @@ -1599,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 @@ -1798,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); @@ -1887,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); -} - } // @@ -1988,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; @@ -2060,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; @@ -2091,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 } @@ -2128,7 +2118,7 @@ int ha_calpont_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO* return 1; } - int compressiontype = thd->variables.infinidb_compression_type; + int compressiontype = get_compression_type(thd); if (compressiontype == 1) compressiontype = 2; @@ -2140,7 +2130,7 @@ int ha_calpont_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO* } if ( compressiontype == MAX_INT ) - compressiontype = thd->variables.infinidb_compression_type; + compressiontype = get_compression_type(thd); else if ( compressiontype < 0 ) { string emsg = IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE); @@ -2269,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 } @@ -2279,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; @@ -2295,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"); @@ -2334,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()); @@ -2343,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. @@ -2395,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; @@ -2418,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); @@ -2473,12 +2505,12 @@ extern "C" if ( thd->db.length ) db = thd->db.str; - int compressiontype = thd->variables.infinidb_compression_type; + int compressiontype = get_compression_type(thd); if (compressiontype == 1) compressiontype = 2; if ( compressiontype == MAX_INT ) - compressiontype = thd->variables.infinidb_compression_type; + compressiontype = get_compression_type(thd); //hdfs if ((compressiontype == 0) && (useHdfs)) diff --git a/dbcon/mysql/ha_calpont_dml.cpp b/dbcon/mysql/ha_calpont_dml.cpp index 43bdc8cd6..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 @@ -1062,6 +1062,7 @@ int ha_calpont_impl_write_batch_row_(uchar* buf, TABLE* table, cal_impl_if::cal_ } case CalpontSystemCatalog::INT: + case CalpontSystemCatalog::MEDINT: { if (nullVal && (ci.columnTypes[colpos].constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT)) fprintf(ci.filePtr, "%c", ci.delimiter); @@ -1073,6 +1074,7 @@ int ha_calpont_impl_write_batch_row_(uchar* buf, TABLE* table, cal_impl_if::cal_ } case CalpontSystemCatalog::UINT: + case CalpontSystemCatalog::UMEDINT: { if (nullVal && (ci.columnTypes[colpos].constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT)) fprintf(ci.filePtr, "%c", ci.delimiter); @@ -1173,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 914743a25..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 @@ -58,6 +58,7 @@ using namespace logging; #include "idb_mysql.h" #include "ha_calpont_impl_if.h" +#include "ha_mcs_sysvars.h" #include "ha_subquery.h" //#include "ha_view.h" using namespace cal_impl_if; @@ -1442,10 +1443,10 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip) } } - if (!(gwip->thd->infinidb_vtable.cal_conn_info)) - gwip->thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(gwip->thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); if (ifp->functype() == Item_func::BETWEEN) @@ -2466,10 +2467,10 @@ void setError(THD* thd, uint32_t errcode, string errmsg) thd->infinidb_vtable.override_largeside_estimate = false; // reset expressionID - if (!(thd->infinidb_vtable.cal_conn_info)) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); ci->expressionId = 0; } @@ -3104,10 +3105,10 @@ ArithmeticColumn* buildArithmeticColumn( bool& nonSupport, bool pushdownHand) { - if (!(gwi.thd->infinidb_vtable.cal_conn_info)) - gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(gwi.thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); ArithmeticColumn* ac = new ArithmeticColumn(); Item** sfitempp = item->arguments(); @@ -3275,7 +3276,7 @@ ArithmeticColumn* buildArithmeticColumn( //idbassert(pt->left() && pt->right() && pt->left()->data() && pt->right()->data()); CalpontSystemCatalog::ColType mysql_type = colType_MysqlToIDB(item); - if (current_thd->variables.infinidb_double_for_decimal_math == 1) + if (get_double_for_decimal_math(current_thd) == true) aop->adjustResultType(mysql_type); else aop->resultType(mysql_type); @@ -3329,10 +3330,10 @@ ReturnedColumn* buildFunctionColumn( bool& nonSupport, bool pushdownHand) { - if (!(gwi.thd->infinidb_vtable.cal_conn_info)) - gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(gwi.thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); string funcName = ifp->func_name(); FuncExp* funcExp = FuncExp::instance(); @@ -3372,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); @@ -3801,10 +3801,10 @@ ReturnedColumn* buildFunctionColumn( FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonSupport) { - if (!(gwi.thd->infinidb_vtable.cal_conn_info)) - gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(gwi.thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); FunctionColumn* fc = new FunctionColumn(); FunctionParm funcParms; @@ -4194,10 +4194,10 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi) vector selCols; vector orderCols; bool bIsConst = false; - if (!(gwi.thd->infinidb_vtable.cal_conn_info)) - gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(gwi.thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); Item_sum* isp = reinterpret_cast(item); Item** sfitempp = isp->get_orig_args(); @@ -4499,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 || @@ -4549,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 || @@ -5775,7 +5706,8 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i return ER_CHECK_NOT_IMPLEMENTED; } - gwi.internalDecimalScale = (gwi.thd->variables.infinidb_use_decimal_scale ? gwi.thd->variables.infinidb_decimal_scale : -1); + gwi.internalDecimalScale = (get_use_decimal_scale(gwi.thd) ? get_decimal_scale(gwi.thd) : -1); + gwi.subSelectType = csep->subType(); JOIN* join = select_lex.join; @@ -5808,25 +5740,25 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i // @bug 2123. Override large table estimate if infinidb_ordered hint was used. // @bug 2404. Always override if the infinidb_ordered_only variable is turned on. - if (gwi.thd->infinidb_vtable.override_largeside_estimate || gwi.thd->variables.infinidb_ordered_only) + if (gwi.thd->infinidb_vtable.override_largeside_estimate || get_ordered_only(gwi.thd)) csep->overrideLargeSideEstimate(true); // @bug 5741. Set a flag when in Local PM only query mode - csep->localQuery(gwi.thd->variables.infinidb_local_query); + csep->localQuery(get_local_query(gwi.thd)); // @bug 3321. Set max number of blocks in a dictionary file to be scanned for filtering - csep->stringScanThreshold(gwi.thd->variables.infinidb_string_scan_threshold); + csep->stringScanThreshold(get_string_scan_threshold(gwi.thd)); - csep->stringTableThreshold(gwi.thd->variables.infinidb_stringtable_threshold); + csep->stringTableThreshold(get_stringtable_threshold(gwi.thd)); - csep->djsSmallSideLimit(gwi.thd->variables.infinidb_diskjoin_smallsidelimit * 1024ULL * 1024); - csep->djsLargeSideLimit(gwi.thd->variables.infinidb_diskjoin_largesidelimit * 1024ULL * 1024); - csep->djsPartitionSize(gwi.thd->variables.infinidb_diskjoin_bucketsize * 1024ULL * 1024); + csep->djsSmallSideLimit(get_diskjoin_smallsidelimit(gwi.thd) * 1024ULL * 1024); + csep->djsLargeSideLimit(get_diskjoin_largesidelimit(gwi.thd) * 1024ULL * 1024); + csep->djsPartitionSize(get_diskjoin_bucketsize(gwi.thd) * 1024ULL * 1024); - if (gwi.thd->variables.infinidb_um_mem_limit == 0) + if (get_um_mem_limit(gwi.thd) == 0) csep->umMemLimit(numeric_limits::max()); else - csep->umMemLimit(gwi.thd->variables.infinidb_um_mem_limit * 1024ULL * 1024); + csep->umMemLimit(get_um_mem_limit(gwi.thd) * 1024ULL * 1024); // populate table map and trigger syscolumn cache for all the tables (@bug 1637). // all tables on FROM list must have at least one col in colmap @@ -8241,7 +8173,7 @@ int cp_get_table_plan(THD* thd, SCSEP& csep, cal_table_info& ti) csep->tableList(tblist); // @bug 3321. Set max number of blocks in a dictionary file to be scanned for filtering - csep->stringScanThreshold(gwi->thd->variables.infinidb_string_scan_threshold); + csep->stringScanThreshold(get_string_scan_threshold(gwi->thd)); return 0; } @@ -8339,7 +8271,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro return ER_CHECK_NOT_IMPLEMENTED; } - gwi.internalDecimalScale = (gwi.thd->variables.infinidb_use_decimal_scale ? gwi.thd->variables.infinidb_decimal_scale : -1); + gwi.internalDecimalScale = (get_use_decimal_scale(gwi.thd) ? get_decimal_scale(gwi.thd) : -1); gwi.subSelectType = csep->subType(); JOIN* join = select_lex.join; @@ -8356,25 +8288,25 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro // @bug 2123. Override large table estimate if infinidb_ordered hint was used. // @bug 2404. Always override if the infinidb_ordered_only variable is turned on. - if (gwi.thd->infinidb_vtable.override_largeside_estimate || gwi.thd->variables.infinidb_ordered_only) + if (gwi.thd->infinidb_vtable.override_largeside_estimate || get_ordered_only(gwi.thd)) csep->overrideLargeSideEstimate(true); // @bug 5741. Set a flag when in Local PM only query mode - csep->localQuery(gwi.thd->variables.infinidb_local_query); + csep->localQuery(get_local_query(gwi.thd)); // @bug 3321. Set max number of blocks in a dictionary file to be scanned for filtering - csep->stringScanThreshold(gwi.thd->variables.infinidb_string_scan_threshold); + csep->stringScanThreshold(get_string_scan_threshold(gwi.thd)); - csep->stringTableThreshold(gwi.thd->variables.infinidb_stringtable_threshold); + csep->stringTableThreshold(get_stringtable_threshold(gwi.thd)); - csep->djsSmallSideLimit(gwi.thd->variables.infinidb_diskjoin_smallsidelimit * 1024ULL * 1024); - csep->djsLargeSideLimit(gwi.thd->variables.infinidb_diskjoin_largesidelimit * 1024ULL * 1024); - csep->djsPartitionSize(gwi.thd->variables.infinidb_diskjoin_bucketsize * 1024ULL * 1024); + csep->djsSmallSideLimit(get_diskjoin_smallsidelimit(gwi.thd) * 1024ULL * 1024); + csep->djsLargeSideLimit(get_diskjoin_largesidelimit(gwi.thd) * 1024ULL * 1024); + csep->djsPartitionSize(get_diskjoin_bucketsize(gwi.thd) * 1024ULL * 1024); - if (gwi.thd->variables.infinidb_um_mem_limit == 0) + if (get_um_mem_limit(gwi.thd) == 0) csep->umMemLimit(numeric_limits::max()); else - csep->umMemLimit(gwi.thd->variables.infinidb_um_mem_limit * 1024ULL * 1024); + csep->umMemLimit(get_um_mem_limit(gwi.thd) * 1024ULL * 1024); // populate table map and trigger syscolumn cache for all the tables (@bug 1637). // all tables on FROM list must have at least one col in colmap diff --git a/dbcon/mysql/ha_calpont_impl.cpp b/dbcon/mysql/ha_calpont_impl.cpp index 3be44d2b8..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 @@ -142,6 +142,7 @@ using namespace funcexp; #include "installdir.h" #include "columnstoreversion.h" +#include "ha_mcs_sysvars.h" namespace cal_impl_if { @@ -168,7 +169,7 @@ static const string interval_names[] = const unsigned NONSUPPORTED_ERR_THRESH = 2000; //TODO: make this session-safe (put in connMap?) -vector rmParms; +//vector rmParms; ResourceManager* rm = ResourceManager::instance(); bool useHdfs = rm->useHdfs(); @@ -220,6 +221,14 @@ void storeNumericField(Field** f, int64_t value, CalpontSystemCatalog::ColType& break; } + case MYSQL_TYPE_INT24: //MEDINT type + { + Field_medium* f2 = (Field_medium*)*f; + longlong int_val = (longlong)value; + f2->store(int_val, f2->unsigned_flag); + break; + } + case MYSQL_TYPE_LONG: //INT type { Field_long* f2 = (Field_long*)*f; @@ -559,7 +568,7 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, bool h { Field_varstring* f2 = (Field_varstring*)*f; - if (current_thd->variables.infinidb_varbin_always_hex) + if (get_varbin_always_hex(current_thd)) { uint32_t l; const uint8_t* p = row.getVarBinaryField(l, s); @@ -592,6 +601,7 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, bool h } case CalpontSystemCatalog::INT: + case CalpontSystemCatalog::MEDINT: { intColVal = row.getIntField<4>(s); storeNumericField(f, intColVal, colType); @@ -599,6 +609,7 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, bool h } case CalpontSystemCatalog::UINT: + case CalpontSystemCatalog::UMEDINT: { uintColVal = row.getUintField<4>(s); storeNumericField(f, uintColVal, colType); @@ -703,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: { @@ -761,7 +827,7 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, bool h ti.moreRows = false; rc = logging::ERR_LOST_CONN_EXEMGR; sm::sm_init(tid2sid(current_thd->thread_id), &ci->cal_conn_hndl, - current_thd->variables.infinidb_local_query); + get_local_query(current_thd)); idbassert(ci->cal_conn_hndl != 0); ci->rc = rc; } @@ -865,10 +931,10 @@ void makeUpdateSemiJoin(const ParseTree* n, void* obj) uint32_t doUpdateDelete(THD* thd) { - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); //@bug 5660. Error out DDL/DML on slave node, or on local query node if (ci->isSlaveNode && !thd->slave_thread) @@ -1592,7 +1658,7 @@ uint32_t doUpdateDelete(THD* thd) ByteStream bytestream, bytestream1; bytestream << sessionID; boost::shared_ptr plan = pDMLPackage->get_ExecutionPlan(); - updateCP->rmParms(rmParms); + updateCP->rmParms(ci->rmParms); updateCP->serialize(*plan); // recover original vtable state thd->infinidb_vtable.vtable_state = origState; @@ -1907,835 +1973,6 @@ uint32_t doUpdateDelete(THD* thd) } //anon namespace -extern "C" -{ -#ifdef _MSC_VER - __declspec(dllexport) -#endif - const char* calgetstats(UDF_INIT* initid, UDF_ARGS* args, - char* result, unsigned long* length, - char* is_null, char* error) - { - THD* thd = current_thd; - - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); - - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); - - unsigned long l = ci->queryStats.size(); - - if (l == 0) - { - *is_null = 1; - return 0; - } - - if (l > 255) l = 255; - - memcpy(result, ci->queryStats.c_str(), l); - *length = l; - return result; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool calgetstats_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - if (args->arg_count != 0) - { - strcpy(message, "CALGETSTATS() takes no arguments"); - return 1; - } - - initid->maybe_null = 1; - initid->max_length = 255; - - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void calgetstats_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - long long calsettrace(UDF_INIT* initid, UDF_ARGS* args, - char* is_null, char* error) - { - THD* thd = current_thd; - - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); - - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); - - long long oldTrace = ci->traceFlags; - ci->traceFlags = (uint32_t)(*((long long*)args->args[0])); - // keep the vtablemode bit - ci->traceFlags |= (oldTrace & CalpontSelectExecutionPlan::TRACE_TUPLE_OFF); - ci->traceFlags |= (oldTrace & CalpontSelectExecutionPlan::TRACE_TUPLE_AUTOSWITCH); - return oldTrace; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool calsettrace_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - if (args->arg_count != 1 || args->arg_type[0] != INT_RESULT) - { - strcpy(message, "CALSETTRACE() requires one INTEGER argument"); - return 1; - } - - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void calsettrace_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif -// Return 1 if system is ready for reads or 0 if not. - long long mcssystemready(UDF_INIT* initid, UDF_ARGS* args, - char* is_null, char* error) - { - long long rtn = 0; - Oam oam; - DBRM dbrm(true); - SystemStatus systemstatus; - - try - { - oam.getSystemStatus(systemstatus); - - if (systemstatus.SystemOpState == ACTIVE - && dbrm.getSystemReady() - && dbrm.getSystemQueryReady()) - { - return 1; - } - } - catch (...) - { - *error = 1; - } - - return rtn; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool mcssystemready_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void mcssystemready_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif -// Return non-zero if system is read only; 0 if writeable - long long mcssystemreadonly(UDF_INIT* initid, UDF_ARGS* args, - char* is_null, char* error) - { - long long rtn = 0; - DBRM dbrm(true); - - try - { - if (dbrm.getSystemSuspended()) - { - rtn = 1; - } - - if (dbrm.isReadWrite() > 0) // Returns 0 for writable, 5 for read only - { - rtn = 2; - } - } - catch (...) - { - *error = 1; - rtn = 1; - } - - return rtn; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool mcssystemreadonly_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void mcssystemreadonly_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif -// Return non-zero if this is the primary UM; 0 if not primary - long long mcssystemprimary(UDF_INIT* initid, UDF_ARGS* args, - char* is_null, char* error) - { - long long rtn = 0; - Oam oam; - string PrimaryUMModuleName; - string localModule; - oamModuleInfo_t st; - - try - { - st = oam.getModuleInfo(); - localModule = boost::get<0>(st); - PrimaryUMModuleName = config::Config::makeConfig()->getConfig("SystemConfig", "PrimaryUMModuleName"); - - if (boost::iequals(localModule, PrimaryUMModuleName)) - rtn = 1; - if (PrimaryUMModuleName == "unassigned") - rtn = 1; - } - catch (runtime_error& e) - { - // It's difficult to return an error message from a numerical UDF - //string msg = string("ERROR: Problem getting Primary UM Module Name. ") + e.what(); - *error = 1; - } - catch (...) - { - *error = 1; - } - return rtn; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool mcssystemprimary_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void mcssystemprimary_deinit(UDF_INIT* initid) - { - } - -#define MAXSTRINGLENGTH 50 - - const char* PmSmallSideMaxMemory = "pmmaxmemorysmallside"; - - const char* SetParmsPrelude = "Updated "; - const char* SetParmsError = "Invalid parameter: "; - const char* InvalidParmSize = "Invalid parameter size: Input value cannot be larger than "; - - const size_t Plen = strlen(SetParmsPrelude); - const size_t Elen = strlen(SetParmsError); - - const char* invalidParmSizeMessage(uint64_t size, size_t& len) - { - static char str[sizeof(InvalidParmSize) + 12] = {0}; - ostringstream os; - os << InvalidParmSize << size; - len = os.str().length(); - strcpy(str, os.str().c_str()); - return str; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - const char* calsetparms(UDF_INIT* initid, UDF_ARGS* args, - char* result, unsigned long* length, - char* is_null, char* error) - { - char parameter[MAXSTRINGLENGTH]; - char valuestr[MAXSTRINGLENGTH]; - size_t plen = args->lengths[0]; - size_t vlen = args->lengths[1]; - - memcpy(parameter, args->args[0], plen); - memcpy(valuestr, args->args[1], vlen); - - parameter[plen] = '\0'; - valuestr[vlen] = '\0'; - - uint64_t value = Config::uFromText(valuestr); - - THD* thd = current_thd; - uint32_t sessionID = tid2sid(thd->thread_id); - - const char* msg = SetParmsError; - size_t mlen = Elen; - bool includeInput = true; - - string pstr(parameter); - boost::algorithm::to_lower(pstr); - - if (pstr == PmSmallSideMaxMemory) - { - joblist::ResourceManager* rm = joblist::ResourceManager::instance(); - - if (rm->getHjTotalUmMaxMemorySmallSide() >= value) - { - rmParms.push_back(RMParam(sessionID, execplan::PMSMALLSIDEMEMORY, value)); - - msg = SetParmsPrelude; - mlen = Plen; - } - else - { - msg = invalidParmSizeMessage(rm->getHjTotalUmMaxMemorySmallSide(), mlen); - includeInput = false; - } - } - - memcpy(result, msg, mlen); - - if (includeInput) - { - memcpy(result + mlen, parameter, plen); - mlen += plen; - memcpy(result + mlen++, " ", 1); - memcpy(result + mlen, valuestr, vlen); - *length = mlen + vlen; - } - else - *length = mlen; - - return result; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool calsetparms_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - if (args->arg_count != 2 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT) - { - strcpy(message, "CALSETPARMS() requires two string arguments"); - return 1; - } - - initid->max_length = MAXSTRINGLENGTH; - - char valuestr[MAXSTRINGLENGTH]; - size_t vlen = args->lengths[1]; - - memcpy(valuestr, args->args[1], vlen--); - - for (size_t i = 0; i < vlen; ++i) - if (!isdigit(valuestr[i])) - { - strcpy(message, "CALSETPARMS() second argument must be numeric or end in G, M or K"); - return 1; - } - - if (!isdigit(valuestr[vlen])) - { - switch (valuestr[vlen]) - { - case 'G': - case 'g': - case 'M': - case 'm': - case 'K': - case 'k': - case '\0': - break; - - default: - strcpy(message, "CALSETPARMS() second argument must be numeric or end in G, M or K"); - return 1; - } - } - - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void calsetparms_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool calviewtablelock_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - if (args->arg_count == 2 && (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT)) - { - strcpy(message, "CALVIEWTABLELOCK() requires two string arguments"); - return 1; - } - else if ((args->arg_count == 1) && (args->arg_type[0] != STRING_RESULT ) ) - { - strcpy(message, "CALVIEWTABLELOCK() requires one string argument"); - return 1; - } - else if (args->arg_count > 2 ) - { - strcpy(message, "CALVIEWTABLELOCK() takes one or two arguments only"); - return 1; - } - else if (args->arg_count == 0 ) - { - strcpy(message, "CALVIEWTABLELOCK() requires at least one argument"); - return 1; - } - - initid->maybe_null = 1; - initid->max_length = 255; - - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - const char* calviewtablelock(UDF_INIT* initid, UDF_ARGS* args, - char* result, unsigned long* length, - char* is_null, char* error) - { - THD* thd = current_thd; - - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); - - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); - CalpontSystemCatalog::TableName tableName; - - if ( args->arg_count == 2 ) - { - tableName.schema = args->args[0]; - tableName.table = args->args[1]; - } - else if ( args->arg_count == 1 ) - { - tableName.table = args->args[0]; - - if (thd->db.length) - tableName.schema = thd->db.str; - else - { - string msg("No schema information provided"); - memcpy(result, msg.c_str(), msg.length()); - *length = msg.length(); - return result; - } - } - - if ( !ci->dmlProc ) - { - ci->dmlProc = new MessageQueueClient("DMLProc"); - //cout << "viewtablelock starts a new client " << ci->dmlProc << " for session " << thd->thread_id << endl; - } - - string lockinfo = ha_calpont_impl_viewtablelock(*ci, tableName); - - memcpy(result, lockinfo.c_str(), lockinfo.length()); - *length = lockinfo.length(); - return result; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void calviewtablelock_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool calcleartablelock_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - if ((args->arg_count != 1) || (args->arg_type[0] != INT_RESULT)) - { - strcpy(message, - "CALCLEARTABLELOCK() requires one integer argument (the lockID)"); - return 1; - } - - initid->maybe_null = 1; - initid->max_length = 255; - - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - const char* calcleartablelock(UDF_INIT* initid, UDF_ARGS* args, - char* result, unsigned long* length, - char* is_null, char* error) - { - THD* thd = current_thd; - - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); - - cal_connection_info* ci = reinterpret_cast( - thd->infinidb_vtable.cal_conn_info); - long long lockID = *reinterpret_cast(args->args[0]); - - if ( !ci->dmlProc ) - { - ci->dmlProc = new MessageQueueClient("DMLProc"); - //cout << "cleartablelock starts a new client " << ci->dmlProc << " for session " << thd->thread_id << endl; - } - - unsigned long long uLockID = lockID; - string lockinfo = ha_calpont_impl_cleartablelock(*ci, uLockID); - - memcpy(result, lockinfo.c_str(), lockinfo.length()); - *length = lockinfo.length(); - return result; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void calcleartablelock_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool callastinsertid_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - if (args->arg_count == 2 && (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT)) - { - strcpy(message, "CALLASTINSRTID() requires two string arguments"); - return 1; - } - else if ((args->arg_count == 1) && (args->arg_type[0] != STRING_RESULT ) ) - { - strcpy(message, "CALLASTINSERTID() requires one string argument"); - return 1; - } - else if (args->arg_count > 2 ) - { - strcpy(message, "CALLASTINSERTID() takes one or two arguments only"); - return 1; - } - else if (args->arg_count == 0 ) - { - strcpy(message, "CALLASTINSERTID() requires at least one argument"); - return 1; - } - - initid->maybe_null = 1; - initid->max_length = 255; - - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - long long callastinsertid(UDF_INIT* initid, UDF_ARGS* args, - char* is_null, char* error) - { - THD* thd = current_thd; - - CalpontSystemCatalog::TableName tableName; - uint64_t nextVal = 0; - - if ( args->arg_count == 2 ) - { - tableName.schema = args->args[0]; - tableName.table = args->args[1]; - } - else if ( args->arg_count == 1 ) - { - tableName.table = args->args[0]; - - if (thd->db.length) - tableName.schema = thd->db.str; - else - { - return -1; - } - } - - boost::shared_ptr csc = CalpontSystemCatalog::makeCalpontSystemCatalog(tid2sid(thd->thread_id)); - csc->identity(execplan::CalpontSystemCatalog::FE); - - try - { - nextVal = csc->nextAutoIncrValue(tableName); - } - catch (std::exception&) - { - string msg("No such table found during autincrement"); - setError(thd, ER_INTERNAL_ERROR, msg); - return nextVal; - } - - if (nextVal == AUTOINCR_SATURATED) - { - setError(thd, ER_INTERNAL_ERROR, IDBErrorInfo::instance()->errorMsg(ERR_EXCEED_LIMIT)); - return nextVal; - } - - //@Bug 3559. Return a message for table without autoincrement column. - if (nextVal == 0) - { - string msg("Autoincrement does not exist for this table."); - setError(thd, ER_INTERNAL_ERROR, msg); - return nextVal; - } - - return (nextVal - 1); - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void callastinsertid_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void calflushcache_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - long long calflushcache(UDF_INIT* initid, UDF_ARGS* args, - char* is_null, char* error) - { - return static_cast(cacheutils::flushPrimProcCache()); - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool calflushcache_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - if (args->arg_count != 0) - { - strcpy(message, "CALFLUSHCACHE() takes no arguments"); - return 1; - } - - return 0; - } - - static const unsigned long TraceSize = 16 * 1024; - -//mysqld will call this with only 766 bytes available in result no matter what we asked for in calgettrace_init() -// if we return a pointer that is not result, mysqld will take our pointer and use it, freeing up result -#ifdef _MSC_VER - __declspec(dllexport) -#endif - const char* calgettrace(UDF_INIT* initid, UDF_ARGS* args, - char* result, unsigned long* length, - char* is_null, char* error) - { - THD* thd = current_thd; - const string* msgp; - int flags = 0; - - if (args->arg_count > 0) - { - if (args->arg_type[0] == INT_RESULT) - { - flags = *reinterpret_cast(args->args[0]); - } - } - - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); - - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); - - if (flags > 0) - //msgp = &connMap[sessionID].extendedStats; - msgp = &ci->extendedStats; - else - //msgp = &connMap[sessionID].miniStats; - msgp = &ci->miniStats; - - unsigned long l = msgp->size(); - - if (l == 0) - { - *is_null = 1; - return 0; - } - - if (l > TraceSize) l = TraceSize; - - *length = l; - return msgp->c_str(); - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool calgettrace_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { -#if 0 - - if (args->arg_count != 0) - { - strcpy(message, "CALGETTRACE() takes no arguments"); - return 1; - } - -#endif - initid->maybe_null = 1; - initid->max_length = TraceSize; - - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void calgettrace_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - const char* calgetversion(UDF_INIT* initid, UDF_ARGS* args, - char* result, unsigned long* length, - char* is_null, char* error) - { - string version(columnstore_version); - *length = version.size(); - memcpy(result, version.c_str(), *length); - return result; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool calgetversion_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - if (args->arg_count != 0) - { - strcpy(message, "CALGETVERSION() takes no arguments"); - return 1; - } - - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void calgetversion_deinit(UDF_INIT* initid) - { - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - const char* calgetsqlcount(UDF_INIT* initid, UDF_ARGS* args, - char* result, unsigned long* length, - char* is_null, char* error) - { - THD* thd = current_thd; - - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); - - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); - idbassert(ci != 0); - - MessageQueueClient* mqc = 0; - mqc = new MessageQueueClient("ExeMgr1"); - - ByteStream msg; - ByteStream::quadbyte runningSql, waitingSql; - ByteStream::quadbyte qb = 5; - msg << qb; - mqc->write(msg); - - //get ExeMgr response - msg.restart(); - msg = mqc->read(); - - if (msg.length() == 0) - { - memcpy(result, "Lost connection to ExeMgr", *length); - return result; - } - - msg >> runningSql; - msg >> waitingSql; - delete mqc; - - char ans[128]; - sprintf(ans, "Running SQL statements %d, Waiting SQL statments %d", runningSql, waitingSql); - *length = strlen(ans); - memcpy(result, ans, *length); - return result; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - my_bool calgetsqlcount_init(UDF_INIT* initid, UDF_ARGS* args, char* message) - { - if (args->arg_count != 0) - { - strcpy(message, "CALGETSQLCOUNT() takes no arguments"); - return 1; - } - - return 0; - } - -#ifdef _MSC_VER - __declspec(dllexport) -#endif - void calgetsqlcount_deinit(UDF_INIT* initid) - { - } - - -} //extern "C" - int ha_calpont_impl_open(const char* name, int mode, uint32_t test_if_locked) { IDEBUG ( cout << "ha_calpont_impl_open: " << name << ", " << mode << ", " << test_if_locked << endl ); @@ -2867,10 +2104,10 @@ int ha_calpont_impl_rnd_init(TABLE* table) boost::shared_ptr csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID); csc->identity(CalpontSystemCatalog::FE); - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); idbassert(ci != 0); @@ -2924,7 +2161,7 @@ int ha_calpont_impl_rnd_init(TABLE* table) CalpontSelectExecutionPlan::TRACE_TUPLE_OFF; } - bool localQuery = (thd->variables.infinidb_local_query > 0 ? true : false); + bool localQuery = get_local_query(thd); // table mode if (thd->infinidb_vtable.vtable_state == THD::INFINIDB_DISABLE_VTABLE) @@ -3145,7 +2382,7 @@ int ha_calpont_impl_rnd_init(TABLE* table) msg << qb; hndl->exeMgr->write(msg); msg.restart(); - csep->rmParms(rmParms); + csep->rmParms(ci->rmParms); //send plan csep->serialize(msg); @@ -3205,7 +2442,7 @@ int ha_calpont_impl_rnd_init(TABLE* table) return ER_INTERNAL_ERROR; } - rmParms.clear(); + ci->rmParms.clear(); if (thd->infinidb_vtable.vtable_state == THD::INFINIDB_DISABLE_VTABLE) { @@ -3405,10 +2642,10 @@ int ha_calpont_impl_rnd_next(uchar* buf, TABLE* table) return ER_INTERNAL_ERROR; } - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); // @bug 3078 if (thd->killed == KILL_QUERY || thd->killed == KILL_QUERY_HARD) @@ -3506,8 +2743,8 @@ int ha_calpont_impl_rnd_end(TABLE* table) thd->infinidb_vtable.isNewQuery = true; - if (thd->infinidb_vtable.cal_conn_info) - ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + if (get_fe_conn_info_ptr() != NULL) + ci = reinterpret_cast(get_fe_conn_info_ptr()); if (thd->infinidb_vtable.vtable_state == THD::INFINIDB_ORDER_BY ) { @@ -3555,8 +2792,8 @@ int ha_calpont_impl_rnd_end(TABLE* table) if (!ci) { - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); - ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + set_fe_conn_info_ptr((void*)new cal_connection_info()); + ci = reinterpret_cast(get_fe_conn_info_ptr()); } // @bug 3078. Also session limit variable works the same as ctrl+c @@ -3676,10 +2913,10 @@ int ha_calpont_impl_create(const char* name, TABLE* table_arg, HA_CREATE_INFO* c { THD* thd = current_thd; - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); // @bug1940 Do nothing for select query. Support of set default engine to IDB. if (thd->infinidb_vtable.vtable_state == THD::INFINIDB_CREATE_VTABLE || @@ -3725,10 +2962,10 @@ int ha_calpont_impl_delete_table(const char* name) if (string(name).find("@0024vtable") != string::npos) return 0; - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); if (!thd) return 0; @@ -3801,10 +3038,10 @@ int ha_calpont_impl_write_row(uchar* buf, TABLE* table) } } - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); if (thd->slave_thread) return 0; @@ -3847,10 +3084,10 @@ int ha_calpont_impl_update_row() //@Bug 2540. Return the correct error code. THD* thd = current_thd; - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); int rc = ci->rc; if ( rc != 0 ) @@ -3864,10 +3101,10 @@ int ha_calpont_impl_delete_row() //@Bug 2540. Return the correct error code. THD* thd = current_thd; - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); int rc = ci->rc; if ( rc != 0 ) @@ -3880,10 +3117,10 @@ void ha_calpont_impl_start_bulk_insert(ha_rows rows, TABLE* table) { THD* thd = current_thd; - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); // clear rows variable ci->rowsHaveInserted = 0; @@ -3948,7 +3185,7 @@ void ha_calpont_impl_start_bulk_insert(ha_rows rows, TABLE* table) ((thd->lex)->sql_command == SQLCOM_LOAD) || (thd->lex)->sql_command == SQLCOM_INSERT_SELECT) && !ci->singleInsert ) { - ci->useCpimport = thd->variables.infinidb_use_import_for_batchinsert; + ci->useCpimport = get_use_import_for_batchinsert(thd); if (((thd->lex)->sql_command == SQLCOM_INSERT) && (rows > 0)) ci->useCpimport = 0; @@ -4021,14 +3258,14 @@ void ha_calpont_impl_start_bulk_insert(ha_rows rows, TABLE* table) ci->mysqld_pid = getpid(); //get delimiter - if (char(thd->variables.infinidb_import_for_batchinsert_delimiter) != '\007') - ci->delimiter = char(thd->variables.infinidb_import_for_batchinsert_delimiter); + if (char(get_import_for_batchinsert_delimiter(thd)) != '\007') + ci->delimiter = char(get_import_for_batchinsert_delimiter(thd)); else ci->delimiter = '\007'; //get enclosed by - if (char(thd->variables.infinidb_import_for_batchinsert_enclosed_by) != 8) - ci->enclosed_by = char(thd->variables.infinidb_import_for_batchinsert_enclosed_by); + if (char(get_import_for_batchinsert_enclosed_by(thd)) != 8) + ci->enclosed_by = char(get_import_for_batchinsert_enclosed_by(thd)); else ci->enclosed_by = 8; @@ -4044,7 +3281,7 @@ void ha_calpont_impl_start_bulk_insert(ha_rows rows, TABLE* table) if (ci->enclosed_by == 34) // Double quotes strcat(escapechar, "\\"); - if (thd->variables.infinidb_local_query > 0 ) + if (get_local_query(thd)) { OamCache* oamcache = OamCache::makeOamCache(); int localModuleId = oamcache->getLocalPMId(); @@ -4448,10 +3685,10 @@ int ha_calpont_impl_end_bulk_insert(bool abort, TABLE* table) std::string aTmpDir(startup::StartUp::tmpDir()); - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); if (thd->slave_thread) return 0; @@ -4706,10 +3943,10 @@ int ha_calpont_impl_commit (handlerton* hton, THD* thd, bool all) thd->infinidb_vtable.vtable_state == THD::INFINIDB_REDO_PHASE1) return 0; - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); if (ci->isAlter) return 0; @@ -4747,10 +3984,10 @@ int ha_calpont_impl_rollback (handlerton* hton, THD* thd, bool all) // return 0; //} - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); if ( !ci->dmlProc ) { @@ -4777,10 +4014,10 @@ int ha_calpont_impl_close_connection (handlerton* hton, THD* thd) execplan::CalpontSystemCatalog::removeCalpontSystemCatalog(tid2sid(thd->thread_id)); - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); if (!ci) return 0; @@ -4807,10 +4044,10 @@ int ha_calpont_impl_rename_table(const char* from, const char* to) IDEBUG( cout << "ha_calpont_impl_rename_table: " << from << " => " << to << endl ); THD* thd = current_thd; - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); //@Bug 1948. Alter table call rename table twice if ( ci->alterTableState == cal_connection_info::ALTER_FIRST_RENAME ) @@ -4858,10 +4095,10 @@ COND* ha_calpont_impl_cond_push(COND* cond, TABLE* table) alias.assign(table->alias.ptr(), table->alias.length()); IDEBUG( cout << "ha_calpont_impl_cond_push: " << alias << endl ); - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); cal_table_info ti = ci->tableMap[table]; @@ -4939,10 +4176,10 @@ int ha_calpont_impl_external_lock(THD* thd, TABLE* table, int lock_type) if ( thd->infinidb_vtable.vtable_state == THD::INFINIDB_INIT ) return 0; - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); if (thd->killed == KILL_QUERY || thd->killed == KILL_QUERY_HARD) { @@ -5104,10 +4341,10 @@ int ha_calpont_impl_group_by_init(ha_calpont_group_by_handler* group_hand, TABLE boost::shared_ptr csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID); csc->identity(CalpontSystemCatalog::FE); - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); idbassert(ci != 0); @@ -5149,7 +4386,7 @@ int ha_calpont_impl_group_by_init(ha_calpont_group_by_handler* group_hand, TABLE sm::cpsm_conhdl_t* hndl; SCSEP csep; - bool localQuery = (thd->variables.infinidb_local_query > 0 ? true : false); + bool localQuery = get_local_query(thd); { ci->stats.reset(); // reset query stats @@ -5328,7 +4565,7 @@ int ha_calpont_impl_group_by_init(ha_calpont_group_by_handler* group_hand, TABLE msg << qb; hndl->exeMgr->write(msg); msg.restart(); - csep->rmParms(rmParms); + csep->rmParms(ci->rmParms); //send plan csep->serialize(msg); @@ -5388,7 +4625,7 @@ int ha_calpont_impl_group_by_init(ha_calpont_group_by_handler* group_hand, TABLE return ER_INTERNAL_ERROR; } - rmParms.clear(); + ci->rmParms.clear(); if (thd->infinidb_vtable.vtable_state == THD::INFINIDB_DISABLE_VTABLE) { @@ -5606,10 +4843,10 @@ int ha_calpont_impl_group_by_next(ha_calpont_group_by_handler* group_hand, TABLE return ER_INTERNAL_ERROR; } */ - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); // @bug 3078 if (thd->killed == KILL_QUERY || thd->killed == KILL_QUERY_HARD) @@ -5710,8 +4947,8 @@ int ha_calpont_impl_group_by_end(ha_calpont_group_by_handler* group_hand, TABLE* thd->infinidb_vtable.isNewQuery = true; thd->infinidb_vtable.isUnion = false; - if (thd->infinidb_vtable.cal_conn_info) - ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + if (get_fe_conn_info_ptr() != NULL) + ci = reinterpret_cast(get_fe_conn_info_ptr()); // MCOL-1052 //if (thd->infinidb_vtable.vtable_state == THD::INFINIDB_ORDER_BY ) @@ -5748,8 +4985,8 @@ int ha_calpont_impl_group_by_end(ha_calpont_group_by_handler* group_hand, TABLE* if (!ci) { - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); - ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + set_fe_conn_info_ptr((void*)new cal_connection_info()); + ci = reinterpret_cast(get_fe_conn_info_ptr()); } // @bug 3078. Also session limit variable works the same as ctrl+c diff --git a/dbcon/mysql/ha_calpont_impl.h b/dbcon/mysql/ha_calpont_impl.h index 7f7c43aae..bdc0e0eef 100644 --- a/dbcon/mysql/ha_calpont_impl.h +++ b/dbcon/mysql/ha_calpont_impl.h @@ -16,12 +16,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* - * $Id: ha_calpont_impl.h 9413 2013-04-22 22:03:42Z zzhu $ - */ - -/** @file */ - #ifndef HA_CALPONT_IMPL_H__ #define HA_CALPONT_IMPL_H__ diff --git a/dbcon/mysql/ha_calpont_impl_if.h b/dbcon/mysql/ha_calpont_impl_if.h index 72579111b..4f0046745 100644 --- a/dbcon/mysql/ha_calpont_impl_if.h +++ b/dbcon/mysql/ha_calpont_impl_if.h @@ -319,10 +319,10 @@ struct cal_connection_info char delimiter; char enclosed_by; std::vector columnTypes; + // MCOL-1101 remove compilation unit variable rmParms + std::vector rmParms; }; -typedef std::tr1::unordered_map CalConnMap; - const std::string infinidb_err_msg = "\nThe query includes syntax that is not supported by MariaDB Columnstore. Use 'show warnings;' to get more information. Review the MariaDB Columnstore Syntax guide for additional information on supported distributed syntax or consider changing the MariaDB Columnstore Operating Mode (infinidb_vtable_mode)."; int cp_get_plan(THD* thd, execplan::SCSEP& csep); 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_mcs_client_udfs.cpp b/dbcon/mysql/ha_mcs_client_udfs.cpp new file mode 100644 index 000000000..1766bdf1c --- /dev/null +++ b/dbcon/mysql/ha_mcs_client_udfs.cpp @@ -0,0 +1,871 @@ +/* Copyright (C) 2014 InfiniDB, Inc. + Copyright (C) 2016 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. */ + +#define NEED_CALPONT_INTERFACE +#include "ha_calpont_impl.h" + +#include "ha_calpont_impl_if.h" +using namespace cal_impl_if; + +#include "configcpp.h" +using namespace config; +#include "brmtypes.h" +using namespace BRM; +#include "bytestream.h" +using namespace messageqcpp; +#include "liboamcpp.h" +using namespace oam; +#include "cacheutils.h" + +#include "errorcodes.h" +#include "idberrorinfo.h" +#include "errorids.h" +using namespace logging; + +//#include "resourcemanager.h" + +#include "columnstoreversion.h" +#include "ha_mcs_sysvars.h" + +extern "C" +{ +#define MAXSTRINGLENGTH 50 + + const char* PmSmallSideMaxMemory = "pmmaxmemorysmallside"; + + const char* SetParmsPrelude = "Updated "; + const char* SetParmsError = "Invalid parameter: "; + const char* InvalidParmSize = "Invalid parameter size: Input value cannot be larger than "; + + const size_t Plen = strlen(SetParmsPrelude); + const size_t Elen = strlen(SetParmsError); + + const char* invalidParmSizeMessage(uint64_t size, size_t& len) + { + static char str[sizeof(InvalidParmSize) + 12] = {0}; + ostringstream os; + os << InvalidParmSize << size; + len = os.str().length(); + strcpy(str, os.str().c_str()); + return str; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + const char* calsetparms(UDF_INIT* initid, UDF_ARGS* args, + char* result, unsigned long* length, + char* is_null, char* error) + { + char parameter[MAXSTRINGLENGTH]; + char valuestr[MAXSTRINGLENGTH]; + size_t plen = args->lengths[0]; + size_t vlen = args->lengths[1]; + + memcpy(parameter, args->args[0], plen); + memcpy(valuestr, args->args[1], vlen); + + parameter[plen] = '\0'; + valuestr[vlen] = '\0'; + + uint64_t value = Config::uFromText(valuestr); + + THD* thd = current_thd; + uint32_t sessionID = CalpontSystemCatalog::idb_tid2sid(thd->thread_id); + + const char* msg = SetParmsError; + size_t mlen = Elen; + bool includeInput = true; + + string pstr(parameter); + boost::algorithm::to_lower(pstr); + + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); + + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); + idbassert(ci != 0); + + if (pstr == PmSmallSideMaxMemory) + { + joblist::ResourceManager* rm = joblist::ResourceManager::instance(); + + if (rm->getHjTotalUmMaxMemorySmallSide() >= value) + { + ci->rmParms.push_back(RMParam(sessionID, execplan::PMSMALLSIDEMEMORY, value)); + + msg = SetParmsPrelude; + mlen = Plen; + } + else + { + msg = invalidParmSizeMessage(rm->getHjTotalUmMaxMemorySmallSide(), mlen); + includeInput = false; + } + } + + memcpy(result, msg, mlen); + + if (includeInput) + { + memcpy(result + mlen, parameter, plen); + mlen += plen; + memcpy(result + mlen++, " ", 1); + memcpy(result + mlen, valuestr, vlen); + *length = mlen + vlen; + } + else + *length = mlen; + + return result; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool calsetparms_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + if (args->arg_count != 2 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT) + { + strcpy(message, "CALSETPARMS() requires two string arguments"); + return 1; + } + + initid->max_length = MAXSTRINGLENGTH; + + char valuestr[MAXSTRINGLENGTH]; + size_t vlen = args->lengths[1]; + + memcpy(valuestr, args->args[1], vlen--); + + for (size_t i = 0; i < vlen; ++i) + if (!isdigit(valuestr[i])) + { + strcpy(message, "CALSETPARMS() second argument must be numeric or end in G, M or K"); + return 1; + } + + if (!isdigit(valuestr[vlen])) + { + switch (valuestr[vlen]) + { + case 'G': + case 'g': + case 'M': + case 'm': + case 'K': + case 'k': + case '\0': + break; + + default: + strcpy(message, "CALSETPARMS() second argument must be numeric or end in G, M or K"); + return 1; + } + } + + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void calsetparms_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + const char* calgetstats(UDF_INIT* initid, UDF_ARGS* args, + char* result, unsigned long* length, + char* is_null, char* error) + { + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); + + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); + + unsigned long l = ci->queryStats.size(); + + if (l == 0) + { + *is_null = 1; + return 0; + } + + if (l > 255) l = 255; + + memcpy(result, ci->queryStats.c_str(), l); + *length = l; + return result; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool calgetstats_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + if (args->arg_count != 0) + { + strcpy(message, "CALGETSTATS() takes no arguments"); + return 1; + } + + initid->maybe_null = 1; + initid->max_length = 255; + + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void calgetstats_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + long long calsettrace(UDF_INIT* initid, UDF_ARGS* args, + char* is_null, char* error) + { + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); + + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); + + long long oldTrace = ci->traceFlags; + ci->traceFlags = (uint32_t)(*((long long*)args->args[0])); + // keep the vtablemode bit + ci->traceFlags |= (oldTrace & CalpontSelectExecutionPlan::TRACE_TUPLE_OFF); + ci->traceFlags |= (oldTrace & CalpontSelectExecutionPlan::TRACE_TUPLE_AUTOSWITCH); + return oldTrace; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool calsettrace_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + if (args->arg_count != 1 || args->arg_type[0] != INT_RESULT) + { + strcpy(message, "CALSETTRACE() requires one INTEGER argument"); + return 1; + } + + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void calsettrace_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif +// Return 1 if system is ready for reads or 0 if not. + long long mcssystemready(UDF_INIT* initid, UDF_ARGS* args, + char* is_null, char* error) + { + long long rtn = 0; + Oam oam; + DBRM dbrm(true); + SystemStatus systemstatus; + + try + { + oam.getSystemStatus(systemstatus); + + if (systemstatus.SystemOpState == ACTIVE + && dbrm.getSystemReady() + && dbrm.getSystemQueryReady()) + { + return 1; + } + } + catch (...) + { + *error = 1; + } + + return rtn; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool mcssystemready_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void mcssystemready_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif +// Return non-zero if system is read only; 0 if writeable + long long mcssystemreadonly(UDF_INIT* initid, UDF_ARGS* args, + char* is_null, char* error) + { + long long rtn = 0; + DBRM dbrm(true); + + try + { + if (dbrm.getSystemSuspended()) + { + rtn = 1; + } + + if (dbrm.isReadWrite() > 0) // Returns 0 for writable, 5 for read only + { + rtn = 2; + } + } + catch (...) + { + *error = 1; + rtn = 1; + } + + return rtn; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool mcssystemreadonly_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void mcssystemreadonly_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif +// Return non-zero if this is the primary UM; 0 if not primary + long long mcssystemprimary(UDF_INIT* initid, UDF_ARGS* args, + char* is_null, char* error) + { + long long rtn = 0; + Oam oam; + string PrimaryUMModuleName; + string localModule; + oamModuleInfo_t st; + + try + { + st = oam.getModuleInfo(); + localModule = boost::get<0>(st); + PrimaryUMModuleName = config::Config::makeConfig()->getConfig("SystemConfig", "PrimaryUMModuleName"); + + if (boost::iequals(localModule, PrimaryUMModuleName)) + rtn = 1; + if (PrimaryUMModuleName == "unassigned") + rtn = 1; + } + catch (runtime_error& e) + { + // It's difficult to return an error message from a numerical UDF + //string msg = string("ERROR: Problem getting Primary UM Module Name. ") + e.what(); + *error = 1; + } + catch (...) + { + *error = 1; + } + return rtn; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool mcssystemprimary_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void mcssystemprimary_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool calviewtablelock_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + if (args->arg_count == 2 && (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT)) + { + strcpy(message, "CALVIEWTABLELOCK() requires two string arguments"); + return 1; + } + else if ((args->arg_count == 1) && (args->arg_type[0] != STRING_RESULT ) ) + { + strcpy(message, "CALVIEWTABLELOCK() requires one string argument"); + return 1; + } + else if (args->arg_count > 2 ) + { + strcpy(message, "CALVIEWTABLELOCK() takes one or two arguments only"); + return 1; + } + else if (args->arg_count == 0 ) + { + strcpy(message, "CALVIEWTABLELOCK() requires at least one argument"); + return 1; + } + + initid->maybe_null = 1; + initid->max_length = 255; + + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + const char* calviewtablelock(UDF_INIT* initid, UDF_ARGS* args, + char* result, unsigned long* length, + char* is_null, char* error) + { + THD* thd = current_thd; + + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); + + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); + CalpontSystemCatalog::TableName tableName; + + if ( args->arg_count == 2 ) + { + tableName.schema = args->args[0]; + tableName.table = args->args[1]; + } + else if ( args->arg_count == 1 ) + { + tableName.table = args->args[0]; + + if (thd->db.length) + tableName.schema = thd->db.str; + else + { + string msg("No schema information provided"); + memcpy(result, msg.c_str(), msg.length()); + *length = msg.length(); + return result; + } + } + + if ( !ci->dmlProc ) + { + ci->dmlProc = new MessageQueueClient("DMLProc"); + //cout << "viewtablelock starts a new client " << ci->dmlProc << " for session " << thd->thread_id << endl; + } + + string lockinfo = ha_calpont_impl_viewtablelock(*ci, tableName); + + memcpy(result, lockinfo.c_str(), lockinfo.length()); + *length = lockinfo.length(); + return result; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void calviewtablelock_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool calcleartablelock_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + if ((args->arg_count != 1) || (args->arg_type[0] != INT_RESULT)) + { + strcpy(message, + "CALCLEARTABLELOCK() requires one integer argument (the lockID)"); + return 1; + } + + initid->maybe_null = 1; + initid->max_length = 255; + + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + const char* calcleartablelock(UDF_INIT* initid, UDF_ARGS* args, + char* result, unsigned long* length, + char* is_null, char* error) + { + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); + + cal_connection_info* ci = reinterpret_cast( + get_fe_conn_info_ptr()); + long long lockID = *reinterpret_cast(args->args[0]); + + if ( !ci->dmlProc ) + { + ci->dmlProc = new MessageQueueClient("DMLProc"); + //cout << "cleartablelock starts a new client " << ci->dmlProc << " for session " << thd->thread_id << endl; + } + + unsigned long long uLockID = lockID; + string lockinfo = ha_calpont_impl_cleartablelock(*ci, uLockID); + + memcpy(result, lockinfo.c_str(), lockinfo.length()); + *length = lockinfo.length(); + return result; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void calcleartablelock_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool callastinsertid_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + if (args->arg_count == 2 && (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT)) + { + strcpy(message, "CALLASTINSRTID() requires two string arguments"); + return 1; + } + else if ((args->arg_count == 1) && (args->arg_type[0] != STRING_RESULT ) ) + { + strcpy(message, "CALLASTINSERTID() requires one string argument"); + return 1; + } + else if (args->arg_count > 2 ) + { + strcpy(message, "CALLASTINSERTID() takes one or two arguments only"); + return 1; + } + else if (args->arg_count == 0 ) + { + strcpy(message, "CALLASTINSERTID() requires at least one argument"); + return 1; + } + + initid->maybe_null = 1; + initid->max_length = 255; + + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + long long callastinsertid(UDF_INIT* initid, UDF_ARGS* args, + char* is_null, char* error) + { + THD* thd = current_thd; + + CalpontSystemCatalog::TableName tableName; + uint64_t nextVal = 0; + + if ( args->arg_count == 2 ) + { + tableName.schema = args->args[0]; + tableName.table = args->args[1]; + } + else if ( args->arg_count == 1 ) + { + tableName.table = args->args[0]; + + if (thd->db.length) + tableName.schema = thd->db.str; + else + { + return -1; + } + } + + boost::shared_ptr csc = + CalpontSystemCatalog::makeCalpontSystemCatalog( + CalpontSystemCatalog::idb_tid2sid(thd->thread_id)); + csc->identity(execplan::CalpontSystemCatalog::FE); + + try + { + nextVal = csc->nextAutoIncrValue(tableName); + } + catch (std::exception&) + { + string msg("No such table found during autincrement"); + setError(thd, ER_INTERNAL_ERROR, msg); + return nextVal; + } + + if (nextVal == AUTOINCR_SATURATED) + { + setError(thd, ER_INTERNAL_ERROR, IDBErrorInfo::instance()->errorMsg(ERR_EXCEED_LIMIT)); + return nextVal; + } + + //@Bug 3559. Return a message for table without autoincrement column. + if (nextVal == 0) + { + string msg("Autoincrement does not exist for this table."); + setError(thd, ER_INTERNAL_ERROR, msg); + return nextVal; + } + + return (nextVal - 1); + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void callastinsertid_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void calflushcache_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + long long calflushcache(UDF_INIT* initid, UDF_ARGS* args, + char* is_null, char* error) + { + return static_cast(cacheutils::flushPrimProcCache()); + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool calflushcache_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + if (args->arg_count != 0) + { + strcpy(message, "CALFLUSHCACHE() takes no arguments"); + return 1; + } + + return 0; + } + + static const unsigned long TraceSize = 16 * 1024; + +//mysqld will call this with only 766 bytes available in result no matter what we asked for in calgettrace_init() +// if we return a pointer that is not result, mysqld will take our pointer and use it, freeing up result +#ifdef _MSC_VER + __declspec(dllexport) +#endif + const char* calgettrace(UDF_INIT* initid, UDF_ARGS* args, + char* result, unsigned long* length, + char* is_null, char* error) + { + const string* msgp; + int flags = 0; + + if (args->arg_count > 0) + { + if (args->arg_type[0] == INT_RESULT) + { + flags = *reinterpret_cast(args->args[0]); + } + } + + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); + + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); + + if (flags > 0) + //msgp = &connMap[sessionID].extendedStats; + msgp = &ci->extendedStats; + else + //msgp = &connMap[sessionID].miniStats; + msgp = &ci->miniStats; + + unsigned long l = msgp->size(); + + if (l == 0) + { + *is_null = 1; + return 0; + } + + if (l > TraceSize) l = TraceSize; + + *length = l; + return msgp->c_str(); + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool calgettrace_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { +#if 0 + + if (args->arg_count != 0) + { + strcpy(message, "CALGETTRACE() takes no arguments"); + return 1; + } + +#endif + initid->maybe_null = 1; + initid->max_length = TraceSize; + + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void calgettrace_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + const char* calgetversion(UDF_INIT* initid, UDF_ARGS* args, + char* result, unsigned long* length, + char* is_null, char* error) + { + string version(columnstore_version); + *length = version.size(); + memcpy(result, version.c_str(), *length); + return result; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool calgetversion_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + if (args->arg_count != 0) + { + strcpy(message, "CALGETVERSION() takes no arguments"); + return 1; + } + + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void calgetversion_deinit(UDF_INIT* initid) + { + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + const char* calgetsqlcount(UDF_INIT* initid, UDF_ARGS* args, + char* result, unsigned long* length, + char* is_null, char* error) + { + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); + + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); + idbassert(ci != 0); + + MessageQueueClient* mqc = 0; + mqc = new MessageQueueClient("ExeMgr1"); + + ByteStream msg; + ByteStream::quadbyte runningSql, waitingSql; + ByteStream::quadbyte qb = 5; + msg << qb; + mqc->write(msg); + + //get ExeMgr response + msg.restart(); + msg = mqc->read(); + + if (msg.length() == 0) + { + memcpy(result, "Lost connection to ExeMgr", *length); + return result; + } + + msg >> runningSql; + msg >> waitingSql; + delete mqc; + + char ans[128]; + sprintf(ans, "Running SQL statements %d, Waiting SQL statments %d", runningSql, waitingSql); + *length = strlen(ans); + memcpy(result, ans, *length); + return result; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + my_bool calgetsqlcount_init(UDF_INIT* initid, UDF_ARGS* args, char* message) + { + if (args->arg_count != 0) + { + strcpy(message, "CALGETSQLCOUNT() takes no arguments"); + return 1; + } + + return 0; + } + +#ifdef _MSC_VER + __declspec(dllexport) +#endif + void calgetsqlcount_deinit(UDF_INIT* initid) + { + } + + +} //extern "C" diff --git a/dbcon/mysql/ha_mcs_sysvars.cpp b/dbcon/mysql/ha_mcs_sysvars.cpp new file mode 100644 index 000000000..ff6943fa4 --- /dev/null +++ b/dbcon/mysql/ha_mcs_sysvars.cpp @@ -0,0 +1,520 @@ +/* Copyright (C) 2014 InfiniDB, Inc. + Copyright (C) 2016 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 +#include "idb_mysql.h" +#include "ha_mcs_sysvars.h" + +const char* mcs_compression_type_names[] = { + "NO_COMPRESSION", + "SNAPPY", + NullS +}; + +static TYPELIB mcs_compression_type_names_lib = { + array_elements(mcs_compression_type_names) - 1, + "mcs_compression_type_names", + mcs_compression_type_names, + NULL +}; + +// compression type +static MYSQL_THDVAR_ENUM( + compression_type, + PLUGIN_VAR_RQCMDARG, + "Controls compression algorithm for create tables. Possible values are: " + "NO_COMPRESSION segment files aren't compressed; " + "SNAPPY segment files are Snappy compressed (default);", + NULL, // check + NULL, // update + 1, //default + &mcs_compression_type_names_lib); // values lib + +// fe_conn_info pointer +static MYSQL_THDVAR_ULONGLONG( + fe_conn_info_ptr, + PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT, + "FrontEnd connection structure pointer. For internal usage.", + NULL, + NULL, + 0, + 0, + ~0U, + 1 +); + +// legacy system variables +static MYSQL_THDVAR_ULONG( + decimal_scale, + PLUGIN_VAR_RQCMDARG, + "The default decimal precision for calculated column sub-operations ", + NULL, + NULL, + 8, + 0, + 18, + 1 +); + +static MYSQL_THDVAR_BOOL( + varbin_always_hex, + PLUGIN_VAR_NOCMDARG, + "Always display/process varbinary columns as if they have been hexified.", + NULL, + NULL, + 0 +); + +static MYSQL_THDVAR_BOOL( + use_decimal_scale, + PLUGIN_VAR_NOCMDARG, + "Enable/disable the MCS decimal scale to be used internally", + NULL, + NULL, + 0 +); + +static MYSQL_THDVAR_BOOL( + double_for_decimal_math, + PLUGIN_VAR_NOCMDARG, + "Enable/disable the InfiniDB to replace DECIMAL with DOUBLE in arithmetic operation.", + NULL, + NULL, + 0 +); + +static MYSQL_THDVAR_BOOL( + ordered_only, + PLUGIN_VAR_NOCMDARG, + "Always use the first table in the from clause as the large side " + "table for joins", + NULL, + NULL, + 0 +); + +static MYSQL_THDVAR_ULONG( + string_scan_threshold, + PLUGIN_VAR_RQCMDARG, + "Max number of blocks in a dictionary file to be scanned for filtering", + NULL, + NULL, + 10, + 1, + ~0U, + 1 +); + +static MYSQL_THDVAR_ULONG( + stringtable_threshold, + PLUGIN_VAR_RQCMDARG, + "The minimum width of a string column to be stored in a string table", + NULL, + NULL, + 20, + 9, + ~0U, + 1 +); + +static MYSQL_THDVAR_ULONG( + diskjoin_smallsidelimit, + PLUGIN_VAR_RQCMDARG, + "The maximum amount of disk space in MB to use per query for storing " + "'small side' tables for a disk-based join. (0 = unlimited)", + NULL, + NULL, + 0, + 0, + ~0U, + 1 +); + +static MYSQL_THDVAR_ULONG( + diskjoin_largesidelimit, + PLUGIN_VAR_RQCMDARG, + "The maximum amount of disk space in MB to use per join for storing " + "'large side' table data for a disk-based join. (0 = unlimited)", + NULL, + NULL, + 0, + 0, + ~0U, + 1 +); + +static MYSQL_THDVAR_ULONG( + diskjoin_bucketsize, + PLUGIN_VAR_RQCMDARG, + "The maximum size in MB of each 'small side' table in memory.", + NULL, + NULL, + 100, + 1, + ~0U, + 1 +); + +static MYSQL_THDVAR_ULONG( + um_mem_limit, + PLUGIN_VAR_RQCMDARG, + "Per user Memory limit(MB). Switch to disk-based JOIN when limit is reached", + NULL, + NULL, + 0, + 0, + ~0U, + 1 +); + +static MYSQL_THDVAR_ULONG( + local_query, + PLUGIN_VAR_RQCMDARG, + "Enable/disable the Infinidb local PM query only feature.", + NULL, + NULL, + 0, + 0, + 2, + 1 +); + +static MYSQL_THDVAR_ULONG( + import_for_batchinsert_delimiter, + PLUGIN_VAR_RQCMDARG, + "ASCII value of the delimiter used by LDI and INSERT..SELECT", + NULL, // check + NULL, // update + 7, // default + 0, // min + 127, // max + 1 // block size +); + +static MYSQL_THDVAR_ULONG( + import_for_batchinsert_enclosed_by, + PLUGIN_VAR_RQCMDARG, + "ASCII value of the quote symbol used by batch data ingestion", + NULL, // check + NULL, // update + 17, // default + 17, // min + 127, // max + 1 // block size +); + +static MYSQL_THDVAR_BOOL( + use_import_for_batchinsert, + PLUGIN_VAR_NOCMDARG, + "LOAD DATA INFILE and INSERT..SELECT will use cpimport internally", + NULL, // check + NULL, // update + 1 // default +); + +static MYSQL_THDVAR_BOOL( + use_legacy_sysvars, + PLUGIN_VAR_NOCMDARG, + "Control CS behavior using legacy * sysvars", + NULL, // check + NULL, // update + 0 // default +); + +st_mysql_sys_var* mcs_system_variables[] = +{ + MYSQL_SYSVAR(compression_type), + MYSQL_SYSVAR(fe_conn_info_ptr), + MYSQL_SYSVAR(decimal_scale), + MYSQL_SYSVAR(use_decimal_scale), + MYSQL_SYSVAR(ordered_only), + MYSQL_SYSVAR(string_scan_threshold), + MYSQL_SYSVAR(stringtable_threshold), + MYSQL_SYSVAR(diskjoin_smallsidelimit), + MYSQL_SYSVAR(diskjoin_largesidelimit), + MYSQL_SYSVAR(diskjoin_bucketsize), + MYSQL_SYSVAR(um_mem_limit), + MYSQL_SYSVAR(double_for_decimal_math), + MYSQL_SYSVAR(local_query), + MYSQL_SYSVAR(use_import_for_batchinsert), + MYSQL_SYSVAR(import_for_batchinsert_delimiter), + MYSQL_SYSVAR(import_for_batchinsert_enclosed_by), + MYSQL_SYSVAR(use_legacy_sysvars), + MYSQL_SYSVAR(varbin_always_hex), + NULL +}; + +void* get_fe_conn_info_ptr(THD* thd) +{ + return ( current_thd == NULL && thd == NULL ) ? NULL : + (void*)THDVAR(current_thd, fe_conn_info_ptr); +} + +void set_fe_conn_info_ptr(void* ptr, THD* thd) +{ + if ( current_thd == NULL && thd == NULL) + { + return; + } + + THDVAR(current_thd, fe_conn_info_ptr) = (uint64_t)(ptr); +} + +bool get_use_legacy_sysvars(THD* thd) +{ + return ( thd == NULL ) ? false : THDVAR(thd, use_legacy_sysvars); +} + +void set_use_legacy_sysvars(THD* thd, bool value) +{ + THDVAR(thd, use_legacy_sysvars) = value; +} + +void set_compression_type(THD* thd, ulong value) +{ + THDVAR(thd, compression_type) = value; +} + +mcs_compression_type_t get_compression_type(THD* thd) { + return (mcs_compression_type_t) THDVAR(thd, compression_type); +} + +bool get_use_decimal_scale(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? false : thd->variables.infinidb_use_decimal_scale; + else + return ( thd == NULL ) ? false : THDVAR(thd, use_decimal_scale); +} +void set_use_decimal_scale(THD* thd, bool value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_use_decimal_scale = value; + else + THDVAR(thd, use_decimal_scale) = value; +} + +ulong get_decimal_scale(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? 0 : thd->variables.infinidb_decimal_scale; + else + return ( thd == NULL ) ? 0 : THDVAR(thd, decimal_scale); +} +void set_decimal_scale(THD* thd, ulong value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_decimal_scale = value; + else + THDVAR(thd, decimal_scale) = value; +} + +bool get_ordered_only(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? false : thd->variables.infinidb_ordered_only; + else + return ( thd == NULL ) ? false : THDVAR(thd, ordered_only); +} +void set_ordered_only(THD* thd, bool value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_ordered_only = value; + else + THDVAR(thd, ordered_only) = value; +} + +ulong get_string_scan_threshold(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? 0 : thd->variables.infinidb_string_scan_threshold; + else + return ( thd == NULL ) ? 0 : THDVAR(thd, string_scan_threshold); +} +void set_string_scan_threshold(THD* thd, ulong value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_string_scan_threshold = value; + else + THDVAR(thd, string_scan_threshold) = value; +} + +ulong get_stringtable_threshold(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? 0 : thd->variables.infinidb_stringtable_threshold; + else + return ( thd == NULL ) ? 0 : THDVAR(thd, stringtable_threshold); +} +void set_stringtable_threshold(THD* thd, ulong value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_stringtable_threshold = value; + else + THDVAR(thd, stringtable_threshold) = value; +} + +ulong get_diskjoin_smallsidelimit(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? 0 : thd->variables.infinidb_diskjoin_smallsidelimit; + else + return ( thd == NULL ) ? 0 : THDVAR(thd, diskjoin_smallsidelimit); +} +void set_diskjoin_smallsidelimit(THD* thd, ulong value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_diskjoin_smallsidelimit = value; + else + THDVAR(thd, diskjoin_smallsidelimit) = value; +} + +ulong get_diskjoin_largesidelimit(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? 0 : thd->variables.infinidb_diskjoin_largesidelimit; + else + return ( thd == NULL ) ? 0 : THDVAR(thd, diskjoin_largesidelimit); +} +void set_diskjoin_largesidelimit(THD* thd, ulong value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_diskjoin_largesidelimit = value; + else + THDVAR(thd, diskjoin_largesidelimit) = value; +} + +ulong get_diskjoin_bucketsize(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? 0 : thd->variables.infinidb_diskjoin_bucketsize; + else + return ( thd == NULL ) ? 0 : THDVAR(thd, diskjoin_bucketsize); +} +void set_diskjoin_bucketsize(THD* thd, ulong value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_diskjoin_bucketsize = value; + else + THDVAR(thd, diskjoin_bucketsize) = value; +} + +ulong get_um_mem_limit(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? 0 : thd->variables.infinidb_um_mem_limit; + else + return ( thd == NULL ) ? 0 : THDVAR(thd, um_mem_limit); +} +void set_um_mem_limit(THD* thd, ulong value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_um_mem_limit = value; + else + THDVAR(thd, um_mem_limit) = value; +} + +bool get_varbin_always_hex(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? false : thd->variables.infinidb_varbin_always_hex; + else + return ( thd == NULL ) ? false : THDVAR(thd, varbin_always_hex); +} +void set_varbin_always_hex(THD* thd, bool value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_varbin_always_hex = value; + else + THDVAR(thd, varbin_always_hex) = value; +} + +bool get_double_for_decimal_math(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? false : thd->variables.infinidb_double_for_decimal_math; + else + return ( thd == NULL ) ? false : THDVAR(thd, double_for_decimal_math); +} +void set_double_for_decimal_math(THD* thd, bool value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_double_for_decimal_math = value; + else + THDVAR(thd, double_for_decimal_math) = value; +} + +ulong get_local_query(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? 0 : thd->variables.infinidb_local_query; + else + return ( thd == NULL ) ? 0 : THDVAR(thd, local_query); +} +void set_local_query(THD* thd, ulong value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_local_query = value; + else + THDVAR(thd, local_query) = value; +} + +bool get_use_import_for_batchinsert(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? false : thd->variables.infinidb_use_import_for_batchinsert; + else + return ( thd == NULL ) ? false : THDVAR(thd, use_import_for_batchinsert); +} +void set_use_import_for_batchinsert(THD* thd, bool value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_use_import_for_batchinsert = value; + else + THDVAR(thd, use_import_for_batchinsert) = value; +} + +ulong get_import_for_batchinsert_delimiter(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? 0 : thd->variables.infinidb_import_for_batchinsert_delimiter; + else + return ( thd == NULL ) ? 0 : THDVAR(thd, import_for_batchinsert_delimiter); +} +void set_import_for_batchinsert_delimiter(THD* thd, ulong value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_import_for_batchinsert_delimiter = value; + else + THDVAR(thd, import_for_batchinsert_delimiter) = value; +} + +ulong get_import_for_batchinsert_enclosed_by(THD* thd) +{ + if(get_use_legacy_sysvars(thd)) + return ( thd == NULL ) ? 0 : thd->variables.infinidb_import_for_batchinsert_enclosed_by; + else + return ( thd == NULL ) ? 0 : THDVAR(thd, import_for_batchinsert_enclosed_by); +} +void set_import_for_batchinsert_enclosed_by(THD* thd, ulong value) +{ + if(get_use_legacy_sysvars(thd)) + thd->variables.infinidb_import_for_batchinsert_enclosed_by = value; + else + THDVAR(thd, import_for_batchinsert_enclosed_by) = value; +} diff --git a/dbcon/mysql/ha_mcs_sysvars.h b/dbcon/mysql/ha_mcs_sysvars.h new file mode 100644 index 000000000..eae31b0ea --- /dev/null +++ b/dbcon/mysql/ha_mcs_sysvars.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2014 InfiniDB, Inc. + Copyright (C) 2016 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 MCS_SYSVARS_H__ +#define MCS_SYSVARS_H__ + +#include +#include "idb_mysql.h" + +extern st_mysql_sys_var* mcs_system_variables[]; + +// compression_type +enum mcs_compression_type_t { + NO_COMPRESSION = 0, + SNAPPY = 2 +}; + +// simple setters/getters +const char* get_original_query(THD* thd); +void set_original_query(THD* thd, char* query); + +mcs_compression_type_t get_compression_type(THD* thd); +void set_compression_type(THD* thd, ulong value); + +void* get_fe_conn_info_ptr(THD* thd = NULL); +void set_fe_conn_info_ptr(void* ptr, THD* thd = NULL); + +bool get_use_legacy_sysvars(THD* thd); +void set_use_legacy_sysvars(THD* thd, bool value); + +bool get_use_decimal_scale(THD* thd); +void set_use_decimal_scale(THD* thd, bool value); + +ulong get_decimal_scale(THD* thd); +void set_decimal_scale(THD* thd, ulong value); + +bool get_ordered_only(THD* thd); +void set_ordered_only(THD* thd, bool value); + +ulong get_string_scan_threshold(THD* thd); +void set_string_scan_threshold(THD* thd, ulong value); + +ulong get_stringtable_threshold(THD* thd); +void set_stringtable_threshold(THD* thd, ulong value); + +ulong get_diskjoin_smallsidelimit(THD* thd); +void set_diskjoin_smallsidelimit(THD* thd, ulong value); + +ulong get_diskjoin_largesidelimit(THD* thd); +void set_diskjoin_largesidelimit(THD* thd, ulong value); + +ulong get_diskjoin_bucketsize(THD* thd); +void set_diskjoin_bucketsize(THD* thd, ulong value); + +ulong get_um_mem_limit(THD* thd); +void set_um_mem_limit(THD* thd, ulong value); + +bool get_varbin_always_hex(THD* thd); +void set_varbin_always_hex(THD* thd, bool value); + +bool get_double_for_decimal_math(THD* thd); +void set_double_for_decimal_math(THD* thd, bool value); + +ulong get_local_query(THD* thd); +void set_local_query(THD* thd, ulong value); + +bool get_use_import_for_batchinsert(THD* thd); +void set_use_import_for_batchinsert(THD* thd, bool value); + +ulong get_import_for_batchinsert_delimiter(THD* thd); +void set_import_for_batchinsert_delimiter(THD* thd, ulong value); + +ulong get_import_for_batchinsert_enclosed_by(THD* thd); +void set_import_for_batchinsert_enclosed_by(THD* thd, ulong value); + +#endif diff --git a/dbcon/mysql/ha_pseudocolumn.cpp b/dbcon/mysql/ha_pseudocolumn.cpp index 284130033..c87196e00 100644 --- a/dbcon/mysql/ha_pseudocolumn.cpp +++ b/dbcon/mysql/ha_pseudocolumn.cpp @@ -20,6 +20,7 @@ using namespace execplan; #include "functor_str.h" #include "ha_calpont_impl_if.h" +#include "ha_mcs_sysvars.h" using namespace cal_impl_if; namespace @@ -54,10 +55,10 @@ int64_t idblocalpm() { THD* thd = current_thd; - if (!thd->infinidb_vtable.cal_conn_info) - thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); if (ci->localPm == -1) { @@ -485,10 +486,10 @@ execplan::ReturnedColumn* buildPseudoColumn(Item* item, bool& nonSupport, uint32_t pseudoType) { - if (!(gwi.thd->infinidb_vtable.cal_conn_info)) - gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(gwi.thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); Item_func* ifp = (Item_func*)item; diff --git a/dbcon/mysql/ha_window_function.cpp b/dbcon/mysql/ha_window_function.cpp index f4a95bbc3..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 @@ -28,6 +28,7 @@ using namespace std; #include "idb_mysql.h" #include "ha_calpont_impl_if.h" +#include "ha_mcs_sysvars.h" #include "arithmeticcolumn.h" #include "arithmeticoperator.h" @@ -93,10 +94,10 @@ WF_FRAME frame(Window_frame_bound::Bound_precedence_type bound, Item* offset) } ReturnedColumn* buildBoundExp(WF_Boundary& bound, SRCP& order, gp_walk_info& gwi) { - if (!(gwi.thd->infinidb_vtable.cal_conn_info)) - gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(gwi.thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); bool addOp = true; ReturnedColumn* rc = NULL; @@ -337,10 +338,10 @@ ReturnedColumn* buildWindowFunctionColumn(Item* item, gp_walk_info& gwi, bool& n //String str; //item->print(&str, QT_INFINIDB_NO_QUOTE); //cout << str.c_ptr() << endl; - if (!(gwi.thd->infinidb_vtable.cal_conn_info)) - gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); + if (get_fe_conn_info_ptr() == NULL) + set_fe_conn_info_ptr((void*)new cal_connection_info()); - cal_connection_info* ci = reinterpret_cast(gwi.thd->infinidb_vtable.cal_conn_info); + cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); gwi.hasWindowFunc = true; Item_window_func* wf = (Item_window_func*)item; @@ -897,12 +898,18 @@ 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)); // bug5736. Make the result type double for some window functions when - // infinidb_double_for_decimal_math is set. + // plugin variable double_for_decimal_math is set. ac->adjustResultType(); } 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 68355980a..d07c67ffb 100644 --- a/oamapps/mcsadmin/mcsadmin.cpp +++ b/oamapps/mcsadmin/mcsadmin.cpp @@ -759,8 +759,11 @@ int processCommand(string* arguments) vector srcDbroots; // all of the currently configured dbroots vector destDbroots; // srcDbroots - removeDbroots set::iterator dbiter; - - if (arguments[1] == "start") +#if _MSC_VER + if (_strnicmp(arguments[1].c_str(), "start", 5) == 0)) +#else + if (strncasecmp(arguments[1].c_str(), "start", 5) == 0) +#endif { // Get a list of all the configured dbroots in the xml file. DBRootConfigList dbRootConfigList; @@ -772,7 +775,11 @@ int processCommand(string* arguments) // The user may choose to redistribute in such a way as to // leave certain dbroots empty, presumably for later removal. - if (arguments[2] == "remove") +#if _MSC_VER + if (_strnicmp(arguments[1].c_str(), "remove", 6) == 0)) +#else + if (strncasecmp(arguments[1].c_str(), "remove", 6) == 0) +#endif { int dbroot; bool error = false; @@ -891,7 +898,11 @@ int processCommand(string* arguments) SendToWES(oam, bs); } - else if (arguments[1] == "stop") +#if _MSC_VER + if (_strnicmp(arguments[1].c_str(), "stop", 4) == 0)) +#else + if (strncasecmp(arguments[1].c_str(), "stop", 4) == 0) +#endif { ByteStream bs; // message WES ID, sequence #, action id @@ -901,7 +912,11 @@ int processCommand(string* arguments) bs.append((const ByteStream::byte*) &header, sizeof(header)); SendToWES(oam, bs); } - else if (arguments[1] == "status") +#if _MSC_VER + if (_strnicmp(arguments[1].c_str(), "status", 6) == 0)) +#else + if (strncasecmp(arguments[1].c_str(), "status", 6) == 0) +#endif { ByteStream bs; // message WES ID, sequence #, action id @@ -5389,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/oamapps/postConfigure/postConfigure.cpp b/oamapps/postConfigure/postConfigure.cpp index c4e9b2126..fdfc1482c 100644 --- a/oamapps/postConfigure/postConfigure.cpp +++ b/oamapps/postConfigure/postConfigure.cpp @@ -662,9 +662,14 @@ int main(int argc, char* argv[]) if (moduleconfig.hostConfigList.size() > 0 ) { HostConfigList::iterator pt1 = moduleconfig.hostConfigList.begin(); - string PM1ipAdd = (*pt1).IPAddr; + + // MCOL-1607. The 'am I pm1?' check below requires an ipaddr. + string PM1ipAdd = oam.getIPAddress((*pt1).IPAddr.c_str()); + if (PM1ipAdd.empty()) + PM1ipAdd = (*pt1).IPAddr; // this is what it was doing before + //cout << PM1ipAdd << endl; - + if ( PM1ipAdd != "127.0.0.1" ) { if ( PM1ipAdd != "0.0.0.0") @@ -2602,6 +2607,13 @@ int main(int argc, char* argv[]) callFree(pcommand); } + + if (!doNotResolveHostNames) + { + string ugh = oam.getIPAddress(newModuleIPAddr); + if (ugh.length() > 0) + newModuleIPAddr = ugh; + } if (newModuleIPAddr == "127.0.0.1" || newModuleIPAddr == "0.0.0.0" || newModuleIPAddr == "128.0.0.1") { @@ -6580,7 +6592,7 @@ bool glusterSetup(string password, bool doNotResolveHostNames) //prompt for IP address while (true) { - prompt = "Enter PM #" + oam.itoa(DataRedundancyConfigs[pm].pmID) + " IP Address of " + moduleHostName + " (" + moduleIPAddr + ") > "; + prompt = "Enter PM #" + oam.itoa(DataRedundancyConfigs[pm].pmID) + " IP Address or hostname of " + moduleHostName + " (" + moduleIPAddr + ") > "; pcommand = callReadline(prompt.c_str()); if (pcommand) @@ -6589,6 +6601,13 @@ bool glusterSetup(string password, bool doNotResolveHostNames) callFree(pcommand); } + + if (!doNotResolveHostNames) + { + string ugh = oam.getIPAddress(moduleIPAddr); + if (ugh.length() > 0) + moduleIPAddr = ugh; + } if (moduleIPAddr == "127.0.0.1" || moduleIPAddr == "0.0.0.0" || moduleIPAddr == "128.0.0.1") { diff --git a/primitives/linux-port/column.cpp b/primitives/linux-port/column.cpp index 2b4450d2c..8832a6448 100644 --- a/primitives/linux-port/column.cpp +++ b/primitives/linux-port/column.cpp @@ -325,6 +325,7 @@ inline bool isEmptyVal<4>(uint8_t type, const uint8_t* ival) return (joblist::CHAR4EMPTYROW == *val); case CalpontSystemCatalog::UINT: + case CalpontSystemCatalog::UMEDINT: return (joblist::UINTEMPTYROW == *val); default: @@ -445,6 +446,7 @@ inline bool isNullVal<4>(uint8_t type, const uint8_t* ival) return (joblist::DATENULL == *val); case CalpontSystemCatalog::UINT: + case CalpontSystemCatalog::UMEDINT: return (joblist::UINTNULL == *val); default: @@ -550,6 +552,7 @@ inline bool isMinMaxValid(const NewColRequestHeader* in) case CalpontSystemCatalog::TINYINT: case CalpontSystemCatalog::SMALLINT: + case CalpontSystemCatalog::MEDINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::DATE: case CalpontSystemCatalog::BIGINT: @@ -557,6 +560,7 @@ inline bool isMinMaxValid(const NewColRequestHeader* in) case CalpontSystemCatalog::TIME: case CalpontSystemCatalog::UTINYINT: case CalpontSystemCatalog::USMALLINT: + case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::UBIGINT: return true; 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 1d196a436..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 @@ -330,6 +331,19 @@ int64_t number_int_value(const string& data, break; case CalpontSystemCatalog::MEDINT: + if (intVal < MIN_MEDINT) + { + intVal = MIN_MEDINT; + pushwarning = true; + } + else if (intVal > MAX_MEDINT) + { + intVal = MAX_MEDINT; + pushwarning = true; + } + + break; + case CalpontSystemCatalog::INT: if (intVal < MIN_INT) { @@ -559,6 +573,14 @@ uint64_t number_uint_value(const string& data, break; case CalpontSystemCatalog::UMEDINT: + if (uintVal > MAX_UMEDINT) + { + uintVal = MAX_UMEDINT; + pushwarning = true; + } + + break; + case CalpontSystemCatalog::UINT: if (uintVal > MAX_UINT) { @@ -871,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; @@ -2995,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: { @@ -3180,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 3750a3e61..80185f524 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 8a80ca683..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; @@ -2757,7 +2585,6 @@ void RowAggregationUM::SetUDAFValue(static_any::any& valOut, int64_t colOut) break; case execplan::CalpontSystemCatalog::SMALLINT: - case execplan::CalpontSystemCatalog::MEDINT: if (valOut.compatible(shortTypeId)) { intOut = valOut.cast(); @@ -2767,6 +2594,7 @@ void RowAggregationUM::SetUDAFValue(static_any::any& valOut, int64_t colOut) break; + case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::INT: if (valOut.compatible(uintTypeId)) { @@ -2809,7 +2637,6 @@ void RowAggregationUM::SetUDAFValue(static_any::any& valOut, int64_t colOut) break; case execplan::CalpontSystemCatalog::USMALLINT: - case execplan::CalpontSystemCatalog::UMEDINT: if (valOut.compatible(ushortTypeId)) { uintOut = valOut.cast(); @@ -2819,6 +2646,7 @@ void RowAggregationUM::SetUDAFValue(static_any::any& valOut, int64_t colOut) break; + case execplan::CalpontSystemCatalog::UMEDINT: case execplan::CalpontSystemCatalog::UINT: if (valOut.compatible(uintTypeId)) { @@ -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 @@ -3030,10 +2883,10 @@ void RowAggregationUM::SetUDAFAnyValue(static_any::any& valOut, int64_t colOut) break; case execplan::CalpontSystemCatalog::SMALLINT: - case execplan::CalpontSystemCatalog::MEDINT: fRow.setIntField<2>(intOut, colOut); break; + case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::INT: fRow.setIntField<4>(intOut, colOut); break; @@ -3049,10 +2902,10 @@ void RowAggregationUM::SetUDAFAnyValue(static_any::any& valOut, int64_t colOut) break; case execplan::CalpontSystemCatalog::USMALLINT: - case execplan::CalpontSystemCatalog::UMEDINT: fRow.setUintField<2>(uintOut, colOut); break; + case execplan::CalpontSystemCatalog::UMEDINT: case execplan::CalpontSystemCatalog::UINT: fRow.setUintField<4>(uintOut, colOut); break; @@ -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) diff --git a/writeengine/bulk/we_bulkloadbuffer.cpp b/writeengine/bulk/we_bulkloadbuffer.cpp index da568f9a6..f0336d79d 100644 --- a/writeengine/bulk/we_bulkloadbuffer.cpp +++ b/writeengine/bulk/we_bulkloadbuffer.cpp @@ -1224,8 +1224,9 @@ void BulkLoadBuffer::convert(char* field, int fieldLength, } //---------------------------------------------------------------------- - // UNSIGNED INTEGER + // UNSIGNED MEDIUM INTEGER AND UNSIGNED INTEGER //---------------------------------------------------------------------- + case WriteEngine::WR_UMEDINT : case WriteEngine::WR_UINT : { int64_t origVal; @@ -1306,8 +1307,9 @@ void BulkLoadBuffer::convert(char* field, int fieldLength, } //---------------------------------------------------------------------- - // INTEGER + // MEDIUM INTEGER AND INTEGER //---------------------------------------------------------------------- + case WriteEngine::WR_MEDINT : case WriteEngine::WR_INT : default : { diff --git a/writeengine/bulk/we_columninfo.cpp b/writeengine/bulk/we_columninfo.cpp index 9c1a1a9e2..4c66e35ff 100644 --- a/writeengine/bulk/we_columninfo.cpp +++ b/writeengine/bulk/we_columninfo.cpp @@ -197,10 +197,12 @@ ColumnInfo::ColumnInfo(Log* logger, case WriteEngine::WR_SHORT: case WriteEngine::WR_BYTE: case WriteEngine::WR_LONGLONG: + case WriteEngine::WR_MEDINT: case WriteEngine::WR_INT: case WriteEngine::WR_USHORT: case WriteEngine::WR_UBYTE: case WriteEngine::WR_ULONGLONG: + case WriteEngine::WR_UMEDINT: case WriteEngine::WR_UINT: default: { diff --git a/writeengine/index/we_indextree.cpp b/writeengine/index/we_indextree.cpp index a2dd97789..0b927c9e6 100644 --- a/writeengine/index/we_indextree.cpp +++ b/writeengine/index/we_indextree.cpp @@ -1182,6 +1182,7 @@ const int IndexTree::setBitsetColumn( void* val, const int pos, const int width, break; case WriteEngine::WR_INT : + case WriteEngine::WR_MEDINT : default : memcpy( m_multiColKey.keyBuf + m_multiColKey.totalBit / 8, (int*) val, copyLen ); m_multiColKey.curBitset = *((int*) val); diff --git a/writeengine/server/we_ddlcommon.h b/writeengine/server/we_ddlcommon.h index 1d482b442..b1e4e48f1 100644 --- a/writeengine/server/we_ddlcommon.h +++ b/writeengine/server/we_ddlcommon.h @@ -464,6 +464,10 @@ inline int convertDataType(int dataType) calpontDataType = CalpontSystemCatalog::USMALLINT; break; + case ddlpackage::DDL_UNSIGNED_MEDINT: + calpontDataType = CalpontSystemCatalog::UMEDINT; + break; + case ddlpackage::DDL_UNSIGNED_INT: calpontDataType = CalpontSystemCatalog::UINT; break; diff --git a/writeengine/server/we_dmlcommandproc.cpp b/writeengine/server/we_dmlcommandproc.cpp index cbc84e26e..5da10433e 100644 --- a/writeengine/server/we_dmlcommandproc.cpp +++ b/writeengine/server/we_dmlcommandproc.cpp @@ -3028,6 +3028,8 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs, case CalpontSystemCatalog::UBIGINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::UINT: + case CalpontSystemCatalog::MEDINT: + case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::SMALLINT: case CalpontSystemCatalog::USMALLINT: case CalpontSystemCatalog::TINYINT: @@ -3363,6 +3365,8 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs, case CalpontSystemCatalog::UBIGINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::UINT: + case CalpontSystemCatalog::MEDINT: + case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::SMALLINT: case CalpontSystemCatalog::USMALLINT: case CalpontSystemCatalog::TINYINT: diff --git a/writeengine/shared/we_convertor.cpp b/writeengine/shared/we_convertor.cpp index 53af4eb59..72d2c6429 100644 --- a/writeengine/shared/we_convertor.cpp +++ b/writeengine/shared/we_convertor.cpp @@ -194,15 +194,20 @@ long long Convertor::convertDecimalString( // range check against int64 - if (dval > LLONG_MAX || dval < LLONG_MIN) + if (dval > LLONG_MAX) + { errno = ERANGE; + return LLONG_MAX; + } + if (dval < LLONG_MIN) + { + errno = ERANGE; + return LLONG_MIN; + } + errno = 0; - else - - errno = 0; - ret = dval; - + // get the fractional part of what's left & round ret up or down. dval -= ret; if (dval >= 0.5 && ret < LLONG_MAX) @@ -345,8 +350,12 @@ void Convertor::convertColType(CalpontSystemCatalog::ColDataType dataType, internalType = WriteEngine::WR_SHORT; break; - // Map MEDINT, INT, and DATE to WR_INT + // Map MEDINT to WR_MEDINT case CalpontSystemCatalog::MEDINT : + internalType = WriteEngine::WR_MEDINT; + break; + + // Map INT, and DATE to WR_INT case CalpontSystemCatalog::INT : case CalpontSystemCatalog::DATE : internalType = WriteEngine::WR_INT; @@ -410,8 +419,12 @@ void Convertor::convertColType(CalpontSystemCatalog::ColDataType dataType, internalType = WriteEngine::WR_USHORT; break; - // Map UMEDINT and UINT to WR_UINT + // Map UMEDINT to WR_UMEDINT case CalpontSystemCatalog::UMEDINT: + internalType = WriteEngine::WR_UMEDINT; + break; + + // Map UINT to WR_UINT case CalpontSystemCatalog::UINT: internalType = WriteEngine::WR_UINT; break; @@ -453,7 +466,12 @@ void Convertor::convertWEColType(ColType internalType, dataType = CalpontSystemCatalog::SMALLINT; break; - // Map MEDINT, INT, and DATE to WR_INT + // Map MEDINT to WR_MEDINT + case WriteEngine::WR_MEDINT : + dataType = CalpontSystemCatalog::MEDINT; + break; + + // Map INT, and DATE to WR_INT case WriteEngine::WR_INT : dataType = CalpontSystemCatalog::INT; break; @@ -503,7 +521,12 @@ void Convertor::convertWEColType(ColType internalType, dataType = CalpontSystemCatalog::USMALLINT; break; - // Map UMEDINT and UINT to WR_UINT + // Map UMEDINT to WR_UMEDINT + case WriteEngine::WR_UMEDINT: + dataType = CalpontSystemCatalog::UMEDINT; + break; + + // Map UINT to WR_UINT case WriteEngine::WR_UINT: dataType = CalpontSystemCatalog::UINT; break; @@ -555,8 +578,12 @@ void Convertor::convertColType(ColStruct* curStruct) *internalType = WriteEngine::WR_SHORT; break; - // Map MEDINT, INT, and DATE to WR_INT + // Map MEDINT to WR_MEDINT case CalpontSystemCatalog::MEDINT : + *internalType = WriteEngine::WR_MEDINT; + break; + + // Map INT, and DATE to WR_INT case CalpontSystemCatalog::INT : case CalpontSystemCatalog::DATE : *internalType = WriteEngine::WR_INT; @@ -639,8 +666,12 @@ void Convertor::convertColType(ColStruct* curStruct) *internalType = WriteEngine::WR_USHORT; break; - // Map UMEDINT and UINT to WR_UINT + // Map UMEDINT to WR_UMEDINT case CalpontSystemCatalog::UMEDINT: + *internalType = WriteEngine::WR_UMEDINT; + break; + + // Map UINT to WR_UINT case CalpontSystemCatalog::UINT: *internalType = WriteEngine::WR_UINT; break; diff --git a/writeengine/shared/we_type.h b/writeengine/shared/we_type.h index 06a367ecb..8a8cae5a9 100644 --- a/writeengine/shared/we_type.h +++ b/writeengine/shared/we_type.h @@ -108,7 +108,9 @@ enum ColType /** @brief Column type enumeration*/ WR_USHORT = 14, /** @brief Unsigned Short */ WR_UINT = 15, /** @brief Unsigned Int */ WR_ULONGLONG = 16, /** @brief Unsigned Long long*/ - WR_TEXT = 17 /** @brief TEXT */ + WR_TEXT = 17, /** @brief TEXT */ + WR_MEDINT = 18, /** @brief Medium Int */ + WR_UMEDINT = 19 /** @brief Unsigned Medium Int */ }; // Describes relation of field to column for a bulk load diff --git a/writeengine/wrapper/we_colop.cpp b/writeengine/wrapper/we_colop.cpp index ffd01df2e..4f0e6a0d2 100644 --- a/writeengine/wrapper/we_colop.cpp +++ b/writeengine/wrapper/we_colop.cpp @@ -1618,6 +1618,7 @@ int ColumnOp::writeRow(Column& curCol, uint64_t totalRow, const RID* rowIdArray, break; case WriteEngine::WR_INT : + case WriteEngine::WR_MEDINT : if (!bDelete) pVal = &((int*) valArray)[i]; //pOldVal = &((int *) oldValArray)[i]; @@ -1636,6 +1637,7 @@ int ColumnOp::writeRow(Column& curCol, uint64_t totalRow, const RID* rowIdArray, break; case WriteEngine::WR_UINT : + case WriteEngine::WR_UMEDINT : if (!bDelete) pVal = &((uint32_t*) valArray)[i]; //pOldVal = &((uint8_t *) oldValArray)[i]; @@ -1789,6 +1791,7 @@ int ColumnOp::writeRows(Column& curCol, uint64_t totalRow, const RIDList& ridLis break; case WriteEngine::WR_INT : + case WriteEngine::WR_MEDINT : if (!bDelete) pVal = &((int*) valArray)[0]; //pOldVal = &((int *) oldValArray)[i]; @@ -1813,6 +1816,7 @@ int ColumnOp::writeRows(Column& curCol, uint64_t totalRow, const RIDList& ridLis break; case WriteEngine::WR_UINT : + case WriteEngine::WR_UMEDINT : if (!bDelete) pVal = &((uint32_t*) valArray)[0]; //pOldVal = &((uint32_t *) oldValArray)[i]; @@ -1944,6 +1948,7 @@ int ColumnOp::writeRowsValues(Column& curCol, uint64_t totalRow, const RIDList& break; case WriteEngine::WR_INT : + case WriteEngine::WR_MEDINT : pVal = &((int*) valArray)[i]; break; @@ -1960,6 +1965,7 @@ int ColumnOp::writeRowsValues(Column& curCol, uint64_t totalRow, const RIDList& break; case WriteEngine::WR_UINT : + case WriteEngine::WR_UMEDINT : pVal = &((uint32_t*) valArray)[i]; break; diff --git a/writeengine/wrapper/writeengine.cpp b/writeengine/wrapper/writeengine.cpp index 6386d70c4..62842da0d 100644 --- a/writeengine/wrapper/writeengine.cpp +++ b/writeengine/wrapper/writeengine.cpp @@ -261,6 +261,7 @@ void WriteEngineWrapper::convertValue(const ColType colType, void* value, boost: switch (colType) { case WriteEngine::WR_INT : + case WriteEngine::WR_MEDINT : if (data.type() == typeid(int)) { int val = boost::any_cast(data); @@ -277,6 +278,7 @@ void WriteEngineWrapper::convertValue(const ColType colType, void* value, boost: break; case WriteEngine::WR_UINT : + case WriteEngine::WR_UMEDINT : { uint32_t val = boost::any_cast(data); size = sizeof(uint32_t); @@ -410,6 +412,7 @@ void WriteEngineWrapper::convertValue(const ColType colType, void* valArray, con switch (colType) { case WriteEngine::WR_INT : + case WriteEngine::WR_MEDINT : if (data.type() == typeid(long)) ((int*)valArray)[pos] = static_cast(boost::any_cast(data)); else if (data.type() == typeid(int)) @@ -420,6 +423,7 @@ void WriteEngineWrapper::convertValue(const ColType colType, void* valArray, con break; case WriteEngine::WR_UINT : + case WriteEngine::WR_UMEDINT : ((uint32_t*)valArray)[pos] = boost::any_cast(data); break; @@ -495,10 +499,12 @@ void WriteEngineWrapper::convertValue(const ColType colType, void* valArray, con switch (colType) { case WriteEngine::WR_INT : + case WriteEngine::WR_MEDINT : data = ((int*)valArray)[pos]; break; case WriteEngine::WR_UINT : + case WriteEngine::WR_UMEDINT : data = ((uint64_t*)valArray)[pos]; break; @@ -814,10 +820,12 @@ int WriteEngineWrapper::deleteBadRows(const TxnID& txnid, ColStructList& colStru switch (colStructs[i].colType) { case WriteEngine::WR_INT: + case WriteEngine::WR_MEDINT: valArray = (int*) calloc(sizeof(int), 1); break; case WriteEngine::WR_UINT: + case WriteEngine::WR_UMEDINT: valArray = (uint32_t*) calloc(sizeof(uint32_t), 1); break; @@ -4484,10 +4492,12 @@ int WriteEngineWrapper::writeColumnRecords(const TxnID& txnid, switch (curColStruct.colType) { case WriteEngine::WR_INT: + case WriteEngine::WR_MEDINT: valArray = (int*) calloc(sizeof(int), totalRow); break; case WriteEngine::WR_UINT: + case WriteEngine::WR_UMEDINT: valArray = (uint32_t*) calloc(sizeof(uint32_t), totalRow); break; @@ -4721,10 +4731,12 @@ int WriteEngineWrapper::writeColumnRec(const TxnID& txnid, switch (colStructList[i].colType) { case WriteEngine::WR_INT: + case WriteEngine::WR_MEDINT: valArray = (int*) calloc(sizeof(int), totalRow1); break; case WriteEngine::WR_UINT: + case WriteEngine::WR_UMEDINT: valArray = (uint32_t*) calloc(sizeof(uint32_t), totalRow1); break; @@ -4894,10 +4906,12 @@ int WriteEngineWrapper::writeColumnRec(const TxnID& txnid, switch (newColStructList[i].colType) { case WriteEngine::WR_INT: + case WriteEngine::WR_MEDINT: valArray = (int*) calloc(sizeof(int), totalRow2); break; case WriteEngine::WR_UINT: + case WriteEngine::WR_UMEDINT: valArray = (uint32_t*) calloc(sizeof(uint32_t), totalRow2); break; @@ -5065,10 +5079,12 @@ int WriteEngineWrapper::writeColumnRec(const TxnID& txnid, switch (colStructList[i].colType) { case WriteEngine::WR_INT: + case WriteEngine::WR_MEDINT: valArray = (int*) calloc(sizeof(int), totalRow1); break; case WriteEngine::WR_UINT: + case WriteEngine::WR_UMEDINT: valArray = (uint32_t*) calloc(sizeof(uint32_t), totalRow1); break; @@ -5308,6 +5324,8 @@ int WriteEngineWrapper::writeColumnRecBinary(const TxnID& txnid, case WriteEngine::WR_INT: case WriteEngine::WR_UINT: + case WriteEngine::WR_MEDINT: + case WriteEngine::WR_UMEDINT: case WriteEngine::WR_FLOAT: tmp32 = curValue; ((uint32_t*)valArray)[j] = tmp32; @@ -5449,6 +5467,8 @@ int WriteEngineWrapper::writeColumnRecBinary(const TxnID& txnid, case WriteEngine::WR_INT: case WriteEngine::WR_UINT: + case WriteEngine::WR_MEDINT: + case WriteEngine::WR_UMEDINT: case WriteEngine::WR_FLOAT: tmp32 = curValue; ((uint32_t*)valArray)[j] = tmp32; @@ -5704,10 +5724,12 @@ int WriteEngineWrapper::writeColumnRec(const TxnID& txnid, switch (curColStruct.colType) { case WriteEngine::WR_INT: + case WriteEngine::WR_MEDINT: valArray = (int*) calloc(sizeof(int), 1); break; case WriteEngine::WR_UINT: + case WriteEngine::WR_UMEDINT: valArray = (uint32_t*) calloc(sizeof(uint32_t), 1); break; diff --git a/writeengine/xml/we_xmljob.cpp b/writeengine/xml/we_xmljob.cpp index 8d755b824..4dd923172 100644 --- a/writeengine/xml/we_xmljob.cpp +++ b/writeengine/xml/we_xmljob.cpp @@ -719,6 +719,18 @@ void XMLJob::initSatLimits( JobColumn& curColumn ) const curColumn.fMinIntSat = MIN_UBIGINT; curColumn.fMaxIntSat = MAX_UBIGINT; } + else if ( curColumn.typeName == + ColDataTypeStr[CalpontSystemCatalog::MEDINT] ) + { + curColumn.fMinIntSat = MIN_MEDINT; + curColumn.fMaxIntSat = MAX_MEDINT; + } + else if ( curColumn.typeName == + ColDataTypeStr[CalpontSystemCatalog::UMEDINT] ) + { + curColumn.fMinIntSat = MIN_UMEDINT; + curColumn.fMaxIntSat = MAX_UMEDINT; + } else if ( curColumn.typeName == ColDataTypeStr[CalpontSystemCatalog::SMALLINT] ) {