예제 #1
0
/**
 * This is invoked when a NOT function is got. It's usually the case NOT<IN optimizer>
 * This function will simple turn the semi join to anti join
 *
 */
void InSub::handleNot()
{
	ParseTree *pt = fGwip.ptWorkStack.top();
	ExistsFilter *subFilter = dynamic_cast<ExistsFilter*>(pt->data());
	idbassert(subFilter);
	subFilter->notExists(true);
	SCSEP csep = subFilter->sub();
	const ParseTree* ptsub = csep->filters();
	if (ptsub)
		ptsub->walk(makeAntiJoin);
	ptsub = csep->having();
	if (ptsub)
		ptsub->walk(makeAntiJoin);
}
/** MySQL transform (NOT) IN subquery to (NOT) EXIST
 *
 */
execplan::ParseTree* InSub::transform()
{
    if (!fFunc)
        return NULL;

    // @todo need to handle scalar IN and BETWEEN specially
    // this blocks handles only one subselect scalar
    // arg[0]: column | arg[1]: subselect
    //assert (fFunc->argument_count() == 2 && fGwip.rcWorkStack.size() >= 2);
    if (fFunc->argument_count() != 2 || fGwip.rcWorkStack.size() < 2)
    {
        fGwip.fatalParseError = true;
        fGwip.parseErrorText = "Unsupported item in IN subquery";
        return NULL;
    }

    ReturnedColumn* rhs = fGwip.rcWorkStack.top();
    fGwip.rcWorkStack.pop();
    delete rhs;
    ReturnedColumn* lhs = fGwip.rcWorkStack.top();
    fGwip.rcWorkStack.pop();
    delete lhs;

    fSub = (Item_subselect*)(fFunc->arguments()[1]);
    idbassert(fSub && fFunc);

    SCSEP csep (new CalpontSelectExecutionPlan());
    csep->sessionID(fGwip.sessionid);
    csep->location(CalpontSelectExecutionPlan::WHERE);
    csep->subType (CalpontSelectExecutionPlan::IN_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)
    {
        fGwip.fatalParseError = true;

        if (gwi.fatalParseError && !gwi.parseErrorText.empty())
            fGwip.parseErrorText = gwi.parseErrorText;
        else
            fGwip.parseErrorText = "Error occured in InSub::transform()";

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

    ExistsFilter* subFilter = new ExistsFilter();
    subFilter->sub(csep);

    if (gwi.subQuery->correlated())
        subFilter->correlated(true);
    else
        subFilter->correlated(false);

    if (fGwip.clauseType == HAVING && subFilter->correlated())
    {
        fGwip.fatalParseError = true;
        fGwip.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_NON_SUPPORT_HAVING);
    }

    fGwip.subselectList.push_back(csep);
    return new ParseTree(subFilter);
}
예제 #3
0
	void serializeCSEP()
	{
	   /*
		* erydbSelectExecutionPlan
		* This is a large class; it makes more sense to write == operators
		* for everything than to write a giant equivalance test here.
		* For now this is mostly a regression test.
		*/

		erydbSelectExecutionPlan csep1, csep2;
		erydbSelectExecutionPlan::ReturnedColumnList colList;
		ParseTree* filterList;
		erydbExecutionPlan *cep;
		ByteStream b;
		
		cep = &csep2;
		
		CPPUNIT_ASSERT(csep1 == csep2);
		CPPUNIT_ASSERT(!(csep1 != csep2));
		CPPUNIT_ASSERT(csep1 == cep);
		CPPUNIT_ASSERT(!(csep1 != cep));
		
        // returned columns
		SimpleColumn *sc = new SimpleColumn("tpch.region.r_regionkey");
		colList.push_back(sc);
               
        // filters
		erydbSelectExecutionPlan::Parser parser;
		std::vector<Token> tokens;
		Token t;
        
		SimpleFilter *sf = new SimpleFilter();
		SimpleColumn *lhs = new SimpleColumn(*sc);       
		SimpleColumn *rhs = new SimpleColumn("tpch.nation.n_regionkey");
		Operator *op = new Operator("=");
        
		sf->op(op);
		sf->lhs(lhs);
		sf->rhs(rhs);
        
		t.value = sf;
		tokens.push_back(t);
        
		Operator *op1 = new Operator ("and");
		t.value = op1;
		tokens.push_back(t);
        
		SimpleFilter *sf1 = new SimpleFilter();
		SimpleColumn *lhs1 = new SimpleColumn (*rhs);       
		ConstantColumn *constCol = new ConstantColumn("3", ConstantColumn::NUM);        
		Operator *op2 = new Operator("!=");
        
		sf1->op(op2);
		sf1->lhs(lhs1);
		sf1->rhs(constCol);

		t.value = sf1;
		tokens.push_back(t);
        
		filterList = parser.parse(tokens.begin(), tokens.end());
        
        // draw filterList tree
		filterList->drawTree("selectExecutionPlan_1.dot");
                     
        // erydb execution plan        
		csep1.returnedCols (colList);
		csep1.filters (filterList);
		
		CPPUNIT_ASSERT(csep1 != csep2);
		CPPUNIT_ASSERT(!(csep1 == csep2));
		CPPUNIT_ASSERT(csep1 != cep);
		CPPUNIT_ASSERT(!(csep1 == cep));
		
		csep1.serialize(b);
		csep2.unserialize(b);
		CPPUNIT_ASSERT(b.length() == 0);
		
		CPPUNIT_ASSERT(csep1 == csep2);
		CPPUNIT_ASSERT(!(csep1 != csep2));
		CPPUNIT_ASSERT(csep1 == cep);
		CPPUNIT_ASSERT(!(csep1 != cep));
		
		erydbSelectExecutionPlan csep3, csep4;
        
        // subselect
		erydbSelectExecutionPlan *subselect = new erydbSelectExecutionPlan;
		subselect->location(erydbSelectExecutionPlan::WHERE);
		subselect->dependent (false);
		CPPUNIT_ASSERT (subselect->location() == erydbSelectExecutionPlan::WHERE);
		CPPUNIT_ASSERT (subselect->dependent() == false);
		erydbSelectExecutionPlan::SelectList selectList;
		selectList.push_back(subselect);
		csep3.subSelects(selectList);
        
        // exist filter
		erydbSelectExecutionPlan* cep1 = new erydbSelectExecutionPlan();
		ExistsFilter *filter = new ExistsFilter();
		delete filter;
		filter = new ExistsFilter(cep1);        
		filter->exists(cep1);
		//erydbSelectExecutionPlan* cep2 = const_cast<erydbSelectExecutionPlan*>(filter->exists());

		erydbSelectExecutionPlan::Parser parser1;
		std::vector<Token> tokens1;
		Token t1;
		t1.value = filter;
		tokens1.push_back(t1);
		csep3.filters(parser1.parse(tokens1.begin(), tokens1.end()));
		
		csep3.serialize(b);
		csep4.unserialize(b);
		
		CPPUNIT_ASSERT(csep3 == csep4);
		CPPUNIT_ASSERT(!(csep3 != csep4));
		
		
	}
