bool ProjectionExecutor::p_execute(const NValueArray &params) {
#ifndef NDEBUG
    ProjectionPlanNode* node = dynamic_cast<ProjectionPlanNode*>(m_abstractNode);
#endif
    assert (node);
    assert (!node->isInline()); // inline projection's execute() should not be
                                // called
    assert (output_table == dynamic_cast<TempTable*>(node->getOutputTable()));
    assert (output_table);
    Table* input_table = m_abstractNode->getInputTable();
    assert (input_table);

    VOLT_TRACE("INPUT TABLE: %s\n", input_table->debug().c_str());

    //
    // Since we have the input params, we need to call substitute to change any
    // nodes in our expression tree to be ready for the projection operations in
    // execute
    //
    assert (m_columnCount == (int)node->getOutputColumnNames().size());
    if (all_tuple_array == NULL && all_param_array == NULL) {
        for (int ctr = m_columnCount - 1; ctr >= 0; --ctr) {
            assert(expression_array[ctr]);
            VOLT_TRACE("predicate[%d]: %s", ctr,
                       expression_array[ctr]->debug(true).c_str());
        }
    }

    //
    // Now loop through all the tuples and push them through our output
    // expression This will generate new tuple values that we will insert into
    // our output table
    //
    TableIterator iterator = input_table->iteratorDeletingAsWeGo();
    assert (tuple.sizeInValues() == input_table->columnCount());
    while (iterator.next(tuple)) {
        //
        // Project (or replace) values from input tuple
        //
        TableTuple &temp_tuple = output_table->tempTuple();
        if (all_tuple_array != NULL) {
            VOLT_TRACE("sweet, all tuples");
            for (int ctr = m_columnCount - 1; ctr >= 0; --ctr) {
                temp_tuple.setNValue(ctr, tuple.getNValue(all_tuple_array[ctr]));
            }
        } else if (all_param_array != NULL) {
            VOLT_TRACE("sweet, all params");
            for (int ctr = m_columnCount - 1; ctr >= 0; --ctr) {
                temp_tuple.setNValue(ctr, params[all_param_array[ctr]]);
            }
        } else {
            for (int ctr = m_columnCount - 1; ctr >= 0; --ctr) {
                temp_tuple.setNValue(ctr, expression_array[ctr]->eval(&tuple, NULL));
            }
        }
        output_table->insertTupleNonVirtual(temp_tuple);

        VOLT_TRACE("OUTPUT TABLE: %s\n", output_table->debug().c_str());
    }

    cleanupInputTempTable(input_table);

    return (true);
}
Example #2
0
/*
 * This function is called straight from AbstractExecutor::execute,
 * which is called from executeExecutors, which is called from the
 * VoltDBEngine::executePlanFragments.  So, this is really the start
 * of execution for this executor.
 *
 * The executor will already have been initialized by p_init.
 */
bool WindowFunctionExecutor::p_execute(const NValueArray& params) {
    VOLT_TRACE("windowFunctionExecutor::p_execute(start)\n");
    // Input table
    Table * input_table = m_abstractNode->getInputTable();
    assert(input_table);
    VOLT_TRACE("WindowFunctionExecutor: input table\n%s", input_table->debug().c_str());
    m_inputSchema = input_table->schema();
    assert(m_inputSchema);

    /*
     * Do this after setting the m_inputSchema.
     */
    initWorkingTupleStorage();
    TableWindow tableWindow(input_table);
    ProgressMonitorProxy pmp(m_engine->getExecutorContext(), this);
    m_pmp = &pmp;

    m_aggregateRow
        = new (m_memoryPool, m_aggTypes.size())
        WindowAggregateRow(m_inputSchema, m_memoryPool);

    initAggInstances();

    VOLT_TRACE("Beginning: %s", tableWindow.debug().c_str());

    TableTuple nextTuple(m_inputSchema);

    /*
     * Force a call p_execute_finish when this is all over.
     */
    EnsureCleanupOnExit finishCleanup(this);
    for (EdgeType etype = START_OF_INPUT,
                  nextEtype = INVALID_EDGE_TYPE;
         etype != END_OF_INPUT;
         etype = nextEtype) {
        // Reset the aggregates if this is the
        // start of a partition group.  The start of
        // input is a special form of this.
        if (etype == START_OF_INPUT || etype == START_OF_PARTITION_GROUP) {
            m_aggregateRow->resetAggs();
        }
        // Find the next edge.  This will
        // give the aggs a crack at each row
        // if they want it.
        nextEtype = findNextEdge(etype, tableWindow);
        // Let the aggs know the results
        // of the lookahead.
        lookaheadNextGroupForAggs(tableWindow);
        // Advance to the end of the current group.
        for (int idx = 0; idx < tableWindow.m_orderByGroupSize; idx += 1) {
            VOLT_TRACE("MiddleEdge: Window = %s", m_tableWindow->debug().c_str());
            tableWindow.m_middleEdge.next(nextTuple);
            m_pmp->countdownProgress();
            m_aggregateRow->recordPassThroughTuple(nextTuple);
            insertOutputTuple();
        }
        endGroupForAggs(tableWindow, etype);
        VOLT_TRACE("FirstEdge: %s", m_tableWindow->debug().c_str());
    }
    VOLT_TRACE("WindowFunctionExecutor: finalizing..");

    cleanupInputTempTable(input_table);
    VOLT_TRACE("WindowFunctionExecutor::p_execute(end)\n");
    return true;
}