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-1234 Nested CASE filters not processed
Change the way buildCaseFunction() handles the ptWorkStack and the rcWorkStack.
This commit is contained in:
@ -102,7 +102,7 @@ void ArithmeticOperator::unserialize(messageqcpp::ByteStream& b)
|
|||||||
|
|
||||||
bool ArithmeticOperator::operator==(const ArithmeticOperator& t) const
|
bool ArithmeticOperator::operator==(const ArithmeticOperator& t) const
|
||||||
{
|
{
|
||||||
if (fData == t.fData)
|
if (data() == t.data())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ const string Filter::toString() const
|
|||||||
|
|
||||||
bool Filter::operator==(const Filter& t) const
|
bool Filter::operator==(const Filter& t) const
|
||||||
{
|
{
|
||||||
if (fData == t.fData)
|
if (data() == t.data())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ void LogicOperator::unserialize(messageqcpp::ByteStream& b)
|
|||||||
|
|
||||||
bool LogicOperator::operator==(const LogicOperator& t) const
|
bool LogicOperator::operator==(const LogicOperator& t) const
|
||||||
{
|
{
|
||||||
if (fData == t.fData)
|
if (data() == t.data())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ void PredicateOperator::unserialize(messageqcpp::ByteStream& b)
|
|||||||
|
|
||||||
bool PredicateOperator::operator==(const PredicateOperator& t) const
|
bool PredicateOperator::operator==(const PredicateOperator& t) const
|
||||||
{
|
{
|
||||||
if (fData == t.fData)
|
if (data() == t.data())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -370,16 +370,16 @@ bool SimpleColumn::operator==(const SimpleColumn& t) const
|
|||||||
return false;
|
return false;
|
||||||
if (fColumnName != t.fColumnName)
|
if (fColumnName != t.fColumnName)
|
||||||
return false;
|
return false;
|
||||||
if (fIndexName != t.fIndexName)
|
// if (fIndexName != t.fIndexName)
|
||||||
return false;
|
// return false;
|
||||||
if (fViewName != t.fViewName)
|
if (fViewName != t.fViewName)
|
||||||
return false;
|
return false;
|
||||||
if (fOid != t.fOid)
|
if (fOid != t.fOid)
|
||||||
return false;
|
return false;
|
||||||
if (fData != t.fData)
|
if (data() != t.data())
|
||||||
return false;
|
|
||||||
if (fAlias != t.fAlias)
|
|
||||||
return false;
|
return false;
|
||||||
|
// if (fAlias != t.fAlias)
|
||||||
|
// return false;
|
||||||
if (fTableAlias != t.fTableAlias)
|
if (fTableAlias != t.fTableAlias)
|
||||||
return false;
|
return false;
|
||||||
if (fAsc != t.fAsc)
|
if (fAsc != t.fAsc)
|
||||||
|
@ -63,7 +63,7 @@ const string TreeNodeImpl::toString() const
|
|||||||
|
|
||||||
bool TreeNodeImpl::operator==(const TreeNodeImpl& t) const
|
bool TreeNodeImpl::operator==(const TreeNodeImpl& t) const
|
||||||
{
|
{
|
||||||
if (fData == t.fData)
|
if (data() == t.data())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -3190,107 +3190,85 @@ FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonS
|
|||||||
funcName = "case_searched";
|
funcName = "case_searched";
|
||||||
|
|
||||||
funcParms.reserve(item->argument_count());
|
funcParms.reserve(item->argument_count());
|
||||||
if (gwi.clauseType == SELECT || gwi.clauseType == HAVING || gwi.clauseType == GROUP_BY) // select clause
|
// so buildXXXcolumn function will not pop stack.
|
||||||
|
ClauseType realClauseType = gwi.clauseType;
|
||||||
|
gwi.clauseType = SELECT;
|
||||||
|
|
||||||
|
// We ought to be able to just build from the stack, and would
|
||||||
|
// be able to if there were any way to know which stack had the
|
||||||
|
// next case item. Unfortunately, parameters may have been pushed
|
||||||
|
// onto the ptWorkStack or rcWorkStack or neither, depending on type
|
||||||
|
// 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.
|
||||||
|
for (int32_t i = item->argument_count()-1; i >=0; i--)
|
||||||
{
|
{
|
||||||
// the first argument
|
// For case_searched, we know the items for the WHEN clause will
|
||||||
if (funcName == "case_searched")
|
// not be ReturnedColumns. We do this separately just to save
|
||||||
|
// some cpu cycles trying to build a ReturnedColumn as below.
|
||||||
|
// 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)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < item->argument_count(); i++)
|
sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport));
|
||||||
|
if (!gwi.ptWorkStack.empty() && *gwi.ptWorkStack.top()->data() == sptp->data())
|
||||||
{
|
{
|
||||||
if (i % 2 == 0 && i != 1 && i != item->argument_count()-1)
|
gwi.ptWorkStack.pop();
|
||||||
{
|
|
||||||
sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport));
|
|
||||||
funcParms.push_back(sptp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ReturnedColumn* parm = buildReturnedColumn(item->arguments()[i], gwi, nonSupport);
|
|
||||||
if (parm)
|
|
||||||
{
|
|
||||||
sptp.reset(new ParseTree(parm));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport));
|
|
||||||
}
|
|
||||||
funcParms.push_back(sptp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < item->argument_count(); i++)
|
// First try building a ReturnedColumn. It may or may not succeed
|
||||||
|
// depending on the types involved. There's also little correlation
|
||||||
|
// between buildReturnedColumn and the existance of the item on
|
||||||
|
// rwWorkStack or ptWorkStack.
|
||||||
|
// For example, simple predicates, such as 1=1 or 1=0, land in the
|
||||||
|
// ptWorkStack but other stuff might land in the rwWorkStack
|
||||||
|
ReturnedColumn* parm = buildReturnedColumn(item->arguments()[i], gwi, nonSupport);
|
||||||
|
if (parm)
|
||||||
{
|
{
|
||||||
ReturnedColumn* parm = buildReturnedColumn(item->arguments()[i], gwi, nonSupport);
|
sptp.reset(new ParseTree(parm));
|
||||||
if (parm)
|
// We need to pop whichever stack is holding it, if any.
|
||||||
|
if ((!gwi.rcWorkStack.empty()) &&
|
||||||
|
*gwi.rcWorkStack.top() == parm)
|
||||||
{
|
{
|
||||||
sptp.reset(new ParseTree(parm));
|
gwi.rcWorkStack.pop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if (!gwi.ptWorkStack.empty())
|
||||||
{
|
{
|
||||||
sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport));
|
ReturnedColumn* ptrc = dynamic_cast<ReturnedColumn*>(gwi.ptWorkStack.top()->data());
|
||||||
}
|
if (ptrc && *ptrc == *parm)
|
||||||
funcParms.push_back(sptp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // where clause
|
|
||||||
{
|
|
||||||
// so buildXXXcolumn function will not pop stack.
|
|
||||||
gwi.clauseType = SELECT;
|
|
||||||
if (funcName == "case_searched")
|
|
||||||
{
|
|
||||||
for (int32_t i = item->argument_count()-1; i >=0; i--)
|
|
||||||
{
|
|
||||||
if (i % 2 == 0 && uint(i) != item->argument_count()-1)
|
|
||||||
{
|
|
||||||
// build item from arguments to avoid parm sequence complexity
|
|
||||||
sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport));
|
|
||||||
if (!gwi.ptWorkStack.empty())
|
|
||||||
gwi.ptWorkStack.pop();
|
gwi.ptWorkStack.pop();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
ReturnedColumn* parm = buildReturnedColumn(item->arguments()[i], gwi, nonSupport);
|
|
||||||
if (parm)
|
|
||||||
{
|
|
||||||
sptp.reset(new ParseTree(parm));
|
|
||||||
if (!gwi.rcWorkStack.empty())
|
|
||||||
gwi.rcWorkStack.pop();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport));
|
|
||||||
if (!gwi.ptWorkStack.empty())
|
|
||||||
gwi.ptWorkStack.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
funcParms.insert(funcParms.begin(), sptp);
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else // simple_case
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < item->argument_count(); i++)
|
|
||||||
{
|
{
|
||||||
ReturnedColumn* parm = buildReturnedColumn(item->arguments()[i], gwi, nonSupport);
|
sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport));
|
||||||
if (parm)
|
// We need to pop whichever stack is holding it, if any.
|
||||||
|
if ((!gwi.ptWorkStack.empty()) &&
|
||||||
|
*gwi.ptWorkStack.top()->data() == sptp->data())
|
||||||
{
|
{
|
||||||
sptp.reset(new ParseTree(parm));
|
gwi.ptWorkStack.pop();
|
||||||
if (!gwi.rcWorkStack.empty())
|
}
|
||||||
|
else
|
||||||
|
if (!gwi.rcWorkStack.empty())
|
||||||
|
{
|
||||||
|
// Probably won't happen, but it might have been on the
|
||||||
|
// rcWorkStack all along.
|
||||||
|
ReturnedColumn* ptrc = dynamic_cast<ReturnedColumn*>(sptp->data());
|
||||||
|
if (ptrc && *ptrc == *gwi.rcWorkStack.top())
|
||||||
|
{
|
||||||
gwi.rcWorkStack.pop();
|
gwi.rcWorkStack.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport));
|
|
||||||
if (!gwi.ptWorkStack.empty())
|
|
||||||
gwi.ptWorkStack.pop();
|
|
||||||
}
|
|
||||||
funcParms.push_back(sptp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// recover clause type
|
funcParms.insert(funcParms.begin(), sptp);
|
||||||
gwi.clauseType = WHERE;
|
|
||||||
}
|
}
|
||||||
|
// recover clause type
|
||||||
|
gwi.clauseType = realClauseType;
|
||||||
|
|
||||||
if (gwi.fatalParseError)
|
if (gwi.fatalParseError)
|
||||||
{
|
{
|
||||||
@ -4259,9 +4237,9 @@ void gp_walk(const Item *item, void *arg)
|
|||||||
}
|
}
|
||||||
// bug 3137. If filter constant like 1=0, put it to ptWorkStack
|
// bug 3137. If filter constant like 1=0, put it to ptWorkStack
|
||||||
// MariaDB bug 750. Breaks if compare is an argument to a function.
|
// MariaDB bug 750. Breaks if compare is an argument to a function.
|
||||||
if ((int32_t)gwip->rcWorkStack.size() <= (gwip->rcBookMarkStack.empty() ? 0 : gwip->rcBookMarkStack.top())
|
// if ((int32_t)gwip->rcWorkStack.size() <= (gwip->rcBookMarkStack.empty() ? 0 : gwip->rcBookMarkStack.top())
|
||||||
&& isPredicateFunction(ifp, gwip))
|
// && isPredicateFunction(ifp, gwip))
|
||||||
// if (isPredicateFunction(ifp, gwip))
|
if (isPredicateFunction(ifp, gwip))
|
||||||
gwip->ptWorkStack.push(new ParseTree(cc));
|
gwip->ptWorkStack.push(new ParseTree(cc));
|
||||||
else
|
else
|
||||||
gwip->rcWorkStack.push(cc);
|
gwip->rcWorkStack.push(cc);
|
||||||
@ -5505,7 +5483,9 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
|||||||
// @bug 1706
|
// @bug 1706
|
||||||
String funcStr;
|
String funcStr;
|
||||||
ifp->print(&funcStr, QT_INFINIDB);
|
ifp->print(&funcStr, QT_INFINIDB);
|
||||||
gwi.selectCols.push_back(string(funcStr.c_ptr()) + " `" + escapeBackTick(ifp->name) + "`");
|
string valStr;
|
||||||
|
valStr.assign(funcStr.ptr(), funcStr.length());
|
||||||
|
gwi.selectCols.push_back(valStr + " `" + escapeBackTick(ifp->name) + "`");
|
||||||
// clear the error set by buildFunctionColumn
|
// clear the error set by buildFunctionColumn
|
||||||
gwi.fatalParseError = false;
|
gwi.fatalParseError = false;
|
||||||
gwi.parseErrorText = "";
|
gwi.parseErrorText = "";
|
||||||
|
Reference in New Issue
Block a user