protected void explain()

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");
        }
    }