http://git-wip-us.apache.org/repos/asf/kylin/blob/19d5b3de/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java ---------------------------------------------------------------------- diff --git a/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java b/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java index 2c308f5..c199c31 100644 --- a/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java +++ b/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java @@ -1,12 +1,13 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,25 +17,6 @@ */ package org.apache.calcite.sql2rel; -import static org.apache.calcite.sql.SqlUtil.stripAs; -import static org.apache.calcite.util.Static.RESOURCE; - -import java.lang.reflect.Type; -import java.math.BigDecimal; -import java.util.AbstractList; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Deque; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - import org.apache.calcite.avatica.util.Spaces; import org.apache.calcite.linq4j.Ord; import org.apache.calcite.plan.Convention; @@ -106,6 +88,7 @@ import org.apache.calcite.schema.ModifiableTable; import org.apache.calcite.schema.ModifiableView; import org.apache.calcite.schema.Table; import org.apache.calcite.schema.TranslatableTable; +import org.apache.calcite.schema.Wrapper; import org.apache.calcite.sql.JoinConditionType; import org.apache.calcite.sql.JoinType; import org.apache.calcite.sql.SemiJoinType; @@ -125,6 +108,7 @@ import org.apache.calcite.sql.SqlIntervalQualifier; import org.apache.calcite.sql.SqlJoin; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlMatchRecognize; import org.apache.calcite.sql.SqlMerge; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; @@ -161,6 +145,7 @@ import org.apache.calcite.sql.validate.ListScope; import org.apache.calcite.sql.validate.ParameterScope; import org.apache.calcite.sql.validate.SelectScope; import org.apache.calcite.sql.validate.SqlMonotonicity; +import org.apache.calcite.sql.validate.SqlNameMatcher; import org.apache.calcite.sql.validate.SqlQualified; import org.apache.calcite.sql.validate.SqlUserDefinedTableFunction; import org.apache.calcite.sql.validate.SqlUserDefinedTableMacro; @@ -168,6 +153,7 @@ import org.apache.calcite.sql.validate.SqlValidator; import org.apache.calcite.sql.validate.SqlValidatorImpl; import org.apache.calcite.sql.validate.SqlValidatorNamespace; import org.apache.calcite.sql.validate.SqlValidatorScope; +import org.apache.calcite.sql.validate.SqlValidatorTable; import org.apache.calcite.sql.validate.SqlValidatorUtil; import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.util.ImmutableBitSet; @@ -178,7 +164,6 @@ import org.apache.calcite.util.NumberUtil; import org.apache.calcite.util.Pair; import org.apache.calcite.util.Util; import org.apache.calcite.util.trace.CalciteTrace; -import org.slf4j.Logger; import com.google.common.base.Function; import com.google.common.base.Preconditions; @@ -190,6 +175,28 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import org.slf4j.Logger; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.util.AbstractList; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import static org.apache.calcite.sql.SqlUtil.stripAs; +import static org.apache.calcite.util.Static.RESOURCE; + /* * The code has synced with calcite. Hope one day, we could remove the hardcode override point. * OVERRIDE POINT: @@ -211,7 +218,7 @@ public class SqlToRelConverter { //~ Static fields/initializers --------------------------------------------- protected static final Logger SQL2REL_LOGGER = - CalciteTrace.getSqlToRelTracer(); + CalciteTrace.getSqlToRelTracer(); private static final BigDecimal TWO = BigDecimal.valueOf(2L); @@ -222,7 +229,7 @@ public class SqlToRelConverter { @Deprecated // to be removed before 2.0 public static final int DEFAULT_IN_SUBQUERY_THRESHOLD = - DEFAULT_IN_SUB_QUERY_THRESHOLD; + DEFAULT_IN_SUB_QUERY_THRESHOLD; //~ Instance fields -------------------------------------------------------- @@ -230,7 +237,6 @@ public class SqlToRelConverter { protected final RexBuilder rexBuilder; protected final Prepare.CatalogReader catalogReader; protected final RelOptCluster cluster; - private DefaultValueFactory defaultValueFactory; private SubQueryConverter subQueryConverter; protected final List<RelNode> leaves = new ArrayList<>(); private final List<SqlDynamicParam> dynamicParamSqlNodes = new ArrayList<>(); @@ -244,7 +250,7 @@ public class SqlToRelConverter { * Fields used in name resolution for correlated sub-queries. */ private final Map<CorrelationId, DeferredLookup> mapCorrelToDeferred = - new HashMap<>(); + new HashMap<>(); /** * Stack of names of datasets requested by the <code> @@ -258,7 +264,7 @@ public class SqlToRelConverter { * already been evaluated. */ private final Map<SqlNode, RexNode> mapConvertedNonCorrSubqs = - new HashMap<>(); + new HashMap<>(); public final RelOptTable.ViewExpander viewExpander; @@ -275,44 +281,43 @@ public class SqlToRelConverter { */ @Deprecated // to be removed before 2.0 public SqlToRelConverter( - RelOptTable.ViewExpander viewExpander, - SqlValidator validator, - Prepare.CatalogReader catalogReader, - RelOptPlanner planner, - RexBuilder rexBuilder, - SqlRexConvertletTable convertletTable) { + RelOptTable.ViewExpander viewExpander, + SqlValidator validator, + Prepare.CatalogReader catalogReader, + RelOptPlanner planner, + RexBuilder rexBuilder, + SqlRexConvertletTable convertletTable) { this(viewExpander, validator, catalogReader, - RelOptCluster.create(planner, rexBuilder), convertletTable, - Config.DEFAULT); + RelOptCluster.create(planner, rexBuilder), convertletTable, + Config.DEFAULT); } @Deprecated // to be removed before 2.0 public SqlToRelConverter( - RelOptTable.ViewExpander viewExpander, - SqlValidator validator, - Prepare.CatalogReader catalogReader, - RelOptCluster cluster, - SqlRexConvertletTable convertletTable) { + RelOptTable.ViewExpander viewExpander, + SqlValidator validator, + Prepare.CatalogReader catalogReader, + RelOptCluster cluster, + SqlRexConvertletTable convertletTable) { this(viewExpander, validator, catalogReader, cluster, convertletTable, - Config.DEFAULT); + Config.DEFAULT); } /* Creates a converter. */ public SqlToRelConverter( - RelOptTable.ViewExpander viewExpander, - SqlValidator validator, - Prepare.CatalogReader catalogReader, - RelOptCluster cluster, - SqlRexConvertletTable convertletTable, - Config config) { + RelOptTable.ViewExpander viewExpander, + SqlValidator validator, + Prepare.CatalogReader catalogReader, + RelOptCluster cluster, + SqlRexConvertletTable convertletTable, + Config config) { this.viewExpander = viewExpander; this.opTab = - (validator - == null) ? SqlStdOperatorTable.instance() - : validator.getOperatorTable(); + (validator + == null) ? SqlStdOperatorTable.instance() + : validator.getOperatorTable(); this.validator = validator; this.catalogReader = catalogReader; - this.defaultValueFactory = new NullDefaultValueFactory(); this.subQueryConverter = new NoOpSubQueryConverter(); this.rexBuilder = cluster.getRexBuilder(); this.typeFactory = rexBuilder.getTypeFactory(); @@ -393,21 +398,11 @@ public class SqlToRelConverter { * @param alreadyConvertedNonCorrSubqs the other map */ public void addConvertedNonCorrSubqs( - Map<SqlNode, RexNode> alreadyConvertedNonCorrSubqs) { + Map<SqlNode, RexNode> alreadyConvertedNonCorrSubqs) { mapConvertedNonCorrSubqs.putAll(alreadyConvertedNonCorrSubqs); } /** - * Set a new DefaultValueFactory. To have any effect, this must be called - * before any convert method. - * - * @param factory new DefaultValueFactory - */ - public void setDefaultValueFactory(DefaultValueFactory factory) { - defaultValueFactory = factory; - } - - /** * Sets a new SubQueryConverter. To have any effect, this must be called * before any convert method. * @@ -438,36 +433,36 @@ public class SqlToRelConverter { // validator type information associated with its result, // hence the namespace check above.) final List<RelDataTypeField> validatedFields = - validator.getValidatedNodeType(query).getFieldList(); + validator.getValidatedNodeType(query).getFieldList(); final RelDataType validatedRowType = - validator.getTypeFactory().createStructType( - Pair.right(validatedFields), - SqlValidatorUtil.uniquify(Pair.left(validatedFields), - catalogReader.isCaseSensitive())); + validator.getTypeFactory().createStructType( + Pair.right(validatedFields), + SqlValidatorUtil.uniquify(Pair.left(validatedFields), + catalogReader.nameMatcher().isCaseSensitive())); final List<RelDataTypeField> convertedFields = - result.getRowType().getFieldList().subList(0, validatedFields.size()); + result.getRowType().getFieldList().subList(0, validatedFields.size()); final RelDataType convertedRowType = - validator.getTypeFactory().createStructType(convertedFields); + validator.getTypeFactory().createStructType(convertedFields); if (!RelOptUtil.equal("validated row type", validatedRowType, - "converted row type", convertedRowType, Litmus.IGNORE)) { + "converted row type", convertedRowType, Litmus.IGNORE)) { throw new AssertionError("Conversion to relational algebra failed to " - + "preserve datatypes:\n" - + "validated type:\n" - + validatedRowType.getFullTypeString() - + "\nconverted type:\n" - + convertedRowType.getFullTypeString() - + "\nrel:\n" - + RelOptUtil.toString(result)); + + "preserve datatypes:\n" + + "validated type:\n" + + validatedRowType.getFullTypeString() + + "\nconverted type:\n" + + convertedRowType.getFullTypeString() + + "\nrel:\n" + + RelOptUtil.toString(result)); } } public RelNode flattenTypes( - RelNode rootRel, - boolean restructure) { + RelNode rootRel, + boolean restructure) { RelStructuredTypeFlattener typeFlattener = - new RelStructuredTypeFlattener(rexBuilder, createToRelContext(), restructure); + new RelStructuredTypeFlattener(rexBuilder, createToRelContext(), restructure); return typeFlattener.rewrite(rootRel); } @@ -514,20 +509,20 @@ public class SqlToRelConverter { if (isTrimUnusedFields()) { final RelFieldTrimmer trimmer = newFieldTrimmer(); final List<RelCollation> collations = - rootRel.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE); + rootRel.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE); rootRel = trimmer.trim(rootRel); if (!ordered - && collations != null - && !collations.isEmpty() - && !collations.equals(ImmutableList.of(RelCollations.EMPTY))) { + && collations != null + && !collations.isEmpty() + && !collations.equals(ImmutableList.of(RelCollations.EMPTY))) { final RelTraitSet traitSet = rootRel.getTraitSet() - .replace(RelCollationTraitDef.INSTANCE, collations); + .replace(RelCollationTraitDef.INSTANCE, collations); rootRel = rootRel.copy(traitSet, rootRel.getInputs()); } if (SQL2REL_LOGGER.isDebugEnabled()) { SQL2REL_LOGGER.debug( - RelOptUtil.dumpPlan("Plan after trimming unused fields", rootRel, - SqlExplainFormat.TEXT, SqlExplainLevel.EXPPLAN_ATTRIBUTES)); + RelOptUtil.dumpPlan("Plan after trimming unused fields", rootRel, + SqlExplainFormat.TEXT, SqlExplainLevel.EXPPLAN_ATTRIBUTES)); } } return rootRel; @@ -540,7 +535,7 @@ public class SqlToRelConverter { */ protected RelFieldTrimmer newFieldTrimmer() { final RelBuilder relBuilder = - RelFactories.LOGICAL_BUILDER.create(cluster, null); + RelFactories.LOGICAL_BUILDER.create(cluster, null); return new RelFieldTrimmer(validator, relBuilder); } @@ -556,17 +551,18 @@ public class SqlToRelConverter { * the query will be part of a view. */ public RelRoot convertQuery( - SqlNode query, - final boolean needsValidation, - final boolean top) { - SqlNode origQuery = query; /* OVERRIDE POINT */ + SqlNode query, + final boolean needsValidation, + final boolean top) { + SqlNode origQuery = query; /* OVERRIDE POINT */ + if (needsValidation) { query = validator.validate(query); } RelMetadataQuery.THREAD_PROVIDERS.set( - JaninoRelMetadataProvider.of(cluster.getMetadataProvider())); + JaninoRelMetadataProvider.of(cluster.getMetadataProvider())); RelNode result = convertQueryRecursive(query, top, null).rel; if (top) { if (isStream(query)) { @@ -583,27 +579,28 @@ public class SqlToRelConverter { if (SQL2REL_LOGGER.isDebugEnabled()) { SQL2REL_LOGGER.debug( - RelOptUtil.dumpPlan("Plan after converting SqlNode to RelNode", - result, SqlExplainFormat.TEXT, - SqlExplainLevel.EXPPLAN_ATTRIBUTES)); + RelOptUtil.dumpPlan("Plan after converting SqlNode to RelNode", + result, SqlExplainFormat.TEXT, + SqlExplainLevel.EXPPLAN_ATTRIBUTES)); } final RelDataType validatedRowType = validator.getValidatedNodeType(query); - RelRoot origResult = RelRoot.of(result, validatedRowType, query.getKind()) - .withCollation(collation); + RelRoot origResult = RelRoot.of(result, validatedRowType, query.getKind()) + .withCollation(collation); return hackSelectStar(origQuery, origResult); } + /* OVERRIDE POINT */ private RelRoot hackSelectStar(SqlNode query, RelRoot root) { -// /* -// * Rel tree is like: -// * -// * LogicalSort (optional) -// * |- LogicalProject -// * |- LogicalFilter (optional) -// * |- OLAPTableScan or LogicalJoin -// */ + // /* + // * Rel tree is like: + // * + // * LogicalSort (optional) + // * |- LogicalProject + // * |- LogicalFilter (optional) + // * |- OLAPTableScan or LogicalJoin + // */ LogicalProject rootPrj = null; LogicalSort rootSort = null; if (root.rel instanceof LogicalProject) { @@ -614,16 +611,16 @@ public class SqlToRelConverter { } else { return root; } -// + // RelNode input = rootPrj.getInput(); -// if (!(// -// isAmong(input, "OLAPTableScan", "LogicalJoin")// -// || (isAmong(input, "LogicalFilter") && isAmong(input.getInput(0), "OLAPTableScan", "LogicalJoin"))// -// )) -// return root; -// -// if (rootPrj.getRowType().getFieldCount() < input.getRowType().getFieldCount()) -// return root; + // if (!(// + // isAmong(input, "OLAPTableScan", "LogicalJoin")// + // || (isAmong(input, "LogicalFilter") && isAmong(input.getInput(0), "OLAPTableScan", "LogicalJoin"))// + // )) + // return root; + // + // if (rootPrj.getRowType().getFieldCount() < input.getRowType().getFieldCount()) + // return root; RelDataType inType = rootPrj.getRowType(); List<String> inFields = inType.getFieldNames(); @@ -654,25 +651,17 @@ public class SqlToRelConverter { return root; } - private boolean isAmong(RelNode rel, String... names) { - String simpleName = rel.getClass().getSimpleName(); - for (String n : names) { - if (simpleName.equals(n)) - return true; - } - return false; - } private static boolean isStream(SqlNode query) { return query instanceof SqlSelect - && ((SqlSelect) query).isKeywordPresent(SqlSelectKeyword.STREAM); + && ((SqlSelect) query).isKeywordPresent(SqlSelectKeyword.STREAM); } public static boolean isOrdered(SqlNode query) { switch (query.getKind()) { case SELECT: return ((SqlSelect) query).getOrderList() != null - && ((SqlSelect) query).getOrderList().size() > 0; + && ((SqlSelect) query).getOrderList().size() > 0; case WITH: return isOrdered(((SqlWith) query).body); case ORDER_BY: @@ -709,7 +698,7 @@ public class SqlToRelConverter { * Factory method for creating translation workspace. */ protected Blackboard createBlackboard(SqlValidatorScope scope, - Map<String, RexNode> nameToNodeMap, boolean top) { + Map<String, RexNode> nameToNodeMap, boolean top) { return new Blackboard(scope, nameToNodeMap, top); } @@ -718,44 +707,44 @@ public class SqlToRelConverter { * derived class may override. */ protected void convertSelectImpl( - final Blackboard bb, - SqlSelect select) { + final Blackboard bb, + SqlSelect select) { convertFrom( - bb, - select.getFrom()); + bb, + select.getFrom()); convertWhere( - bb, - select.getWhere()); + bb, + select.getWhere()); final List<SqlNode> orderExprList = new ArrayList<>(); final List<RelFieldCollation> collationList = new ArrayList<>(); gatherOrderExprs( - bb, - select, - select.getOrderList(), - orderExprList, - collationList); + bb, + select, + select.getOrderList(), + orderExprList, + collationList); final RelCollation collation = - cluster.traitSet().canonize(RelCollations.of(collationList)); + cluster.traitSet().canonize(RelCollations.of(collationList)); if (validator.isAggregate(select)) { convertAgg( - bb, - select, - orderExprList); + bb, + select, + orderExprList); } else { convertSelectList( - bb, - select, - orderExprList); + bb, + select, + orderExprList); } if (select.isDistinct()) { distinctify(bb, true); } convertOrder( - select, bb, collation, orderExprList, select.getOffset(), - select.getFetch()); + select, bb, collation, orderExprList, select.getOffset(), + select.getFetch()); bb.setRoot(bb.root, true); } @@ -772,8 +761,8 @@ public class SqlToRelConverter { * @param checkForDupExprs Check for duplicate expressions */ private void distinctify( - Blackboard bb, - boolean checkForDupExprs) { + Blackboard bb, + boolean checkForDupExprs) { // Look for duplicate expressions in the project. // Say we have 'select x, y, x, z'. // Then dups will be {[2, 0]} @@ -808,8 +797,8 @@ public class SqlToRelConverter { } } rel = - LogicalProject.create(rel, Pair.left(newProjects), - Pair.right(newProjects)); + LogicalProject.create(rel, Pair.left(newProjects), + Pair.right(newProjects)); bb.root = rel; distinctify(bb, false); rel = bb.root; @@ -821,18 +810,18 @@ public class SqlToRelConverter { final int origin = origins.get(i); RelDataTypeField field = fields.get(i); undoProjects.add( - Pair.of( - (RexNode) new RexInputRef( - squished.get(origin), field.getType()), - field.getName())); + Pair.of( + (RexNode) new RexInputRef( + squished.get(origin), field.getType()), + field.getName())); } rel = - LogicalProject.create(rel, Pair.left(undoProjects), - Pair.right(undoProjects)); + LogicalProject.create(rel, Pair.left(undoProjects), + Pair.right(undoProjects)); bb.setRoot( - rel, - false); + rel, + false); return; } @@ -840,14 +829,14 @@ public class SqlToRelConverter { // Usual case: all of the expressions in the SELECT clause are // different. final ImmutableBitSet groupSet = - ImmutableBitSet.range(rel.getRowType().getFieldCount()); + ImmutableBitSet.range(rel.getRowType().getFieldCount()); rel = - createAggregate(bb, false, groupSet, ImmutableList.of(groupSet), - ImmutableList.<AggregateCall>of()); + createAggregate(bb, false, groupSet, ImmutableList.of(groupSet), + ImmutableList.<AggregateCall>of()); bb.setRoot( - rel, - false); + rel, + false); } private int findExpr(RexNode seek, List<RexNode> exprs, int count) { @@ -873,28 +862,28 @@ public class SqlToRelConverter { * @param fetch Expression for number of rows to fetch */ protected void convertOrder( - SqlSelect select, - Blackboard bb, - RelCollation collation, - List<SqlNode> orderExprList, - SqlNode offset, - SqlNode fetch) { + SqlSelect select, + Blackboard bb, + RelCollation collation, + List<SqlNode> orderExprList, + SqlNode offset, + SqlNode fetch) { if (select.getOrderList() == null - || select.getOrderList().getList().isEmpty()) { + || select.getOrderList().getList().isEmpty()) { assert collation.getFieldCollations().isEmpty(); if ((offset == null - || ((SqlLiteral) offset).bigDecimalValue().equals(BigDecimal.ZERO)) - && fetch == null) { + || ((SqlLiteral) offset).bigDecimalValue().equals(BigDecimal.ZERO)) + && fetch == null) { return; } } // Create a sorter using the previously constructed collations. bb.setRoot( - LogicalSort.create(bb.root, collation, - offset == null ? null : convertExpression(offset), - fetch == null ? null : convertExpression(fetch)), - false); + LogicalSort.create(bb.root, collation, + offset == null ? null : convertExpression(offset), + fetch == null ? null : convertExpression(fetch)), + false); // If extra expressions were added to the project list for sorting, // add another project to remove them. But make the collation empty, because @@ -905,14 +894,14 @@ public class SqlToRelConverter { final List<RexNode> exprs = new ArrayList<>(); final RelDataType rowType = bb.root.getRowType(); final int fieldCount = - rowType.getFieldCount() - orderExprList.size(); + rowType.getFieldCount() - orderExprList.size(); for (int i = 0; i < fieldCount; i++) { exprs.add(rexBuilder.makeInputRef(bb.root, i)); } bb.setRoot( - LogicalProject.create(bb.root, exprs, - rowType.getFieldNames().subList(0, fieldCount)), - false); + LogicalProject.create(bb.root, exprs, + rowType.getFieldNames().subList(0, fieldCount)), + false); } } @@ -922,17 +911,17 @@ public class SqlToRelConverter { * @param node a RexNode tree */ private static boolean containsInOperator( - SqlNode node) { + SqlNode node) { try { SqlVisitor<Void> visitor = - new SqlBasicVisitor<Void>() { - public Void visit(SqlCall call) { - if (call.getOperator() instanceof SqlInOperator) { - throw new Util.FoundOne(call); - } - return super.visit(call); + new SqlBasicVisitor<Void>() { + public Void visit(SqlCall call) { + if (call.getOperator() instanceof SqlInOperator) { + throw new Util.FoundOne(call); } - }; + return super.visit(call); + } + }; node.accept(visitor); return false; } catch (Util.FoundOne e) { @@ -949,11 +938,11 @@ public class SqlToRelConverter { * @return the transformed SqlNode representation with NOT pushed down. */ private static SqlNode pushDownNotForIn(SqlValidatorScope scope, - SqlNode sqlNode) { + SqlNode sqlNode) { if ((sqlNode instanceof SqlCall) && containsInOperator(sqlNode)) { SqlCall sqlCall = (SqlCall) sqlNode; if ((sqlCall.getOperator() == SqlStdOperatorTable.AND) - || (sqlCall.getOperator() == SqlStdOperatorTable.OR)) { + || (sqlCall.getOperator() == SqlStdOperatorTable.OR)) { SqlNode[] sqlOperands = ((SqlBasicCall) sqlCall).operands; for (int i = 0; i < sqlOperands.length; i++) { sqlOperands[i] = pushDownNotForIn(scope, sqlOperands[i]); @@ -967,22 +956,30 @@ public class SqlToRelConverter { SqlNode[] andOperands = childSqlCall.getOperands(); SqlNode[] orOperands = new SqlNode[andOperands.length]; for (int i = 0; i < orOperands.length; i++) { - orOperands[i] = reg(scope, SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, andOperands[i])); + orOperands[i] = reg(scope, + SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, + andOperands[i])); } for (int i = 0; i < orOperands.length; i++) { orOperands[i] = pushDownNotForIn(scope, orOperands[i]); } - return reg(scope, SqlStdOperatorTable.OR.createCall(SqlParserPos.ZERO, orOperands[0], orOperands[1])); + return reg(scope, + SqlStdOperatorTable.OR.createCall(SqlParserPos.ZERO, + orOperands[0], orOperands[1])); } else if (childSqlCall.getOperator() == SqlStdOperatorTable.OR) { SqlNode[] orOperands = childSqlCall.getOperands(); SqlNode[] andOperands = new SqlNode[orOperands.length]; for (int i = 0; i < andOperands.length; i++) { - andOperands[i] = reg(scope, SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, orOperands[i])); + andOperands[i] = reg(scope, + SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, + orOperands[i])); } for (int i = 0; i < andOperands.length; i++) { andOperands[i] = pushDownNotForIn(scope, andOperands[i]); } - return reg(scope, SqlStdOperatorTable.AND.createCall(SqlParserPos.ZERO, andOperands[0], andOperands[1])); + return reg(scope, + SqlStdOperatorTable.AND.createCall(SqlParserPos.ZERO, + andOperands[0], andOperands[1])); } else if (childSqlCall.getOperator() == SqlStdOperatorTable.NOT) { SqlNode[] notOperands = childSqlCall.getOperands(); assert notOperands.length == 1; @@ -990,11 +987,15 @@ public class SqlToRelConverter { } else if (childSqlCall.getOperator() instanceof SqlInOperator) { SqlNode[] inOperands = childSqlCall.getOperands(); SqlInOperator inOp = - (SqlInOperator) childSqlCall.getOperator(); + (SqlInOperator) childSqlCall.getOperator(); if (inOp.isNotIn()) { - return reg(scope, SqlStdOperatorTable.IN.createCall(SqlParserPos.ZERO, inOperands[0], inOperands[1])); + return reg(scope, + SqlStdOperatorTable.IN.createCall(SqlParserPos.ZERO, + inOperands[0], inOperands[1])); } else { - return reg(scope, SqlStdOperatorTable.NOT_IN.createCall(SqlParserPos.ZERO, inOperands[0], inOperands[1])); + return reg(scope, + SqlStdOperatorTable.NOT_IN.createCall(SqlParserPos.ZERO, + inOperands[0], inOperands[1])); } } else { // childSqlCall is "leaf" node in a logical expression tree @@ -1013,7 +1014,7 @@ public class SqlToRelConverter { } /** Registers with the validator a {@link SqlNode} that has been created - * during the Sql-to-Rel process. */ + * during the Sql-to-Rel process. */ private static SqlNode reg(SqlValidatorScope scope, SqlNode e) { scope.getValidator().deriveType(scope, e); return e; @@ -1026,8 +1027,8 @@ public class SqlToRelConverter { * @param where WHERE clause, may be null */ private void convertWhere( - final Blackboard bb, - final SqlNode where) { + final Blackboard bb, + final SqlNode where) { if (where == null) { return; } @@ -1041,7 +1042,7 @@ public class SqlToRelConverter { } final RelFactories.FilterFactory factory = - RelFactories.DEFAULT_FILTER_FACTORY; + RelFactories.DEFAULT_FILTER_FACTORY; final RelNode filter = factory.createFilter(bb.root, convertedWhere); final RelNode r; final CorrelationUse p = getCorrelationUse(bb, filter); @@ -1049,7 +1050,7 @@ public class SqlToRelConverter { assert p.r instanceof Filter; Filter f = (Filter) p.r; r = LogicalFilter.create(f.getInput(), f.getCondition(), - ImmutableSet.of(p.id)); + ImmutableSet.of(p.id)); } else { r = filter; } @@ -1058,9 +1059,9 @@ public class SqlToRelConverter { } private void replaceSubQueries( - final Blackboard bb, - final SqlNode expr, - RelOptUtil.Logic logic) { + final Blackboard bb, + final SqlNode expr, + RelOptUtil.Logic logic) { findSubQueries(bb, expr, logic, false); for (SubQuery node : bb.subQueryList) { substituteSubQuery(bb, node); @@ -1114,14 +1115,14 @@ public class SqlToRelConverter { if (query instanceof SqlNodeList) { SqlNodeList valueList = (SqlNodeList) query; if (!containsNullLiteral(valueList) - && valueList.size() < config.getInSubQueryThreshold()) { + && valueList.size() < config.getInSubQueryThreshold()) { // We're under the threshold, so convert to OR. subQuery.expr = - convertInToOr( - bb, - leftKeys, - valueList, - notIn); + convertInToOr( + bb, + leftKeys, + valueList, + notIn); return; } @@ -1153,36 +1154,36 @@ public class SqlToRelConverter { // and q.indicator <> TRUE" // final RelDataType targetRowType = - SqlTypeUtil.promoteToRowType(typeFactory, - validator.getValidatedNodeType(leftKeyNode), null); + SqlTypeUtil.promoteToRowType(typeFactory, + validator.getValidatedNodeType(leftKeyNode), null); converted = - convertExists(query, RelOptUtil.SubQueryType.IN, subQuery.logic, - notIn, targetRowType); + convertExists(query, RelOptUtil.SubQueryType.IN, subQuery.logic, + notIn, targetRowType); if (converted.indicator) { // Generate // emp CROSS JOIN (SELECT COUNT(*) AS c, // COUNT(deptno) AS ck FROM dept) final RelDataType longType = - typeFactory.createSqlType(SqlTypeName.BIGINT); + typeFactory.createSqlType(SqlTypeName.BIGINT); final RelNode seek = converted.r.getInput(0); // fragile final int keyCount = leftKeys.size(); final List<Integer> args = ImmutableIntList.range(0, keyCount); LogicalAggregate aggregate = - LogicalAggregate.create(seek, false, ImmutableBitSet.of(), null, - ImmutableList.of( - AggregateCall.create(SqlStdOperatorTable.COUNT, false, - ImmutableList.<Integer>of(), -1, longType, null), - AggregateCall.create(SqlStdOperatorTable.COUNT, false, - args, -1, longType, null))); + LogicalAggregate.create(seek, false, ImmutableBitSet.of(), null, + ImmutableList.of( + AggregateCall.create(SqlStdOperatorTable.COUNT, false, + ImmutableList.<Integer>of(), -1, longType, null), + AggregateCall.create(SqlStdOperatorTable.COUNT, false, + args, -1, longType, null))); LogicalJoin join = - LogicalJoin.create(bb.root, aggregate, rexBuilder.makeLiteral(true), - ImmutableSet.<CorrelationId>of(), JoinRelType.INNER); + LogicalJoin.create(bb.root, aggregate, rexBuilder.makeLiteral(true), + ImmutableSet.<CorrelationId>of(), JoinRelType.INNER); bb.setRoot(join, false); } final RexNode rex = - bb.register(converted.r, - converted.outerJoin ? JoinRelType.LEFT : JoinRelType.INNER, - leftKeys); + bb.register(converted.r, + converted.outerJoin ? JoinRelType.LEFT : JoinRelType.INNER, + leftKeys); RelOptUtil.Logic logic = subQuery.logic; switch (logic) { @@ -1195,7 +1196,7 @@ public class SqlToRelConverter { subQuery.expr = translateIn(logic, bb.root, rex); if (notIn) { subQuery.expr = - rexBuilder.makeCall(SqlStdOperatorTable.NOT, subQuery.expr); + rexBuilder.makeCall(SqlStdOperatorTable.NOT, subQuery.expr); } return; @@ -1215,7 +1216,7 @@ public class SqlToRelConverter { return; } converted = convertExists(query, RelOptUtil.SubQueryType.EXISTS, - subQuery.logic, true, null); + subQuery.logic, true, null); assert !converted.indicator; if (convertNonCorrelatedSubQuery(subQuery, bb, converted.r, true)) { return; @@ -1232,7 +1233,7 @@ public class SqlToRelConverter { call = (SqlBasicCall) subQuery.node; query = call.operand(0); converted = convertExists(query, RelOptUtil.SubQueryType.SCALAR, - subQuery.logic, true, null); + subQuery.logic, true, null); assert !converted.indicator; if (convertNonCorrelatedSubQuery(subQuery, bb, converted.r, false)) { return; @@ -1247,18 +1248,19 @@ public class SqlToRelConverter { // select * from unnest(select multiset[deptno] from emps); // converted = convertExists(subQuery.node, RelOptUtil.SubQueryType.SCALAR, - subQuery.logic, true, null); + subQuery.logic, true, null); assert !converted.indicator; subQuery.expr = bb.register(converted.r, JoinRelType.LEFT); return; default: - throw Util.newInternal("unexpected kind of sub-query :" + subQuery.node); + throw new AssertionError("unexpected kind of sub-query: " + + subQuery.node); } } private RexNode translateIn(RelOptUtil.Logic logic, RelNode root, - final RexNode rex) { + final RexNode rex) { switch (logic) { case TRUE: return rexBuilder.makeLiteral(true); @@ -1281,12 +1283,12 @@ public class SqlToRelConverter { final int k = (fieldCount - 1) / 2; for (int i = 0; i < k; i++) { rexNode = + rexBuilder.makeCall( + SqlStdOperatorTable.AND, + rexNode, rexBuilder.makeCall( - SqlStdOperatorTable.AND, - rexNode, - rexBuilder.makeCall( - SqlStdOperatorTable.IS_NOT_NULL, - rexBuilder.makeFieldAccess(rex, i))); + SqlStdOperatorTable.IS_NOT_NULL, + rexBuilder.makeFieldAccess(rex, i))); } return rexNode; @@ -1309,33 +1311,33 @@ public class SqlToRelConverter { final RelNode leftLeft = ((Join) left.getInput()).getLeft(); final int leftLeftCount = leftLeft.getRowType().getFieldCount(); final RelDataType longType = - typeFactory.createSqlType(SqlTypeName.BIGINT); + typeFactory.createSqlType(SqlTypeName.BIGINT); final RexNode cRef = rexBuilder.makeInputRef(root, leftLeftCount); final RexNode ckRef = rexBuilder.makeInputRef(root, leftLeftCount + 1); final RexNode iRef = - rexBuilder.makeInputRef(root, root.getRowType().getFieldCount() - 1); + rexBuilder.makeInputRef(root, root.getRowType().getFieldCount() - 1); final RexLiteral zero = - rexBuilder.makeExactLiteral(BigDecimal.ZERO, longType); + rexBuilder.makeExactLiteral(BigDecimal.ZERO, longType); final RexLiteral trueLiteral = rexBuilder.makeLiteral(true); final RexLiteral falseLiteral = rexBuilder.makeLiteral(false); final RexNode unknownLiteral = - rexBuilder.makeNullLiteral(SqlTypeName.BOOLEAN); + rexBuilder.makeNullLiteral(trueLiteral.getType()); final ImmutableList.Builder<RexNode> args = ImmutableList.builder(); args.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, cRef, zero), - falseLiteral, - rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, iRef), - trueLiteral); + falseLiteral, + rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, iRef), + trueLiteral); final JoinInfo joinInfo = join.analyzeCondition(); for (int leftKey : joinInfo.leftKeys) { final RexNode kRef = rexBuilder.makeInputRef(root, leftKey); args.add(rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, kRef), - unknownLiteral); + unknownLiteral); } args.add(rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, ckRef, cRef), - unknownLiteral, - falseLiteral); + unknownLiteral, + falseLiteral); return rexBuilder.makeCall(SqlStdOperatorTable.CASE, args.build()); @@ -1367,24 +1369,24 @@ public class SqlToRelConverter { * @return Whether the sub-query can be converted to a constant */ private boolean convertNonCorrelatedSubQuery( - SubQuery subQuery, - Blackboard bb, - RelNode converted, - boolean isExists) { + SubQuery subQuery, + Blackboard bb, + RelNode converted, + boolean isExists) { SqlCall call = (SqlBasicCall) subQuery.node; if (subQueryConverter.canConvertSubQuery() - && isSubQueryNonCorrelated(converted, bb)) { + && isSubQueryNonCorrelated(converted, bb)) { // First check if the sub-query has already been converted // because it's a nested sub-query. If so, don't re-evaluate // it again. RexNode constExpr = mapConvertedNonCorrSubqs.get(call); if (constExpr == null) { constExpr = - subQueryConverter.convertSubQuery( - call, - this, - isExists, - config.isExplain()); + subQueryConverter.convertSubQuery( + call, + this, + isExists, + config.isExplain()); } if (constExpr != null) { subQuery.expr = constExpr; @@ -1404,8 +1406,8 @@ public class SqlToRelConverter { * @return the converted RelNode tree */ public RelNode convertToSingleValueSubq( - SqlNode query, - RelNode plan) { + SqlNode query, + RelNode plan) { // Check whether query is guaranteed to produce a single value. if (query instanceof SqlSelect) { SqlSelect select = (SqlSelect) query; @@ -1413,7 +1415,7 @@ public class SqlToRelConverter { SqlNodeList groupList = select.getGroup(); if ((selectList.size() == 1) - && ((groupList == null) || (groupList.size() == 0))) { + && ((groupList == null) || (groupList.size() == 0))) { SqlNode selectExpr = selectList.get(0); if (selectExpr instanceof SqlCall) { SqlCall selectExprCall = (SqlCall) selectExpr; @@ -1425,7 +1427,7 @@ public class SqlToRelConverter { // If there is a limit with 0 or 1, // it is ensured to produce a single value if (select.getFetch() != null - && select.getFetch() instanceof SqlNumericLiteral) { + && select.getFetch() instanceof SqlNumericLiteral) { SqlNumericLiteral limitNum = (SqlNumericLiteral) select.getFetch(); if (((BigDecimal) limitNum.getValue()).intValue() < 2) { return plan; @@ -1438,16 +1440,16 @@ public class SqlToRelConverter { // whether SingleValueAgg is necessary SqlCall exprCall = (SqlCall) query; if (exprCall.getOperator() - instanceof SqlValuesOperator - && Util.isSingleValue(exprCall)) { + instanceof SqlValuesOperator + && Util.isSingleValue(exprCall)) { return plan; } } // If not, project SingleValueAgg return RelOptUtil.createSingleValueAggRel( - cluster, - plan); + cluster, + plan); } /** @@ -1459,51 +1461,51 @@ public class SqlToRelConverter { * @return converted expression */ private RexNode convertInToOr( - final Blackboard bb, - final List<RexNode> leftKeys, - SqlNodeList valuesList, - boolean isNotIn) { + final Blackboard bb, + final List<RexNode> leftKeys, + SqlNodeList valuesList, + boolean isNotIn) { final List<RexNode> comparisons = new ArrayList<>(); for (SqlNode rightVals : valuesList) { RexNode rexComparison; if (leftKeys.size() == 1) { rexComparison = - rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, - leftKeys.get(0), - ensureSqlType(leftKeys.get(0).getType(), - bb.convertExpression(rightVals))); + rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, + leftKeys.get(0), + ensureSqlType(leftKeys.get(0).getType(), + bb.convertExpression(rightVals))); } else { assert rightVals instanceof SqlCall; final SqlBasicCall call = (SqlBasicCall) rightVals; assert (call.getOperator() instanceof SqlRowOperator) - && call.operandCount() == leftKeys.size(); + && call.operandCount() == leftKeys.size(); rexComparison = - RexUtil.composeConjunction( - rexBuilder, - Iterables.transform( - Pair.zip(leftKeys, call.getOperandList()), - new Function<Pair<RexNode, SqlNode>, RexNode>() { - public RexNode apply(Pair<RexNode, SqlNode> pair) { - return rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, - pair.left, - ensureSqlType(pair.left.getType(), - bb.convertExpression(pair.right))); - } - }), - false); + RexUtil.composeConjunction( + rexBuilder, + Iterables.transform( + Pair.zip(leftKeys, call.getOperandList()), + new Function<Pair<RexNode, SqlNode>, RexNode>() { + public RexNode apply(Pair<RexNode, SqlNode> pair) { + return rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, + pair.left, + ensureSqlType(pair.left.getType(), + bb.convertExpression(pair.right))); + } + }), + false); } comparisons.add(rexComparison); } RexNode result = - RexUtil.composeDisjunction(rexBuilder, comparisons, true); + RexUtil.composeDisjunction(rexBuilder, comparisons, true); assert result != null; if (isNotIn) { result = - rexBuilder.makeCall( - SqlStdOperatorTable.NOT, - result); + rexBuilder.makeCall( + SqlStdOperatorTable.NOT, + result); } return result; @@ -1514,8 +1516,8 @@ public class SqlToRelConverter { * returns the expression unchanged. */ private RexNode ensureSqlType(RelDataType type, RexNode node) { if (type.getSqlTypeName() == node.getType().getSqlTypeName() - || (type.getSqlTypeName() == SqlTypeName.VARCHAR - && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) { + || (type.getSqlTypeName() == SqlTypeName.VARCHAR + && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) { return node; } return rexBuilder.ensureType(type, node, true); @@ -1551,18 +1553,17 @@ public class SqlToRelConverter { * approximation (say representing UNKNOWN as FALSE) * @param notIn Whether the operation is NOT IN * @return join expression - * @pre extraExpr == null || extraName != null */ private RelOptUtil.Exists convertExists( - SqlNode seek, - RelOptUtil.SubQueryType subQueryType, - RelOptUtil.Logic logic, - boolean notIn, - RelDataType targetDataType) { + SqlNode seek, + RelOptUtil.SubQueryType subQueryType, + RelOptUtil.Logic logic, + boolean notIn, + RelDataType targetDataType) { final SqlValidatorScope seekScope = - (seek instanceof SqlSelect) - ? validator.getSelectScope((SqlSelect) seek) - : null; + (seek instanceof SqlSelect) + ? validator.getSelectScope((SqlSelect) seek) + : null; final Blackboard seekBb = createBlackboard(seekScope, null, false); RelNode seekRel = convertQueryOrInList(seekBb, seek, targetDataType); @@ -1570,9 +1571,9 @@ public class SqlToRelConverter { } private RelNode convertQueryOrInList( - Blackboard bb, - SqlNode seek, - RelDataType targetRowType) { + Blackboard bb, + SqlNode seek, + RelDataType targetRowType) { // NOTE: Once we start accepting single-row queries as row constructors, // there will be an ambiguity here for a case like X IN ((SELECT Y FROM // Z)). The SQL standard resolves the ambiguity by saying that a lone @@ -1581,22 +1582,22 @@ public class SqlToRelConverter { // return multiple rows. if (seek instanceof SqlNodeList) { return convertRowValues( - bb, - seek, - ((SqlNodeList) seek).getList(), - false, - targetRowType); + bb, + seek, + ((SqlNodeList) seek).getList(), + false, + targetRowType); } else { return convertQueryRecursive(seek, false, null).project(); } } private RelNode convertRowValues( - Blackboard bb, - SqlNode rowList, - Collection<SqlNode> rows, - boolean allowLiteralsOnly, - RelDataType targetRowType) { + Blackboard bb, + SqlNode rowList, + Collection<SqlNode> rows, + boolean allowLiteralsOnly, + RelDataType targetRowType) { // NOTE jvs 30-Apr-2006: We combine all rows consisting entirely of // literals into a single LogicalValues; this gives the optimizer a smaller // input tree. For everything else (computed expressions, row @@ -1604,16 +1605,16 @@ public class SqlToRelConverter { // LogicalOneRow. final ImmutableList.Builder<ImmutableList<RexLiteral>> tupleList = - ImmutableList.builder(); + ImmutableList.builder(); final RelDataType rowType; if (targetRowType != null) { rowType = targetRowType; } else { rowType = - SqlTypeUtil.promoteToRowType( - typeFactory, - validator.getValidatedNodeType(rowList), - null); + SqlTypeUtil.promoteToRowType( + typeFactory, + validator.getValidatedNodeType(rowList), + null); } final List<RelNode> unionInputs = new ArrayList<>(); @@ -1624,11 +1625,11 @@ public class SqlToRelConverter { ImmutableList.Builder<RexLiteral> tuple = ImmutableList.builder(); for (Ord<SqlNode> operand : Ord.zip(call.operands)) { RexLiteral rexLiteral = - convertLiteralInValuesList( - operand.e, - bb, - rowType, - operand.i); + convertLiteralInValuesList( + operand.e, + bb, + rowType, + operand.i); if ((rexLiteral == null) && allowLiteralsOnly) { return null; } @@ -1645,11 +1646,11 @@ public class SqlToRelConverter { } } else { RexLiteral rexLiteral = - convertLiteralInValuesList( - node, - bb, - rowType, - 0); + convertLiteralInValuesList( + node, + bb, + rowType, + 0); if ((rexLiteral != null) && config.isCreateValuesRel()) { tupleList.add(ImmutableList.of(rexLiteral)); continue; @@ -1661,14 +1662,14 @@ public class SqlToRelConverter { // convert "1" to "row(1)" call = - (SqlBasicCall) SqlStdOperatorTable.ROW.createCall( - SqlParserPos.ZERO, - node); + (SqlBasicCall) SqlStdOperatorTable.ROW.createCall( + SqlParserPos.ZERO, + node); } unionInputs.add(convertRowConstructor(bb, call)); } LogicalValues values = - LogicalValues.create(cluster, rowType, tupleList.build()); + LogicalValues.create(cluster, rowType, tupleList.build()); RelNode resultRel; if (unionInputs.isEmpty()) { resultRel = values; @@ -1683,10 +1684,10 @@ public class SqlToRelConverter { } private RexLiteral convertLiteralInValuesList( - SqlNode sqlNode, - Blackboard bb, - RelDataType rowType, - int iField) { + SqlNode sqlNode, + Blackboard bb, + RelDataType rowType, + int iField) { if (!(sqlNode instanceof SqlLiteral)) { return null; } @@ -1700,9 +1701,9 @@ public class SqlToRelConverter { } RexNode literalExpr = - exprConverter.convertLiteral( - bb, - (SqlLiteral) sqlNode); + exprConverter.convertLiteral( + bb, + (SqlLiteral) sqlNode); if (!(literalExpr instanceof RexLiteral)) { assert literalExpr.isA(SqlKind.CAST); @@ -1720,23 +1721,23 @@ public class SqlToRelConverter { if (SqlTypeUtil.isExactNumeric(type) && SqlTypeUtil.hasScale(type)) { BigDecimal roundedValue = - NumberUtil.rescaleBigDecimal( - (BigDecimal) value, - type.getScale()); + NumberUtil.rescaleBigDecimal( + (BigDecimal) value, + type.getScale()); return rexBuilder.makeExactLiteral( - roundedValue, - type); + roundedValue, + type); } if ((value instanceof NlsString) - && (type.getSqlTypeName() == SqlTypeName.CHAR)) { + && (type.getSqlTypeName() == SqlTypeName.CHAR)) { // pad fixed character type NlsString unpadded = (NlsString) value; return rexBuilder.makeCharLiteral( - new NlsString( - Spaces.padRight(unpadded.getValue(), type.getPrecision()), - unpadded.getCharsetName(), - unpadded.getCollation())); + new NlsString( + Spaces.padRight(unpadded.getValue(), type.getPrecision()), + unpadded.getCharsetName(), + unpadded.getCollation())); } return literal; } @@ -1764,10 +1765,10 @@ public class SqlToRelConverter { * sub-query */ private void findSubQueries( - Blackboard bb, - SqlNode node, - RelOptUtil.Logic logic, - boolean registerOnlyScalarSubQueries) { + Blackboard bb, + SqlNode node, + RelOptUtil.Logic logic, + boolean registerOnlyScalarSubQueries) { final SqlKind kind = node.getKind(); switch (kind) { case EXISTS: @@ -1778,7 +1779,7 @@ public class SqlToRelConverter { case CURSOR: case SCALAR_QUERY: if (!registerOnlyScalarSubQueries - || (kind == SqlKind.SCALAR_QUERY)) { + || (kind == SqlKind.SCALAR_QUERY)) { bb.registerSubQuery(node, RelOptUtil.Logic.TRUE_FALSE); } return; @@ -1797,19 +1798,19 @@ public class SqlToRelConverter { // In the case of an IN expression, locate scalar // sub-queries so we can convert them to constants findSubQueries( - bb, - operand, - logic, - kind == SqlKind.IN || registerOnlyScalarSubQueries); + bb, + operand, + logic, + kind == SqlKind.IN || registerOnlyScalarSubQueries); } } } else if (node instanceof SqlNodeList) { for (SqlNode child : (SqlNodeList) node) { findSubQueries( - bb, - child, - logic, - kind == SqlKind.IN || registerOnlyScalarSubQueries); + bb, + child, + logic, + kind == SqlKind.IN || registerOnlyScalarSubQueries); } } @@ -1840,10 +1841,10 @@ public class SqlToRelConverter { * @return Converted expression */ public RexNode convertExpression( - SqlNode node) { + SqlNode node) { Map<String, RelDataType> nameToTypeMap = Collections.emptyMap(); final ParameterScope scope = - new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap); + new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap); final Blackboard bb = createBlackboard(scope, null, false); return bb.convertExpression(node); } @@ -1860,14 +1861,14 @@ public class SqlToRelConverter { * @return Converted expression */ public RexNode convertExpression( - SqlNode node, - Map<String, RexNode> nameToNodeMap) { + SqlNode node, + Map<String, RexNode> nameToNodeMap) { final Map<String, RelDataType> nameToTypeMap = new HashMap<>(); for (Map.Entry<String, RexNode> entry : nameToNodeMap.entrySet()) { nameToTypeMap.put(entry.getKey(), entry.getValue().getType()); } final ParameterScope scope = - new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap); + new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap); final Blackboard bb = createBlackboard(scope, nameToNodeMap, false); return bb.convertExpression(node); } @@ -1884,8 +1885,8 @@ public class SqlToRelConverter { * @return null to proceed with the usual expression translation process */ protected RexNode convertExtendedExpression( - SqlNode node, - Blackboard bb) { + SqlNode node, + Blackboard bb) { return null; } @@ -1894,7 +1895,7 @@ public class SqlToRelConverter { SqlCall aggCall = call.operand(0); SqlNode windowOrRef = call.operand(1); final SqlWindow window = - validator.resolveWindow(windowOrRef, bb.scope, true); + validator.resolveWindow(windowOrRef, bb.scope, true); // ROW_NUMBER() expects specific kind of framing. if (aggCall.getKind() == SqlKind.ROW_NUMBER) { @@ -1904,7 +1905,7 @@ public class SqlToRelConverter { } final SqlNodeList partitionList = window.getPartitionList(); final ImmutableList.Builder<RexNode> partitionKeys = - ImmutableList.builder(); + ImmutableList.builder(); for (SqlNode partition : partitionList) { partitionKeys.add(bb.convertExpression(partition)); } @@ -1918,11 +1919,11 @@ public class SqlToRelConverter { orderList = bb.scope.getOrderList(); if (orderList == null) { throw new AssertionError( - "Relation should have sort key for implicit ORDER BY"); + "Relation should have sort key for implicit ORDER BY"); } } final ImmutableList.Builder<RexFieldCollation> orderKeys = - ImmutableList.builder(); + ImmutableList.builder(); final Set<SqlKind> flags = EnumSet.noneOf(SqlKind.class); for (SqlNode order : orderList) { flags.clear(); @@ -1930,22 +1931,23 @@ public class SqlToRelConverter { orderKeys.add(new RexFieldCollation(e, flags)); } try { - Util.permAssert(bb.window == null, "already in window agg mode"); + Preconditions.checkArgument(bb.window == null, + "already in window agg mode"); bb.window = window; RexNode rexAgg = exprConverter.convertCall(bb, aggCall); rexAgg = - rexBuilder.ensureType( - validator.getValidatedNodeType(call), rexAgg, false); + rexBuilder.ensureType( + validator.getValidatedNodeType(call), rexAgg, false); // Walk over the tree and apply 'over' to all agg functions. This is // necessary because the returned expression is not necessarily a call // to an agg function. For example, AVG(x) becomes SUM(x) / COUNT(x). final RexShuttle visitor = - new HistogramShuttle( - partitionKeys.build(), orderKeys.build(), - RexWindowBound.create(window.getLowerBound(), lowerBound), - RexWindowBound.create(window.getUpperBound(), upperBound), - window); + new HistogramShuttle( + partitionKeys.build(), orderKeys.build(), + RexWindowBound.create(window.getLowerBound(), lowerBound), + RexWindowBound.create(window.getUpperBound(), upperBound), + window); return rexAgg.accept(visitor); } finally { bb.window = null; @@ -1970,8 +1972,8 @@ public class SqlToRelConverter { * </ul> */ protected void convertFrom( - Blackboard bb, - SqlNode from) { + Blackboard bb, + SqlNode from) { if (from == null) { bb.setRoot(LogicalValues.createOneRow(cluster), false); return; @@ -1980,6 +1982,10 @@ public class SqlToRelConverter { final SqlCall call; final SqlNode[] operands; switch (from.getKind()) { + case MATCH_RECOGNIZE: + convertMatchRecognize(bb, (SqlCall) from); + return; + case AS: convertFrom(bb, ((SqlCall) from).operand(0)); return; @@ -1997,54 +2003,36 @@ public class SqlToRelConverter { SqlSampleSpec sampleSpec = SqlLiteral.sampleValue(operands[1]); if (sampleSpec instanceof SqlSampleSpec.SqlSubstitutionSampleSpec) { String sampleName = - ((SqlSampleSpec.SqlSubstitutionSampleSpec) sampleSpec) - .getName(); + ((SqlSampleSpec.SqlSubstitutionSampleSpec) sampleSpec) + .getName(); datasetStack.push(sampleName); convertFrom(bb, operands[0]); datasetStack.pop(); } else if (sampleSpec instanceof SqlSampleSpec.SqlTableSampleSpec) { SqlSampleSpec.SqlTableSampleSpec tableSampleSpec = - (SqlSampleSpec.SqlTableSampleSpec) sampleSpec; + (SqlSampleSpec.SqlTableSampleSpec) sampleSpec; convertFrom(bb, operands[0]); RelOptSamplingParameters params = - new RelOptSamplingParameters( - tableSampleSpec.isBernoulli(), - tableSampleSpec.getSamplePercentage(), - tableSampleSpec.isRepeatable(), - tableSampleSpec.getRepeatableSeed()); + new RelOptSamplingParameters( + tableSampleSpec.isBernoulli(), + tableSampleSpec.getSamplePercentage(), + tableSampleSpec.isRepeatable(), + tableSampleSpec.getRepeatableSeed()); bb.setRoot(new Sample(cluster, bb.root, params), false); } else { - throw Util.newInternal( - "unknown TABLESAMPLE type: " + sampleSpec); + throw new AssertionError("unknown TABLESAMPLE type: " + sampleSpec); } return; case IDENTIFIER: - final SqlValidatorNamespace fromNamespace = - validator.getNamespace(from).resolve(); - if (fromNamespace.getNode() != null) { - convertFrom(bb, fromNamespace.getNode()); - return; - } - final String datasetName = - datasetStack.isEmpty() ? null : datasetStack.peek(); - boolean[] usedDataset = {false}; - RelOptTable table = - SqlValidatorUtil.getRelOptTable( - fromNamespace, - catalogReader, - datasetName, - usedDataset); - final RelNode tableRel; - if (config.isConvertTableAccess()) { - tableRel = toRel(table); - } else { - tableRel = LogicalTableScan.create(cluster, table); - } - bb.setRoot(tableRel, true); - if (usedDataset[0]) { - bb.setDataset(datasetName); - } + convertIdentifier(bb, (SqlIdentifier) from, null); + return; + + case EXTEND: + call = (SqlCall) from; + SqlIdentifier id = (SqlIdentifier) call.getOperandList().get(0); + SqlNodeList extendedColumns = (SqlNodeList) call.getOperandList().get(1); + convertIdentifier(bb, id, extendedColumns); return; case JOIN: @@ -2056,15 +2044,15 @@ public class SqlToRelConverter { final boolean isNatural = join.isNatural(); final JoinType joinType = join.getJoinType(); final SqlValidatorScope leftScope = - Util.first(validator.getJoinScope(left), - ((DelegatingScope) bb.scope).getParent()); + Util.first(validator.getJoinScope(left), + ((DelegatingScope) bb.scope).getParent()); final Blackboard leftBlackboard = - createBlackboard(leftScope, null, false); + createBlackboard(leftScope, null, false); final SqlValidatorScope rightScope = - Util.first(validator.getJoinScope(right), - ((DelegatingScope) bb.scope).getParent()); + Util.first(validator.getJoinScope(right), + ((DelegatingScope) bb.scope).getParent()); final Blackboard rightBlackboard = - createBlackboard(rightScope, null, false); + createBlackboard(rightScope, null, false); convertFrom(leftBlackboard, left); RelNode leftRel = leftBlackboard.root; convertFrom(rightBlackboard, right); @@ -2077,29 +2065,29 @@ public class SqlToRelConverter { final RelDataType leftRowType = leftNamespace.getRowType(); final RelDataType rightRowType = rightNamespace.getRowType(); final List<String> columnList = - SqlValidatorUtil.deriveNaturalJoinColumnList(leftRowType, - rightRowType); + SqlValidatorUtil.deriveNaturalJoinColumnList(leftRowType, + rightRowType); conditionExp = convertUsing(leftNamespace, rightNamespace, - columnList); + columnList); } else { conditionExp = - convertJoinCondition( - fromBlackboard, - leftNamespace, - rightNamespace, - join.getCondition(), - join.getConditionType(), - leftRel, - rightRel); + convertJoinCondition( + fromBlackboard, + leftNamespace, + rightNamespace, + join.getCondition(), + join.getConditionType(), + leftRel, + rightRel); } final RelNode joinRel = - createJoin( - fromBlackboard, - leftRel, - rightRel, - conditionExp, - convertedJoinType); + createJoin( + fromBlackboard, + leftRel, + rightRel, + conditionExp, + convertedJoinType); bb.setRoot(joinRel, false); return; @@ -2129,13 +2117,13 @@ public class SqlToRelConverter { fieldNames.add(validator.deriveAlias(node.e, node.i)); } final RelNode input = - RelOptUtil.createProject( - (null != bb.root) ? bb.root : LogicalValues.createOneRow(cluster), - exprs, fieldNames, true); + RelOptUtil.createProject( + (null != bb.root) ? bb.root : LogicalValues.createOneRow(cluster), + exprs, fieldNames, true); Uncollect uncollect = - new Uncollect(cluster, cluster.traitSetOf(Convention.NONE), - input, operator.withOrdinality); + new Uncollect(cluster, cluster.traitSetOf(Convention.NONE), + input, operator.withOrdinality); bb.setRoot(uncollect, true); return; @@ -2149,13 +2137,116 @@ public class SqlToRelConverter { return; default: - throw Util.newInternal("not a join operator " + from); + throw new AssertionError("not a join operator " + from); + } + } + + protected void convertMatchRecognize(Blackboard bb, SqlCall call) { + final SqlMatchRecognize matchRecognize = (SqlMatchRecognize) call; + final SqlValidatorNamespace ns = validator.getNamespace(matchRecognize); + final SqlValidatorScope scope = validator.getMatchRecognizeScope(matchRecognize); + + final Blackboard mrBlackBoard = createBlackboard(scope, null, false); + final RelDataType rowType = ns.getRowType(); + // convert inner query, could be a table name or a derived table + SqlNode expr = matchRecognize.getTableRef(); + convertFrom(mrBlackBoard, expr); + final RelNode input = mrBlackBoard.root; + + // convert pattern + final Set<String> patternVarsSet = new HashSet<>(); + SqlNode pattern = matchRecognize.getPattern(); + final SqlBasicVisitor<RexNode> patternVarVisitor = + new SqlBasicVisitor<RexNode>() { + @Override public RexNode visit(SqlCall call) { + List<SqlNode> operands = call.getOperandList(); + List<RexNode> newOperands = Lists.newArrayList(); + for (SqlNode node : operands) { + newOperands.add(node.accept(this)); + } + return rexBuilder.makeCall( + validator.getUnknownType(), call.getOperator(), newOperands); + } + + @Override public RexNode visit(SqlIdentifier id) { + assert id.isSimple(); + patternVarsSet.add(id.getSimple()); + return rexBuilder.makeLiteral(id.getSimple()); + } + + @Override public RexNode visit(SqlLiteral literal) { + if (literal instanceof SqlNumericLiteral) { + return rexBuilder.makeExactLiteral(BigDecimal.valueOf(literal.intValue(true))); + } else { + return rexBuilder.makeLiteral(literal.booleanValue()); + } + } + }; + final RexNode patternNode = pattern.accept(patternVarVisitor); + + mrBlackBoard.setPatternVarRef(true); + + // convert definitions + final ImmutableMap.Builder<String, RexNode> definitionNodes = + ImmutableMap.builder(); + for (SqlNode def : matchRecognize.getPatternDefList()) { + List<SqlNode> operands = ((SqlCall) def).getOperandList(); + String alias = ((SqlIdentifier) operands.get(1)).getSimple(); + RexNode rex = mrBlackBoard.convertExpression(operands.get(0)); + definitionNodes.put(alias, rex); + } + + mrBlackBoard.setPatternVarRef(false); + + final RelFactories.MatchFactory factory = + RelFactories.DEFAULT_MATCH_FACTORY; + final RelNode rel = + factory.createMatchRecognize(input, patternNode, + matchRecognize.getStrictStart().booleanValue(), + matchRecognize.getStrictEnd().booleanValue(), + definitionNodes.build(), + rowType); + bb.setRoot(rel, false); + } + + private void convertIdentifier(Blackboard bb, SqlIdentifier id, + SqlNodeList extendedColumns) { + final SqlValidatorNamespace fromNamespace = + validator.getNamespace(id).resolve(); + if (fromNamespace.getNode() != null) { + convertFrom(bb, fromNamespace.getNode()); + return; + } + final String datasetName = + datasetStack.isEmpty() ? null : datasetStack.peek(); + final boolean[] usedDataset = {false}; + RelOptTable table = + SqlValidatorUtil.getRelOptTable(fromNamespace, catalogReader, + datasetName, usedDataset); + if (extendedColumns != null && extendedColumns.size() > 0) { + assert table != null; + final SqlValidatorTable validatorTable = + table.unwrap(SqlValidatorTable.class); + final List<RelDataTypeField> extendedFields = + SqlValidatorUtil.getExtendedColumns(validator, validatorTable, + extendedColumns); + table = table.extend(extendedFields); + } + final RelNode tableRel; + if (config.isConvertTableAccess()) { + tableRel = toRel(table); + } else { + tableRel = LogicalTableScan.create(cluster, table); + } + bb.setRoot(tableRel, true); + if (usedDataset[0]) { + bb.setDataset(datasetName); } } protected void convertCollectionTable( - Blackboard bb, - SqlCall call) { + Blackboard bb, + SqlCall call) { final SqlOperator operator = call.getOperator(); if (operator == SqlStdOperatorTable.TABLESAMPLE) { final String sampleName = (String) SqlLiteral.value(call.operand(0)); @@ -2172,15 +2263,15 @@ public class SqlToRelConverter { // Expand table macro if possible. It's more efficient than // LogicalTableFunctionScan. final SqlCallBinding callBinding = - new SqlCallBinding(bb.scope.getValidator(), bb.scope, call); + new SqlCallBinding(bb.scope.getValidator(), bb.scope, call); if (operator instanceof SqlUserDefinedTableMacro) { final SqlUserDefinedTableMacro udf = - (SqlUserDefinedTableMacro) operator; + (SqlUserDefinedTableMacro) operator; final TranslatableTable table = - udf.getTable(typeFactory, callBinding.operands()); + udf.getTable(typeFactory, callBinding.operands()); final RelDataType rowType = table.getRowType(typeFactory); RelOptTable relOptTable = RelOptTableImpl.create(null, rowType, table, - udf.getNameAsId().names); + udf.getNameAsId().names); RelNode converted = toRel(relOptTable); bb.setRoot(converted, true); return; @@ -2197,23 +2288,23 @@ public class SqlToRelConverter { RexNode rexCall = bb.convertExpression(call); final List<RelNode> inputs = bb.retrieveCursors(); Set<RelColumnMapping> columnMappings = - getColumnMappings(operator); + getColumnMappings(operator); LogicalTableFunctionScan callRel = - LogicalTableFunctionScan.create( - cluster, - inputs, - rexCall, - elementType, - validator.getValidatedNodeType(call), - columnMappings); + LogicalTableFunctionScan.create( + cluster, + inputs, + rexCall, + elementType, + validator.getValidatedNodeType(call), + columnMappings); bb.setRoot(callRel, true); afterTableFunction(bb, call, callRel); } protected void afterTableFunction( - SqlToRelConverter.Blackboard bb, - SqlCall call, - LogicalTableFunctionScan callRel) { + SqlToRelConverter.Blackboard bb, + SqlCall call, + LogicalTableFunctionScan callRel) { } private Set<RelColumnMapping> getColumnMappings(SqlOperator op) { @@ -2223,7 +2314,7 @@ public class SqlToRelConverter { } if (rti instanceof TableFunctionReturnTypeInference) { TableFunctionReturnTypeInference tfrti = - (TableFunctionReturnTypeInference) rti; + (TableFunctionReturnTypeInference) rti; return tfrti.getColumnMappings(); } else { return null; @@ -2231,35 +2322,35 @@ public class SqlToRelConverter { } protected RelNode createJoin( - Blackboard bb, - RelNode leftRel, - RelNode rightRel, - RexNode joinCond, - JoinRelType joinType) { + Blackboard bb, + RelNode leftRel, + RelNode rightRel, + RexNode joinCond, + JoinRelType joinType) { assert joinCond != null; final CorrelationUse p = getCorrelationUse(bb, rightRel); if (p != null) { LogicalCorrelate corr = LogicalCorrelate.create(leftRel, p.r, - p.id, p.requiredColumns, SemiJoinType.of(joinType)); + p.id, p.requiredColumns, SemiJoinType.of(joinType)); if (!joinCond.isAlwaysTrue()) { final RelFactories.FilterFactory factory = - RelFactories.DEFAULT_FILTER_FACTORY; + RelFactories.DEFAULT_FILTER_FACTORY; return factory.createFilter(corr, joinCond); } return corr; } final Join originalJoin = - (Join) RelFactories.DEFAULT_JOIN_FACTORY.createJoin(leftRel, rightRel, - joinCond, ImmutableSet.<CorrelationId>of(), joinType, false); + (Join) RelFactories.DEFAULT_JOIN_FACTORY.createJoin(leftRel, rightRel, + joinCond, ImmutableSet.<CorrelationId>of(), joinType, false); return RelOptUtil.pushDownJoinConditions(originalJoin); } private CorrelationUse getCorrelationUse(Blackboard bb, final RelNode r0) { final Set<CorrelationId> correlatedVariables = - RelOptUtil.getVariablesUsed(r0); + RelOptUtil.getVariablesUsed(r0); if (correlatedVariables.isEmpty()) { return null; } @@ -2274,18 +2365,21 @@ public class SqlToRelConverter { for (CorrelationId correlName : correlatedVariables) { DeferredLookup lookup = - mapCorrelToDeferred.get(correlName); + mapCorrelToDeferred.get(correlName); RexFieldAccess fieldAccess = lookup.getFieldAccess(correlName); String originalRelName = lookup.getOriginalRelName(); String originalFieldName = fieldAccess.getField().getName(); - SqlValidatorScope.ResolvedImpl resolved = - new SqlValidatorScope.ResolvedImpl(); - lookup.bb.scope.resolve(ImmutableList.of(originalRelName), false, - resolved); + final SqlNameMatcher nameMatcher = + lookup.bb.scope.getValidator().getCatalogReader().nameMatcher(); + final SqlValidatorScope.ResolvedImpl resolved = + new SqlValidatorScope.ResolvedImpl(); + lookup.bb.scope.resolve(ImmutableList.of(originalRelName), + nameMatcher, false, resolved); assert resolved.count() == 1; final SqlValidatorScope.Resolve resolve = resolved.only(); final SqlValidatorNamespace foundNs = resolve.namespace; +
<TRUNCATED>