You've already forked mariadb-columnstore-engine
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:
@ -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())
|
||||
|
@ -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,7 +465,7 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@ -437,7 +479,7 @@ 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<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,
|
||||
@ -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,7 +590,7 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@ -560,7 +604,7 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user