Пример #1
0
Table* TableCatalogDelegate::constructTableFromCatalog(catalog::Database const& catalogDatabase,
                                                       catalog::Table const& catalogTable,
                                                       bool isXDCR,
                                                       int tableAllocationTargetSize,
                                                       bool forceNoDR) {
    // Create a persistent table for this table in our catalog
    int32_t tableId = catalogTable.relativeIndex();

    // get an array of table column names
    const int numColumns = static_cast<int>(catalogTable.columns().size());
    std::map<std::string, catalog::Column*>::const_iterator colIterator;
    std::vector<std::string> columnNames(numColumns);
    for (colIterator = catalogTable.columns().begin();
         colIterator != catalogTable.columns().end();
         colIterator++) {
        auto catalogColumn = colIterator->second;
        columnNames[catalogColumn->index()] = catalogColumn->name();
    }

    // get the schema for the table
    TupleSchema* schema = createTupleSchema(catalogTable, isXDCR);

    // Indexes
    std::map<std::string, TableIndexScheme> index_map;
    std::map<std::string, catalog::Index*>::const_iterator idxIterator;
    for (idxIterator = catalogTable.indexes().begin();
         idxIterator != catalogTable.indexes().end(); idxIterator++) {
        auto catalogIndex = idxIterator->second;

        TableIndexScheme index_scheme;
        if (getIndexScheme(catalogTable, *catalogIndex, schema, &index_scheme)) {
            index_map[catalogIndex->name()] = index_scheme;
        }
    }

    // Constraints
    std::string pkeyIndexId;
    std::map<std::string, catalog::Constraint*>::const_iterator constraintIterator;
    for (constraintIterator = catalogTable.constraints().begin();
         constraintIterator != catalogTable.constraints().end();
         constraintIterator++) {
        auto catalogConstraint = constraintIterator->second;

        // Constraint Type
        ConstraintType type = (ConstraintType) catalogConstraint->type();
        switch (type) {
        case CONSTRAINT_TYPE_PRIMARY_KEY:
            // Make sure we have an index to use
            assert(catalogConstraint->index());
            // Make sure they didn't declare more than one primary key index
            assert(pkeyIndexId.empty());
            pkeyIndexId = catalogConstraint->index()->name();
            break;
        case CONSTRAINT_TYPE_UNIQUE:
            // Make sure we have an index to use
            // TODO: In the future I would like bring back my Constraint
            //       object so that we can keep track of everything that a
            //       table has...
            assert(catalogConstraint->index());
            break;
        // Unsupported
        case CONSTRAINT_TYPE_CHECK:
        case CONSTRAINT_TYPE_FOREIGN_KEY:
        case CONSTRAINT_TYPE_MAIN:
            VOLT_WARN("Unsupported type '%s' for constraint '%s'",
                      constraintutil::getTypeName(type).c_str(),
                      catalogConstraint->name().c_str());
            break;
        // Unknown
        default:
            VOLT_ERROR("Invalid constraint type '%s' for '%s'",
                       constraintutil::getTypeName(type).c_str(),
                       catalogConstraint->name().c_str());
            assert(false);
            return NULL;
        }
    }

    // Build the index array
    // Please note the index array should follow the order of primary key first,
    // all unique indices afterwards, and all the non-unique indices at the end.
    std::deque<TableIndexScheme> indexes;
    TableIndexScheme pkeyIndex_scheme;
    std::map<std::string, TableIndexScheme>::const_iterator indexIterator;
    for (indexIterator = index_map.begin(); indexIterator != index_map.end();
         indexIterator++) {
        // Exclude the primary key
        if (indexIterator->second.name.compare(pkeyIndexId) == 0) {
            pkeyIndex_scheme = indexIterator->second;
        // Just add it to the list
        }
        else {
            if (indexIterator->second.unique) {
                indexes.push_front(indexIterator->second);
            }
            else {
                indexes.push_back(indexIterator->second);
            }
        }
    }

    // partition column:
    catalog::Column const* partitionColumn = catalogTable.partitioncolumn();
    int partitionColumnIndex = -1;
    if (partitionColumn != NULL) {
        partitionColumnIndex = partitionColumn->index();
    }

    bool exportEnabled = isExportEnabledForTable(catalogDatabase, tableId);
    bool tableIsExportOnly = isTableExportOnly(catalogDatabase, tableId);
    bool drEnabled = !forceNoDR && catalogTable.isDRed();
    bool isReplicated = catalogTable.isreplicated();
    m_materialized = isTableMaterialized(catalogTable);
    std::string const& tableName = catalogTable.name();
    int32_t databaseId = catalogDatabase.relativeIndex();
    SHA1_CTX shaCTX;
    SHA1Init(&shaCTX);
    SHA1Update(&shaCTX, reinterpret_cast<const uint8_t*>(catalogTable.signature().c_str()), (uint32_t )::strlen(catalogTable.signature().c_str()));
    SHA1Final(reinterpret_cast<unsigned char*>(m_signatureHash), &shaCTX);
    // Persistent table will use default size (2MB) if tableAllocationTargetSize is zero.
    if (m_materialized) {
      catalog::MaterializedViewInfo* mvInfo = catalogTable.materializer()->views().get(catalogTable.name());
      if (mvInfo && mvInfo->groupbycols().size() == 0) {
        // ENG-8490: If the materialized view came with no group by, set table block size to 64KB
        // to achieve better space efficiency.
        // FYI: maximum column count = 1024, largest fixed length data type is short varchars (64 bytes)
        tableAllocationTargetSize = 1024 * 64;
      }
    }
    VOLT_DEBUG("Creating %s %s as %s", m_materialized?"VIEW":"TABLE", tableName.c_str(), isReplicated?"REPLICATED":"PARTITIONED");
    Table* table = TableFactory::getPersistentTable(databaseId, tableName,
                                                    schema, columnNames, m_signatureHash,
                                                    m_materialized,
                                                    partitionColumnIndex, exportEnabled,
                                                    tableIsExportOnly,
                                                    tableAllocationTargetSize,
                                                    catalogTable.tuplelimit(),
                                                    m_compactionThreshold,
                                                    drEnabled,
                                                    isReplicated);
    PersistentTable* persistentTable = dynamic_cast<PersistentTable*>(table);
    if ( ! persistentTable) {
        assert(pkeyIndexId.empty());
        assert(indexes.empty());
        return table;
    }

    // add a pkey index if one exists
    if ( ! pkeyIndexId.empty()) {
        TableIndex* pkeyIndex = TableIndexFactory::getInstance(pkeyIndex_scheme);
        assert(pkeyIndex);
        persistentTable->addIndex(pkeyIndex);
        persistentTable->setPrimaryKeyIndex(pkeyIndex);
    }

    // add other indexes
    BOOST_FOREACH(TableIndexScheme& scheme, indexes) {
        TableIndex* index = TableIndexFactory::getInstance(scheme);
        assert(index);
        persistentTable->addIndex(index);
    }
Пример #2
0
int
TableCatalogDelegate::init(ExecutorContext *executorContext,
                           catalog::Database &catalogDatabase,
                           catalog::Table &catalogTable)
{
    // Create a persistent table for this table in our catalog
    int32_t table_id = catalogTable.relativeIndex();

    // Columns:
    // Column is stored as map<String, Column*> in Catalog. We have to
    // sort it by Column index to preserve column order.
    const int numColumns = static_cast<int>(catalogTable.columns().size());
    vector<ValueType> columnTypes(numColumns);
    vector<int32_t> columnLengths(numColumns);
    vector<bool> columnAllowNull(numColumns);
    // GWW
    vector<bool> columnisEscrow(numColumns);

    map<string, catalog::Column*>::const_iterator col_iterator;
    string *columnNames = new string[numColumns];
    for (col_iterator = catalogTable.columns().begin();
         col_iterator != catalogTable.columns().end(); col_iterator++) {
        const catalog::Column *catalog_column = col_iterator->second;
        const int columnIndex = catalog_column->index();
        const ValueType type = static_cast<ValueType>(catalog_column->type());
        columnTypes[columnIndex] = type;
        const int32_t size = static_cast<int32_t>(catalog_column->size());
        //Strings length is provided, other lengths are derived from type
        bool varlength = (type == VALUE_TYPE_VARCHAR) || (type == VALUE_TYPE_VARBINARY);
        const int32_t length = varlength ? size : static_cast<int32_t>(NValue::getTupleStorageSize(type));
        columnLengths[columnIndex] = length;
        columnAllowNull[columnIndex] = catalog_column->nullable();
        //GWW
        columnisEscrow[columnIndex] = catalog_column->escrowColumn();
        columnNames[catalog_column->index()] = catalog_column->name();
    }

    /*
    TupleSchema *schema = TupleSchema::createTupleSchema(columnTypes,
                                                         columnLengths,
                                                         columnAllowNull, true);

    */

    TupleSchema *schema = TupleSchema::createTupleSchema(columnTypes,
                                                         columnLengths,
                                                         columnAllowNull,
                                                         columnisEscrow, true);


    // Indexes
    map<string, TableIndexScheme> index_map;
    map<string, catalog::Index*>::const_iterator idx_iterator;
    for (idx_iterator = catalogTable.indexes().begin();
         idx_iterator != catalogTable.indexes().end(); idx_iterator++) {
        catalog::Index *catalog_index = idx_iterator->second;
        vector<int> index_columns;
        vector<ValueType> column_types;

        // The catalog::Index object now has a list of columns that are to be
        // used
        if (catalog_index->columns().size() == (size_t)0) {
            VOLT_ERROR("Index '%s' in table '%s' does not declare any columns"
                       " to use",
                       catalog_index->name().c_str(),
                       catalogTable.name().c_str());
            delete [] columnNames;
            return false;
        }

        // Since the columns are not going to come back in the proper order from
        // the catalogs, we'll use the index attribute to make sure we put them
        // in the right order
        index_columns.resize(catalog_index->columns().size());
        column_types.resize(catalog_index->columns().size());
        bool isIntsOnly = true;
        map<string, catalog::ColumnRef*>::const_iterator colref_iterator;
        for (colref_iterator = catalog_index->columns().begin();
             colref_iterator != catalog_index->columns().end();
             colref_iterator++) {
            catalog::ColumnRef *catalog_colref = colref_iterator->second;
            if (catalog_colref->index() < 0) {
                VOLT_ERROR("Invalid column '%d' for index '%s' in table '%s'",
                           catalog_colref->index(),
                           catalog_index->name().c_str(),
                           catalogTable.name().c_str());
                delete [] columnNames;
                return false;
            }
            // check if the column does not have an int type
            if ((catalog_colref->column()->type() != VALUE_TYPE_TINYINT) &&
                (catalog_colref->column()->type() != VALUE_TYPE_SMALLINT) &&
                (catalog_colref->column()->type() != VALUE_TYPE_INTEGER) &&
                (catalog_colref->column()->type() != VALUE_TYPE_BIGINT)) {
                isIntsOnly = false;
            }
            index_columns[catalog_colref->index()] = catalog_colref->column()->index();
            column_types[catalog_colref->index()] = (ValueType) catalog_colref->column()->type();
        }

        TableIndexScheme index_scheme(catalog_index->name(),
                                      (TableIndexType)catalog_index->type(),
                                      index_columns,
                                      column_types,
                                      catalog_index->unique(),
                                      isIntsOnly,
                                      schema);
        index_map[catalog_index->name()] = index_scheme;
    }

    // Constraints
    string pkey_index_id;
    map<string, catalog::Constraint*>::const_iterator constraint_iterator;
    for (constraint_iterator = catalogTable.constraints().begin();
         constraint_iterator != catalogTable.constraints().end();
         constraint_iterator++) {
        catalog::Constraint *catalog_constraint = constraint_iterator->second;

        // Constraint Type
        ConstraintType type = (ConstraintType)catalog_constraint->type();
        switch (type) {
            case CONSTRAINT_TYPE_PRIMARY_KEY:
                // Make sure we have an index to use
                if (catalog_constraint->index() == NULL) {
                    VOLT_ERROR("The '%s' constraint '%s' on table '%s' does"
                               " not specify an index",
                               constraintutil::getTypeName(type).c_str(),
                               catalog_constraint->name().c_str(),
                               catalogTable.name().c_str());
                    delete [] columnNames;
                    return false;
                }
                // Make sure they didn't declare more than one primary key index
                else if (pkey_index_id.size() > 0) {
                    VOLT_ERROR("Trying to declare a primary key on table '%s'"
                               "using index '%s' but '%s' was already set as"
                               " the primary key",
                               catalogTable.name().c_str(),
                               catalog_constraint->index()->name().c_str(),
                               pkey_index_id.c_str());
                    delete [] columnNames;
                    return false;
                }
                pkey_index_id = catalog_constraint->index()->name();
                break;
            case CONSTRAINT_TYPE_UNIQUE:
                // Make sure we have an index to use
                // TODO: In the future I would like bring back my Constraint
                //       object so that we can keep track of everything that a
                //       table has...
                if (catalog_constraint->index() == NULL) {
                    VOLT_ERROR("The '%s' constraint '%s' on table '%s' does"
                               " not specify an index",
                               constraintutil::getTypeName(type).c_str(),
                               catalog_constraint->name().c_str(),
                               catalogTable.name().c_str());
                    delete [] columnNames;
                    return false;
                }
                break;
            // Unsupported
            case CONSTRAINT_TYPE_CHECK:
            case CONSTRAINT_TYPE_FOREIGN_KEY:
            case CONSTRAINT_TYPE_MAIN:
                VOLT_WARN("Unsupported type '%s' for constraint '%s'",
                          constraintutil::getTypeName(type).c_str(),
                          catalog_constraint->name().c_str());
                break;
            // Unknown
            default:
                VOLT_ERROR("Invalid constraint type '%s' for '%s'",
                           constraintutil::getTypeName(type).c_str(),
                           catalog_constraint->name().c_str());
                delete [] columnNames;
                return false;
        }
    }

    // Build the index array
    vector<TableIndexScheme> indexes;
    TableIndexScheme pkey_index;
    map<string, TableIndexScheme>::const_iterator index_iterator;
    for (index_iterator = index_map.begin(); index_iterator != index_map.end();
         index_iterator++) {
        // Exclude the primary key
        if (index_iterator->first.compare(pkey_index_id) == 0) {
            pkey_index = index_iterator->second;
        // Just add it to the list
        } else {
            indexes.push_back(index_iterator->second);
        }
    }

    // partition column:
    const catalog::Column* partitionColumn = catalogTable.partitioncolumn();
    int partitionColumnIndex = -1;
    if (partitionColumn != NULL) {
        partitionColumnIndex = partitionColumn->index();
    }

    if (pkey_index_id.size() == 0) {
        int32_t databaseId = catalogDatabase.relativeIndex();
        m_table = TableFactory::getPersistentTable(databaseId, executorContext,
                                                 catalogTable.name(), schema, columnNames,
                                                 indexes, partitionColumnIndex,
                                                 isExportEnabledForTable(catalogDatabase, table_id),
                                                 isTableExportOnly(catalogDatabase, table_id));
    } else {
        int32_t databaseId = catalogDatabase.relativeIndex();
        m_table = TableFactory::getPersistentTable(databaseId, executorContext,
                                                 catalogTable.name(), schema, columnNames,
                                                 pkey_index, indexes, partitionColumnIndex,
                                                 isExportEnabledForTable(catalogDatabase, table_id),
                                                 isTableExportOnly(catalogDatabase, table_id));
    }
    delete[] columnNames;

    m_exportEnabled = isExportEnabledForTable(catalogDatabase, table_id);
    m_table->incrementRefcount();
    return 0;
}