OmniSciDB  94e8789169
 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 
22 
23 import org.apache.calcite.config.CalciteConnectionConfig;
24 import org.apache.calcite.config.CalciteConnectionConfigImpl;
25 import org.apache.calcite.config.CalciteConnectionProperty;
26 import org.apache.calcite.jdbc.CalciteSchema;
27 import org.apache.calcite.linq4j.function.Functions;
28 import org.apache.calcite.plan.Context;
29 import org.apache.calcite.plan.RelOptCluster;
30 import org.apache.calcite.plan.RelOptCostImpl;
31 import org.apache.calcite.plan.hep.HepPlanner;
32 import org.apache.calcite.plan.hep.HepProgram;
33 import org.apache.calcite.plan.hep.HepProgramBuilder;
34 import org.apache.calcite.plan.volcano.VolcanoPlanner;
35 import org.apache.calcite.rel.RelNode;
36 import org.apache.calcite.rel.RelRoot;
37 import org.apache.calcite.rel.core.RelFactories;
39 import org.apache.calcite.rel.rules.CoreRules;
41 import org.apache.calcite.rel.rules.FilterJoinRule;
46 import org.apache.calcite.rex.RexBuilder;
47 import org.apache.calcite.schema.SchemaPlus;
48 import org.apache.calcite.sql.SqlKind;
49 import org.apache.calcite.sql.SqlNode;
50 import org.apache.calcite.sql.advise.SqlAdvisor;
51 import org.apache.calcite.sql.parser.SqlParseException;
52 import org.apache.calcite.sql.validate.SqlConformanceEnum;
53 import org.apache.calcite.sql.validate.SqlMoniker;
54 import org.apache.calcite.sql.validate.SqlValidator;
55 import org.apache.calcite.tools.FrameworkConfig;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58 
59 import java.io.IOException;
60 import java.lang.reflect.InvocationTargetException;
61 import java.lang.reflect.Method;
62 import java.util.ArrayList;
63 import java.util.List;
64 import java.util.Properties;
65 
72 public class MapDPlanner extends PlannerImpl {
73  FrameworkConfig config;
74  private List<MapDParserOptions.FilterPushDownInfo> filterPushDownInfo =
75  new ArrayList<>();
76  private Restriction restriction = null;
77  final static Logger MAPDLOGGER = LoggerFactory.getLogger(MapDPlanner.class);
78 
79  public MapDPlanner(FrameworkConfig config) {
80  super(config);
81  this.config = config;
82  }
83 
84  private static SchemaPlus rootSchema(SchemaPlus schema) {
85  for (;;) {
86  if (schema.getParentSchema() == null) {
87  return schema;
88  }
89  schema = schema.getParentSchema();
90  }
91  }
92 
93  public static class CompletionResult {
94  public List<SqlMoniker> hints;
95  public String replaced;
96 
97  CompletionResult(final List<SqlMoniker> hints, final String replaced) {
98  this.hints = hints;
99  this.replaced = replaced;
100  }
101  }
102 
103  private CalciteCatalogReader createCatalogReader() {
104  final SchemaPlus rootSchema = rootSchema(config.getDefaultSchema());
105  final Context context = config.getContext();
106  final CalciteConnectionConfig connectionConfig;
107 
108  if (context != null) {
109  connectionConfig = context.unwrap(CalciteConnectionConfig.class);
110  } else {
111  Properties properties = new Properties();
112  properties.setProperty(CalciteConnectionProperty.CASE_SENSITIVE.camelName(),
113  String.valueOf(config.getParserConfig().caseSensitive()));
114  connectionConfig = new CalciteConnectionConfigImpl(properties);
115  }
116 
117  return new CalciteCatalogReader(CalciteSchema.from(rootSchema),
118  CalciteSchema.from(config.getDefaultSchema()).path(null),
119  getTypeFactory(),
120  connectionConfig);
121  }
122 
123  public void advanceToValidate() {
124  try {
125  String dummySql = "SELECT 1";
126  super.parse(dummySql);
127  } catch (SqlParseException e) {
128  throw new RuntimeException(e);
129  }
130  }
131 
132  public void ready() {
133  // need to call ready on the super class, but that method is marked private
134  // circumventing via reflection for now
135  try {
136  Method readyMethod = getClass().getSuperclass().getDeclaredMethod("ready");
137  readyMethod.setAccessible(true);
138  readyMethod.invoke(this);
139  } catch (InvocationTargetException e) {
140  if (e.getCause() instanceof RuntimeException) {
141  throw(RuntimeException) e.getCause();
142  } else {
143  throw new RuntimeException(e.getCause());
144  }
145  } catch (Exception e) {
146  throw new RuntimeException(e);
147  }
148  }
149 
151  final String sql, final int cursor, final List<String> visibleTables) {
152  ready();
153 
154  SqlValidator.Config validatorConfig = SqlValidator.Config.DEFAULT;
155  validatorConfig = validatorConfig.withSqlConformance(SqlConformanceEnum.LENIENT);
156 
157  MapDSqlAdvisorValidator advisor_validator = new MapDSqlAdvisorValidator(visibleTables,
158  config.getOperatorTable(),
160  getTypeFactory(),
161  validatorConfig);
162  SqlAdvisor advisor = new MapDSqlAdvisor(advisor_validator, config.getParserConfig());
163  String[] replaced = new String[1];
164  int adjusted_cursor = cursor < 0 ? sql.length() : cursor;
165  java.util.List<SqlMoniker> hints =
166  advisor.getCompletionHints(sql, adjusted_cursor, replaced);
167  return new CompletionResult(hints, replaced[0]);
168  }
169 
170  @Override
171  public RelRoot rel(SqlNode sql) {
172  RelRoot root = super.rel(sql);
173  if (restriction != null) {
174  root = applyInjectFilterRule(root, restriction);
175  }
176  root = applyQueryOptimizationRules(root);
177  root = applyFilterPushdown(root);
178  return root;
179  }
180 
181  private RelRoot applyInjectFilterRule(RelRoot root, Restriction restriction) {
182  // TODO consider doing these rules in one preplan pass
183 
184  final InjectFilterRule injectFilterRule =
185  InjectFilterRule.Config.DEFAULT.toRule(restriction);
186 
187  final HepProgram program =
188  HepProgram.builder().addRuleInstance(injectFilterRule).build();
189  HepPlanner prePlanner = new HepPlanner(program);
190  prePlanner.setRoot(root.rel);
191  final RelNode rootRelNode = prePlanner.findBestExp();
192  return root.withRel(rootRelNode);
193  }
194 
195  private RelRoot applyFilterPushdown(RelRoot root) {
196  if (filterPushDownInfo.isEmpty()) {
197  return root;
198  }
199  final DynamicFilterJoinRule dynamicFilterJoinRule = new DynamicFilterJoinRule(true,
200  RelFactories.LOGICAL_BUILDER,
201  FilterJoinRule.TRUE_PREDICATE,
203  final HepProgram program =
204  HepProgram.builder().addRuleInstance(dynamicFilterJoinRule).build();
205  HepPlanner prePlanner = new HepPlanner(program);
206  prePlanner.setRoot(root.rel);
207  final RelNode rootRelNode = prePlanner.findBestExp();
208  filterPushDownInfo.clear();
209  return root.withRel(rootRelNode);
210  }
211 
212  private RelRoot applyQueryOptimizationRules(RelRoot root) {
213  QueryOptimizationRules outerJoinOptRule =
214  new OuterJoinOptViaNullRejectionRule(RelFactories.LOGICAL_BUILDER);
215 
216  HepProgram opt_program =
217  HepProgram.builder().addRuleInstance(outerJoinOptRule).build();
218  HepPlanner prePlanner = new HepPlanner(
219  opt_program, null, true, Functions.ignore2(), RelOptCostImpl.FACTORY);
220  prePlanner.setRoot(root.rel);
221  final RelNode rootRelNode = prePlanner.findBestExp();
222  return root.withRel(rootRelNode);
223  }
224 
225  public RelRoot optimizeRaQuery(String query, MapDSchema schema) throws IOException {
226  ready();
227  RexBuilder builder = new RexBuilder(getTypeFactory());
228  RelOptCluster cluster = RelOptCluster.create(new VolcanoPlanner(), builder);
229  CalciteCatalogReader catalogReader = createCatalogReader();
230  MapDRelJsonReader reader = new MapDRelJsonReader(cluster, catalogReader, schema);
231 
232  RelRoot relR = RelRoot.of(reader.read(query), SqlKind.SELECT);
234  applyFilterPushdown(relR);
235 
236  HepProgramBuilder hepBuilder = new HepProgramBuilder();
237  hepBuilder.addRuleInstance(CoreRules.JOIN_PROJECT_BOTH_TRANSPOSE_INCLUDE_OUTER);
238  hepBuilder.addRuleInstance(CoreRules.FILTER_MERGE);
239  hepBuilder.addRuleInstance(CoreRules.FILTER_PROJECT_TRANSPOSE);
240  hepBuilder.addRuleInstance(CoreRules.PROJECT_MERGE);
241  hepBuilder.addRuleInstance(ProjectProjectRemoveRule.INSTANCE);
242 
243  HepPlanner hepPlanner = new HepPlanner(hepBuilder.build());
244  final RelNode root = relR.project();
245  hepPlanner.setRoot(root);
246  final RelNode newRel = hepPlanner.findBestExp();
247 
248  return RelRoot.of(newRel, relR.kind);
249  }
250 
252  final List<MapDParserOptions.FilterPushDownInfo> filterPushDownInfo) {
253  this.filterPushDownInfo = filterPushDownInfo;
254  }
255 
257  this.restriction = restriction;
258  }
259 }
260 
261 // End MapDPlanner.java
RelRoot applyQueryOptimizationRules(RelRoot root)
static SchemaPlus rootSchema(SchemaPlus schema)
CalciteCatalogReader createCatalogReader()
RelRoot optimizeRaQuery(String query, MapDSchema schema)
void setRestriction(Restriction restriction)
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)
RelRoot applyInjectFilterRule(RelRoot root, Restriction restriction)
MapDPlanner(FrameworkConfig config)
RelRoot applyFilterPushdown(RelRoot root)