public MutationPlan compile(DeleteStatement delete) throws SQLException {
final PhoenixConnection connection = statement.getConnection();
final boolean isAutoCommit = connection.getAutoCommit();
final boolean hasLimit = delete.getLimit() != null;
final ConnectionQueryServices services = connection.getQueryServices();
QueryPlan planToBe = null;
NamedTableNode tableNode = delete.getTable();
String tableName = tableNode.getName().getTableName();
String schemaName = tableNode.getName().getSchemaName();
boolean retryOnce = !isAutoCommit;
TableRef tableRefToBe;
boolean noQueryReqd = false;
boolean runOnServer = false;
SelectStatement select = null;
DeletingParallelIteratorFactory parallelIteratorFactory = null;
while (true) {
try {
ColumnResolver resolver = FromCompiler.getResolverForMutation(delete, connection);
tableRefToBe = resolver.getTables().get(0);
PTable table = tableRefToBe.getTable();
if (table.getType() == PTableType.VIEW && table.getViewType().isReadOnly()) {
throw new ReadOnlyTableException(table.getSchemaName().getString(),table.getTableName().getString());
}
noQueryReqd = !hasLimit && !hasImmutableIndex(tableRefToBe);
runOnServer = isAutoCommit && noQueryReqd;
HintNode hint = delete.getHint();
if (runOnServer && !delete.getHint().hasHint(Hint.USE_INDEX_OVER_DATA_TABLE)) {
hint = HintNode.create(hint, Hint.USE_DATA_OVER_INDEX_TABLE);
}
List<AliasedNode> aliasedNodes = Lists.newArrayListWithExpectedSize(table.getPKColumns().size());
boolean isSalted = table.getBucketNum() != null;
boolean isMultiTenant = connection.getTenantId() != null && table.isMultiTenant();
boolean isSharedViewIndex = table.getViewIndexId() != null;
for (int i = (isSalted ? 1 : 0) + (isMultiTenant ? 1 : 0) + (isSharedViewIndex ? 1 : 0); i < table.getPKColumns().size(); i++) {
PColumn column = table.getPKColumns().get(i);
aliasedNodes.add(FACTORY.aliasedNode(null, FACTORY.column(null, '"' + column.getName().getString() + '"', null)));
}
select = FACTORY.select(
Collections.singletonList(delete.getTable()),
hint, false, aliasedNodes, delete.getWhere(),
Collections.<ParseNode>emptyList(), null,
delete.getOrderBy(), delete.getLimit(),
delete.getBindCount(), false, false);
select = StatementNormalizer.normalize(select, resolver);
parallelIteratorFactory = hasLimit ? null : new DeletingParallelIteratorFactory(connection, tableRefToBe);
planToBe = new QueryOptimizer(services).optimize(statement, select, resolver, Collections.<PColumn>emptyList(), parallelIteratorFactory);
} catch (MetaDataEntityNotFoundException e) {
// Catch column/column family not found exception, as our meta data may
// be out of sync. Update the cache once and retry if we were out of sync.
// Otherwise throw, as we'll just get the same error next time.
if (retryOnce) {
retryOnce = false;
MetaDataMutationResult result = new MetaDataClient(connection).updateCache(schemaName, tableName);
if (result.wasUpdated()) {
continue;
}
}
throw e;
}
break;
}
final TableRef tableRef = tableRefToBe;
final QueryPlan plan = planToBe;
if (!plan.getTableRef().equals(tableRef)) {
runOnServer = false;
noQueryReqd = false;
}
final int maxSize = services.getProps().getInt(QueryServices.MAX_MUTATION_SIZE_ATTRIB,QueryServicesOptions.DEFAULT_MAX_MUTATION_SIZE);
if (hasImmutableIndexWithKeyValueColumns(tableRef)) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_DELETE_IF_IMMUTABLE_INDEX).setSchemaName(tableRef.getTable().getSchemaName().getString())
.setTableName(tableRef.getTable().getTableName().getString()).build().buildException();
}