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);

}
Exemple #3
0
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();
	}
}