bool TableCatalogDelegate::getIndexScheme(catalog::Table &catalogTable,
                                          catalog::Index &catalogIndex,
                                          const TupleSchema *schema,
                                          TableIndexScheme *scheme)
{
    vector<int> index_columns;
    vector<ValueType> column_types;

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

    vector<AbstractExpression*> indexedExpressions = TableIndex::simplyIndexColumns();
    const std::string expressionsAsText = catalogIndex.expressionsjson();
    if (expressionsAsText.length() != 0) {
        ExpressionUtil::loadIndexedExprsFromJson(indexedExpressions, expressionsAsText);
    }

    // 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(catalogIndex.columns().size());
    map<string, catalog::ColumnRef*>::const_iterator colref_iterator;
    for (colref_iterator = catalogIndex.columns().begin();
         colref_iterator != catalogIndex.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(),
                       catalogIndex.name().c_str(),
                       catalogTable.name().c_str());
            return false;
        }
        index_columns[catalog_colref->index()] = catalog_colref->column()->index();
    }

    *scheme = TableIndexScheme(catalogIndex.name(),
                               (TableIndexType)catalogIndex.type(),
                               index_columns,
                               indexedExpressions,
                               catalogIndex.unique(),
                               true, // support counting indexes (wherever supported)
                               expressionsAsText,
                               schema);
    return true;
}
std::string
TableCatalogDelegate::getIndexIdString(const catalog::Index &catalogIndex)
{
    vector<int32_t> columnIndexes(catalogIndex.columns().size());

    // get the list of column indexes in the target table
    // in the order they appear in the index
    map<string, catalog::ColumnRef*>::const_iterator col_iterator;
    for (col_iterator = catalogIndex.columns().begin();
         col_iterator != catalogIndex.columns().end();
         col_iterator++)
    {
        int32_t index = col_iterator->second->index();
        const catalog::Column *catalogColumn = col_iterator->second->column();
        columnIndexes[index] = catalogColumn->index();
    }

    const std::string expressionsAsText = catalogIndex.expressionsjson();

    const std::string predicateAsText = catalogIndex.predicatejson();

    return getIndexIdFromMap((TableIndexType)catalogIndex.type(),
                             true, //catalogIndex.countable(), // always counting for now
                             catalogIndex.unique(),
                             expressionsAsText,
                             columnIndexes,
                             predicateAsText);
}
bool TableCatalogDelegate::getIndexScheme(catalog::Table const& catalogTable,
                                          catalog::Index const& catalogIndex,
                                          TupleSchema const* schema,
                                          TableIndexScheme* scheme) {
    std::vector<int> index_columns;
    std::vector<ValueType> column_types;

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

    auto indexedExpressions = TableIndex::simplyIndexColumns();
    std::string const& expressionsAsText = catalogIndex.expressionsjson();
    if (expressionsAsText.length() != 0) {
        ExpressionUtil::loadIndexedExprsFromJson(indexedExpressions, expressionsAsText);
    }

    // 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(catalogIndex.columns().size());
    std::map<std::string, catalog::ColumnRef*>::const_iterator colrefIterator;
    for (colrefIterator = catalogIndex.columns().begin();
         colrefIterator != catalogIndex.columns().end();
         colrefIterator++) {
        auto catalogColref = colrefIterator->second;
        assert(catalogColref->index() >= 0);
        index_columns[catalogColref->index()] = catalogColref->column()->index();
    }
    // partial index predicate
    std::string const& predicateAsText  = catalogIndex.predicatejson();
    AbstractExpression* predicate = NULL;
    if (!predicateAsText.empty()) {
        predicate = ExpressionUtil::loadExpressionFromJson(predicateAsText);
    }
    *scheme = TableIndexScheme(catalogIndex.name(),
                               (TableIndexType)catalogIndex.type(),
                               index_columns,
                               indexedExpressions,
                               predicate,
                               catalogIndex.unique(),
                               catalogIndex.countable(),
                               expressionsAsText,
                               predicateAsText,
                               schema);
    return true;
}