From 6b8adb822b691f0b3639056244cef815b05c02bc Mon Sep 17 00:00:00 2001 From: drrtuy Date: Fri, 4 Apr 2025 21:27:07 +0100 Subject: [PATCH] chore(connector): remove unused and disabled group by handler (#3481) --- dbcon/joblist/jlf_tuplejoblist.cpp | 2 +- dbcon/mysql/ha_mcs.cpp | 1 - dbcon/mysql/ha_mcs_execplan.cpp | 1848 +--------------------------- dbcon/mysql/ha_mcs_impl.cpp | 697 ----------- dbcon/mysql/ha_mcs_impl.h | 3 - dbcon/mysql/ha_mcs_impl_if.h | 29 - dbcon/mysql/ha_mcs_pushdown.cpp | 168 --- dbcon/mysql/ha_mcs_pushdown.h | 1 - dbcon/mysql/ha_mcs_sysvars.cpp | 13 - dbcon/mysql/ha_mcs_sysvars.h | 3 - 10 files changed, 2 insertions(+), 2763 deletions(-) diff --git a/dbcon/joblist/jlf_tuplejoblist.cpp b/dbcon/joblist/jlf_tuplejoblist.cpp index 866deed85..4285dc67f 100644 --- a/dbcon/joblist/jlf_tuplejoblist.cpp +++ b/dbcon/joblist/jlf_tuplejoblist.cpp @@ -5125,7 +5125,7 @@ SJSTEP unionQueries(JobStepVector& queries, uint64_t distinctUnionNum, JobInfo& // This return code in the call to convertUnionColType() below would // always be 0. This is because convertUnionColType() is also called - // in the connector code in getSelectPlan()/getGroupPlan() which handle + // in the connector code in getSelectPlan() which handle // the non-zero return code scenarios from this function call and error // out, in which case, the execution does not even get to ExeMgr. unsigned int dummyUnionedTypeRc = 0; diff --git a/dbcon/mysql/ha_mcs.cpp b/dbcon/mysql/ha_mcs.cpp index 0ef4430dc..b61dd88d9 100644 --- a/dbcon/mysql/ha_mcs.cpp +++ b/dbcon/mysql/ha_mcs.cpp @@ -1841,7 +1841,6 @@ static int columnstore_init_func(void* p) mcs_hton->commit = mcs_commit; mcs_hton->rollback = mcs_rollback; mcs_hton->close_connection = mcs_close_connection; - mcs_hton->create_group_by = create_columnstore_group_by_handler; mcs_hton->create_derived = create_columnstore_derived_handler; mcs_hton->create_select = create_columnstore_select_handler; mcs_hton->create_unit = create_columnstore_unit_handler; diff --git a/dbcon/mysql/ha_mcs_execplan.cpp b/dbcon/mysql/ha_mcs_execplan.cpp index 6b2f4946e..bc8596d1b 100644 --- a/dbcon/mysql/ha_mcs_execplan.cpp +++ b/dbcon/mysql/ha_mcs_execplan.cpp @@ -422,7 +422,7 @@ bool nonConstFunc(Item_func* ifp) * This f() looks for a first proper Item_ident and populate * ostream with schema, table and column names. * Used to build db.table.field tuple for debugging output - * in getSelectPlan(). TBD getGroupPlan must use this also. + * in getSelectPlan(). * PARAMETERS: * item source Item* * ostream output stream @@ -9221,35 +9221,6 @@ int cp_get_table_plan(THD* thd, SCSEP& csep, cal_table_info& ti, long timeZone) return 0; } -int cp_get_group_plan(THD* thd, SCSEP& csep, cal_impl_if::cal_group_info& gi) -{ - SELECT_LEX* select_lex = gi.groupByTables->select_lex; - const char* timeZone = thd->variables.time_zone->get_name()->ptr(); - long timeZoneOffset; - dataconvert::timeZoneToOffset(timeZone, strlen(timeZone), &timeZoneOffset); - SubQuery* chain = nullptr; - 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 - cerr << "---------------- cp_get_group_plan EXECUTION PLAN ----------------" << endl; - cerr << *csep << endl; - cerr << "-------------- EXECUTION PLAN END --------------\n" << endl; -#endif - - if (status > 0) - return ER_INTERNAL_ERROR; - else if (status < 0) - return status; - // Derived table projection and filter optimization. - derivedTableOptimization(&gwi, csep); - - return 0; -} - int cs_get_derived_plan(ha_columnstore_derived_handler* handler, THD* thd, SCSEP& csep, gp_walk_info& gwi) { SELECT_LEX& select_lex = *handler->select; @@ -9303,1821 +9274,4 @@ int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, SCSEP& return 0; } -/*@brief buildConstColFromFilter- change SimpleColumn into ConstColumn*/ -/*********************************************************** - * DESCRIPTION: - * Server could optimize out fields from GROUP BY list, when certain - * filter predicate is used, e.g. - * field = 'AIR', field IN ('AIR'). This utility function tries to - * replace such fields with ConstantColumns using cond_pushed filters. - * TBD Take into account that originalSC SimpleColumn could be: - * SimpleColumn, ArithmeticColumn, FunctionColumn. - * PARAMETERS: - * originalSC SimpleColumn* removed field - * gwi main strucutre - * gi auxilary group_by handler structure - * RETURNS - * ConstantColumn* if originalSC equals with cond_pushed columns. - * NULL otherwise - ***********************************************************/ -ConstantColumn* buildConstColFromFilter(SimpleColumn* originalSC, gp_walk_info& gwi, cal_group_info& gi) -{ - execplan::SimpleColumn* simpleCol; - execplan::ConstantColumn* constCol; - execplan::SOP op; - execplan::SimpleFilter* simpFilter; - execplan::ConstantColumn* result = NULL; - std::vector::iterator ptIt = gi.pushedPts.begin(); - - for (; ptIt != gi.pushedPts.end(); ptIt++) - { - simpFilter = dynamic_cast((*ptIt)->data()); - - if (simpFilter == NULL) - continue; - - simpleCol = dynamic_cast(simpFilter->lhs()); - constCol = dynamic_cast(simpFilter->rhs()); - - if (simpleCol == NULL || constCol == NULL) - continue; - - op = simpFilter->op(); - execplan::ReturnedColumn* rc = dynamic_cast(simpleCol); - - // The filter could have any kind of op - if (originalSC->sameColumn(rc)) - { -#ifdef DEBUG_WALK_COND - cerr << "buildConstColFromFilter() replaced " << endl; - cerr << simpleCol->toString() << endl; - cerr << " with " << endl; - cerr << constCol << endl; -#endif - result = constCol; - } - } - - return result; -} - -// XXX: need to trigger that somehow. -int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_group_info& gi, bool isUnion) -{ -#ifdef DEBUG_WALK_COND - cerr << "getGroupPlan()" << endl; -#endif - idbassert_s(false, "getGroupPlan is utterly out of date"); - - // XXX: rollup is currently not supported (not tested) in this part. - // but this is not triggered in any of tests. - if (select_lex.olap == ROLLUP_TYPE) - { - gwi.fatalParseError = true; - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_ROLLUP_NOT_SUPPORT); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - gwi.internalDecimalScale = (get_use_decimal_scale(gwi.thd) ? get_decimal_scale(gwi.thd) : -1); - gwi.subSelectType = csep->subType(); - - JOIN* join = select_lex.join; - Item_cond* icp = 0; - - if (gi.groupByWhere) - icp = static_cast(gi.groupByWhere); - - uint32_t sessionID = csep->sessionID(); - gwi.sessionid = sessionID; - boost::shared_ptr csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID); - csc->identity(CalpontSystemCatalog::FE); - gwi.csc = csc; - - // @bug 2123. Override large table estimate if infinidb_ordered hint was used. - // @bug 2404. Always override if the infinidb_ordered_only variable is turned on. - if (get_ordered_only(gwi.thd)) - csep->overrideLargeSideEstimate(true); - - // @bug 5741. Set a flag when in Local PM only query mode - csep->localQuery(get_local_query(gwi.thd)); - - // @bug 3321. Set max number of blocks in a dictionary file to be scanned for filtering - csep->stringScanThreshold(get_string_scan_threshold(gwi.thd)); - - csep->stringTableThreshold(get_stringtable_threshold(gwi.thd)); - - csep->djsSmallSideLimit(get_diskjoin_smallsidelimit(gwi.thd) * 1024ULL * 1024); - csep->djsLargeSideLimit(get_diskjoin_largesidelimit(gwi.thd) * 1024ULL * 1024); - csep->djsPartitionSize(get_diskjoin_bucketsize(gwi.thd) * 1024ULL * 1024); - - if (get_um_mem_limit(gwi.thd) == 0) - csep->umMemLimit(numeric_limits::max()); - else - csep->umMemLimit(get_um_mem_limit(gwi.thd) * 1024ULL * 1024); - - // populate table map and trigger syscolumn cache for all the tables (@bug 1637). - // all tables on FROM list must have at least one col in colmap - TABLE_LIST* table_ptr = gi.groupByTables; - CalpontSelectExecutionPlan::SelectList derivedTbList; - -// DEBUG -#ifdef DEBUG_WALK_COND - List_iterator sj_list_it(select_lex.sj_nests); - TABLE_LIST* sj_nest; - - while ((sj_nest = sj_list_it++)) - { - cerr << sj_nest->db.str << "." << sj_nest->table_name.str << endl; - } - -#endif - - // @bug 1796. Remember table order on the FROM list. - gwi.clauseType = FROM; - - try - { - for (; table_ptr; table_ptr = table_ptr->next_local) - { - // mysql put vtable here for from sub. we ignore it - // if (string(table_ptr->table_name).find("$vtable") != string::npos) - // continue; - - // Until we handle recursive cte: - // Checking here ensures we catch all with clauses in the query. - if (table_ptr->is_recursive_with_table()) - { - gwi.fatalParseError = true; - gwi.parseErrorText = "Recursive CTE"; - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - string viewName = getViewName(table_ptr); - if (lower_case_table_names) - { - boost::algorithm::to_lower(viewName); - } - - // @todo process from subquery - if (table_ptr->derived) - { - String str; - (table_ptr->derived->first_select())->print(gwi.thd, &str, QT_ORDINARY); - - SELECT_LEX* select_cursor = table_ptr->derived->first_select(); - // Use Pushdown handler for subquery processing - FromSubQuery* fromSub = new FromSubQuery(gwi, select_cursor); - string alias(table_ptr->alias.str); - if (lower_case_table_names) - { - boost::algorithm::to_lower(alias); - } - fromSub->alias(alias); - - CalpontSystemCatalog::TableAliasName tn = make_aliasview("", "", alias, viewName); - // @bug 3852. check return execplan - SCSEP plan = fromSub->transform(); - - if (!plan) - { - setError(gwi.thd, ER_INTERNAL_ERROR, fromSub->gwip().parseErrorText, gwi); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - return ER_INTERNAL_ERROR; - } - - gwi.derivedTbList.push_back(plan); - gwi.tbList.push_back(tn); - CalpontSystemCatalog::TableAliasName tan = make_aliastable("", alias, alias); - gwi.tableMap[tan] = make_pair(0, table_ptr); - // MCOL-2178 isUnion member only assigned, never used - // MIGR::infinidb_vtable.isUnion = true; //by-pass the 2nd pass of rnd_init - } - else if (table_ptr->view) - { - View* view = new View(*table_ptr->view->first_select_lex(), &gwi); - CalpontSystemCatalog::TableAliasName tn = make_aliastable( - table_ptr->db.str, table_ptr->table_name.str, table_ptr->alias.str, true, lower_case_table_names); - view->viewName(tn); - gwi.viewList.push_back(view); - view->transform(); - } - else - { - // check foreign engine tables - bool columnStore = (table_ptr->table ? isMCSTable(table_ptr->table) : true); - - // trigger system catalog cache - if (columnStore) - csc->columnRIDs(make_table(table_ptr->db.str, table_ptr->table_name.str, lower_case_table_names), - true); - - string table_name = table_ptr->table_name.str; - - // @bug5523 - if (table_ptr->db.length && strcmp(table_ptr->db.str, "information_schema") == 0) - table_name = - (table_ptr->schema_table_name.length ? table_ptr->schema_table_name.str : table_ptr->alias.str); - - CalpontSystemCatalog::TableAliasName tn = - make_aliasview(table_ptr->db.str, table_name, table_ptr->alias.str, viewName, columnStore, - lower_case_table_names); - gwi.tbList.push_back(tn); - CalpontSystemCatalog::TableAliasName tan = make_aliastable( - table_ptr->db.str, table_name, table_ptr->alias.str, columnStore, lower_case_table_names); - gwi.tableMap[tan] = make_pair(0, table_ptr); -#ifdef DEBUG_WALK_COND - cerr << tn << endl; -#endif - } - } - - if (gwi.fatalParseError) - { - setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText, gwi); - return ER_INTERNAL_ERROR; - } - } - catch (IDBExcept& ie) - { - setError(gwi.thd, ER_INTERNAL_ERROR, ie.what(), gwi); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - // @bug 3852. set error status for gwi. - gwi.fatalParseError = true; - gwi.parseErrorText = ie.what(); - return ER_INTERNAL_ERROR; - } - catch (...) - { - string emsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR); - // @bug3852 set error status for gwi. - gwi.fatalParseError = true; - gwi.parseErrorText = emsg; - setError(gwi.thd, ER_INTERNAL_ERROR, emsg, gwi); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - return ER_INTERNAL_ERROR; - } - - csep->tableList(gwi.tbList); - - bool unionSel = false; - - gwi.clauseType = WHERE; - - if (icp) - { - // MCOL-1052 The condition could be useless. - // MariaDB bug 624 - without the fix_fields call, delete with join may error with "No query step". - // #if MYSQL_VERSION_ID < 50172 - //@bug 3039. fix fields for constants - if (!icp->fixed()) - { - icp->fix_fields(gwi.thd, (Item**)&icp); - } - - // #endif - gwi.fatalParseError = false; -#ifdef DEBUG_WALK_COND - cerr << "------------------ WHERE -----------------------" << endl; - icp->traverse_cond(debug_walk, &gwi, Item::POSTFIX); - cerr << "------------------------------------------------\n" << endl; -#endif - - icp->traverse_cond(gp_walk, &gwi, Item::POSTFIX); - - if (gwi.fatalParseError) - { - // if this is dervied table process phase, mysql may have not developed the plan - // completely. Do not error and eventually mysql will call JOIN::exec() again. - // related to bug 2922. Need to find a way to skip calling rnd_init for derived table - // processing. - if (gwi.thd->derived_tables_processing) - { - // MCOL-2178 isUnion member only assigned, never used - // MIGR::infinidb_vtable.isUnion = false; - return -1; - } - - setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText, gwi); - return ER_INTERNAL_ERROR; - } - } - else if (join && join->zero_result_cause) - { - gwi.rcWorkStack.push(new ConstantColumn((int64_t)0, ConstantColumn::NUM)); - (dynamic_cast(gwi.rcWorkStack.top()))->timeZone(gwi.timeZone); - } - - SELECT_LEX tmp_select_lex; - tmp_select_lex.table_list.first = gi.groupByTables; - - // InfiniDB bug5764 requires outer joins to be appended to the - // end of the filter list. This causes outer join filters to - // have a higher join id than inner join filters. - // TODO MCOL-4680 Figure out why this is the case, and possibly - // eliminate this requirement. - std::stack outerJoinStack; - - uint32_t failed = buildJoin(gwi, tmp_select_lex.top_join_list, outerJoinStack); - - if (failed) - return failed; - - if (gwi.subQuery) - { - for (uint i = 0; i < gwi.viewList.size(); i++) - { - failed = gwi.viewList[i]->processJoin(gwi, outerJoinStack); - - if (failed) - break; - } - } - - if (failed != 0) - return failed; - - ParseTree* filters = NULL; - ParseTree* outerJoinFilters = NULL; - ParseTree* ptp = NULL; - ParseTree* rhs = NULL; - - // @bug 2932. for "select * from region where r_name" case. if icp not null and - // ptWorkStack empty, the item is in rcWorkStack. - // MySQL 5.6 (MariaDB?). when icp is null and zero_result_cause is set, a constant 0 - // is pushed to rcWorkStack. - if (/*icp && */ gwi.ptWorkStack.empty() && !gwi.rcWorkStack.empty()) - { - filters = new ParseTree(gwi.rcWorkStack.top()); - gwi.rcWorkStack.pop(); - } - - while (!gwi.ptWorkStack.empty()) - { - filters = gwi.ptWorkStack.top(); - gwi.ptWorkStack.pop(); - - if (gwi.ptWorkStack.empty()) - break; - - ptp = new ParseTree(new LogicOperator("and")); - ptp->left(filters); - rhs = gwi.ptWorkStack.top(); - gwi.ptWorkStack.pop(); - ptp->right(rhs); - gwi.ptWorkStack.push(ptp); - } - - while (!outerJoinStack.empty()) - { - outerJoinFilters = outerJoinStack.top(); - outerJoinStack.pop(); - - if (outerJoinStack.empty()) - break; - - ptp = new ParseTree(new LogicOperator("and")); - ptp->left(outerJoinFilters); - rhs = outerJoinStack.top(); - outerJoinStack.pop(); - ptp->right(rhs); - outerJoinStack.push(ptp); - } - - // Append outer join filters at the end of inner join filters. - // JLF_ExecPlanToJobList::walkTree processes ParseTree::left - // before ParseTree::right which is what we intend to do in the - // below. - if (filters && outerJoinFilters) - { - ptp = new ParseTree(new LogicOperator("and")); - ptp->left(filters); - ptp->right(outerJoinFilters); - filters = ptp; - } - else if (outerJoinFilters) - { - filters = outerJoinFilters; - } - - if (filters) - { - csep->filters(filters); -#ifdef DEBUG_WALK_COND - std::string aTmpDir(startup::StartUp::tmpDir()); - aTmpDir = aTmpDir + "/filter1.dot"; - filters->drawTree(aTmpDir); -#endif - } - - gwi.clauseType = SELECT; -#ifdef DEBUG_WALK_COND - { - cerr << "------------------- SELECT --------------------" << endl; - List_iterator_fast it(*gi.groupByFields); - Item* item; - - while ((item = it++)) - { - debug_walk(item, 0); - } - - cerr << "-----------------------------------------------\n" << endl; - } -#endif - - // populate returnedcolumnlist and columnmap - List_iterator_fast it(*gi.groupByFields); - Item* item; - vector funcFieldVec; - bool redo = false; - - // empty rcWorkStack and ptWorkStack. They should all be empty by now. - clearStacks(gwi, false); - - // indicate the starting pos of scalar returned column, because some join column - // has been inserted to the returned column list. - if (gwi.subQuery) - { - ScalarSub* scalar = dynamic_cast(gwi.subQuery); - - if (scalar) - scalar->returnedColPos(gwi.additionalRetCols.size()); - } - - CalpontSelectExecutionPlan::SelectList selectSubList; - - while ((item = it++)) - { - string itemAlias; - if (item->name.length) - itemAlias = (item->name.str); - else - { - itemAlias = ""; - } - - // @bug 5916. Need to keep checking until getting concret item in case - // of nested view. - while (item->type() == Item::REF_ITEM) - { - Item_ref* ref = (Item_ref*)item; - item = (*(ref->ref)); - } - - Item::Type itype = item->type(); - - switch (itype) - { - case Item::FIELD_ITEM: - { - Item_field* ifp = (Item_field*)item; - SimpleColumn* sc = NULL; - ConstantColumn* constCol = NULL; - - if (ifp->field_name.length && string(ifp->field_name.str) == "*") - { - collectAllCols(gwi, ifp); - break; - } - - sc = buildSimpleColumn(ifp, gwi); - - if (sc) - { - constCol = buildConstColFromFilter(sc, gwi, gi); - boost::shared_ptr spcc(constCol); - boost::shared_ptr spsc(sc); - - string fullname; - String str; - ifp->print(&str, QT_ORDINARY); - fullname = str.c_ptr(); - - if (!ifp->is_explicit_name()) // no alias - { - sc->alias(fullname); - } - else // alias - { - if (!itemAlias.empty()) - sc->alias(itemAlias); - } - - // MCOL-1052 Replace SimpleColumn with ConstantColumn, - // since it must have a single value only. - if (constCol) - { - gwi.returnedCols.push_back(spcc); - gwi.columnMap.insert( - CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name.str), spcc)); - } - else - { - gwi.returnedCols.push_back(spsc); - gwi.columnMap.insert( - CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name.str), spsc)); - } - - TABLE_LIST* tmp = 0; - - if (ifp->cached_table) - tmp = ifp->cached_table; - - gwi.tableMap[make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias(), - sc->isColumnStore())] = make_pair(1, tmp); - } - else - { - setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText, gwi); - delete sc; - return ER_INTERNAL_ERROR; - } - - break; - } - - // aggregate column - case Item::SUM_FUNC_ITEM: - { - ReturnedColumn* ac = buildAggregateColumn(item, gwi); - - if (gwi.fatalParseError) - { - // e.g., non-support ref column - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - delete ac; - return ER_CHECK_NOT_IMPLEMENTED; - } - - // add this agg col to returnedColumnList - boost::shared_ptr spac(ac); - gwi.returnedCols.push_back(spac); - // This item could be used in projection or HAVING later. - gwi.extSelAggColsItems.push_back(item); - - break; - } - - case Item::FUNC_ITEM: - { - Item_func* ifp = static_cast(item); - - // @bug4383. error out non-support stored function - if (ifp->functype() == Item_func::FUNC_SP) - { - gwi.fatalParseError = true; - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_SP_FUNCTION_NOT_SUPPORT); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - if (string(ifp->func_name()) == "xor") - { - gwi.fatalParseError = true; - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_FILTER_COND_EXP); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - uint16_t parseInfo = 0; - vector tmpVec; - bool hasNonSupportItem = false; - parse_item(ifp, tmpVec, hasNonSupportItem, parseInfo, &gwi); - - if (ifp->with_subquery() || string(ifp->func_name()) == string("") || - ifp->functype() == Item_func::NOT_ALL_FUNC || parseInfo & SUB_BIT) - { - gwi.fatalParseError = true; - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SELECT_SUB); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - ReturnedColumn* rc = buildFunctionColumn(ifp, gwi, hasNonSupportItem, true); - SRCP srcp(rc); - - if (rc) - { - if (!hasNonSupportItem && !nonConstFunc(ifp) && !(parseInfo & AF_BIT) && tmpVec.size() == 0) - { - if (isUnion || unionSel || gwi.subSelectType != CalpontSelectExecutionPlan::MAIN_SELECT || - parseInfo & SUB_BIT) //|| select_lex.group_list.elements != 0) - { - srcp.reset(buildReturnedColumn(item, gwi, gwi.fatalParseError)); - gwi.returnedCols.push_back(srcp); - - if (ifp->name.length) - srcp->alias(ifp->name.str); - - continue; - } - - break; - } - - gwi.returnedCols.push_back(srcp); - } - else // InfiniDB Non support functions still go through post process for now - { - hasNonSupportItem = false; - uint32_t before_size = funcFieldVec.size(); - // MCOL-1510 Use gwi pointer here to catch funcs with - // not supported aggregate args in projections, - // e.g. NOT(SUM(i)). - parse_item(ifp, funcFieldVec, hasNonSupportItem, parseInfo, &gwi); - uint32_t after_size = funcFieldVec.size(); - - // group by func and func in subquery can not be post processed - // @bug3881. set_user_var can not be treated as constant function - // @bug5716. Try to avoid post process function for union query. - if ((gwi.subQuery /*|| select_lex.group_list.elements != 0 */ || !csep->unionVec().empty() || - isUnion) && - !hasNonSupportItem && (after_size - before_size) == 0 && !(parseInfo & AGG_BIT) && - !(parseInfo & SUB_BIT)) - { - ConstantColumn* cc = buildConstantColumnMaybeNullUsingValStr(ifp, gwi); - - SRCP srcp(cc); - - if (ifp->name.length) - cc->alias(ifp->name.str); - - gwi.returnedCols.push_back(srcp); - - // clear the error set by buildFunctionColumn - gwi.fatalParseError = false; - gwi.parseErrorText = ""; - break; - } - else if (hasNonSupportItem || parseInfo & AGG_BIT || parseInfo & SUB_BIT || - (gwi.fatalParseError && gwi.subQuery)) - { - if (gwi.parseErrorText.empty()) - { - Message::Args args; - args.add(ifp->func_name()); - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORTED_FUNCTION, args); - } - - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - else if (gwi.subQuery && (isPredicateFunction(ifp, &gwi) || ifp->type() == Item::COND_ITEM)) - { - gwi.fatalParseError = true; - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_FILTER_COND_EXP); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - //@Bug 3030 Add error check for dml statement - if (isUpdateOrDeleteStatement(gwi.thd->lex->sql_command)) - { - if (after_size - before_size != 0) - { - gwi.parseErrorText = ifp->func_name(); - return -1; - } - } - else - { - // clear the error set by buildFunctionColumn - gwi.fatalParseError = false; - gwi.parseErrorText = ""; - } - } - - break; - } - - // DRRTUY Replace the whole section with typeid() checks or use - // static_cast here - case Item::CONST_ITEM: - { - switch (item->cmp_type()) - { - case INT_RESULT: - case STRING_RESULT: - case DECIMAL_RESULT: - case REAL_RESULT: - case TIME_RESULT: - { - if (isUpdateOrDeleteStatement(gwi.thd->lex->sql_command)) - { - } - else - { - // do not push the dummy column (mysql added) to returnedCol - if (item->name.length && string(item->name.str) == "Not_used") - continue; - - // @bug3509. Constant column is sent to ExeMgr now. - SRCP srcp(buildReturnedColumn(item, gwi, gwi.fatalParseError)); - - if (item->name.length) - srcp->alias(item->name.str); - - gwi.returnedCols.push_back(srcp); - } - - break; - } - - // MCOL-2178 This switch doesn't handl - // ROW_ - default: - { - IDEBUG(cerr << "Warning unsupported cmp_type() in projection" << endl); - } - } - break; - } // CONST_ITEM ends here - - case Item::NULL_ITEM: - { - if (isUpdateOrDeleteStatement(gwi.thd->lex->sql_command)) - { - } - else - { - SRCP srcp(buildReturnedColumn(item, gwi, gwi.fatalParseError)); - gwi.returnedCols.push_back(srcp); - - if (item->name.length) - srcp->alias(item->name.str); - } - - break; - } - - case Item::SUBSELECT_ITEM: - { - Item_subselect* sub = (Item_subselect*)item; - - if (sub->substype() != Item_subselect::SINGLEROW_SUBS) - { - gwi.fatalParseError = true; - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SELECT_SUB); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - -#ifdef DEBUG_WALK_COND - cerr << "SELECT clause SUBSELECT Item: " << sub->substype() << endl; - JOIN* join = sub->get_select_lex()->join; - - if (join) - { - Item_cond* cond = static_cast(join->conds); - - if (cond) - cond->traverse_cond(debug_walk, &gwi, Item::POSTFIX); - } - - cerr << "Finish SELECT clause subselect item traversing" << endl; -#endif - SelectSubQuery* selectSub = new SelectSubQuery(gwi, sub); - // selectSub->gwip(&gwi); - SCSEP ssub = selectSub->transform(); - - if (!ssub || gwi.fatalParseError) - { - if (gwi.parseErrorText.empty()) - gwi.parseErrorText = "Unsupported Item in SELECT subquery."; - - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - selectSubList.push_back(ssub); - SimpleColumn* rc = new SimpleColumn(); - rc->colSource(rc->colSource() | SELECT_SUB); - rc->timeZone(gwi.timeZone); - - if (sub->get_select_lex()->get_table_list()) - { - rc->viewName(getViewName(sub->get_select_lex()->get_table_list()), lower_case_table_names); - } - if (sub->name.length) - rc->alias(sub->name.str); - - gwi.returnedCols.push_back(SRCP(rc)); - - break; - } - - case Item::COND_ITEM: - { - gwi.fatalParseError = true; - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_FILTER_COND_EXP); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - case Item::EXPR_CACHE_ITEM: - { - printf("EXPR_CACHE_ITEM in getSelectPlan\n"); - gwi.fatalParseError = true; - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_UNKNOWN_COL); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - case Item::WINDOW_FUNC_ITEM: - { - SRCP srcp(buildWindowFunctionColumn(item, gwi, gwi.fatalParseError)); - - if (!srcp || gwi.fatalParseError) - { - if (gwi.parseErrorText.empty()) - gwi.parseErrorText = "Unsupported Item in SELECT subquery."; - - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - gwi.returnedCols.push_back(srcp); - break; - } - - default: - { - break; - } - } - } - - // @bug4388 normalize the project coltypes for union main select list - if (!csep->unionVec().empty()) - { - unsigned int unionedTypeRc = 0; - - for (uint32_t i = 0; i < gwi.returnedCols.size(); i++) - { - vector coltypes; - - for (uint32_t j = 0; j < csep->unionVec().size(); j++) - { - CalpontSelectExecutionPlan* unionCsep = - dynamic_cast(csep->unionVec()[j].get()); - coltypes.push_back(unionCsep->returnedCols()[i]->resultType()); - - // @bug5976. set hasAggregate true for the main column if - // one corresponding union column has aggregate - if (unionCsep->returnedCols()[i]->hasAggregate()) - gwi.returnedCols[i]->hasAggregate(true); - } - - gwi.returnedCols[i]->resultType( - CalpontSystemCatalog::ColType::convertUnionColType(coltypes, unionedTypeRc)); - - if (unionedTypeRc != 0) - { - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(unionedTypeRc); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - } - } - - // Having clause handling - gwi.clauseType = HAVING; - clearStacks(gwi, false); - ParseTree* havingFilter = 0; - // clear fatalParseError that may be left from post process functions - gwi.fatalParseError = false; - gwi.parseErrorText = ""; - - if (gi.groupByHaving != 0) - { - Item_cond* having = static_cast(gi.groupByHaving); -#ifdef DEBUG_WALK_COND - cerr << "------------------- HAVING ---------------------" << endl; - having->traverse_cond(debug_walk, &gwi, Item::POSTFIX); - cerr << "------------------------------------------------\n" << endl; -#endif - having->traverse_cond(gp_walk, &gwi, Item::POSTFIX); - - if (gwi.fatalParseError) - { - setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText, gwi); - return ER_INTERNAL_ERROR; - } - - ParseTree* ptp = 0; - ParseTree* rhs = 0; - - // @bug 4215. some function filter will be in the rcWorkStack. - if (gwi.ptWorkStack.empty() && !gwi.rcWorkStack.empty()) - { - havingFilter = new ParseTree(gwi.rcWorkStack.top()); - gwi.rcWorkStack.pop(); - } - - while (!gwi.ptWorkStack.empty()) - { - havingFilter = gwi.ptWorkStack.top(); - gwi.ptWorkStack.pop(); - - if (gwi.ptWorkStack.empty()) - break; - - ptp = new ParseTree(new LogicOperator("and")); - ptp->left(havingFilter); - rhs = gwi.ptWorkStack.top(); - gwi.ptWorkStack.pop(); - ptp->right(rhs); - gwi.ptWorkStack.push(ptp); - } - } - - // for post process expressions on the select list - // error out post process for union and sub select unit - if (isUnion || gwi.subSelectType != CalpontSelectExecutionPlan::MAIN_SELECT) - { - if (funcFieldVec.size() != 0 && !gwi.fatalParseError) - { - string emsg("Fatal parse error in vtable mode: Unsupported Items in union or sub select unit"); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, emsg); - return ER_CHECK_NOT_IMPLEMENTED; - } - } - - for (uint32_t i = 0; i < funcFieldVec.size(); i++) - { - SimpleColumn* sc = buildSimpleColumn(funcFieldVec[i], gwi); - - if (!sc || gwi.fatalParseError) - { - string emsg; - - if (gwi.parseErrorText.empty()) - { - emsg = "un-recognized column"; - - if (funcFieldVec[i]->name.length) - emsg += string(funcFieldVec[i]->name.str); - } - else - { - emsg = gwi.parseErrorText; - } - - setError(gwi.thd, ER_INTERNAL_ERROR, emsg, gwi); - return ER_INTERNAL_ERROR; - } - - String str; - funcFieldVec[i]->print(&str, QT_ORDINARY); - sc->alias(string(str.c_ptr())); - // sc->tableAlias(funcFieldVec[i]->table_name); - sc->tableAlias(sc->alias()); - SRCP srcp(sc); - uint32_t j = 0; - - for (; j < gwi.returnedCols.size(); j++) - { - if (sc->sameColumn(gwi.returnedCols[j].get())) - { - SimpleColumn* field = dynamic_cast(gwi.returnedCols[j].get()); - - if (field && field->alias() == sc->alias()) - break; - } - } - - if (j == gwi.returnedCols.size()) - { - gwi.returnedCols.push_back(srcp); - gwi.columnMap.insert( - CalpontSelectExecutionPlan::ColumnMap::value_type(string(funcFieldVec[i]->field_name.str), srcp)); - - string fullname; - fullname = str.c_ptr(); - TABLE_LIST* tmp = (funcFieldVec[i]->cached_table ? funcFieldVec[i]->cached_table : 0); - gwi.tableMap[make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias(), - sc->isColumnStore())] = make_pair(1, tmp); - } - } - - // post-process Order by list and expressions on select by redo phase1. only for vtable - // ignore ORDER BY clause for union select unit - string ord_cols = ""; // for normal select phase - SRCP minSc; // min width projected column. for count(*) use - - // Group by list. not valid for union main query - if (!unionSel) - { - gwi.clauseType = GROUP_BY; - Item* nonSupportItem = NULL; - ORDER* groupcol = static_cast(gi.groupByGroup); - - // check if window functions are in order by. InfiniDB process order by list if - // window functions are involved, either in order by or projection. - bool hasWindowFunc = gwi.hasWindowFunc; - gwi.hasWindowFunc = false; - - for (; groupcol; groupcol = groupcol->next) - { - if ((*(groupcol->item))->type() == Item::WINDOW_FUNC_ITEM) - gwi.hasWindowFunc = true; - } - - if (gwi.hasWindowFunc) - { - gwi.fatalParseError = true; - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_WF_NOT_ALLOWED, "GROUP BY clause"); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - gwi.hasWindowFunc = hasWindowFunc; - groupcol = static_cast(gi.groupByGroup); - - for (; groupcol; groupcol = groupcol->next) - { - Item* groupItem = *(groupcol->item); - - // @bug5993. Could be nested ref. - while (groupItem->type() == Item::REF_ITEM) - groupItem = (*((Item_ref*)groupItem)->ref); - - if (groupItem->type() == Item::FUNC_ITEM) - { - Item_func* ifp = (Item_func*)groupItem; - - // call buildFunctionColumn here mostly for finding out - // non-support column on GB list. Should be simplified. - ReturnedColumn* fc = buildFunctionColumn(ifp, gwi, gwi.fatalParseError); - - if (!fc || gwi.fatalParseError) - { - nonSupportItem = ifp; - break; - } - - if (groupcol->in_field_list && groupcol->counter_used) - { - delete fc; - fc = gwi.returnedCols[groupcol->counter - 1].get(); - SRCP srcp(fc->clone()); - - // check if no column parm - for (uint32_t i = 0; i < gwi.no_parm_func_list.size(); i++) - { - if (gwi.no_parm_func_list[i]->expressionId() == fc->expressionId()) - { - gwi.no_parm_func_list.push_back(dynamic_cast(srcp.get())); - break; - } - } - - srcp->orderPos(groupcol->counter - 1); - gwi.groupByCols.push_back(srcp); - continue; - } - else if (groupItem->is_explicit_name()) // alias - { - uint32_t i = 0; - - for (; i < gwi.returnedCols.size(); i++) - { - if (string(groupItem->name.str) == gwi.returnedCols[i]->alias()) - { - ReturnedColumn* rc = gwi.returnedCols[i]->clone(); - rc->orderPos(i); - gwi.groupByCols.push_back(SRCP(rc)); - delete fc; - break; - } - } - - if (i == gwi.returnedCols.size()) - { - nonSupportItem = groupItem; - break; - } - } - else - { - uint32_t i = 0; - - for (; i < gwi.returnedCols.size(); i++) - { - if (fc->operator==(gwi.returnedCols[i].get())) - { - ReturnedColumn* rc = gwi.returnedCols[i]->clone(); - rc->orderPos(i); - gwi.groupByCols.push_back(SRCP(rc)); - delete fc; - break; - } - } - - if (i == gwi.returnedCols.size()) - { - gwi.groupByCols.push_back(SRCP(fc)); - break; - } - } - } - else if (groupItem->type() == Item::FIELD_ITEM) - { - Item_field* ifp = (Item_field*)groupItem; - // this GB col could be an alias of F&E on the SELECT clause, not necessarily a field. - ReturnedColumn* rc = buildSimpleColumn(ifp, gwi); - SimpleColumn* sc = dynamic_cast(rc); - - for (uint32_t j = 0; j < gwi.returnedCols.size(); j++) - { - if (sc) - { - if (sc->sameColumn(gwi.returnedCols[j].get())) - { - sc->orderPos(j); - break; - } - else if (strcasecmp(sc->alias().c_str(), gwi.returnedCols[j]->alias().c_str()) == 0) - { - rc = gwi.returnedCols[j].get()->clone(); - rc->orderPos(j); - break; - } - } - else - { - if (ifp->name.length && string(ifp->name.str) == gwi.returnedCols[j].get()->alias()) - { - rc = gwi.returnedCols[j].get()->clone(); - rc->orderPos(j); - break; - } - } - } - - if (!rc) - { - nonSupportItem = ifp; - break; - } - - SRCP srcp(rc); - - // bug 3151 - AggregateColumn* ac = dynamic_cast(rc); - - if (ac) - { - nonSupportItem = ifp; - break; - } - - gwi.groupByCols.push_back(srcp); - gwi.columnMap.insert( - CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name.str), srcp)); - } - // @bug5638. The group by column is constant but not counter, alias has to match a column - // on the select list - else if (!groupcol->counter_used && - (groupItem->type() == Item::CONST_ITEM && - (groupItem->cmp_type() == INT_RESULT || groupItem->cmp_type() == STRING_RESULT || - groupItem->cmp_type() == REAL_RESULT || groupItem->cmp_type() == DECIMAL_RESULT))) - - { - ReturnedColumn* rc = 0; - - for (uint32_t j = 0; j < gwi.returnedCols.size(); j++) - { - if (groupItem->name.length && string(groupItem->name.str) == gwi.returnedCols[j].get()->alias()) - { - rc = gwi.returnedCols[j].get()->clone(); - rc->orderPos(j); - break; - } - } - - if (!rc) - { - nonSupportItem = groupItem; - break; - } - - gwi.groupByCols.push_back(SRCP(rc)); - } - else if ((*(groupcol->item))->type() == Item::SUBSELECT_ITEM) - { - if (!groupcol->in_field_list || !groupItem->name.length) - { - nonSupportItem = groupItem; - } - else - { - uint32_t i = 0; - - for (; i < gwi.returnedCols.size(); i++) - { - if (string(groupItem->name.str) == gwi.returnedCols[i]->alias()) - { - ReturnedColumn* rc = gwi.returnedCols[i]->clone(); - rc->orderPos(i); - gwi.groupByCols.push_back(SRCP(rc)); - break; - } - } - - if (i == gwi.returnedCols.size()) - { - nonSupportItem = groupItem; - } - } - } - // @bug 3761. - else if (groupcol->counter_used) - { - if (gwi.returnedCols.size() <= (uint32_t)(groupcol->counter - 1)) - { - nonSupportItem = groupItem; - } - else - { - gwi.groupByCols.push_back(SRCP(gwi.returnedCols[groupcol->counter - 1]->clone())); - } - } - else - { - nonSupportItem = groupItem; - } - } - - // @bug 4756. Add internal groupby column for correlated join to the groupby list - if (gwi.aggOnSelect && !gwi.subGroupByCols.empty()) - gwi.groupByCols.insert(gwi.groupByCols.end(), gwi.subGroupByCols.begin(), gwi.subGroupByCols.end()); - - // this is window func on SELECT becuase ORDER BY has not been processed - if (!gwi.windowFuncList.empty() && !gwi.subGroupByCols.empty()) - { - for (uint32_t i = 0; i < gwi.windowFuncList.size(); i++) - { - if (gwi.windowFuncList[i]->hasWindowFunc()) - { - vector windowFunctions = gwi.windowFuncList[i]->windowfunctionColumnList(); - - for (uint32_t j = 0; j < windowFunctions.size(); j++) - windowFunctions[j]->addToPartition(gwi.subGroupByCols); - } - } - } - - if (nonSupportItem) - { - Message::Args args; - - if (nonSupportItem->name.length) - args.add("'" + string(nonSupportItem->name.str) + "'"); - else - args.add(""); - - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_GROUP_BY, args); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - } // GROUP processing ends here - - // ORDER BY processing starts here - { - ORDER* ordercol = static_cast(gi.groupByOrder); - - // check if window functions are in order by. InfiniDB process order by list if - // window functions are involved, either in order by or projection. - for (; ordercol; ordercol = ordercol->next) - { - if ((*(ordercol->item))->type() == Item::WINDOW_FUNC_ITEM) - gwi.hasWindowFunc = true; - } - - // re-visit the first of ordercol list - ordercol = static_cast(gi.groupByOrder); - - // for subquery, order+limit by will be supported in infinidb. build order by columns - // @todo union order by and limit support - // if (gwi.hasWindowFunc || gwi.subSelectType != CalpontSelectExecutionPlan::MAIN_SELECT) - - for (; ordercol; ordercol = ordercol->next) - { - ReturnedColumn* rc = NULL; - - if (ordercol->in_field_list && ordercol->counter_used) - { - rc = gwi.returnedCols[ordercol->counter - 1]->clone(); - rc->orderPos(ordercol->counter - 1); - // can not be optimized off if used in order by with counter. - // set with self derived table alias if it's derived table - gwi.returnedCols[ordercol->counter - 1]->incRefCount(); - } - else - { - Item* ord_item = *(ordercol->item); - bool nonAggField = true; - - // ignore not_used column on order by. - if ((ord_item->type() == Item::CONST_ITEM && ord_item->cmp_type() == INT_RESULT) && - ord_item->full_name() && !strcmp(ord_item->full_name(), "Not_used")) - { - continue; - } - else if (ord_item->type() == Item::CONST_ITEM && ord_item->cmp_type() == INT_RESULT) - { - rc = gwi.returnedCols[((Item_int*)ord_item)->val_int() - 1]->clone(); - } - else if (ord_item->type() == Item::SUBSELECT_ITEM) - { - gwi.fatalParseError = true; - } - else if (ordercol->in_field_list && ord_item->type() == Item::FIELD_ITEM) - { - rc = buildReturnedColumn(ord_item, gwi, gwi.fatalParseError); - Item_field* ifp = static_cast(ord_item); - - // The item must be an alias for a projected column - // and extended SELECT list must contain a proper rc - // either aggregation or a field. - if (!rc && ifp->name.length) - { - gwi.fatalParseError = false; - execplan::CalpontSelectExecutionPlan::ReturnedColumnList::iterator iter = - gwi.returnedCols.begin(); - - for (; iter != gwi.returnedCols.end(); iter++) - { - if ((*iter).get()->alias() == ord_item->name.str) - { - rc = (*iter).get()->clone(); - nonAggField = rc->hasAggregate() ? false : true; - break; - } - } - } - } - else - rc = buildReturnedColumn(ord_item, gwi, gwi.fatalParseError); - - // Looking for a match for this item in GROUP BY list. - if (rc && ord_item->type() == Item::FIELD_ITEM && nonAggField) - { - execplan::CalpontSelectExecutionPlan::ReturnedColumnList::iterator iter = gwi.groupByCols.begin(); - - for (; iter != gwi.groupByCols.end(); iter++) - { - if (rc->sameColumn((*iter).get())) - break; - } - - // MCOL-1052 Find and remove the optimized field - // from ORDER using cond_pushed filters. - if (buildConstColFromFilter(dynamic_cast(rc), gwi, gi)) - { - break; - } - - // MCOL-1052 GROUP BY items list doesn't contain - // this ORDER BY item. - if (iter == gwi.groupByCols.end()) - { - std::ostringstream ostream; - std::ostringstream& osr = ostream; - getColNameFromItem(osr, *ordercol->item); - Message::Args args; - args.add(ostream.str()); - string emsg = IDBErrorInfo::instance()->errorMsg(ERR_NOT_GROUPBY_EXPRESSION, args); - gwi.parseErrorText = emsg; - setError(gwi.thd, ER_INTERNAL_ERROR, emsg, gwi); - return ERR_NOT_GROUPBY_EXPRESSION; - } - } - - // @bug5501 try item_ptr if item can not be fixed. For some - // weird dml statement state, item can not be fixed but the - // infomation is available in item_ptr. - if (!rc || gwi.fatalParseError) - { - gwi.fatalParseError = false; - Item* item_ptr = ordercol->item_ptr; - - while (item_ptr->type() == Item::REF_ITEM) - item_ptr = *(((Item_ref*)item_ptr)->ref); - - rc = buildReturnedColumn(item_ptr, gwi, gwi.fatalParseError); - } - - // This ORDER BY item must be an agg function - - // the ordercol->item_ptr and exteded SELECT list - // must contain the corresponding item. - if (!rc) - { - Item* item_ptr = ordercol->item_ptr; - - if (item_ptr) - rc = buildReturnedColumn(item_ptr, gwi, gwi.fatalParseError); - } - - if (!rc) - { - string emsg = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_ORDER_BY); - gwi.parseErrorText = emsg; - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, emsg, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - } - - if (ordercol->direction == ORDER::ORDER_ASC) - rc->asc(true); - else - rc->asc(false); - - gwi.orderByCols.push_back(SRCP(rc)); - } - - // make sure columnmap, returnedcols and count(*) arg_list are not empty - TableMap::iterator tb_iter = gwi.tableMap.begin(); - - try - { - for (; tb_iter != gwi.tableMap.end(); tb_iter++) - { - if ((*tb_iter).second.first == 1) - continue; - - CalpontSystemCatalog::TableAliasName tan = (*tb_iter).first; - CalpontSystemCatalog::TableName tn = make_table((*tb_iter).first.schema, (*tb_iter).first.table); - SimpleColumn* sc = getSmallestColumn(csc, tn, tan, (*tb_iter).second.second->table, gwi); - SRCP srcp(sc); - gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(sc->columnName(), srcp)); - (*tb_iter).second.first = 1; - } - } - catch (runtime_error& e) - { - setError(gwi.thd, ER_INTERNAL_ERROR, e.what(), gwi); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - return ER_INTERNAL_ERROR; - } - catch (...) - { - string emsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR); - setError(gwi.thd, ER_INTERNAL_ERROR, emsg, gwi); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - return ER_INTERNAL_ERROR; - } - - if (!gwi.count_asterisk_list.empty() || !gwi.no_parm_func_list.empty() || gwi.returnedCols.empty()) - { - // get the smallest column from colmap - CalpontSelectExecutionPlan::ColumnMap::const_iterator iter; - int minColWidth = 0; - CalpontSystemCatalog::ColType ct; - - try - { - for (iter = gwi.columnMap.begin(); iter != gwi.columnMap.end(); ++iter) - { - // should always not null - SimpleColumn* sc = dynamic_cast(iter->second.get()); - - if (sc && !(sc->joinInfo() & JOIN_CORRELATED)) - { - ct = csc->colType(sc->oid()); - - if (minColWidth == 0) - { - minColWidth = ct.colWidth; - minSc = iter->second; - } - else if (ct.colWidth < minColWidth) - { - minColWidth = ct.colWidth; - minSc = iter->second; - } - } - } - } - catch (...) - { - string emsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR); - setError(gwi.thd, ER_INTERNAL_ERROR, emsg, gwi); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - return ER_INTERNAL_ERROR; - } - - if (gwi.returnedCols.empty() && gwi.additionalRetCols.empty()) - gwi.returnedCols.push_back(minSc); - } - - if (!isUnion && !gwi.hasWindowFunc && gwi.subSelectType == CalpontSelectExecutionPlan::MAIN_SELECT) - { - // re-construct the select query and redo phase 1 - if (redo) - { - TABLE_LIST* table_ptr = gi.groupByTables; - - // put all tables, derived tables and views on the list - // TABLE_LIST* table_ptr = select_lex.get_table_list(); - set aliasSet; // to avoid duplicate table alias - - for (; table_ptr; table_ptr = table_ptr->next_local) - { - if (string(table_ptr->table_name.str).find("$vtable") != string::npos) - continue; - - if (table_ptr->derived) - { - if (aliasSet.find(table_ptr->alias.str) != aliasSet.end()) - continue; - - aliasSet.insert(table_ptr->alias.str); - } - else if (table_ptr->view) - { - if (aliasSet.find(table_ptr->alias.str) != aliasSet.end()) - continue; - - aliasSet.insert(table_ptr->alias.str); - } - else - { - // table referenced by view is represented by viewAlias_tableAlias. - // consistent with item.cc field print. - if (table_ptr->referencing_view) - { - if (aliasSet.find(string(table_ptr->referencing_view->alias.str) + "_" + - string(table_ptr->alias.str)) != aliasSet.end()) - continue; - - aliasSet.insert(string(table_ptr->referencing_view->alias.str) + "_" + - string(table_ptr->alias.str)); - } - else - { - if (aliasSet.find(table_ptr->alias.str) != aliasSet.end()) - continue; - - aliasSet.insert(table_ptr->alias.str); - } - } - } - } - else - { - // remove order by clause in case this phase has been executed before. - // need a better fix later, like skip all the other non-optimized phase. - - // MCOL-1052 - if (unionSel) - { - ordercol = static_cast(gi.groupByOrder); - } - else - ordercol = 0; - - for (; ordercol; ordercol = ordercol->next) - { - Item* ord_item = *(ordercol->item); - - if (ord_item->type() == Item::NULL_ITEM) - { - // MCOL-793 Do nothing for an ORDER BY NULL - } - else if (ord_item->type() == Item::SUM_FUNC_ITEM) - { - Item_sum* ifp = (Item_sum*)(*(ordercol->item)); - ReturnedColumn* fc = buildAggregateColumn(ifp, gwi); - - for (uint32_t i = 0; i < gwi.returnedCols.size(); i++) - { - if (fc->operator==(gwi.returnedCols[i].get())) - { - ostringstream oss; - oss << i + 1; - ord_cols += oss.str(); - break; - } - } - - // continue; - } - // @bug 3518. if order by clause = selected column, use position. - else if (ord_item->name.length && ord_item->type() == Item::FIELD_ITEM) - { - Item_field* field = static_cast(ord_item); - string fullname; - - if (field->db_name.str) - fullname += string(field->db_name.str) + "."; - - if (field->table_name.str) - fullname += string(field->table_name.str) + "."; - - if (field->field_name.length) - fullname += string(field->field_name.str); - - uint32_t i = 0; - - for (i = 0; i < gwi.returnedCols.size(); i++) - { - SimpleColumn* sc = dynamic_cast(gwi.returnedCols[i].get()); - - if (sc && ((Item_field*)ord_item)->cached_table && - (strcasecmp(getViewName(((Item_field*)ord_item)->cached_table).c_str(), - sc->viewName().c_str()) != 0)) - continue; - - if (strcasecmp(fullname.c_str(), gwi.returnedCols[i]->alias().c_str()) == 0 || - strcasecmp(ord_item->name.str, gwi.returnedCols[i]->alias().c_str()) == 0) - { - ostringstream oss; - oss << i + 1; - ord_cols += oss.str(); - break; - } - } - - if (i == gwi.returnedCols.size()) - ord_cols += string(" `") + escapeBackTick(ord_item->name.str) + '`'; - } - - else if (ord_item->name.length) - { - // for union order by 1 case. For unknown reason, it doesn't show in_field_list - if (ord_item->type() == Item::CONST_ITEM && ord_item->cmp_type() == INT_RESULT) - { - ord_cols += ord_item->name.str; - } - else if (ord_item->type() == Item::SUBSELECT_ITEM) - { - string emsg = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_ORDER_BY); - setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, emsg, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - else - { - ord_cols += string(" `") + escapeBackTick(ord_item->name.str) + '`'; - } - } - else if (ord_item->type() == Item::FUNC_ITEM) - { - // @bug5636. check if this order by column is on the select list - ReturnedColumn* rc = buildFunctionColumn((Item_func*)(ord_item), gwi, gwi.fatalParseError); - - for (uint32_t i = 0; i < gwi.returnedCols.size(); i++) - { - if (rc && rc->operator==(gwi.returnedCols[i].get())) - { - ostringstream oss; - oss << i + 1; - ord_cols += oss.str(); - break; - } - } - } - else - { - String str; - ord_item->print(&str, QT_ORDINARY); - ord_cols += string(str.c_ptr()); - } - - if (ordercol->direction != ORDER::ORDER_ASC) - ord_cols += " desc"; - } - } - - if (gwi.orderByCols.size()) // has order by - { - csep->hasOrderBy(true); - csep->specHandlerProcessed(true); - csep->orderByThreads(get_orderby_threads(gwi.thd)); - } - } - - // LIMIT and OFFSET are extracted from TABLE_LIST elements. - // All of JOIN-ed tables contain relevant limit and offset. - uint64_t limit = (uint64_t)-1; - if (gi.groupByTables->select_lex->limit_params.select_limit && - (limit = - static_cast(gi.groupByTables->select_lex->limit_params.select_limit)->val_int()) && - limit != (uint64_t)-1) - { - csep->limitNum(limit); - } - else if (csep->hasOrderBy()) - { - // We use LimitedOrderBy so set the limit to - // go through the check in addOrderByAndLimit - csep->limitNum((uint64_t)-2); - } - - if (gi.groupByTables->select_lex->limit_params.offset_limit) - { - csep->limitStart(((Item_int*)gi.groupByTables->select_lex->limit_params.offset_limit)->val_int()); - } - - // We don't currently support limit with correlated subquery - if (csep->limitNum() != (uint64_t)-1 && gwi.subQuery && !gwi.correlatedTbNameVec.empty()) - { - gwi.fatalParseError = true; - gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_LIMIT_SUB); - setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - } // ORDER BY processing ends here - - if (gi.groupByDistinct) - csep->distinct(true); - - // add the smallest column to count(*) parm. - // select constant in subquery case - std::vector::iterator coliter; - - if (!minSc) - { - if (!gwi.returnedCols.empty()) - minSc = gwi.returnedCols[0]; - else if (!gwi.additionalRetCols.empty()) - minSc = gwi.additionalRetCols[0]; - } - - // @bug3523, count(*) on subquery always pick column[0]. - SimpleColumn* sc = dynamic_cast(minSc.get()); - - if (sc && sc->schemaName().empty()) - { - if (gwi.derivedTbList.size() >= 1) - { - SimpleColumn* sc1 = new SimpleColumn(); - sc1->columnName(sc->columnName()); - sc1->tableName(sc->tableName()); - sc1->tableAlias(sc->tableAlias()); - sc1->viewName(sc->viewName()); - sc1->timeZone(gwi.timeZone); - sc1->colPosition(0); - minSc.reset(sc1); - } - } - - for (coliter = gwi.count_asterisk_list.begin(); coliter != gwi.count_asterisk_list.end(); ++coliter) - { - // @bug5977 @note should never throw this, but checking just in case. - // When ExeMgr fix is ready, this should not error out... - if (dynamic_cast(minSc.get())) - { - gwi.fatalParseError = true; - gwi.parseErrorText = "No project column found for aggregate function"; - setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText, gwi); - return ER_CHECK_NOT_IMPLEMENTED; - } - - // Replace the last (presumably constant) object with minSc - if ((*coliter)->aggParms().empty()) - { - (*coliter)->aggParms().push_back(minSc); - } - else - { - (*coliter)->aggParms()[0] = minSc; - } - } - - std::vector::iterator funciter; - - SPTP sptp(new ParseTree(minSc.get()->clone())); - - for (funciter = gwi.no_parm_func_list.begin(); funciter != gwi.no_parm_func_list.end(); ++funciter) - { - FunctionParm funcParms = (*funciter)->functionParms(); - funcParms.push_back(sptp); - (*funciter)->functionParms(funcParms); - } - - // set sequence# for subquery localCols - for (uint32_t i = 0; i < gwi.localCols.size(); i++) - gwi.localCols[i]->sequence(i); - - // append additionalRetCols to returnedCols - gwi.returnedCols.insert(gwi.returnedCols.begin(), gwi.additionalRetCols.begin(), - gwi.additionalRetCols.end()); - - csep->groupByCols(gwi.groupByCols); - csep->orderByCols(gwi.orderByCols); - csep->returnedCols(gwi.returnedCols); - csep->columnMap(gwi.columnMap); - csep->having(havingFilter); - csep->derivedTableList(gwi.derivedTbList); - csep->selectSubList(selectSubList); - csep->subSelectList(gwi.subselectList); - clearStacks(gwi); - return 0; -} - } // namespace cal_impl_if diff --git a/dbcon/mysql/ha_mcs_impl.cpp b/dbcon/mysql/ha_mcs_impl.cpp index 21adbb281..6eaf8a34a 100644 --- a/dbcon/mysql/ha_mcs_impl.cpp +++ b/dbcon/mysql/ha_mcs_impl.cpp @@ -4005,703 +4005,6 @@ int ha_mcs_impl_rnd_pos(uchar* buf, uchar* pos) return ER_INTERNAL_ERROR; } -/*@brief ha_mcs_impl_group_by_init - Get data for MariaDB group_by - pushdown handler */ -/*********************************************************** - * DESCRIPTION: - * Prepares data for group_by_handler::next_row() calls. - * PARAMETERS: - * group_hand - group by handler, that preserves initial table and items lists. . - * table - TABLE pointer The table to save the result set into. - * RETURN: - * 0 if success - * others if something went wrong whilst getting the result set - ***********************************************************/ -int ha_mcs_impl_group_by_init(mcs_handler_info* handler_info, TABLE* table) -{ - ha_mcs_group_by_handler* group_hand = reinterpret_cast(handler_info->hndl_ptr); - string tableName = group_hand->table_list->table->s->table_name.str; - IDEBUG(cout << "group_by_init for table " << tableName << endl); - THD* thd = current_thd; - - // check whether the system is ready to process statement. - static DBRM dbrm(true); - int bSystemQueryReady = dbrm.getSystemQueryReady(); - - if (bSystemQueryReady == 0) - { - // Still not ready - setError(thd, ER_INTERNAL_ERROR, "The system is not yet ready to accept queries"); - return ER_INTERNAL_ERROR; - } - else if (bSystemQueryReady < 0) - { - // Still not ready - setError(thd, ER_INTERNAL_ERROR, "DBRM is not responding. Cannot accept queries"); - return ER_INTERNAL_ERROR; - } - - - uint32_t sessionID = tid2sid(thd->thread_id); - boost::shared_ptr csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID); - csc->identity(CalpontSystemCatalog::FE); - - if (get_fe_conn_info_ptr() == nullptr) { - set_fe_conn_info_ptr((void*)new cal_connection_info()); - thd_set_ha_data(thd, mcs_hton, get_fe_conn_info_ptr()); - } - - cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); - - idbassert(ci != 0); - - if (thd->killed == KILL_QUERY || thd->killed == KILL_QUERY_HARD) - { - force_close_fep_conn(thd, ci); - return 0; - } - - sm::tableid_t tableid = 0; - cal_table_info ti; - cal_group_info gi; - sm::cpsm_conhdl_t* hndl; - SCSEP csep; - - bool localQuery = get_local_query(thd); - - { - ci->stats.reset(); // reset query stats - ci->stats.setStartTime(); - if (thd->main_security_ctx.user) - { - ci->stats.fUser = thd->main_security_ctx.user; - } - else - { - ci->stats.fUser = ""; - } - - if (thd->main_security_ctx.host) - ci->stats.fHost = thd->main_security_ctx.host; - else if (thd->main_security_ctx.host_or_ip) - ci->stats.fHost = thd->main_security_ctx.host_or_ip; - else - ci->stats.fHost = "unknown"; - - try - { - ci->stats.userPriority(ci->stats.fHost, ci->stats.fUser); - } - catch (std::exception& e) - { - string msg = string("Columnstore User Priority - ") + e.what(); - ci->warningMsg = msg; - } - - // If the previous query has error and - // this is not a subquery run by the server(MCOL-1601) - // re-establish the connection - if (ci->queryState != 0) - { - if (ci->cal_conn_hndl_st.size() == 0) - sm::sm_cleanup(ci->cal_conn_hndl); - ci->cal_conn_hndl = 0; - } - - sm::sm_init(sessionID, &ci->cal_conn_hndl, localQuery); - idbassert(ci->cal_conn_hndl != 0); - ci->cal_conn_hndl->csc = csc; - idbassert(ci->cal_conn_hndl->exeMgr != 0); - - try - { - ci->cal_conn_hndl->connect(); - } - catch (...) - { - setError(thd, ER_INTERNAL_ERROR, IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR)); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - goto error; - } - - hndl = ci->cal_conn_hndl; - - ci->cal_conn_hndl_st.push(ci->cal_conn_hndl); - if (!csep) - csep.reset(new CalpontSelectExecutionPlan()); - - SessionManager sm; - BRM::TxnID txnID; - txnID = sm.getTxnID(sessionID); - - if (!txnID.valid) - { - txnID.id = 0; - txnID.valid = true; - } - - QueryContext verID; - verID = sm.verID(); - - csep->txnID(txnID.id); - csep->verID(verID); - csep->sessionID(sessionID); - - if (group_hand->table_list->db.length) - csep->schemaName(group_hand->table_list->db.str, lower_case_table_names); - - csep->traceFlags(ci->traceFlags); - - // MCOL-1052 Send Items lists down to the optimizer. - gi.groupByTables = group_hand->table_list; - gi.groupByFields = group_hand->select; - gi.groupByWhere = group_hand->where; - gi.groupByGroup = group_hand->group_by; - gi.groupByOrder = group_hand->order_by; - gi.groupByHaving = group_hand->having; - gi.groupByDistinct = group_hand->distinct; - - // MCOL-1052 Send pushed conditions here, since server could omit GROUP BY - // items in case of = or IN functions used on GROUP BY columns. - { - CalTableMap::iterator mapiter; - execplan::CalpontSelectExecutionPlan::ColumnMap::iterator colMapIter; - execplan::CalpontSelectExecutionPlan::ColumnMap::iterator condColMapIter; - execplan::ParseTree* ptIt; - - for (TABLE_LIST* tl = gi.groupByTables; tl; tl = tl->next_local) - { - mapiter = ci->tableMap.find(tl->table); - - if (mapiter != ci->tableMap.end() && mapiter->second.condInfo != NULL && - mapiter->second.condInfo->gwi.condPush) - { - while (!mapiter->second.condInfo->gwi.ptWorkStack.empty()) - { - ptIt = mapiter->second.condInfo->gwi.ptWorkStack.top(); - mapiter->second.condInfo->gwi.ptWorkStack.pop(); - gi.pushedPts.push_back(ptIt); - } - } - } - } - // send plan whenever group_init is called - int status = cp_get_group_plan(thd, csep, gi); - - // Never proceed if status != 0 to avoid empty DA - // crashes on later stages - if (status != 0) - goto internal_error; - - // @bug 2547. don't need to send the plan if it's impossible where for all unions. - // MCOL-2178 commenting the below out since cp_get_group_plan does not modify this variable - // which has a default value of false - // if (MIGR::infinidb_vtable.impossibleWhereOnUnion) - // return 0; - - string query; - // Set the query text only once if the server executes - // subqueries separately. - if (ci->queryState) - query.assign(""); - else - query.assign(thd->query_string.str(), thd->query_string.length()); - csep->data(query); - - try - { - csep->priority(ci->stats.userPriority(ci->stats.fHost, ci->stats.fUser)); - } - catch (std::exception& e) - { - string msg = string("Columnstore User Priority - ") + e.what(); - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, msg.c_str()); - } - -#ifdef PLAN_HEX_FILE - // plan serialization - string tmpDir = aTmpDir + "/li1-plan.hex"; - - ifstream ifs(tmpDir); - ByteStream bs1; - ifs >> bs1; - ifs.close(); - csep->unserialize(bs1); -#endif - - if (ci->traceFlags & 1) - { - cerr << "---------------- EXECUTION PLAN ----------------" << endl; - cerr << *csep << endl; - cerr << "-------------- EXECUTION PLAN END --------------\n" << endl; - } - else - { - IDEBUG(cout << "---------------- EXECUTION PLAN ----------------" << endl); - IDEBUG(cerr << *csep << endl); - IDEBUG(cout << "-------------- EXECUTION PLAN END --------------\n" << endl); - } - } // end of execution plan generation - - { - ByteStream msg; - ByteStream emsgBs; - - int ntries = 10; - - // XXX: MCOL-5396: unable to reach this code. - while (true) - { - string emsg; - if (ntries < 0) - { - emsg = "Lost connection to ExeMgr. Please contact your administrator"; - setError(thd, ER_INTERNAL_ERROR, emsg); - return ER_INTERNAL_ERROR; - } - try - { - ByteStream::quadbyte qb = 4; - msg << qb; - hndl->exeMgr->write(msg); - msg.restart(); - csep->rmParms(ci->rmParms); - - // send plan - csep->serialize(msg); - hndl->exeMgr->write(msg); - - // get ExeMgr status back to indicate a vtable joblist success or not - msg.restart(); - emsgBs.restart(); - msg = hndl->exeMgr->read(); - emsgBs = hndl->exeMgr->read(); - - if (msg.length() == 0 || emsgBs.length() == 0) - { - emsg = "Lost connection to ExeMgr. Please contact your administrator"; - setError(thd, ER_INTERNAL_ERROR, emsg); - return ER_INTERNAL_ERROR; - } - - string emsgStr; - emsgBs >> emsgStr; - bool err = false; - - if (msg.length() == 4) - { - msg >> qb; - - if (qb != 0) - { - err = true; - // for makejoblist error, stats contains only error code and insert from here - // because table fetch is not started - ci->stats.setEndTime(); - ci->stats.fQuery = csep->data(); - ci->stats.fQueryType = csep->queryType(); - ci->stats.fErrorNo = qb; - - try - { - ci->stats.insert(); - } - catch (std::exception& e) - { - string msg = string("Columnstore Query Stats - ") + e.what(); - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, msg.c_str()); - } - } - } - else - { - err = true; - } - - if (err) - { - setError(thd, ER_INTERNAL_ERROR, emsgStr); - return ER_INTERNAL_ERROR; - } - - ci->rmParms.clear(); - - ci->queryState = 1; - - break; - } - catch (...) - { - sm::sm_cleanup(hndl); - hndl = 0; - - sm::sm_init(sessionID, &hndl, localQuery); - idbassert(hndl != 0); - hndl->csc = csc; - - ci->cal_conn_hndl = hndl; - ci->cal_conn_hndl_st.pop(); - ci->cal_conn_hndl_st.push(ci->cal_conn_hndl); - - using namespace std::chrono_literals; - std::this_thread::sleep_for(100ms); - ntries --; - - try - { - hndl->connect(); - } - catch (...) - { - setError(thd, ER_INTERNAL_ERROR, IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR)); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - goto error; - } - - msg.restart(); - } - } - } - - // set query state to be in_process. Sometimes mysql calls rnd_init multiple - // times, this makes sure plan only being generated and sent once. It will be - // reset when query finishes in sm::end_query - - // common path for both vtable select phase and table mode -- open scan handle - ti = ci->tableMap[table]; - ti.msTablePtr = table; - - { - // MCOL-1601 Using stacks of ExeMgr conn hndls, table and scan contexts. - ti.tpl_ctx.reset(new sm::cpsm_tplh_t()); - ti.tpl_ctx_st.push(ti.tpl_ctx); - ti.tpl_scan_ctx = sm::sp_cpsm_tplsch_t(new sm::cpsm_tplsch_t()); - ti.tpl_scan_ctx_st.push(ti.tpl_scan_ctx); - - // make sure rowgroup is null so the new meta data can be taken. This is for some case mysql - // call rnd_init for a table more than once. - ti.tpl_scan_ctx->rowGroup = nullptr; - - try - { - tableid = execplan::IDB_VTABLE_ID; - } - catch (...) - { - string emsg = "No table ID found for table " + string(table->s->table_name.str); - setError(thd, ER_INTERNAL_ERROR, emsg); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - goto internal_error; - } - - try - { - sm::tpl_open(tableid, ti.tpl_ctx, hndl); - sm::tpl_scan_open(tableid, ti.tpl_scan_ctx, hndl); - } - catch (std::exception& e) - { - string emsg = "table can not be opened: " + string(e.what()); - setError(thd, ER_INTERNAL_ERROR, emsg); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - goto internal_error; - } - catch (...) - { - string emsg = "table can not be opened"; - setError(thd, ER_INTERNAL_ERROR, emsg); - CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID); - goto internal_error; - } - - ti.tpl_scan_ctx->traceFlags = ci->traceFlags; - - if ((ti.tpl_scan_ctx->ctp).size() == 0) - { - uint32_t num_attr = table->s->fields; - - for (uint32_t i = 0; i < num_attr; i++) - { - CalpontSystemCatalog::ColType ctype; - ti.tpl_scan_ctx->ctp.push_back(ctype); - } - } - } - - ci->tableMap[table] = ti; - return 0; - -error: - - if (ci->cal_conn_hndl) - { - // end_query() should be called here. - sm::sm_cleanup(ci->cal_conn_hndl); - ci->cal_conn_hndl = 0; - } - - // do we need to close all connection handle of the table map? - return ER_INTERNAL_ERROR; - -internal_error: - - if (ci->cal_conn_hndl) - { - // end_query() should be called here. - sm::sm_cleanup(ci->cal_conn_hndl); - ci->cal_conn_hndl = 0; - } - - return ER_INTERNAL_ERROR; -} - -/*@brief ha_mcs_impl_group_by_next - Return result set for MariaDB group_by - pushdown handler -*/ -/*********************************************************** - * DESCRIPTION: - * Return a result record for each group_by_handler::next_row() call. - * PARAMETERS: - * group_hand - group by handler, that preserves initial table and items lists. . - * table - TABLE pointer The table to save the result set in. - * RETURN: - * 0 if success - * HA_ERR_END_OF_FILE if the record set has come to an end - * others if something went wrong whilst getting the result set - ***********************************************************/ -int ha_mcs_impl_group_by_next(TABLE* table, long timeZone) -{ - THD* thd = current_thd; - - if (thd->slave_thread && !get_replication_slave(thd) && isDMLStatement(thd->lex->sql_command)) - return HA_ERR_END_OF_FILE; - - if (isMCSTableUpdate(thd) || isMCSTableDelete(thd)) - return HA_ERR_END_OF_FILE; - - if (get_fe_conn_info_ptr() == nullptr) { - set_fe_conn_info_ptr((void*)new cal_connection_info()); - thd_set_ha_data(thd, mcs_hton, get_fe_conn_info_ptr()); - } - - cal_connection_info* ci = reinterpret_cast(get_fe_conn_info_ptr()); - - if (thd->killed == KILL_QUERY || thd->killed == KILL_QUERY_HARD) - { - force_close_fep_conn(thd, ci); - return 0; - } - - if (ci->alterTableState > 0) - return HA_ERR_END_OF_FILE; - - cal_table_info ti; - ti = ci->tableMap[table]; - int rc = HA_ERR_END_OF_FILE; - - if (!ti.tpl_ctx || !ti.tpl_scan_ctx) - { - CalpontSystemCatalog::removeCalpontSystemCatalog(tid2sid(thd->thread_id)); - return ER_INTERNAL_ERROR; - } - - idbassert(ti.msTablePtr == table); - - try - { - // fetchNextRow interface forces to use buf. - unsigned char buf; - rc = fetchNextRow(&buf, ti, ci, timeZone, true); - } - catch (std::exception& e) - { - string emsg = string("Error while fetching from ExeMgr: ") + e.what(); - setError(thd, ER_INTERNAL_ERROR, emsg); - CalpontSystemCatalog::removeCalpontSystemCatalog(tid2sid(thd->thread_id)); - return ER_INTERNAL_ERROR; - } - - ci->tableMap[table] = ti; - - if (rc != 0 && rc != HA_ERR_END_OF_FILE) - { - string emsg; - - // remove this check when all error handling migrated to the new framework. - if (rc >= 1000) - emsg = ti.tpl_scan_ctx->errMsg; - else - { - logging::ErrorCodes errorcodes; - emsg = errorcodes.errorString(rc); - } - - setError(thd, ER_INTERNAL_ERROR, emsg); - ci->stats.fErrorNo = rc; - CalpontSystemCatalog::removeCalpontSystemCatalog(tid2sid(thd->thread_id)); - rc = ER_INTERNAL_ERROR; - } - - return rc; -} - -int ha_mcs_impl_group_by_end(TABLE* table) -{ - int rc = 0; - THD* thd = current_thd; - - if (thd->slave_thread && !get_replication_slave(thd) && isDMLStatement(thd->lex->sql_command)) - return 0; - - cal_connection_info* ci = nullptr; - - if (get_fe_conn_info_ptr() != NULL) - ci = reinterpret_cast(get_fe_conn_info_ptr()); - - if (!ci) - { - set_fe_conn_info_ptr((void*)new cal_connection_info()); - ci = reinterpret_cast(get_fe_conn_info_ptr()); - thd_set_ha_data(thd, mcs_hton, ci); - } - - if (((thd->lex)->sql_command == SQLCOM_INSERT) || ((thd->lex)->sql_command == SQLCOM_INSERT_SELECT)) - { - force_close_fep_conn(thd, ci, true); // with checking prev command rc - return rc; - } - - if (thd->killed == KILL_QUERY || thd->killed == KILL_QUERY_HARD) - { - force_close_fep_conn(thd, ci); - // clear querystats because no query stats available for cancelled query - ci->queryStats = ""; - // Poping next ExeMgr connection out of the stack - if (ci->cal_conn_hndl_st.size()) - { - ci->cal_conn_hndl_st.pop(); - if (ci->cal_conn_hndl_st.size()) - ci->cal_conn_hndl = ci->cal_conn_hndl_st.top(); - } - - return 0; - } - - IDEBUG(cerr << "group_by_end for table " << table->s->table_name.str << endl); - - cal_table_info ti = ci->tableMap[table]; - sm::cpsm_conhdl_t* hndl; - bool clearScanCtx = false; - - hndl = ci->cal_conn_hndl; - - if (ti.tpl_ctx) - { - if (ti.tpl_scan_ctx.get()) - { - clearScanCtx = ((ti.tpl_scan_ctx.get()->rowsreturned) && - ti.tpl_scan_ctx.get()->rowsreturned == ti.tpl_scan_ctx.get()->getRowCount()); - try - { - sm::tpl_scan_close(ti.tpl_scan_ctx); - } - catch (...) - { - rc = ER_INTERNAL_ERROR; - } - } - - ti.tpl_scan_ctx.reset(); - if (ti.tpl_scan_ctx_st.size()) - { - ti.tpl_scan_ctx_st.pop(); - if (ti.tpl_scan_ctx_st.size()) - ti.tpl_scan_ctx = ti.tpl_scan_ctx_st.top(); - } - try - { - if (hndl) - { - { - bool ask_4_stats = (ci->traceFlags) ? true : false; - sm::tpl_close(ti.tpl_ctx, &hndl, ci->stats, ask_4_stats, clearScanCtx); - ti.tpl_ctx = 0; - } - // Normaly stats variables are set in external_lock method but we set it here - // since they we pretend we are in vtable_disabled mode and the stats vars won't be set. - // We sum the stats up here since server could run a number of - // queries e.g. each for a subquery in a filter. - if (hndl) - { - if (hndl->queryStats.length()) - ci->queryStats += hndl->queryStats; - if (hndl->extendedStats.length()) - ci->extendedStats += hndl->extendedStats; - if (hndl->miniStats.length()) - ci->miniStats += hndl->miniStats; - } - } - else - { - ti.tpl_ctx.reset(); - } - - ci->cal_conn_hndl = hndl; - - } - catch (IDBExcept& e) - { - if (e.errorCode() == ERR_CROSS_ENGINE_CONNECT || e.errorCode() == ERR_CROSS_ENGINE_CONFIG) - { - string msg = string("Columnstore Query Stats - ") + e.what(); - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, msg.c_str()); - } - else - { - setError(thd, ER_INTERNAL_ERROR, e.what()); - rc = ER_INTERNAL_ERROR; - } - } - catch (std::exception& e) - { - setError(thd, ER_INTERNAL_ERROR, e.what()); - rc = ER_INTERNAL_ERROR; - } - catch (...) - { - setError(thd, ER_INTERNAL_ERROR, "Internal error throwed in group_by_end"); - rc = ER_INTERNAL_ERROR; - } - } - - ti.tpl_ctx = 0; - - if (ti.tpl_ctx_st.size()) - { - ti.tpl_ctx_st.pop(); - if (ti.tpl_ctx_st.size()) - ti.tpl_ctx = ti.tpl_ctx_st.top(); - } - - if (ci->cal_conn_hndl_st.size()) - { - ci->cal_conn_hndl_st.pop(); - if (ci->cal_conn_hndl_st.size()) - ci->cal_conn_hndl = ci->cal_conn_hndl_st.top(); - } - - ci->tableMap[table] = ti; - - // push warnings from CREATE phase - if (!ci->warningMsg.empty()) - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, ci->warningMsg.c_str()); - - ci->warningMsg.clear(); - // reset expressionId just in case - ci->expressionId = 0; - return rc; -} - /*@brief Initiate the query for derived_handler */ /*********************************************************** * DESCRIPTION: diff --git a/dbcon/mysql/ha_mcs_impl.h b/dbcon/mysql/ha_mcs_impl.h index 3f1b9d34c..0ab135241 100644 --- a/dbcon/mysql/ha_mcs_impl.h +++ b/dbcon/mysql/ha_mcs_impl.h @@ -46,9 +46,6 @@ extern int ha_mcs_impl_delete_row(); extern int ha_mcs_impl_rnd_pos(uchar* buf, uchar* pos); extern int ha_mcs_impl_pushdown_init(mcs_handler_info* handler_info, TABLE* table, bool isSelectLexUnit = false); extern int ha_mcs_impl_select_next(uchar* buf, TABLE* table, long timeZone); -extern int ha_mcs_impl_group_by_init(mcs_handler_info* handler_info, TABLE* table); -extern int ha_mcs_impl_group_by_next(TABLE* table, long timeZone); -extern int ha_mcs_impl_group_by_end(TABLE* table); #endif diff --git a/dbcon/mysql/ha_mcs_impl_if.h b/dbcon/mysql/ha_mcs_impl_if.h index 4ffecba92..7b02d82e0 100644 --- a/dbcon/mysql/ha_mcs_impl_if.h +++ b/dbcon/mysql/ha_mcs_impl_if.h @@ -167,7 +167,6 @@ struct gp_walk_info bool cs_vtable_is_update_with_derive; bool cs_vtable_impossible_where_on_union; - bool isGroupByHandler; long timeZone; // MCOL-4617 The below 2 fields are used for in-to-exists @@ -219,7 +218,6 @@ struct gp_walk_info , inCaseStmt(false) , cs_vtable_is_update_with_derive(false) , cs_vtable_impossible_where_on_union(false) - , isGroupByHandler(false) , timeZone(timeZone_) , inSubQueryLHS(nullptr) , inSubQueryLHSItem(nullptr) @@ -266,30 +264,6 @@ struct cal_table_info bool moreRows; // are there more rows to consume (b/c of limit) }; -struct cal_group_info -{ - cal_group_info() - : groupByFields(nullptr) - , groupByTables(nullptr) - , groupByWhere(nullptr) - , groupByGroup(nullptr) - , groupByOrder(nullptr) - , groupByHaving(nullptr) - , groupByDistinct(false) - { - } - ~cal_group_info() = default; - - List* groupByFields; // MCOL-1052 SELECT - TABLE_LIST* groupByTables; // MCOL-1052 FROM - Item* groupByWhere; // MCOL-1052 WHERE - ORDER* groupByGroup; // MCOL-1052 GROUP BY - ORDER* groupByOrder; // MCOL-1052 ORDER BY - Item* groupByHaving; // MCOL-1052 HAVING - bool groupByDistinct; // MCOL-1052 DISTINCT - std::vector pushedPts; -}; - typedef std::tr1::unordered_map CalTableMap; typedef std::vector ColNameList; typedef std::bitset<4096> NullValuesBitset; @@ -413,7 +387,6 @@ const std::string infinidb_err_msg = int cp_get_plan(THD* thd, execplan::SCSEP& csep); int cp_get_table_plan(THD* thd, execplan::SCSEP& csep, cal_impl_if::cal_table_info& ti, long timeZone); -int cp_get_group_plan(THD* thd, execplan::SCSEP& csep, cal_impl_if::cal_group_info& gi); int cs_get_derived_plan(ha_columnstore_derived_handler* handler, THD* thd, execplan::SCSEP& csep, gp_walk_info& gwi); int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, execplan::SCSEP& csep, @@ -421,8 +394,6 @@ int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, execpla int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, execplan::SCSEP& csep, bool isUnion = false, bool isSelectHandlerTop = false, bool isSelectLexUnit = false, const std::vector& condStack = std::vector()); -int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, execplan::SCSEP& csep, cal_group_info& gi, - bool isUnion = false); void setError(THD* thd, uint32_t errcode, const std::string errmsg, gp_walk_info* gwi); void setError(THD* thd, uint32_t errcode, const std::string errmsg); void gp_walk(const Item* item, void* arg); diff --git a/dbcon/mysql/ha_mcs_pushdown.cpp b/dbcon/mysql/ha_mcs_pushdown.cpp index 533b1724a..592161616 100644 --- a/dbcon/mysql/ha_mcs_pushdown.cpp +++ b/dbcon/mysql/ha_mcs_pushdown.cpp @@ -360,101 +360,6 @@ bool check_user_var(SELECT_LEX* select_lex) return is_user_var_func; } -/*@brief create_columnstore_group_by_handler- Creates handler*/ -/*********************************************************** - * DESCRIPTION: - * Creates a group_by pushdown handler if there is no: - * non-equi JOIN, e.g * t1.c1 > t2.c2 - * logical OR in the filter predicates - * Impossible WHERE - * Impossible HAVING - * and there is either GROUP BY or aggregation function - * exists at the top level. - * Valid queries with the last two crashes the server if - * processed. - * Details are in server/sql/group_by_handler.h - * PARAMETERS: - * thd - THD pointer - * query - Query structure LFM in group_by_handler.h - * RETURN: - * group_by_handler if success - * NULL in other case - ***********************************************************/ -group_by_handler* create_columnstore_group_by_handler(THD* thd, Query* query) -{ - ha_mcs_group_by_handler* handler = NULL; - // Disable GBH. - return handler; - - // same as thd->lex->current_select - SELECT_LEX* select_lex = query->from->select_lex; - - // MCOL-2178 Disable SP support in the group_by_handler for now - // Check the session variable value to enable/disable use of - // group_by_handler. There is no GBH if SH works for the query. - if ((get_select_handler_mode(thd) == mcs_select_handler_mode_t::ON) || !get_group_by_handler(thd) || - (thd->lex)->sphead) - { - return handler; - } - - // Create a handler if query is valid. See comments for details. - if (query->group_by || select_lex->with_sum_func) - { - bool unsupported_feature = false; - // revisit SELECT_LEX for all units - for (TABLE_LIST* tl = query->from; !unsupported_feature && tl; tl = tl->next_global) - { - select_lex = tl->select_lex; - // Correlation subquery. Comming soon so fail on this yet. - unsupported_feature = select_lex->is_correlated; - - // Impossible HAVING or WHERE - if (!unsupported_feature && - (select_lex->having_value == Item::COND_FALSE || select_lex->cond_value == Item::COND_FALSE)) - { - unsupported_feature = true; - } - - // Unsupported JOIN conditions - if (!unsupported_feature) - { - JOIN* join = select_lex->join; - - if (unsupported_feature == false && join && join->conds) - { - join->conds->traverse_cond(check_walk, &unsupported_feature, Item::POSTFIX); - } - - if (unsupported_feature == false && select_lex->where) - { - select_lex->where->traverse_cond(check_walk, &unsupported_feature, Item::POSTFIX); - } - } - - // Iterate and traverse through the item list and the JOIN cond - // and do not create GBH if the unsupported (set_user_var) - // function is present. - if (check_user_var(select_lex)) - { - return handler; - } - } // unsupported features check ends here - - if (!unsupported_feature) - { - handler = new ha_mcs_group_by_handler(thd, query); - - // Notify the server, that CS handles GROUP BY, ORDER BY and HAVING clauses. - query->group_by = NULL; - query->order_by = NULL; - query->having = NULL; - } - } - - return handler; -} - /*@brief create_columnstore_derived_handler- Creates handler*/ /************************************************************ * DESCRIPTION: @@ -644,79 +549,6 @@ void ha_columnstore_derived_handler::print_error(int, unsigned long) { } -/*********************************************************** - * DESCRIPTION: - * GROUP BY handler constructor - * PARAMETERS: - * thd - THD pointer. - * query - Query describing structure - ***********************************************************/ -ha_mcs_group_by_handler::ha_mcs_group_by_handler(THD* thd_arg, Query* query) - : group_by_handler(thd_arg, mcs_hton) - , select(query->select) - , table_list(query->from) - , distinct(query->distinct) - , where(query->where) - , group_by(query->group_by) - , order_by(query->order_by) - , having(query->having) -{ - const char* timeZone = thd_arg->variables.time_zone->get_name()->ptr(); - dataconvert::timeZoneToOffset(timeZone, strlen(timeZone), &time_zone); -} - -/*********************************************************** - * DESCRIPTION: - * GROUP BY destructor - ***********************************************************/ -ha_mcs_group_by_handler::~ha_mcs_group_by_handler() -{ -} - -/*********************************************************** - * DESCRIPTION: - * Makes the plan and prepares the data - * RETURN: - * int rc - ***********************************************************/ -int ha_mcs_group_by_handler::init_scan() -{ - DBUG_ENTER("ha_mcs_group_by_handler::init_scan"); - - mcs_handler_info mhi = mcs_handler_info(reinterpret_cast(this), GROUP_BY); - int rc = ha_mcs_impl_group_by_init(&mhi, table); - - DBUG_RETURN(rc); -} - -/*********************************************************** - * DESCRIPTION: - * Fetches a row and saves it to a temporary table. - * RETURN: - * int rc - ***********************************************************/ -int ha_mcs_group_by_handler::next_row() -{ - DBUG_ENTER("ha_mcs_group_by_handler::next_row"); - int rc = ha_mcs_impl_group_by_next(table, time_zone); - - DBUG_RETURN(rc); -} - -/*********************************************************** - * DESCRIPTION: - * Shuts the scan down. - * RETURN: - * int rc - ***********************************************************/ -int ha_mcs_group_by_handler::end_scan() -{ - DBUG_ENTER("ha_mcs_group_by_handler::end_scan"); - int rc = ha_mcs_impl_group_by_end(table); - - DBUG_RETURN(rc); -} - /*@brief create_columnstore_select_handler_- Creates handler ************************************************************ * DESCRIPTION: diff --git a/dbcon/mysql/ha_mcs_pushdown.h b/dbcon/mysql/ha_mcs_pushdown.h index f1c7253c9..6be7d64b9 100644 --- a/dbcon/mysql/ha_mcs_pushdown.h +++ b/dbcon/mysql/ha_mcs_pushdown.h @@ -32,7 +32,6 @@ enum mcs_handler_types_t { SELECT, DERIVED, - GROUP_BY, LEGACY }; diff --git a/dbcon/mysql/ha_mcs_sysvars.cpp b/dbcon/mysql/ha_mcs_sysvars.cpp index 029ff1396..3c22e9be1 100644 --- a/dbcon/mysql/ha_mcs_sysvars.cpp +++ b/dbcon/mysql/ha_mcs_sysvars.cpp @@ -78,9 +78,6 @@ static MYSQL_THDVAR_ENUM(select_handler, PLUGIN_VAR_RQCMDARG, static MYSQL_THDVAR_BOOL(derived_handler, PLUGIN_VAR_NOCMDARG, "Enable/Disable the MCS derived_handler", NULL, NULL, 1); -static MYSQL_THDVAR_BOOL(group_by_handler, PLUGIN_VAR_NOCMDARG, "Enable/Disable the MCS group_by_handler", - NULL, NULL, 0); - static MYSQL_THDVAR_BOOL(select_handler_in_stored_procedures, PLUGIN_VAR_NOCMDARG, "Enable/Disable the MCS select_handler for Stored Procedures", NULL, NULL, 1); @@ -229,7 +226,6 @@ st_mysql_sys_var* mcs_system_variables[] = {MYSQL_SYSVAR(compression_type), MYSQL_SYSVAR(original_option_bits), MYSQL_SYSVAR(select_handler), MYSQL_SYSVAR(derived_handler), - MYSQL_SYSVAR(group_by_handler), MYSQL_SYSVAR(select_handler_in_stored_procedures), MYSQL_SYSVAR(orderby_threads), MYSQL_SYSVAR(decimal_scale), @@ -334,15 +330,6 @@ void set_derived_handler(THD* thd, bool value) THDVAR(thd, derived_handler) = value; } -bool get_group_by_handler(THD* thd) -{ - return (thd == NULL) ? false : THDVAR(thd, group_by_handler); -} -void set_group_by_handler(THD* thd, bool value) -{ - THDVAR(thd, group_by_handler) = value; -} - bool get_select_handler_in_stored_procedures(THD* thd) { return (thd == NULL) ? true : THDVAR(thd, select_handler_in_stored_procedures); diff --git a/dbcon/mysql/ha_mcs_sysvars.h b/dbcon/mysql/ha_mcs_sysvars.h index f31dfd69c..92612bb53 100644 --- a/dbcon/mysql/ha_mcs_sysvars.h +++ b/dbcon/mysql/ha_mcs_sysvars.h @@ -75,9 +75,6 @@ void set_select_handler_mode(THD* thd, ulong value); bool get_derived_handler(THD* thd); void set_derived_handler(THD* thd, bool value); -bool get_group_by_handler(THD* thd); -void set_group_by_handler(THD* thd, bool value); - bool get_select_handler_in_stored_procedures(THD* thd); void set_select_handler_in_stored_procedures(THD* thd, bool value);