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