You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-08-01 06:46:55 +03:00
MCOL-1201 manual rebase with develop. Obsoletes branch MCOL-1201
This commit is contained in:
@ -4038,6 +4038,10 @@ ParseTree* buildParseTree(Item_func* item, gp_walk_info& gwi, bool& nonSupport)
|
||||
|
||||
ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
{
|
||||
// MCOL-1201 For UDAnF multiple parameters
|
||||
vector<SRCP> selCols;
|
||||
vector<SRCP> orderCols;
|
||||
|
||||
if (!(gwi.thd->infinidb_vtable.cal_conn_info))
|
||||
gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info());
|
||||
|
||||
@ -4054,6 +4058,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
|
||||
// N.B. argument_count() is the # of formal parms to the agg fcn. InifniDB only supports 1 argument
|
||||
// TODO: Support more than one parm
|
||||
#if 0
|
||||
if (isp->argument_count() != 1 && isp->sum_func() != Item_sum::GROUP_CONCAT_FUNC
|
||||
&& isp->sum_func() != Item_sum::UDF_SUM_FUNC)
|
||||
{
|
||||
@ -4061,7 +4066,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_MUL_ARG_AGG);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
AggregateColumn* ac = NULL;
|
||||
|
||||
if (isp->sum_func() == Item_sum::GROUP_CONCAT_FUNC)
|
||||
@ -4084,444 +4089,509 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText = "Non supported aggregate type on the select clause";
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// special parsing for group_concat
|
||||
if (isp->sum_func() == Item_sum::GROUP_CONCAT_FUNC)
|
||||
try
|
||||
{
|
||||
Item_func_group_concat* gc = (Item_func_group_concat*)isp;
|
||||
|
||||
// special parsing for group_concat
|
||||
if (isp->sum_func() == Item_sum::GROUP_CONCAT_FUNC)
|
||||
{
|
||||
Item_func_group_concat* gc = (Item_func_group_concat*)isp;
|
||||
vector<SRCP> orderCols;
|
||||
RowColumn* rowCol = new RowColumn();
|
||||
RowColumn* rowCol = new RowColumn();
|
||||
vector<SRCP> selCols;
|
||||
|
||||
uint32_t select_ctn = gc->count_field();
|
||||
ReturnedColumn* rc = NULL;
|
||||
uint32_t select_ctn = gc->count_field();
|
||||
ReturnedColumn* rc = NULL;
|
||||
|
||||
for (uint32_t i = 0; i < select_ctn; i++)
|
||||
{
|
||||
rc = buildReturnedColumn(sfitempp[i], gwi, gwi.fatalParseError);
|
||||
|
||||
if (!rc || gwi.fatalParseError)
|
||||
return NULL;
|
||||
|
||||
selCols.push_back(SRCP(rc));
|
||||
}
|
||||
|
||||
ORDER** order_item, **end;
|
||||
|
||||
for (order_item = gc->get_order(),
|
||||
end = order_item + gc->order_field(); order_item < end;
|
||||
order_item++)
|
||||
{
|
||||
Item* ord_col = *(*order_item)->item;
|
||||
|
||||
if (ord_col->type() == Item::INT_ITEM)
|
||||
for (uint32_t i = 0; i < select_ctn; i++)
|
||||
{
|
||||
Item_int* id = (Item_int*)ord_col;
|
||||
|
||||
if (id->val_int() > (int)selCols.size())
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = selCols[id->val_int() - 1]->clone();
|
||||
rc->orderPos(id->val_int() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = buildReturnedColumn(ord_col, gwi, gwi.fatalParseError);
|
||||
rc = buildReturnedColumn(sfitempp[i], gwi, gwi.fatalParseError);
|
||||
|
||||
if (!rc || gwi.fatalParseError)
|
||||
{
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
selCols.push_back(SRCP(rc));
|
||||
}
|
||||
|
||||
// 10.2 TODO: direction is now a tri-state flag
|
||||
rc->asc((*order_item)->direction == ORDER::ORDER_ASC ? true : false);
|
||||
orderCols.push_back(SRCP(rc));
|
||||
}
|
||||
ORDER** order_item, **end;
|
||||
|
||||
rowCol->columnVec(selCols);
|
||||
(dynamic_cast<GroupConcatColumn*>(ac))->orderCols(orderCols);
|
||||
parm.reset(rowCol);
|
||||
|
||||
if (gc->str_separator())
|
||||
{
|
||||
string separator;
|
||||
separator.assign(gc->str_separator()->ptr(), gc->str_separator()->length());
|
||||
(dynamic_cast<GroupConcatColumn*>(ac))->separator(separator);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < isp->argument_count(); i++)
|
||||
{
|
||||
Item* sfitemp = sfitempp[i];
|
||||
Item::Type sfitype = sfitemp->type();
|
||||
|
||||
switch (sfitype)
|
||||
for (order_item = gc->get_order(),
|
||||
end = order_item + gc->order_field(); order_item < end;
|
||||
order_item++)
|
||||
{
|
||||
case Item::FIELD_ITEM:
|
||||
{
|
||||
Item_field* ifp = reinterpret_cast<Item_field*>(sfitemp);
|
||||
SimpleColumn* sc = buildSimpleColumn(ifp, gwi);
|
||||
Item* ord_col = *(*order_item)->item;
|
||||
|
||||
if (!sc)
|
||||
if (ord_col->type() == Item::INT_ITEM)
|
||||
{
|
||||
Item_int* id = (Item_int*)ord_col;
|
||||
|
||||
if (id->val_int() > (int)selCols.size())
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
break;
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parm.reset(sc);
|
||||
gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name), parm));
|
||||
TABLE_LIST* tmp = (ifp->cached_table ? ifp->cached_table : 0);
|
||||
gwi.tableMap[make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias(), sc->isInfiniDB())] = make_pair(1, tmp);
|
||||
break;
|
||||
rc = selCols[id->val_int() - 1]->clone();
|
||||
rc->orderPos(id->val_int() - 1);
|
||||
}
|
||||
|
||||
case Item::INT_ITEM:
|
||||
case Item::STRING_ITEM:
|
||||
case Item::REAL_ITEM:
|
||||
case Item::DECIMAL_ITEM:
|
||||
else
|
||||
{
|
||||
// treat as count(*)
|
||||
if (ac->aggOp() == AggregateColumn::COUNT)
|
||||
ac->aggOp(AggregateColumn::COUNT_ASTERISK);
|
||||
rc = buildReturnedColumn(ord_col, gwi, gwi.fatalParseError);
|
||||
|
||||
ac->constCol(SRCP(buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError)));
|
||||
break;
|
||||
}
|
||||
|
||||
case Item::NULL_ITEM:
|
||||
{
|
||||
//ac->aggOp(AggregateColumn::COUNT);
|
||||
parm.reset(new ConstantColumn("", ConstantColumn::NULLDATA));
|
||||
//ac->functionParms(parm);
|
||||
ac->constCol(SRCP(buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError)));
|
||||
break;
|
||||
}
|
||||
|
||||
case Item::FUNC_ITEM:
|
||||
{
|
||||
Item_func* ifp = (Item_func*)sfitemp;
|
||||
ReturnedColumn* rc = 0;
|
||||
|
||||
// check count(1+1) case
|
||||
vector <Item_field*> tmpVec;
|
||||
uint16_t parseInfo = 0;
|
||||
parse_item(ifp, tmpVec, gwi.fatalParseError, parseInfo);
|
||||
|
||||
if (parseInfo & SUB_BIT)
|
||||
if (!rc || gwi.fatalParseError)
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
break;
|
||||
}
|
||||
else if (!gwi.fatalParseError &&
|
||||
!(parseInfo & AGG_BIT) &&
|
||||
!(parseInfo & AF_BIT) &&
|
||||
tmpVec.size() == 0)
|
||||
{
|
||||
rc = buildFunctionColumn(ifp, gwi, gwi.fatalParseError);
|
||||
FunctionColumn* fc = dynamic_cast<FunctionColumn*>(rc);
|
||||
|
||||
if ((fc && fc->functionParms().empty()) || !fc)
|
||||
{
|
||||
//ac->aggOp(AggregateColumn::COUNT_ASTERISK);
|
||||
ReturnedColumn* rc = buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError);
|
||||
|
||||
if (dynamic_cast<ConstantColumn*>(rc))
|
||||
{
|
||||
//@bug5229. handle constant function on aggregate argument
|
||||
ac->constCol(SRCP(rc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MySQL carelessly allows correlated aggregate function on the WHERE clause.
|
||||
// Here is the work around to deal with that inconsistence.
|
||||
// e.g., SELECT (SELECT t.c FROM t1 AS t WHERE t.b=MAX(t1.b + 0)) FROM t1;
|
||||
ClauseType clauseType = gwi.clauseType;
|
||||
|
||||
if (gwi.clauseType == WHERE)
|
||||
gwi.clauseType = HAVING;
|
||||
|
||||
// @bug 3603. for cases like max(rand()). try to build function first.
|
||||
if (!rc)
|
||||
rc = buildFunctionColumn(ifp, gwi, gwi.fatalParseError);
|
||||
|
||||
parm.reset(rc);
|
||||
gwi.clauseType = clauseType;
|
||||
|
||||
if (gwi.fatalParseError)
|
||||
break;
|
||||
|
||||
//ac->functionParms(parm);
|
||||
break;
|
||||
}
|
||||
|
||||
case Item::REF_ITEM:
|
||||
{
|
||||
ReturnedColumn* rc = buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
parm.reset(rc);
|
||||
//ac->functionParms(parm);
|
||||
break;
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
//gwi.parseErrorText = "Non-supported Item in Aggregate function";
|
||||
}
|
||||
// 10.2 TODO: direction is now a tri-state flag
|
||||
rc->asc((*order_item)->direction == ORDER::ORDER_ASC ? true : false);
|
||||
orderCols.push_back(SRCP(rc));
|
||||
}
|
||||
|
||||
if (gwi.fatalParseError)
|
||||
rowCol->columnVec(selCols);
|
||||
(dynamic_cast<GroupConcatColumn*>(ac))->orderCols(orderCols);
|
||||
parm.reset(rowCol);
|
||||
|
||||
if (gc->str_separator())
|
||||
{
|
||||
if (gwi.parseErrorText.empty())
|
||||
{
|
||||
Message::Args args;
|
||||
|
||||
if (item->name)
|
||||
args.add(item->name);
|
||||
else
|
||||
args.add("");
|
||||
|
||||
gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_AGG_ARGS, args);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
string separator;
|
||||
separator.assign(gc->str_separator()->ptr(), gc->str_separator()->length());
|
||||
(dynamic_cast<GroupConcatColumn*>(ac))->separator(separator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parm)
|
||||
{
|
||||
ac->functionParms(parm);
|
||||
|
||||
if (isp->sum_func() == Item_sum::AVG_FUNC ||
|
||||
isp->sum_func() == Item_sum::AVG_DISTINCT_FUNC)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct = parm->resultType();
|
||||
|
||||
switch (ct.colDataType)
|
||||
{
|
||||
case CalpontSystemCatalog::TINYINT:
|
||||
case CalpontSystemCatalog::SMALLINT:
|
||||
case CalpontSystemCatalog::MEDINT:
|
||||
case CalpontSystemCatalog::INT:
|
||||
case CalpontSystemCatalog::BIGINT:
|
||||
case CalpontSystemCatalog::DECIMAL:
|
||||
case CalpontSystemCatalog::UDECIMAL:
|
||||
case CalpontSystemCatalog::UTINYINT:
|
||||
case CalpontSystemCatalog::USMALLINT:
|
||||
case CalpontSystemCatalog::UMEDINT:
|
||||
case CalpontSystemCatalog::UINT:
|
||||
case CalpontSystemCatalog::UBIGINT:
|
||||
ct.colDataType = CalpontSystemCatalog::DECIMAL;
|
||||
ct.colWidth = 8;
|
||||
ct.scale += 4;
|
||||
break;
|
||||
|
||||
#if PROMOTE_FLOAT_TO_DOUBLE_ON_SUM
|
||||
|
||||
case CalpontSystemCatalog::FLOAT:
|
||||
case CalpontSystemCatalog::UFLOAT:
|
||||
case CalpontSystemCatalog::DOUBLE:
|
||||
case CalpontSystemCatalog::UDOUBLE:
|
||||
ct.colDataType = CalpontSystemCatalog::DOUBLE;
|
||||
ct.colWidth = 8;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else if (isp->sum_func() == Item_sum::COUNT_FUNC ||
|
||||
isp->sum_func() == Item_sum::COUNT_DISTINCT_FUNC)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct;
|
||||
ct.colDataType = CalpontSystemCatalog::BIGINT;
|
||||
ct.colWidth = 8;
|
||||
ct.scale = parm->resultType().scale;
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else if (isp->sum_func() == Item_sum::SUM_FUNC ||
|
||||
isp->sum_func() == Item_sum::SUM_DISTINCT_FUNC)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct = parm->resultType();
|
||||
|
||||
switch (ct.colDataType)
|
||||
{
|
||||
case CalpontSystemCatalog::TINYINT:
|
||||
case CalpontSystemCatalog::SMALLINT:
|
||||
case CalpontSystemCatalog::MEDINT:
|
||||
case CalpontSystemCatalog::INT:
|
||||
case CalpontSystemCatalog::BIGINT:
|
||||
ct.colDataType = CalpontSystemCatalog::BIGINT;
|
||||
|
||||
// no break, let fall through
|
||||
|
||||
case CalpontSystemCatalog::DECIMAL:
|
||||
case CalpontSystemCatalog::UDECIMAL:
|
||||
ct.colWidth = 8;
|
||||
break;
|
||||
|
||||
case CalpontSystemCatalog::UTINYINT:
|
||||
case CalpontSystemCatalog::USMALLINT:
|
||||
case CalpontSystemCatalog::UMEDINT:
|
||||
case CalpontSystemCatalog::UINT:
|
||||
case CalpontSystemCatalog::UBIGINT:
|
||||
ct.colDataType = CalpontSystemCatalog::UBIGINT;
|
||||
ct.colWidth = 8;
|
||||
break;
|
||||
|
||||
#if PROMOTE_FLOAT_TO_DOUBLE_ON_SUM
|
||||
|
||||
case CalpontSystemCatalog::FLOAT:
|
||||
case CalpontSystemCatalog::UFLOAT:
|
||||
case CalpontSystemCatalog::DOUBLE:
|
||||
case CalpontSystemCatalog::UDOUBLE:
|
||||
ct.colDataType = CalpontSystemCatalog::DOUBLE;
|
||||
ct.colWidth = 8;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else if (isp->sum_func() == Item_sum::STD_FUNC ||
|
||||
isp->sum_func() == Item_sum::VARIANCE_FUNC)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct;
|
||||
ct.colDataType = CalpontSystemCatalog::DOUBLE;
|
||||
ct.colWidth = 8;
|
||||
ct.scale = 0;
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else if (isp->sum_func() == Item_sum::SUM_BIT_FUNC)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct;
|
||||
ct.colDataType = CalpontSystemCatalog::BIGINT;
|
||||
ct.colWidth = 8;
|
||||
ct.scale = 0;
|
||||
ct.precision = -16; // borrowed to indicate skip null value check on connector
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else if (isp->sum_func() == Item_sum::GROUP_CONCAT_FUNC)
|
||||
{
|
||||
//Item_func_group_concat* gc = (Item_func_group_concat*)isp;
|
||||
CalpontSystemCatalog::ColType ct;
|
||||
ct.colDataType = CalpontSystemCatalog::VARCHAR;
|
||||
ct.colWidth = isp->max_length;
|
||||
ct.precision = 0;
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else
|
||||
{
|
||||
ac->resultType(parm->resultType());
|
||||
for (uint32_t i = 0; i < isp->argument_count(); i++)
|
||||
{
|
||||
Item* sfitemp = sfitempp[i];
|
||||
Item::Type sfitype = sfitemp->type();
|
||||
|
||||
switch (sfitype)
|
||||
{
|
||||
case Item::FIELD_ITEM:
|
||||
{
|
||||
Item_field* ifp = reinterpret_cast<Item_field*>(sfitemp);
|
||||
SimpleColumn* sc = buildSimpleColumn(ifp, gwi);
|
||||
|
||||
if (!sc)
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
break;
|
||||
}
|
||||
|
||||
parm.reset(sc);
|
||||
gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name), parm));
|
||||
TABLE_LIST* tmp = (ifp->cached_table ? ifp->cached_table : 0);
|
||||
gwi.tableMap[make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias(), sc->isInfiniDB())] = make_pair(1, tmp);
|
||||
break;
|
||||
}
|
||||
|
||||
case Item::INT_ITEM:
|
||||
case Item::STRING_ITEM:
|
||||
case Item::REAL_ITEM:
|
||||
case Item::DECIMAL_ITEM:
|
||||
{
|
||||
// treat as count(*)
|
||||
if (ac->aggOp() == AggregateColumn::COUNT)
|
||||
ac->aggOp(AggregateColumn::COUNT_ASTERISK);
|
||||
|
||||
ac->constCol(SRCP(buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError)));
|
||||
break;
|
||||
}
|
||||
|
||||
case Item::NULL_ITEM:
|
||||
{
|
||||
parm.reset(new ConstantColumn("", ConstantColumn::NULLDATA));
|
||||
ac->constCol(SRCP(buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError)));
|
||||
break;
|
||||
}
|
||||
|
||||
case Item::FUNC_ITEM:
|
||||
{
|
||||
Item_func* ifp = (Item_func*)sfitemp;
|
||||
ReturnedColumn* rc = 0;
|
||||
|
||||
// check count(1+1) case
|
||||
vector <Item_field*> tmpVec;
|
||||
uint16_t parseInfo = 0;
|
||||
parse_item(ifp, tmpVec, gwi.fatalParseError, parseInfo);
|
||||
|
||||
if (parseInfo & SUB_BIT)
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
break;
|
||||
}
|
||||
else if (!gwi.fatalParseError &&
|
||||
!(parseInfo & AGG_BIT) &&
|
||||
!(parseInfo & AF_BIT) &&
|
||||
tmpVec.size() == 0)
|
||||
{
|
||||
rc = buildFunctionColumn(ifp, gwi, gwi.fatalParseError);
|
||||
FunctionColumn* fc = dynamic_cast<FunctionColumn*>(rc);
|
||||
|
||||
if ((fc && fc->functionParms().empty()) || !fc)
|
||||
{
|
||||
//ac->aggOp(AggregateColumn::COUNT_ASTERISK);
|
||||
ReturnedColumn* rc = buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError);
|
||||
|
||||
if (dynamic_cast<ConstantColumn*>(rc))
|
||||
{
|
||||
//@bug5229. handle constant function on aggregate argument
|
||||
ac->constCol(SRCP(rc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MySQL carelessly allows correlated aggregate function on the WHERE clause.
|
||||
// Here is the work around to deal with that inconsistence.
|
||||
// e.g., SELECT (SELECT t.c FROM t1 AS t WHERE t.b=MAX(t1.b + 0)) FROM t1;
|
||||
ClauseType clauseType = gwi.clauseType;
|
||||
|
||||
if (gwi.clauseType == WHERE)
|
||||
gwi.clauseType = HAVING;
|
||||
|
||||
// @bug 3603. for cases like max(rand()). try to build function first.
|
||||
if (!rc)
|
||||
rc = buildFunctionColumn(ifp, gwi, gwi.fatalParseError);
|
||||
|
||||
parm.reset(rc);
|
||||
gwi.clauseType = clauseType;
|
||||
|
||||
if (gwi.fatalParseError)
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Item::REF_ITEM:
|
||||
{
|
||||
ReturnedColumn* rc = buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
parm.reset(rc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
//gwi.parseErrorText = "Non-supported Item in Aggregate function";
|
||||
}
|
||||
}
|
||||
|
||||
if (gwi.fatalParseError)
|
||||
{
|
||||
if (gwi.parseErrorText.empty())
|
||||
{
|
||||
Message::Args args;
|
||||
|
||||
if (item->name)
|
||||
args.add(item->name);
|
||||
else
|
||||
args.add("");
|
||||
|
||||
gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_AGG_ARGS, args);
|
||||
}
|
||||
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
if (parm)
|
||||
{
|
||||
// MCOL-1201 multi-argument aggregate
|
||||
ac->aggParms().push_back(parm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ac->resultType(colType_MysqlToIDB(isp));
|
||||
}
|
||||
|
||||
// adjust decimal result type according to internalDecimalScale
|
||||
if (gwi.internalDecimalScale >= 0 && ac->resultType().colDataType == CalpontSystemCatalog::DECIMAL)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct = ac->resultType();
|
||||
ct.scale = gwi.internalDecimalScale;
|
||||
ac->resultType(ct);
|
||||
}
|
||||
|
||||
// check for same aggregate on the select list
|
||||
ac->expressionId(ci->expressionId++);
|
||||
|
||||
if (gwi.clauseType != SELECT)
|
||||
{
|
||||
for (uint32_t i = 0; i < gwi.returnedCols.size(); i++)
|
||||
// Get result type
|
||||
// Modified for MCOL-1201 multi-argument aggregate
|
||||
if (ac->aggParms().size() > 0)
|
||||
{
|
||||
if (*ac == gwi.returnedCols[i].get())
|
||||
ac->expressionId(gwi.returnedCols[i]->expressionId());
|
||||
}
|
||||
}
|
||||
// These are all one parm functions, so we can safely
|
||||
// use the first parm for result type.
|
||||
parm = ac->aggParms()[0];
|
||||
if (isp->sum_func() == Item_sum::AVG_FUNC ||
|
||||
isp->sum_func() == Item_sum::AVG_DISTINCT_FUNC)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct = parm->resultType();
|
||||
|
||||
// @bug5977 @note Temporary fix to avoid mysqld crash. The permanent fix will
|
||||
// be applied in ExeMgr. When the ExeMgr fix is available, this checking
|
||||
// will be taken out.
|
||||
if (ac->constCol() && gwi.tbList.empty() && gwi.derivedTbList.empty())
|
||||
switch (ct.colDataType)
|
||||
{
|
||||
case CalpontSystemCatalog::TINYINT:
|
||||
case CalpontSystemCatalog::SMALLINT:
|
||||
case CalpontSystemCatalog::MEDINT:
|
||||
case CalpontSystemCatalog::INT:
|
||||
case CalpontSystemCatalog::BIGINT:
|
||||
case CalpontSystemCatalog::DECIMAL:
|
||||
case CalpontSystemCatalog::UDECIMAL:
|
||||
case CalpontSystemCatalog::UTINYINT:
|
||||
case CalpontSystemCatalog::USMALLINT:
|
||||
case CalpontSystemCatalog::UMEDINT:
|
||||
case CalpontSystemCatalog::UINT:
|
||||
case CalpontSystemCatalog::UBIGINT:
|
||||
ct.colDataType = CalpontSystemCatalog::DECIMAL;
|
||||
ct.colWidth = 8;
|
||||
ct.scale += 4;
|
||||
break;
|
||||
|
||||
#if PROMOTE_FLOAT_TO_DOUBLE_ON_SUM
|
||||
|
||||
case CalpontSystemCatalog::FLOAT:
|
||||
case CalpontSystemCatalog::UFLOAT:
|
||||
case CalpontSystemCatalog::DOUBLE:
|
||||
case CalpontSystemCatalog::UDOUBLE:
|
||||
ct.colDataType = CalpontSystemCatalog::DOUBLE;
|
||||
ct.colWidth = 8;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else if (isp->sum_func() == Item_sum::COUNT_FUNC ||
|
||||
isp->sum_func() == Item_sum::COUNT_DISTINCT_FUNC)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct;
|
||||
ct.colDataType = CalpontSystemCatalog::BIGINT;
|
||||
ct.colWidth = 8;
|
||||
ct.scale = parm->resultType().scale;
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else if (isp->sum_func() == Item_sum::SUM_FUNC ||
|
||||
isp->sum_func() == Item_sum::SUM_DISTINCT_FUNC)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct = parm->resultType();
|
||||
|
||||
switch (ct.colDataType)
|
||||
{
|
||||
case CalpontSystemCatalog::TINYINT:
|
||||
case CalpontSystemCatalog::SMALLINT:
|
||||
case CalpontSystemCatalog::MEDINT:
|
||||
case CalpontSystemCatalog::INT:
|
||||
case CalpontSystemCatalog::BIGINT:
|
||||
ct.colDataType = CalpontSystemCatalog::BIGINT;
|
||||
|
||||
// no break, let fall through
|
||||
|
||||
case CalpontSystemCatalog::DECIMAL:
|
||||
case CalpontSystemCatalog::UDECIMAL:
|
||||
ct.colWidth = 8;
|
||||
break;
|
||||
|
||||
case CalpontSystemCatalog::UTINYINT:
|
||||
case CalpontSystemCatalog::USMALLINT:
|
||||
case CalpontSystemCatalog::UMEDINT:
|
||||
case CalpontSystemCatalog::UINT:
|
||||
case CalpontSystemCatalog::UBIGINT:
|
||||
ct.colDataType = CalpontSystemCatalog::UBIGINT;
|
||||
ct.colWidth = 8;
|
||||
break;
|
||||
|
||||
#if PROMOTE_FLOAT_TO_DOUBLE_ON_SUM
|
||||
|
||||
case CalpontSystemCatalog::FLOAT:
|
||||
case CalpontSystemCatalog::UFLOAT:
|
||||
case CalpontSystemCatalog::DOUBLE:
|
||||
case CalpontSystemCatalog::UDOUBLE:
|
||||
ct.colDataType = CalpontSystemCatalog::DOUBLE;
|
||||
ct.colWidth = 8;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else if (isp->sum_func() == Item_sum::STD_FUNC ||
|
||||
isp->sum_func() == Item_sum::VARIANCE_FUNC)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct;
|
||||
ct.colDataType = CalpontSystemCatalog::DOUBLE;
|
||||
ct.colWidth = 8;
|
||||
ct.scale = 0;
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else if (isp->sum_func() == Item_sum::SUM_BIT_FUNC)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct;
|
||||
ct.colDataType = CalpontSystemCatalog::BIGINT;
|
||||
ct.colWidth = 8;
|
||||
ct.scale = 0;
|
||||
ct.precision = -16; // borrowed to indicate skip null value check on connector
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else if (isp->sum_func() == Item_sum::GROUP_CONCAT_FUNC)
|
||||
{
|
||||
//Item_func_group_concat* gc = (Item_func_group_concat*)isp;
|
||||
CalpontSystemCatalog::ColType ct;
|
||||
ct.colDataType = CalpontSystemCatalog::VARCHAR;
|
||||
ct.colWidth = isp->max_length;
|
||||
ct.precision = 0;
|
||||
ac->resultType(ct);
|
||||
}
|
||||
else
|
||||
{
|
||||
// UDAF result type will be set below.
|
||||
ac->resultType(parm->resultType());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ac->resultType(colType_MysqlToIDB(isp));
|
||||
}
|
||||
|
||||
// adjust decimal result type according to internalDecimalScale
|
||||
if (gwi.internalDecimalScale >= 0 && ac->resultType().colDataType == CalpontSystemCatalog::DECIMAL)
|
||||
{
|
||||
CalpontSystemCatalog::ColType ct = ac->resultType();
|
||||
ct.scale = gwi.internalDecimalScale;
|
||||
ac->resultType(ct);
|
||||
}
|
||||
|
||||
// check for same aggregate on the select list
|
||||
ac->expressionId(ci->expressionId++);
|
||||
|
||||
if (gwi.clauseType != SELECT)
|
||||
{
|
||||
for (uint32_t i = 0; i < gwi.returnedCols.size(); i++)
|
||||
{
|
||||
if (*ac == gwi.returnedCols[i].get())
|
||||
ac->expressionId(gwi.returnedCols[i]->expressionId());
|
||||
}
|
||||
}
|
||||
|
||||
// @bug5977 @note Temporary fix to avoid mysqld crash. The permanent fix will
|
||||
// be applied in ExeMgr. When the ExeMgr fix is available, this checking
|
||||
// will be taken out.
|
||||
if (ac->constCol() && gwi.tbList.empty() && gwi.derivedTbList.empty())
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText = "No project column found for aggregate function";
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
else if (ac->constCol())
|
||||
{
|
||||
gwi.count_asterisk_list.push_back(ac);
|
||||
}
|
||||
|
||||
// For UDAF, populate the context and call the UDAF init() function.
|
||||
// The return type is (should be) set in context by init().
|
||||
if (isp->sum_func() == Item_sum::UDF_SUM_FUNC)
|
||||
{
|
||||
UDAFColumn* udafc = dynamic_cast<UDAFColumn*>(ac);
|
||||
|
||||
if (udafc)
|
||||
{
|
||||
mcsv1Context& context = udafc->getContext();
|
||||
context.setName(isp->func_name());
|
||||
|
||||
// Set up the return type defaults for the call to init()
|
||||
context.setResultType(udafc->resultType().colDataType);
|
||||
context.setColWidth(udafc->resultType().colWidth);
|
||||
context.setScale(udafc->resultType().scale);
|
||||
context.setPrecision(udafc->resultType().precision);
|
||||
|
||||
context.setParamCount(udafc->aggParms().size());
|
||||
ColumnDatum colType;
|
||||
ColumnDatum colTypes[udafc->aggParms().size()];
|
||||
// Build the column type vector.
|
||||
// Modified for MCOL-1201 multi-argument aggregate
|
||||
for (uint32_t i = 0; i < udafc->aggParms().size(); ++i)
|
||||
{
|
||||
const execplan::CalpontSystemCatalog::ColType& resultType
|
||||
= udafc->aggParms()[i]->resultType();
|
||||
colType.dataType = resultType.colDataType;
|
||||
colType.precision = resultType.precision;
|
||||
colType.scale = resultType.scale;
|
||||
colTypes[i] = colType;
|
||||
}
|
||||
|
||||
// Call the user supplied init()
|
||||
mcsv1sdk::mcsv1_UDAF* udaf = context.getFunction();
|
||||
if (!udaf)
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText = "Aggregate Function " + context.getName() + " doesn't exist in the ColumnStore engine";
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
if (udaf->init(&context, colTypes) == mcsv1_UDAF::ERROR)
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText = udafc->getContext().getErrorMessage();
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// UDAF_OVER_REQUIRED means that this function is for Window
|
||||
// Function only. Reject it here in aggregate land.
|
||||
if (udafc->getContext().getRunFlag(UDAF_OVER_REQUIRED))
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText =
|
||||
logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_WINDOW_FUNC_ONLY,
|
||||
context.getName());
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set the return type as set in init()
|
||||
CalpontSystemCatalog::ColType ct;
|
||||
ct.colDataType = context.getResultType();
|
||||
ct.colWidth = context.getColWidth();
|
||||
ct.scale = context.getScale();
|
||||
ct.precision = context.getPrecision();
|
||||
udafc->resultType(ct);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (std::logic_error e)
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText = "No project column found for aggregate function";
|
||||
gwi.parseErrorText = "error building Aggregate Function: ";
|
||||
gwi.parseErrorText += e.what();
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
else if (ac->constCol())
|
||||
catch (...)
|
||||
{
|
||||
gwi.count_asterisk_list.push_back(ac);
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText = "error building Aggregate Function: Unspecified exception";
|
||||
if (ac)
|
||||
delete ac;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// For UDAF, populate the context and call the UDAF init() function.
|
||||
if (isp->sum_func() == Item_sum::UDF_SUM_FUNC)
|
||||
{
|
||||
UDAFColumn* udafc = dynamic_cast<UDAFColumn*>(ac);
|
||||
|
||||
if (udafc)
|
||||
{
|
||||
mcsv1Context& context = udafc->getContext();
|
||||
context.setName(isp->func_name());
|
||||
|
||||
// Set up the return type defaults for the call to init()
|
||||
context.setResultType(udafc->resultType().colDataType);
|
||||
context.setColWidth(udafc->resultType().colWidth);
|
||||
context.setScale(udafc->resultType().scale);
|
||||
context.setPrecision(udafc->resultType().precision);
|
||||
|
||||
COL_TYPES colTypes;
|
||||
execplan::CalpontSelectExecutionPlan::ColumnMap::iterator cmIter;
|
||||
|
||||
// Build the column type vector. For now, there is only one
|
||||
colTypes.push_back(make_pair(udafc->functionParms()->alias(), udafc->functionParms()->resultType().colDataType));
|
||||
|
||||
// Call the user supplied init()
|
||||
if (context.getFunction()->init(&context, colTypes) == mcsv1_UDAF::ERROR)
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText = udafc->getContext().getErrorMessage();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (udafc->getContext().getRunFlag(UDAF_OVER_REQUIRED))
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText =
|
||||
logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_WINDOW_FUNC_ONLY,
|
||||
context.getName());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set the return type as set in init()
|
||||
CalpontSystemCatalog::ColType ct;
|
||||
ct.colDataType = context.getResultType();
|
||||
ct.colWidth = context.getColWidth();
|
||||
ct.scale = context.getScale();
|
||||
ct.precision = context.getPrecision();
|
||||
udafc->resultType(ct);
|
||||
}
|
||||
}
|
||||
|
||||
return ac;
|
||||
}
|
||||
|
||||
@ -7839,7 +7909,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
return ER_CHECK_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
(*coliter)->functionParms(minSc);
|
||||
(*coliter)->aggParms().push_back(minSc);
|
||||
}
|
||||
|
||||
std::vector<FunctionColumn*>::iterator funciter;
|
||||
@ -9949,7 +10019,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
|
||||
return ER_CHECK_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
(*coliter)->functionParms(minSc);
|
||||
(*coliter)->aggParms().push_back(minSc);
|
||||
}
|
||||
|
||||
std::vector<FunctionColumn*>::iterator funciter;
|
||||
|
Reference in New Issue
Block a user