diff --git a/dbcon/mysql/ha_calpont_execplan.cpp b/dbcon/mysql/ha_calpont_execplan.cpp index da80366b8..0f54d8bdb 100755 --- a/dbcon/mysql/ha_calpont_execplan.cpp +++ b/dbcon/mysql/ha_calpont_execplan.cpp @@ -3201,6 +3201,20 @@ FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonS // and position. We can't tell which at this point, so we // rebuild the item from the arguments directly and then try to // figure what to pop, if anything, in order to sync the stacks. + // + // MCOL-1341 - With MariaDB 10.2.14 onwards CASE is now in the order: + // [case,]when1,when2,...,then1,then2,...[,else] + // See server commit bf1ca14ff3f3faa9f7a018097b25aa0f66d068cd for more + // information. + int32_t arg_offset = 0; + if ((item->argument_count() - 1) % 2) + { + arg_offset = (item->argument_count() - 1) / 2; + } + else + { + arg_offset = item->argument_count() / 2; + } for (int32_t i = item->argument_count()-1; i >=0; i--) { // For case_searched, we know the items for the WHEN clause will @@ -3209,7 +3223,7 @@ FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonS // Every even numbered arg is a WHEN. In between are the THEN. // An odd number of args indicates an ELSE residing in the last spot. if (funcName == "case_searched" && - i % 2 == 0 && uint(i) != item->argument_count()-1) + (i < arg_offset)) { sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport)); if (!gwi.ptWorkStack.empty() && *gwi.ptWorkStack.top()->data() == sptp->data()) diff --git a/utils/funcexp/func_case.cpp b/utils/funcexp/func_case.cpp index 3787947ab..2b5ae58c2 100644 --- a/utils/funcexp/func_case.cpp +++ b/utils/funcexp/func_case.cpp @@ -52,9 +52,10 @@ inline uint64_t simple_case_cmp(Row& row, CalpontSystemCatalog::ColType& operationColType) { uint64_t i = 0; // index to the parm list - uint64_t n = parm.size() - 1; // remove expression from count of expression_i + result_i - uint64_t hasElse = n % 2; // if 1, then ELSE exist - n -= hasElse; // index to expression + uint64_t n = 0; // remove expression from count of expression_i + result_i + uint64_t hasElse = (parm.size()-1) % 2; // if 1, then ELSE exist + uint64_t whereCount = hasElse ? (parm.size() - 2) / 2 : (parm.size() - 1) / 2; + bool foundIt = false; switch (operationColType.colDataType) { @@ -70,10 +71,13 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { if (ev == parm[i]->data()->getIntVal(row, isNull) && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -90,10 +94,13 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { if (ev == parm[i]->data()->getUintVal(row, isNull) && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -108,11 +115,14 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { //BUG 5362 if (utf8::idb_strcoll(ev.c_str(), parm[i]->data()->getStrVal(row, isNull).c_str()) == 0 && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -126,10 +136,13 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { if (ev == parm[i]->data()->getDecimalVal(row, isNull) && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -143,10 +156,13 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { if (ev == parm[i]->data()->getDoubleVal(row, isNull) && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -160,10 +176,13 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { if (ev == parm[i]->data()->getFloatVal(row, isNull) && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -178,16 +197,24 @@ inline uint64_t simple_case_cmp(Row& row, } } - if (i == n && !hasElse) + if (!foundIt && !hasElse) isNull = true; + else if (!foundIt && hasElse && !isNull) + { + i = parm.size() - 1; + } else if (isNull && hasElse) // BUG 5110. Only way we can exit above with isNull == true is when ev is NULL - // if so and we have else condition we need to use it by setting i = n + // if so and we have else condition we need to use it by setting i = else { - i = n; + i = parm.size() - 1; isNull = false; } + if (foundIt) + { + i += whereCount; + } return i; } @@ -198,21 +225,33 @@ inline uint64_t searched_case_cmp(Row& row, bool& isNull) { uint64_t i = 0; // index to the parm list - uint64_t n = parm.size(); // count of boolean_expression_i + result_i - uint64_t hasElse = n % 2; // if 1, then ELSE exist - n -= hasElse; // index to expression + uint64_t hasElse = parm.size() % 2; // if 1, then ELSE exist + uint64_t whereCount = hasElse ? (parm.size() - 1) / 2 : parm.size() / 2; + bool foundIt = false; - for (; i < n; i += 2) + + for (i = 0; i < whereCount; i++) { if (parm[i]->getBoolVal(row, isNull)) + { + foundIt = true; break; + } } isNull = false; - if (i == n && !hasElse) + if (!foundIt && !hasElse) isNull = true; + else if (!foundIt && hasElse) + { + i = parm.size() - 1; + } + if (foundIt) + { + i += whereCount; + } - return (i == n ? i-1 : i); + return i; } @@ -220,7 +259,6 @@ CalpontSystemCatalog::ColType caseOperationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType, bool simpleCase) { - // ... expression_i + result_i + ... [[expression] + result_N] FunctionParm::size_type n = fp.size(); if (simpleCase) // simple case has an expression @@ -228,6 +266,9 @@ CalpontSystemCatalog::ColType caseOperationType(FunctionParm& fp, bool hasElse = ((n % 2) != 0); // if 1, then ELSE exist if (hasElse) --n; // n now is an even number + uint64_t parmCount = hasElse ? (fp.size() - 2) : (fp.size() - 1); + uint64_t whereCount = hasElse ? (fp.size() - 2 + simpleCase) / 2 : (fp.size() - 1) / 2 + simpleCase; + idbassert((n % 2) == 0); bool allStringO = true; @@ -238,10 +279,10 @@ CalpontSystemCatalog::ColType caseOperationType(FunctionParm& fp, CalpontSystemCatalog::ColType oct = fp[l]->data()->resultType(); CalpontSystemCatalog::ColType rct = resultType; bool operation = true; - for (uint64_t i = 0; i <= n; i++) + for (uint64_t i = 0; i <= parmCount; i++) { // operation or result type - operation = ((i % 2) == 0); + operation = ((i > 0) && (i <= whereCount)); // the result type of ELSE, if exists. if (i == n) @@ -334,8 +375,9 @@ namespace funcexp // END // // simple CASE parm order: -// expression1 result1 expression2 result2 ... expression [resultN] +// expression condition1 condition2 ... result1 result2 ... [resultN] // +// Note that this order changed in 10.2.14, see MCOL-1341 CalpontSystemCatalog::ColType Func_simple_case::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) { @@ -353,7 +395,7 @@ bool Func_simple_case::getBoolVal(Row& row, if (isNull) return joblist::BIGINTNULL; - return parm[i+1]->data()->getBoolVal(row, isNull); + return parm[i]->data()->getBoolVal(row, isNull); } @@ -367,7 +409,7 @@ int64_t Func_simple_case::getIntVal(Row& row, if (isNull) return joblist::BIGINTNULL; - return parm[i+1]->data()->getIntVal(row, isNull); + return parm[i]->data()->getIntVal(row, isNull); } @@ -381,7 +423,7 @@ string Func_simple_case::getStrVal(Row& row, if (isNull) return string(""); - return parm[i+1]->data()->getStrVal(row, isNull); + return parm[i]->data()->getStrVal(row, isNull); } @@ -395,7 +437,7 @@ IDB_Decimal Func_simple_case::getDecimalVal(Row& row, if (isNull) return IDB_Decimal(); // need a null value for IDB_Decimal?? - return parm[i+1]->data()->getDecimalVal(row, isNull); + return parm[i]->data()->getDecimalVal(row, isNull); } @@ -409,7 +451,7 @@ double Func_simple_case::getDoubleVal(Row& row, if (isNull) return doubleNullVal(); - return parm[i+1]->data()->getDoubleVal(row, isNull); + return parm[i]->data()->getDoubleVal(row, isNull); } @@ -423,9 +465,9 @@ int32_t Func_simple_case::getDateIntVal(rowgroup::Row& row, if (isNull) return joblist::DATENULL; - return parm[i+1]->data()->getDateIntVal(row, isNull); -} - + return parm[i]->data()->getDateIntVal(row, isNull); +} + int64_t Func_simple_case::getDatetimeIntVal(rowgroup::Row& row, FunctionParm& parm, @@ -437,8 +479,8 @@ int64_t Func_simple_case::getDatetimeIntVal(rowgroup::Row& row, if (isNull) return joblist::DATETIMENULL; - return parm[i+1]->data()->getDatetimeIntVal(row, isNull); -} + return parm[i]->data()->getDatetimeIntVal(row, isNull); +} @@ -451,8 +493,10 @@ int64_t Func_simple_case::getDatetimeIntVal(rowgroup::Row& row, // END // // searched CASE parm order: -// boolean_expression1 result1 boolean_expression2 result2 ... [resultN] +// boolean_expression1 boolean_expression2 ... result1 result2 ... [resultN] // +// Note that this order changed in 10.2.14, see MCOL-1341 + CalpontSystemCatalog::ColType Func_searched_case::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) { // operation type not used by this functor. @@ -470,14 +514,14 @@ bool Func_searched_case::getBoolVal(Row& row, if (isNull) return joblist::BIGINTNULL; - ParseTree* lop = parm[i+1]->left(); - ParseTree* rop = parm[i+1]->right(); + ParseTree* lop = parm[i]->left(); + ParseTree* rop = parm[i]->right(); if (lop && rop) { - return (reinterpret_cast(parm[i+1]->data()))->getBoolVal(row, isNull, lop, rop); + return (reinterpret_cast(parm[i]->data()))->getBoolVal(row, isNull, lop, rop); } - return parm[i+1]->data()->getBoolVal(row, isNull); + return parm[i]->data()->getBoolVal(row, isNull); } int64_t Func_searched_case::getIntVal(Row& row, @@ -490,7 +534,7 @@ int64_t Func_searched_case::getIntVal(Row& row, if (isNull) return joblist::BIGINTNULL; - return parm[i+1]->data()->getIntVal(row, isNull); + return parm[i]->data()->getIntVal(row, isNull); } @@ -504,7 +548,7 @@ string Func_searched_case::getStrVal(Row& row, if (isNull) return string(""); - return parm[i+1]->data()->getStrVal(row, isNull); + return parm[i]->data()->getStrVal(row, isNull); } @@ -518,7 +562,7 @@ IDB_Decimal Func_searched_case::getDecimalVal(Row& row, if (isNull) return IDB_Decimal(); // need a null value for IDB_Decimal?? - return parm[i+1]->data()->getDecimalVal(row, isNull); + return parm[i]->data()->getDecimalVal(row, isNull); } @@ -532,7 +576,7 @@ double Func_searched_case::getDoubleVal(Row& row, if (isNull) return doubleNullVal(); - return parm[i+1]->data()->getDoubleVal(row, isNull); + return parm[i]->data()->getDoubleVal(row, isNull); } @@ -546,10 +590,10 @@ int32_t Func_searched_case::getDateIntVal(rowgroup::Row& row, if (isNull) return joblist::DATENULL; - return parm[i+1]->data()->getDateIntVal(row, isNull); -} + return parm[i]->data()->getDateIntVal(row, isNull); +} + - int64_t Func_searched_case::getDatetimeIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, @@ -560,8 +604,8 @@ int64_t Func_searched_case::getDatetimeIntVal(rowgroup::Row& row, if (isNull) return joblist::DATETIMENULL; - return parm[i+1]->data()->getDatetimeIntVal(row, isNull); -} + return parm[i]->data()->getDatetimeIntVal(row, isNull); +} } // namespace funcexp