You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-29 08:21:15 +03:00
fix(group by, having): MCOL-5776: GROUP BY/HAVING closer to server's (#3371)
This patch introduces an internal aggregate operator SELECT_SOME that is automatically added to columns that are not in GROUP BY. It "computes" some plausible value of the column (actually, last one passed). Along the way it fixes incorrect handling of HAVING being transferred into WHERE, window function handling and a bit of other inconsistencies.
This commit is contained in:
@ -96,6 +96,7 @@ const uint64_t SUB_BIT = 0x02;
|
||||
const uint64_t AF_BIT = 0x04;
|
||||
const uint64_t CORRELATED = 0x08;
|
||||
|
||||
|
||||
// In certain cases, gp_walk is called recursively. When done so,
|
||||
// we need to bookmark the rcWorkStack for those cases where a constant
|
||||
// expression such as 1=1 is used in an if statement or function call.
|
||||
@ -161,6 +162,51 @@ void calculateNotNullTables(const std::vector<COND*>& condList, table_map& not_n
|
||||
}
|
||||
}
|
||||
|
||||
bool itemDisablesWrapping(Item* item, gp_walk_info& gwi);
|
||||
|
||||
void pushReturnedCol(gp_walk_info& gwi, Item* from, SRCP rc)
|
||||
{
|
||||
uint32_t i;
|
||||
for ( i = 0; i < gwi.processed.size(); i++)
|
||||
{
|
||||
Item* ith = gwi.processed[i].first;
|
||||
|
||||
bool same = ith->eq(from, false);
|
||||
|
||||
if (same && ith->type() == Item::FUNC_ITEM)
|
||||
{
|
||||
// an exception for cast(column as decimal(X,Y)) - they are equal (in the eq() call sense)
|
||||
// even if Xs and Ys are different.
|
||||
string funcName = ((Item_func*)ith)->func_name();
|
||||
|
||||
if (funcName == "decimal_typecast")
|
||||
{
|
||||
Item_decimal_typecast* ithdtc = (Item_decimal_typecast*)ith;
|
||||
Item_decimal_typecast* fromdtc = (Item_decimal_typecast*)from;
|
||||
same = ithdtc->decimals == fromdtc->decimals && ithdtc->max_length == fromdtc->max_length;
|
||||
}
|
||||
}
|
||||
if (same)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool needChange = true;
|
||||
if (dynamic_cast<SimpleColumn*>(rc.get()) == nullptr && gwi.select_lex && !itemDisablesWrapping(from, gwi))
|
||||
{
|
||||
needChange = false;
|
||||
}
|
||||
if (needChange && i < gwi.processed.size())
|
||||
{
|
||||
rc->expressionId(gwi.processed[i].second);
|
||||
}
|
||||
else
|
||||
{
|
||||
gwi.processed.push_back(std::make_pair(from, rc->expressionId()));
|
||||
}
|
||||
gwi.returnedCols.push_back(rc);
|
||||
}
|
||||
|
||||
// Recursively iterate through the join_list and store all non-null
|
||||
// TABLE_LIST::on_expr items to a hash map keyed by the TABLE_LIST ptr.
|
||||
// This is then used by convertOuterJoinToInnerJoin().
|
||||
@ -605,7 +651,6 @@ ReturnedColumn* buildAggFrmTempField(Item* item, gp_walk_info& gwi)
|
||||
Item_field* ifip = NULL;
|
||||
Item_ref* irip;
|
||||
Item_func_or_sum* isfp;
|
||||
|
||||
switch (item->type())
|
||||
{
|
||||
case Item::FIELD_ITEM: ifip = static_cast<Item_field*>(item); break;
|
||||
@ -2069,15 +2114,18 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
|
||||
}
|
||||
|
||||
sop.reset(new PredicateOperator(eqop));
|
||||
sop->setOpType(gwip->scsp->resultType(), rhs->resultType());
|
||||
SRCP scsp = gwip->scsp;
|
||||
idbassert(scsp.get() != nullptr);
|
||||
//sop->setOpType(gwip->scsp->resultType(), rhs->resultType());
|
||||
sop->setOpType(scsp->resultType(), rhs->resultType());
|
||||
ConstantFilter* cf = 0;
|
||||
|
||||
cf = new ConstantFilter(sop, gwip->scsp->clone(), rhs);
|
||||
cf = new ConstantFilter(sop, scsp->clone(), lhs);
|
||||
sop.reset(new LogicOperator(cmbop));
|
||||
cf->op(sop);
|
||||
sop.reset(new PredicateOperator(eqop));
|
||||
sop->setOpType(gwip->scsp->resultType(), lhs->resultType());
|
||||
cf->pushFilter(new SimpleFilter(sop, gwip->scsp->clone(), lhs, gwip->timeZone));
|
||||
sop->setOpType(scsp->resultType(), rhs->resultType());
|
||||
cf->pushFilter(new SimpleFilter(sop, scsp->clone(), rhs->clone(), gwip->timeZone));
|
||||
|
||||
while (!gwip->rcWorkStack.empty())
|
||||
{
|
||||
@ -2088,8 +2136,8 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
|
||||
|
||||
gwip->rcWorkStack.pop();
|
||||
sop.reset(new PredicateOperator(eqop));
|
||||
sop->setOpType(gwip->scsp->resultType(), lhs->resultType());
|
||||
cf->pushFilter(new SimpleFilter(sop, gwip->scsp->clone(), lhs, gwip->timeZone));
|
||||
sop->setOpType(scsp->resultType(), lhs->resultType());
|
||||
cf->pushFilter(new SimpleFilter(sop, scsp->clone(), lhs->clone(), gwip->timeZone));
|
||||
}
|
||||
|
||||
if (!gwip->rcWorkStack.empty())
|
||||
@ -2413,7 +2461,9 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
|
||||
RowColumn* rlhs = dynamic_cast<RowColumn*>(lhs);
|
||||
|
||||
if (rrhs && rlhs)
|
||||
{
|
||||
return buildRowColumnFilter(gwip, rrhs, rlhs, ifp);
|
||||
}
|
||||
|
||||
vector<Item*> itemList;
|
||||
|
||||
@ -3320,6 +3370,78 @@ CalpontSystemCatalog::ColType colType_MysqlToIDB(const Item* item)
|
||||
return ct;
|
||||
}
|
||||
|
||||
bool itemDisablesWrapping(Item* item, gp_walk_info& gwi)
|
||||
{
|
||||
if (gwi.select_lex == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
ORDER* groupcol = static_cast<ORDER*>(gwi.select_lex->group_list.first);
|
||||
|
||||
while (groupcol)
|
||||
{
|
||||
Item* gci = *groupcol->item;
|
||||
while (gci->type() == Item::REF_ITEM)
|
||||
{
|
||||
if (item->eq(gci, false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Item_ref* ref = (Item_ref*)gci;
|
||||
gci = *(ref->ref);
|
||||
}
|
||||
if (item->eq(gci, false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
groupcol = groupcol->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ReturnedColumn* wrapIntoAggregate(ReturnedColumn* rc, gp_walk_info& gwi, Item* baseItem)
|
||||
{
|
||||
if (!gwi.implicitExplicitGroupBy || gwi.disableWrapping || !gwi.select_lex)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (dynamic_cast<AggregateColumn*>(rc) != nullptr || dynamic_cast<ConstantColumn*>(rc) != nullptr)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (itemDisablesWrapping(baseItem, gwi))
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
cal_connection_info* ci = static_cast<cal_connection_info*>(get_fe_conn_info_ptr());
|
||||
|
||||
AggregateColumn* ac = new AggregateColumn(gwi.sessionid);
|
||||
ac->timeZone(gwi.timeZone);
|
||||
ac->alias(rc->alias());
|
||||
ac->aggOp(AggregateColumn::SELECT_SOME);
|
||||
ac->asc(rc->asc());
|
||||
ac->charsetNumber(rc->charsetNumber());
|
||||
ac->orderPos(rc->orderPos());
|
||||
uint32_t i;
|
||||
for(i=0; i < gwi.processed.size() && !gwi.processed[i].first->eq(baseItem, false);i++)
|
||||
{ }
|
||||
if (i < gwi.processed.size())
|
||||
{
|
||||
ac->expressionId(gwi.processed[i].second);
|
||||
}
|
||||
else
|
||||
{
|
||||
ac->expressionId(ci->expressionId++);
|
||||
}
|
||||
|
||||
ac->aggParms().push_back(SRCP(rc));
|
||||
ac->resultType(rc->resultType());
|
||||
return ac;
|
||||
}
|
||||
|
||||
|
||||
ReturnedColumn* buildReturnedColumnNull(gp_walk_info& gwi)
|
||||
{
|
||||
if (gwi.condPush)
|
||||
@ -3486,7 +3608,7 @@ static ConstantColumn* buildConstantColumnNotNullUsingValNative(Item* item, gp_w
|
||||
return rc;
|
||||
}
|
||||
|
||||
ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupport, bool isRefItem)
|
||||
ReturnedColumn* buildReturnedColumnBody(Item* item, gp_walk_info& gwi, bool& nonSupport, bool isRefItem)
|
||||
{
|
||||
ReturnedColumn* rc = NULL;
|
||||
|
||||
@ -3508,12 +3630,7 @@ ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupp
|
||||
{
|
||||
Item_field* ifp = (Item_field*)item;
|
||||
|
||||
if (isRefItem && gwi.isGroupByHandler && !gwi.extSelAggColsItems.empty())
|
||||
{
|
||||
return buildAggFrmTempField(ifp, gwi);
|
||||
}
|
||||
|
||||
return buildSimpleColumn(ifp, gwi);
|
||||
return wrapIntoAggregate(buildSimpleColumn(ifp, gwi), gwi, ifp);
|
||||
}
|
||||
case Item::NULL_ITEM: return buildReturnedColumnNull(gwi);
|
||||
case Item::CONST_ITEM:
|
||||
@ -3554,7 +3671,9 @@ ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupp
|
||||
if (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/")
|
||||
return buildArithmeticColumn(ifp, gwi, nonSupport);
|
||||
else
|
||||
{
|
||||
return buildFunctionColumn(ifp, gwi, nonSupport);
|
||||
}
|
||||
}
|
||||
|
||||
case Item::SUM_FUNC_ITEM:
|
||||
@ -3675,6 +3794,14 @@ ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupp
|
||||
|
||||
return rc;
|
||||
}
|
||||
ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupport, bool isRefItem)
|
||||
{
|
||||
bool disableWrapping = gwi.disableWrapping;
|
||||
gwi.disableWrapping = gwi.disableWrapping || itemDisablesWrapping(item, gwi);
|
||||
ReturnedColumn* rc = buildReturnedColumnBody(item, gwi, nonSupport, isRefItem);
|
||||
gwi.disableWrapping = disableWrapping;
|
||||
return rc;
|
||||
}
|
||||
|
||||
// parse the boolean fields to string "true" or "false"
|
||||
ReturnedColumn* buildBooleanConstantColumn(Item* item, gp_walk_info& gwi, bool& nonSupport)
|
||||
@ -3705,7 +3832,7 @@ ReturnedColumn* buildBooleanConstantColumn(Item* item, gp_walk_info& gwi, bool&
|
||||
return cc;
|
||||
}
|
||||
|
||||
ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool& nonSupport)
|
||||
ReturnedColumn* buildArithmeticColumnBody(Item_func* item, gp_walk_info& gwi, bool& nonSupport)
|
||||
{
|
||||
if (get_fe_conn_info_ptr() == NULL)
|
||||
{
|
||||
@ -3748,7 +3875,8 @@ ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool
|
||||
// Could have it set if there are aggregation funcs as this function arguments.
|
||||
gwi.fatalParseError = false;
|
||||
|
||||
ReturnedColumn* rc = buildAggFrmTempField(sfitempp[0], gwi);
|
||||
//ReturnedColumn* rc = buildAggFrmTempField(sfitempp[0], gwi);
|
||||
ReturnedColumn* rc = buildReturnedColumn(sfitempp[0], gwi, nonSupport);
|
||||
if (rc)
|
||||
lhs = new ParseTree(rc);
|
||||
}
|
||||
@ -3767,12 +3895,13 @@ ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool
|
||||
// Could have it set if there are aggregation funcs as this function arguments.
|
||||
gwi.fatalParseError = false;
|
||||
|
||||
ReturnedColumn* rc = buildAggFrmTempField(sfitempp[1], gwi);
|
||||
//ReturnedColumn* rc = buildAggFrmTempField(sfitempp[1], gwi);
|
||||
ReturnedColumn* rc = buildReturnedColumn(sfitempp[1], gwi, nonSupport);
|
||||
if (rc)
|
||||
rhs = new ParseTree(rc);
|
||||
}
|
||||
}
|
||||
else // where clause
|
||||
else // where clause SZ: XXX: is it also HAVING clause??? it appears so judging from condition above.
|
||||
{
|
||||
if (isPredicateFunction(sfitempp[1], &gwi))
|
||||
{
|
||||
@ -3939,7 +4068,8 @@ ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool
|
||||
ac->expressionId(ci->expressionId++);
|
||||
|
||||
// @3391. optimization. try to associate expression ID to the expression on the select list
|
||||
if (gwi.clauseType != SELECT)
|
||||
bool isOnSelectList = false;
|
||||
if (gwi.clauseType != SELECT || gwi.havingDespiteSelect)
|
||||
{
|
||||
for (uint32_t i = 0; i < gwi.returnedCols.size(); i++)
|
||||
{
|
||||
@ -3947,6 +4077,7 @@ ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool
|
||||
strcasecmp(ac->alias().c_str(), gwi.returnedCols[i]->alias().c_str()) == 0)
|
||||
{
|
||||
ac->expressionId(gwi.returnedCols[i]->expressionId());
|
||||
isOnSelectList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3965,10 +4096,24 @@ ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool
|
||||
}
|
||||
}
|
||||
|
||||
if (isOnSelectList && gwi.havingDespiteSelect)
|
||||
{
|
||||
SimpleColumn* sc = new SimpleColumn(*ac);
|
||||
delete ac;
|
||||
return sc;
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
ReturnedColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool& nonSupport)
|
||||
{
|
||||
bool disableWrapping = gwi.disableWrapping;
|
||||
gwi.disableWrapping = gwi.disableWrapping || itemDisablesWrapping(item, gwi);
|
||||
ReturnedColumn* rc = buildArithmeticColumnBody(item, gwi, nonSupport);
|
||||
gwi.disableWrapping = disableWrapping;
|
||||
return rc;
|
||||
}
|
||||
|
||||
ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& nonSupport, bool selectBetweenIn)
|
||||
ReturnedColumn* buildFunctionColumnBody(Item_func* ifp, gp_walk_info& gwi, bool& nonSupport, bool selectBetweenIn)
|
||||
{
|
||||
if (get_fe_conn_info_ptr() == NULL)
|
||||
{
|
||||
@ -4031,8 +4176,7 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
|
||||
// Arithmetic exp
|
||||
if (funcName == "+" || funcName == "-" || funcName == "*" || funcName == "/")
|
||||
{
|
||||
ArithmeticColumn* ac = buildArithmeticColumn(ifp, gwi, nonSupport);
|
||||
return ac;
|
||||
return buildArithmeticColumn(ifp, gwi, nonSupport);
|
||||
}
|
||||
|
||||
else if (funcName == "case")
|
||||
@ -4211,7 +4355,9 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
|
||||
if (mayHasBoolArg && isBoolType)
|
||||
rc = buildBooleanConstantColumn(ifp->arguments()[i], gwi, nonSupport);
|
||||
else
|
||||
{
|
||||
rc = buildReturnedColumn(ifp->arguments()[i], gwi, nonSupport);
|
||||
}
|
||||
|
||||
// MCOL-1510 It must be a temp table field, so find the corresponding column.
|
||||
if (!rc && ifp->arguments()[i]->type() == Item::REF_ITEM)
|
||||
@ -4569,6 +4715,14 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
|
||||
|
||||
return fc;
|
||||
}
|
||||
ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& nonSupport, bool selectBetweenIn)
|
||||
{
|
||||
bool disableWrapping = gwi.disableWrapping;
|
||||
gwi.disableWrapping = gwi.disableWrapping || itemDisablesWrapping(ifp, gwi);
|
||||
ReturnedColumn* rc = buildFunctionColumnBody(ifp, gwi, nonSupport, selectBetweenIn);
|
||||
gwi.disableWrapping = disableWrapping;
|
||||
return rc;
|
||||
}
|
||||
|
||||
FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonSupport)
|
||||
{
|
||||
@ -5027,44 +5181,7 @@ void analyzeForImplicitGroupBy(Item* item, gp_walk_info& gwi)
|
||||
}
|
||||
}
|
||||
|
||||
ReturnedColumn* wrapIntoAggregate(ReturnedColumn* rc, gp_walk_info& gwi, SELECT_LEX& select_lex, Item* baseItem)
|
||||
{
|
||||
if (!gwi.implicitExplicitGroupBy)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (dynamic_cast<AggregateColumn*>(rc) != nullptr || dynamic_cast<ConstantColumn*>(rc) != nullptr)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
ORDER* groupcol = static_cast<ORDER*>(select_lex.group_list.first);
|
||||
|
||||
while (groupcol)
|
||||
{
|
||||
if (baseItem->eq(*groupcol->item, false))
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
groupcol = groupcol->next;
|
||||
}
|
||||
|
||||
cal_connection_info* ci = static_cast<cal_connection_info*>(get_fe_conn_info_ptr());
|
||||
|
||||
AggregateColumn* ac = new AggregateColumn(gwi.sessionid);
|
||||
ac->timeZone(gwi.timeZone);
|
||||
ac->alias(rc->alias());
|
||||
ac->aggOp(AggregateColumn::SELECT_SOME);
|
||||
ac->asc(rc->asc());
|
||||
ac->charsetNumber(rc->charsetNumber());
|
||||
ac->expressionId(ci->expressionId++);
|
||||
|
||||
ac->aggParms().push_back(SRCP(rc));
|
||||
return ac;
|
||||
}
|
||||
|
||||
ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
ReturnedColumn* buildAggregateColumnBody(Item* item, gp_walk_info& gwi)
|
||||
{
|
||||
// MCOL-1201 For UDAnF multiple parameters
|
||||
vector<SRCP> selCols;
|
||||
@ -5364,6 +5481,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
{
|
||||
//@bug5229. handle constant function on aggregate argument
|
||||
ac->constCol(SRCP(rc));
|
||||
// XXX: this skips restoration of clauseType.
|
||||
break;
|
||||
}
|
||||
// the "rc" can be in gwi.no_parm_func_list. erase it from that list and
|
||||
@ -5745,6 +5863,14 @@ because it has multiple arguments.";
|
||||
ac->charsetNumber(item->collation.collation->number);
|
||||
return ac;
|
||||
}
|
||||
ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
{
|
||||
bool disableWrapping = gwi.disableWrapping;
|
||||
gwi.disableWrapping = true;
|
||||
ReturnedColumn* rc = buildAggregateColumnBody(item, gwi);
|
||||
gwi.disableWrapping = disableWrapping;
|
||||
return rc;
|
||||
}
|
||||
|
||||
void addIntervalArgs(gp_walk_info* gwip, Item_func* ifp, FunctionParm& functionParms)
|
||||
{
|
||||
@ -5876,6 +6002,7 @@ void gp_walk(const Item* item, void* arg)
|
||||
|
||||
if (ifp)
|
||||
{
|
||||
// XXX: this looks awfuly wrong.
|
||||
SimpleColumn* scp = buildSimpleColumn(ifp, *gwip);
|
||||
|
||||
if (!scp)
|
||||
@ -5884,7 +6011,7 @@ void gp_walk(const Item* item, void* arg)
|
||||
string aliasTableName(scp->tableAlias());
|
||||
scp->tableAlias(aliasTableName);
|
||||
gwip->rcWorkStack.push(scp->clone());
|
||||
boost::shared_ptr<SimpleColumn> scsp(scp);
|
||||
boost::shared_ptr<SimpleColumn> scsp(scp);
|
||||
gwip->scsp = scsp;
|
||||
|
||||
gwip->funcName.clear();
|
||||
@ -5979,7 +6106,7 @@ void gp_walk(const Item* item, void* arg)
|
||||
}
|
||||
|
||||
ostringstream oss;
|
||||
oss << "Unhandled Item type: " << item->type();
|
||||
oss << "Unhandled Item type(): " << item->type();
|
||||
gwip->parseErrorText = oss.str();
|
||||
gwip->fatalParseError = true;
|
||||
break;
|
||||
@ -6329,7 +6456,7 @@ void gp_walk(const Item* item, void* arg)
|
||||
gwip->fatalParseError = false;
|
||||
}
|
||||
|
||||
SimpleColumn* sc = dynamic_cast<SimpleColumn*>(rc);
|
||||
SimpleColumn* sc = clauseType == HAVING ? nullptr : dynamic_cast<SimpleColumn*>(rc);
|
||||
|
||||
if (sc)
|
||||
{
|
||||
@ -6423,19 +6550,27 @@ void gp_walk(const Item* item, void* arg)
|
||||
}
|
||||
else if (col->type() == Item::FIELD_ITEM && gwip->clauseType == HAVING)
|
||||
{
|
||||
ReturnedColumn* rc = buildAggFrmTempField(const_cast<Item*>(item), *gwip);
|
||||
//ReturnedColumn* rc = buildAggFrmTempField(const_cast<Item*>(item), *gwip);
|
||||
ReturnedColumn* rc = buildReturnedColumn(const_cast<Item*>(item), *gwip, gwip->fatalParseError);
|
||||
if (rc)
|
||||
gwip->rcWorkStack.push(rc);
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
cando = false;
|
||||
}
|
||||
|
||||
if (!cando)
|
||||
SimpleColumn* thisSC = dynamic_cast<SimpleColumn*>(rc);
|
||||
if (thisSC)
|
||||
{
|
||||
gwip->scsp.reset(thisSC->clone());
|
||||
}
|
||||
if (!rc && !cando)
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << "Unhandled Item type: " << item->type();
|
||||
oss << "Unhandled Item type(): " << item->type();
|
||||
gwip->parseErrorText = oss.str();
|
||||
gwip->fatalParseError = true;
|
||||
}
|
||||
@ -6488,7 +6623,6 @@ void gp_walk(const Item* item, void* arg)
|
||||
vector<SRCP> cols;
|
||||
// temp change clause type because the elements of row column are not walked yet
|
||||
gwip->clauseType = SELECT;
|
||||
|
||||
for (uint32_t i = 0; i < row->cols(); i++)
|
||||
cols.push_back(SRCP(buildReturnedColumn(row->element_index(i), *gwip, gwip->fatalParseError)));
|
||||
|
||||
@ -6547,7 +6681,7 @@ void gp_walk(const Item* item, void* arg)
|
||||
}
|
||||
|
||||
ostringstream oss;
|
||||
oss << "Unhandled Item type: " << item->type();
|
||||
oss << "Unhandled Item type (2): " << item->type();
|
||||
gwip->parseErrorText = oss.str();
|
||||
gwip->fatalParseError = true;
|
||||
break;
|
||||
@ -6650,15 +6784,15 @@ void parse_item(Item* item, vector<Item_field*>& field_vec, bool& hasNonSupportI
|
||||
// MCOL-1510. This could be a non-supported function
|
||||
// argument in form of a temp_table_field, so check
|
||||
// and set hasNonSupportItem if it is so.
|
||||
ReturnedColumn* rc = NULL;
|
||||
if (gwi)
|
||||
rc = buildAggFrmTempField(ref, *gwi);
|
||||
//ReturnedColumn* rc = NULL;
|
||||
//if (gwi)
|
||||
// rc = buildAggFrmTempField(ref, *gwi);
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
//if (!rc)
|
||||
//{
|
||||
Item_field* ifp = static_cast<Item_field*>(*(ref->ref));
|
||||
field_vec.push_back(ifp);
|
||||
}
|
||||
//}
|
||||
break;
|
||||
}
|
||||
else if ((*(ref->ref))->type() == Item::FUNC_ITEM)
|
||||
@ -7683,6 +7817,8 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
}
|
||||
|
||||
gwi.clauseType = SELECT;
|
||||
SELECT_LEX* oldSelectLex = gwi.select_lex; // XXX: SZ: should it be restored in case of error return?
|
||||
gwi.select_lex = &select_lex;
|
||||
#ifdef DEBUG_WALK_COND
|
||||
{
|
||||
cerr << "------------------- SELECT --------------------" << endl;
|
||||
@ -7791,10 +7927,10 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
}
|
||||
|
||||
// We need to look into GROUP BY columns to decide if we need to wrap a column.
|
||||
ReturnedColumn* rc = wrapIntoAggregate(sc, gwi, select_lex, baseItem);
|
||||
ReturnedColumn* rc = wrapIntoAggregate(sc, gwi, baseItem);
|
||||
|
||||
SRCP sprc(rc);
|
||||
gwi.returnedCols.push_back(sprc);
|
||||
pushReturnedCol(gwi, baseItem, sprc);
|
||||
|
||||
gwi.columnMap.insert(
|
||||
CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name.str), sprc));
|
||||
@ -7831,7 +7967,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
|
||||
// add this agg col to returnedColumnList
|
||||
boost::shared_ptr<ReturnedColumn> spac(ac);
|
||||
gwi.returnedCols.push_back(spac);
|
||||
pushReturnedCol(gwi, item, spac);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -7890,7 +8026,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
if (!hasNonSupportItem && ifp->const_item() && !(parseInfo & AF_BIT) && tmpVec.size() == 0)
|
||||
{
|
||||
srcp.reset(buildReturnedColumn(item, gwi, gwi.fatalParseError));
|
||||
gwi.returnedCols.push_back(srcp);
|
||||
pushReturnedCol(gwi, item, srcp);
|
||||
|
||||
if (ifp->name.length)
|
||||
srcp->alias(ifp->name.str);
|
||||
@ -7898,7 +8034,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
continue;
|
||||
}
|
||||
|
||||
gwi.returnedCols.push_back(srcp);
|
||||
pushReturnedCol(gwi, item, srcp);
|
||||
}
|
||||
else // This was a vtable post-process block
|
||||
{
|
||||
@ -7920,7 +8056,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
if (ifp->name.length)
|
||||
cc->alias(ifp->name.str);
|
||||
|
||||
gwi.returnedCols.push_back(srcp);
|
||||
pushReturnedCol(gwi, ifp, srcp);
|
||||
|
||||
// clear the error set by buildFunctionColumn
|
||||
gwi.fatalParseError = false;
|
||||
@ -7998,7 +8134,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
if (item->name.length)
|
||||
srcp->alias(item->name.str);
|
||||
|
||||
gwi.returnedCols.push_back(srcp);
|
||||
pushReturnedCol(gwi, item, srcp);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -8022,7 +8158,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
else
|
||||
{
|
||||
SRCP srcp(buildReturnedColumn(item, gwi, gwi.fatalParseError));
|
||||
gwi.returnedCols.push_back(srcp);
|
||||
pushReturnedCol(gwi, item, srcp);
|
||||
|
||||
if (item->name.length)
|
||||
srcp->alias(item->name.str);
|
||||
@ -8118,7 +8254,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
return ER_CHECK_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
gwi.returnedCols.push_back(srcp);
|
||||
pushReturnedCol(gwi, item, srcp);
|
||||
break;
|
||||
}
|
||||
case Item::TYPE_HOLDER:
|
||||
@ -8179,12 +8315,16 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
|
||||
// Having clause handling
|
||||
gwi.clauseType = HAVING;
|
||||
gwi.havingDespiteSelect = true;
|
||||
clearStacks(gwi, false, true);
|
||||
std::unique_ptr<ParseTree> havingFilter;
|
||||
|
||||
// clear fatalParseError that may be left from post process functions
|
||||
gwi.fatalParseError = false;
|
||||
gwi.parseErrorText = "";
|
||||
|
||||
gwi.disableWrapping = false;
|
||||
gwi.havingDespiteSelect = true;
|
||||
if (select_lex.having != 0)
|
||||
{
|
||||
#ifdef DEBUG_WALK_COND
|
||||
@ -8226,6 +8366,8 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
gwi.ptWorkStack.push(ptp);
|
||||
}
|
||||
}
|
||||
gwi.havingDespiteSelect = false;
|
||||
gwi.disableWrapping = false;
|
||||
|
||||
// MCOL-4617 If this is an IN subquery, then create the in-to-exists
|
||||
// predicate and inject it into the csep
|
||||
@ -8311,7 +8453,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
funcFieldVec[i]->print(&str, QT_ORDINARY);
|
||||
sc->alias(string(str.c_ptr()));
|
||||
sc->tableAlias(sc->tableAlias());
|
||||
SRCP srcp(sc);
|
||||
SRCP srcp(wrapIntoAggregate(sc, gwi, funcFieldVec[i]));
|
||||
uint32_t j = 0;
|
||||
|
||||
for (; j < gwi.returnedCols.size(); j++)
|
||||
@ -8328,6 +8470,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
if (j == gwi.returnedCols.size())
|
||||
{
|
||||
gwi.returnedCols.push_back(srcp);
|
||||
// XXX: SZ: deduplicate here?
|
||||
gwi.columnMap.insert(
|
||||
CalpontSelectExecutionPlan::ColumnMap::value_type(string(funcFieldVec[i]->field_name.str), srcp));
|
||||
|
||||
@ -8372,6 +8515,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
gwi.hasWindowFunc = hasWindowFunc;
|
||||
groupcol = static_cast<ORDER*>(select_lex.group_list.first);
|
||||
|
||||
gwi.disableWrapping = true;
|
||||
for (; groupcol; groupcol = groupcol->next)
|
||||
{
|
||||
Item* groupItem = *(groupcol->item);
|
||||
@ -8595,6 +8739,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
nonSupportItem = groupItem;
|
||||
}
|
||||
}
|
||||
gwi.disableWrapping = false;
|
||||
|
||||
// @bug 4756. Add internal groupby column for correlated join to the groupby list
|
||||
if (gwi.aggOnSelect && !gwi.subGroupByCols.empty())
|
||||
@ -8713,7 +8858,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
{
|
||||
rc = buildReturnedColumn(ord_item, gwi, gwi.fatalParseError);
|
||||
|
||||
rc = wrapIntoAggregate(rc, gwi, select_lex, ord_item);
|
||||
rc = wrapIntoAggregate(rc, gwi, ord_item);
|
||||
}
|
||||
// @bug5501 try item_ptr if item can not be fixed. For some
|
||||
// weird dml statement state, item can not be fixed but the
|
||||
@ -8940,6 +9085,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
for (uint32_t i = 0; i < gwi.localCols.size(); i++)
|
||||
gwi.localCols[i]->sequence(i);
|
||||
|
||||
gwi.select_lex = oldSelectLex;
|
||||
// append additionalRetCols to returnedCols
|
||||
gwi.returnedCols.insert(gwi.returnedCols.begin(), gwi.additionalRetCols.begin(),
|
||||
gwi.additionalRetCols.end());
|
||||
@ -9084,6 +9230,7 @@ int cp_get_group_plan(THD* thd, SCSEP& csep, cal_impl_if::cal_group_info& gi)
|
||||
gp_walk_info gwi(timeZoneOffset, &chain);
|
||||
gwi.thd = thd;
|
||||
gwi.isGroupByHandler = true;
|
||||
idbassert(0);
|
||||
int status = getGroupPlan(gwi, *select_lex, csep, gi);
|
||||
|
||||
#ifdef DEBUG_WALK_COND
|
||||
|
Reference in New Issue
Block a user