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

Fix XOR handling in gp_walk to be consistent with other logical operators . XOR is no more ITEM_COND, but ITEM_FUNC

This commit is contained in:
root
2016-05-18 17:15:57 +02:00
parent e28242a885
commit 94a3174688

View File

@ -3734,8 +3734,10 @@ void gp_walk(const Item *item, void *arg)
RecursionCounter r(gwip); // Increments and auto-decrements upon exit. RecursionCounter r(gwip); // Increments and auto-decrements upon exit.
Item::Type itype = item->type(); Item::Type itype = item->type();
//if (itype == Item::FUNC_ITEM && string(((Item_func*)item)->func_name()) == "xor")
// itype = Item::COND_ITEM; // Allow to process XOR(which is Item_func) like other logical operators (which are Item_cond)
if (itype == Item::FUNC_ITEM && ((Item_func*)item)->functype() == Item_func::XOR_FUNC )
itype = Item::COND_ITEM;
if(item->type() == Item::CACHE_ITEM) if(item->type() == Item::CACHE_ITEM)
{ {
@ -3995,20 +3997,40 @@ void gp_walk(const Item *item, void *arg)
} }
case Item::COND_ITEM: case Item::COND_ITEM:
{ {
Item_cond* icp = (Item_cond*)item; // All logical functions are handled here, most of them are Item_cond,
// but XOR (it is Item_func_boolean2)
Item_func *func =(Item_func *)item;
if (icp) enum Item_func::Functype ftype = func->functype();
bool isOr = (ftype == Item_func::COND_OR_FUNC);
bool isXor = (ftype == Item_func::XOR_FUNC);
List<Item> *argumentList;
List<Item> xorArgumentList;
if (isXor)
{ {
for(unsigned i = 0; i < func->argument_count(); i++)
{
xorArgumentList.push_back(func->arguments()[i]);
}
argumentList = &xorArgumentList;
}
else
{
argumentList = ((Item_cond*)item)->argument_list();
}
List_iterator_fast<Item> li(*argumentList);
// @bug2932. if ptWorkStack contains less items than the condition's arguments, // @bug2932. if ptWorkStack contains less items than the condition's arguments,
// the missing one should be in the rcWorkStack, unless the it's subselect. // the missing one should be in the rcWorkStack, unless the it's subselect.
// @todo need to figure out a way to combine these two stacks while walking. // @todo need to figure out a way to combine these two stacks while walking.
//if (gwip->ptWorkStack.size() < icp->argument_list()->elements) //if (gwip->ptWorkStack.size() < icp->argument_list()->elements)
{ {
List_iterator_fast<Item> li(*(icp->argument_list()));
while (Item *it= li++) while (Item *it= li++)
{ {
//@bug3495, @bug5865 error out non-supported OR with correlated subquery //@bug3495, @bug5865 error out non-supported OR with correlated subquery
if (icp->functype() == Item_func::COND_OR_FUNC) if (isOr)
{ {
vector <Item_field*> fieldVec; vector <Item_field*> fieldVec;
uint16_t parseInfo = 0; uint16_t parseInfo = 0;
@ -4035,20 +4057,20 @@ void gp_walk(const Item *item, void *arg)
} }
} }
} }
// @bug1603. MySQL's filter tree is a multi-tree grouped by operator. So more than // @bug1603. MySQL's filter tree is a multi-tree grouped by operator. So more than
// two filters saved on the stack so far might belong to this operator. // two filters saved on the stack so far might belong to this operator.
uint32_t leftInStack = gwip->ptWorkStack.size() - icp->argument_list()->elements + 1; uint32_t leftInStack = gwip->ptWorkStack.size() - argumentList->elements + 1;
while (true) while (true)
{ {
if (gwip->ptWorkStack.size() < 2) if (gwip->ptWorkStack.size() < 2)
break; break;
ParseTree* lhs = gwip->ptWorkStack.top(); ParseTree* lhs = gwip->ptWorkStack.top();
gwip->ptWorkStack.pop(); gwip->ptWorkStack.pop();
SimpleFilter *lsf = dynamic_cast<SimpleFilter*>(lhs->data()); SimpleFilter *lsf = dynamic_cast<SimpleFilter*>(lhs->data());
if (lsf && lsf->op()->data() == "noop") if (lsf && lsf->op()->data() == "noop")
{ {
if (icp->functype() == Item_func::COND_OR_FUNC) if (isOr)
{ {
gwip->parseErrorText = "Unhandled item in WHERE or HAVING clause"; gwip->parseErrorText = "Unhandled item in WHERE or HAVING clause";
gwip->fatalParseError = true; gwip->fatalParseError = true;
@ -4063,7 +4085,7 @@ void gp_walk(const Item *item, void *arg)
SimpleFilter *rsf = dynamic_cast<SimpleFilter*>(rhs->data()); SimpleFilter *rsf = dynamic_cast<SimpleFilter*>(rhs->data());
if (rsf && rsf->op()->data() == "noop") if (rsf && rsf->op()->data() == "noop")
{ {
if (icp->functype() == Item_func::COND_OR_FUNC) if (isOr)
{ {
gwip->parseErrorText = "Unhandled item in WHERE or HAVING clause"; gwip->parseErrorText = "Unhandled item in WHERE or HAVING clause";
gwip->fatalParseError = true; gwip->fatalParseError = true;
@ -4075,22 +4097,19 @@ void gp_walk(const Item *item, void *arg)
continue; continue;
} }
} }
Operator* op = new LogicOperator(icp->func_name()); Operator* op = new LogicOperator(func->func_name());
ParseTree* ptp = new ParseTree(op); ParseTree* ptp = new ParseTree(op);
ptp->left(lhs); ptp->left(lhs);
ptp->right(rhs); ptp->right(rhs);
gwip->ptWorkStack.push(ptp); gwip->ptWorkStack.push(ptp);
if (gwip->ptWorkStack.size() == leftInStack) if (gwip->ptWorkStack.size() == leftInStack)
break; break;
} }
// special handling for subquery with aggregate. MySQL adds isnull function to the selected // special handling for subquery with aggregate. MySQL adds isnull function to the selected
// column. InfiniDB will remove it and set nullmatch flag if it's NOT_IN sub. // column. InfiniDB will remove it and set nullmatch flag if it's NOT_IN sub.
// @todo need more checking here to make sure it's not a user input OR operator // @todo need more checking here to make sure it's not a user input OR operator
if (icp->functype() == Item_func::COND_OR_FUNC && gwip->subQuery) if (isOr && gwip->subQuery)
gwip->subQuery->handleFunc(gwip, icp); gwip->subQuery->handleFunc(gwip, func);
}
break; break;
} }
case Item::REF_ITEM: case Item::REF_ITEM: