void SimpleColumn::setOID() { boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(fSessionID); CalpontSystemCatalog::TableColName tcn; tcn = make_tcn(fSchemaName, fTableName, fColumnName); fOid = csc->lookupOID (tcn); if (fOid == -1) { // get colMap from CalpontSelectExecutionPlan // and try to map the schema and table name CalpontSelectExecutionPlan::ColumnMap::iterator iter; CalpontSelectExecutionPlan::ColumnMap colMap = CalpontSelectExecutionPlan::colMap(); // if this is the only column name exist in the map, return it ?? for (iter = colMap.find(fColumnName); iter != colMap.end(); ++iter) { SRCP srcp = iter->second; SimpleColumn* scp = dynamic_cast<SimpleColumn*>(srcp.get()); if (colMap.count(fColumnName) == 1 || scp->tableName().compare(fTableName) == 0) { fOid = scp->oid(); //@bug 221 fix fTableName = scp->tableName(); fSchemaName = scp->schemaName(); //@info assign tableAlias also. watch for other conflict fTableAlias = scp->tableAlias(); fResultType = scp->resultType(); return; } } } fResultType = csc->colType(fOid); }
RowColumn::RowColumn (const RowColumn& rhs, const uint32_t sessionID): ReturnedColumn(rhs, sessionID) { fColumnVec.clear(); //fColumnVec = rhs.fColumnVec; SRCP srcp; for (uint32_t i = 0; i < rhs.fColumnVec.size(); i++) { srcp.reset(rhs.fColumnVec[i]->clone()); fColumnVec.push_back(srcp); } }
void CalpontSelectExecutionPlan::columnMap (const ColumnMap& columnMap) { ColumnMap::const_iterator map_it1, map_it2; fColumnMap.erase(fColumnMap.begin(), fColumnMap.end()); SRCP srcp; for (map_it2 = columnMap.begin(); map_it2 != columnMap.end(); ++map_it2) { srcp.reset(map_it2->second->clone()); fColumnMap.insert(ColumnMap::value_type(map_it2->first, srcp)); } }
void RowColumn::unserialize(messageqcpp::ByteStream& b) { fColumnVec.clear(); ObjectReader::checkType(b, ObjectReader::ROWCOLUMN); ReturnedColumn::unserialize(b); uint32_t size; SRCP srcp; b >> (uint32_t&)size; for (uint32_t i = 0; i < size; i++) { srcp.reset(dynamic_cast<ReturnedColumn*>((ObjectReader::createTreeNode(b)))); fColumnVec.push_back(srcp); } }
void SelectFilter::unserialize(messageqcpp::ByteStream& b) { ObjectReader::checkType(b, ObjectReader::SELECTFILTER); Filter::unserialize(b); fCols.clear(); uint32_t size; SRCP srcp; b >> size; for (uint32_t i = 0; i < size; i++) { srcp.reset(dynamic_cast<ReturnedColumn*>(ObjectReader::createTreeNode(b))); fCols.push_back(srcp); } fOp.reset(dynamic_cast<Operator*>(ObjectReader::createTreeNode(b))); fSub.reset(dynamic_cast<CalpontSelectExecutionPlan*>(ObjectReader::createExecutionPlan(b))); b >> static_cast<uint64_t&>(fReturnedColPos); }
void* ing_opentbl(void* qctx, const char* sn, const char* tn) { try { if (!qctx) return 0; if (!sn) return 0; if (!tn) return 0; if (strlen(sn) == 0) return 0; if (strlen(tn) == 0) return 0; IngQCtx* ingQctx = reinterpret_cast<IngQCtx*>(qctx); cpsm_conhdl_t* cal_conn_hndl = reinterpret_cast<cpsm_conhdl_t*>(ingQctx->dhcs_ses_ctx); IngTCtx* tctx = new IngTCtx(); dhcs_tableid_t tableid = 0; //tableid = tbname2id(sn, tn, cal_conn_hndl); tableid = tbname2id("te", "f_trans", cal_conn_hndl); RequiredColOidSet requiredColOidSet; const CalpontSelectExecutionPlan::ColumnMap colMap = ingQctx->csep.columnMap(); CalpontSelectExecutionPlan::ColumnMap::const_iterator colIter = colMap.begin(); CalpontSelectExecutionPlan::ColumnMap::const_iterator colend = colMap.end(); while (colIter != colend) { SRCP srcp = colIter->second; SimpleColumn* scp = dynamic_cast<SimpleColumn*>(srcp.get()); if (scp) requiredColOidSet.insert(scp->oid()); ++colIter; } tctx->dhcs_tpl_ctx = new cpsm_tplh_t(); dhcs_tpl_open(tableid, &tctx->dhcs_tpl_ctx, ingQctx->dhcs_ses_ctx, requiredColOidSet); tctx->dhcs_tpl_scan_ctx = new cpsm_tplsch_t(); dhcs_tpl_scan_open(tableid, DHCS_TPL_FH_READ, &tctx->dhcs_tpl_scan_ctx, ingQctx->dhcs_ses_ctx); return tctx; } catch (...) { } return NULL; }
void addAggregateColumn(AggregateColumn* agc, int idx, RetColsVector& vec, JobInfo& jobInfo) { uint32_t eid = agc->expressionId(); setExpTupleInfo(agc->resultType(), eid, agc->alias(), jobInfo); vector<pair<int, int> >::iterator i; for (i = jobInfo.aggEidIndexList.begin(); i != jobInfo.aggEidIndexList.end(); ++i) { if (i->first == (int) eid) break; } if (idx < 0 && i != jobInfo.aggEidIndexList.end()) { agc->inputIndex(i->second); jobInfo.cloneAggregateColMap.insert(make_pair(vec[i->second].get(), agc)); } else { SRCP srcp; if (idx < 0) { srcp.reset(agc->clone()); idx = vec.size(); vec.push_back(srcp); } else { srcp = vec[idx]; } jobInfo.aggEidIndexList.push_back(make_pair(eid, idx)); agc->inputIndex(idx); jobInfo.cloneAggregateColMap.insert(make_pair(srcp.get(), agc)); } }
void VirtualTable::addColumn(const SRCP& column) { // As of bug3695, make sure varbinary is not used in subquery. if (column->resultType().colDataType == CalpontSystemCatalog::VARBINARY && !fVarBinOK) throw runtime_error ("VARBINARY in subquery is not supported."); AggregateColumn* agc = NULL; ArithmeticColumn* arc = NULL; ConstantColumn* cc = NULL; FunctionColumn* fc = NULL; SimpleColumn* sc = NULL; WindowFunctionColumn* wc = NULL; string columnName; ostringstream oss; UniqId colId; if ((sc = dynamic_cast<SimpleColumn*>(column.get())) != NULL) { columnName = sc->columnName(); colId = UniqId(sc); } else if ((agc = dynamic_cast<AggregateColumn*>(column.get())) != NULL) { // oss << agc->functionName() << "_" << agc->expressionId(); // oss << "Aggregate_" << agc->expressionId(); columnName = agc->data(); colId = UniqId(agc->expressionId(), "", "", ""); } else if ((wc = dynamic_cast<WindowFunctionColumn*>(column.get())) != NULL) { // oss << wc->functionName() << "_" << wc->expressionId(); // oss << "Window_" << wc->expressionId(); columnName = wc->data(); colId = UniqId(wc->expressionId(), "", "", ""); } else if ((arc = dynamic_cast<ArithmeticColumn*>(column.get())) != NULL) { // oss << "Arithmetic_" << arc->expressionId(); columnName = arc->data(); colId = UniqId(arc->expressionId(), "", "", ""); } else if ((fc = dynamic_cast<FunctionColumn*>(column.get())) != NULL) { // oss << fc->functionName() << "_" << fc->expressionId(); columnName = fc->data(); colId = UniqId(fc->expressionId(), "", "", ""); } else if ((cc = dynamic_cast<ConstantColumn*>(column.get())) != NULL) { // oss << "Constant_" << cc->expressionId(); columnName = cc->data(); colId = UniqId(cc->expressionId(), cc->alias(), "", fView); } else // new column type has added, but this code is not updated. { oss << "not supported column type: " << typeid(*(column.get())).name(); throw runtime_error(oss.str()); } if (columnName.empty()) columnName = column->alias(); SimpleColumn* vc = new SimpleColumn(); vc->tableName(fName); vc->tableAlias(fAlias); vc->columnName(columnName); vc->alias(column->alias()); vc->viewName(fView); uint32_t index = fColumns.size(); vc->colPosition(index); vc->oid(fTableOid+index+1); vc->resultType(column->resultType()); SSC ssc(vc); fColumns.push_back(ssc); fColumnTypes.push_back(column->resultType()); fColumnMap.insert(make_pair(colId, index)); }
uint32_t getTupleKey(JobInfo& jobInfo, const SRCP& srcp, bool add) { int key = -1; if (add) { // setTupleInfo first if add is ture, ok if already set. const SimpleColumn* sc = dynamic_cast<const SimpleColumn*>(srcp.get()); if (sc != NULL) { if (sc->schemaName().empty()) { SimpleColumn tmp(*sc, jobInfo.sessionId); tmp.oid(tableOid(sc, jobInfo.csc) + 1 + sc->colPosition()); key = getTupleKey(jobInfo, &tmp); // sub-query should be there } else { erydbSystemCatalog::ColType ct = sc->colType(); string alias(extractTableAlias(sc)); erydbSystemCatalog::OID tblOid = tableOid(sc, jobInfo.csc); TupleInfo ti(setTupleInfo(ct, sc->oid(), jobInfo, tblOid, sc, alias)); key = ti.key; erydbSystemCatalog::OID dictOid = isDictCol(ct); if (dictOid > 0) { ti = setTupleInfo(ct, dictOid, jobInfo, tblOid, sc, alias); jobInfo.keyInfo->dictKeyMap[key] = ti.key; key = ti.key; } } } else { erydbSystemCatalog::ColType ct = srcp->resultType(); TupleInfo ti(setExpTupleInfo(ct, srcp->expressionId(), srcp->alias(), jobInfo)); key = ti.key; } } else { // TupleInfo is expected to be set already const SimpleColumn* sc = dynamic_cast<const SimpleColumn*>(srcp.get()); if (sc != NULL) { if (sc->schemaName().empty()) { SimpleColumn tmp(*sc, jobInfo.sessionId); tmp.oid(tableOid(sc, jobInfo.csc) + 1 + sc->colPosition()); key = getTupleKey(jobInfo, &tmp); } else { key = getTupleKey(jobInfo, sc); } // check if this is a dictionary column if (jobInfo.keyInfo->dictKeyMap.find(key) != jobInfo.keyInfo->dictKeyMap.end()) key = jobInfo.keyInfo->dictKeyMap[key]; } else { key = getExpTupleKey(jobInfo, srcp->expressionId()); } } return key; }
ReturnedColumn* buildWindowFunctionColumn(Item* item, gp_walk_info& gwi, bool& nonSupport) { //@todo fix print for create view //String str; //item->print(&str, QT_INFINIDB_NO_QUOTE); //cout << str.c_ptr() << endl; if (!(gwi.thd->infinidb_vtable.cal_conn_info)) gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info()); cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(gwi.thd->infinidb_vtable.cal_conn_info); gwi.hasWindowFunc = true; Item_func_window* wf = (Item_func_window*)item; string funcName = wf->func_name(); WindowFunctionColumn* ac = new WindowFunctionColumn(funcName); ac->distinct(wf->isDistinct()); Window_context *wf_ctx = wf->window_ctx(); SRCP srcp; // arguments vector<SRCP> funcParms; for (uint32_t i = 0; i < wf->arg_count; i++) { srcp.reset(buildReturnedColumn(wf->arguments()[i], gwi, nonSupport)); if (!srcp) return nullOnError(gwi); funcParms.push_back(srcp); if (gwi.clauseType == WHERE && !gwi.rcWorkStack.empty()) gwi.rcWorkStack.pop(); } ac->functionParms(funcParms); // Partition by if (wf_ctx) { vector<SRCP> partitions; for (uint32_t i = 0; i < wf_ctx->partition_count; i++) { srcp.reset(buildReturnedColumn(wf_ctx->partitions[i], gwi, nonSupport)); if (!srcp) return nullOnError(gwi); partitions.push_back(srcp); } ac->partitions(partitions); // Order by if (wf_ctx->ordering) { WF_OrderBy orderBy; // order columns if (wf_ctx->ordering->orders) { vector<SRCP> orders; ORDER* orderCol = reinterpret_cast<ORDER*>(wf_ctx->ordering->orders->first); for (; orderCol; orderCol= orderCol->next) { Item* orderItem = *(orderCol->item); srcp.reset(buildReturnedColumn(orderItem, gwi, nonSupport)); if (!srcp) return nullOnError(gwi); srcp->asc(orderCol->asc); srcp->nullsFirst(orderCol->nulls); // nulls 1-nulls first 0-nulls last orders.push_back(srcp); } orderBy.fOrders = orders; } // window frame WF_Frame frm; if (wf_ctx->ordering->frame) { frm.fIsRange = wf_ctx->ordering->frame->isRange; // start if (wf_ctx->ordering->frame->start) { frm.fStart.fFrame = frame(wf_ctx->ordering->frame->start->bound); if (wf_ctx->ordering->frame->start->item) { frm.fStart.fVal.reset(buildReturnedColumn(wf_ctx->ordering->frame->start->item, gwi, nonSupport)); if (!frm.fStart.fVal) return nullOnError(gwi); // 1. check expr is numeric type (rows) or interval (range) bool boundTypeErr = false; switch (frm.fStart.fVal->resultType().colDataType) { case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::VARCHAR: case CalpontSystemCatalog::VARBINARY: case CalpontSystemCatalog::BLOB: case CalpontSystemCatalog::CLOB: boundTypeErr = true; break; case CalpontSystemCatalog::DATE: case CalpontSystemCatalog::DATETIME: if (!frm.fIsRange) boundTypeErr = true; else if (dynamic_cast<IntervalColumn*>(frm.fStart.fVal.get()) == NULL) boundTypeErr = true; break; default: //okay break; } if (boundTypeErr) { gwi.fatalParseError = true; gwi.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_WF_INVALID_BOUND_TYPE, colDataTypeToString(frm.fStart.fVal->resultType().colDataType)); return nullOnError(gwi); } } } // end if (wf_ctx->ordering->frame->end) { frm.fEnd.fFrame = frame(wf_ctx->ordering->frame->end->bound); if (wf_ctx->ordering->frame->end->item) { frm.fEnd.fVal.reset(buildReturnedColumn(wf_ctx->ordering->frame->end->item, gwi, nonSupport)); if (!frm.fEnd.fVal) return nullOnError(gwi); // check expr is numeric type (rows) or interval (range) bool boundTypeErr = false; switch (frm.fEnd.fVal->resultType().colDataType) { case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::VARCHAR: case CalpontSystemCatalog::VARBINARY: case CalpontSystemCatalog::BLOB: case CalpontSystemCatalog::CLOB: boundTypeErr = true; break; case CalpontSystemCatalog::DATE: case CalpontSystemCatalog::DATETIME: if (!frm.fIsRange) boundTypeErr = true; else if (dynamic_cast<IntervalColumn*>(frm.fEnd.fVal.get()) == NULL) boundTypeErr = true; break; default: //okay break; } if (boundTypeErr) { gwi.fatalParseError = true; gwi.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_WF_INVALID_BOUND_TYPE, colDataTypeToString(frm.fStart.fVal->resultType().colDataType)); return nullOnError(gwi); } } } else // no end specified. default end to current row { frm.fEnd.fFrame = WF_CURRENT_ROW; } if (frm.fStart.fVal || frm.fEnd.fVal) { // check order by key only 1 (should be error-ed out in parser. double check here) if (frm.fIsRange && orderBy.fOrders.size() > 1) { gwi.fatalParseError = true; gwi.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_WF_INVALID_ORDER_KEY); return nullOnError(gwi); } // check order by key type is numeric or date/datetime bool orderTypeErr = false; if (frm.fIsRange && orderBy.fOrders.size() == 1) { switch (orderBy.fOrders[0]->resultType().colDataType) { case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::VARCHAR: case CalpontSystemCatalog::VARBINARY: case CalpontSystemCatalog::BLOB: case CalpontSystemCatalog::CLOB: orderTypeErr = true; break; default: //okay // interval bound has to have date/datetime order key if ((dynamic_cast<IntervalColumn*>(frm.fStart.fVal.get()) != NULL || dynamic_cast<IntervalColumn*>(frm.fEnd.fVal.get()) != NULL)) { if (orderBy.fOrders[0]->resultType().colDataType != CalpontSystemCatalog::DATE && orderBy.fOrders[0]->resultType().colDataType != CalpontSystemCatalog::DATETIME) orderTypeErr = true; } else { if (orderBy.fOrders[0]->resultType().colDataType == CalpontSystemCatalog::DATETIME) orderTypeErr = true; } break; } if (orderTypeErr) { gwi.fatalParseError = true; gwi.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_WF_INVALID_ORDER_TYPE, colDataTypeToString(orderBy.fOrders[0]->resultType().colDataType)); return nullOnError(gwi); } } } // construct +,- or interval function for boundary if (frm.fIsRange && frm.fStart.fVal) { frm.fStart.fBound.reset(buildBoundExp(frm.fStart, orderBy.fOrders[0], gwi)); if (!frm.fStart.fBound) return nullOnError(gwi); } if (frm.fIsRange && frm.fEnd.fVal) { frm.fEnd.fBound.reset(buildBoundExp(frm.fEnd, orderBy.fOrders[0], gwi)); if (!frm.fEnd.fVal) return nullOnError(gwi); } } else { frm.fStart.fFrame = WF_UNBOUNDED_PRECEDING; frm.fEnd.fFrame = WF_CURRENT_ROW; } orderBy.fFrame = frm; ac->orderBy(orderBy); } } if (gwi.fatalParseError || nonSupport) { if (gwi.parseErrorText.empty()) gwi.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_WF_NON_SUPPORT); setError(gwi.thd, HA_ERR_UNSUPPORTED, gwi.parseErrorText); return NULL; } ac->resultType(colType_MysqlToIDB(wf)); // bug5736. Make the result type double for some window functions when // infinidb_double_for_decimal_math is set. ac->adjustResultType(); ac->expressionId(ci->expressionId++); if (item->name) ac->alias(item->name); // put ac on windowFuncList gwi.windowFuncList.push_back(ac); return ac; }