OmniSciDB  b24e664e58
 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 
28 import org.apache.calcite.avatica.util.Spaces;
29 import org.apache.calcite.linq4j.Ord;
30 import org.apache.calcite.plan.Convention;
31 import org.apache.calcite.plan.RelOptCluster;
32 import org.apache.calcite.plan.RelOptPlanner;
33 import org.apache.calcite.plan.RelOptSamplingParameters;
34 import org.apache.calcite.plan.RelOptTable;
35 import org.apache.calcite.plan.RelOptUtil;
36 import org.apache.calcite.plan.RelTraitSet;
37 import org.apache.calcite.plan.ViewExpanders;
38 import org.apache.calcite.prepare.Prepare;
39 import org.apache.calcite.prepare.RelOptTableImpl;
40 import org.apache.calcite.rel.RelCollation;
41 import org.apache.calcite.rel.RelCollationTraitDef;
42 import org.apache.calcite.rel.RelCollations;
43 import org.apache.calcite.rel.RelFieldCollation;
44 import org.apache.calcite.rel.RelNode;
45 import org.apache.calcite.rel.RelRoot;
46 import org.apache.calcite.rel.SingleRel;
47 import org.apache.calcite.rel.core.AggregateCall;
48 import org.apache.calcite.rel.core.Collect;
49 import org.apache.calcite.rel.core.CorrelationId;
50 import org.apache.calcite.rel.core.Filter;
51 import org.apache.calcite.rel.core.Join;
52 import org.apache.calcite.rel.core.JoinInfo;
53 import org.apache.calcite.rel.core.JoinRelType;
54 import org.apache.calcite.rel.core.Project;
55 import org.apache.calcite.rel.core.RelFactories;
56 import org.apache.calcite.rel.core.Sample;
57 import org.apache.calcite.rel.core.Sort;
58 import org.apache.calcite.rel.core.TableScan;
59 import org.apache.calcite.rel.core.Uncollect;
60 import org.apache.calcite.rel.core.Values;
61 import org.apache.calcite.rel.logical.LogicalAggregate;
62 import org.apache.calcite.rel.logical.LogicalCorrelate;
63 import org.apache.calcite.rel.logical.LogicalFilter;
64 import org.apache.calcite.rel.logical.LogicalIntersect;
65 import org.apache.calcite.rel.logical.LogicalJoin;
66 import org.apache.calcite.rel.logical.LogicalMatch;
67 import org.apache.calcite.rel.logical.LogicalMinus;
68 import org.apache.calcite.rel.logical.LogicalProject;
69 import org.apache.calcite.rel.logical.LogicalSort;
70 import org.apache.calcite.rel.logical.LogicalTableFunctionScan;
71 import org.apache.calcite.rel.logical.LogicalTableModify;
72 import org.apache.calcite.rel.logical.LogicalTableScan;
73 import org.apache.calcite.rel.logical.LogicalUnion;
74 import org.apache.calcite.rel.logical.LogicalValues;
75 import org.apache.calcite.rel.metadata.JaninoRelMetadataProvider;
76 import org.apache.calcite.rel.metadata.RelColumnMapping;
77 import org.apache.calcite.rel.metadata.RelMetadataQuery;
78 import org.apache.calcite.rel.stream.Delta;
79 import org.apache.calcite.rel.stream.LogicalDelta;
80 import org.apache.calcite.rel.type.RelDataType;
81 import org.apache.calcite.rel.type.RelDataTypeFactory;
82 import org.apache.calcite.rel.type.RelDataTypeField;
83 import org.apache.calcite.rex.RexBuilder;
84 import org.apache.calcite.rex.RexCall;
85 import org.apache.calcite.rex.RexCallBinding;
86 import org.apache.calcite.rex.RexCorrelVariable;
87 import org.apache.calcite.rex.RexDynamicParam;
88 import org.apache.calcite.rex.RexFieldAccess;
89 import org.apache.calcite.rex.RexFieldCollation;
90 import org.apache.calcite.rex.RexInputRef;
91 import org.apache.calcite.rex.RexLiteral;
92 import org.apache.calcite.rex.RexNode;
93 import org.apache.calcite.rex.RexPatternFieldRef;
94 import org.apache.calcite.rex.RexRangeRef;
95 import org.apache.calcite.rex.RexShuttle;
96 import org.apache.calcite.rex.RexSubQuery;
97 import org.apache.calcite.rex.RexUtil;
98 import org.apache.calcite.rex.RexWindowBound;
99 import org.apache.calcite.schema.ColumnStrategy;
100 import org.apache.calcite.schema.ModifiableTable;
101 import org.apache.calcite.schema.ModifiableView;
102 import org.apache.calcite.schema.Table;
103 import org.apache.calcite.schema.TranslatableTable;
104 import org.apache.calcite.schema.Wrapper;
105 import org.apache.calcite.sql.JoinConditionType;
107 import org.apache.calcite.sql.SqlAggFunction;
108 import org.apache.calcite.sql.SqlBasicCall;
109 import org.apache.calcite.sql.SqlCall;
110 import org.apache.calcite.sql.SqlCallBinding;
111 import org.apache.calcite.sql.SqlDataTypeSpec;
112 import org.apache.calcite.sql.SqlDelete;
113 import org.apache.calcite.sql.SqlDynamicParam;
114 import org.apache.calcite.sql.SqlExplainFormat;
115 import org.apache.calcite.sql.SqlExplainLevel;
116 import org.apache.calcite.sql.SqlFunction;
117 import org.apache.calcite.sql.SqlIdentifier;
118 import org.apache.calcite.sql.SqlInsert;
119 import org.apache.calcite.sql.SqlIntervalQualifier;
120 import org.apache.calcite.sql.SqlJoin;
121 import org.apache.calcite.sql.SqlKind;
122 import org.apache.calcite.sql.SqlLiteral;
123 import org.apache.calcite.sql.SqlMatchRecognize;
124 import org.apache.calcite.sql.SqlMerge;
125 import org.apache.calcite.sql.SqlNode;
126 import org.apache.calcite.sql.SqlNodeList;
127 import org.apache.calcite.sql.SqlNumericLiteral;
128 import org.apache.calcite.sql.SqlOperator;
129 import org.apache.calcite.sql.SqlOperatorTable;
130 import org.apache.calcite.sql.SqlOrderBy;
131 import org.apache.calcite.sql.SqlSampleSpec;
132 import org.apache.calcite.sql.SqlSelect;
133 import org.apache.calcite.sql.SqlSelectKeyword;
134 import org.apache.calcite.sql.SqlSetOperator;
135 import org.apache.calcite.sql.SqlSnapshot;
136 import org.apache.calcite.sql.SqlUnnestOperator;
137 import org.apache.calcite.sql.SqlUpdate;
138 import org.apache.calcite.sql.SqlUtil;
139 import org.apache.calcite.sql.SqlValuesOperator;
140 import org.apache.calcite.sql.SqlWindow;
141 import org.apache.calcite.sql.SqlWith;
142 import org.apache.calcite.sql.SqlWithItem;
143 import org.apache.calcite.sql.fun.SqlCase;
144 import org.apache.calcite.sql.fun.SqlCountAggFunction;
145 import org.apache.calcite.sql.fun.SqlInOperator;
146 import org.apache.calcite.sql.fun.SqlQuantifyOperator;
147 import org.apache.calcite.sql.fun.SqlRowOperator;
148 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
149 import org.apache.calcite.sql.parser.SqlParserPos;
150 import org.apache.calcite.sql.type.SqlReturnTypeInference;
151 import org.apache.calcite.sql.type.SqlTypeName;
152 import org.apache.calcite.sql.type.SqlTypeUtil;
153 import org.apache.calcite.sql.type.TableFunctionReturnTypeInference;
154 import org.apache.calcite.sql.util.SqlBasicVisitor;
155 import org.apache.calcite.sql.util.SqlVisitor;
156 import org.apache.calcite.sql.validate.AggregatingSelectScope;
157 import org.apache.calcite.sql.validate.CollectNamespace;
158 import org.apache.calcite.sql.validate.DelegatingScope;
159 import org.apache.calcite.sql.validate.ListScope;
160 import org.apache.calcite.sql.validate.MatchRecognizeScope;
161 import org.apache.calcite.sql.validate.ParameterScope;
162 import org.apache.calcite.sql.validate.SelectScope;
163 import org.apache.calcite.sql.validate.SqlMonotonicity;
164 import org.apache.calcite.sql.validate.SqlNameMatcher;
165 import org.apache.calcite.sql.validate.SqlQualified;
166 import org.apache.calcite.sql.validate.SqlUserDefinedTableFunction;
167 import org.apache.calcite.sql.validate.SqlUserDefinedTableMacro;
168 import org.apache.calcite.sql.validate.SqlValidator;
169 import org.apache.calcite.sql.validate.SqlValidatorImpl;
170 import org.apache.calcite.sql.validate.SqlValidatorNamespace;
171 import org.apache.calcite.sql.validate.SqlValidatorScope;
172 import org.apache.calcite.sql.validate.SqlValidatorTable;
173 import org.apache.calcite.sql.validate.SqlValidatorUtil;
174 import org.apache.calcite.tools.RelBuilder;
175 import org.apache.calcite.tools.RelBuilderFactory;
176 import org.apache.calcite.util.ImmutableBitSet;
177 import org.apache.calcite.util.ImmutableIntList;
178 import org.apache.calcite.util.Litmus;
179 import org.apache.calcite.util.NlsString;
180 import org.apache.calcite.util.NumberUtil;
181 import org.apache.calcite.util.Pair;
182 import org.apache.calcite.util.Util;
183 import org.apache.calcite.util.trace.CalciteTrace;
184 import org.slf4j.Logger;
185 
187 import java.math.BigDecimal;
188 import java.util.AbstractList;
189 import java.util.ArrayDeque;
190 import java.util.ArrayList;
191 import java.util.BitSet;
192 import java.util.Collection;
193 import java.util.Collections;
194 import java.util.Deque;
195 import java.util.EnumSet;
196 import java.util.HashMap;
197 import java.util.HashSet;
198 import java.util.LinkedHashSet;
199 import java.util.List;
200 import java.util.Map;
201 import java.util.Objects;
202 import java.util.Set;
203 import java.util.TreeSet;
204 import java.util.function.BiPredicate;
205 import java.util.function.Supplier;
206 import java.util.stream.Collectors;
207 
217 public class SqlToRelConverter {
218  // ~ Static fields/initializers ---------------------------------------------
219 
220  protected static final Logger SQL2REL_LOGGER = CalciteTrace.getSqlToRelTracer();
221 
222  private static final BigDecimal TWO = BigDecimal.valueOf(2L);
223 
228  public static final int DEFAULT_IN_SUB_QUERY_THRESHOLD = 20;
229 
230  @Deprecated // to be removed before 2.0
232 
233  // ~ Instance fields --------------------------------------------------------
234 
235  protected final SqlValidator validator;
236  protected final RexBuilder rexBuilder;
237  protected final Prepare.CatalogReader catalogReader;
238  protected final RelOptCluster cluster;
239  private SubQueryConverter subQueryConverter;
240  protected final List<RelNode> leaves = new ArrayList<>();
241  private final List<SqlDynamicParam> dynamicParamSqlNodes = new ArrayList<>();
242  private final SqlOperatorTable opTab;
243  protected final RelDataTypeFactory typeFactory;
244  private final SqlNodeToRexConverter exprConverter;
245  private int explainParamCount;
246  public final SqlToRelConverter.Config config;
247  private final RelBuilder relBuilder;
248 
252  private final Map<CorrelationId, DeferredLookup> mapCorrelToDeferred = new HashMap<>();
253 
258  private final Deque<String> datasetStack = new ArrayDeque<>();
259 
265  private final Map<SqlNode, RexNode> mapConvertedNonCorrSubqs = new HashMap<>();
266 
267  public final RelOptTable.ViewExpander viewExpander;
268 
269  // ~ Constructors -----------------------------------------------------------
280  @Deprecated // to be removed before 2.0
281  public SqlToRelConverter(RelOptTable.ViewExpander viewExpander,
282  SqlValidator validator,
283  Prepare.CatalogReader catalogReader,
284  RelOptPlanner planner,
285  RexBuilder rexBuilder,
286  SqlRexConvertletTable convertletTable) {
287  this(viewExpander,
288  validator,
290  RelOptCluster.create(planner, rexBuilder),
291  convertletTable,
292  Config.DEFAULT);
293  }
294 
295  @Deprecated // to be removed before 2.0
296  public SqlToRelConverter(RelOptTable.ViewExpander viewExpander,
297  SqlValidator validator,
298  Prepare.CatalogReader catalogReader,
299  RelOptCluster cluster,
300  SqlRexConvertletTable convertletTable) {
301  this(viewExpander,
302  validator,
304  cluster,
305  convertletTable,
307  }
308 
309  /* Creates a converter. */
310  public SqlToRelConverter(RelOptTable.ViewExpander viewExpander,
311  SqlValidator validator,
312  Prepare.CatalogReader catalogReader,
313  RelOptCluster cluster,
314  SqlRexConvertletTable convertletTable,
315  Config config) {
316  this.viewExpander = viewExpander;
317  this.opTab = (validator == null) ? SqlStdOperatorTable.instance()
318  : validator.getOperatorTable();
319  this.validator = validator;
320  this.catalogReader = catalogReader;
321  this.subQueryConverter = new NoOpSubQueryConverter();
322  this.rexBuilder = cluster.getRexBuilder();
323  this.typeFactory = rexBuilder.getTypeFactory();
324  this.cluster = Objects.requireNonNull(cluster);
325  this.exprConverter = new SqlNodeToRexConverterImpl(convertletTable);
326  this.explainParamCount = 0;
327  this.config = new ConfigBuilder().withConfig(config).build();
328  this.relBuilder = config.getRelBuilderFactory().create(cluster, null);
329  }
330 
331  // ~ Methods ----------------------------------------------------------------
332 
336  public RelOptCluster getCluster() {
337  return cluster;
338  }
339 
343  public RexBuilder getRexBuilder() {
344  return rexBuilder;
345  }
346 
353  public int getDynamicParamCount() {
354  return dynamicParamSqlNodes.size();
355  }
356 
363  public RelDataType getDynamicParamType(int index) {
364  SqlNode sqlNode = dynamicParamSqlNodes.get(index);
365  if (sqlNode == null) {
366  throw Util.needToImplement("dynamic param type inference");
367  }
368  return validator.getValidatedNodeType(sqlNode);
369  }
370 
378  public int getDynamicParamCountInExplain(boolean increment) {
379  int retVal = explainParamCount;
380  if (increment) {
382  }
383  return retVal;
384  }
385 
390  public Map<SqlNode, RexNode> getMapConvertedNonCorrSubqs() {
392  }
393 
402  Map<SqlNode, RexNode> alreadyConvertedNonCorrSubqs) {
403  mapConvertedNonCorrSubqs.putAll(alreadyConvertedNonCorrSubqs);
404  }
405 
412  public void setSubQueryConverter(SubQueryConverter converter) {
413  subQueryConverter = converter;
414  }
415 
422  assert config.isExplain();
423  this.explainParamCount = explainParamCount;
424  }
425 
426  private void checkConvertedType(SqlNode query, RelNode result) {
427  if (query.isA(SqlKind.DML)) {
428  return;
429  }
430  // Verify that conversion from SQL to relational algebra did
431  // not perturb any type information. (We can't do this if the
432  // SQL statement is something like an INSERT which has no
433  // validator type information associated with its result,
434  // hence the namespace check above.)
435  final List<RelDataTypeField> validatedFields =
436  validator.getValidatedNodeType(query).getFieldList();
437  final RelDataType validatedRowType =
438  validator.getTypeFactory().createStructType(Pair.right(validatedFields),
439  SqlValidatorUtil.uniquify(Pair.left(validatedFields),
440  catalogReader.nameMatcher().isCaseSensitive()));
441 
442  final List<RelDataTypeField> convertedFields =
443  result.getRowType().getFieldList().subList(0, validatedFields.size());
444  final RelDataType convertedRowType =
445  validator.getTypeFactory().createStructType(convertedFields);
446 
447  if (!RelOptUtil.equal("validated row type",
448  validatedRowType,
449  "converted row type",
450  convertedRowType,
451  Litmus.IGNORE)) {
452  throw new AssertionError("Conversion to relational algebra failed to "
453  + "preserve datatypes:\n"
454  + "validated type:\n" + validatedRowType.getFullTypeString()
455  + "\nconverted type:\n" + convertedRowType.getFullTypeString() + "\nrel:\n"
456  + RelOptUtil.toString(result));
457  }
458  }
459 
460  public RelNode flattenTypes(RelNode rootRel, boolean restructure) {
461  RelStructuredTypeFlattener typeFlattener = new RelStructuredTypeFlattener(
462  relBuilder, rexBuilder, createToRelContext(), restructure);
463  return typeFlattener.rewrite(rootRel);
464  }
465 
474  public RelNode decorrelate(SqlNode query, RelNode rootRel) {
475  if (!enableDecorrelation()) {
476  return rootRel;
477  }
478  final RelNode result = decorrelateQuery(rootRel);
479  if (result != rootRel) {
480  checkConvertedType(query, result);
481  }
482  return result;
483  }
484 
507  public RelNode trimUnusedFields(boolean ordered, RelNode rootRel) {
508  // Trim fields that are not used by their consumer.
509  if (isTrimUnusedFields()) {
510  final RelFieldTrimmer trimmer = newFieldTrimmer();
511  final List<RelCollation> collations =
512  rootRel.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE);
513  rootRel = trimmer.trim(rootRel);
514  if (!ordered && collations != null && !collations.isEmpty()
515  && !collations.equals(ImmutableList.of(RelCollations.EMPTY))) {
516  final RelTraitSet traitSet =
517  rootRel.getTraitSet().replace(RelCollationTraitDef.INSTANCE, collations);
518  rootRel = rootRel.copy(traitSet, rootRel.getInputs());
519  }
520  if (SQL2REL_LOGGER.isDebugEnabled()) {
521  SQL2REL_LOGGER.debug(RelOptUtil.dumpPlan("Plan after trimming unused fields",
522  rootRel,
523  SqlExplainFormat.TEXT,
524  SqlExplainLevel.EXPPLAN_ATTRIBUTES));
525  }
526  }
527  return rootRel;
528  }
529 
535  protected RelFieldTrimmer newFieldTrimmer() {
536  return new RelFieldTrimmer(validator, relBuilder);
537  }
538 
550  public RelRoot convertQuery(
551  SqlNode query, final boolean needsValidation, final boolean top) {
552  if (needsValidation) {
553  query = validator.validate(query);
554  }
555 
556  RelMetadataQuery.THREAD_PROVIDERS.set(
557  JaninoRelMetadataProvider.of(cluster.getMetadataProvider()));
558  RelNode result = convertQueryRecursive(query, top, null).rel;
559  if (top) {
560  if (isStream(query)) {
561  result = new LogicalDelta(cluster, result.getTraitSet(), result);
562  }
563  }
564  RelCollation collation = RelCollations.EMPTY;
565  if (!query.isA(SqlKind.DML)) {
566  if (isOrdered(query)) {
567  collation = requiredCollation(result);
568  }
569  }
570  checkConvertedType(query, result);
571 
572  if (SQL2REL_LOGGER.isDebugEnabled()) {
573  SQL2REL_LOGGER.debug(RelOptUtil.dumpPlan("Plan after converting SqlNode to RelNode",
574  result,
575  SqlExplainFormat.TEXT,
576  SqlExplainLevel.EXPPLAN_ATTRIBUTES));
577  }
578 
579  final RelDataType validatedRowType = validator.getValidatedNodeType(query);
580  return RelRoot.of(result, validatedRowType, query.getKind()).withCollation(collation);
581  }
582 
583  private static boolean isStream(SqlNode query) {
584  return query instanceof SqlSelect
585  && ((SqlSelect) query).isKeywordPresent(SqlSelectKeyword.STREAM);
586  }
587 
588  public static boolean isOrdered(SqlNode query) {
589  switch (query.getKind()) {
590  case SELECT:
591  return ((SqlSelect) query).getOrderList() != null
592  && ((SqlSelect) query).getOrderList().size() > 0;
593  case WITH:
594  return isOrdered(((SqlWith) query).body);
595  case ORDER_BY:
596  return ((SqlOrderBy) query).orderList.size() > 0;
597  default:
598  return false;
599  }
600  }
601 
602  private RelCollation requiredCollation(RelNode r) {
603  if (r instanceof Sort) {
604  return ((Sort) r).collation;
605  }
606  if (r instanceof Project) {
607  return requiredCollation(((Project) r).getInput());
608  }
609  if (r instanceof Delta) {
610  return requiredCollation(((Delta) r).getInput());
611  }
612  throw new AssertionError();
613  }
614 
618  public RelNode convertSelect(SqlSelect select, boolean top) {
619  final SqlValidatorScope selectScope = validator.getWhereScope(select);
620  final Blackboard bb = createBlackboard(selectScope, null, top);
621  convertSelectImpl(bb, select);
622  return bb.root;
623  }
624 
629  SqlValidatorScope scope, Map<String, RexNode> nameToNodeMap, boolean top) {
630  return new Blackboard(scope, nameToNodeMap, top);
631  }
632 
637  protected void convertSelectImpl(final Blackboard bb, SqlSelect select) {
638  convertFrom(bb, select.getFrom());
639  convertWhere(bb, select.getWhere());
640 
641  final List<SqlNode> orderExprList = new ArrayList<>();
642  final List<RelFieldCollation> collationList = new ArrayList<>();
643  gatherOrderExprs(bb, select, select.getOrderList(), orderExprList, collationList);
644  final RelCollation collation =
645  cluster.traitSet().canonize(RelCollations.of(collationList));
646 
647  if (validator.isAggregate(select)) {
648  convertAgg(bb, select, orderExprList);
649  } else {
650  convertSelectList(bb, select, orderExprList);
651  }
652 
653  if (select.isDistinct()) {
654  distinctify(bb, true);
655  }
656  convertOrder(
657  select, bb, collation, orderExprList, select.getOffset(), select.getFetch());
658  bb.setRoot(bb.root, true);
659  }
660 
674  private void distinctify(Blackboard bb, boolean checkForDupExprs) {
675  // Look for duplicate expressions in the project.
676  // Say we have 'select x, y, x, z'.
677  // Then dups will be {[2, 0]}
678  // and oldToNew will be {[0, 0], [1, 1], [2, 0], [3, 2]}
679  RelNode rel = bb.root;
680  if (checkForDupExprs && (rel instanceof LogicalProject)) {
681  LogicalProject project = (LogicalProject) rel;
682  final List<RexNode> projectExprs = project.getProjects();
683  final List<Integer> origins = new ArrayList<>();
684  int dupCount = 0;
685  for (int i = 0; i < projectExprs.size(); i++) {
686  int x = projectExprs.indexOf(projectExprs.get(i));
687  if (x >= 0 && x < i) {
688  origins.add(x);
689  ++dupCount;
690  } else {
691  origins.add(i);
692  }
693  }
694  if (dupCount == 0) {
695  distinctify(bb, false);
696  return;
697  }
698 
699  final Map<Integer, Integer> squished = new HashMap<>();
700  final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
701  final List<Pair<RexNode, String>> newProjects = new ArrayList<>();
702  for (int i = 0; i < fields.size(); i++) {
703  if (origins.get(i) == i) {
704  squished.put(i, newProjects.size());
705  newProjects.add(RexInputRef.of2(i, fields));
706  }
707  }
708  rel = LogicalProject.create(rel, Pair.left(newProjects), Pair.right(newProjects));
709  bb.root = rel;
710  distinctify(bb, false);
711  rel = bb.root;
712 
713  // Create the expressions to reverse the mapping.
714  // Project($0, $1, $0, $2).
715  final List<Pair<RexNode, String>> undoProjects = new ArrayList<>();
716  for (int i = 0; i < fields.size(); i++) {
717  final int origin = origins.get(i);
718  RelDataTypeField field = fields.get(i);
719  undoProjects.add(
720  Pair.of((RexNode) new RexInputRef(squished.get(origin), field.getType()),
721  field.getName()));
722  }
723 
724  rel = LogicalProject.create(rel, Pair.left(undoProjects), Pair.right(undoProjects));
725  bb.setRoot(rel, false);
726 
727  return;
728  }
729 
730  // Usual case: all of the expressions in the SELECT clause are
731  // different.
732  final ImmutableBitSet groupSet =
733  ImmutableBitSet.range(rel.getRowType().getFieldCount());
734  rel = createAggregate(bb, groupSet, ImmutableList.of(groupSet), ImmutableList.of());
735 
736  bb.setRoot(rel, false);
737  }
738 
755  protected void convertOrder(SqlSelect select,
756  Blackboard bb,
757  RelCollation collation,
758  List<SqlNode> orderExprList,
759  SqlNode offset,
760  SqlNode fetch) {
761  if (!bb.top || select.getOrderList() == null
762  || select.getOrderList().getList().isEmpty()) {
763  assert !bb.top || collation.getFieldCollations().isEmpty();
764  if ((offset == null
765  || (offset instanceof SqlLiteral
766  && ((SqlLiteral) offset)
767  .bigDecimalValue()
768  .equals(BigDecimal.ZERO)))
769  && fetch == null) {
770  return;
771  }
772  }
773 
774  // Create a sorter using the previously constructed collations.
775  bb.setRoot(LogicalSort.create(bb.root,
776  collation,
777  offset == null ? null : convertExpression(offset),
778  fetch == null ? null : convertExpression(fetch)),
779  false);
780 
781  // If extra expressions were added to the project list for sorting,
782  // add another project to remove them. But make the collation empty, because
783  // we can't represent the real collation.
784  //
785  // If it is the top node, use the real collation, but don't trim fields.
786  if (orderExprList.size() > 0 && !bb.top) {
787  final List<RexNode> exprs = new ArrayList<>();
788  final RelDataType rowType = bb.root.getRowType();
789  final int fieldCount = rowType.getFieldCount() - orderExprList.size();
790  for (int i = 0; i < fieldCount; i++) {
791  exprs.add(rexBuilder.makeInputRef(bb.root, i));
792  }
793  bb.setRoot(LogicalProject.create(
794  bb.root, exprs, rowType.getFieldNames().subList(0, fieldCount)),
795  false);
796  }
797  }
798 
804  private static boolean containsInOperator(SqlNode node) {
805  try {
806  SqlVisitor<Void> visitor = new SqlBasicVisitor<Void>() {
807  public Void visit(SqlCall call) {
808  if (call.getOperator() instanceof SqlInOperator) {
809  throw new Util.FoundOne(call);
810  }
811  return super.visit(call);
812  }
813  };
814  node.accept(visitor);
815  return false;
816  } catch (Util.FoundOne e) {
817  Util.swallow(e, null);
818  return true;
819  }
820  }
821 
829  private static SqlNode pushDownNotForIn(SqlValidatorScope scope, SqlNode sqlNode) {
830  if (!(sqlNode instanceof SqlCall) || !containsInOperator(sqlNode)) {
831  return sqlNode;
832  }
833  final SqlCall sqlCall = (SqlCall) sqlNode;
834  switch (sqlCall.getKind()) {
835  case AND:
836  case OR:
837  final List<SqlNode> operands = new ArrayList<>();
838  for (SqlNode operand : sqlCall.getOperandList()) {
839  operands.add(pushDownNotForIn(scope, operand));
840  }
841  final SqlCall newCall =
842  sqlCall.getOperator().createCall(sqlCall.getParserPosition(), operands);
843  return reg(scope, newCall);
844 
845  case NOT:
846  assert sqlCall.operand(0) instanceof SqlCall;
847  final SqlCall call = sqlCall.operand(0);
848  switch (sqlCall.operand(0).getKind()) {
849  case CASE:
850  final SqlCase caseNode = (SqlCase) call;
851  final SqlNodeList thenOperands = new SqlNodeList(SqlParserPos.ZERO);
852 
853  for (SqlNode thenOperand : caseNode.getThenOperands()) {
854  final SqlCall not =
855  SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, thenOperand);
856  thenOperands.add(pushDownNotForIn(scope, reg(scope, not)));
857  }
858  SqlNode elseOperand = caseNode.getElseOperand();
859  if (!SqlUtil.isNull(elseOperand)) {
860  // "not(unknown)" is "unknown", so no need to simplify
861  final SqlCall not =
862  SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, elseOperand);
863  elseOperand = pushDownNotForIn(scope, reg(scope, not));
864  }
865 
866  return reg(scope,
867  SqlStdOperatorTable.CASE.createCall(SqlParserPos.ZERO,
868  caseNode.getValueOperand(),
869  caseNode.getWhenOperands(),
870  thenOperands,
871  elseOperand));
872 
873  case AND:
874  final List<SqlNode> orOperands = new ArrayList<>();
875  for (SqlNode operand : call.getOperandList()) {
876  orOperands.add(pushDownNotForIn(scope,
877  reg(scope,
878  SqlStdOperatorTable.NOT.createCall(
879  SqlParserPos.ZERO, operand))));
880  }
881  return reg(scope,
882  SqlStdOperatorTable.OR.createCall(SqlParserPos.ZERO, orOperands));
883 
884  case OR:
885  final List<SqlNode> andOperands = new ArrayList<>();
886  for (SqlNode operand : call.getOperandList()) {
887  andOperands.add(pushDownNotForIn(scope,
888  reg(scope,
889  SqlStdOperatorTable.NOT.createCall(
890  SqlParserPos.ZERO, operand))));
891  }
892  return reg(scope,
893  SqlStdOperatorTable.AND.createCall(SqlParserPos.ZERO, andOperands));
894 
895  case NOT:
896  assert call.operandCount() == 1;
897  return pushDownNotForIn(scope, call.operand(0));
898 
899  case NOT_IN:
900  return reg(scope,
901  SqlStdOperatorTable.IN.createCall(
902  SqlParserPos.ZERO, call.getOperandList()));
903 
904  case IN:
905  return reg(scope,
906  SqlStdOperatorTable.NOT_IN.createCall(
907  SqlParserPos.ZERO, call.getOperandList()));
908  }
909  }
910  return sqlNode;
911  }
912 
917  private static SqlNode reg(SqlValidatorScope scope, SqlNode e) {
918  scope.getValidator().deriveType(scope, e);
919  return e;
920  }
921 
928  private void convertWhere(final Blackboard bb, final SqlNode where) {
929  if (where == null) {
930  return;
931  }
932  SqlNode newWhere = pushDownNotForIn(bb.scope, where);
933  replaceSubQueries(bb, newWhere, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
934  final RexNode convertedWhere = bb.convertExpression(newWhere);
935  final RexNode convertedWhere2 =
936  RexUtil.removeNullabilityCast(typeFactory, convertedWhere);
937 
938  // only allocate filter if the condition is not TRUE
939  if (convertedWhere2.isAlwaysTrue()) {
940  return;
941  }
942 
943  final RelFactories.FilterFactory filterFactory = RelFactories.DEFAULT_FILTER_FACTORY;
944  final RelNode filter =
945  filterFactory.createFilter(bb.root, convertedWhere2, ImmutableSet.of());
946  final RelNode r;
947  final CorrelationUse p = getCorrelationUse(bb, filter);
948  if (p != null) {
949  assert p.r instanceof Filter;
950  Filter f = (Filter) p.r;
951  r = LogicalFilter.create(f.getInput(), f.getCondition(), ImmutableSet.of(p.id));
952  } else {
953  r = filter;
954  }
955 
956  bb.setRoot(r, false);
957  }
958 
959  private void replaceSubQueries(
960  final Blackboard bb, final SqlNode expr, RelOptUtil.Logic logic) {
961  findSubQueries(bb, expr, logic, false);
962  for (SubQuery node : bb.subQueryList) {
963  substituteSubQuery(bb, node);
964  }
965  }
966 
967  private void substituteSubQuery(Blackboard bb, SubQuery subQuery) {
968  final RexNode expr = subQuery.expr;
969  if (expr != null) {
970  // Already done.
971  return;
972  }
973 
974  final SqlBasicCall call;
975  final RelNode rel;
976  final SqlNode query;
977  final RelOptUtil.Exists converted;
978 
979  boolean isExpand = config.getExpandPredicate().test(bb.getTopNode(), subQuery.node);
980 
981  switch (subQuery.node.getKind()) {
982  case CURSOR:
983  convertCursor(bb, subQuery);
984  return;
985 
986  case MULTISET_QUERY_CONSTRUCTOR:
987  case MULTISET_VALUE_CONSTRUCTOR:
988  case ARRAY_QUERY_CONSTRUCTOR:
989  rel = convertMultisets(ImmutableList.of(subQuery.node), bb);
990  subQuery.expr = bb.register(rel, JoinRelType.INNER);
991  return;
992 
993  case IN:
994  case NOT_IN:
995  case SOME:
996  case ALL:
997  call = (SqlBasicCall) subQuery.node;
998  query = call.operand(1);
999  if (!isExpand && !(query instanceof SqlNodeList)) {
1000  return;
1001  }
1002  final SqlNode leftKeyNode = call.operand(0);
1003 
1004  final List<RexNode> leftKeys;
1005  switch (leftKeyNode.getKind()) {
1006  case ROW:
1007  leftKeys = new ArrayList<>();
1008  for (SqlNode sqlExpr : ((SqlBasicCall) leftKeyNode).getOperandList()) {
1009  leftKeys.add(bb.convertExpression(sqlExpr));
1010  }
1011  break;
1012  default:
1013  leftKeys = ImmutableList.of(bb.convertExpression(leftKeyNode));
1014  }
1015 
1016  if (query instanceof SqlNodeList) {
1017  SqlNodeList valueList = (SqlNodeList) query;
1018  if (!containsNullLiteral(valueList)
1019  && valueList.size() < config.getInSubQueryThreshold()) {
1020  // We're under the threshold, so convert to OR.
1021  subQuery.expr = convertInToOr(
1022  bb, leftKeys, valueList, (SqlInOperator) call.getOperator());
1023  return;
1024  }
1025 
1026  // Otherwise, let convertExists translate
1027  // values list into an inline table for the
1028  // reference to Q below.
1029  }
1030 
1031  // Project out the search columns from the left side
1032 
1033  // Q1:
1034  // "select from emp where emp.deptno in (select col1 from T)"
1035  //
1036  // is converted to
1037  //
1038  // "select from
1039  // emp inner join (select distinct col1 from T)) q
1040  // on emp.deptno = q.col1
1041  //
1042  // Q2:
1043  // "select from emp where emp.deptno not in (Q)"
1044  //
1045  // is converted to
1046  //
1047  // "select from
1048  // emp left outer join (select distinct col1, TRUE from T) q
1049  // on emp.deptno = q.col1
1050  // where emp.deptno <> null
1051  // and q.indicator <> TRUE"
1052  //
1053  // Note: Sub-query can be used as SqlUpdate#condition like below:
1054  //
1055  // UPDATE emp
1056  // SET empno = 1 WHERE emp.empno IN (
1057  // SELECT emp.empno FROM emp WHERE emp.empno = 2)
1058  //
1059  // In such case, when converting SqlUpdate#condition, bb.root is null
1060  // and it makes no sense to do the sub-query substitution.
1061  if (bb.root == null) {
1062  return;
1063  }
1064  final RelDataType targetRowType = SqlTypeUtil.promoteToRowType(
1065  typeFactory, validator.getValidatedNodeType(leftKeyNode), null);
1066  final boolean notIn = call.getOperator().kind == SqlKind.NOT_IN;
1067  converted = convertExists(
1068  query, RelOptUtil.SubQueryType.IN, subQuery.logic, notIn, targetRowType);
1069  if (converted.indicator) {
1070  // Generate
1071  // emp CROSS JOIN (SELECT COUNT(*) AS c,
1072  // COUNT(deptno) AS ck FROM dept)
1073  final RelDataType longType = typeFactory.createSqlType(SqlTypeName.BIGINT);
1074  final RelNode seek = converted.r.getInput(0); // fragile
1075  final int keyCount = leftKeys.size();
1076  final List<Integer> args = ImmutableIntList.range(0, keyCount);
1077  LogicalAggregate aggregate = LogicalAggregate.create(seek,
1078  ImmutableBitSet.of(),
1079  null,
1080  ImmutableList.of(AggregateCall.create(SqlStdOperatorTable.COUNT,
1081  false,
1082  false,
1083  false,
1084  ImmutableList.of(),
1085  -1,
1086  RelCollations.EMPTY,
1087  longType,
1088  null),
1089  AggregateCall.create(SqlStdOperatorTable.COUNT,
1090  false,
1091  false,
1092  false,
1093  args,
1094  -1,
1095  RelCollations.EMPTY,
1096  longType,
1097  null)));
1098  LogicalJoin join = LogicalJoin.create(bb.root,
1099  aggregate,
1100  rexBuilder.makeLiteral(true),
1101  ImmutableSet.of(),
1102  JoinRelType.INNER);
1103  bb.setRoot(join, false);
1104  }
1105  final RexNode rex = bb.register(converted.r,
1106  converted.outerJoin ? JoinRelType.LEFT : JoinRelType.INNER,
1107  leftKeys);
1108 
1109  RelOptUtil.Logic logic = subQuery.logic;
1110  switch (logic) {
1111  case TRUE_FALSE_UNKNOWN:
1112  case UNKNOWN_AS_TRUE:
1113  if (!converted.indicator) {
1114  logic = RelOptUtil.Logic.TRUE_FALSE;
1115  }
1116  }
1117  subQuery.expr = translateIn(logic, bb.root, rex);
1118  if (notIn) {
1119  subQuery.expr = rexBuilder.makeCall(SqlStdOperatorTable.NOT, subQuery.expr);
1120  }
1121  return;
1122 
1123  case EXISTS:
1124  // "select from emp where exists (select a from T)"
1125  //
1126  // is converted to the following if the sub-query is correlated:
1127  //
1128  // "select from emp left outer join (select AGG_TRUE() as indicator
1129  // from T group by corr_var) q where q.indicator is true"
1130  //
1131  // If there is no correlation, the expression is replaced with a
1132  // boolean indicating whether the sub-query returned 0 or >= 1 row.
1133  call = (SqlBasicCall) subQuery.node;
1134  query = call.operand(0);
1135  if (!isExpand) {
1136  return;
1137  }
1138  final SqlValidatorScope seekScope = (query instanceof SqlSelect)
1139  ? validator.getSelectScope((SqlSelect) query)
1140  : null;
1141  final Blackboard seekBb = createBlackboard(seekScope, null, false);
1142  final RelNode seekRel = convertQueryOrInList(seekBb, query, null);
1143  // An EXIST sub-query whose inner child has at least 1 tuple
1144  // (e.g. an Aggregate with no grouping columns or non-empty Values
1145  // node) should be simplified to a Boolean constant expression.
1146  final RelMetadataQuery mq = seekRel.getCluster().getMetadataQuery();
1147  final Double minRowCount = mq.getMinRowCount(seekRel);
1148  if (minRowCount != null && minRowCount >= 1D) {
1149  subQuery.expr = rexBuilder.makeLiteral(true);
1150  return;
1151  }
1152  converted = RelOptUtil.createExistsPlan(seekRel,
1153  RelOptUtil.SubQueryType.EXISTS,
1154  subQuery.logic,
1155  true,
1156  relBuilder);
1157  assert !converted.indicator;
1158  if (convertNonCorrelatedSubQuery(subQuery, bb, converted.r, true)) {
1159  return;
1160  }
1161  subQuery.expr = bb.register(converted.r, JoinRelType.LEFT);
1162  return;
1163 
1164  case SCALAR_QUERY:
1165  // Convert the sub-query. If it's non-correlated, convert it
1166  // to a constant expression.
1167  if (!isExpand) {
1168  return;
1169  }
1170  call = (SqlBasicCall) subQuery.node;
1171  query = call.operand(0);
1172  converted = convertExists(
1173  query, RelOptUtil.SubQueryType.SCALAR, subQuery.logic, true, null);
1174  assert !converted.indicator;
1175  if (convertNonCorrelatedSubQuery(subQuery, bb, converted.r, false)) {
1176  return;
1177  }
1178  rel = convertToSingleValueSubq(query, converted.r);
1179  subQuery.expr = bb.register(rel, JoinRelType.LEFT);
1180  return;
1181 
1182  case SELECT:
1183  // This is used when converting multiset queries:
1184  //
1185  // select * from unnest(select multiset[deptno] from emps);
1186  //
1187  converted = convertExists(subQuery.node,
1188  RelOptUtil.SubQueryType.SCALAR,
1189  subQuery.logic,
1190  true,
1191  null);
1192  assert !converted.indicator;
1193  subQuery.expr = bb.register(converted.r, JoinRelType.LEFT);
1194  return;
1195 
1196  default:
1197  throw new AssertionError("unexpected kind of sub-query: " + subQuery.node);
1198  }
1199  }
1200 
1201  private RexNode translateIn(RelOptUtil.Logic logic, RelNode root, final RexNode rex) {
1202  switch (logic) {
1203  case TRUE:
1204  return rexBuilder.makeLiteral(true);
1205 
1206  case TRUE_FALSE:
1207  case UNKNOWN_AS_FALSE:
1208  assert rex instanceof RexRangeRef;
1209  final int fieldCount = rex.getType().getFieldCount();
1210  RexNode rexNode = rexBuilder.makeFieldAccess(rex, fieldCount - 1);
1211  rexNode = rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, rexNode);
1212 
1213  // Then append the IS NOT NULL(leftKeysForIn).
1214  //
1215  // RexRangeRef contains the following fields:
1216  // leftKeysForIn,
1217  // rightKeysForIn (the original sub-query select list),
1218  // nullIndicator
1219  //
1220  // The first two lists contain the same number of fields.
1221  final int k = (fieldCount - 1) / 2;
1222  for (int i = 0; i < k; i++) {
1223  rexNode = rexBuilder.makeCall(SqlStdOperatorTable.AND,
1224  rexNode,
1225  rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL,
1226  rexBuilder.makeFieldAccess(rex, i)));
1227  }
1228  return rexNode;
1229 
1230  case TRUE_FALSE_UNKNOWN:
1231  case UNKNOWN_AS_TRUE:
1232  // select e.deptno,
1233  // case
1234  // when ct.c = 0 then false
1235  // when dt.i is not null then true
1236  // when e.deptno is null then null
1237  // when ct.ck < ct.c then null
1238  // else false
1239  // end
1240  // from e
1241  // cross join (select count(*) as c, count(deptno) as ck from v) as ct
1242  // left join (select distinct deptno, true as i from v) as dt
1243  // on e.deptno = dt.deptno
1244  final Join join = (Join) root;
1245  final Project left = (Project) join.getLeft();
1246  final RelNode leftLeft = ((Join) left.getInput()).getLeft();
1247  final int leftLeftCount = leftLeft.getRowType().getFieldCount();
1248  final RelDataType longType = typeFactory.createSqlType(SqlTypeName.BIGINT);
1249  final RexNode cRef = rexBuilder.makeInputRef(root, leftLeftCount);
1250  final RexNode ckRef = rexBuilder.makeInputRef(root, leftLeftCount + 1);
1251  final RexNode iRef =
1252  rexBuilder.makeInputRef(root, root.getRowType().getFieldCount() - 1);
1253 
1254  final RexLiteral zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO, longType);
1255  final RexLiteral trueLiteral = rexBuilder.makeLiteral(true);
1256  final RexLiteral falseLiteral = rexBuilder.makeLiteral(false);
1257  final RexNode unknownLiteral = rexBuilder.makeNullLiteral(trueLiteral.getType());
1258 
1259  final ImmutableList.Builder<RexNode> args = ImmutableList.builder();
1260  args.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, cRef, zero),
1261  falseLiteral,
1262  rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, iRef),
1263  trueLiteral);
1264  final JoinInfo joinInfo = join.analyzeCondition();
1265  for (int leftKey : joinInfo.leftKeys) {
1266  final RexNode kRef = rexBuilder.makeInputRef(root, leftKey);
1267  args.add(
1268  rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, kRef), unknownLiteral);
1269  }
1270  args.add(rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, ckRef, cRef),
1271  unknownLiteral,
1272  falseLiteral);
1273 
1274  return rexBuilder.makeCall(SqlStdOperatorTable.CASE, args.build());
1275 
1276  default:
1277  throw new AssertionError(logic);
1278  }
1279  }
1280 
1281  private static boolean containsNullLiteral(SqlNodeList valueList) {
1282  for (SqlNode node : valueList.getList()) {
1283  if (node instanceof SqlLiteral) {
1284  SqlLiteral lit = (SqlLiteral) node;
1285  if (lit.getValue() == null) {
1286  return true;
1287  }
1288  }
1289  }
1290  return false;
1291  }
1292 
1304  SubQuery subQuery, Blackboard bb, RelNode converted, boolean isExists) {
1305  SqlCall call = (SqlBasicCall) subQuery.node;
1306  if (subQueryConverter.canConvertSubQuery()
1307  && isSubQueryNonCorrelated(converted, bb)) {
1308  // First check if the sub-query has already been converted
1309  // because it's a nested sub-query. If so, don't re-evaluate
1310  // it again.
1311  RexNode constExpr = mapConvertedNonCorrSubqs.get(call);
1312  if (constExpr == null) {
1313  constExpr = subQueryConverter.convertSubQuery(
1314  call, this, isExists, config.isExplain());
1315  }
1316  if (constExpr != null) {
1317  subQuery.expr = constExpr;
1318  mapConvertedNonCorrSubqs.put(call, constExpr);
1319  return true;
1320  }
1321  }
1322  return false;
1323  }
1324 
1333  public RelNode convertToSingleValueSubq(SqlNode query, RelNode plan) {
1334  // Check whether query is guaranteed to produce a single value.
1335  if (query instanceof SqlSelect) {
1336  SqlSelect select = (SqlSelect) query;
1337  SqlNodeList selectList = select.getSelectList();
1338  SqlNodeList groupList = select.getGroup();
1339 
1340  if ((selectList.size() == 1) && ((groupList == null) || (groupList.size() == 0))) {
1341  SqlNode selectExpr = selectList.get(0);
1342  if (selectExpr instanceof SqlCall) {
1343  SqlCall selectExprCall = (SqlCall) selectExpr;
1344  if (Util.isSingleValue(selectExprCall)) {
1345  return plan;
1346  }
1347  }
1348 
1349  // If there is a limit with 0 or 1,
1350  // it is ensured to produce a single value
1351  if (select.getFetch() != null && select.getFetch() instanceof SqlNumericLiteral) {
1352  SqlNumericLiteral limitNum = (SqlNumericLiteral) select.getFetch();
1353  if (((BigDecimal) limitNum.getValue()).intValue() < 2) {
1354  return plan;
1355  }
1356  }
1357  }
1358  } else if (query instanceof SqlCall) {
1359  // If the query is (values ...),
1360  // it is necessary to look into the operands to determine
1361  // whether SingleValueAgg is necessary
1362  SqlCall exprCall = (SqlCall) query;
1363  if (exprCall.getOperator() instanceof SqlValuesOperator
1364  && Util.isSingleValue(exprCall)) {
1365  return plan;
1366  }
1367  }
1368 
1369  // If not, project SingleValueAgg
1370  return RelOptUtil.createSingleValueAggRel(cluster, plan);
1371  }
1372 
1381  private RexNode convertInToOr(final Blackboard bb,
1382  final List<RexNode> leftKeys,
1383  SqlNodeList valuesList,
1384  SqlInOperator op) {
1385  final List<RexNode> comparisons = new ArrayList<>();
1386  for (SqlNode rightVals : valuesList) {
1387  RexNode rexComparison;
1388  final SqlOperator comparisonOp;
1389  if (op instanceof SqlQuantifyOperator) {
1390  comparisonOp = RelOptUtil.op(
1391  ((SqlQuantifyOperator) op).comparisonKind, SqlStdOperatorTable.EQUALS);
1392  } else {
1393  comparisonOp = SqlStdOperatorTable.EQUALS;
1394  }
1395  if (leftKeys.size() == 1) {
1396  rexComparison = rexBuilder.makeCall(comparisonOp,
1397  leftKeys.get(0),
1398  ensureSqlType(
1399  leftKeys.get(0).getType(), bb.convertExpression(rightVals)));
1400  } else {
1401  assert rightVals instanceof SqlCall;
1402  final SqlBasicCall call = (SqlBasicCall) rightVals;
1403  assert (call.getOperator() instanceof SqlRowOperator)
1404  && call.operandCount() == leftKeys.size();
1405  rexComparison = RexUtil.composeConjunction(rexBuilder,
1406  Iterables.transform(Pair.zip(leftKeys, call.getOperandList()),
1407  pair
1408  -> rexBuilder.makeCall(comparisonOp,
1409  pair.left,
1410  ensureSqlType(pair.left.getType(),
1411  bb.convertExpression(pair.right)))));
1412  }
1413  comparisons.add(rexComparison);
1414  }
1415 
1416  switch (op.kind) {
1417  case ALL:
1418  return RexUtil.composeConjunction(rexBuilder, comparisons, true);
1419  case NOT_IN:
1420  return rexBuilder.makeCall(SqlStdOperatorTable.NOT,
1421  RexUtil.composeDisjunction(rexBuilder, comparisons, true));
1422  case IN:
1423  case SOME:
1424  return RexUtil.composeDisjunction(rexBuilder, comparisons, true);
1425  default:
1426  throw new AssertionError();
1427  }
1428  }
1429 
1435  private RexNode ensureSqlType(RelDataType type, RexNode node) {
1436  if (type.getSqlTypeName() == node.getType().getSqlTypeName()
1437  || (type.getSqlTypeName() == SqlTypeName.VARCHAR
1438  && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) {
1439  return node;
1440  }
1441  return rexBuilder.ensureType(type, node, true);
1442  }
1443 
1453  @Deprecated // to be removed before 2.0
1454  protected int getInSubqueryThreshold() {
1455  return config.getInSubQueryThreshold();
1456  }
1457 
1475  private RelOptUtil.Exists convertExists(SqlNode seek,
1476  RelOptUtil.SubQueryType subQueryType,
1477  RelOptUtil.Logic logic,
1478  boolean notIn,
1479  RelDataType targetDataType) {
1480  final SqlValidatorScope seekScope = (seek instanceof SqlSelect)
1481  ? validator.getSelectScope((SqlSelect) seek)
1482  : null;
1483  final Blackboard seekBb = createBlackboard(seekScope, null, false);
1484  RelNode seekRel = convertQueryOrInList(seekBb, seek, targetDataType);
1485 
1486  return RelOptUtil.createExistsPlan(seekRel, subQueryType, logic, notIn, relBuilder);
1487  }
1488 
1489  private RelNode convertQueryOrInList(
1490  Blackboard bb, SqlNode seek, RelDataType targetRowType) {
1491  // NOTE: Once we start accepting single-row queries as row constructors,
1492  // there will be an ambiguity here for a case like X IN ((SELECT Y FROM
1493  // Z)). The SQL standard resolves the ambiguity by saying that a lone
1494  // select should be interpreted as a table expression, not a row
1495  // expression. The semantic difference is that a table expression can
1496  // return multiple rows.
1497  if (seek instanceof SqlNodeList) {
1498  return convertRowValues(
1499  bb, seek, ((SqlNodeList) seek).getList(), false, targetRowType);
1500  } else {
1501  return convertQueryRecursive(seek, false, null).project();
1502  }
1503  }
1504 
1505  private RelNode convertRowValues(Blackboard bb,
1506  SqlNode rowList,
1507  Collection<SqlNode> rows,
1508  boolean allowLiteralsOnly,
1509  RelDataType targetRowType) {
1510  // NOTE jvs 30-Apr-2006: We combine all rows consisting entirely of
1511  // literals into a single LogicalValues; this gives the optimizer a smaller
1512  // input tree. For everything else (computed expressions, row
1513  // sub-queries), we union each row in as a projection on top of a
1514  // LogicalOneRow.
1515 
1516  final ImmutableList.Builder<ImmutableList<RexLiteral>> tupleList =
1517  ImmutableList.builder();
1518  final RelDataType rowType;
1519  if (targetRowType != null) {
1520  rowType = targetRowType;
1521  } else {
1522  rowType = SqlTypeUtil.promoteToRowType(
1523  typeFactory, validator.getValidatedNodeType(rowList), null);
1524  }
1525 
1526  final List<RelNode> unionInputs = new ArrayList<>();
1527  for (SqlNode node : rows) {
1528  SqlBasicCall call;
1529  if (isRowConstructor(node)) {
1530  call = (SqlBasicCall) node;
1531  ImmutableList.Builder<RexLiteral> tuple = ImmutableList.builder();
1532  for (Ord<SqlNode> operand : Ord.zip(call.operands)) {
1533  RexLiteral rexLiteral =
1534  convertLiteralInValuesList(operand.e, bb, rowType, operand.i);
1535  if ((rexLiteral == null) && allowLiteralsOnly) {
1536  return null;
1537  }
1538  if ((rexLiteral == null) || !config.isCreateValuesRel()) {
1539  // fallback to convertRowConstructor
1540  tuple = null;
1541  break;
1542  }
1543  tuple.add(rexLiteral);
1544  }
1545  if (tuple != null) {
1546  tupleList.add(tuple.build());
1547  continue;
1548  }
1549  } else {
1550  RexLiteral rexLiteral = convertLiteralInValuesList(node, bb, rowType, 0);
1551  if ((rexLiteral != null) && config.isCreateValuesRel()) {
1552  tupleList.add(ImmutableList.of(rexLiteral));
1553  continue;
1554  } else {
1555  if ((rexLiteral == null) && allowLiteralsOnly) {
1556  return null;
1557  }
1558  }
1559 
1560  // convert "1" to "row(1)"
1561  call = (SqlBasicCall) SqlStdOperatorTable.ROW.createCall(SqlParserPos.ZERO, node);
1562  }
1563  unionInputs.add(convertRowConstructor(bb, call));
1564  }
1565  LogicalValues values = LogicalValues.create(cluster, rowType, tupleList.build());
1566  RelNode resultRel;
1567  if (unionInputs.isEmpty()) {
1568  resultRel = values;
1569  } else {
1570  if (!values.getTuples().isEmpty()) {
1571  unionInputs.add(values);
1572  }
1573  resultRel = LogicalUnion.create(unionInputs, true);
1574  }
1575  leaves.add(resultRel);
1576  return resultRel;
1577  }
1578 
1579  private RexLiteral convertLiteralInValuesList(
1580  SqlNode sqlNode, Blackboard bb, RelDataType rowType, int iField) {
1581  if (!(sqlNode instanceof SqlLiteral)) {
1582  return null;
1583  }
1584  RelDataTypeField field = rowType.getFieldList().get(iField);
1585  RelDataType type = field.getType();
1586  if (type.isStruct()) {
1587  // null literals for weird stuff like UDT's need
1588  // special handling during type flattening, so
1589  // don't use LogicalValues for those
1590  return null;
1591  }
1592 
1593  RexNode literalExpr = exprConverter.convertLiteral(bb, (SqlLiteral) sqlNode);
1594 
1595  if (!(literalExpr instanceof RexLiteral)) {
1596  assert literalExpr.isA(SqlKind.CAST);
1597  RexNode child = ((RexCall) literalExpr).getOperands().get(0);
1598  assert RexLiteral.isNullLiteral(child);
1599 
1600  // NOTE jvs 22-Nov-2006: we preserve type info
1601  // in LogicalValues digest, so it's OK to lose it here
1602  return (RexLiteral) child;
1603  }
1604 
1605  RexLiteral literal = (RexLiteral) literalExpr;
1606 
1607  Comparable value = literal.getValue();
1608 
1609  if (SqlTypeUtil.isExactNumeric(type) && SqlTypeUtil.hasScale(type)) {
1610  BigDecimal roundedValue =
1611  NumberUtil.rescaleBigDecimal((BigDecimal) value, type.getScale());
1612  return rexBuilder.makeExactLiteral(roundedValue, type);
1613  }
1614 
1615  if ((value instanceof NlsString) && (type.getSqlTypeName() == SqlTypeName.CHAR)) {
1616  // pad fixed character type
1617  NlsString unpadded = (NlsString) value;
1618  return rexBuilder.makeCharLiteral(
1619  new NlsString(Spaces.padRight(unpadded.getValue(), type.getPrecision()),
1620  unpadded.getCharsetName(),
1621  unpadded.getCollation()));
1622  }
1623  return literal;
1624  }
1625 
1626  private boolean isRowConstructor(SqlNode node) {
1627  if (!(node.getKind() == SqlKind.ROW)) {
1628  return false;
1629  }
1630  SqlCall call = (SqlCall) node;
1631  return call.getOperator().getName().equalsIgnoreCase("row");
1632  }
1633 
1650  private void findSubQueries(Blackboard bb,
1651  SqlNode node,
1652  RelOptUtil.Logic logic,
1653  boolean registerOnlyScalarSubQueries) {
1654  final SqlKind kind = node.getKind();
1655  switch (kind) {
1656  case EXISTS:
1657  case SELECT:
1658  case MULTISET_QUERY_CONSTRUCTOR:
1659  case MULTISET_VALUE_CONSTRUCTOR:
1660  case ARRAY_QUERY_CONSTRUCTOR:
1661  case CURSOR:
1662  case SCALAR_QUERY:
1663  if (!registerOnlyScalarSubQueries || (kind == SqlKind.SCALAR_QUERY)) {
1664  bb.registerSubQuery(node, RelOptUtil.Logic.TRUE_FALSE);
1665  }
1666  return;
1667  case IN:
1668  break;
1669  case NOT_IN:
1670  case NOT:
1671  logic = logic.negate();
1672  break;
1673  }
1674  if (node instanceof SqlCall) {
1675  switch (kind) {
1676  // Do no change logic for AND, IN and NOT IN expressions;
1677  // but do change logic for OR, NOT and others;
1678  // EXISTS was handled already.
1679  case AND:
1680  case IN:
1681  case NOT_IN:
1682  break;
1683  default:
1684  logic = RelOptUtil.Logic.TRUE_FALSE_UNKNOWN;
1685  break;
1686  }
1687  for (SqlNode operand : ((SqlCall) node).getOperandList()) {
1688  if (operand != null) {
1689  // In the case of an IN expression, locate scalar
1690  // sub-queries so we can convert them to constants
1691  findSubQueries(bb,
1692  operand,
1693  logic,
1694  kind == SqlKind.IN || kind == SqlKind.NOT_IN || kind == SqlKind.SOME
1695  || kind == SqlKind.ALL || registerOnlyScalarSubQueries);
1696  }
1697  }
1698  } else if (node instanceof SqlNodeList) {
1699  for (SqlNode child : (SqlNodeList) node) {
1700  findSubQueries(bb,
1701  child,
1702  logic,
1703  kind == SqlKind.IN || kind == SqlKind.NOT_IN || kind == SqlKind.SOME
1704  || kind == SqlKind.ALL || registerOnlyScalarSubQueries);
1705  }
1706  }
1707 
1708  // Now that we've located any scalar sub-queries inside the IN
1709  // expression, register the IN expression itself. We need to
1710  // register the scalar sub-queries first so they can be converted
1711  // before the IN expression is converted.
1712  switch (kind) {
1713  case IN:
1714  case NOT_IN:
1715  case SOME:
1716  case ALL:
1717  switch (logic) {
1718  case TRUE_FALSE_UNKNOWN:
1719  RelDataType type = validator.getValidatedNodeTypeIfKnown(node);
1720  if (type == null) {
1721  // The node might not be validated if we still don't know type of the node.
1722  // Therefore return directly.
1723  return;
1724  } else {
1725  break;
1726  }
1727  // fall through
1728  case UNKNOWN_AS_FALSE:
1729  logic = RelOptUtil.Logic.TRUE;
1730  }
1731  bb.registerSubQuery(node, logic);
1732  break;
1733  }
1734  }
1735 
1742  public RexNode convertExpression(SqlNode node) {
1743  Map<String, RelDataType> nameToTypeMap = Collections.emptyMap();
1744  final ParameterScope scope =
1745  new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap);
1746  final Blackboard bb = createBlackboard(scope, null, false);
1747  return bb.convertExpression(node);
1748  }
1749 
1761  public RexNode convertExpression(SqlNode node, Map<String, RexNode> nameToNodeMap) {
1762  final Map<String, RelDataType> nameToTypeMap = new HashMap<>();
1763  for (Map.Entry<String, RexNode> entry : nameToNodeMap.entrySet()) {
1764  nameToTypeMap.put(entry.getKey(), entry.getValue().getType());
1765  }
1766  final ParameterScope scope =
1767  new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap);
1768  final Blackboard bb = createBlackboard(scope, nameToNodeMap, false);
1769  return bb.convertExpression(node);
1770  }
1771 
1784  protected RexNode convertExtendedExpression(SqlNode node, Blackboard bb) {
1785  return null;
1786  }
1787 
1788  private RexNode convertOver(Blackboard bb, SqlNode node) {
1789  SqlCall call = (SqlCall) node;
1790  SqlCall aggCall = call.operand(0);
1791  boolean ignoreNulls = false;
1792  switch (aggCall.getKind()) {
1793  case IGNORE_NULLS:
1794  ignoreNulls = true;
1795  // fall through
1796  case RESPECT_NULLS:
1797  aggCall = aggCall.operand(0);
1798  }
1799 
1800  SqlNode windowOrRef = call.operand(1);
1801  final SqlWindow window = validator.resolveWindow(windowOrRef, bb.scope, true);
1802 
1803  // ROW_NUMBER() expects specific kind of framing.
1804  if (aggCall.getKind() == SqlKind.ROW_NUMBER) {
1805  window.setLowerBound(SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO));
1806  window.setUpperBound(SqlWindow.createCurrentRow(SqlParserPos.ZERO));
1807  window.setRows(SqlLiteral.createBoolean(true, SqlParserPos.ZERO));
1808  }
1809  final SqlNodeList partitionList = window.getPartitionList();
1810  final ImmutableList.Builder<RexNode> partitionKeys = ImmutableList.builder();
1811  for (SqlNode partition : partitionList) {
1812  partitionKeys.add(bb.convertExpression(partition));
1813  }
1814  RexNode lowerBound = bb.convertExpression(window.getLowerBound());
1815  RexNode upperBound = bb.convertExpression(window.getUpperBound());
1816  SqlNodeList orderList = window.getOrderList();
1817  if ((orderList.size() == 0) && !window.isRows()) {
1818  // A logical range requires an ORDER BY clause. Use the implicit
1819  // ordering of this relation. There must be one, otherwise it would
1820  // have failed validation.
1821  orderList = bb.scope.getOrderList();
1822  if (orderList == null) {
1823  throw new AssertionError("Relation should have sort key for implicit ORDER BY");
1824  }
1825  }
1826 
1827  final ImmutableList.Builder<RexFieldCollation> orderKeys = ImmutableList.builder();
1828  for (SqlNode order : orderList) {
1829  orderKeys.add(bb.convertSortExpression(order,
1830  RelFieldCollation.Direction.ASCENDING,
1831  RelFieldCollation.NullDirection.UNSPECIFIED));
1832  }
1833 
1834  try {
1835  Preconditions.checkArgument(bb.window == null, "already in window agg mode");
1836  bb.window = window;
1837  RexNode rexAgg = exprConverter.convertCall(bb, aggCall);
1838  rexAgg = rexBuilder.ensureType(validator.getValidatedNodeType(call), rexAgg, false);
1839 
1840  // Walk over the tree and apply 'over' to all agg functions. This is
1841  // necessary because the returned expression is not necessarily a call
1842  // to an agg function. For example, AVG(x) becomes SUM(x) / COUNT(x).
1843 
1844  final SqlLiteral q = aggCall.getFunctionQuantifier();
1845  final boolean isDistinct = q != null && q.getValue() == SqlSelectKeyword.DISTINCT;
1846 
1847  final RexShuttle visitor = new HistogramShuttle(partitionKeys.build(),
1848  orderKeys.build(),
1849  RexWindowBound.create(window.getLowerBound(), lowerBound),
1850  RexWindowBound.create(window.getUpperBound(), upperBound),
1851  window,
1852  isDistinct,
1853  ignoreNulls);
1854  RexNode overNode = rexAgg.accept(visitor);
1855 
1856  return overNode;
1857  } finally {
1858  bb.window = null;
1859  }
1860  }
1861 
1879  protected void convertFrom(Blackboard bb, SqlNode from) {
1880  if (from == null) {
1881  bb.setRoot(LogicalValues.createOneRow(cluster), false);
1882  return;
1883  }
1884 
1885  final SqlCall call;
1886  final SqlNode[] operands;
1887  switch (from.getKind()) {
1888  case MATCH_RECOGNIZE:
1889  convertMatchRecognize(bb, (SqlCall) from);
1890  return;
1891 
1892  case AS:
1893  call = (SqlCall) from;
1894  convertFrom(bb, call.operand(0));
1895  if (call.operandCount() > 2
1896  && (bb.root instanceof Values || bb.root instanceof Uncollect)) {
1897  final List<String> fieldNames = new ArrayList<>();
1898  for (SqlNode node : Util.skip(call.getOperandList(), 2)) {
1899  fieldNames.add(((SqlIdentifier) node).getSimple());
1900  }
1901  bb.setRoot(relBuilder.push(bb.root).rename(fieldNames).build(), true);
1902  }
1903  return;
1904 
1905  case WITH_ITEM:
1906  convertFrom(bb, ((SqlWithItem) from).query);
1907  return;
1908 
1909  case WITH:
1910  convertFrom(bb, ((SqlWith) from).body);
1911  return;
1912 
1913  case TABLESAMPLE:
1914  operands = ((SqlBasicCall) from).getOperands();
1915  SqlSampleSpec sampleSpec = SqlLiteral.sampleValue(operands[1]);
1916  if (sampleSpec instanceof SqlSampleSpec.SqlSubstitutionSampleSpec) {
1917  String sampleName =
1918  ((SqlSampleSpec.SqlSubstitutionSampleSpec) sampleSpec).getName();
1919  datasetStack.push(sampleName);
1920  convertFrom(bb, operands[0]);
1921  datasetStack.pop();
1922  } else if (sampleSpec instanceof SqlSampleSpec.SqlTableSampleSpec) {
1923  SqlSampleSpec.SqlTableSampleSpec tableSampleSpec =
1924  (SqlSampleSpec.SqlTableSampleSpec) sampleSpec;
1925  convertFrom(bb, operands[0]);
1926  RelOptSamplingParameters params =
1927  new RelOptSamplingParameters(tableSampleSpec.isBernoulli(),
1928  tableSampleSpec.getSamplePercentage(),
1929  tableSampleSpec.isRepeatable(),
1930  tableSampleSpec.getRepeatableSeed());
1931  bb.setRoot(new Sample(cluster, bb.root, params), false);
1932  } else {
1933  throw new AssertionError("unknown TABLESAMPLE type: " + sampleSpec);
1934  }
1935  return;
1936 
1937  case IDENTIFIER:
1938  convertIdentifier(bb, (SqlIdentifier) from, null);
1939  return;
1940 
1941  case EXTEND:
1942  call = (SqlCall) from;
1943  SqlIdentifier id = (SqlIdentifier) call.getOperandList().get(0);
1944  SqlNodeList extendedColumns = (SqlNodeList) call.getOperandList().get(1);
1945  convertIdentifier(bb, id, extendedColumns);
1946  return;
1947 
1948  case SNAPSHOT:
1949  snapshotTemporalTable(bb, (SqlCall) from);
1950  return;
1951 
1952  case JOIN:
1953  final SqlJoin join = (SqlJoin) from;
1954  final SqlValidatorScope scope = validator.getJoinScope(from);
1955  final Blackboard fromBlackboard = createBlackboard(scope, null, false);
1956  SqlNode left = join.getLeft();
1957  SqlNode right = join.getRight();
1958  final boolean isNatural = join.isNatural();
1959  final JoinType joinType = join.getJoinType();
1960  final SqlValidatorScope leftScope = Util.first(
1961  validator.getJoinScope(left), ((DelegatingScope) bb.scope).getParent());
1962  final Blackboard leftBlackboard = createBlackboard(leftScope, null, false);
1963  final SqlValidatorScope rightScope = Util.first(
1964  validator.getJoinScope(right), ((DelegatingScope) bb.scope).getParent());
1965  final Blackboard rightBlackboard = createBlackboard(rightScope, null, false);
1966  convertFrom(leftBlackboard, left);
1967  RelNode leftRel = leftBlackboard.root;
1968  convertFrom(rightBlackboard, right);
1969  RelNode rightRel = rightBlackboard.root;
1970  JoinRelType convertedJoinType = convertJoinType(joinType);
1971  RexNode conditionExp;
1972  final SqlValidatorNamespace leftNamespace = validator.getNamespace(left);
1973  final SqlValidatorNamespace rightNamespace = validator.getNamespace(right);
1974  if (isNatural) {
1975  final RelDataType leftRowType = leftNamespace.getRowType();
1976  final RelDataType rightRowType = rightNamespace.getRowType();
1977  final List<String> columnList = SqlValidatorUtil.deriveNaturalJoinColumnList(
1978  catalogReader.nameMatcher(), leftRowType, rightRowType);
1979  conditionExp = convertUsing(leftNamespace, rightNamespace, columnList);
1980  } else {
1981  conditionExp = convertJoinCondition(fromBlackboard,
1982  leftNamespace,
1983  rightNamespace,
1984  join.getCondition(),
1985  join.getConditionType(),
1986  leftRel,
1987  rightRel);
1988  }
1989 
1990  final RelNode joinRel = createJoin(
1991  fromBlackboard, leftRel, rightRel, conditionExp, convertedJoinType);
1992  bb.setRoot(joinRel, false);
1993  return;
1994 
1995  case SELECT:
1996  case INTERSECT:
1997  case EXCEPT:
1998  case UNION:
1999  final RelNode rel = convertQueryRecursive(from, false, null).project();
2000  bb.setRoot(rel, true);
2001  return;
2002 
2003  case VALUES:
2004  convertValuesImpl(bb, (SqlCall) from, null);
2005  return;
2006 
2007  case UNNEST:
2008  call = (SqlCall) from;
2009  final List<SqlNode> nodes = call.getOperandList();
2010  final SqlUnnestOperator operator = (SqlUnnestOperator) call.getOperator();
2011  for (SqlNode node : nodes) {
2012  replaceSubQueries(bb, node, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2013  }
2014  final List<RexNode> exprs = new ArrayList<>();
2015  final List<String> fieldNames = new ArrayList<>();
2016  for (Ord<SqlNode> node : Ord.zip(nodes)) {
2017  exprs.add(bb.convertExpression(node.e));
2018  fieldNames.add(validator.deriveAlias(node.e, node.i));
2019  }
2020  RelNode child = (null != bb.root) ? bb.root : LogicalValues.createOneRow(cluster);
2021  relBuilder.push(child).projectNamed(exprs, fieldNames, false);
2022 
2023  Uncollect uncollect = new Uncollect(cluster,
2024  cluster.traitSetOf(Convention.NONE),
2025  relBuilder.build(),
2026  operator.withOrdinality);
2027  bb.setRoot(uncollect, true);
2028  return;
2029 
2030  case COLLECTION_TABLE:
2031  call = (SqlCall) from;
2032 
2033  // Dig out real call; TABLE() wrapper is just syntactic.
2034  assert call.getOperandList().size() == 1;
2035  final SqlCall call2 = call.operand(0);
2036  convertCollectionTable(bb, call2);
2037  return;
2038 
2039  default:
2040  throw new AssertionError("not a join operator " + from);
2041  }
2042  }
2043 
2044  protected void convertMatchRecognize(Blackboard bb, SqlCall call) {
2045  final SqlMatchRecognize matchRecognize = (SqlMatchRecognize) call;
2046  final SqlValidatorNamespace ns = validator.getNamespace(matchRecognize);
2047  final SqlValidatorScope scope = validator.getMatchRecognizeScope(matchRecognize);
2048 
2049  final Blackboard matchBb = createBlackboard(scope, null, false);
2050  final RelDataType rowType = ns.getRowType();
2051  // convert inner query, could be a table name or a derived table
2052  SqlNode expr = matchRecognize.getTableRef();
2053  convertFrom(matchBb, expr);
2054  final RelNode input = matchBb.root;
2055 
2056  // PARTITION BY
2057  final SqlNodeList partitionList = matchRecognize.getPartitionList();
2058  final ImmutableBitSet.Builder partitionKeys = ImmutableBitSet.builder();
2059  for (SqlNode partition : partitionList) {
2060  RexNode e = matchBb.convertExpression(partition);
2061  partitionKeys.set(((RexInputRef) e).getIndex());
2062  }
2063 
2064  // ORDER BY
2065  final SqlNodeList orderList = matchRecognize.getOrderList();
2066  final List<RelFieldCollation> orderKeys = new ArrayList<>();
2067  for (SqlNode order : orderList) {
2068  final RelFieldCollation.Direction direction;
2069  switch (order.getKind()) {
2070  case DESCENDING:
2071  direction = RelFieldCollation.Direction.DESCENDING;
2072  order = ((SqlCall) order).operand(0);
2073  break;
2074  case NULLS_FIRST:
2075  case NULLS_LAST:
2076  throw new AssertionError();
2077  default:
2078  direction = RelFieldCollation.Direction.ASCENDING;
2079  break;
2080  }
2081  final RelFieldCollation.NullDirection nullDirection =
2082  validator.getDefaultNullCollation().last(desc(direction))
2083  ? RelFieldCollation.NullDirection.LAST
2084  : RelFieldCollation.NullDirection.FIRST;
2085  RexNode e = matchBb.convertExpression(order);
2086  orderKeys.add(new RelFieldCollation(
2087  ((RexInputRef) e).getIndex(), direction, nullDirection));
2088  }
2089  final RelCollation orders = cluster.traitSet().canonize(RelCollations.of(orderKeys));
2090 
2091  // convert pattern
2092  final Set<String> patternVarsSet = new HashSet<>();
2093  SqlNode pattern = matchRecognize.getPattern();
2094  final SqlBasicVisitor<RexNode> patternVarVisitor = new SqlBasicVisitor<RexNode>() {
2095  @Override
2096  public RexNode visit(SqlCall call) {
2097  List<SqlNode> operands = call.getOperandList();
2098  List<RexNode> newOperands = new ArrayList<>();
2099  for (SqlNode node : operands) {
2100  newOperands.add(node.accept(this));
2101  }
2102  return rexBuilder.makeCall(
2103  validator.getUnknownType(), call.getOperator(), newOperands);
2104  }
2105 
2106  @Override
2107  public RexNode visit(SqlIdentifier id) {
2108  assert id.isSimple();
2109  patternVarsSet.add(id.getSimple());
2110  return rexBuilder.makeLiteral(id.getSimple());
2111  }
2112 
2113  @Override
2114  public RexNode visit(SqlLiteral literal) {
2115  if (literal instanceof SqlNumericLiteral) {
2116  return rexBuilder.makeExactLiteral(BigDecimal.valueOf(literal.intValue(true)));
2117  } else {
2118  return rexBuilder.makeLiteral(literal.booleanValue());
2119  }
2120  }
2121  };
2122  final RexNode patternNode = pattern.accept(patternVarVisitor);
2123 
2124  SqlLiteral interval = matchRecognize.getInterval();
2125  RexNode intervalNode = null;
2126  if (interval != null) {
2127  intervalNode = matchBb.convertLiteral(interval);
2128  }
2129 
2130  // convert subset
2131  final SqlNodeList subsets = matchRecognize.getSubsetList();
2132  final Map<String, TreeSet<String>> subsetMap = new HashMap<>();
2133  for (SqlNode node : subsets) {
2134  List<SqlNode> operands = ((SqlCall) node).getOperandList();
2135  SqlIdentifier left = (SqlIdentifier) operands.get(0);
2136  patternVarsSet.add(left.getSimple());
2137  SqlNodeList rights = (SqlNodeList) operands.get(1);
2138  final TreeSet<String> list = new TreeSet<>();
2139  for (SqlNode right : rights) {
2140  assert right instanceof SqlIdentifier;
2141  list.add(((SqlIdentifier) right).getSimple());
2142  }
2143  subsetMap.put(left.getSimple(), list);
2144  }
2145 
2146  SqlNode afterMatch = matchRecognize.getAfter();
2147  if (afterMatch == null) {
2148  afterMatch =
2149  SqlMatchRecognize.AfterOption.SKIP_TO_NEXT_ROW.symbol(SqlParserPos.ZERO);
2150  }
2151 
2152  final RexNode after;
2153  if (afterMatch instanceof SqlCall) {
2154  List<SqlNode> operands = ((SqlCall) afterMatch).getOperandList();
2155  SqlOperator operator = ((SqlCall) afterMatch).getOperator();
2156  assert operands.size() == 1;
2157  SqlIdentifier id = (SqlIdentifier) operands.get(0);
2158  assert patternVarsSet.contains(id.getSimple())
2159  : id.getSimple()
2160  + " not defined in pattern";
2161  RexNode rex = rexBuilder.makeLiteral(id.getSimple());
2162  after = rexBuilder.makeCall(
2163  validator.getUnknownType(), operator, ImmutableList.of(rex));
2164  } else {
2165  after = matchBb.convertExpression(afterMatch);
2166  }
2167 
2168  matchBb.setPatternVarRef(true);
2169 
2170  // convert measures
2171  final ImmutableMap.Builder<String, RexNode> measureNodes = ImmutableMap.builder();
2172  for (SqlNode measure : matchRecognize.getMeasureList()) {
2173  List<SqlNode> operands = ((SqlCall) measure).getOperandList();
2174  String alias = ((SqlIdentifier) operands.get(1)).getSimple();
2175  RexNode rex = matchBb.convertExpression(operands.get(0));
2176  measureNodes.put(alias, rex);
2177  }
2178 
2179  // convert definitions
2180  final ImmutableMap.Builder<String, RexNode> definitionNodes = ImmutableMap.builder();
2181  for (SqlNode def : matchRecognize.getPatternDefList()) {
2182  replaceSubQueries(matchBb, def, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
2183  List<SqlNode> operands = ((SqlCall) def).getOperandList();
2184  String alias = ((SqlIdentifier) operands.get(1)).getSimple();
2185  RexNode rex = matchBb.convertExpression(operands.get(0));
2186  definitionNodes.put(alias, rex);
2187  }
2188 
2189  final SqlLiteral rowsPerMatch = matchRecognize.getRowsPerMatch();
2190  final boolean allRows = rowsPerMatch != null
2191  && rowsPerMatch.getValue() == SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS;
2192 
2193  matchBb.setPatternVarRef(false);
2194 
2195  final RelFactories.MatchFactory factory = RelFactories.DEFAULT_MATCH_FACTORY;
2196  final RelNode rel = factory.createMatch(input,
2197  patternNode,
2198  rowType,
2199  matchRecognize.getStrictStart().booleanValue(),
2200  matchRecognize.getStrictEnd().booleanValue(),
2201  definitionNodes.build(),
2202  measureNodes.build(),
2203  after,
2204  subsetMap,
2205  allRows,
2206  partitionKeys.build(),
2207  orders,
2208  intervalNode);
2209  bb.setRoot(rel, false);
2210  }
2211 
2212  private void convertIdentifier(
2213  Blackboard bb, SqlIdentifier id, SqlNodeList extendedColumns) {
2214  final SqlValidatorNamespace fromNamespace = validator.getNamespace(id).resolve();
2215  if (fromNamespace.getNode() != null) {
2216  convertFrom(bb, fromNamespace.getNode());
2217  return;
2218  }
2219  final String datasetName = datasetStack.isEmpty() ? null : datasetStack.peek();
2220  final boolean[] usedDataset = {false};
2221  RelOptTable table = SqlValidatorUtil.getRelOptTable(
2222  fromNamespace, catalogReader, datasetName, usedDataset);
2223  if (extendedColumns != null && extendedColumns.size() > 0) {
2224  assert table != null;
2225  final SqlValidatorTable validatorTable = table.unwrap(SqlValidatorTable.class);
2226  final List<RelDataTypeField> extendedFields = SqlValidatorUtil.getExtendedColumns(
2227  validator, validatorTable, extendedColumns);
2228  table = table.extend(extendedFields);
2229  }
2230  final RelNode tableRel;
2231  if (config.isConvertTableAccess()) {
2232  tableRel = toRel(table);
2233  } else {
2234  tableRel = LogicalTableScan.create(cluster, table);
2235  }
2236  bb.setRoot(tableRel, true);
2237  if (usedDataset[0]) {
2238  bb.setDataset(datasetName);
2239  }
2240  }
2241 
2242  protected void convertCollectionTable(Blackboard bb, SqlCall call) {
2243  final SqlOperator operator = call.getOperator();
2244  if (operator == SqlStdOperatorTable.TABLESAMPLE) {
2245  final String sampleName =
2246  SqlLiteral.unchain(call.operand(0)).getValueAs(String.class);
2247  datasetStack.push(sampleName);
2248  SqlCall cursorCall = call.operand(1);
2249  SqlNode query = cursorCall.operand(0);
2250  RelNode converted = convertQuery(query, false, false).rel;
2251  bb.setRoot(converted, false);
2252  datasetStack.pop();
2253  return;
2254  }
2255  replaceSubQueries(bb, call, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2256 
2257  // Expand table macro if possible. It's more efficient than
2258  // LogicalTableFunctionScan.
2259  final SqlCallBinding callBinding =
2260  new SqlCallBinding(bb.scope.getValidator(), bb.scope, call);
2261  if (operator instanceof SqlUserDefinedTableMacro) {
2262  final SqlUserDefinedTableMacro udf = (SqlUserDefinedTableMacro) operator;
2263  final TranslatableTable table = udf.getTable(typeFactory, callBinding.operands());
2264  final RelDataType rowType = table.getRowType(typeFactory);
2265  RelOptTable relOptTable =
2266  RelOptTableImpl.create(null, rowType, table, udf.getNameAsId().names);
2267  RelNode converted = toRel(relOptTable);
2268  bb.setRoot(converted, true);
2269  return;
2270  }
2271 
2272  Type elementType;
2273  if (operator instanceof SqlUserDefinedTableFunction) {
2274  SqlUserDefinedTableFunction udtf = (SqlUserDefinedTableFunction) operator;
2275  elementType = udtf.getElementType(typeFactory, callBinding.operands());
2276  } else {
2277  elementType = null;
2278  }
2279 
2280  RexNode rexCall = bb.convertExpression(call);
2281  final List<RelNode> inputs = bb.retrieveCursors();
2282  Set<RelColumnMapping> columnMappings = getColumnMappings(operator);
2283  LogicalTableFunctionScan callRel = LogicalTableFunctionScan.create(cluster,
2284  inputs,
2285  rexCall,
2286  elementType,
2287  validator.getValidatedNodeType(call),
2288  columnMappings);
2289  bb.setRoot(callRel, true);
2290  afterTableFunction(bb, call, callRel);
2291  }
2292 
2293  protected void afterTableFunction(SqlToRelConverter.Blackboard bb,
2294  SqlCall call,
2295  LogicalTableFunctionScan callRel) {}
2296 
2297  private void snapshotTemporalTable(Blackboard bb, SqlCall call) {
2298  final SqlSnapshot snapshot = (SqlSnapshot) call;
2299  final RexNode period = bb.convertExpression(snapshot.getPeriod());
2300 
2301  // convert inner query, could be a table name or a derived table
2302  SqlNode expr = snapshot.getTableRef();
2303  convertFrom(bb, expr);
2304  final TableScan scan = (TableScan) bb.root;
2305 
2306  final RelNode snapshotRel = relBuilder.push(scan).snapshot(period).build();
2307 
2308  bb.setRoot(snapshotRel, false);
2309  }
2310 
2311  private Set<RelColumnMapping> getColumnMappings(SqlOperator op) {
2312  SqlReturnTypeInference rti = op.getReturnTypeInference();
2313  if (rti == null) {
2314  return null;
2315  }
2316  if (rti instanceof TableFunctionReturnTypeInference) {
2317  TableFunctionReturnTypeInference tfrti = (TableFunctionReturnTypeInference) rti;
2318  return tfrti.getColumnMappings();
2319  } else {
2320  return null;
2321  }
2322  }
2323 
2329  private static class RexAccessShuttle extends RexShuttle {
2330  private final RexBuilder builder;
2331  private final RexCorrelVariable rexCorrel;
2332  private final BitSet varCols = new BitSet();
2333 
2334  RexAccessShuttle(RexBuilder builder, RexCorrelVariable rexCorrel) {
2335  this.builder = builder;
2336  this.rexCorrel = rexCorrel;
2337  }
2338 
2339  @Override
2340  public RexNode visitInputRef(RexInputRef input) {
2341  int i = input.getIndex() - rexCorrel.getType().getFieldCount();
2342  if (i < 0) {
2343  varCols.set(input.getIndex());
2344  return builder.makeFieldAccess(rexCorrel, input.getIndex());
2345  }
2346  return builder.makeInputRef(input.getType(), i);
2347  }
2348  }
2349 
2350  protected RelNode createJoin(Blackboard bb,
2351  RelNode leftRel,
2352  RelNode rightRel,
2353  RexNode joinCond,
2354  JoinRelType joinType) {
2355  assert joinCond != null;
2356 
2357  final CorrelationUse p = getCorrelationUse(bb, rightRel);
2358  if (p != null) {
2359  RelNode innerRel = p.r;
2360  ImmutableBitSet requiredCols = p.requiredColumns;
2361 
2362  if (!joinCond.isAlwaysTrue()) {
2363  final RelFactories.FilterFactory factory = RelFactories.DEFAULT_FILTER_FACTORY;
2364  final RexCorrelVariable rexCorrel =
2365  (RexCorrelVariable) rexBuilder.makeCorrel(leftRel.getRowType(), p.id);
2366  final RexAccessShuttle shuttle = new RexAccessShuttle(rexBuilder, rexCorrel);
2367 
2368  // Replace outer RexInputRef with RexFieldAccess,
2369  // and push lateral join predicate into inner child
2370  final RexNode newCond = joinCond.accept(shuttle);
2371  innerRel = factory.createFilter(p.r, newCond, ImmutableSet.of());
2372  requiredCols =
2373  ImmutableBitSet.fromBitSet(shuttle.varCols).union(p.requiredColumns);
2374  }
2375 
2376  LogicalCorrelate corr =
2377  LogicalCorrelate.create(leftRel, innerRel, p.id, requiredCols, joinType);
2378  return corr;
2379  }
2380 
2381  final Join originalJoin = (Join) RelFactories.DEFAULT_JOIN_FACTORY.createJoin(
2382  leftRel, rightRel, joinCond, ImmutableSet.of(), joinType, false);
2383 
2384  boolean applyPushdown =
2385  config.getPushdownJoinCondition().test(bb.getTopNode(), originalJoin);
2386  if (applyPushdown) {
2387  return RelOptUtil.pushDownJoinConditions(originalJoin, relBuilder);
2388  } else {
2389  return originalJoin;
2390  }
2391  }
2392 
2393  private CorrelationUse getCorrelationUse(Blackboard bb, final RelNode r0) {
2394  final Set<CorrelationId> correlatedVariables = RelOptUtil.getVariablesUsed(r0);
2395  if (correlatedVariables.isEmpty()) {
2396  return null;
2397  }
2398  final ImmutableBitSet.Builder requiredColumns = ImmutableBitSet.builder();
2399  final List<CorrelationId> correlNames = new ArrayList<>();
2400 
2401  // All correlations must refer the same namespace since correlation
2402  // produces exactly one correlation source.
2403  // The same source might be referenced by different variables since
2404  // DeferredLookups are not de-duplicated at create time.
2405  SqlValidatorNamespace prevNs = null;
2406 
2407  for (CorrelationId correlName : correlatedVariables) {
2408  DeferredLookup lookup = mapCorrelToDeferred.get(correlName);
2409  RexFieldAccess fieldAccess = lookup.getFieldAccess(correlName);
2410  String originalRelName = lookup.getOriginalRelName();
2411  String originalFieldName = fieldAccess.getField().getName();
2412 
2413  final SqlNameMatcher nameMatcher =
2414  bb.getValidator().getCatalogReader().nameMatcher();
2415  final SqlValidatorScope.ResolvedImpl resolved =
2416  new SqlValidatorScope.ResolvedImpl();
2417  lookup.bb.scope.resolve(
2418  ImmutableList.of(originalRelName), nameMatcher, false, resolved);
2419  assert resolved.count() == 1;
2420  final SqlValidatorScope.Resolve resolve = resolved.only();
2421  final SqlValidatorNamespace foundNs = resolve.namespace;
2422  final RelDataType rowType = resolve.rowType();
2423  final int childNamespaceIndex = resolve.path.steps().get(0).i;
2424  final SqlValidatorScope ancestorScope = resolve.scope;
2425  boolean correlInCurrentScope = bb.scope.isWithin(ancestorScope);
2426 
2427  if (!correlInCurrentScope) {
2428  continue;
2429  }
2430 
2431  if (prevNs == null) {
2432  prevNs = foundNs;
2433  } else {
2434  assert prevNs
2435  == foundNs : "All correlation variables should resolve"
2436  + " to the same namespace."
2437  + " Prev ns="
2438  + prevNs
2439  + ", new ns="
2440  + foundNs;
2441  }
2442 
2443  int namespaceOffset = 0;
2444  if (childNamespaceIndex > 0) {
2445  // If not the first child, need to figure out the width
2446  // of output types from all the preceding namespaces
2447  assert ancestorScope instanceof ListScope;
2448  List<SqlValidatorNamespace> children = ((ListScope) ancestorScope).getChildren();
2449 
2450  for (int i = 0; i < childNamespaceIndex; i++) {
2451  SqlValidatorNamespace child = children.get(i);
2452  namespaceOffset += child.getRowType().getFieldCount();
2453  }
2454  }
2455 
2456  RexFieldAccess topLevelFieldAccess = fieldAccess;
2457  while (topLevelFieldAccess.getReferenceExpr() instanceof RexFieldAccess) {
2458  topLevelFieldAccess = (RexFieldAccess) topLevelFieldAccess.getReferenceExpr();
2459  }
2460  final RelDataTypeField field = rowType.getFieldList().get(
2461  topLevelFieldAccess.getField().getIndex() - namespaceOffset);
2462  int pos = namespaceOffset + field.getIndex();
2463 
2464  assert field.getType() == topLevelFieldAccess.getField().getType();
2465 
2466  assert pos != -1;
2467 
2468  if (bb.mapRootRelToFieldProjection.containsKey(bb.root)) {
2469  // bb.root is an aggregate and only projects group by
2470  // keys.
2471  Map<Integer, Integer> exprProjection =
2472  bb.mapRootRelToFieldProjection.get(bb.root);
2473 
2474  // sub-query can reference group by keys projected from
2475  // the root of the outer relation.
2476  if (exprProjection.containsKey(pos)) {
2477  pos = exprProjection.get(pos);
2478  } else {
2479  // correl not grouped
2480  throw new AssertionError("Identifier '" + originalRelName + "."
2481  + originalFieldName + "' is not a group expr");
2482  }
2483  }
2484 
2485  requiredColumns.set(pos);
2486  correlNames.add(correlName);
2487  }
2488 
2489  if (correlNames.isEmpty()) {
2490  // None of the correlating variables originated in this scope.
2491  return null;
2492  }
2493 
2494  RelNode r = r0;
2495  if (correlNames.size() > 1) {
2496  // The same table was referenced more than once.
2497  // So we deduplicate.
2498  r = DeduplicateCorrelateVariables.go(
2499  rexBuilder, correlNames.get(0), Util.skip(correlNames), r0);
2500  // Add new node to leaves.
2501  leaves.add(r);
2502  }
2503  return new CorrelationUse(correlNames.get(0), requiredColumns.build(), r);
2504  }
2505 
2516  private boolean isSubQueryNonCorrelated(RelNode subq, Blackboard bb) {
2517  Set<CorrelationId> correlatedVariables = RelOptUtil.getVariablesUsed(subq);
2518  for (CorrelationId correlName : correlatedVariables) {
2519  DeferredLookup lookup = mapCorrelToDeferred.get(correlName);
2520  String originalRelName = lookup.getOriginalRelName();
2521 
2522  final SqlNameMatcher nameMatcher =
2523  lookup.bb.scope.getValidator().getCatalogReader().nameMatcher();
2524  final SqlValidatorScope.ResolvedImpl resolved =
2525  new SqlValidatorScope.ResolvedImpl();
2526  lookup.bb.scope.resolve(
2527  ImmutableList.of(originalRelName), nameMatcher, false, resolved);
2528 
2529  SqlValidatorScope ancestorScope = resolved.only().scope;
2530 
2531  // If the correlated reference is in a scope that's "above" the
2532  // sub-query, then this is a correlated sub-query.
2533  SqlValidatorScope parentScope = bb.scope;
2534  do {
2535  if (ancestorScope == parentScope) {
2536  return false;
2537  }
2538  if (parentScope instanceof DelegatingScope) {
2539  parentScope = ((DelegatingScope) parentScope).getParent();
2540  } else {
2541  break;
2542  }
2543  } while (parentScope != null);
2544  }
2545  return true;
2546  }
2547 
2553  protected List<RelDataTypeField> getSystemFields() {
2554  return Collections.emptyList();
2555  }
2556 
2557  private RexNode convertJoinCondition(Blackboard bb,
2558  SqlValidatorNamespace leftNamespace,
2559  SqlValidatorNamespace rightNamespace,
2560  SqlNode condition,
2561  JoinConditionType conditionType,
2562  RelNode leftRel,
2563  RelNode rightRel) {
2564  if (condition == null) {
2565  return rexBuilder.makeLiteral(true);
2566  }
2567  bb.setRoot(ImmutableList.of(leftRel, rightRel));
2568  replaceSubQueries(bb, condition, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
2569  switch (conditionType) {
2570  case ON:
2571  bb.setRoot(ImmutableList.of(leftRel, rightRel));
2572  return bb.convertExpression(condition);
2573  case USING:
2574  final SqlNodeList list = (SqlNodeList) condition;
2575  final List<String> nameList = new ArrayList<>();
2576  for (SqlNode columnName : list) {
2577  final SqlIdentifier id = (SqlIdentifier) columnName;
2578  String name = id.getSimple();
2579  nameList.add(name);
2580  }
2581  return convertUsing(leftNamespace, rightNamespace, nameList);
2582  default:
2583  throw Util.unexpected(conditionType);
2584  }
2585  }
2586 
2598  private RexNode convertUsing(SqlValidatorNamespace leftNamespace,
2599  SqlValidatorNamespace rightNamespace,
2600  List<String> nameList) {
2601  final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
2602  final List<RexNode> list = new ArrayList<>();
2603  for (String name : nameList) {
2604  List<RexNode> operands = new ArrayList<>();
2605  int offset = 0;
2606  for (SqlValidatorNamespace n : ImmutableList.of(leftNamespace, rightNamespace)) {
2607  final RelDataType rowType = n.getRowType();
2608  final RelDataTypeField field = nameMatcher.field(rowType, name);
2609  operands.add(rexBuilder.makeInputRef(field.getType(), offset + field.getIndex()));
2610  offset += rowType.getFieldList().size();
2611  }
2612  list.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, operands));
2613  }
2614  return RexUtil.composeConjunction(rexBuilder, list);
2615  }
2616 
2617  private static JoinRelType convertJoinType(JoinType joinType) {
2618  switch (joinType) {
2619  case COMMA:
2620  case INNER:
2621  case CROSS:
2622  return JoinRelType.INNER;
2623  case FULL:
2624  return JoinRelType.FULL;
2625  case LEFT:
2626  return JoinRelType.LEFT;
2627  case RIGHT:
2628  return JoinRelType.RIGHT;
2629  default:
2630  throw Util.unexpected(joinType);
2631  }
2632  }
2633 
2647  protected void convertAgg(
2648  Blackboard bb, SqlSelect select, List<SqlNode> orderExprList) {
2649  assert bb.root != null : "precondition: child != null";
2650  SqlNodeList groupList = select.getGroup();
2651  SqlNodeList selectList = select.getSelectList();
2652  SqlNode having = select.getHaving();
2653 
2654  final AggConverter aggConverter = new AggConverter(bb, select);
2655  createAggImpl(bb, aggConverter, selectList, groupList, having, orderExprList);
2656  }
2657 
2658  protected final void createAggImpl(Blackboard bb,
2659  final AggConverter aggConverter,
2660  SqlNodeList selectList,
2661  SqlNodeList groupList,
2662  SqlNode having,
2663  List<SqlNode> orderExprList) {
2664  // Find aggregate functions in SELECT and HAVING clause
2665  final AggregateFinder aggregateFinder = new AggregateFinder();
2666  selectList.accept(aggregateFinder);
2667  if (having != null) {
2668  having.accept(aggregateFinder);
2669  }
2670 
2671  // first replace the sub-queries inside the aggregates
2672  // because they will provide input rows to the aggregates.
2673  replaceSubQueries(bb, aggregateFinder.list, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2674 
2675  // also replace sub-queries inside filters in the aggregates
2677  bb, aggregateFinder.filterList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2678 
2679  // also replace sub-queries inside ordering spec in the aggregates
2680  replaceSubQueries(bb, aggregateFinder.orderList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2681 
2682  // If group-by clause is missing, pretend that it has zero elements.
2683  if (groupList == null) {
2684  groupList = SqlNodeList.EMPTY;
2685  }
2686 
2687  replaceSubQueries(bb, groupList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2688 
2689  // register the group exprs
2690 
2691  // build a map to remember the projections from the top scope to the
2692  // output of the current root.
2693  //
2694  // Calcite allows expressions, not just column references in
2695  // group by list. This is not SQL 2003 compliant, but hey.
2696 
2697  final AggregatingSelectScope scope = aggConverter.aggregatingSelectScope;
2698  final AggregatingSelectScope.Resolved r = scope.resolved.get();
2699  for (SqlNode groupExpr : r.groupExprList) {
2700  aggConverter.addGroupExpr(groupExpr);
2701  }
2702 
2703  final RexNode havingExpr;
2704  final List<Pair<RexNode, String>> projects = new ArrayList<>();
2705 
2706  try {
2707  Preconditions.checkArgument(bb.agg == null, "already in agg mode");
2708  bb.agg = aggConverter;
2709 
2710  // convert the select and having expressions, so that the
2711  // agg converter knows which aggregations are required
2712 
2713  selectList.accept(aggConverter);
2714  // Assert we don't have dangling items left in the stack
2715  assert !aggConverter.inOver;
2716  for (SqlNode expr : orderExprList) {
2717  expr.accept(aggConverter);
2718  assert !aggConverter.inOver;
2719  }
2720  if (having != null) {
2721  having.accept(aggConverter);
2722  assert !aggConverter.inOver;
2723  }
2724 
2725  // compute inputs to the aggregator
2726  List<Pair<RexNode, String>> preExprs = aggConverter.getPreExprs();
2727 
2728  if (preExprs.size() == 0) {
2729  // Special case for COUNT(*), where we can end up with no inputs
2730  // at all. The rest of the system doesn't like 0-tuples, so we
2731  // select a dummy constant here.
2732  final RexNode zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO);
2733  preExprs = ImmutableList.of(Pair.of(zero, (String) null));
2734  }
2735 
2736  final RelNode inputRel = bb.root;
2737 
2738  // Project the expressions required by agg and having.
2739  bb.setRoot(relBuilder.push(inputRel)
2740  .projectNamed(Pair.left(preExprs), Pair.right(preExprs), false)
2741  .build(),
2742  false);
2743  bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
2744 
2745  // REVIEW jvs 31-Oct-2007: doesn't the declaration of
2746  // monotonicity here assume sort-based aggregation at
2747  // the physical level?
2748 
2749  // Tell bb which of group columns are sorted.
2750  bb.columnMonotonicities.clear();
2751  for (SqlNode groupItem : groupList) {
2752  bb.columnMonotonicities.add(bb.scope.getMonotonicity(groupItem));
2753  }
2754 
2755  // Add the aggregator
2756  bb.setRoot(createAggregate(bb, r.groupSet, r.groupSets, aggConverter.getAggCalls()),
2757  false);
2758 
2759  bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
2760 
2761  // Replace sub-queries in having here and modify having to use
2762  // the replaced expressions
2763  if (having != null) {
2764  SqlNode newHaving = pushDownNotForIn(bb.scope, having);
2765  replaceSubQueries(bb, newHaving, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
2766  havingExpr = bb.convertExpression(newHaving);
2767  } else {
2768  havingExpr = relBuilder.literal(true);
2769  }
2770 
2771  // Now convert the other sub-queries in the select list.
2772  // This needs to be done separately from the sub-query inside
2773  // any aggregate in the select list, and after the aggregate rel
2774  // is allocated.
2775  replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2776 
2777  // Now sub-queries in the entire select list have been converted.
2778  // Convert the select expressions to get the final list to be
2779  // projected.
2780  int k = 0;
2781 
2782  // For select expressions, use the field names previously assigned
2783  // by the validator. If we derive afresh, we might generate names
2784  // like "EXPR$2" that don't match the names generated by the
2785  // validator. This is especially the case when there are system
2786  // fields; system fields appear in the relnode's rowtype but do not
2787  // (yet) appear in the validator type.
2788  final SelectScope selectScope = SqlValidatorUtil.getEnclosingSelectScope(bb.scope);
2789  assert selectScope != null;
2790  final SqlValidatorNamespace selectNamespace =
2791  validator.getNamespace(selectScope.getNode());
2792  final List<String> names = selectNamespace.getRowType().getFieldNames();
2793  int sysFieldCount = selectList.size() - names.size();
2794  for (SqlNode expr : selectList) {
2795  projects.add(Pair.of(bb.convertExpression(expr),
2796  k < sysFieldCount ? validator.deriveAlias(expr, k++)
2797  : names.get(k++ - sysFieldCount)));
2798  }
2799 
2800  for (SqlNode expr : orderExprList) {
2801  projects.add(
2802  Pair.of(bb.convertExpression(expr), validator.deriveAlias(expr, k++)));
2803  }
2804  } finally {
2805  bb.agg = null;
2806  }
2807 
2808  // implement HAVING (we have already checked that it is non-trivial)
2809  relBuilder.push(bb.root);
2810  if (havingExpr != null) {
2811  relBuilder.filter(havingExpr);
2812  }
2813 
2814  // implement the SELECT list
2815  relBuilder.project(Pair.left(projects), Pair.right(projects))
2816  .rename(Pair.right(projects));
2817  bb.setRoot(relBuilder.build(), false);
2818 
2819  // Tell bb which of group columns are sorted.
2820  bb.columnMonotonicities.clear();
2821  for (SqlNode selectItem : selectList) {
2822  bb.columnMonotonicities.add(bb.scope.getMonotonicity(selectItem));
2823  }
2824  }
2825 
2845  protected RelNode createAggregate(Blackboard bb,
2846  ImmutableBitSet groupSet,
2847  ImmutableList<ImmutableBitSet> groupSets,
2848  List<AggregateCall> aggCalls) {
2849  return LogicalAggregate.create(bb.root, groupSet, groupSets, aggCalls);
2850  }
2851 
2852  public RexDynamicParam convertDynamicParam(final SqlDynamicParam dynamicParam) {
2853  // REVIEW jvs 8-Jan-2005: dynamic params may be encountered out of
2854  // order. Should probably cross-check with the count from the parser
2855  // at the end and make sure they all got filled in. Why doesn't List
2856  // have a resize() method?!? Make this a utility.
2857  while (dynamicParam.getIndex() >= dynamicParamSqlNodes.size()) {
2858  dynamicParamSqlNodes.add(null);
2859  }
2860 
2861  dynamicParamSqlNodes.set(dynamicParam.getIndex(), dynamicParam);
2862  return rexBuilder.makeDynamicParam(
2863  getDynamicParamType(dynamicParam.getIndex()), dynamicParam.getIndex());
2864  }
2865 
2880  protected void gatherOrderExprs(Blackboard bb,
2881  SqlSelect select,
2882  SqlNodeList orderList,
2883  List<SqlNode> extraOrderExprs,
2884  List<RelFieldCollation> collationList) {
2885  // TODO: add validation rules to SqlValidator also
2886  assert bb.root != null : "precondition: child != null";
2887  assert select != null;
2888  if (orderList == null) {
2889  return;
2890  }
2891 
2892  if (!bb.top) {
2893  SqlNode offset = select.getOffset();
2894  if ((offset == null
2895  || (offset instanceof SqlLiteral
2896  && ((SqlLiteral) offset)
2897  .bigDecimalValue()
2898  .equals(BigDecimal.ZERO)))
2899  && select.getFetch() == null) {
2900  return;
2901  }
2902  }
2903 
2904  for (SqlNode orderItem : orderList) {
2905  collationList.add(convertOrderItem(select,
2906  orderItem,
2907  extraOrderExprs,
2908  RelFieldCollation.Direction.ASCENDING,
2909  RelFieldCollation.NullDirection.UNSPECIFIED));
2910  }
2911  }
2912 
2913  protected RelFieldCollation convertOrderItem(SqlSelect select,
2914  SqlNode orderItem,
2915  List<SqlNode> extraExprs,
2916  RelFieldCollation.Direction direction,
2917  RelFieldCollation.NullDirection nullDirection) {
2918  assert select != null;
2919  // Handle DESC keyword, e.g. 'select a, b from t order by a desc'.
2920  switch (orderItem.getKind()) {
2921  case DESCENDING:
2922  return convertOrderItem(select,
2923  ((SqlCall) orderItem).operand(0),
2924  extraExprs,
2925  RelFieldCollation.Direction.DESCENDING,
2926  nullDirection);
2927  case NULLS_FIRST:
2928  return convertOrderItem(select,
2929  ((SqlCall) orderItem).operand(0),
2930  extraExprs,
2931  direction,
2932  RelFieldCollation.NullDirection.FIRST);
2933  case NULLS_LAST:
2934  return convertOrderItem(select,
2935  ((SqlCall) orderItem).operand(0),
2936  extraExprs,
2937  direction,
2938  RelFieldCollation.NullDirection.LAST);
2939  }
2940 
2941  SqlNode converted = validator.expandOrderExpr(select, orderItem);
2942 
2943  switch (nullDirection) {
2944  case UNSPECIFIED:
2945  nullDirection = validator.getDefaultNullCollation().last(desc(direction))
2946  ? RelFieldCollation.NullDirection.LAST
2947  : RelFieldCollation.NullDirection.FIRST;
2948  }
2949 
2950  // Scan the select list and order exprs for an identical expression.
2951  final SelectScope selectScope = validator.getRawSelectScope(select);
2952  int ordinal = -1;
2953  for (SqlNode selectItem : selectScope.getExpandedSelectList()) {
2954  ++ordinal;
2955  if (converted.equalsDeep(stripAs(selectItem), Litmus.IGNORE)) {
2956  return new RelFieldCollation(ordinal, direction, nullDirection);
2957  }
2958  }
2959 
2960  for (SqlNode extraExpr : extraExprs) {
2961  ++ordinal;
2962  if (converted.equalsDeep(extraExpr, Litmus.IGNORE)) {
2963  return new RelFieldCollation(ordinal, direction, nullDirection);
2964  }
2965  }
2966 
2967  // TODO: handle collation sequence
2968  // TODO: flag expressions as non-standard
2969 
2970  extraExprs.add(converted);
2971  return new RelFieldCollation(ordinal + 1, direction, nullDirection);
2972  }
2973 
2974  private static boolean desc(RelFieldCollation.Direction direction) {
2975  switch (direction) {
2976  case DESCENDING:
2977  case STRICTLY_DESCENDING:
2978  return true;
2979  default:
2980  return false;
2981  }
2982  }
2983 
2984  @Deprecated // to be removed before 2.0
2985  protected boolean enableDecorrelation() {
2986  // disable sub-query decorrelation when needed.
2987  // e.g. if outer joins are not supported.
2988  return config.isDecorrelationEnabled();
2989  }
2990 
2991  protected RelNode decorrelateQuery(RelNode rootRel) {
2992  return RelDecorrelator.decorrelateQuery(rootRel, relBuilder);
2993  }
2994 
3000  @Deprecated // to be removed before 2.0
3001  public boolean isTrimUnusedFields() {
3002  return config.isTrimUnusedFields();
3003  }
3004 
3014  protected RelRoot convertQueryRecursive(
3015  SqlNode query, boolean top, RelDataType targetRowType) {
3016  final SqlKind kind = query.getKind();
3017  switch (kind) {
3018  case SELECT:
3019  return RelRoot.of(convertSelect((SqlSelect) query, top), kind);
3020  case INSERT:
3021  return RelRoot.of(convertInsert((SqlInsert) query), kind);
3022  case DELETE:
3023  return RelRoot.of(convertDelete((SqlDelete) query), kind);
3024  case UPDATE:
3025  return RelRoot.of(convertUpdate((SqlUpdate) query), kind);
3026  case MERGE:
3027  return RelRoot.of(convertMerge((SqlMerge) query), kind);
3028  case UNION:
3029  case INTERSECT:
3030  case EXCEPT:
3031  return RelRoot.of(convertSetOp((SqlCall) query), kind);
3032  case WITH:
3033  return convertWith((SqlWith) query, top);
3034  case VALUES:
3035  return RelRoot.of(convertValues((SqlCall) query, targetRowType), kind);
3036  default:
3037  throw new AssertionError("not a query: " + query);
3038  }
3039  }
3040 
3048  protected RelNode convertSetOp(SqlCall call) {
3049  final RelNode left = convertQueryRecursive(call.operand(0), false, null).project();
3050  final RelNode right = convertQueryRecursive(call.operand(1), false, null).project();
3051  switch (call.getKind()) {
3052  case UNION:
3053  return LogicalUnion.create(ImmutableList.of(left, right), all(call));
3054 
3055  case INTERSECT:
3056  return LogicalIntersect.create(ImmutableList.of(left, right), all(call));
3057 
3058  case EXCEPT:
3059  return LogicalMinus.create(ImmutableList.of(left, right), all(call));
3060 
3061  default:
3062  throw Util.unexpected(call.getKind());
3063  }
3064  }
3065 
3066  private boolean all(SqlCall call) {
3067  return ((SqlSetOperator) call.getOperator()).isAll();
3068  }
3069 
3070  protected RelNode convertInsert(SqlInsert call) {
3071  RelOptTable targetTable = getTargetTable(call);
3072 
3073  final RelDataType targetRowType = validator.getValidatedNodeType(call);
3074  assert targetRowType != null;
3075  RelNode sourceRel =
3076  convertQueryRecursive(call.getSource(), false, targetRowType).project();
3077  RelNode massagedRel = convertColumnList(call, sourceRel);
3078 
3079  return createModify(targetTable, massagedRel);
3080  }
3081 
3083  private RelNode createModify(RelOptTable targetTable, RelNode source) {
3084  final ModifiableTable modifiableTable = targetTable.unwrap(ModifiableTable.class);
3085  if (modifiableTable != null && modifiableTable == targetTable.unwrap(Table.class)) {
3086  return modifiableTable.toModificationRel(cluster,
3087  targetTable,
3088  catalogReader,
3089  source,
3090  LogicalTableModify.Operation.INSERT,
3091  null,
3092  null,
3093  false);
3094  }
3095  final ModifiableView modifiableView = targetTable.unwrap(ModifiableView.class);
3096  if (modifiableView != null) {
3097  final Table delegateTable = modifiableView.getTable();
3098  final RelDataType delegateRowType = delegateTable.getRowType(typeFactory);
3099  final RelOptTable delegateRelOptTable = RelOptTableImpl.create(
3100  null, delegateRowType, delegateTable, modifiableView.getTablePath());
3101  final RelNode newSource =
3102  createSource(targetTable, source, modifiableView, delegateRowType);
3103  return createModify(delegateRelOptTable, newSource);
3104  }
3105  return LogicalTableModify.create(targetTable,
3106  catalogReader,
3107  source,
3108  LogicalTableModify.Operation.INSERT,
3109  null,
3110  null,
3111  false);
3112  }
3113 
3127  private RelNode createSource(RelOptTable targetTable,
3128  RelNode source,
3129  ModifiableView modifiableView,
3130  RelDataType delegateRowType) {
3131  final ImmutableIntList mapping = modifiableView.getColumnMapping();
3132  assert mapping.size() == targetTable.getRowType().getFieldCount();
3133 
3134  // For columns represented in the mapping, the expression is just a field
3135  // reference.
3136  final Map<Integer, RexNode> projectMap = new HashMap<>();
3137  final List<RexNode> filters = new ArrayList<>();
3138  for (int i = 0; i < mapping.size(); i++) {
3139  int target = mapping.get(i);
3140  if (target >= 0) {
3141  projectMap.put(target, RexInputRef.of(i, source.getRowType()));
3142  }
3143  }
3144 
3145  // For columns that are not in the mapping, and have a constraint of the
3146  // form "column = value", the expression is the literal "value".
3147  //
3148  // If a column has multiple constraints, the extra ones will become a
3149  // filter.
3150  final RexNode constraint = modifiableView.getConstraint(rexBuilder, delegateRowType);
3151  RelOptUtil.inferViewPredicates(projectMap, filters, constraint);
3152  final List<Pair<RexNode, String>> projects = new ArrayList<>();
3153  for (RelDataTypeField field : delegateRowType.getFieldList()) {
3154  RexNode node = projectMap.get(field.getIndex());
3155  if (node == null) {
3156  node = rexBuilder.makeNullLiteral(field.getType());
3157  }
3158  projects.add(Pair.of(
3159  rexBuilder.ensureType(field.getType(), node, false), field.getName()));
3160  }
3161 
3162  return relBuilder.push(source)
3163  .projectNamed(Pair.left(projects), Pair.right(projects), false)
3164  .filter(filters)
3165  .build();
3166  }
3167 
3168  private RelOptTable.ToRelContext createToRelContext() {
3169  return ViewExpanders.toRelContext(viewExpander, cluster);
3170  }
3171 
3172  public RelNode toRel(final RelOptTable table) {
3173  final RelNode scan = table.toRel(createToRelContext());
3174 
3175  final InitializerExpressionFactory ief =
3176  Util.first(table.unwrap(InitializerExpressionFactory.class),
3177  NullInitializerExpressionFactory.INSTANCE);
3178 
3179  // Lazily create a blackboard that contains all non-generated columns.
3180  final Supplier<Blackboard> bb = () -> {
3181  RexNode sourceRef = rexBuilder.makeRangeReference(scan);
3182  return createInsertBlackboard(table, sourceRef, table.getRowType().getFieldNames());
3183  };
3184 
3185  int virtualCount = 0;
3186  final List<RexNode> list = new ArrayList<>();
3187  for (RelDataTypeField f : table.getRowType().getFieldList()) {
3188  final ColumnStrategy strategy = ief.generationStrategy(table, f.getIndex());
3189  switch (strategy) {
3190  case VIRTUAL:
3191  list.add(ief.newColumnDefaultValue(table, f.getIndex(), bb.get()));
3192  ++virtualCount;
3193  break;
3194  default:
3195  list.add(rexBuilder.makeInputRef(
3196  scan, RelOptTableImpl.realOrdinal(table, f.getIndex())));
3197  }
3198  }
3199  if (virtualCount > 0) {
3200  relBuilder.push(scan);
3201  relBuilder.project(list);
3202  return relBuilder.build();
3203  }
3204  return scan;
3205  }
3206 
3207  protected RelOptTable getTargetTable(SqlNode call) {
3208  final SqlValidatorNamespace targetNs = validator.getNamespace(call);
3209  if (targetNs.isWrapperFor(SqlValidatorImpl.DmlNamespace.class)) {
3210  final SqlValidatorImpl.DmlNamespace dmlNamespace =
3211  targetNs.unwrap(SqlValidatorImpl.DmlNamespace.class);
3212  return SqlValidatorUtil.getRelOptTable(dmlNamespace, catalogReader, null, null);
3213  }
3214  final SqlValidatorNamespace resolvedNamespace = targetNs.resolve();
3215  return SqlValidatorUtil.getRelOptTable(resolvedNamespace, catalogReader, null, null);
3216  }
3217 
3235  protected RelNode convertColumnList(final SqlInsert call, RelNode source) {
3236  RelDataType sourceRowType = source.getRowType();
3237  final RexNode sourceRef = rexBuilder.makeRangeReference(sourceRowType, 0, false);
3238  final List<String> targetColumnNames = new ArrayList<>();
3239  final List<RexNode> columnExprs = new ArrayList<>();
3240  collectInsertTargets(call, sourceRef, targetColumnNames, columnExprs);
3241 
3242  final RelOptTable targetTable = getTargetTable(call);
3243  final RelDataType targetRowType = RelOptTableImpl.realRowType(targetTable);
3244  final List<RelDataTypeField> targetFields = targetRowType.getFieldList();
3245  final List<RexNode> sourceExps =
3246  new ArrayList<>(Collections.nCopies(targetFields.size(), null));
3247  final List<String> fieldNames =
3248  new ArrayList<>(Collections.nCopies(targetFields.size(), null));
3249 
3250  final InitializerExpressionFactory initializerFactory =
3251  getInitializerFactory(validator.getNamespace(call).getTable());
3252 
3253  // Walk the name list and place the associated value in the
3254  // expression list according to the ordinal value returned from
3255  // the table construct, leaving nulls in the list for columns
3256  // that are not referenced.
3257  final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
3258  for (Pair<String, RexNode> p : Pair.zip(targetColumnNames, columnExprs)) {
3259  RelDataTypeField field = nameMatcher.field(targetRowType, p.left);
3260  assert field != null : "column " + p.left + " not found";
3261  sourceExps.set(field.getIndex(), p.right);
3262  }
3263 
3264  // Lazily create a blackboard that contains all non-generated columns.
3265  final Supplier<Blackboard> bb =
3266  () -> createInsertBlackboard(targetTable, sourceRef, targetColumnNames);
3267 
3268  // Walk the expression list and get default values for any columns
3269  // that were not supplied in the statement. Get field names too.
3270  for (int i = 0; i < targetFields.size(); ++i) {
3271  final RelDataTypeField field = targetFields.get(i);
3272  final String fieldName = field.getName();
3273  fieldNames.set(i, fieldName);
3274  if (sourceExps.get(i) == null || sourceExps.get(i).getKind() == SqlKind.DEFAULT) {
3275  sourceExps.set(
3276  i, initializerFactory.newColumnDefaultValue(targetTable, i, bb.get()));
3277 
3278  // bare nulls are dangerous in the wrong hands
3279  sourceExps.set(i, castNullLiteralIfNeeded(sourceExps.get(i), field.getType()));
3280  }
3281  }
3282 
3283  return relBuilder.push(source).projectNamed(sourceExps, fieldNames, false).build();
3284  }
3285 
3291  RelOptTable targetTable, RexNode sourceRef, List<String> targetColumnNames) {
3292  final Map<String, RexNode> nameToNodeMap = new HashMap<>();
3293  int j = 0;
3294 
3295  // Assign expressions for non-generated columns.
3296  final List<ColumnStrategy> strategies = targetTable.getColumnStrategies();
3297  final List<String> targetFields = targetTable.getRowType().getFieldNames();
3298  for (String targetColumnName : targetColumnNames) {
3299  final int i = targetFields.indexOf(targetColumnName);
3300  switch (strategies.get(i)) {
3301  case STORED:
3302  case VIRTUAL:
3303  break;
3304  default:
3305  nameToNodeMap.put(targetColumnName, rexBuilder.makeFieldAccess(sourceRef, j++));
3306  }
3307  }
3308  return createBlackboard(null, nameToNodeMap, false);
3309  }
3310 
3311  private InitializerExpressionFactory getInitializerFactory(
3312  SqlValidatorTable validatorTable) {
3313  // We might unwrap a null instead of a InitializerExpressionFactory.
3314  final Table table = unwrap(validatorTable, Table.class);
3315  if (table != null) {
3316  InitializerExpressionFactory f = unwrap(table, InitializerExpressionFactory.class);
3317  if (f != null) {
3318  return f;
3319  }
3320  }
3321  return NullInitializerExpressionFactory.INSTANCE;
3322  }
3323 
3324  private static <T> T unwrap(Object o, Class<T> clazz) {
3325  if (o instanceof Wrapper) {
3326  return ((Wrapper) o).unwrap(clazz);
3327  }
3328  return null;
3329  }
3330 
3331  private RexNode castNullLiteralIfNeeded(RexNode node, RelDataType type) {
3332  if (!RexLiteral.isNullLiteral(node)) {
3333  return node;
3334  }
3335  return rexBuilder.makeCast(type, node);
3336  }
3337 
3348  protected void collectInsertTargets(SqlInsert call,
3349  final RexNode sourceRef,
3350  final List<String> targetColumnNames,
3351  List<RexNode> columnExprs) {
3352  final RelOptTable targetTable = getTargetTable(call);
3353  final RelDataType tableRowType = targetTable.getRowType();
3354  SqlNodeList targetColumnList = call.getTargetColumnList();
3355  if (targetColumnList == null) {
3356  if (validator.getConformance().isInsertSubsetColumnsAllowed()) {
3357  final RelDataType targetRowType =
3358  typeFactory.createStructType(tableRowType.getFieldList().subList(
3359  0, sourceRef.getType().getFieldCount()));
3360  targetColumnNames.addAll(targetRowType.getFieldNames());
3361  } else {
3362  targetColumnNames.addAll(tableRowType.getFieldNames());
3363  }
3364  } else {
3365  for (int i = 0; i < targetColumnList.size(); i++) {
3366  SqlIdentifier id = (SqlIdentifier) targetColumnList.get(i);
3367  RelDataTypeField field = SqlValidatorUtil.getTargetField(
3368  tableRowType, typeFactory, id, catalogReader, targetTable);
3369  assert field != null : "column " + id.toString() + " not found";
3370  targetColumnNames.add(field.getName());
3371  }
3372  }
3373 
3374  final Blackboard bb =
3375  createInsertBlackboard(targetTable, sourceRef, targetColumnNames);
3376 
3377  // Next, assign expressions for generated columns.
3378  final List<ColumnStrategy> strategies = targetTable.getColumnStrategies();
3379  for (String columnName : targetColumnNames) {
3380  final int i = tableRowType.getFieldNames().indexOf(columnName);
3381  final RexNode expr;
3382  switch (strategies.get(i)) {
3383  case STORED:
3384  final InitializerExpressionFactory f =
3385  Util.first(targetTable.unwrap(InitializerExpressionFactory.class),
3386  NullInitializerExpressionFactory.INSTANCE);
3387  expr = f.newColumnDefaultValue(targetTable, i, bb);
3388  break;
3389  case VIRTUAL:
3390  expr = null;
3391  break;
3392  default:
3393  expr = bb.nameToNodeMap.get(columnName);
3394  }
3395  columnExprs.add(expr);
3396  }
3397 
3398  // Remove virtual columns from the list.
3399  for (int i = 0; i < targetColumnNames.size(); i++) {
3400  if (columnExprs.get(i) == null) {
3401  columnExprs.remove(i);
3402  targetColumnNames.remove(i);
3403  --i;
3404  }
3405  }
3406  }
3407 
3408  private RelNode convertDelete(SqlDelete call) {
3409  RelOptTable targetTable = getTargetTable(call);
3410  RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
3411  return LogicalTableModify.create(targetTable,
3412  catalogReader,
3413  sourceRel,
3414  LogicalTableModify.Operation.DELETE,
3415  null,
3416  null,
3417  false);
3418  }
3419 
3420  private RelNode convertUpdate(SqlUpdate call) {
3421  final SqlValidatorScope scope = validator.getWhereScope(call.getSourceSelect());
3422  Blackboard bb = createBlackboard(scope, null, false);
3423 
3424  replaceSubQueries(bb, call, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
3425 
3426  Builder<RexNode> rexNodeSourceExpressionListBuilder = ImmutableList.builder();
3427  for (SqlNode n : call.getSourceExpressionList()) {
3428  RexNode rn = bb.convertExpression(n);
3429  rexNodeSourceExpressionListBuilder.add(rn);
3430  }
3431 
3432  RelOptTable targetTable = getTargetTable(call);
3433 
3434  // convert update column list from SqlIdentifier to String
3435  final List<String> targetColumnNameList = new ArrayList<>();
3436  final RelDataType targetRowType = targetTable.getRowType();
3437  for (SqlNode node : call.getTargetColumnList()) {
3438  SqlIdentifier id = (SqlIdentifier) node;
3439  RelDataTypeField field = SqlValidatorUtil.getTargetField(
3440  targetRowType, typeFactory, id, catalogReader, targetTable);
3441  assert field != null : "column " + id.toString() + " not found";
3442  targetColumnNameList.add(field.getName());
3443  }
3444 
3445  RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
3446 
3447  return LogicalTableModify.create(targetTable,
3448  catalogReader,
3449  sourceRel,
3450  LogicalTableModify.Operation.UPDATE,
3451  targetColumnNameList,
3452  rexNodeSourceExpressionListBuilder.build(),
3453  false);
3454  }
3455 
3456  private RelNode convertMerge(SqlMerge call) {
3457  RelOptTable targetTable = getTargetTable(call);
3458 
3459  // convert update column list from SqlIdentifier to String
3460  final List<String> targetColumnNameList = new ArrayList<>();
3461  final RelDataType targetRowType = targetTable.getRowType();
3462  SqlUpdate updateCall = call.getUpdateCall();
3463  if (updateCall != null) {
3464  for (SqlNode targetColumn : updateCall.getTargetColumnList()) {
3465  SqlIdentifier id = (SqlIdentifier) targetColumn;
3466  RelDataTypeField field = SqlValidatorUtil.getTargetField(
3467  targetRowType, typeFactory, id, catalogReader, targetTable);
3468  assert field != null : "column " + id.toString() + " not found";
3469  targetColumnNameList.add(field.getName());
3470  }
3471  }
3472 
3473  // replace the projection of the source select with a
3474  // projection that contains the following:
3475  // 1) the expressions corresponding to the new insert row (if there is
3476  // an insert)
3477  // 2) all columns from the target table (if there is an update)
3478  // 3) the set expressions in the update call (if there is an update)
3479 
3480  // first, convert the merge's source select to construct the columns
3481  // from the target table and the set expressions in the update call
3482  RelNode mergeSourceRel = convertSelect(call.getSourceSelect(), false);
3483 
3484  // then, convert the insert statement so we can get the insert
3485  // values expressions
3486  SqlInsert insertCall = call.getInsertCall();
3487  int nLevel1Exprs = 0;
3488  List<RexNode> level1InsertExprs = null;
3489  List<RexNode> level2InsertExprs = null;
3490  if (insertCall != null) {
3491  RelNode insertRel = convertInsert(insertCall);
3492 
3493  // if there are 2 level of projections in the insert source, combine
3494  // them into a single project; level1 refers to the topmost project;
3495  // the level1 projection contains references to the level2
3496  // expressions, except in the case where no target expression was
3497  // provided, in which case, the expression is the default value for
3498  // the column; or if the expressions directly map to the source
3499  // table
3500  level1InsertExprs = ((LogicalProject) insertRel.getInput(0)).getProjects();
3501  if (insertRel.getInput(0).getInput(0) instanceof LogicalProject) {
3502  level2InsertExprs =
3503  ((LogicalProject) insertRel.getInput(0).getInput(0)).getProjects();
3504  }
3505  nLevel1Exprs = level1InsertExprs.size();
3506  }
3507 
3508  LogicalJoin join = (LogicalJoin) mergeSourceRel.getInput(0);
3509  int nSourceFields = join.getLeft().getRowType().getFieldCount();
3510  final List<RexNode> projects = new ArrayList<>();
3511  for (int level1Idx = 0; level1Idx < nLevel1Exprs; level1Idx++) {
3512  if ((level2InsertExprs != null)
3513  && (level1InsertExprs.get(level1Idx) instanceof RexInputRef)) {
3514  int level2Idx = ((RexInputRef) level1InsertExprs.get(level1Idx)).getIndex();
3515  projects.add(level2InsertExprs.get(level2Idx));
3516  } else {
3517  projects.add(level1InsertExprs.get(level1Idx));
3518  }
3519  }
3520  if (updateCall != null) {
3521  final LogicalProject project = (LogicalProject) mergeSourceRel;
3522  projects.addAll(Util.skip(project.getProjects(), nSourceFields));
3523  }
3524 
3525  relBuilder.push(join).project(projects);
3526 
3527  return LogicalTableModify.create(targetTable,
3528  catalogReader,
3529  relBuilder.build(),
3530  LogicalTableModify.Operation.MERGE,
3531  targetColumnNameList,
3532  null,
3533  false);
3534  }
3535 
3540  private RexNode convertIdentifier(Blackboard bb, SqlIdentifier identifier) {
3541  // first check for reserved identifiers like CURRENT_USER
3542  final SqlCall call = bb.getValidator().makeNullaryCall(identifier);
3543  if (call != null) {
3544  return bb.convertExpression(call);
3545  }
3546 
3547  String pv = null;
3548  if (bb.isPatternVarRef && identifier.names.size() > 1) {
3549  pv = identifier.names.get(0);
3550  }
3551 
3552  final SqlQualified qualified;
3553  if (bb.scope != null) {
3554  qualified = bb.scope.fullyQualify(identifier);
3555  } else {
3556  qualified = SqlQualified.create(null, 1, null, identifier);
3557  }
3558  final Pair<RexNode, Map<String, Integer>> e0 = bb.lookupExp(qualified);
3559  RexNode e = e0.left;
3560  for (String name : qualified.suffix()) {
3561  if (e == e0.left && e0.right != null) {
3562  int i = e0.right.get(name);
3563  e = rexBuilder.makeFieldAccess(e, i);
3564  } else {
3565  final boolean caseSensitive = true; // name already fully-qualified
3566  if (identifier.isStar() && bb.scope instanceof MatchRecognizeScope) {
3567  e = rexBuilder.makeFieldAccess(e, 0);
3568  } else {
3569  e = rexBuilder.makeFieldAccess(e, name, caseSensitive);
3570  }
3571  }
3572  }
3573  if (e instanceof RexInputRef) {
3574  // adjust the type to account for nulls introduced by outer joins
3575  e = adjustInputRef(bb, (RexInputRef) e);
3576  if (pv != null) {
3577  e = RexPatternFieldRef.of(pv, (RexInputRef) e);
3578  }
3579  }
3580 
3581  if (e0.left instanceof RexCorrelVariable) {
3582  assert e instanceof RexFieldAccess;
3583  final RexNode prev = bb.mapCorrelateToRex.put(
3584  ((RexCorrelVariable) e0.left).id, (RexFieldAccess) e);
3585  assert prev == null;
3586  }
3587  return e;
3588  }
3589 
3599  protected RexNode adjustInputRef(Blackboard bb, RexInputRef inputRef) {
3600  RelDataTypeField field = bb.getRootField(inputRef);
3601  if (field != null) {
3602  return rexBuilder.makeInputRef(field.getType(), inputRef.getIndex());
3603  }
3604  return inputRef;
3605  }
3606 
3614  private RelNode convertRowConstructor(Blackboard bb, SqlCall rowConstructor) {
3615  Preconditions.checkArgument(isRowConstructor(rowConstructor));
3616  final List<SqlNode> operands = rowConstructor.getOperandList();
3617  return convertMultisets(operands, bb);
3618  }
3619 
3620  private RelNode convertCursor(Blackboard bb, SubQuery subQuery) {
3621  final SqlCall cursorCall = (SqlCall) subQuery.node;
3622  assert cursorCall.operandCount() == 1;
3623  SqlNode query = cursorCall.operand(0);
3624  RelNode converted = convertQuery(query, false, false).rel;
3625  int iCursor = bb.cursors.size();
3626  bb.cursors.add(converted);
3627  subQuery.expr = new RexInputRef(iCursor, converted.getRowType());
3628  return converted;
3629  }
3630 
3631  private RelNode convertMultisets(final List<SqlNode> operands, Blackboard bb) {
3632  // NOTE: Wael 2/04/05: this implementation is not the most efficient in
3633  // terms of planning since it generates XOs that can be reduced.
3634  final List<Object> joinList = new ArrayList<>();
3635  List<SqlNode> lastList = new ArrayList<>();
3636  for (int i = 0; i < operands.size(); i++) {
3637  SqlNode operand = operands.get(i);
3638  if (!(operand instanceof SqlCall)) {
3639  lastList.add(operand);
3640  continue;
3641  }
3642 
3643  final SqlCall call = (SqlCall) operand;
3644  final RelNode input;
3645  switch (call.getKind()) {
3646  case MULTISET_VALUE_CONSTRUCTOR:
3647  case ARRAY_VALUE_CONSTRUCTOR:
3648  final SqlNodeList list =
3649  new SqlNodeList(call.getOperandList(), call.getParserPosition());
3650  CollectNamespace nss = (CollectNamespace) validator.getNamespace(call);
3651  Blackboard usedBb;
3652  if (null != nss) {
3653  usedBb = createBlackboard(nss.getScope(), null, false);
3654  } else {
3655  usedBb = createBlackboard(new ListScope(bb.scope) {
3656  public SqlNode getNode() {
3657  return call;
3658  }
3659  }, null, false);
3660  }
3661  RelDataType multisetType = validator.getValidatedNodeType(call);
3662  ((SqlValidatorImpl) validator)
3663  .setValidatedNodeType(list, multisetType.getComponentType());
3664  input = convertQueryOrInList(usedBb, list, null);
3665  break;
3666  case MULTISET_QUERY_CONSTRUCTOR:
3667  case ARRAY_QUERY_CONSTRUCTOR:
3668  final RelRoot root = convertQuery(call.operand(0), false, true);
3669  input = root.rel;
3670  break;
3671  default:
3672  lastList.add(operand);
3673  continue;
3674  }
3675 
3676  if (lastList.size() > 0) {
3677  joinList.add(lastList);
3678  }
3679  lastList = new ArrayList<>();
3680  Collect collect = new Collect(cluster,
3681  cluster.traitSetOf(Convention.NONE),
3682  input,
3683  validator.deriveAlias(call, i));
3684  joinList.add(collect);
3685  }
3686 
3687  if (joinList.size() == 0) {
3688  joinList.add(lastList);
3689  }
3690 
3691  for (int i = 0; i < joinList.size(); i++) {
3692  Object o = joinList.get(i);
3693  if (o instanceof List) {
3694  @SuppressWarnings("unchecked")
3695  List<SqlNode> projectList = (List<SqlNode>) o;
3696  final List<RexNode> selectList = new ArrayList<>();
3697  final List<String> fieldNameList = new ArrayList<>();
3698  for (int j = 0; j < projectList.size(); j++) {
3699  SqlNode operand = projectList.get(j);
3700  selectList.add(bb.convertExpression(operand));
3701 
3702  // REVIEW angel 5-June-2005: Use deriveAliasFromOrdinal
3703  // instead of deriveAlias to match field names from
3704  // SqlRowOperator. Otherwise, get error Type
3705  // 'RecordType(INTEGER EMPNO)' has no field 'EXPR$0' when
3706  // doing select * from unnest( select multiset[empno]
3707  // from sales.emps);
3708 
3709  fieldNameList.add(SqlUtil.deriveAliasFromOrdinal(j));
3710  }
3711 
3712  relBuilder.push(LogicalValues.createOneRow(cluster))
3713  .projectNamed(selectList, fieldNameList, true);
3714 
3715  joinList.set(i, relBuilder.build());
3716  }
3717  }
3718 
3719  RelNode ret = (RelNode) joinList.get(0);
3720  for (int i = 1; i < joinList.size(); i++) {
3721  RelNode relNode = (RelNode) joinList.get(i);
3722  ret = RelFactories.DEFAULT_JOIN_FACTORY.createJoin(ret,
3723  relNode,
3724  rexBuilder.makeLiteral(true),
3725  ImmutableSet.of(),
3726  JoinRelType.INNER,
3727  false);
3728  }
3729  return ret;
3730  }
3731 
3732  private void convertSelectList(
3733  Blackboard bb, SqlSelect select, List<SqlNode> orderList) {
3734  SqlNodeList selectList = select.getSelectList();
3735  selectList = validator.expandStar(selectList, select, false);
3736 
3737  replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
3738 
3739  List<String> fieldNames = new ArrayList<>();
3740  final List<RexNode> exprs = new ArrayList<>();
3741  final Collection<String> aliases = new TreeSet<>();
3742 
3743  // Project any system fields. (Must be done before regular select items,
3744  // because offsets may be affected.)
3745  final List<SqlMonotonicity> columnMonotonicityList = new ArrayList<>();
3746  extraSelectItems(bb, select, exprs, fieldNames, aliases, columnMonotonicityList);
3747 
3748  // Project select clause.
3749  int i = -1;
3750  for (SqlNode expr : selectList) {
3751  ++i;
3752  exprs.add(bb.convertExpression(expr));
3753  fieldNames.add(deriveAlias(expr, aliases, i));
3754  }
3755 
3756  // Project extra fields for sorting.
3757  for (SqlNode expr : orderList) {
3758  ++i;
3759  SqlNode expr2 = validator.expandOrderExpr(select, expr);
3760  exprs.add(bb.convertExpression(expr2));
3761  fieldNames.add(deriveAlias(expr, aliases, i));
3762  }
3763 
3764  fieldNames = SqlValidatorUtil.uniquify(
3765  fieldNames, catalogReader.nameMatcher().isCaseSensitive());
3766 
3767  relBuilder.push(bb.root).projectNamed(exprs, fieldNames, true);
3768  bb.setRoot(relBuilder.build(), false);
3769 
3770  assert bb.columnMonotonicities.isEmpty();
3771  bb.columnMonotonicities.addAll(columnMonotonicityList);
3772  for (SqlNode selectItem : selectList) {
3773  bb.columnMonotonicities.add(selectItem.getMonotonicity(bb.scope));
3774  }
3775  }
3776 
3790  protected void extraSelectItems(Blackboard bb,
3791  SqlSelect select,
3792  List<RexNode> exprList,
3793  List<String> nameList,
3794  Collection<String> aliasList,
3795  List<SqlMonotonicity> columnMonotonicityList) {}
3796 
3798  final SqlNode node, Collection<String> aliases, final int ordinal) {
3799  String alias = validator.deriveAlias(node, ordinal);
3800  if ((alias == null) || aliases.contains(alias)) {
3801  String aliasBase = (alias == null) ? "EXPR$" : alias;
3802  for (int j = 0;; j++) {
3803  alias = aliasBase + j;
3804  if (!aliases.contains(alias)) {
3805  break;
3806  }
3807  }
3808  }
3809  aliases.add(alias);
3810  return alias;
3811  }
3812 
3816  public RelRoot convertWith(SqlWith with, boolean top) {
3817  return convertQuery(with.body, false, top);
3818  }
3819 
3823  public RelNode convertValues(SqlCall values, RelDataType targetRowType) {
3824  final SqlValidatorScope scope = validator.getOverScope(values);
3825  assert scope != null;
3826  final Blackboard bb = createBlackboard(scope, null, false);
3827  convertValuesImpl(bb, values, targetRowType);
3828  return bb.root;
3829  }
3830 
3839  private void convertValuesImpl(
3840  Blackboard bb, SqlCall values, RelDataType targetRowType) {
3841  // Attempt direct conversion to LogicalValues; if that fails, deal with
3842  // fancy stuff like sub-queries below.
3843  RelNode valuesRel =
3844  convertRowValues(bb, values, values.getOperandList(), true, targetRowType);
3845  if (valuesRel != null) {
3846  bb.setRoot(valuesRel, true);
3847  return;
3848  }
3849 
3850  final List<RelNode> unionRels = new ArrayList<>();
3851  for (SqlNode rowConstructor1 : values.getOperandList()) {
3852  SqlCall rowConstructor = (SqlCall) rowConstructor1;
3853  Blackboard tmpBb = createBlackboard(bb.scope, null, false);
3854  replaceSubQueries(tmpBb, rowConstructor, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
3855  final List<Pair<RexNode, String>> exps = new ArrayList<>();
3856  for (Ord<SqlNode> operand : Ord.zip(rowConstructor.getOperandList())) {
3857  exps.add(Pair.of(tmpBb.convertExpression(operand.e),
3858  validator.deriveAlias(operand.e, operand.i)));
3859  }
3860  RelNode in =
3861  (null == tmpBb.root) ? LogicalValues.createOneRow(cluster) : tmpBb.root;
3862  unionRels.add(
3863  relBuilder.push(in).project(Pair.left(exps), Pair.right(exps)).build());
3864  }
3865 
3866  if (unionRels.size() == 0) {
3867  throw new AssertionError("empty values clause");
3868  } else if (unionRels.size() == 1) {
3869  bb.setRoot(unionRels.get(0), true);
3870  } else {
3871  bb.setRoot(LogicalUnion.create(unionRels, true), true);
3872  }
3873  }
3874 
3875  // ~ Inner Classes ----------------------------------------------------------
3876 
3880  protected class Blackboard
3881  implements SqlRexContext, SqlVisitor<RexNode>, InitializerContext {
3885  public final SqlValidatorScope scope;
3886  private final Map<String, RexNode> nameToNodeMap;
3887  public RelNode root;
3888  private List<RelNode> inputs;
3889  private final Map<CorrelationId, RexFieldAccess> mapCorrelateToRex = new HashMap<>();
3890 
3891  private boolean isPatternVarRef = false;
3892 
3893  final List<RelNode> cursors = new ArrayList<>();
3894 
3899  private final Set<SubQuery> subQueryList = new LinkedHashSet<>();
3900 
3905 
3910  SqlWindow window;
3911 
3917  private final Map<RelNode, Map<Integer, Integer>> mapRootRelToFieldProjection =
3918  new HashMap<>();
3919 
3920  private final List<SqlMonotonicity> columnMonotonicities = new ArrayList<>();
3921 
3922  private final List<RelDataTypeField> systemFieldList = new ArrayList<>();
3923  final boolean top;
3924 
3925  private final InitializerExpressionFactory initializerExpressionFactory =
3926  new NullInitializerExpressionFactory();
3927 
3939  protected Blackboard(
3940  SqlValidatorScope scope, Map<String, RexNode> nameToNodeMap, boolean top) {
3941  this.scope = scope;
3942  this.nameToNodeMap = nameToNodeMap;
3943  this.top = top;
3944  }
3945 
3946  public SqlNode getTopNode() {
3947  try {
3948  if (null == scope) {
3949  return null;
3950  }
3951  return scope.getNode();
3952  } catch (Exception e) {
3953  return null;
3954  }
3955  }
3956 
3957  public void setPatternVarRef(boolean isVarRef) {
3958  this.isPatternVarRef = isVarRef;
3959  }
3960 
3961  public RexNode register(RelNode rel, JoinRelType joinType) {
3962  return register(rel, joinType, null);
3963  }
3964 
3974  public RexNode register(RelNode rel, JoinRelType joinType, List<RexNode> leftKeys) {
3975  assert joinType != null;
3976  if (root == null) {
3977  assert leftKeys == null;
3978  setRoot(rel, false);
3979  return rexBuilder.makeRangeReference(root.getRowType(), 0, false);
3980  }
3981 
3982  final RexNode joinCond;
3983  final int origLeftInputCount = root.getRowType().getFieldCount();
3984  if (leftKeys != null) {
3985  List<RexNode> newLeftInputExprs = new ArrayList<>();
3986  for (int i = 0; i < origLeftInputCount; i++) {
3987  newLeftInputExprs.add(rexBuilder.makeInputRef(root, i));
3988  }
3989 
3990  final List<Integer> leftJoinKeys = new ArrayList<>();
3991  for (RexNode leftKey : leftKeys) {
3992  int index = newLeftInputExprs.indexOf(leftKey);
3993  if (index < 0 || joinType == JoinRelType.LEFT) {
3994  index = newLeftInputExprs.size();
3995  newLeftInputExprs.add(leftKey);
3996  }
3997  leftJoinKeys.add(index);
3998  }
3999 
4000  RelNode newLeftInput = relBuilder.push(root).project(newLeftInputExprs).build();
4001 
4002  // maintain the group by mapping in the new LogicalProject
4003  if (mapRootRelToFieldProjection.containsKey(root)) {
4004  mapRootRelToFieldProjection.put(
4005  newLeftInput, mapRootRelToFieldProjection.get(root));
4006  }
4007 
4008  setRoot(newLeftInput, false);
4009 
4010  // right fields appear after the LHS fields.
4011  final int rightOffset = root.getRowType().getFieldCount()
4012  - newLeftInput.getRowType().getFieldCount();
4013  final List<Integer> rightKeys =
4014  Util.range(rightOffset, rightOffset + leftKeys.size());
4015 
4016  joinCond = RelOptUtil.createEquiJoinCondition(
4017  newLeftInput, leftJoinKeys, rel, rightKeys, rexBuilder);
4018  } else {
4019  joinCond = rexBuilder.makeLiteral(true);
4020  }
4021 
4022  int leftFieldCount = root.getRowType().getFieldCount();
4023  final RelNode join = createJoin(this, root, rel, joinCond, joinType);
4024 
4025  setRoot(join, false);
4026 
4027  if (leftKeys != null && joinType == JoinRelType.LEFT) {
4028  final int leftKeyCount = leftKeys.size();
4029  int rightFieldLength = rel.getRowType().getFieldCount();
4030  assert leftKeyCount == rightFieldLength - 1;
4031 
4032  final int rexRangeRefLength = leftKeyCount + rightFieldLength;
4033  RelDataType returnType = typeFactory.createStructType(
4034  new AbstractList<Map.Entry<String, RelDataType>>() {
4035  public Map.Entry<String, RelDataType> get(int index) {
4036  return join.getRowType().getFieldList().get(
4037  origLeftInputCount + index);
4038  }
4039 
4040  public int size() {
4041  return rexRangeRefLength;
4042  }
4043  });
4044 
4045  return rexBuilder.makeRangeReference(returnType, origLeftInputCount, false);
4046  } else {
4047  return rexBuilder.makeRangeReference(
4048  rel.getRowType(), leftFieldCount, joinType.generatesNullsOnRight());
4049  }
4050  }
4051 
4063  public void setRoot(RelNode root, boolean leaf) {
4064  setRoot(Collections.singletonList(root), root, root instanceof LogicalJoin);
4065  if (leaf) {
4066  leaves.add(root);
4067  }
4068  this.columnMonotonicities.clear();
4069  }
4070 
4071  private void setRoot(List<RelNode> inputs, RelNode root, boolean hasSystemFields) {
4072  this.inputs = inputs;
4073  this.root = root;
4074  this.systemFieldList.clear();
4075  if (hasSystemFields) {
4076  this.systemFieldList.addAll(getSystemFields());
4077  }
4078  }
4079 
4090  public void setDataset(String datasetName) {}
4091 
4092  void setRoot(List<RelNode> inputs) {
4093  setRoot(inputs, null, false);
4094  }
4095 
4102  Pair<RexNode, Map<String, Integer>> lookupExp(SqlQualified qualified) {
4103  if (nameToNodeMap != null && qualified.prefixLength == 1) {
4104  RexNode node = nameToNodeMap.get(qualified.identifier.names.get(0));
4105  if (node == null) {
4106  throw new AssertionError("Unknown identifier '" + qualified.identifier
4107  + "' encountered while expanding expression");
4108  }
4109  return Pair.of(node, null);
4110  }
4111  final SqlNameMatcher nameMatcher =
4112  scope.getValidator().getCatalogReader().nameMatcher();
4113  final SqlValidatorScope.ResolvedImpl resolved =
4114  new SqlValidatorScope.ResolvedImpl();
4115  scope.resolve(qualified.prefix(), nameMatcher, false, resolved);
4116  if (!(resolved.count() == 1)) {
4117  return null;
4118  }
4119  final SqlValidatorScope.Resolve resolve = resolved.only();
4120  final RelDataType rowType = resolve.rowType();
4121 
4122  // Found in current query's from list. Find which from item.
4123  // We assume that the order of the from clause items has been
4124  // preserved.
4125  final SqlValidatorScope ancestorScope = resolve.scope;
4126  boolean isParent = ancestorScope != scope;
4127  if ((inputs != null) && !isParent) {
4128  final LookupContext rels =
4129  new LookupContext(this, inputs, systemFieldList.size());
4130  final RexNode node = lookup(resolve.path.steps().get(0).i, rels);
4131  if (node == null) {
4132  return null;
4133  } else {
4134  final Map<String, Integer> fieldOffsets = new HashMap<>();
4135  for (RelDataTypeField f : resolve.rowType().getFieldList()) {
4136  if (!fieldOffsets.containsKey(f.getName())) {
4137  fieldOffsets.put(f.getName(), f.getIndex());
4138  }
4139  }
4140  final Map<String, Integer> map = ImmutableMap.copyOf(fieldOffsets);
4141  return Pair.of(node, map);
4142  }
4143  } else {
4144  // We're referencing a relational expression which has not been
4145  // converted yet. This occurs when from items are correlated,
4146  // e.g. "select from emp as emp join emp.getDepts() as dept".
4147  // Create a temporary expression.
4148  DeferredLookup lookup =
4149  new DeferredLookup(this, qualified.identifier.names.get(0));
4150  final CorrelationId correlId = cluster.createCorrel();
4151  mapCorrelToDeferred.put(correlId, lookup);
4152  if (resolve.path.steps().get(0).i < 0) {
4153  return Pair.of(rexBuilder.makeCorrel(rowType, correlId), null);
4154  } else {
4155  final RelDataTypeFactory.Builder builder = typeFactory.builder();
4156  final ListScope ancestorScope1 = (ListScope) resolve.scope;
4157  final ImmutableMap.Builder<String, Integer> fields = ImmutableMap.builder();
4158  int i = 0;
4159  int offset = 0;
4160  for (SqlValidatorNamespace c : ancestorScope1.getChildren()) {
4161  builder.addAll(c.getRowType().getFieldList());
4162  if (i == resolve.path.steps().get(0).i) {
4163  for (RelDataTypeField field : c.getRowType().getFieldList()) {
4164  fields.put(field.getName(), field.getIndex() + offset);
4165  }
4166  }
4167  ++i;
4168  offset += c.getRowType().getFieldCount();
4169  }
4170  final RexNode c = rexBuilder.makeCorrel(builder.uniquify().build(), correlId);
4171  return Pair.of(c, fields.build());
4172  }
4173  }
4174  }
4175 
4180  RexNode lookup(int offset, LookupContext lookupContext) {
4181  Pair<RelNode, Integer> pair = lookupContext.findRel(offset);
4182  return rexBuilder.makeRangeReference(pair.left.getRowType(), pair.right, false);
4183  }
4184 
4185  RelDataTypeField getRootField(RexInputRef inputRef) {
4186  if (inputs == null) {
4187  return null;
4188  }
4189  int fieldOffset = inputRef.getIndex();
4190  for (RelNode input : inputs) {
4191  RelDataType rowType = input.getRowType();
4192  if (rowType == null) {
4193  // TODO: remove this once leastRestrictive
4194  // is correctly implemented
4195  return null;
4196  }
4197  if (fieldOffset < rowType.getFieldCount()) {
4198  return rowType.getFieldList().get(fieldOffset);
4199  }
4200  fieldOffset -= rowType.getFieldCount();
4201  }
4202  throw new AssertionError();
4203  }
4204 
4205  public void flatten(List<RelNode> rels,
4206  int systemFieldCount,
4207  int[] start,
4208  List<Pair<RelNode, Integer>> relOffsetList) {
4209  for (RelNode rel : rels) {
4210  if (leaves.contains(rel) || rel instanceof LogicalMatch) {
4211  relOffsetList.add(Pair.of(rel, start[0]));
4212  start[0] += rel.getRowType().getFieldCount();
4213  } else {
4214  if (rel instanceof LogicalJoin || rel instanceof LogicalAggregate) {
4215  start[0] += systemFieldCount;
4216  }
4217  flatten(rel.getInputs(), systemFieldCount, start, relOffsetList);
4218  }
4219  }
4220  }
4221 
4222  void registerSubQuery(SqlNode node, RelOptUtil.Logic logic) {
4223  for (SubQuery subQuery : subQueryList) {
4224  if (node.equalsDeep(subQuery.node, Litmus.IGNORE)) {
4225  return;
4226  }
4227  }
4228  subQueryList.add(new SubQuery(node, logic));
4229  }
4230 
4231  SubQuery getSubQuery(SqlNode expr) {
4232  for (SubQuery subQuery : subQueryList) {
4233  if (expr.equalsDeep(subQuery.node, Litmus.IGNORE)) {
4234  return subQuery;
4235  }
4236  }
4237 
4238  return null;
4239  }
4240 
4241  ImmutableList<RelNode> retrieveCursors() {
4242  try {
4243  return ImmutableList.copyOf(cursors);
4244  } finally {
4245  cursors.clear();
4246  }
4247  }
4248 
4249  public RexNode convertExpression(SqlNode expr) {
4250  // If we're in aggregation mode and this is an expression in the
4251  // GROUP BY clause, return a reference to the field.
4252  if (agg != null) {
4253  final SqlNode expandedGroupExpr = validator.expand(expr, scope);
4254  final int ref = agg.lookupGroupExpr(expandedGroupExpr);
4255  if (ref >= 0) {
4256  return rexBuilder.makeInputRef(root, ref);
4257  }
4258  if (expr instanceof SqlCall) {
4259  final RexNode rex = agg.lookupAggregates((SqlCall) expr);
4260  if (rex != null) {
4261  return rex;
4262  }
4263  }
4264  }
4265 
4266  // Allow the derived class chance to override the standard
4267  // behavior for special kinds of expressions.
4268  RexNode rex = convertExtendedExpression(expr, this);
4269  if (rex != null) {
4270  return rex;
4271  }
4272 
4273  // Sub-queries and OVER expressions are not like ordinary
4274  // expressions.
4275  final SqlKind kind = expr.getKind();
4276  final SubQuery subQuery;
4277 
4278  boolean isExpand = config.getExpandPredicate().test(getTopNode(), expr);
4279  if (!isExpand) {
4280  final SqlCall call;
4281  final SqlNode query;
4282  final RelRoot root;
4283  switch (kind) {
4284  case IN:
4285  case NOT_IN:
4286  case SOME:
4287  case ALL:
4288  call = (SqlCall) expr;
4289  query = call.operand(1);
4290  if (!(query instanceof SqlNodeList)) {
4291  root = convertQueryRecursive(query, false, null);
4292  final SqlNode operand = call.operand(0);
4293  List<SqlNode> nodes;
4294  switch (operand.getKind()) {
4295  case ROW:
4296  nodes = ((SqlCall) operand).getOperandList();
4297  break;
4298  default:
4299  nodes = ImmutableList.of(operand);
4300  }
4301  final ImmutableList.Builder<RexNode> builder = ImmutableList.builder();
4302  for (SqlNode node : nodes) {
4303  builder.add(convertExpression(node));
4304  }
4305  final ImmutableList<RexNode> list = builder.build();
4306  switch (kind) {
4307  case IN:
4308  return RexSubQuery.in(root.rel, list);
4309  case NOT_IN:
4310  return rexBuilder.makeCall(
4311  SqlStdOperatorTable.NOT, RexSubQuery.in(root.rel, list));
4312  case SOME:
4313  return RexSubQuery.some(
4314  root.rel, list, (SqlQuantifyOperator) call.getOperator());
4315  case ALL:
4316  return rexBuilder.makeCall(SqlStdOperatorTable.NOT,
4317  RexSubQuery.some(root.rel,
4318  list,
4319  negate((SqlQuantifyOperator) call.getOperator())));
4320  default:
4321  throw new AssertionError(kind);
4322  }
4323  }
4324  break;
4325 
4326  case EXISTS:
4327  call = (SqlCall) expr;
4328  query = Iterables.getOnlyElement(call.getOperandList());
4329  root = convertQueryRecursive(query, false, null);
4330  RelNode rel = root.rel;
4331  while (rel instanceof Project
4332  || rel instanceof Sort && ((Sort) rel).fetch == null
4333  && ((Sort) rel).offset == null) {
4334  rel = ((SingleRel) rel).getInput();
4335  }
4336  return RexSubQuery.exists(rel);
4337 
4338  case SCALAR_QUERY:
4339  call = (SqlCall) expr;
4340  query = Iterables.getOnlyElement(call.getOperandList());
4341  root = convertQueryRecursive(query, false, null);
4342  return RexSubQuery.scalar(root.rel);
4343  }
4344  }
4345 
4346  switch (kind) {
4347  case SOME:
4348  case ALL:
4349  if (isExpand) {
4350  throw new RuntimeException(kind + " is only supported if expand = false");
4351  }
4352  // fall through
4353  case CURSOR:
4354  case IN:
4355  case NOT_IN:
4356  subQuery = Objects.requireNonNull(getSubQuery(expr));
4357  rex = Objects.requireNonNull(subQuery.expr);
4358  return StandardConvertletTable.castToValidatedType(
4359  expr, rex, validator, rexBuilder);
4360 
4361  case SELECT:
4362  case EXISTS:
4363  case SCALAR_QUERY:
4364  subQuery = getSubQuery(expr);
4365  assert subQuery != null;
4366  rex = subQuery.expr;
4367  assert rex != null : "rex != null";
4368 
4369  if (((kind == SqlKind.SCALAR_QUERY) || (kind == SqlKind.EXISTS))
4370  && isConvertedSubq(rex)) {
4371  // scalar sub-query or EXISTS has been converted to a
4372  // constant
4373  return rex;
4374  }
4375 
4376  // The indicator column is the last field of the sub-query.
4377  RexNode fieldAccess =
4378  rexBuilder.makeFieldAccess(rex, rex.getType().getFieldCount() - 1);
4379 
4380  // The indicator column will be nullable if it comes from
4381  // the null-generating side of the join. For EXISTS, add an
4382  // "IS TRUE" check so that the result is "BOOLEAN NOT NULL".
4383  if (fieldAccess.getType().isNullable() && kind == SqlKind.EXISTS) {
4384  fieldAccess =
4385  rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, fieldAccess);
4386  }
4387  return fieldAccess;
4388 
4389  case OVER:
4390  return convertOver(this, expr);
4391 
4392  default:
4393  // fall through
4394  }
4395 
4396  // Apply standard conversions.
4397  rex = expr.accept(this);
4398  return Objects.requireNonNull(rex);
4399  }
4400 
4405  public RexFieldCollation convertSortExpression(SqlNode expr,
4406  RelFieldCollation.Direction direction,
4407  RelFieldCollation.NullDirection nullDirection) {
4408  switch (expr.getKind()) {
4409  case DESCENDING:
4410  return convertSortExpression(((SqlCall) expr).operand(0),
4411  RelFieldCollation.Direction.DESCENDING,
4412  nullDirection);
4413  case NULLS_LAST:
4414  return convertSortExpression(((SqlCall) expr).operand(0),
4415  direction,
4416  RelFieldCollation.NullDirection.LAST);
4417  case NULLS_FIRST:
4418  return convertSortExpression(((SqlCall) expr).operand(0),
4419  direction,
4420  RelFieldCollation.NullDirection.FIRST);
4421  default:
4422  final Set<SqlKind> flags = EnumSet.noneOf(SqlKind.class);
4423  switch (direction) {
4424  case DESCENDING:
4425  flags.add(SqlKind.DESCENDING);
4426  }
4427  switch (nullDirection) {
4428  case UNSPECIFIED:
4429  final RelFieldCollation.NullDirection nullDefaultDirection =
4430  validator.getDefaultNullCollation().last(desc(direction))
4431  ? RelFieldCollation.NullDirection.LAST
4432  : RelFieldCollation.NullDirection.FIRST;
4433  if (nullDefaultDirection != direction.defaultNullDirection()) {
4434  SqlKind nullDirectionSqlKind =
4435  validator.getDefaultNullCollation().last(desc(direction))
4436  ? SqlKind.NULLS_LAST
4437  : SqlKind.NULLS_FIRST;
4438  flags.add(nullDirectionSqlKind);
4439  }
4440  break;
4441  case FIRST:
4442  flags.add(SqlKind.NULLS_FIRST);
4443  break;
4444  case LAST:
4445  flags.add(SqlKind.NULLS_LAST);
4446  break;
4447  }
4448  return new RexFieldCollation(convertExpression(expr), flags);
4449  }
4450  }
4451 
4460  private boolean isConvertedSubq(RexNode rex) {
4461  if ((rex instanceof RexLiteral) || (rex instanceof RexDynamicParam)) {
4462  return true;
4463  }
4464  if (rex instanceof RexCall) {
4465  RexCall call = (RexCall) rex;
4466  if (call.getOperator() == SqlStdOperatorTable.CAST) {
4467  RexNode operand = call.getOperands().get(0);
4468  if (operand instanceof RexLiteral) {
4469  return true;
4470  }
4471  }
4472  }
4473  return false;
4474  }
4475 
4476  public int getGroupCount() {
4477  if (agg != null) {
4478  return agg.groupExprs.size();
4479  }
4480  if (window != null) {
4481  return window.isAlwaysNonEmpty() ? 1 : 0;
4482  }
4483  return -1;
4484  }
4485 
4486  public RexBuilder getRexBuilder() {
4487  return rexBuilder;
4488  }
4489 
4490  public RexRangeRef getSubQueryExpr(SqlCall call) {
4491  final SubQuery subQuery = getSubQuery(call);
4492  assert subQuery != null;
4493  return (RexRangeRef) subQuery.expr;
4494  }
4495 
4496  public RelDataTypeFactory getTypeFactory() {
4497  return typeFactory;
4498  }
4499 
4500  public InitializerExpressionFactory getInitializerExpressionFactory() {
4501  return initializerExpressionFactory;
4502  }
4503 
4504  public SqlValidator getValidator() {
4505  return validator;
4506  }
4507 
4508  public RexNode convertLiteral(SqlLiteral literal) {
4509  return exprConverter.convertLiteral(this, literal);
4510  }
4511 
4512  public RexNode convertInterval(SqlIntervalQualifier intervalQualifier) {
4513  return exprConverter.convertInterval(this, intervalQualifier);
4514  }
4515 
4516  public RexNode visit(SqlLiteral literal) {
4517  return exprConverter.convertLiteral(this, literal);
4518  }
4519 
4520  public RexNode visit(SqlCall call) {
4521  if (agg != null) {
4522  final SqlOperator op = call.getOperator();
4523  if (window == null
4524  && (op.isAggregator() || op.getKind() == SqlKind.FILTER
4525  || op.getKind() == SqlKind.WITHIN_GROUP)) {
4526  return agg.lookupAggregates(call);
4527  }
4528  }
4529  return exprConverter.convertCall(
4530  this, new SqlCallBinding(validator, scope, call).permutedCall());
4531  }
4532 
4533  public RexNode visit(SqlNodeList nodeList) {
4534  throw new UnsupportedOperationException();
4535  }
4536 
4537  public RexNode visit(SqlIdentifier id) {
4538  return convertIdentifier(this, id);
4539  }
4540 
4541  public RexNode visit(SqlDataTypeSpec type) {
4542  throw new UnsupportedOperationException();
4543  }
4544 
4545  public RexNode visit(SqlDynamicParam param) {
4546  return convertDynamicParam(param);
4547  }
4548 
4549  public RexNode visit(SqlIntervalQualifier intervalQualifier) {
4550  return convertInterval(intervalQualifier);
4551  }
4552 
4553  public List<SqlMonotonicity> getColumnMonotonicities() {
4554  return columnMonotonicities;
4555  }
4556  }
4557 
4558  private SqlQuantifyOperator negate(SqlQuantifyOperator operator) {
4559  assert operator.kind == SqlKind.ALL;
4560  return SqlStdOperatorTable.some(operator.comparisonKind.negateNullSafe());
4561  }
4562 
4564  private static class DeferredLookup {
4567 
4568  DeferredLookup(Blackboard bb, String originalRelName) {
4569  this.bb = bb;
4570  this.originalRelName = originalRelName;
4571  }
4572 
4573  public RexFieldAccess getFieldAccess(CorrelationId name) {
4574  return (RexFieldAccess) bb.mapCorrelateToRex.get(name);
4575  }
4576 
4578  return originalRelName;
4579  }
4580  }
4581 
4585  private class NoOpSubQueryConverter implements SubQueryConverter {
4586  public boolean canConvertSubQuery() {
4587  return false;
4588  }
4589 
4590  public RexNode convertSubQuery(SqlCall subQuery,
4591  SqlToRelConverter parentConverter,
4592  boolean isExists,
4593  boolean isExplain) {
4594  throw new IllegalArgumentException();
4595  }
4596  }
4597 
4617  protected class AggConverter implements SqlVisitor<Void> {
4618  private final Blackboard bb;
4619  public final AggregatingSelectScope aggregatingSelectScope;
4620 
4621  private final Map<String, String> nameMap = new HashMap<>();
4622 
4626  private final SqlNodeList groupExprs = new SqlNodeList(SqlParserPos.ZERO);
4627 
4631  private final Map<SqlNode, Ord<AuxiliaryConverter>> auxiliaryGroupExprs =
4632  new HashMap<>();
4633 
4641  private final List<Pair<RexNode, String>> convertedInputExprs = new ArrayList<>();
4642 
4649  private final List<AggregateCall> aggCalls = new ArrayList<>();
4650  private final Map<SqlNode, RexNode> aggMapping = new HashMap<>();
4651  private final Map<AggregateCall, RexNode> aggCallMapping = new HashMap<>();
4652 
4654  private boolean inOver = false;
4655 
4666  public AggConverter(Blackboard bb, SqlSelect select) {
4667  this.bb = bb;
4668  this.aggregatingSelectScope =
4669  (AggregatingSelectScope) bb.getValidator().getSelectScope(select);
4670 
4671  // Collect all expressions used in the select list so that aggregate
4672  // calls can be named correctly.
4673  final SqlNodeList selectList = select.getSelectList();
4674  for (int i = 0; i < selectList.size(); i++) {
4675  SqlNode selectItem = selectList.get(i);
4676  String name = null;
4677  if (SqlUtil.isCallTo(selectItem, SqlStdOperatorTable.AS)) {
4678  final SqlCall call = (SqlCall) selectItem;
4679  selectItem = call.operand(0);
4680  name = call.operand(1).toString();
4681  }
4682  if (name == null) {
4683  name = validator.deriveAlias(selectItem, i);
4684  }
4685  nameMap.put(selectItem.toString(), name);
4686  }
4687  }
4688 
4689  public int addGroupExpr(SqlNode expr) {
4690  int ref = lookupGroupExpr(expr);
4691  if (ref >= 0) {
4692  return ref;
4693  }
4694  final int index = groupExprs.size();
4695  groupExprs.add(expr);
4696  String name = nameMap.get(expr.toString());
4697  RexNode convExpr = bb.convertExpression(expr);
4698  addExpr(convExpr, name);
4699 
4700  if (expr instanceof SqlCall) {
4701  SqlCall call = (SqlCall) expr;
4702  for (Pair<SqlNode, AuxiliaryConverter> p :
4703  SqlStdOperatorTable.convertGroupToAuxiliaryCalls(call)) {
4704  addAuxiliaryGroupExpr(p.left, index, p.right);
4705  }
4706  }
4707 
4708  return index;
4709  }
4710 
4711  void addAuxiliaryGroupExpr(SqlNode node, int index, AuxiliaryConverter converter) {
4712  for (SqlNode node2 : auxiliaryGroupExprs.keySet()) {
4713  if (node2.equalsDeep(node, Litmus.IGNORE)) {
4714  return;
4715  }
4716  }
4717  auxiliaryGroupExprs.put(node, Ord.of(index, converter));
4718  }
4719 
4726  private void addExpr(RexNode expr, String name) {
4727  if ((name == null) && (expr instanceof RexInputRef)) {
4728  final int i = ((RexInputRef) expr).getIndex();
4729  name = bb.root.getRowType().getFieldList().get(i).getName();
4730  }
4731  if (Pair.right(convertedInputExprs).contains(name)) {
4732  // In case like 'SELECT ... GROUP BY x, y, x', don't add
4733  // name 'x' twice.
4734  name = null;
4735  }
4736  convertedInputExprs.add(Pair.of(expr, name));
4737  }
4738 
4739  public Void visit(SqlIdentifier id) {
4740  return null;
4741  }
4742 
4743  public Void visit(SqlNodeList nodeList) {
4744  for (int i = 0; i < nodeList.size(); i++) {
4745  nodeList.get(i).accept(this);
4746  }
4747  return null;
4748  }
4749 
4750  public Void visit(SqlLiteral lit) {
4751  return null;
4752  }
4753 
4754  public Void visit(SqlDataTypeSpec type) {
4755  return null;
4756  }
4757 
4758  public Void visit(SqlDynamicParam param) {
4759  return null;
4760  }
4761 
4762  public Void visit(SqlIntervalQualifier intervalQualifier) {
4763  return null;
4764  }
4765 
4766  public Void visit(SqlCall call) {
4767  switch (call.getKind()) {
4768  case FILTER:
4769  case WITHIN_GROUP:
4770  translateAgg(call);
4771  return null;
4772  case SELECT:
4773  // rchen 2006-10-17:
4774  // for now do not detect aggregates in sub-queries.
4775  return null;
4776  }
4777  final boolean prevInOver = inOver;
4778  // Ignore window aggregates and ranking functions (associated with OVER
4779  // operator). However, do not ignore nested window aggregates.
4780  if (call.getOperator().getKind() == SqlKind.OVER) {
4781  // Track aggregate nesting levels only within an OVER operator.
4782  List<SqlNode> operandList = call.getOperandList();
4783  assert operandList.size() == 2;
4784 
4785  // Ignore the top level window aggregates and ranking functions
4786  // positioned as the first operand of a OVER operator
4787  inOver = true;
4788  operandList.get(0).accept(this);
4789 
4790  // Normal translation for the second operand of a OVER operator
4791  inOver = false;
4792  operandList.get(1).accept(this);
4793  return null;
4794  }
4795 
4796  // Do not translate the top level window aggregate. Only do so for
4797  // nested aggregates, if present
4798  if (call.getOperator().isAggregator()) {
4799  if (inOver) {
4800  // Add the parent aggregate level before visiting its children
4801  inOver = false;
4802  } else {
4803  // We're beyond the one ignored level
4804  translateAgg(call);
4805  return null;
4806  }
4807  }
4808  for (SqlNode operand : call.getOperandList()) {
4809  // Operands are occasionally null, e.g. switched CASE arg 0.
4810  if (operand != null) {
4811  operand.accept(this);
4812  }
4813  }
4814  // Remove the parent aggregate level after visiting its children
4815  inOver = prevInOver;
4816  return null;
4817  }
4818 
4819  private void translateAgg(SqlCall call) {
4820  translateAgg(call, null, null, false, call);
4821  }
4822 
4823  private void translateAgg(SqlCall call,
4824  SqlNode filter,
4825  SqlNodeList orderList,
4826  boolean ignoreNulls,
4827  SqlCall outerCall) {
4828  assert bb.agg == this;
4829  assert outerCall != null;
4830  switch (call.getKind()) {
4831  case FILTER:
4832  assert filter == null;
4833  translateAgg(
4834  call.operand(0), call.operand(1), orderList, ignoreNulls, outerCall);
4835  return;
4836  case WITHIN_GROUP:
4837  assert orderList == null;
4838  translateAgg(call.operand(0), filter, call.operand(1), ignoreNulls, outerCall);
4839  return;
4840  case IGNORE_NULLS:
4841  ignoreNulls = true;
4842  // fall through
4843  case RESPECT_NULLS:
4844  translateAgg(call.operand(0), filter, orderList, ignoreNulls, outerCall);
4845  return;
4846  }
4847  final List<Integer> args = new ArrayList<>();
4848  int filterArg = -1;
4849  final List<RelDataType> argTypes = call.getOperator() instanceof SqlCountAggFunction
4850  ? new ArrayList<>(call.getOperandList().size())
4851  : null;
4852  try {
4853  // switch out of agg mode
4854  bb.agg = null;
4855  for (SqlNode operand : call.getOperandList()) {
4856  // special case for COUNT(*): delete the *
4857  if (operand instanceof SqlIdentifier) {
4858  SqlIdentifier id = (SqlIdentifier) operand;
4859  if (id.isStar()) {
4860  assert call.operandCount() == 1;
4861  assert args.isEmpty();
4862  break;
4863  }
4864  }
4865  RexNode convertedExpr = bb.convertExpression(operand);
4866  assert convertedExpr != null;
4867  if (argTypes != null) {
4868  argTypes.add(convertedExpr.getType());
4869  }
4870  args.add(lookupOrCreateGroupExpr(convertedExpr));
4871  }
4872 
4873  if (filter != null) {
4874  RexNode convertedExpr = bb.convertExpression(filter);
4875  assert convertedExpr != null;
4876  if (convertedExpr.getType().isNullable()) {
4877  convertedExpr =
4878  rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, convertedExpr);
4879  }
4880  filterArg = lookupOrCreateGroupExpr(convertedExpr);
4881  }
4882  } finally {
4883  // switch back into agg mode
4884  bb.agg = this;
4885  }
4886 
4887  SqlAggFunction aggFunction = (SqlAggFunction) call.getOperator();
4888  final RelDataType type = validator.deriveType(bb.scope, call);
4889  boolean distinct = false;
4890  SqlLiteral quantifier = call.getFunctionQuantifier();
4891  if ((null != quantifier) && (quantifier.getValue() == SqlSelectKeyword.DISTINCT)) {
4892  distinct = true;
4893  }
4894  boolean approximate = false;
4895  if (aggFunction == SqlStdOperatorTable.APPROX_COUNT_DISTINCT) {
4896  aggFunction = SqlStdOperatorTable.COUNT;
4897  distinct = true;
4898  approximate = true;
4899  }
4900  final RelCollation collation;
4901  if (orderList == null || orderList.size() == 0) {
4902  collation = RelCollations.EMPTY;
4903  } else {
4904  collation = RelCollations.of(
4905  orderList.getList()
4906  .stream()
4907  .map(order
4908  -> bb.convertSortExpression(order,
4909  RelFieldCollation.Direction.ASCENDING,
4910  RelFieldCollation.NullDirection.UNSPECIFIED))
4911  .map(fieldCollation
4912  -> new RelFieldCollation(
4913  lookupOrCreateGroupExpr(fieldCollation.left),
4914  fieldCollation.getDirection(),
4915  fieldCollation.getNullDirection()))
4916  .collect(Collectors.toList()));
4917  }
4918  final AggregateCall aggCall = AggregateCall.create(aggFunction,
4919  distinct,
4920  approximate,
4921  ignoreNulls,
4922  args,
4923  filterArg,
4924  collation,
4925  type,
4926  nameMap.get(outerCall.toString()));
4927  final AggregatingSelectScope.Resolved r = aggregatingSelectScope.resolved.get();
4928  RexNode rex = rexBuilder.addAggCall(
4929  aggCall, groupExprs.size(), aggCalls, aggCallMapping, argTypes);
4930  aggMapping.put(outerCall, rex);
4931  }
4932 
4933  private int lookupOrCreateGroupExpr(RexNode expr) {
4934  int index = 0;
4935  for (RexNode convertedInputExpr : Pair.left(convertedInputExprs)) {
4936  if (expr.equals(convertedInputExpr)) {
4937  return index;
4938  }
4939  ++index;
4940  }
4941 
4942  // not found -- add it
4943  addExpr(expr, null);
4944  return index;
4945  }
4946 
4951  public int lookupGroupExpr(SqlNode expr) {
4952  for (int i = 0; i < groupExprs.size(); i++) {
4953  SqlNode groupExpr = groupExprs.get(i);
4954  if (expr.equalsDeep(groupExpr, Litmus.IGNORE)) {
4955  return i;
4956  }
4957  }
4958  return -1;
4959  }
4960 
4961  public RexNode lookupAggregates(SqlCall call) {
4962  // assert call.getOperator().isAggregator();
4963  assert bb.agg == this;
4964 
4965  for (Map.Entry<SqlNode, Ord<AuxiliaryConverter>> e :
4966  auxiliaryGroupExprs.entrySet()) {
4967  if (call.equalsDeep(e.getKey(), Litmus.IGNORE)) {
4968  AuxiliaryConverter converter = e.getValue().e;
4969  final int groupOrdinal = e.getValue().i;
4970  return converter.convert(rexBuilder,
4971  convertedInputExprs.get(groupOrdinal).left,
4972  rexBuilder.makeInputRef(bb.root, groupOrdinal));
4973  }
4974  }
4975 
4976  return aggMapping.get(call);
4977  }
4978 
4979  public List<Pair<RexNode, String>> getPreExprs() {
4980  return convertedInputExprs;
4981  }
4982 
4983  public List<AggregateCall> getAggCalls() {
4984  return aggCalls;
4985  }
4986 
4987  public RelDataTypeFactory getTypeFactory() {
4988  return typeFactory;
4989  }
4990  }
4991 
4995  private static class LookupContext {
4996  private final List<Pair<RelNode, Integer>> relOffsetList = new ArrayList<>();
4997 
5005  LookupContext(Blackboard bb, List<RelNode> rels, int systemFieldCount) {
5006  bb.flatten(rels, systemFieldCount, new int[] {0}, relOffsetList);
5007  }
5008 
5021  Pair<RelNode, Integer> findRel(int offset) {
5022  return relOffsetList.get(offset);
5023  }
5024  }
5025 
5058  private class HistogramShuttle extends RexShuttle {
5063  static final boolean ENABLE_HISTOGRAM_AGG = false;
5064 
5065  private final List<RexNode> partitionKeys;
5066  private final ImmutableList<RexFieldCollation> orderKeys;
5067  private final RexWindowBound lowerBound;
5068  private final RexWindowBound upperBound;
5069  private final SqlWindow window;
5070  private final boolean distinct;
5071  private final boolean ignoreNulls;
5072 
5073  HistogramShuttle(List<RexNode> partitionKeys,
5074  ImmutableList<RexFieldCollation> orderKeys,
5075  RexWindowBound lowerBound,
5076  RexWindowBound upperBound,
5077  SqlWindow window,
5078  boolean distinct,
5079  boolean ignoreNulls) {
5080  this.partitionKeys = partitionKeys;
5081  this.orderKeys = orderKeys;
5082  this.lowerBound = lowerBound;
5083  this.upperBound = upperBound;
5084  this.window = window;
5085  this.distinct = distinct;
5086  this.ignoreNulls = ignoreNulls;
5087  }
5088 
5089  public RexNode visitCall(RexCall call) {
5090  final SqlOperator op = call.getOperator();
5091  if (!(op instanceof SqlAggFunction)) {
5092  return super.visitCall(call);
5093  }
5094  final SqlAggFunction aggOp = (SqlAggFunction) op;
5095  final RelDataType type = call.getType();
5096  List<RexNode> exprs = call.getOperands();
5097 
5098  SqlFunction histogramOp = !ENABLE_HISTOGRAM_AGG ? null : getHistogramOp(aggOp);
5099 
5100  if (histogramOp != null) {
5101  final RelDataType histogramType = computeHistogramType(type);
5102 
5103  // For DECIMAL, since it's already represented as a bigint we
5104  // want to do a reinterpretCast instead of a cast to avoid
5105  // losing any precision.
5106  boolean reinterpretCast = type.getSqlTypeName() == SqlTypeName.DECIMAL;
5107 
5108  // Replace original expression with CAST of not one
5109  // of the supported types
5110  if (histogramType != type) {
5111  exprs = new ArrayList<>(exprs);
5112  exprs.set(0,
5113  reinterpretCast ? rexBuilder.makeReinterpretCast(
5114  histogramType, exprs.get(0), rexBuilder.makeLiteral(false))
5115  : rexBuilder.makeCast(histogramType, exprs.get(0)));
5116  }
5117 
5118  RexCallBinding bind = new RexCallBinding(rexBuilder.getTypeFactory(),
5119  SqlStdOperatorTable.HISTOGRAM_AGG,
5120  exprs,
5121  ImmutableList.of());
5122 
5123  RexNode over = rexBuilder.makeOver(
5124  SqlStdOperatorTable.HISTOGRAM_AGG.inferReturnType(bind),
5125  SqlStdOperatorTable.HISTOGRAM_AGG,
5126  exprs,
5127  partitionKeys,
5128  orderKeys,
5129  lowerBound,
5130  upperBound,
5131  window.isRows(),
5132  window.isAllowPartial(),
5133  false,
5134  distinct,
5135  ignoreNulls);
5136 
5137  RexNode histogramCall =
5138  rexBuilder.makeCall(histogramType, histogramOp, ImmutableList.of(over));
5139 
5140  // If needed, post Cast result back to original
5141  // type.
5142  if (histogramType != type) {
5143  if (reinterpretCast) {
5144  histogramCall = rexBuilder.makeReinterpretCast(
5145  type, histogramCall, rexBuilder.makeLiteral(false));
5146  } else {
5147  histogramCall = rexBuilder.makeCast(type, histogramCall);
5148  }
5149  }
5150 
5151  return histogramCall;
5152  } else {
5153  boolean needSum0 = aggOp == SqlStdOperatorTable.SUM && type.isNullable();
5154  SqlAggFunction aggOpToUse = needSum0 ? SqlStdOperatorTable.SUM0 : aggOp;
5155  return rexBuilder.makeOver(type,
5156  aggOpToUse,
5157  exprs,
5158  partitionKeys,
5159  orderKeys,
5160  lowerBound,
5161  upperBound,
5162  window.isRows(),
5163  window.isAllowPartial(),
5164  needSum0,
5165  distinct,
5166  ignoreNulls);
5167  }
5168  }
5169 
5181  SqlFunction getHistogramOp(SqlAggFunction aggFunction) {
5182  if (aggFunction == SqlStdOperatorTable.MIN) {
5183  return SqlStdOperatorTable.HISTOGRAM_MIN;
5184  } else if (aggFunction == SqlStdOperatorTable.MAX) {
5185  return SqlStdOperatorTable.HISTOGRAM_MAX;
5186  } else if (aggFunction == SqlStdOperatorTable.FIRST_VALUE) {
5187  return SqlStdOperatorTable.HISTOGRAM_FIRST_VALUE;
5188  } else if (aggFunction == SqlStdOperatorTable.LAST_VALUE) {
5189  return SqlStdOperatorTable.HISTOGRAM_LAST_VALUE;
5190  } else {
5191  return null;
5192  }
5193  }
5194 
5199  private RelDataType computeHistogramType(RelDataType type) {
5200  if (SqlTypeUtil.isExactNumeric(type)
5201  && type.getSqlTypeName() != SqlTypeName.BIGINT) {
5202  return typeFactory.createSqlType(SqlTypeName.BIGINT);
5203  } else if (SqlTypeUtil.isApproximateNumeric(type)
5204  && type.getSqlTypeName() != SqlTypeName.DOUBLE) {
5205  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
5206  } else {
5207  return type;
5208  }
5209  }
5210  }
5211 
5215  private static class SubQuery {
5216  final SqlNode node;
5217  final RelOptUtil.Logic logic;
5218  RexNode expr;
5219 
5220  private SubQuery(SqlNode node, RelOptUtil.Logic logic) {
5221  this.node = node;
5222  this.logic = logic;
5223  }
5224  }
5225 
5229  private static class AggregateFinder extends SqlBasicVisitor<Void> {
5230  final SqlNodeList list = new SqlNodeList(SqlParserPos.ZERO);
5231  final SqlNodeList filterList = new SqlNodeList(SqlParserPos.ZERO);
5232  final SqlNodeList orderList = new SqlNodeList(SqlParserPos.ZERO);
5233 
5234  @Override
5235  public Void visit(SqlCall call) {
5236  // ignore window aggregates and ranking functions (associated with OVER
5237  // operator)
5238  if (call.getOperator().getKind() == SqlKind.OVER) {
5239  return null;
5240  }
5241 
5242  if (call.getOperator().getKind() == SqlKind.FILTER) {
5243  // the WHERE in a FILTER must be tracked too so we can call replaceSubQueries on
5244  // it.
5245  // see https://issues.apache.org/jira/browse/CALCITE-1910
5246  final SqlNode aggCall = call.getOperandList().get(0);
5247  final SqlNode whereCall = call.getOperandList().get(1);
5248  list.add(aggCall);
5249  filterList.add(whereCall);
5250  return null;
5251  }
5252 
5253  if (call.getOperator().getKind() == SqlKind.WITHIN_GROUP) {
5254  // the WHERE in a WITHIN_GROUP must be tracked too so we can call
5255  // replaceSubQueries on it.
5256  // see https://issues.apache.org/jira/browse/CALCITE-1910
5257  final SqlNode aggCall = call.getOperandList().get(0);
5258  final SqlNodeList orderList = (SqlNodeList) call.getOperandList().get(1);
5259  list.add(aggCall);
5260  orderList.getList().forEach(this.orderList::add);
5261  return null;
5262  }
5263 
5264  if (call.getOperator().isAggregator()) {
5265  list.add(call);
5266  return null;
5267  }
5268 
5269  // Don't traverse into sub-queries, even if they contain aggregate
5270  // functions.
5271  if (call instanceof SqlSelect) {
5272  return null;
5273  }
5274 
5275  return call.getOperator().acceptCall(this, call);
5276  }
5277  }
5278 
5282  private static class CorrelationUse {
5283  private final CorrelationId id;
5284  private final ImmutableBitSet requiredColumns;
5286  private final RelNode r;
5287 
5288  CorrelationUse(CorrelationId id, ImmutableBitSet requiredColumns, RelNode r) {
5289  this.id = id;
5290  this.requiredColumns = requiredColumns;
5291  this.r = r;
5292  }
5293  }
5294 
5296  public static ConfigBuilder configBuilder() {
5297  return new ConfigBuilder();
5298  }
5299 
5307  public interface Config {
5309  Config DEFAULT = configBuilder().build();
5310 
5318  boolean isConvertTableAccess();
5319 
5324  BiPredicate<SqlNode, Join> getPushdownJoinCondition();
5325 
5330  boolean isDecorrelationEnabled();
5331 
5336  boolean isTrimUnusedFields();
5337 
5343  boolean isCreateValuesRel();
5344 
5349  boolean isExplain();
5350 
5355  boolean isExpand();
5356 
5363  BiPredicate<SqlNode, SqlNode> getExpandPredicate();
5364 
5374  int getInSubQueryThreshold();
5375 
5380  RelBuilderFactory getRelBuilderFactory();
5381  }
5382 
5384  public static class ConfigBuilder {
5385  private boolean convertTableAccess = true;
5386  private boolean decorrelationEnabled = true;
5387  private boolean trimUnusedFields = false;
5388  private boolean createValuesRel = true;
5389  private boolean explain;
5390  private boolean expand = true;
5391  private BiPredicate<SqlNode, Join> pushdownJoinCondition;
5392  private int inSubQueryThreshold = DEFAULT_IN_SUB_QUERY_THRESHOLD;
5393  private RelBuilderFactory relBuilderFactory = RelFactories.LOGICAL_BUILDER;
5394  private BiPredicate<SqlNode, SqlNode> expandPredicate;
5395 
5396  private ConfigBuilder() {}
5397 
5400  this.convertTableAccess = config.isConvertTableAccess();
5401  this.decorrelationEnabled = config.isDecorrelationEnabled();
5402  this.trimUnusedFields = config.isTrimUnusedFields();
5403  this.createValuesRel = config.isCreateValuesRel();
5404  this.explain = config.isExplain();
5405  this.expand = config.isExpand();
5406  this.inSubQueryThreshold = config.getInSubQueryThreshold();
5407  this.relBuilderFactory = config.getRelBuilderFactory();
5408  if (!(config.getExpandPredicate() instanceof ConfigImpl.DefaultExpandPredicate)) {
5409  this.expandPredicate = config.getExpandPredicate();
5410  }
5411  this.pushdownJoinCondition = config.getPushdownJoinCondition();
5412  return this;
5413  }
5414 
5415  public ConfigBuilder withConvertTableAccess(boolean convertTableAccess) {
5416  this.convertTableAccess = convertTableAccess;
5417  return this;
5418  }
5419 
5420  public ConfigBuilder withDecorrelationEnabled(boolean enabled) {
5421  this.decorrelationEnabled = enabled;
5422  return this;
5423  }
5424 
5425  public ConfigBuilder withTrimUnusedFields(boolean trimUnusedFields) {
5426  this.trimUnusedFields = trimUnusedFields;
5427  return this;
5428  }
5429 
5430  public ConfigBuilder withCreateValuesRel(boolean createValuesRel) {
5431  this.createValuesRel = createValuesRel;
5432  return this;
5433  }
5434 
5435  public ConfigBuilder withExplain(boolean explain) {
5436  this.explain = explain;
5437  return this;
5438  }
5439 
5440  public ConfigBuilder withExpand(boolean expand) {
5441  this.expand = expand;
5442  return this;
5443  }
5444 
5445  public ConfigBuilder withPushdownJoinCondition(BiPredicate<SqlNode, Join> pushdown) {
5446  this.pushdownJoinCondition = pushdown;
5447  return this;
5448  }
5449 
5450  public ConfigBuilder withExpandPredicate(BiPredicate<SqlNode, SqlNode> predicate) {
5451  this.expandPredicate = predicate;
5452  return this;
5453  }
5454 
5455  @Deprecated // to be removed before 2.0
5456  public ConfigBuilder withInSubqueryThreshold(int inSubQueryThreshold) {
5457  return withInSubQueryThreshold(inSubQueryThreshold);
5458  }
5459 
5460  public ConfigBuilder withInSubQueryThreshold(int inSubQueryThreshold) {
5461  this.inSubQueryThreshold = inSubQueryThreshold;
5462  return this;
5463  }
5464 
5465  public ConfigBuilder withRelBuilderFactory(RelBuilderFactory relBuilderFactory) {
5466  this.relBuilderFactory = relBuilderFactory;
5467  return this;
5468  }
5469 
5471  public Config build() {
5472  return new ConfigImpl(convertTableAccess,
5473  decorrelationEnabled,
5474  trimUnusedFields,
5475  createValuesRel,
5476  explain,
5477  expand,
5478  pushdownJoinCondition,
5479  expandPredicate,
5480  inSubQueryThreshold,
5481  relBuilderFactory);
5482  }
5483  }
5484 
5489  private static class ConfigImpl implements Config {
5490  private final boolean convertTableAccess;
5491  private final boolean decorrelationEnabled;
5492  private final boolean trimUnusedFields;
5493  private final boolean createValuesRel;
5494  private final boolean explain;
5495  private final boolean expand;
5496  private final BiPredicate<SqlNode, SqlNode> expandPredicate;
5497  private final int inSubQueryThreshold;
5498  private final RelBuilderFactory relBuilderFactory;
5499 
5500  private class DefaultExpandPredicate implements BiPredicate<SqlNode, SqlNode> {
5501  @Override
5502  public boolean test(SqlNode t, SqlNode u) {
5503  return expand;
5504  }
5505  }
5506 
5507  private BiPredicate<SqlNode, Join> pushdownJoinCondition =
5508  new BiPredicate<SqlNode, Join>() {
5509  public boolean test(SqlNode t, Join u) {
5510  return true;
5511  };
5512  };
5513 
5514  private ConfigImpl(boolean convertTableAccess,
5515  boolean decorrelationEnabled,
5516  boolean trimUnusedFields,
5517  boolean createValuesRel,
5518  boolean explain,
5519  boolean expand,
5520  BiPredicate<SqlNode, Join> pushdownJoinCondition,
5521  BiPredicate<SqlNode, SqlNode> expandPredicate,
5522  int inSubQueryThreshold,
5523  RelBuilderFactory relBuilderFactory) {
5524  this.convertTableAccess = convertTableAccess;
5525  this.decorrelationEnabled = decorrelationEnabled;
5526  this.trimUnusedFields = trimUnusedFields;
5527  this.createValuesRel = createValuesRel;
5528  this.explain = explain;
5529  this.expand = expand;
5530 
5531  if (null == expandPredicate) {
5532  expandPredicate = new DefaultExpandPredicate();
5533  }
5534  this.expandPredicate = expandPredicate;
5535  this.inSubQueryThreshold = inSubQueryThreshold;
5536  this.relBuilderFactory = relBuilderFactory;
5537 
5538  if (null != pushdownJoinCondition) {
5539  this.pushdownJoinCondition = pushdownJoinCondition;
5540  }
5541  }
5542 
5543  public boolean isConvertTableAccess() {
5544  return convertTableAccess;
5545  }
5546 
5547  public boolean isDecorrelationEnabled() {
5548  return decorrelationEnabled;
5549  }
5550 
5551  public boolean isTrimUnusedFields() {
5552  return trimUnusedFields;
5553  }
5554 
5555  public boolean isCreateValuesRel() {
5556  return createValuesRel;
5557  }
5558 
5559  public boolean isExplain() {
5560  return explain;
5561  }
5562 
5563  public boolean isExpand() {
5564  return expand;
5565  }
5566 
5567  public BiPredicate<SqlNode, Join> getPushdownJoinCondition() {
5568  return pushdownJoinCondition;
5569  }
5570 
5571  public int getInSubQueryThreshold() {
5572  return inSubQueryThreshold;
5573  }
5574 
5575  public RelBuilderFactory getRelBuilderFactory() {
5576  return relBuilderFactory;
5577  }
5578 
5579  public BiPredicate<SqlNode, SqlNode> getExpandPredicate() {
5580  return expandPredicate;
5581  }
5582  }
5583 }
5584 
5585 // End SqlToRelConverter.java
RelRoot convertWith(SqlWith with, boolean top)
void snapshotTemporalTable(Blackboard bb, SqlCall call)
SqlQuantifyOperator negate(SqlQuantifyOperator operator)
JoinType
Definition: sqldefs.h:98
void setDynamicParamCountInExplain(int explainParamCount)
static SqlNode pushDownNotForIn(SqlValidatorScope scope, SqlNode sqlNode)
HistogramShuttle(List< RexNode > partitionKeys, ImmutableList< RexFieldCollation > orderKeys, RexWindowBound lowerBound, RexWindowBound upperBound, SqlWindow window, boolean distinct, boolean ignoreNulls)
void extraSelectItems(Blackboard bb, SqlSelect select, List< RexNode > exprList, List< String > nameList, Collection< String > aliasList, List< SqlMonotonicity > columnMonotonicityList)
void addAuxiliaryGroupExpr(SqlNode node, int index, AuxiliaryConverter converter)
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)
ConfigBuilder withCreateValuesRel(boolean createValuesRel)
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)
RexFieldCollation convertSortExpression(SqlNode expr, RelFieldCollation.Direction direction, RelFieldCollation.NullDirection nullDirection)
Void visit(SqlIntervalQualifier intervalQualifier)
ConfigBuilder withExpandPredicate(BiPredicate< SqlNode, SqlNode > predicate)
void afterTableFunction(SqlToRelConverter.Blackboard bb, SqlCall call, LogicalTableFunctionScan callRel)
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:35
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)
ConfigBuilder withRelBuilderFactory(RelBuilderFactory relBuilderFactory)
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
void flatten(List< RelNode > rels, int systemFieldCount, int[] start, List< Pair< RelNode, Integer >> relOffsetList)
final Map< SqlNode, RexNode > mapConvertedNonCorrSubqs
RexLiteral convertLiteralInValuesList(SqlNode sqlNode, Blackboard bb, RelDataType rowType, int iField)
RexNode lookup(int offset, LookupContext lookupContext)
ConfigBuilder withInSubqueryThreshold(int inSubQueryThreshold)
void distinctify(Blackboard bb, boolean checkForDupExprs)
ConfigBuilder withPushdownJoinCondition(BiPredicate< SqlNode, Join > pushdown)
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)
void convertIdentifier(Blackboard bb, SqlIdentifier id, SqlNodeList extendedColumns)
LookupContext(Blackboard bb, List< RelNode > rels, int systemFieldCount)
ConfigBuilder withInSubQueryThreshold(int inSubQueryThreshold)
int64_t const int32_t sz assert(dest)
ConfigBuilder withTrimUnusedFields(boolean trimUnusedFields)
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)
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)
BiPredicate< SqlNode, SqlNode > getExpandPredicate()
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)
static SqlNode reg(SqlValidatorScope scope, SqlNode e)
RexNode visit(SqlIntervalQualifier intervalQualifier)
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 convertInterval(SqlIntervalQualifier intervalQualifier)
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)
ConfigImpl(boolean convertTableAccess, boolean decorrelationEnabled, boolean trimUnusedFields, boolean createValuesRel, boolean explain, boolean expand, BiPredicate< SqlNode, Join > pushdownJoinCondition, BiPredicate< SqlNode, SqlNode > expandPredicate, int inSubQueryThreshold, RelBuilderFactory relBuilderFactory)
static boolean desc(RelFieldCollation.Direction direction)
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
void registerSubQuery(SqlNode node, RelOptUtil.Logic logic)
CorrelationUse(CorrelationId id, ImmutableBitSet requiredColumns, RelNode r)
RelNode convertToSingleValueSubq(SqlNode query, RelNode plan)
static JoinRelType convertJoinType(JoinType joinType)
ConfigBuilder withConvertTableAccess(boolean convertTableAccess)
void translateAgg(SqlCall call, SqlNode filter, SqlNodeList orderList, boolean ignoreNulls, SqlCall outerCall)
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)