in phoenix-core-client/src/main/java/org/apache/phoenix/iterate/ExplainTable.java [128:318]
protected void explain(String prefix,
List<String> planSteps,
ExplainPlanAttributesBuilder explainPlanAttributesBuilder,
List<HRegionLocation> regionLocations) {
StringBuilder buf = new StringBuilder(prefix);
ScanRanges scanRanges = context.getScanRanges();
Scan scan = context.getScan();
if (scan.getConsistency() != Consistency.STRONG){
buf.append("TIMELINE-CONSISTENCY ");
}
if (hint.hasHint(Hint.SMALL)) {
buf.append(Hint.SMALL).append(" ");
}
if (OrderBy.REV_ROW_KEY_ORDER_BY.equals(orderBy)) {
buf.append("REVERSE ");
}
String scanTypeDetails;
if (scanRanges.isEverything()) {
scanTypeDetails = "FULL SCAN ";
} else {
scanTypeDetails = explainSkipScan();
}
buf.append(scanTypeDetails);
String tableName = tableRef.getTable().getPhysicalName().getString();
if (tableRef.getTable().getIndexType() == PTable.IndexType.LOCAL) {
String indexName = tableRef.getTable().getName().getString();
if (tableRef.getTable().getViewIndexId() != null
&& indexName.contains(QueryConstants.CHILD_VIEW_INDEX_NAME_SEPARATOR)) {
int lastIndexOf = indexName.lastIndexOf(
QueryConstants.CHILD_VIEW_INDEX_NAME_SEPARATOR);
indexName = indexName.substring(lastIndexOf + 1);
}
tableName = indexName + "(" + tableName + ")";
}
buf.append("OVER ").append(tableName);
if (!scanRanges.isPointLookup()) {
buf.append(appendKeyRanges());
}
planSteps.add(buf.toString());
if (explainPlanAttributesBuilder != null) {
explainPlanAttributesBuilder.setConsistency(scan.getConsistency());
if (hint.hasHint(Hint.SMALL)) {
explainPlanAttributesBuilder.setHint(Hint.SMALL);
}
if (OrderBy.REV_ROW_KEY_ORDER_BY.equals(orderBy)) {
explainPlanAttributesBuilder.setClientSortedBy("REVERSE");
}
explainPlanAttributesBuilder.setExplainScanType(scanTypeDetails);
explainPlanAttributesBuilder.setTableName(tableName);
if (!scanRanges.isPointLookup()) {
explainPlanAttributesBuilder.setKeyRanges(appendKeyRanges());
}
}
if (context.getScan() != null && tableRef.getTable().getRowTimestampColPos() != -1) {
TimeRange range = context.getScan().getTimeRange();
planSteps.add(" ROW TIMESTAMP FILTER [" + range.getMin() + ", " + range.getMax() + ")");
if (explainPlanAttributesBuilder != null) {
explainPlanAttributesBuilder.setScanTimeRangeMin(range.getMin());
explainPlanAttributesBuilder.setScanTimeRangeMax(range.getMax());
}
}
PageFilter pageFilter = null;
FirstKeyOnlyFilter firstKeyOnlyFilter = null;
EmptyColumnOnlyFilter emptyColumnOnlyFilter = null;
BooleanExpressionFilter whereFilter = null;
DistinctPrefixFilter distinctFilter = null;
Iterator<Filter> filterIterator = ScanUtil.getFilterIterator(scan);
if (filterIterator.hasNext()) {
do {
Filter filter = filterIterator.next();
if (filter instanceof FirstKeyOnlyFilter) {
firstKeyOnlyFilter = (FirstKeyOnlyFilter)filter;
} else if (filter instanceof EmptyColumnOnlyFilter) {
emptyColumnOnlyFilter = (EmptyColumnOnlyFilter)filter;
} else if (filter instanceof PageFilter) {
pageFilter = (PageFilter)filter;
} else if (filter instanceof BooleanExpressionFilter) {
whereFilter = (BooleanExpressionFilter)filter;
} else if (filter instanceof DistinctPrefixFilter) {
distinctFilter = (DistinctPrefixFilter)filter;
}
} while (filterIterator.hasNext());
}
Set<PColumn> dataColumns = context.getDataColumns();
if (dataColumns != null && !dataColumns.isEmpty()) {
planSteps.add(" SERVER MERGE " + dataColumns.toString());
if (explainPlanAttributesBuilder != null) {
explainPlanAttributesBuilder.setServerMergeColumns(dataColumns);
}
}
String whereFilterStr = null;
if (whereFilter != null) {
whereFilterStr = whereFilter.toString();
} else {
byte[] expBytes = scan.getAttribute(BaseScannerRegionObserverConstants.INDEX_FILTER_STR);
if (expBytes == null) {
// For older clients
expBytes = scan.getAttribute(BaseScannerRegionObserverConstants.LOCAL_INDEX_FILTER_STR);
}
if (expBytes != null) {
whereFilterStr = Bytes.toString(expBytes);
}
}
if (whereFilterStr != null) {
String serverWhereFilter = "SERVER FILTER BY "
+ (firstKeyOnlyFilter == null ? "" : "FIRST KEY ONLY AND ")
+ (emptyColumnOnlyFilter == null ? "" : "EMPTY COLUMN ONLY AND ")
+ whereFilterStr;
planSteps.add(" " + serverWhereFilter);
if (explainPlanAttributesBuilder != null) {
explainPlanAttributesBuilder.setServerWhereFilter(serverWhereFilter);
}
} else if (firstKeyOnlyFilter != null) {
planSteps.add(" SERVER FILTER BY FIRST KEY ONLY");
if (explainPlanAttributesBuilder != null) {
explainPlanAttributesBuilder.setServerWhereFilter(
"SERVER FILTER BY FIRST KEY ONLY");
}
} else if (emptyColumnOnlyFilter != null) {
planSteps.add(" SERVER FILTER BY EMPTY COLUMN ONLY");
if (explainPlanAttributesBuilder != null) {
explainPlanAttributesBuilder.setServerWhereFilter(
"SERVER FILTER BY EMPTY COLUMN ONLY");
}
}
if (distinctFilter != null) {
String serverDistinctFilter = "SERVER DISTINCT PREFIX FILTER OVER "
+ groupBy.getExpressions().toString();
planSteps.add(" " + serverDistinctFilter);
if (explainPlanAttributesBuilder != null) {
explainPlanAttributesBuilder.setServerDistinctFilter(serverDistinctFilter);
}
}
if (!orderBy.getOrderByExpressions().isEmpty() && groupBy.isEmpty()) { // with GROUP BY, sort happens client-side
String orderByExpressions = "SERVER"
+ (limit == null ? "" : " TOP " + limit + " ROW" + (limit == 1 ? "" : "S"))
+ " SORTED BY " + orderBy.getOrderByExpressions().toString();
planSteps.add(" " + orderByExpressions);
if (explainPlanAttributesBuilder != null) {
if (limit != null) {
explainPlanAttributesBuilder.setServerRowLimit(limit.longValue());
}
explainPlanAttributesBuilder.setServerSortedBy(
orderBy.getOrderByExpressions().toString());
}
} else {
if (offset != null) {
planSteps.add(" SERVER OFFSET " + offset);
}
Long limit = null;
if (pageFilter != null) {
limit = pageFilter.getPageSize();
} else {
byte[] limitBytes = scan.getAttribute(BaseScannerRegionObserverConstants.INDEX_LIMIT);
if (limitBytes != null) {
limit = Bytes.toLong(limitBytes);
}
}
if (limit != null) {
planSteps.add(" SERVER " + limit + " ROW LIMIT");
}
if (explainPlanAttributesBuilder != null) {
explainPlanAttributesBuilder.setServerOffset(offset);
if (pageFilter != null) {
explainPlanAttributesBuilder.setServerRowLimit(
pageFilter.getPageSize());
}
}
}
Integer groupByLimit = null;
byte[] groupByLimitBytes = scan.getAttribute(BaseScannerRegionObserverConstants.GROUP_BY_LIMIT);
if (groupByLimitBytes != null) {
groupByLimit = (Integer) PInteger.INSTANCE.toObject(groupByLimitBytes);
}
getRegionLocations(planSteps, explainPlanAttributesBuilder, regionLocations);
groupBy.explain(planSteps, groupByLimit, explainPlanAttributesBuilder);
if (scan.getAttribute(BaseScannerRegionObserverConstants.SPECIFIC_ARRAY_INDEX) != null) {
planSteps.add(" SERVER ARRAY ELEMENT PROJECTION");
if (explainPlanAttributesBuilder != null) {
explainPlanAttributesBuilder.setServerArrayElementProjection(true);
}
}
if (scan.getAttribute(BaseScannerRegionObserverConstants.JSON_VALUE_FUNCTION) != null
|| scan.getAttribute(BaseScannerRegionObserverConstants.JSON_QUERY_FUNCTION) != null) {
planSteps.add(" SERVER JSON FUNCTION PROJECTION");
}
}