17 package org.apache.calcite.rel.externalize;
19 import com.google.common.collect.ImmutableList;
21 import org.apache.calcite.avatica.util.Spacer;
22 import org.apache.calcite.linq4j.Ord;
23 import org.apache.calcite.plan.RelOptTable;
24 import org.apache.calcite.rel.RelNode;
25 import org.apache.calcite.rel.RelWriter;
26 import org.apache.calcite.rel.core.AggregateCall;
27 import org.apache.calcite.rel.logical.LogicalAggregate;
28 import org.apache.calcite.rel.metadata.RelColumnOrigin;
29 import org.apache.calcite.rel.metadata.RelMetadataQuery;
30 import org.apache.calcite.rex.RexInputRef;
31 import org.apache.calcite.rex.RexNode;
32 import org.apache.calcite.rex.RexShuttle;
33 import org.apache.calcite.sql.SqlExplainLevel;
34 import org.apache.calcite.util.Pair;
35 import org.checkerframework.checker.nullness.qual.Nullable;
37 import java.io.PrintWriter;
46 protected final PrintWriter
pw;
49 protected final Spacer
spacer =
new Spacer();
50 private final List<Pair<String, @Nullable Object>>
values =
new ArrayList<>();
55 this(
pw, SqlExplainLevel.EXPPLAN_ATTRIBUTES,
true);
68 RelMetadataQuery mq, RelNode rel,
int targetColumnIndex) {
69 Set<RelColumnOrigin> columnOrigins =
new HashSet<>();
70 Map<String, Set<String>> originInfoMap =
new HashMap<>();
71 Set<String> originInfo =
new HashSet<>();
73 if (!rel.getInputs().isEmpty()) {
74 RelNode sourceNode = rel.getInputs().size() == 1 ? rel.getInput(0) : rel;
75 columnOrigins = mq.getColumnOrigins(sourceNode, targetColumnIndex);
77 for (RelColumnOrigin rco : columnOrigins) {
78 RelOptTable relOptTable = rco.getOriginTable();
79 String dbName = relOptTable.getQualifiedName().
get(0);
80 String tableName = relOptTable.getQualifiedName().
get(1);
81 String colName = relOptTable.getRowType()
83 .get(rco.getOriginColumnOrdinal())
85 String key =
"$" + targetColumnIndex;
86 String info =
"db:" + dbName +
",tableName:" + tableName +
",colName:" + colName;
87 if (originInfoMap.containsKey(key)) {
88 originInfoMap.get(key).add(info);
90 Set<String> originList =
new HashSet<>();
92 originInfoMap.put(key, originList);
95 }
catch (Exception ex) {
96 throw new RuntimeException(
"EXPLAIN CALCITE DETAILED error: " + ex.getMessage());
99 for (Map.Entry<String, Set<String>> entry : originInfoMap.entrySet()) {
101 for (String colInfo : entry.getValue()) {
102 if (entry.getValue().size() > 1) {
103 originInfo.add(entry.getKey() +
"-" + index +
"->" + colInfo);
105 originInfo.add(entry.getKey() +
"->" + colInfo);
113 protected void explain_(RelNode rel, List<Pair<String, @Nullable Object>>
values) {
114 List<RelNode> inputs = rel.getInputs();
115 final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
122 StringBuilder s =
new StringBuilder();
125 s.append(rel.getId()).append(
":");
127 s.append(rel.getRelTypeName());
128 if (
detailLevel != SqlExplainLevel.NO_ATTRIBUTES) {
130 for (Pair<String, @Nullable Object> value :
values) {
131 if (value.right instanceof RelNode) {
139 s.append(value.left).
append(
"=[").append(value.right).
append(
"]");
147 s.append(
": rowcount = ")
148 .
append(mq.getRowCount(rel))
149 .
append(
", cumulative cost = ")
150 .append(mq.getCumulativeCost(rel));
156 case NON_COST_ATTRIBUTES:
161 s.append(
", id = ").
append(rel.getId());
167 Set<String> originInfo =
new HashSet<>();
168 if (rel instanceof LogicalAggregate) {
169 LogicalAggregate aggregate = (LogicalAggregate) rel;
170 for (AggregateCall aggCall : aggregate.getAggCallList()) {
171 for (
int expressionIndex : aggCall.getArgList()) {
176 rel.accept(
new RexShuttle() {
178 public RexNode visitInputRef(
final RexInputRef inputRef) {
184 if (!originInfo.isEmpty()) {
187 for (String info : originInfo) {
188 s.append(
"[").
append(info).append(
"]");
189 if (index < originInfo.size()) {
203 for (RelNode input : inputs) {
209 public final void explain(RelNode rel, List<Pair<String, @Nullable Object>> valueList) {
219 public RelWriter
item(String term, @Nullable Object value) {
220 values.add(Pair.of(term, value));
225 public RelWriter
done(RelNode node) {
227 final List<Pair<String, @Nullable Object>> valuesCopy = ImmutableList.copyOf(
values);
236 if (
values.size() > 0 && values.get(0).left.equals(
"subset")) {
239 for (RelNode input : node.getInputs()) {
240 assert values.get(i).right == input;
251 final StringBuilder buf =
new StringBuilder(
"(");
252 for (Ord<Pair<String, @Nullable Object>> ord : Ord.zip(
values)) {
256 buf.append(ord.e.left).
append(
"=[").append(ord.e.right).
append(
"]");
259 return buf.toString();
size_t append(FILE *f, const size_t size, const int8_t *buf)
Appends the specified number of bytes to the end of the file f from buf.
Set< String > collectRelColumnOrigin(RelMetadataQuery mq, RelNode rel, int targetColumnIndex)
final void explain(RelNode rel, List< Pair< String,@Nullable Object >> valueList)
final List< Pair< String,@Nullable Object > > values
SqlExplainLevel getDetailLevel()
void explainInputs(List< RelNode > inputs)
final SqlExplainLevel detailLevel
RelWriter item(String term,@Nullable Object value)
HeavyDBRelWriterImpl(PrintWriter pw)
void explain_(RelNode rel, List< Pair< String,@Nullable Object >> values)
boolean checkInputsPresentInExplain(RelNode node)
final boolean withIdPrefix
HeavyDBRelWriterImpl(PrintWriter pw, SqlExplainLevel detailLevel, boolean withIdPrefix)
RelWriter done(RelNode node)