OmniSciDB  340b00dbf6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MapDPlanner.java
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to you under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.calcite.prepare;
18 
19 import com.google.common.collect.ImmutableList;
23 
24 import org.apache.calcite.config.CalciteConnectionConfig;
25 import org.apache.calcite.config.CalciteConnectionConfigImpl;
26 import org.apache.calcite.config.CalciteConnectionProperty;
27 import org.apache.calcite.jdbc.CalciteSchema;
28 import org.apache.calcite.linq4j.function.Functions;
29 import org.apache.calcite.plan.Context;
30 import org.apache.calcite.plan.RelOptCluster;
31 import org.apache.calcite.plan.RelOptCostImpl;
32 import org.apache.calcite.plan.RelOptLattice;
33 import org.apache.calcite.plan.RelOptMaterialization;
34 import org.apache.calcite.plan.RelOptUtil;
35 import org.apache.calcite.plan.hep.HepPlanner;
36 import org.apache.calcite.plan.hep.HepProgram;
37 import org.apache.calcite.plan.volcano.VolcanoPlanner;
38 import org.apache.calcite.rel.RelNode;
39 import org.apache.calcite.rel.RelRoot;
40 import org.apache.calcite.rel.core.RelFactories;
42 import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider;
44 import org.apache.calcite.rel.rules.FilterJoinRule;
45 import org.apache.calcite.rel.rules.FilterMergeRule;
46 import org.apache.calcite.rel.rules.FilterProjectTransposeRule;
48 import org.apache.calcite.rel.rules.ProjectMergeRule;
50 import org.apache.calcite.rex.RexBuilder;
51 import org.apache.calcite.schema.SchemaPlus;
52 import org.apache.calcite.sql.SqlKind;
53 import org.apache.calcite.sql.SqlNode;
54 import org.apache.calcite.sql.advise.SqlAdvisor;
55 import org.apache.calcite.sql.advise.SqlAdvisorValidator;
56 import org.apache.calcite.sql.parser.SqlParseException;
57 import org.apache.calcite.sql.validate.SqlConformance;
58 import org.apache.calcite.sql.validate.SqlConformanceEnum;
59 import org.apache.calcite.sql.validate.SqlMoniker;
60 import org.apache.calcite.sql.validate.SqlValidator;
61 import org.apache.calcite.tools.FrameworkConfig;
62 import org.apache.calcite.tools.Program;
63 import org.apache.calcite.tools.Programs;
64 import org.apache.calcite.tools.RelConversionException;
65 
66 import java.io.IOException;
67 import java.lang.reflect.InvocationTargetException;
68 import java.lang.reflect.Method;
69 import java.util.ArrayList;
70 import java.util.List;
71 import java.util.Properties;
72 
79 public class MapDPlanner extends PlannerImpl {
80  FrameworkConfig config;
81  private List<MapDParserOptions.FilterPushDownInfo> filterPushDownInfo =
82  new ArrayList<>();
83 
84  public MapDPlanner(FrameworkConfig config) {
85  super(config);
86  this.config = config;
87  }
88 
89  private static SchemaPlus rootSchema(SchemaPlus schema) {
90  for (;;) {
91  if (schema.getParentSchema() == null) {
92  return schema;
93  }
94  schema = schema.getParentSchema();
95  }
96  }
97 
98  public static class CompletionResult {
99  public List<SqlMoniker> hints;
100  public String replaced;
101 
102  CompletionResult(final List<SqlMoniker> hints, final String replaced) {
103  this.hints = hints;
104  this.replaced = replaced;
105  }
106  }
107 
108  private CalciteCatalogReader createCatalogReader() {
109  final SchemaPlus rootSchema = rootSchema(config.getDefaultSchema());
110  final Context context = config.getContext();
111  final CalciteConnectionConfig connectionConfig;
112 
113  if (context != null) {
114  connectionConfig = context.unwrap(CalciteConnectionConfig.class);
115  } else {
116  Properties properties = new Properties();
117  properties.setProperty(CalciteConnectionProperty.CASE_SENSITIVE.camelName(),
118  String.valueOf(config.getParserConfig().caseSensitive()));
119  connectionConfig = new CalciteConnectionConfigImpl(properties);
120  }
121 
122  return new CalciteCatalogReader(CalciteSchema.from(rootSchema),
123  CalciteSchema.from(config.getDefaultSchema()).path(null),
124  getTypeFactory(),
125  connectionConfig);
126  }
127 
128  public void advanceToValidate() {
129  try {
130  String dummySql = "SELECT 1";
131  super.parse(dummySql);
132  } catch (SqlParseException e) {
133  throw new RuntimeException(e);
134  }
135  }
136 
137  public void ready() {
138  // need to call ready on the super class, but that method is marked private
139  // circumventing via reflection for now
140  try {
141  Method readyMethod = getClass().getSuperclass().getDeclaredMethod("ready");
142  readyMethod.setAccessible(true);
143  readyMethod.invoke(this);
144  } catch (InvocationTargetException e) {
145  if (e.getCause() instanceof RuntimeException) {
146  throw(RuntimeException) e.getCause();
147  } else {
148  throw new RuntimeException(e.getCause());
149  }
150  } catch (Exception e) {
151  throw new RuntimeException(e);
152  }
153  }
154 
156  final String sql, final int cursor, final List<String> visibleTables) {
157  ready();
158 
159  SqlValidator.Config validatorConfig = SqlValidator.Config.DEFAULT;
160  validatorConfig = validatorConfig.withSqlConformance(SqlConformanceEnum.LENIENT);
161 
162  MapDSqlAdvisorValidator advisor_validator = new MapDSqlAdvisorValidator(visibleTables,
163  config.getOperatorTable(),
165  getTypeFactory(),
166  validatorConfig);
167  SqlAdvisor advisor = new MapDSqlAdvisor(advisor_validator);
168  String[] replaced = new String[1];
169  int adjusted_cursor = cursor < 0 ? sql.length() : cursor;
170  java.util.List<SqlMoniker> hints =
171  advisor.getCompletionHints(sql, adjusted_cursor, replaced);
172  return new CompletionResult(hints, replaced[0]);
173  }
174 
175  @Override
176  public RelRoot rel(SqlNode sql) {
177  RelRoot root = super.rel(sql);
178  root = applyQueryOptimizationRules(root);
179  root = applyFilterPushdown(root);
180  return root;
181  }
182 
183  private RelRoot applyFilterPushdown(RelRoot root) {
184  if (filterPushDownInfo.isEmpty()) {
185  return root;
186  }
187  final DynamicFilterJoinRule dynamicFilterJoinRule = new DynamicFilterJoinRule(true,
188  RelFactories.LOGICAL_BUILDER,
189  FilterJoinRule.TRUE_PREDICATE,
191  final HepProgram program =
192  HepProgram.builder().addRuleInstance(dynamicFilterJoinRule).build();
193  HepPlanner prePlanner = new HepPlanner(program);
194  prePlanner.setRoot(root.rel);
195  final RelNode rootRelNode = prePlanner.findBestExp();
196  filterPushDownInfo.clear();
197  return root.withRel(rootRelNode);
198  }
199 
200  private RelRoot applyQueryOptimizationRules(RelRoot root) {
201  QueryOptimizationRules outerJoinOptRule =
202  new OuterJoinOptViaNullRejectionRule(RelFactories.LOGICAL_BUILDER);
203 
204  HepProgram opt_program =
205  HepProgram.builder().addRuleInstance(outerJoinOptRule).build();
206  HepPlanner prePlanner = new HepPlanner(
207  opt_program, null, true, Functions.ignore2(), RelOptCostImpl.FACTORY);
208  prePlanner.setRoot(root.rel);
209  final RelNode rootRelNode = prePlanner.findBestExp();
210  return root.withRel(rootRelNode);
211  }
212 
213  public RelRoot optimizeRaQuery(String query, MapDSchema schema) throws IOException {
214  ready();
215  RexBuilder builder = new RexBuilder(getTypeFactory());
216  RelOptCluster cluster = RelOptCluster.create(new VolcanoPlanner(), builder);
217  CalciteCatalogReader catalogReader = createCatalogReader();
218  MapDRelJsonReader reader = new MapDRelJsonReader(cluster, catalogReader, schema);
219 
220  RelRoot relR = RelRoot.of(reader.read(query), SqlKind.SELECT);
222  applyFilterPushdown(relR);
223 
224  ProjectMergeRule projectMergeRule =
225  new ProjectMergeRule(true, RelFactories.LOGICAL_BUILDER);
226  final Program program =
227  Programs.hep(ImmutableList.of(FilterProjectTransposeRule.INSTANCE,
228  projectMergeRule,
230  FilterMergeRule.INSTANCE),
231  true,
232  DefaultRelMetadataProvider.INSTANCE);
233  RelNode oldRel;
234  RelNode newRel = relR.project();
235 
236  do {
237  oldRel = newRel;
238  newRel = program.run(null,
239  oldRel,
240  null,
241  ImmutableList.<RelOptMaterialization>of(),
242  ImmutableList.<RelOptLattice>of());
243  // there must be a better way to compare these
244  } while (!RelOptUtil.toString(oldRel).equals(RelOptUtil.toString(newRel)));
245 
246  return RelRoot.of(newRel, relR.kind);
247  }
248 
250  final List<MapDParserOptions.FilterPushDownInfo> filterPushDownInfo) {
251  this.filterPushDownInfo = filterPushDownInfo;
252  }
253 }
254 
255 // End MapDPlanner.java
RelRoot applyQueryOptimizationRules(RelRoot root)
static SchemaPlus rootSchema(SchemaPlus schema)
CalciteCatalogReader createCatalogReader()
RelRoot optimizeRaQuery(String query, MapDSchema schema)
List< MapDParserOptions.FilterPushDownInfo > filterPushDownInfo
CompletionResult(final List< SqlMoniker > hints, final String replaced)
void setFilterPushDownInfo(final List< MapDParserOptions.FilterPushDownInfo > filterPushDownInfo)
CompletionResult getCompletionHints(final String sql, final int cursor, final List< String > visibleTables)
MapDPlanner(FrameworkConfig config)
RelRoot applyFilterPushdown(RelRoot root)