예제 #4
0
 void selectExecutionPlan_2()
 {
     erydbSelectExecutionPlan cep;
     
     // select filter
     erydbSelectExecutionPlan *subselect = new erydbSelectExecutionPlan;
     subselect->location(erydbSelectExecutionPlan::WHERE);
     subselect->dependent (false);
     CPPUNIT_ASSERT (subselect->location() == erydbSelectExecutionPlan::WHERE);
     CPPUNIT_ASSERT (subselect->dependent() == false);
     ByteStream selb;
     subselect->serialize(selb);
     erydbSelectExecutionPlan *subselect1 = new erydbSelectExecutionPlan;
     subselect->location(erydbSelectExecutionPlan::WHERE);
     subselect1->unserialize(selb);
     
     SelectFilter *sef = new SelectFilter ( new SimpleColumn ("tpch.region.r_regionkey", 0),
                                             new Operator (">="),
                                             subselect);
     cout << *sef;
     ByteStream b;
     sef->serialize(b);
     SelectFilter *newsef = new SelectFilter ( new SimpleColumn ("tpch.nation.n_regionke", 0),
                                             new Operator ("<="),
                                             subselect1);
     newsef->unserialize(b);
     CPPUNIT_ASSERT(*sef == *newsef);                                                
     delete sef;
     delete newsef;
     
     // simple filter
     Filter *sf = new SimpleFilter(new Operator("="), 
     															new SimpleColumn ("tpch.nation.n_regionke", 0),
     															new SimpleColumn ("tpch.region.r_regionkey", 0));
     cout << *sf;
     
     ByteStream sfb;
     SimpleFilter *sf2 = new SimpleFilter();
     sf2->serialize (sfb);
     sf->unserialize (sfb);
     CPPUNIT_ASSERT (*sf == *sf2);
     delete sf2;
     delete sf;
      
     // exist filter
     erydbSelectExecutionPlan *cep1 = new erydbSelectExecutionPlan();
     ExistsFilter *filter = new ExistsFilter();
     delete filter;
     filter = new ExistsFilter(cep1);        
     filter->exists(cep1);
     const erydbSelectExecutionPlan* cep2 = filter->exists();
     cout << *filter;
     CPPUNIT_ASSERT (*cep1 == *cep2);
     erydbSelectExecutionPlan::Parser parser;
     std::vector<Token> tokens;
     Token t;
     t.value = filter;
     tokens.push_back(t);
     cep.filters(parser.parse(tokens.begin(), tokens.end())); 
     cout << cep;
     
     cout << " --- end of test 2 ---" << endl;
 }