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
Merge branch 'stable-23.10' into 23.10.1-2
This commit is contained in:
@ -474,6 +474,22 @@ bool sortItemIsInGrouping(Item* sort_item, ORDER* groupcol)
|
||||
if (sort_item->type() == Item::SUM_FUNC_ITEM)
|
||||
{
|
||||
found = true;
|
||||
return found;
|
||||
}
|
||||
|
||||
{
|
||||
// as we now can warp ORDER BY or SELECT expression into
|
||||
// an aggregate, we can pass FIELD_ITEM as "found" as well.
|
||||
Item* item = sort_item;
|
||||
while (item->type() == Item::REF_ITEM)
|
||||
{
|
||||
const Item_ref* ref_item = static_cast<const Item_ref*>(item);
|
||||
item = (Item*)*ref_item->ref;
|
||||
}
|
||||
if (item->type() == Item::FIELD_ITEM || item->type() == Item::CONST_ITEM || item->type() == Item::NULL_ITEM)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// A function that contains an aggregate function
|
||||
@ -498,9 +514,18 @@ bool sortItemIsInGrouping(Item* sort_item, ORDER* groupcol)
|
||||
// is either Field or Func
|
||||
// Consider nonConstFunc() check here
|
||||
if (!found && sort_item->type() == Item::FUNC_ITEM &&
|
||||
(group_item->type() == Item::FUNC_ITEM || group_item->type() == Item::FIELD_ITEM))
|
||||
(group_item->type() == Item::FUNC_ITEM || group_item->type() == Item::FIELD_ITEM ||
|
||||
group_item->type() == Item::REF_ITEM))
|
||||
{
|
||||
found = sortItemIsInGroupRec(sort_item, group_item);
|
||||
// MCOL-5236: see @bug5993 and @bug5916.
|
||||
Item* item = group_item;
|
||||
while (item->type() == Item::REF_ITEM)
|
||||
{
|
||||
Item_ref* item_ref = static_cast<Item_ref*>(item);
|
||||
item = *item_ref->ref;
|
||||
}
|
||||
|
||||
found = sortItemIsInGroupRec(sort_item, item);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3180,6 +3205,9 @@ CalpontSystemCatalog::ColType colType_MysqlToIDB(const Item* item)
|
||||
|
||||
if (item->field_type() == MYSQL_TYPE_BLOB)
|
||||
{
|
||||
// We default to BLOB, but then try to correct type,
|
||||
// because many textual types in server have type_handler_blob
|
||||
// (and variants) as their type.
|
||||
ct.colDataType = CalpontSystemCatalog::BLOB;
|
||||
}
|
||||
}
|
||||
@ -4395,7 +4423,7 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
|
||||
|
||||
// A few functions use a different collation than that found in
|
||||
// the base ifp class
|
||||
if (funcName == "locate" || funcName == "find_in_set" || funcName == "strcmp")
|
||||
if (funcName == "locate" || funcName == "find_in_set" || funcName == "strcmp" || funcName == "regexp_instr")
|
||||
{
|
||||
DTCollation dt;
|
||||
ifp->Type_std_attributes::agg_arg_charsets_for_comparison(dt, ifp->func_name_cstring(),
|
||||
@ -4893,6 +4921,70 @@ static void processAggregateColumnConstArg(gp_walk_info& gwi, SRCP& parm, Aggreg
|
||||
}
|
||||
}
|
||||
|
||||
void analyzeForImplicitGroupBy(Item* item, gp_walk_info& gwi)
|
||||
{
|
||||
if (gwi.implicitExplicitGroupBy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (item->type() == Item::REF_ITEM)
|
||||
{
|
||||
Item_ref* ref = static_cast<Item_ref*>(item);
|
||||
item = *ref->ref;
|
||||
}
|
||||
if (item->type() == Item::SUM_FUNC_ITEM)
|
||||
{
|
||||
// definitely an aggregate and thus needs an implicit group by.
|
||||
gwi.implicitExplicitGroupBy = true;
|
||||
return;
|
||||
}
|
||||
if (item->type() == Item::FUNC_ITEM)
|
||||
{
|
||||
Item_func* ifp = static_cast<Item_func*>(item);
|
||||
for(uint32_t i = 0;i<ifp->argument_count() && !gwi.implicitExplicitGroupBy;i++)
|
||||
{
|
||||
analyzeForImplicitGroupBy(ifp->arguments()[i], 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)
|
||||
{
|
||||
// MCOL-1201 For UDAnF multiple parameters
|
||||
@ -5000,8 +5092,9 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
if (ord_col->type() == Item::CONST_ITEM && ord_col->cmp_type() == INT_RESULT)
|
||||
{
|
||||
Item_int* id = (Item_int*)ord_col;
|
||||
int64_t index = id->val_int();
|
||||
|
||||
if (id->val_int() > (int)selCols.size())
|
||||
if (index > (int)selCols.size() || index < 1)
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
|
||||
@ -5011,8 +5104,8 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = selCols[id->val_int() - 1]->clone();
|
||||
rc->orderPos(id->val_int() - 1);
|
||||
rc = selCols[index - 1]->clone();
|
||||
rc->orderPos(index - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -6830,6 +6923,26 @@ int processFrom(bool& isUnion, SELECT_LEX& select_lex, gp_walk_info& gwi, SCSEP&
|
||||
// Existed pushdown handlers won't get in this scope
|
||||
// MDEV-25080 Union pushdown would enter this scope
|
||||
// is_unit_op() give a segv for derived_handler's SELECT_LEX
|
||||
|
||||
// check INTERSECT or EXCEPT, that are not implemented
|
||||
if (select_lex.master_unit() && select_lex.master_unit()->first_select())
|
||||
{
|
||||
for (auto nextSelect = select_lex.master_unit()->first_select()->next_select(); nextSelect;
|
||||
nextSelect = nextSelect->next_select())
|
||||
{
|
||||
if (nextSelect->get_linkage() == INTERSECT_TYPE)
|
||||
{
|
||||
setError(gwi.thd, ER_INTERNAL_ERROR, "INTERSECT is not supported by Columnstore engine", gwi);
|
||||
return ER_INTERNAL_ERROR;
|
||||
}
|
||||
else if (nextSelect->get_linkage() == EXCEPT_TYPE)
|
||||
{
|
||||
setError(gwi.thd, ER_INTERNAL_ERROR, "EXCEPT is not supported by Columnstore engine", gwi);
|
||||
return ER_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isUnion && (!isSelectHandlerTop || isSelectLexUnit) && select_lex.master_unit()->is_unit_op())
|
||||
{
|
||||
// MCOL-2178 isUnion member only assigned, never used
|
||||
@ -7454,6 +7567,32 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
}
|
||||
#endif
|
||||
|
||||
// analyze SELECT and ORDER BY parts - do they have implicit GROUP BY induced by aggregates?
|
||||
{
|
||||
if (select_lex.group_list.first)
|
||||
{
|
||||
// we have an explicit GROUP BY.
|
||||
gwi.implicitExplicitGroupBy = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// do we have an implicit GROUP BY?
|
||||
List_iterator_fast<Item> it(select_lex.item_list);
|
||||
Item* item;
|
||||
|
||||
while ((item = it++))
|
||||
{
|
||||
analyzeForImplicitGroupBy(item, gwi);
|
||||
}
|
||||
SQL_I_List<ORDER> order_list = select_lex.order_list;
|
||||
ORDER* ordercol = static_cast<ORDER*>(order_list.first);
|
||||
|
||||
for (; ordercol; ordercol = ordercol->next)
|
||||
{
|
||||
analyzeForImplicitGroupBy(*(ordercol->item), gwi);
|
||||
}
|
||||
}
|
||||
}
|
||||
// populate returnedcolumnlist and columnmap
|
||||
List_iterator_fast<Item> it(select_lex.item_list);
|
||||
Item* item;
|
||||
@ -7480,6 +7619,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
|
||||
// @bug 5916. Need to keep checking until getting concret item in case
|
||||
// of nested view.
|
||||
Item* baseItem = item;
|
||||
while (item->type() == Item::REF_ITEM)
|
||||
{
|
||||
Item_ref* ref = (Item_ref*)item;
|
||||
@ -7504,8 +7644,6 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
|
||||
if (sc)
|
||||
{
|
||||
boost::shared_ptr<SimpleColumn> spsc(sc);
|
||||
|
||||
string fullname;
|
||||
String str;
|
||||
ifp->print(&str, QT_ORDINARY);
|
||||
@ -7521,10 +7659,14 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
sc->alias(itemAlias);
|
||||
}
|
||||
|
||||
gwi.returnedCols.push_back(spsc);
|
||||
// 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);
|
||||
|
||||
SRCP sprc(rc);
|
||||
gwi.returnedCols.push_back(sprc);
|
||||
|
||||
gwi.columnMap.insert(
|
||||
CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name.str), spsc));
|
||||
CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name.str), sprc));
|
||||
TABLE_LIST* tmp = 0;
|
||||
|
||||
if (ifp->cached_table)
|
||||
@ -8192,18 +8334,18 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
ReturnedColumn* rc = buildSimpleColumn(ifp, gwi);
|
||||
SimpleColumn* sc = dynamic_cast<SimpleColumn*>(rc);
|
||||
|
||||
if (sc)
|
||||
{
|
||||
bool found = false;
|
||||
if (sc)
|
||||
{
|
||||
bool found = false;
|
||||
for (uint32_t j = 0; j < gwi.returnedCols.size(); j++)
|
||||
{
|
||||
if (sc->sameColumn(gwi.returnedCols[j].get()))
|
||||
{
|
||||
sc->orderPos(j);
|
||||
found = true;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint32_t j = 0; !found && j < gwi.returnedCols.size(); j++)
|
||||
{
|
||||
if (strcasecmp(sc->alias().c_str(), gwi.returnedCols[j]->alias().c_str()) == 0)
|
||||
@ -8213,9 +8355,9 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t j = 0; j < gwi.returnedCols.size(); j++)
|
||||
{
|
||||
if (ifp->name.length && string(ifp->name.str) == gwi.returnedCols[j].get()->alias())
|
||||
@ -8225,7 +8367,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
@ -8371,6 +8513,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
{
|
||||
if ((*(ordercol->item))->type() == Item::WINDOW_FUNC_ITEM)
|
||||
gwi.hasWindowFunc = true;
|
||||
// XXX: TODO: implement a proper analysis of what we support.
|
||||
// MCOL-2166 Looking for this sorting item in GROUP_BY items list.
|
||||
// Shouldn't look into this if query doesn't have GROUP BY or
|
||||
// aggregations
|
||||
@ -8382,10 +8525,10 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
getColNameFromItem(osr, *ordercol->item);
|
||||
Message::Args args;
|
||||
args.add(ostream.str());
|
||||
string emsg = IDBErrorInfo::instance()->errorMsg(ERR_NOT_GROUPBY_EXPRESSION, args);
|
||||
string emsg = IDBErrorInfo::instance()->errorMsg(ERR_NOT_SUPPORTED_GROUPBY_ORDERBY_EXPRESSION, args);
|
||||
gwi.parseErrorText = emsg;
|
||||
setError(gwi.thd, ER_INTERNAL_ERROR, emsg, gwi);
|
||||
return ERR_NOT_GROUPBY_EXPRESSION;
|
||||
return ERR_NOT_SUPPORTED_GROUPBY_ORDERBY_EXPRESSION;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8435,6 +8578,8 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
else
|
||||
{
|
||||
rc = buildReturnedColumn(ord_item, gwi, gwi.fatalParseError);
|
||||
|
||||
rc = wrapIntoAggregate(rc, gwi, select_lex, 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
|
||||
@ -8466,6 +8611,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
gwi.orderByCols.push_back(SRCP(rc));
|
||||
}
|
||||
}
|
||||
|
||||
// make sure columnmap, returnedcols and count(*) arg_list are not empty
|
||||
TableMap::iterator tb_iter = gwi.tableMap.begin();
|
||||
|
||||
@ -9947,7 +10093,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
|
||||
}
|
||||
}
|
||||
|
||||
srcp->orderPos(groupcol->counter - 1);
|
||||
srcp->orderPos(groupcol->counter - 1);
|
||||
gwi.groupByCols.push_back(srcp);
|
||||
continue;
|
||||
}
|
||||
|
@ -401,6 +401,7 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, long t
|
||||
// @2835. Handle empty string and null confusion. store empty string for string column
|
||||
if (colType.colDataType == CalpontSystemCatalog::CHAR ||
|
||||
colType.colDataType == CalpontSystemCatalog::VARCHAR ||
|
||||
colType.colDataType == CalpontSystemCatalog::TEXT ||
|
||||
colType.colDataType == CalpontSystemCatalog::VARBINARY)
|
||||
{
|
||||
(*f)->reset();
|
||||
|
@ -141,6 +141,9 @@ struct gp_walk_info
|
||||
std::vector<execplan::CalpontSystemCatalog::TableAliasName> correlatedTbNameVec;
|
||||
ClauseType clauseType;
|
||||
execplan::CalpontSystemCatalog::TableAliasName viewName;
|
||||
// we can have explicit GROUP BY and implicit one, triggered by aggregate in pojection or ORDER BY.
|
||||
// this flag tells us whether we have either case.
|
||||
bool implicitExplicitGroupBy;
|
||||
bool aggOnSelect;
|
||||
bool hasWindowFunc;
|
||||
bool hasSubSelect;
|
||||
@ -186,6 +189,7 @@ struct gp_walk_info
|
||||
, subSelectType(uint64_t(-1))
|
||||
, subQuery(0)
|
||||
, clauseType(INIT)
|
||||
, implicitExplicitGroupBy(false)
|
||||
, aggOnSelect(false)
|
||||
, hasWindowFunc(false)
|
||||
, hasSubSelect(false)
|
||||
|
@ -428,6 +428,7 @@ execplan::ReturnedColumn* buildPseudoColumn(Item* item, gp_walk_info& gwi, bool&
|
||||
|
||||
if ((pseudoType == PSEUDO_EXTENTMIN || pseudoType == PSEUDO_EXTENTMAX) &&
|
||||
(sc->colType().colDataType == CalpontSystemCatalog::VARBINARY ||
|
||||
(sc->colType().colDataType == CalpontSystemCatalog::TEXT) ||
|
||||
(sc->colType().colDataType == CalpontSystemCatalog::VARCHAR && sc->colType().colWidth > 7) ||
|
||||
(sc->colType().colDataType == CalpontSystemCatalog::CHAR && sc->colType().colWidth > 8)))
|
||||
return nullOnError(gwi, funcName);
|
||||
|
Reference in New Issue
Block a user