29 package org.apache.calcite.sql2rel;
31 import static org.apache.calcite.sql.SqlUtil.stripAs;
33 import com.google.common.base.Preconditions;
34 import com.google.common.collect.ImmutableList;
35 import com.google.common.collect.ImmutableList.Builder;
36 import com.google.common.collect.ImmutableMap;
37 import com.google.common.collect.ImmutableSet;
38 import com.google.common.collect.Iterables;
39 import com.google.common.collect.Sets;
41 import org.apache.calcite.avatica.util.Spaces;
42 import org.apache.calcite.linq4j.Ord;
43 import org.apache.calcite.plan.Convention;
44 import org.apache.calcite.plan.RelOptCluster;
45 import org.apache.calcite.plan.RelOptPlanner;
46 import org.apache.calcite.plan.RelOptSamplingParameters;
47 import org.apache.calcite.plan.RelOptTable;
48 import org.apache.calcite.plan.RelOptUtil;
49 import org.apache.calcite.plan.RelTraitSet;
50 import org.apache.calcite.plan.ViewExpanders;
51 import org.apache.calcite.prepare.Prepare;
52 import org.apache.calcite.prepare.RelOptTableImpl;
53 import org.apache.calcite.rel.RelCollation;
54 import org.apache.calcite.rel.RelCollationTraitDef;
55 import org.apache.calcite.rel.RelCollations;
56 import org.apache.calcite.rel.RelFieldCollation;
57 import org.apache.calcite.rel.RelNode;
58 import org.apache.calcite.rel.RelRoot;
59 import org.apache.calcite.rel.RelShuttleImpl;
60 import org.apache.calcite.rel.SingleRel;
61 import org.apache.calcite.rel.core.AggregateCall;
62 import org.apache.calcite.rel.core.Collect;
63 import org.apache.calcite.rel.core.CorrelationId;
64 import org.apache.calcite.rel.core.Filter;
65 import org.apache.calcite.rel.core.Join;
66 import org.apache.calcite.rel.core.JoinInfo;
67 import org.apache.calcite.rel.core.JoinRelType;
68 import org.apache.calcite.rel.core.Project;
69 import org.apache.calcite.rel.core.RelFactories;
70 import org.apache.calcite.rel.core.Sample;
71 import org.apache.calcite.rel.core.Sort;
72 import org.apache.calcite.rel.hint.HintStrategyTable;
73 import org.apache.calcite.rel.hint.Hintable;
74 import org.apache.calcite.rel.hint.RelHint;
75 import org.apache.calcite.rel.logical.LogicalAggregate;
76 import org.apache.calcite.rel.logical.LogicalCorrelate;
77 import org.apache.calcite.rel.logical.LogicalFilter;
78 import org.apache.calcite.rel.logical.LogicalIntersect;
79 import org.apache.calcite.rel.logical.LogicalJoin;
80 import org.apache.calcite.rel.logical.LogicalMatch;
81 import org.apache.calcite.rel.logical.LogicalMinus;
82 import org.apache.calcite.rel.logical.LogicalProject;
83 import org.apache.calcite.rel.logical.LogicalSort;
84 import org.apache.calcite.rel.logical.LogicalTableFunctionScan;
85 import org.apache.calcite.rel.logical.LogicalTableModify;
86 import org.apache.calcite.rel.logical.LogicalTableScan;
87 import org.apache.calcite.rel.logical.LogicalUnion;
88 import org.apache.calcite.rel.logical.LogicalValues;
89 import org.apache.calcite.rel.metadata.RelColumnMapping;
90 import org.apache.calcite.rel.metadata.RelMetadataQuery;
91 import org.apache.calcite.rel.stream.Delta;
92 import org.apache.calcite.rel.stream.LogicalDelta;
93 import org.apache.calcite.rel.type.RelDataType;
94 import org.apache.calcite.rel.type.RelDataTypeFactory;
95 import org.apache.calcite.rel.type.RelDataTypeField;
96 import org.apache.calcite.rex.RexBuilder;
97 import org.apache.calcite.rex.RexCall;
98 import org.apache.calcite.rex.RexCallBinding;
99 import org.apache.calcite.rex.RexCorrelVariable;
100 import org.apache.calcite.rex.RexDynamicParam;
101 import org.apache.calcite.rex.RexFieldAccess;
102 import org.apache.calcite.rex.RexFieldCollation;
103 import org.apache.calcite.rex.RexInputRef;
104 import org.apache.calcite.rex.RexLiteral;
105 import org.apache.calcite.rex.RexNode;
106 import org.apache.calcite.rex.RexPatternFieldRef;
107 import org.apache.calcite.rex.RexRangeRef;
108 import org.apache.calcite.rex.RexShuttle;
109 import org.apache.calcite.rex.RexSubQuery;
110 import org.apache.calcite.rex.RexUtil;
111 import org.apache.calcite.rex.RexWindowBound;
112 import org.apache.calcite.rex.RexWindowBounds;
113 import org.apache.calcite.schema.ColumnStrategy;
114 import org.apache.calcite.schema.ModifiableTable;
115 import org.apache.calcite.schema.ModifiableView;
116 import org.apache.calcite.schema.Table;
117 import org.apache.calcite.schema.TranslatableTable;
118 import org.apache.calcite.schema.Wrapper;
119 import org.apache.calcite.sql.JoinConditionType;
121 import org.apache.calcite.sql.SqlAggFunction;
122 import org.apache.calcite.sql.SqlBasicCall;
123 import org.apache.calcite.sql.SqlCall;
124 import org.apache.calcite.sql.SqlCallBinding;
125 import org.apache.calcite.sql.SqlDataTypeSpec;
126 import org.apache.calcite.sql.SqlDelete;
127 import org.apache.calcite.sql.SqlDynamicParam;
128 import org.apache.calcite.sql.SqlExplainFormat;
129 import org.apache.calcite.sql.SqlExplainLevel;
130 import org.apache.calcite.sql.SqlFunction;
131 import org.apache.calcite.sql.SqlIdentifier;
132 import org.apache.calcite.sql.SqlInsert;
133 import org.apache.calcite.sql.SqlIntervalQualifier;
134 import org.apache.calcite.sql.SqlJoin;
135 import org.apache.calcite.sql.SqlKind;
136 import org.apache.calcite.sql.SqlLiteral;
137 import org.apache.calcite.sql.SqlMatchRecognize;
138 import org.apache.calcite.sql.SqlMerge;
139 import org.apache.calcite.sql.SqlNode;
140 import org.apache.calcite.sql.SqlNodeList;
141 import org.apache.calcite.sql.SqlNumericLiteral;
142 import org.apache.calcite.sql.SqlOperator;
143 import org.apache.calcite.sql.SqlOperatorTable;
144 import org.apache.calcite.sql.SqlOrderBy;
145 import org.apache.calcite.sql.SqlSampleSpec;
146 import org.apache.calcite.sql.SqlSelect;
147 import org.apache.calcite.sql.SqlSelectKeyword;
148 import org.apache.calcite.sql.SqlSetOperator;
149 import org.apache.calcite.sql.SqlSnapshot;
150 import org.apache.calcite.sql.SqlUnnestOperator;
151 import org.apache.calcite.sql.SqlUpdate;
152 import org.apache.calcite.sql.SqlUtil;
153 import org.apache.calcite.sql.SqlValuesOperator;
154 import org.apache.calcite.sql.SqlWindow;
155 import org.apache.calcite.sql.SqlWith;
156 import org.apache.calcite.sql.SqlWithItem;
157 import org.apache.calcite.sql.fun.SqlCase;
158 import org.apache.calcite.sql.fun.SqlCountAggFunction;
159 import org.apache.calcite.sql.fun.SqlInOperator;
160 import org.apache.calcite.sql.fun.SqlQuantifyOperator;
161 import org.apache.calcite.sql.fun.SqlRowOperator;
162 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
163 import org.apache.calcite.sql.parser.SqlParserPos;
164 import org.apache.calcite.sql.type.SqlReturnTypeInference;
165 import org.apache.calcite.sql.type.SqlTypeName;
166 import org.apache.calcite.sql.type.SqlTypeUtil;
167 import org.apache.calcite.sql.type.TableFunctionReturnTypeInference;
168 import org.apache.calcite.sql.util.SqlBasicVisitor;
169 import org.apache.calcite.sql.util.SqlVisitor;
170 import org.apache.calcite.sql.validate.AggregatingSelectScope;
171 import org.apache.calcite.sql.validate.CollectNamespace;
172 import org.apache.calcite.sql.validate.DelegatingScope;
173 import org.apache.calcite.sql.validate.ListScope;
174 import org.apache.calcite.sql.validate.MatchRecognizeScope;
175 import org.apache.calcite.sql.validate.ParameterScope;
176 import org.apache.calcite.sql.validate.SelectScope;
177 import org.apache.calcite.sql.validate.SqlMonotonicity;
178 import org.apache.calcite.sql.validate.SqlNameMatcher;
179 import org.apache.calcite.sql.validate.SqlQualified;
180 import org.apache.calcite.sql.validate.SqlUserDefinedTableFunction;
181 import org.apache.calcite.sql.validate.SqlUserDefinedTableMacro;
182 import org.apache.calcite.sql.validate.SqlValidator;
183 import org.apache.calcite.sql.validate.SqlValidatorImpl;
184 import org.apache.calcite.sql.validate.SqlValidatorNamespace;
185 import org.apache.calcite.sql.validate.SqlValidatorScope;
186 import org.apache.calcite.sql.validate.SqlValidatorTable;
187 import org.apache.calcite.sql.validate.SqlValidatorUtil;
188 import org.apache.calcite.tools.RelBuilder;
189 import org.apache.calcite.tools.RelBuilderFactory;
190 import org.apache.calcite.util.ImmutableBitSet;
191 import org.apache.calcite.util.ImmutableIntList;
192 import org.apache.calcite.util.Litmus;
193 import org.apache.calcite.util.NlsString;
194 import org.apache.calcite.util.NumberUtil;
195 import org.apache.calcite.util.Pair;
196 import org.apache.calcite.util.Util;
197 import org.apache.calcite.util.trace.CalciteTrace;
198 import org.slf4j.Logger;
201 import java.math.BigDecimal;
202 import java.util.AbstractList;
203 import java.util.ArrayDeque;
204 import java.util.ArrayList;
205 import java.util.BitSet;
206 import java.util.Collection;
207 import java.util.Collections;
208 import java.util.Deque;
209 import java.util.EnumSet;
210 import java.util.HashMap;
211 import java.util.HashSet;
212 import java.util.List;
213 import java.util.Map;
214 import java.util.Objects;
215 import java.util.Set;
216 import java.util.TreeSet;
217 import java.util.function.BiPredicate;
218 import java.util.function.Supplier;
219 import java.util.function.UnaryOperator;
220 import java.util.stream.Collectors;
222 import javax.annotation.Nonnull;
253 protected final Map<RelNode, Integer>
leaves =
new HashMap<>();
255 private final SqlOperatorTable
opTab;
260 public final SqlToRelConverter.Config
config;
298 RelOptPlanner planner,
300 SqlRexConvertletTable convertletTable) {
314 SqlRexConvertletTable convertletTable) {
328 SqlRexConvertletTable convertletTable,
331 this.opTab = (validator == null) ? SqlStdOperatorTable.instance()
332 : validator.getOperatorTable();
336 this.rexBuilder = cluster.getRexBuilder();
337 this.typeFactory = rexBuilder.getTypeFactory();
338 this.exprConverter =
new SqlNodeToRexConverterImpl(convertletTable);
339 this.explainParamCount = 0;
340 this.config =
new ConfigBuilder().withConfig(
config).build();
341 this.relBuilder = config.getRelBuilderFactory()
343 .transform(config.getRelBuilderConfigTransform());
344 this.hintStrategies = config.getHintStrategyTable();
346 cluster.setHintStrategies(this.hintStrategies);
347 this.cluster = Objects.requireNonNull(
cluster);
371 return dynamicParamSqlNodes.size();
381 SqlNode sqlNode = dynamicParamSqlNodes.get(index);
382 if (sqlNode == null) {
383 throw Util.needToImplement(
"dynamic param type inference");
385 return validator.getValidatedNodeType(sqlNode);
419 Map<SqlNode, RexNode> alreadyConvertedNonCorrSubqs) {
420 mapConvertedNonCorrSubqs.putAll(alreadyConvertedNonCorrSubqs);
439 assert config.isExplain();
444 if (query.isA(SqlKind.DML)) {
452 final List<RelDataTypeField> validatedFields =
453 validator.getValidatedNodeType(query).getFieldList();
454 final RelDataType validatedRowType =
455 validator.getTypeFactory().createStructType(Pair.right(validatedFields),
456 SqlValidatorUtil.uniquify(Pair.left(validatedFields),
459 final List<RelDataTypeField> convertedFields =
460 result.getRowType().getFieldList().subList(0, validatedFields.size());
461 final RelDataType convertedRowType =
462 validator.getTypeFactory().createStructType(convertedFields);
464 if (!RelOptUtil.equal(
"validated row type",
466 "converted row type",
469 throw new AssertionError(
"Conversion to relational algebra failed to "
470 +
"preserve datatypes:\n"
471 +
"validated type:\n" + validatedRowType.getFullTypeString()
472 +
"\nconverted type:\n" + convertedRowType.getFullTypeString() +
"\nrel:\n"
473 + RelOptUtil.toString(result));
478 RelStructuredTypeFlattener typeFlattener =
new RelStructuredTypeFlattener(
480 return typeFlattener.rewrite(rootRel);
492 if (!
config.isDecorrelationEnabled()) {
496 if (result != rootRel) {
528 final List<RelCollation> collations =
529 rootRel.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE);
530 rootRel = trimmer.trim(rootRel);
531 if (!ordered && collations != null && !collations.isEmpty()
532 && !collations.equals(ImmutableList.of(RelCollations.EMPTY))) {
533 final RelTraitSet traitSet =
534 rootRel.getTraitSet().replace(RelCollationTraitDef.INSTANCE, collations);
535 rootRel = rootRel.copy(traitSet, rootRel.getInputs());
538 SQL2REL_LOGGER.debug(RelOptUtil.dumpPlan(
"Plan after trimming unused fields",
540 SqlExplainFormat.TEXT,
541 SqlExplainLevel.EXPPLAN_ATTRIBUTES));
568 SqlNode query,
final boolean needsValidation,
final boolean top) {
569 if (needsValidation) {
570 query = validator.validate(query);
576 result =
new LogicalDelta(
cluster, result.getTraitSet(),
result);
579 RelCollation collation = RelCollations.EMPTY;
580 if (!query.isA(SqlKind.DML)) {
588 SQL2REL_LOGGER.debug(RelOptUtil.dumpPlan(
"Plan after converting SqlNode to RelNode",
590 SqlExplainFormat.TEXT,
591 SqlExplainLevel.EXPPLAN_ATTRIBUTES));
594 final RelDataType validatedRowType = validator.getValidatedNodeType(query);
595 List<RelHint> hints =
new ArrayList<>();
596 if (query.getKind() == SqlKind.SELECT) {
597 final SqlSelect select = (SqlSelect) query;
598 if (select.hasHints()) {
603 result = RelOptUtil.propagateRelHints(
result,
false);
604 return RelRoot.of(
result, validatedRowType, query.getKind())
605 .withCollation(collation)
610 return query instanceof SqlSelect
611 && ((SqlSelect) query).isKeywordPresent(SqlSelectKeyword.STREAM);
615 switch (query.getKind()) {
617 return ((SqlSelect) query).getOrderList() != null
618 && ((SqlSelect) query).getOrderList().size() > 0;
620 return isOrdered(((SqlWith) query).body);
622 return ((SqlOrderBy) query).orderList.size() > 0;
629 if (r instanceof Sort) {
630 return ((Sort) r).collation;
632 if (r instanceof Project) {
635 if (r instanceof Delta) {
638 throw new AssertionError();
645 final SqlValidatorScope selectScope = validator.getWhereScope(select);
655 SqlValidatorScope scope, Map<String, RexNode> nameToNodeMap,
boolean top) {
656 return new Blackboard(scope, nameToNodeMap, top);
667 final List<SqlNode> orderExprList =
new ArrayList<>();
668 final List<RelFieldCollation> collationList =
new ArrayList<>();
669 gatherOrderExprs(bb, select, select.getOrderList(), orderExprList, collationList);
670 final RelCollation collation =
671 cluster.traitSet().canonize(RelCollations.of(collationList));
679 if (select.isDistinct()) {
684 select, bb, collation, orderExprList, select.getOffset(), select.getFetch());
686 if (select.hasHints()) {
687 final List<RelHint> hints = SqlUtil.getRelHint(
hintStrategies, select.getHints());
689 bb.setRoot(bb.root.accept(
new RelShuttleImpl() {
690 boolean attached =
false;
693 public RelNode visitChild(RelNode parent,
int i, RelNode child) {
694 if (parent instanceof Hintable && !attached) {
696 return ((Hintable) parent).attachHints(hints);
698 return super.visitChild(parent,
i, child);
704 bb.setRoot(bb.root,
true);
726 RelNode rel = bb.root;
727 if (checkForDupExprs && (rel instanceof LogicalProject)) {
728 LogicalProject project = (LogicalProject) rel;
729 final List<RexNode> projectExprs = project.getProjects();
730 final List<Integer> origins =
new ArrayList<>();
732 for (
int i = 0;
i < projectExprs.size();
i++) {
733 int x = projectExprs.indexOf(projectExprs.get(
i));
734 if (x >= 0 && x <
i) {
746 final Map<Integer, Integer> squished =
new HashMap<>();
747 final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
748 final List<Pair<RexNode, String>> newProjects =
new ArrayList<>();
749 for (
int i = 0;
i < fields.size();
i++) {
750 if (origins.get(
i) ==
i) {
751 squished.put(
i, newProjects.size());
752 newProjects.add(RexInputRef.of2(
i, fields));
755 rel = LogicalProject.create(
756 rel, ImmutableList.of(), Pair.left(newProjects), Pair.right(newProjects));
763 final List<Pair<RexNode, String>> undoProjects =
new ArrayList<>();
764 for (
int i = 0;
i < fields.size();
i++) {
765 final int origin = origins.get(
i);
766 RelDataTypeField
field = fields.get(
i);
767 undoProjects.add(Pair.of(
768 new RexInputRef(squished.get(origin), field.getType()), field.getName()));
771 rel = LogicalProject.create(
772 rel, ImmutableList.of(), Pair.left(undoProjects), Pair.right(undoProjects));
773 bb.setRoot(rel,
false);
780 final ImmutableBitSet groupSet =
781 ImmutableBitSet.range(rel.getRowType().getFieldCount());
782 rel =
createAggregate(bb, groupSet, ImmutableList.of(groupSet), ImmutableList.of());
784 bb.setRoot(rel,
false);
805 RelCollation collation,
806 List<SqlNode> orderExprList,
809 if (!bb.
top || select.getOrderList() == null
810 || select.getOrderList().getList().isEmpty()) {
811 assert !bb.top || collation.getFieldCollations().isEmpty();
813 || (offset instanceof SqlLiteral
814 && ((SqlLiteral) offset)
816 .equals(BigDecimal.ZERO)))
823 bb.setRoot(LogicalSort.create(bb.root,
834 if (orderExprList.size() > 0 && !bb.top) {
835 final List<RexNode> exprs =
new ArrayList<>();
836 final RelDataType rowType = bb.root.getRowType();
837 final int fieldCount = rowType.getFieldCount() - orderExprList.size();
838 for (
int i = 0;
i < fieldCount;
i++) {
839 exprs.add(rexBuilder.makeInputRef(bb.root,
i));
841 bb.setRoot(LogicalProject.create(bb.root,
844 rowType.getFieldNames().subList(0, fieldCount)),
856 SqlVisitor<Void> visitor =
new SqlBasicVisitor<Void>() {
857 public Void visit(SqlCall call) {
858 if (call.getOperator() instanceof SqlInOperator) {
859 throw new Util.FoundOne(call);
861 return super.visit(call);
864 node.accept(visitor);
866 }
catch (Util.FoundOne e) {
867 Util.swallow(e, null);
883 final SqlCall sqlCall = (SqlCall) sqlNode;
884 switch (sqlCall.getKind()) {
887 final List<SqlNode> operands =
new ArrayList<>();
888 for (SqlNode operand : sqlCall.getOperandList()) {
891 final SqlCall newCall =
892 sqlCall.getOperator().createCall(sqlCall.getParserPosition(), operands);
893 return reg(scope, newCall);
896 assert sqlCall.operand(0) instanceof SqlCall;
897 final SqlCall call = sqlCall.operand(0);
898 switch (sqlCall.operand(0).getKind()) {
900 final SqlCase caseNode = (SqlCase) call;
901 final SqlNodeList thenOperands =
new SqlNodeList(SqlParserPos.ZERO);
903 for (SqlNode thenOperand : caseNode.getThenOperands()) {
905 SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, thenOperand);
908 SqlNode elseOperand = caseNode.getElseOperand();
909 if (!SqlUtil.isNull(elseOperand)) {
912 SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, elseOperand);
917 SqlStdOperatorTable.CASE.createCall(SqlParserPos.ZERO,
918 caseNode.getValueOperand(),
919 caseNode.getWhenOperands(),
924 final List<SqlNode> orOperands =
new ArrayList<>();
925 for (SqlNode operand : call.getOperandList()) {
928 SqlStdOperatorTable.NOT.createCall(
929 SqlParserPos.ZERO, operand))));
932 SqlStdOperatorTable.OR.createCall(SqlParserPos.ZERO, orOperands));
935 final List<SqlNode> andOperands =
new ArrayList<>();
936 for (SqlNode operand : call.getOperandList()) {
939 SqlStdOperatorTable.NOT.createCall(
940 SqlParserPos.ZERO, operand))));
943 SqlStdOperatorTable.AND.createCall(SqlParserPos.ZERO, andOperands));
946 assert call.operandCount() == 1;
951 SqlStdOperatorTable.IN.createCall(
952 SqlParserPos.ZERO, call.getOperandList()));
956 SqlStdOperatorTable.NOT_IN.createCall(
957 SqlParserPos.ZERO, call.getOperandList()));
967 private static SqlNode
reg(SqlValidatorScope scope, SqlNode e) {
968 scope.getValidator().deriveType(scope, e);
984 final RexNode convertedWhere = bb.convertExpression(newWhere);
985 final RexNode convertedWhere2 =
986 RexUtil.removeNullabilityCast(
typeFactory, convertedWhere);
989 if (convertedWhere2.isAlwaysTrue()) {
993 final RelFactories.FilterFactory filterFactory = RelFactories.DEFAULT_FILTER_FACTORY;
994 final RelNode filter =
995 filterFactory.createFilter(bb.root, convertedWhere2, ImmutableSet.of());
999 assert p.r instanceof Filter;
1000 Filter
f = (Filter) p.r;
1001 r = LogicalFilter.create(f.getInput(), f.getCondition(), ImmutableSet.of(p.id));
1006 bb.setRoot(
r,
false);
1010 final Blackboard bb,
final SqlNode expr, RelOptUtil.Logic logic) {
1018 final RexNode expr = subQuery.expr;
1024 final SqlBasicCall call;
1026 final SqlNode query;
1027 final RelOptUtil.Exists converted;
1029 boolean isExpand = config.getExpandPredicate().test(bb.
getTopNode(), subQuery.node);
1031 switch (subQuery.node.getKind()) {
1036 case MULTISET_QUERY_CONSTRUCTOR:
1037 case MULTISET_VALUE_CONSTRUCTOR:
1038 case ARRAY_QUERY_CONSTRUCTOR:
1040 subQuery.expr = bb.register(rel, JoinRelType.INNER);
1047 call = (SqlBasicCall) subQuery.node;
1048 query = call.operand(1);
1049 if (!isExpand && !(query instanceof SqlNodeList)) {
1052 final SqlNode leftKeyNode = call.operand(0);
1054 final List<RexNode> leftKeys;
1055 switch (leftKeyNode.getKind()) {
1057 leftKeys =
new ArrayList<>();
1058 for (SqlNode sqlExpr : ((SqlBasicCall) leftKeyNode).getOperandList()) {
1059 leftKeys.add(bb.convertExpression(sqlExpr));
1063 leftKeys = ImmutableList.of(bb.convertExpression(leftKeyNode));
1066 if (query instanceof SqlNodeList) {
1067 SqlNodeList valueList = (SqlNodeList) query;
1069 && valueList.size() <
config.getInSubQueryThreshold()) {
1072 bb, leftKeys, valueList, (SqlInOperator) call.getOperator());
1111 if (bb.
root == null) {
1114 final RelDataType targetRowType = SqlTypeUtil.promoteToRowType(
1115 typeFactory, validator.getValidatedNodeType(leftKeyNode), null);
1116 final boolean notIn = call.getOperator().kind == SqlKind.NOT_IN;
1118 query, RelOptUtil.SubQueryType.IN, subQuery.logic, notIn, targetRowType);
1119 if (converted.indicator) {
1123 final RelDataType longType = typeFactory.createSqlType(SqlTypeName.BIGINT);
1124 final RelNode seek = converted.r.getInput(0);
1125 final int keyCount = leftKeys.size();
1126 final List<Integer>
args = ImmutableIntList.range(0, keyCount);
1127 LogicalAggregate aggregate = LogicalAggregate.create(seek,
1129 ImmutableBitSet.of(),
1131 ImmutableList.of(AggregateCall.create(SqlStdOperatorTable.COUNT,
1137 RelCollations.EMPTY,
1140 AggregateCall.create(SqlStdOperatorTable.COUNT,
1146 RelCollations.EMPTY,
1149 LogicalJoin
join = LogicalJoin.create(bb.root,
1155 bb.setRoot(
join,
false);
1158 converted.outerJoin ? JoinRelType.LEFT : JoinRelType.INNER,
1161 RelOptUtil.Logic logic = subQuery.logic;
1163 case TRUE_FALSE_UNKNOWN:
1164 case UNKNOWN_AS_TRUE:
1165 if (!converted.indicator) {
1166 logic = RelOptUtil.Logic.TRUE_FALSE;
1171 subQuery.expr = rexBuilder.makeCall(SqlStdOperatorTable.NOT, subQuery.expr);
1185 call = (SqlBasicCall) subQuery.node;
1186 query = call.operand(0);
1190 final SqlValidatorScope seekScope = (query instanceof SqlSelect)
1191 ?
validator.getSelectScope((SqlSelect) query)
1198 final RelMetadataQuery mq = seekRel.getCluster().getMetadataQuery();
1199 final Double minRowCount = mq.getMinRowCount(seekRel);
1200 if (minRowCount != null && minRowCount >= 1D) {
1201 subQuery.expr = rexBuilder.makeLiteral(
true);
1204 converted = RelOptUtil.createExistsPlan(seekRel,
1205 RelOptUtil.SubQueryType.EXISTS,
1209 assert !converted.indicator;
1213 subQuery.expr = bb.register(
converted.r, JoinRelType.LEFT);
1222 call = (SqlBasicCall) subQuery.node;
1223 query = call.operand(0);
1225 query, RelOptUtil.SubQueryType.SCALAR, subQuery.logic,
true, null);
1226 assert !converted.indicator;
1231 subQuery.expr = bb.register(rel, JoinRelType.LEFT);
1240 RelOptUtil.SubQueryType.SCALAR,
1244 assert !converted.indicator;
1245 subQuery.expr = bb.register(
converted.r, JoinRelType.LEFT);
1255 throw new AssertionError(
"unexpected kind of sub-query: " + subQuery.node);
1259 private RexNode
translateIn(RelOptUtil.Logic logic, RelNode root,
final RexNode rex) {
1262 return rexBuilder.makeLiteral(
true);
1265 case UNKNOWN_AS_FALSE:
1266 assert rex instanceof RexRangeRef;
1267 final int fieldCount = rex.getType().getFieldCount();
1268 RexNode rexNode = rexBuilder.makeFieldAccess(rex, fieldCount - 1);
1269 rexNode = rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, rexNode);
1279 final int k = (fieldCount - 1) / 2;
1280 for (
int i = 0;
i <
k;
i++) {
1281 rexNode = rexBuilder.makeCall(SqlStdOperatorTable.AND,
1283 rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL,
1284 rexBuilder.makeFieldAccess(rex,
i)));
1288 case TRUE_FALSE_UNKNOWN:
1289 case UNKNOWN_AS_TRUE:
1302 final Join
join = (Join) root;
1303 final Project left = (Project) join.getLeft();
1304 final RelNode leftLeft = ((Join) left.getInput()).getLeft();
1305 final int leftLeftCount = leftLeft.getRowType().getFieldCount();
1306 final RelDataType longType = typeFactory.createSqlType(SqlTypeName.BIGINT);
1307 final RexNode cRef = rexBuilder.makeInputRef(root, leftLeftCount);
1308 final RexNode ckRef = rexBuilder.makeInputRef(root, leftLeftCount + 1);
1309 final RexNode iRef =
1310 rexBuilder.makeInputRef(root, root.getRowType().getFieldCount() - 1);
1312 final RexLiteral zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO, longType);
1313 final RexLiteral trueLiteral = rexBuilder.makeLiteral(
true);
1314 final RexLiteral falseLiteral = rexBuilder.makeLiteral(
false);
1315 final RexNode unknownLiteral = rexBuilder.makeNullLiteral(trueLiteral.getType());
1317 final ImmutableList.Builder<RexNode>
args = ImmutableList.builder();
1318 args.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, cRef, zero),
1320 rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, iRef),
1322 final JoinInfo joinInfo = join.analyzeCondition();
1323 for (
int leftKey : joinInfo.leftKeys) {
1324 final RexNode kRef = rexBuilder.makeInputRef(root, leftKey);
1326 rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, kRef), unknownLiteral);
1328 args.add(rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, ckRef, cRef),
1332 return rexBuilder.makeCall(SqlStdOperatorTable.CASE, args.build());
1335 throw new AssertionError(logic);
1340 for (SqlNode node : valueList.getList()) {
1341 if (node instanceof SqlLiteral) {
1342 SqlLiteral lit = (SqlLiteral) node;
1343 if (lit.getValue() == null) {
1362 SubQuery subQuery,
Blackboard bb, RelNode converted,
boolean isExists) {
1363 SqlCall call = (SqlBasicCall) subQuery.node;
1369 RexNode constExpr = mapConvertedNonCorrSubqs.get(call);
1370 if (constExpr == null) {
1371 constExpr = subQueryConverter.convertSubQuery(
1372 call,
this, isExists, config.isExplain());
1374 if (constExpr != null) {
1375 subQuery.expr = constExpr;
1376 mapConvertedNonCorrSubqs.put(call, constExpr);
1393 if (query instanceof SqlSelect) {
1394 SqlSelect select = (SqlSelect) query;
1395 SqlNodeList selectList = select.getSelectList();
1396 SqlNodeList groupList = select.getGroup();
1398 if ((selectList.size() == 1) && ((groupList == null) || (groupList.size() == 0))) {
1399 SqlNode selectExpr = selectList.get(0);
1400 if (selectExpr instanceof SqlCall) {
1401 SqlCall selectExprCall = (SqlCall) selectExpr;
1402 if (Util.isSingleValue(selectExprCall)) {
1409 if (select.getFetch() != null && select.getFetch() instanceof SqlNumericLiteral) {
1410 SqlNumericLiteral limitNum = (SqlNumericLiteral) select.getFetch();
1411 if (((BigDecimal) limitNum.getValue()).intValue() < 2) {
1416 }
else if (query instanceof SqlCall) {
1420 SqlCall exprCall = (SqlCall) query;
1421 if (exprCall.getOperator() instanceof SqlValuesOperator
1422 && Util.isSingleValue(exprCall)) {
1428 return RelOptUtil.createSingleValueAggRel(
cluster, plan);
1440 final List<RexNode> leftKeys,
1441 SqlNodeList valuesList,
1443 final List<RexNode> comparisons =
new ArrayList<>();
1444 for (SqlNode rightVals : valuesList) {
1445 RexNode rexComparison;
1446 final SqlOperator comparisonOp;
1447 if (op instanceof SqlQuantifyOperator) {
1448 comparisonOp = RelOptUtil.op(
1449 ((SqlQuantifyOperator) op).comparisonKind, SqlStdOperatorTable.EQUALS);
1451 comparisonOp = SqlStdOperatorTable.EQUALS;
1453 if (leftKeys.size() == 1) {
1454 rexComparison = rexBuilder.makeCall(comparisonOp,
1457 leftKeys.get(0).getType(), bb.convertExpression(rightVals)));
1459 assert rightVals instanceof SqlCall;
1460 final SqlBasicCall call = (SqlBasicCall) rightVals;
1461 assert (call.getOperator() instanceof SqlRowOperator)
1462 && call.operandCount() == leftKeys.size();
1463 rexComparison = RexUtil.composeConjunction(
rexBuilder,
1464 Iterables.transform(Pair.zip(leftKeys, call.getOperandList()),
1466 -> rexBuilder.makeCall(comparisonOp,
1469 bb.convertExpression(pair.right)))));
1471 comparisons.add(rexComparison);
1476 return RexUtil.composeConjunction(
rexBuilder, comparisons,
true);
1478 return rexBuilder.makeCall(SqlStdOperatorTable.NOT,
1479 RexUtil.composeDisjunction(
rexBuilder, comparisons,
true));
1482 return RexUtil.composeDisjunction(
rexBuilder, comparisons,
true);
1484 throw new AssertionError();
1494 if (type.getSqlTypeName() == node.getType().getSqlTypeName()
1495 || (type.getSqlTypeName() == SqlTypeName.VARCHAR
1496 && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) {
1499 return rexBuilder.ensureType(
type, node,
true);
1513 return config.getInSubQueryThreshold();
1534 RelOptUtil.SubQueryType subQueryType,
1535 RelOptUtil.Logic logic,
1537 RelDataType targetDataType) {
1538 final SqlValidatorScope seekScope = (seek instanceof SqlSelect)
1539 ?
validator.getSelectScope((SqlSelect) seek)
1544 return RelOptUtil.createExistsPlan(seekRel, subQueryType, logic, notIn,
relBuilder);
1548 Blackboard bb, SqlNode seek, RelDataType targetRowType) {
1555 if (seek instanceof SqlNodeList) {
1557 bb, seek, ((SqlNodeList) seek).getList(),
false, targetRowType);
1565 Collection<SqlNode> rows,
1566 boolean allowLiteralsOnly,
1567 RelDataType targetRowType) {
1574 final ImmutableList.Builder<ImmutableList<RexLiteral>> tupleList =
1575 ImmutableList.builder();
1576 final RelDataType rowType;
1577 if (targetRowType != null) {
1578 rowType = targetRowType;
1580 rowType = SqlTypeUtil.promoteToRowType(
1581 typeFactory, validator.getValidatedNodeType(rowList), null);
1584 final List<RelNode> unionInputs =
new ArrayList<>();
1585 for (SqlNode node : rows) {
1588 call = (SqlBasicCall) node;
1589 ImmutableList.Builder<RexLiteral> tuple = ImmutableList.builder();
1590 for (Ord<SqlNode> operand : Ord.zip(call.operands)) {
1591 RexLiteral rexLiteral =
1593 if ((rexLiteral == null) && allowLiteralsOnly) {
1596 if ((rexLiteral == null) || !
config.isCreateValuesRel()) {
1601 tuple.add(rexLiteral);
1603 if (tuple != null) {
1604 tupleList.add(tuple.build());
1609 if ((rexLiteral != null) &&
config.isCreateValuesRel()) {
1610 tupleList.add(ImmutableList.of(rexLiteral));
1613 if ((rexLiteral == null) && allowLiteralsOnly) {
1619 call = (SqlBasicCall) SqlStdOperatorTable.ROW.createCall(SqlParserPos.ZERO, node);
1623 LogicalValues values = LogicalValues.create(
cluster, rowType, tupleList.build());
1625 if (unionInputs.isEmpty()) {
1628 if (!values.getTuples().isEmpty()) {
1629 unionInputs.add(values);
1631 resultRel = LogicalUnion.create(unionInputs,
true);
1633 leaves.put(resultRel, resultRel.getRowType().getFieldCount());
1638 SqlNode sqlNode,
Blackboard bb, RelDataType rowType,
int iField) {
1639 if (!(sqlNode instanceof SqlLiteral)) {
1642 RelDataTypeField
field = rowType.getFieldList().
get(iField);
1643 RelDataType
type = field.getType();
1644 if (type.isStruct()) {
1651 RexNode literalExpr = exprConverter.convertLiteral(bb, (SqlLiteral) sqlNode);
1653 if (!(literalExpr instanceof RexLiteral)) {
1654 assert literalExpr.isA(SqlKind.CAST);
1655 RexNode child = ((RexCall) literalExpr).getOperands().
get(0);
1656 assert RexLiteral.isNullLiteral(child);
1660 return (RexLiteral) child;
1663 RexLiteral literal = (RexLiteral) literalExpr;
1665 Comparable value = literal.getValue();
1667 if (SqlTypeUtil.isExactNumeric(type) && SqlTypeUtil.hasScale(
type)) {
1668 BigDecimal roundedValue =
1669 NumberUtil.rescaleBigDecimal((BigDecimal) value, type.getScale());
1670 return rexBuilder.makeExactLiteral(roundedValue,
type);
1673 if ((value instanceof NlsString) && (type.getSqlTypeName() == SqlTypeName.CHAR)) {
1675 NlsString unpadded = (NlsString) value;
1676 return rexBuilder.makeCharLiteral(
1677 new NlsString(Spaces.padRight(unpadded.getValue(), type.getPrecision()),
1678 unpadded.getCharsetName(),
1679 unpadded.getCollation()));
1685 if (!(node.getKind() == SqlKind.ROW)) {
1688 SqlCall call = (SqlCall) node;
1689 return call.getOperator().getName().equalsIgnoreCase(
"row");
1710 RelOptUtil.Logic logic,
1711 boolean registerOnlyScalarSubQueries) {
1712 final SqlKind kind = node.getKind();
1716 case MULTISET_QUERY_CONSTRUCTOR:
1717 case MULTISET_VALUE_CONSTRUCTOR:
1718 case ARRAY_QUERY_CONSTRUCTOR:
1721 if (!registerOnlyScalarSubQueries || (kind == SqlKind.SCALAR_QUERY)) {
1722 bb.registerSubQuery(node, RelOptUtil.Logic.TRUE_FALSE);
1729 logic = logic.negate();
1732 if (node instanceof SqlCall) {
1742 logic = RelOptUtil.Logic.TRUE_FALSE_UNKNOWN;
1745 for (SqlNode operand : ((SqlCall) node).getOperandList()) {
1746 if (operand != null) {
1752 kind == SqlKind.IN || kind == SqlKind.NOT_IN || kind == SqlKind.SOME
1753 || kind == SqlKind.ALL || registerOnlyScalarSubQueries);
1756 }
else if (node instanceof SqlNodeList) {
1757 for (SqlNode child : (SqlNodeList) node) {
1761 kind == SqlKind.IN || kind == SqlKind.NOT_IN || kind == SqlKind.SOME
1762 || kind == SqlKind.ALL || registerOnlyScalarSubQueries);
1776 case TRUE_FALSE_UNKNOWN:
1777 RelDataType
type = validator.getValidatedNodeTypeIfKnown(node);
1786 case UNKNOWN_AS_FALSE:
1787 logic = RelOptUtil.Logic.TRUE;
1789 bb.registerSubQuery(node, logic);
1801 Map<String, RelDataType> nameToTypeMap = Collections.emptyMap();
1802 final ParameterScope scope =
1803 new ParameterScope((SqlValidatorImpl)
validator, nameToTypeMap);
1805 return bb.convertExpression(node);
1820 final Map<String, RelDataType> nameToTypeMap =
new HashMap<>();
1821 for (Map.Entry<String, RexNode> entry : nameToNodeMap.entrySet()) {
1822 nameToTypeMap.put(entry.getKey(), entry.getValue().getType());
1824 final ParameterScope scope =
1825 new ParameterScope((SqlValidatorImpl)
validator, nameToTypeMap);
1827 return bb.convertExpression(node);
1847 SqlCall call = (SqlCall) node;
1848 SqlCall aggCall = call.operand(0);
1849 boolean ignoreNulls =
false;
1850 switch (aggCall.getKind()) {
1855 aggCall = aggCall.operand(0);
1858 SqlNode windowOrRef = call.operand(1);
1859 final SqlWindow window = validator.resolveWindow(windowOrRef, bb.scope);
1861 SqlNode sqlLowerBound = window.getLowerBound();
1862 SqlNode sqlUpperBound = window.getUpperBound();
1863 boolean rows = window.isRows();
1864 SqlNodeList orderList = window.getOrderList();
1866 if (!aggCall.getOperator().allowsFraming()) {
1869 sqlLowerBound = SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO);
1870 sqlUpperBound = SqlWindow.createCurrentRow(SqlParserPos.ZERO);
1871 if (aggCall.getKind() == SqlKind.ROW_NUMBER) {
1875 }
else if (orderList.size() == 0) {
1877 sqlLowerBound = SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO);
1878 sqlUpperBound = SqlWindow.createUnboundedFollowing(SqlParserPos.ZERO);
1879 }
else if (sqlLowerBound == null && sqlUpperBound == null) {
1880 sqlLowerBound = SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO);
1881 sqlUpperBound = SqlWindow.createCurrentRow(SqlParserPos.ZERO);
1882 }
else if (sqlUpperBound == null) {
1883 sqlUpperBound = SqlWindow.createCurrentRow(SqlParserPos.ZERO);
1884 }
else if (sqlLowerBound == null) {
1885 sqlLowerBound = SqlWindow.createCurrentRow(SqlParserPos.ZERO);
1887 final SqlNodeList partitionList = window.getPartitionList();
1888 final ImmutableList.Builder<RexNode> partitionKeys = ImmutableList.builder();
1889 for (SqlNode partition : partitionList) {
1890 partitionKeys.add(bb.convertExpression(partition));
1892 final RexNode lowerBound = bb.convertExpression(sqlLowerBound);
1893 final RexNode upperBound = bb.convertExpression(sqlUpperBound);
1894 if (orderList.size() == 0 && !rows) {
1898 orderList = bb.scope.getOrderList();
1899 if (orderList == null) {
1900 throw new AssertionError(
"Relation should have sort key for implicit ORDER BY");
1904 final ImmutableList.Builder<RexFieldCollation> orderKeys = ImmutableList.builder();
1905 for (SqlNode order : orderList) {
1906 orderKeys.add(bb.convertSortExpression(order,
1907 RelFieldCollation.Direction.ASCENDING,
1908 RelFieldCollation.NullDirection.UNSPECIFIED));
1912 Preconditions.checkArgument(bb.window == null,
"already in window agg mode");
1914 RexNode rexAgg = exprConverter.convertCall(bb, aggCall);
1915 rexAgg = rexBuilder.ensureType(validator.getValidatedNodeType(call), rexAgg,
false);
1921 final SqlLiteral q = aggCall.getFunctionQuantifier();
1922 final boolean isDistinct = q != null && q.getValue() == SqlSelectKeyword.DISTINCT;
1924 final RexShuttle visitor =
new HistogramShuttle(partitionKeys.build(),
1926 RexWindowBounds.create(sqlLowerBound, lowerBound),
1927 RexWindowBounds.create(sqlUpperBound, upperBound),
1929 window.isAllowPartial(),
1932 return rexAgg.accept(visitor);
1962 bb.setRoot(LogicalValues.createOneRow(
cluster),
false);
1967 final SqlNode[] operands;
1968 switch (from.getKind()) {
1969 case MATCH_RECOGNIZE:
1974 call = (SqlCall) from;
1975 SqlNode firstOperand = call.operand(0);
1976 final List<String> fieldNameList =
new ArrayList<>();
1977 if (call.operandCount() > 2) {
1978 for (SqlNode node : Util.skip(call.getOperandList(), 2)) {
1979 fieldNameList.add(((SqlIdentifier) node).getSimple());
1994 operands = ((SqlBasicCall) from).getOperands();
1995 SqlSampleSpec sampleSpec = SqlLiteral.sampleValue(operands[1]);
1996 if (sampleSpec instanceof SqlSampleSpec.SqlSubstitutionSampleSpec) {
1998 ((SqlSampleSpec.SqlSubstitutionSampleSpec) sampleSpec).getName();
1999 datasetStack.push(sampleName);
2002 }
else if (sampleSpec instanceof SqlSampleSpec.SqlTableSampleSpec) {
2003 SqlSampleSpec.SqlTableSampleSpec tableSampleSpec =
2004 (SqlSampleSpec.SqlTableSampleSpec) sampleSpec;
2006 RelOptSamplingParameters params =
2007 new RelOptSamplingParameters(tableSampleSpec.isBernoulli(),
2008 tableSampleSpec.getSamplePercentage(),
2009 tableSampleSpec.isRepeatable(),
2010 tableSampleSpec.getRepeatableSeed());
2011 bb.setRoot(
new Sample(
cluster, bb.
root, params),
false);
2013 throw new AssertionError(
"unknown TABLESAMPLE type: " + sampleSpec);
2018 call = (SqlCall) from;
2027 call = (SqlCall) from;
2028 final SqlNode operand0 = call.getOperandList().
get(0);
2029 final SqlIdentifier
id = operand0.getKind() == SqlKind.TABLE_REF
2030 ? ((SqlCall) operand0).operand(0)
2031 : (SqlIdentifier) operand0;
2032 SqlNodeList extendedColumns = (SqlNodeList) call.getOperandList().get(1);
2041 final SqlJoin
join = (SqlJoin) from;
2042 final SqlValidatorScope scope = validator.getJoinScope(from);
2044 SqlNode left = join.getLeft();
2045 SqlNode right = join.getRight();
2046 final boolean isNatural = join.isNatural();
2047 final JoinType joinType = join.getJoinType();
2048 final SqlValidatorScope leftScope = Util.first(
2049 validator.getJoinScope(left), ((DelegatingScope) bb.scope).getParent());
2051 final SqlValidatorScope rightScope = Util.first(
2052 validator.getJoinScope(right), ((DelegatingScope) bb.scope).getParent());
2055 RelNode leftRel = leftBlackboard.root;
2057 RelNode rightRel = rightBlackboard.root;
2059 RexNode conditionExp;
2060 final SqlValidatorNamespace leftNamespace = validator.getNamespace(left);
2061 final SqlValidatorNamespace rightNamespace = validator.getNamespace(right);
2063 final RelDataType leftRowType = leftNamespace.getRowType();
2064 final RelDataType rightRowType = rightNamespace.getRowType();
2065 final List<String> columnList = SqlValidatorUtil.deriveNaturalJoinColumnList(
2066 catalogReader.nameMatcher(), leftRowType, rightRowType);
2067 conditionExp =
convertUsing(leftNamespace, rightNamespace, columnList);
2072 join.getCondition(),
2073 join.getConditionType(),
2079 fromBlackboard, leftRel, rightRel, conditionExp, convertedJoinType);
2080 bb.setRoot(joinRel,
false);
2088 bb.setRoot(rel,
true);
2093 if (fieldNames.size() > 0) {
2094 bb.setRoot(relBuilder.push(bb.root).rename(fieldNames).build(),
true);
2102 case COLLECTION_TABLE:
2103 call = (SqlCall) from;
2106 assert call.getOperandList().size() == 1;
2107 final SqlCall call2 = call.operand(0);
2112 throw new AssertionError(
"not a join operator " + from);
2117 final List<SqlNode> nodes = call.getOperandList();
2118 final SqlUnnestOperator operator = (SqlUnnestOperator) call.getOperator();
2119 for (SqlNode node : nodes) {
2122 final List<RexNode> exprs =
new ArrayList<>();
2123 for (Ord<SqlNode> node : Ord.zip(nodes)) {
2124 exprs.add(relBuilder.alias(
2125 bb.convertExpression(node.e),
validator.deriveAlias(node.e, node.i)));
2127 RelNode child = (null != bb.root) ? bb.
root : LogicalValues.createOneRow(
cluster);
2129 if (
validator.config().sqlConformance().allowAliasUnnestItems()) {
2130 uncollect = relBuilder.push(child)
2132 .uncollect(fieldNames, operator.withOrdinality)
2137 uncollect = relBuilder.push(child)
2139 .uncollect(Collections.emptyList(),
operator.withOrdinality)
2143 bb.setRoot(uncollect,
true);
2147 final SqlMatchRecognize matchRecognize = (SqlMatchRecognize) call;
2148 final SqlValidatorNamespace ns = validator.getNamespace(matchRecognize);
2149 final SqlValidatorScope scope = validator.getMatchRecognizeScope(matchRecognize);
2152 final RelDataType rowType = ns.getRowType();
2154 SqlNode expr = matchRecognize.getTableRef();
2156 final RelNode input = matchBb.root;
2159 final SqlNodeList partitionList = matchRecognize.getPartitionList();
2160 final ImmutableBitSet.Builder partitionKeys = ImmutableBitSet.builder();
2161 for (SqlNode partition : partitionList) {
2162 RexNode e = matchBb.convertExpression(partition);
2163 partitionKeys.set(((RexInputRef) e).getIndex());
2167 final SqlNodeList orderList = matchRecognize.getOrderList();
2168 final List<RelFieldCollation> orderKeys =
new ArrayList<>();
2169 for (SqlNode order : orderList) {
2170 final RelFieldCollation.Direction direction;
2171 switch (order.getKind()) {
2173 direction = RelFieldCollation.Direction.DESCENDING;
2174 order = ((SqlCall) order).operand(0);
2178 throw new AssertionError();
2180 direction = RelFieldCollation.Direction.ASCENDING;
2183 final RelFieldCollation.NullDirection nullDirection =
2184 validator.config().defaultNullCollation().last(
desc(direction))
2185 ? RelFieldCollation.NullDirection.LAST
2186 : RelFieldCollation.NullDirection.FIRST;
2187 RexNode e = matchBb.convertExpression(order);
2188 orderKeys.add(
new RelFieldCollation(
2189 ((RexInputRef) e).getIndex(), direction, nullDirection));
2191 final RelCollation orders = cluster.traitSet().canonize(RelCollations.of(orderKeys));
2194 final Set<String> patternVarsSet =
new HashSet<>();
2195 SqlNode pattern = matchRecognize.getPattern();
2196 final SqlBasicVisitor<RexNode> patternVarVisitor =
new SqlBasicVisitor<RexNode>() {
2198 public RexNode visit(SqlCall call) {
2199 List<SqlNode> operands = call.getOperandList();
2200 List<RexNode> newOperands =
new ArrayList<>();
2201 for (SqlNode node : operands) {
2202 newOperands.add(node.accept(
this));
2204 return rexBuilder.makeCall(
2205 validator.getUnknownType(), call.getOperator(), newOperands);
2209 public RexNode visit(SqlIdentifier
id) {
2210 assert id.isSimple();
2211 patternVarsSet.add(id.getSimple());
2212 return rexBuilder.makeLiteral(id.getSimple());
2216 public RexNode visit(SqlLiteral literal) {
2217 if (literal instanceof SqlNumericLiteral) {
2218 return rexBuilder.makeExactLiteral(BigDecimal.valueOf(literal.intValue(
true)));
2220 return rexBuilder.makeLiteral(literal.booleanValue());
2224 final RexNode patternNode = pattern.accept(patternVarVisitor);
2226 SqlLiteral interval = matchRecognize.getInterval();
2227 RexNode intervalNode = null;
2228 if (interval != null) {
2229 intervalNode = matchBb.convertLiteral(interval);
2233 final SqlNodeList subsets = matchRecognize.getSubsetList();
2234 final Map<String, TreeSet<String>> subsetMap =
new HashMap<>();
2235 for (SqlNode node : subsets) {
2236 List<SqlNode> operands = ((SqlCall) node).getOperandList();
2237 SqlIdentifier left = (SqlIdentifier) operands.get(0);
2238 patternVarsSet.add(left.getSimple());
2239 SqlNodeList rights = (SqlNodeList) operands.get(1);
2240 final TreeSet<String> list =
new TreeSet<>();
2241 for (SqlNode right : rights) {
2242 assert right instanceof SqlIdentifier;
2243 list.add(((SqlIdentifier) right).getSimple());
2245 subsetMap.put(left.getSimple(), list);
2248 SqlNode afterMatch = matchRecognize.getAfter();
2249 if (afterMatch == null) {
2251 SqlMatchRecognize.AfterOption.SKIP_TO_NEXT_ROW.symbol(SqlParserPos.ZERO);
2254 final RexNode after;
2255 if (afterMatch instanceof SqlCall) {
2256 List<SqlNode> operands = ((SqlCall) afterMatch).getOperandList();
2257 SqlOperator operator = ((SqlCall) afterMatch).getOperator();
2258 assert operands.size() == 1;
2259 SqlIdentifier
id = (SqlIdentifier) operands.get(0);
2260 assert patternVarsSet.contains(id.getSimple())
2262 +
" not defined in pattern";
2263 RexNode rex = rexBuilder.makeLiteral(id.getSimple());
2264 after = rexBuilder.makeCall(
2265 validator.getUnknownType(),
operator, ImmutableList.of(rex));
2267 after = matchBb.convertExpression(afterMatch);
2270 matchBb.setPatternVarRef(
true);
2273 final ImmutableMap.Builder<String, RexNode> measureNodes = ImmutableMap.builder();
2274 for (SqlNode
measure : matchRecognize.getMeasureList()) {
2275 List<SqlNode> operands = ((SqlCall)
measure).getOperandList();
2276 String alias = ((SqlIdentifier) operands.get(1)).getSimple();
2277 RexNode rex = matchBb.convertExpression(operands.get(0));
2278 measureNodes.put(alias, rex);
2282 final ImmutableMap.Builder<String, RexNode> definitionNodes = ImmutableMap.builder();
2283 for (SqlNode def : matchRecognize.getPatternDefList()) {
2285 List<SqlNode> operands = ((SqlCall) def).getOperandList();
2286 String alias = ((SqlIdentifier) operands.get(1)).getSimple();
2287 RexNode rex = matchBb.convertExpression(operands.get(0));
2288 definitionNodes.put(alias, rex);
2291 final SqlLiteral rowsPerMatch = matchRecognize.getRowsPerMatch();
2292 final boolean allRows = rowsPerMatch != null
2293 && rowsPerMatch.getValue() == SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS;
2295 matchBb.setPatternVarRef(
false);
2297 final RelFactories.MatchFactory factory = RelFactories.DEFAULT_MATCH_FACTORY;
2298 final RelNode rel = factory.createMatch(input,
2301 matchRecognize.getStrictStart().booleanValue(),
2302 matchRecognize.getStrictEnd().booleanValue(),
2303 definitionNodes.build(),
2304 measureNodes.build(),
2308 partitionKeys.build(),
2311 bb.setRoot(rel,
false);
2316 SqlNodeList extendedColumns,
2317 SqlNodeList tableHints) {
2318 final SqlValidatorNamespace fromNamespace = validator.getNamespace(id).resolve();
2319 if (fromNamespace.getNode() != null) {
2323 final String datasetName = datasetStack.isEmpty() ? null :
datasetStack.peek();
2324 final boolean[] usedDataset = {
false};
2325 RelOptTable table = SqlValidatorUtil.getRelOptTable(
2327 if (extendedColumns != null && extendedColumns.size() > 0) {
2328 assert table != null;
2329 final SqlValidatorTable validatorTable = table.unwrap(SqlValidatorTable.class);
2330 final List<RelDataTypeField> extendedFields = SqlValidatorUtil.getExtendedColumns(
2331 validator, validatorTable, extendedColumns);
2332 table = table.extend(extendedFields);
2334 final RelNode tableRel;
2337 final List<RelHint> hints =
2338 hintStrategies.apply(SqlUtil.getRelHint(
hintStrategies, tableHints),
2339 LogicalTableScan.create(
cluster, table, ImmutableList.of()));
2340 tableRel =
toRel(table, hints);
2341 bb.setRoot(tableRel,
true);
2342 if (usedDataset[0]) {
2343 bb.setDataset(datasetName);
2348 final SqlOperator
operator = call.getOperator();
2349 if (
operator == SqlStdOperatorTable.TABLESAMPLE) {
2350 final String sampleName =
2351 SqlLiteral.unchain(call.operand(0)).getValueAs(String.class);
2352 datasetStack.push(sampleName);
2353 SqlCall cursorCall = call.operand(1);
2354 SqlNode query = cursorCall.operand(0);
2355 RelNode converted =
convertQuery(query,
false,
false).rel;
2356 bb.setRoot(converted,
false);
2364 final SqlCallBinding callBinding =
2365 new SqlCallBinding(bb.
scope.getValidator(), bb.scope, call);
2366 if (
operator instanceof SqlUserDefinedTableMacro) {
2367 final SqlUserDefinedTableMacro udf = (SqlUserDefinedTableMacro)
operator;
2368 final TranslatableTable table = udf.getTable(callBinding);
2369 final RelDataType rowType = table.getRowType(
typeFactory);
2370 RelOptTable relOptTable =
2371 RelOptTableImpl.create(null, rowType, table, udf.getNameAsId().names);
2372 RelNode converted =
toRel(relOptTable, ImmutableList.of());
2373 bb.setRoot(converted,
true);
2378 if (
operator instanceof SqlUserDefinedTableFunction) {
2379 SqlUserDefinedTableFunction udtf = (SqlUserDefinedTableFunction)
operator;
2380 elementType = udtf.getElementType(callBinding);
2385 RexNode rexCall = bb.convertExpression(call);
2386 final List<RelNode> inputs = bb.retrieveCursors();
2388 LogicalTableFunctionScan callRel = LogicalTableFunctionScan.create(
cluster,
2392 validator.getValidatedNodeType(call),
2394 bb.setRoot(callRel,
true);
2400 LogicalTableFunctionScan callRel) {}
2403 final SqlSnapshot snapshot = (SqlSnapshot) call;
2404 final RexNode period = bb.convertExpression(snapshot.getPeriod());
2407 SqlNode expr = snapshot.getTableRef();
2410 final RelNode snapshotRel = relBuilder.push(bb.root).snapshot(period).build();
2412 bb.setRoot(snapshotRel,
false);
2416 SqlReturnTypeInference rti = op.getReturnTypeInference();
2420 if (rti instanceof TableFunctionReturnTypeInference) {
2421 TableFunctionReturnTypeInference tfrti = (TableFunctionReturnTypeInference) rti;
2422 return tfrti.getColumnMappings();
2445 int i = input.getIndex() -
rexCorrel.getType().getFieldCount();
2447 varCols.set(input.getIndex());
2448 return builder.makeFieldAccess(
rexCorrel, input.getIndex());
2450 return builder.makeInputRef(input.getType(), i);
2458 JoinRelType joinType) {
2459 assert joinCond != null;
2463 RelNode innerRel =
p.r;
2464 ImmutableBitSet requiredCols = p.requiredColumns;
2466 if (!joinCond.isAlwaysTrue()) {
2467 final RelFactories.FilterFactory factory = RelFactories.DEFAULT_FILTER_FACTORY;
2468 final RexCorrelVariable rexCorrel =
2469 (RexCorrelVariable)
rexBuilder.makeCorrel(leftRel.getRowType(), p.id);
2474 final RexNode newCond = joinCond.accept(shuttle);
2475 innerRel = factory.createFilter(
p.r, newCond, ImmutableSet.of());
2477 ImmutableBitSet.fromBitSet(shuttle.varCols).
union(p.requiredColumns);
2480 return LogicalCorrelate.create(leftRel, innerRel, p.id, requiredCols, joinType);
2488 final Join originalJoin = (Join) RelFactories.DEFAULT_JOIN_FACTORY.createJoin(leftRel,
2495 boolean applyPushdown =
2496 config.getPushdownJoinCondition().test(bb.
getTopNode(), originalJoin);
2498 if (applyPushdown) {
2500 relBuilder.push(leftRel).push(rightRel).join(joinType, joinCond).build();
2502 node = originalJoin;
2507 if (node instanceof Project) {
2508 final Join newJoin = (Join) node.getInputs().get(0);
2509 if (
leaves.containsKey(leftRel)) {
2510 leaves.put(newJoin.getLeft(),
leaves.get(leftRel));
2512 if (
leaves.containsKey(rightRel)) {
2513 leaves.put(newJoin.getRight(),
leaves.get(rightRel));
2520 final Set<CorrelationId> correlatedVariables = RelOptUtil.getVariablesUsed(r0);
2521 if (correlatedVariables.isEmpty()) {
2524 final ImmutableBitSet.Builder requiredColumns = ImmutableBitSet.builder();
2525 final List<CorrelationId> correlNames =
new ArrayList<>();
2531 SqlValidatorNamespace prevNs = null;
2533 for (CorrelationId correlName : correlatedVariables) {
2535 RexFieldAccess fieldAccess = lookup.getFieldAccess(correlName);
2536 String originalRelName = lookup.getOriginalRelName();
2537 String originalFieldName = fieldAccess.getField().getName();
2539 final SqlNameMatcher nameMatcher =
2540 bb.getValidator().getCatalogReader().nameMatcher();
2541 final SqlValidatorScope.ResolvedImpl resolved =
2542 new SqlValidatorScope.ResolvedImpl();
2543 lookup.bb.scope.resolve(
2544 ImmutableList.of(originalRelName), nameMatcher,
false, resolved);
2545 assert resolved.count() == 1;
2546 final SqlValidatorScope.Resolve resolve = resolved.only();
2547 final SqlValidatorNamespace foundNs = resolve.namespace;
2548 final RelDataType rowType = resolve.rowType();
2549 final int childNamespaceIndex = resolve.path.steps().
get(0).i;
2550 final SqlValidatorScope ancestorScope = resolve.scope;
2551 boolean correlInCurrentScope = bb.scope.isWithin(ancestorScope);
2553 if (!correlInCurrentScope) {
2557 if (prevNs == null) {
2561 == foundNs :
"All correlation variables should resolve"
2562 +
" to the same namespace."
2569 int namespaceOffset = 0;
2570 if (childNamespaceIndex > 0) {
2573 assert ancestorScope instanceof ListScope;
2574 List<SqlValidatorNamespace> children = ((ListScope) ancestorScope).getChildren();
2576 for (
int i = 0;
i < childNamespaceIndex;
i++) {
2577 SqlValidatorNamespace child = children.get(
i);
2578 namespaceOffset += child.getRowType().getFieldCount();
2582 RexFieldAccess topLevelFieldAccess = fieldAccess;
2583 while (topLevelFieldAccess.getReferenceExpr() instanceof RexFieldAccess) {
2584 topLevelFieldAccess = (RexFieldAccess) topLevelFieldAccess.getReferenceExpr();
2586 final RelDataTypeField
field = rowType.getFieldList().
get(
2587 topLevelFieldAccess.getField().getIndex() - namespaceOffset);
2588 int pos = namespaceOffset + field.getIndex();
2590 assert field.getType() == topLevelFieldAccess.getField().getType();
2597 Map<Integer, Integer> exprProjection =
2598 bb.mapRootRelToFieldProjection.get(bb.root);
2602 if (exprProjection.containsKey(pos)) {
2603 pos = exprProjection.get(pos);
2606 throw new AssertionError(
"Identifier '" + originalRelName +
"."
2607 + originalFieldName +
"' is not a group expr");
2611 requiredColumns.set(pos);
2612 correlNames.add(correlName);
2615 if (correlNames.isEmpty()) {
2621 if (correlNames.size() > 1) {
2624 r = DeduplicateCorrelateVariables.go(
2625 rexBuilder, correlNames.get(0), Util.skip(correlNames), r0);
2627 leaves.put(
r, r.getRowType().getFieldCount());
2629 return new CorrelationUse(correlNames.get(0), requiredColumns.build(), r);
2643 Set<CorrelationId> correlatedVariables = RelOptUtil.getVariablesUsed(subq);
2644 for (CorrelationId correlName : correlatedVariables) {
2646 String originalRelName = lookup.getOriginalRelName();
2648 final SqlNameMatcher nameMatcher =
2649 lookup.bb.scope.getValidator().getCatalogReader().nameMatcher();
2650 final SqlValidatorScope.ResolvedImpl resolved =
2651 new SqlValidatorScope.ResolvedImpl();
2652 lookup.bb.scope.resolve(
2653 ImmutableList.of(originalRelName), nameMatcher,
false, resolved);
2655 SqlValidatorScope ancestorScope = resolved.only().scope;
2659 SqlValidatorScope parentScope = bb.scope;
2661 if (ancestorScope == parentScope) {
2664 if (parentScope instanceof DelegatingScope) {
2665 parentScope = ((DelegatingScope) parentScope).getParent();
2669 }
while (parentScope != null);
2680 return Collections.emptyList();
2684 SqlValidatorNamespace leftNamespace,
2685 SqlValidatorNamespace rightNamespace,
2687 JoinConditionType conditionType,
2690 if (condition == null) {
2691 return rexBuilder.makeLiteral(
true);
2693 bb.setRoot(ImmutableList.of(leftRel, rightRel));
2695 switch (conditionType) {
2697 bb.setRoot(ImmutableList.of(leftRel, rightRel));
2698 return bb.convertExpression(condition);
2700 final SqlNodeList list = (SqlNodeList) condition;
2701 final List<String> nameList =
new ArrayList<>();
2702 for (SqlNode columnName : list) {
2703 final SqlIdentifier
id = (SqlIdentifier) columnName;
2704 String
name = id.getSimple();
2707 return convertUsing(leftNamespace, rightNamespace, nameList);
2709 throw Util.unexpected(conditionType);
2725 SqlValidatorNamespace rightNamespace,
2726 List<String> nameList) {
2727 final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
2728 final List<RexNode> list =
new ArrayList<>();
2729 for (String
name : nameList) {
2730 List<RexNode> operands =
new ArrayList<>();
2732 for (SqlValidatorNamespace n : ImmutableList.of(leftNamespace, rightNamespace)) {
2733 final RelDataType rowType = n.getRowType();
2734 final RelDataTypeField
field = nameMatcher.field(rowType,
name);
2735 operands.add(rexBuilder.makeInputRef(field.getType(), offset + field.getIndex()));
2736 offset += rowType.getFieldList().size();
2738 list.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, operands));
2740 return RexUtil.composeConjunction(
rexBuilder, list);
2748 return JoinRelType.INNER;
2750 return JoinRelType.FULL;
2752 return JoinRelType.LEFT;
2754 return JoinRelType.RIGHT;
2756 throw Util.unexpected(joinType);
2774 Blackboard bb, SqlSelect select, List<SqlNode> orderExprList) {
2775 assert bb.root != null :
"precondition: child != null";
2776 SqlNodeList groupList = select.getGroup();
2777 SqlNodeList selectList = select.getSelectList();
2778 SqlNode having = select.getHaving();
2780 final AggConverter aggConverter =
new AggConverter(bb, select);
2781 createAggImpl(bb, aggConverter, selectList, groupList, having, orderExprList);
2785 final AggConverter aggConverter,
2786 SqlNodeList selectList,
2787 SqlNodeList groupList,
2789 List<SqlNode> orderExprList) {
2791 final AggregateFinder aggregateFinder =
new AggregateFinder();
2792 selectList.accept(aggregateFinder);
2793 if (having != null) {
2794 having.accept(aggregateFinder);
2799 replaceSubQueries(bb, aggregateFinder.list, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2803 bb, aggregateFinder.filterList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2806 replaceSubQueries(bb, aggregateFinder.orderList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
2809 if (groupList == null) {
2810 groupList = SqlNodeList.EMPTY;
2823 final AggregatingSelectScope scope = aggConverter.aggregatingSelectScope;
2824 final AggregatingSelectScope.Resolved
r = scope.resolved.get();
2825 for (SqlNode groupExpr : r.groupExprList) {
2826 aggConverter.addGroupExpr(groupExpr);
2829 final RexNode havingExpr;
2830 final List<Pair<RexNode, String>> projects =
new ArrayList<>();
2833 Preconditions.checkArgument(bb.agg == null,
"already in agg mode");
2834 bb.agg = aggConverter;
2839 selectList.accept(aggConverter);
2841 assert !aggConverter.inOver;
2842 for (SqlNode expr : orderExprList) {
2843 expr.accept(aggConverter);
2844 assert !aggConverter.inOver;
2846 if (having != null) {
2847 having.accept(aggConverter);
2848 assert !aggConverter.inOver;
2852 List<Pair<RexNode, String>> preExprs = aggConverter.getPreExprs();
2854 if (preExprs.size() == 0) {
2858 final RexNode zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO);
2859 preExprs = ImmutableList.of(Pair.of(zero, (String) null));
2862 final RelNode inputRel = bb.root;
2865 bb.setRoot(relBuilder.push(inputRel)
2866 .projectNamed(Pair.left(preExprs), Pair.right(preExprs),
false)
2869 bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
2876 bb.columnMonotonicities.clear();
2877 for (SqlNode groupItem : groupList) {
2878 bb.columnMonotonicities.add(bb.scope.getMonotonicity(groupItem));
2881 final RelNode relNode = aggConverter.containsGroupId()
2883 :
createAggregate(bb, r.groupSet, r.groupSets, aggConverter.getAggCalls());
2885 bb.setRoot(relNode,
false);
2886 bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
2890 if (having != null) {
2893 havingExpr = bb.convertExpression(newHaving);
2895 havingExpr = relBuilder.literal(
true);
2915 final SelectScope selectScope = SqlValidatorUtil.getEnclosingSelectScope(bb.scope);
2916 assert selectScope != null;
2917 final SqlValidatorNamespace selectNamespace =
2918 validator.getNamespace(selectScope.getNode());
2919 final List<String> names = selectNamespace.getRowType().getFieldNames();
2920 int sysFieldCount = selectList.size() - names.size();
2921 for (SqlNode expr : selectList) {
2922 projects.add(Pair.of(bb.convertExpression(expr),
2923 k < sysFieldCount ?
validator.deriveAlias(expr, k++)
2924 : names.get(k++ - sysFieldCount)));
2927 for (SqlNode expr : orderExprList) {
2929 Pair.of(bb.convertExpression(expr),
validator.deriveAlias(expr, k++)));
2936 relBuilder.push(bb.root);
2937 if (havingExpr != null) {
2938 relBuilder.filter(havingExpr);
2942 relBuilder.project(Pair.left(projects), Pair.right(projects))
2943 .rename(Pair.right(projects));
2944 bb.setRoot(relBuilder.build(),
false);
2947 bb.columnMonotonicities.clear();
2948 for (SqlNode selectItem : selectList) {
2949 bb.columnMonotonicities.add(bb.scope.getMonotonicity(selectItem));
2967 Blackboard bb, AggregatingSelectScope.Resolved
r, AggConverter converter) {
2968 final List<AggregateCall> aggregateCalls = converter.getAggCalls();
2969 final ImmutableBitSet groupSet = r.groupSet;
2970 final Map<ImmutableBitSet, Integer> groupSetCount = r.groupSetCount;
2972 final List<String> fieldNamesIfNoRewrite =
2987 final Map<Integer, Set<ImmutableBitSet>> groupIdToGroupSets =
new HashMap<>();
2989 for (Map.Entry<ImmutableBitSet, Integer> entry : groupSetCount.entrySet()) {
2990 int groupId = entry.getValue() - 1;
2991 if (groupId > maxGroupId) {
2992 maxGroupId = groupId;
2994 for (
int i = 0;
i <= groupId;
i++) {
2996 .computeIfAbsent(
i,
k -> Sets.newTreeSet(ImmutableBitSet.COMPARATOR))
2997 .add(entry.getKey());
3002 final List<AggregateCall> aggregateCallsWithoutGroupId =
new ArrayList<>();
3003 for (AggregateCall aggregateCall : aggregateCalls) {
3004 if (aggregateCall.getAggregation().kind != SqlKind.GROUP_ID) {
3005 aggregateCallsWithoutGroupId.add(aggregateCall);
3008 final List<RelNode> projects =
new ArrayList<>();
3012 for (
int groupId = 0; groupId <= maxGroupId; groupId++) {
3014 final ImmutableList<ImmutableBitSet> groupSets =
3015 ImmutableList.copyOf(groupIdToGroupSets.get(groupId));
3016 final RelNode aggregate =
3017 createAggregate(bb, groupSet, groupSets, aggregateCallsWithoutGroupId);
3020 final RelDataType groupIdType = typeFactory.createSqlType(SqlTypeName.BIGINT);
3021 final RexNode groupIdLiteral =
3022 rexBuilder.makeExactLiteral(BigDecimal.valueOf(groupId), groupIdType);
3024 relBuilder.push(aggregate);
3025 final List<RexNode> selectList =
new ArrayList<>();
3026 final int groupExprLength = r.groupExprList.size();
3028 for (
int i = 0;
i < groupExprLength;
i++) {
3029 selectList.add(relBuilder.field(
i));
3032 int groupIdCount = 0;
3033 for (
int i = 0;
i < aggregateCalls.size();
i++) {
3034 if (aggregateCalls.get(
i).getAggregation().kind == SqlKind.GROUP_ID) {
3035 selectList.add(groupIdLiteral);
3038 int ordinal = groupExprLength +
i - groupIdCount;
3039 selectList.add(relBuilder.field(ordinal));
3042 final RelNode project =
3043 relBuilder.project(selectList, fieldNamesIfNoRewrite).build();
3044 projects.add(project);
3048 if (projects.size() == 1) {
3049 return projects.get(0);
3051 return LogicalUnion.create(projects,
true);
3074 ImmutableBitSet groupSet,
3075 ImmutableList<ImmutableBitSet> groupSets,
3076 List<AggregateCall> aggCalls) {
3077 return LogicalAggregate.create(
3078 bb.root, ImmutableList.of(), groupSet, groupSets, aggCalls);
3086 while (dynamicParam.getIndex() >= dynamicParamSqlNodes.size()) {
3087 dynamicParamSqlNodes.add(null);
3090 dynamicParamSqlNodes.set(dynamicParam.getIndex(), dynamicParam);
3091 return rexBuilder.makeDynamicParam(
3111 SqlNodeList orderList,
3112 List<SqlNode> extraOrderExprs,
3113 List<RelFieldCollation> collationList) {
3115 assert bb.root != null :
"precondition: child != null";
3116 assert select != null;
3117 if (orderList == null) {
3122 SqlNode offset = select.getOffset();
3124 || (offset instanceof SqlLiteral
3125 && ((SqlLiteral) offset)
3127 .equals(BigDecimal.ZERO)))
3128 && select.getFetch() == null) {
3133 for (SqlNode orderItem : orderList) {
3137 RelFieldCollation.Direction.ASCENDING,
3138 RelFieldCollation.NullDirection.UNSPECIFIED));
3144 List<SqlNode> extraExprs,
3145 RelFieldCollation.Direction direction,
3146 RelFieldCollation.NullDirection nullDirection) {
3147 assert select != null;
3149 switch (orderItem.getKind()) {
3152 ((SqlCall) orderItem).operand(0),
3154 RelFieldCollation.Direction.DESCENDING,
3158 ((SqlCall) orderItem).operand(0),
3161 RelFieldCollation.NullDirection.FIRST);
3164 ((SqlCall) orderItem).operand(0),
3167 RelFieldCollation.NullDirection.LAST);
3170 SqlNode converted = validator.expandOrderExpr(select, orderItem);
3172 switch (nullDirection) {
3174 nullDirection = validator.config().defaultNullCollation().last(
desc(direction))
3175 ? RelFieldCollation.NullDirection.LAST
3176 : RelFieldCollation.NullDirection.FIRST;
3180 final SelectScope selectScope = validator.getRawSelectScope(select);
3182 for (SqlNode selectItem : selectScope.getExpandedSelectList()) {
3184 if (converted.equalsDeep(stripAs(selectItem), Litmus.IGNORE)) {
3185 return new RelFieldCollation(ordinal, direction, nullDirection);
3189 for (SqlNode extraExpr : extraExprs) {
3191 if (converted.equalsDeep(extraExpr, Litmus.IGNORE)) {
3192 return new RelFieldCollation(ordinal, direction, nullDirection);
3199 extraExprs.add(converted);
3200 return new RelFieldCollation(ordinal + 1, direction, nullDirection);
3203 private static boolean desc(RelFieldCollation.Direction direction) {
3204 switch (direction) {
3206 case STRICTLY_DESCENDING:
3217 return config.isDecorrelationEnabled();
3221 return RelDecorrelator.decorrelateQuery(rootRel,
relBuilder);
3231 return config.isTrimUnusedFields();
3244 SqlNode query,
boolean top, RelDataType targetRowType) {
3245 final SqlKind kind = query.getKind();
3248 return RelRoot.of(
convertSelect((SqlSelect) query, top), kind);
3256 return RelRoot.of(
convertMerge((SqlMerge) query), kind);
3260 return RelRoot.of(
convertSetOp((SqlCall) query), kind);
3264 return RelRoot.of(
convertValues((SqlCall) query, targetRowType), kind);
3266 throw new AssertionError(
"not a query: " + query);
3280 switch (call.getKind()) {
3282 return LogicalUnion.create(ImmutableList.of(left, right),
all(call));
3285 return LogicalIntersect.create(ImmutableList.of(left, right),
all(call));
3288 return LogicalMinus.create(ImmutableList.of(left, right),
all(call));
3291 throw Util.unexpected(call.getKind());
3295 private boolean all(SqlCall call) {
3296 return ((SqlSetOperator) call.getOperator()).isAll();
3302 final RelDataType targetRowType = validator.getValidatedNodeType(call);
3303 assert targetRowType != null;
3313 final ModifiableTable modifiableTable = targetTable.unwrap(ModifiableTable.class);
3314 if (modifiableTable != null && modifiableTable == targetTable.unwrap(Table.class)) {
3315 return modifiableTable.toModificationRel(
cluster,
3319 LogicalTableModify.Operation.INSERT,
3324 final ModifiableView modifiableView = targetTable.unwrap(ModifiableView.class);
3325 if (modifiableView != null) {
3326 final Table delegateTable = modifiableView.getTable();
3327 final RelDataType delegateRowType = delegateTable.getRowType(
typeFactory);
3328 final RelOptTable delegateRelOptTable = RelOptTableImpl.create(
3329 null, delegateRowType, delegateTable, modifiableView.getTablePath());
3330 final RelNode newSource =
3331 createSource(targetTable, source, modifiableView, delegateRowType);
3334 return LogicalTableModify.create(targetTable,
3337 LogicalTableModify.Operation.INSERT,
3358 ModifiableView modifiableView,
3359 RelDataType delegateRowType) {
3360 final ImmutableIntList mapping = modifiableView.getColumnMapping();
3361 assert mapping.size() == targetTable.getRowType().getFieldCount();
3365 final Map<Integer, RexNode> projectMap =
new HashMap<>();
3366 final List<RexNode> filters =
new ArrayList<>();
3367 for (
int i = 0;
i < mapping.size();
i++) {
3368 int target = mapping.get(
i);
3370 projectMap.put(target, RexInputRef.of(
i, source.getRowType()));
3379 final RexNode constraint = modifiableView.getConstraint(
rexBuilder, delegateRowType);
3380 RelOptUtil.inferViewPredicates(projectMap, filters, constraint);
3381 final List<Pair<RexNode, String>> projects =
new ArrayList<>();
3382 for (RelDataTypeField
field : delegateRowType.getFieldList()) {
3383 RexNode node = projectMap.get(field.getIndex());
3385 node = rexBuilder.makeNullLiteral(field.getType());
3387 projects.add(Pair.of(
3388 rexBuilder.ensureType(field.getType(), node,
false), field.getName()));
3391 return relBuilder.push(source)
3392 .projectNamed(Pair.left(projects), Pair.right(projects),
false)
3401 public RelNode
toRel(
final RelOptTable table,
final List<RelHint> hints) {
3404 final InitializerExpressionFactory ief =
3405 Util.first(table.unwrap(InitializerExpressionFactory.class),
3406 NullInitializerExpressionFactory.INSTANCE);
3408 boolean hasVirtualFields = table.getRowType().getFieldList().stream().anyMatch(
3409 f -> ief.generationStrategy(table,
f.getIndex()) == ColumnStrategy.VIRTUAL);
3411 if (hasVirtualFields) {
3412 final RexNode sourceRef = rexBuilder.makeRangeReference(scan);
3414 table, sourceRef, table.getRowType().getFieldNames());
3415 final List<RexNode> list =
new ArrayList<>();
3416 for (RelDataTypeField
f : table.getRowType().getFieldList()) {
3417 final ColumnStrategy strategy = ief.generationStrategy(table, f.getIndex());
3420 list.add(ief.newColumnDefaultValue(table, f.getIndex(), bb));
3423 list.add(rexBuilder.makeInputRef(
3424 scan, RelOptTableImpl.realOrdinal(table, f.getIndex())));
3427 relBuilder.push(scan);
3428 relBuilder.project(list);
3429 final RelNode project = relBuilder.build();
3430 if (ief.postExpressionConversionHook() != null) {
3431 return ief.postExpressionConversionHook().apply(bb, project);
3441 final SqlValidatorNamespace targetNs = validator.getNamespace(call);
3442 if (targetNs.isWrapperFor(SqlValidatorImpl.DmlNamespace.class)) {
3443 final SqlValidatorImpl.DmlNamespace dmlNamespace =
3444 targetNs.unwrap(SqlValidatorImpl.DmlNamespace.class);
3445 return SqlValidatorUtil.getRelOptTable(dmlNamespace,
catalogReader, null, null);
3447 final SqlValidatorNamespace resolvedNamespace = targetNs.resolve();
3448 return SqlValidatorUtil.getRelOptTable(resolvedNamespace,
catalogReader, null, null);
3469 RelDataType sourceRowType = source.getRowType();
3470 final RexNode sourceRef = rexBuilder.makeRangeReference(sourceRowType, 0,
false);
3471 final List<String> targetColumnNames =
new ArrayList<>();
3472 final List<RexNode> columnExprs =
new ArrayList<>();
3476 final RelDataType targetRowType = RelOptTableImpl.realRowType(targetTable);
3477 final List<RelDataTypeField> targetFields = targetRowType.getFieldList();
3478 final List<RexNode> sourceExps =
3479 new ArrayList<>(Collections.nCopies(targetFields.size(), null));
3480 final List<String> fieldNames =
3481 new ArrayList<>(Collections.nCopies(targetFields.size(), null));
3483 final InitializerExpressionFactory initializerFactory =
3490 final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
3491 for (Pair<String, RexNode> p : Pair.zip(targetColumnNames, columnExprs)) {
3492 RelDataTypeField
field = nameMatcher.field(targetRowType, p.left);
3493 assert field != null :
"column " + p.left +
" not found";
3494 sourceExps.set(field.getIndex(), p.right);
3498 final Supplier<Blackboard> bb =
3503 for (
int i = 0;
i < targetFields.size(); ++
i) {
3504 final RelDataTypeField
field = targetFields.get(
i);
3505 final String fieldName = field.getName();
3506 fieldNames.set(
i, fieldName);
3507 if (sourceExps.get(i) == null || sourceExps.get(
i).getKind() == SqlKind.DEFAULT) {
3509 i, initializerFactory.newColumnDefaultValue(targetTable,
i, bb.get()));
3516 return relBuilder.push(source).projectNamed(sourceExps, fieldNames,
false).build();
3524 RelOptTable targetTable, RexNode sourceRef, List<String> targetColumnNames) {
3525 final Map<String, RexNode> nameToNodeMap =
new HashMap<>();
3529 final List<ColumnStrategy> strategies = targetTable.getColumnStrategies();
3530 final List<String> targetFields = targetTable.getRowType().getFieldNames();
3531 for (String targetColumnName : targetColumnNames) {
3532 final int i = targetFields.indexOf(targetColumnName);
3533 switch (strategies.get(i)) {
3538 nameToNodeMap.put(targetColumnName, rexBuilder.makeFieldAccess(sourceRef, j++));
3545 SqlValidatorTable validatorTable) {
3547 final Table table =
unwrap(validatorTable, Table.class);
3548 if (table != null) {
3549 InitializerExpressionFactory
f =
unwrap(table, InitializerExpressionFactory.class);
3554 return NullInitializerExpressionFactory.INSTANCE;
3557 private static <T>
T unwrap(Object o, Class<T> clazz) {
3558 if (o instanceof Wrapper) {
3559 return ((Wrapper) o).unwrap(clazz);
3565 if (!RexLiteral.isNullLiteral(node)) {
3568 return rexBuilder.makeCast(
type, node);
3582 final RexNode sourceRef,
3583 final List<String> targetColumnNames,
3584 List<RexNode> columnExprs) {
3586 final RelDataType tableRowType = targetTable.getRowType();
3587 SqlNodeList targetColumnList = call.getTargetColumnList();
3588 if (targetColumnList == null) {
3589 if (
validator.config().sqlConformance().isInsertSubsetColumnsAllowed()) {
3590 final RelDataType targetRowType =
3591 typeFactory.createStructType(tableRowType.getFieldList().subList(
3592 0, sourceRef.getType().getFieldCount()));
3593 targetColumnNames.addAll(targetRowType.getFieldNames());
3595 targetColumnNames.addAll(tableRowType.getFieldNames());
3598 for (
int i = 0;
i < targetColumnList.size();
i++) {
3599 SqlIdentifier
id = (SqlIdentifier) targetColumnList.get(
i);
3600 RelDataTypeField
field = SqlValidatorUtil.getTargetField(
3602 assert field != null :
"column " + id.toString() +
" not found";
3603 targetColumnNames.add(field.getName());
3611 final List<ColumnStrategy> strategies = targetTable.getColumnStrategies();
3612 for (String columnName : targetColumnNames) {
3613 final int i = tableRowType.getFieldNames().
indexOf(columnName);
3615 switch (strategies.get(i)) {
3617 final InitializerExpressionFactory
f =
3618 Util.first(targetTable.unwrap(InitializerExpressionFactory.class),
3619 NullInitializerExpressionFactory.INSTANCE);
3620 expr = f.newColumnDefaultValue(targetTable,
i, bb);
3626 expr = bb.nameToNodeMap.get(columnName);
3628 columnExprs.add(expr);
3632 for (
int i = 0;
i < targetColumnNames.size();
i++) {
3633 if (columnExprs.get(
i) == null) {
3634 columnExprs.remove(
i);
3635 targetColumnNames.remove(
i);
3643 RelNode sourceRel =
convertSelect(call.getSourceSelect(),
false);
3644 return LogicalTableModify.create(targetTable,
3647 LogicalTableModify.Operation.DELETE,
3654 final SqlValidatorScope scope = validator.getWhereScope(call.getSourceSelect());
3662 final List<String> targetColumnNameList =
new ArrayList<>();
3663 final RelDataType targetRowType = targetTable.getRowType();
3664 for (SqlNode node : call.getTargetColumnList()) {
3665 SqlIdentifier
id = (SqlIdentifier) node;
3666 RelDataTypeField
field = SqlValidatorUtil.getTargetField(
3668 assert field != null :
"column " + id.toString() +
" not found";
3669 targetColumnNameList.add(field.getName());
3672 RelNode sourceRel =
convertSelect(call.getSourceSelect(),
false);
3674 bb.setRoot(sourceRel,
false);
3675 Builder<RexNode> rexNodeSourceExpressionListBuilder = ImmutableList.builder();
3676 for (SqlNode n : call.getSourceExpressionList()) {
3677 RexNode rn = bb.convertExpression(n);
3678 rexNodeSourceExpressionListBuilder.add(rn);
3681 return LogicalTableModify.create(targetTable,
3684 LogicalTableModify.Operation.UPDATE,
3685 targetColumnNameList,
3686 rexNodeSourceExpressionListBuilder.build(),
3694 final List<String> targetColumnNameList =
new ArrayList<>();
3695 final RelDataType targetRowType = targetTable.getRowType();
3696 SqlUpdate updateCall = call.getUpdateCall();
3697 if (updateCall != null) {
3698 for (SqlNode targetColumn : updateCall.getTargetColumnList()) {
3699 SqlIdentifier
id = (SqlIdentifier) targetColumn;
3700 RelDataTypeField
field = SqlValidatorUtil.getTargetField(
3702 assert field != null :
"column " + id.toString() +
" not found";
3703 targetColumnNameList.add(field.getName());
3716 RelNode mergeSourceRel =
convertSelect(call.getSourceSelect(),
false);
3720 SqlInsert insertCall = call.getInsertCall();
3721 int nLevel1Exprs = 0;
3722 List<RexNode> level1InsertExprs = null;
3723 List<RexNode> level2InsertExprs = null;
3724 if (insertCall != null) {
3734 level1InsertExprs = ((LogicalProject) insertRel.getInput(0)).getProjects();
3735 if (insertRel.getInput(0).getInput(0) instanceof LogicalProject) {
3737 ((LogicalProject) insertRel.getInput(0).getInput(0)).getProjects();
3739 nLevel1Exprs = level1InsertExprs.size();
3742 LogicalJoin
join = (LogicalJoin) mergeSourceRel.getInput(0);
3743 int nSourceFields = join.getLeft().getRowType().getFieldCount();
3744 final List<RexNode> projects =
new ArrayList<>();
3745 for (
int level1Idx = 0; level1Idx < nLevel1Exprs; level1Idx++) {
3746 if ((level2InsertExprs != null)
3747 && (level1InsertExprs.get(level1Idx) instanceof RexInputRef)) {
3748 int level2Idx = ((RexInputRef) level1InsertExprs.get(level1Idx)).getIndex();
3749 projects.add(level2InsertExprs.get(level2Idx));
3751 projects.add(level1InsertExprs.get(level1Idx));
3754 if (updateCall != null) {
3755 final LogicalProject project = (LogicalProject) mergeSourceRel;
3756 projects.addAll(Util.skip(project.getProjects(), nSourceFields));
3759 relBuilder.push(
join).project(projects);
3761 return LogicalTableModify.create(targetTable,
3764 LogicalTableModify.Operation.MERGE,
3765 targetColumnNameList,
3776 final SqlCall call = bb.getValidator().makeNullaryCall(identifier);
3778 return bb.convertExpression(call);
3783 pv = identifier.names.get(0);
3786 final SqlQualified qualified;
3787 if (bb.
scope != null) {
3788 qualified = bb.scope.fullyQualify(identifier);
3790 qualified = SqlQualified.create(null, 1, null, identifier);
3792 final Pair<RexNode, Map<String, Integer>> e0 = bb.lookupExp(qualified);
3793 RexNode e = e0.left;
3794 for (String
name : qualified.suffix()) {
3795 if (e == e0.left && e0.right != null) {
3796 int i = e0.right.get(
name);
3797 e = rexBuilder.makeFieldAccess(e,
i);
3799 final boolean caseSensitive =
true;
3800 if (identifier.isStar() && bb.scope instanceof MatchRecognizeScope) {
3801 e = rexBuilder.makeFieldAccess(e, 0);
3803 e = rexBuilder.makeFieldAccess(e,
name, caseSensitive);
3807 if (e instanceof RexInputRef) {
3811 e = RexPatternFieldRef.of(pv, (RexInputRef) e);
3815 if (e0.left instanceof RexCorrelVariable) {
3816 assert e instanceof RexFieldAccess;
3817 final RexNode prev = bb.mapCorrelateToRex.put(
3818 ((RexCorrelVariable) e0.left).id, (RexFieldAccess) e);
3819 assert prev == null;
3834 RelDataTypeField
field = bb.getRootField(inputRef);
3835 if (field != null) {
3836 return rexBuilder.makeInputRef(field.getType(), inputRef.getIndex());
3850 final List<SqlNode> operands = rowConstructor.getOperandList();
3855 final SqlCall cursorCall = (SqlCall) subQuery.node;
3856 assert cursorCall.operandCount() == 1;
3857 SqlNode query = cursorCall.operand(0);
3858 RelNode converted =
convertQuery(query,
false,
false).rel;
3859 int iCursor = bb.cursors.size();
3860 bb.cursors.add(converted);
3861 subQuery.expr =
new RexInputRef(iCursor, converted.getRowType());
3868 final List<Object> joinList =
new ArrayList<>();
3869 List<SqlNode> lastList =
new ArrayList<>();
3870 for (
int i = 0;
i < operands.size();
i++) {
3871 SqlNode operand = operands.get(
i);
3872 if (!(operand instanceof SqlCall)) {
3873 lastList.add(operand);
3877 final SqlCall call = (SqlCall) operand;
3878 final RelNode input;
3879 switch (call.getKind()) {
3880 case MULTISET_VALUE_CONSTRUCTOR:
3881 case ARRAY_VALUE_CONSTRUCTOR:
3882 final SqlNodeList list =
3883 new SqlNodeList(call.getOperandList(), call.getParserPosition());
3884 CollectNamespace nss = (CollectNamespace)
validator.getNamespace(call);
3890 public SqlNode getNode() {
3895 RelDataType multisetType = validator.getValidatedNodeType(call);
3896 validator.setValidatedNodeType(list, multisetType.getComponentType());
3899 case MULTISET_QUERY_CONSTRUCTOR:
3900 case ARRAY_QUERY_CONSTRUCTOR:
3901 final RelRoot root =
convertQuery(call.operand(0),
false,
true);
3905 lastList.add(operand);
3909 if (lastList.size() > 0) {
3910 joinList.add(lastList);
3912 lastList =
new ArrayList<>();
3913 Collect collect =
new Collect(
cluster,
3914 cluster.traitSetOf(Convention.NONE),
3916 validator.deriveAlias(call,
i));
3917 joinList.add(collect);
3920 if (joinList.size() == 0) {
3921 joinList.add(lastList);
3924 for (
int i = 0;
i < joinList.size();
i++) {
3925 Object o = joinList.get(
i);
3926 if (o instanceof List) {
3927 @SuppressWarnings(
"unchecked")
3928 List<SqlNode> projectList = (List<SqlNode>) o;
3929 final List<RexNode> selectList = new ArrayList<>();
3930 final List<String> fieldNameList = new ArrayList<>();
3931 for (
int j = 0; j < projectList.size(); j++) {
3932 SqlNode operand = projectList.get(
j);
3933 selectList.add(bb.convertExpression(operand));
3942 fieldNameList.add(SqlUtil.deriveAliasFromOrdinal(
j));
3945 relBuilder.push(LogicalValues.createOneRow(
cluster))
3946 .projectNamed(selectList, fieldNameList,
true);
3948 joinList.set(
i, relBuilder.build());
3952 RelNode ret = (RelNode) joinList.get(0);
3953 for (
int i = 1;
i < joinList.size();
i++) {
3954 RelNode relNode = (RelNode) joinList.get(
i);
3955 ret = RelFactories.DEFAULT_JOIN_FACTORY.createJoin(ret,
3967 Blackboard bb, SqlSelect select, List<SqlNode> orderList) {
3968 SqlNodeList selectList = select.getSelectList();
3969 selectList = validator.expandStar(selectList, select,
false);
3971 replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
3973 List<String> fieldNames =
new ArrayList<>();
3974 final List<RexNode> exprs =
new ArrayList<>();
3975 final Collection<String> aliases =
new TreeSet<>();
3979 final List<SqlMonotonicity> columnMonotonicityList =
new ArrayList<>();
3980 extraSelectItems(bb, select, exprs, fieldNames, aliases, columnMonotonicityList);
3984 for (SqlNode expr : selectList) {
3986 exprs.add(bb.convertExpression(expr));
3987 fieldNames.add(deriveAlias(expr, aliases, i));
3991 for (SqlNode expr : orderList) {
3993 SqlNode expr2 = validator.expandOrderExpr(select, expr);
3994 exprs.add(bb.convertExpression(expr2));
3995 fieldNames.add(deriveAlias(expr, aliases, i));
3998 fieldNames = SqlValidatorUtil.uniquify(
3999 fieldNames, catalogReader.nameMatcher().isCaseSensitive());
4001 relBuilder.push(bb.root).projectNamed(exprs, fieldNames,
true);
4002 bb.setRoot(relBuilder.build(),
false);
4004 assert bb.columnMonotonicities.isEmpty();
4005 bb.columnMonotonicities.addAll(columnMonotonicityList);
4006 for (SqlNode selectItem : selectList) {
4007 bb.columnMonotonicities.add(selectItem.getMonotonicity(bb.scope));
4026 List<RexNode> exprList,
4027 List<String> nameList,
4028 Collection<String> aliasList,
4029 List<SqlMonotonicity> columnMonotonicityList) {}
4032 final SqlNode node, Collection<String> aliases,
final int ordinal) {
4033 String alias = validator.deriveAlias(node, ordinal);
4034 if ((alias == null) || aliases.contains(alias)) {
4035 String aliasBase = (alias == null) ?
"EXPR$" : alias;
4036 for (
int j = 0;;
j++) {
4037 alias = aliasBase +
j;
4038 if (!aliases.contains(alias)) {
4051 return convertQuery(with.body,
false, top);
4058 final SqlValidatorScope scope = validator.getOverScope(values);
4059 assert scope != null;
4060 final Blackboard bb = createBlackboard(scope, null,
false);
4061 convertValuesImpl(bb, values, targetRowType);
4074 Blackboard bb, SqlCall values, RelDataType targetRowType) {
4078 convertRowValues(bb, values, values.getOperandList(),
true, targetRowType);
4079 if (valuesRel != null) {
4080 bb.setRoot(valuesRel,
true);
4084 final List<RelNode> unionRels =
new ArrayList<>();
4085 for (SqlNode rowConstructor1 : values.getOperandList()) {
4086 SqlCall rowConstructor = (SqlCall) rowConstructor1;
4088 replaceSubQueries(tmpBb, rowConstructor, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
4089 final List<Pair<RexNode, String>> exps =
new ArrayList<>();
4090 for (Ord<SqlNode> operand : Ord.zip(rowConstructor.getOperandList())) {
4091 exps.add(Pair.of(tmpBb.convertExpression(operand.e),
4092 validator.deriveAlias(operand.e, operand.i)));
4095 (null == tmpBb.root) ? LogicalValues.createOneRow(cluster) : tmpBb.root;
4097 relBuilder.push(in).project(Pair.left(exps), Pair.right(exps)).build());
4100 if (unionRels.size() == 0) {
4101 throw new AssertionError(
"empty values clause");
4102 }
else if (unionRels.size() == 1) {
4103 bb.setRoot(unionRels.get(0),
true);
4105 bb.setRoot(LogicalUnion.create(unionRels,
true),
true);
4115 implements SqlRexContext, SqlVisitor<RexNode>, InitializerContext {
4123 private final Map<CorrelationId, RexFieldAccess> mapCorrelateToRex =
new HashMap<>();
4125 private boolean isPatternVarRef =
false;
4127 final List<RelNode> cursors =
new ArrayList<>();
4133 private final List<SubQuery> subQueryList =
new ArrayList<>();
4151 private final Map<RelNode, Map<Integer, Integer>> mapRootRelToFieldProjection =
4154 private final List<SqlMonotonicity> columnMonotonicities =
new ArrayList<>();
4156 private final List<RelDataTypeField> systemFieldList =
new ArrayList<>();
4159 private final InitializerExpressionFactory initializerExpressionFactory =
4160 new NullInitializerExpressionFactory();
4174 SqlValidatorScope scope, Map<String, RexNode> nameToNodeMap,
boolean top) {
4176 this.nameToNodeMap = nameToNodeMap;
4182 if (null == scope) {
4185 return scope.getNode();
4186 }
catch (Exception e) {
4192 this.isPatternVarRef = isVarRef;
4195 public RexNode
register(RelNode rel, JoinRelType joinType) {
4196 return register(rel, joinType, null);
4208 public RexNode
register(RelNode rel, JoinRelType joinType, List<RexNode> leftKeys) {
4209 assert joinType != null;
4211 assert leftKeys == null;
4212 setRoot(rel,
false);
4213 return rexBuilder.makeRangeReference(root.getRowType(), 0,
false);
4216 final RexNode joinCond;
4217 final int origLeftInputCount = root.getRowType().getFieldCount();
4218 if (leftKeys != null) {
4219 List<RexNode> newLeftInputExprs =
new ArrayList<>();
4220 for (
int i = 0;
i < origLeftInputCount;
i++) {
4221 newLeftInputExprs.add(rexBuilder.makeInputRef(root,
i));
4224 final List<Integer> leftJoinKeys =
new ArrayList<>();
4225 for (RexNode leftKey : leftKeys) {
4226 int index = newLeftInputExprs.indexOf(leftKey);
4227 if (index < 0 || joinType == JoinRelType.LEFT) {
4228 index = newLeftInputExprs.size();
4229 newLeftInputExprs.add(leftKey);
4231 leftJoinKeys.add(index);
4234 RelNode newLeftInput = relBuilder.push(root).project(newLeftInputExprs).build();
4237 if (mapRootRelToFieldProjection.containsKey(root)) {
4238 mapRootRelToFieldProjection.put(
4239 newLeftInput, mapRootRelToFieldProjection.get(root));
4242 setRoot(newLeftInput,
false);
4245 final int rightOffset = root.getRowType().getFieldCount()
4246 - newLeftInput.getRowType().getFieldCount();
4247 final List<Integer> rightKeys =
4248 Util.range(rightOffset, rightOffset + leftKeys.size());
4250 joinCond = RelOptUtil.createEquiJoinCondition(
4251 newLeftInput, leftJoinKeys, rel, rightKeys, rexBuilder);
4253 joinCond = rexBuilder.makeLiteral(
true);
4256 int leftFieldCount = root.getRowType().getFieldCount();
4257 final RelNode
join = createJoin(
this, root, rel, joinCond, joinType);
4259 setRoot(join,
false);
4261 if (leftKeys != null && joinType == JoinRelType.LEFT) {
4262 final int leftKeyCount = leftKeys.size();
4263 int rightFieldLength = rel.getRowType().getFieldCount();
4264 assert leftKeyCount == rightFieldLength - 1;
4266 final int rexRangeRefLength = leftKeyCount + rightFieldLength;
4267 RelDataType returnType = typeFactory.createStructType(
4268 new AbstractList<Map.Entry<String, RelDataType>>() {
4269 public Map.Entry<String, RelDataType>
get(
int index) {
4270 return join.getRowType().getFieldList().get(
4271 origLeftInputCount + index);
4275 return rexRangeRefLength;
4279 return rexBuilder.makeRangeReference(returnType, origLeftInputCount,
false);
4281 return rexBuilder.makeRangeReference(
4282 rel.getRowType(), leftFieldCount, joinType.generatesNullsOnRight());
4298 setRoot(Collections.singletonList(root), root, root instanceof LogicalJoin);
4300 leaves.put(root, root.getRowType().getFieldCount());
4302 this.columnMonotonicities.clear();
4305 private void setRoot(List<RelNode> inputs, RelNode root,
boolean hasSystemFields) {
4306 this.inputs = inputs;
4308 this.systemFieldList.clear();
4309 if (hasSystemFields) {
4310 this.systemFieldList.addAll(getSystemFields());
4327 setRoot(inputs, null,
false);
4336 Pair<RexNode, Map<String, Integer>>
lookupExp(SqlQualified qualified) {
4337 if (nameToNodeMap != null && qualified.prefixLength == 1) {
4338 RexNode node = nameToNodeMap.get(qualified.identifier.names.get(0));
4340 throw new AssertionError(
"Unknown identifier '" + qualified.identifier
4341 +
"' encountered while expanding expression");
4343 return Pair.of(node, null);
4345 final SqlNameMatcher nameMatcher =
4346 scope.getValidator().getCatalogReader().nameMatcher();
4347 final SqlValidatorScope.ResolvedImpl resolved =
4348 new SqlValidatorScope.ResolvedImpl();
4349 scope.resolve(qualified.prefix(), nameMatcher,
false, resolved);
4350 if (!(resolved.count() == 1)) {
4353 final SqlValidatorScope.Resolve resolve = resolved.only();
4354 final RelDataType rowType = resolve.rowType();
4359 final SqlValidatorScope ancestorScope = resolve.scope;
4360 boolean isParent = ancestorScope != scope;
4361 if ((inputs != null) && !isParent) {
4362 final LookupContext rels =
4363 new LookupContext(
this, inputs, systemFieldList.size());
4364 final RexNode node = lookup(resolve.path.steps().get(0).
i, rels);
4368 final Map<String, Integer> fieldOffsets =
new HashMap<>();
4369 for (RelDataTypeField
f : resolve.rowType().getFieldList()) {
4370 if (!fieldOffsets.containsKey(
f.getName())) {
4371 fieldOffsets.put(f.getName(),
f.getIndex());
4374 final Map<String, Integer> map = ImmutableMap.copyOf(fieldOffsets);
4375 return Pair.of(node, map);
4384 final CorrelationId correlId = cluster.createCorrel();
4385 mapCorrelToDeferred.put(correlId, lookup);
4386 if (resolve.path.steps().get(0).
i < 0) {
4387 return Pair.of(rexBuilder.makeCorrel(rowType, correlId), null);
4389 final RelDataTypeFactory.Builder builder = typeFactory.builder();
4390 final ListScope ancestorScope1 = (ListScope) resolve.scope;
4391 final ImmutableMap.Builder<String, Integer> fields = ImmutableMap.builder();
4394 for (SqlValidatorNamespace c : ancestorScope1.getChildren()) {
4395 builder.addAll(c.getRowType().getFieldList());
4396 if (i == resolve.path.steps().get(0).i) {
4397 for (RelDataTypeField
field : c.getRowType().getFieldList()) {
4398 fields.put(field.getName(),
field.getIndex() + offset);
4402 offset += c.getRowType().getFieldCount();
4404 final RexNode c = rexBuilder.makeCorrel(builder.uniquify().build(), correlId);
4405 return Pair.of(c, fields.build());
4414 RexNode lookup(
int offset, LookupContext lookupContext) {
4415 Pair<RelNode, Integer> pair = lookupContext.findRel(offset);
4416 return rexBuilder.makeRangeReference(pair.left.getRowType(), pair.right,
false);
4419 RelDataTypeField getRootField(RexInputRef inputRef) {
4420 if (inputs == null) {
4423 int fieldOffset = inputRef.getIndex();
4424 for (RelNode input : inputs) {
4425 RelDataType rowType = input.getRowType();
4426 if (fieldOffset < rowType.getFieldCount()) {
4427 return rowType.getFieldList().
get(fieldOffset);
4429 fieldOffset -= rowType.getFieldCount();
4434 public void flatten(List<RelNode> rels,
4435 int systemFieldCount,
4437 List<Pair<RelNode, Integer>> relOffsetList) {
4438 for (RelNode rel : rels) {
4439 if (leaves.containsKey(rel)) {
4440 relOffsetList.add(Pair.of(rel, start[0]));
4441 start[0] += leaves.get(rel);
4442 }
else if (rel instanceof LogicalMatch) {
4443 relOffsetList.add(Pair.of(rel, start[0]));
4444 start[0] += rel.getRowType().getFieldCount();
4446 if (rel instanceof LogicalJoin || rel instanceof LogicalAggregate) {
4447 start[0] += systemFieldCount;
4449 flatten(rel.getInputs(), systemFieldCount, start, relOffsetList);
4454 void registerSubQuery(SqlNode node, RelOptUtil.Logic logic) {
4455 for (SubQuery subQuery : subQueryList) {
4458 if (node == subQuery.node) {
4462 subQueryList.add(
new SubQuery(node, logic));
4465 SubQuery getSubQuery(SqlNode expr) {
4466 for (SubQuery subQuery : subQueryList) {
4469 if (expr == subQuery.node) {
4477 ImmutableList<RelNode> retrieveCursors() {
4479 return ImmutableList.copyOf(cursors);
4485 public RexNode convertExpression(SqlNode expr) {
4489 final SqlNode expandedGroupExpr = validator.expand(expr, scope);
4490 final int ref = agg.lookupGroupExpr(expandedGroupExpr);
4492 return rexBuilder.makeInputRef(root, ref);
4494 if (expr instanceof SqlCall) {
4495 final RexNode rex = agg.lookupAggregates((SqlCall) expr);
4504 RexNode rex = convertExtendedExpression(expr,
this);
4511 final SqlKind kind = expr.getKind();
4512 final SubQuery subQuery;
4513 boolean isExpand = config.getExpandPredicate().test(getTopNode(), expr);
4516 final SqlNode query;
4523 call = (SqlCall) expr;
4524 query = call.operand(1);
4525 if (!(query instanceof SqlNodeList)) {
4526 root = convertQueryRecursive(query,
false, null);
4527 final SqlNode operand = call.operand(0);
4528 List<SqlNode> nodes;
4529 switch (operand.getKind()) {
4531 nodes = ((SqlCall) operand).getOperandList();
4534 nodes = ImmutableList.of(operand);
4536 final ImmutableList.Builder<RexNode> builder = ImmutableList.builder();
4537 for (SqlNode node : nodes) {
4538 builder.add(convertExpression(node));
4540 final ImmutableList<RexNode> list = builder.build();
4543 return RexSubQuery.in(root.rel, list);
4545 return rexBuilder.makeCall(
4546 SqlStdOperatorTable.NOT, RexSubQuery.in(root.rel, list));
4548 return RexSubQuery.some(
4549 root.rel, list, (SqlQuantifyOperator) call.getOperator());
4551 return rexBuilder.makeCall(SqlStdOperatorTable.NOT,
4552 RexSubQuery.some(root.rel,
4554 negate((SqlQuantifyOperator) call.getOperator())));
4556 throw new AssertionError(kind);
4562 call = (SqlCall) expr;
4563 query = Iterables.getOnlyElement(call.getOperandList());
4564 root = convertQueryRecursive(query,
false, null);
4565 RelNode rel = root.rel;
4566 while (rel instanceof Project
4567 || rel instanceof Sort && ((Sort) rel).fetch == null
4568 && ((Sort) rel).offset == null) {
4569 rel = ((SingleRel) rel).getInput();
4571 return RexSubQuery.exists(rel);
4574 call = (SqlCall) expr;
4575 query = Iterables.getOnlyElement(call.getOperandList());
4576 root = convertQueryRecursive(query,
false, null);
4577 return RexSubQuery.scalar(root.rel);
4585 throw new RuntimeException(kind +
" is only supported if expand = false");
4591 subQuery = Objects.requireNonNull(getSubQuery(expr));
4592 rex = Objects.requireNonNull(subQuery.expr);
4593 return StandardConvertletTable.castToValidatedType(
4594 expr, rex, validator, rexBuilder);
4599 subQuery = getSubQuery(expr);
4600 assert subQuery != null;
4601 rex = subQuery.expr;
4602 assert rex != null :
"rex != null";
4604 if (((kind == SqlKind.SCALAR_QUERY) || (kind == SqlKind.EXISTS))
4605 && isConvertedSubq(rex)) {
4612 RexNode fieldAccess =
4613 rexBuilder.makeFieldAccess(rex, rex.getType().getFieldCount() - 1);
4618 if (fieldAccess.getType().isNullable() && kind == SqlKind.EXISTS) {
4620 rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, fieldAccess);
4625 return convertOver(
this, expr);
4632 rex = expr.accept(
this);
4633 return Objects.requireNonNull(rex);
4640 public RexFieldCollation convertSortExpression(SqlNode expr,
4641 RelFieldCollation.Direction direction,
4642 RelFieldCollation.NullDirection nullDirection) {
4643 switch (expr.getKind()) {
4645 return convertSortExpression(((SqlCall) expr).operand(0),
4646 RelFieldCollation.Direction.DESCENDING,
4649 return convertSortExpression(((SqlCall) expr).operand(0),
4651 RelFieldCollation.NullDirection.LAST);
4653 return convertSortExpression(((SqlCall) expr).operand(0),
4655 RelFieldCollation.NullDirection.FIRST);
4657 final Set<SqlKind> flags = EnumSet.noneOf(SqlKind.class);
4658 switch (direction) {
4660 flags.add(SqlKind.DESCENDING);
4662 switch (nullDirection) {
4664 final RelFieldCollation.NullDirection nullDefaultDirection =
4665 validator.config().defaultNullCollation().last(desc(direction))
4666 ? RelFieldCollation.NullDirection.LAST
4667 : RelFieldCollation.NullDirection.FIRST;
4668 if (nullDefaultDirection != direction.defaultNullDirection()) {
4669 SqlKind nullDirectionSqlKind =
4670 validator.config().defaultNullCollation().last(desc(direction))
4671 ? SqlKind.NULLS_LAST
4672 : SqlKind.NULLS_FIRST;
4673 flags.add(nullDirectionSqlKind);
4677 flags.add(SqlKind.NULLS_FIRST);
4680 flags.add(SqlKind.NULLS_LAST);
4683 return new RexFieldCollation(convertExpression(expr), flags);
4695 private boolean isConvertedSubq(RexNode rex) {
4696 if ((rex instanceof
RexLiteral) || (rex instanceof RexDynamicParam)) {
4699 if (rex instanceof RexCall) {
4700 RexCall call = (RexCall) rex;
4701 if (call.getOperator() == SqlStdOperatorTable.CAST) {
4702 RexNode operand = call.getOperands().
get(0);
4703 if (operand instanceof RexLiteral) {
4711 public int getGroupCount() {
4713 return agg.groupExprs.size();
4715 if (window != null) {
4716 return window.isAlwaysNonEmpty() ? 1 : 0;
4721 public RexBuilder getRexBuilder() {
4725 public SqlNode validateExpression(RelDataType rowType, SqlNode expr) {
4726 return SqlValidatorUtil
4727 .validateExprWithRowType(catalogReader.nameMatcher().isCaseSensitive(),
4735 public RexRangeRef getSubQueryExpr(SqlCall call) {
4736 final SubQuery subQuery = getSubQuery(call);
4737 assert subQuery != null;
4738 return (RexRangeRef) subQuery.expr;
4741 public RelDataTypeFactory getTypeFactory() {
4745 public InitializerExpressionFactory getInitializerExpressionFactory() {
4746 return initializerExpressionFactory;
4749 public SqlValidator getValidator() {
4753 public RexNode convertLiteral(SqlLiteral literal) {
4754 return exprConverter.convertLiteral(
this, literal);
4757 public RexNode convertInterval(SqlIntervalQualifier intervalQualifier) {
4758 return exprConverter.convertInterval(
this, intervalQualifier);
4761 public RexNode visit(SqlLiteral literal) {
4762 return exprConverter.convertLiteral(
this, literal);
4765 public RexNode visit(SqlCall call) {
4767 final SqlOperator op = call.getOperator();
4769 && (op.isAggregator() || op.getKind() == SqlKind.FILTER
4770 || op.getKind() == SqlKind.WITHIN_GROUP)) {
4771 return agg.lookupAggregates(call);
4774 return exprConverter.convertCall(
4775 this,
new SqlCallBinding(validator, scope, call).permutedCall());
4778 public RexNode visit(SqlNodeList nodeList) {
4779 throw new UnsupportedOperationException();
4782 public RexNode visit(SqlIdentifier
id) {
4783 return convertIdentifier(
this,
id);
4786 public RexNode visit(SqlDataTypeSpec
type) {
4787 throw new UnsupportedOperationException();
4790 public RexNode visit(SqlDynamicParam param) {
4791 return convertDynamicParam(param);
4794 public RexNode visit(SqlIntervalQualifier intervalQualifier) {
4795 return convertInterval(intervalQualifier);
4798 public List<SqlMonotonicity> getColumnMonotonicities() {
4799 return columnMonotonicities;
4803 private SqlQuantifyOperator
negate(SqlQuantifyOperator
operator) {
4804 assert operator.kind == SqlKind.ALL;
4805 return SqlStdOperatorTable.some(operator.comparisonKind.negateNullSafe());
4815 this.originalRelName = originalRelName;
4819 return (RexFieldAccess) bb.mapCorrelateToRex.get(
name);
4823 return originalRelName;
4838 boolean isExplain) {
4839 throw new IllegalArgumentException();
4862 protected class AggConverter
implements SqlVisitor<Void> {
4863 private final Blackboard bb;
4864 public final AggregatingSelectScope aggregatingSelectScope;
4866 private final Map<String, String> nameMap =
new HashMap<>();
4871 private final SqlNodeList groupExprs =
new SqlNodeList(SqlParserPos.ZERO);
4876 private final Map<SqlNode, Ord<AuxiliaryConverter>> auxiliaryGroupExprs =
4886 private final List<Pair<RexNode, String>> convertedInputExprs =
new ArrayList<>();
4894 private final List<AggregateCall> aggCalls =
new ArrayList<>();
4895 private final Map<SqlNode, RexNode> aggMapping =
new HashMap<>();
4896 private final Map<AggregateCall, RexNode> aggCallMapping =
new HashMap<>();
4899 private boolean inOver =
false;
4911 public AggConverter(Blackboard bb, SqlSelect select) {
4913 this.aggregatingSelectScope =
4914 (AggregatingSelectScope) bb.getValidator().getSelectScope(select);
4918 final SqlNodeList selectList = select.getSelectList();
4919 for (
int i = 0;
i < selectList.size();
i++) {
4920 SqlNode selectItem = selectList.get(
i);
4922 if (SqlUtil.isCallTo(selectItem, SqlStdOperatorTable.AS)) {
4923 final SqlCall call = (SqlCall) selectItem;
4924 selectItem = call.operand(0);
4928 name = validator.deriveAlias(selectItem,
i);
4930 nameMap.put(selectItem.toString(), name);
4934 public int addGroupExpr(SqlNode expr) {
4935 int ref = lookupGroupExpr(expr);
4939 final int index = groupExprs.size();
4940 groupExprs.add(expr);
4942 RexNode convExpr = bb.convertExpression(expr);
4943 addExpr(convExpr,
name);
4945 if (expr instanceof SqlCall) {
4946 SqlCall call = (SqlCall) expr;
4947 for (Pair<SqlNode, AuxiliaryConverter> p :
4948 SqlStdOperatorTable.convertGroupToAuxiliaryCalls(call)) {
4949 addAuxiliaryGroupExpr(p.left, index, p.right);
4956 void addAuxiliaryGroupExpr(SqlNode node,
int index, AuxiliaryConverter converter) {
4957 for (SqlNode node2 : auxiliaryGroupExprs.keySet()) {
4958 if (node2.equalsDeep(node, Litmus.IGNORE)) {
4962 auxiliaryGroupExprs.put(node, Ord.of(index, converter));
4971 private void addExpr(RexNode expr, String
name) {
4972 if ((name == null) && (expr instanceof RexInputRef)) {
4973 final int i = ((RexInputRef) expr).getIndex();
4974 name = bb.root.getRowType().getFieldList().get(
i).getName();
4976 if (Pair.right(convertedInputExprs).contains(
name)) {
4981 convertedInputExprs.add(Pair.of(expr,
name));
4984 public Void visit(SqlIdentifier
id) {
4988 public Void visit(SqlNodeList nodeList) {
4989 for (
int i = 0;
i < nodeList.size();
i++) {
4990 nodeList.get(
i).accept(
this);
4995 public Void visit(SqlLiteral lit) {
4999 public Void visit(SqlDataTypeSpec
type) {
5003 public Void visit(SqlDynamicParam param) {
5007 public Void visit(SqlIntervalQualifier intervalQualifier) {
5011 public Void visit(SqlCall call) {
5012 switch (call.getKind()) {
5022 final boolean prevInOver = inOver;
5025 if (call.getOperator().getKind() == SqlKind.OVER) {
5027 List<SqlNode> operandList = call.getOperandList();
5028 assert operandList.size() == 2;
5033 operandList.get(0).accept(
this);
5037 operandList.get(1).accept(
this);
5043 if (call.getOperator().isAggregator()) {
5053 for (SqlNode operand : call.getOperandList()) {
5055 if (operand != null) {
5056 operand.accept(
this);
5060 inOver = prevInOver;
5064 private void translateAgg(SqlCall call) {
5065 translateAgg(call, null, null,
false, call);
5068 private void translateAgg(SqlCall call,
5070 SqlNodeList orderList,
5071 boolean ignoreNulls,
5072 SqlCall outerCall) {
5073 assert bb.agg ==
this;
5074 assert outerCall != null;
5075 switch (call.getKind()) {
5077 assert filter == null;
5079 call.operand(0), call.operand(1), orderList, ignoreNulls, outerCall);
5082 assert orderList == null;
5083 translateAgg(call.operand(0), filter, call.operand(1), ignoreNulls, outerCall);
5089 translateAgg(call.operand(0), filter, orderList, ignoreNulls, outerCall);
5092 final List<Integer>
args =
new ArrayList<>();
5094 final List<RelDataType> argTypes = call.getOperator() instanceof SqlCountAggFunction
5095 ?
new ArrayList<>(call.getOperandList().size())
5100 for (SqlNode operand : call.getOperandList()) {
5102 if (operand instanceof SqlIdentifier) {
5103 SqlIdentifier
id = (SqlIdentifier) operand;
5105 assert call.operandCount() == 1;
5106 assert args.isEmpty();
5110 RexNode convertedExpr = bb.convertExpression(operand);
5111 assert convertedExpr != null;
5112 if (argTypes != null) {
5113 argTypes.add(convertedExpr.getType());
5115 args.add(lookupOrCreateGroupExpr(convertedExpr));
5118 if (filter != null) {
5119 RexNode convertedExpr = bb.convertExpression(filter);
5120 assert convertedExpr != null;
5121 if (convertedExpr.getType().isNullable()) {
5123 rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, convertedExpr);
5125 filterArg = lookupOrCreateGroupExpr(convertedExpr);
5132 SqlAggFunction aggFunction = (SqlAggFunction) call.getOperator();
5133 final RelDataType
type = validator.deriveType(bb.scope, call);
5134 boolean distinct =
false;
5135 SqlLiteral quantifier = call.getFunctionQuantifier();
5136 if ((null != quantifier) && (quantifier.getValue() == SqlSelectKeyword.DISTINCT)) {
5139 boolean approximate =
false;
5140 if (aggFunction == SqlStdOperatorTable.APPROX_COUNT_DISTINCT) {
5141 aggFunction = SqlStdOperatorTable.COUNT;
5145 final RelCollation collation;
5146 if (orderList == null || orderList.size() == 0) {
5147 collation = RelCollations.EMPTY;
5149 collation = RelCollations.of(
5153 -> bb.convertSortExpression(order,
5154 RelFieldCollation.Direction.ASCENDING,
5155 RelFieldCollation.NullDirection.UNSPECIFIED))
5157 ->
new RelFieldCollation(
5158 lookupOrCreateGroupExpr(fieldCollation.left),
5159 fieldCollation.getDirection(),
5160 fieldCollation.getNullDirection()))
5161 .collect(Collectors.toList()));
5163 final AggregateCall aggCall = AggregateCall.create(aggFunction,
5171 nameMap.get(outerCall.toString()));
5172 RexNode rex = rexBuilder.addAggCall(
5173 aggCall, groupExprs.size(), aggCalls, aggCallMapping, argTypes);
5174 aggMapping.put(outerCall, rex);
5177 private int lookupOrCreateGroupExpr(RexNode expr) {
5179 for (RexNode convertedInputExpr : Pair.left(convertedInputExprs)) {
5180 if (expr.equals(convertedInputExpr)) {
5187 addExpr(expr, null);
5195 public int lookupGroupExpr(SqlNode expr) {
5196 for (
int i = 0;
i < groupExprs.size();
i++) {
5197 SqlNode groupExpr = groupExprs.get(
i);
5198 if (expr.equalsDeep(groupExpr, Litmus.IGNORE)) {
5205 public RexNode lookupAggregates(SqlCall call) {
5207 assert bb.agg ==
this;
5209 for (Map.Entry<SqlNode, Ord<AuxiliaryConverter>> e :
5210 auxiliaryGroupExprs.entrySet()) {
5211 if (call.equalsDeep(e.getKey(), Litmus.IGNORE)) {
5212 AuxiliaryConverter converter = e.getValue().e;
5213 final int groupOrdinal = e.getValue().
i;
5214 return converter.convert(rexBuilder,
5215 convertedInputExprs.get(groupOrdinal).left,
5216 rexBuilder.makeInputRef(bb.root, groupOrdinal));
5220 return aggMapping.get(call);
5223 public List<Pair<RexNode, String>> getPreExprs() {
5224 return convertedInputExprs;
5227 public List<AggregateCall> getAggCalls() {
5231 private boolean containsGroupId() {
5232 return aggCalls.stream().anyMatch(
5233 agg -> agg.getAggregation().kind == SqlKind.GROUP_ID);
5236 public RelDataTypeFactory getTypeFactory() {
5244 private static class LookupContext {
5245 private final List<Pair<RelNode, Integer>> relOffsetList =
new ArrayList<>();
5254 LookupContext(Blackboard bb, List<RelNode> rels,
int systemFieldCount) {
5255 bb.flatten(rels, systemFieldCount,
new int[] {0}, relOffsetList);
5270 Pair<RelNode, Integer> findRel(
int offset) {
5271 return relOffsetList.get(offset);
5307 private class HistogramShuttle
extends RexShuttle {
5312 static final boolean ENABLE_HISTOGRAM_AGG =
false;
5314 private final List<RexNode> partitionKeys;
5315 private final ImmutableList<RexFieldCollation> orderKeys;
5316 private final RexWindowBound lowerBound;
5317 private final RexWindowBound upperBound;
5318 private final boolean rows;
5319 private final boolean allowPartial;
5320 private final boolean distinct;
5321 private final boolean ignoreNulls;
5323 HistogramShuttle(List<RexNode> partitionKeys,
5324 ImmutableList<RexFieldCollation> orderKeys,
5325 RexWindowBound lowerBound,
5326 RexWindowBound upperBound,
5328 boolean allowPartial,
5330 boolean ignoreNulls) {
5331 this.partitionKeys = partitionKeys;
5332 this.orderKeys = orderKeys;
5333 this.lowerBound = lowerBound;
5334 this.upperBound = upperBound;
5336 this.allowPartial = allowPartial;
5337 this.distinct = distinct;
5338 this.ignoreNulls = ignoreNulls;
5341 public RexNode visitCall(RexCall call) {
5342 final SqlOperator op = call.getOperator();
5343 if (!(op instanceof SqlAggFunction)) {
5344 return super.visitCall(call);
5346 final SqlAggFunction aggOp = (SqlAggFunction) op;
5347 final RelDataType type = call.getType();
5348 List<RexNode> exprs = call.getOperands();
5350 SqlFunction histogramOp = !ENABLE_HISTOGRAM_AGG ? null : getHistogramOp(aggOp);
5352 if (histogramOp != null) {
5353 final RelDataType histogramType = computeHistogramType(type);
5358 boolean reinterpretCast = type.getSqlTypeName() == SqlTypeName.DECIMAL;
5362 if (histogramType != type) {
5363 exprs =
new ArrayList<>(exprs);
5365 reinterpretCast ? rexBuilder.makeReinterpretCast(
5366 histogramType, exprs.get(0), rexBuilder.makeLiteral(
false))
5367 : rexBuilder.makeCast(histogramType, exprs.get(0)));
5370 RexCallBinding bind =
new RexCallBinding(rexBuilder.getTypeFactory(),
5371 SqlStdOperatorTable.HISTOGRAM_AGG,
5373 ImmutableList.of());
5375 RexNode over = rexBuilder.makeOver(
5376 SqlStdOperatorTable.HISTOGRAM_AGG.inferReturnType(bind),
5377 SqlStdOperatorTable.HISTOGRAM_AGG,
5389 RexNode histogramCall =
5390 rexBuilder.makeCall(histogramType, histogramOp, ImmutableList.of(over));
5394 if (histogramType != type) {
5395 if (reinterpretCast) {
5396 histogramCall = rexBuilder.makeReinterpretCast(
5397 type, histogramCall, rexBuilder.makeLiteral(
false));
5399 histogramCall = rexBuilder.makeCast(
type, histogramCall);
5403 return histogramCall;
5405 boolean needSum0 = aggOp == SqlStdOperatorTable.SUM && type.isNullable();
5406 SqlAggFunction aggOpToUse = needSum0 ? SqlStdOperatorTable.SUM0 : aggOp;
5407 return rexBuilder.makeOver(
type,
5433 SqlFunction getHistogramOp(SqlAggFunction aggFunction) {
5434 if (aggFunction == SqlStdOperatorTable.MIN) {
5435 return SqlStdOperatorTable.HISTOGRAM_MIN;
5436 }
else if (aggFunction == SqlStdOperatorTable.MAX) {
5437 return SqlStdOperatorTable.HISTOGRAM_MAX;
5438 }
else if (aggFunction == SqlStdOperatorTable.FIRST_VALUE) {
5439 return SqlStdOperatorTable.HISTOGRAM_FIRST_VALUE;
5440 }
else if (aggFunction == SqlStdOperatorTable.LAST_VALUE) {
5441 return SqlStdOperatorTable.HISTOGRAM_LAST_VALUE;
5451 private RelDataType computeHistogramType(RelDataType type) {
5452 if (SqlTypeUtil.isExactNumeric(type)
5453 && type.getSqlTypeName() != SqlTypeName.BIGINT) {
5454 return typeFactory.createSqlType(SqlTypeName.BIGINT);
5455 }
else if (SqlTypeUtil.isApproximateNumeric(type)
5456 && type.getSqlTypeName() != SqlTypeName.DOUBLE) {
5457 return typeFactory.createSqlType(SqlTypeName.DOUBLE);
5467 private static class SubQuery {
5469 final RelOptUtil.Logic logic;
5472 private SubQuery(SqlNode node, RelOptUtil.Logic logic) {
5481 private static class AggregateFinder
extends SqlBasicVisitor<Void> {
5482 final SqlNodeList list =
new SqlNodeList(SqlParserPos.ZERO);
5483 final SqlNodeList filterList =
new SqlNodeList(SqlParserPos.ZERO);
5484 final SqlNodeList orderList =
new SqlNodeList(SqlParserPos.ZERO);
5487 public Void visit(SqlCall call) {
5490 if (call.getOperator().getKind() == SqlKind.OVER) {
5494 if (call.getOperator().getKind() == SqlKind.FILTER) {
5498 final SqlNode aggCall = call.getOperandList().
get(0);
5499 final SqlNode whereCall = call.getOperandList().
get(1);
5501 filterList.add(whereCall);
5505 if (call.getOperator().getKind() == SqlKind.WITHIN_GROUP) {
5509 final SqlNode aggCall = call.getOperandList().
get(0);
5510 final SqlNodeList orderList = (SqlNodeList) call.getOperandList().get(1);
5516 if (call.getOperator().isAggregator()) {
5523 if (call instanceof SqlSelect) {
5527 return call.getOperator().acceptCall(
this, call);
5534 private static class CorrelationUse {
5535 private final CorrelationId id;
5536 private final ImmutableBitSet requiredColumns;
5538 private final RelNode
r;
5540 CorrelationUse(CorrelationId
id, ImmutableBitSet requiredColumns, RelNode
r) {
5542 this.requiredColumns = requiredColumns;
5548 public static ConfigBuilder configBuilder() {
5549 return new ConfigBuilder();
5559 public interface Config {
5561 Config DEFAULT = configBuilder().build();
5567 boolean isDecorrelationEnabled();
5573 boolean isTrimUnusedFields();
5580 boolean isCreateValuesRel();
5586 boolean isExplain();
5603 int getInSubQueryThreshold();
5609 RelBuilderFactory getRelBuilderFactory();
5615 UnaryOperator<RelBuilder.Config> getRelBuilderConfigTransform();
5621 HintStrategyTable getHintStrategyTable();
5629 BiPredicate<SqlNode, SqlNode> getExpandPredicate();
5635 BiPredicate<SqlNode, Join> getPushdownJoinCondition();
5639 public static class ConfigBuilder {
5640 private boolean decorrelationEnabled =
true;
5641 private boolean trimUnusedFields =
false;
5642 private boolean createValuesRel =
true;
5643 private boolean explain;
5644 private boolean expand =
true;
5645 private int inSubQueryThreshold = DEFAULT_IN_SUB_QUERY_THRESHOLD;
5646 private UnaryOperator<RelBuilder.Config> relBuilderConfigTransform =
5647 c -> c.withPushJoinCondition(
true);
5648 private RelBuilderFactory relBuilderFactory = RelFactories.LOGICAL_BUILDER;
5649 private HintStrategyTable hintStrategyTable = HintStrategyTable.EMPTY;
5651 private BiPredicate<SqlNode, Join> pushdownJoinCondition;
5652 private BiPredicate<SqlNode, SqlNode> expandPredicate;
5655 private ConfigBuilder() {}
5658 public ConfigBuilder withConfig(Config config) {
5659 this.decorrelationEnabled = config.isDecorrelationEnabled();
5660 this.trimUnusedFields = config.isTrimUnusedFields();
5661 this.createValuesRel = config.isCreateValuesRel();
5662 this.explain = config.isExplain();
5663 this.expand = config.isExpand();
5664 this.inSubQueryThreshold = config.getInSubQueryThreshold();
5665 this.relBuilderConfigTransform = config.getRelBuilderConfigTransform();
5666 this.relBuilderFactory = config.getRelBuilderFactory();
5667 this.hintStrategyTable = config.getHintStrategyTable();
5670 if (!(config.getExpandPredicate() instanceof ConfigImpl.DefaultExpandPredicate)) {
5671 this.expandPredicate = config.getExpandPredicate();
5673 this.pushdownJoinCondition = config.getPushdownJoinCondition();
5678 public ConfigBuilder withDecorrelationEnabled(
boolean enabled) {
5679 this.decorrelationEnabled = enabled;
5683 public ConfigBuilder withTrimUnusedFields(
boolean trimUnusedFields) {
5684 this.trimUnusedFields = trimUnusedFields;
5688 public ConfigBuilder withCreateValuesRel(
boolean createValuesRel) {
5689 this.createValuesRel = createValuesRel;
5693 public ConfigBuilder withExplain(
boolean explain) {
5694 this.explain = explain;
5698 public ConfigBuilder withExpand(
boolean expand) {
5699 this.expand = expand;
5703 public ConfigBuilder withPushdownJoinCondition(BiPredicate<SqlNode, Join> pushdown) {
5704 this.pushdownJoinCondition = pushdown;
5708 public ConfigBuilder withExpandPredicate(BiPredicate<SqlNode, SqlNode> predicate) {
5709 this.expandPredicate = predicate;
5714 public ConfigBuilder withPushJoinCondition(
boolean pushJoinCondition) {
5715 return withRelBuilderConfigTransform(Util.andThen(relBuilderConfigTransform,
5716 c -> c.withPushJoinCondition(pushJoinCondition)));
5720 public ConfigBuilder withInSubqueryThreshold(
int inSubQueryThreshold) {
5721 return withInSubQueryThreshold(inSubQueryThreshold);
5724 public ConfigBuilder withInSubQueryThreshold(
int inSubQueryThreshold) {
5725 this.inSubQueryThreshold = inSubQueryThreshold;
5729 public ConfigBuilder withRelBuilderConfigTransform(
5730 UnaryOperator<RelBuilder.Config> relBuilderConfigTransform) {
5731 this.relBuilderConfigTransform = relBuilderConfigTransform;
5735 public ConfigBuilder withRelBuilderFactory(RelBuilderFactory relBuilderFactory) {
5736 this.relBuilderFactory = relBuilderFactory;
5740 public ConfigBuilder withHintStrategyTable(HintStrategyTable hintStrategyTable) {
5741 this.hintStrategyTable = hintStrategyTable;
5746 public Config build() {
5747 return new ConfigImpl(decorrelationEnabled,
5752 pushdownJoinCondition,
5754 inSubQueryThreshold,
5755 relBuilderConfigTransform,
5765 private static class ConfigImpl
implements Config {
5766 private final boolean decorrelationEnabled;
5767 private final boolean trimUnusedFields;
5768 private final boolean createValuesRel;
5769 private final boolean explain;
5770 private final boolean expand;
5771 private final int inSubQueryThreshold;
5772 private final UnaryOperator<RelBuilder.Config> relBuilderConfigTransform;
5773 private final RelBuilderFactory relBuilderFactory;
5774 private final HintStrategyTable hintStrategyTable;
5776 private final BiPredicate<SqlNode, SqlNode> expandPredicate;
5779 private class DefaultExpandPredicate
implements BiPredicate<SqlNode, SqlNode> {
5781 public boolean test(SqlNode
t, SqlNode u) {
5786 private BiPredicate<SqlNode, Join> pushdownJoinCondition =
5787 new BiPredicate<SqlNode, Join>() {
5788 public boolean test(SqlNode
t, Join u) {
5794 private ConfigImpl(
boolean decorrelationEnabled,
5795 boolean trimUnusedFields,
5796 boolean createValuesRel,
5800 BiPredicate<SqlNode, Join> pushdownJoinCondition,
5801 BiPredicate<SqlNode, SqlNode> expandPredicate,
5803 int inSubQueryThreshold,
5804 UnaryOperator<RelBuilder.Config> relBuilderConfigTransform,
5805 RelBuilderFactory relBuilderFactory,
5806 HintStrategyTable hintStrategyTable) {
5807 this.decorrelationEnabled = decorrelationEnabled;
5808 this.trimUnusedFields = trimUnusedFields;
5809 this.createValuesRel = createValuesRel;
5811 this.explain = explain;
5812 this.expand = expand;
5814 this.inSubQueryThreshold = inSubQueryThreshold;
5815 this.relBuilderConfigTransform = relBuilderConfigTransform;
5816 this.relBuilderFactory = relBuilderFactory;
5817 this.hintStrategyTable = hintStrategyTable;
5819 if (null == expandPredicate) {
5820 expandPredicate =
new DefaultExpandPredicate();
5822 this.expandPredicate = expandPredicate;
5824 if (null != pushdownJoinCondition) {
5825 this.pushdownJoinCondition = pushdownJoinCondition;
5832 public boolean equals(Object obj) {
5834 || obj instanceof ConfigImpl
5835 && decorrelationEnabled == ((ConfigImpl) obj).decorrelationEnabled
5836 && trimUnusedFields == ((ConfigImpl) obj).trimUnusedFields
5837 && createValuesRel == ((ConfigImpl) obj).createValuesRel
5838 && explain == ((ConfigImpl) obj).explain
5839 && expand == ((ConfigImpl) obj).expand
5840 && inSubQueryThreshold == ((ConfigImpl) obj).inSubQueryThreshold
5841 && relBuilderFactory == ((ConfigImpl) obj).relBuilderFactory
5842 && hintStrategyTable == ((ConfigImpl) obj).hintStrategyTable;
5846 public int hashCode() {
5847 return Objects.hash(decorrelationEnabled,
5852 inSubQueryThreshold,
5857 public boolean isDecorrelationEnabled() {
5858 return decorrelationEnabled;
5861 public boolean isTrimUnusedFields() {
5862 return trimUnusedFields;
5865 public boolean isCreateValuesRel() {
5866 return createValuesRel;
5869 public boolean isExplain() {
5873 public boolean isExpand() {
5877 public int getInSubQueryThreshold() {
5878 return inSubQueryThreshold;
5881 public UnaryOperator<RelBuilder.Config> getRelBuilderConfigTransform() {
5882 return relBuilderConfigTransform;
5885 public RelBuilderFactory getRelBuilderFactory() {
5886 return relBuilderFactory;
5889 public HintStrategyTable getHintStrategyTable() {
5890 return hintStrategyTable;
5894 public BiPredicate<SqlNode, Join> getPushdownJoinCondition() {
5895 return pushdownJoinCondition;
5898 public BiPredicate<SqlNode, SqlNode> getExpandPredicate() {
5899 return expandPredicate;
RelRoot convertWith(SqlWith with, boolean top)
RelOptTable.ToRelContext createToRelContext(List< RelHint > hints)
static boolean isOrdered(SqlNode query)
Map< SqlNode, RexNode > getMapConvertedNonCorrSubqs()
final SqlNodeToRexConverter exprConverter
SqlQuantifyOperator negate(SqlQuantifyOperator operator)
int getDynamicParamCount()
RexBuilder getRexBuilder()
std::string toString(const ExtArgumentType &sig_type)
void setDynamicParamCountInExplain(int explainParamCount)
static SqlNode pushDownNotForIn(SqlValidatorScope scope, SqlNode sqlNode)
void extraSelectItems(Blackboard bb, SqlSelect select, List< RexNode > exprList, List< String > nameList, Collection< String > aliasList, List< SqlMonotonicity > columnMonotonicityList)
RelNode convertInsert(SqlInsert call)
static boolean isStream(SqlNode query)
static final Logger SQL2REL_LOGGER
final RelBuilder relBuilder
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)
DeferredLookup(Blackboard bb, String originalRelName)
RexNode translateIn(RelOptUtil.Logic logic, RelNode root, final RexNode rex)
RelNode convertCursor(Blackboard bb, SubQuery subQuery)
RelNode convertQueryOrInList(Blackboard bb, SqlNode seek, RelDataType targetRowType)
RexNode castNullLiteralIfNeeded(RexNode node, RelDataType type)
RexNode ensureSqlType(RelDataType type, RexNode node)
RelOptCluster getCluster()
final List< SubQuery > subQueryList
void afterTableFunction(SqlToRelConverter.Blackboard bb, SqlCall call, LogicalTableFunctionScan callRel)
final RelOptCluster cluster
RelNode toRel(final RelOptTable table, final List< RelHint > hints)
SqlToRelConverter(RelOptTable.ViewExpander viewExpander, SqlValidator validator, Prepare.CatalogReader catalogReader, RelOptCluster cluster, SqlRexConvertletTable convertletTable)
void convertValuesImpl(Blackboard bb, SqlCall values, RelDataType targetRowType)
void convertFrom(Blackboard bb, SqlNode from)
final SqlValidatorScope scope
InitializerExpressionFactory getInitializerFactory(SqlValidatorTable validatorTable)
String deriveAlias(final SqlNode node, Collection< String > aliases, final int ordinal)
void setRoot(List< RelNode > inputs)
FILE * create(const std::string &basePath, const int fileId, const size_t pageSize, const size_t numPages)
void setPatternVarRef(boolean isVarRef)
RelNode decorrelate(SqlNode query, RelNode rootRel)
void setRoot(List< RelNode > inputs, RelNode root, boolean hasSystemFields)
final SqlToRelConverter.Config config
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
final Map< CorrelationId, DeferredLookup > mapCorrelToDeferred
RelOptUtil.Exists convertExists(SqlNode seek, RelOptUtil.SubQueryType subQueryType, RelOptUtil.Logic logic, boolean notIn, RelDataType targetDataType)
final SqlOperatorTable opTab
RelNode createSource(RelOptTable targetTable, RelNode source, ModifiableView modifiableView, RelDataType delegateRowType)
RelNode convertRowConstructor(Blackboard bb, SqlCall rowConstructor)
final RexBuilder rexBuilder
RelRoot convertQueryRecursive(SqlNode query, boolean top, RelDataType targetRowType)
String getOriginalRelName()
SqlToRelConverter(RelOptTable.ViewExpander viewExpander, SqlValidator validator, Prepare.CatalogReader catalogReader, RelOptPlanner planner, RexBuilder rexBuilder, SqlRexConvertletTable convertletTable)
final List< SqlDynamicParam > dynamicParamSqlNodes
void setRoot(RelNode root, boolean leaf)
final Map< SqlNode, RexNode > mapConvertedNonCorrSubqs
RexLiteral convertLiteralInValuesList(SqlNode sqlNode, Blackboard bb, RelDataType rowType, int iField)
void convertUnnest(Blackboard bb, SqlCall call, List< String > fieldNames)
final RexCorrelVariable rexCorrel
void distinctify(Blackboard bb, boolean checkForDupExprs)
RelFieldTrimmer newFieldTrimmer()
RelNode createModify(RelOptTable targetTable, RelNode source)
final Prepare.CatalogReader catalogReader
RelNode trimUnusedFields(boolean ordered, RelNode rootRel)
RexNode convertUsing(SqlValidatorNamespace leftNamespace, SqlValidatorNamespace rightNamespace, List< String > nameList)
void convertSelectImpl(final Blackboard bb, SqlSelect select)
List< RelDataTypeField > getSystemFields()
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)
final SqlValidator validator
void replaceSubQueries(final Blackboard bb, final SqlNode expr, RelOptUtil.Logic logic)
final Deque< String > datasetStack
RelNode convertMerge(SqlMerge call)
static< T > T unwrap(Object o, Class< T > clazz)
size_t indexOf(std::vector< T > &vec, T val)
boolean isTrimUnusedFields()
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)
RexFieldAccess getFieldAccess(CorrelationId name)
RelNode convertSetOp(SqlCall call)
SubQueryConverter subQueryConverter
RelNode convertValues(SqlCall values, RelDataType targetRowType)
static final int DEFAULT_IN_SUBQUERY_THRESHOLD
void convertAgg(Blackboard bb, SqlSelect select, List< SqlNode > orderExprList)
int getDynamicParamCountInExplain(boolean increment)
RexNode convertOver(Blackboard bb, SqlNode node)
final void createAggImpl(Blackboard bb, final AggConverter aggConverter, SqlNodeList selectList, SqlNodeList groupList, SqlNode having, List< SqlNode > orderExprList)
boolean isRowConstructor(SqlNode node)
Blackboard createInsertBlackboard(RelOptTable targetTable, RexNode sourceRef, List< String > targetColumnNames)
static boolean containsInOperator(SqlNode node)
boolean canConvertSubQuery()
RelNode convertUpdate(SqlUpdate call)
void convertIdentifier(Blackboard bb, SqlIdentifier id, SqlNodeList extendedColumns, SqlNodeList tableHints)
RelNode convertMultisets(final List< SqlNode > operands, Blackboard bb)
static boolean containsNullLiteral(SqlNodeList valueList)
RelNode decorrelateQuery(RelNode rootRel)
RelDataType getDynamicParamType(int index)
final RelDataTypeFactory typeFactory
void gatherOrderExprs(Blackboard bb, SqlSelect select, SqlNodeList orderList, List< SqlNode > extraOrderExprs, List< RelFieldCollation > collationList)
static final int DEFAULT_IN_SUB_QUERY_THRESHOLD
RexNode convertExtendedExpression(SqlNode node, Blackboard bb)
RexNode convertExpression(SqlNode node)
final HintStrategyTable hintStrategies
void convertMatchRecognize(Blackboard bb, SqlCall call)
void convertWhere(final Blackboard bb, final SqlNode where)
RexNode convertExpression(SqlNode node, Map< String, RexNode > nameToNodeMap)
void setDataset(String datasetName)
Blackboard(SqlValidatorScope scope, Map< String, RexNode > nameToNodeMap, boolean top)
RelNode rewriteAggregateWithGroupId(Blackboard bb, AggregatingSelectScope.Resolved r, AggConverter converter)
final RelOptTable.ViewExpander viewExpander
static SqlNode reg(SqlValidatorScope scope, SqlNode e)
boolean convertNonCorrelatedSubQuery(SubQuery subQuery, Blackboard bb, RelNode converted, boolean isExists)
void findSubQueries(Blackboard bb, SqlNode node, RelOptUtil.Logic logic, boolean registerOnlyScalarSubQueries)
int getInSubqueryThreshold()
Pair< RexNode, Map< String, Integer > > lookupExp(SqlQualified qualified)
boolean isSubQueryNonCorrelated(RelNode subq, Blackboard bb)
boolean enableDecorrelation()
RexNode convertIdentifier(Blackboard bb, SqlIdentifier identifier)
RelNode createJoin(Blackboard bb, RelNode leftRel, RelNode rightRel, RexNode joinCond, JoinRelType joinType)
RexAccessShuttle(RexBuilder builder, RexCorrelVariable rexCorrel)
RelNode convertColumnList(final SqlInsert call, RelNode source)
void convertFrom(Blackboard bb, SqlNode from, List< String > fieldNames)
final Map< String, RexNode > nameToNodeMap
void convertTemporalTable(Blackboard bb, SqlCall call)
static boolean desc(RelFieldCollation.Direction direction)
boolean all(SqlCall call)
Set< RelColumnMapping > getColumnMappings(SqlOperator op)
Blackboard createBlackboard(SqlValidatorScope scope, Map< String, RexNode > nameToNodeMap, boolean top)
RelRoot convertQuery(SqlNode query, final boolean needsValidation, final boolean top)
RelFieldCollation convertOrderItem(SqlSelect select, SqlNode orderItem, List< SqlNode > extraExprs, RelFieldCollation.Direction direction, RelFieldCollation.NullDirection nullDirection)
final Map< RelNode, Map< Integer, Integer > > mapRootRelToFieldProjection
RelNode convertToSingleValueSubq(SqlNode query, RelNode plan)
static JoinRelType convertJoinType(JoinType joinType)
RelCollation requiredCollation(RelNode r)
void setSubQueryConverter(SubQueryConverter converter)
final Map< RelNode, Integer > leaves
RelOptTable getTargetTable(SqlNode call)
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 convertDelete(SqlDelete call)
RexNode visitInputRef(RexInputRef input)
RelNode convertSelect(SqlSelect select, boolean top)