/**
 * Set up a multi-column temp output table for those executors that require one.
 * Called from p_init.
 */
void AbstractExecutor::setTempOutputTable(const ExecutorVector& executorVector,
                                          const string tempTableName) {
    TupleSchema* schema = m_abstractNode->generateTupleSchema();
    int column_count = schema->columnCount();
    std::vector<std::string> column_names(column_count);
    assert(column_count >= 1);
    const std::vector<SchemaColumn*>& outputSchema = m_abstractNode->getOutputSchema();

    for (int ctr = 0; ctr < column_count; ctr++) {
        column_names[ctr] = outputSchema[ctr]->getColumnName();
    }

    if (executorVector.isLargeQuery()) {
        m_tmpOutputTable = TableFactory::buildLargeTempTable(tempTableName,
                                                             schema,
                                                             column_names);
    }
    else {
        m_tmpOutputTable = TableFactory::buildTempTable(tempTableName,
                                                        schema,
                                                        column_names,
                                                        executorVector.limits());
    }

    m_abstractNode->setOutputTable(m_tmpOutputTable);
}
Beispiel #2
0
bool DeleteExecutor::p_init(AbstractPlanNode *abstract_node,
                            const ExecutorVector& executorVector)
{
    VOLT_TRACE("init Delete Executor");

    m_node = dynamic_cast<DeletePlanNode*>(abstract_node);
    assert(m_node);
    assert(m_node->getTargetTable());

    setDMLCountOutputTable(executorVector.limits());

    m_truncate = m_node->getTruncate();
    if (m_truncate) {
        assert(m_node->getInputTableCount() == 0);
        return true;
    }

    assert(m_node->getInputTableCount() == 1);
    m_inputTable = dynamic_cast<AbstractTempTable*>(m_node->getInputTable()); //input table should be temptable
    assert(m_inputTable);

    m_inputTuple = TableTuple(m_inputTable->schema());
    return true;
}
Beispiel #3
0
bool InsertExecutor::p_init(AbstractPlanNode* abstractNode,
                            const ExecutorVector& executorVector)
{
    VOLT_TRACE("init Insert Executor");

    m_node = dynamic_cast<InsertPlanNode*>(abstractNode);
    assert(m_node);
    assert(m_node->getTargetTable());
    assert(m_node->getInputTableCount() == (m_node->isInline() ? 0 : 1));

    Table* targetTable = m_node->getTargetTable();
    m_isUpsert = m_node->isUpsert();

    //
    // The insert node's input schema is fixed.  But
    // if this is an inline node we don't set it here.
    // We let the parent node set it in p_execute_init.
    //
    // Also, we don't want to set the input table for inline
    // insert nodes.
    //
    if ( ! m_node->isInline()) {
        setDMLCountOutputTable(executorVector.limits());
        m_inputTable = dynamic_cast<AbstractTempTable*>(m_node->getInputTable()); //input table should be temptable
        assert(m_inputTable);
    } else {
        m_inputTable = NULL;
    }

    // Target table can be StreamedTable or PersistentTable and must not be NULL
    PersistentTable *persistentTarget = dynamic_cast<PersistentTable*>(targetTable);
    m_partitionColumn = -1;
    StreamedTable *streamTarget = dynamic_cast<StreamedTable*>(targetTable);
    m_hasStreamView = false;
    if (streamTarget != NULL) {
        m_isStreamed = true;
        //See if we have any views.
        m_hasStreamView = streamTarget->hasViews();
        m_partitionColumn = streamTarget->partitionColumn();
    }
    if (m_isUpsert) {
        VOLT_TRACE("init Upsert Executor actually");
        assert( ! m_node->isInline() );
        if (m_isStreamed) {
            VOLT_ERROR("UPSERT is not supported for Stream table %s", targetTable->name().c_str());
        }
        // look up the tuple whether it exists already
        if (persistentTarget->primaryKeyIndex() == NULL) {
            VOLT_ERROR("No primary keys were found in our target table '%s'",
                    targetTable->name().c_str());
        }
    }

    if (persistentTarget) {
        m_partitionColumn = persistentTarget->partitionColumn();
        m_replicatedTableOperation = persistentTarget->isCatalogTableReplicated();
    }

    m_multiPartition = m_node->isMultiPartition();

    m_sourceIsPartitioned = m_node->sourceIsPartitioned();

    // allocate memory for template tuple, set defaults for all columns
    m_templateTupleStorage.init(targetTable->schema());


    TableTuple tuple = m_templateTupleStorage.tuple();

    std::set<int> fieldsExplicitlySet(m_node->getFieldMap().begin(), m_node->getFieldMap().end());
    // These default values are used for an INSERT including the INSERT sub-case of an UPSERT.
    // The defaults are purposely ignored in favor of existing column values
    // for the UPDATE subcase of an UPSERT.
    m_node->initTupleWithDefaultValues(m_engine,
                                       &m_memoryPool,
                                       fieldsExplicitlySet,
                                       tuple,
                                       m_nowFields);
    m_hasPurgeFragment = persistentTarget ? persistentTarget->hasPurgeFragment() : false;

    return true;
}
Beispiel #4
0
bool UnionExecutor::p_init(AbstractPlanNode* abstract_node,
                           const ExecutorVector& executorVector)
{
    VOLT_TRACE("init Union Executor");
    assert(! executorVector.isLargeQuery());

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

    //
    // First check to make sure they have the same number of columns
    //
    assert(node->getInputTableCount() > 0);

    Table* input_table_0 = node->getInputTable(0);
    const TupleSchema *table_0_schema = input_table_0->schema();

    for (int table_ctr = 1, table_cnt = (int)node->getInputTableCount();
         table_ctr < table_cnt;
         ++table_ctr) {
        Table* input_table_n = node->getInputTable(table_ctr);
        if (input_table_0->columnCount() != input_table_n->columnCount()) {
            VOLT_ERROR("Table '%s' has %d columns, but table '%s' has %d"
                       " columns",
                       input_table_0->name().c_str(),
                       input_table_0->columnCount(),
                       input_table_n->name().c_str(),
                       input_table_n->columnCount());
            return false;
        }

        //
        // Then check that they have the same types
        //

        // iterate over all columns in the first table
        for (int col_ctr = 0, col_cnt = table_0_schema->columnCount();
             col_ctr < col_cnt;
             col_ctr++) {
            // get the type for the current column
            ValueType type_0 = table_0_schema->columnType(col_ctr);

            const TupleSchema *table_n_schema = input_table_n->schema();
            ValueType type_n = table_n_schema->columnType(col_ctr);
            if (type_0 != type_n) {
                VOLT_ERROR("Table '%s' has value type '%s' for column '%d',"
                           " table '%s' has value type '%s' for column '%d'",
                           input_table_0->name().c_str(), getTypeName(type_0).c_str(), col_ctr,
                           input_table_n->name().c_str(), getTypeName(type_n).c_str(), col_ctr);
                return false;
            }
        }
    }
    //
    // Create our output table that will hold all the tuples that we are appending into.
    // Since we're are assuming that all of the tables have the same number of columns with
    // the same format. Therefore, we will just grab the first table in the list
    //
    node->setOutputTable(TableFactory::buildCopiedTempTable(node->getInputTable(0)->name(),
                                                            node->getInputTable(0),
                                                            executorVector));

    m_setOperator.reset(detail::SetOperator::getSetOperator(node));
    return true;
}