diff --git a/dbcon/execplan/functioncolumn.cpp b/dbcon/execplan/functioncolumn.cpp index 4826a8c53..7ccf87e4c 100644 --- a/dbcon/execplan/functioncolumn.cpp +++ b/dbcon/execplan/functioncolumn.cpp @@ -307,6 +307,7 @@ void FunctionColumn::unserialize(messageqcpp::ByteStream& b) FuncExp* funcExp = FuncExp::instance(); fFunctor = funcExp->getFunctor(fFunctionName); fFunctor->timeZone(fTimeZone); + fFunctor->fix(*this); // @bug 3506. Special treatment for rand() function. reset the seed Func_rand* rand = dynamic_cast(fFunctor); diff --git a/dbcon/execplan/functioncolumn.h b/dbcon/execplan/functioncolumn.h index 57d39431d..63d7c0572 100644 --- a/dbcon/execplan/functioncolumn.h +++ b/dbcon/execplan/functioncolumn.h @@ -309,15 +309,6 @@ public: return fFunctor->getTimeIntVal(row, fFunctionParms, isNull, fOperationType); } - bool fixIfNeeded() override - { - if (fFixed) - return false; - if (fFunctor->fix(*this)) - return true; - fFixed = true; - return false; - } void setFunctor(funcexp::Func* functor) { fFunctor = functor; diff --git a/dbcon/execplan/returnedcolumn.h b/dbcon/execplan/returnedcolumn.h index 22e1dc15b..6c07f5694 100644 --- a/dbcon/execplan/returnedcolumn.h +++ b/dbcon/execplan/returnedcolumn.h @@ -328,11 +328,6 @@ public: return false; } - virtual bool fixIfNeeded() - { - return false; - } - protected: // return all flag set if the other column is outer join column (+) bool fReturnAll; diff --git a/exemgr/main.cpp b/exemgr/main.cpp index 950f2cc70..0511326d3 100644 --- a/exemgr/main.cpp +++ b/exemgr/main.cpp @@ -594,6 +594,17 @@ private: } } + void writeCodeAndError(messageqcpp::ByteStream::quadbyte code, + const std::string emsg) + { + messageqcpp::ByteStream emsgBs; + messageqcpp::ByteStream tbs; + tbs << code; + fIos.write(tbs); + emsgBs << emsg; + fIos.write(emsgBs); + } + public: void operator()() @@ -692,7 +703,18 @@ public: } new_plan: - csep.unserialize(bs); + try + { + csep.unserialize(bs); + } + catch (logging::IDBExcept &ex) + { + // We can get here on illegal function parameter data type, e.g. + // SELECT blob_column|1 FROM t1; + statementsRunningCount->decr(stmtCounted); + writeCodeAndError(ex.errorCode(), std::string(ex.what())); + continue; + } querytele::QueryTeleStats qts; @@ -781,41 +803,28 @@ new_plan: { try // @bug2244: try/catch around fIos.write() calls responding to makeTupleList { - std::string emsg("NOERROR"); - messageqcpp::ByteStream emsgBs; - messageqcpp::ByteStream::quadbyte tflg = 0; jl = joblist::JobListFactory::makeJobList(&csep, fRm, true, true); // assign query stats jl->queryStats(fStats); - messageqcpp::ByteStream tbs; if ((jl->status()) == 0 && (jl->putEngineComm(fEc) == 0)) { usingTuples = true; //Tell the FE that we're sending tuples back, not TableBands - tbs << tflg; - fIos.write(tbs); - emsgBs.reset(); - emsgBs << emsg; - fIos.write(emsgBs); + writeCodeAndError(0, "NOERROR"); auto tjlp = dynamic_cast(jl.get()); assert(tjlp); - tbs.restart(); + messageqcpp::ByteStream tbs; tbs << tjlp->getOutputRowGroup(); fIos.write(tbs); } else { + const std::string emsg = jl->errMsg(); statementsRunningCount->decr(stmtCounted); - tflg = jl->status(); - emsg = jl->errMsg(); - tbs << tflg; - fIos.write(tbs); - emsgBs.reset(); - emsgBs << emsg; - fIos.write(emsgBs); + writeCodeAndError(jl->status(), emsg); std::cerr << "ExeMgr: could not build a tuple joblist: " << emsg << std::endl; continue; } diff --git a/mtr/basic/r/func_bit.result b/mtr/basic/r/func_bit.result index 20ffc50f4..2b6fbf120 100644 --- a/mtr/basic/r/func_bit.result +++ b/mtr/basic/r/func_bit.result @@ -105,5 +105,20 @@ a 1<>a 64 0 0 65 0 0 DROP TABLE t1; +# +# MCOL-4666 Empty set when using BIT OR and BIT AND functions in WHERE +# +CREATE TABLE t1 (a DECIMAL(18,2)); +INSERT INTO t1 VALUES (3.4); +SELECT a, a|4, a&4 FROM t1; +a a|4 a&4 +3.40 7 0 +SELECT * FROM t1 WHERE (a|4) <> a; +a +3.40 +SELECT * FROM t1 WHERE (a&4) <> a; +a +3.40 +DROP TABLE t1; DROP DATABASE func_bit; USE test; diff --git a/mtr/basic/r/func_bit_mcs.result b/mtr/basic/r/func_bit_mcs.result new file mode 100644 index 000000000..e1cb0b9d7 --- /dev/null +++ b/mtr/basic/r/func_bit_mcs.result @@ -0,0 +1,14 @@ +SET default_storage_engine=ColumnStore; +DROP DATABASE IF EXISTS func_bit_mcs; +CREATE DATABASE func_bit_mcs; +USE func_bit_mcs; +# +# MCOL-4666 Empty set when using BIT OR and BIT AND functions in WHERE +# +CREATE TABLE t1 (a BLOB); +INSERT INTO t1 VALUES ('1'); +SELECT a|1 FROM t1; +ERROR HY000: Internal error: Illegal parameter data type blob for operation bitor +DROP TABLE t1; +DROP DATABASE func_bit_mcs; +USE test; diff --git a/mtr/basic/t/func_bit.test b/mtr/basic/t/func_bit.test index 035359d93..7ff6e4bbe 100644 --- a/mtr/basic/t/func_bit.test +++ b/mtr/basic/t/func_bit.test @@ -131,6 +131,19 @@ SELECT a, 1<>a FROM t1; DROP TABLE t1; +--echo # +--echo # MCOL-4666 Empty set when using BIT OR and BIT AND functions in WHERE +--echo # + +CREATE TABLE t1 (a DECIMAL(18,2)); +INSERT INTO t1 VALUES (3.4); +SELECT a, a|4, a&4 FROM t1; +SELECT * FROM t1 WHERE (a|4) <> a; +SELECT * FROM t1 WHERE (a&4) <> a; +DROP TABLE t1; + + + # # Clean up # diff --git a/mtr/basic/t/func_bit_mcs.test b/mtr/basic/t/func_bit_mcs.test new file mode 100644 index 000000000..22c2ff4c0 --- /dev/null +++ b/mtr/basic/t/func_bit_mcs.test @@ -0,0 +1,30 @@ +--source ../include/have_columnstore.inc + +SET default_storage_engine=ColumnStore; + +--disable_warnings +DROP DATABASE IF EXISTS func_bit_mcs; +--enable_warnings +CREATE DATABASE func_bit_mcs; +USE func_bit_mcs; + + +--echo # +--echo # MCOL-4666 Empty set when using BIT OR and BIT AND functions in WHERE +--echo # + +CREATE TABLE t1 (a BLOB); +INSERT INTO t1 VALUES ('1'); +--error ER_INTERNAL_ERROR +SELECT a|1 FROM t1; +DROP TABLE t1; + + + +# +# Clean up +# + +DROP DATABASE func_bit_mcs; +USE test; + diff --git a/utils/funcexp/func_bitwise.cpp b/utils/funcexp/func_bitwise.cpp index ce0f365ba..69264d197 100644 --- a/utils/funcexp/func_bitwise.cpp +++ b/utils/funcexp/func_bitwise.cpp @@ -50,15 +50,6 @@ namespace using namespace funcexp; -void bitWiseExceptionHandler(const std::string& funcName, - const CalpontSystemCatalog::ColType& colType) -{ - std::ostringstream oss; - oss << funcName << ": datatype of " << execplan::colDataTypeToString(colType.colDataType); - throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT); -} - - bool validateBitOperandTypeOrError(execplan::FunctionColumn &col, const Func & func, uint argno) @@ -66,7 +57,7 @@ bool validateBitOperandTypeOrError(execplan::FunctionColumn &col, auto & type = col.functionParms()[argno]->data()->resultType(); if (type.canReturnXInt64()) return false; - bitWiseExceptionHandler(func.funcName(), type); + func.raiseIllegalParameterDataTypeError(type); return true; } diff --git a/utils/funcexp/funcexp.cpp b/utils/funcexp/funcexp.cpp index 150e3ee0c..6b33bad6e 100644 --- a/utils/funcexp/funcexp.cpp +++ b/utils/funcexp/funcexp.cpp @@ -262,8 +262,6 @@ void FuncExp::evaluate(rowgroup::Row& row, std::vector& expressi { isNull = false; - expression[i]->fixIfNeeded(); - switch (expression[i]->resultType().colDataType) { case CalpontSystemCatalog::DATE: diff --git a/utils/funcexp/functor.h b/utils/funcexp/functor.h index 9ee1dd676..9027ab351 100644 --- a/utils/funcexp/functor.h +++ b/utils/funcexp/functor.h @@ -84,6 +84,16 @@ public: fTimeZone = timeZone; } + void raiseIllegalParameterDataTypeError(const execplan::CalpontSystemCatalog::ColType& colType) const + { + std::ostringstream oss; + oss << "Illegal parameter data type " + << execplan::colDataTypeToString(colType.colDataType) + << " for operation " + << funcName(); + throw logging::IDBExcept(oss.str(), logging::ERR_DATATYPE_NOT_SUPPORT); + } + virtual bool fix(execplan::FunctionColumn &col) const { return false;