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