Skip to content

Commit b166b9a

Browse files
committed
[CALCITE-4004] Show RelOptRuleOperand description in debugger to facilitate debugging
To facilitate IDE shows the operand description in the debugger, override Object.toString() in RelOptRuleOperand, return the root operand description, but highlight current operand's matches class with '*' in the description. e.g. The following are examples of rule operand description for the operands that match with LogicalFilter. - SemiJoinRule:project: Project(Join(*RelNode*, Aggregate)) - ProjectFilterTransposeRule: LogicalProject(*LogicalFilter*) - FilterProjectTransposeRule: *Filter*(Project) - ReduceExpressionsRule(Filter): *LogicalFilter* - PruneEmptyJoin(right): Join(*RelNode*, Values) Close #1978
1 parent 2b1254b commit b166b9a

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

core/src/main/java/org/apache/calcite/plan/RelOptRuleOperand.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,70 @@ public boolean equals(Object obj) {
184184
&& this.children.equals(that.children);
185185
}
186186

187+
/**
188+
* <b>FOR DEBUG ONLY.</b>
189+
*
190+
* <p>To facilitate IDE shows the operand description in the debugger,
191+
* returns the root operand description, but highlight current
192+
* operand's matched class with '*' in the description.</p>
193+
*
194+
* <p>e.g. The following are examples of rule operand description for
195+
* the operands that match with {@code LogicalFilter}.</p>
196+
*
197+
* <ul>
198+
* <li>SemiJoinRule:project: Project(Join(*RelNode*, Aggregate))</li>
199+
* <li>ProjectFilterTransposeRule: LogicalProject(*LogicalFilter*)</li>
200+
* <li>FilterProjectTransposeRule: *Filter*(Project)</li>
201+
* <li>ReduceExpressionsRule(Filter): *LogicalFilter*</li>
202+
* <li>PruneEmptyJoin(right): Join(*RelNode*, Values)</li>
203+
* </ul>
204+
*
205+
* @see #describeIt(RelOptRuleOperand)
206+
*/
207+
@Override public String toString() {
208+
RelOptRuleOperand root = this;
209+
while (root.parent != null) {
210+
root = root.parent;
211+
}
212+
StringBuilder s = root.describeIt(this);
213+
return s.toString();
214+
}
215+
216+
/**
217+
* Returns this rule operand description, and highlight the operand's
218+
* class name with '*' if {@code that} operand equals current operand.
219+
*
220+
* @param that The rule operand that needs to be highlighted
221+
* @return The string builder that describes this rule operand
222+
* @see #toString()
223+
*/
224+
private StringBuilder describeIt(RelOptRuleOperand that) {
225+
StringBuilder s = new StringBuilder();
226+
if (parent == null) {
227+
s.append(rule).append(": ");
228+
}
229+
if (this == that) {
230+
s.append('*');
231+
}
232+
s.append(clazz.getSimpleName());
233+
if (this == that) {
234+
s.append('*');
235+
}
236+
if (children != null && !children.isEmpty()) {
237+
s.append('(');
238+
boolean first = true;
239+
for (RelOptRuleOperand child : children) {
240+
if (!first) {
241+
s.append(", ");
242+
}
243+
s.append(child.describeIt(that));
244+
first = false;
245+
}
246+
s.append(')');
247+
}
248+
return s;
249+
}
250+
187251
/**
188252
* @return relational expression class matched by this operand
189253
*/

0 commit comments

Comments
 (0)