[ 
https://issues.apache.org/jira/browse/PHOENIX-1580?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14393020#comment-14393020
 ] 

James Taylor commented on PHOENIX-1580:
---------------------------------------

Thanks for the revisions, [~ayingshu]. Here's some more feedback:
- Passing through the tableRef to UnionPlan as you're doing is fine.
- In UnionCompiler, create static constant final PName member variables for the 
dummy table name and schema name so that you're not instantiating these again 
and again. I'd recommend calling them UNION_FAMILY_NAME, UNION_TABLE_NAME, and 
UNION_SCHEMA_NAME. We'll use the same names when UNION is implemented versus 
UNION ALL, so no need to have ALL in them.
{code}
+    public static TableRef contructSchemaTable(PhoenixStatement statement, 
QueryPlan plan) throws SQLException {
+        List<PColumn> projectedColumns = new ArrayList<PColumn>();
+        for (int i=0; i< plan.getProjector().getColumnCount(); i++) {
+            ColumnProjector colProj = 
plan.getProjector().getColumnProjector(i);
+            Expression sourceExpression = colProj.getExpression();
+            PColumnImpl projectedColumn = new 
PColumnImpl(PNameFactory.newName(colProj.getName().getBytes()), 
PNameFactory.newName(DUMMY_FAMILY.getBytes()),
+                    sourceExpression.getDataType(), 
sourceExpression.getMaxLength(), sourceExpression.getScale(), 
sourceExpression.isNullable(),
+                    i, sourceExpression.getSortOrder(), 500, null, false, 
sourceExpression.toString());
+            projectedColumns.add(projectedColumn);
+        }
+        Long scn = statement.getConnection().getSCN();
+        PTable tempTable = 
PTableImpl.makePTable(statement.getConnection().getTenantId(), 
PNameFactory.newName(UNION_ALL_SCHEMA.getBytes()), 
PNameFactory.newName(UNION_ALL_TABLE.getBytes()), 
+                PTableType.SUBQUERY, null, HConstants.LATEST_TIMESTAMP, scn == 
null ? HConstants.LATEST_TIMESTAMP : scn, null, null, projectedColumns, null, 
null, null,
+                        true, null, null, null, true, true, true, null, null, 
null);
+        TableRef tableRef = new TableRef(null, tempTable, 0, false);
+        return tableRef;
+    }
{code}
- In the above code, construct your PName like this as it prevents a String 
from being created again:
{code}
 new PColumnImpl(PNameFactory.newName(colProj.getName())
{code}
- In UnionPlan, declare these member variables as constants. When you calculate 
isDegenerate just use a local variable in the constructor and initialize the 
member variables once with the final result:
{code}
+    private boolean isDegenerate = true;
+    private final List<QueryPlan> plans;
{code}
- For the explain plan, you've essentially implemented part of the logic twice, 
in two different ways. Once in UnionPlan.getExplainPlan() where you loop over 
the query plans:
{code}
+    @Override
+    public ExplainPlan getExplainPlan() throws SQLException {
+        List<String> steps = new ArrayList<String>();
+        steps.add("UNION ALL " + iterators.size() + " queries\n");
+        for (QueryPlan plan : this.getPlans()) {
+            List<String> planSteps = plan.getExplainPlan().getPlanSteps();
+            steps.addAll(planSteps);   
+        } 
{code}
And then the same logic again in UnionResultIterators.explain():
{code}
+    @Override
+    public void explain(List<String> planSteps) {
+        for (int index=0; index < iterators.size(); index++) {
+            iterators.get(index).explain(planSteps);
+        } 
+    }
{code}
Although both are correct, the former is much easier to understand. So I 
recommend you implement explain like this instead:
{code}
+    @Override
+    public void explain(List<String> planSteps) {
+        for (QueryPlan plan : plans) {
+            List<String> planSteps = plan.getExplainPlan().getPlanSteps();
+            steps.addAll(planSteps);   
+        } 
+    }
{code}
and modify the UnionPlan.getExplainPlan() to delegate to UnionResultIterators 
as you're already doing for many of the calls:
{code}
+    @Override
+    public ExplainPlan getExplainPlan() throws SQLException {
+        List<String> steps = new ArrayList<String>();
+        steps.add("UNION ALL " + iterators.size() + " queries\n");
+        iterators.explain(steps);
+        if (!orderBy.getOrderByExpressions().isEmpty()) {
+            steps.add("CLIENT" + (limit == null ? "" : " TOP " + limit + " 
ROW"  + (limit == 1 ? "" : "S"))  + " SORTED BY " + 
orderBy.getOrderByExpressions().toString());
+        } else if (limit != null) {
+            steps.add("CLIENT " + limit + " ROW LIMIT");
+        }
+
+        return new ExplainPlan(steps);
+    }
{code}
- In UnionResultIterators, size all the lists in the constructor, as you have a 
good idea of what the size will be:
{code}
+public class UnionResultIterators implements ResultIterators {
+    private final List<KeyRange> splits = new ArrayList<KeyRange>();
+    private final List<List<Scan>> scans = new ArrayList<List<Scan>>();
+    private final List<PeekingResultIterator> iterators = new 
ArrayList<PeekingResultIterator>();
+    private final List<QueryPlan> plans;
+
+    public UnionResultIterators(List<QueryPlan> plans) throws SQLException {
+        this.plans = plans;
+        for (QueryPlan plan : this.plans) {
+            iterators.add(LookAheadResultIterator.wrap(plan.iterator()));
+            if (plan.getSplits() != null)
+                splits.addAll(plan.getSplits());
+            if (plan.getScans() != null)
+                scans.addAll(plan.getScans());
+        }
+    }
+
{code}

> Support UNION ALL
> -----------------
>
>                 Key: PHOENIX-1580
>                 URL: https://issues.apache.org/jira/browse/PHOENIX-1580
>             Project: Phoenix
>          Issue Type: Bug
>            Reporter: Alicia Ying Shu
>            Assignee: Alicia Ying Shu
>         Attachments: PHOENIX-1580-grammar.patch, Phoenix-1580-v1.patch, 
> Phoenix-1580-v2.patch, Phoenix-1580-v3.patch, Phoenix-1580-v4.patch, 
> Phoenix-1580-v5.patch, Phoenix-1580-v6.patch, phoenix-1580-v1-wipe.patch, 
> phoenix-1580.patch, unionall-wipe.patch
>
>
> Select * from T1
> UNION ALL
> Select * from T2



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to