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
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:
@ -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:
|
||||||
|
Reference in New Issue
Block a user