Skip to content

Commit 4737cbb

Browse files
committed
Clean up RelNode.explain, to make it easier to extend. A RelNode derived class can now call super.explainTerms, so only needs to describe the attributes it adds over its base class.
1 parent 02b1c86 commit 4737cbb

34 files changed

+389
-510
lines changed

‎src/main/java/net/hydromatic/optiq/rules/java/JavaRules.java‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -550,9 +550,8 @@ public PhysType getPhysType() {
550550
return physType;
551551
}
552552

553-
public void explain(RelOptPlanWriter pw)
554-
{
555-
program.explainCalc(this, pw);
553+
public RelOptPlanWriter explainTerms(RelOptPlanWriter pw) {
554+
return program.explainCalc(super.explainTerms(pw));
556555
}
557556

558557
public double getRows() {

‎src/main/java/org/eigenbase/oj/rel/IterCalcRel.java‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,8 @@ public IterCalcRel(
105105
// TODO jvs 10-May-2004: need a computeSelfCost which takes condition into
106106
// account; maybe inherit from CalcRelBase?
107107

108-
public void explain(RelOptPlanWriter pw)
109-
{
110-
program.explainCalc(this, pw);
108+
public RelOptPlanWriter explainTerms(RelOptPlanWriter pw) {
109+
return program.explainCalc(super.explainTerms(pw));
111110
}
112111

113112
protected String computeDigest()

‎src/main/java/org/eigenbase/rel/AbstractRelNode.java‎

Lines changed: 27 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,20 @@ public RelOptCost computeSelfCost(RelOptPlanner planner)
299299
0);
300300
}
301301

302-
public void explain(RelOptPlanWriter pw)
303-
{
304-
pw.explain(this, Util.emptyStringArray, Util.emptyObjectArray);
302+
public final void explain(RelOptPlanWriter pw) {
303+
explainTerms(pw).done(this);
304+
}
305+
306+
/** Describes the inputs and attributes of this relational expression.
307+
* Each node should call {@code super.explainTerms}, then call the
308+
* {@link RelOptPlanWriter#input(String, RelNode)}
309+
* and {@link RelOptPlanWriter#item(String, Object)} methods for each input
310+
* and attribute.
311+
*
312+
* @param pw Plan writer
313+
*/
314+
public RelOptPlanWriter explainTerms(RelOptPlanWriter pw) {
315+
return pw;
305316
}
306317

307318
public RelNode onRegister(RelOptPlanner planner)
@@ -380,8 +391,6 @@ public RelOptTable getTable()
380391

381392
/**
382393
* Computes the digest. Does not modify this object.
383-
*
384-
* @post return != null
385394
*/
386395
protected String computeDigest()
387396
{
@@ -391,54 +400,28 @@ protected String computeDigest()
391400
new PrintWriter(sw),
392401
SqlExplainLevel.DIGEST_ATTRIBUTES)
393402
{
394-
public void explain(
395-
RelNode rel,
396-
String [] terms,
397-
Object [] values)
403+
protected void explain_(
404+
RelNode rel, List<Pair<String, Object>> values)
398405
{
399-
List<RelNode> inputs = rel.getInputs();
400-
RexNode [] childExps = rel.getChildExps();
401-
assert terms.length
402-
== (inputs.size() + childExps.length + values.length)
403-
: "terms.length="
404-
+ terms.length
405-
+ " inputs.length=" + inputs.size()
406-
+ " childExps.length=" + childExps.length
407-
+ " values.length=" + values.length;
408-
write(getRelTypeName());
409-
410-
for (int i = 0; i < traitSet.size(); i++) {
411-
write(".");
412-
write(traitSet.getTrait(i).toString());
406+
pw.write(getRelTypeName());
407+
408+
for (RelTrait trait : traitSet) {
409+
pw.write(".");
410+
pw.write(trait.toString());
413411
}
414412

415-
write("(");
413+
pw.write("(");
416414
int j = 0;
417-
for (int i = 0; i < inputs.size(); i++) {
418-
if (j > 0) {
419-
write(",");
420-
}
421-
write(terms[j++] + "=" + inputs.get(i).getDigest());
422-
}
423-
for (int i = 0; i < childExps.length; i++) {
424-
if (j > 0) {
425-
write(",");
426-
}
427-
RexNode childExp = childExps[i];
428-
write(terms[j++] + "=" + childExp.toString());
429-
}
430-
for (int i = 0; i < values.length; i++) {
431-
Object value = values[i];
432-
if (j > 0) {
433-
write(",");
415+
for (Pair<String, Object> value : values) {
416+
if (j++ > 0) {
417+
pw.write(",");
434418
}
435-
write(terms[j++] + "=" + value);
419+
pw.write(value.left + "=" + value.right);
436420
}
437-
write(")");
421+
pw.write(")");
438422
}
439423
};
440424
explain(pw);
441-
pw.flush();
442425
return sw.toString();
443426
}
444427
}

‎src/main/java/org/eigenbase/rel/AggregateRelBase.java‎

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.eigenbase.sql.validate.*;
2828
import org.eigenbase.util.*;
2929

30+
import net.hydromatic.linq4j.Ord;
31+
3032

3133
/**
3234
* <code>AggregateRelBase</code> is an abstract base class for implementations
@@ -120,39 +122,19 @@ public BitSet getGroupSet()
120122
return groupSet;
121123
}
122124

123-
public void explain(RelOptPlanWriter pw)
124-
{
125-
List<String> names = new ArrayList<String>();
126-
List<Object> values = new ArrayList<Object>();
127-
populateExplainAttributes(names, values);
128-
pw.explain(this, names, values);
129-
}
130-
131-
/**
132-
* Populates attributes for EXPLAIN.
133-
*
134-
* @param names Names of attributes
135-
* @param values Values of attributes
136-
*/
137-
protected void populateExplainAttributes(
138-
List<String> names,
139-
List<Object> values)
140-
{
141-
names.add("child");
142-
names.add("group");
143-
values.add(groupSet);
144-
int i = -1;
145-
for (AggregateCall aggCall : aggCalls) {
146-
++i;
125+
public RelOptPlanWriter explainTerms(RelOptPlanWriter pw) {
126+
super.explainTerms(pw)
127+
.item("group", groupSet);
128+
for (Ord<AggregateCall> ord : Ord.zip(aggCalls)) {
147129
final String name;
148-
if (aggCall.getName() != null) {
149-
name = aggCall.getName();
130+
if (ord.e.getName() != null) {
131+
name = ord.e.getName();
150132
} else {
151-
name = "agg#" + i;
133+
name = "agg#" + ord.i;
152134
}
153-
names.add(name);
154-
values.add(aggCall);
135+
pw.item(name, ord.e);
155136
}
137+
return pw;
156138
}
157139

158140
// implement RelNode

‎src/main/java/org/eigenbase/rel/CalcRelBase.java‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,8 @@ public RelOptCost computeSelfCost(RelOptPlanner planner)
129129
return RexNode.EMPTY_ARRAY;
130130
}
131131

132-
public void explain(RelOptPlanWriter pw)
133-
{
134-
program.explainCalc(this, pw);
132+
public RelOptPlanWriter explainTerms(RelOptPlanWriter pw) {
133+
return program.explainCalc(super.explainTerms(pw));
135134
}
136135
}
137136

‎src/main/java/org/eigenbase/rel/CorrelatorRel.java‎

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,9 @@ public CorrelatorRel copy(
120120
joinType);
121121
}
122122

123-
public void explain(RelOptPlanWriter pw)
124-
{
125-
pw.explain(
126-
this,
127-
new String[] {
128-
"left", "right", "condition", "joinType", "correlations"
129-
},
130-
new Object[] {
131-
joinType.name().toLowerCase(),
132-
correlations
133-
});
123+
public RelOptPlanWriter explainTerms(RelOptPlanWriter pw) {
124+
return super.explainTerms(pw)
125+
.item("correlations", correlations);
134126
}
135127

136128
/**

‎src/main/java/org/eigenbase/rel/EmptyRel.java‎

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,15 @@ public double getRows()
9393
}
9494

9595
// implement RelNode
96-
public void explain(RelOptPlanWriter pw)
97-
{
98-
if (pw.getDetailLevel() == SqlExplainLevel.DIGEST_ATTRIBUTES) {
96+
public RelOptPlanWriter explainTerms(RelOptPlanWriter pw) {
97+
return super.explainTerms(pw)
9998
// For rel digest, include the row type to discriminate
10099
// this from other empties with different row types.
101-
pw.explain(
102-
this,
103-
new String[] { "type", },
104-
new Object[] { rowType });
105-
} else {
106100
// For normal EXPLAIN PLAN, omit the type.
107-
super.explain(pw);
108-
}
101+
.itemIf(
102+
"type",
103+
rowType,
104+
pw.getDetailLevel() == SqlExplainLevel.DIGEST_ATTRIBUTES);
109105
}
110106
}
111107

‎src/main/java/org/eigenbase/rel/FilterRelBase.java‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,9 @@ public static double estimateFilteredRows(RelNode child, RexNode condition)
107107
* RelMetadataQuery.getSelectivity(child, condition);
108108
}
109109

110-
public void explain(RelOptPlanWriter pw)
111-
{
112-
pw.explain(
113-
this,
114-
new String[] { "child", "condition" });
110+
public RelOptPlanWriter explainTerms(RelOptPlanWriter pw) {
111+
return super.explainTerms(pw)
112+
.item("condition", condition);
115113
}
116114
}
117115

‎src/main/java/org/eigenbase/rel/JoinRel.java‎

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -146,22 +146,16 @@ public JoinRel copy(
146146
systemFieldList);
147147
}
148148

149-
public void explain(RelOptPlanWriter pw)
149+
public RelOptPlanWriter explainTerms(RelOptPlanWriter pw)
150150
{
151151
// NOTE jvs 14-Mar-2006: Do it this way so that semijoin state
152152
// don't clutter things up in optimizers that don't use semijoins
153153
if (!semiJoinDone) {
154-
super.explain(pw);
155-
return;
154+
return super.explainTerms(pw);
156155
}
157-
pw.explain(
158-
this,
159-
new String[] {
160-
"left", "right", "condition", "joinType", "semiJoinDone"
161-
},
162-
new Object[] {
163-
joinType.name().toLowerCase(), semiJoinDone
164-
});
156+
return super.explainTerms(pw)
157+
.item("joinType", joinType.name().toLowerCase())
158+
.item("semiJoinDone", semiJoinDone);
165159
}
166160

167161
/**

‎src/main/java/org/eigenbase/rel/JoinRelBase.java‎

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -201,18 +201,16 @@ public void childrenAccept(RelVisitor visitor)
201201
visitor.visit(right, 1, this);
202202
}
203203

204-
public void explain(RelOptPlanWriter pw)
205-
{
206-
final List<String> nameList =
207-
new ArrayList<String>(Arrays.asList("left", "right", "condition"));
208-
final List<Object> valueList = new ArrayList<Object>();
209-
nameList.add("joinType");
210-
valueList.add(joinType.name().toLowerCase());
211-
if (!getSystemFieldList().isEmpty()) {
212-
nameList.add("systemFields");
213-
valueList.add(getSystemFieldList());
214-
}
215-
pw.explain(this, nameList, valueList);
204+
public RelOptPlanWriter explainTerms(RelOptPlanWriter pw) {
205+
return super.explainTerms(pw)
206+
.input("left", left)
207+
.input("right", right)
208+
.item("condition", condition)
209+
.item("joinType", joinType.name().toLowerCase())
210+
.itemIf(
211+
"systemFields",
212+
getSystemFieldList(),
213+
!getSystemFieldList().isEmpty());
216214
}
217215

218216
public void registerStoppedVariable(String name)

0 commit comments

Comments
 (0)