boolean retry = true;
Short viewIndexId = null;
boolean allocateViewIndexId = false;
while (true) {
try {
ColumnResolver resolver = FromCompiler.getResolver(statement, connection);
tableRef = resolver.getTables().get(0);
PTable dataTable = tableRef.getTable();
boolean isTenantConnection = connection.getTenantId() != null;
if (isTenantConnection) {
if (dataTable.getType() != PTableType.VIEW) {
throw new SQLFeatureNotSupportedException("An index may only be created for a VIEW through a tenant-specific connection");
}
}
int hbaseVersion = connection.getQueryServices().getLowestClusterHBaseVersion();
if (!dataTable.isImmutableRows()) {
if (hbaseVersion < PhoenixDatabaseMetaData.MUTABLE_SI_VERSION_THRESHOLD) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_MUTABLE_INDEXES).setTableName(indexTableName.getTableName()).build().buildException();
}
if (connection.getQueryServices().hasInvalidIndexConfiguration()) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.INVALID_MUTABLE_INDEX_CONFIG).setTableName(indexTableName.getTableName()).build().buildException();
}
}
int posOffset = 0;
Set<PColumn> unusedPkColumns;
if (dataTable.getBucketNum() != null) { // Ignore SALT column
unusedPkColumns = new LinkedHashSet<PColumn>(dataTable.getPKColumns().subList(1, dataTable.getPKColumns().size()));
posOffset++;
} else {
unusedPkColumns = new LinkedHashSet<PColumn>(dataTable.getPKColumns());
}
List<Pair<ColumnName, SortOrder>> allPkColumns = Lists.newArrayListWithExpectedSize(unusedPkColumns.size());
List<ColumnDef> columnDefs = Lists.newArrayListWithExpectedSize(includedColumns.size() + indexedPkColumns.size());
if (dataTable.isMultiTenant()) {
// Add tenant ID column as first column in index
PColumn col = dataTable.getPKColumns().get(posOffset);
unusedPkColumns.remove(col);
PDataType dataType = IndexUtil.getIndexColumnDataType(col);
ColumnName colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
allPkColumns.add(new Pair<ColumnName, SortOrder>(colName, col.getSortOrder()));
columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), col.isNullable(), col.getMaxLength(), col.getScale(), false, SortOrder.getDefault()));
}
if (dataTable.getType() == PTableType.VIEW && dataTable.getViewType() != ViewType.MAPPED) {
allocateViewIndexId = true;
// Next add index ID column
PDataType dataType = MetaDataUtil.getViewIndexIdDataType();
ColumnName colName = ColumnName.caseSensitiveColumnName(MetaDataUtil.getViewIndexIdColumnName());
allPkColumns.add(new Pair<ColumnName, SortOrder>(colName, SortOrder.getDefault()));
columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), false, null, null, false, SortOrder.getDefault()));
}
// First columns are the indexed ones
for (Pair<ColumnName, SortOrder> pair : indexedPkColumns) {
ColumnName colName = pair.getFirst();
PColumn col = resolver.resolveColumn(null, colName.getFamilyName(), colName.getColumnName()).getColumn();
unusedPkColumns.remove(col);
// Ignore view constants for updatable views as we don't need these in the index
if (col.getViewConstant() == null) {
PDataType dataType = IndexUtil.getIndexColumnDataType(col);
colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
allPkColumns.add(new Pair<ColumnName, SortOrder>(colName, pair.getSecond()));
columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), col.isNullable(), col.getMaxLength(), col.getScale(), false, SortOrder.getDefault()));
}
}
// Next all the PK columns from the data table that aren't indexed
if (!unusedPkColumns.isEmpty()) {
for (PColumn col : unusedPkColumns) {
// Don't add columns with constant values from updatable views, as
// we don't need these in the index
if (col.getViewConstant() == null) {
ColumnName colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
allPkColumns.add(new Pair<ColumnName, SortOrder>(colName, col.getSortOrder()));
PDataType dataType = IndexUtil.getIndexColumnDataType(col);
columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), col.isNullable(), col.getMaxLength(), col.getScale(), false, col.getSortOrder()));
}
}
}
pk = FACTORY.primaryKey(null, allPkColumns);
// Last all the included columns (minus any PK columns)
for (ColumnName colName : includedColumns) {
PColumn col = resolver.resolveColumn(null, colName.getFamilyName(), colName.getColumnName()).getColumn();
if (SchemaUtil.isPKColumn(col)) {
if (!unusedPkColumns.contains(col)) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.COLUMN_EXIST_IN_DEF).build().buildException();
}
} else {