1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

MCOL-1341 Fix CASE handling with 10.2.14

MariaDB Server 10.2.14 changed the order that CASE items are processed.
This broke the engine's CASE handling. This patch uses the new order
instead since this is what will be used in 10.2 and 10.3 going forward.
This commit is contained in:
Andrew Hutchings
2018-04-16 19:21:28 +01:00
parent ae04b8a687
commit 0c6dc5e15c
2 changed files with 105 additions and 47 deletions

View File

@ -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 // and position. We can't tell which at this point, so we
// rebuild the item from the arguments directly and then try to // rebuild the item from the arguments directly and then try to
// figure what to pop, if anything, in order to sync the stacks. // 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 (int32_t i = item->argument_count()-1; i >=0; i--)
{ {
// For case_searched, we know the items for the WHEN clause will // 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. // 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. // An odd number of args indicates an ELSE residing in the last spot.
if (funcName == "case_searched" && 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)); sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport));
if (!gwi.ptWorkStack.empty() && *gwi.ptWorkStack.top()->data() == sptp->data()) if (!gwi.ptWorkStack.empty() && *gwi.ptWorkStack.top()->data() == sptp->data())

View File

@ -52,9 +52,10 @@ inline uint64_t simple_case_cmp(Row& row,
CalpontSystemCatalog::ColType& operationColType) CalpontSystemCatalog::ColType& operationColType)
{ {
uint64_t i = 0; // index to the parm list 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 n = 0; // remove expression from count of expression_i + result_i
uint64_t hasElse = n % 2; // if 1, then ELSE exist uint64_t hasElse = (parm.size()-1) % 2; // if 1, then ELSE exist
n -= hasElse; // index to expression uint64_t whereCount = hasElse ? (parm.size() - 2) / 2 : (parm.size() - 1) / 2;
bool foundIt = false;
switch (operationColType.colDataType) switch (operationColType.colDataType)
{ {
@ -70,10 +71,13 @@ inline uint64_t simple_case_cmp(Row& row,
if (isNull) if (isNull)
break; break;
for (; i < n; i += 2) for (i = 1; i <= whereCount; i++)
{ {
if (ev == parm[i]->data()->getIntVal(row, isNull) && !isNull) if (ev == parm[i]->data()->getIntVal(row, isNull) && !isNull)
{
foundIt = true;
break; break;
}
else else
isNull = false; isNull = false;
} }
@ -90,10 +94,13 @@ inline uint64_t simple_case_cmp(Row& row,
if (isNull) if (isNull)
break; break;
for (; i < n; i += 2) for (i = 1; i <= whereCount; i++)
{ {
if (ev == parm[i]->data()->getUintVal(row, isNull) && !isNull) if (ev == parm[i]->data()->getUintVal(row, isNull) && !isNull)
{
foundIt = true;
break; break;
}
else else
isNull = false; isNull = false;
} }
@ -108,11 +115,14 @@ inline uint64_t simple_case_cmp(Row& row,
if (isNull) if (isNull)
break; break;
for (; i < n; i += 2) for (i = 1; i <= whereCount; i++)
{ {
//BUG 5362 //BUG 5362
if (utf8::idb_strcoll(ev.c_str(), parm[i]->data()->getStrVal(row, isNull).c_str()) == 0 && !isNull) if (utf8::idb_strcoll(ev.c_str(), parm[i]->data()->getStrVal(row, isNull).c_str()) == 0 && !isNull)
{
foundIt = true;
break; break;
}
else else
isNull = false; isNull = false;
} }
@ -126,10 +136,13 @@ inline uint64_t simple_case_cmp(Row& row,
if (isNull) if (isNull)
break; break;
for (; i < n; i += 2) for (i = 1; i <= whereCount; i++)
{ {
if (ev == parm[i]->data()->getDecimalVal(row, isNull) && !isNull) if (ev == parm[i]->data()->getDecimalVal(row, isNull) && !isNull)
{
foundIt = true;
break; break;
}
else else
isNull = false; isNull = false;
} }
@ -143,10 +156,13 @@ inline uint64_t simple_case_cmp(Row& row,
if (isNull) if (isNull)
break; break;
for (; i < n; i += 2) for (i = 1; i <= whereCount; i++)
{ {
if (ev == parm[i]->data()->getDoubleVal(row, isNull) && !isNull) if (ev == parm[i]->data()->getDoubleVal(row, isNull) && !isNull)
{
foundIt = true;
break; break;
}
else else
isNull = false; isNull = false;
} }
@ -160,10 +176,13 @@ inline uint64_t simple_case_cmp(Row& row,
if (isNull) if (isNull)
break; break;
for (; i < n; i += 2) for (i = 1; i <= whereCount; i++)
{ {
if (ev == parm[i]->data()->getFloatVal(row, isNull) && !isNull) if (ev == parm[i]->data()->getFloatVal(row, isNull) && !isNull)
{
foundIt = true;
break; break;
}
else else
isNull = false; isNull = false;
} }
@ -178,16 +197,24 @@ inline uint64_t simple_case_cmp(Row& row,
} }
} }
if (i == n && !hasElse) if (!foundIt && !hasElse)
isNull = true; isNull = true;
else if (!foundIt && hasElse && !isNull)
{
i = parm.size() - 1;
}
else if (isNull && hasElse) else if (isNull && hasElse)
// BUG 5110. Only way we can exit above with isNull == true is when ev is NULL // 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; isNull = false;
} }
if (foundIt)
{
i += whereCount;
}
return i; return i;
} }
@ -198,21 +225,33 @@ inline uint64_t searched_case_cmp(Row& row,
bool& isNull) bool& isNull)
{ {
uint64_t i = 0; // index to the parm list uint64_t i = 0; // index to the parm list
uint64_t n = parm.size(); // count of boolean_expression_i + result_i uint64_t hasElse = parm.size() % 2; // if 1, then ELSE exist
uint64_t hasElse = n % 2; // if 1, then ELSE exist uint64_t whereCount = hasElse ? (parm.size() - 1) / 2 : parm.size() / 2;
n -= hasElse; // index to expression bool foundIt = false;
for (; i < n; i += 2)
for (i = 0; i < whereCount; i++)
{ {
if (parm[i]->getBoolVal(row, isNull)) if (parm[i]->getBoolVal(row, isNull))
{
foundIt = true;
break; break;
}
} }
isNull = false; isNull = false;
if (i == n && !hasElse) if (!foundIt && !hasElse)
isNull = true; 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, CalpontSystemCatalog::ColType& resultType,
bool simpleCase) bool simpleCase)
{ {
// ... expression_i + result_i + ... [[expression] + result_N]
FunctionParm::size_type n = fp.size(); FunctionParm::size_type n = fp.size();
if (simpleCase) // simple case has an expression 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 bool hasElse = ((n % 2) != 0); // if 1, then ELSE exist
if (hasElse) if (hasElse)
--n; // n now is an even number --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); idbassert((n % 2) == 0);
bool allStringO = true; bool allStringO = true;
@ -238,10 +279,10 @@ CalpontSystemCatalog::ColType caseOperationType(FunctionParm& fp,
CalpontSystemCatalog::ColType oct = fp[l]->data()->resultType(); CalpontSystemCatalog::ColType oct = fp[l]->data()->resultType();
CalpontSystemCatalog::ColType rct = resultType; CalpontSystemCatalog::ColType rct = resultType;
bool operation = true; bool operation = true;
for (uint64_t i = 0; i <= n; i++) for (uint64_t i = 0; i <= parmCount; i++)
{ {
// operation or result type // operation or result type
operation = ((i % 2) == 0); operation = ((i > 0) && (i <= whereCount));
// the result type of ELSE, if exists. // the result type of ELSE, if exists.
if (i == n) if (i == n)
@ -334,8 +375,9 @@ namespace funcexp
// END // END
// //
// simple CASE parm order: // 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) CalpontSystemCatalog::ColType Func_simple_case::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType)
{ {
@ -353,7 +395,7 @@ bool Func_simple_case::getBoolVal(Row& row,
if (isNull) if (isNull)
return joblist::BIGINTNULL; 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) if (isNull)
return joblist::BIGINTNULL; 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) if (isNull)
return string(""); 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) if (isNull)
return IDB_Decimal(); // need a null value for IDB_Decimal?? 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) if (isNull)
return doubleNullVal(); 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) if (isNull)
return joblist::DATENULL; 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, int64_t Func_simple_case::getDatetimeIntVal(rowgroup::Row& row,
FunctionParm& parm, FunctionParm& parm,
@ -437,8 +479,8 @@ int64_t Func_simple_case::getDatetimeIntVal(rowgroup::Row& row,
if (isNull) if (isNull)
return joblist::DATETIMENULL; 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 // END
// //
// searched CASE parm order: // 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) CalpontSystemCatalog::ColType Func_searched_case::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType)
{ {
// operation type not used by this functor. // operation type not used by this functor.
@ -470,14 +514,14 @@ bool Func_searched_case::getBoolVal(Row& row,
if (isNull) if (isNull)
return joblist::BIGINTNULL; return joblist::BIGINTNULL;
ParseTree* lop = parm[i+1]->left(); ParseTree* lop = parm[i]->left();
ParseTree* rop = parm[i+1]->right(); ParseTree* rop = parm[i]->right();
if (lop && rop) if (lop && rop)
{ {
return (reinterpret_cast<Operator*>(parm[i+1]->data()))->getBoolVal(row, isNull, lop, rop); return (reinterpret_cast<Operator*>(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, int64_t Func_searched_case::getIntVal(Row& row,
@ -490,7 +534,7 @@ int64_t Func_searched_case::getIntVal(Row& row,
if (isNull) if (isNull)
return joblist::BIGINTNULL; 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) if (isNull)
return string(""); 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) if (isNull)
return IDB_Decimal(); // need a null value for IDB_Decimal?? 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) if (isNull)
return doubleNullVal(); 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) if (isNull)
return joblist::DATENULL; 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, int64_t Func_searched_case::getDatetimeIntVal(rowgroup::Row& row,
FunctionParm& parm, FunctionParm& parm,
bool& isNull, bool& isNull,
@ -560,8 +604,8 @@ int64_t Func_searched_case::getDatetimeIntVal(rowgroup::Row& row,
if (isNull) if (isNull)
return joblist::DATETIMENULL; return joblist::DATETIMENULL;
return parm[i+1]->data()->getDatetimeIntVal(row, isNull); return parm[i]->data()->getDatetimeIntVal(row, isNull);
} }
} // namespace funcexp } // namespace funcexp