You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by st...@apache.org on 2020/12/07 07:15:07 UTC
[phoenix] branch 4.x updated: PHOENIX-5728 : ExplainPlan with plan
as attributes object
This is an automated email from the ASF dual-hosted git repository.
stoty pushed a commit to branch 4.x
in repository https://gitbox.apache.org/repos/asf/phoenix.git
The following commit(s) were added to refs/heads/4.x by this push:
new e281ec6 PHOENIX-5728 : ExplainPlan with plan as attributes object
e281ec6 is described below
commit e281ec67e49b1dc8b924a7faa5f6fc8529bce1b3
Author: Viraj Jasani <vj...@apache.org>
AuthorDate: Mon Nov 30 23:02:12 2020 +0530
PHOENIX-5728 : ExplainPlan with plan as attributes object
---
.../apache/phoenix/iterate/MockResultIterator.java | 7 +
.../phoenix/schema/stats/BaseStatsCollectorIT.java | 129 +++--
.../org/apache/phoenix/compile/DeleteCompiler.java | 25 +-
.../org/apache/phoenix/compile/ExplainPlan.java | 19 +-
.../phoenix/compile/ExplainPlanAttributes.java | 598 +++++++++++++++++++++
.../apache/phoenix/compile/GroupByCompiler.java | 51 +-
.../apache/phoenix/compile/ListJarsQueryPlan.java | 7 +
.../compile/MutatingParallelIteratorFactory.java | 7 +
.../org/apache/phoenix/compile/TraceQueryPlan.java | 7 +
.../org/apache/phoenix/compile/UpsertCompiler.java | 28 +-
.../org/apache/phoenix/execute/BaseQueryPlan.java | 18 +-
.../phoenix/execute/ClientAggregatePlan.java | 34 +-
.../org/apache/phoenix/execute/ClientScanPlan.java | 23 +-
.../org/apache/phoenix/execute/CorrelatePlan.java | 37 +-
.../org/apache/phoenix/execute/HashJoinPlan.java | 1 +
.../execute/LiteralResultIterationPlan.java | 9 +-
.../apache/phoenix/execute/SortMergeJoinPlan.java | 44 +-
.../phoenix/execute/TupleProjectionPlan.java | 14 +-
.../java/org/apache/phoenix/execute/UnionPlan.java | 12 +-
.../apache/phoenix/execute/UnnestArrayPlan.java | 13 +-
.../BaseGroupedAggregatingResultIterator.java | 7 +
.../apache/phoenix/iterate/BaseResultIterator.java | 7 +
.../phoenix/iterate/BaseResultIterators.java | 67 ++-
.../phoenix/iterate/ChunkedResultIterator.java | 14 +
.../ClientHashAggregatingResultIterator.java | 8 +
.../phoenix/iterate/ConcatResultIterator.java | 10 +
.../phoenix/iterate/CursorResultIterator.java | 10 +
.../phoenix/iterate/DelegateResultIterator.java | 8 +
.../iterate/DistinctAggregatingResultIterator.java | 11 +
.../org/apache/phoenix/iterate/ExplainTable.java | 91 +++-
.../iterate/FilterAggregatingResultIterator.java | 20 +-
.../phoenix/iterate/FilterResultIterator.java | 20 +-
.../phoenix/iterate/LimitingResultIterator.java | 22 +-
.../phoenix/iterate/LookAheadResultIterator.java | 8 +
.../MaterializedComparableResultIterator.java | 8 +
.../iterate/MaterializedResultIterator.java | 7 +
.../iterate/MergeSortRowKeyResultIterator.java | 20 +-
.../iterate/MergeSortTopNResultIterator.java | 30 +-
.../phoenix/iterate/OffsetResultIterator.java | 10 +
.../phoenix/iterate/OrderedResultIterator.java | 20 +
.../phoenix/iterate/PeekingResultIterator.java | 7 +
.../org/apache/phoenix/iterate/ResultIterator.java | 24 +
.../apache/phoenix/iterate/ResultIterators.java | 20 +
.../phoenix/iterate/RoundRobinResultIterator.java | 16 +
.../RowKeyOrderedAggregateResultIterator.java | 10 +
.../phoenix/iterate/ScanningResultIterator.java | 7 +
.../phoenix/iterate/SequenceResultIterator.java | 22 +-
.../apache/phoenix/iterate/SerialIterators.java | 7 +
.../phoenix/iterate/SpoolingResultIterator.java | 17 +
.../phoenix/iterate/TableResultIterator.java | 8 +
.../iterate/TableSnapshotResultIterator.java | 15 +-
.../phoenix/iterate/UnionResultIterators.java | 30 +-
.../phoenix/iterate/ConcatResultIteratorTest.java | 8 +
.../iterate/MaterializedResultIterators.java | 7 +
.../iterate/MergeSortResultIteratorTest.java | 17 +
55 files changed, 1552 insertions(+), 144 deletions(-)
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/iterate/MockResultIterator.java b/phoenix-core/src/it/java/org/apache/phoenix/iterate/MockResultIterator.java
index e842317..5b5b643 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/iterate/MockResultIterator.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/iterate/MockResultIterator.java
@@ -28,6 +28,8 @@ import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.execute.TupleProjector;
import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.tuple.ResultTuple;
@@ -56,6 +58,11 @@ public class MockResultIterator implements PeekingResultIterator {
public void explain(List<String> planSteps) {}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
+ @Override
public void close() throws SQLException {}
@Override
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/schema/stats/BaseStatsCollectorIT.java b/phoenix-core/src/it/java/org/apache/phoenix/schema/stats/BaseStatsCollectorIT.java
index 39c68e5..97cfa8f 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/schema/stats/BaseStatsCollectorIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/schema/stats/BaseStatsCollectorIT.java
@@ -26,6 +26,7 @@ import static org.apache.phoenix.util.TestUtil.getAllSplits;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -46,6 +47,9 @@ import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.TableName;
+import org.apache.phoenix.compile.ExplainPlan;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.jdbc.PhoenixPreparedStatement;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
@@ -252,12 +256,16 @@ public abstract class BaseStatsCollectorIT extends BaseUniqueNamesOwnClusterIT {
conn.createStatement().execute(
"CREATE TABLE " + fullTableName +" ( k CHAR(1) PRIMARY KEY )" + tableDDLOptions);
collectStatistics(conn, fullTableName);
- ResultSet rs = conn.createStatement().executeQuery("EXPLAIN SELECT * FROM " + fullTableName);
- String explainPlan = QueryUtil.getExplainPlan(rs);
- assertEquals(
- "CLIENT 1-CHUNK 0 ROWS 20 BYTES PARALLEL 1-WAY FULL SCAN OVER " + physicalTableName + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- explainPlan);
+ ExplainPlan plan = conn.prepareStatement("SELECT * FROM " + fullTableName)
+ .unwrap(PhoenixPreparedStatement.class).optimizeQuery().getExplainPlan();
+ ExplainPlanAttributes planAttributes = plan.getPlanStepsAsAttributes();
+ assertEquals(1, (int) planAttributes.getSplitsChunk());
+ assertEquals(0, (long) planAttributes.getEstimatedRows());
+ assertEquals(20, (long) planAttributes.getEstimatedSizeInBytes());
+ assertEquals("PARALLEL 1-WAY", planAttributes.getIteratorTypeAndScanSize());
+ assertEquals("FULL SCAN ", planAttributes.getExplainScanType());
+ assertEquals(physicalTableName, planAttributes.getTableName());
+ assertEquals("SERVER FILTER BY FIRST KEY ONLY", planAttributes.getServerWhereFilter());
conn.close();
}
@@ -270,30 +278,56 @@ public abstract class BaseStatsCollectorIT extends BaseUniqueNamesOwnClusterIT {
conn.createStatement().execute("UPSERT INTO " + fullTableName + "(k,v1) VALUES('a','123456789')");
collectStatistics(conn, fullTableName);
- ResultSet rs;
- String explainPlan;
- rs = conn.createStatement().executeQuery("EXPLAIN SELECT v2 FROM " + fullTableName + " WHERE v2='foo'");
- explainPlan = QueryUtil.getExplainPlan(rs);
- // if we are using the ONE_CELL_PER_COLUMN_FAMILY storage scheme, we will have the single kv even though there are no values for col family v2
- String stats = columnEncoded && !mutable ? "4-CHUNK 1 ROWS 38 BYTES" : "3-CHUNK 0 ROWS 20 BYTES";
- assertEquals(
- "CLIENT " + stats + " PARALLEL 3-WAY FULL SCAN OVER " + physicalTableName + "\n" +
- " SERVER FILTER BY B.V2 = 'foo'\n" +
- "CLIENT MERGE SORT",
- explainPlan);
- rs = conn.createStatement().executeQuery("EXPLAIN SELECT * FROM " + fullTableName);
- explainPlan = QueryUtil.getExplainPlan(rs);
- assertEquals(
- "CLIENT 4-CHUNK 1 ROWS " + (columnEncoded ? "28" : TransactionFactory.Provider.OMID.name().equals(transactionProvider) ? "38" : "34") + " BYTES PARALLEL 3-WAY FULL SCAN OVER " + physicalTableName + "\n" +
- "CLIENT MERGE SORT",
- explainPlan);
- rs = conn.createStatement().executeQuery("EXPLAIN SELECT * FROM " + fullTableName + " WHERE k = 'a'");
- explainPlan = QueryUtil.getExplainPlan(rs);
- assertEquals(
- "CLIENT 1-CHUNK 1 ROWS " + (columnEncoded ? "204" : "202") + " BYTES PARALLEL 1-WAY POINT LOOKUP ON 1 KEY OVER " + physicalTableName + "\n" +
- "CLIENT MERGE SORT",
- explainPlan);
-
+ // if we are using the ONE_CELL_PER_COLUMN_FAMILY storage scheme, we will have the single kv even though there are no values for col family v2
+
+ ExplainPlan plan = conn.prepareStatement(
+ "SELECT v2 FROM " + fullTableName + " WHERE v2='foo'")
+ .unwrap(PhoenixPreparedStatement.class).optimizeQuery().getExplainPlan();
+ ExplainPlanAttributes planAttributes = plan.getPlanStepsAsAttributes();
+ assertEquals(columnEncoded && !mutable ? 4 : 3,
+ (int) planAttributes.getSplitsChunk());
+ assertEquals(columnEncoded && !mutable ? 1 : 0,
+ (long) planAttributes.getEstimatedRows());
+ assertEquals(columnEncoded && !mutable ? 38 : 20,
+ (long) planAttributes.getEstimatedSizeInBytes());
+ assertEquals("PARALLEL 3-WAY", planAttributes.getIteratorTypeAndScanSize());
+ assertEquals("FULL SCAN ", planAttributes.getExplainScanType());
+ assertEquals(physicalTableName, planAttributes.getTableName());
+ assertEquals("SERVER FILTER BY B.V2 = 'foo'",
+ planAttributes.getServerWhereFilter());
+ assertEquals("CLIENT MERGE SORT", planAttributes.getClientSortAlgo());
+
+ long estimatedSizeInBytes = columnEncoded ? 28
+ : TransactionFactory.Provider.OMID.name().equals(transactionProvider)
+ ? 38 : 34;
+ plan = conn.prepareStatement(
+ "SELECT * FROM " + fullTableName)
+ .unwrap(PhoenixPreparedStatement.class).optimizeQuery().getExplainPlan();
+ planAttributes = plan.getPlanStepsAsAttributes();
+ assertEquals(4, (int) planAttributes.getSplitsChunk());
+ assertEquals(1, (long) planAttributes.getEstimatedRows());
+ assertEquals(estimatedSizeInBytes,
+ (long) planAttributes.getEstimatedSizeInBytes());
+ assertEquals("PARALLEL 3-WAY", planAttributes.getIteratorTypeAndScanSize());
+ assertEquals("FULL SCAN ", planAttributes.getExplainScanType());
+ assertEquals(physicalTableName, planAttributes.getTableName());
+ assertNull(planAttributes.getServerWhereFilter());
+ assertEquals("CLIENT MERGE SORT", planAttributes.getClientSortAlgo());
+
+ plan = conn.prepareStatement(
+ "SELECT * FROM " + fullTableName + " WHERE k = 'a'")
+ .unwrap(PhoenixPreparedStatement.class).optimizeQuery().getExplainPlan();
+ planAttributes = plan.getPlanStepsAsAttributes();
+ assertEquals(1, (int) planAttributes.getSplitsChunk());
+ assertEquals(1, (long) planAttributes.getEstimatedRows());
+ assertEquals(columnEncoded ? 204 : 202,
+ (long) planAttributes.getEstimatedSizeInBytes());
+ assertEquals("PARALLEL 1-WAY", planAttributes.getIteratorTypeAndScanSize());
+ assertEquals("POINT LOOKUP ON 1 KEY ", planAttributes.getExplainScanType());
+ assertEquals(physicalTableName, planAttributes.getTableName());
+ assertNull(planAttributes.getServerWhereFilter());
+ assertEquals("CLIENT MERGE SORT", planAttributes.getClientSortAlgo());
+
conn.close();
}
@@ -569,9 +603,23 @@ public abstract class BaseStatsCollectorIT extends BaseUniqueNamesOwnClusterIT {
collectStatistics(conn, fullTableName);
List<KeyRange> keyRanges = getAllSplits(conn, fullTableName);
assertEquals(26, keyRanges.size());
- rs = conn.createStatement().executeQuery("EXPLAIN SELECT * FROM " + fullTableName);
- assertEquals("CLIENT 26-CHUNK 25 ROWS " + (columnEncoded ? ( mutable ? "12530" : "13902" ) : (TransactionFactory.Provider.OMID.name().equals(transactionProvider)) ? "25044" : "12420") + " BYTES PARALLEL 1-WAY FULL SCAN OVER " + physicalTableName,
- QueryUtil.getExplainPlan(rs));
+
+ long sizeInBytes = columnEncoded ? (mutable ? 12530 : 13902)
+ : (TransactionFactory.Provider.OMID.name().equals(transactionProvider))
+ ? 25044 : 12420;
+
+ ExplainPlan plan = conn.prepareStatement(
+ "SELECT * FROM " + fullTableName)
+ .unwrap(PhoenixPreparedStatement.class).optimizeQuery().getExplainPlan();
+ ExplainPlanAttributes planAttributes = plan.getPlanStepsAsAttributes();
+ assertEquals(26, (int) planAttributes.getSplitsChunk());
+ assertEquals(25, (long) planAttributes.getEstimatedRows());
+ assertEquals(sizeInBytes,
+ (long) planAttributes.getEstimatedSizeInBytes());
+ assertEquals("PARALLEL 1-WAY",
+ planAttributes.getIteratorTypeAndScanSize());
+ assertEquals("FULL SCAN ", planAttributes.getExplainScanType());
+ assertEquals(physicalTableName, planAttributes.getTableName());
ConnectionQueryServices services = conn.unwrap(PhoenixConnection.class).getQueryServices();
List<HRegionLocation> regions = services.getAllTableRegions(Bytes.toBytes(physicalTableName));
@@ -625,9 +673,18 @@ public abstract class BaseStatsCollectorIT extends BaseUniqueNamesOwnClusterIT {
assertTrue(rs.next());
assertEquals(0, rs.getLong(1));
assertFalse(rs.next());
- rs = conn.createStatement().executeQuery("EXPLAIN SELECT * FROM " + fullTableName);
- assertEquals("CLIENT 1-CHUNK PARALLEL 1-WAY FULL SCAN OVER " + physicalTableName,
- QueryUtil.getExplainPlan(rs));
+
+ plan = conn.prepareStatement(
+ "SELECT * FROM " + fullTableName)
+ .unwrap(PhoenixPreparedStatement.class).optimizeQuery().getExplainPlan();
+ planAttributes = plan.getPlanStepsAsAttributes();
+ assertEquals(1, (int) planAttributes.getSplitsChunk());
+ assertNull(planAttributes.getEstimatedRows());
+ assertNull(planAttributes.getEstimatedSizeInBytes());
+ assertEquals("PARALLEL 1-WAY",
+ planAttributes.getIteratorTypeAndScanSize());
+ assertEquals("FULL SCAN ", planAttributes.getExplainScanType());
+ assertEquals(physicalTableName, planAttributes.getTableName());
}
@Test
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
index 8b43c8c..ebba909 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
@@ -36,6 +36,8 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.phoenix.cache.ServerCacheClient;
import org.apache.phoenix.cache.ServerCacheClient.ServerCache;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.coprocessor.BaseScannerRegionObserver;
@@ -823,11 +825,18 @@ public class DeleteCompiler {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
- List<String> queryPlanSteps = aggPlan.getExplainPlan().getPlanSteps();
- List<String> planSteps = Lists.newArrayListWithExpectedSize(queryPlanSteps.size()+1);
+ ExplainPlan explainPlan = aggPlan.getExplainPlan();
+ List<String> queryPlanSteps = explainPlan.getPlanSteps();
+ ExplainPlanAttributes explainPlanAttributes =
+ explainPlan.getPlanStepsAsAttributes();
+ List<String> planSteps =
+ Lists.newArrayListWithExpectedSize(queryPlanSteps.size() + 1);
+ ExplainPlanAttributesBuilder newBuilder =
+ new ExplainPlanAttributesBuilder(explainPlanAttributes);
+ newBuilder.setAbstractExplainPlan("DELETE ROWS SERVER SELECT");
planSteps.add("DELETE ROWS SERVER SELECT");
planSteps.addAll(queryPlanSteps);
- return new ExplainPlan(planSteps);
+ return new ExplainPlan(planSteps, newBuilder.build());
}
@Override
@@ -945,11 +954,17 @@ public class DeleteCompiler {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
- List<String> queryPlanSteps = bestPlan.getExplainPlan().getPlanSteps();
+ ExplainPlan explainPlan = bestPlan.getExplainPlan();
+ List<String> queryPlanSteps = explainPlan.getPlanSteps();
+ ExplainPlanAttributes explainPlanAttributes =
+ explainPlan.getPlanStepsAsAttributes();
List<String> planSteps = Lists.newArrayListWithExpectedSize(queryPlanSteps.size()+1);
+ ExplainPlanAttributesBuilder newBuilder =
+ new ExplainPlanAttributesBuilder(explainPlanAttributes);
+ newBuilder.setAbstractExplainPlan("DELETE ROWS CLIENT SELECT");
planSteps.add("DELETE ROWS CLIENT SELECT");
planSteps.addAll(queryPlanSteps);
- return new ExplainPlan(planSteps);
+ return new ExplainPlan(planSteps, newBuilder.build());
}
@Override
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExplainPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExplainPlan.java
index ef34daa..a180b6f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExplainPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExplainPlan.java
@@ -26,15 +26,28 @@ public class ExplainPlan {
public static final ExplainPlan EMPTY_PLAN = new ExplainPlan(Collections.<String>emptyList());
private final List<String> planSteps;
-
+ private final ExplainPlanAttributes planStepsAsAttributes;
+
public ExplainPlan(List<String> planSteps) {
this.planSteps = ImmutableList.copyOf(planSteps);
+ this.planStepsAsAttributes =
+ ExplainPlanAttributes.getDefaultExplainPlan();
+ }
+
+ public ExplainPlan(List<String> planSteps,
+ ExplainPlanAttributes planStepsAsAttributes) {
+ this.planSteps = planSteps;
+ this.planStepsAsAttributes = planStepsAsAttributes;
}
-
+
public List<String> getPlanSteps() {
return planSteps;
}
-
+
+ public ExplainPlanAttributes getPlanStepsAsAttributes() {
+ return planStepsAsAttributes;
+ }
+
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExplainPlanAttributes.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExplainPlanAttributes.java
new file mode 100644
index 0000000..855ce96
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExplainPlanAttributes.java
@@ -0,0 +1,598 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.phoenix.compile;
+
+import org.apache.hadoop.hbase.client.Consistency;
+import org.apache.phoenix.parse.HintNode;
+import org.apache.phoenix.parse.HintNode.Hint;
+
+/**
+ * ExplainPlan attributes that contain individual attributes of ExplainPlan
+ * that we can assert against. This also makes attribute retrieval easier
+ * as an API rather than retrieving list of Strings containing entire plan.
+ */
+public class ExplainPlanAttributes {
+
+ private final String abstractExplainPlan;
+ private final Integer splitsChunk;
+ private final Long estimatedRows;
+ private final Long estimatedSizeInBytes;
+ private final String iteratorTypeAndScanSize;
+ private final Double samplingRate;
+ private final boolean useRoundRobinIterator;
+ private final String hexStringRVCOffset;
+ private final Consistency consistency;
+ private final Hint hint;
+ private final String serverSortedBy;
+ private final String explainScanType;
+ private final String tableName;
+ private final String keyRanges;
+ private final Long scanTimeRangeMin;
+ private final Long scanTimeRangeMax;
+ private final String serverWhereFilter;
+ private final String serverDistinctFilter;
+ private final Integer serverOffset;
+ private final Long serverRowLimit;
+ private final boolean serverArrayElementProjection;
+ private final String serverAggregate;
+ private final String clientFilterBy;
+ private final String clientAggregate;
+ private final String clientSortedBy;
+ private final String clientAfterAggregate;
+ private final String clientDistinctFilter;
+ private final Integer clientOffset;
+ private final Integer clientRowLimit;
+ private final Integer clientSequenceCount;
+ private final String clientCursorName;
+ private final String clientSortAlgo;
+ // This object represents PlanAttributes object for rhs query
+ // to be used only by Join queries. In case of Join query, lhs plan is
+ // represented by 'this' object and rhs plan is represented by
+ // 'rhsJoinQueryExplainPlan' object (which in turn should
+ // have null rhsJoinQueryExplainPlan)
+ // For non-Join queries related Plans, rhsJoinQueryExplainPlan will always
+ // be null
+ private final ExplainPlanAttributes rhsJoinQueryExplainPlan;
+
+ private static final ExplainPlanAttributes EXPLAIN_PLAN_INSTANCE =
+ new ExplainPlanAttributes();
+
+ private ExplainPlanAttributes() {
+ this.abstractExplainPlan = null;
+ this.splitsChunk = null;
+ this.estimatedRows = null;
+ this.estimatedSizeInBytes = null;
+ this.iteratorTypeAndScanSize = null;
+ this.samplingRate = null;
+ this.useRoundRobinIterator = false;
+ this.hexStringRVCOffset = null;
+ this.consistency = null;
+ this.hint = null;
+ this.serverSortedBy = null;
+ this.explainScanType = null;
+ this.tableName = null;
+ this.keyRanges = null;
+ this.scanTimeRangeMin = null;
+ this.scanTimeRangeMax = null;
+ this.serverWhereFilter = null;
+ this.serverDistinctFilter = null;
+ this.serverOffset = null;
+ this.serverRowLimit = null;
+ this.serverArrayElementProjection = false;
+ this.serverAggregate = null;
+ this.clientFilterBy = null;
+ this.clientAggregate = null;
+ this.clientSortedBy = null;
+ this.clientAfterAggregate = null;
+ this.clientDistinctFilter = null;
+ this.clientOffset = null;
+ this.clientRowLimit = null;
+ this.clientSequenceCount = null;
+ this.clientCursorName = null;
+ this.clientSortAlgo = null;
+ this.rhsJoinQueryExplainPlan = null;
+ }
+
+ public ExplainPlanAttributes(String abstractExplainPlan,
+ Integer splitsChunk, Long estimatedRows, Long estimatedSizeInBytes,
+ String iteratorTypeAndScanSize, Double samplingRate,
+ boolean useRoundRobinIterator,
+ String hexStringRVCOffset, Consistency consistency,
+ Hint hint, String serverSortedBy, String explainScanType,
+ String tableName, String keyRanges, Long scanTimeRangeMin,
+ Long scanTimeRangeMax, String serverWhereFilter,
+ String serverDistinctFilter,
+ Integer serverOffset, Long serverRowLimit,
+ boolean serverArrayElementProjection, String serverAggregate,
+ String clientFilterBy, String clientAggregate,
+ String clientSortedBy,
+ String clientAfterAggregate, String clientDistinctFilter,
+ Integer clientOffset, Integer clientRowLimit,
+ Integer clientSequenceCount, String clientCursorName,
+ String clientSortAlgo,
+ ExplainPlanAttributes rhsJoinQueryExplainPlan) {
+ this.abstractExplainPlan = abstractExplainPlan;
+ this.splitsChunk = splitsChunk;
+ this.estimatedRows = estimatedRows;
+ this.estimatedSizeInBytes = estimatedSizeInBytes;
+ this.iteratorTypeAndScanSize = iteratorTypeAndScanSize;
+ this.samplingRate = samplingRate;
+ this.useRoundRobinIterator = useRoundRobinIterator;
+ this.hexStringRVCOffset = hexStringRVCOffset;
+ this.consistency = consistency;
+ this.hint = hint;
+ this.serverSortedBy = serverSortedBy;
+ this.explainScanType = explainScanType;
+ this.tableName = tableName;
+ this.keyRanges = keyRanges;
+ this.scanTimeRangeMin = scanTimeRangeMin;
+ this.scanTimeRangeMax = scanTimeRangeMax;
+ this.serverWhereFilter = serverWhereFilter;
+ this.serverDistinctFilter = serverDistinctFilter;
+ this.serverOffset = serverOffset;
+ this.serverRowLimit = serverRowLimit;
+ this.serverArrayElementProjection = serverArrayElementProjection;
+ this.serverAggregate = serverAggregate;
+ this.clientFilterBy = clientFilterBy;
+ this.clientAggregate = clientAggregate;
+ this.clientSortedBy = clientSortedBy;
+ this.clientAfterAggregate = clientAfterAggregate;
+ this.clientDistinctFilter = clientDistinctFilter;
+ this.clientOffset = clientOffset;
+ this.clientRowLimit = clientRowLimit;
+ this.clientSequenceCount = clientSequenceCount;
+ this.clientCursorName = clientCursorName;
+ this.clientSortAlgo = clientSortAlgo;
+ this.rhsJoinQueryExplainPlan = rhsJoinQueryExplainPlan;
+ }
+
+ public String getAbstractExplainPlan() {
+ return abstractExplainPlan;
+ }
+
+ public Integer getSplitsChunk() {
+ return splitsChunk;
+ }
+
+ public Long getEstimatedRows() {
+ return estimatedRows;
+ }
+
+ public Long getEstimatedSizeInBytes() {
+ return estimatedSizeInBytes;
+ }
+
+ public String getIteratorTypeAndScanSize() {
+ return iteratorTypeAndScanSize;
+ }
+
+ public Double getSamplingRate() {
+ return samplingRate;
+ }
+
+ public boolean isUseRoundRobinIterator() {
+ return useRoundRobinIterator;
+ }
+
+ public String getHexStringRVCOffset() {
+ return hexStringRVCOffset;
+ }
+
+ public Consistency getConsistency() {
+ return consistency;
+ }
+
+ public Hint getHint() {
+ return hint;
+ }
+
+ public String getServerSortedBy() {
+ return serverSortedBy;
+ }
+
+ public String getExplainScanType() {
+ return explainScanType;
+ }
+
+ public String getTableName() {
+ return tableName;
+ }
+
+ public String getKeyRanges() {
+ return keyRanges;
+ }
+
+ public Long getScanTimeRangeMin() {
+ return scanTimeRangeMin;
+ }
+
+ public Long getScanTimeRangeMax() {
+ return scanTimeRangeMax;
+ }
+
+ public String getServerWhereFilter() {
+ return serverWhereFilter;
+ }
+
+ public String getServerDistinctFilter() {
+ return serverDistinctFilter;
+ }
+
+ public Integer getServerOffset() {
+ return serverOffset;
+ }
+
+ public Long getServerRowLimit() {
+ return serverRowLimit;
+ }
+
+ public boolean isServerArrayElementProjection() {
+ return serverArrayElementProjection;
+ }
+
+ public String getServerAggregate() {
+ return serverAggregate;
+ }
+
+ public String getClientFilterBy() {
+ return clientFilterBy;
+ }
+
+ public String getClientAggregate() {
+ return clientAggregate;
+ }
+
+ public String getClientSortedBy() {
+ return clientSortedBy;
+ }
+
+ public String getClientAfterAggregate() {
+ return clientAfterAggregate;
+ }
+
+ public String getClientDistinctFilter() {
+ return clientDistinctFilter;
+ }
+
+ public Integer getClientOffset() {
+ return clientOffset;
+ }
+
+ public Integer getClientRowLimit() {
+ return clientRowLimit;
+ }
+
+ public Integer getClientSequenceCount() {
+ return clientSequenceCount;
+ }
+
+ public String getClientCursorName() {
+ return clientCursorName;
+ }
+
+ public String getClientSortAlgo() {
+ return clientSortAlgo;
+ }
+
+ public ExplainPlanAttributes getRhsJoinQueryExplainPlan() {
+ return rhsJoinQueryExplainPlan;
+ }
+
+ public static ExplainPlanAttributes getDefaultExplainPlan() {
+ return EXPLAIN_PLAN_INSTANCE;
+ }
+
+ public static class ExplainPlanAttributesBuilder {
+ private String abstractExplainPlan;
+ private Integer splitsChunk;
+ private Long estimatedRows;
+ private Long estimatedSizeInBytes;
+ private String iteratorTypeAndScanSize;
+ private Double samplingRate;
+ private boolean useRoundRobinIterator;
+ private String hexStringRVCOffset;
+ private Consistency consistency;
+ private HintNode.Hint hint;
+ private String serverSortedBy;
+ private String explainScanType;
+ private String tableName;
+ private String keyRanges;
+ private Long scanTimeRangeMin;
+ private Long scanTimeRangeMax;
+ private String serverWhereFilter;
+ private String serverDistinctFilter;
+ private Integer serverOffset;
+ private Long serverRowLimit;
+ private boolean serverArrayElementProjection;
+ private String serverAggregate;
+ private String clientFilterBy;
+ private String clientAggregate;
+ private String clientSortedBy;
+ private String clientAfterAggregate;
+ private String clientDistinctFilter;
+ private Integer clientOffset;
+ private Integer clientRowLimit;
+ private Integer clientSequenceCount;
+ private String clientCursorName;
+ private String clientSortAlgo;
+ private ExplainPlanAttributes rhsJoinQueryExplainPlan;
+
+ public ExplainPlanAttributesBuilder() {
+ // default
+ }
+
+ public ExplainPlanAttributesBuilder(
+ ExplainPlanAttributes explainPlanAttributes) {
+ this.abstractExplainPlan =
+ explainPlanAttributes.getAbstractExplainPlan();
+ this.splitsChunk = explainPlanAttributes.getSplitsChunk();
+ this.estimatedRows = explainPlanAttributes.getEstimatedRows();
+ this.estimatedSizeInBytes =
+ explainPlanAttributes.getEstimatedSizeInBytes();
+ this.iteratorTypeAndScanSize = explainPlanAttributes.getIteratorTypeAndScanSize();
+ this.samplingRate = explainPlanAttributes.getSamplingRate();
+ this.useRoundRobinIterator =
+ explainPlanAttributes.isUseRoundRobinIterator();
+ this.hexStringRVCOffset =
+ explainPlanAttributes.getHexStringRVCOffset();
+ this.consistency = explainPlanAttributes.getConsistency();
+ this.hint = explainPlanAttributes.getHint();
+ this.serverSortedBy = explainPlanAttributes.getServerSortedBy();
+ this.explainScanType = explainPlanAttributes.getExplainScanType();
+ this.tableName = explainPlanAttributes.getTableName();
+ this.keyRanges = explainPlanAttributes.getKeyRanges();
+ this.scanTimeRangeMin = explainPlanAttributes.getScanTimeRangeMin();
+ this.scanTimeRangeMax = explainPlanAttributes.getScanTimeRangeMax();
+ this.serverWhereFilter =
+ explainPlanAttributes.getServerWhereFilter();
+ this.serverDistinctFilter =
+ explainPlanAttributes.getServerDistinctFilter();
+ this.serverOffset = explainPlanAttributes.getServerOffset();
+ this.serverRowLimit = explainPlanAttributes.getServerRowLimit();
+ this.serverArrayElementProjection =
+ explainPlanAttributes.isServerArrayElementProjection();
+ this.serverAggregate = explainPlanAttributes.getServerAggregate();
+ this.clientFilterBy = explainPlanAttributes.getClientFilterBy();
+ this.clientAggregate = explainPlanAttributes.getClientAggregate();
+ this.clientSortedBy = explainPlanAttributes.getClientSortedBy();
+ this.clientAfterAggregate =
+ explainPlanAttributes.getClientAfterAggregate();
+ this.clientDistinctFilter =
+ explainPlanAttributes.getClientDistinctFilter();
+ this.clientOffset = explainPlanAttributes.getClientOffset();
+ this.clientRowLimit = explainPlanAttributes.getClientRowLimit();
+ this.clientSequenceCount =
+ explainPlanAttributes.getClientSequenceCount();
+ this.clientCursorName = explainPlanAttributes.getClientCursorName();
+ this.clientSortAlgo = explainPlanAttributes.getClientSortAlgo();
+ this.rhsJoinQueryExplainPlan =
+ explainPlanAttributes.getRhsJoinQueryExplainPlan();
+ }
+
+ public ExplainPlanAttributesBuilder setAbstractExplainPlan(
+ String abstractExplainPlan) {
+ this.abstractExplainPlan = abstractExplainPlan;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setSplitsChunk(
+ Integer splitsChunk) {
+ this.splitsChunk = splitsChunk;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setEstimatedRows(
+ Long estimatedRows) {
+ this.estimatedRows = estimatedRows;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setEstimatedSizeInBytes(
+ Long estimatedSizeInBytes) {
+ this.estimatedSizeInBytes = estimatedSizeInBytes;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setIteratorTypeAndScanSize(
+ String iteratorTypeAndScanSize) {
+ this.iteratorTypeAndScanSize = iteratorTypeAndScanSize;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setSamplingRate(
+ Double samplingRate) {
+ this.samplingRate = samplingRate;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setUseRoundRobinIterator(
+ boolean useRoundRobinIterator) {
+ this.useRoundRobinIterator = useRoundRobinIterator;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setHexStringRVCOffset(
+ String hexStringRVCOffset) {
+ this.hexStringRVCOffset = hexStringRVCOffset;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setConsistency(
+ Consistency consistency) {
+ this.consistency = consistency;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setHint(HintNode.Hint hint) {
+ this.hint = hint;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setServerSortedBy(
+ String serverSortedBy) {
+ this.serverSortedBy = serverSortedBy;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setExplainScanType(
+ String explainScanType) {
+ this.explainScanType = explainScanType;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setTableName(String tableName) {
+ this.tableName = tableName;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setKeyRanges(String keyRanges) {
+ this.keyRanges = keyRanges;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setScanTimeRangeMin(
+ Long scanTimeRangeMin) {
+ this.scanTimeRangeMin = scanTimeRangeMin;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setScanTimeRangeMax(
+ Long scanTimeRangeMax) {
+ this.scanTimeRangeMax = scanTimeRangeMax;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setServerWhereFilter(
+ String serverWhereFilter) {
+ this.serverWhereFilter = serverWhereFilter;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setServerDistinctFilter(
+ String serverDistinctFilter) {
+ this.serverDistinctFilter = serverDistinctFilter;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setServerOffset(
+ Integer serverOffset) {
+ this.serverOffset = serverOffset;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setServerRowLimit(
+ Long serverRowLimit) {
+ this.serverRowLimit = serverRowLimit;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setServerArrayElementProjection(
+ boolean serverArrayElementProjection) {
+ this.serverArrayElementProjection = serverArrayElementProjection;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setServerAggregate(
+ String serverAggregate) {
+ this.serverAggregate = serverAggregate;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setClientFilterBy(
+ String clientFilterBy) {
+ this.clientFilterBy = clientFilterBy;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setClientAggregate(
+ String clientAggregate) {
+ this.clientAggregate = clientAggregate;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setClientSortedBy(
+ String clientSortedBy) {
+ this.clientSortedBy = clientSortedBy;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setClientAfterAggregate(
+ String clientAfterAggregate) {
+ this.clientAfterAggregate = clientAfterAggregate;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setClientDistinctFilter(
+ String clientDistinctFilter) {
+ this.clientDistinctFilter = clientDistinctFilter;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setClientOffset(
+ Integer clientOffset) {
+ this.clientOffset = clientOffset;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setClientRowLimit(
+ Integer clientRowLimit) {
+ this.clientRowLimit = clientRowLimit;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setClientSequenceCount(
+ Integer clientSequenceCount) {
+ this.clientSequenceCount = clientSequenceCount;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setClientCursorName(
+ String clientCursorName) {
+ this.clientCursorName = clientCursorName;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setClientSortAlgo(
+ String clientSortAlgo) {
+ this.clientSortAlgo = clientSortAlgo;
+ return this;
+ }
+
+ public ExplainPlanAttributesBuilder setRhsJoinQueryExplainPlan(
+ ExplainPlanAttributes rhsJoinQueryExplainPlan) {
+ this.rhsJoinQueryExplainPlan = rhsJoinQueryExplainPlan;
+ return this;
+ }
+
+ public ExplainPlanAttributes build() {
+ return new ExplainPlanAttributes(abstractExplainPlan, splitsChunk,
+ estimatedRows, estimatedSizeInBytes, iteratorTypeAndScanSize,
+ samplingRate, useRoundRobinIterator, hexStringRVCOffset,
+ consistency, hint, serverSortedBy, explainScanType, tableName,
+ keyRanges, scanTimeRangeMin, scanTimeRangeMax,
+ serverWhereFilter, serverDistinctFilter,
+ serverOffset, serverRowLimit,
+ serverArrayElementProjection, serverAggregate,
+ clientFilterBy, clientAggregate, clientSortedBy,
+ clientAfterAggregate, clientDistinctFilter, clientOffset,
+ clientRowLimit, clientSequenceCount, clientCursorName,
+ clientSortAlgo, rhsJoinQueryExplainPlan);
+ }
+ }
+}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/GroupByCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/GroupByCompiler.java
index c47e9a0..12e1a46 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/GroupByCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/GroupByCompiler.java
@@ -26,6 +26,8 @@ import java.util.List;
import net.jcip.annotations.Immutable;
import org.apache.hadoop.hbase.util.Pair;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.OrderPreservingTracker.Info;
import org.apache.phoenix.compile.OrderPreservingTracker.Ordering;
import org.apache.phoenix.coprocessor.BaseScannerRegionObserver;
@@ -73,12 +75,18 @@ public class GroupByCompiler {
@Override
public void explain(List<String> planSteps, Integer limit) {
}
-
+
+ @Override
+ public void explain(List<String> planSteps, Integer limit,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
@Override
public String getScanAttribName() {
return null;
}
};
+
public static final GroupByCompiler.GroupBy UNGROUPED_GROUP_BY = new GroupBy(new GroupByBuilder().setIsOrderPreserving(true).setIsUngroupedAggregate(true)) {
@Override
public GroupBy compile(StatementContext context, QueryPlan innerQueryPlan, Expression whereExpression) throws SQLException {
@@ -89,7 +97,17 @@ public class GroupByCompiler {
public void explain(List<String> planSteps, Integer limit) {
planSteps.add(" SERVER AGGREGATE INTO SINGLE ROW");
}
-
+
+ @Override
+ public void explain(List<String> planSteps, Integer limit,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ planSteps.add(" SERVER AGGREGATE INTO SINGLE ROW");
+ if (explainPlanAttributesBuilder != null) {
+ explainPlanAttributesBuilder.setServerAggregate(
+ "SERVER AGGREGATE INTO SINGLE ROW");
+ }
+ }
+
@Override
public String getScanAttribName() {
return BaseScannerRegionObserver.UNGROUPED_AGG;
@@ -335,14 +353,35 @@ public class GroupByCompiler {
}
public void explain(List<String> planSteps, Integer limit) {
+ explainUtil(planSteps, limit, null);
+ }
+
+ private void explainUtil(List<String> planSteps, Integer limit,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ String serverAggregate;
if (isUngroupedAggregate) {
- planSteps.add(" SERVER AGGREGATE INTO SINGLE ROW");
- } else if (isOrderPreserving) {
- planSteps.add(" SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY " + getExpressions() + (limit == null ? "" : " LIMIT " + limit + " GROUP" + (limit.intValue() == 1 ? "" : "S")));
+ serverAggregate = "SERVER AGGREGATE INTO SINGLE ROW";
} else {
- planSteps.add(" SERVER AGGREGATE INTO DISTINCT ROWS BY " + getExpressions() + (limit == null ? "" : " LIMIT " + limit + " GROUP" + (limit.intValue() == 1 ? "" : "S")));
+ String groupLimit = limit == null ? "" : (" LIMIT " + limit
+ + " GROUP" + (limit == 1 ? "" : "S"));
+ if (isOrderPreserving) {
+ serverAggregate = "SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY "
+ + getExpressions() + groupLimit;
+ } else {
+ serverAggregate = "SERVER AGGREGATE INTO DISTINCT ROWS BY "
+ + getExpressions() + groupLimit;
+ }
+ }
+ planSteps.add(" " + serverAggregate);
+ if (explainPlanAttributesBuilder != null) {
+ explainPlanAttributesBuilder.setServerAggregate(serverAggregate);
}
}
+
+ public void explain(List<String> planSteps, Integer limit,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ explainUtil(planSteps, limit, explainPlanAttributesBuilder);
+ }
}
/**
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
index e7db5b1..ec77621 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
@@ -37,6 +37,8 @@ import org.apache.hadoop.hbase.KeyValue.Type;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.execute.visitor.QueryPlanVisitor;
@@ -179,6 +181,11 @@ public class ListJarsQueryPlan implements QueryPlan {
@Override
public void explain(List<String> planSteps) {
}
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
};
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/MutatingParallelIteratorFactory.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/MutatingParallelIteratorFactory.java
index 213ff0a..37a87de 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/MutatingParallelIteratorFactory.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/MutatingParallelIteratorFactory.java
@@ -27,6 +27,8 @@ import java.util.List;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Scan;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.execute.MutationState;
import org.apache.phoenix.iterate.ParallelIteratorFactory;
import org.apache.phoenix.iterate.PeekingResultIterator;
@@ -98,6 +100,11 @@ public abstract class MutatingParallelIteratorFactory implements ParallelIterato
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
+ @Override
public void close() throws SQLException {
try {
/*
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/TraceQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/TraceQueryPlan.java
index 7d36f0b..1558752 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/TraceQueryPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/TraceQueryPlan.java
@@ -33,6 +33,8 @@ import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.htrace.Sampler;
import org.apache.htrace.TraceScope;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.execute.visitor.QueryPlanVisitor;
@@ -187,6 +189,11 @@ public class TraceQueryPlan implements QueryPlan {
@Override
public void explain(List<String> planSteps) {
}
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
};
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
index 48a23eb..6724e6a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
@@ -40,6 +40,8 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.phoenix.cache.ServerCacheClient;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.coprocessor.BaseScannerRegionObserver;
@@ -1138,11 +1140,18 @@ public class UpsertCompiler {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
- List<String> queryPlanSteps = aggPlan.getExplainPlan().getPlanSteps();
- List<String> planSteps = Lists.newArrayListWithExpectedSize(queryPlanSteps.size()+1);
+ ExplainPlan explainPlan = aggPlan.getExplainPlan();
+ List<String> queryPlanSteps = explainPlan.getPlanSteps();
+ ExplainPlanAttributes explainPlanAttributes =
+ explainPlan.getPlanStepsAsAttributes();
+ List<String> planSteps =
+ Lists.newArrayListWithExpectedSize(queryPlanSteps.size() + 1);
+ ExplainPlanAttributesBuilder newBuilder =
+ new ExplainPlanAttributesBuilder(explainPlanAttributes);
+ newBuilder.setAbstractExplainPlan("UPSERT ROWS");
planSteps.add("UPSERT ROWS");
planSteps.addAll(queryPlanSteps);
- return new ExplainPlan(planSteps);
+ return new ExplainPlan(planSteps, newBuilder.build());
}
@Override
@@ -1418,11 +1427,18 @@ public class UpsertCompiler {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
- List<String> queryPlanSteps = queryPlan.getExplainPlan().getPlanSteps();
- List<String> planSteps = Lists.newArrayListWithExpectedSize(queryPlanSteps.size()+1);
+ ExplainPlan explainPlan = queryPlan.getExplainPlan();
+ List<String> queryPlanSteps = explainPlan.getPlanSteps();
+ ExplainPlanAttributes explainPlanAttributes =
+ explainPlan.getPlanStepsAsAttributes();
+ List<String> planSteps =
+ Lists.newArrayListWithExpectedSize(queryPlanSteps.size() + 1);
+ ExplainPlanAttributesBuilder newBuilder =
+ new ExplainPlanAttributesBuilder(explainPlanAttributes);
+ newBuilder.setAbstractExplainPlan("UPSERT SELECT");
planSteps.add("UPSERT SELECT");
planSteps.addAll(queryPlanSteps);
- return new ExplainPlan(planSteps);
+ return new ExplainPlan(planSteps, newBuilder.build());
}
@Override
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
index 2b10780..dace7c0 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
@@ -28,6 +28,10 @@ import java.util.Map;
import java.util.Set;
import com.google.common.base.Optional;
+import org.apache.commons.math3.util.Pair;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
@@ -516,7 +520,10 @@ public abstract class BaseQueryPlan implements QueryPlan {
}
ResultIterator iterator = iterator();
- ExplainPlan explainPlan = new ExplainPlan(getPlanSteps(iterator));
+ Pair<List<String>, ExplainPlanAttributes> planSteps =
+ getPlanStepsV2(iterator);
+ ExplainPlan explainPlan = new ExplainPlan(planSteps.getFirst(),
+ planSteps.getSecond());
iterator.close();
return explainPlan;
}
@@ -527,6 +534,15 @@ public abstract class BaseQueryPlan implements QueryPlan {
return planSteps;
}
+ private Pair<List<String>, ExplainPlanAttributes> getPlanStepsV2(
+ ResultIterator iterator) {
+ List<String> planSteps = Lists.newArrayListWithExpectedSize(5);
+ ExplainPlanAttributesBuilder builder =
+ new ExplainPlanAttributesBuilder();
+ iterator.explain(planSteps, builder);
+ return new Pair<>(planSteps, builder.build());
+ }
+
@Override
public boolean isRowKeyOrdered() {
return groupBy.isEmpty() ? orderBy.getOrderByExpressions().isEmpty() : groupBy.isOrderPreserving();
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientAggregatePlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientAggregatePlan.java
index aa99cab..f0199ac 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientAggregatePlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientAggregatePlan.java
@@ -29,6 +29,9 @@ import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.compile.ExplainPlan;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.compile.QueryPlan;
@@ -220,45 +223,70 @@ public class ClientAggregatePlan extends ClientProcessingPlan {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
- List<String> planSteps = Lists.newArrayList(delegate.getExplainPlan().getPlanSteps());
+ ExplainPlan explainPlan = delegate.getExplainPlan();
+ List<String> planSteps = Lists.newArrayList(explainPlan.getPlanSteps());
+ ExplainPlanAttributes explainPlanAttributes =
+ explainPlan.getPlanStepsAsAttributes();
+ ExplainPlanAttributesBuilder newBuilder =
+ new ExplainPlanAttributesBuilder(explainPlanAttributes);
if (where != null) {
planSteps.add("CLIENT FILTER BY " + where.toString());
+ newBuilder.setClientFilterBy(where.toString());
}
if (groupBy.isEmpty()) {
planSteps.add("CLIENT AGGREGATE INTO SINGLE ROW");
+ newBuilder.setClientAggregate("CLIENT AGGREGATE INTO SINGLE ROW");
} else if (groupBy.isOrderPreserving()) {
planSteps.add("CLIENT AGGREGATE INTO DISTINCT ROWS BY " + groupBy.getExpressions().toString());
+ newBuilder.setClientAggregate("CLIENT AGGREGATE INTO DISTINCT ROWS BY "
+ + groupBy.getExpressions().toString());
} else if (useHashAgg) {
planSteps.add("CLIENT HASH AGGREGATE INTO DISTINCT ROWS BY " + groupBy.getExpressions().toString());
+ newBuilder.setClientAggregate("CLIENT HASH AGGREGATE INTO DISTINCT ROWS BY "
+ + groupBy.getExpressions().toString());
if (orderBy == OrderBy.FWD_ROW_KEY_ORDER_BY || orderBy == OrderBy.REV_ROW_KEY_ORDER_BY) {
planSteps.add("CLIENT SORTED BY " + groupBy.getKeyExpressions().toString());
+ newBuilder.setClientSortedBy(
+ groupBy.getKeyExpressions().toString());
}
} else {
planSteps.add("CLIENT SORTED BY " + groupBy.getKeyExpressions().toString());
planSteps.add("CLIENT AGGREGATE INTO DISTINCT ROWS BY " + groupBy.getExpressions().toString());
+ newBuilder.setClientSortedBy(groupBy.getKeyExpressions().toString());
+ newBuilder.setClientAggregate("CLIENT AGGREGATE INTO DISTINCT ROWS BY "
+ + groupBy.getExpressions().toString());
}
if (having != null) {
planSteps.add("CLIENT AFTER-AGGREGATION FILTER BY " + having.toString());
+ newBuilder.setClientAfterAggregate("CLIENT AFTER-AGGREGATION FILTER BY "
+ + having.toString());
}
if (statement.isDistinct() && statement.isAggregate()) {
planSteps.add("CLIENT DISTINCT ON " + projector.toString());
+ newBuilder.setClientDistinctFilter(projector.toString());
}
if (offset != null) {
planSteps.add("CLIENT OFFSET " + offset);
+ newBuilder.setClientOffset(offset);
}
if (orderBy.getOrderByExpressions().isEmpty()) {
if (limit != null) {
planSteps.add("CLIENT " + limit + " ROW LIMIT");
+ newBuilder.setClientRowLimit(limit);
}
} else {
planSteps.add("CLIENT" + (limit == null ? "" : " TOP " + limit + " ROW" + (limit == 1 ? "" : "S")) + " SORTED BY " + orderBy.getOrderByExpressions().toString());
+ newBuilder.setClientRowLimit(limit);
+ newBuilder.setClientSortedBy(
+ orderBy.getOrderByExpressions().toString());
}
if (context.getSequenceManager().getSequenceCount() > 0) {
int nSequences = context.getSequenceManager().getSequenceCount();
planSteps.add("CLIENT RESERVE VALUES FROM " + nSequences + " SEQUENCE" + (nSequences == 1 ? "" : "S"));
+ newBuilder.setClientSequenceCount(nSequences);
}
-
- return new ExplainPlan(planSteps);
+
+ return new ExplainPlan(planSteps, newBuilder.build());
}
@Override
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientScanPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientScanPlan.java
index f39e5bf..be4a65b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientScanPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientScanPlan.java
@@ -23,6 +23,9 @@ import java.util.List;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.phoenix.compile.ExplainPlan;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.compile.RowProjector;
@@ -121,30 +124,44 @@ public class ClientScanPlan extends ClientProcessingPlan {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
- List<String> planSteps = Lists.newArrayList(delegate.getExplainPlan().getPlanSteps());
+ ExplainPlan explainPlan = delegate.getExplainPlan();
+ List<String> currentPlanSteps = explainPlan.getPlanSteps();
+ ExplainPlanAttributes explainPlanAttributes =
+ explainPlan.getPlanStepsAsAttributes();
+ List<String> planSteps = Lists.newArrayList(currentPlanSteps);
+ ExplainPlanAttributesBuilder newBuilder =
+ new ExplainPlanAttributesBuilder(explainPlanAttributes);
if (where != null) {
planSteps.add("CLIENT FILTER BY " + where.toString());
+ newBuilder.setClientFilterBy(where.toString());
}
if (!orderBy.getOrderByExpressions().isEmpty()) {
if (offset != null) {
planSteps.add("CLIENT OFFSET " + offset);
+ newBuilder.setClientOffset(offset);
}
planSteps.add("CLIENT" + (limit == null ? "" : " TOP " + limit + " ROW" + (limit == 1 ? "" : "S"))
+ " SORTED BY " + orderBy.getOrderByExpressions().toString());
+ newBuilder.setClientRowLimit(limit);
+ newBuilder.setClientSortedBy(
+ orderBy.getOrderByExpressions().toString());
} else {
if (offset != null) {
planSteps.add("CLIENT OFFSET " + offset);
+ newBuilder.setClientOffset(offset);
}
if (limit != null) {
planSteps.add("CLIENT " + limit + " ROW LIMIT");
+ newBuilder.setClientRowLimit(limit);
}
}
if (context.getSequenceManager().getSequenceCount() > 0) {
int nSequences = context.getSequenceManager().getSequenceCount();
planSteps.add("CLIENT RESERVE VALUES FROM " + nSequences + " SEQUENCE" + (nSequences == 1 ? "" : "S"));
+ newBuilder.setClientSequenceCount(nSequences);
}
-
- return new ExplainPlan(planSteps);
+
+ return new ExplainPlan(planSteps, newBuilder.build());
}
private static List<OrderBy> convertActualOutputOrderBy(
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/CorrelatePlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/CorrelatePlan.java
index 68b1505..6d9afd6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/CorrelatePlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/CorrelatePlan.java
@@ -24,6 +24,9 @@ import java.util.List;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.compile.ExplainPlan;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.exception.SQLExceptionInfo;
@@ -92,14 +95,33 @@ public class CorrelatePlan extends DelegateQueryPlan {
public ExplainPlan getExplainPlan() throws SQLException {
List<String> steps = Lists.newArrayList();
steps.add("NESTED-LOOP-JOIN (" + joinType.toString().toUpperCase() + ") TABLES");
- for (String step : delegate.getExplainPlan().getPlanSteps()) {
- steps.add(" " + step);
+ ExplainPlan lhsExplainPlan = delegate.getExplainPlan();
+ List<String> lhsPlanSteps = lhsExplainPlan.getPlanSteps();
+ ExplainPlanAttributes lhsPlanAttributes =
+ lhsExplainPlan.getPlanStepsAsAttributes();
+ ExplainPlanAttributesBuilder lhsPlanBuilder =
+ new ExplainPlanAttributesBuilder(lhsPlanAttributes);
+ lhsPlanBuilder.setAbstractExplainPlan("NESTED-LOOP-JOIN ("
+ + joinType.toString().toUpperCase() + ")");
+
+ for (String step : lhsPlanSteps) {
+ steps.add(" " + step);
}
steps.add("AND" + (rhsSchema.getFieldCount() == 0 ? " (SKIP MERGE)" : ""));
- for (String step : rhs.getExplainPlan().getPlanSteps()) {
- steps.add(" " + step);
+
+ ExplainPlan rhsExplainPlan = rhs.getExplainPlan();
+ List<String> rhsPlanSteps = rhsExplainPlan.getPlanSteps();
+ ExplainPlanAttributes rhsPlanAttributes =
+ rhsExplainPlan.getPlanStepsAsAttributes();
+ ExplainPlanAttributesBuilder rhsPlanBuilder =
+ new ExplainPlanAttributesBuilder(rhsPlanAttributes);
+
+ lhsPlanBuilder.setRhsJoinQueryExplainPlan(rhsPlanBuilder.build());
+
+ for (String step : rhsPlanSteps) {
+ steps.add(" " + step);
}
- return new ExplainPlan(steps);
+ return new ExplainPlan(steps, lhsPlanBuilder.build());
}
@Override
@@ -217,6 +239,11 @@ public class CorrelatePlan extends DelegateQueryPlan {
@Override
public void explain(List<String> planSteps) { }
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
private ProjectedValueTuple convertLhs(Tuple lhs) throws IOException {
ProjectedValueTuple tuple;
if (lhs instanceof ProjectedValueTuple) {
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
index 71fb3fb..aa21ae2 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
@@ -295,6 +295,7 @@ public class HashJoinPlan extends DelegateQueryPlan {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
+ // TODO : Support ExplainPlanAttributes for HashJoinPlan
List<String> planSteps = Lists.newArrayList(delegate.getExplainPlan().getPlanSteps());
int count = subPlans.length;
for (int i = 0; i < count; i++) {
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
index a9f9d8e..10e9031 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
@@ -26,6 +26,8 @@ import java.util.Map;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.phoenix.cache.ServerCacheClient.ServerCache;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.compile.RowProjector;
@@ -118,7 +120,12 @@ public class LiteralResultIterationPlan extends BaseQueryPlan {
@Override
public void explain(List<String> planSteps) {
}
-
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
};
if (context.getSequenceManager().getSequenceCount() > 0) {
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/SortMergeJoinPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/SortMergeJoinPlan.java
index 94f8452..51ff20f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/SortMergeJoinPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/SortMergeJoinPlan.java
@@ -39,6 +39,9 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.phoenix.compile.ColumnResolver;
import org.apache.phoenix.compile.ExplainPlan;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.compile.QueryCompiler;
@@ -197,14 +200,33 @@ public class SortMergeJoinPlan implements QueryPlan {
public ExplainPlan getExplainPlan() throws SQLException {
List<String> steps = Lists.newArrayList();
steps.add("SORT-MERGE-JOIN (" + joinType.toString().toUpperCase() + ") TABLES");
- for (String step : lhsPlan.getExplainPlan().getPlanSteps()) {
- steps.add(" " + step);
+ ExplainPlan lhsExplainPlan = lhsPlan.getExplainPlan();
+ List<String> lhsPlanSteps = lhsExplainPlan.getPlanSteps();
+ ExplainPlanAttributes lhsPlanAttributes =
+ lhsExplainPlan.getPlanStepsAsAttributes();
+ ExplainPlanAttributesBuilder lhsPlanBuilder =
+ new ExplainPlanAttributesBuilder(lhsPlanAttributes);
+ lhsPlanBuilder.setAbstractExplainPlan("SORT-MERGE-JOIN ("
+ + joinType.toString().toUpperCase() + ")");
+
+ for (String step : lhsPlanSteps) {
+ steps.add(" " + step);
}
steps.add("AND" + (rhsSchema.getFieldCount() == 0 ? " (SKIP MERGE)" : ""));
- for (String step : rhsPlan.getExplainPlan().getPlanSteps()) {
- steps.add(" " + step);
+
+ ExplainPlan rhsExplainPlan = rhsPlan.getExplainPlan();
+ List<String> rhsPlanSteps = rhsExplainPlan.getPlanSteps();
+ ExplainPlanAttributes rhsPlanAttributes =
+ rhsExplainPlan.getPlanStepsAsAttributes();
+ ExplainPlanAttributesBuilder rhsPlanBuilder =
+ new ExplainPlanAttributesBuilder(rhsPlanAttributes);
+
+ lhsPlanBuilder.setRhsJoinQueryExplainPlan(rhsPlanBuilder.build());
+
+ for (String step : rhsPlanSteps) {
+ steps.add(" " + step);
}
- return new ExplainPlan(steps);
+ return new ExplainPlan(steps, lhsPlanBuilder.build());
}
@Override
@@ -481,6 +503,11 @@ public class SortMergeJoinPlan implements QueryPlan {
public void explain(List<String> planSteps) {
}
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
private void doInit(boolean lhs) throws SQLException {
if(lhs) {
nextLhsTuple = lhsIterator.next();
@@ -745,7 +772,12 @@ public class SortMergeJoinPlan implements QueryPlan {
@Override
public void explain(List<String> planSteps) {
}
-
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
private void advance(boolean lhs) throws SQLException {
if (lhs) {
lhsTuple = lhsIterator.next();
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjectionPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjectionPlan.java
index 4b56c23..18b1aec 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjectionPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjectionPlan.java
@@ -27,6 +27,9 @@ import java.util.Map;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.phoenix.compile.ColumnResolver;
import org.apache.phoenix.compile.ExplainPlan;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.OrderPreservingTracker;
import org.apache.phoenix.compile.OrderPreservingTracker.Info;
import org.apache.phoenix.compile.QueryPlan;
@@ -151,12 +154,19 @@ public class TupleProjectionPlan extends DelegateQueryPlan {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
- List<String> planSteps = Lists.newArrayList(delegate.getExplainPlan().getPlanSteps());
+ ExplainPlan explainPlan = delegate.getExplainPlan();
+ List<String> planSteps = Lists.newArrayList(explainPlan.getPlanSteps());
+ ExplainPlanAttributes explainPlanAttributes =
+ explainPlan.getPlanStepsAsAttributes();
if (postFilter != null) {
planSteps.add("CLIENT FILTER BY " + postFilter.toString());
+ ExplainPlanAttributesBuilder newBuilder =
+ new ExplainPlanAttributesBuilder(explainPlanAttributes);
+ newBuilder.setClientFilterBy(postFilter.toString());
+ explainPlanAttributes = newBuilder.build();
}
- return new ExplainPlan(planSteps);
+ return new ExplainPlan(planSteps, explainPlanAttributes);
}
@Override
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/UnionPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/UnionPlan.java
index cefd7b6..a6631d5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/UnionPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/UnionPlan.java
@@ -29,6 +29,8 @@ import java.util.Set;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.phoenix.compile.ExplainPlan;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.compile.QueryPlan;
@@ -182,15 +184,19 @@ public class UnionPlan implements QueryPlan {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
List<String> steps = new ArrayList<String>();
- steps.add("UNION ALL OVER " + this.plans.size() + " QUERIES");
+ ExplainPlanAttributesBuilder builder = new ExplainPlanAttributesBuilder();
+ String abstractExplainPlan = "UNION ALL OVER " + this.plans.size()
+ + " QUERIES";
+ builder.setAbstractExplainPlan(abstractExplainPlan);
+ steps.add(abstractExplainPlan);
ResultIterator iterator = iterator();
- iterator.explain(steps);
+ iterator.explain(steps, builder);
// Indent plans steps nested under union, except last client-side merge/concat step (if there is one)
int offset = !orderBy.getOrderByExpressions().isEmpty() && limit != null ? 2 : limit != null ? 1 : 0;
for (int i = 1 ; i < steps.size()-offset; i++) {
steps.set(i, " " + steps.get(i));
}
- return new ExplainPlan(steps);
+ return new ExplainPlan(steps, builder.build());
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/UnnestArrayPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/UnnestArrayPlan.java
index 896d1ed..19c9340 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/UnnestArrayPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/UnnestArrayPlan.java
@@ -24,6 +24,9 @@ import java.util.List;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.compile.ExplainPlan;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.execute.visitor.QueryPlanVisitor;
@@ -57,9 +60,15 @@ public class UnnestArrayPlan extends DelegateQueryPlan {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
- List<String> planSteps = delegate.getExplainPlan().getPlanSteps();
+ ExplainPlan explainPlan = delegate.getExplainPlan();
+ List<String> planSteps = explainPlan.getPlanSteps();
+ ExplainPlanAttributes explainPlanAttributes =
+ explainPlan.getPlanStepsAsAttributes();
+ ExplainPlanAttributesBuilder newBuilder =
+ new ExplainPlanAttributesBuilder(explainPlanAttributes);
planSteps.add("UNNEST");
- return new ExplainPlan(planSteps);
+ newBuilder.setAbstractExplainPlan("UNNEST");
+ return new ExplainPlan(planSteps, newBuilder.build());
}
@Override
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseGroupedAggregatingResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseGroupedAggregatingResultIterator.java
index 84d29ff..6b9f240 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseGroupedAggregatingResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseGroupedAggregatingResultIterator.java
@@ -26,6 +26,8 @@ import java.util.List;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.expression.aggregator.Aggregator;
import org.apache.phoenix.expression.aggregator.Aggregators;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -103,4 +105,9 @@ public abstract class BaseGroupedAggregatingResultIterator implements
resultIterator.explain(planSteps);
}
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ resultIterator.explain(planSteps, explainPlanAttributesBuilder);
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterator.java
index 59ab5c9..17b6372 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterator.java
@@ -17,6 +17,9 @@
*/
package org.apache.phoenix.iterate;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
+
import java.sql.SQLException;
import java.util.List;
@@ -38,4 +41,8 @@ public abstract class BaseResultIterator implements ResultIterator {
public void explain(List<String> planSteps) {
}
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
index c271487..151216c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
@@ -72,6 +72,8 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.phoenix.cache.ServerCacheClient.ServerCache;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.compile.RowProjector;
@@ -80,7 +82,6 @@ import org.apache.phoenix.compile.StatementContext;
import org.apache.phoenix.coprocessor.BaseScannerRegionObserver;
import org.apache.phoenix.coprocessor.HashJoinCacheNotFoundException;
import org.apache.phoenix.coprocessor.UngroupedAggregateRegionObserver;
-import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.exception.SQLExceptionInfo;
import org.apache.phoenix.execute.MutationState;
import org.apache.phoenix.execute.ScanPlan;
@@ -1565,6 +1566,21 @@ public abstract class BaseResultIterators extends ExplainTable implements Result
@Override
public void explain(List<String> planSteps) {
+ explainUtil(planSteps, null);
+ }
+
+ /**
+ * Utility to generate ExplainPlan steps.
+ *
+ * @param planSteps Add generated plan in list of planSteps. This argument
+ * is used to provide planSteps as whole statement consisting of
+ * list of Strings.
+ * @param explainPlanAttributesBuilder Add generated plan in attributes
+ * object. Having an API to provide planSteps as an object is easier
+ * while comparing individual attributes of ExplainPlan.
+ */
+ private void explainUtil(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
boolean displayChunkCount = context.getConnection().getQueryServices().getProps().getBoolean(
QueryServices.EXPLAIN_CHUNK_COUNT_ATTRIB,
QueryServicesOptions.DEFAULT_EXPLAIN_CHUNK_COUNT);
@@ -1575,32 +1591,65 @@ public abstract class BaseResultIterators extends ExplainTable implements Result
QueryServices.EXPLAIN_ROW_COUNT_ATTRIB,
QueryServicesOptions.DEFAULT_EXPLAIN_ROW_COUNT);
buf.append(this.splits.size()).append("-CHUNK ");
+ if (explainPlanAttributesBuilder != null) {
+ explainPlanAttributesBuilder.setSplitsChunk(this.splits.size());
+ }
if (displayRowCount && estimatedRows != null) {
buf.append(estimatedRows).append(" ROWS ");
buf.append(estimatedSize).append(" BYTES ");
+ if (explainPlanAttributesBuilder != null) {
+ explainPlanAttributesBuilder.setEstimatedRows(estimatedRows);
+ explainPlanAttributesBuilder.setEstimatedSizeInBytes(estimatedSize);
+ }
}
}
- buf.append(getName()).append(" ").append(size()).append("-WAY ");
-
- if(this.plan.getStatement().getTableSamplingRate()!=null){
- buf.append(plan.getStatement().getTableSamplingRate()/100D).append("-").append("SAMPLED ");
+ String iteratorTypeAndScanSize = getName() + " " + size() + "-WAY";
+ buf.append(iteratorTypeAndScanSize).append(" ");
+ if (explainPlanAttributesBuilder != null) {
+ explainPlanAttributesBuilder.setIteratorTypeAndScanSize(
+ iteratorTypeAndScanSize);
+ }
+
+ if (this.plan.getStatement().getTableSamplingRate() != null) {
+ Double samplingRate = plan.getStatement().getTableSamplingRate() / 100D;
+ buf.append(samplingRate).append("-").append("SAMPLED ");
+ if (explainPlanAttributesBuilder != null) {
+ explainPlanAttributesBuilder.setSamplingRate(samplingRate);
+ }
}
try {
if (plan.useRoundRobinIterator()) {
buf.append("ROUND ROBIN ");
+ if (explainPlanAttributesBuilder != null) {
+ explainPlanAttributesBuilder.setUseRoundRobinIterator(true);
+ }
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
- if(this.plan instanceof ScanPlan) {
+ if (this.plan instanceof ScanPlan) {
ScanPlan scanPlan = (ScanPlan) this.plan;
- if(scanPlan.getRowOffset().isPresent()) {
- buf.append("With RVC Offset " + "0x" + Hex.encodeHexString(scanPlan.getRowOffset().get()) + " ");
+ if (scanPlan.getRowOffset().isPresent()) {
+ String rowOffset =
+ Hex.encodeHexString(scanPlan.getRowOffset().get());
+ buf.append("With RVC Offset " + "0x")
+ .append(rowOffset)
+ .append(" ");
+ if (explainPlanAttributesBuilder != null) {
+ explainPlanAttributesBuilder.setHexStringRVCOffset(
+ "0x" + rowOffset);
+ }
}
}
- explain(buf.toString(),planSteps);
+ explain(buf.toString(), planSteps, explainPlanAttributesBuilder);
+ }
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ explainUtil(planSteps, explainPlanAttributesBuilder);
}
public Long getEstimatedRowCount() {
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ChunkedResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ChunkedResultIterator.java
index 2fb7b72..8c8f810 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ChunkedResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ChunkedResultIterator.java
@@ -26,6 +26,8 @@ import java.util.List;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.compile.StatementContext;
import org.apache.phoenix.execute.MutationState;
@@ -132,6 +134,12 @@ public class ChunkedResultIterator implements PeekingResultIterator {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ resultIterator.explain(planSteps, explainPlanAttributesBuilder);
+ }
+
+ @Override
public void close() throws SQLException {
resultIterator.close();
}
@@ -210,6 +218,12 @@ public class ChunkedResultIterator implements PeekingResultIterator {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ delegate.explain(planSteps, explainPlanAttributesBuilder);
+ }
+
+ @Override
public void close() throws SQLException {
delegate.close();
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ClientHashAggregatingResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ClientHashAggregatingResultIterator.java
index a07ea16..3a4a86c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ClientHashAggregatingResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ClientHashAggregatingResultIterator.java
@@ -35,6 +35,8 @@ import java.util.Objects;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.StatementContext;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.expression.Expression;
@@ -144,6 +146,12 @@ public class ClientHashAggregatingResultIterator
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ resultIterator.explain(planSteps, explainPlanAttributesBuilder);
+ }
+
+ @Override
public String toString() {
return "ClientHashAggregatingResultIterator [resultIterator="
+ resultIterator + ", aggregators=" + aggregators + ", groupByExpressions="
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ConcatResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ConcatResultIterator.java
index fcc88aa..6a40177 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ConcatResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ConcatResultIterator.java
@@ -20,6 +20,8 @@ package org.apache.phoenix.iterate;
import java.sql.SQLException;
import java.util.List;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.phoenix.util.ServerUtil;
@@ -93,6 +95,14 @@ public class ConcatResultIterator implements PeekingResultIterator {
}
}
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ if (resultIterators != null) {
+ resultIterators.explain(planSteps, explainPlanAttributesBuilder);
+ }
+ }
+
private PeekingResultIterator currentIterator() throws SQLException {
List<PeekingResultIterator> iterators = getIterators();
while (index < iterators.size()) {
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/CursorResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/CursorResultIterator.java
index 7ff2785..c09f2e1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/CursorResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/CursorResultIterator.java
@@ -17,6 +17,8 @@
*/
package org.apache.phoenix.iterate;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.phoenix.util.CursorUtil;
@@ -55,6 +57,14 @@ public class CursorResultIterator implements ResultIterator {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ delegate.explain(planSteps, explainPlanAttributesBuilder);
+ explainPlanAttributesBuilder.setClientCursorName(cursorName);
+ planSteps.add("CLIENT CURSOR " + cursorName);
+ }
+
+ @Override
public String toString() {
return "CursorResultIterator [cursor=" + cursorName + "]";
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/DelegateResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/DelegateResultIterator.java
index 63b3142..375e0c3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/DelegateResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/DelegateResultIterator.java
@@ -20,6 +20,8 @@ package org.apache.phoenix.iterate;
import java.sql.SQLException;
import java.util.List;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -49,4 +51,10 @@ public class DelegateResultIterator implements ResultIterator {
delegate.explain(planSteps);
}
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ delegate.explain(planSteps, explainPlanAttributesBuilder);
+ }
+
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/DistinctAggregatingResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/DistinctAggregatingResultIterator.java
index 669b75a..106acea 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/DistinctAggregatingResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/DistinctAggregatingResultIterator.java
@@ -25,6 +25,8 @@ import java.util.Set;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.compile.ColumnProjector;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.RowProjector;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.expression.aggregator.Aggregator;
@@ -158,6 +160,15 @@ public class DistinctAggregatingResultIterator implements AggregatingResultItera
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ delegate.explain(planSteps, explainPlanAttributesBuilder);
+ explainPlanAttributesBuilder.setClientDistinctFilter(
+ rowProjector.toString());
+ planSteps.add("CLIENT DISTINCT ON " + rowProjector.toString());
+ }
+
+ @Override
public Aggregator[] aggregate(Tuple result) {
return delegate.aggregate(result);
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ExplainTable.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ExplainTable.java
index 1aaa3f9..31713d9 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ExplainTable.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ExplainTable.java
@@ -31,6 +31,8 @@ import org.apache.hadoop.hbase.filter.PageFilter;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.io.TimeRange;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.compile.ScanRanges;
@@ -78,7 +80,8 @@ public abstract class ExplainTable {
this.offset = offset;
}
- private boolean explainSkipScan(StringBuilder buf) {
+ private String explainSkipScan() {
+ StringBuilder buf = new StringBuilder();
ScanRanges scanRanges = context.getScanRanges();
if (scanRanges.isPointLookup()) {
int keyCount = scanRanges.getPointLookupCount();
@@ -102,10 +105,11 @@ public abstract class ExplainTable {
} else {
buf.append("RANGE SCAN ");
}
- return scanRanges.useSkipScanFilter();
+ return buf.toString();
}
-
- protected void explain(String prefix, List<String> planSteps) {
+
+ protected void explain(String prefix, List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
StringBuilder buf = new StringBuilder(prefix);
ScanRanges scanRanges = context.getScanRanges();
Scan scan = context.getScan();
@@ -119,19 +123,40 @@ public abstract class ExplainTable {
if (OrderBy.REV_ROW_KEY_ORDER_BY.equals(orderBy)) {
buf.append("REVERSE ");
}
+ String scanTypeDetails;
if (scanRanges.isEverything()) {
- buf.append("FULL SCAN ");
+ scanTypeDetails = "FULL SCAN ";
} else {
- explainSkipScan(buf);
+ scanTypeDetails = explainSkipScan();
}
+ buf.append(scanTypeDetails);
buf.append("OVER ").append(tableRef.getTable().getPhysicalName().getString());
if (!scanRanges.isPointLookup()) {
- appendKeyRanges(buf);
+ 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(tableRef.getTable()
+ .getPhysicalName().getString());
+ 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;
@@ -154,16 +179,40 @@ public abstract class ExplainTable {
} while (filterIterator.hasNext());
}
if (whereFilter != null) {
- planSteps.add(" SERVER FILTER BY " + (firstKeyOnlyFilter == null ? "" : "FIRST KEY ONLY AND ") + whereFilter.toString());
+ String serverWhereFilter = "SERVER FILTER BY "
+ + (firstKeyOnlyFilter == null ? "" : "FIRST KEY ONLY AND ")
+ + whereFilter.toString();
+ 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");
+ }
}
if (distinctFilter != null) {
- planSteps.add(" SERVER DISTINCT PREFIX FILTER OVER "+groupBy.getExpressions().toString());
+ 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
- planSteps.add(" SERVER" + (limit == null ? "" : " TOP " + limit + " ROW" + (limit == 1 ? "" : "S"))
- + " SORTED BY " + orderBy.getOrderByExpressions().toString());
+ 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);
@@ -171,15 +220,25 @@ public abstract class ExplainTable {
if (pageFilter != null) {
planSteps.add(" SERVER " + pageFilter.getPageSize() + " ROW LIMIT");
}
+ if (explainPlanAttributesBuilder != null) {
+ explainPlanAttributesBuilder.setServerOffset(offset);
+ if (pageFilter != null) {
+ explainPlanAttributesBuilder.setServerRowLimit(
+ pageFilter.getPageSize());
+ }
+ }
}
Integer groupByLimit = null;
byte[] groupByLimitBytes = scan.getAttribute(BaseScannerRegionObserver.GROUP_BY_LIMIT);
if (groupByLimitBytes != null) {
groupByLimit = (Integer) PInteger.INSTANCE.toObject(groupByLimitBytes);
}
- groupBy.explain(planSteps, groupByLimit);
+ groupBy.explain(planSteps, groupByLimit, explainPlanAttributesBuilder);
if (scan.getAttribute(BaseScannerRegionObserver.SPECIFIC_ARRAY_INDEX) != null) {
planSteps.add(" SERVER ARRAY ELEMENT PROJECTION");
+ if (explainPlanAttributesBuilder != null) {
+ explainPlanAttributesBuilder.setServerArrayElementProjection(true);
+ }
}
}
@@ -292,11 +351,12 @@ public abstract class ExplainTable {
buf.append(',');
}
}
-
- private void appendKeyRanges(StringBuilder buf) {
+
+ private String appendKeyRanges() {
+ final StringBuilder buf = new StringBuilder();
ScanRanges scanRanges = context.getScanRanges();
if (scanRanges.isDegenerate() || scanRanges.isEverything()) {
- return;
+ return "";
}
buf.append(" [");
StringBuilder buf1 = new StringBuilder();
@@ -310,5 +370,6 @@ public abstract class ExplainTable {
buf.append(buf2);
}
buf.setCharAt(buf.length()-1, ']');
+ return buf.toString();
}
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/FilterAggregatingResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/FilterAggregatingResultIterator.java
index 5fd2028..bd47a78 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/FilterAggregatingResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/FilterAggregatingResultIterator.java
@@ -21,6 +21,8 @@ import java.sql.SQLException;
import java.util.List;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.expression.aggregator.Aggregator;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -76,9 +78,17 @@ public class FilterAggregatingResultIterator implements AggregatingResultIterat
planSteps.add("CLIENT FILTER BY " + expression.toString());
}
- @Override
- public String toString() {
- return "FilterAggregatingResultIterator [delegate=" + delegate
- + ", expression=" + expression + ", ptr=" + ptr + "]";
- }
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ delegate.explain(planSteps, explainPlanAttributesBuilder);
+ explainPlanAttributesBuilder.setClientFilterBy(expression.toString());
+ planSteps.add("CLIENT FILTER BY " + expression.toString());
+ }
+
+ @Override
+ public String toString() {
+ return "FilterAggregatingResultIterator [delegate=" + delegate
+ + ", expression=" + expression + ", ptr=" + ptr + "]";
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/FilterResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/FilterResultIterator.java
index 65bcad2..bf97782 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/FilterResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/FilterResultIterator.java
@@ -21,6 +21,8 @@ import java.sql.SQLException;
import java.util.List;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.phoenix.schema.types.PBoolean;
@@ -74,9 +76,17 @@ public class FilterResultIterator extends LookAheadResultIterator {
planSteps.add("CLIENT FILTER BY " + expression.toString());
}
- @Override
- public String toString() {
- return "FilterResultIterator [delegate=" + delegate + ", expression="
- + expression + ", ptr=" + ptr + "]";
- }
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ delegate.explain(planSteps, explainPlanAttributesBuilder);
+ explainPlanAttributesBuilder.setClientFilterBy(expression.toString());
+ planSteps.add("CLIENT FILTER BY " + expression.toString());
+ }
+
+ @Override
+ public String toString() {
+ return "FilterResultIterator [delegate=" + delegate + ", expression="
+ + expression + ", ptr=" + ptr + "]";
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/LimitingResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/LimitingResultIterator.java
index 7cf8d3e..6e1c52d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/LimitingResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/LimitingResultIterator.java
@@ -20,6 +20,8 @@ package org.apache.phoenix.iterate;
import java.sql.SQLException;
import java.util.List;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.Tuple;
/**
@@ -50,12 +52,20 @@ public class LimitingResultIterator extends DelegateResultIterator {
@Override
public void explain(List<String> planSteps) {
super.explain(planSteps);
- planSteps.add("CLIENT " + limit + " ROW LIMIT");
+ planSteps.add("CLIENT " + limit + " ROW LIMIT");
}
- @Override
- public String toString() {
- return "LimitingResultIterator [rowCount=" + rowCount + ", limit="
- + limit + "]";
- }
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ super.explain(planSteps, explainPlanAttributesBuilder);
+ explainPlanAttributesBuilder.setClientRowLimit(limit);
+ planSteps.add("CLIENT " + limit + " ROW LIMIT");
+ }
+
+ @Override
+ public String toString() {
+ return "LimitingResultIterator [rowCount=" + rowCount + ", limit="
+ + limit + "]";
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/LookAheadResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/LookAheadResultIterator.java
index 1e5f09e..f7c46d4 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/LookAheadResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/LookAheadResultIterator.java
@@ -20,6 +20,8 @@ package org.apache.phoenix.iterate;
import java.sql.SQLException;
import java.util.List;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.ResultTuple;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -38,6 +40,12 @@ abstract public class LookAheadResultIterator implements PeekingResultIterator {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ iterator.explain(planSteps, explainPlanAttributesBuilder);
+ }
+
+ @Override
public void close() throws SQLException {
iterator.close();
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/MaterializedComparableResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/MaterializedComparableResultIterator.java
index a76f1e3..5808a0e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/MaterializedComparableResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/MaterializedComparableResultIterator.java
@@ -21,6 +21,8 @@ import java.sql.SQLException;
import java.util.Comparator;
import java.util.List;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.Tuple;
/**
@@ -72,4 +74,10 @@ public class MaterializedComparableResultIterator
public void explain(List<String> planSteps) {
delegate.explain(planSteps);
}
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ delegate.explain(planSteps, explainPlanAttributesBuilder);
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/MaterializedResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/MaterializedResultIterator.java
index befaa2d..a8c75af 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/MaterializedResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/MaterializedResultIterator.java
@@ -20,6 +20,8 @@ package org.apache.phoenix.iterate;
import java.sql.SQLException;
import java.util.*;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -107,4 +109,9 @@ public class MaterializedResultIterator implements PeekingResultIterator {
@Override
public void explain(List<String> planSteps) {
}
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/MergeSortRowKeyResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/MergeSortRowKeyResultIterator.java
index 1da5142..16551b5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/MergeSortRowKeyResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/MergeSortRowKeyResultIterator.java
@@ -19,6 +19,8 @@ package org.apache.phoenix.iterate;
import java.util.List;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.phoenix.util.TupleUtil;
@@ -57,9 +59,17 @@ public class MergeSortRowKeyResultIterator extends MergeSortResultIterator {
planSteps.add("CLIENT MERGE SORT");
}
- @Override
- public String toString() {
- return "MergeSortRowKeyResultIterator [keyOffset=" + keyOffset
- + ", factor=" + factor + "]";
- }
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ resultIterators.explain(planSteps, explainPlanAttributesBuilder);
+ explainPlanAttributesBuilder.setClientSortAlgo("CLIENT MERGE SORT");
+ planSteps.add("CLIENT MERGE SORT");
+ }
+
+ @Override
+ public String toString() {
+ return "MergeSortRowKeyResultIterator [keyOffset=" + keyOffset
+ + ", factor=" + factor + "]";
+ }
}
\ No newline at end of file
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/MergeSortTopNResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/MergeSortTopNResultIterator.java
index 42429b1..eace244 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/MergeSortTopNResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/MergeSortTopNResultIterator.java
@@ -21,6 +21,8 @@ import java.sql.SQLException;
import java.util.List;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.expression.OrderByExpression;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -108,10 +110,26 @@ public class MergeSortTopNResultIterator extends MergeSortResultIterator {
}
}
- @Override
- public String toString() {
- return "MergeSortTopNResultIterator [limit=" + limit + ", count="
- + count + ", orderByColumns=" + orderByColumns + ", ptr1="
- + ptr1 + ", ptr2=" + ptr2 + ",offset=" + offset + "]";
- }
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ resultIterators.explain(planSteps, explainPlanAttributesBuilder);
+ explainPlanAttributesBuilder.setClientSortAlgo("CLIENT MERGE SORT");
+ planSteps.add("CLIENT MERGE SORT");
+ if (offset > 0) {
+ explainPlanAttributesBuilder.setClientOffset(offset);
+ planSteps.add("CLIENT OFFSET " + offset);
+ }
+ if (limit > 0) {
+ explainPlanAttributesBuilder.setClientRowLimit(limit);
+ planSteps.add("CLIENT LIMIT " + limit);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "MergeSortTopNResultIterator [limit=" + limit + ", count="
+ + count + ", orderByColumns=" + orderByColumns + ", ptr1="
+ + ptr1 + ", ptr2=" + ptr2 + ",offset=" + offset + "]";
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/OffsetResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/OffsetResultIterator.java
index db53806..5c5a6d3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/OffsetResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/OffsetResultIterator.java
@@ -20,6 +20,8 @@ package org.apache.phoenix.iterate;
import java.sql.SQLException;
import java.util.List;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.Tuple;
/**
@@ -52,6 +54,14 @@ public class OffsetResultIterator extends DelegateResultIterator {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ super.explain(planSteps, explainPlanAttributesBuilder);
+ explainPlanAttributesBuilder.setClientOffset(offset);
+ planSteps.add("CLIENT OFFSET " + offset);
+ }
+
+ @Override
public String toString() {
return "OffsetResultIterator [rowCount=" + rowCount + ", offset=" + offset + "]";
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/OrderedResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/OrderedResultIterator.java
index 5430226..a433759 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/OrderedResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/OrderedResultIterator.java
@@ -31,6 +31,8 @@ import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.execute.DescVarLengthFastByteComparisons;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.expression.OrderByExpression;
@@ -303,6 +305,19 @@ public class OrderedResultIterator implements PeekingResultIterator {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ delegate.explain(planSteps, explainPlanAttributesBuilder);
+ explainPlanAttributesBuilder.setClientOffset(offset);
+ explainPlanAttributesBuilder.setClientRowLimit(limit);
+ explainPlanAttributesBuilder.setClientSortedBy(
+ orderByExpressions.toString());
+ planSteps.add("CLIENT" + (offset == null || offset == 0 ? "" : " OFFSET " + offset)
+ + (limit == null ? "" : " TOP " + limit + " ROW" + (limit == 1 ? "" : "S"))
+ + " SORTED BY " + orderByExpressions.toString());
+ }
+
+ @Override
public String toString() {
return "OrderedResultIterator [thresholdBytes=" + thresholdBytes
+ ", limit=" + limit + ", offset=" + offset + ", delegate=" + delegate
@@ -356,6 +371,11 @@ public class OrderedResultIterator implements PeekingResultIterator {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
+ @Override
public void close() throws SQLException {
try {
queueEntries.close();
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/PeekingResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/PeekingResultIterator.java
index 9470d56..f4a193e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/PeekingResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/PeekingResultIterator.java
@@ -20,6 +20,8 @@ package org.apache.phoenix.iterate;
import java.sql.SQLException;
import java.util.List;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -51,6 +53,11 @@ public interface PeekingResultIterator extends ResultIterator {
@Override
public void explain(List<String> planSteps) {
}
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
};
/**
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ResultIterator.java
index e2127f8..f721456 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ResultIterator.java
@@ -20,6 +20,8 @@ package org.apache.phoenix.iterate;
import java.sql.SQLException;
import java.util.List;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.phoenix.util.SQLCloseable;
@@ -38,6 +40,11 @@ public interface ResultIterator extends SQLCloseable {
@Override
public void explain(List<String> planSteps) {
}
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
};
/**
@@ -49,4 +56,21 @@ public interface ResultIterator extends SQLCloseable {
public Tuple next() throws SQLException;
public void explain(List<String> planSteps);
+
+ /**
+ * Generate ExplainPlan steps and add steps as list of Strings in
+ * planSteps argument as readable statement as well as add same generated
+ * steps in explainPlanAttributesBuilder so that we prepare ExplainPlan
+ * result as an attribute object useful to retrieve individual plan step
+ * attributes.
+ *
+ * @param planSteps Add generated plan in list of planSteps. This argument
+ * is used to provide planSteps as whole statement consisting of
+ * list of Strings.
+ * @param explainPlanAttributesBuilder Add generated plan in attributes
+ * object. Having an API to provide planSteps as an object is easier
+ * while comparing individual attributes of ExplainPlan.
+ */
+ void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder);
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ResultIterators.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ResultIterators.java
index 16f8b41..8bc47cc 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ResultIterators.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ResultIterators.java
@@ -21,6 +21,8 @@ import java.sql.SQLException;
import java.util.List;
import org.apache.hadoop.hbase.client.Scan;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.query.KeyRange;
import org.apache.phoenix.util.SQLCloseable;
@@ -30,4 +32,22 @@ public interface ResultIterators extends SQLCloseable {
public List<List<Scan>> getScans();
public void explain(List<String> planSteps);
public List<PeekingResultIterator> getIterators() throws SQLException;
+
+ /**
+ * Generate ExplainPlan steps and add steps as list of Strings in
+ * planSteps argument as readable statement as well as add same generated
+ * steps in explainPlanAttributesBuilder so that we prepare ExplainPlan
+ * result as an attribute object useful to retrieve individual plan step
+ * attributes.
+ *
+ * @param planSteps Add generated plan in list of planSteps. This argument
+ * is used to provide planSteps as whole statement consisting of
+ * list of Strings.
+ * @param explainPlanAttributesBuilder Add generated plan in attributes
+ * object. Having an API to provide planSteps as an object is easier
+ * while comparing individual attributes of ExplainPlan.
+ */
+ void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder);
+
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/RoundRobinResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/RoundRobinResultIterator.java
index bc77c98..232cdd6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/RoundRobinResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/RoundRobinResultIterator.java
@@ -28,6 +28,8 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.compile.StatementContext;
import org.apache.phoenix.query.ConnectionQueryServices;
@@ -154,6 +156,14 @@ public class RoundRobinResultIterator implements ResultIterator {
}
}
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ if (resultIterators != null) {
+ resultIterators.explain(planSteps, explainPlanAttributesBuilder);
+ }
+ }
+
@VisibleForTesting
int getNumberOfParallelFetches() {
return numParallelFetches;
@@ -315,6 +325,12 @@ public class RoundRobinResultIterator implements ResultIterator {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ delegate.explain(planSteps, explainPlanAttributesBuilder);
+ }
+
+ @Override
public Tuple peek() throws SQLException {
if (tuple != null) { return tuple; }
return delegate.peek();
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/RowKeyOrderedAggregateResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/RowKeyOrderedAggregateResultIterator.java
index 3c52e51..dc72d72 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/RowKeyOrderedAggregateResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/RowKeyOrderedAggregateResultIterator.java
@@ -25,6 +25,8 @@ import java.sql.SQLException;
import java.util.List;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.expression.aggregator.Aggregator;
import org.apache.phoenix.expression.aggregator.Aggregators;
import org.apache.phoenix.schema.tuple.SingleKeyValueTuple;
@@ -104,6 +106,14 @@ public class RowKeyOrderedAggregateResultIterator extends LookAheadResultIterato
}
}
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ if (resultIterators != null) {
+ resultIterators.explain(planSteps, explainPlanAttributesBuilder);
+ }
+ }
+
private Tuple nextTuple() throws SQLException {
List<PeekingResultIterator> iterators = getIterators();
while (index < iterators.size()) {
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ScanningResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ScanningResultIterator.java
index 6c521c1..4cafb88 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ScanningResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ScanningResultIterator.java
@@ -51,6 +51,8 @@ import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.metrics.ScanMetrics;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.monitoring.CombinableMetric;
import org.apache.phoenix.monitoring.GlobalClientMetrics;
import org.apache.phoenix.monitoring.ScanMetricsHolder;
@@ -178,6 +180,11 @@ public class ScanningResultIterator implements ResultIterator {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
+ @Override
public String toString() {
return "ScanningResultIterator [scanner=" + scanner + "]";
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/SequenceResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/SequenceResultIterator.java
index 80b5401..5674a6a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/SequenceResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/SequenceResultIterator.java
@@ -20,6 +20,8 @@ package org.apache.phoenix.iterate;
import java.sql.SQLException;
import java.util.List;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.SequenceManager;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -55,9 +57,19 @@ public class SequenceResultIterator extends DelegateResultIterator {
planSteps.add("CLIENT RESERVE VALUES FROM " + nSequences + " SEQUENCE" + (nSequences == 1 ? "" : "S"));
}
- @Override
- public String toString() {
- return "SequenceResultIterator [sequenceManager=" + sequenceManager
- + "]";
- }
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ super.explain(planSteps, explainPlanAttributesBuilder);
+ int nSequences = sequenceManager.getSequenceCount();
+ explainPlanAttributesBuilder.setClientSequenceCount(nSequences);
+ planSteps.add("CLIENT RESERVE VALUES FROM " + nSequences
+ + " SEQUENCE" + (nSequences == 1 ? "" : "S"));
+ }
+
+ @Override
+ public String toString() {
+ return "SequenceResultIterator [sequenceManager=" + sequenceManager
+ + "]";
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/SerialIterators.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/SerialIterators.java
index 1693421..4fd38c5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/SerialIterators.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/SerialIterators.java
@@ -29,6 +29,8 @@ import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.phoenix.cache.ServerCacheClient.ServerCache;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.coprocessor.BaseScannerRegionObserver;
import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
@@ -207,6 +209,11 @@ public class SerialIterators extends BaseResultIterators {
public void explain(List<String> planSteps) {}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
+ @Override
public void close() throws SQLException {
if (currentIterator != null) {
currentIterator.close();
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/SpoolingResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/SpoolingResultIterator.java
index 6995e79..b2d3794 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/SpoolingResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/SpoolingResultIterator.java
@@ -36,6 +36,8 @@ import org.apache.commons.io.output.DeferredFileOutputStream;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.io.WritableUtils;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.compile.StatementContext;
import org.apache.phoenix.memory.MemoryManager;
@@ -253,6 +255,11 @@ public class SpoolingResultIterator implements PeekingResultIterator {
@Override
public void explain(List<String> planSteps) {
}
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
}
/**
@@ -354,9 +361,19 @@ public class SpoolingResultIterator implements PeekingResultIterator {
@Override
public void explain(List<String> planSteps) {
}
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
}
@Override
public void explain(List<String> planSteps) {
}
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableResultIterator.java
index c576ad8..2ae9223 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableResultIterator.java
@@ -44,6 +44,8 @@ import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.cache.ServerCacheClient.ServerCache;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.coprocessor.BaseScannerRegionObserver;
import org.apache.phoenix.coprocessor.HashJoinCacheNotFoundException;
@@ -297,4 +299,10 @@ public class TableResultIterator implements ResultIterator {
scanIterator.explain(planSteps);
}
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ scanIterator.explain(planSteps, explainPlanAttributesBuilder);
+ }
+
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableSnapshotResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableSnapshotResultIterator.java
index 6f5e2ee..9cca642 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableSnapshotResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableSnapshotResultIterator.java
@@ -28,6 +28,8 @@ import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper;
import org.apache.hadoop.hbase.util.FSUtils;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.mapreduce.util.PhoenixConfigurationUtil;
import org.apache.phoenix.monitoring.ScanMetricsHolder;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -171,9 +173,14 @@ public class TableSnapshotResultIterator implements ResultIterator {
}
}
- @Override
- public void explain(List<String> planSteps) {
- // noop
- }
+ @Override
+ public void explain(List<String> planSteps) {
+ // noop
+ }
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/UnionResultIterators.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/UnionResultIterators.java
index 910a514..a90e8a6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/UnionResultIterators.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/UnionResultIterators.java
@@ -22,6 +22,9 @@ import java.util.Collections;
import java.util.List;
import org.apache.hadoop.hbase.client.Scan;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.compile.StatementContext;
import org.apache.phoenix.monitoring.OverAllQueryMetrics;
@@ -128,8 +131,8 @@ public class UnionResultIterators implements ResultIterators {
@Override
public void explain(List<String> planSteps) {
- for (int index=0; index < iterators.size(); index++) {
- iterators.get(index).explain(planSteps);
+ for (PeekingResultIterator iterator : iterators) {
+ iterator.explain(planSteps);
}
}
@@ -137,4 +140,27 @@ public class UnionResultIterators implements ResultIterators {
public List<PeekingResultIterator> getIterators() throws SQLException {
return iterators;
}
+
+ @Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ boolean moreThanOneIters = false;
+ ExplainPlanAttributesBuilder lhsPointer = null;
+ // For more than one iterators, explainPlanAttributes will create
+ // chain of objects as lhs and rhs query plans.
+ for (PeekingResultIterator iterator : iterators) {
+ if (moreThanOneIters) {
+ ExplainPlanAttributesBuilder rhsBuilder =
+ new ExplainPlanAttributesBuilder();
+ iterator.explain(planSteps, rhsBuilder);
+ ExplainPlanAttributes rhsPlans = rhsBuilder.build();
+ lhsPointer.setRhsJoinQueryExplainPlan(rhsPlans);
+ lhsPointer = rhsBuilder;
+ } else {
+ iterator.explain(planSteps, explainPlanAttributesBuilder);
+ lhsPointer = explainPlanAttributesBuilder;
+ }
+ moreThanOneIters = true;
+ }
+ }
}
\ No newline at end of file
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/iterate/ConcatResultIteratorTest.java b/phoenix-core/src/test/java/org/apache/phoenix/iterate/ConcatResultIteratorTest.java
index 67d5cd0..106aa9d 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/iterate/ConcatResultIteratorTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/iterate/ConcatResultIteratorTest.java
@@ -29,6 +29,8 @@ import java.util.List;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.query.KeyRange;
import org.apache.phoenix.schema.tuple.SingleKeyValueTuple;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -98,6 +100,12 @@ public class ConcatResultIteratorTest {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+
+ }
+
+ @Override
public int size() {
return results.size();
}
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/iterate/MaterializedResultIterators.java b/phoenix-core/src/test/java/org/apache/phoenix/iterate/MaterializedResultIterators.java
index c4b0265..6efc211 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/iterate/MaterializedResultIterators.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/iterate/MaterializedResultIterators.java
@@ -22,6 +22,8 @@ import java.util.Collections;
import java.util.List;
import org.apache.hadoop.hbase.client.Scan;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.query.KeyRange;
/**
@@ -42,6 +44,11 @@ public class MaterializedResultIterators implements ResultIterators {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
+ @Override
public int size() {
return results.size();
}
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/iterate/MergeSortResultIteratorTest.java b/phoenix-core/src/test/java/org/apache/phoenix/iterate/MergeSortResultIteratorTest.java
index 9b2e8de..3879405 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/iterate/MergeSortResultIteratorTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/iterate/MergeSortResultIteratorTest.java
@@ -29,6 +29,8 @@ import java.util.List;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.compile.ExplainPlanAttributes
+ .ExplainPlanAttributesBuilder;
import org.apache.phoenix.query.KeyRange;
import org.apache.phoenix.schema.tuple.SingleKeyValueTuple;
import org.apache.phoenix.schema.tuple.Tuple;
@@ -79,6 +81,11 @@ public class MergeSortResultIteratorTest {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
+ @Override
public int size() {
return results.size();
}
@@ -109,6 +116,11 @@ public class MergeSortResultIteratorTest {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
+ @Override
public int size() {
return results.size();
}
@@ -172,6 +184,11 @@ public class MergeSortResultIteratorTest {
}
@Override
+ public void explain(List<String> planSteps,
+ ExplainPlanAttributesBuilder explainPlanAttributesBuilder) {
+ }
+
+ @Override
public int size() {
return results.size();
}