コード例 #1
0
ファイル: nestloopexecutor.cpp プロジェクト: algking/voltdb
bool NestLoopExecutor::p_init(AbstractPlanNode* abstract_node,
                              TempTableLimits* limits)
{
    VOLT_TRACE("init NestLoop Executor");

    NestLoopPlanNode* node = dynamic_cast<NestLoopPlanNode*>(abstract_node);
    assert(node);

    // Create output table based on output schema from the plan
    setTempOutputTable(limits);

    // NULL tuple for outer join
    if (node->getJoinType() == JOIN_TYPE_LEFT) {
        Table* inner_table = node->getInputTables()[1];
        assert(inner_table);
        m_null_tuple.init(inner_table->schema());
    }

    return true;
}
コード例 #2
0
ファイル: nestloopexecutor.cpp プロジェクト: algking/voltdb
bool NestLoopExecutor::p_execute(const NValueArray &params) {
    VOLT_DEBUG("executing NestLoop...");

    NestLoopPlanNode* node = dynamic_cast<NestLoopPlanNode*>(m_abstractNode);
    assert(node);
    assert(node->getInputTables().size() == 2);

    Table* output_table_ptr = node->getOutputTable();
    assert(output_table_ptr);

    // output table must be a temp table
    TempTable* output_table = dynamic_cast<TempTable*>(output_table_ptr);
    assert(output_table);

    Table* outer_table = node->getInputTables()[0];
    assert(outer_table);

    Table* inner_table = node->getInputTables()[1];
    assert(inner_table);

    VOLT_TRACE ("input table left:\n %s", outer_table->debug().c_str());
    VOLT_TRACE ("input table right:\n %s", inner_table->debug().c_str());

    //
    // Pre Join Expression
    //
    AbstractExpression *preJoinPredicate = node->getPreJoinPredicate();
    if (preJoinPredicate) {
        preJoinPredicate->substitute(params);
        VOLT_TRACE ("Pre Join predicate: %s", preJoinPredicate == NULL ?
                    "NULL" : preJoinPredicate->debug(true).c_str());
    }
    //
    // Join Expression
    //
    AbstractExpression *joinPredicate = node->getJoinPredicate();
    if (joinPredicate) {
        joinPredicate->substitute(params);
        VOLT_TRACE ("Join predicate: %s", joinPredicate == NULL ?
                    "NULL" : joinPredicate->debug(true).c_str());
    }
    //
    // Where Expression
    //
    AbstractExpression *wherePredicate = node->getWherePredicate();
    if (wherePredicate) {
        wherePredicate->substitute(params);
        VOLT_TRACE ("Where predicate: %s", wherePredicate == NULL ?
                    "NULL" : wherePredicate->debug(true).c_str());
    }

    // Join type
    JoinType join_type = node->getJoinType();
    assert(join_type == JOIN_TYPE_INNER || join_type == JOIN_TYPE_LEFT);

    int outer_cols = outer_table->columnCount();
    int inner_cols = inner_table->columnCount();
    TableTuple outer_tuple(node->getInputTables()[0]->schema());
    TableTuple inner_tuple(node->getInputTables()[1]->schema());
    TableTuple &joined = output_table->tempTuple();
    TableTuple null_tuple = m_null_tuple;

    TableIterator iterator0 = outer_table->iterator();
    while (iterator0.next(outer_tuple)) {

        // did this loop body find at least one match for this tuple?
        bool match = false;
        // For outer joins if outer tuple fails pre-join predicate
        // (join expression based on the outer table only)
        // it can't match any of inner tuples
        if (preJoinPredicate == NULL || preJoinPredicate->eval(&outer_tuple, NULL).isTrue()) {

            // populate output table's temp tuple with outer table's values
            // probably have to do this at least once - avoid doing it many
            // times per outer tuple
            joined.setNValues(0, outer_tuple, 0, outer_cols);

            TableIterator iterator1 = inner_table->iterator();
            while (iterator1.next(inner_tuple)) {
                // Apply join filter to produce matches for each outer that has them,
                // then pad unmatched outers, then filter them all
                if (joinPredicate == NULL || joinPredicate->eval(&outer_tuple, &inner_tuple).isTrue()) {
                    match = true;
                    // Filter the joined tuple
                    if (wherePredicate == NULL || wherePredicate->eval(&outer_tuple, &inner_tuple).isTrue()) {
                        // Matched! Complete the joined tuple with the inner column values.
                        joined.setNValues(outer_cols, inner_tuple, 0, inner_cols);
                        output_table->insertTupleNonVirtual(joined);
                    }
                }
            }
        }
        //
        // Left Outer Join
        //
        if (join_type == JOIN_TYPE_LEFT && !match) {
            // Still needs to pass the filter
            if (wherePredicate == NULL || wherePredicate->eval(&outer_tuple, &null_tuple).isTrue()) {
                joined.setNValues(outer_cols, null_tuple, 0, inner_cols);
                output_table->insertTupleNonVirtual(joined);
            }
        }
    }

    return (true);
}
コード例 #3
0
ファイル: nestloopexecutor.cpp プロジェクト: AllenShi/h-store
bool NestLoopExecutor::p_execute(const NValueArray &params, ReadWriteTracker *tracker) {
    VOLT_DEBUG("executing NestLoop...");

    NestLoopPlanNode* node = dynamic_cast<NestLoopPlanNode*>(abstract_node);
    assert(node);
    assert(node->getInputTables().size() == 2);

    Table* output_table_ptr = node->getOutputTable();
    assert(output_table_ptr);

    // output table must be a temp table
    TempTable* output_table = dynamic_cast<TempTable*>(output_table_ptr);
    assert(output_table);

    Table* outer_table = node->getInputTables()[0];
    assert(outer_table);

    Table* inner_table = node->getInputTables()[1];
    assert(inner_table);

    VOLT_TRACE ("input table left:\n %s", outer_table->debug().c_str());
    VOLT_TRACE ("input table right:\n %s", inner_table->debug().c_str());

    //
    // Join Expression
    //
    AbstractExpression *predicate = node->getPredicate();
    if (predicate) {
        predicate->substitute(params);
        VOLT_TRACE ("predicate: %s", predicate == NULL ?
                    "NULL" : predicate->debug(true).c_str());
    }

    int outer_cols = outer_table->columnCount();
    int inner_cols = inner_table->columnCount();
    TableTuple outer_tuple(node->getInputTables()[0]->schema());
    TableTuple inner_tuple(node->getInputTables()[1]->schema());
    TableTuple &joined = output_table->tempTuple();

    TableIterator iterator0(outer_table);
    while (iterator0.next(outer_tuple)) {

        // populate output table's temp tuple with outer table's values
        // probably have to do this at least once - avoid doing it many
        // times per outer tuple
        for (int col_ctr = 0; col_ctr < outer_cols; col_ctr++) {
            joined.setNValue(col_ctr, outer_tuple.getNValue(col_ctr));
        }

        TableIterator iterator1(inner_table);
        while (iterator1.next(inner_tuple)) {
            if (predicate == NULL || predicate->eval(&outer_tuple, &inner_tuple).isTrue()) {
                // Matched! Complete the joined tuple with the inner column values.
                for (int col_ctr = 0; col_ctr < inner_cols; col_ctr++) {
                    joined.setNValue(col_ctr + outer_cols, inner_tuple.getNValue(col_ctr));
                }
                output_table->insertTupleNonVirtual(joined);
            }
        }
    }

    return (true);
}
コード例 #4
0
ファイル: nestloopexecutor.cpp プロジェクト: AllenShi/h-store
bool NestLoopExecutor::p_init(AbstractPlanNode* abstract_node, const catalog::Database* catalog_db, int* tempTableMemoryInBytes) {
    VOLT_TRACE("init NestLoop Executor");
    assert(tempTableMemoryInBytes);

    NestLoopPlanNode* node = dynamic_cast<NestLoopPlanNode*>(abstract_node);
    assert(node);

    // produce the fully joined schema relying on a later projection
    // to narrow the output later as required.
    assert(node->getInputTables().size() == 2);
    const TupleSchema *first = node->getInputTables()[0]->schema();
    const TupleSchema *second = node->getInputTables()[1]->schema();
    TupleSchema *schema = TupleSchema::createTupleSchema(first, second);

    int combinedColumnCount = first->columnCount() + second->columnCount();
    std::string *columnNames = new std::string[combinedColumnCount];
    std::vector<int> outputColumnGuids;
    int index = 0;

    for (int ctr = 0; ctr < 2; ctr++) {
        assert(node->getInputTables()[ctr]);
        for (int col_ctr = 0, col_cnt = node->getInputTables()[ctr]->columnCount();
             col_ctr < col_cnt;
             col_ctr++, index++)
        {
            outputColumnGuids.
                push_back(node->getChildren()[ctr]->getOutputColumnGuids()[col_ctr]);
            columnNames[index] = node->getInputTables()[ctr]->columnName(col_ctr);
        }
    }

    // Set the mapping of column names to column indexes in output tables
    node->setOutputColumnGuids(outputColumnGuids);

    // create the output table
    node->setOutputTable(
        TableFactory::getTempTable(
            node->getInputTables()[0]->databaseId(), "temp", schema, columnNames, tempTableMemoryInBytes));

    // for each tuple value expression in the predicate, determine
    // which tuple is being represented. Tuple could come from outer
    // table or inner table. Configure the predicate to use the correct
    // eval() tuple parameter. By convention, eval's first parameter
    // will always be the outer table and its second parameter the inner
    const AbstractExpression *predicate = node->getPredicate();
    std::stack<const AbstractExpression*> stack;
    while (predicate != NULL) {
        const AbstractExpression *left = predicate->getLeft();
        const AbstractExpression *right = predicate->getRight();

        if (right != NULL) {
            if (right->getExpressionType() == EXPRESSION_TYPE_VALUE_TUPLE) {
                if (!assignTupleValueIndex(const_cast<AbstractExpression*>(right),
                                           node->getInputTables()[0]->name(),
                                           node->getInputTables()[1]->name())) {
                    delete [] columnNames;
                    return false;
                }
            }
            // remember the right node - must visit its children
            stack.push(right);
        }
        if (left != NULL) {
            if (left->getExpressionType() == EXPRESSION_TYPE_VALUE_TUPLE) {
                if (!assignTupleValueIndex(const_cast<AbstractExpression*>(left),
                                           node->getInputTables()[0]->name(),
                                           node->getInputTables()[1]->name())) {
                    delete [] columnNames;
                    return false;
                }
            }
        }

        predicate = left;
        if (!predicate && !stack.empty()) {
            predicate = stack.top();
            stack.pop();
        }
    }

    delete[] columnNames;
    return true;
}