OmniSciDB  95562058bd
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MapDRelJsonWriter.java
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.apache.calcite.rel.externalize;
18 
19 import com.google.common.collect.ImmutableList;
20 
21 import org.apache.calcite.rel.RelNode;
22 import org.apache.calcite.rel.RelWriter;
23 import org.apache.calcite.rel.core.TableScan;
24 import org.apache.calcite.rel.hint.RelHint;
25 import org.apache.calcite.rel.logical.*;
26 import org.apache.calcite.rel.type.RelDataType;
27 import org.apache.calcite.sql.SqlExplainLevel;
28 import org.apache.calcite.util.JsonBuilder;
29 import org.apache.calcite.util.Pair;
30 import org.apache.commons.text.StringEscapeUtils;
31 
32 import java.util.*;
33 import java.util.stream.Collectors;
34 
35 final class EscapedStringJsonBuilder extends JsonBuilder {
36  @Override
37  public void append(StringBuilder buf, int indent, Object o) {
38  if (o instanceof String) {
39  buf.append('"').append(StringEscapeUtils.escapeJson((String) o)).append('"');
40  } else {
41  super.append(buf, indent, o);
42  }
43  }
44 }
45 
51 public class MapDRelJsonWriter implements RelWriter {
52  //~ Instance fields ----------------------------------------------------------
53 
55  private final MapDRelJson relJson;
56  private final Map<RelNode, String> relIdMap = new IdentityHashMap<RelNode, String>();
57  private final List<Object> relList;
58  private final List<Pair<String, Object>> values = new ArrayList<Pair<String, Object>>();
59  private String previousId;
60 
61  //~ Constructors -------------------------------------------------------------
62 
63  public MapDRelJsonWriter() {
65  relList = jsonBuilder.list();
67  }
68 
69  //~ Methods ------------------------------------------------------------------
70 
71  protected void explain_(RelNode rel, List<Pair<String, Object>> values) {
72  final Map<String, Object> map = jsonBuilder.map();
73 
74  map.put("id", null); // ensure that id is the first attribute
75  map.put("relOp", relJson.classToTypeName(rel.getClass()));
76  if (rel instanceof TableScan) {
77  RelDataType row_type = ((TableScan) rel).getTable().getRowType();
78  List<String> field_names = row_type.getFieldNames();
79  map.put("fieldNames", field_names);
80  }
81  if (rel instanceof LogicalAggregate) {
82  map.put("fields", rel.getRowType().getFieldNames());
83  }
84  if (rel instanceof LogicalTableModify) {
85  // FIX-ME: What goes here?
86  }
87 
88  // handle hints
89  if (deliverHints(rel)) {
90  map.put("hints", explainHints(rel));
91  }
92 
93  for (Pair<String, Object> value : values) {
94  if (value.right instanceof RelNode) {
95  continue;
96  }
97  put(map, value.left, value.right);
98  }
99  // omit 'inputs: ["3"]' if "3" is the preceding rel
100  final List<Object> list = explainInputs(rel.getInputs());
101  if (list.size() != 1 || !list.get(0).equals(previousId)) {
102  map.put("inputs", list);
103  }
104 
105  final String id = Integer.toString(relIdMap.size());
106  relIdMap.put(rel, id);
107  map.put("id", id);
108 
109  relList.add(map);
110  previousId = id;
111  }
112 
113  private void put(Map<String, Object> map, String name, Object value) {
114  map.put(name, relJson.toJson(value));
115  }
116 
117  private List<Object> explainInputs(List<RelNode> inputs) {
118  final List<Object> list = jsonBuilder.list();
119  for (RelNode input : inputs) {
120  String id = relIdMap.get(input);
121  if (id == null) {
122  input.explain(this);
123  id = previousId;
124  }
125  list.add(id);
126  }
127  return list;
128  }
129 
130  private boolean deliverHints(RelNode rel) {
131  if (rel instanceof LogicalTableScan) {
132  LogicalTableScan node = (LogicalTableScan) rel;
133  if (!node.getHints().isEmpty()) {
134  return true;
135  } else {
136  return false;
137  }
138  } else if (rel instanceof LogicalAggregate) {
139  LogicalAggregate node = (LogicalAggregate) rel;
140  if (!node.getHints().isEmpty()) {
141  return true;
142  } else {
143  return false;
144  }
145  } else if (rel instanceof LogicalJoin) {
146  LogicalJoin node = (LogicalJoin) rel;
147  if (!node.getHints().isEmpty()) {
148  return true;
149  } else {
150  return false;
151  }
152  } else if (rel instanceof LogicalProject) {
153  LogicalProject node = (LogicalProject) rel;
154  if (!node.getHints().isEmpty()) {
155  return true;
156  } else {
157  return false;
158  }
159  } else if (rel instanceof LogicalCalc) {
160  LogicalCalc node = (LogicalCalc) rel;
161  if (!node.getHints().isEmpty()) {
162  return true;
163  } else {
164  return false;
165  }
166  }
167  return false;
168  }
169 
170  private String explainHints(RelNode rel) {
171  List<String> explained = new ArrayList<>();
172  if (rel instanceof LogicalTableScan) {
173  LogicalTableScan node = (LogicalTableScan) rel;
174  node.getHints().stream().forEach(s -> explained.add(s.toString().toLowerCase()));
175  } else if (rel instanceof LogicalAggregate) {
176  LogicalAggregate node = (LogicalAggregate) rel;
177  node.getHints().stream().forEach(s -> explained.add(s.toString().toLowerCase()));
178  } else if (rel instanceof LogicalJoin) {
179  LogicalJoin node = (LogicalJoin) rel;
180  node.getHints().stream().forEach(s -> explained.add(s.toString().toLowerCase()));
181  } else if (rel instanceof LogicalProject) {
182  LogicalProject node = (LogicalProject) rel;
183  node.getHints().stream().forEach(s -> explained.add(s.toString().toLowerCase()));
184  } else if (rel instanceof LogicalCalc) {
185  LogicalCalc node = (LogicalCalc) rel;
186  node.getHints().stream().forEach(s -> explained.add(s.toString().toLowerCase()));
187  }
188  return explained.stream().collect(Collectors.joining("|"));
189  }
190 
191  public final void explain(RelNode rel, List<Pair<String, Object>> valueList) {
192  explain_(rel, valueList);
193  }
194 
195  public SqlExplainLevel getDetailLevel() {
196  return SqlExplainLevel.ALL_ATTRIBUTES;
197  }
198 
199  public RelWriter input(String term, RelNode input) {
200  return this;
201  }
202 
203  public RelWriter item(String term, Object value) {
204  values.add(Pair.of(term, value));
205  return this;
206  }
207 
208  private List<Object> getList(List<Pair<String, Object>> values, String tag) {
209  for (Pair<String, Object> value : values) {
210  if (value.left.equals(tag)) {
211  // noinspection unchecked
212  return (List<Object>) value.right;
213  }
214  }
215  final List<Object> list = new ArrayList<Object>();
216  values.add(Pair.of(tag, (Object) list));
217  return list;
218  }
219 
220  public RelWriter itemIf(String term, Object value, boolean condition) {
221  if (condition) {
222  item(term, value);
223  }
224  return this;
225  }
226 
227  public RelWriter done(RelNode node) {
228  final List<Pair<String, Object>> valuesCopy = ImmutableList.copyOf(values);
229  values.clear();
230  explain_(node, valuesCopy);
231  return this;
232  }
233 
234  public boolean nest() {
235  return true;
236  }
237 
242  public String asString() {
243  return jsonBuilder.toJsonString(asJsonMap());
244  }
245 
246  public Map<String, Object> asJsonMap() {
247  final Map<String, Object> map = jsonBuilder.map();
248  map.put("rels", relList);
249  return map;
250  }
251 }
252 
253 // End RelJsonWriter.java
void explain_(RelNode rel, List< Pair< String, Object >> values)
List< Object > getList(List< Pair< String, Object >> values, String tag)
List< Object > explainInputs(List< RelNode > inputs)
void append(StringBuilder buf, int indent, Object o)
final void explain(RelNode rel, List< Pair< String, Object >> valueList)
RelWriter itemIf(String term, Object value, boolean condition)
string name
Definition: setup.py:35
void put(Map< String, Object > map, String name, Object value)