OmniSciDB  fe05a0c208
 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,
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,
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,
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(r);
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,
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  RelNode node = originalJoin;
2496  // MAT 08 Jan 2021 end of OmniSci Code
2497 
2498  // If join conditions are pushed down, update the leaves.
2499  if (node instanceof Project) {
2500  final Join newJoin = (Join) node.getInputs().get(0);
2501  if (leaves.containsKey(leftRel)) {
2502  leaves.put(newJoin.getLeft(), leaves.get(leftRel));
2503  }
2504  if (leaves.containsKey(rightRel)) {
2505  leaves.put(newJoin.getRight(), leaves.get(rightRel));
2506  }
2507  }
2508  return node;
2509  }
2510 
2511  private CorrelationUse getCorrelationUse(Blackboard bb, final RelNode r0) {
2512  final Set<CorrelationId> correlatedVariables = RelOptUtil.getVariablesUsed(r0);
2513  if (correlatedVariables.isEmpty()) {
2514  return null;
2515  }
2516  final ImmutableBitSet.Builder requiredColumns = ImmutableBitSet.builder();
2517  final List<CorrelationId> correlNames = new ArrayList<>();
2518 
2519  // All correlations must refer the same namespace since correlation
2520  // produces exactly one correlation source.
2521  // The same source might be referenced by different variables since
2522  // DeferredLookups are not de-duplicated at create time.
2523  SqlValidatorNamespace prevNs = null;
2524 
2525  for (CorrelationId correlName : correlatedVariables) {
2526  DeferredLookup lookup = mapCorrelToDeferred.get(correlName);
2527  RexFieldAccess fieldAccess = lookup.getFieldAccess(correlName);
2528  String originalRelName = lookup.getOriginalRelName();
2529  String originalFieldName = fieldAccess.getField().getName();
2530 
2531  final SqlNameMatcher nameMatcher =
2532  bb.getValidator().getCatalogReader().nameMatcher();
2533  final SqlValidatorScope.ResolvedImpl resolved =
2534  new SqlValidatorScope.ResolvedImpl();
2535  lookup.bb.scope.resolve(
2536  ImmutableList.of(originalRelName), nameMatcher, false, resolved);
2537  assert resolved.count() == 1;
2538  final SqlValidatorScope.Resolve resolve = resolved.only();
2539  final SqlValidatorNamespace foundNs = resolve.namespace;
2540  final RelDataType rowType = resolve.rowType();
2541  final int childNamespaceIndex = resolve.path.steps().get(0).i;
2542  final SqlValidatorScope ancestorScope = resolve.scope;
2543  boolean correlInCurrentScope = bb.scope.isWithin(ancestorScope);
2544 
2545  if (!correlInCurrentScope) {
2546  continue;
2547  }
2548 
2549  if (prevNs == null) {
2550  prevNs = foundNs;
2551  } else {
2552  assert prevNs
2553  == foundNs : "All correlation variables should resolve"
2554  + " to the same namespace."
2555  + " Prev ns="
2556  + prevNs
2557  + ", new ns="
2558  + foundNs;
2559  }
2560 
2561  int namespaceOffset = 0;
2562  if (childNamespaceIndex > 0) {
2563  // If not the first child, need to figure out the width
2564  // of output types from all the preceding namespaces
2565  assert ancestorScope instanceof ListScope;
2566  List<SqlValidatorNamespace> children = ((ListScope) ancestorScope).getChildren();
2567 
2568  for (int i = 0; i < childNamespaceIndex; i++) {
2569  SqlValidatorNamespace child = children.get(i);
2570  namespaceOffset += child.getRowType().getFieldCount();
2571  }
2572  }
2573 
2574  RexFieldAccess topLevelFieldAccess = fieldAccess;
2575  while (topLevelFieldAccess.getReferenceExpr() instanceof RexFieldAccess) {
2576  topLevelFieldAccess = (RexFieldAccess) topLevelFieldAccess.getReferenceExpr();
2577  }
2578  final RelDataTypeField field = rowType.getFieldList().get(
2579  topLevelFieldAccess.getField().getIndex() - namespaceOffset);
2580  int pos = namespaceOffset + field.getIndex();
2581 
2582  assert field.getType() == topLevelFieldAccess.getField().getType();
2583 
2584  assert pos != -1;
2585 
2586  if (bb.mapRootRelToFieldProjection.containsKey(bb.root)) {
2587  // bb.root is an aggregate and only projects group by
2588  // keys.
2589  Map<Integer, Integer> exprProjection =
2590  bb.mapRootRelToFieldProjection.get(bb.root);
2591 
2592  // sub-query can reference group by keys projected from
2593  // the root of the outer relation.
2594  if (exprProjection.containsKey(pos)) {
2595  pos = exprProjection.get(pos);
2596  } else {
2597  // correl not grouped
2598  throw new AssertionError("Identifier '" + originalRelName + "."
2599  + originalFieldName + "' is not a group expr");
2600  }
2601  }
2602 
2603  requiredColumns.set(pos);
2604  correlNames.add(correlName);
2605  }
2606 
2607  if (correlNames.isEmpty()) {
2608  // None of the correlating variables originated in this scope.
2609  return null;
2610  }
2611 
2612  RelNode r = r0;
2613  if (correlNames.size() > 1) {
2614  // The same table was referenced more than once.
2615  // So we deduplicate.
2616  r = DeduplicateCorrelateVariables.go(
2617  rexBuilder, correlNames.get(0), Util.skip(correlNames), r0);
2618  // Add new node to leaves.
2619  leaves.put(r, r.getRowType().getFieldCount());
2620  }
2621  return new CorrelationUse(correlNames.get(0), requiredColumns.build(), r);
2622  }
2623 
2634  private boolean isSubQueryNonCorrelated(RelNode subq, Blackboard bb) {
2635  Set<CorrelationId> correlatedVariables = RelOptUtil.getVariablesUsed(subq);
2636  for (CorrelationId correlName : correlatedVariables) {
2637  DeferredLookup lookup = mapCorrelToDeferred.get(correlName);
2638  String originalRelName = lookup.getOriginalRelName();
2639 
2640  final SqlNameMatcher nameMatcher =
2641  lookup.bb.scope.getValidator().getCatalogReader().nameMatcher();
2642  final SqlValidatorScope.ResolvedImpl resolved =
2643  new SqlValidatorScope.ResolvedImpl();
2644  lookup.bb.scope.resolve(
2645  ImmutableList.of(originalRelName), nameMatcher, false, resolved);
2646 
2647  SqlValidatorScope ancestorScope = resolved.only().scope;
2648 
2649  // If the correlated reference is in a scope that's "above" the
2650  // sub-query, then this is a correlated sub-query.
2651  SqlValidatorScope parentScope = bb.scope;
2652  do {
2653  if (ancestorScope == parentScope) {
2654  return false;
2655  }
2656  if (parentScope instanceof DelegatingScope) {
2657  parentScope = ((DelegatingScope) parentScope).getParent();
2658  } else {
2659  break;
2660  }
2661  } while (parentScope != null);
2662  }
2663  return true;
2664  }
2665 
2671  protected List<RelDataTypeField> getSystemFields() {
2672  return Collections.emptyList();
2673  }
2674 
2675  private RexNode convertJoinCondition(Blackboard bb,
2676  SqlValidatorNamespace leftNamespace,
2677  SqlValidatorNamespace rightNamespace,
2678  SqlNode condition,
2679  JoinConditionType conditionType,
2680  RelNode leftRel,
2681  RelNode rightRel) {
2682  if (condition == null) {
2683  return rexBuilder.makeLiteral(true);
2684  }
2685  bb.setRoot(ImmutableList.of(leftRel, rightRel));
2686  replaceSubQueries(bb, condition, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
2687  switch (conditionType) {
2688  case ON:
2689  bb.setRoot(ImmutableList.of(leftRel, rightRel));
2690  return bb.convertExpression(condition);
2691  case USING:
2692  final SqlNodeList list = (SqlNodeList) condition;
2693  final List<String> nameList = new ArrayList<>();
2694  for (SqlNode columnName : list) {
2695  final SqlIdentifier id = (SqlIdentifier) columnName;
2696  String name = id.getSimple();
2697  nameList.add(name);
2698  }
2699  return convertUsing(leftNamespace, rightNamespace, nameList);
2700  default:
2701  throw Util.unexpected(conditionType);
2702  }
2703  }
2704 
2716  private RexNode convertUsing(SqlValidatorNamespace leftNamespace,
2717  SqlValidatorNamespace rightNamespace,
2718  List<String> nameList) {
2719  final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
2720  final List<RexNode> list = new ArrayList<>();
2721  for (String name : nameList) {
2722  List<RexNode> operands = new ArrayList<>();
2723  int offset = 0;
2724  for (SqlValidatorNamespace n : ImmutableList.of(leftNamespace, rightNamespace)) {
2725  final RelDataType rowType = n.getRowType();
2726  final RelDataTypeField field = nameMatcher.field(rowType, name);
2727  operands.add(rexBuilder.makeInputRef(field.getType(), offset + field.getIndex()));
2728  offset += rowType.getFieldList().size();
2729  }
2730  list.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, operands));
2731  }
2732  return RexUtil.composeConjunction(rexBuilder, list);
2733  }
2734 
2735  private static JoinRelType convertJoinType(JoinType joinType) {
2736  switch (joinType) {
2737  case COMMA:
2738  case INNER:
2739  case CROSS:
2740  return JoinRelType.INNER;
2741  case FULL:
2742  return JoinRelType.FULL;
2743  case LEFT:
2744  return JoinRelType.LEFT;
2745  case RIGHT:
2746  return JoinRelType.RIGHT;
2747  default:
2748  throw Util.unexpected(joinType);
2749  }
2750  }
2751 
2765  protected void convertAgg(
2766  Blackboard bb, SqlSelect select, List<SqlNode> orderExprList) {
2767  assert bb.root != null : "precondition: child != null";
2768  SqlNodeList groupList = select.getGroup();
2769  SqlNodeList selectList = select.getSelectList();
2770  SqlNode having = select.getHaving();
2771 
2772  final AggConverter aggConverter = new AggConverter(bb, select);
2773  createAggImpl(bb, aggConverter, selectList, groupList, having, orderExprList);
2774  }
2775 
2776  protected final void createAggImpl(Blackboard bb,
2777  final AggConverter aggConverter,
2778  SqlNodeList selectList,
2779  SqlNodeList groupList,
2780  SqlNode having,
2781  List<SqlNode> orderExprList) {
2782  // Find aggregate functions in SELECT and HAVING clause
2783  final AggregateFinder aggregateFinder = new AggregateFinder();
2784  selectList.accept(aggregateFinder);
2785  if (having != null) {
2786  having.accept(aggregateFinder);
2787  }
2788 
2789  // first replace the sub-queries inside the aggregates
2790  // because they will provide input rows to the aggregates.
2791  replaceSubQueries(bb, aggregateFinder.list, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2792 
2793  // also replace sub-queries inside filters in the aggregates
2795  bb, aggregateFinder.filterList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2796 
2797  // also replace sub-queries inside ordering spec in the aggregates
2798  replaceSubQueries(bb, aggregateFinder.orderList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2799 
2800  // If group-by clause is missing, pretend that it has zero elements.
2801  if (groupList == null) {
2802  groupList = SqlNodeList.EMPTY;
2803  }
2804 
2805  replaceSubQueries(bb, groupList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2806 
2807  // register the group exprs
2808 
2809  // build a map to remember the projections from the top scope to the
2810  // output of the current root.
2811  //
2812  // Calcite allows expressions, not just column references in
2813  // group by list. This is not SQL 2003 compliant, but hey.
2814 
2815  final AggregatingSelectScope scope = aggConverter.aggregatingSelectScope;
2816  final AggregatingSelectScope.Resolved r = scope.resolved.get();
2817  for (SqlNode groupExpr : r.groupExprList) {
2818  aggConverter.addGroupExpr(groupExpr);
2819  }
2820 
2821  final RexNode havingExpr;
2822  final List<Pair<RexNode, String>> projects = new ArrayList<>();
2823 
2824  try {
2825  Preconditions.checkArgument(bb.agg == null, "already in agg mode");
2826  bb.agg = aggConverter;
2827 
2828  // convert the select and having expressions, so that the
2829  // agg converter knows which aggregations are required
2830 
2831  selectList.accept(aggConverter);
2832  // Assert we don't have dangling items left in the stack
2833  assert !aggConverter.inOver;
2834  for (SqlNode expr : orderExprList) {
2835  expr.accept(aggConverter);
2836  assert !aggConverter.inOver;
2837  }
2838  if (having != null) {
2839  having.accept(aggConverter);
2840  assert !aggConverter.inOver;
2841  }
2842 
2843  // compute inputs to the aggregator
2844  List<Pair<RexNode, String>> preExprs = aggConverter.getPreExprs();
2845 
2846  if (preExprs.size() == 0) {
2847  // Special case for COUNT(*), where we can end up with no inputs
2848  // at all. The rest of the system doesn't like 0-tuples, so we
2849  // select a dummy constant here.
2850  final RexNode zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO);
2851  preExprs = ImmutableList.of(Pair.of(zero, (String) null));
2852  }
2853 
2854  final RelNode inputRel = bb.root;
2855 
2856  // Project the expressions required by agg and having.
2857  bb.setRoot(relBuilder.push(inputRel)
2858  .projectNamed(Pair.left(preExprs), Pair.right(preExprs), false)
2859  .build(),
2860  false);
2861  bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
2862 
2863  // REVIEW jvs 31-Oct-2007: doesn't the declaration of
2864  // monotonicity here assume sort-based aggregation at
2865  // the physical level?
2866 
2867  // Tell bb which of group columns are sorted.
2868  bb.columnMonotonicities.clear();
2869  for (SqlNode groupItem : groupList) {
2870  bb.columnMonotonicities.add(bb.scope.getMonotonicity(groupItem));
2871  }
2872 
2873  final RelNode relNode = aggConverter.containsGroupId()
2874  ? rewriteAggregateWithGroupId(bb, r, aggConverter)
2875  : createAggregate(bb, r.groupSet, r.groupSets, aggConverter.getAggCalls());
2876 
2877  bb.setRoot(relNode, false);
2878  bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
2879 
2880  // Replace sub-queries in having here and modify having to use
2881  // the replaced expressions
2882  if (having != null) {
2883  SqlNode newHaving = pushDownNotForIn(bb.scope, having);
2884  replaceSubQueries(bb, newHaving, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
2885  havingExpr = bb.convertExpression(newHaving);
2886  } else {
2887  havingExpr = relBuilder.literal(true);
2888  }
2889 
2890  // Now convert the other sub-queries in the select list.
2891  // This needs to be done separately from the sub-query inside
2892  // any aggregate in the select list, and after the aggregate rel
2893  // is allocated.
2894  replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2895 
2896  // Now sub-queries in the entire select list have been converted.
2897  // Convert the select expressions to get the final list to be
2898  // projected.
2899  int k = 0;
2900 
2901  // For select expressions, use the field names previously assigned
2902  // by the validator. If we derive afresh, we might generate names
2903  // like "EXPR$2" that don't match the names generated by the
2904  // validator. This is especially the case when there are system
2905  // fields; system fields appear in the relnode's rowtype but do not
2906  // (yet) appear in the validator type.
2907  final SelectScope selectScope = SqlValidatorUtil.getEnclosingSelectScope(bb.scope);
2908  assert selectScope != null;
2909  final SqlValidatorNamespace selectNamespace =
2910  validator.getNamespace(selectScope.getNode());
2911  final List<String> names = selectNamespace.getRowType().getFieldNames();
2912  int sysFieldCount = selectList.size() - names.size();
2913  for (SqlNode expr : selectList) {
2914  projects.add(Pair.of(bb.convertExpression(expr),
2915  k < sysFieldCount ? validator.deriveAlias(expr, k++)
2916  : names.get(k++ - sysFieldCount)));
2917  }
2918 
2919  for (SqlNode expr : orderExprList) {
2920  projects.add(
2921  Pair.of(bb.convertExpression(expr), validator.deriveAlias(expr, k++)));
2922  }
2923  } finally {
2924  bb.agg = null;
2925  }
2926 
2927  // implement HAVING (we have already checked that it is non-trivial)
2928  relBuilder.push(bb.root);
2929  if (havingExpr != null) {
2930  relBuilder.filter(havingExpr);
2931  }
2932 
2933  // implement the SELECT list
2934  relBuilder.project(Pair.left(projects), Pair.right(projects))
2935  .rename(Pair.right(projects));
2936  bb.setRoot(relBuilder.build(), false);
2937 
2938  // Tell bb which of group columns are sorted.
2939  bb.columnMonotonicities.clear();
2940  for (SqlNode selectItem : selectList) {
2941  bb.columnMonotonicities.add(bb.scope.getMonotonicity(selectItem));
2942  }
2943  }
2944 
2959  Blackboard bb, AggregatingSelectScope.Resolved r, AggConverter converter) {
2960  final List<AggregateCall> aggregateCalls = converter.getAggCalls();
2961  final ImmutableBitSet groupSet = r.groupSet;
2962  final Map<ImmutableBitSet, Integer> groupSetCount = r.groupSetCount;
2963 
2964  final List<String> fieldNamesIfNoRewrite =
2965  createAggregate(bb, groupSet, r.groupSets, aggregateCalls)
2966  .getRowType()
2967  .getFieldNames();
2968 
2969  // If n duplicates exist for a particular grouping, the {@code GROUP_ID()}
2970  // function produces values in the range 0 to n-1. For each value,
2971  // we need to figure out the corresponding group sets.
2972  //
2973  // For example, "... GROUPING SETS (a, a, b, c, c, c, c)"
2974  // (i) The max value of the GROUP_ID() function returns is 3
2975  // (ii) GROUPING SETS (a, b, c) produces value 0,
2976  // GROUPING SETS (a, c) produces value 1,
2977  // GROUPING SETS (c) produces value 2
2978  // GROUPING SETS (c) produces value 3
2979  final Map<Integer, Set<ImmutableBitSet>> groupIdToGroupSets = new HashMap<>();
2980  int maxGroupId = 0;
2981  for (Map.Entry<ImmutableBitSet, Integer> entry : groupSetCount.entrySet()) {
2982  int groupId = entry.getValue() - 1;
2983  if (groupId > maxGroupId) {
2984  maxGroupId = groupId;
2985  }
2986  for (int i = 0; i <= groupId; i++) {
2987  groupIdToGroupSets
2988  .computeIfAbsent(i, k -> Sets.newTreeSet(ImmutableBitSet.COMPARATOR))
2989  .add(entry.getKey());
2990  }
2991  }
2992 
2993  // AggregateCall list without GROUP_ID function
2994  final List<AggregateCall> aggregateCallsWithoutGroupId = new ArrayList<>();
2995  for (AggregateCall aggregateCall : aggregateCalls) {
2996  if (aggregateCall.getAggregation().kind != SqlKind.GROUP_ID) {
2997  aggregateCallsWithoutGroupId.add(aggregateCall);
2998  }
2999  }
3000  final List<RelNode> projects = new ArrayList<>();
3001  // For each group id value , we first construct an Aggregate without
3002  // GROUP_ID() function call, and then create a Project node on top of it.
3003  // The Project adds literal value for group id in right position.
3004  for (int groupId = 0; groupId <= maxGroupId; groupId++) {
3005  // Create the Aggregate node without GROUP_ID() call
3006  final ImmutableList<ImmutableBitSet> groupSets =
3007  ImmutableList.copyOf(groupIdToGroupSets.get(groupId));
3008  final RelNode aggregate =
3009  createAggregate(bb, groupSet, groupSets, aggregateCallsWithoutGroupId);
3010 
3011  // RexLiteral for each GROUP_ID, note the type should be BIGINT
3012  final RelDataType groupIdType = typeFactory.createSqlType(SqlTypeName.BIGINT);
3013  final RexNode groupIdLiteral =
3014  rexBuilder.makeExactLiteral(BigDecimal.valueOf(groupId), groupIdType);
3015 
3016  relBuilder.push(aggregate);
3017  final List<RexNode> selectList = new ArrayList<>();
3018  final int groupExprLength = r.groupExprList.size();
3019  // Project fields in group by expressions
3020  for (int i = 0; i < groupExprLength; i++) {
3021  selectList.add(relBuilder.field(i));
3022  }
3023  // Project fields in aggregate calls
3024  int groupIdCount = 0;
3025  for (int i = 0; i < aggregateCalls.size(); i++) {
3026  if (aggregateCalls.get(i).getAggregation().kind == SqlKind.GROUP_ID) {
3027  selectList.add(groupIdLiteral);
3028  groupIdCount++;
3029  } else {
3030  int ordinal = groupExprLength + i - groupIdCount;
3031  selectList.add(relBuilder.field(ordinal));
3032  }
3033  }
3034  final RelNode project =
3035  relBuilder.project(selectList, fieldNamesIfNoRewrite).build();
3036  projects.add(project);
3037  }
3038  // Skip to create Union when there is only one child, i.e., no duplicate group
3039  // set.
3040  if (projects.size() == 1) {
3041  return projects.get(0);
3042  }
3043  return LogicalUnion.create(projects, true);
3044  }
3045 
3065  protected RelNode createAggregate(Blackboard bb,
3066  ImmutableBitSet groupSet,
3067  ImmutableList<ImmutableBitSet> groupSets,
3068  List<AggregateCall> aggCalls) {
3069  return LogicalAggregate.create(
3070  bb.root, ImmutableList.of(), groupSet, groupSets, aggCalls);
3071  }
3072 
3073  public RexDynamicParam convertDynamicParam(final SqlDynamicParam dynamicParam) {
3074  // REVIEW jvs 8-Jan-2005: dynamic params may be encountered out of
3075  // order. Should probably cross-check with the count from the parser
3076  // at the end and make sure they all got filled in. Why doesn't List
3077  // have a resize() method?!? Make this a utility.
3078  while (dynamicParam.getIndex() >= dynamicParamSqlNodes.size()) {
3079  dynamicParamSqlNodes.add(null);
3080  }
3081 
3082  dynamicParamSqlNodes.set(dynamicParam.getIndex(), dynamicParam);
3083  return rexBuilder.makeDynamicParam(
3084  getDynamicParamType(dynamicParam.getIndex()), dynamicParam.getIndex());
3085  }
3086 
3101  protected void gatherOrderExprs(Blackboard bb,
3102  SqlSelect select,
3103  SqlNodeList orderList,
3104  List<SqlNode> extraOrderExprs,
3105  List<RelFieldCollation> collationList) {
3106  // TODO: add validation rules to SqlValidator also
3107  assert bb.root != null : "precondition: child != null";
3108  assert select != null;
3109  if (orderList == null) {
3110  return;
3111  }
3112 
3113  if (!bb.top) {
3114  SqlNode offset = select.getOffset();
3115  if ((offset == null
3116  || (offset instanceof SqlLiteral
3117  && ((SqlLiteral) offset)
3118  .bigDecimalValue()
3119  .equals(BigDecimal.ZERO)))
3120  && select.getFetch() == null) {
3121  return;
3122  }
3123  }
3124 
3125  for (SqlNode orderItem : orderList) {
3126  collationList.add(convertOrderItem(select,
3127  orderItem,
3128  extraOrderExprs,
3129  RelFieldCollation.Direction.ASCENDING,
3130  RelFieldCollation.NullDirection.UNSPECIFIED));
3131  }
3132  }
3133 
3134  protected RelFieldCollation convertOrderItem(SqlSelect select,
3135  SqlNode orderItem,
3136  List<SqlNode> extraExprs,
3137  RelFieldCollation.Direction direction,
3138  RelFieldCollation.NullDirection nullDirection) {
3139  assert select != null;
3140  // Handle DESC keyword, e.g. 'select a, b from t order by a desc'.
3141  switch (orderItem.getKind()) {
3142  case DESCENDING:
3143  return convertOrderItem(select,
3144  ((SqlCall) orderItem).operand(0),
3145  extraExprs,
3146  RelFieldCollation.Direction.DESCENDING,
3147  nullDirection);
3148  case NULLS_FIRST:
3149  return convertOrderItem(select,
3150  ((SqlCall) orderItem).operand(0),
3151  extraExprs,
3152  direction,
3153  RelFieldCollation.NullDirection.FIRST);
3154  case NULLS_LAST:
3155  return convertOrderItem(select,
3156  ((SqlCall) orderItem).operand(0),
3157  extraExprs,
3158  direction,
3159  RelFieldCollation.NullDirection.LAST);
3160  }
3161 
3162  SqlNode converted = validator.expandOrderExpr(select, orderItem);
3163 
3164  switch (nullDirection) {
3165  case UNSPECIFIED:
3166  nullDirection = validator.config().defaultNullCollation().last(desc(direction))
3167  ? RelFieldCollation.NullDirection.LAST
3168  : RelFieldCollation.NullDirection.FIRST;
3169  }
3170 
3171  // Scan the select list and order exprs for an identical expression.
3172  final SelectScope selectScope = validator.getRawSelectScope(select);
3173  int ordinal = -1;
3174  for (SqlNode selectItem : selectScope.getExpandedSelectList()) {
3175  ++ordinal;
3176  if (converted.equalsDeep(stripAs(selectItem), Litmus.IGNORE)) {
3177  return new RelFieldCollation(ordinal, direction, nullDirection);
3178  }
3179  }
3180 
3181  for (SqlNode extraExpr : extraExprs) {
3182  ++ordinal;
3183  if (converted.equalsDeep(extraExpr, Litmus.IGNORE)) {
3184  return new RelFieldCollation(ordinal, direction, nullDirection);
3185  }
3186  }
3187 
3188  // TODO: handle collation sequence
3189  // TODO: flag expressions as non-standard
3190 
3191  extraExprs.add(converted);
3192  return new RelFieldCollation(ordinal + 1, direction, nullDirection);
3193  }
3194 
3195  private static boolean desc(RelFieldCollation.Direction direction) {
3196  switch (direction) {
3197  case DESCENDING:
3198  case STRICTLY_DESCENDING:
3199  return true;
3200  default:
3201  return false;
3202  }
3203  }
3204 
3205  @Deprecated // to be removed before 2.0
3206  protected boolean enableDecorrelation() {
3207  // disable sub-query decorrelation when needed.
3208  // e.g. if outer joins are not supported.
3209  return config.isDecorrelationEnabled();
3210  }
3211 
3212  protected RelNode decorrelateQuery(RelNode rootRel) {
3213  return RelDecorrelator.decorrelateQuery(rootRel, relBuilder);
3214  }
3215 
3221  @Deprecated // to be removed before 2.0
3222  public boolean isTrimUnusedFields() {
3223  return config.isTrimUnusedFields();
3224  }
3225 
3235  protected RelRoot convertQueryRecursive(
3236  SqlNode query, boolean top, RelDataType targetRowType) {
3237  final SqlKind kind = query.getKind();
3238  switch (kind) {
3239  case SELECT:
3240  return RelRoot.of(convertSelect((SqlSelect) query, top), kind);
3241  case INSERT:
3242  return RelRoot.of(convertInsert((SqlInsert) query), kind);
3243  case DELETE:
3244  return RelRoot.of(convertDelete((SqlDelete) query), kind);
3245  case UPDATE:
3246  return RelRoot.of(convertUpdate((SqlUpdate) query), kind);
3247  case MERGE:
3248  return RelRoot.of(convertMerge((SqlMerge) query), kind);
3249  case UNION:
3250  case INTERSECT:
3251  case EXCEPT:
3252  return RelRoot.of(convertSetOp((SqlCall) query), kind);
3253  case WITH:
3254  return convertWith((SqlWith) query, top);
3255  case VALUES:
3256  return RelRoot.of(convertValues((SqlCall) query, targetRowType), kind);
3257  default:
3258  throw new AssertionError("not a query: " + query);
3259  }
3260  }
3261 
3269  protected RelNode convertSetOp(SqlCall call) {
3270  final RelNode left = convertQueryRecursive(call.operand(0), false, null).project();
3271  final RelNode right = convertQueryRecursive(call.operand(1), false, null).project();
3272  switch (call.getKind()) {
3273  case UNION:
3274  return LogicalUnion.create(ImmutableList.of(left, right), all(call));
3275 
3276  case INTERSECT:
3277  return LogicalIntersect.create(ImmutableList.of(left, right), all(call));
3278 
3279  case EXCEPT:
3280  return LogicalMinus.create(ImmutableList.of(left, right), all(call));
3281 
3282  default:
3283  throw Util.unexpected(call.getKind());
3284  }
3285  }
3286 
3287  private boolean all(SqlCall call) {
3288  return ((SqlSetOperator) call.getOperator()).isAll();
3289  }
3290 
3291  protected RelNode convertInsert(SqlInsert call) {
3292  RelOptTable targetTable = getTargetTable(call);
3293 
3294  final RelDataType targetRowType = validator.getValidatedNodeType(call);
3295  assert targetRowType != null;
3296  RelNode sourceRel =
3297  convertQueryRecursive(call.getSource(), true, targetRowType).project();
3298  RelNode massagedRel = convertColumnList(call, sourceRel);
3299 
3300  return createModify(targetTable, massagedRel);
3301  }
3302 
3304  private RelNode createModify(RelOptTable targetTable, RelNode source) {
3305  final ModifiableTable modifiableTable = targetTable.unwrap(ModifiableTable.class);
3306  if (modifiableTable != null && modifiableTable == targetTable.unwrap(Table.class)) {
3307  return modifiableTable.toModificationRel(cluster,
3308  targetTable,
3309  catalogReader,
3310  source,
3312  null,
3313  null,
3314  false);
3315  }
3316  final ModifiableView modifiableView = targetTable.unwrap(ModifiableView.class);
3317  if (modifiableView != null) {
3318  final Table delegateTable = modifiableView.getTable();
3319  final RelDataType delegateRowType = delegateTable.getRowType(typeFactory);
3320  final RelOptTable delegateRelOptTable = RelOptTableImpl.create(
3321  null, delegateRowType, delegateTable, modifiableView.getTablePath());
3322  final RelNode newSource =
3323  createSource(targetTable, source, modifiableView, delegateRowType);
3324  return createModify(delegateRelOptTable, newSource);
3325  }
3326  return LogicalTableModify.create(targetTable,
3327  catalogReader,
3328  source,
3330  null,
3331  null,
3332  false);
3333  }
3334 
3348  private RelNode createSource(RelOptTable targetTable,
3349  RelNode source,
3350  ModifiableView modifiableView,
3351  RelDataType delegateRowType) {
3352  final ImmutableIntList mapping = modifiableView.getColumnMapping();
3353  assert mapping.size() == targetTable.getRowType().getFieldCount();
3354 
3355  // For columns represented in the mapping, the expression is just a field
3356  // reference.
3357  final Map<Integer, RexNode> projectMap = new HashMap<>();
3358  final List<RexNode> filters = new ArrayList<>();
3359  for (int i = 0; i < mapping.size(); i++) {
3360  int target = mapping.get(i);
3361  if (target >= 0) {
3362  projectMap.put(target, RexInputRef.of(i, source.getRowType()));
3363  }
3364  }
3365 
3366  // For columns that are not in the mapping, and have a constraint of the
3367  // form "column = value", the expression is the literal "value".
3368  //
3369  // If a column has multiple constraints, the extra ones will become a
3370  // filter.
3371  final RexNode constraint = modifiableView.getConstraint(rexBuilder, delegateRowType);
3372  RelOptUtil.inferViewPredicates(projectMap, filters, constraint);
3373  final List<Pair<RexNode, String>> projects = new ArrayList<>();
3374  for (RelDataTypeField field : delegateRowType.getFieldList()) {
3375  RexNode node = projectMap.get(field.getIndex());
3376  if (node == null) {
3377  node = rexBuilder.makeNullLiteral(field.getType());
3378  }
3379  projects.add(Pair.of(
3380  rexBuilder.ensureType(field.getType(), node, false), field.getName()));
3381  }
3382 
3383  return relBuilder.push(source)
3384  .projectNamed(Pair.left(projects), Pair.right(projects), false)
3385  .filter(filters)
3386  .build();
3387  }
3388 
3389  private RelOptTable.ToRelContext createToRelContext(List<RelHint> hints) {
3390  return ViewExpanders.toRelContext(viewExpander, cluster, hints);
3391  }
3392 
3393  public RelNode toRel(final RelOptTable table, final List<RelHint> hints) {
3394  final RelNode scan = table.toRel(createToRelContext(hints));
3395 
3396  final InitializerExpressionFactory ief =
3397  Util.first(table.unwrap(InitializerExpressionFactory.class),
3398  NullInitializerExpressionFactory.INSTANCE);
3399 
3400  boolean hasVirtualFields = table.getRowType().getFieldList().stream().anyMatch(
3401  f -> ief.generationStrategy(table, f.getIndex()) == ColumnStrategy.VIRTUAL);
3402 
3403  if (hasVirtualFields) {
3404  final RexNode sourceRef = rexBuilder.makeRangeReference(scan);
3406  table, sourceRef, table.getRowType().getFieldNames());
3407  final List<RexNode> list = new ArrayList<>();
3408  for (RelDataTypeField f : table.getRowType().getFieldList()) {
3409  final ColumnStrategy strategy = ief.generationStrategy(table, f.getIndex());
3410  switch (strategy) {
3411  case VIRTUAL:
3412  list.add(ief.newColumnDefaultValue(table, f.getIndex(), bb));
3413  break;
3414  default:
3415  list.add(rexBuilder.makeInputRef(
3416  scan, RelOptTableImpl.realOrdinal(table, f.getIndex())));
3417  }
3418  }
3419  relBuilder.push(scan);
3420  relBuilder.project(list);
3421  final RelNode project = relBuilder.build();
3422  if (ief.postExpressionConversionHook() != null) {
3423  return ief.postExpressionConversionHook().apply(bb, project);
3424  } else {
3425  return project;
3426  }
3427  }
3428 
3429  return scan;
3430  }
3431 
3432  protected RelOptTable getTargetTable(SqlNode call) {
3433  final SqlValidatorNamespace targetNs = validator.getNamespace(call);
3434  if (targetNs.isWrapperFor(SqlValidatorImpl.DmlNamespace.class)) {
3435  final SqlValidatorImpl.DmlNamespace dmlNamespace =
3436  targetNs.unwrap(SqlValidatorImpl.DmlNamespace.class);
3437  return SqlValidatorUtil.getRelOptTable(dmlNamespace, catalogReader, null, null);
3438  }
3439  final SqlValidatorNamespace resolvedNamespace = targetNs.resolve();
3440  return SqlValidatorUtil.getRelOptTable(resolvedNamespace, catalogReader, null, null);
3441  }
3442 
3460  protected RelNode convertColumnList(final SqlInsert call, RelNode source) {
3461  RelDataType sourceRowType = source.getRowType();
3462  final RexNode sourceRef = rexBuilder.makeRangeReference(sourceRowType, 0, false);
3463  final List<String> targetColumnNames = new ArrayList<>();
3464  final List<RexNode> columnExprs = new ArrayList<>();
3465  collectInsertTargets(call, sourceRef, targetColumnNames, columnExprs);
3466 
3467  final RelOptTable targetTable = getTargetTable(call);
3468  final RelDataType targetRowType = RelOptTableImpl.realRowType(targetTable);
3469  final List<RelDataTypeField> targetFields = targetRowType.getFieldList();
3470  final List<RexNode> sourceExps =
3471  new ArrayList<>(Collections.nCopies(targetFields.size(), null));
3472  final List<String> fieldNames =
3473  new ArrayList<>(Collections.nCopies(targetFields.size(), null));
3474 
3475  final InitializerExpressionFactory initializerFactory =
3476  getInitializerFactory(validator.getNamespace(call).getTable());
3477 
3478  // Walk the name list and place the associated value in the
3479  // expression list according to the ordinal value returned from
3480  // the table construct, leaving nulls in the list for columns
3481  // that are not referenced.
3482  final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
3483  for (Pair<String, RexNode> p : Pair.zip(targetColumnNames, columnExprs)) {
3484  RelDataTypeField field = nameMatcher.field(targetRowType, p.left);
3485  assert field != null : "column " + p.left + " not found";
3486  sourceExps.set(field.getIndex(), p.right);
3487  }
3488 
3489  // Lazily create a blackboard that contains all non-generated columns.
3490  final Supplier<Blackboard> bb =
3491  () -> createInsertBlackboard(targetTable, sourceRef, targetColumnNames);
3492 
3493  // Walk the expression list and get default values for any columns
3494  // that were not supplied in the statement. Get field names too.
3495  for (int i = 0; i < targetFields.size(); ++i) {
3496  final RelDataTypeField field = targetFields.get(i);
3497  final String fieldName = field.getName();
3498  fieldNames.set(i, fieldName);
3499  if (sourceExps.get(i) == null || sourceExps.get(i).getKind() == SqlKind.DEFAULT) {
3500  sourceExps.set(
3501  i, initializerFactory.newColumnDefaultValue(targetTable, i, bb.get()));
3502 
3503  // bare nulls are dangerous in the wrong hands
3504  sourceExps.set(i, castNullLiteralIfNeeded(sourceExps.get(i), field.getType()));
3505  }
3506  }
3507 
3508  return relBuilder.push(source).projectNamed(sourceExps, fieldNames, false).build();
3509  }
3510 
3516  RelOptTable targetTable, RexNode sourceRef, List<String> targetColumnNames) {
3517  final Map<String, RexNode> nameToNodeMap = new HashMap<>();
3518  int j = 0;
3519 
3520  // Assign expressions for non-generated columns.
3521  final List<ColumnStrategy> strategies = targetTable.getColumnStrategies();
3522  final List<String> targetFields = targetTable.getRowType().getFieldNames();
3523  for (String targetColumnName : targetColumnNames) {
3524  final int i = targetFields.indexOf(targetColumnName);
3525  switch (strategies.get(i)) {
3526  case STORED:
3527  case VIRTUAL:
3528  break;
3529  default:
3530  nameToNodeMap.put(targetColumnName, rexBuilder.makeFieldAccess(sourceRef, j++));
3531  }
3532  }
3533  return createBlackboard(null, nameToNodeMap, false);
3534  }
3535 
3536  private InitializerExpressionFactory getInitializerFactory(
3537  SqlValidatorTable validatorTable) {
3538  // We might unwrap a null instead of a InitializerExpressionFactory.
3539  final Table table = unwrap(validatorTable, Table.class);
3540  if (table != null) {
3541  InitializerExpressionFactory f = unwrap(table, InitializerExpressionFactory.class);
3542  if (f != null) {
3543  return f;
3544  }
3545  }
3546  return NullInitializerExpressionFactory.INSTANCE;
3547  }
3548 
3549  private static <T> T unwrap(Object o, Class<T> clazz) {
3550  if (o instanceof Wrapper) {
3551  return ((Wrapper) o).unwrap(clazz);
3552  }
3553  return null;
3554  }
3555 
3556  private RexNode castNullLiteralIfNeeded(RexNode node, RelDataType type) {
3557  if (!RexLiteral.isNullLiteral(node)) {
3558  return node;
3559  }
3560  return rexBuilder.makeCast(type, node);
3561  }
3562 
3573  protected void collectInsertTargets(SqlInsert call,
3574  final RexNode sourceRef,
3575  final List<String> targetColumnNames,
3576  List<RexNode> columnExprs) {
3577  final RelOptTable targetTable = getTargetTable(call);
3578  final RelDataType tableRowType = targetTable.getRowType();
3579  SqlNodeList targetColumnList = call.getTargetColumnList();
3580  if (targetColumnList == null) {
3581  if (validator.config().sqlConformance().isInsertSubsetColumnsAllowed()) {
3582  final RelDataType targetRowType =
3583  typeFactory.createStructType(tableRowType.getFieldList().subList(
3584  0, sourceRef.getType().getFieldCount()));
3585  targetColumnNames.addAll(targetRowType.getFieldNames());
3586  } else {
3587  targetColumnNames.addAll(tableRowType.getFieldNames());
3588  }
3589  } else {
3590  for (int i = 0; i < targetColumnList.size(); i++) {
3591  SqlIdentifier id = (SqlIdentifier) targetColumnList.get(i);
3592  RelDataTypeField field = SqlValidatorUtil.getTargetField(
3593  tableRowType, typeFactory, id, catalogReader, targetTable);
3594  assert field != null : "column " + id.toString() + " not found";
3595  targetColumnNames.add(field.getName());
3596  }
3597  }
3598 
3599  final Blackboard bb =
3600  createInsertBlackboard(targetTable, sourceRef, targetColumnNames);
3601 
3602  // Next, assign expressions for generated columns.
3603  final List<ColumnStrategy> strategies = targetTable.getColumnStrategies();
3604  for (String columnName : targetColumnNames) {
3605  final int i = tableRowType.getFieldNames().indexOf(columnName);
3606  final RexNode expr;
3607  switch (strategies.get(i)) {
3608  case STORED:
3609  final InitializerExpressionFactory f =
3610  Util.first(targetTable.unwrap(InitializerExpressionFactory.class),
3611  NullInitializerExpressionFactory.INSTANCE);
3612  expr = f.newColumnDefaultValue(targetTable, i, bb);
3613  break;
3614  case VIRTUAL:
3615  expr = null;
3616  break;
3617  default:
3618  expr = bb.nameToNodeMap.get(columnName);
3619  }
3620  columnExprs.add(expr);
3621  }
3622 
3623  // Remove virtual columns from the list.
3624  for (int i = 0; i < targetColumnNames.size(); i++) {
3625  if (columnExprs.get(i) == null) {
3626  columnExprs.remove(i);
3627  targetColumnNames.remove(i);
3628  --i;
3629  }
3630  }
3631  }
3632 
3633  private RelNode convertDelete(SqlDelete call) {
3634  RelOptTable targetTable = getTargetTable(call);
3635  RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
3636  return LogicalTableModify.create(targetTable,
3637  catalogReader,
3638  sourceRel,
3640  null,
3641  null,
3642  false);
3643  }
3644 
3645  private RelNode convertUpdate(SqlUpdate call) {
3646  final SqlValidatorScope scope = validator.getWhereScope(call.getSourceSelect());
3647  Blackboard bb = createBlackboard(scope, null, false);
3648 
3649  replaceSubQueries(bb, call, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
3650 
3651  RelOptTable targetTable = getTargetTable(call);
3652 
3653  // convert update column list from SqlIdentifier to String
3654  final List<String> targetColumnNameList = new ArrayList<>();
3655  final RelDataType targetRowType = targetTable.getRowType();
3656  for (SqlNode node : call.getTargetColumnList()) {
3657  SqlIdentifier id = (SqlIdentifier) node;
3658  RelDataTypeField field = SqlValidatorUtil.getTargetField(
3659  targetRowType, typeFactory, id, catalogReader, targetTable);
3660  assert field != null : "column " + id.toString() + " not found";
3661  targetColumnNameList.add(field.getName());
3662  }
3663 
3664  RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
3665 
3666  bb.setRoot(sourceRel, false);
3667  Builder<RexNode> rexNodeSourceExpressionListBuilder = ImmutableList.builder();
3668  for (SqlNode n : call.getSourceExpressionList()) {
3669  RexNode rn = bb.convertExpression(n);
3670  rexNodeSourceExpressionListBuilder.add(rn);
3671  }
3672 
3673  return LogicalTableModify.create(targetTable,
3674  catalogReader,
3675  sourceRel,
3677  targetColumnNameList,
3678  rexNodeSourceExpressionListBuilder.build(),
3679  false);
3680  }
3681 
3682  private RelNode convertMerge(SqlMerge call) {
3683  RelOptTable targetTable = getTargetTable(call);
3684 
3685  // convert update column list from SqlIdentifier to String
3686  final List<String> targetColumnNameList = new ArrayList<>();
3687  final RelDataType targetRowType = targetTable.getRowType();
3688  SqlUpdate updateCall = call.getUpdateCall();
3689  if (updateCall != null) {
3690  for (SqlNode targetColumn : updateCall.getTargetColumnList()) {
3691  SqlIdentifier id = (SqlIdentifier) targetColumn;
3692  RelDataTypeField field = SqlValidatorUtil.getTargetField(
3693  targetRowType, typeFactory, id, catalogReader, targetTable);
3694  assert field != null : "column " + id.toString() + " not found";
3695  targetColumnNameList.add(field.getName());
3696  }
3697  }
3698 
3699  // replace the projection of the source select with a
3700  // projection that contains the following:
3701  // 1) the expressions corresponding to the new insert row (if there is
3702  // an insert)
3703  // 2) all columns from the target table (if there is an update)
3704  // 3) the set expressions in the update call (if there is an update)
3705 
3706  // first, convert the merge's source select to construct the columns
3707  // from the target table and the set expressions in the update call
3708  RelNode mergeSourceRel = convertSelect(call.getSourceSelect(), false);
3709 
3710  // then, convert the insert statement so we can get the insert
3711  // values expressions
3712  SqlInsert insertCall = call.getInsertCall();
3713  int nLevel1Exprs = 0;
3714  List<RexNode> level1InsertExprs = null;
3715  List<RexNode> level2InsertExprs = null;
3716  if (insertCall != null) {
3717  RelNode insertRel = convertInsert(insertCall);
3718 
3719  // if there are 2 level of projections in the insert source, combine
3720  // them into a single project; level1 refers to the topmost project;
3721  // the level1 projection contains references to the level2
3722  // expressions, except in the case where no target expression was
3723  // provided, in which case, the expression is the default value for
3724  // the column; or if the expressions directly map to the source
3725  // table
3726  level1InsertExprs = ((LogicalProject) insertRel.getInput(0)).getProjects();
3727  if (insertRel.getInput(0).getInput(0) instanceof LogicalProject) {
3728  level2InsertExprs =
3729  ((LogicalProject) insertRel.getInput(0).getInput(0)).getProjects();
3730  }
3731  nLevel1Exprs = level1InsertExprs.size();
3732  }
3733 
3734  LogicalJoin join = (LogicalJoin) mergeSourceRel.getInput(0);
3735  int nSourceFields = join.getLeft().getRowType().getFieldCount();
3736  final List<RexNode> projects = new ArrayList<>();
3737  for (int level1Idx = 0; level1Idx < nLevel1Exprs; level1Idx++) {
3738  if ((level2InsertExprs != null)
3739  && (level1InsertExprs.get(level1Idx) instanceof RexInputRef)) {
3740  int level2Idx = ((RexInputRef) level1InsertExprs.get(level1Idx)).getIndex();
3741  projects.add(level2InsertExprs.get(level2Idx));
3742  } else {
3743  projects.add(level1InsertExprs.get(level1Idx));
3744  }
3745  }
3746  if (updateCall != null) {
3747  final LogicalProject project = (LogicalProject) mergeSourceRel;
3748  projects.addAll(Util.skip(project.getProjects(), nSourceFields));
3749  }
3750 
3751  relBuilder.push(join).project(projects);
3752 
3753  return LogicalTableModify.create(targetTable,
3754  catalogReader,
3755  relBuilder.build(),
3756  LogicalTableModify.Operation.MERGE,
3757  targetColumnNameList,
3758  null,
3759  false);
3760  }
3761 
3766  private RexNode convertIdentifier(Blackboard bb, SqlIdentifier identifier) {
3767  // first check for reserved identifiers like CURRENT_USER
3768  final SqlCall call = bb.getValidator().makeNullaryCall(identifier);
3769  if (call != null) {
3770  return bb.convertExpression(call);
3771  }
3772 
3773  String pv = null;
3774  if (bb.isPatternVarRef && identifier.names.size() > 1) {
3775  pv = identifier.names.get(0);
3776  }
3777 
3778  final SqlQualified qualified;
3779  if (bb.scope != null) {
3780  qualified = bb.scope.fullyQualify(identifier);
3781  } else {
3782  qualified = SqlQualified.create(null, 1, null, identifier);
3783  }
3784  final Pair<RexNode, Map<String, Integer>> e0 = bb.lookupExp(qualified);
3785  RexNode e = e0.left;
3786  for (String name : qualified.suffix()) {
3787  if (e == e0.left && e0.right != null) {
3788  int i = e0.right.get(name);
3789  e = rexBuilder.makeFieldAccess(e, i);
3790  } else {
3791  final boolean caseSensitive = true; // name already fully-qualified
3792  if (identifier.isStar() && bb.scope instanceof MatchRecognizeScope) {
3793  e = rexBuilder.makeFieldAccess(e, 0);
3794  } else {
3795  e = rexBuilder.makeFieldAccess(e, name, caseSensitive);
3796  }
3797  }
3798  }
3799  if (e instanceof RexInputRef) {
3800  // adjust the type to account for nulls introduced by outer joins
3801  e = adjustInputRef(bb, (RexInputRef) e);
3802  if (pv != null) {
3803  e = RexPatternFieldRef.of(pv, (RexInputRef) e);
3804  }
3805  }
3806 
3807  if (e0.left instanceof RexCorrelVariable) {
3808  assert e instanceof RexFieldAccess;
3809  final RexNode prev = bb.mapCorrelateToRex.put(
3810  ((RexCorrelVariable) e0.left).id, (RexFieldAccess) e);
3811  assert prev == null;
3812  }
3813  return e;
3814  }
3815 
3825  protected RexNode adjustInputRef(Blackboard bb, RexInputRef inputRef) {
3826  RelDataTypeField field = bb.getRootField(inputRef);
3827  if (field != null) {
3828  return rexBuilder.makeInputRef(field.getType(), inputRef.getIndex());
3829  }
3830  return inputRef;
3831  }
3832 
3840  private RelNode convertRowConstructor(Blackboard bb, SqlCall rowConstructor) {
3841  Preconditions.checkArgument(isRowConstructor(rowConstructor));
3842  final List<SqlNode> operands = rowConstructor.getOperandList();
3843  return convertMultisets(operands, bb);
3844  }
3845 
3846  private RelNode convertCursor(Blackboard bb, SubQuery subQuery) {
3847  final SqlCall cursorCall = (SqlCall) subQuery.node;
3848  assert cursorCall.operandCount() == 1;
3849  SqlNode query = cursorCall.operand(0);
3850  RelNode converted = convertQuery(query, false, false).rel;
3851  int iCursor = bb.cursors.size();
3852  bb.cursors.add(converted);
3853  subQuery.expr = new RexInputRef(iCursor, converted.getRowType());
3854  return converted;
3855  }
3856 
3857  private RelNode convertMultisets(final List<SqlNode> operands, Blackboard bb) {
3858  // NOTE: Wael 2/04/05: this implementation is not the most efficient in
3859  // terms of planning since it generates XOs that can be reduced.
3860  final List<Object> joinList = new ArrayList<>();
3861  List<SqlNode> lastList = new ArrayList<>();
3862  for (int i = 0; i < operands.size(); i++) {
3863  SqlNode operand = operands.get(i);
3864  if (!(operand instanceof SqlCall)) {
3865  lastList.add(operand);
3866  continue;
3867  }
3868 
3869  final SqlCall call = (SqlCall) operand;
3870  final RelNode input;
3871  switch (call.getKind()) {
3872  case MULTISET_VALUE_CONSTRUCTOR:
3873  case ARRAY_VALUE_CONSTRUCTOR:
3874  final SqlNodeList list =
3875  new SqlNodeList(call.getOperandList(), call.getParserPosition());
3876  CollectNamespace nss = (CollectNamespace) validator.getNamespace(call);
3877  Blackboard usedBb;
3878  if (null != nss) {
3879  usedBb = createBlackboard(nss.getScope(), null, false);
3880  } else {
3881  usedBb = createBlackboard(new ListScope(bb.scope) {
3882  public SqlNode getNode() {
3883  return call;
3884  }
3885  }, null, false);
3886  }
3887  RelDataType multisetType = validator.getValidatedNodeType(call);
3888  validator.setValidatedNodeType(list, multisetType.getComponentType());
3889  input = convertQueryOrInList(usedBb, list, null);
3890  break;
3891  case MULTISET_QUERY_CONSTRUCTOR:
3892  case ARRAY_QUERY_CONSTRUCTOR:
3893  final RelRoot root = convertQuery(call.operand(0), false, true);
3894  input = root.rel;
3895  break;
3896  default:
3897  lastList.add(operand);
3898  continue;
3899  }
3900 
3901  if (lastList.size() > 0) {
3902  joinList.add(lastList);
3903  }
3904  lastList = new ArrayList<>();
3905  Collect collect = new Collect(cluster,
3906  cluster.traitSetOf(Convention.NONE),
3907  input,
3908  validator.deriveAlias(call, i));
3909  joinList.add(collect);
3910  }
3911 
3912  if (joinList.size() == 0) {
3913  joinList.add(lastList);
3914  }
3915 
3916  for (int i = 0; i < joinList.size(); i++) {
3917  Object o = joinList.get(i);
3918  if (o instanceof List) {
3919  @SuppressWarnings("unchecked")
3920  List<SqlNode> projectList = (List<SqlNode>) o;
3921  final List<RexNode> selectList = new ArrayList<>();
3922  final List<String> fieldNameList = new ArrayList<>();
3923  for (int j = 0; j < projectList.size(); j++) {
3924  SqlNode operand = projectList.get(j);
3925  selectList.add(bb.convertExpression(operand));
3926 
3927  // REVIEW angel 5-June-2005: Use deriveAliasFromOrdinal
3928  // instead of deriveAlias to match field names from
3929  // SqlRowOperator. Otherwise, get error Type
3930  // 'RecordType(INTEGER EMPNO)' has no field 'EXPR$0' when
3931  // doing select * from unnest( select multiset[empno]
3932  // from sales.emps);
3933 
3934  fieldNameList.add(SqlUtil.deriveAliasFromOrdinal(j));
3935  }
3936 
3937  relBuilder.push(LogicalValues.createOneRow(cluster))
3938  .projectNamed(selectList, fieldNameList, true);
3939 
3940  joinList.set(i, relBuilder.build());
3941  }
3942  }
3943 
3944  RelNode ret = (RelNode) joinList.get(0);
3945  for (int i = 1; i < joinList.size(); i++) {
3946  RelNode relNode = (RelNode) joinList.get(i);
3947  ret = RelFactories.DEFAULT_JOIN_FACTORY.createJoin(ret,
3948  relNode,
3949  ImmutableList.of(),
3950  rexBuilder.makeLiteral(true),
3951  ImmutableSet.of(),
3952  JoinRelType.INNER,
3953  false);
3954  }
3955  return ret;
3956  }
3957 
3958  private void convertSelectList(
3959  Blackboard bb, SqlSelect select, List<SqlNode> orderList) {
3960  SqlNodeList selectList = select.getSelectList();
3961  selectList = validator.expandStar(selectList, select, false);
3962 
3963  replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
3964 
3965  List<String> fieldNames = new ArrayList<>();
3966  final List<RexNode> exprs = new ArrayList<>();
3967  final Collection<String> aliases = new TreeSet<>();
3968 
3969  // Project any system fields. (Must be done before regular select items,
3970  // because offsets may be affected.)
3971  final List<SqlMonotonicity> columnMonotonicityList = new ArrayList<>();
3972  extraSelectItems(bb, select, exprs, fieldNames, aliases, columnMonotonicityList);
3973 
3974  // Project select clause.
3975  int i = -1;
3976  for (SqlNode expr : selectList) {
3977  ++i;
3978  exprs.add(bb.convertExpression(expr));
3979  fieldNames.add(deriveAlias(expr, aliases, i));
3980  }
3981 
3982  // Project extra fields for sorting.
3983  for (SqlNode expr : orderList) {
3984  ++i;
3985  SqlNode expr2 = validator.expandOrderExpr(select, expr);
3986  exprs.add(bb.convertExpression(expr2));
3987  fieldNames.add(deriveAlias(expr, aliases, i));
3988  }
3989 
3990  fieldNames = SqlValidatorUtil.uniquify(
3991  fieldNames, catalogReader.nameMatcher().isCaseSensitive());
3992 
3993  relBuilder.push(bb.root).projectNamed(exprs, fieldNames, true);
3994  bb.setRoot(relBuilder.build(), false);
3995 
3996  assert bb.columnMonotonicities.isEmpty();
3997  bb.columnMonotonicities.addAll(columnMonotonicityList);
3998  for (SqlNode selectItem : selectList) {
3999  bb.columnMonotonicities.add(selectItem.getMonotonicity(bb.scope));
4000  }
4001  }
4002 
4016  protected void extraSelectItems(Blackboard bb,
4017  SqlSelect select,
4018  List<RexNode> exprList,
4019  List<String> nameList,
4020  Collection<String> aliasList,
4021  List<SqlMonotonicity> columnMonotonicityList) {}
4022 
4023  private String deriveAlias(
4024  final SqlNode node, Collection<String> aliases, final int ordinal) {
4025  String alias = validator.deriveAlias(node, ordinal);
4026  if ((alias == null) || aliases.contains(alias)) {
4027  String aliasBase = (alias == null) ? "EXPR$" : alias;
4028  for (int j = 0;; j++) {
4029  alias = aliasBase + j;
4030  if (!aliases.contains(alias)) {
4031  break;
4032  }
4033  }
4034  }
4035  aliases.add(alias);
4036  return alias;
4037  }
4038 
4042  public RelRoot convertWith(SqlWith with, boolean top) {
4043  return convertQuery(with.body, false, top);
4044  }
4045 
4049  public RelNode convertValues(SqlCall values, RelDataType targetRowType) {
4050  final SqlValidatorScope scope = validator.getOverScope(values);
4051  assert scope != null;
4052  final Blackboard bb = createBlackboard(scope, null, false);
4053  convertValuesImpl(bb, values, targetRowType);
4054  return bb.root;
4055  }
4056 
4065  private void convertValuesImpl(
4066  Blackboard bb, SqlCall values, RelDataType targetRowType) {
4067  // Attempt direct conversion to LogicalValues; if that fails, deal with
4068  // fancy stuff like sub-queries below.
4069  RelNode valuesRel =
4070  convertRowValues(bb, values, values.getOperandList(), true, targetRowType);
4071  if (valuesRel != null) {
4072  bb.setRoot(valuesRel, true);
4073  return;
4074  }
4075 
4076  final List<RelNode> unionRels = new ArrayList<>();
4077  for (SqlNode rowConstructor1 : values.getOperandList()) {
4078  SqlCall rowConstructor = (SqlCall) rowConstructor1;
4079  Blackboard tmpBb = createBlackboard(bb.scope, null, false);
4080  replaceSubQueries(tmpBb, rowConstructor, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
4081  final List<Pair<RexNode, String>> exps = new ArrayList<>();
4082  for (Ord<SqlNode> operand : Ord.zip(rowConstructor.getOperandList())) {
4083  exps.add(Pair.of(tmpBb.convertExpression(operand.e),
4084  validator.deriveAlias(operand.e, operand.i)));
4085  }
4086  RelNode in =
4087  (null == tmpBb.root) ? LogicalValues.createOneRow(cluster) : tmpBb.root;
4088  unionRels.add(
4089  relBuilder.push(in).project(Pair.left(exps), Pair.right(exps)).build());
4090  }
4091 
4092  if (unionRels.size() == 0) {
4093  throw new AssertionError("empty values clause");
4094  } else if (unionRels.size() == 1) {
4095  bb.setRoot(unionRels.get(0), true);
4096  } else {
4097  bb.setRoot(LogicalUnion.create(unionRels, true), true);
4098  }
4099  }
4100 
4101  // ~ Inner Classes ----------------------------------------------------------
4102 
4106  protected class Blackboard
4107  implements SqlRexContext, SqlVisitor<RexNode>, InitializerContext {
4111  public final SqlValidatorScope scope;
4112  private final Map<String, RexNode> nameToNodeMap;
4113  public RelNode root;
4114  private List<RelNode> inputs;
4115  private final Map<CorrelationId, RexFieldAccess> mapCorrelateToRex = new HashMap<>();
4116 
4117  private boolean isPatternVarRef = false;
4118 
4119  final List<RelNode> cursors = new ArrayList<>();
4120 
4125  private final List<SubQuery> subQueryList = new ArrayList<>();
4126 
4130  AggConverter agg;
4131 
4136  SqlWindow window;
4137 
4143  private final Map<RelNode, Map<Integer, Integer>> mapRootRelToFieldProjection =
4144  new HashMap<>();
4145 
4146  private final List<SqlMonotonicity> columnMonotonicities = new ArrayList<>();
4147 
4148  private final List<RelDataTypeField> systemFieldList = new ArrayList<>();
4149  final boolean top;
4150 
4151  private final InitializerExpressionFactory initializerExpressionFactory =
4152  new NullInitializerExpressionFactory();
4153 
4165  protected Blackboard(
4166  SqlValidatorScope scope, Map<String, RexNode> nameToNodeMap, boolean top) {
4167  this.scope = scope;
4168  this.nameToNodeMap = nameToNodeMap;
4169  this.top = top;
4170  }
4171 
4172  public SqlNode getTopNode() {
4173  try {
4174  if (null == scope) {
4175  return null;
4176  }
4177  return scope.getNode();
4178  } catch (Exception e) {
4179  return null;
4180  }
4181  }
4182 
4183  public void setPatternVarRef(boolean isVarRef) {
4184  this.isPatternVarRef = isVarRef;
4185  }
4186 
4187  public RexNode register(RelNode rel, JoinRelType joinType) {
4188  return register(rel, joinType, null);
4189  }
4190 
4200  public RexNode register(RelNode rel, JoinRelType joinType, List<RexNode> leftKeys) {
4201  assert joinType != null;
4202  if (root == null) {
4203  assert leftKeys == null;
4204  setRoot(rel, false);
4205  return rexBuilder.makeRangeReference(root.getRowType(), 0, false);
4206  }
4207 
4208  final RexNode joinCond;
4209  final int origLeftInputCount = root.getRowType().getFieldCount();
4210  if (leftKeys != null) {
4211  List<RexNode> newLeftInputExprs = new ArrayList<>();
4212  for (int i = 0; i < origLeftInputCount; i++) {
4213  newLeftInputExprs.add(rexBuilder.makeInputRef(root, i));
4214  }
4215 
4216  final List<Integer> leftJoinKeys = new ArrayList<>();
4217  for (RexNode leftKey : leftKeys) {
4218  int index = newLeftInputExprs.indexOf(leftKey);
4219  if (index < 0 || joinType == JoinRelType.LEFT) {
4220  index = newLeftInputExprs.size();
4221  newLeftInputExprs.add(leftKey);
4222  }
4223  leftJoinKeys.add(index);
4224  }
4225 
4226  RelNode newLeftInput = relBuilder.push(root).project(newLeftInputExprs).build();
4227 
4228  // maintain the group by mapping in the new LogicalProject
4229  if (mapRootRelToFieldProjection.containsKey(root)) {
4230  mapRootRelToFieldProjection.put(
4231  newLeftInput, mapRootRelToFieldProjection.get(root));
4232  }
4233 
4234  setRoot(newLeftInput, false);
4235 
4236  // right fields appear after the LHS fields.
4237  final int rightOffset = root.getRowType().getFieldCount()
4238  - newLeftInput.getRowType().getFieldCount();
4239  final List<Integer> rightKeys =
4240  Util.range(rightOffset, rightOffset + leftKeys.size());
4241 
4242  joinCond = RelOptUtil.createEquiJoinCondition(
4243  newLeftInput, leftJoinKeys, rel, rightKeys, rexBuilder);
4244  } else {
4245  joinCond = rexBuilder.makeLiteral(true);
4246  }
4247 
4248  int leftFieldCount = root.getRowType().getFieldCount();
4249  final RelNode join = createJoin(this, root, rel, joinCond, joinType);
4250 
4251  setRoot(join, false);
4252 
4253  if (leftKeys != null && joinType == JoinRelType.LEFT) {
4254  final int leftKeyCount = leftKeys.size();
4255  int rightFieldLength = rel.getRowType().getFieldCount();
4256  assert leftKeyCount == rightFieldLength - 1;
4257 
4258  final int rexRangeRefLength = leftKeyCount + rightFieldLength;
4259  RelDataType returnType = typeFactory.createStructType(
4260  new AbstractList<Map.Entry<String, RelDataType>>() {
4261  public Map.Entry<String, RelDataType> get(int index) {
4262  return join.getRowType().getFieldList().get(
4263  origLeftInputCount + index);
4264  }
4265 
4266  public int size() {
4267  return rexRangeRefLength;
4268  }
4269  });
4270 
4271  return rexBuilder.makeRangeReference(returnType, origLeftInputCount, false);
4272  } else {
4273  return rexBuilder.makeRangeReference(
4274  rel.getRowType(), leftFieldCount, joinType.generatesNullsOnRight());
4275  }
4276  }
4277 
4289  public void setRoot(RelNode root, boolean leaf) {
4290  setRoot(Collections.singletonList(root), root, root instanceof LogicalJoin);
4291  if (leaf) {
4292  leaves.put(root, root.getRowType().getFieldCount());
4293  }
4294  this.columnMonotonicities.clear();
4295  }
4296 
4297  private void setRoot(List<RelNode> inputs, RelNode root, boolean hasSystemFields) {
4298  this.inputs = inputs;
4299  this.root = root;
4300  this.systemFieldList.clear();
4301  if (hasSystemFields) {
4302  this.systemFieldList.addAll(getSystemFields());
4303  }
4304  }
4305 
4316  public void setDataset(String datasetName) {}
4317 
4318  void setRoot(List<RelNode> inputs) {
4319  setRoot(inputs, null, false);
4320  }
4321 
4328  Pair<RexNode, Map<String, Integer>> lookupExp(SqlQualified qualified) {
4329  if (nameToNodeMap != null && qualified.prefixLength == 1) {
4330  RexNode node = nameToNodeMap.get(qualified.identifier.names.get(0));
4331  if (node == null) {
4332  throw new AssertionError("Unknown identifier '" + qualified.identifier
4333  + "' encountered while expanding expression");
4334  }
4335  return Pair.of(node, null);
4336  }
4337  final SqlNameMatcher nameMatcher =
4338  scope.getValidator().getCatalogReader().nameMatcher();
4339  final SqlValidatorScope.ResolvedImpl resolved =
4340  new SqlValidatorScope.ResolvedImpl();
4341  scope.resolve(qualified.prefix(), nameMatcher, false, resolved);
4342  if (!(resolved.count() == 1)) {
4343  return null;
4344  }
4345  final SqlValidatorScope.Resolve resolve = resolved.only();
4346  final RelDataType rowType = resolve.rowType();
4347 
4348  // Found in current query's from list. Find which from item.
4349  // We assume that the order of the from clause items has been
4350  // preserved.
4351  final SqlValidatorScope ancestorScope = resolve.scope;
4352  boolean isParent = ancestorScope != scope;
4353  if ((inputs != null) && !isParent) {
4354  final LookupContext rels =
4355  new LookupContext(this, inputs, systemFieldList.size());
4356  final RexNode node = lookup(resolve.path.steps().get(0).i, rels);
4357  if (node == null) {
4358  return null;
4359  } else {
4360  final Map<String, Integer> fieldOffsets = new HashMap<>();
4361  for (RelDataTypeField f : resolve.rowType().getFieldList()) {
4362  if (!fieldOffsets.containsKey(f.getName())) {
4363  fieldOffsets.put(f.getName(), f.getIndex());
4364  }
4365  }
4366  final Map<String, Integer> map = ImmutableMap.copyOf(fieldOffsets);
4367  return Pair.of(node, map);
4368  }
4369  } else {
4370  // We're referencing a relational expression which has not been
4371  // converted yet. This occurs when from items are correlated,
4372  // e.g. "select from emp as emp join emp.getDepts() as dept".
4373  // Create a temporary expression.
4374  DeferredLookup lookup =
4375  new DeferredLookup(this, qualified.identifier.names.get(0));
4376  final CorrelationId correlId = cluster.createCorrel();
4377  mapCorrelToDeferred.put(correlId, lookup);
4378  if (resolve.path.steps().get(0).i < 0) {
4379  return Pair.of(rexBuilder.makeCorrel(rowType, correlId), null);
4380  } else {
4381  final RelDataTypeFactory.Builder builder = typeFactory.builder();
4382  final ListScope ancestorScope1 = (ListScope) resolve.scope;
4383  final ImmutableMap.Builder<String, Integer> fields = ImmutableMap.builder();
4384  int i = 0;
4385  int offset = 0;
4386  for (SqlValidatorNamespace c : ancestorScope1.getChildren()) {
4387  builder.addAll(c.getRowType().getFieldList());
4388  if (i == resolve.path.steps().get(0).i) {
4389  for (RelDataTypeField field : c.getRowType().getFieldList()) {
4390  fields.put(field.getName(), field.getIndex() + offset);
4391  }
4392  }
4393  ++i;
4394  offset += c.getRowType().getFieldCount();
4395  }
4396  final RexNode c = rexBuilder.makeCorrel(builder.uniquify().build(), correlId);
4397  return Pair.of(c, fields.build());
4398  }
4399  }
4400  }
4401 
4406  RexNode lookup(int offset, LookupContext lookupContext) {
4407  Pair<RelNode, Integer> pair = lookupContext.findRel(offset);
4408  return rexBuilder.makeRangeReference(pair.left.getRowType(), pair.right, false);
4409  }
4410 
4411  RelDataTypeField getRootField(RexInputRef inputRef) {
4412  if (inputs == null) {
4413  return null;
4414  }
4415  int fieldOffset = inputRef.getIndex();
4416  for (RelNode input : inputs) {
4417  RelDataType rowType = input.getRowType();
4418  if (fieldOffset < rowType.getFieldCount()) {
4419  return rowType.getFieldList().get(fieldOffset);
4420  }
4421  fieldOffset -= rowType.getFieldCount();
4422  }
4423  return null;
4424  }
4425 
4426  public void flatten(List<RelNode> rels,
4427  int systemFieldCount,
4428  int[] start,
4429  List<Pair<RelNode, Integer>> relOffsetList) {
4430  for (RelNode rel : rels) {
4431  if (leaves.containsKey(rel)) {
4432  relOffsetList.add(Pair.of(rel, start[0]));
4433  start[0] += leaves.get(rel);
4434  } else if (rel instanceof LogicalMatch) {
4435  relOffsetList.add(Pair.of(rel, start[0]));
4436  start[0] += rel.getRowType().getFieldCount();
4437  } else {
4438  if (rel instanceof LogicalJoin || rel instanceof LogicalAggregate) {
4439  start[0] += systemFieldCount;
4440  }
4441  flatten(rel.getInputs(), systemFieldCount, start, relOffsetList);
4442  }
4443  }
4444  }
4445 
4446  void registerSubQuery(SqlNode node, RelOptUtil.Logic logic) {
4447  for (SubQuery subQuery : subQueryList) {
4448  // Compare the reference to make sure the matched node has
4449  // exact scope where it belongs.
4450  if (node == subQuery.node) {
4451  return;
4452  }
4453  }
4454  subQueryList.add(new SubQuery(node, logic));
4455  }
4456 
4457  SubQuery getSubQuery(SqlNode expr) {
4458  for (SubQuery subQuery : subQueryList) {
4459  // Compare the reference to make sure the matched node has
4460  // exact scope where it belongs.
4461  if (expr == subQuery.node) {
4462  return subQuery;
4463  }
4464  }
4465 
4466  return null;
4467  }
4468 
4469  ImmutableList<RelNode> retrieveCursors() {
4470  try {
4471  return ImmutableList.copyOf(cursors);
4472  } finally {
4473  cursors.clear();
4474  }
4475  }
4476 
4477  public RexNode convertExpression(SqlNode expr) {
4478  // If we're in aggregation mode and this is an expression in the
4479  // GROUP BY clause, return a reference to the field.
4480  if (agg != null) {
4481  final SqlNode expandedGroupExpr = validator.expand(expr, scope);
4482  final int ref = agg.lookupGroupExpr(expandedGroupExpr);
4483  if (ref >= 0) {
4484  return rexBuilder.makeInputRef(root, ref);
4485  }
4486  if (expr instanceof SqlCall) {
4487  final RexNode rex = agg.lookupAggregates((SqlCall) expr);
4488  if (rex != null) {
4489  return rex;
4490  }
4491  }
4492  }
4493 
4494  // Allow the derived class chance to override the standard
4495  // behavior for special kinds of expressions.
4496  RexNode rex = convertExtendedExpression(expr, this);
4497  if (rex != null) {
4498  return rex;
4499  }
4500 
4501  // Sub-queries and OVER expressions are not like ordinary
4502  // expressions.
4503  final SqlKind kind = expr.getKind();
4504  final SubQuery subQuery;
4505  boolean isExpand = config.getExpandPredicate().test(getTopNode(), expr);
4506  if (!isExpand) {
4507  final SqlCall call;
4508  final SqlNode query;
4509  final RelRoot root;
4510  switch (kind) {
4511  case IN:
4512  case NOT_IN:
4513  case SOME:
4514  case ALL:
4515  call = (SqlCall) expr;
4516  query = call.operand(1);
4517  if (!(query instanceof SqlNodeList)) {
4518  root = convertQueryRecursive(query, false, null);
4519  final SqlNode operand = call.operand(0);
4520  List<SqlNode> nodes;
4521  switch (operand.getKind()) {
4522  case ROW:
4523  nodes = ((SqlCall) operand).getOperandList();
4524  break;
4525  default:
4526  nodes = ImmutableList.of(operand);
4527  }
4528  final ImmutableList.Builder<RexNode> builder = ImmutableList.builder();
4529  for (SqlNode node : nodes) {
4530  builder.add(convertExpression(node));
4531  }
4532  final ImmutableList<RexNode> list = builder.build();
4533  switch (kind) {
4534  case IN:
4535  return RexSubQuery.in(root.rel, list);
4536  case NOT_IN:
4537  return rexBuilder.makeCall(
4538  SqlStdOperatorTable.NOT, RexSubQuery.in(root.rel, list));
4539  case SOME:
4540  return RexSubQuery.some(
4541  root.rel, list, (SqlQuantifyOperator) call.getOperator());
4542  case ALL:
4543  return rexBuilder.makeCall(SqlStdOperatorTable.NOT,
4544  RexSubQuery.some(root.rel,
4545  list,
4546  negate((SqlQuantifyOperator) call.getOperator())));
4547  default:
4548  throw new AssertionError(kind);
4549  }
4550  }
4551  break;
4552 
4553  case EXISTS:
4554  call = (SqlCall) expr;
4555  query = Iterables.getOnlyElement(call.getOperandList());
4556  root = convertQueryRecursive(query, false, null);
4557  RelNode rel = root.rel;
4558  while (rel instanceof Project
4559  || rel instanceof Sort && ((Sort) rel).fetch == null
4560  && ((Sort) rel).offset == null) {
4561  rel = ((SingleRel) rel).getInput();
4562  }
4563  return RexSubQuery.exists(rel);
4564 
4565  case SCALAR_QUERY:
4566  call = (SqlCall) expr;
4567  query = Iterables.getOnlyElement(call.getOperandList());
4568  root = convertQueryRecursive(query, false, null);
4569  return RexSubQuery.scalar(root.rel);
4570  }
4571  }
4572 
4573  switch (kind) {
4574  case SOME:
4575  case ALL:
4576  if (isExpand) {
4577  throw new RuntimeException(kind + " is only supported if expand = false");
4578  }
4579  // fall through
4580  case CURSOR:
4581  case IN:
4582  case NOT_IN:
4583  subQuery = Objects.requireNonNull(getSubQuery(expr));
4584  rex = Objects.requireNonNull(subQuery.expr);
4585  return StandardConvertletTable.castToValidatedType(
4586  expr, rex, validator, rexBuilder);
4587 
4588  case SELECT:
4589  case EXISTS:
4590  case SCALAR_QUERY:
4591  subQuery = getSubQuery(expr);
4592  assert subQuery != null;
4593  rex = subQuery.expr;
4594  assert rex != null : "rex != null";
4595 
4596  if (((kind == SqlKind.SCALAR_QUERY) || (kind == SqlKind.EXISTS))
4597  && isConvertedSubq(rex)) {
4598  // scalar sub-query or EXISTS has been converted to a
4599  // constant
4600  return rex;
4601  }
4602 
4603  // The indicator column is the last field of the sub-query.
4604  RexNode fieldAccess =
4605  rexBuilder.makeFieldAccess(rex, rex.getType().getFieldCount() - 1);
4606 
4607  // The indicator column will be nullable if it comes from
4608  // the null-generating side of the join. For EXISTS, add an
4609  // "IS TRUE" check so that the result is "BOOLEAN NOT NULL".
4610  if (fieldAccess.getType().isNullable() && kind == SqlKind.EXISTS) {
4611  fieldAccess =
4612  rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, fieldAccess);
4613  }
4614  return fieldAccess;
4615 
4616  case OVER:
4617  return convertOver(this, expr);
4618 
4619  default:
4620  // fall through
4621  }
4622 
4623  // Apply standard conversions.
4624  rex = expr.accept(this);
4625  return Objects.requireNonNull(rex);
4626  }
4627 
4632  public RexFieldCollation convertSortExpression(SqlNode expr,
4633  RelFieldCollation.Direction direction,
4634  RelFieldCollation.NullDirection nullDirection) {
4635  switch (expr.getKind()) {
4636  case DESCENDING:
4637  return convertSortExpression(((SqlCall) expr).operand(0),
4638  RelFieldCollation.Direction.DESCENDING,
4639  nullDirection);
4640  case NULLS_LAST:
4641  return convertSortExpression(((SqlCall) expr).operand(0),
4642  direction,
4643  RelFieldCollation.NullDirection.LAST);
4644  case NULLS_FIRST:
4645  return convertSortExpression(((SqlCall) expr).operand(0),
4646  direction,
4647  RelFieldCollation.NullDirection.FIRST);
4648  default:
4649  final Set<SqlKind> flags = EnumSet.noneOf(SqlKind.class);
4650  switch (direction) {
4651  case DESCENDING:
4652  flags.add(SqlKind.DESCENDING);
4653  }
4654  switch (nullDirection) {
4655  case UNSPECIFIED:
4656  final RelFieldCollation.NullDirection nullDefaultDirection =
4657  validator.config().defaultNullCollation().last(desc(direction))
4658  ? RelFieldCollation.NullDirection.LAST
4659  : RelFieldCollation.NullDirection.FIRST;
4660  if (nullDefaultDirection != direction.defaultNullDirection()) {
4661  SqlKind nullDirectionSqlKind =
4662  validator.config().defaultNullCollation().last(desc(direction))
4663  ? SqlKind.NULLS_LAST
4664  : SqlKind.NULLS_FIRST;
4665  flags.add(nullDirectionSqlKind);
4666  }
4667  break;
4668  case FIRST:
4669  flags.add(SqlKind.NULLS_FIRST);
4670  break;
4671  case LAST:
4672  flags.add(SqlKind.NULLS_LAST);
4673  break;
4674  }
4675  return new RexFieldCollation(convertExpression(expr), flags);
4676  }
4677  }
4678 
4687  private boolean isConvertedSubq(RexNode rex) {
4688  if ((rex instanceof RexLiteral) || (rex instanceof RexDynamicParam)) {
4689  return true;
4690  }
4691  if (rex instanceof RexCall) {
4692  RexCall call = (RexCall) rex;
4693  if (call.getOperator() == SqlStdOperatorTable.CAST) {
4694  RexNode operand = call.getOperands().get(0);
4695  if (operand instanceof RexLiteral) {
4696  return true;
4697  }
4698  }
4699  }
4700  return false;
4701  }
4702 
4703  public int getGroupCount() {
4704  if (agg != null) {
4705  return agg.groupExprs.size();
4706  }
4707  if (window != null) {
4708  return window.isAlwaysNonEmpty() ? 1 : 0;
4709  }
4710  return -1;
4711  }
4712 
4713  public RexBuilder getRexBuilder() {
4714  return rexBuilder;
4715  }
4716 
4717  public SqlNode validateExpression(RelDataType rowType, SqlNode expr) {
4718  return SqlValidatorUtil
4719  .validateExprWithRowType(catalogReader.nameMatcher().isCaseSensitive(),
4720  opTab,
4721  typeFactory,
4722  rowType,
4723  expr)
4724  .left;
4725  }
4726 
4727  public RexRangeRef getSubQueryExpr(SqlCall call) {
4728  final SubQuery subQuery = getSubQuery(call);
4729  assert subQuery != null;
4730  return (RexRangeRef) subQuery.expr;
4731  }
4732 
4733  public RelDataTypeFactory getTypeFactory() {
4734  return typeFactory;
4735  }
4736 
4737  public InitializerExpressionFactory getInitializerExpressionFactory() {
4738  return initializerExpressionFactory;
4739  }
4740 
4741  public SqlValidator getValidator() {
4742  return validator;
4743  }
4744 
4745  public RexNode convertLiteral(SqlLiteral literal) {
4746  return exprConverter.convertLiteral(this, literal);
4747  }
4748 
4749  public RexNode convertInterval(SqlIntervalQualifier intervalQualifier) {
4750  return exprConverter.convertInterval(this, intervalQualifier);
4751  }
4752 
4753  public RexNode visit(SqlLiteral literal) {
4754  return exprConverter.convertLiteral(this, literal);
4755  }
4756 
4757  public RexNode visit(SqlCall call) {
4758  if (agg != null) {
4759  final SqlOperator op = call.getOperator();
4760  if (window == null
4761  && (op.isAggregator() || op.getKind() == SqlKind.FILTER
4762  || op.getKind() == SqlKind.WITHIN_GROUP)) {
4763  return agg.lookupAggregates(call);
4764  }
4765  }
4766  return exprConverter.convertCall(
4767  this, new SqlCallBinding(validator, scope, call).permutedCall());
4768  }
4769 
4770  public RexNode visit(SqlNodeList nodeList) {
4771  throw new UnsupportedOperationException();
4772  }
4773 
4774  public RexNode visit(SqlIdentifier id) {
4775  return convertIdentifier(this, id);
4776  }
4777 
4778  public RexNode visit(SqlDataTypeSpec type) {
4779  throw new UnsupportedOperationException();
4780  }
4781 
4782  public RexNode visit(SqlDynamicParam param) {
4783  return convertDynamicParam(param);
4784  }
4785 
4786  public RexNode visit(SqlIntervalQualifier intervalQualifier) {
4787  return convertInterval(intervalQualifier);
4788  }
4789 
4790  public List<SqlMonotonicity> getColumnMonotonicities() {
4791  return columnMonotonicities;
4792  }
4793  }
4794 
4795  private SqlQuantifyOperator negate(SqlQuantifyOperator operator) {
4796  assert operator.kind == SqlKind.ALL;
4797  return SqlStdOperatorTable.some(operator.comparisonKind.negateNullSafe());
4798  }
4799 
4801  private static class DeferredLookup {
4804 
4805  DeferredLookup(Blackboard bb, String originalRelName) {
4806  this.bb = bb;
4807  this.originalRelName = originalRelName;
4808  }
4809 
4810  public RexFieldAccess getFieldAccess(CorrelationId name) {
4811  return (RexFieldAccess) bb.mapCorrelateToRex.get(name);
4812  }
4813 
4814  public String getOriginalRelName() {
4815  return originalRelName;
4816  }
4817  }
4818 
4822  private class NoOpSubQueryConverter implements SubQueryConverter {
4823  public boolean canConvertSubQuery() {
4824  return false;
4825  }
4826 
4827  public RexNode convertSubQuery(SqlCall subQuery,
4828  SqlToRelConverter parentConverter,
4829  boolean isExists,
4830  boolean isExplain) {
4831  throw new IllegalArgumentException();
4832  }
4833  }
4834 
4854  protected class AggConverter implements SqlVisitor<Void> {
4855  private final Blackboard bb;
4856  public final AggregatingSelectScope aggregatingSelectScope;
4857 
4858  private final Map<String, String> nameMap = new HashMap<>();
4859 
4863  private final SqlNodeList groupExprs = new SqlNodeList(SqlParserPos.ZERO);
4864 
4868  private final Map<SqlNode, Ord<AuxiliaryConverter>> auxiliaryGroupExprs =
4869  new HashMap<>();
4870 
4878  private final List<Pair<RexNode, String>> convertedInputExprs = new ArrayList<>();
4879 
4886  private final List<AggregateCall> aggCalls = new ArrayList<>();
4887  private final Map<SqlNode, RexNode> aggMapping = new HashMap<>();
4888  private final Map<AggregateCall, RexNode> aggCallMapping = new HashMap<>();
4889 
4891  private boolean inOver = false;
4892 
4903  public AggConverter(Blackboard bb, SqlSelect select) {
4904  this.bb = bb;
4905  this.aggregatingSelectScope =
4906  (AggregatingSelectScope) bb.getValidator().getSelectScope(select);
4907 
4908  // Collect all expressions used in the select list so that aggregate
4909  // calls can be named correctly.
4910  final SqlNodeList selectList = select.getSelectList();
4911  for (int i = 0; i < selectList.size(); i++) {
4912  SqlNode selectItem = selectList.get(i);
4913  String name = null;
4914  if (SqlUtil.isCallTo(selectItem, SqlStdOperatorTable.AS)) {
4915  final SqlCall call = (SqlCall) selectItem;
4916  selectItem = call.operand(0);
4917  name = call.operand(1).toString();
4918  }
4919  if (name == null) {
4920  name = validator.deriveAlias(selectItem, i);
4921  }
4922  nameMap.put(selectItem.toString(), name);
4923  }
4924  }
4925 
4926  public int addGroupExpr(SqlNode expr) {
4927  int ref = lookupGroupExpr(expr);
4928  if (ref >= 0) {
4929  return ref;
4930  }
4931  final int index = groupExprs.size();
4932  groupExprs.add(expr);
4933  String name = nameMap.get(expr.toString());
4934  RexNode convExpr = bb.convertExpression(expr);
4935  addExpr(convExpr, name);
4936 
4937  if (expr instanceof SqlCall) {
4938  SqlCall call = (SqlCall) expr;
4939  for (Pair<SqlNode, AuxiliaryConverter> p :
4940  SqlStdOperatorTable.convertGroupToAuxiliaryCalls(call)) {
4941  addAuxiliaryGroupExpr(p.left, index, p.right);
4942  }
4943  }
4944 
4945  return index;
4946  }
4947 
4948  void addAuxiliaryGroupExpr(SqlNode node, int index, AuxiliaryConverter converter) {
4949  for (SqlNode node2 : auxiliaryGroupExprs.keySet()) {
4950  if (node2.equalsDeep(node, Litmus.IGNORE)) {
4951  return;
4952  }
4953  }
4954  auxiliaryGroupExprs.put(node, Ord.of(index, converter));
4955  }
4956 
4963  private void addExpr(RexNode expr, String name) {
4964  if ((name == null) && (expr instanceof RexInputRef)) {
4965  final int i = ((RexInputRef) expr).getIndex();
4966  name = bb.root.getRowType().getFieldList().get(i).getName();
4967  }
4968  if (Pair.right(convertedInputExprs).contains(name)) {
4969  // In case like 'SELECT ... GROUP BY x, y, x', don't add
4970  // name 'x' twice.
4971  name = null;
4972  }
4973  convertedInputExprs.add(Pair.of(expr, name));
4974  }
4975 
4976  public Void visit(SqlIdentifier id) {
4977  return null;
4978  }
4979 
4980  public Void visit(SqlNodeList nodeList) {
4981  for (int i = 0; i < nodeList.size(); i++) {
4982  nodeList.get(i).accept(this);
4983  }
4984  return null;
4985  }
4986 
4987  public Void visit(SqlLiteral lit) {
4988  return null;
4989  }
4990 
4991  public Void visit(SqlDataTypeSpec type) {
4992  return null;
4993  }
4994 
4995  public Void visit(SqlDynamicParam param) {
4996  return null;
4997  }
4998 
4999  public Void visit(SqlIntervalQualifier intervalQualifier) {
5000  return null;
5001  }
5002 
5003  public Void visit(SqlCall call) {
5004  switch (call.getKind()) {
5005  case FILTER:
5006  case WITHIN_GROUP:
5007  translateAgg(call);
5008  return null;
5009  case SELECT:
5010  // rchen 2006-10-17:
5011  // for now do not detect aggregates in sub-queries.
5012  return null;
5013  }
5014  final boolean prevInOver = inOver;
5015  // Ignore window aggregates and ranking functions (associated with OVER
5016  // operator). However, do not ignore nested window aggregates.
5017  if (call.getOperator().getKind() == SqlKind.OVER) {
5018  // Track aggregate nesting levels only within an OVER operator.
5019  List<SqlNode> operandList = call.getOperandList();
5020  assert operandList.size() == 2;
5021 
5022  // Ignore the top level window aggregates and ranking functions
5023  // positioned as the first operand of a OVER operator
5024  inOver = true;
5025  operandList.get(0).accept(this);
5026 
5027  // Normal translation for the second operand of a OVER operator
5028  inOver = false;
5029  operandList.get(1).accept(this);
5030  return null;
5031  }
5032 
5033  // Do not translate the top level window aggregate. Only do so for
5034  // nested aggregates, if present
5035  if (call.getOperator().isAggregator()) {
5036  if (inOver) {
5037  // Add the parent aggregate level before visiting its children
5038  inOver = false;
5039  } else {
5040  // We're beyond the one ignored level
5041  translateAgg(call);
5042  return null;
5043  }
5044  }
5045  for (SqlNode operand : call.getOperandList()) {
5046  // Operands are occasionally null, e.g. switched CASE arg 0.
5047  if (operand != null) {
5048  operand.accept(this);
5049  }
5050  }
5051  // Remove the parent aggregate level after visiting its children
5052  inOver = prevInOver;
5053  return null;
5054  }
5055 
5056  private void translateAgg(SqlCall call) {
5057  translateAgg(call, null, null, false, call);
5058  }
5059 
5060  private void translateAgg(SqlCall call,
5061  SqlNode filter,
5062  SqlNodeList orderList,
5063  boolean ignoreNulls,
5064  SqlCall outerCall) {
5065  assert bb.agg == this;
5066  assert outerCall != null;
5067  switch (call.getKind()) {
5068  case FILTER:
5069  assert filter == null;
5070  translateAgg(
5071  call.operand(0), call.operand(1), orderList, ignoreNulls, outerCall);
5072  return;
5073  case WITHIN_GROUP:
5074  assert orderList == null;
5075  translateAgg(call.operand(0), filter, call.operand(1), ignoreNulls, outerCall);
5076  return;
5077  case IGNORE_NULLS:
5078  ignoreNulls = true;
5079  // fall through
5080  case RESPECT_NULLS:
5081  translateAgg(call.operand(0), filter, orderList, ignoreNulls, outerCall);
5082  return;
5083  }
5084  final List<Integer> args = new ArrayList<>();
5085  int filterArg = -1;
5086  final List<RelDataType> argTypes = call.getOperator() instanceof SqlCountAggFunction
5087  ? new ArrayList<>(call.getOperandList().size())
5088  : null;
5089  try {
5090  // switch out of agg mode
5091  bb.agg = null;
5092  for (SqlNode operand : call.getOperandList()) {
5093  // special case for COUNT(*): delete the *
5094  if (operand instanceof SqlIdentifier) {
5095  SqlIdentifier id = (SqlIdentifier) operand;
5096  if (id.isStar()) {
5097  assert call.operandCount() == 1;
5098  assert args.isEmpty();
5099  break;
5100  }
5101  }
5102  RexNode convertedExpr = bb.convertExpression(operand);
5103  assert convertedExpr != null;
5104  if (argTypes != null) {
5105  argTypes.add(convertedExpr.getType());
5106  }
5107  args.add(lookupOrCreateGroupExpr(convertedExpr));
5108  }
5109 
5110  if (filter != null) {
5111  RexNode convertedExpr = bb.convertExpression(filter);
5112  assert convertedExpr != null;
5113  if (convertedExpr.getType().isNullable()) {
5114  convertedExpr =
5115  rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, convertedExpr);
5116  }
5117  filterArg = lookupOrCreateGroupExpr(convertedExpr);
5118  }
5119  } finally {
5120  // switch back into agg mode
5121  bb.agg = this;
5122  }
5123 
5124  SqlAggFunction aggFunction = (SqlAggFunction) call.getOperator();
5125  final RelDataType type = validator.deriveType(bb.scope, call);
5126  boolean distinct = false;
5127  SqlLiteral quantifier = call.getFunctionQuantifier();
5128  if ((null != quantifier) && (quantifier.getValue() == SqlSelectKeyword.DISTINCT)) {
5129  distinct = true;
5130  }
5131  boolean approximate = false;
5132  if (aggFunction == SqlStdOperatorTable.APPROX_COUNT_DISTINCT) {
5133  aggFunction = SqlStdOperatorTable.COUNT;
5134  distinct = true;
5135  approximate = true;
5136  }
5137  final RelCollation collation;
5138  if (orderList == null || orderList.size() == 0) {
5139  collation = RelCollations.EMPTY;
5140  } else {
5141  collation = RelCollations.of(
5142  orderList.getList()
5143  .stream()
5144  .map(order
5145  -> bb.convertSortExpression(order,
5146  RelFieldCollation.Direction.ASCENDING,
5147  RelFieldCollation.NullDirection.UNSPECIFIED))
5148  .map(fieldCollation
5149  -> new RelFieldCollation(
5150  lookupOrCreateGroupExpr(fieldCollation.left),
5151  fieldCollation.getDirection(),
5152  fieldCollation.getNullDirection()))
5153  .collect(Collectors.toList()));
5154  }
5155  final AggregateCall aggCall = AggregateCall.create(aggFunction,
5156  distinct,
5157  approximate,
5158  ignoreNulls,
5159  args,
5160  filterArg,
5161  collation,
5162  type,
5163  nameMap.get(outerCall.toString()));
5164  RexNode rex = rexBuilder.addAggCall(
5165  aggCall, groupExprs.size(), aggCalls, aggCallMapping, argTypes);
5166  aggMapping.put(outerCall, rex);
5167  }
5168 
5169  private int lookupOrCreateGroupExpr(RexNode expr) {
5170  int index = 0;
5171  for (RexNode convertedInputExpr : Pair.left(convertedInputExprs)) {
5172  if (expr.equals(convertedInputExpr)) {
5173  return index;
5174  }
5175  ++index;
5176  }
5177 
5178  // not found -- add it
5179  addExpr(expr, null);
5180  return index;
5181  }
5182 
5187  public int lookupGroupExpr(SqlNode expr) {
5188  for (int i = 0; i < groupExprs.size(); i++) {
5189  SqlNode groupExpr = groupExprs.get(i);
5190  if (expr.equalsDeep(groupExpr, Litmus.IGNORE)) {
5191  return i;
5192  }
5193  }
5194  return -1;
5195  }
5196 
5197  public RexNode lookupAggregates(SqlCall call) {
5198  // assert call.getOperator().isAggregator();
5199  assert bb.agg == this;
5200 
5201  for (Map.Entry<SqlNode, Ord<AuxiliaryConverter>> e :
5202  auxiliaryGroupExprs.entrySet()) {
5203  if (call.equalsDeep(e.getKey(), Litmus.IGNORE)) {
5204  AuxiliaryConverter converter = e.getValue().e;
5205  final int groupOrdinal = e.getValue().i;
5206  return converter.convert(rexBuilder,
5207  convertedInputExprs.get(groupOrdinal).left,
5208  rexBuilder.makeInputRef(bb.root, groupOrdinal));
5209  }
5210  }
5211 
5212  return aggMapping.get(call);
5213  }
5214 
5215  public List<Pair<RexNode, String>> getPreExprs() {
5216  return convertedInputExprs;
5217  }
5218 
5219  public List<AggregateCall> getAggCalls() {
5220  return aggCalls;
5221  }
5222 
5223  private boolean containsGroupId() {
5224  return aggCalls.stream().anyMatch(
5225  agg -> agg.getAggregation().kind == SqlKind.GROUP_ID);
5226  }
5227 
5228  public RelDataTypeFactory getTypeFactory() {
5229  return typeFactory;
5230  }
5231  }
5232 
5236  private static class LookupContext {
5237  private final List<Pair<RelNode, Integer>> relOffsetList = new ArrayList<>();
5238 
5246  LookupContext(Blackboard bb, List<RelNode> rels, int systemFieldCount) {
5247  bb.flatten(rels, systemFieldCount, new int[] {0}, relOffsetList);
5248  }
5249 
5262  Pair<RelNode, Integer> findRel(int offset) {
5263  return relOffsetList.get(offset);
5264  }
5265  }
5266 
5299  private class HistogramShuttle extends RexShuttle {
5304  static final boolean ENABLE_HISTOGRAM_AGG = false;
5305 
5306  private final List<RexNode> partitionKeys;
5307  private final ImmutableList<RexFieldCollation> orderKeys;
5308  private final RexWindowBound lowerBound;
5309  private final RexWindowBound upperBound;
5310  private final boolean rows;
5311  private final boolean allowPartial;
5312  private final boolean distinct;
5313  private final boolean ignoreNulls;
5314 
5315  HistogramShuttle(List<RexNode> partitionKeys,
5316  ImmutableList<RexFieldCollation> orderKeys,
5317  RexWindowBound lowerBound,
5318  RexWindowBound upperBound,
5319  boolean rows,
5320  boolean allowPartial,
5321  boolean distinct,
5322  boolean ignoreNulls) {
5323  this.partitionKeys = partitionKeys;
5324  this.orderKeys = orderKeys;
5325  this.lowerBound = lowerBound;
5326  this.upperBound = upperBound;
5327  this.rows = rows;
5328  this.allowPartial = allowPartial;
5329  this.distinct = distinct;
5330  this.ignoreNulls = ignoreNulls;
5331  }
5332 
5333  public RexNode visitCall(RexCall call) {
5334  final SqlOperator op = call.getOperator();
5335  if (!(op instanceof SqlAggFunction)) {
5336  return super.visitCall(call);
5337  }
5338  final SqlAggFunction aggOp = (SqlAggFunction) op;
5339  final RelDataType type = call.getType();
5340  List<RexNode> exprs = call.getOperands();
5341 
5342  SqlFunction histogramOp = !ENABLE_HISTOGRAM_AGG ? null : getHistogramOp(aggOp);
5343 
5344  if (histogramOp != null) {
5345  final RelDataType histogramType = computeHistogramType(type);
5346 
5347  // For DECIMAL, since it's already represented as a bigint we
5348  // want to do a reinterpretCast instead of a cast to avoid
5349  // losing any precision.
5350  boolean reinterpretCast = type.getSqlTypeName() == SqlTypeName.DECIMAL;
5351 
5352  // Replace original expression with CAST of not one
5353  // of the supported types
5354  if (histogramType != type) {
5355  exprs = new ArrayList<>(exprs);
5356  exprs.set(0,
5357  reinterpretCast ? rexBuilder.makeReinterpretCast(
5358  histogramType, exprs.get(0), rexBuilder.makeLiteral(false))
5359  : rexBuilder.makeCast(histogramType, exprs.get(0)));
5360  }
5361 
5362  RexCallBinding bind = new RexCallBinding(rexBuilder.getTypeFactory(),
5363  SqlStdOperatorTable.HISTOGRAM_AGG,
5364  exprs,
5365  ImmutableList.of());
5366 
5367  RexNode over = rexBuilder.makeOver(
5368  SqlStdOperatorTable.HISTOGRAM_AGG.inferReturnType(bind),
5369  SqlStdOperatorTable.HISTOGRAM_AGG,
5370  exprs,
5371  partitionKeys,
5372  orderKeys,
5373  lowerBound,
5374  upperBound,
5375  rows,
5376  allowPartial,
5377  false,
5378  distinct,
5379  ignoreNulls);
5380 
5381  RexNode histogramCall =
5382  rexBuilder.makeCall(histogramType, histogramOp, ImmutableList.of(over));
5383 
5384  // If needed, post Cast result back to original
5385  // type.
5386  if (histogramType != type) {
5387  if (reinterpretCast) {
5388  histogramCall = rexBuilder.makeReinterpretCast(
5389  type, histogramCall, rexBuilder.makeLiteral(false));
5390  } else {
5391  histogramCall = rexBuilder.makeCast(type, histogramCall);
5392  }
5393  }
5394 
5395  return histogramCall;
5396  } else {
5397  boolean needSum0 = aggOp == SqlStdOperatorTable.SUM && type.isNullable();
5398  SqlAggFunction aggOpToUse = needSum0 ? SqlStdOperatorTable.SUM0 : aggOp;
5399  return rexBuilder.makeOver(type,
5400  aggOpToUse,
5401  exprs,
5402  partitionKeys,
5403  orderKeys,
5404  lowerBound,
5405  upperBound,
5406  rows,
5407  allowPartial,
5408  needSum0,
5409  distinct,
5410  ignoreNulls);
5411  }
5412  }
5413 
5425  SqlFunction getHistogramOp(SqlAggFunction aggFunction) {
5426  if (aggFunction == SqlStdOperatorTable.MIN) {
5427  return SqlStdOperatorTable.HISTOGRAM_MIN;
5428  } else if (aggFunction == SqlStdOperatorTable.MAX) {
5429  return SqlStdOperatorTable.HISTOGRAM_MAX;
5430  } else if (aggFunction == SqlStdOperatorTable.FIRST_VALUE) {
5431  return SqlStdOperatorTable.HISTOGRAM_FIRST_VALUE;
5432  } else if (aggFunction == SqlStdOperatorTable.LAST_VALUE) {
5433  return SqlStdOperatorTable.HISTOGRAM_LAST_VALUE;
5434  } else {
5435  return null;
5436  }
5437  }
5438 
5443  private RelDataType computeHistogramType(RelDataType type) {
5444  if (SqlTypeUtil.isExactNumeric(type)
5445  && type.getSqlTypeName() != SqlTypeName.BIGINT) {
5446  return typeFactory.createSqlType(SqlTypeName.BIGINT);
5447  } else if (SqlTypeUtil.isApproximateNumeric(type)
5448  && type.getSqlTypeName() != SqlTypeName.DOUBLE) {
5449  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
5450  } else {
5451  return type;
5452  }
5453  }
5454  }
5455 
5459  private static class SubQuery {
5460  final SqlNode node;
5461  final RelOptUtil.Logic logic;
5462  RexNode expr;
5463 
5464  private SubQuery(SqlNode node, RelOptUtil.Logic logic) {
5465  this.node = node;
5466  this.logic = logic;
5467  }
5468  }
5469 
5473  private static class AggregateFinder extends SqlBasicVisitor<Void> {
5474  final SqlNodeList list = new SqlNodeList(SqlParserPos.ZERO);
5475  final SqlNodeList filterList = new SqlNodeList(SqlParserPos.ZERO);
5476  final SqlNodeList orderList = new SqlNodeList(SqlParserPos.ZERO);
5477 
5478  @Override
5479  public Void visit(SqlCall call) {
5480  // ignore window aggregates and ranking functions (associated with OVER
5481  // operator)
5482  if (call.getOperator().getKind() == SqlKind.OVER) {
5483  return null;
5484  }
5485 
5486  if (call.getOperator().getKind() == SqlKind.FILTER) {
5487  // the WHERE in a FILTER must be tracked too so we can call replaceSubQueries on
5488  // it.
5489  // see https://issues.apache.org/jira/browse/CALCITE-1910
5490  final SqlNode aggCall = call.getOperandList().get(0);
5491  final SqlNode whereCall = call.getOperandList().get(1);
5492  list.add(aggCall);
5493  filterList.add(whereCall);
5494  return null;
5495  }
5496 
5497  if (call.getOperator().getKind() == SqlKind.WITHIN_GROUP) {
5498  // the WHERE in a WITHIN_GROUP must be tracked too so we can call
5499  // replaceSubQueries on it.
5500  // see https://issues.apache.org/jira/browse/CALCITE-1910
5501  final SqlNode aggCall = call.getOperandList().get(0);
5502  final SqlNodeList orderList = (SqlNodeList) call.getOperandList().get(1);
5503  list.add(aggCall);
5504  orderList.getList().forEach(this.orderList::add);
5505  return null;
5506  }
5507 
5508  if (call.getOperator().isAggregator()) {
5509  list.add(call);
5510  return null;
5511  }
5512 
5513  // Don't traverse into sub-queries, even if they contain aggregate
5514  // functions.
5515  if (call instanceof SqlSelect) {
5516  return null;
5517  }
5518 
5519  return call.getOperator().acceptCall(this, call);
5520  }
5521  }
5522 
5526  private static class CorrelationUse {
5527  private final CorrelationId id;
5528  private final ImmutableBitSet requiredColumns;
5530  private final RelNode r;
5531 
5532  CorrelationUse(CorrelationId id, ImmutableBitSet requiredColumns, RelNode r) {
5533  this.id = id;
5534  this.requiredColumns = requiredColumns;
5535  this.r = r;
5536  }
5537  }
5538 
5540  public static ConfigBuilder configBuilder() {
5541  return new ConfigBuilder();
5542  }
5543 
5551  public interface Config {
5553  Config DEFAULT = configBuilder().build();
5554 
5559  boolean isDecorrelationEnabled();
5560 
5565  boolean isTrimUnusedFields();
5566 
5572  boolean isCreateValuesRel();
5573 
5578  boolean isExplain();
5579 
5584  boolean isExpand();
5585 
5595  int getInSubQueryThreshold();
5596 
5601  RelBuilderFactory getRelBuilderFactory();
5602 
5607  UnaryOperator<RelBuilder.Config> getRelBuilderConfigTransform();
5608 
5613  HintStrategyTable getHintStrategyTable();
5614 
5621  BiPredicate<SqlNode, SqlNode> getExpandPredicate();
5622  }
5623 
5625  public static class ConfigBuilder {
5626  private boolean decorrelationEnabled = true;
5627  private boolean trimUnusedFields = false;
5628  private boolean createValuesRel = true;
5629  private boolean explain;
5630  private boolean expand = true;
5631  private int inSubQueryThreshold = DEFAULT_IN_SUB_QUERY_THRESHOLD;
5632  private UnaryOperator<RelBuilder.Config> relBuilderConfigTransform =
5633  c -> c.withPushJoinCondition(true);
5634  private RelBuilderFactory relBuilderFactory = RelFactories.LOGICAL_BUILDER;
5635  private HintStrategyTable hintStrategyTable = HintStrategyTable.EMPTY;
5636  // MAT 08 Jan 2021 OmniSci code
5637  // pushdown join condition incurs an extra projection overhead, so remove it (21 Apr
5638  // 2021)
5639  private BiPredicate<SqlNode, SqlNode> expandPredicate;
5640  // MAT 08 Jan 2021 OmniSci code ends
5641 
5642  private ConfigBuilder() {}
5643 
5645  public ConfigBuilder withConfig(Config config) {
5646  this.decorrelationEnabled = config.isDecorrelationEnabled();
5647  this.trimUnusedFields = config.isTrimUnusedFields();
5648  this.createValuesRel = config.isCreateValuesRel();
5649  this.explain = config.isExplain();
5650  this.expand = config.isExpand();
5651  this.inSubQueryThreshold = config.getInSubQueryThreshold();
5652  this.relBuilderConfigTransform = config.getRelBuilderConfigTransform();
5653  this.relBuilderFactory = config.getRelBuilderFactory();
5654  this.hintStrategyTable = config.getHintStrategyTable();
5655 
5656  // MAT 08 Jan 2021 OmniSci code
5657  if (!(config.getExpandPredicate() instanceof ConfigImpl.DefaultExpandPredicate)) {
5658  this.expandPredicate = config.getExpandPredicate();
5659  }
5660  // MAT 08 Jan 2021 OmniSci code ends
5661  return this;
5662  }
5663 
5664  public ConfigBuilder withDecorrelationEnabled(boolean enabled) {
5665  this.decorrelationEnabled = enabled;
5666  return this;
5667  }
5668 
5669  public ConfigBuilder withTrimUnusedFields(boolean trimUnusedFields) {
5670  this.trimUnusedFields = trimUnusedFields;
5671  return this;
5672  }
5673 
5674  public ConfigBuilder withCreateValuesRel(boolean createValuesRel) {
5675  this.createValuesRel = createValuesRel;
5676  return this;
5677  }
5678 
5679  public ConfigBuilder withExplain(boolean explain) {
5680  this.explain = explain;
5681  return this;
5682  }
5683 
5684  public ConfigBuilder withExpand(boolean expand) {
5685  this.expand = expand;
5686  return this;
5687  }
5688 
5689  public ConfigBuilder withExpandPredicate(BiPredicate<SqlNode, SqlNode> predicate) {
5690  this.expandPredicate = predicate;
5691  return this;
5692  }
5693 
5695  public ConfigBuilder withPushJoinCondition(boolean pushJoinCondition) {
5696  return withRelBuilderConfigTransform(Util.andThen(relBuilderConfigTransform,
5697  c -> c.withPushJoinCondition(pushJoinCondition)));
5698  }
5699 
5700  @Deprecated // to be removed before 2.0
5701  public ConfigBuilder withInSubqueryThreshold(int inSubQueryThreshold) {
5702  return withInSubQueryThreshold(inSubQueryThreshold);
5703  }
5704 
5705  public ConfigBuilder withInSubQueryThreshold(int inSubQueryThreshold) {
5706  this.inSubQueryThreshold = inSubQueryThreshold;
5707  return this;
5708  }
5709 
5710  public ConfigBuilder withRelBuilderConfigTransform(
5711  UnaryOperator<RelBuilder.Config> relBuilderConfigTransform) {
5712  this.relBuilderConfigTransform = relBuilderConfigTransform;
5713  return this;
5714  }
5715 
5716  public ConfigBuilder withRelBuilderFactory(RelBuilderFactory relBuilderFactory) {
5717  this.relBuilderFactory = relBuilderFactory;
5718  return this;
5719  }
5720 
5721  public ConfigBuilder withHintStrategyTable(HintStrategyTable hintStrategyTable) {
5722  this.hintStrategyTable = hintStrategyTable;
5723  return this;
5724  }
5725 
5727  public Config build() {
5728  return new ConfigImpl(decorrelationEnabled,
5729  trimUnusedFields,
5730  createValuesRel,
5731  explain,
5732  expand,
5733  expandPredicate,
5734  inSubQueryThreshold,
5735  relBuilderConfigTransform,
5736  relBuilderFactory,
5737  hintStrategyTable);
5738  }
5739  }
5740 
5745  private static class ConfigImpl implements Config {
5746  private final boolean decorrelationEnabled;
5747  private final boolean trimUnusedFields;
5748  private final boolean createValuesRel;
5749  private final boolean explain;
5750  private final boolean expand;
5751  private final int inSubQueryThreshold;
5752  private final UnaryOperator<RelBuilder.Config> relBuilderConfigTransform;
5753  private final RelBuilderFactory relBuilderFactory;
5754  private final HintStrategyTable hintStrategyTable;
5755 
5756  private final BiPredicate<SqlNode, SqlNode> expandPredicate;
5757 
5758  // MAT 08 Jab 2021 Omnisci code
5759  private class DefaultExpandPredicate implements BiPredicate<SqlNode, SqlNode> {
5760  @Override
5761  public boolean test(SqlNode t, SqlNode u) {
5762  return expand;
5763  }
5764  }
5765 
5766  // MAT 08 Jan 2021 OmniSci code ends
5767 
5768  private ConfigImpl(boolean decorrelationEnabled,
5769  boolean trimUnusedFields,
5770  boolean createValuesRel,
5771  boolean explain,
5772  boolean expand,
5773  // MAT 08 Jan 2021 OmniSci code
5774  BiPredicate<SqlNode, SqlNode> expandPredicate,
5775  // MAT 08 Jan 2021 Omnisci code ends
5776  int inSubQueryThreshold,
5777  UnaryOperator<RelBuilder.Config> relBuilderConfigTransform,
5778  RelBuilderFactory relBuilderFactory,
5779  HintStrategyTable hintStrategyTable) {
5780  this.decorrelationEnabled = decorrelationEnabled;
5781  this.trimUnusedFields = trimUnusedFields;
5782  this.createValuesRel = createValuesRel;
5783  // MAT 08 Jan 2021 OmniSci code
5784  this.explain = explain;
5785  this.expand = expand;
5786  // MAT 08 Jan 2021 OmniSci code ends
5787  this.inSubQueryThreshold = inSubQueryThreshold;
5788  this.relBuilderConfigTransform = relBuilderConfigTransform;
5789  this.relBuilderFactory = relBuilderFactory;
5790  this.hintStrategyTable = hintStrategyTable;
5791  // MAT 08 Jan 2021 OmniSci code
5792  if (null == expandPredicate) {
5793  expandPredicate = new DefaultExpandPredicate();
5794  }
5795  this.expandPredicate = expandPredicate;
5796 
5797  // MAT 08 Jan 2021 OmniSci code ends
5798  }
5799 
5800  // TODO MAT 08 Jan 2021 add our added types to this equals
5801  @Override
5802  public boolean equals(Object obj) {
5803  return this == obj
5804  || obj instanceof ConfigImpl
5805  && decorrelationEnabled == ((ConfigImpl) obj).decorrelationEnabled
5806  && trimUnusedFields == ((ConfigImpl) obj).trimUnusedFields
5807  && createValuesRel == ((ConfigImpl) obj).createValuesRel
5808  && explain == ((ConfigImpl) obj).explain
5809  && expand == ((ConfigImpl) obj).expand
5810  && inSubQueryThreshold == ((ConfigImpl) obj).inSubQueryThreshold
5811  && relBuilderFactory == ((ConfigImpl) obj).relBuilderFactory
5812  && hintStrategyTable == ((ConfigImpl) obj).hintStrategyTable;
5813  }
5814 
5815  @Override
5816  public int hashCode() {
5817  return Objects.hash(decorrelationEnabled,
5818  trimUnusedFields,
5819  createValuesRel,
5820  explain,
5821  expand,
5822  inSubQueryThreshold,
5823  relBuilderFactory,
5824  hintStrategyTable);
5825  }
5826 
5827  public boolean isDecorrelationEnabled() {
5828  return decorrelationEnabled;
5829  }
5830 
5831  public boolean isTrimUnusedFields() {
5832  return trimUnusedFields;
5833  }
5834 
5835  public boolean isCreateValuesRel() {
5836  return createValuesRel;
5837  }
5838 
5839  public boolean isExplain() {
5840  return explain;
5841  }
5842 
5843  public boolean isExpand() {
5844  return expand;
5845  }
5846 
5847  public int getInSubQueryThreshold() {
5848  return inSubQueryThreshold;
5849  }
5850 
5851  public UnaryOperator<RelBuilder.Config> getRelBuilderConfigTransform() {
5852  return relBuilderConfigTransform;
5853  }
5854 
5855  public RelBuilderFactory getRelBuilderFactory() {
5856  return relBuilderFactory;
5857  }
5858 
5859  public HintStrategyTable getHintStrategyTable() {
5860  return hintStrategyTable;
5861  }
5862 
5863  // MAT 08 Jan 2021 OmniSci code
5864  public BiPredicate<SqlNode, SqlNode> getExpandPredicate() {
5865  return expandPredicate;
5866  }
5867  // MAT 08 Jan 2021 OmniSci code ends
5868  }
5869 }
RelRoot convertWith(SqlWith with, boolean top)
RelOptTable.ToRelContext createToRelContext(List< RelHint > hints)
#define DELETE
#define VALUES
#define NOT
#define INSERT
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)
#define CURSOR
RexNode convertSubQuery(SqlCall subQuery, SqlToRelConverter parentConverter, boolean isExists, boolean isExplain)
void checkConvertedType(SqlNode query, RelNode result)
#define EXISTS
RexNode translateIn(RelOptUtil.Logic logic, RelNode root, final RexNode rex)
RelNode convertCursor(Blackboard bb, SubQuery subQuery)
#define DOUBLE
string name
Definition: setup.in.py:72
RelNode convertQueryOrInList(Blackboard bb, SqlNode seek, RelDataType targetRowType)
tuple r
Definition: test_fsi.py:16
std::string join(T const &container, std::string const &delim)
#define BIGINT
RexNode castNullLiteralIfNeeded(RexNode node, RelDataType type)
RexNode ensureSqlType(RelDataType type, RexNode node)
tuple root
Definition: setup.in.py:14
void afterTableFunction(SqlToRelConverter.Blackboard bb, SqlCall call, LogicalTableFunctionScan callRel)
#define IN
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:49
RelNode decorrelate(SqlNode query, RelNode rootRel)
#define TEXT
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)
#define FIRST
RelNode createSource(RelOptTable targetTable, RelNode source, ModifiableView modifiableView, RelDataType delegateRowType)
RelNode convertRowConstructor(Blackboard bb, SqlCall rowConstructor)
#define UNION
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)
#define WITH
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)
#define ON
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)
#define LAST
#define CASE
#define SOME
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)
#define UPDATE
void convertMatchRecognize(Blackboard bb, SqlCall call)
void convertWhere(final Blackboard bb, final SqlNode where)
#define OR
RexNode convertExpression(SqlNode node, Map< String, RexNode > nameToNodeMap)
Blackboard(SqlValidatorScope scope, Map< String, RexNode > nameToNodeMap, boolean top)
char * t
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)
#define DEFAULT
char * f
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)
#define CAST
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)
#define AND
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)
if(yyssp >=yyss+yystacksize-1)
RexNode adjustInputRef(Blackboard bb, RexInputRef inputRef)
#define ALL
#define AS
#define SELECT
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)