OmniSciDB  94e8789169
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SqlToRelConverter.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 
18 /* MAT 9 Jan 2021
19  * We have moved this code from calcite 1.25
20  * we keep our own copy as we have added some
21  * special handling of pushdown and correlation handling
22  *
23  * If we make changes from the original source please make
24  * sure you add good comments around the changed block
25  * as each time we move to a new calcite version we need to move
26  * our chnages to the new code
27  *
28  */
29 package org.apache.calcite.sql2rel;
30 
31 import static org.apache.calcite.sql.SqlUtil.stripAs;
32 
33 import com.google.common.base.Preconditions;
34 import com.google.common.collect.ImmutableList;
35 import com.google.common.collect.ImmutableList.Builder;
36 import com.google.common.collect.ImmutableMap;
37 import com.google.common.collect.ImmutableSet;
38 import com.google.common.collect.Iterables;
39 import com.google.common.collect.Sets;
40 
41 import org.apache.calcite.avatica.util.Spaces;
42 import org.apache.calcite.linq4j.Ord;
43 import org.apache.calcite.plan.Convention;
44 import org.apache.calcite.plan.RelOptCluster;
45 import org.apache.calcite.plan.RelOptPlanner;
46 import org.apache.calcite.plan.RelOptSamplingParameters;
47 import org.apache.calcite.plan.RelOptTable;
48 import org.apache.calcite.plan.RelOptUtil;
49 import org.apache.calcite.plan.RelTraitSet;
50 import org.apache.calcite.plan.ViewExpanders;
51 import org.apache.calcite.prepare.Prepare;
52 import org.apache.calcite.prepare.RelOptTableImpl;
53 import org.apache.calcite.rel.RelCollation;
54 import org.apache.calcite.rel.RelCollationTraitDef;
55 import org.apache.calcite.rel.RelCollations;
56 import org.apache.calcite.rel.RelFieldCollation;
57 import org.apache.calcite.rel.RelNode;
58 import org.apache.calcite.rel.RelRoot;
59 import org.apache.calcite.rel.RelShuttleImpl;
60 import org.apache.calcite.rel.SingleRel;
61 import org.apache.calcite.rel.core.AggregateCall;
62 import org.apache.calcite.rel.core.Collect;
63 import org.apache.calcite.rel.core.CorrelationId;
64 import org.apache.calcite.rel.core.Filter;
65 import org.apache.calcite.rel.core.Join;
66 import org.apache.calcite.rel.core.JoinInfo;
67 import org.apache.calcite.rel.core.JoinRelType;
68 import org.apache.calcite.rel.core.Project;
69 import org.apache.calcite.rel.core.RelFactories;
70 import org.apache.calcite.rel.core.Sample;
71 import org.apache.calcite.rel.core.Sort;
72 import org.apache.calcite.rel.hint.HintStrategyTable;
73 import org.apache.calcite.rel.hint.Hintable;
74 import org.apache.calcite.rel.hint.RelHint;
75 import org.apache.calcite.rel.logical.LogicalAggregate;
76 import org.apache.calcite.rel.logical.LogicalCorrelate;
77 import org.apache.calcite.rel.logical.LogicalFilter;
78 import org.apache.calcite.rel.logical.LogicalIntersect;
79 import org.apache.calcite.rel.logical.LogicalJoin;
80 import org.apache.calcite.rel.logical.LogicalMatch;
81 import org.apache.calcite.rel.logical.LogicalMinus;
82 import org.apache.calcite.rel.logical.LogicalProject;
83 import org.apache.calcite.rel.logical.LogicalSort;
84 import org.apache.calcite.rel.logical.LogicalTableFunctionScan;
85 import org.apache.calcite.rel.logical.LogicalTableModify;
86 import org.apache.calcite.rel.logical.LogicalTableScan;
87 import org.apache.calcite.rel.logical.LogicalUnion;
88 import org.apache.calcite.rel.logical.LogicalValues;
89 import org.apache.calcite.rel.metadata.RelColumnMapping;
90 import org.apache.calcite.rel.metadata.RelMetadataQuery;
91 import org.apache.calcite.rel.stream.Delta;
92 import org.apache.calcite.rel.stream.LogicalDelta;
93 import org.apache.calcite.rel.type.RelDataType;
94 import org.apache.calcite.rel.type.RelDataTypeFactory;
95 import org.apache.calcite.rel.type.RelDataTypeField;
96 import org.apache.calcite.rex.RexBuilder;
97 import org.apache.calcite.rex.RexCall;
98 import org.apache.calcite.rex.RexCallBinding;
99 import org.apache.calcite.rex.RexCorrelVariable;
100 import org.apache.calcite.rex.RexDynamicParam;
101 import org.apache.calcite.rex.RexFieldAccess;
102 import org.apache.calcite.rex.RexFieldCollation;
103 import org.apache.calcite.rex.RexInputRef;
104 import org.apache.calcite.rex.RexLiteral;
105 import org.apache.calcite.rex.RexNode;
106 import org.apache.calcite.rex.RexPatternFieldRef;
107 import org.apache.calcite.rex.RexRangeRef;
108 import org.apache.calcite.rex.RexShuttle;
109 import org.apache.calcite.rex.RexSubQuery;
110 import org.apache.calcite.rex.RexUtil;
111 import org.apache.calcite.rex.RexWindowBound;
112 import org.apache.calcite.rex.RexWindowBounds;
113 import org.apache.calcite.schema.ColumnStrategy;
114 import org.apache.calcite.schema.ModifiableTable;
115 import org.apache.calcite.schema.ModifiableView;
116 import org.apache.calcite.schema.Table;
117 import org.apache.calcite.schema.TranslatableTable;
118 import org.apache.calcite.schema.Wrapper;
119 import org.apache.calcite.sql.JoinConditionType;
121 import org.apache.calcite.sql.SqlAggFunction;
122 import org.apache.calcite.sql.SqlBasicCall;
123 import org.apache.calcite.sql.SqlCall;
124 import org.apache.calcite.sql.SqlCallBinding;
125 import org.apache.calcite.sql.SqlDataTypeSpec;
126 import org.apache.calcite.sql.SqlDelete;
127 import org.apache.calcite.sql.SqlDynamicParam;
128 import org.apache.calcite.sql.SqlExplainFormat;
129 import org.apache.calcite.sql.SqlExplainLevel;
130 import org.apache.calcite.sql.SqlFunction;
131 import org.apache.calcite.sql.SqlIdentifier;
132 import org.apache.calcite.sql.SqlInsert;
133 import org.apache.calcite.sql.SqlIntervalQualifier;
134 import org.apache.calcite.sql.SqlJoin;
135 import org.apache.calcite.sql.SqlKind;
136 import org.apache.calcite.sql.SqlLiteral;
137 import org.apache.calcite.sql.SqlMatchRecognize;
138 import org.apache.calcite.sql.SqlMerge;
139 import org.apache.calcite.sql.SqlNode;
140 import org.apache.calcite.sql.SqlNodeList;
141 import org.apache.calcite.sql.SqlNumericLiteral;
142 import org.apache.calcite.sql.SqlOperator;
143 import org.apache.calcite.sql.SqlOperatorTable;
144 import org.apache.calcite.sql.SqlOrderBy;
145 import org.apache.calcite.sql.SqlSampleSpec;
146 import org.apache.calcite.sql.SqlSelect;
147 import org.apache.calcite.sql.SqlSelectKeyword;
148 import org.apache.calcite.sql.SqlSetOperator;
149 import org.apache.calcite.sql.SqlSnapshot;
150 import org.apache.calcite.sql.SqlUnnestOperator;
151 import org.apache.calcite.sql.SqlUpdate;
152 import org.apache.calcite.sql.SqlUtil;
153 import org.apache.calcite.sql.SqlValuesOperator;
154 import org.apache.calcite.sql.SqlWindow;
155 import org.apache.calcite.sql.SqlWith;
156 import org.apache.calcite.sql.SqlWithItem;
157 import org.apache.calcite.sql.fun.SqlCase;
158 import org.apache.calcite.sql.fun.SqlCountAggFunction;
159 import org.apache.calcite.sql.fun.SqlInOperator;
160 import org.apache.calcite.sql.fun.SqlQuantifyOperator;
161 import org.apache.calcite.sql.fun.SqlRowOperator;
162 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
163 import org.apache.calcite.sql.parser.SqlParserPos;
164 import org.apache.calcite.sql.type.SqlReturnTypeInference;
165 import org.apache.calcite.sql.type.SqlTypeName;
166 import org.apache.calcite.sql.type.SqlTypeUtil;
167 import org.apache.calcite.sql.type.TableFunctionReturnTypeInference;
168 import org.apache.calcite.sql.util.SqlBasicVisitor;
169 import org.apache.calcite.sql.util.SqlVisitor;
170 import org.apache.calcite.sql.validate.AggregatingSelectScope;
171 import org.apache.calcite.sql.validate.CollectNamespace;
172 import org.apache.calcite.sql.validate.DelegatingScope;
173 import org.apache.calcite.sql.validate.ListScope;
174 import org.apache.calcite.sql.validate.MatchRecognizeScope;
175 import org.apache.calcite.sql.validate.ParameterScope;
176 import org.apache.calcite.sql.validate.SelectScope;
177 import org.apache.calcite.sql.validate.SqlMonotonicity;
178 import org.apache.calcite.sql.validate.SqlNameMatcher;
179 import org.apache.calcite.sql.validate.SqlQualified;
180 import org.apache.calcite.sql.validate.SqlUserDefinedTableFunction;
181 import org.apache.calcite.sql.validate.SqlUserDefinedTableMacro;
182 import org.apache.calcite.sql.validate.SqlValidator;
183 import org.apache.calcite.sql.validate.SqlValidatorImpl;
184 import org.apache.calcite.sql.validate.SqlValidatorNamespace;
185 import org.apache.calcite.sql.validate.SqlValidatorScope;
186 import org.apache.calcite.sql.validate.SqlValidatorTable;
187 import org.apache.calcite.sql.validate.SqlValidatorUtil;
188 import org.apache.calcite.tools.RelBuilder;
189 import org.apache.calcite.tools.RelBuilderFactory;
190 import org.apache.calcite.util.ImmutableBitSet;
191 import org.apache.calcite.util.ImmutableIntList;
192 import org.apache.calcite.util.Litmus;
193 import org.apache.calcite.util.NlsString;
194 import org.apache.calcite.util.NumberUtil;
195 import org.apache.calcite.util.Pair;
196 import org.apache.calcite.util.Util;
197 import org.apache.calcite.util.trace.CalciteTrace;
198 import org.slf4j.Logger;
199 
201 import java.math.BigDecimal;
202 import java.util.AbstractList;
203 import java.util.ArrayDeque;
204 import java.util.ArrayList;
205 import java.util.BitSet;
206 import java.util.Collection;
207 import java.util.Collections;
208 import java.util.Deque;
209 import java.util.EnumSet;
210 import java.util.HashMap;
211 import java.util.HashSet;
212 import java.util.List;
213 import java.util.Map;
214 import java.util.Objects;
215 import java.util.Set;
216 import java.util.TreeSet;
217 import java.util.function.BiPredicate;
218 import java.util.function.Supplier;
219 import java.util.function.UnaryOperator;
220 import java.util.stream.Collectors;
221 
222 import javax.annotation.Nonnull;
232 public class SqlToRelConverter {
233  // ~ Static fields/initializers ---------------------------------------------
234 
235  protected static final Logger SQL2REL_LOGGER = CalciteTrace.getSqlToRelTracer();
236 
241  public static final int DEFAULT_IN_SUB_QUERY_THRESHOLD = 20;
242 
243  @Deprecated // to be removed before 2.0
245 
246  // ~ Instance fields --------------------------------------------------------
247 
248  protected final SqlValidator validator;
249  protected final RexBuilder rexBuilder;
250  protected final Prepare.CatalogReader catalogReader;
251  protected final RelOptCluster cluster;
252  private SubQueryConverter subQueryConverter;
253  protected final Map<RelNode, Integer> leaves = new HashMap<>();
254  private final List<SqlDynamicParam> dynamicParamSqlNodes = new ArrayList<>();
255  private final SqlOperatorTable opTab;
256  protected final RelDataTypeFactory typeFactory;
257  private final SqlNodeToRexConverter exprConverter;
258  private final HintStrategyTable hintStrategies;
259  private int explainParamCount;
260  public final SqlToRelConverter.Config config;
261  private final RelBuilder relBuilder;
262 
266  private final Map<CorrelationId, DeferredLookup> mapCorrelToDeferred = new HashMap<>();
267 
272  private final Deque<String> datasetStack = new ArrayDeque<>();
273 
279  private final Map<SqlNode, RexNode> mapConvertedNonCorrSubqs = new HashMap<>();
280 
281  public final RelOptTable.ViewExpander viewExpander;
282 
283  // ~ Constructors -----------------------------------------------------------
294  @Deprecated // to be removed before 2.0
295  public SqlToRelConverter(RelOptTable.ViewExpander viewExpander,
296  SqlValidator validator,
297  Prepare.CatalogReader catalogReader,
298  RelOptPlanner planner,
299  RexBuilder rexBuilder,
300  SqlRexConvertletTable convertletTable) {
301  this(viewExpander,
302  validator,
304  RelOptCluster.create(planner, rexBuilder),
305  convertletTable,
306  Config.DEFAULT);
307  }
308 
309  @Deprecated // to be removed before 2.0
310  public SqlToRelConverter(RelOptTable.ViewExpander viewExpander,
311  SqlValidator validator,
312  Prepare.CatalogReader catalogReader,
313  RelOptCluster cluster,
314  SqlRexConvertletTable convertletTable) {
315  this(viewExpander,
316  validator,
318  cluster,
319  convertletTable,
320  Config.DEFAULT);
321  }
322 
323  /* Creates a converter. */
324  public SqlToRelConverter(RelOptTable.ViewExpander viewExpander,
325  SqlValidator validator,
326  Prepare.CatalogReader catalogReader,
327  RelOptCluster cluster,
328  SqlRexConvertletTable convertletTable,
329  Config config) {
330  this.viewExpander = viewExpander;
331  this.opTab = (validator == null) ? SqlStdOperatorTable.instance()
332  : validator.getOperatorTable();
333  this.validator = validator;
334  this.catalogReader = catalogReader;
335  this.subQueryConverter = new NoOpSubQueryConverter();
336  this.rexBuilder = cluster.getRexBuilder();
337  this.typeFactory = rexBuilder.getTypeFactory();
338  this.exprConverter = new SqlNodeToRexConverterImpl(convertletTable);
339  this.explainParamCount = 0;
340  this.config = new ConfigBuilder().withConfig(config).build();
341  this.relBuilder = config.getRelBuilderFactory()
342  .create(cluster, null)
343  .transform(config.getRelBuilderConfigTransform());
344  this.hintStrategies = config.getHintStrategyTable();
345 
346  cluster.setHintStrategies(this.hintStrategies);
347  this.cluster = Objects.requireNonNull(cluster);
348  }
349 
350  // ~ Methods ----------------------------------------------------------------
351 
353  public RelOptCluster getCluster() {
354  return cluster;
355  }
356 
360  public RexBuilder getRexBuilder() {
361  return rexBuilder;
362  }
363 
370  public int getDynamicParamCount() {
371  return dynamicParamSqlNodes.size();
372  }
373 
380  public RelDataType getDynamicParamType(int index) {
381  SqlNode sqlNode = dynamicParamSqlNodes.get(index);
382  if (sqlNode == null) {
383  throw Util.needToImplement("dynamic param type inference");
384  }
385  return validator.getValidatedNodeType(sqlNode);
386  }
387 
395  public int getDynamicParamCountInExplain(boolean increment) {
396  int retVal = explainParamCount;
397  if (increment) {
399  }
400  return retVal;
401  }
402 
407  public Map<SqlNode, RexNode> getMapConvertedNonCorrSubqs() {
409  }
410 
419  Map<SqlNode, RexNode> alreadyConvertedNonCorrSubqs) {
420  mapConvertedNonCorrSubqs.putAll(alreadyConvertedNonCorrSubqs);
421  }
422 
429  public void setSubQueryConverter(SubQueryConverter converter) {
430  subQueryConverter = converter;
431  }
432 
439  assert config.isExplain();
440  this.explainParamCount = explainParamCount;
441  }
442 
443  private void checkConvertedType(SqlNode query, RelNode result) {
444  if (query.isA(SqlKind.DML)) {
445  return;
446  }
447  // Verify that conversion from SQL to relational algebra did
448  // not perturb any type information. (We can't do this if the
449  // SQL statement is something like an INSERT which has no
450  // validator type information associated with its result,
451  // hence the namespace check above.)
452  final List<RelDataTypeField> validatedFields =
453  validator.getValidatedNodeType(query).getFieldList();
454  final RelDataType validatedRowType =
455  validator.getTypeFactory().createStructType(Pair.right(validatedFields),
456  SqlValidatorUtil.uniquify(Pair.left(validatedFields),
457  catalogReader.nameMatcher().isCaseSensitive()));
458 
459  final List<RelDataTypeField> convertedFields =
460  result.getRowType().getFieldList().subList(0, validatedFields.size());
461  final RelDataType convertedRowType =
462  validator.getTypeFactory().createStructType(convertedFields);
463 
464  if (!RelOptUtil.equal("validated row type",
465  validatedRowType,
466  "converted row type",
467  convertedRowType,
468  Litmus.IGNORE)) {
469  throw new AssertionError("Conversion to relational algebra failed to "
470  + "preserve datatypes:\n"
471  + "validated type:\n" + validatedRowType.getFullTypeString()
472  + "\nconverted type:\n" + convertedRowType.getFullTypeString() + "\nrel:\n"
473  + RelOptUtil.toString(result));
474  }
475  }
476 
477  public RelNode flattenTypes(RelNode rootRel, boolean restructure) {
478  RelStructuredTypeFlattener typeFlattener = new RelStructuredTypeFlattener(
479  relBuilder, rexBuilder, createToRelContext(ImmutableList.of()), restructure);
480  return typeFlattener.rewrite(rootRel);
481  }
482 
491  public RelNode decorrelate(SqlNode query, RelNode rootRel) {
492  if (!config.isDecorrelationEnabled()) {
493  return rootRel;
494  }
495  final RelNode result = decorrelateQuery(rootRel);
496  if (result != rootRel) {
497  checkConvertedType(query, result);
498  }
499  return result;
500  }
501 
524  public RelNode trimUnusedFields(boolean ordered, RelNode rootRel) {
525  // Trim fields that are not used by their consumer.
526  if (isTrimUnusedFields()) {
527  final RelFieldTrimmer trimmer = newFieldTrimmer();
528  final List<RelCollation> collations =
529  rootRel.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE);
530  rootRel = trimmer.trim(rootRel);
531  if (!ordered && collations != null && !collations.isEmpty()
532  && !collations.equals(ImmutableList.of(RelCollations.EMPTY))) {
533  final RelTraitSet traitSet =
534  rootRel.getTraitSet().replace(RelCollationTraitDef.INSTANCE, collations);
535  rootRel = rootRel.copy(traitSet, rootRel.getInputs());
536  }
537  if (SQL2REL_LOGGER.isDebugEnabled()) {
538  SQL2REL_LOGGER.debug(RelOptUtil.dumpPlan("Plan after trimming unused fields",
539  rootRel,
540  SqlExplainFormat.TEXT,
541  SqlExplainLevel.EXPPLAN_ATTRIBUTES));
542  }
543  }
544  return rootRel;
545  }
546 
552  protected RelFieldTrimmer newFieldTrimmer() {
553  return new RelFieldTrimmer(validator, relBuilder);
554  }
555 
567  public RelRoot convertQuery(
568  SqlNode query, final boolean needsValidation, final boolean top) {
569  if (needsValidation) {
570  query = validator.validate(query);
571  }
572 
573  RelNode result = convertQueryRecursive(query, top, null).rel;
574  if (top) {
575  if (isStream(query)) {
576  result = new LogicalDelta(cluster, result.getTraitSet(), result);
577  }
578  }
579  RelCollation collation = RelCollations.EMPTY;
580  if (!query.isA(SqlKind.DML)) {
581  if (isOrdered(query)) {
582  collation = requiredCollation(result);
583  }
584  }
585  checkConvertedType(query, result);
586 
587  if (SQL2REL_LOGGER.isDebugEnabled()) {
588  SQL2REL_LOGGER.debug(RelOptUtil.dumpPlan("Plan after converting SqlNode to RelNode",
589  result,
590  SqlExplainFormat.TEXT,
591  SqlExplainLevel.EXPPLAN_ATTRIBUTES));
592  }
593 
594  final RelDataType validatedRowType = validator.getValidatedNodeType(query);
595  List<RelHint> hints = new ArrayList<>();
596  if (query.getKind() == SqlKind.SELECT) {
597  final SqlSelect select = (SqlSelect) query;
598  if (select.hasHints()) {
599  hints = SqlUtil.getRelHint(hintStrategies, select.getHints());
600  }
601  }
602  // propagate the hints.
603  result = RelOptUtil.propagateRelHints(result, false);
604  return RelRoot.of(result, validatedRowType, query.getKind())
605  .withCollation(collation)
606  .withHints(hints);
607  }
608 
609  private static boolean isStream(SqlNode query) {
610  return query instanceof SqlSelect
611  && ((SqlSelect) query).isKeywordPresent(SqlSelectKeyword.STREAM);
612  }
613 
614  public static boolean isOrdered(SqlNode query) {
615  switch (query.getKind()) {
616  case SELECT:
617  return ((SqlSelect) query).getOrderList() != null
618  && ((SqlSelect) query).getOrderList().size() > 0;
619  case WITH:
620  return isOrdered(((SqlWith) query).body);
621  case ORDER_BY:
622  return ((SqlOrderBy) query).orderList.size() > 0;
623  default:
624  return false;
625  }
626  }
627 
628  private RelCollation requiredCollation(RelNode r) {
629  if (r instanceof Sort) {
630  return ((Sort) r).collation;
631  }
632  if (r instanceof Project) {
633  return requiredCollation(((Project) r).getInput());
634  }
635  if (r instanceof Delta) {
636  return requiredCollation(((Delta) r).getInput());
637  }
638  throw new AssertionError();
639  }
640 
644  public RelNode convertSelect(SqlSelect select, boolean top) {
645  final SqlValidatorScope selectScope = validator.getWhereScope(select);
646  final Blackboard bb = createBlackboard(selectScope, null, top);
647  convertSelectImpl(bb, select);
648  return bb.root;
649  }
650 
655  SqlValidatorScope scope, Map<String, RexNode> nameToNodeMap, boolean top) {
656  return new Blackboard(scope, nameToNodeMap, top);
657  }
658 
663  protected void convertSelectImpl(final Blackboard bb, SqlSelect select) {
664  convertFrom(bb, select.getFrom());
665  convertWhere(bb, select.getWhere());
666 
667  final List<SqlNode> orderExprList = new ArrayList<>();
668  final List<RelFieldCollation> collationList = new ArrayList<>();
669  gatherOrderExprs(bb, select, select.getOrderList(), orderExprList, collationList);
670  final RelCollation collation =
671  cluster.traitSet().canonize(RelCollations.of(collationList));
672 
673  if (validator.isAggregate(select)) {
674  convertAgg(bb, select, orderExprList);
675  } else {
676  convertSelectList(bb, select, orderExprList);
677  }
678 
679  if (select.isDistinct()) {
680  distinctify(bb, true);
681  }
682 
683  convertOrder(
684  select, bb, collation, orderExprList, select.getOffset(), select.getFetch());
685 
686  if (select.hasHints()) {
687  final List<RelHint> hints = SqlUtil.getRelHint(hintStrategies, select.getHints());
688  // Attach the hints to the first Hintable node we found from the root node.
689  bb.setRoot(bb.root.accept(new RelShuttleImpl() {
690  boolean attached = false;
691 
692  @Override
693  public RelNode visitChild(RelNode parent, int i, RelNode child) {
694  if (parent instanceof Hintable && !attached) {
695  attached = true;
696  return ((Hintable) parent).attachHints(hints);
697  } else {
698  return super.visitChild(parent, i, child);
699  }
700  }
701  }),
702  true);
703  } else {
704  bb.setRoot(bb.root, true);
705  }
706  }
707 
721  private void distinctify(Blackboard bb, boolean checkForDupExprs) {
722  // Look for duplicate expressions in the project.
723  // Say we have 'select x, y, x, z'.
724  // Then dups will be {[2, 0]}
725  // and oldToNew will be {[0, 0], [1, 1], [2, 0], [3, 2]}
726  RelNode rel = bb.root;
727  if (checkForDupExprs && (rel instanceof LogicalProject)) {
728  LogicalProject project = (LogicalProject) rel;
729  final List<RexNode> projectExprs = project.getProjects();
730  final List<Integer> origins = new ArrayList<>();
731  int dupCount = 0;
732  for (int i = 0; i < projectExprs.size(); i++) {
733  int x = projectExprs.indexOf(projectExprs.get(i));
734  if (x >= 0 && x < i) {
735  origins.add(x);
736  ++dupCount;
737  } else {
738  origins.add(i);
739  }
740  }
741  if (dupCount == 0) {
742  distinctify(bb, false);
743  return;
744  }
745 
746  final Map<Integer, Integer> squished = new HashMap<>();
747  final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
748  final List<Pair<RexNode, String>> newProjects = new ArrayList<>();
749  for (int i = 0; i < fields.size(); i++) {
750  if (origins.get(i) == i) {
751  squished.put(i, newProjects.size());
752  newProjects.add(RexInputRef.of2(i, fields));
753  }
754  }
755  rel = LogicalProject.create(
756  rel, ImmutableList.of(), Pair.left(newProjects), Pair.right(newProjects));
757  bb.root = rel;
758  distinctify(bb, false);
759  rel = bb.root;
760 
761  // Create the expressions to reverse the mapping.
762  // Project($0, $1, $0, $2).
763  final List<Pair<RexNode, String>> undoProjects = new ArrayList<>();
764  for (int i = 0; i < fields.size(); i++) {
765  final int origin = origins.get(i);
766  RelDataTypeField field = fields.get(i);
767  undoProjects.add(Pair.of(
768  new RexInputRef(squished.get(origin), field.getType()), field.getName()));
769  }
770 
771  rel = LogicalProject.create(
772  rel, ImmutableList.of(), Pair.left(undoProjects), Pair.right(undoProjects));
773  bb.setRoot(rel, false);
774 
775  return;
776  }
777 
778  // Usual case: all of the expressions in the SELECT clause are
779  // different.
780  final ImmutableBitSet groupSet =
781  ImmutableBitSet.range(rel.getRowType().getFieldCount());
782  rel = createAggregate(bb, groupSet, ImmutableList.of(groupSet), ImmutableList.of());
783 
784  bb.setRoot(rel, false);
785  }
786 
803  protected void convertOrder(SqlSelect select,
804  Blackboard bb,
805  RelCollation collation,
806  List<SqlNode> orderExprList,
807  SqlNode offset,
808  SqlNode fetch) {
809  if (!bb.top || select.getOrderList() == null
810  || select.getOrderList().getList().isEmpty()) {
811  assert !bb.top || collation.getFieldCollations().isEmpty();
812  if ((offset == null
813  || (offset instanceof SqlLiteral
814  && ((SqlLiteral) offset)
815  .bigDecimalValue()
816  .equals(BigDecimal.ZERO)))
817  && fetch == null) {
818  return;
819  }
820  }
821 
822  // Create a sorter using the previously constructed collations.
823  bb.setRoot(LogicalSort.create(bb.root,
824  collation,
825  offset == null ? null : convertExpression(offset),
826  fetch == null ? null : convertExpression(fetch)),
827  false);
828 
829  // If extra expressions were added to the project list for sorting,
830  // add another project to remove them. But make the collation empty, because
831  // we can't represent the real collation.
832  //
833  // If it is the top node, use the real collation, but don't trim fields.
834  if (orderExprList.size() > 0 && !bb.top) {
835  final List<RexNode> exprs = new ArrayList<>();
836  final RelDataType rowType = bb.root.getRowType();
837  final int fieldCount = rowType.getFieldCount() - orderExprList.size();
838  for (int i = 0; i < fieldCount; i++) {
839  exprs.add(rexBuilder.makeInputRef(bb.root, i));
840  }
841  bb.setRoot(LogicalProject.create(bb.root,
842  ImmutableList.of(),
843  exprs,
844  rowType.getFieldNames().subList(0, fieldCount)),
845  false);
846  }
847  }
848 
854  private static boolean containsInOperator(SqlNode node) {
855  try {
856  SqlVisitor<Void> visitor = new SqlBasicVisitor<Void>() {
857  public Void visit(SqlCall call) {
858  if (call.getOperator() instanceof SqlInOperator) {
859  throw new Util.FoundOne(call);
860  }
861  return super.visit(call);
862  }
863  };
864  node.accept(visitor);
865  return false;
866  } catch (Util.FoundOne e) {
867  Util.swallow(e, null);
868  return true;
869  }
870  }
871 
879  private static SqlNode pushDownNotForIn(SqlValidatorScope scope, SqlNode sqlNode) {
880  if (!(sqlNode instanceof SqlCall) || !containsInOperator(sqlNode)) {
881  return sqlNode;
882  }
883  final SqlCall sqlCall = (SqlCall) sqlNode;
884  switch (sqlCall.getKind()) {
885  case AND:
886  case OR:
887  final List<SqlNode> operands = new ArrayList<>();
888  for (SqlNode operand : sqlCall.getOperandList()) {
889  operands.add(pushDownNotForIn(scope, operand));
890  }
891  final SqlCall newCall =
892  sqlCall.getOperator().createCall(sqlCall.getParserPosition(), operands);
893  return reg(scope, newCall);
894 
895  case NOT:
896  assert sqlCall.operand(0) instanceof SqlCall;
897  final SqlCall call = sqlCall.operand(0);
898  switch (sqlCall.operand(0).getKind()) {
899  case CASE:
900  final SqlCase caseNode = (SqlCase) call;
901  final SqlNodeList thenOperands = new SqlNodeList(SqlParserPos.ZERO);
902 
903  for (SqlNode thenOperand : caseNode.getThenOperands()) {
904  final SqlCall not =
905  SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, thenOperand);
906  thenOperands.add(pushDownNotForIn(scope, reg(scope, not)));
907  }
908  SqlNode elseOperand = caseNode.getElseOperand();
909  if (!SqlUtil.isNull(elseOperand)) {
910  // "not(unknown)" is "unknown", so no need to simplify
911  final SqlCall not =
912  SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, elseOperand);
913  elseOperand = pushDownNotForIn(scope, reg(scope, not));
914  }
915 
916  return reg(scope,
917  SqlStdOperatorTable.CASE.createCall(SqlParserPos.ZERO,
918  caseNode.getValueOperand(),
919  caseNode.getWhenOperands(),
920  thenOperands,
921  elseOperand));
922 
923  case AND:
924  final List<SqlNode> orOperands = new ArrayList<>();
925  for (SqlNode operand : call.getOperandList()) {
926  orOperands.add(pushDownNotForIn(scope,
927  reg(scope,
928  SqlStdOperatorTable.NOT.createCall(
929  SqlParserPos.ZERO, operand))));
930  }
931  return reg(scope,
932  SqlStdOperatorTable.OR.createCall(SqlParserPos.ZERO, orOperands));
933 
934  case OR:
935  final List<SqlNode> andOperands = new ArrayList<>();
936  for (SqlNode operand : call.getOperandList()) {
937  andOperands.add(pushDownNotForIn(scope,
938  reg(scope,
939  SqlStdOperatorTable.NOT.createCall(
940  SqlParserPos.ZERO, operand))));
941  }
942  return reg(scope,
943  SqlStdOperatorTable.AND.createCall(SqlParserPos.ZERO, andOperands));
944 
945  case NOT:
946  assert call.operandCount() == 1;
947  return pushDownNotForIn(scope, call.operand(0));
948 
949  case NOT_IN:
950  return reg(scope,
951  SqlStdOperatorTable.IN.createCall(
952  SqlParserPos.ZERO, call.getOperandList()));
953 
954  case IN:
955  return reg(scope,
956  SqlStdOperatorTable.NOT_IN.createCall(
957  SqlParserPos.ZERO, call.getOperandList()));
958  }
959  }
960  return sqlNode;
961  }
962 
967  private static SqlNode reg(SqlValidatorScope scope, SqlNode e) {
968  scope.getValidator().deriveType(scope, e);
969  return e;
970  }
971 
978  private void convertWhere(final Blackboard bb, final SqlNode where) {
979  if (where == null) {
980  return;
981  }
982  SqlNode newWhere = pushDownNotForIn(bb.scope, where);
983  replaceSubQueries(bb, newWhere, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
984  final RexNode convertedWhere = bb.convertExpression(newWhere);
985  final RexNode convertedWhere2 =
986  RexUtil.removeNullabilityCast(typeFactory, convertedWhere);
987 
988  // only allocate filter if the condition is not TRUE
989  if (convertedWhere2.isAlwaysTrue()) {
990  return;
991  }
992 
993  final RelFactories.FilterFactory filterFactory = RelFactories.DEFAULT_FILTER_FACTORY;
994  final RelNode filter =
995  filterFactory.createFilter(bb.root, convertedWhere2, ImmutableSet.of());
996  final RelNode r;
997  final CorrelationUse p = getCorrelationUse(bb, filter);
998  if (p != null) {
999  assert p.r instanceof Filter;
1000  Filter f = (Filter) p.r;
1001  r = LogicalFilter.create(f.getInput(), f.getCondition(), ImmutableSet.of(p.id));
1002  } else {
1003  r = filter;
1004  }
1005 
1006  bb.setRoot(r, false);
1007  }
1008 
1009  private void replaceSubQueries(
1010  final Blackboard bb, final SqlNode expr, RelOptUtil.Logic logic) {
1011  findSubQueries(bb, expr, logic, false);
1012  for (SubQuery node : bb.subQueryList) {
1013  substituteSubQuery(bb, node);
1014  }
1015  }
1016 
1017  private void substituteSubQuery(Blackboard bb, SubQuery subQuery) {
1018  final RexNode expr = subQuery.expr;
1019  if (expr != null) {
1020  // Already done.
1021  return;
1022  }
1023 
1024  final SqlBasicCall call;
1025  final RelNode rel;
1026  final SqlNode query;
1027  final RelOptUtil.Exists converted;
1028 
1029  boolean isExpand = config.getExpandPredicate().test(bb.getTopNode(), subQuery.node);
1030 
1031  switch (subQuery.node.getKind()) {
1032  case CURSOR:
1033  convertCursor(bb, subQuery);
1034  return;
1035 
1036  case MULTISET_QUERY_CONSTRUCTOR:
1037  case MULTISET_VALUE_CONSTRUCTOR:
1038  case ARRAY_QUERY_CONSTRUCTOR:
1039  rel = convertMultisets(ImmutableList.of(subQuery.node), bb);
1040  subQuery.expr = bb.register(rel, JoinRelType.INNER);
1041  return;
1042 
1043  case IN:
1044  case NOT_IN:
1045  case SOME:
1046  case ALL:
1047  call = (SqlBasicCall) subQuery.node;
1048  query = call.operand(1);
1049  if (!isExpand && !(query instanceof SqlNodeList)) {
1050  return;
1051  }
1052  final SqlNode leftKeyNode = call.operand(0);
1053 
1054  final List<RexNode> leftKeys;
1055  switch (leftKeyNode.getKind()) {
1056  case ROW:
1057  leftKeys = new ArrayList<>();
1058  for (SqlNode sqlExpr : ((SqlBasicCall) leftKeyNode).getOperandList()) {
1059  leftKeys.add(bb.convertExpression(sqlExpr));
1060  }
1061  break;
1062  default:
1063  leftKeys = ImmutableList.of(bb.convertExpression(leftKeyNode));
1064  }
1065 
1066  if (query instanceof SqlNodeList) {
1067  SqlNodeList valueList = (SqlNodeList) query;
1068  if (!containsNullLiteral(valueList)
1069  && valueList.size() < config.getInSubQueryThreshold()) {
1070  // We're under the threshold, so convert to OR.
1071  subQuery.expr = convertInToOr(
1072  bb, leftKeys, valueList, (SqlInOperator) call.getOperator());
1073  return;
1074  }
1075 
1076  // Otherwise, let convertExists translate
1077  // values list into an inline table for the
1078  // reference to Q below.
1079  }
1080 
1081  // Project out the search columns from the left side
1082 
1083  // Q1:
1084  // "select from emp where emp.deptno in (select col1 from T)"
1085  //
1086  // is converted to
1087  //
1088  // "select from
1089  // emp inner join (select distinct col1 from T)) q
1090  // on emp.deptno = q.col1
1091  //
1092  // Q2:
1093  // "select from emp where emp.deptno not in (Q)"
1094  //
1095  // is converted to
1096  //
1097  // "select from
1098  // emp left outer join (select distinct col1, TRUE from T) q
1099  // on emp.deptno = q.col1
1100  // where emp.deptno <> null
1101  // and q.indicator <> TRUE"
1102  //
1103  // Note: Sub-query can be used as SqlUpdate#condition like below:
1104  //
1105  // UPDATE emp
1106  // SET empno = 1 WHERE emp.empno IN (
1107  // SELECT emp.empno FROM emp WHERE emp.empno = 2)
1108  //
1109  // In such case, when converting SqlUpdate#condition, bb.root is null
1110  // and it makes no sense to do the sub-query substitution.
1111  if (bb.root == null) {
1112  return;
1113  }
1114  final RelDataType targetRowType = SqlTypeUtil.promoteToRowType(
1115  typeFactory, validator.getValidatedNodeType(leftKeyNode), null);
1116  final boolean notIn = call.getOperator().kind == SqlKind.NOT_IN;
1117  converted = convertExists(
1118  query, RelOptUtil.SubQueryType.IN, subQuery.logic, notIn, targetRowType);
1119  if (converted.indicator) {
1120  // Generate
1121  // emp CROSS JOIN (SELECT COUNT(*) AS c,
1122  // COUNT(deptno) AS ck FROM dept)
1123  final RelDataType longType = typeFactory.createSqlType(SqlTypeName.BIGINT);
1124  final RelNode seek = converted.r.getInput(0); // fragile
1125  final int keyCount = leftKeys.size();
1126  final List<Integer> args = ImmutableIntList.range(0, keyCount);
1127  LogicalAggregate aggregate = LogicalAggregate.create(seek,
1128  ImmutableList.of(),
1129  ImmutableBitSet.of(),
1130  null,
1131  ImmutableList.of(AggregateCall.create(SqlStdOperatorTable.COUNT,
1132  false,
1133  false,
1134  false,
1135  ImmutableList.of(),
1136  -1,
1137  RelCollations.EMPTY,
1138  longType,
1139  null),
1140  AggregateCall.create(SqlStdOperatorTable.COUNT,
1141  false,
1142  false,
1143  false,
1144  args,
1145  -1,
1146  RelCollations.EMPTY,
1147  longType,
1148  null)));
1149  LogicalJoin join = LogicalJoin.create(bb.root,
1150  aggregate,
1151  ImmutableList.of(),
1152  rexBuilder.makeLiteral(true),
1153  ImmutableSet.of(),
1154  JoinRelType.INNER);
1155  bb.setRoot(join, false);
1156  }
1157  final RexNode rex = bb.register(converted.r,
1158  converted.outerJoin ? JoinRelType.LEFT : JoinRelType.INNER,
1159  leftKeys);
1160 
1161  RelOptUtil.Logic logic = subQuery.logic;
1162  switch (logic) {
1163  case TRUE_FALSE_UNKNOWN:
1164  case UNKNOWN_AS_TRUE:
1165  if (!converted.indicator) {
1166  logic = RelOptUtil.Logic.TRUE_FALSE;
1167  }
1168  }
1169  subQuery.expr = translateIn(logic, bb.root, rex);
1170  if (notIn) {
1171  subQuery.expr = rexBuilder.makeCall(SqlStdOperatorTable.NOT, subQuery.expr);
1172  }
1173  return;
1174 
1175  case EXISTS:
1176  // "select from emp where exists (select a from T)"
1177  //
1178  // is converted to the following if the sub-query is correlated:
1179  //
1180  // "select from emp left outer join (select AGG_TRUE() as indicator
1181  // from T group by corr_var) q where q.indicator is true"
1182  //
1183  // If there is no correlation, the expression is replaced with a
1184  // boolean indicating whether the sub-query returned 0 or >= 1 row.
1185  call = (SqlBasicCall) subQuery.node;
1186  query = call.operand(0);
1187  if (!isExpand) {
1188  return;
1189  }
1190  final SqlValidatorScope seekScope = (query instanceof SqlSelect)
1191  ? validator.getSelectScope((SqlSelect) query)
1192  : null;
1193  final Blackboard seekBb = createBlackboard(seekScope, null, false);
1194  final RelNode seekRel = convertQueryOrInList(seekBb, query, null);
1195  // An EXIST sub-query whose inner child has at least 1 tuple
1196  // (e.g. an Aggregate with no grouping columns or non-empty Values
1197  // node) should be simplified to a Boolean constant expression.
1198  final RelMetadataQuery mq = seekRel.getCluster().getMetadataQuery();
1199  final Double minRowCount = mq.getMinRowCount(seekRel);
1200  if (minRowCount != null && minRowCount >= 1D) {
1201  subQuery.expr = rexBuilder.makeLiteral(true);
1202  return;
1203  }
1204  converted = RelOptUtil.createExistsPlan(seekRel,
1205  RelOptUtil.SubQueryType.EXISTS,
1206  subQuery.logic,
1207  true,
1208  relBuilder);
1209  assert !converted.indicator;
1210  if (convertNonCorrelatedSubQuery(subQuery, bb, converted.r, true)) {
1211  return;
1212  }
1213  subQuery.expr = bb.register(converted.r, JoinRelType.LEFT);
1214  return;
1215 
1216  case SCALAR_QUERY:
1217  // Convert the sub-query. If it's non-correlated, convert it
1218  // to a constant expression.
1219  if (!isExpand) {
1220  return;
1221  }
1222  call = (SqlBasicCall) subQuery.node;
1223  query = call.operand(0);
1224  converted = convertExists(
1225  query, RelOptUtil.SubQueryType.SCALAR, subQuery.logic, true, null);
1226  assert !converted.indicator;
1227  if (convertNonCorrelatedSubQuery(subQuery, bb, converted.r, false)) {
1228  return;
1229  }
1230  rel = convertToSingleValueSubq(query, converted.r);
1231  subQuery.expr = bb.register(rel, JoinRelType.LEFT);
1232  return;
1233 
1234  case SELECT:
1235  // This is used when converting multiset queries:
1236  //
1237  // select * from unnest(select multiset[deptno] from emps);
1238  //
1239  converted = convertExists(subQuery.node,
1240  RelOptUtil.SubQueryType.SCALAR,
1241  subQuery.logic,
1242  true,
1243  null);
1244  assert !converted.indicator;
1245  subQuery.expr = bb.register(converted.r, JoinRelType.LEFT);
1246 
1247  // This is used when converting window table functions:
1248  //
1249  // select * from table(tumble(table emps, descriptor(deptno), interval '3' DAY))
1250  //
1251  bb.cursors.add(converted.r);
1252  return;
1253 
1254  default:
1255  throw new AssertionError("unexpected kind of sub-query: " + subQuery.node);
1256  }
1257  }
1258 
1259  private RexNode translateIn(RelOptUtil.Logic logic, RelNode root, final RexNode rex) {
1260  switch (logic) {
1261  case TRUE:
1262  return rexBuilder.makeLiteral(true);
1263 
1264  case TRUE_FALSE:
1265  case UNKNOWN_AS_FALSE:
1266  assert rex instanceof RexRangeRef;
1267  final int fieldCount = rex.getType().getFieldCount();
1268  RexNode rexNode = rexBuilder.makeFieldAccess(rex, fieldCount - 1);
1269  rexNode = rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, rexNode);
1270 
1271  // Then append the IS NOT NULL(leftKeysForIn).
1272  //
1273  // RexRangeRef contains the following fields:
1274  // leftKeysForIn,
1275  // rightKeysForIn (the original sub-query select list),
1276  // nullIndicator
1277  //
1278  // The first two lists contain the same number of fields.
1279  final int k = (fieldCount - 1) / 2;
1280  for (int i = 0; i < k; i++) {
1281  rexNode = rexBuilder.makeCall(SqlStdOperatorTable.AND,
1282  rexNode,
1283  rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL,
1284  rexBuilder.makeFieldAccess(rex, i)));
1285  }
1286  return rexNode;
1287 
1288  case TRUE_FALSE_UNKNOWN:
1289  case UNKNOWN_AS_TRUE:
1290  // select e.deptno,
1291  // case
1292  // when ct.c = 0 then false
1293  // when dt.i is not null then true
1294  // when e.deptno is null then null
1295  // when ct.ck < ct.c then null
1296  // else false
1297  // end
1298  // from e
1299  // cross join (select count(*) as c, count(deptno) as ck from v) as ct
1300  // left join (select distinct deptno, true as i from v) as dt
1301  // on e.deptno = dt.deptno
1302  final Join join = (Join) root;
1303  final Project left = (Project) join.getLeft();
1304  final RelNode leftLeft = ((Join) left.getInput()).getLeft();
1305  final int leftLeftCount = leftLeft.getRowType().getFieldCount();
1306  final RelDataType longType = typeFactory.createSqlType(SqlTypeName.BIGINT);
1307  final RexNode cRef = rexBuilder.makeInputRef(root, leftLeftCount);
1308  final RexNode ckRef = rexBuilder.makeInputRef(root, leftLeftCount + 1);
1309  final RexNode iRef =
1310  rexBuilder.makeInputRef(root, root.getRowType().getFieldCount() - 1);
1311 
1312  final RexLiteral zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO, longType);
1313  final RexLiteral trueLiteral = rexBuilder.makeLiteral(true);
1314  final RexLiteral falseLiteral = rexBuilder.makeLiteral(false);
1315  final RexNode unknownLiteral = rexBuilder.makeNullLiteral(trueLiteral.getType());
1316 
1317  final ImmutableList.Builder<RexNode> args = ImmutableList.builder();
1318  args.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, cRef, zero),
1319  falseLiteral,
1320  rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, iRef),
1321  trueLiteral);
1322  final JoinInfo joinInfo = join.analyzeCondition();
1323  for (int leftKey : joinInfo.leftKeys) {
1324  final RexNode kRef = rexBuilder.makeInputRef(root, leftKey);
1325  args.add(
1326  rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, kRef), unknownLiteral);
1327  }
1328  args.add(rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, ckRef, cRef),
1329  unknownLiteral,
1330  falseLiteral);
1331 
1332  return rexBuilder.makeCall(SqlStdOperatorTable.CASE, args.build());
1333 
1334  default:
1335  throw new AssertionError(logic);
1336  }
1337  }
1338 
1339  private static boolean containsNullLiteral(SqlNodeList valueList) {
1340  for (SqlNode node : valueList.getList()) {
1341  if (node instanceof SqlLiteral) {
1342  SqlLiteral lit = (SqlLiteral) node;
1343  if (lit.getValue() == null) {
1344  return true;
1345  }
1346  }
1347  }
1348  return false;
1349  }
1350 
1362  SubQuery subQuery, Blackboard bb, RelNode converted, boolean isExists) {
1363  SqlCall call = (SqlBasicCall) subQuery.node;
1364  if (subQueryConverter.canConvertSubQuery()
1365  && isSubQueryNonCorrelated(converted, bb)) {
1366  // First check if the sub-query has already been converted
1367  // because it's a nested sub-query. If so, don't re-evaluate
1368  // it again.
1369  RexNode constExpr = mapConvertedNonCorrSubqs.get(call);
1370  if (constExpr == null) {
1371  constExpr = subQueryConverter.convertSubQuery(
1372  call, this, isExists, config.isExplain());
1373  }
1374  if (constExpr != null) {
1375  subQuery.expr = constExpr;
1376  mapConvertedNonCorrSubqs.put(call, constExpr);
1377  return true;
1378  }
1379  }
1380  return false;
1381  }
1382 
1391  public RelNode convertToSingleValueSubq(SqlNode query, RelNode plan) {
1392  // Check whether query is guaranteed to produce a single value.
1393  if (query instanceof SqlSelect) {
1394  SqlSelect select = (SqlSelect) query;
1395  SqlNodeList selectList = select.getSelectList();
1396  SqlNodeList groupList = select.getGroup();
1397 
1398  if ((selectList.size() == 1) && ((groupList == null) || (groupList.size() == 0))) {
1399  SqlNode selectExpr = selectList.get(0);
1400  if (selectExpr instanceof SqlCall) {
1401  SqlCall selectExprCall = (SqlCall) selectExpr;
1402  if (Util.isSingleValue(selectExprCall)) {
1403  return plan;
1404  }
1405  }
1406 
1407  // If there is a limit with 0 or 1,
1408  // it is ensured to produce a single value
1409  if (select.getFetch() != null && select.getFetch() instanceof SqlNumericLiteral) {
1410  SqlNumericLiteral limitNum = (SqlNumericLiteral) select.getFetch();
1411  if (((BigDecimal) limitNum.getValue()).intValue() < 2) {
1412  return plan;
1413  }
1414  }
1415  }
1416  } else if (query instanceof SqlCall) {
1417  // If the query is (values ...),
1418  // it is necessary to look into the operands to determine
1419  // whether SingleValueAgg is necessary
1420  SqlCall exprCall = (SqlCall) query;
1421  if (exprCall.getOperator() instanceof SqlValuesOperator
1422  && Util.isSingleValue(exprCall)) {
1423  return plan;
1424  }
1425  }
1426 
1427  // If not, project SingleValueAgg
1428  return RelOptUtil.createSingleValueAggRel(cluster, plan);
1429  }
1430 
1439  private RexNode convertInToOr(final Blackboard bb,
1440  final List<RexNode> leftKeys,
1441  SqlNodeList valuesList,
1442  SqlInOperator op) {
1443  final List<RexNode> comparisons = new ArrayList<>();
1444  for (SqlNode rightVals : valuesList) {
1445  RexNode rexComparison;
1446  final SqlOperator comparisonOp;
1447  if (op instanceof SqlQuantifyOperator) {
1448  comparisonOp = RelOptUtil.op(
1449  ((SqlQuantifyOperator) op).comparisonKind, SqlStdOperatorTable.EQUALS);
1450  } else {
1451  comparisonOp = SqlStdOperatorTable.EQUALS;
1452  }
1453  if (leftKeys.size() == 1) {
1454  rexComparison = rexBuilder.makeCall(comparisonOp,
1455  leftKeys.get(0),
1456  ensureSqlType(
1457  leftKeys.get(0).getType(), bb.convertExpression(rightVals)));
1458  } else {
1459  assert rightVals instanceof SqlCall;
1460  final SqlBasicCall call = (SqlBasicCall) rightVals;
1461  assert (call.getOperator() instanceof SqlRowOperator)
1462  && call.operandCount() == leftKeys.size();
1463  rexComparison = RexUtil.composeConjunction(rexBuilder,
1464  Iterables.transform(Pair.zip(leftKeys, call.getOperandList()),
1465  pair
1466  -> rexBuilder.makeCall(comparisonOp,
1467  pair.left,
1468  ensureSqlType(pair.left.getType(),
1469  bb.convertExpression(pair.right)))));
1470  }
1471  comparisons.add(rexComparison);
1472  }
1473 
1474  switch (op.kind) {
1475  case ALL:
1476  return RexUtil.composeConjunction(rexBuilder, comparisons, true);
1477  case NOT_IN:
1478  return rexBuilder.makeCall(SqlStdOperatorTable.NOT,
1479  RexUtil.composeDisjunction(rexBuilder, comparisons, true));
1480  case IN:
1481  case SOME:
1482  return RexUtil.composeDisjunction(rexBuilder, comparisons, true);
1483  default:
1484  throw new AssertionError();
1485  }
1486  }
1487 
1493  private RexNode ensureSqlType(RelDataType type, RexNode node) {
1494  if (type.getSqlTypeName() == node.getType().getSqlTypeName()
1495  || (type.getSqlTypeName() == SqlTypeName.VARCHAR
1496  && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) {
1497  return node;
1498  }
1499  return rexBuilder.ensureType(type, node, true);
1500  }
1501 
1511  @Deprecated // to be removed before 2.0
1512  protected int getInSubqueryThreshold() {
1513  return config.getInSubQueryThreshold();
1514  }
1515 
1533  private RelOptUtil.Exists convertExists(SqlNode seek,
1534  RelOptUtil.SubQueryType subQueryType,
1535  RelOptUtil.Logic logic,
1536  boolean notIn,
1537  RelDataType targetDataType) {
1538  final SqlValidatorScope seekScope = (seek instanceof SqlSelect)
1539  ? validator.getSelectScope((SqlSelect) seek)
1540  : null;
1541  final Blackboard seekBb = createBlackboard(seekScope, null, false);
1542  RelNode seekRel = convertQueryOrInList(seekBb, seek, targetDataType);
1543 
1544  return RelOptUtil.createExistsPlan(seekRel, subQueryType, logic, notIn, relBuilder);
1545  }
1546 
1547  private RelNode convertQueryOrInList(
1548  Blackboard bb, SqlNode seek, RelDataType targetRowType) {
1549  // NOTE: Once we start accepting single-row queries as row constructors,
1550  // there will be an ambiguity here for a case like X IN ((SELECT Y FROM
1551  // Z)). The SQL standard resolves the ambiguity by saying that a lone
1552  // select should be interpreted as a table expression, not a row
1553  // expression. The semantic difference is that a table expression can
1554  // return multiple rows.
1555  if (seek instanceof SqlNodeList) {
1556  return convertRowValues(
1557  bb, seek, ((SqlNodeList) seek).getList(), false, targetRowType);
1558  } else {
1559  return convertQueryRecursive(seek, false, null).project();
1560  }
1561  }
1562 
1563  private RelNode convertRowValues(Blackboard bb,
1564  SqlNode rowList,
1565  Collection<SqlNode> rows,
1566  boolean allowLiteralsOnly,
1567  RelDataType targetRowType) {
1568  // NOTE jvs 30-Apr-2006: We combine all rows consisting entirely of
1569  // literals into a single LogicalValues; this gives the optimizer a smaller
1570  // input tree. For everything else (computed expressions, row
1571  // sub-queries), we union each row in as a projection on top of a
1572  // LogicalOneRow.
1573 
1574  final ImmutableList.Builder<ImmutableList<RexLiteral>> tupleList =
1575  ImmutableList.builder();
1576  final RelDataType rowType;
1577  if (targetRowType != null) {
1578  rowType = targetRowType;
1579  } else {
1580  rowType = SqlTypeUtil.promoteToRowType(
1581  typeFactory, validator.getValidatedNodeType(rowList), null);
1582  }
1583 
1584  final List<RelNode> unionInputs = new ArrayList<>();
1585  for (SqlNode node : rows) {
1586  SqlBasicCall call;
1587  if (isRowConstructor(node)) {
1588  call = (SqlBasicCall) node;
1589  ImmutableList.Builder<RexLiteral> tuple = ImmutableList.builder();
1590  for (Ord<SqlNode> operand : Ord.zip(call.operands)) {
1591  RexLiteral rexLiteral =
1592  convertLiteralInValuesList(operand.e, bb, rowType, operand.i);
1593  if ((rexLiteral == null) && allowLiteralsOnly) {
1594  return null;
1595  }
1596  if ((rexLiteral == null) || !config.isCreateValuesRel()) {
1597  // fallback to convertRowConstructor
1598  tuple = null;
1599  break;
1600  }
1601  tuple.add(rexLiteral);
1602  }
1603  if (tuple != null) {
1604  tupleList.add(tuple.build());
1605  continue;
1606  }
1607  } else {
1608  RexLiteral rexLiteral = convertLiteralInValuesList(node, bb, rowType, 0);
1609  if ((rexLiteral != null) && config.isCreateValuesRel()) {
1610  tupleList.add(ImmutableList.of(rexLiteral));
1611  continue;
1612  } else {
1613  if ((rexLiteral == null) && allowLiteralsOnly) {
1614  return null;
1615  }
1616  }
1617 
1618  // convert "1" to "row(1)"
1619  call = (SqlBasicCall) SqlStdOperatorTable.ROW.createCall(SqlParserPos.ZERO, node);
1620  }
1621  unionInputs.add(convertRowConstructor(bb, call));
1622  }
1623  LogicalValues values = LogicalValues.create(cluster, rowType, tupleList.build());
1624  RelNode resultRel;
1625  if (unionInputs.isEmpty()) {
1626  resultRel = values;
1627  } else {
1628  if (!values.getTuples().isEmpty()) {
1629  unionInputs.add(values);
1630  }
1631  resultRel = LogicalUnion.create(unionInputs, true);
1632  }
1633  leaves.put(resultRel, resultRel.getRowType().getFieldCount());
1634  return resultRel;
1635  }
1636 
1637  private RexLiteral convertLiteralInValuesList(
1638  SqlNode sqlNode, Blackboard bb, RelDataType rowType, int iField) {
1639  if (!(sqlNode instanceof SqlLiteral)) {
1640  return null;
1641  }
1642  RelDataTypeField field = rowType.getFieldList().get(iField);
1643  RelDataType type = field.getType();
1644  if (type.isStruct()) {
1645  // null literals for weird stuff like UDT's need
1646  // special handling during type flattening, so
1647  // don't use LogicalValues for those
1648  return null;
1649  }
1650 
1651  RexNode literalExpr = exprConverter.convertLiteral(bb, (SqlLiteral) sqlNode);
1652 
1653  if (!(literalExpr instanceof RexLiteral)) {
1654  assert literalExpr.isA(SqlKind.CAST);
1655  RexNode child = ((RexCall) literalExpr).getOperands().get(0);
1656  assert RexLiteral.isNullLiteral(child);
1657 
1658  // NOTE jvs 22-Nov-2006: we preserve type info
1659  // in LogicalValues digest, so it's OK to lose it here
1660  return (RexLiteral) child;
1661  }
1662 
1663  RexLiteral literal = (RexLiteral) literalExpr;
1664 
1665  Comparable value = literal.getValue();
1666 
1667  if (SqlTypeUtil.isExactNumeric(type) && SqlTypeUtil.hasScale(type)) {
1668  BigDecimal roundedValue =
1669  NumberUtil.rescaleBigDecimal((BigDecimal) value, type.getScale());
1670  return rexBuilder.makeExactLiteral(roundedValue, type);
1671  }
1672 
1673  if ((value instanceof NlsString) && (type.getSqlTypeName() == SqlTypeName.CHAR)) {
1674  // pad fixed character type
1675  NlsString unpadded = (NlsString) value;
1676  return rexBuilder.makeCharLiteral(
1677  new NlsString(Spaces.padRight(unpadded.getValue(), type.getPrecision()),
1678  unpadded.getCharsetName(),
1679  unpadded.getCollation()));
1680  }
1681  return literal;
1682  }
1683 
1684  private boolean isRowConstructor(SqlNode node) {
1685  if (!(node.getKind() == SqlKind.ROW)) {
1686  return false;
1687  }
1688  SqlCall call = (SqlCall) node;
1689  return call.getOperator().getName().equalsIgnoreCase("row");
1690  }
1691 
1708  private void findSubQueries(Blackboard bb,
1709  SqlNode node,
1710  RelOptUtil.Logic logic,
1711  boolean registerOnlyScalarSubQueries) {
1712  final SqlKind kind = node.getKind();
1713  switch (kind) {
1714  case EXISTS:
1715  case SELECT:
1716  case MULTISET_QUERY_CONSTRUCTOR:
1717  case MULTISET_VALUE_CONSTRUCTOR:
1718  case ARRAY_QUERY_CONSTRUCTOR:
1719  case CURSOR:
1720  case SCALAR_QUERY:
1721  if (!registerOnlyScalarSubQueries || (kind == SqlKind.SCALAR_QUERY)) {
1722  bb.registerSubQuery(node, RelOptUtil.Logic.TRUE_FALSE);
1723  }
1724  return;
1725  case IN:
1726  break;
1727  case NOT_IN:
1728  case NOT:
1729  logic = logic.negate();
1730  break;
1731  }
1732  if (node instanceof SqlCall) {
1733  switch (kind) {
1734  // Do no change logic for AND, IN and NOT IN expressions;
1735  // but do change logic for OR, NOT and others;
1736  // EXISTS was handled already.
1737  case AND:
1738  case IN:
1739  case NOT_IN:
1740  break;
1741  default:
1742  logic = RelOptUtil.Logic.TRUE_FALSE_UNKNOWN;
1743  break;
1744  }
1745  for (SqlNode operand : ((SqlCall) node).getOperandList()) {
1746  if (operand != null) {
1747  // In the case of an IN expression, locate scalar
1748  // sub-queries so we can convert them to constants
1749  findSubQueries(bb,
1750  operand,
1751  logic,
1752  kind == SqlKind.IN || kind == SqlKind.NOT_IN || kind == SqlKind.SOME
1753  || kind == SqlKind.ALL || registerOnlyScalarSubQueries);
1754  }
1755  }
1756  } else if (node instanceof SqlNodeList) {
1757  for (SqlNode child : (SqlNodeList) node) {
1758  findSubQueries(bb,
1759  child,
1760  logic,
1761  kind == SqlKind.IN || kind == SqlKind.NOT_IN || kind == SqlKind.SOME
1762  || kind == SqlKind.ALL || registerOnlyScalarSubQueries);
1763  }
1764  }
1765 
1766  // Now that we've located any scalar sub-queries inside the IN
1767  // expression, register the IN expression itself. We need to
1768  // register the scalar sub-queries first so they can be converted
1769  // before the IN expression is converted.
1770  switch (kind) {
1771  case IN:
1772  case NOT_IN:
1773  case SOME:
1774  case ALL:
1775  switch (logic) {
1776  case TRUE_FALSE_UNKNOWN:
1777  RelDataType type = validator.getValidatedNodeTypeIfKnown(node);
1778  if (type == null) {
1779  // The node might not be validated if we still don't know type of the node.
1780  // Therefore return directly.
1781  return;
1782  } else {
1783  break;
1784  }
1785  // fall through
1786  case UNKNOWN_AS_FALSE:
1787  logic = RelOptUtil.Logic.TRUE;
1788  }
1789  bb.registerSubQuery(node, logic);
1790  break;
1791  }
1792  }
1793 
1800  public RexNode convertExpression(SqlNode node) {
1801  Map<String, RelDataType> nameToTypeMap = Collections.emptyMap();
1802  final ParameterScope scope =
1803  new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap);
1804  final Blackboard bb = createBlackboard(scope, null, false);
1805  return bb.convertExpression(node);
1806  }
1807 
1819  public RexNode convertExpression(SqlNode node, Map<String, RexNode> nameToNodeMap) {
1820  final Map<String, RelDataType> nameToTypeMap = new HashMap<>();
1821  for (Map.Entry<String, RexNode> entry : nameToNodeMap.entrySet()) {
1822  nameToTypeMap.put(entry.getKey(), entry.getValue().getType());
1823  }
1824  final ParameterScope scope =
1825  new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap);
1826  final Blackboard bb = createBlackboard(scope, nameToNodeMap, false);
1827  return bb.convertExpression(node);
1828  }
1829 
1842  protected RexNode convertExtendedExpression(SqlNode node, Blackboard bb) {
1843  return null;
1844  }
1845 
1846  private RexNode convertOver(Blackboard bb, SqlNode node) {
1847  SqlCall call = (SqlCall) node;
1848  SqlCall aggCall = call.operand(0);
1849  boolean ignoreNulls = false;
1850  switch (aggCall.getKind()) {
1851  case IGNORE_NULLS:
1852  ignoreNulls = true;
1853  // fall through
1854  case RESPECT_NULLS:
1855  aggCall = aggCall.operand(0);
1856  }
1857 
1858  SqlNode windowOrRef = call.operand(1);
1859  final SqlWindow window = validator.resolveWindow(windowOrRef, bb.scope);
1860 
1861  SqlNode sqlLowerBound = window.getLowerBound();
1862  SqlNode sqlUpperBound = window.getUpperBound();
1863  boolean rows = window.isRows();
1864  SqlNodeList orderList = window.getOrderList();
1865 
1866  if (!aggCall.getOperator().allowsFraming()) {
1867  // If the operator does not allow framing, bracketing is implicitly
1868  // everything up to the current row.
1869  sqlLowerBound = SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO);
1870  sqlUpperBound = SqlWindow.createCurrentRow(SqlParserPos.ZERO);
1871  if (aggCall.getKind() == SqlKind.ROW_NUMBER) {
1872  // ROW_NUMBER() expects specific kind of framing.
1873  rows = true;
1874  }
1875  } else if (orderList.size() == 0) {
1876  // Without ORDER BY, there must be no bracketing.
1877  sqlLowerBound = SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO);
1878  sqlUpperBound = SqlWindow.createUnboundedFollowing(SqlParserPos.ZERO);
1879  } else if (sqlLowerBound == null && sqlUpperBound == null) {
1880  sqlLowerBound = SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO);
1881  sqlUpperBound = SqlWindow.createCurrentRow(SqlParserPos.ZERO);
1882  } else if (sqlUpperBound == null) {
1883  sqlUpperBound = SqlWindow.createCurrentRow(SqlParserPos.ZERO);
1884  } else if (sqlLowerBound == null) {
1885  sqlLowerBound = SqlWindow.createCurrentRow(SqlParserPos.ZERO);
1886  }
1887  final SqlNodeList partitionList = window.getPartitionList();
1888  final ImmutableList.Builder<RexNode> partitionKeys = ImmutableList.builder();
1889  for (SqlNode partition : partitionList) {
1890  partitionKeys.add(bb.convertExpression(partition));
1891  }
1892  final RexNode lowerBound = bb.convertExpression(sqlLowerBound);
1893  final RexNode upperBound = bb.convertExpression(sqlUpperBound);
1894  if (orderList.size() == 0 && !rows) {
1895  // A logical range requires an ORDER BY clause. Use the implicit
1896  // ordering of this relation. There must be one, otherwise it would
1897  // have failed validation.
1898  orderList = bb.scope.getOrderList();
1899  if (orderList == null) {
1900  throw new AssertionError("Relation should have sort key for implicit ORDER BY");
1901  }
1902  }
1903 
1904  final ImmutableList.Builder<RexFieldCollation> orderKeys = ImmutableList.builder();
1905  for (SqlNode order : orderList) {
1906  orderKeys.add(bb.convertSortExpression(order,
1907  RelFieldCollation.Direction.ASCENDING,
1908  RelFieldCollation.NullDirection.UNSPECIFIED));
1909  }
1910 
1911  try {
1912  Preconditions.checkArgument(bb.window == null, "already in window agg mode");
1913  bb.window = window;
1914  RexNode rexAgg = exprConverter.convertCall(bb, aggCall);
1915  rexAgg = rexBuilder.ensureType(validator.getValidatedNodeType(call), rexAgg, false);
1916 
1917  // Walk over the tree and apply 'over' to all agg functions. This is
1918  // necessary because the returned expression is not necessarily a call
1919  // to an agg function. For example, AVG(x) becomes SUM(x) / COUNT(x).
1920 
1921  final SqlLiteral q = aggCall.getFunctionQuantifier();
1922  final boolean isDistinct = q != null && q.getValue() == SqlSelectKeyword.DISTINCT;
1923 
1924  final RexShuttle visitor = new HistogramShuttle(partitionKeys.build(),
1925  orderKeys.build(),
1926  RexWindowBounds.create(sqlLowerBound, lowerBound),
1927  RexWindowBounds.create(sqlUpperBound, upperBound),
1928  rows,
1929  window.isAllowPartial(),
1930  isDistinct,
1931  ignoreNulls);
1932  return rexAgg.accept(visitor);
1933  } finally {
1934  bb.window = null;
1935  }
1936  }
1937 
1938  protected void convertFrom(Blackboard bb, SqlNode from) {
1939  convertFrom(bb, from, Collections.emptyList());
1940  }
1941 
1960  protected void convertFrom(Blackboard bb, SqlNode from, List<String> fieldNames) {
1961  if (from == null) {
1962  bb.setRoot(LogicalValues.createOneRow(cluster), false);
1963  return;
1964  }
1965 
1966  final SqlCall call;
1967  final SqlNode[] operands;
1968  switch (from.getKind()) {
1969  case MATCH_RECOGNIZE:
1970  convertMatchRecognize(bb, (SqlCall) from);
1971  return;
1972 
1973  case AS:
1974  call = (SqlCall) from;
1975  SqlNode firstOperand = call.operand(0);
1976  final List<String> fieldNameList = new ArrayList<>();
1977  if (call.operandCount() > 2) {
1978  for (SqlNode node : Util.skip(call.getOperandList(), 2)) {
1979  fieldNameList.add(((SqlIdentifier) node).getSimple());
1980  }
1981  }
1982  convertFrom(bb, firstOperand, fieldNameList);
1983  return;
1984 
1985  case WITH_ITEM:
1986  convertFrom(bb, ((SqlWithItem) from).query);
1987  return;
1988 
1989  case WITH:
1990  convertFrom(bb, ((SqlWith) from).body);
1991  return;
1992 
1993  case TABLESAMPLE:
1994  operands = ((SqlBasicCall) from).getOperands();
1995  SqlSampleSpec sampleSpec = SqlLiteral.sampleValue(operands[1]);
1996  if (sampleSpec instanceof SqlSampleSpec.SqlSubstitutionSampleSpec) {
1997  String sampleName =
1998  ((SqlSampleSpec.SqlSubstitutionSampleSpec) sampleSpec).getName();
1999  datasetStack.push(sampleName);
2000  convertFrom(bb, operands[0]);
2001  datasetStack.pop();
2002  } else if (sampleSpec instanceof SqlSampleSpec.SqlTableSampleSpec) {
2003  SqlSampleSpec.SqlTableSampleSpec tableSampleSpec =
2004  (SqlSampleSpec.SqlTableSampleSpec) sampleSpec;
2005  convertFrom(bb, operands[0]);
2006  RelOptSamplingParameters params =
2007  new RelOptSamplingParameters(tableSampleSpec.isBernoulli(),
2008  tableSampleSpec.getSamplePercentage(),
2009  tableSampleSpec.isRepeatable(),
2010  tableSampleSpec.getRepeatableSeed());
2011  bb.setRoot(new Sample(cluster, bb.root, params), false);
2012  } else {
2013  throw new AssertionError("unknown TABLESAMPLE type: " + sampleSpec);
2014  }
2015  return;
2016 
2017  case TABLE_REF:
2018  call = (SqlCall) from;
2019  convertIdentifier(bb, call.operand(0), null, call.operand(1));
2020  return;
2021 
2022  case IDENTIFIER:
2023  convertIdentifier(bb, (SqlIdentifier) from, null, null);
2024  return;
2025 
2026  case EXTEND:
2027  call = (SqlCall) from;
2028  final SqlNode operand0 = call.getOperandList().get(0);
2029  final SqlIdentifier id = operand0.getKind() == SqlKind.TABLE_REF
2030  ? ((SqlCall) operand0).operand(0)
2031  : (SqlIdentifier) operand0;
2032  SqlNodeList extendedColumns = (SqlNodeList) call.getOperandList().get(1);
2033  convertIdentifier(bb, id, extendedColumns, null);
2034  return;
2035 
2036  case SNAPSHOT:
2037  convertTemporalTable(bb, (SqlCall) from);
2038  return;
2039 
2040  case JOIN:
2041  final SqlJoin join = (SqlJoin) from;
2042  final SqlValidatorScope scope = validator.getJoinScope(from);
2043  final Blackboard fromBlackboard = createBlackboard(scope, null, false);
2044  SqlNode left = join.getLeft();
2045  SqlNode right = join.getRight();
2046  final boolean isNatural = join.isNatural();
2047  final JoinType joinType = join.getJoinType();
2048  final SqlValidatorScope leftScope = Util.first(
2049  validator.getJoinScope(left), ((DelegatingScope) bb.scope).getParent());
2050  final Blackboard leftBlackboard = createBlackboard(leftScope, null, false);
2051  final SqlValidatorScope rightScope = Util.first(
2052  validator.getJoinScope(right), ((DelegatingScope) bb.scope).getParent());
2053  final Blackboard rightBlackboard = createBlackboard(rightScope, null, false);
2054  convertFrom(leftBlackboard, left);
2055  RelNode leftRel = leftBlackboard.root;
2056  convertFrom(rightBlackboard, right);
2057  RelNode rightRel = rightBlackboard.root;
2058  JoinRelType convertedJoinType = convertJoinType(joinType);
2059  RexNode conditionExp;
2060  final SqlValidatorNamespace leftNamespace = validator.getNamespace(left);
2061  final SqlValidatorNamespace rightNamespace = validator.getNamespace(right);
2062  if (isNatural) {
2063  final RelDataType leftRowType = leftNamespace.getRowType();
2064  final RelDataType rightRowType = rightNamespace.getRowType();
2065  final List<String> columnList = SqlValidatorUtil.deriveNaturalJoinColumnList(
2066  catalogReader.nameMatcher(), leftRowType, rightRowType);
2067  conditionExp = convertUsing(leftNamespace, rightNamespace, columnList);
2068  } else {
2069  conditionExp = convertJoinCondition(fromBlackboard,
2070  leftNamespace,
2071  rightNamespace,
2072  join.getCondition(),
2073  join.getConditionType(),
2074  leftRel,
2075  rightRel);
2076  }
2077 
2078  final RelNode joinRel = createJoin(
2079  fromBlackboard, leftRel, rightRel, conditionExp, convertedJoinType);
2080  bb.setRoot(joinRel, false);
2081  return;
2082 
2083  case SELECT:
2084  case INTERSECT:
2085  case EXCEPT:
2086  case UNION:
2087  final RelNode rel = convertQueryRecursive(from, false, null).project();
2088  bb.setRoot(rel, true);
2089  return;
2090 
2091  case VALUES:
2092  convertValuesImpl(bb, (SqlCall) from, null);
2093  if (fieldNames.size() > 0) {
2094  bb.setRoot(relBuilder.push(bb.root).rename(fieldNames).build(), true);
2095  }
2096  return;
2097 
2098  case UNNEST:
2099  convertUnnest(bb, (SqlCall) from, fieldNames);
2100  return;
2101 
2102  case COLLECTION_TABLE:
2103  call = (SqlCall) from;
2104 
2105  // Dig out real call; TABLE() wrapper is just syntactic.
2106  assert call.getOperandList().size() == 1;
2107  final SqlCall call2 = call.operand(0);
2108  convertCollectionTable(bb, call2);
2109  return;
2110 
2111  default:
2112  throw new AssertionError("not a join operator " + from);
2113  }
2114  }
2115 
2116  private void convertUnnest(Blackboard bb, SqlCall call, List<String> fieldNames) {
2117  final List<SqlNode> nodes = call.getOperandList();
2118  final SqlUnnestOperator operator = (SqlUnnestOperator) call.getOperator();
2119  for (SqlNode node : nodes) {
2120  replaceSubQueries(bb, node, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2121  }
2122  final List<RexNode> exprs = new ArrayList<>();
2123  for (Ord<SqlNode> node : Ord.zip(nodes)) {
2124  exprs.add(relBuilder.alias(
2125  bb.convertExpression(node.e), validator.deriveAlias(node.e, node.i)));
2126  }
2127  RelNode child = (null != bb.root) ? bb.root : LogicalValues.createOneRow(cluster);
2128  RelNode uncollect;
2129  if (validator.config().sqlConformance().allowAliasUnnestItems()) {
2130  uncollect = relBuilder.push(child)
2131  .project(exprs)
2132  .uncollect(fieldNames, operator.withOrdinality)
2133  .build();
2134  } else {
2135  // REVIEW danny 2020-04-26: should we unify the normal field aliases and the
2136  // item aliases ?
2137  uncollect = relBuilder.push(child)
2138  .project(exprs)
2139  .uncollect(Collections.emptyList(), operator.withOrdinality)
2140  .rename(fieldNames)
2141  .build();
2142  }
2143  bb.setRoot(uncollect, true);
2144  }
2145 
2146  protected void convertMatchRecognize(Blackboard bb, SqlCall call) {
2147  final SqlMatchRecognize matchRecognize = (SqlMatchRecognize) call;
2148  final SqlValidatorNamespace ns = validator.getNamespace(matchRecognize);
2149  final SqlValidatorScope scope = validator.getMatchRecognizeScope(matchRecognize);
2150 
2151  final Blackboard matchBb = createBlackboard(scope, null, false);
2152  final RelDataType rowType = ns.getRowType();
2153  // convert inner query, could be a table name or a derived table
2154  SqlNode expr = matchRecognize.getTableRef();
2155  convertFrom(matchBb, expr);
2156  final RelNode input = matchBb.root;
2157 
2158  // PARTITION BY
2159  final SqlNodeList partitionList = matchRecognize.getPartitionList();
2160  final ImmutableBitSet.Builder partitionKeys = ImmutableBitSet.builder();
2161  for (SqlNode partition : partitionList) {
2162  RexNode e = matchBb.convertExpression(partition);
2163  partitionKeys.set(((RexInputRef) e).getIndex());
2164  }
2165 
2166  // ORDER BY
2167  final SqlNodeList orderList = matchRecognize.getOrderList();
2168  final List<RelFieldCollation> orderKeys = new ArrayList<>();
2169  for (SqlNode order : orderList) {
2170  final RelFieldCollation.Direction direction;
2171  switch (order.getKind()) {
2172  case DESCENDING:
2173  direction = RelFieldCollation.Direction.DESCENDING;
2174  order = ((SqlCall) order).operand(0);
2175  break;
2176  case NULLS_FIRST:
2177  case NULLS_LAST:
2178  throw new AssertionError();
2179  default:
2180  direction = RelFieldCollation.Direction.ASCENDING;
2181  break;
2182  }
2183  final RelFieldCollation.NullDirection nullDirection =
2184  validator.config().defaultNullCollation().last(desc(direction))
2185  ? RelFieldCollation.NullDirection.LAST
2186  : RelFieldCollation.NullDirection.FIRST;
2187  RexNode e = matchBb.convertExpression(order);
2188  orderKeys.add(new RelFieldCollation(
2189  ((RexInputRef) e).getIndex(), direction, nullDirection));
2190  }
2191  final RelCollation orders = cluster.traitSet().canonize(RelCollations.of(orderKeys));
2192 
2193  // convert pattern
2194  final Set<String> patternVarsSet = new HashSet<>();
2195  SqlNode pattern = matchRecognize.getPattern();
2196  final SqlBasicVisitor<RexNode> patternVarVisitor = new SqlBasicVisitor<RexNode>() {
2197  @Override
2198  public RexNode visit(SqlCall call) {
2199  List<SqlNode> operands = call.getOperandList();
2200  List<RexNode> newOperands = new ArrayList<>();
2201  for (SqlNode node : operands) {
2202  newOperands.add(node.accept(this));
2203  }
2204  return rexBuilder.makeCall(
2205  validator.getUnknownType(), call.getOperator(), newOperands);
2206  }
2207 
2208  @Override
2209  public RexNode visit(SqlIdentifier id) {
2210  assert id.isSimple();
2211  patternVarsSet.add(id.getSimple());
2212  return rexBuilder.makeLiteral(id.getSimple());
2213  }
2214 
2215  @Override
2216  public RexNode visit(SqlLiteral literal) {
2217  if (literal instanceof SqlNumericLiteral) {
2218  return rexBuilder.makeExactLiteral(BigDecimal.valueOf(literal.intValue(true)));
2219  } else {
2220  return rexBuilder.makeLiteral(literal.booleanValue());
2221  }
2222  }
2223  };
2224  final RexNode patternNode = pattern.accept(patternVarVisitor);
2225 
2226  SqlLiteral interval = matchRecognize.getInterval();
2227  RexNode intervalNode = null;
2228  if (interval != null) {
2229  intervalNode = matchBb.convertLiteral(interval);
2230  }
2231 
2232  // convert subset
2233  final SqlNodeList subsets = matchRecognize.getSubsetList();
2234  final Map<String, TreeSet<String>> subsetMap = new HashMap<>();
2235  for (SqlNode node : subsets) {
2236  List<SqlNode> operands = ((SqlCall) node).getOperandList();
2237  SqlIdentifier left = (SqlIdentifier) operands.get(0);
2238  patternVarsSet.add(left.getSimple());
2239  SqlNodeList rights = (SqlNodeList) operands.get(1);
2240  final TreeSet<String> list = new TreeSet<>();
2241  for (SqlNode right : rights) {
2242  assert right instanceof SqlIdentifier;
2243  list.add(((SqlIdentifier) right).getSimple());
2244  }
2245  subsetMap.put(left.getSimple(), list);
2246  }
2247 
2248  SqlNode afterMatch = matchRecognize.getAfter();
2249  if (afterMatch == null) {
2250  afterMatch =
2251  SqlMatchRecognize.AfterOption.SKIP_TO_NEXT_ROW.symbol(SqlParserPos.ZERO);
2252  }
2253 
2254  final RexNode after;
2255  if (afterMatch instanceof SqlCall) {
2256  List<SqlNode> operands = ((SqlCall) afterMatch).getOperandList();
2257  SqlOperator operator = ((SqlCall) afterMatch).getOperator();
2258  assert operands.size() == 1;
2259  SqlIdentifier id = (SqlIdentifier) operands.get(0);
2260  assert patternVarsSet.contains(id.getSimple())
2261  : id.getSimple()
2262  + " not defined in pattern";
2263  RexNode rex = rexBuilder.makeLiteral(id.getSimple());
2264  after = rexBuilder.makeCall(
2265  validator.getUnknownType(), operator, ImmutableList.of(rex));
2266  } else {
2267  after = matchBb.convertExpression(afterMatch);
2268  }
2269 
2270  matchBb.setPatternVarRef(true);
2271 
2272  // convert measures
2273  final ImmutableMap.Builder<String, RexNode> measureNodes = ImmutableMap.builder();
2274  for (SqlNode measure : matchRecognize.getMeasureList()) {
2275  List<SqlNode> operands = ((SqlCall) measure).getOperandList();
2276  String alias = ((SqlIdentifier) operands.get(1)).getSimple();
2277  RexNode rex = matchBb.convertExpression(operands.get(0));
2278  measureNodes.put(alias, rex);
2279  }
2280 
2281  // convert definitions
2282  final ImmutableMap.Builder<String, RexNode> definitionNodes = ImmutableMap.builder();
2283  for (SqlNode def : matchRecognize.getPatternDefList()) {
2284  replaceSubQueries(matchBb, def, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
2285  List<SqlNode> operands = ((SqlCall) def).getOperandList();
2286  String alias = ((SqlIdentifier) operands.get(1)).getSimple();
2287  RexNode rex = matchBb.convertExpression(operands.get(0));
2288  definitionNodes.put(alias, rex);
2289  }
2290 
2291  final SqlLiteral rowsPerMatch = matchRecognize.getRowsPerMatch();
2292  final boolean allRows = rowsPerMatch != null
2293  && rowsPerMatch.getValue() == SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS;
2294 
2295  matchBb.setPatternVarRef(false);
2296 
2297  final RelFactories.MatchFactory factory = RelFactories.DEFAULT_MATCH_FACTORY;
2298  final RelNode rel = factory.createMatch(input,
2299  patternNode,
2300  rowType,
2301  matchRecognize.getStrictStart().booleanValue(),
2302  matchRecognize.getStrictEnd().booleanValue(),
2303  definitionNodes.build(),
2304  measureNodes.build(),
2305  after,
2306  subsetMap,
2307  allRows,
2308  partitionKeys.build(),
2309  orders,
2310  intervalNode);
2311  bb.setRoot(rel, false);
2312  }
2313 
2315  SqlIdentifier id,
2316  SqlNodeList extendedColumns,
2317  SqlNodeList tableHints) {
2318  final SqlValidatorNamespace fromNamespace = validator.getNamespace(id).resolve();
2319  if (fromNamespace.getNode() != null) {
2320  convertFrom(bb, fromNamespace.getNode());
2321  return;
2322  }
2323  final String datasetName = datasetStack.isEmpty() ? null : datasetStack.peek();
2324  final boolean[] usedDataset = {false};
2325  RelOptTable table = SqlValidatorUtil.getRelOptTable(
2326  fromNamespace, catalogReader, datasetName, usedDataset);
2327  if (extendedColumns != null && extendedColumns.size() > 0) {
2328  assert table != null;
2329  final SqlValidatorTable validatorTable = table.unwrap(SqlValidatorTable.class);
2330  final List<RelDataTypeField> extendedFields = SqlValidatorUtil.getExtendedColumns(
2331  validator, validatorTable, extendedColumns);
2332  table = table.extend(extendedFields);
2333  }
2334  final RelNode tableRel;
2335  // Review Danny 2020-01-13: hacky to construct a new table scan
2336  // in order to apply the hint strategies.
2337  final List<RelHint> hints =
2338  hintStrategies.apply(SqlUtil.getRelHint(hintStrategies, tableHints),
2339  LogicalTableScan.create(cluster, table, ImmutableList.of()));
2340  tableRel = toRel(table, hints);
2341  bb.setRoot(tableRel, true);
2342  if (usedDataset[0]) {
2343  bb.setDataset(datasetName);
2344  }
2345  }
2346 
2347  protected void convertCollectionTable(Blackboard bb, SqlCall call) {
2348  final SqlOperator operator = call.getOperator();
2349  if (operator == SqlStdOperatorTable.TABLESAMPLE) {
2350  final String sampleName =
2351  SqlLiteral.unchain(call.operand(0)).getValueAs(String.class);
2352  datasetStack.push(sampleName);
2353  SqlCall cursorCall = call.operand(1);
2354  SqlNode query = cursorCall.operand(0);
2355  RelNode converted = convertQuery(query, false, false).rel;
2356  bb.setRoot(converted, false);
2357  datasetStack.pop();
2358  return;
2359  }
2360  replaceSubQueries(bb, call, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2361 
2362  // Expand table macro if possible. It's more efficient than
2363  // LogicalTableFunctionScan.
2364  final SqlCallBinding callBinding =
2365  new SqlCallBinding(bb.scope.getValidator(), bb.scope, call);
2366  if (operator instanceof SqlUserDefinedTableMacro) {
2367  final SqlUserDefinedTableMacro udf = (SqlUserDefinedTableMacro) operator;
2368  final TranslatableTable table = udf.getTable(callBinding);
2369  final RelDataType rowType = table.getRowType(typeFactory);
2370  RelOptTable relOptTable =
2371  RelOptTableImpl.create(null, rowType, table, udf.getNameAsId().names);
2372  RelNode converted = toRel(relOptTable, ImmutableList.of());
2373  bb.setRoot(converted, true);
2374  return;
2375  }
2376 
2377  Type elementType;
2378  if (operator instanceof SqlUserDefinedTableFunction) {
2379  SqlUserDefinedTableFunction udtf = (SqlUserDefinedTableFunction) operator;
2380  elementType = udtf.getElementType(callBinding);
2381  } else {
2382  elementType = null;
2383  }
2384 
2385  RexNode rexCall = bb.convertExpression(call);
2386  final List<RelNode> inputs = bb.retrieveCursors();
2387  Set<RelColumnMapping> columnMappings = getColumnMappings(operator);
2388  LogicalTableFunctionScan callRel = LogicalTableFunctionScan.create(cluster,
2389  inputs,
2390  rexCall,
2391  elementType,
2392  validator.getValidatedNodeType(call),
2393  columnMappings);
2394  bb.setRoot(callRel, true);
2395  afterTableFunction(bb, call, callRel);
2396  }
2397 
2398  protected void afterTableFunction(SqlToRelConverter.Blackboard bb,
2399  SqlCall call,
2400  LogicalTableFunctionScan callRel) {}
2401 
2402  private void convertTemporalTable(Blackboard bb, SqlCall call) {
2403  final SqlSnapshot snapshot = (SqlSnapshot) call;
2404  final RexNode period = bb.convertExpression(snapshot.getPeriod());
2405 
2406  // convert inner query, could be a table name or a derived table
2407  SqlNode expr = snapshot.getTableRef();
2408  convertFrom(bb, expr);
2409 
2410  final RelNode snapshotRel = relBuilder.push(bb.root).snapshot(period).build();
2411 
2412  bb.setRoot(snapshotRel, false);
2413  }
2414 
2415  private Set<RelColumnMapping> getColumnMappings(SqlOperator op) {
2416  SqlReturnTypeInference rti = op.getReturnTypeInference();
2417  if (rti == null) {
2418  return null;
2419  }
2420  if (rti instanceof TableFunctionReturnTypeInference) {
2421  TableFunctionReturnTypeInference tfrti = (TableFunctionReturnTypeInference) rti;
2422  return tfrti.getColumnMappings();
2423  } else {
2424  return null;
2425  }
2426  }
2427 
2433  private static class RexAccessShuttle extends RexShuttle {
2434  private final RexBuilder builder;
2435  private final RexCorrelVariable rexCorrel;
2436  private final BitSet varCols = new BitSet();
2437 
2438  RexAccessShuttle(RexBuilder builder, RexCorrelVariable rexCorrel) {
2439  this.builder = builder;
2440  this.rexCorrel = rexCorrel;
2441  }
2442 
2443  @Override
2444  public RexNode visitInputRef(RexInputRef input) {
2445  int i = input.getIndex() - rexCorrel.getType().getFieldCount();
2446  if (i < 0) {
2447  varCols.set(input.getIndex());
2448  return builder.makeFieldAccess(rexCorrel, input.getIndex());
2449  }
2450  return builder.makeInputRef(input.getType(), i);
2451  }
2452  }
2453 
2454  protected RelNode createJoin(Blackboard bb,
2455  RelNode leftRel,
2456  RelNode rightRel,
2457  RexNode joinCond,
2458  JoinRelType joinType) {
2459  assert joinCond != null;
2460 
2461  final CorrelationUse p = getCorrelationUse(bb, rightRel);
2462  if (p != null) {
2463  RelNode innerRel = p.r;
2464  ImmutableBitSet requiredCols = p.requiredColumns;
2465 
2466  if (!joinCond.isAlwaysTrue()) {
2467  final RelFactories.FilterFactory factory = RelFactories.DEFAULT_FILTER_FACTORY;
2468  final RexCorrelVariable rexCorrel =
2469  (RexCorrelVariable) rexBuilder.makeCorrel(leftRel.getRowType(), p.id);
2470  final RexAccessShuttle shuttle = new RexAccessShuttle(rexBuilder, rexCorrel);
2471 
2472  // Replace outer RexInputRef with RexFieldAccess,
2473  // and push lateral join predicate into inner child
2474  final RexNode newCond = joinCond.accept(shuttle);
2475  innerRel = factory.createFilter(p.r, newCond, ImmutableSet.of());
2476  requiredCols =
2477  ImmutableBitSet.fromBitSet(shuttle.varCols).union(p.requiredColumns);
2478  }
2479 
2480  return LogicalCorrelate.create(leftRel, innerRel, p.id, requiredCols, joinType);
2481  }
2482 
2483  // MAt 8 Jan 2021 original code
2484  // final RelNode node = relBuilder.push(leftRel).push(rightRel).join(joinType,
2485  // joinCond).build();
2486 
2487  // MAT 8 Jan 2021 this is Omnisci code
2488  final Join originalJoin = (Join) RelFactories.DEFAULT_JOIN_FACTORY.createJoin(leftRel,
2489  rightRel,
2490  ImmutableList.of(),
2491  joinCond,
2492  ImmutableSet.of(),
2493  joinType,
2494  false);
2495  boolean applyPushdown =
2496  config.getPushdownJoinCondition().test(bb.getTopNode(), originalJoin);
2497  RelNode node;
2498  if (applyPushdown) {
2499  node = node =
2500  relBuilder.push(leftRel).push(rightRel).join(joinType, joinCond).build();
2501  } else {
2502  node = originalJoin;
2503  }
2504  // MAT 08 Jan 2021 end of OmniSci Code
2505 
2506  // If join conditions are pushed down, update the leaves.
2507  if (node instanceof Project) {
2508  final Join newJoin = (Join) node.getInputs().get(0);
2509  if (leaves.containsKey(leftRel)) {
2510  leaves.put(newJoin.getLeft(), leaves.get(leftRel));
2511  }
2512  if (leaves.containsKey(rightRel)) {
2513  leaves.put(newJoin.getRight(), leaves.get(rightRel));
2514  }
2515  }
2516  return node;
2517  }
2518 
2519  private CorrelationUse getCorrelationUse(Blackboard bb, final RelNode r0) {
2520  final Set<CorrelationId> correlatedVariables = RelOptUtil.getVariablesUsed(r0);
2521  if (correlatedVariables.isEmpty()) {
2522  return null;
2523  }
2524  final ImmutableBitSet.Builder requiredColumns = ImmutableBitSet.builder();
2525  final List<CorrelationId> correlNames = new ArrayList<>();
2526 
2527  // All correlations must refer the same namespace since correlation
2528  // produces exactly one correlation source.
2529  // The same source might be referenced by different variables since
2530  // DeferredLookups are not de-duplicated at create time.
2531  SqlValidatorNamespace prevNs = null;
2532 
2533  for (CorrelationId correlName : correlatedVariables) {
2534  DeferredLookup lookup = mapCorrelToDeferred.get(correlName);
2535  RexFieldAccess fieldAccess = lookup.getFieldAccess(correlName);
2536  String originalRelName = lookup.getOriginalRelName();
2537  String originalFieldName = fieldAccess.getField().getName();
2538 
2539  final SqlNameMatcher nameMatcher =
2540  bb.getValidator().getCatalogReader().nameMatcher();
2541  final SqlValidatorScope.ResolvedImpl resolved =
2542  new SqlValidatorScope.ResolvedImpl();
2543  lookup.bb.scope.resolve(
2544  ImmutableList.of(originalRelName), nameMatcher, false, resolved);
2545  assert resolved.count() == 1;
2546  final SqlValidatorScope.Resolve resolve = resolved.only();
2547  final SqlValidatorNamespace foundNs = resolve.namespace;
2548  final RelDataType rowType = resolve.rowType();
2549  final int childNamespaceIndex = resolve.path.steps().get(0).i;
2550  final SqlValidatorScope ancestorScope = resolve.scope;
2551  boolean correlInCurrentScope = bb.scope.isWithin(ancestorScope);
2552 
2553  if (!correlInCurrentScope) {
2554  continue;
2555  }
2556 
2557  if (prevNs == null) {
2558  prevNs = foundNs;
2559  } else {
2560  assert prevNs
2561  == foundNs : "All correlation variables should resolve"
2562  + " to the same namespace."
2563  + " Prev ns="
2564  + prevNs
2565  + ", new ns="
2566  + foundNs;
2567  }
2568 
2569  int namespaceOffset = 0;
2570  if (childNamespaceIndex > 0) {
2571  // If not the first child, need to figure out the width
2572  // of output types from all the preceding namespaces
2573  assert ancestorScope instanceof ListScope;
2574  List<SqlValidatorNamespace> children = ((ListScope) ancestorScope).getChildren();
2575 
2576  for (int i = 0; i < childNamespaceIndex; i++) {
2577  SqlValidatorNamespace child = children.get(i);
2578  namespaceOffset += child.getRowType().getFieldCount();
2579  }
2580  }
2581 
2582  RexFieldAccess topLevelFieldAccess = fieldAccess;
2583  while (topLevelFieldAccess.getReferenceExpr() instanceof RexFieldAccess) {
2584  topLevelFieldAccess = (RexFieldAccess) topLevelFieldAccess.getReferenceExpr();
2585  }
2586  final RelDataTypeField field = rowType.getFieldList().get(
2587  topLevelFieldAccess.getField().getIndex() - namespaceOffset);
2588  int pos = namespaceOffset + field.getIndex();
2589 
2590  assert field.getType() == topLevelFieldAccess.getField().getType();
2591 
2592  assert pos != -1;
2593 
2594  if (bb.mapRootRelToFieldProjection.containsKey(bb.root)) {
2595  // bb.root is an aggregate and only projects group by
2596  // keys.
2597  Map<Integer, Integer> exprProjection =
2598  bb.mapRootRelToFieldProjection.get(bb.root);
2599 
2600  // sub-query can reference group by keys projected from
2601  // the root of the outer relation.
2602  if (exprProjection.containsKey(pos)) {
2603  pos = exprProjection.get(pos);
2604  } else {
2605  // correl not grouped
2606  throw new AssertionError("Identifier '" + originalRelName + "."
2607  + originalFieldName + "' is not a group expr");
2608  }
2609  }
2610 
2611  requiredColumns.set(pos);
2612  correlNames.add(correlName);
2613  }
2614 
2615  if (correlNames.isEmpty()) {
2616  // None of the correlating variables originated in this scope.
2617  return null;
2618  }
2619 
2620  RelNode r = r0;
2621  if (correlNames.size() > 1) {
2622  // The same table was referenced more than once.
2623  // So we deduplicate.
2624  r = DeduplicateCorrelateVariables.go(
2625  rexBuilder, correlNames.get(0), Util.skip(correlNames), r0);
2626  // Add new node to leaves.
2627  leaves.put(r, r.getRowType().getFieldCount());
2628  }
2629  return new CorrelationUse(correlNames.get(0), requiredColumns.build(), r);
2630  }
2631 
2642  private boolean isSubQueryNonCorrelated(RelNode subq, Blackboard bb) {
2643  Set<CorrelationId> correlatedVariables = RelOptUtil.getVariablesUsed(subq);
2644  for (CorrelationId correlName : correlatedVariables) {
2645  DeferredLookup lookup = mapCorrelToDeferred.get(correlName);
2646  String originalRelName = lookup.getOriginalRelName();
2647 
2648  final SqlNameMatcher nameMatcher =
2649  lookup.bb.scope.getValidator().getCatalogReader().nameMatcher();
2650  final SqlValidatorScope.ResolvedImpl resolved =
2651  new SqlValidatorScope.ResolvedImpl();
2652  lookup.bb.scope.resolve(
2653  ImmutableList.of(originalRelName), nameMatcher, false, resolved);
2654 
2655  SqlValidatorScope ancestorScope = resolved.only().scope;
2656 
2657  // If the correlated reference is in a scope that's "above" the
2658  // sub-query, then this is a correlated sub-query.
2659  SqlValidatorScope parentScope = bb.scope;
2660  do {
2661  if (ancestorScope == parentScope) {
2662  return false;
2663  }
2664  if (parentScope instanceof DelegatingScope) {
2665  parentScope = ((DelegatingScope) parentScope).getParent();
2666  } else {
2667  break;
2668  }
2669  } while (parentScope != null);
2670  }
2671  return true;
2672  }
2673 
2679  protected List<RelDataTypeField> getSystemFields() {
2680  return Collections.emptyList();
2681  }
2682 
2683  private RexNode convertJoinCondition(Blackboard bb,
2684  SqlValidatorNamespace leftNamespace,
2685  SqlValidatorNamespace rightNamespace,
2686  SqlNode condition,
2687  JoinConditionType conditionType,
2688  RelNode leftRel,
2689  RelNode rightRel) {
2690  if (condition == null) {
2691  return rexBuilder.makeLiteral(true);
2692  }
2693  bb.setRoot(ImmutableList.of(leftRel, rightRel));
2694  replaceSubQueries(bb, condition, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
2695  switch (conditionType) {
2696  case ON:
2697  bb.setRoot(ImmutableList.of(leftRel, rightRel));
2698  return bb.convertExpression(condition);
2699  case USING:
2700  final SqlNodeList list = (SqlNodeList) condition;
2701  final List<String> nameList = new ArrayList<>();
2702  for (SqlNode columnName : list) {
2703  final SqlIdentifier id = (SqlIdentifier) columnName;
2704  String name = id.getSimple();
2705  nameList.add(name);
2706  }
2707  return convertUsing(leftNamespace, rightNamespace, nameList);
2708  default:
2709  throw Util.unexpected(conditionType);
2710  }
2711  }
2712 
2724  private RexNode convertUsing(SqlValidatorNamespace leftNamespace,
2725  SqlValidatorNamespace rightNamespace,
2726  List<String> nameList) {
2727  final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
2728  final List<RexNode> list = new ArrayList<>();
2729  for (String name : nameList) {
2730  List<RexNode> operands = new ArrayList<>();
2731  int offset = 0;
2732  for (SqlValidatorNamespace n : ImmutableList.of(leftNamespace, rightNamespace)) {
2733  final RelDataType rowType = n.getRowType();
2734  final RelDataTypeField field = nameMatcher.field(rowType, name);
2735  operands.add(rexBuilder.makeInputRef(field.getType(), offset + field.getIndex()));
2736  offset += rowType.getFieldList().size();
2737  }
2738  list.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, operands));
2739  }
2740  return RexUtil.composeConjunction(rexBuilder, list);
2741  }
2742 
2743  private static JoinRelType convertJoinType(JoinType joinType) {
2744  switch (joinType) {
2745  case COMMA:
2746  case INNER:
2747  case CROSS:
2748  return JoinRelType.INNER;
2749  case FULL:
2750  return JoinRelType.FULL;
2751  case LEFT:
2752  return JoinRelType.LEFT;
2753  case RIGHT:
2754  return JoinRelType.RIGHT;
2755  default:
2756  throw Util.unexpected(joinType);
2757  }
2758  }
2759 
2773  protected void convertAgg(
2774  Blackboard bb, SqlSelect select, List<SqlNode> orderExprList) {
2775  assert bb.root != null : "precondition: child != null";
2776  SqlNodeList groupList = select.getGroup();
2777  SqlNodeList selectList = select.getSelectList();
2778  SqlNode having = select.getHaving();
2779 
2780  final AggConverter aggConverter = new AggConverter(bb, select);
2781  createAggImpl(bb, aggConverter, selectList, groupList, having, orderExprList);
2782  }
2783 
2784  protected final void createAggImpl(Blackboard bb,
2785  final AggConverter aggConverter,
2786  SqlNodeList selectList,
2787  SqlNodeList groupList,
2788  SqlNode having,
2789  List<SqlNode> orderExprList) {
2790  // Find aggregate functions in SELECT and HAVING clause
2791  final AggregateFinder aggregateFinder = new AggregateFinder();
2792  selectList.accept(aggregateFinder);
2793  if (having != null) {
2794  having.accept(aggregateFinder);
2795  }
2796 
2797  // first replace the sub-queries inside the aggregates
2798  // because they will provide input rows to the aggregates.
2799  replaceSubQueries(bb, aggregateFinder.list, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2800 
2801  // also replace sub-queries inside filters in the aggregates
2803  bb, aggregateFinder.filterList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2804 
2805  // also replace sub-queries inside ordering spec in the aggregates
2806  replaceSubQueries(bb, aggregateFinder.orderList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2807 
2808  // If group-by clause is missing, pretend that it has zero elements.
2809  if (groupList == null) {
2810  groupList = SqlNodeList.EMPTY;
2811  }
2812 
2813  replaceSubQueries(bb, groupList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2814 
2815  // register the group exprs
2816 
2817  // build a map to remember the projections from the top scope to the
2818  // output of the current root.
2819  //
2820  // Calcite allows expressions, not just column references in
2821  // group by list. This is not SQL 2003 compliant, but hey.
2822 
2823  final AggregatingSelectScope scope = aggConverter.aggregatingSelectScope;
2824  final AggregatingSelectScope.Resolved r = scope.resolved.get();
2825  for (SqlNode groupExpr : r.groupExprList) {
2826  aggConverter.addGroupExpr(groupExpr);
2827  }
2828 
2829  final RexNode havingExpr;
2830  final List<Pair<RexNode, String>> projects = new ArrayList<>();
2831 
2832  try {
2833  Preconditions.checkArgument(bb.agg == null, "already in agg mode");
2834  bb.agg = aggConverter;
2835 
2836  // convert the select and having expressions, so that the
2837  // agg converter knows which aggregations are required
2838 
2839  selectList.accept(aggConverter);
2840  // Assert we don't have dangling items left in the stack
2841  assert !aggConverter.inOver;
2842  for (SqlNode expr : orderExprList) {
2843  expr.accept(aggConverter);
2844  assert !aggConverter.inOver;
2845  }
2846  if (having != null) {
2847  having.accept(aggConverter);
2848  assert !aggConverter.inOver;
2849  }
2850 
2851  // compute inputs to the aggregator
2852  List<Pair<RexNode, String>> preExprs = aggConverter.getPreExprs();
2853 
2854  if (preExprs.size() == 0) {
2855  // Special case for COUNT(*), where we can end up with no inputs
2856  // at all. The rest of the system doesn't like 0-tuples, so we
2857  // select a dummy constant here.
2858  final RexNode zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO);
2859  preExprs = ImmutableList.of(Pair.of(zero, (String) null));
2860  }
2861 
2862  final RelNode inputRel = bb.root;
2863 
2864  // Project the expressions required by agg and having.
2865  bb.setRoot(relBuilder.push(inputRel)
2866  .projectNamed(Pair.left(preExprs), Pair.right(preExprs), false)
2867  .build(),
2868  false);
2869  bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
2870 
2871  // REVIEW jvs 31-Oct-2007: doesn't the declaration of
2872  // monotonicity here assume sort-based aggregation at
2873  // the physical level?
2874 
2875  // Tell bb which of group columns are sorted.
2876  bb.columnMonotonicities.clear();
2877  for (SqlNode groupItem : groupList) {
2878  bb.columnMonotonicities.add(bb.scope.getMonotonicity(groupItem));
2879  }
2880 
2881  final RelNode relNode = aggConverter.containsGroupId()
2882  ? rewriteAggregateWithGroupId(bb, r, aggConverter)
2883  : createAggregate(bb, r.groupSet, r.groupSets, aggConverter.getAggCalls());
2884 
2885  bb.setRoot(relNode, false);
2886  bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
2887 
2888  // Replace sub-queries in having here and modify having to use
2889  // the replaced expressions
2890  if (having != null) {
2891  SqlNode newHaving = pushDownNotForIn(bb.scope, having);
2892  replaceSubQueries(bb, newHaving, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
2893  havingExpr = bb.convertExpression(newHaving);
2894  } else {
2895  havingExpr = relBuilder.literal(true);
2896  }
2897 
2898  // Now convert the other sub-queries in the select list.
2899  // This needs to be done separately from the sub-query inside
2900  // any aggregate in the select list, and after the aggregate rel
2901  // is allocated.
2902  replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2903 
2904  // Now sub-queries in the entire select list have been converted.
2905  // Convert the select expressions to get the final list to be
2906  // projected.
2907  int k = 0;
2908 
2909  // For select expressions, use the field names previously assigned
2910  // by the validator. If we derive afresh, we might generate names
2911  // like "EXPR$2" that don't match the names generated by the
2912  // validator. This is especially the case when there are system
2913  // fields; system fields appear in the relnode's rowtype but do not
2914  // (yet) appear in the validator type.
2915  final SelectScope selectScope = SqlValidatorUtil.getEnclosingSelectScope(bb.scope);
2916  assert selectScope != null;
2917  final SqlValidatorNamespace selectNamespace =
2918  validator.getNamespace(selectScope.getNode());
2919  final List<String> names = selectNamespace.getRowType().getFieldNames();
2920  int sysFieldCount = selectList.size() - names.size();
2921  for (SqlNode expr : selectList) {
2922  projects.add(Pair.of(bb.convertExpression(expr),
2923  k < sysFieldCount ? validator.deriveAlias(expr, k++)
2924  : names.get(k++ - sysFieldCount)));
2925  }
2926 
2927  for (SqlNode expr : orderExprList) {
2928  projects.add(
2929  Pair.of(bb.convertExpression(expr), validator.deriveAlias(expr, k++)));
2930  }
2931  } finally {
2932  bb.agg = null;
2933  }
2934 
2935  // implement HAVING (we have already checked that it is non-trivial)
2936  relBuilder.push(bb.root);
2937  if (havingExpr != null) {
2938  relBuilder.filter(havingExpr);
2939  }
2940 
2941  // implement the SELECT list
2942  relBuilder.project(Pair.left(projects), Pair.right(projects))
2943  .rename(Pair.right(projects));
2944  bb.setRoot(relBuilder.build(), false);
2945 
2946  // Tell bb which of group columns are sorted.
2947  bb.columnMonotonicities.clear();
2948  for (SqlNode selectItem : selectList) {
2949  bb.columnMonotonicities.add(bb.scope.getMonotonicity(selectItem));
2950  }
2951  }
2952 
2967  Blackboard bb, AggregatingSelectScope.Resolved r, AggConverter converter) {
2968  final List<AggregateCall> aggregateCalls = converter.getAggCalls();
2969  final ImmutableBitSet groupSet = r.groupSet;
2970  final Map<ImmutableBitSet, Integer> groupSetCount = r.groupSetCount;
2971 
2972  final List<String> fieldNamesIfNoRewrite =
2973  createAggregate(bb, groupSet, r.groupSets, aggregateCalls)
2974  .getRowType()
2975  .getFieldNames();
2976 
2977  // If n duplicates exist for a particular grouping, the {@code GROUP_ID()}
2978  // function produces values in the range 0 to n-1. For each value,
2979  // we need to figure out the corresponding group sets.
2980  //
2981  // For example, "... GROUPING SETS (a, a, b, c, c, c, c)"
2982  // (i) The max value of the GROUP_ID() function returns is 3
2983  // (ii) GROUPING SETS (a, b, c) produces value 0,
2984  // GROUPING SETS (a, c) produces value 1,
2985  // GROUPING SETS (c) produces value 2
2986  // GROUPING SETS (c) produces value 3
2987  final Map<Integer, Set<ImmutableBitSet>> groupIdToGroupSets = new HashMap<>();
2988  int maxGroupId = 0;
2989  for (Map.Entry<ImmutableBitSet, Integer> entry : groupSetCount.entrySet()) {
2990  int groupId = entry.getValue() - 1;
2991  if (groupId > maxGroupId) {
2992  maxGroupId = groupId;
2993  }
2994  for (int i = 0; i <= groupId; i++) {
2995  groupIdToGroupSets
2996  .computeIfAbsent(i, k -> Sets.newTreeSet(ImmutableBitSet.COMPARATOR))
2997  .add(entry.getKey());
2998  }
2999  }
3000 
3001  // AggregateCall list without GROUP_ID function
3002  final List<AggregateCall> aggregateCallsWithoutGroupId = new ArrayList<>();
3003  for (AggregateCall aggregateCall : aggregateCalls) {
3004  if (aggregateCall.getAggregation().kind != SqlKind.GROUP_ID) {
3005  aggregateCallsWithoutGroupId.add(aggregateCall);
3006  }
3007  }
3008  final List<RelNode> projects = new ArrayList<>();
3009  // For each group id value , we first construct an Aggregate without
3010  // GROUP_ID() function call, and then create a Project node on top of it.
3011  // The Project adds literal value for group id in right position.
3012  for (int groupId = 0; groupId <= maxGroupId; groupId++) {
3013  // Create the Aggregate node without GROUP_ID() call
3014  final ImmutableList<ImmutableBitSet> groupSets =
3015  ImmutableList.copyOf(groupIdToGroupSets.get(groupId));
3016  final RelNode aggregate =
3017  createAggregate(bb, groupSet, groupSets, aggregateCallsWithoutGroupId);
3018 
3019  // RexLiteral for each GROUP_ID, note the type should be BIGINT
3020  final RelDataType groupIdType = typeFactory.createSqlType(SqlTypeName.BIGINT);
3021  final RexNode groupIdLiteral =
3022  rexBuilder.makeExactLiteral(BigDecimal.valueOf(groupId), groupIdType);
3023 
3024  relBuilder.push(aggregate);
3025  final List<RexNode> selectList = new ArrayList<>();
3026  final int groupExprLength = r.groupExprList.size();
3027  // Project fields in group by expressions
3028  for (int i = 0; i < groupExprLength; i++) {
3029  selectList.add(relBuilder.field(i));
3030  }
3031  // Project fields in aggregate calls
3032  int groupIdCount = 0;
3033  for (int i = 0; i < aggregateCalls.size(); i++) {
3034  if (aggregateCalls.get(i).getAggregation().kind == SqlKind.GROUP_ID) {
3035  selectList.add(groupIdLiteral);
3036  groupIdCount++;
3037  } else {
3038  int ordinal = groupExprLength + i - groupIdCount;
3039  selectList.add(relBuilder.field(ordinal));
3040  }
3041  }
3042  final RelNode project =
3043  relBuilder.project(selectList, fieldNamesIfNoRewrite).build();
3044  projects.add(project);
3045  }
3046  // Skip to create Union when there is only one child, i.e., no duplicate group
3047  // set.
3048  if (projects.size() == 1) {
3049  return projects.get(0);
3050  }
3051  return LogicalUnion.create(projects, true);
3052  }
3053 
3073  protected RelNode createAggregate(Blackboard bb,
3074  ImmutableBitSet groupSet,
3075  ImmutableList<ImmutableBitSet> groupSets,
3076  List<AggregateCall> aggCalls) {
3077  return LogicalAggregate.create(
3078  bb.root, ImmutableList.of(), groupSet, groupSets, aggCalls);
3079  }
3080 
3081  public RexDynamicParam convertDynamicParam(final SqlDynamicParam dynamicParam) {
3082  // REVIEW jvs 8-Jan-2005: dynamic params may be encountered out of
3083  // order. Should probably cross-check with the count from the parser
3084  // at the end and make sure they all got filled in. Why doesn't List
3085  // have a resize() method?!? Make this a utility.
3086  while (dynamicParam.getIndex() >= dynamicParamSqlNodes.size()) {
3087  dynamicParamSqlNodes.add(null);
3088  }
3089 
3090  dynamicParamSqlNodes.set(dynamicParam.getIndex(), dynamicParam);
3091  return rexBuilder.makeDynamicParam(
3092  getDynamicParamType(dynamicParam.getIndex()), dynamicParam.getIndex());
3093  }
3094 
3109  protected void gatherOrderExprs(Blackboard bb,
3110  SqlSelect select,
3111  SqlNodeList orderList,
3112  List<SqlNode> extraOrderExprs,
3113  List<RelFieldCollation> collationList) {
3114  // TODO: add validation rules to SqlValidator also
3115  assert bb.root != null : "precondition: child != null";
3116  assert select != null;
3117  if (orderList == null) {
3118  return;
3119  }
3120 
3121  if (!bb.top) {
3122  SqlNode offset = select.getOffset();
3123  if ((offset == null
3124  || (offset instanceof SqlLiteral
3125  && ((SqlLiteral) offset)
3126  .bigDecimalValue()
3127  .equals(BigDecimal.ZERO)))
3128  && select.getFetch() == null) {
3129  return;
3130  }
3131  }
3132 
3133  for (SqlNode orderItem : orderList) {
3134  collationList.add(convertOrderItem(select,
3135  orderItem,
3136  extraOrderExprs,
3137  RelFieldCollation.Direction.ASCENDING,
3138  RelFieldCollation.NullDirection.UNSPECIFIED));
3139  }
3140  }
3141 
3142  protected RelFieldCollation convertOrderItem(SqlSelect select,
3143  SqlNode orderItem,
3144  List<SqlNode> extraExprs,
3145  RelFieldCollation.Direction direction,
3146  RelFieldCollation.NullDirection nullDirection) {
3147  assert select != null;
3148  // Handle DESC keyword, e.g. 'select a, b from t order by a desc'.
3149  switch (orderItem.getKind()) {
3150  case DESCENDING:
3151  return convertOrderItem(select,
3152  ((SqlCall) orderItem).operand(0),
3153  extraExprs,
3154  RelFieldCollation.Direction.DESCENDING,
3155  nullDirection);
3156  case NULLS_FIRST:
3157  return convertOrderItem(select,
3158  ((SqlCall) orderItem).operand(0),
3159  extraExprs,
3160  direction,
3161  RelFieldCollation.NullDirection.FIRST);
3162  case NULLS_LAST:
3163  return convertOrderItem(select,
3164  ((SqlCall) orderItem).operand(0),
3165  extraExprs,
3166  direction,
3167  RelFieldCollation.NullDirection.LAST);
3168  }
3169 
3170  SqlNode converted = validator.expandOrderExpr(select, orderItem);
3171 
3172  switch (nullDirection) {
3173  case UNSPECIFIED:
3174  nullDirection = validator.config().defaultNullCollation().last(desc(direction))
3175  ? RelFieldCollation.NullDirection.LAST
3176  : RelFieldCollation.NullDirection.FIRST;
3177  }
3178 
3179  // Scan the select list and order exprs for an identical expression.
3180  final SelectScope selectScope = validator.getRawSelectScope(select);
3181  int ordinal = -1;
3182  for (SqlNode selectItem : selectScope.getExpandedSelectList()) {
3183  ++ordinal;
3184  if (converted.equalsDeep(stripAs(selectItem), Litmus.IGNORE)) {
3185  return new RelFieldCollation(ordinal, direction, nullDirection);
3186  }
3187  }
3188 
3189  for (SqlNode extraExpr : extraExprs) {
3190  ++ordinal;
3191  if (converted.equalsDeep(extraExpr, Litmus.IGNORE)) {
3192  return new RelFieldCollation(ordinal, direction, nullDirection);
3193  }
3194  }
3195 
3196  // TODO: handle collation sequence
3197  // TODO: flag expressions as non-standard
3198 
3199  extraExprs.add(converted);
3200  return new RelFieldCollation(ordinal + 1, direction, nullDirection);
3201  }
3202 
3203  private static boolean desc(RelFieldCollation.Direction direction) {
3204  switch (direction) {
3205  case DESCENDING:
3206  case STRICTLY_DESCENDING:
3207  return true;
3208  default:
3209  return false;
3210  }
3211  }
3212 
3213  @Deprecated // to be removed before 2.0
3214  protected boolean enableDecorrelation() {
3215  // disable sub-query decorrelation when needed.
3216  // e.g. if outer joins are not supported.
3217  return config.isDecorrelationEnabled();
3218  }
3219 
3220  protected RelNode decorrelateQuery(RelNode rootRel) {
3221  return RelDecorrelator.decorrelateQuery(rootRel, relBuilder);
3222  }
3223 
3229  @Deprecated // to be removed before 2.0
3230  public boolean isTrimUnusedFields() {
3231  return config.isTrimUnusedFields();
3232  }
3233 
3243  protected RelRoot convertQueryRecursive(
3244  SqlNode query, boolean top, RelDataType targetRowType) {
3245  final SqlKind kind = query.getKind();
3246  switch (kind) {
3247  case SELECT:
3248  return RelRoot.of(convertSelect((SqlSelect) query, top), kind);
3249  case INSERT:
3250  return RelRoot.of(convertInsert((SqlInsert) query), kind);
3251  case DELETE:
3252  return RelRoot.of(convertDelete((SqlDelete) query), kind);
3253  case UPDATE:
3254  return RelRoot.of(convertUpdate((SqlUpdate) query), kind);
3255  case MERGE:
3256  return RelRoot.of(convertMerge((SqlMerge) query), kind);
3257  case UNION:
3258  case INTERSECT:
3259  case EXCEPT:
3260  return RelRoot.of(convertSetOp((SqlCall) query), kind);
3261  case WITH:
3262  return convertWith((SqlWith) query, top);
3263  case VALUES:
3264  return RelRoot.of(convertValues((SqlCall) query, targetRowType), kind);
3265  default:
3266  throw new AssertionError("not a query: " + query);
3267  }
3268  }
3269 
3277  protected RelNode convertSetOp(SqlCall call) {
3278  final RelNode left = convertQueryRecursive(call.operand(0), false, null).project();
3279  final RelNode right = convertQueryRecursive(call.operand(1), false, null).project();
3280  switch (call.getKind()) {
3281  case UNION:
3282  return LogicalUnion.create(ImmutableList.of(left, right), all(call));
3283 
3284  case INTERSECT:
3285  return LogicalIntersect.create(ImmutableList.of(left, right), all(call));
3286 
3287  case EXCEPT:
3288  return LogicalMinus.create(ImmutableList.of(left, right), all(call));
3289 
3290  default:
3291  throw Util.unexpected(call.getKind());
3292  }
3293  }
3294 
3295  private boolean all(SqlCall call) {
3296  return ((SqlSetOperator) call.getOperator()).isAll();
3297  }
3298 
3299  protected RelNode convertInsert(SqlInsert call) {
3300  RelOptTable targetTable = getTargetTable(call);
3301 
3302  final RelDataType targetRowType = validator.getValidatedNodeType(call);
3303  assert targetRowType != null;
3304  RelNode sourceRel =
3305  convertQueryRecursive(call.getSource(), true, targetRowType).project();
3306  RelNode massagedRel = convertColumnList(call, sourceRel);
3307 
3308  return createModify(targetTable, massagedRel);
3309  }
3310 
3312  private RelNode createModify(RelOptTable targetTable, RelNode source) {
3313  final ModifiableTable modifiableTable = targetTable.unwrap(ModifiableTable.class);
3314  if (modifiableTable != null && modifiableTable == targetTable.unwrap(Table.class)) {
3315  return modifiableTable.toModificationRel(cluster,
3316  targetTable,
3317  catalogReader,
3318  source,
3319  LogicalTableModify.Operation.INSERT,
3320  null,
3321  null,
3322  false);
3323  }
3324  final ModifiableView modifiableView = targetTable.unwrap(ModifiableView.class);
3325  if (modifiableView != null) {
3326  final Table delegateTable = modifiableView.getTable();
3327  final RelDataType delegateRowType = delegateTable.getRowType(typeFactory);
3328  final RelOptTable delegateRelOptTable = RelOptTableImpl.create(
3329  null, delegateRowType, delegateTable, modifiableView.getTablePath());
3330  final RelNode newSource =
3331  createSource(targetTable, source, modifiableView, delegateRowType);
3332  return createModify(delegateRelOptTable, newSource);
3333  }
3334  return LogicalTableModify.create(targetTable,
3335  catalogReader,
3336  source,
3337  LogicalTableModify.Operation.INSERT,
3338  null,
3339  null,
3340  false);
3341  }
3342 
3356  private RelNode createSource(RelOptTable targetTable,
3357  RelNode source,
3358  ModifiableView modifiableView,
3359  RelDataType delegateRowType) {
3360  final ImmutableIntList mapping = modifiableView.getColumnMapping();
3361  assert mapping.size() == targetTable.getRowType().getFieldCount();
3362 
3363  // For columns represented in the mapping, the expression is just a field
3364  // reference.
3365  final Map<Integer, RexNode> projectMap = new HashMap<>();
3366  final List<RexNode> filters = new ArrayList<>();
3367  for (int i = 0; i < mapping.size(); i++) {
3368  int target = mapping.get(i);
3369  if (target >= 0) {
3370  projectMap.put(target, RexInputRef.of(i, source.getRowType()));
3371  }
3372  }
3373 
3374  // For columns that are not in the mapping, and have a constraint of the
3375  // form "column = value", the expression is the literal "value".
3376  //
3377  // If a column has multiple constraints, the extra ones will become a
3378  // filter.
3379  final RexNode constraint = modifiableView.getConstraint(rexBuilder, delegateRowType);
3380  RelOptUtil.inferViewPredicates(projectMap, filters, constraint);
3381  final List<Pair<RexNode, String>> projects = new ArrayList<>();
3382  for (RelDataTypeField field : delegateRowType.getFieldList()) {
3383  RexNode node = projectMap.get(field.getIndex());
3384  if (node == null) {
3385  node = rexBuilder.makeNullLiteral(field.getType());
3386  }
3387  projects.add(Pair.of(
3388  rexBuilder.ensureType(field.getType(), node, false), field.getName()));
3389  }
3390 
3391  return relBuilder.push(source)
3392  .projectNamed(Pair.left(projects), Pair.right(projects), false)
3393  .filter(filters)
3394  .build();
3395  }
3396 
3397  private RelOptTable.ToRelContext createToRelContext(List<RelHint> hints) {
3398  return ViewExpanders.toRelContext(viewExpander, cluster, hints);
3399  }
3400 
3401  public RelNode toRel(final RelOptTable table, final List<RelHint> hints) {
3402  final RelNode scan = table.toRel(createToRelContext(hints));
3403 
3404  final InitializerExpressionFactory ief =
3405  Util.first(table.unwrap(InitializerExpressionFactory.class),
3406  NullInitializerExpressionFactory.INSTANCE);
3407 
3408  boolean hasVirtualFields = table.getRowType().getFieldList().stream().anyMatch(
3409  f -> ief.generationStrategy(table, f.getIndex()) == ColumnStrategy.VIRTUAL);
3410 
3411  if (hasVirtualFields) {
3412  final RexNode sourceRef = rexBuilder.makeRangeReference(scan);
3414  table, sourceRef, table.getRowType().getFieldNames());
3415  final List<RexNode> list = new ArrayList<>();
3416  for (RelDataTypeField f : table.getRowType().getFieldList()) {
3417  final ColumnStrategy strategy = ief.generationStrategy(table, f.getIndex());
3418  switch (strategy) {
3419  case VIRTUAL:
3420  list.add(ief.newColumnDefaultValue(table, f.getIndex(), bb));
3421  break;
3422  default:
3423  list.add(rexBuilder.makeInputRef(
3424  scan, RelOptTableImpl.realOrdinal(table, f.getIndex())));
3425  }
3426  }
3427  relBuilder.push(scan);
3428  relBuilder.project(list);
3429  final RelNode project = relBuilder.build();
3430  if (ief.postExpressionConversionHook() != null) {
3431  return ief.postExpressionConversionHook().apply(bb, project);
3432  } else {
3433  return project;
3434  }
3435  }
3436 
3437  return scan;
3438  }
3439 
3440  protected RelOptTable getTargetTable(SqlNode call) {
3441  final SqlValidatorNamespace targetNs = validator.getNamespace(call);
3442  if (targetNs.isWrapperFor(SqlValidatorImpl.DmlNamespace.class)) {
3443  final SqlValidatorImpl.DmlNamespace dmlNamespace =
3444  targetNs.unwrap(SqlValidatorImpl.DmlNamespace.class);
3445  return SqlValidatorUtil.getRelOptTable(dmlNamespace, catalogReader, null, null);
3446  }
3447  final SqlValidatorNamespace resolvedNamespace = targetNs.resolve();
3448  return SqlValidatorUtil.getRelOptTable(resolvedNamespace, catalogReader, null, null);
3449  }
3450 
3468  protected RelNode convertColumnList(final SqlInsert call, RelNode source) {
3469  RelDataType sourceRowType = source.getRowType();
3470  final RexNode sourceRef = rexBuilder.makeRangeReference(sourceRowType, 0, false);
3471  final List<String> targetColumnNames = new ArrayList<>();
3472  final List<RexNode> columnExprs = new ArrayList<>();
3473  collectInsertTargets(call, sourceRef, targetColumnNames, columnExprs);
3474 
3475  final RelOptTable targetTable = getTargetTable(call);
3476  final RelDataType targetRowType = RelOptTableImpl.realRowType(targetTable);
3477  final List<RelDataTypeField> targetFields = targetRowType.getFieldList();
3478  final List<RexNode> sourceExps =
3479  new ArrayList<>(Collections.nCopies(targetFields.size(), null));
3480  final List<String> fieldNames =
3481  new ArrayList<>(Collections.nCopies(targetFields.size(), null));
3482 
3483  final InitializerExpressionFactory initializerFactory =
3484  getInitializerFactory(validator.getNamespace(call).getTable());
3485 
3486  // Walk the name list and place the associated value in the
3487  // expression list according to the ordinal value returned from
3488  // the table construct, leaving nulls in the list for columns
3489  // that are not referenced.
3490  final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
3491  for (Pair<String, RexNode> p : Pair.zip(targetColumnNames, columnExprs)) {
3492  RelDataTypeField field = nameMatcher.field(targetRowType, p.left);
3493  assert field != null : "column " + p.left + " not found";
3494  sourceExps.set(field.getIndex(), p.right);
3495  }
3496 
3497  // Lazily create a blackboard that contains all non-generated columns.
3498  final Supplier<Blackboard> bb =
3499  () -> createInsertBlackboard(targetTable, sourceRef, targetColumnNames);
3500 
3501  // Walk the expression list and get default values for any columns
3502  // that were not supplied in the statement. Get field names too.
3503  for (int i = 0; i < targetFields.size(); ++i) {
3504  final RelDataTypeField field = targetFields.get(i);
3505  final String fieldName = field.getName();
3506  fieldNames.set(i, fieldName);
3507  if (sourceExps.get(i) == null || sourceExps.get(i).getKind() == SqlKind.DEFAULT) {
3508  sourceExps.set(
3509  i, initializerFactory.newColumnDefaultValue(targetTable, i, bb.get()));
3510 
3511  // bare nulls are dangerous in the wrong hands
3512  sourceExps.set(i, castNullLiteralIfNeeded(sourceExps.get(i), field.getType()));
3513  }
3514  }
3515 
3516  return relBuilder.push(source).projectNamed(sourceExps, fieldNames, false).build();
3517  }
3518 
3524  RelOptTable targetTable, RexNode sourceRef, List<String> targetColumnNames) {
3525  final Map<String, RexNode> nameToNodeMap = new HashMap<>();
3526  int j = 0;
3527 
3528  // Assign expressions for non-generated columns.
3529  final List<ColumnStrategy> strategies = targetTable.getColumnStrategies();
3530  final List<String> targetFields = targetTable.getRowType().getFieldNames();
3531  for (String targetColumnName : targetColumnNames) {
3532  final int i = targetFields.indexOf(targetColumnName);
3533  switch (strategies.get(i)) {
3534  case STORED:
3535  case VIRTUAL:
3536  break;
3537  default:
3538  nameToNodeMap.put(targetColumnName, rexBuilder.makeFieldAccess(sourceRef, j++));
3539  }
3540  }
3541  return createBlackboard(null, nameToNodeMap, false);
3542  }
3543 
3544  private InitializerExpressionFactory getInitializerFactory(
3545  SqlValidatorTable validatorTable) {
3546  // We might unwrap a null instead of a InitializerExpressionFactory.
3547  final Table table = unwrap(validatorTable, Table.class);
3548  if (table != null) {
3549  InitializerExpressionFactory f = unwrap(table, InitializerExpressionFactory.class);
3550  if (f != null) {
3551  return f;
3552  }
3553  }
3554  return NullInitializerExpressionFactory.INSTANCE;
3555  }
3556 
3557  private static <T> T unwrap(Object o, Class<T> clazz) {
3558  if (o instanceof Wrapper) {
3559  return ((Wrapper) o).unwrap(clazz);
3560  }
3561  return null;
3562  }
3563 
3564  private RexNode castNullLiteralIfNeeded(RexNode node, RelDataType type) {
3565  if (!RexLiteral.isNullLiteral(node)) {
3566  return node;
3567  }
3568  return rexBuilder.makeCast(type, node);
3569  }
3570 
3581  protected void collectInsertTargets(SqlInsert call,
3582  final RexNode sourceRef,
3583  final List<String> targetColumnNames,
3584  List<RexNode> columnExprs) {
3585  final RelOptTable targetTable = getTargetTable(call);
3586  final RelDataType tableRowType = targetTable.getRowType();
3587  SqlNodeList targetColumnList = call.getTargetColumnList();
3588  if (targetColumnList == null) {
3589  if (validator.config().sqlConformance().isInsertSubsetColumnsAllowed()) {
3590  final RelDataType targetRowType =
3591  typeFactory.createStructType(tableRowType.getFieldList().subList(
3592  0, sourceRef.getType().getFieldCount()));
3593  targetColumnNames.addAll(targetRowType.getFieldNames());
3594  } else {
3595  targetColumnNames.addAll(tableRowType.getFieldNames());
3596  }
3597  } else {
3598  for (int i = 0; i < targetColumnList.size(); i++) {
3599  SqlIdentifier id = (SqlIdentifier) targetColumnList.get(i);
3600  RelDataTypeField field = SqlValidatorUtil.getTargetField(
3601  tableRowType, typeFactory, id, catalogReader, targetTable);
3602  assert field != null : "column " + id.toString() + " not found";
3603  targetColumnNames.add(field.getName());
3604  }
3605  }
3606 
3607  final Blackboard bb =
3608  createInsertBlackboard(targetTable, sourceRef, targetColumnNames);
3609 
3610  // Next, assign expressions for generated columns.
3611  final List<ColumnStrategy> strategies = targetTable.getColumnStrategies();
3612  for (String columnName : targetColumnNames) {
3613  final int i = tableRowType.getFieldNames().indexOf(columnName);
3614  final RexNode expr;
3615  switch (strategies.get(i)) {
3616  case STORED:
3617  final InitializerExpressionFactory f =
3618  Util.first(targetTable.unwrap(InitializerExpressionFactory.class),
3619  NullInitializerExpressionFactory.INSTANCE);
3620  expr = f.newColumnDefaultValue(targetTable, i, bb);
3621  break;
3622  case VIRTUAL:
3623  expr = null;
3624  break;
3625  default:
3626  expr = bb.nameToNodeMap.get(columnName);
3627  }
3628  columnExprs.add(expr);
3629  }
3630 
3631  // Remove virtual columns from the list.
3632  for (int i = 0; i < targetColumnNames.size(); i++) {
3633  if (columnExprs.get(i) == null) {
3634  columnExprs.remove(i);
3635  targetColumnNames.remove(i);
3636  --i;
3637  }
3638  }
3639  }
3640 
3641  private RelNode convertDelete(SqlDelete call) {
3642  RelOptTable targetTable = getTargetTable(call);
3643  RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
3644  return LogicalTableModify.create(targetTable,
3645  catalogReader,
3646  sourceRel,
3647  LogicalTableModify.Operation.DELETE,
3648  null,
3649  null,
3650  false);
3651  }
3652 
3653  private RelNode convertUpdate(SqlUpdate call) {
3654  final SqlValidatorScope scope = validator.getWhereScope(call.getSourceSelect());
3655  Blackboard bb = createBlackboard(scope, null, false);
3656 
3657  replaceSubQueries(bb, call, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
3658 
3659  RelOptTable targetTable = getTargetTable(call);
3660 
3661  // convert update column list from SqlIdentifier to String
3662  final List<String> targetColumnNameList = new ArrayList<>();
3663  final RelDataType targetRowType = targetTable.getRowType();
3664  for (SqlNode node : call.getTargetColumnList()) {
3665  SqlIdentifier id = (SqlIdentifier) node;
3666  RelDataTypeField field = SqlValidatorUtil.getTargetField(
3667  targetRowType, typeFactory, id, catalogReader, targetTable);
3668  assert field != null : "column " + id.toString() + " not found";
3669  targetColumnNameList.add(field.getName());
3670  }
3671 
3672  RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
3673 
3674  bb.setRoot(sourceRel, false);
3675  Builder<RexNode> rexNodeSourceExpressionListBuilder = ImmutableList.builder();
3676  for (SqlNode n : call.getSourceExpressionList()) {
3677  RexNode rn = bb.convertExpression(n);
3678  rexNodeSourceExpressionListBuilder.add(rn);
3679  }
3680 
3681  return LogicalTableModify.create(targetTable,
3682  catalogReader,
3683  sourceRel,
3684  LogicalTableModify.Operation.UPDATE,
3685  targetColumnNameList,
3686  rexNodeSourceExpressionListBuilder.build(),
3687  false);
3688  }
3689 
3690  private RelNode convertMerge(SqlMerge call) {
3691  RelOptTable targetTable = getTargetTable(call);
3692 
3693  // convert update column list from SqlIdentifier to String
3694  final List<String> targetColumnNameList = new ArrayList<>();
3695  final RelDataType targetRowType = targetTable.getRowType();
3696  SqlUpdate updateCall = call.getUpdateCall();
3697  if (updateCall != null) {
3698  for (SqlNode targetColumn : updateCall.getTargetColumnList()) {
3699  SqlIdentifier id = (SqlIdentifier) targetColumn;
3700  RelDataTypeField field = SqlValidatorUtil.getTargetField(
3701  targetRowType, typeFactory, id, catalogReader, targetTable);
3702  assert field != null : "column " + id.toString() + " not found";
3703  targetColumnNameList.add(field.getName());
3704  }
3705  }
3706 
3707  // replace the projection of the source select with a
3708  // projection that contains the following:
3709  // 1) the expressions corresponding to the new insert row (if there is
3710  // an insert)
3711  // 2) all columns from the target table (if there is an update)
3712  // 3) the set expressions in the update call (if there is an update)
3713 
3714  // first, convert the merge's source select to construct the columns
3715  // from the target table and the set expressions in the update call
3716  RelNode mergeSourceRel = convertSelect(call.getSourceSelect(), false);
3717 
3718  // then, convert the insert statement so we can get the insert
3719  // values expressions
3720  SqlInsert insertCall = call.getInsertCall();
3721  int nLevel1Exprs = 0;
3722  List<RexNode> level1InsertExprs = null;
3723  List<RexNode> level2InsertExprs = null;
3724  if (insertCall != null) {
3725  RelNode insertRel = convertInsert(insertCall);
3726 
3727  // if there are 2 level of projections in the insert source, combine
3728  // them into a single project; level1 refers to the topmost project;
3729  // the level1 projection contains references to the level2
3730  // expressions, except in the case where no target expression was
3731  // provided, in which case, the expression is the default value for
3732  // the column; or if the expressions directly map to the source
3733  // table
3734  level1InsertExprs = ((LogicalProject) insertRel.getInput(0)).getProjects();
3735  if (insertRel.getInput(0).getInput(0) instanceof LogicalProject) {
3736  level2InsertExprs =
3737  ((LogicalProject) insertRel.getInput(0).getInput(0)).getProjects();
3738  }
3739  nLevel1Exprs = level1InsertExprs.size();
3740  }
3741 
3742  LogicalJoin join = (LogicalJoin) mergeSourceRel.getInput(0);
3743  int nSourceFields = join.getLeft().getRowType().getFieldCount();
3744  final List<RexNode> projects = new ArrayList<>();
3745  for (int level1Idx = 0; level1Idx < nLevel1Exprs; level1Idx++) {
3746  if ((level2InsertExprs != null)
3747  && (level1InsertExprs.get(level1Idx) instanceof RexInputRef)) {
3748  int level2Idx = ((RexInputRef) level1InsertExprs.get(level1Idx)).getIndex();
3749  projects.add(level2InsertExprs.get(level2Idx));
3750  } else {
3751  projects.add(level1InsertExprs.get(level1Idx));
3752  }
3753  }
3754  if (updateCall != null) {
3755  final LogicalProject project = (LogicalProject) mergeSourceRel;
3756  projects.addAll(Util.skip(project.getProjects(), nSourceFields));
3757  }
3758 
3759  relBuilder.push(join).project(projects);
3760 
3761  return LogicalTableModify.create(targetTable,
3762  catalogReader,
3763  relBuilder.build(),
3764  LogicalTableModify.Operation.MERGE,
3765  targetColumnNameList,
3766  null,
3767  false);
3768  }
3769 
3774  private RexNode convertIdentifier(Blackboard bb, SqlIdentifier identifier) {
3775  // first check for reserved identifiers like CURRENT_USER
3776  final SqlCall call = bb.getValidator().makeNullaryCall(identifier);
3777  if (call != null) {
3778  return bb.convertExpression(call);
3779  }
3780 
3781  String pv = null;
3782  if (bb.isPatternVarRef && identifier.names.size() > 1) {
3783  pv = identifier.names.get(0);
3784  }
3785 
3786  final SqlQualified qualified;
3787  if (bb.scope != null) {
3788  qualified = bb.scope.fullyQualify(identifier);
3789  } else {
3790  qualified = SqlQualified.create(null, 1, null, identifier);
3791  }
3792  final Pair<RexNode, Map<String, Integer>> e0 = bb.lookupExp(qualified);
3793  RexNode e = e0.left;
3794  for (String name : qualified.suffix()) {
3795  if (e == e0.left && e0.right != null) {
3796  int i = e0.right.get(name);
3797  e = rexBuilder.makeFieldAccess(e, i);
3798  } else {
3799  final boolean caseSensitive = true; // name already fully-qualified
3800  if (identifier.isStar() && bb.scope instanceof MatchRecognizeScope) {
3801  e = rexBuilder.makeFieldAccess(e, 0);
3802  } else {
3803  e = rexBuilder.makeFieldAccess(e, name, caseSensitive);
3804  }
3805  }
3806  }
3807  if (e instanceof RexInputRef) {
3808  // adjust the type to account for nulls introduced by outer joins
3809  e = adjustInputRef(bb, (RexInputRef) e);
3810  if (pv != null) {
3811  e = RexPatternFieldRef.of(pv, (RexInputRef) e);
3812  }
3813  }
3814 
3815  if (e0.left instanceof RexCorrelVariable) {
3816  assert e instanceof RexFieldAccess;
3817  final RexNode prev = bb.mapCorrelateToRex.put(
3818  ((RexCorrelVariable) e0.left).id, (RexFieldAccess) e);
3819  assert prev == null;
3820  }
3821  return e;
3822  }
3823 
3833  protected RexNode adjustInputRef(Blackboard bb, RexInputRef inputRef) {
3834  RelDataTypeField field = bb.getRootField(inputRef);
3835  if (field != null) {
3836  return rexBuilder.makeInputRef(field.getType(), inputRef.getIndex());
3837  }
3838  return inputRef;
3839  }
3840 
3848  private RelNode convertRowConstructor(Blackboard bb, SqlCall rowConstructor) {
3849  Preconditions.checkArgument(isRowConstructor(rowConstructor));
3850  final List<SqlNode> operands = rowConstructor.getOperandList();
3851  return convertMultisets(operands, bb);
3852  }
3853 
3854  private RelNode convertCursor(Blackboard bb, SubQuery subQuery) {
3855  final SqlCall cursorCall = (SqlCall) subQuery.node;
3856  assert cursorCall.operandCount() == 1;
3857  SqlNode query = cursorCall.operand(0);
3858  RelNode converted = convertQuery(query, false, false).rel;
3859  int iCursor = bb.cursors.size();
3860  bb.cursors.add(converted);
3861  subQuery.expr = new RexInputRef(iCursor, converted.getRowType());
3862  return converted;
3863  }
3864 
3865  private RelNode convertMultisets(final List<SqlNode> operands, Blackboard bb) {
3866  // NOTE: Wael 2/04/05: this implementation is not the most efficient in
3867  // terms of planning since it generates XOs that can be reduced.
3868  final List<Object> joinList = new ArrayList<>();
3869  List<SqlNode> lastList = new ArrayList<>();
3870  for (int i = 0; i < operands.size(); i++) {
3871  SqlNode operand = operands.get(i);
3872  if (!(operand instanceof SqlCall)) {
3873  lastList.add(operand);
3874  continue;
3875  }
3876 
3877  final SqlCall call = (SqlCall) operand;
3878  final RelNode input;
3879  switch (call.getKind()) {
3880  case MULTISET_VALUE_CONSTRUCTOR:
3881  case ARRAY_VALUE_CONSTRUCTOR:
3882  final SqlNodeList list =
3883  new SqlNodeList(call.getOperandList(), call.getParserPosition());
3884  CollectNamespace nss = (CollectNamespace) validator.getNamespace(call);
3885  Blackboard usedBb;
3886  if (null != nss) {
3887  usedBb = createBlackboard(nss.getScope(), null, false);
3888  } else {
3889  usedBb = createBlackboard(new ListScope(bb.scope) {
3890  public SqlNode getNode() {
3891  return call;
3892  }
3893  }, null, false);
3894  }
3895  RelDataType multisetType = validator.getValidatedNodeType(call);
3896  validator.setValidatedNodeType(list, multisetType.getComponentType());
3897  input = convertQueryOrInList(usedBb, list, null);
3898  break;
3899  case MULTISET_QUERY_CONSTRUCTOR:
3900  case ARRAY_QUERY_CONSTRUCTOR:
3901  final RelRoot root = convertQuery(call.operand(0), false, true);
3902  input = root.rel;
3903  break;
3904  default:
3905  lastList.add(operand);
3906  continue;
3907  }
3908 
3909  if (lastList.size() > 0) {
3910  joinList.add(lastList);
3911  }
3912  lastList = new ArrayList<>();
3913  Collect collect = new Collect(cluster,
3914  cluster.traitSetOf(Convention.NONE),
3915  input,
3916  validator.deriveAlias(call, i));
3917  joinList.add(collect);
3918  }
3919 
3920  if (joinList.size() == 0) {
3921  joinList.add(lastList);
3922  }
3923 
3924  for (int i = 0; i < joinList.size(); i++) {
3925  Object o = joinList.get(i);
3926  if (o instanceof List) {
3927  @SuppressWarnings("unchecked")
3928  List<SqlNode> projectList = (List<SqlNode>) o;
3929  final List<RexNode> selectList = new ArrayList<>();
3930  final List<String> fieldNameList = new ArrayList<>();
3931  for (int j = 0; j < projectList.size(); j++) {
3932  SqlNode operand = projectList.get(j);
3933  selectList.add(bb.convertExpression(operand));
3934 
3935  // REVIEW angel 5-June-2005: Use deriveAliasFromOrdinal
3936  // instead of deriveAlias to match field names from
3937  // SqlRowOperator. Otherwise, get error Type
3938  // 'RecordType(INTEGER EMPNO)' has no field 'EXPR$0' when
3939  // doing select * from unnest( select multiset[empno]
3940  // from sales.emps);
3941 
3942  fieldNameList.add(SqlUtil.deriveAliasFromOrdinal(j));
3943  }
3944 
3945  relBuilder.push(LogicalValues.createOneRow(cluster))
3946  .projectNamed(selectList, fieldNameList, true);
3947 
3948  joinList.set(i, relBuilder.build());
3949  }
3950  }
3951 
3952  RelNode ret = (RelNode) joinList.get(0);
3953  for (int i = 1; i < joinList.size(); i++) {
3954  RelNode relNode = (RelNode) joinList.get(i);
3955  ret = RelFactories.DEFAULT_JOIN_FACTORY.createJoin(ret,
3956  relNode,
3957  ImmutableList.of(),
3958  rexBuilder.makeLiteral(true),
3959  ImmutableSet.of(),
3960  JoinRelType.INNER,
3961  false);
3962  }
3963  return ret;
3964  }
3965 
3966  private void convertSelectList(
3967  Blackboard bb, SqlSelect select, List<SqlNode> orderList) {
3968  SqlNodeList selectList = select.getSelectList();
3969  selectList = validator.expandStar(selectList, select, false);
3970 
3971  replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
3972 
3973  List<String> fieldNames = new ArrayList<>();
3974  final List<RexNode> exprs = new ArrayList<>();
3975  final Collection<String> aliases = new TreeSet<>();
3976 
3977  // Project any system fields. (Must be done before regular select items,
3978  // because offsets may be affected.)
3979  final List<SqlMonotonicity> columnMonotonicityList = new ArrayList<>();
3980  extraSelectItems(bb, select, exprs, fieldNames, aliases, columnMonotonicityList);
3981 
3982  // Project select clause.
3983  int i = -1;
3984  for (SqlNode expr : selectList) {
3985  ++i;
3986  exprs.add(bb.convertExpression(expr));
3987  fieldNames.add(deriveAlias(expr, aliases, i));
3988  }
3989 
3990  // Project extra fields for sorting.
3991  for (SqlNode expr : orderList) {
3992  ++i;
3993  SqlNode expr2 = validator.expandOrderExpr(select, expr);
3994  exprs.add(bb.convertExpression(expr2));
3995  fieldNames.add(deriveAlias(expr, aliases, i));
3996  }
3997 
3998  fieldNames = SqlValidatorUtil.uniquify(
3999  fieldNames, catalogReader.nameMatcher().isCaseSensitive());
4000 
4001  relBuilder.push(bb.root).projectNamed(exprs, fieldNames, true);
4002  bb.setRoot(relBuilder.build(), false);
4003 
4004  assert bb.columnMonotonicities.isEmpty();
4005  bb.columnMonotonicities.addAll(columnMonotonicityList);
4006  for (SqlNode selectItem : selectList) {
4007  bb.columnMonotonicities.add(selectItem.getMonotonicity(bb.scope));
4008  }
4009  }
4010 
4024  protected void extraSelectItems(Blackboard bb,
4025  SqlSelect select,
4026  List<RexNode> exprList,
4027  List<String> nameList,
4028  Collection<String> aliasList,
4029  List<SqlMonotonicity> columnMonotonicityList) {}
4030 
4031  private String deriveAlias(
4032  final SqlNode node, Collection<String> aliases, final int ordinal) {
4033  String alias = validator.deriveAlias(node, ordinal);
4034  if ((alias == null) || aliases.contains(alias)) {
4035  String aliasBase = (alias == null) ? "EXPR$" : alias;
4036  for (int j = 0;; j++) {
4037  alias = aliasBase + j;
4038  if (!aliases.contains(alias)) {
4039  break;
4040  }
4041  }
4042  }
4043  aliases.add(alias);
4044  return alias;
4045  }
4046 
4050  public RelRoot convertWith(SqlWith with, boolean top) {
4051  return convertQuery(with.body, false, top);
4052  }
4053 
4057  public RelNode convertValues(SqlCall values, RelDataType targetRowType) {
4058  final SqlValidatorScope scope = validator.getOverScope(values);
4059  assert scope != null;
4060  final Blackboard bb = createBlackboard(scope, null, false);
4061  convertValuesImpl(bb, values, targetRowType);
4062  return bb.root;
4063  }
4064 
4073  private void convertValuesImpl(
4074  Blackboard bb, SqlCall values, RelDataType targetRowType) {
4075  // Attempt direct conversion to LogicalValues; if that fails, deal with
4076  // fancy stuff like sub-queries below.
4077  RelNode valuesRel =
4078  convertRowValues(bb, values, values.getOperandList(), true, targetRowType);
4079  if (valuesRel != null) {
4080  bb.setRoot(valuesRel, true);
4081  return;
4082  }
4083 
4084  final List<RelNode> unionRels = new ArrayList<>();
4085  for (SqlNode rowConstructor1 : values.getOperandList()) {
4086  SqlCall rowConstructor = (SqlCall) rowConstructor1;
4087  Blackboard tmpBb = createBlackboard(bb.scope, null, false);
4088  replaceSubQueries(tmpBb, rowConstructor, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
4089  final List<Pair<RexNode, String>> exps = new ArrayList<>();
4090  for (Ord<SqlNode> operand : Ord.zip(rowConstructor.getOperandList())) {
4091  exps.add(Pair.of(tmpBb.convertExpression(operand.e),
4092  validator.deriveAlias(operand.e, operand.i)));
4093  }
4094  RelNode in =
4095  (null == tmpBb.root) ? LogicalValues.createOneRow(cluster) : tmpBb.root;
4096  unionRels.add(
4097  relBuilder.push(in).project(Pair.left(exps), Pair.right(exps)).build());
4098  }
4099 
4100  if (unionRels.size() == 0) {
4101  throw new AssertionError("empty values clause");
4102  } else if (unionRels.size() == 1) {
4103  bb.setRoot(unionRels.get(0), true);
4104  } else {
4105  bb.setRoot(LogicalUnion.create(unionRels, true), true);
4106  }
4107  }
4108 
4109  // ~ Inner Classes ----------------------------------------------------------
4110 
4114  protected class Blackboard
4115  implements SqlRexContext, SqlVisitor<RexNode>, InitializerContext {
4119  public final SqlValidatorScope scope;
4120  private final Map<String, RexNode> nameToNodeMap;
4121  public RelNode root;
4122  private List<RelNode> inputs;
4123  private final Map<CorrelationId, RexFieldAccess> mapCorrelateToRex = new HashMap<>();
4124 
4125  private boolean isPatternVarRef = false;
4126 
4127  final List<RelNode> cursors = new ArrayList<>();
4128 
4133  private final List<SubQuery> subQueryList = new ArrayList<>();
4134 
4138  AggConverter agg;
4139 
4144  SqlWindow window;
4145 
4151  private final Map<RelNode, Map<Integer, Integer>> mapRootRelToFieldProjection =
4152  new HashMap<>();
4153 
4154  private final List<SqlMonotonicity> columnMonotonicities = new ArrayList<>();
4155 
4156  private final List<RelDataTypeField> systemFieldList = new ArrayList<>();
4157  final boolean top;
4158 
4159  private final InitializerExpressionFactory initializerExpressionFactory =
4160  new NullInitializerExpressionFactory();
4161 
4173  protected Blackboard(
4174  SqlValidatorScope scope, Map<String, RexNode> nameToNodeMap, boolean top) {
4175  this.scope = scope;
4176  this.nameToNodeMap = nameToNodeMap;
4177  this.top = top;
4178  }
4179 
4180  public SqlNode getTopNode() {
4181  try {
4182  if (null == scope) {
4183  return null;
4184  }
4185  return scope.getNode();
4186  } catch (Exception e) {
4187  return null;
4188  }
4189  }
4190 
4191  public void setPatternVarRef(boolean isVarRef) {
4192  this.isPatternVarRef = isVarRef;
4193  }
4194 
4195  public RexNode register(RelNode rel, JoinRelType joinType) {
4196  return register(rel, joinType, null);
4197  }
4198 
4208  public RexNode register(RelNode rel, JoinRelType joinType, List<RexNode> leftKeys) {
4209  assert joinType != null;
4210  if (root == null) {
4211  assert leftKeys == null;
4212  setRoot(rel, false);
4213  return rexBuilder.makeRangeReference(root.getRowType(), 0, false);
4214  }
4215 
4216  final RexNode joinCond;
4217  final int origLeftInputCount = root.getRowType().getFieldCount();
4218  if (leftKeys != null) {
4219  List<RexNode> newLeftInputExprs = new ArrayList<>();
4220  for (int i = 0; i < origLeftInputCount; i++) {
4221  newLeftInputExprs.add(rexBuilder.makeInputRef(root, i));
4222  }
4223 
4224  final List<Integer> leftJoinKeys = new ArrayList<>();
4225  for (RexNode leftKey : leftKeys) {
4226  int index = newLeftInputExprs.indexOf(leftKey);
4227  if (index < 0 || joinType == JoinRelType.LEFT) {
4228  index = newLeftInputExprs.size();
4229  newLeftInputExprs.add(leftKey);
4230  }
4231  leftJoinKeys.add(index);
4232  }
4233 
4234  RelNode newLeftInput = relBuilder.push(root).project(newLeftInputExprs).build();
4235 
4236  // maintain the group by mapping in the new LogicalProject
4237  if (mapRootRelToFieldProjection.containsKey(root)) {
4238  mapRootRelToFieldProjection.put(
4239  newLeftInput, mapRootRelToFieldProjection.get(root));
4240  }
4241 
4242  setRoot(newLeftInput, false);
4243 
4244  // right fields appear after the LHS fields.
4245  final int rightOffset = root.getRowType().getFieldCount()
4246  - newLeftInput.getRowType().getFieldCount();
4247  final List<Integer> rightKeys =
4248  Util.range(rightOffset, rightOffset + leftKeys.size());
4249 
4250  joinCond = RelOptUtil.createEquiJoinCondition(
4251  newLeftInput, leftJoinKeys, rel, rightKeys, rexBuilder);
4252  } else {
4253  joinCond = rexBuilder.makeLiteral(true);
4254  }
4255 
4256  int leftFieldCount = root.getRowType().getFieldCount();
4257  final RelNode join = createJoin(this, root, rel, joinCond, joinType);
4258 
4259  setRoot(join, false);
4260 
4261  if (leftKeys != null && joinType == JoinRelType.LEFT) {
4262  final int leftKeyCount = leftKeys.size();
4263  int rightFieldLength = rel.getRowType().getFieldCount();
4264  assert leftKeyCount == rightFieldLength - 1;
4265 
4266  final int rexRangeRefLength = leftKeyCount + rightFieldLength;
4267  RelDataType returnType = typeFactory.createStructType(
4268  new AbstractList<Map.Entry<String, RelDataType>>() {
4269  public Map.Entry<String, RelDataType> get(int index) {
4270  return join.getRowType().getFieldList().get(
4271  origLeftInputCount + index);
4272  }
4273 
4274  public int size() {
4275  return rexRangeRefLength;
4276  }
4277  });
4278 
4279  return rexBuilder.makeRangeReference(returnType, origLeftInputCount, false);
4280  } else {
4281  return rexBuilder.makeRangeReference(
4282  rel.getRowType(), leftFieldCount, joinType.generatesNullsOnRight());
4283  }
4284  }
4285 
4297  public void setRoot(RelNode root, boolean leaf) {
4298  setRoot(Collections.singletonList(root), root, root instanceof LogicalJoin);
4299  if (leaf) {
4300  leaves.put(root, root.getRowType().getFieldCount());
4301  }
4302  this.columnMonotonicities.clear();
4303  }
4304 
4305  private void setRoot(List<RelNode> inputs, RelNode root, boolean hasSystemFields) {
4306  this.inputs = inputs;
4307  this.root = root;
4308  this.systemFieldList.clear();
4309  if (hasSystemFields) {
4310  this.systemFieldList.addAll(getSystemFields());
4311  }
4312  }
4313 
4324  public void setDataset(String datasetName) {}
4325 
4326  void setRoot(List<RelNode> inputs) {
4327  setRoot(inputs, null, false);
4328  }
4329 
4336  Pair<RexNode, Map<String, Integer>> lookupExp(SqlQualified qualified) {
4337  if (nameToNodeMap != null && qualified.prefixLength == 1) {
4338  RexNode node = nameToNodeMap.get(qualified.identifier.names.get(0));
4339  if (node == null) {
4340  throw new AssertionError("Unknown identifier '" + qualified.identifier
4341  + "' encountered while expanding expression");
4342  }
4343  return Pair.of(node, null);
4344  }
4345  final SqlNameMatcher nameMatcher =
4346  scope.getValidator().getCatalogReader().nameMatcher();
4347  final SqlValidatorScope.ResolvedImpl resolved =
4348  new SqlValidatorScope.ResolvedImpl();
4349  scope.resolve(qualified.prefix(), nameMatcher, false, resolved);
4350  if (!(resolved.count() == 1)) {
4351  return null;
4352  }
4353  final SqlValidatorScope.Resolve resolve = resolved.only();
4354  final RelDataType rowType = resolve.rowType();
4355 
4356  // Found in current query's from list. Find which from item.
4357  // We assume that the order of the from clause items has been
4358  // preserved.
4359  final SqlValidatorScope ancestorScope = resolve.scope;
4360  boolean isParent = ancestorScope != scope;
4361  if ((inputs != null) && !isParent) {
4362  final LookupContext rels =
4363  new LookupContext(this, inputs, systemFieldList.size());
4364  final RexNode node = lookup(resolve.path.steps().get(0).i, rels);
4365  if (node == null) {
4366  return null;
4367  } else {
4368  final Map<String, Integer> fieldOffsets = new HashMap<>();
4369  for (RelDataTypeField f : resolve.rowType().getFieldList()) {
4370  if (!fieldOffsets.containsKey(f.getName())) {
4371  fieldOffsets.put(f.getName(), f.getIndex());
4372  }
4373  }
4374  final Map<String, Integer> map = ImmutableMap.copyOf(fieldOffsets);
4375  return Pair.of(node, map);
4376  }
4377  } else {
4378  // We're referencing a relational expression which has not been
4379  // converted yet. This occurs when from items are correlated,
4380  // e.g. "select from emp as emp join emp.getDepts() as dept".
4381  // Create a temporary expression.
4382  DeferredLookup lookup =
4383  new DeferredLookup(this, qualified.identifier.names.get(0));
4384  final CorrelationId correlId = cluster.createCorrel();
4385  mapCorrelToDeferred.put(correlId, lookup);
4386  if (resolve.path.steps().get(0).i < 0) {
4387  return Pair.of(rexBuilder.makeCorrel(rowType, correlId), null);
4388  } else {
4389  final RelDataTypeFactory.Builder builder = typeFactory.builder();
4390  final ListScope ancestorScope1 = (ListScope) resolve.scope;
4391  final ImmutableMap.Builder<String, Integer> fields = ImmutableMap.builder();
4392  int i = 0;
4393  int offset = 0;
4394  for (SqlValidatorNamespace c : ancestorScope1.getChildren()) {
4395  builder.addAll(c.getRowType().getFieldList());
4396  if (i == resolve.path.steps().get(0).i) {
4397  for (RelDataTypeField field : c.getRowType().getFieldList()) {
4398  fields.put(field.getName(), field.getIndex() + offset);
4399  }
4400  }
4401  ++i;
4402  offset += c.getRowType().getFieldCount();
4403  }
4404  final RexNode c = rexBuilder.makeCorrel(builder.uniquify().build(), correlId);
4405  return Pair.of(c, fields.build());
4406  }
4407  }
4408  }
4409 
4414  RexNode lookup(int offset, LookupContext lookupContext) {
4415  Pair<RelNode, Integer> pair = lookupContext.findRel(offset);
4416  return rexBuilder.makeRangeReference(pair.left.getRowType(), pair.right, false);
4417  }
4418 
4419  RelDataTypeField getRootField(RexInputRef inputRef) {
4420  if (inputs == null) {
4421  return null;
4422  }
4423  int fieldOffset = inputRef.getIndex();
4424  for (RelNode input : inputs) {
4425  RelDataType rowType = input.getRowType();
4426  if (fieldOffset < rowType.getFieldCount()) {
4427  return rowType.getFieldList().get(fieldOffset);
4428  }
4429  fieldOffset -= rowType.getFieldCount();
4430  }
4431  return null;
4432  }
4433 
4434  public void flatten(List<RelNode> rels,
4435  int systemFieldCount,
4436  int[] start,
4437  List<Pair<RelNode, Integer>> relOffsetList) {
4438  for (RelNode rel : rels) {
4439  if (leaves.containsKey(rel)) {
4440  relOffsetList.add(Pair.of(rel, start[0]));
4441  start[0] += leaves.get(rel);
4442  } else if (rel instanceof LogicalMatch) {
4443  relOffsetList.add(Pair.of(rel, start[0]));
4444  start[0] += rel.getRowType().getFieldCount();
4445  } else {
4446  if (rel instanceof LogicalJoin || rel instanceof LogicalAggregate) {
4447  start[0] += systemFieldCount;
4448  }
4449  flatten(rel.getInputs(), systemFieldCount, start, relOffsetList);
4450  }
4451  }
4452  }
4453 
4454  void registerSubQuery(SqlNode node, RelOptUtil.Logic logic) {
4455  for (SubQuery subQuery : subQueryList) {
4456  // Compare the reference to make sure the matched node has
4457  // exact scope where it belongs.
4458  if (node == subQuery.node) {
4459  return;
4460  }
4461  }
4462  subQueryList.add(new SubQuery(node, logic));
4463  }
4464 
4465  SubQuery getSubQuery(SqlNode expr) {
4466  for (SubQuery subQuery : subQueryList) {
4467  // Compare the reference to make sure the matched node has
4468  // exact scope where it belongs.
4469  if (expr == subQuery.node) {
4470  return subQuery;
4471  }
4472  }
4473 
4474  return null;
4475  }
4476 
4477  ImmutableList<RelNode> retrieveCursors() {
4478  try {
4479  return ImmutableList.copyOf(cursors);
4480  } finally {
4481  cursors.clear();
4482  }
4483  }
4484 
4485  public RexNode convertExpression(SqlNode expr) {
4486  // If we're in aggregation mode and this is an expression in the
4487  // GROUP BY clause, return a reference to the field.
4488  if (agg != null) {
4489  final SqlNode expandedGroupExpr = validator.expand(expr, scope);
4490  final int ref = agg.lookupGroupExpr(expandedGroupExpr);
4491  if (ref >= 0) {
4492  return rexBuilder.makeInputRef(root, ref);
4493  }
4494  if (expr instanceof SqlCall) {
4495  final RexNode rex = agg.lookupAggregates((SqlCall) expr);
4496  if (rex != null) {
4497  return rex;
4498  }
4499  }
4500  }
4501 
4502  // Allow the derived class chance to override the standard
4503  // behavior for special kinds of expressions.
4504  RexNode rex = convertExtendedExpression(expr, this);
4505  if (rex != null) {
4506  return rex;
4507  }
4508 
4509  // Sub-queries and OVER expressions are not like ordinary
4510  // expressions.
4511  final SqlKind kind = expr.getKind();
4512  final SubQuery subQuery;
4513  boolean isExpand = config.getExpandPredicate().test(getTopNode(), expr);
4514  if (!isExpand) {
4515  final SqlCall call;
4516  final SqlNode query;
4517  final RelRoot root;
4518  switch (kind) {
4519  case IN:
4520  case NOT_IN:
4521  case SOME:
4522  case ALL:
4523  call = (SqlCall) expr;
4524  query = call.operand(1);
4525  if (!(query instanceof SqlNodeList)) {
4526  root = convertQueryRecursive(query, false, null);
4527  final SqlNode operand = call.operand(0);
4528  List<SqlNode> nodes;
4529  switch (operand.getKind()) {
4530  case ROW:
4531  nodes = ((SqlCall) operand).getOperandList();
4532  break;
4533  default:
4534  nodes = ImmutableList.of(operand);
4535  }
4536  final ImmutableList.Builder<RexNode> builder = ImmutableList.builder();
4537  for (SqlNode node : nodes) {
4538  builder.add(convertExpression(node));
4539  }
4540  final ImmutableList<RexNode> list = builder.build();
4541  switch (kind) {
4542  case IN:
4543  return RexSubQuery.in(root.rel, list);
4544  case NOT_IN:
4545  return rexBuilder.makeCall(
4546  SqlStdOperatorTable.NOT, RexSubQuery.in(root.rel, list));
4547  case SOME:
4548  return RexSubQuery.some(
4549  root.rel, list, (SqlQuantifyOperator) call.getOperator());
4550  case ALL:
4551  return rexBuilder.makeCall(SqlStdOperatorTable.NOT,
4552  RexSubQuery.some(root.rel,
4553  list,
4554  negate((SqlQuantifyOperator) call.getOperator())));
4555  default:
4556  throw new AssertionError(kind);
4557  }
4558  }
4559  break;
4560 
4561  case EXISTS:
4562  call = (SqlCall) expr;
4563  query = Iterables.getOnlyElement(call.getOperandList());
4564  root = convertQueryRecursive(query, false, null);
4565  RelNode rel = root.rel;
4566  while (rel instanceof Project
4567  || rel instanceof Sort && ((Sort) rel).fetch == null
4568  && ((Sort) rel).offset == null) {
4569  rel = ((SingleRel) rel).getInput();
4570  }
4571  return RexSubQuery.exists(rel);
4572 
4573  case SCALAR_QUERY:
4574  call = (SqlCall) expr;
4575  query = Iterables.getOnlyElement(call.getOperandList());
4576  root = convertQueryRecursive(query, false, null);
4577  return RexSubQuery.scalar(root.rel);
4578  }
4579  }
4580 
4581  switch (kind) {
4582  case SOME:
4583  case ALL:
4584  if (isExpand) {
4585  throw new RuntimeException(kind + " is only supported if expand = false");
4586  }
4587  // fall through
4588  case CURSOR:
4589  case IN:
4590  case NOT_IN:
4591  subQuery = Objects.requireNonNull(getSubQuery(expr));
4592  rex = Objects.requireNonNull(subQuery.expr);
4593  return StandardConvertletTable.castToValidatedType(
4594  expr, rex, validator, rexBuilder);
4595 
4596  case SELECT:
4597  case EXISTS:
4598  case SCALAR_QUERY:
4599  subQuery = getSubQuery(expr);
4600  assert subQuery != null;
4601  rex = subQuery.expr;
4602  assert rex != null : "rex != null";
4603 
4604  if (((kind == SqlKind.SCALAR_QUERY) || (kind == SqlKind.EXISTS))
4605  && isConvertedSubq(rex)) {
4606  // scalar sub-query or EXISTS has been converted to a
4607  // constant
4608  return rex;
4609  }
4610 
4611  // The indicator column is the last field of the sub-query.
4612  RexNode fieldAccess =
4613  rexBuilder.makeFieldAccess(rex, rex.getType().getFieldCount() - 1);
4614 
4615  // The indicator column will be nullable if it comes from
4616  // the null-generating side of the join. For EXISTS, add an
4617  // "IS TRUE" check so that the result is "BOOLEAN NOT NULL".
4618  if (fieldAccess.getType().isNullable() && kind == SqlKind.EXISTS) {
4619  fieldAccess =
4620  rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, fieldAccess);
4621  }
4622  return fieldAccess;
4623 
4624  case OVER:
4625  return convertOver(this, expr);
4626 
4627  default:
4628  // fall through
4629  }
4630 
4631  // Apply standard conversions.
4632  rex = expr.accept(this);
4633  return Objects.requireNonNull(rex);
4634  }
4635 
4640  public RexFieldCollation convertSortExpression(SqlNode expr,
4641  RelFieldCollation.Direction direction,
4642  RelFieldCollation.NullDirection nullDirection) {
4643  switch (expr.getKind()) {
4644  case DESCENDING:
4645  return convertSortExpression(((SqlCall) expr).operand(0),
4646  RelFieldCollation.Direction.DESCENDING,
4647  nullDirection);
4648  case NULLS_LAST:
4649  return convertSortExpression(((SqlCall) expr).operand(0),
4650  direction,
4651  RelFieldCollation.NullDirection.LAST);
4652  case NULLS_FIRST:
4653  return convertSortExpression(((SqlCall) expr).operand(0),
4654  direction,
4655  RelFieldCollation.NullDirection.FIRST);
4656  default:
4657  final Set<SqlKind> flags = EnumSet.noneOf(SqlKind.class);
4658  switch (direction) {
4659  case DESCENDING:
4660  flags.add(SqlKind.DESCENDING);
4661  }
4662  switch (nullDirection) {
4663  case UNSPECIFIED:
4664  final RelFieldCollation.NullDirection nullDefaultDirection =
4665  validator.config().defaultNullCollation().last(desc(direction))
4666  ? RelFieldCollation.NullDirection.LAST
4667  : RelFieldCollation.NullDirection.FIRST;
4668  if (nullDefaultDirection != direction.defaultNullDirection()) {
4669  SqlKind nullDirectionSqlKind =
4670  validator.config().defaultNullCollation().last(desc(direction))
4671  ? SqlKind.NULLS_LAST
4672  : SqlKind.NULLS_FIRST;
4673  flags.add(nullDirectionSqlKind);
4674  }
4675  break;
4676  case FIRST:
4677  flags.add(SqlKind.NULLS_FIRST);
4678  break;
4679  case LAST:
4680  flags.add(SqlKind.NULLS_LAST);
4681  break;
4682  }
4683  return new RexFieldCollation(convertExpression(expr), flags);
4684  }
4685  }
4686 
4695  private boolean isConvertedSubq(RexNode rex) {
4696  if ((rex instanceof RexLiteral) || (rex instanceof RexDynamicParam)) {
4697  return true;
4698  }
4699  if (rex instanceof RexCall) {
4700  RexCall call = (RexCall) rex;
4701  if (call.getOperator() == SqlStdOperatorTable.CAST) {
4702  RexNode operand = call.getOperands().get(0);
4703  if (operand instanceof RexLiteral) {
4704  return true;
4705  }
4706  }
4707  }
4708  return false;
4709  }
4710 
4711  public int getGroupCount() {
4712  if (agg != null) {
4713  return agg.groupExprs.size();
4714  }
4715  if (window != null) {
4716  return window.isAlwaysNonEmpty() ? 1 : 0;
4717  }
4718  return -1;
4719  }
4720 
4721  public RexBuilder getRexBuilder() {
4722  return rexBuilder;
4723  }
4724 
4725  public SqlNode validateExpression(RelDataType rowType, SqlNode expr) {
4726  return SqlValidatorUtil
4727  .validateExprWithRowType(catalogReader.nameMatcher().isCaseSensitive(),
4728  opTab,
4729  typeFactory,
4730  rowType,
4731  expr)
4732  .left;
4733  }
4734 
4735  public RexRangeRef getSubQueryExpr(SqlCall call) {
4736  final SubQuery subQuery = getSubQuery(call);
4737  assert subQuery != null;
4738  return (RexRangeRef) subQuery.expr;
4739  }
4740 
4741  public RelDataTypeFactory getTypeFactory() {
4742  return typeFactory;
4743  }
4744 
4745  public InitializerExpressionFactory getInitializerExpressionFactory() {
4746  return initializerExpressionFactory;
4747  }
4748 
4749  public SqlValidator getValidator() {
4750  return validator;
4751  }
4752 
4753  public RexNode convertLiteral(SqlLiteral literal) {
4754  return exprConverter.convertLiteral(this, literal);
4755  }
4756 
4757  public RexNode convertInterval(SqlIntervalQualifier intervalQualifier) {
4758  return exprConverter.convertInterval(this, intervalQualifier);
4759  }
4760 
4761  public RexNode visit(SqlLiteral literal) {
4762  return exprConverter.convertLiteral(this, literal);
4763  }
4764 
4765  public RexNode visit(SqlCall call) {
4766  if (agg != null) {
4767  final SqlOperator op = call.getOperator();
4768  if (window == null
4769  && (op.isAggregator() || op.getKind() == SqlKind.FILTER
4770  || op.getKind() == SqlKind.WITHIN_GROUP)) {
4771  return agg.lookupAggregates(call);
4772  }
4773  }
4774  return exprConverter.convertCall(
4775  this, new SqlCallBinding(validator, scope, call).permutedCall());
4776  }
4777 
4778  public RexNode visit(SqlNodeList nodeList) {
4779  throw new UnsupportedOperationException();
4780  }
4781 
4782  public RexNode visit(SqlIdentifier id) {
4783  return convertIdentifier(this, id);
4784  }
4785 
4786  public RexNode visit(SqlDataTypeSpec type) {
4787  throw new UnsupportedOperationException();
4788  }
4789 
4790  public RexNode visit(SqlDynamicParam param) {
4791  return convertDynamicParam(param);
4792  }
4793 
4794  public RexNode visit(SqlIntervalQualifier intervalQualifier) {
4795  return convertInterval(intervalQualifier);
4796  }
4797 
4798  public List<SqlMonotonicity> getColumnMonotonicities() {
4799  return columnMonotonicities;
4800  }
4801  }
4802 
4803  private SqlQuantifyOperator negate(SqlQuantifyOperator operator) {
4804  assert operator.kind == SqlKind.ALL;
4805  return SqlStdOperatorTable.some(operator.comparisonKind.negateNullSafe());
4806  }
4807 
4809  private static class DeferredLookup {
4812 
4813  DeferredLookup(Blackboard bb, String originalRelName) {
4814  this.bb = bb;
4815  this.originalRelName = originalRelName;
4816  }
4817 
4818  public RexFieldAccess getFieldAccess(CorrelationId name) {
4819  return (RexFieldAccess) bb.mapCorrelateToRex.get(name);
4820  }
4821 
4822  public String getOriginalRelName() {
4823  return originalRelName;
4824  }
4825  }
4826 
4830  private class NoOpSubQueryConverter implements SubQueryConverter {
4831  public boolean canConvertSubQuery() {
4832  return false;
4833  }
4834 
4835  public RexNode convertSubQuery(SqlCall subQuery,
4836  SqlToRelConverter parentConverter,
4837  boolean isExists,
4838  boolean isExplain) {
4839  throw new IllegalArgumentException();
4840  }
4841  }
4842 
4862  protected class AggConverter implements SqlVisitor<Void> {
4863  private final Blackboard bb;
4864  public final AggregatingSelectScope aggregatingSelectScope;
4865 
4866  private final Map<String, String> nameMap = new HashMap<>();
4867 
4871  private final SqlNodeList groupExprs = new SqlNodeList(SqlParserPos.ZERO);
4872 
4876  private final Map<SqlNode, Ord<AuxiliaryConverter>> auxiliaryGroupExprs =
4877  new HashMap<>();
4878 
4886  private final List<Pair<RexNode, String>> convertedInputExprs = new ArrayList<>();
4887 
4894  private final List<AggregateCall> aggCalls = new ArrayList<>();
4895  private final Map<SqlNode, RexNode> aggMapping = new HashMap<>();
4896  private final Map<AggregateCall, RexNode> aggCallMapping = new HashMap<>();
4897 
4899  private boolean inOver = false;
4900 
4911  public AggConverter(Blackboard bb, SqlSelect select) {
4912  this.bb = bb;
4913  this.aggregatingSelectScope =
4914  (AggregatingSelectScope) bb.getValidator().getSelectScope(select);
4915 
4916  // Collect all expressions used in the select list so that aggregate
4917  // calls can be named correctly.
4918  final SqlNodeList selectList = select.getSelectList();
4919  for (int i = 0; i < selectList.size(); i++) {
4920  SqlNode selectItem = selectList.get(i);
4921  String name = null;
4922  if (SqlUtil.isCallTo(selectItem, SqlStdOperatorTable.AS)) {
4923  final SqlCall call = (SqlCall) selectItem;
4924  selectItem = call.operand(0);
4925  name = call.operand(1).toString();
4926  }
4927  if (name == null) {
4928  name = validator.deriveAlias(selectItem, i);
4929  }
4930  nameMap.put(selectItem.toString(), name);
4931  }
4932  }
4933 
4934  public int addGroupExpr(SqlNode expr) {
4935  int ref = lookupGroupExpr(expr);
4936  if (ref >= 0) {
4937  return ref;
4938  }
4939  final int index = groupExprs.size();
4940  groupExprs.add(expr);
4941  String name = nameMap.get(expr.toString());
4942  RexNode convExpr = bb.convertExpression(expr);
4943  addExpr(convExpr, name);
4944 
4945  if (expr instanceof SqlCall) {
4946  SqlCall call = (SqlCall) expr;
4947  for (Pair<SqlNode, AuxiliaryConverter> p :
4948  SqlStdOperatorTable.convertGroupToAuxiliaryCalls(call)) {
4949  addAuxiliaryGroupExpr(p.left, index, p.right);
4950  }
4951  }
4952 
4953  return index;
4954  }
4955 
4956  void addAuxiliaryGroupExpr(SqlNode node, int index, AuxiliaryConverter converter) {
4957  for (SqlNode node2 : auxiliaryGroupExprs.keySet()) {
4958  if (node2.equalsDeep(node, Litmus.IGNORE)) {
4959  return;
4960  }
4961  }
4962  auxiliaryGroupExprs.put(node, Ord.of(index, converter));
4963  }
4964 
4971  private void addExpr(RexNode expr, String name) {
4972  if ((name == null) && (expr instanceof RexInputRef)) {
4973  final int i = ((RexInputRef) expr).getIndex();
4974  name = bb.root.getRowType().getFieldList().get(i).getName();
4975  }
4976  if (Pair.right(convertedInputExprs).contains(name)) {
4977  // In case like 'SELECT ... GROUP BY x, y, x', don't add
4978  // name 'x' twice.
4979  name = null;
4980  }
4981  convertedInputExprs.add(Pair.of(expr, name));
4982  }
4983 
4984  public Void visit(SqlIdentifier id) {
4985  return null;
4986  }
4987 
4988  public Void visit(SqlNodeList nodeList) {
4989  for (int i = 0; i < nodeList.size(); i++) {
4990  nodeList.get(i).accept(this);
4991  }
4992  return null;
4993  }
4994 
4995  public Void visit(SqlLiteral lit) {
4996  return null;
4997  }
4998 
4999  public Void visit(SqlDataTypeSpec type) {
5000  return null;
5001  }
5002 
5003  public Void visit(SqlDynamicParam param) {
5004  return null;
5005  }
5006 
5007  public Void visit(SqlIntervalQualifier intervalQualifier) {
5008  return null;
5009  }
5010 
5011  public Void visit(SqlCall call) {
5012  switch (call.getKind()) {
5013  case FILTER:
5014  case WITHIN_GROUP:
5015  translateAgg(call);
5016  return null;
5017  case SELECT:
5018  // rchen 2006-10-17:
5019  // for now do not detect aggregates in sub-queries.
5020  return null;
5021  }
5022  final boolean prevInOver = inOver;
5023  // Ignore window aggregates and ranking functions (associated with OVER
5024  // operator). However, do not ignore nested window aggregates.
5025  if (call.getOperator().getKind() == SqlKind.OVER) {
5026  // Track aggregate nesting levels only within an OVER operator.
5027  List<SqlNode> operandList = call.getOperandList();
5028  assert operandList.size() == 2;
5029 
5030  // Ignore the top level window aggregates and ranking functions
5031  // positioned as the first operand of a OVER operator
5032  inOver = true;
5033  operandList.get(0).accept(this);
5034 
5035  // Normal translation for the second operand of a OVER operator
5036  inOver = false;
5037  operandList.get(1).accept(this);
5038  return null;
5039  }
5040 
5041  // Do not translate the top level window aggregate. Only do so for
5042  // nested aggregates, if present
5043  if (call.getOperator().isAggregator()) {
5044  if (inOver) {
5045  // Add the parent aggregate level before visiting its children
5046  inOver = false;
5047  } else {
5048  // We're beyond the one ignored level
5049  translateAgg(call);
5050  return null;
5051  }
5052  }
5053  for (SqlNode operand : call.getOperandList()) {
5054  // Operands are occasionally null, e.g. switched CASE arg 0.
5055  if (operand != null) {
5056  operand.accept(this);
5057  }
5058  }
5059  // Remove the parent aggregate level after visiting its children
5060  inOver = prevInOver;
5061  return null;
5062  }
5063 
5064  private void translateAgg(SqlCall call) {
5065  translateAgg(call, null, null, false, call);
5066  }
5067 
5068  private void translateAgg(SqlCall call,
5069  SqlNode filter,
5070  SqlNodeList orderList,
5071  boolean ignoreNulls,
5072  SqlCall outerCall) {
5073  assert bb.agg == this;
5074  assert outerCall != null;
5075  switch (call.getKind()) {
5076  case FILTER:
5077  assert filter == null;
5078  translateAgg(
5079  call.operand(0), call.operand(1), orderList, ignoreNulls, outerCall);
5080  return;
5081  case WITHIN_GROUP:
5082  assert orderList == null;
5083  translateAgg(call.operand(0), filter, call.operand(1), ignoreNulls, outerCall);
5084  return;
5085  case IGNORE_NULLS:
5086  ignoreNulls = true;
5087  // fall through
5088  case RESPECT_NULLS:
5089  translateAgg(call.operand(0), filter, orderList, ignoreNulls, outerCall);
5090  return;
5091  }
5092  final List<Integer> args = new ArrayList<>();
5093  int filterArg = -1;
5094  final List<RelDataType> argTypes = call.getOperator() instanceof SqlCountAggFunction
5095  ? new ArrayList<>(call.getOperandList().size())
5096  : null;
5097  try {
5098  // switch out of agg mode
5099  bb.agg = null;
5100  for (SqlNode operand : call.getOperandList()) {
5101  // special case for COUNT(*): delete the *
5102  if (operand instanceof SqlIdentifier) {
5103  SqlIdentifier id = (SqlIdentifier) operand;
5104  if (id.isStar()) {
5105  assert call.operandCount() == 1;
5106  assert args.isEmpty();
5107  break;
5108  }
5109  }
5110  RexNode convertedExpr = bb.convertExpression(operand);
5111  assert convertedExpr != null;
5112  if (argTypes != null) {
5113  argTypes.add(convertedExpr.getType());
5114  }
5115  args.add(lookupOrCreateGroupExpr(convertedExpr));
5116  }
5117 
5118  if (filter != null) {
5119  RexNode convertedExpr = bb.convertExpression(filter);
5120  assert convertedExpr != null;
5121  if (convertedExpr.getType().isNullable()) {
5122  convertedExpr =
5123  rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, convertedExpr);
5124  }
5125  filterArg = lookupOrCreateGroupExpr(convertedExpr);
5126  }
5127  } finally {
5128  // switch back into agg mode
5129  bb.agg = this;
5130  }
5131 
5132  SqlAggFunction aggFunction = (SqlAggFunction) call.getOperator();
5133  final RelDataType type = validator.deriveType(bb.scope, call);
5134  boolean distinct = false;
5135  SqlLiteral quantifier = call.getFunctionQuantifier();
5136  if ((null != quantifier) && (quantifier.getValue() == SqlSelectKeyword.DISTINCT)) {
5137  distinct = true;
5138  }
5139  boolean approximate = false;
5140  if (aggFunction == SqlStdOperatorTable.APPROX_COUNT_DISTINCT) {
5141  aggFunction = SqlStdOperatorTable.COUNT;
5142  distinct = true;
5143  approximate = true;
5144  }
5145  final RelCollation collation;
5146  if (orderList == null || orderList.size() == 0) {
5147  collation = RelCollations.EMPTY;
5148  } else {
5149  collation = RelCollations.of(
5150  orderList.getList()
5151  .stream()
5152  .map(order
5153  -> bb.convertSortExpression(order,
5154  RelFieldCollation.Direction.ASCENDING,
5155  RelFieldCollation.NullDirection.UNSPECIFIED))
5156  .map(fieldCollation
5157  -> new RelFieldCollation(
5158  lookupOrCreateGroupExpr(fieldCollation.left),
5159  fieldCollation.getDirection(),
5160  fieldCollation.getNullDirection()))
5161  .collect(Collectors.toList()));
5162  }
5163  final AggregateCall aggCall = AggregateCall.create(aggFunction,
5164  distinct,
5165  approximate,
5166  ignoreNulls,
5167  args,
5168  filterArg,
5169  collation,
5170  type,
5171  nameMap.get(outerCall.toString()));
5172  RexNode rex = rexBuilder.addAggCall(
5173  aggCall, groupExprs.size(), aggCalls, aggCallMapping, argTypes);
5174  aggMapping.put(outerCall, rex);
5175  }
5176 
5177  private int lookupOrCreateGroupExpr(RexNode expr) {
5178  int index = 0;
5179  for (RexNode convertedInputExpr : Pair.left(convertedInputExprs)) {
5180  if (expr.equals(convertedInputExpr)) {
5181  return index;
5182  }
5183  ++index;
5184  }
5185 
5186  // not found -- add it
5187  addExpr(expr, null);
5188  return index;
5189  }
5190 
5195  public int lookupGroupExpr(SqlNode expr) {
5196  for (int i = 0; i < groupExprs.size(); i++) {
5197  SqlNode groupExpr = groupExprs.get(i);
5198  if (expr.equalsDeep(groupExpr, Litmus.IGNORE)) {
5199  return i;
5200  }
5201  }
5202  return -1;
5203  }
5204 
5205  public RexNode lookupAggregates(SqlCall call) {
5206  // assert call.getOperator().isAggregator();
5207  assert bb.agg == this;
5208 
5209  for (Map.Entry<SqlNode, Ord<AuxiliaryConverter>> e :
5210  auxiliaryGroupExprs.entrySet()) {
5211  if (call.equalsDeep(e.getKey(), Litmus.IGNORE)) {
5212  AuxiliaryConverter converter = e.getValue().e;
5213  final int groupOrdinal = e.getValue().i;
5214  return converter.convert(rexBuilder,
5215  convertedInputExprs.get(groupOrdinal).left,
5216  rexBuilder.makeInputRef(bb.root, groupOrdinal));
5217  }
5218  }
5219 
5220  return aggMapping.get(call);
5221  }
5222 
5223  public List<Pair<RexNode, String>> getPreExprs() {
5224  return convertedInputExprs;
5225  }
5226 
5227  public List<AggregateCall> getAggCalls() {
5228  return aggCalls;
5229  }
5230 
5231  private boolean containsGroupId() {
5232  return aggCalls.stream().anyMatch(
5233  agg -> agg.getAggregation().kind == SqlKind.GROUP_ID);
5234  }
5235 
5236  public RelDataTypeFactory getTypeFactory() {
5237  return typeFactory;
5238  }
5239  }
5240 
5244  private static class LookupContext {
5245  private final List<Pair<RelNode, Integer>> relOffsetList = new ArrayList<>();
5246 
5254  LookupContext(Blackboard bb, List<RelNode> rels, int systemFieldCount) {
5255  bb.flatten(rels, systemFieldCount, new int[] {0}, relOffsetList);
5256  }
5257 
5270  Pair<RelNode, Integer> findRel(int offset) {
5271  return relOffsetList.get(offset);
5272  }
5273  }
5274 
5307  private class HistogramShuttle extends RexShuttle {
5312  static final boolean ENABLE_HISTOGRAM_AGG = false;
5313 
5314  private final List<RexNode> partitionKeys;
5315  private final ImmutableList<RexFieldCollation> orderKeys;
5316  private final RexWindowBound lowerBound;
5317  private final RexWindowBound upperBound;
5318  private final boolean rows;
5319  private final boolean allowPartial;
5320  private final boolean distinct;
5321  private final boolean ignoreNulls;
5322 
5323  HistogramShuttle(List<RexNode> partitionKeys,
5324  ImmutableList<RexFieldCollation> orderKeys,
5325  RexWindowBound lowerBound,
5326  RexWindowBound upperBound,
5327  boolean rows,
5328  boolean allowPartial,
5329  boolean distinct,
5330  boolean ignoreNulls) {
5331  this.partitionKeys = partitionKeys;
5332  this.orderKeys = orderKeys;
5333  this.lowerBound = lowerBound;
5334  this.upperBound = upperBound;
5335  this.rows = rows;
5336  this.allowPartial = allowPartial;
5337  this.distinct = distinct;
5338  this.ignoreNulls = ignoreNulls;
5339  }
5340 
5341  public RexNode visitCall(RexCall call) {
5342  final SqlOperator op = call.getOperator();
5343  if (!(op instanceof SqlAggFunction)) {
5344  return super.visitCall(call);
5345  }
5346  final SqlAggFunction aggOp = (SqlAggFunction) op;
5347  final RelDataType type = call.getType();
5348  List<RexNode> exprs = call.getOperands();
5349 
5350  SqlFunction histogramOp = !ENABLE_HISTOGRAM_AGG ? null : getHistogramOp(aggOp);
5351 
5352  if (histogramOp != null) {
5353  final RelDataType histogramType = computeHistogramType(type);
5354 
5355  // For DECIMAL, since it's already represented as a bigint we
5356  // want to do a reinterpretCast instead of a cast to avoid
5357  // losing any precision.
5358  boolean reinterpretCast = type.getSqlTypeName() == SqlTypeName.DECIMAL;
5359 
5360  // Replace original expression with CAST of not one
5361  // of the supported types
5362  if (histogramType != type) {
5363  exprs = new ArrayList<>(exprs);
5364  exprs.set(0,
5365  reinterpretCast ? rexBuilder.makeReinterpretCast(
5366  histogramType, exprs.get(0), rexBuilder.makeLiteral(false))
5367  : rexBuilder.makeCast(histogramType, exprs.get(0)));
5368  }
5369 
5370  RexCallBinding bind = new RexCallBinding(rexBuilder.getTypeFactory(),
5371  SqlStdOperatorTable.HISTOGRAM_AGG,
5372  exprs,
5373  ImmutableList.of());
5374 
5375  RexNode over = rexBuilder.makeOver(
5376  SqlStdOperatorTable.HISTOGRAM_AGG.inferReturnType(bind),
5377  SqlStdOperatorTable.HISTOGRAM_AGG,
5378  exprs,
5379  partitionKeys,
5380  orderKeys,
5381  lowerBound,
5382  upperBound,
5383  rows,
5384  allowPartial,
5385  false,
5386  distinct,
5387  ignoreNulls);
5388 
5389  RexNode histogramCall =
5390  rexBuilder.makeCall(histogramType, histogramOp, ImmutableList.of(over));
5391 
5392  // If needed, post Cast result back to original
5393  // type.
5394  if (histogramType != type) {
5395  if (reinterpretCast) {
5396  histogramCall = rexBuilder.makeReinterpretCast(
5397  type, histogramCall, rexBuilder.makeLiteral(false));
5398  } else {
5399  histogramCall = rexBuilder.makeCast(type, histogramCall);
5400  }
5401  }
5402 
5403  return histogramCall;
5404  } else {
5405  boolean needSum0 = aggOp == SqlStdOperatorTable.SUM && type.isNullable();
5406  SqlAggFunction aggOpToUse = needSum0 ? SqlStdOperatorTable.SUM0 : aggOp;
5407  return rexBuilder.makeOver(type,
5408  aggOpToUse,
5409  exprs,
5410  partitionKeys,
5411  orderKeys,
5412  lowerBound,
5413  upperBound,
5414  rows,
5415  allowPartial,
5416  needSum0,
5417  distinct,
5418  ignoreNulls);
5419  }
5420  }
5421 
5433  SqlFunction getHistogramOp(SqlAggFunction aggFunction) {
5434  if (aggFunction == SqlStdOperatorTable.MIN) {
5435  return SqlStdOperatorTable.HISTOGRAM_MIN;
5436  } else if (aggFunction == SqlStdOperatorTable.MAX) {
5437  return SqlStdOperatorTable.HISTOGRAM_MAX;
5438  } else if (aggFunction == SqlStdOperatorTable.FIRST_VALUE) {
5439  return SqlStdOperatorTable.HISTOGRAM_FIRST_VALUE;
5440  } else if (aggFunction == SqlStdOperatorTable.LAST_VALUE) {
5441  return SqlStdOperatorTable.HISTOGRAM_LAST_VALUE;
5442  } else {
5443  return null;
5444  }
5445  }
5446 
5451  private RelDataType computeHistogramType(RelDataType type) {
5452  if (SqlTypeUtil.isExactNumeric(type)
5453  && type.getSqlTypeName() != SqlTypeName.BIGINT) {
5454  return typeFactory.createSqlType(SqlTypeName.BIGINT);
5455  } else if (SqlTypeUtil.isApproximateNumeric(type)
5456  && type.getSqlTypeName() != SqlTypeName.DOUBLE) {
5457  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
5458  } else {
5459  return type;
5460  }
5461  }
5462  }
5463 
5467  private static class SubQuery {
5468  final SqlNode node;
5469  final RelOptUtil.Logic logic;
5470  RexNode expr;
5471 
5472  private SubQuery(SqlNode node, RelOptUtil.Logic logic) {
5473  this.node = node;
5474  this.logic = logic;
5475  }
5476  }
5477 
5481  private static class AggregateFinder extends SqlBasicVisitor<Void> {
5482  final SqlNodeList list = new SqlNodeList(SqlParserPos.ZERO);
5483  final SqlNodeList filterList = new SqlNodeList(SqlParserPos.ZERO);
5484  final SqlNodeList orderList = new SqlNodeList(SqlParserPos.ZERO);
5485 
5486  @Override
5487  public Void visit(SqlCall call) {
5488  // ignore window aggregates and ranking functions (associated with OVER
5489  // operator)
5490  if (call.getOperator().getKind() == SqlKind.OVER) {
5491  return null;
5492  }
5493 
5494  if (call.getOperator().getKind() == SqlKind.FILTER) {
5495  // the WHERE in a FILTER must be tracked too so we can call replaceSubQueries on
5496  // it.
5497  // see https://issues.apache.org/jira/browse/CALCITE-1910
5498  final SqlNode aggCall = call.getOperandList().get(0);
5499  final SqlNode whereCall = call.getOperandList().get(1);
5500  list.add(aggCall);
5501  filterList.add(whereCall);
5502  return null;
5503  }
5504 
5505  if (call.getOperator().getKind() == SqlKind.WITHIN_GROUP) {
5506  // the WHERE in a WITHIN_GROUP must be tracked too so we can call
5507  // replaceSubQueries on it.
5508  // see https://issues.apache.org/jira/browse/CALCITE-1910
5509  final SqlNode aggCall = call.getOperandList().get(0);
5510  final SqlNodeList orderList = (SqlNodeList) call.getOperandList().get(1);
5511  list.add(aggCall);
5512  orderList.getList().forEach(this.orderList::add);
5513  return null;
5514  }
5515 
5516  if (call.getOperator().isAggregator()) {
5517  list.add(call);
5518  return null;
5519  }
5520 
5521  // Don't traverse into sub-queries, even if they contain aggregate
5522  // functions.
5523  if (call instanceof SqlSelect) {
5524  return null;
5525  }
5526 
5527  return call.getOperator().acceptCall(this, call);
5528  }
5529  }
5530 
5534  private static class CorrelationUse {
5535  private final CorrelationId id;
5536  private final ImmutableBitSet requiredColumns;
5538  private final RelNode r;
5539 
5540  CorrelationUse(CorrelationId id, ImmutableBitSet requiredColumns, RelNode r) {
5541  this.id = id;
5542  this.requiredColumns = requiredColumns;
5543  this.r = r;
5544  }
5545  }
5546 
5548  public static ConfigBuilder configBuilder() {
5549  return new ConfigBuilder();
5550  }
5551 
5559  public interface Config {
5561  Config DEFAULT = configBuilder().build();
5562 
5567  boolean isDecorrelationEnabled();
5568 
5573  boolean isTrimUnusedFields();
5574 
5580  boolean isCreateValuesRel();
5581 
5586  boolean isExplain();
5587 
5592  boolean isExpand();
5593 
5603  int getInSubQueryThreshold();
5604 
5609  RelBuilderFactory getRelBuilderFactory();
5610 
5615  UnaryOperator<RelBuilder.Config> getRelBuilderConfigTransform();
5616 
5621  HintStrategyTable getHintStrategyTable();
5622 
5629  BiPredicate<SqlNode, SqlNode> getExpandPredicate();
5630 
5635  BiPredicate<SqlNode, Join> getPushdownJoinCondition();
5636  }
5637 
5639  public static class ConfigBuilder {
5640  private boolean decorrelationEnabled = true;
5641  private boolean trimUnusedFields = false;
5642  private boolean createValuesRel = true;
5643  private boolean explain;
5644  private boolean expand = true;
5645  private int inSubQueryThreshold = DEFAULT_IN_SUB_QUERY_THRESHOLD;
5646  private UnaryOperator<RelBuilder.Config> relBuilderConfigTransform =
5647  c -> c.withPushJoinCondition(true);
5648  private RelBuilderFactory relBuilderFactory = RelFactories.LOGICAL_BUILDER;
5649  private HintStrategyTable hintStrategyTable = HintStrategyTable.EMPTY;
5650  // MAT 08 Jan 2021 OmniSci code
5651  private BiPredicate<SqlNode, Join> pushdownJoinCondition;
5652  private BiPredicate<SqlNode, SqlNode> expandPredicate;
5653  // MAT 08 Jan 2021 OmniSci code ends
5654 
5655  private ConfigBuilder() {}
5656 
5658  public ConfigBuilder withConfig(Config config) {
5659  this.decorrelationEnabled = config.isDecorrelationEnabled();
5660  this.trimUnusedFields = config.isTrimUnusedFields();
5661  this.createValuesRel = config.isCreateValuesRel();
5662  this.explain = config.isExplain();
5663  this.expand = config.isExpand();
5664  this.inSubQueryThreshold = config.getInSubQueryThreshold();
5665  this.relBuilderConfigTransform = config.getRelBuilderConfigTransform();
5666  this.relBuilderFactory = config.getRelBuilderFactory();
5667  this.hintStrategyTable = config.getHintStrategyTable();
5668 
5669  // MAT 08 Jan 2021 OmniSci code
5670  if (!(config.getExpandPredicate() instanceof ConfigImpl.DefaultExpandPredicate)) {
5671  this.expandPredicate = config.getExpandPredicate();
5672  }
5673  this.pushdownJoinCondition = config.getPushdownJoinCondition();
5674  // MAT 08 Jan 2021 OmniSci code ends
5675  return this;
5676  }
5677 
5678  public ConfigBuilder withDecorrelationEnabled(boolean enabled) {
5679  this.decorrelationEnabled = enabled;
5680  return this;
5681  }
5682 
5683  public ConfigBuilder withTrimUnusedFields(boolean trimUnusedFields) {
5684  this.trimUnusedFields = trimUnusedFields;
5685  return this;
5686  }
5687 
5688  public ConfigBuilder withCreateValuesRel(boolean createValuesRel) {
5689  this.createValuesRel = createValuesRel;
5690  return this;
5691  }
5692 
5693  public ConfigBuilder withExplain(boolean explain) {
5694  this.explain = explain;
5695  return this;
5696  }
5697 
5698  public ConfigBuilder withExpand(boolean expand) {
5699  this.expand = expand;
5700  return this;
5701  }
5702 
5703  public ConfigBuilder withPushdownJoinCondition(BiPredicate<SqlNode, Join> pushdown) {
5704  this.pushdownJoinCondition = pushdown;
5705  return this;
5706  }
5707 
5708  public ConfigBuilder withExpandPredicate(BiPredicate<SqlNode, SqlNode> predicate) {
5709  this.expandPredicate = predicate;
5710  return this;
5711  }
5712 
5714  public ConfigBuilder withPushJoinCondition(boolean pushJoinCondition) {
5715  return withRelBuilderConfigTransform(Util.andThen(relBuilderConfigTransform,
5716  c -> c.withPushJoinCondition(pushJoinCondition)));
5717  }
5718 
5719  @Deprecated // to be removed before 2.0
5720  public ConfigBuilder withInSubqueryThreshold(int inSubQueryThreshold) {
5721  return withInSubQueryThreshold(inSubQueryThreshold);
5722  }
5723 
5724  public ConfigBuilder withInSubQueryThreshold(int inSubQueryThreshold) {
5725  this.inSubQueryThreshold = inSubQueryThreshold;
5726  return this;
5727  }
5728 
5729  public ConfigBuilder withRelBuilderConfigTransform(
5730  UnaryOperator<RelBuilder.Config> relBuilderConfigTransform) {
5731  this.relBuilderConfigTransform = relBuilderConfigTransform;
5732  return this;
5733  }
5734 
5735  public ConfigBuilder withRelBuilderFactory(RelBuilderFactory relBuilderFactory) {
5736  this.relBuilderFactory = relBuilderFactory;
5737  return this;
5738  }
5739 
5740  public ConfigBuilder withHintStrategyTable(HintStrategyTable hintStrategyTable) {
5741  this.hintStrategyTable = hintStrategyTable;
5742  return this;
5743  }
5744 
5746  public Config build() {
5747  return new ConfigImpl(decorrelationEnabled,
5748  trimUnusedFields,
5749  createValuesRel,
5750  explain,
5751  expand,
5752  pushdownJoinCondition,
5753  expandPredicate,
5754  inSubQueryThreshold,
5755  relBuilderConfigTransform,
5756  relBuilderFactory,
5757  hintStrategyTable);
5758  }
5759  }
5760 
5765  private static class ConfigImpl implements Config {
5766  private final boolean decorrelationEnabled;
5767  private final boolean trimUnusedFields;
5768  private final boolean createValuesRel;
5769  private final boolean explain;
5770  private final boolean expand;
5771  private final int inSubQueryThreshold;
5772  private final UnaryOperator<RelBuilder.Config> relBuilderConfigTransform;
5773  private final RelBuilderFactory relBuilderFactory;
5774  private final HintStrategyTable hintStrategyTable;
5775 
5776  private final BiPredicate<SqlNode, SqlNode> expandPredicate;
5777 
5778  // MAT 08 Jab 2021 Omnisci code
5779  private class DefaultExpandPredicate implements BiPredicate<SqlNode, SqlNode> {
5780  @Override
5781  public boolean test(SqlNode t, SqlNode u) {
5782  return expand;
5783  }
5784  }
5785 
5786  private BiPredicate<SqlNode, Join> pushdownJoinCondition =
5787  new BiPredicate<SqlNode, Join>() {
5788  public boolean test(SqlNode t, Join u) {
5789  return true;
5790  };
5791  };
5792  // MAT 08 Jan 2021 OmniSci code ends
5793 
5794  private ConfigImpl(boolean decorrelationEnabled,
5795  boolean trimUnusedFields,
5796  boolean createValuesRel,
5797  boolean explain,
5798  boolean expand,
5799  // MAT 08 Jan 2021 OmniSci code
5800  BiPredicate<SqlNode, Join> pushdownJoinCondition,
5801  BiPredicate<SqlNode, SqlNode> expandPredicate,
5802  // MAT 08 Jan 2021 Omnisci code ends
5803  int inSubQueryThreshold,
5804  UnaryOperator<RelBuilder.Config> relBuilderConfigTransform,
5805  RelBuilderFactory relBuilderFactory,
5806  HintStrategyTable hintStrategyTable) {
5807  this.decorrelationEnabled = decorrelationEnabled;
5808  this.trimUnusedFields = trimUnusedFields;
5809  this.createValuesRel = createValuesRel;
5810  // MAT 08 Jan 2021 OmniSci code
5811  this.explain = explain;
5812  this.expand = expand;
5813  // MAT 08 Jan 2021 OmniSci code ends
5814  this.inSubQueryThreshold = inSubQueryThreshold;
5815  this.relBuilderConfigTransform = relBuilderConfigTransform;
5816  this.relBuilderFactory = relBuilderFactory;
5817  this.hintStrategyTable = hintStrategyTable;
5818  // MAT 08 Jan 2021 OmniSci code
5819  if (null == expandPredicate) {
5820  expandPredicate = new DefaultExpandPredicate();
5821  }
5822  this.expandPredicate = expandPredicate;
5823 
5824  if (null != pushdownJoinCondition) {
5825  this.pushdownJoinCondition = pushdownJoinCondition;
5826  }
5827  // MAT 08 Jan 2021 OmniSci code ends
5828  }
5829 
5830  // TODO MAT 08 Jan 2021 add our added types to this equals
5831  @Override
5832  public boolean equals(Object obj) {
5833  return this == obj
5834  || obj instanceof ConfigImpl
5835  && decorrelationEnabled == ((ConfigImpl) obj).decorrelationEnabled
5836  && trimUnusedFields == ((ConfigImpl) obj).trimUnusedFields
5837  && createValuesRel == ((ConfigImpl) obj).createValuesRel
5838  && explain == ((ConfigImpl) obj).explain
5839  && expand == ((ConfigImpl) obj).expand
5840  && inSubQueryThreshold == ((ConfigImpl) obj).inSubQueryThreshold
5841  && relBuilderFactory == ((ConfigImpl) obj).relBuilderFactory
5842  && hintStrategyTable == ((ConfigImpl) obj).hintStrategyTable;
5843  }
5844 
5845  @Override
5846  public int hashCode() {
5847  return Objects.hash(decorrelationEnabled,
5848  trimUnusedFields,
5849  createValuesRel,
5850  explain,
5851  expand,
5852  inSubQueryThreshold,
5853  relBuilderFactory,
5854  hintStrategyTable);
5855  }
5856 
5857  public boolean isDecorrelationEnabled() {
5858  return decorrelationEnabled;
5859  }
5860 
5861  public boolean isTrimUnusedFields() {
5862  return trimUnusedFields;
5863  }
5864 
5865  public boolean isCreateValuesRel() {
5866  return createValuesRel;
5867  }
5868 
5869  public boolean isExplain() {
5870  return explain;
5871  }
5872 
5873  public boolean isExpand() {
5874  return expand;
5875  }
5876 
5877  public int getInSubQueryThreshold() {
5878  return inSubQueryThreshold;
5879  }
5880 
5881  public UnaryOperator<RelBuilder.Config> getRelBuilderConfigTransform() {
5882  return relBuilderConfigTransform;
5883  }
5884 
5885  public RelBuilderFactory getRelBuilderFactory() {
5886  return relBuilderFactory;
5887  }
5888 
5889  public HintStrategyTable getHintStrategyTable() {
5890  return hintStrategyTable;
5891  }
5892 
5893  // MAT 08 Jan 2021 OmniSci code
5894  public BiPredicate<SqlNode, Join> getPushdownJoinCondition() {
5895  return pushdownJoinCondition;
5896  }
5897 
5898  public BiPredicate<SqlNode, SqlNode> getExpandPredicate() {
5899  return expandPredicate;
5900  }
5901  // MAT 08 Jan 2021 OmniSci code ends
5902  }
5903 }
RelRoot convertWith(SqlWith with, boolean top)
RelOptTable.ToRelContext createToRelContext(List< RelHint > hints)
SqlQuantifyOperator negate(SqlQuantifyOperator operator)
JoinType
Definition: sqldefs.h:108
std::string toString(const ExtArgumentType &sig_type)
void setDynamicParamCountInExplain(int explainParamCount)
static SqlNode pushDownNotForIn(SqlValidatorScope scope, SqlNode sqlNode)
void extraSelectItems(Blackboard bb, SqlSelect select, List< RexNode > exprList, List< String > nameList, Collection< String > aliasList, List< SqlMonotonicity > columnMonotonicityList)
void substituteSubQuery(Blackboard bb, SubQuery subQuery)
void convertCollectionTable(Blackboard bb, SqlCall call)
RexNode convertSubQuery(SqlCall subQuery, SqlToRelConverter parentConverter, boolean isExists, boolean isExplain)
void checkConvertedType(SqlNode query, RelNode result)
RexNode translateIn(RelOptUtil.Logic logic, RelNode root, final RexNode rex)
RelNode convertCursor(Blackboard bb, SubQuery subQuery)
RelNode convertQueryOrInList(Blackboard bb, SqlNode seek, RelDataType targetRowType)
std::string join(T const &container, std::string const &delim)
RexNode castNullLiteralIfNeeded(RexNode node, RelDataType type)
RexNode ensureSqlType(RelDataType type, RexNode node)
void afterTableFunction(SqlToRelConverter.Blackboard bb, SqlCall call, LogicalTableFunctionScan callRel)
RelNode toRel(final RelOptTable table, final List< RelHint > hints)
SqlToRelConverter(RelOptTable.ViewExpander viewExpander, SqlValidator validator, Prepare.CatalogReader catalogReader, RelOptCluster cluster, SqlRexConvertletTable convertletTable)
void convertValuesImpl(Blackboard bb, SqlCall values, RelDataType targetRowType)
void convertFrom(Blackboard bb, SqlNode from)
InitializerExpressionFactory getInitializerFactory(SqlValidatorTable validatorTable)
String deriveAlias(final SqlNode node, Collection< String > aliases, final int ordinal)
FILE * create(const std::string &basePath, const int fileId, const size_t pageSize, const size_t numPages)
Definition: File.cpp:40
RelNode decorrelate(SqlNode query, RelNode rootRel)
void setRoot(List< RelNode > inputs, RelNode root, boolean hasSystemFields)
RexDynamicParam convertDynamicParam(final SqlDynamicParam dynamicParam)
RelNode convertRowValues(Blackboard bb, SqlNode rowList, Collection< SqlNode > rows, boolean allowLiteralsOnly, RelDataType targetRowType)
RexNode convertInToOr(final Blackboard bb, final List< RexNode > leftKeys, SqlNodeList valuesList, SqlInOperator op)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
final Map< CorrelationId, DeferredLookup > mapCorrelToDeferred
RelOptUtil.Exists convertExists(SqlNode seek, RelOptUtil.SubQueryType subQueryType, RelOptUtil.Logic logic, boolean notIn, RelDataType targetDataType)
RelNode createSource(RelOptTable targetTable, RelNode source, ModifiableView modifiableView, RelDataType delegateRowType)
RelNode convertRowConstructor(Blackboard bb, SqlCall rowConstructor)
RelRoot convertQueryRecursive(SqlNode query, boolean top, RelDataType targetRowType)
SqlToRelConverter(RelOptTable.ViewExpander viewExpander, SqlValidator validator, Prepare.CatalogReader catalogReader, RelOptPlanner planner, RexBuilder rexBuilder, SqlRexConvertletTable convertletTable)
final List< SqlDynamicParam > dynamicParamSqlNodes
final Map< SqlNode, RexNode > mapConvertedNonCorrSubqs
RexLiteral convertLiteralInValuesList(SqlNode sqlNode, Blackboard bb, RelDataType rowType, int iField)
void convertUnnest(Blackboard bb, SqlCall call, List< String > fieldNames)
void distinctify(Blackboard bb, boolean checkForDupExprs)
RelNode createModify(RelOptTable targetTable, RelNode source)
RelNode trimUnusedFields(boolean ordered, RelNode rootRel)
RexNode convertUsing(SqlValidatorNamespace leftNamespace, SqlValidatorNamespace rightNamespace, List< String > nameList)
void convertSelectImpl(final Blackboard bb, SqlSelect select)
void addConvertedNonCorrSubqs(Map< SqlNode, RexNode > alreadyConvertedNonCorrSubqs)
RexNode convertJoinCondition(Blackboard bb, SqlValidatorNamespace leftNamespace, SqlValidatorNamespace rightNamespace, SqlNode condition, JoinConditionType conditionType, RelNode leftRel, RelNode rightRel)
void collectInsertTargets(SqlInsert call, final RexNode sourceRef, final List< String > targetColumnNames, List< RexNode > columnExprs)
void replaceSubQueries(final Blackboard bb, final SqlNode expr, RelOptUtil.Logic logic)
static< T > T unwrap(Object o, Class< T > clazz)
size_t indexOf(std::vector< T > &vec, T val)
SqlToRelConverter(RelOptTable.ViewExpander viewExpander, SqlValidator validator, Prepare.CatalogReader catalogReader, RelOptCluster cluster, SqlRexConvertletTable convertletTable, Config config)
RelNode flattenTypes(RelNode rootRel, boolean restructure)
RelNode createAggregate(Blackboard bb, ImmutableBitSet groupSet, ImmutableList< ImmutableBitSet > groupSets, List< AggregateCall > aggCalls)
CorrelationUse getCorrelationUse(Blackboard bb, final RelNode r0)
RelNode convertValues(SqlCall values, RelDataType targetRowType)
void convertAgg(Blackboard bb, SqlSelect select, List< SqlNode > orderExprList)
RexNode convertOver(Blackboard bb, SqlNode node)
final void createAggImpl(Blackboard bb, final AggConverter aggConverter, SqlNodeList selectList, SqlNodeList groupList, SqlNode having, List< SqlNode > orderExprList)
Blackboard createInsertBlackboard(RelOptTable targetTable, RexNode sourceRef, List< String > targetColumnNames)
void convertIdentifier(Blackboard bb, SqlIdentifier id, SqlNodeList extendedColumns, SqlNodeList tableHints)
RelNode convertMultisets(final List< SqlNode > operands, Blackboard bb)
static boolean containsNullLiteral(SqlNodeList valueList)
void gatherOrderExprs(Blackboard bb, SqlSelect select, SqlNodeList orderList, List< SqlNode > extraOrderExprs, List< RelFieldCollation > collationList)
RexNode convertExtendedExpression(SqlNode node, Blackboard bb)
void convertMatchRecognize(Blackboard bb, SqlCall call)
void convertWhere(final Blackboard bb, final SqlNode where)
RexNode convertExpression(SqlNode node, Map< String, RexNode > nameToNodeMap)
Blackboard(SqlValidatorScope scope, Map< String, RexNode > nameToNodeMap, boolean top)
RelNode rewriteAggregateWithGroupId(Blackboard bb, AggregatingSelectScope.Resolved r, AggConverter converter)
static SqlNode reg(SqlValidatorScope scope, SqlNode e)
boolean convertNonCorrelatedSubQuery(SubQuery subQuery, Blackboard bb, RelNode converted, boolean isExists)
void findSubQueries(Blackboard bb, SqlNode node, RelOptUtil.Logic logic, boolean registerOnlyScalarSubQueries)
Pair< RexNode, Map< String, Integer > > lookupExp(SqlQualified qualified)
boolean isSubQueryNonCorrelated(RelNode subq, Blackboard bb)
RexNode convertIdentifier(Blackboard bb, SqlIdentifier identifier)
RelNode createJoin(Blackboard bb, RelNode leftRel, RelNode rightRel, RexNode joinCond, JoinRelType joinType)
RexAccessShuttle(RexBuilder builder, RexCorrelVariable rexCorrel)
RelNode convertColumnList(final SqlInsert call, RelNode source)
void convertFrom(Blackboard bb, SqlNode from, List< String > fieldNames)
void convertTemporalTable(Blackboard bb, SqlCall call)
static boolean desc(RelFieldCollation.Direction direction)
string name
Definition: setup.py:44
Set< RelColumnMapping > getColumnMappings(SqlOperator op)
Blackboard createBlackboard(SqlValidatorScope scope, Map< String, RexNode > nameToNodeMap, boolean top)
RelRoot convertQuery(SqlNode query, final boolean needsValidation, final boolean top)
RelFieldCollation convertOrderItem(SqlSelect select, SqlNode orderItem, List< SqlNode > extraExprs, RelFieldCollation.Direction direction, RelFieldCollation.NullDirection nullDirection)
final Map< RelNode, Map< Integer, Integer > > mapRootRelToFieldProjection
RelNode convertToSingleValueSubq(SqlNode query, RelNode plan)
static JoinRelType convertJoinType(JoinType joinType)
void setSubQueryConverter(SubQueryConverter converter)
RexNode adjustInputRef(Blackboard bb, RexInputRef inputRef)
void convertOrder(SqlSelect select, Blackboard bb, RelCollation collation, List< SqlNode > orderExprList, SqlNode offset, SqlNode fetch)
void convertSelectList(Blackboard bb, SqlSelect select, List< SqlNode > orderList)
RelNode convertSelect(SqlSelect select, boolean top)