execplan::ReturnedColumn* buildPseudoColumn(Item* item, gp_walk_info& gwi, bool& nonSupport, uint32_t pseudoType) { Item_func* ifp = (Item_func*)item; // idblocalpm is replaced by constant if (pseudoType == PSEUDO_LOCALPM) { int64_t localPm = idblocalpm(); ConstantColumn* cc; if (localPm) cc = new ConstantColumn(localPm); else cc = new ConstantColumn("", ConstantColumn::NULLDATA); cc->alias(ifp->name? ifp->name : ""); return cc; } // convert udf item to pseudocolumn item. // adjust result type // put arg col to column map string funcName = ifp->func_name(); if (ifp->arg_count != 1 || !(ifp->arguments()) || !(ifp->arguments()[0]) || ifp->arguments()[0]->type() != Item::FIELD_ITEM) return nullOnError(gwi, funcName); Item_field* field = (Item_field*)(ifp->arguments()[0]); // @todo rule out derive table if (!field->field || !field->db_name || strlen(field->db_name) == 0) return nullOnError(gwi, funcName); SimpleColumn *sc = buildSimpleColumn(field, gwi); if (!sc) return nullOnError(gwi, funcName); if ((pseudoType == PSEUDO_EXTENTMIN || pseudoType == PSEUDO_EXTENTMAX) && (sc->colType().colDataType == CalpontSystemCatalog::VARBINARY || (sc->colType().colDataType == CalpontSystemCatalog::VARCHAR && sc->colType().colWidth > 7) || (sc->colType().colDataType == CalpontSystemCatalog::CHAR && sc->colType().colWidth > 8))) return nullOnError(gwi, funcName); // put arg col to column map if (gwi.clauseType == SELECT || gwi.clauseType == GROUP_BY) // select clause { SRCP srcp(sc); gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(sc->columnName(), srcp)); gwi.tableMap[make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias(), sc->isInfiniDB())] = make_pair(1, field->cached_table); } else if (!gwi.rcWorkStack.empty()) { gwi.rcWorkStack.pop(); } if (pseudoType == PSEUDO_PARTITION) { // parms: psueducolumn dbroot, segmentdir, segment SPTP sptp; FunctionColumn *fc = new FunctionColumn(funcName); funcexp::FunctionParm parms; PseudoColumn *dbroot = new PseudoColumn(*sc, PSEUDO_DBROOT); sptp.reset(new ParseTree(dbroot)); parms.push_back(sptp); PseudoColumn *pp = new PseudoColumn(*sc, PSEUDO_SEGMENTDIR); sptp.reset(new ParseTree(pp)); parms.push_back(sptp); PseudoColumn* seg = new PseudoColumn(*sc, PSEUDO_SEGMENT); sptp.reset(new ParseTree(seg)); parms.push_back(sptp); fc->functionParms(parms); fc->expressionId(gwi.expressionId++); // string result type CalpontSystemCatalog::ColType ct; ct.colDataType = CalpontSystemCatalog::VARCHAR; ct.colWidth = 256; fc->resultType(ct); // operation type integer funcexp::Func_idbpartition* idbpartition = new funcexp::Func_idbpartition(); fc->operationType(idbpartition->operationType(parms, fc->resultType())); fc->alias(ifp->name? ifp->name : ""); return fc; } PseudoColumn *pc = new PseudoColumn(*sc, pseudoType); // @bug5892. set alias for derived table column matching. pc->alias(ifp->name? ifp->name : ""); return pc; }
execplan::ParseTree* ScalarSub::buildParseTree(PredicateOperator* op) { idbassert(fColumn.get() && fSub && fFunc); vector<SRCP> cols; Filter* filter; RowColumn* rcol = dynamic_cast<RowColumn*>(fColumn.get()); if (rcol) { // IDB only supports (c1,c2..) =/!= (subquery) if (fFunc->functype() != Item_func::EQ_FUNC && fFunc->functype() != Item_func::NE_FUNC) { fGwip.fatalParseError = true; fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_INVALID_OPERATOR_WITH_LIST); return NULL; } cols = rcol->columnVec(); } else cols.push_back(fColumn); SCSEP csep(new CalpontSelectExecutionPlan()); csep->sessionID(fGwip.sessionid); csep->location(CalpontSelectExecutionPlan::WHERE); csep->subType (CalpontSelectExecutionPlan::SINGLEROW_SUBS); // gwi for the sub query gp_walk_info gwi; gwi.thd = fGwip.thd; gwi.subQuery = this; // @4827 merge table list to gwi in case there is FROM sub to be referenced // in the FROM sub gwi.derivedTbCnt = fGwip.derivedTbList.size(); uint32_t tbCnt = fGwip.tbList.size(); gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end()); gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end()); if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep) != 0) { //@todo more in error handling if (!gwi.fatalParseError) { fGwip.fatalParseError = true; fGwip.parseErrorText = "Error occured in ScalarSub::transform()"; } else { fGwip.fatalParseError = gwi.fatalParseError; fGwip.parseErrorText = gwi.parseErrorText; } return NULL; } fGwip.subselectList.push_back(csep); // error out non-support case for now: comparison out of semi join tables. // only check for simplecolumn if (!gwi.correlatedTbNameVec.empty()) { for (uint32_t i = 0; i < cols.size(); i++) { SimpleColumn* sc = dynamic_cast<SimpleColumn*>(cols[i].get()); if (sc) { CalpontSystemCatalog::TableAliasName tan = make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias()); uint32_t j = 0; for (; j < gwi.correlatedTbNameVec.size(); j++) if (tan == gwi.correlatedTbNameVec[j]) break; if (j == gwi.correlatedTbNameVec.size()) { fGwip.fatalParseError = true; fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR); return NULL; } } } } // remove outer query tables CalpontSelectExecutionPlan::TableList tblist; if (csep->tableList().size() >= tbCnt) tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end()); CalpontSelectExecutionPlan::SelectList derivedTbList; if (csep->derivedTableList().size() >= gwi.derivedTbCnt) derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt, csep->derivedTableList().end()); csep->tableList(tblist); csep->derivedTableList(derivedTbList); // if (fSub->is_correlated) if (fSub->unit->first_select()->master_unit()->uncacheable) { SelectFilter* subFilter = new SelectFilter(); subFilter->correlated(true); subFilter->cols(cols); subFilter->sub(csep); subFilter->op(SOP(op)); subFilter->returnedColPos(fReturnedColPos); filter = subFilter; } else { SimpleScalarFilter* subFilter = new SimpleScalarFilter(); subFilter->cols(cols); subFilter->sub(csep); subFilter->op(SOP(op)); filter = subFilter; } return new ParseTree(filter); }
void View::transform() { erydbSelectExecutionPlan* csep = new erydbSelectExecutionPlan(); csep->sessionID(fParentGwip->sessionid); // gwi for the sub query gp_walk_info gwi; gwi.thd = fParentGwip->thd; uint32_t sessionID = csep->sessionID(); gwi.sessionid = sessionID; boost::shared_ptr<erydbSystemCatalog> csc = erydbSystemCatalog::makeerydbSystemCatalog(sessionID); csc->identity(erydbSystemCatalog::FE); gwi.csc = csc; // traverse the table list of the view TABLE_LIST* table_ptr = fSelect.get_table_list(); erydbSelectExecutionPlan::SelectList derivedTbList; // @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; string viewName = getViewName(table_ptr); if (table_ptr->derived) { SELECT_LEX *select_cursor = table_ptr->derived->first_select(); FromSubQuery *fromSub = new FromSubQuery(gwi, select_cursor); string alias(table_ptr->alias); gwi.viewName = make_aliasview("", alias, table_ptr->belong_to_view->alias, ""); algorithm::to_lower(alias); fromSub->alias(alias); gwi.derivedTbList.push_back(SCSEP(fromSub->transform())); // set alias to both table name and alias name of the derived table erydbSystemCatalog::TableAliasName tn = make_aliasview("", "", alias, viewName); gwi.tbList.push_back(tn); gwi.tableMap[tn] = make_pair(0, table_ptr); gwi.thd->erydb_vtable.isUnion = true; //by-pass the 2nd pass of rnd_init } else if (table_ptr->view) { // for nested view, the view name is vout.vin... format erydbSystemCatalog::TableAliasName tn = make_aliasview(table_ptr->db, table_ptr->table_name, table_ptr->alias, viewName); gwi.viewName = make_aliastable(table_ptr->db, table_ptr->table_name, viewName); View *view = new View(table_ptr->view->select_lex, &gwi); view->viewName(gwi.viewName); gwi.viewList.push_back(view); view->transform(); } else { // check foreign engine tables bool infiniDB = (table_ptr->table ? isEryDB(table_ptr->table) : true); // trigger system catalog cache if (infiniDB) csc->columnRIDs(make_table(table_ptr->db, table_ptr->table_name), true); erydbSystemCatalog::TableAliasName tn = make_aliasview(table_ptr->db, table_ptr->table_name, table_ptr->alias, viewName, infiniDB); gwi.tbList.push_back(tn); gwi.tableMap[tn] = make_pair(0, table_ptr); fParentGwip->tableMap[tn] = make_pair(0, table_ptr); } } if (gwi.fatalParseError) { setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText); return; } } catch (ERYDBExcept& ie) { setError(gwi.thd, ER_INTERNAL_ERROR, ie.what()); erydbSystemCatalog::removeerydbSystemCatalog(sessionID); return; } catch (...) { string emsg = ERYDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR); setError(gwi.thd, ER_INTERNAL_ERROR, emsg); erydbSystemCatalog::removeerydbSystemCatalog(sessionID); return; } // merge table list to parent select fParentGwip->tbList.insert(fParentGwip->tbList.end(), gwi.tbList.begin(), gwi.tbList.end()); fParentGwip->derivedTbList.insert(fParentGwip->derivedTbList.end(), gwi.derivedTbList.begin(), gwi.derivedTbList.end()); fParentGwip->correlatedTbNameVec.insert(fParentGwip->correlatedTbNameVec.end(), gwi.correlatedTbNameVec.begin(), gwi.correlatedTbNameVec.end()); // merge view list to parent fParentGwip->viewList.insert(fParentGwip->viewList.end(), gwi.viewList.begin(), gwi.viewList.end()); // merge non-collapsed outer join to parent select stack<ParseTree*> tmpstack; while (!gwi.ptWorkStack.empty()) { tmpstack.push(gwi.ptWorkStack.top()); gwi.ptWorkStack.pop(); } while (!tmpstack.empty()) { fParentGwip->ptWorkStack.push(tmpstack.top()); tmpstack.pop(); } }