KYLIN-2419 rollback KYLIN-2292
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/7611338b Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/7611338b Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/7611338b Branch: refs/heads/master-hbase0.98 Commit: 7611338b5f022d216f5c9564a13c161374751adf Parents: a058bfb Author: Li Yang <liy...@apache.org> Authored: Sat Feb 4 11:03:25 2017 +0800 Committer: Li Yang <liy...@apache.org> Committed: Sat Feb 4 11:03:25 2017 +0800 ---------------------------------------------------------------------- .../adapter/enumerable/EnumerableWindow.java | 981 ------------------- .../calcite/adapter/enumerable/PhysType.java | 209 ---- .../adapter/enumerable/PhysTypeImpl.java | 654 ------------- 3 files changed, 1844 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/7611338b/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java ---------------------------------------------------------------------- diff --git a/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java b/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java deleted file mode 100644 index 216b07c..0000000 --- a/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java +++ /dev/null @@ -1,981 +0,0 @@ -/* - * 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.calcite.adapter.enumerable; - -import org.apache.calcite.adapter.enumerable.impl.WinAggAddContextImpl; -import org.apache.calcite.adapter.enumerable.impl.WinAggResetContextImpl; -import org.apache.calcite.adapter.enumerable.impl.WinAggResultContextImpl; -import org.apache.calcite.adapter.java.JavaTypeFactory; -import org.apache.calcite.linq4j.tree.BinaryExpression; -import org.apache.calcite.linq4j.tree.BlockBuilder; -import org.apache.calcite.linq4j.tree.BlockStatement; -import org.apache.calcite.linq4j.tree.DeclarationStatement; -import org.apache.calcite.linq4j.tree.Expression; -import org.apache.calcite.linq4j.tree.Expressions; -import org.apache.calcite.linq4j.tree.ParameterExpression; -import org.apache.calcite.linq4j.tree.Primitive; -import org.apache.calcite.linq4j.tree.Statement; -import org.apache.calcite.linq4j.tree.Types; -import org.apache.calcite.plan.RelOptCluster; -import org.apache.calcite.plan.RelOptCost; -import org.apache.calcite.plan.RelOptPlanner; -import org.apache.calcite.plan.RelTraitSet; -import org.apache.calcite.prepare.CalcitePrepareImpl; -import org.apache.calcite.rel.RelFieldCollation; -import org.apache.calcite.rel.RelNode; -import org.apache.calcite.rel.core.AggregateCall; -import org.apache.calcite.rel.core.Window; -import org.apache.calcite.rel.metadata.RelMetadataQuery; -import org.apache.calcite.rel.type.RelDataType; -import org.apache.calcite.rel.type.RelDataTypeFactory; -import org.apache.calcite.rex.RexInputRef; -import org.apache.calcite.rex.RexLiteral; -import org.apache.calcite.rex.RexNode; -import org.apache.calcite.rex.RexWindowBound; -import org.apache.calcite.runtime.SortedMultiMap; -import org.apache.calcite.sql.SqlAggFunction; -import org.apache.calcite.util.BuiltInMethod; -import org.apache.calcite.util.Pair; -import org.apache.calcite.util.Util; - -import com.google.common.base.Function; -import com.google.common.collect.ImmutableList; - -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -/* - * OVERRIDE POINT: patching CALCITE-1540 on calcite 1.8.0 - */ - -/** Implementation of {@link org.apache.calcite.rel.core.Window} in - * {@link org.apache.calcite.adapter.enumerable.EnumerableConvention enumerable calling convention}. */ -public class EnumerableWindow extends Window implements EnumerableRel { - /** Creates an EnumerableWindowRel. */ - EnumerableWindow(RelOptCluster cluster, RelTraitSet traits, RelNode child, - List<RexLiteral> constants, RelDataType rowType, List<Group> groups) { - super(cluster, traits, child, constants, rowType, groups); - } - - @Override public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) { - return new EnumerableWindow(getCluster(), traitSet, sole(inputs), - constants, rowType, groups); - } - - @Override - public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) { - return super.computeSelfCost(planner, mq) - .multiplyBy(EnumerableConvention.COST_MULTIPLIER); - } - - /** Implementation of {@link RexToLixTranslator.InputGetter} - * suitable for generating implementations of windowed aggregate - * functions. */ - private static class WindowRelInputGetter - implements RexToLixTranslator.InputGetter { - private final Expression row; - private final PhysType rowPhysType; - private final int actualInputFieldCount; - private final List<Expression> constants; - - private WindowRelInputGetter(Expression row, - PhysType rowPhysType, int actualInputFieldCount, - List<Expression> constants) { - this.row = row; - this.rowPhysType = rowPhysType; - this.actualInputFieldCount = actualInputFieldCount; - this.constants = constants; - } - - @Override - public Expression field(BlockBuilder list, int index, Type storageType) { - if (index < actualInputFieldCount) { - Expression current = list.append("current", row); - return rowPhysType.fieldReference(current, index, storageType); - } - return constants.get(index - actualInputFieldCount); - } - } - - private void sampleOfTheGeneratedWindowedAggregate() { - // Here's overview of the generated code - // For each list of rows that have the same partitioning key, evaluate - // all of the windowed aggregate functions. - - // builder - Iterator<Integer[]> iterator = null; - - // builder3 - Integer[] rows = iterator.next(); - - int prevStart = -1; - int prevEnd = -1; - - for (int i = 0; i < rows.length; i++) { - // builder4 - Integer row = rows[i]; - - int start = 0; - int end = 100; - if (start != prevStart || end != prevEnd) { - // builder5 - int actualStart = 0; - if (start != prevStart || end < prevEnd) { - // builder6 - // recompute - actualStart = start; - // implementReset - } else { // must be start == prevStart && end > prevEnd - actualStart = prevEnd + 1; - } - prevStart = start; - prevEnd = end; - - if (start != -1) { - for (int j = actualStart; j <= end; j++) { - // builder7 - // implementAdd - } - } - // implementResult - // list.add(new Xxx(row.deptno, row.empid, sum, count)); - } - } - // multiMap.clear(); // allows gc - // source = Linq4j.asEnumerable(list); - } - - @Override - public Result implement(EnumerableRelImplementor implementor, Prefer pref) { - final JavaTypeFactory typeFactory = implementor.getTypeFactory(); - final EnumerableRel child = (EnumerableRel) getInput(); - final BlockBuilder builder = new BlockBuilder(); - final Result result = implementor.visitChild(this, 0, child, pref); - Expression source_ = builder.append("source", result.block); - - final List<Expression> translatedConstants = - new ArrayList<>(constants.size()); - for (RexLiteral constant : constants) { - translatedConstants.add( - RexToLixTranslator.translateLiteral(constant, constant.getType(), - typeFactory, RexImpTable.NullAs.NULL)); - } - - PhysType inputPhysType = result.physType; - - ParameterExpression prevStart = - Expressions.parameter(int.class, builder.newName("prevStart")); - ParameterExpression prevEnd = - Expressions.parameter(int.class, builder.newName("prevEnd")); - - builder.add(Expressions.declare(0, prevStart, null)); - builder.add(Expressions.declare(0, prevEnd, null)); - - for (int windowIdx = 0; windowIdx < groups.size(); windowIdx++) { - Group group = groups.get(windowIdx); - // Comparator: - // final Comparator<JdbcTest.Employee> comparator = - // new Comparator<JdbcTest.Employee>() { - // public int compare(JdbcTest.Employee o1, - // JdbcTest.Employee o2) { - // return Integer.compare(o1.empid, o2.empid); - // } - // }; - final Expression comparator_ = - builder.append( - "comparator", - inputPhysType.generateComparator( - group.collation())); - - Pair<Expression, Expression> partitionIterator = - getPartitionIterator(builder, source_, inputPhysType, group, - comparator_); - final Expression collectionExpr = partitionIterator.left; - final Expression iterator_ = partitionIterator.right; - - List<AggImpState> aggs = new ArrayList<AggImpState>(); - List<AggregateCall> aggregateCalls = group.getAggregateCalls(this); - for (int aggIdx = 0; aggIdx < aggregateCalls.size(); aggIdx++) { - AggregateCall call = aggregateCalls.get(aggIdx); - aggs.add(new AggImpState(aggIdx, call, true)); - } - - // The output from this stage is the input plus the aggregate functions. - final RelDataTypeFactory.FieldInfoBuilder typeBuilder = - typeFactory.builder(); - typeBuilder.addAll(inputPhysType.getRowType().getFieldList()); - for (AggImpState agg : aggs) { - typeBuilder.add(agg.call.name, agg.call.type); - } - RelDataType outputRowType = typeBuilder.build(); - final PhysType outputPhysType = - PhysTypeImpl.of( - typeFactory, outputRowType, pref.prefer(result.format)); - - final Expression list_ = - builder.append( - "list", - Expressions.new_( - ArrayList.class, - Expressions.call( - collectionExpr, BuiltInMethod.COLLECTION_SIZE.method)), - false); - - Pair<Expression, Expression> collationKey = - getRowCollationKey(builder, inputPhysType, group, windowIdx); - Expression keySelector = collationKey.left; - Expression keyComparator = collationKey.right; - final BlockBuilder builder3 = new BlockBuilder(); - final Expression rows_ = - builder3.append( - "rows", - Expressions.convert_( - Expressions.call( - iterator_, BuiltInMethod.ITERATOR_NEXT.method), - Object[].class), - false); - - builder3.add( - Expressions.statement( - Expressions.assign(prevStart, Expressions.constant(-1)))); - builder3.add( - Expressions.statement( - Expressions.assign(prevEnd, - Expressions.constant(Integer.MAX_VALUE)))); - - final BlockBuilder builder4 = new BlockBuilder(); - - final ParameterExpression i_ = - Expressions.parameter(int.class, builder4.newName("i")); - - final Expression row_ = - builder4.append( - "row", - RexToLixTranslator.convert( - Expressions.arrayIndex(rows_, i_), - inputPhysType.getJavaRowType())); - - final RexToLixTranslator.InputGetter inputGetter = - new WindowRelInputGetter(row_, inputPhysType, - result.physType.getRowType().getFieldCount(), - translatedConstants); - - final RexToLixTranslator translator = - RexToLixTranslator.forAggregation(typeFactory, builder4, - inputGetter); - - final List<Expression> outputRow = new ArrayList<Expression>(); - int fieldCountWithAggResults = - inputPhysType.getRowType().getFieldCount(); - for (int i = 0; i < fieldCountWithAggResults; i++) { - outputRow.add( - inputPhysType.fieldReference( - row_, i, - outputPhysType.getJavaFieldType(i))); - } - - declareAndResetState(typeFactory, builder, result, windowIdx, aggs, - outputPhysType, outputRow); - - // There are assumptions that minX==0. If ever change this, look for - // frameRowCount, bounds checking, etc - final Expression minX = Expressions.constant(0); - final Expression partitionRowCount = - builder3.append("partRows", Expressions.field(rows_, "length")); - final Expression maxX = builder3.append("maxX", - Expressions.subtract( - partitionRowCount, Expressions.constant(1))); - - final Expression startUnchecked = builder4.append("start", - translateBound(translator, i_, row_, minX, maxX, rows_, - group, true, - inputPhysType, comparator_, keySelector, keyComparator)); - final Expression endUnchecked = builder4.append("end", - translateBound(translator, i_, row_, minX, maxX, rows_, - group, false, - inputPhysType, comparator_, keySelector, keyComparator)); - - final Expression startX; - final Expression endX; - final Expression hasRows; - if (group.isAlwaysNonEmpty()) { - startX = startUnchecked; - endX = endUnchecked; - hasRows = Expressions.constant(true); - } else { - Expression startTmp = - group.lowerBound.isUnbounded() || startUnchecked == i_ - ? startUnchecked - : builder4.append("startTmp", - Expressions.call(null, BuiltInMethod.MATH_MAX.method, - startUnchecked, minX)); - Expression endTmp = - group.upperBound.isUnbounded() || endUnchecked == i_ - ? endUnchecked - : builder4.append("endTmp", - Expressions.call(null, BuiltInMethod.MATH_MIN.method, - endUnchecked, maxX)); - - ParameterExpression startPe = Expressions.parameter(0, int.class, - builder4.newName("startChecked")); - ParameterExpression endPe = Expressions.parameter(0, int.class, - builder4.newName("endChecked")); - builder4.add(Expressions.declare(Modifier.FINAL, startPe, null)); - builder4.add(Expressions.declare(Modifier.FINAL, endPe, null)); - - hasRows = builder4.append("hasRows", - Expressions.lessThanOrEqual(startTmp, endTmp)); - builder4.add( - Expressions.ifThenElse(hasRows, - Expressions.block( - Expressions.statement( - Expressions.assign(startPe, startTmp)), - Expressions.statement( - Expressions.assign(endPe, endTmp))), - Expressions.block( - Expressions.statement( - Expressions.assign(startPe, Expressions.constant(-1))), - Expressions.statement( - Expressions.assign(endPe, Expressions.constant(-1)))))); - startX = startPe; - endX = endPe; - } - - final BlockBuilder builder5 = new BlockBuilder(true, builder4); - - BinaryExpression rowCountWhenNonEmpty = Expressions.add( - startX == minX ? endX : Expressions.subtract(endX, startX), - Expressions.constant(1)); - - final Expression frameRowCount; - - if (hasRows.equals(Expressions.constant(true))) { - frameRowCount = - builder4.append("totalRows", rowCountWhenNonEmpty); - } else { - frameRowCount = - builder4.append("totalRows", - Expressions.condition(hasRows, rowCountWhenNonEmpty, - Expressions.constant(0))); - } - - ParameterExpression actualStart = Expressions.parameter( - 0, int.class, builder5.newName("actualStart")); - - final BlockBuilder builder6 = new BlockBuilder(true, builder5); - builder6.add( - Expressions.statement(Expressions.assign(actualStart, startX))); - - for (final AggImpState agg : aggs) { - agg.implementor.implementReset(agg.context, - new WinAggResetContextImpl(builder6, agg.state, i_, startX, endX, - hasRows, partitionRowCount, frameRowCount)); - } - - Expression lowerBoundCanChange = - group.lowerBound.isUnbounded() && group.lowerBound.isPreceding() - ? Expressions.constant(false) - : Expressions.notEqual(startX, prevStart); - Expression needRecomputeWindow = Expressions.orElse( - lowerBoundCanChange, - Expressions.lessThan(endX, prevEnd)); - - BlockStatement resetWindowState = builder6.toBlock(); - if (resetWindowState.statements.size() == 1) { - builder5.add( - Expressions.declare(0, actualStart, - Expressions.condition(needRecomputeWindow, startX, - Expressions.add(prevEnd, Expressions.constant(1))))); - } else { - builder5.add( - Expressions.declare(0, actualStart, null)); - builder5.add( - Expressions.ifThenElse(needRecomputeWindow, - resetWindowState, - Expressions.statement( - Expressions.assign(actualStart, - Expressions.add(prevEnd, Expressions.constant(1)))))); - } - - if (lowerBoundCanChange instanceof BinaryExpression) { - builder5.add( - Expressions.statement(Expressions.assign(prevStart, startX))); - } - builder5.add( - Expressions.statement(Expressions.assign(prevEnd, endX))); - - final BlockBuilder builder7 = new BlockBuilder(true, builder5); - final DeclarationStatement jDecl = - Expressions.declare(0, "j", actualStart); - - final PhysType inputPhysTypeFinal = inputPhysType; - final Function<BlockBuilder, WinAggFrameResultContext> - resultContextBuilder = - getBlockBuilderWinAggFrameResultContextFunction(typeFactory, result, - translatedConstants, comparator_, rows_, i_, startX, endX, - minX, maxX, - hasRows, frameRowCount, partitionRowCount, - jDecl, inputPhysTypeFinal); - - final Function<AggImpState, List<RexNode>> rexArguments = - new Function<AggImpState, List<RexNode>>() { - public List<RexNode> apply(AggImpState agg) { - List<Integer> argList = agg.call.getArgList(); - List<RelDataType> inputTypes = - EnumUtils.fieldRowTypes( - result.physType.getRowType(), - constants, - argList); - List<RexNode> args = new ArrayList<RexNode>( - inputTypes.size()); - for (int i = 0; i < argList.size(); i++) { - Integer idx = argList.get(i); - args.add(new RexInputRef(idx, inputTypes.get(i))); - } - return args; - } - }; - - implementAdd(aggs, builder7, resultContextBuilder, rexArguments, jDecl); - - BlockStatement forBlock = builder7.toBlock(); - if (!forBlock.statements.isEmpty()) { - // For instance, row_number does not use for loop to compute the value - Statement forAggLoop = Expressions.for_( - Arrays.asList(jDecl), - Expressions.lessThanOrEqual(jDecl.parameter, endX), - Expressions.preIncrementAssign(jDecl.parameter), - forBlock); - if (!hasRows.equals(Expressions.constant(true))) { - forAggLoop = Expressions.ifThen(hasRows, forAggLoop); - } - builder5.add(forAggLoop); - } - - if (implementResult(aggs, builder5, resultContextBuilder, rexArguments, - true)) { - builder4.add( - Expressions.ifThen( - Expressions.orElse(lowerBoundCanChange, - Expressions.notEqual(endX, prevEnd)), - builder5.toBlock())); - } - - implementResult(aggs, builder4, resultContextBuilder, rexArguments, - false); - - builder4.add( - Expressions.statement( - Expressions.call( - list_, - BuiltInMethod.COLLECTION_ADD.method, - outputPhysType.record(outputRow)))); - - builder3.add( - Expressions.for_( - Expressions.declare(0, i_, Expressions.constant(0)), - Expressions.lessThan( - i_, - Expressions.field(rows_, "length")), - Expressions.preIncrementAssign(i_), - builder4.toBlock())); - - builder.add( - Expressions.while_( - Expressions.call( - iterator_, - BuiltInMethod.ITERATOR_HAS_NEXT.method), - builder3.toBlock())); - builder.add( - Expressions.statement( - Expressions.call( - collectionExpr, - BuiltInMethod.MAP_CLEAR.method))); - - // We're not assigning to "source". For each group, create a new - // final variable called "source" or "sourceN". - source_ = - builder.append( - "source", - Expressions.call( - BuiltInMethod.AS_ENUMERABLE.method, list_)); - - inputPhysType = outputPhysType; - } - - // return Linq4j.asEnumerable(list); - builder.add( - Expressions.return_(null, source_)); - return implementor.result(inputPhysType, builder.toBlock()); - } - - private Function<BlockBuilder, WinAggFrameResultContext> - getBlockBuilderWinAggFrameResultContextFunction( - final JavaTypeFactory typeFactory, final Result result, - final List<Expression> translatedConstants, - final Expression comparator_, - final Expression rows_, final ParameterExpression i_, - final Expression startX, final Expression endX, - final Expression minX, final Expression maxX, - final Expression hasRows, final Expression frameRowCount, - final Expression partitionRowCount, - final DeclarationStatement jDecl, - final PhysType inputPhysType) { - return new Function<BlockBuilder, - WinAggFrameResultContext>() { - public WinAggFrameResultContext apply( - final BlockBuilder block) { - return new WinAggFrameResultContext() { - public RexToLixTranslator rowTranslator(Expression rowIndex) { - Expression row = - getRow(rowIndex); - final RexToLixTranslator.InputGetter inputGetter = - new WindowRelInputGetter(row, inputPhysType, - result.physType.getRowType().getFieldCount(), - translatedConstants); - - return RexToLixTranslator.forAggregation(typeFactory, - block, inputGetter); - } - - public Expression computeIndex(Expression offset, - WinAggImplementor.SeekType seekType) { - Expression index; - if (seekType == WinAggImplementor.SeekType.AGG_INDEX) { - index = jDecl.parameter; - } else if (seekType == WinAggImplementor.SeekType.SET) { - index = i_; - } else if (seekType == WinAggImplementor.SeekType.START) { - index = startX; - } else if (seekType == WinAggImplementor.SeekType.END) { - index = endX; - } else { - throw new IllegalArgumentException("SeekSet " + seekType - + " is not supported"); - } - if (!Expressions.constant(0).equals(offset)) { - index = block.append("idx", Expressions.add(index, offset)); - } - return index; - } - - private Expression checkBounds(Expression rowIndex, - Expression minIndex, Expression maxIndex) { - if (rowIndex == i_ || rowIndex == startX || rowIndex == endX) { - // No additional bounds check required - return hasRows; - } - - //noinspection UnnecessaryLocalVariable - Expression res = block.append("rowInFrame", - Expressions.foldAnd( - ImmutableList.of(hasRows, - Expressions.greaterThanOrEqual(rowIndex, minIndex), - Expressions.lessThanOrEqual(rowIndex, maxIndex)))); - - return res; - } - - public Expression rowInFrame(Expression rowIndex) { - return checkBounds(rowIndex, startX, endX); - } - - public Expression rowInPartition(Expression rowIndex) { - return checkBounds(rowIndex, minX, maxX); - } - - public Expression compareRows(Expression a, Expression b) { - return Expressions.call(comparator_, - BuiltInMethod.COMPARATOR_COMPARE.method, - getRow(a), getRow(b)); - } - - public Expression getRow(Expression rowIndex) { - return block.append( - "jRow", - RexToLixTranslator.convert( - Expressions.arrayIndex(rows_, rowIndex), - inputPhysType.getJavaRowType())); - } - - public Expression index() { - return i_; - } - - public Expression startIndex() { - return startX; - } - - public Expression endIndex() { - return endX; - } - - public Expression hasRows() { - return hasRows; - } - - public Expression getFrameRowCount() { - return frameRowCount; - } - - public Expression getPartitionRowCount() { - return partitionRowCount; - } - }; - } - }; - } - - private Pair<Expression, Expression> getPartitionIterator( - BlockBuilder builder, - Expression source_, - PhysType inputPhysType, - Group group, - Expression comparator_) { - // Populate map of lists, one per partition - // final Map<Integer, List<Employee>> multiMap = - // new SortedMultiMap<Integer, List<Employee>>(); - // source.foreach( - // new Function1<Employee, Void>() { - // public Void apply(Employee v) { - // final Integer k = v.deptno; - // multiMap.putMulti(k, v); - // return null; - // } - // }); - // final List<Xxx> list = new ArrayList<Xxx>(multiMap.size()); - // Iterator<Employee[]> iterator = multiMap.arrays(comparator); - // - if (group.keys.isEmpty()) { - // If partition key is empty, no need to partition. - // - // final List<Employee> tempList = - // source.into(new ArrayList<Employee>()); - // Iterator<Employee[]> iterator = - // SortedMultiMap.singletonArrayIterator(comparator, tempList); - // final List<Xxx> list = new ArrayList<Xxx>(tempList.size()); - - final Expression tempList_ = builder.append( - "tempList", - Expressions.convert_( - Expressions.call( - source_, - BuiltInMethod.INTO.method, - Expressions.new_(ArrayList.class)), - List.class)); - return Pair.of(tempList_, - builder.append( - "iterator", - Expressions.call( - null, - BuiltInMethod.SORTED_MULTI_MAP_SINGLETON.method, - comparator_, - tempList_))); - } - Expression multiMap_ = - builder.append( - "multiMap", Expressions.new_(SortedMultiMap.class)); - final BlockBuilder builder2 = new BlockBuilder(); - final ParameterExpression v_ = - Expressions.parameter(inputPhysType.getJavaRowType(), - builder2.newName("v")); - - Pair<Type, List<Expression>> selector = inputPhysType.selector( - v_, - group.keys.asList(), - JavaRowFormat.CUSTOM); - final ParameterExpression key_; - if(selector.left instanceof Types.RecordType) { - Types.RecordType keyJavaType = (Types.RecordType) selector.left; - List<Expression> initExpressions = selector.right; - - key_ = Expressions.parameter(keyJavaType, "key"); - builder2.add(Expressions.declare(0, key_, null)); - builder2.add(Expressions.statement(Expressions.assign(key_, Expressions.new_(keyJavaType)))); - List<Types.RecordField> fieldList = keyJavaType.getRecordFields(); - for (int i = 0; i < initExpressions.size(); i++) { - Expression right = initExpressions.get(i); - builder2.add( - Expressions.statement( - Expressions.assign( - Expressions.field(key_, fieldList.get(i)), right))); - } - } - else - { - DeclarationStatement declare = Expressions.declare(0, "key", selector.right.get(0)); - builder2.add(declare); - key_ = declare.parameter; - } - builder2.add( - Expressions.statement( - Expressions.call( - multiMap_, - BuiltInMethod.SORTED_MULTI_MAP_PUT_MULTI.method, - key_, - v_))); - builder2.add( - Expressions.return_( - null, Expressions.constant(null))); - - builder.add( - Expressions.statement( - Expressions.call( - source_, - BuiltInMethod.ENUMERABLE_FOREACH.method, - Expressions.lambda( - builder2.toBlock(), v_)))); - - return Pair.of(multiMap_, - builder.append( - "iterator", - Expressions.call( - multiMap_, - BuiltInMethod.SORTED_MULTI_MAP_ARRAYS.method, - comparator_))); - } - - private Pair<Expression, Expression> getRowCollationKey( - BlockBuilder builder, PhysType inputPhysType, - Group group, int windowIdx) { - if (!(group.isRows || (group.upperBound.isUnbounded() - && group.lowerBound.isUnbounded()))) { - Pair<Expression, Expression> pair = - inputPhysType.generateCollationKey( - group.collation().getFieldCollations()); - // optimize=false to prevent inlining of object create into for-loops - return Pair.of( - builder.append("keySelector" + windowIdx, pair.left, false), - builder.append("keyComparator" + windowIdx, pair.right, false)); - } else { - return Pair.of(null, null); - } - } - - private void declareAndResetState(final JavaTypeFactory typeFactory, - BlockBuilder builder, final Result result, int windowIdx, - List<AggImpState> aggs, PhysType outputPhysType, - List<Expression> outputRow) { - for (final AggImpState agg : aggs) { - agg.context = - new WinAggContext() { - public SqlAggFunction aggregation() { - return agg.call.getAggregation(); - } - - public RelDataType returnRelType() { - return agg.call.type; - } - - public Type returnType() { - return EnumUtils.javaClass(typeFactory, returnRelType()); - } - - public List<? extends Type> parameterTypes() { - return EnumUtils.fieldTypes(typeFactory, - parameterRelTypes()); - } - - public List<? extends RelDataType> parameterRelTypes() { - return EnumUtils.fieldRowTypes(result.physType.getRowType(), - constants, agg.call.getArgList()); - } - }; - String aggName = "a" + agg.aggIdx; - if (CalcitePrepareImpl.DEBUG) { - aggName = Util.toJavaId(agg.call.getAggregation().getName(), 0) - .substring("ID$0$".length()) + aggName; - } - List<Type> state = agg.implementor.getStateType(agg.context); - final List<Expression> decls = - new ArrayList<Expression>(state.size()); - for (int i = 0; i < state.size(); i++) { - Type type = state.get(i); - ParameterExpression pe = - Expressions.parameter(type, - builder.newName(aggName - + "s" + i + "w" + windowIdx)); - builder.add(Expressions.declare(0, pe, null)); - decls.add(pe); - } - agg.state = decls; - Type aggHolderType = agg.context.returnType(); - Type aggStorageType = - outputPhysType.getJavaFieldType(outputRow.size()); - if (Primitive.is(aggHolderType) && !Primitive.is(aggStorageType)) { - aggHolderType = Primitive.box(aggHolderType); - } - ParameterExpression aggRes = Expressions.parameter(0, - aggHolderType, - builder.newName(aggName + "w" + windowIdx)); - - builder.add( - Expressions.declare(0, aggRes, - Expressions.constant(Primitive.is(aggRes.getType()) - ? Primitive.of(aggRes.getType()).defaultValue - : null, - aggRes.getType()))); - agg.result = aggRes; - outputRow.add(aggRes); - agg.implementor.implementReset(agg.context, - new WinAggResetContextImpl(builder, agg.state, - null, null, null, null, null, null)); - } - } - - private void implementAdd(List<AggImpState> aggs, - final BlockBuilder builder7, - final Function<BlockBuilder, WinAggFrameResultContext> frame, - final Function<AggImpState, List<RexNode>> rexArguments, - final DeclarationStatement jDecl) { - for (final AggImpState agg : aggs) { - final WinAggAddContext addContext = - new WinAggAddContextImpl(builder7, agg.state, frame) { - public Expression currentPosition() { - return jDecl.parameter; - } - - public List<RexNode> rexArguments() { - return rexArguments.apply(agg); - } - - public RexNode rexFilterArgument() { - return null; // REVIEW - } - }; - agg.implementor.implementAdd(agg.context, addContext); - } - } - - private boolean implementResult(List<AggImpState> aggs, - final BlockBuilder builder, - final Function<BlockBuilder, WinAggFrameResultContext> frame, - final Function<AggImpState, List<RexNode>> rexArguments, - boolean cachedBlock) { - boolean nonEmpty = false; - for (final AggImpState agg : aggs) { - boolean needCache = true; - if (agg.implementor instanceof WinAggImplementor) { - WinAggImplementor imp = (WinAggImplementor) agg.implementor; - needCache = imp.needCacheWhenFrameIntact(); - } - if (needCache ^ cachedBlock) { - // Regular aggregates do not change when the windowing frame keeps - // the same. Ths - continue; - } - nonEmpty = true; - Expression res = agg.implementor.implementResult(agg.context, - new WinAggResultContextImpl(builder, agg.state, frame) { - public List<RexNode> rexArguments() { - return rexArguments.apply(agg); - } - }); - // Several count(a) and count(b) might share the result - Expression aggRes = builder.append("a" + agg.aggIdx + "res", - RexToLixTranslator.convert(res, agg.result.getType())); - builder.add( - Expressions.statement(Expressions.assign(agg.result, aggRes))); - } - return nonEmpty; - } - - private Expression translateBound(RexToLixTranslator translator, - ParameterExpression i_, Expression row_, Expression min_, - Expression max_, Expression rows_, Group group, - boolean lower, - PhysType physType, Expression rowComparator, - Expression keySelector, Expression keyComparator) { - RexWindowBound bound = lower ? group.lowerBound : group.upperBound; - if (bound.isUnbounded()) { - return bound.isPreceding() ? min_ : max_; - } - if (group.isRows) { - if (bound.isCurrentRow()) { - return i_; - } - RexNode node = bound.getOffset(); - Expression offs = translator.translate(node); - // Floating offset does not make sense since we refer to array index. - // Nulls do not make sense as well. - offs = RexToLixTranslator.convert(offs, int.class); - - Expression b = i_; - if (bound.isFollowing()) { - b = Expressions.add(b, offs); - } else { - b = Expressions.subtract(b, offs); - } - return b; - } - Expression searchLower = min_; - Expression searchUpper = max_; - if (bound.isCurrentRow()) { - if (lower) { - searchUpper = i_; - } else { - searchLower = i_; - } - } - - List<RelFieldCollation> fieldCollations = - group.collation().getFieldCollations(); - if (bound.isCurrentRow() && fieldCollations.size() != 1) { - return Expressions.call( - (lower - ? BuiltInMethod.BINARY_SEARCH5_LOWER - : BuiltInMethod.BINARY_SEARCH5_UPPER).method, - rows_, row_, searchLower, searchUpper, keySelector, keyComparator); - } - assert fieldCollations.size() == 1 - : "When using range window specification, ORDER BY should have" - + " exactly one expression." - + " Actual collation is " + group.collation(); - // isRange - int orderKey = - fieldCollations.get(0).getFieldIndex(); - RelDataType keyType = - physType.getRowType().getFieldList().get(orderKey).getType(); - Type desiredKeyType = translator.typeFactory.getJavaClass(keyType); - if (bound.getOffset() == null) { - desiredKeyType = Primitive.box(desiredKeyType); - } - Expression val = translator.translate( - new RexInputRef(orderKey, keyType), desiredKeyType); - if (!bound.isCurrentRow()) { - RexNode node = bound.getOffset(); - Expression offs = translator.translate(node); - // TODO: support date + interval somehow - if (bound.isFollowing()) { - val = Expressions.add(val, offs); - } else { - val = Expressions.subtract(val, offs); - } - } - return Expressions.call( - (lower - ? BuiltInMethod.BINARY_SEARCH6_LOWER - : BuiltInMethod.BINARY_SEARCH6_UPPER).method, - rows_, val, searchLower, searchUpper, keySelector, keyComparator); - } -} - -// End EnumerableWindow.java http://git-wip-us.apache.org/repos/asf/kylin/blob/7611338b/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/PhysType.java ---------------------------------------------------------------------- diff --git a/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/PhysType.java b/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/PhysType.java deleted file mode 100644 index e37b196..0000000 --- a/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/PhysType.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.calcite.adapter.enumerable; - -import org.apache.calcite.linq4j.tree.Expression; -import org.apache.calcite.linq4j.tree.ParameterExpression; -import org.apache.calcite.rel.RelCollation; -import org.apache.calcite.rel.RelFieldCollation; -import org.apache.calcite.rel.type.RelDataType; -import org.apache.calcite.util.Pair; - -import java.lang.reflect.Type; -import java.util.List; - -/* - * OVERRIDE POINT: patching CALCITE-1540 on calcite 1.8.0 - */ - -/** - * Physical type of a row. - * - * <p>Consists of the SQL row type (returned by {@link #getRowType()}), the Java - * type of the row (returned by {@link #getJavaRowType()}), and methods to - * generate expressions to access fields, generate records, and so forth. - * Together, the records encapsulate how the logical type maps onto the physical - * type.</p> - */ -public interface PhysType { - /** Returns the Java type (often a Class) that represents a row. For - * example, in one row format, always returns {@code Object[].class}. */ - Type getJavaRowType(); - - /** - * Returns the Java class that is used to store the field with the given - * ordinal. - * - * <p>For instance, when the java row type is {@code Object[]}, the java - * field type is {@code Object} even if the field is not nullable.</p> */ - Type getJavaFieldType(int field); - - /** Returns the physical type of a field. */ - PhysType field(int ordinal); - - /** Returns the physical type of a given field's component type. */ - PhysType component(int field); - - /** Returns the SQL row type. */ - RelDataType getRowType(); - - /** Returns the Java class of the field with the given ordinal. */ - Class fieldClass(int field); - - /** Returns whether a given field allows null values. */ - boolean fieldNullable(int index); - - /** Generates a reference to a given field in an expression. - * - * <p>For example given {@code expression=employee} and {@code field=2}, - * generates</p> - * - * <pre>{@code employee.deptno}</pre> - * - * @param expression Expression - * @param field Ordinal of field - * @return Expression to access the field of the expression - */ - Expression fieldReference(Expression expression, int field); - - /** Generates a reference to a given field in an expression. - * - * <p>This method optimizes for the target storage type (i.e. avoids - * casts).</p> - * - * <p>For example given {@code expression=employee} and {@code field=2}, - * generates</p> - * - * <pre>{@code employee.deptno}</pre> - * - * @param expression Expression - * @param field Ordinal of field - * @param storageType optional hint for storage class - * @return Expression to access the field of the expression - */ - Expression fieldReference(Expression expression, int field, - Type storageType); - - /** Generates an accessor function for a given list of fields. The resulting - * object is a {@link List} (implementing {@link Object#hashCode()} and - * {@link Object#equals(Object)} per that interface) and also implements - * {@link Comparable}. - * - * <p>For example:</p> - * - * <pre>{@code - * new Function1<Employee, Object[]> { - * public Object[] apply(Employee v1) { - * return FlatLists.of(v1.<fieldN>, v1.<fieldM>); - * } - * } - * }</pre> - */ - Expression generateAccessor(List<Integer> fields); - - /** Generates a selector for the given fields from an expression, with the - * default row format. */ - Expression generateSelector( - ParameterExpression parameter, - List<Integer> fields); - - /** Generates a lambda expression that is a selector for the given fields from - * an expression. */ - Expression generateSelector( - ParameterExpression parameter, - List<Integer> fields, - JavaRowFormat targetFormat); - - /** Generates a lambda expression that is a selector for the given fields from - * an expression. - * - * <p>{@code usedFields} must be a subset of {@code fields}. - * For each field, there is a corresponding indicator field. - * If a field is used, its value is assigned and its indicator is left - * {@code false}. - * If a field is not used, its value is not assigned and its indicator is - * set to {@code true}; - * This will become a value of 1 when {@code GROUPING(field)} is called. */ - Expression generateSelector( - ParameterExpression parameter, - List<Integer> fields, - List<Integer> usedFields, - JavaRowFormat targetFormat); - - /** Generates a selector for the given fields from an expression. */ - /** Only used by EnumerableWindow */ - Pair<Type, List<Expression>> selector( - ParameterExpression parameter, - List<Integer> fields, - JavaRowFormat targetFormat); - - /** Projects a given collection of fields from this input record, into - * a particular preferred output format. The output format is optimized - * if there are 0 or 1 fields. */ - PhysType project( - List<Integer> integers, - JavaRowFormat format); - - /** Projects a given collection of fields from this input record, optionally - * with indicator fields, into a particular preferred output format. - * - * <p>The output format is optimized if there are 0 or 1 fields - * and indicators are disabled. */ - PhysType project( - List<Integer> integers, - boolean indicator, - JavaRowFormat format); - - /** Returns a lambda to create a collation key and a comparator. The - * comparator is sometimes null. */ - Pair<Expression, Expression> generateCollationKey( - List<RelFieldCollation> collations); - - /** Returns a comparator. Unlike the comparator returned by - * {@link #generateCollationKey(java.util.List)}, this comparator acts on the - * whole element. */ - Expression generateComparator( - RelCollation collation); - - /** Returns a expression that yields a comparer, or null if this type - * is comparable. */ - Expression comparer(); - - /** Generates an expression that creates a record for a row, initializing - * its fields with the given expressions. There must be one expression per - * field. - * - * @param expressions Expression to initialize each field - * @return Expression to create a row - */ - Expression record(List<Expression> expressions); - - /** Returns the format. */ - JavaRowFormat getFormat(); - - List<Expression> accessors(Expression parameter, List<Integer> argList); - - /** Returns a copy of this type that allows nulls if {@code nullable} is - * true. */ - PhysType makeNullable(boolean nullable); - - /** Converts an enumerable of this physical type to an enumerable that uses a - * given physical type for its rows. */ - Expression convertTo(Expression expression, PhysType targetPhysType); -} - -// End PhysType.java http://git-wip-us.apache.org/repos/asf/kylin/blob/7611338b/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java ---------------------------------------------------------------------- diff --git a/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java b/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java deleted file mode 100644 index 678b469..0000000 --- a/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java +++ /dev/null @@ -1,654 +0,0 @@ -/* - * 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.calcite.adapter.enumerable; - -import org.apache.calcite.adapter.java.JavaTypeFactory; -import org.apache.calcite.linq4j.Ord; -import org.apache.calcite.linq4j.function.Function1; -import org.apache.calcite.linq4j.tree.BlockBuilder; -import org.apache.calcite.linq4j.tree.Expression; -import org.apache.calcite.linq4j.tree.Expressions; -import org.apache.calcite.linq4j.tree.MemberDeclaration; -import org.apache.calcite.linq4j.tree.ParameterExpression; -import org.apache.calcite.linq4j.tree.Primitive; -import org.apache.calcite.linq4j.tree.Types; -import org.apache.calcite.rel.RelCollation; -import org.apache.calcite.rel.RelFieldCollation; -import org.apache.calcite.rel.type.RelDataType; -import org.apache.calcite.rel.type.RelDataTypeFactory; -import org.apache.calcite.rel.type.RelDataTypeField; -import org.apache.calcite.runtime.Utilities; -import org.apache.calcite.sql.SqlUtil; -import org.apache.calcite.sql.type.SqlTypeName; -import org.apache.calcite.util.BuiltInMethod; -import org.apache.calcite.util.Pair; -import org.apache.calcite.util.Util; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import static org.apache.calcite.adapter.enumerable.EnumUtils.javaRowClass; -import static org.apache.calcite.adapter.enumerable.EnumUtils.overridingMethodDecl; - -/* - * OVERRIDE POINT: patching CALCITE-1540 on calcite 1.8.0 - */ - -/** Implementation of {@link PhysType}. */ -public class PhysTypeImpl implements PhysType { - private final JavaTypeFactory typeFactory; - private final RelDataType rowType; - private final Type javaRowClass; - private final List<Class> fieldClasses = new ArrayList<>(); - final JavaRowFormat format; - - /** Creates a PhysTypeImpl. */ - PhysTypeImpl( - JavaTypeFactory typeFactory, - RelDataType rowType, - Type javaRowClass, - JavaRowFormat format) { - this.typeFactory = typeFactory; - this.rowType = rowType; - this.javaRowClass = javaRowClass; - this.format = format; - for (RelDataTypeField field : rowType.getFieldList()) { - fieldClasses.add(javaRowClass(typeFactory, field.getType())); - } - } - - public static PhysType of( - JavaTypeFactory typeFactory, - RelDataType rowType, - JavaRowFormat format) { - return of(typeFactory, rowType, format, true); - } - - public static PhysType of( - JavaTypeFactory typeFactory, - RelDataType rowType, - JavaRowFormat format, - boolean optimize) { - if (optimize) { - format = format.optimize(rowType); - } - final Type javaRowClass = format.javaRowClass(typeFactory, rowType); - return new PhysTypeImpl(typeFactory, rowType, javaRowClass, format); - } - - static PhysType of( - final JavaTypeFactory typeFactory, - Type javaRowClass) { - final RelDataTypeFactory.FieldInfoBuilder builder = typeFactory.builder(); - if (javaRowClass instanceof Types.RecordType) { - final Types.RecordType recordType = (Types.RecordType) javaRowClass; - for (Types.RecordField field : recordType.getRecordFields()) { - builder.add(field.getName(), typeFactory.createType(field.getType())); - } - } - RelDataType rowType = builder.build(); - // Do not optimize if there are 0 or 1 fields. - return new PhysTypeImpl(typeFactory, rowType, javaRowClass, - JavaRowFormat.CUSTOM); - } - - public JavaRowFormat getFormat() { - return format; - } - - public PhysType project(List<Integer> integers, JavaRowFormat format) { - return project(integers, false, format); - } - - public PhysType project(List<Integer> integers, boolean indicator, - JavaRowFormat format) { - final RelDataTypeFactory.FieldInfoBuilder builder = typeFactory.builder(); - for (int index : integers) { - builder.add(rowType.getFieldList().get(index)); - } - if (indicator) { - final RelDataType booleanType = - typeFactory.createTypeWithNullability( - typeFactory.createSqlType(SqlTypeName.BOOLEAN), false); - for (int index : integers) { - builder.add("i$" + rowType.getFieldList().get(index).getName(), - booleanType); - } - } - RelDataType projectedRowType = builder.build(); - return of(typeFactory, projectedRowType, format.optimize(projectedRowType)); - } - - public Expression generateSelector( - ParameterExpression parameter, - List<Integer> fields) { - return generateSelector(parameter, fields, format); - } - - public Expression generateSelector( - ParameterExpression parameter, - List<Integer> fields, - JavaRowFormat targetFormat) { - // Optimize target format - switch (fields.size()) { - case 0: - targetFormat = JavaRowFormat.LIST; - break; - case 1: - targetFormat = JavaRowFormat.SCALAR; - break; - } - final PhysType targetPhysType = - project(fields, targetFormat); - switch (format) { - case SCALAR: - return Expressions.call(BuiltInMethod.IDENTITY_SELECTOR.method); - default: - return Expressions.lambda(Function1.class, - targetPhysType.record(fieldReferences(parameter, fields)), parameter); - } - } - - public Expression generateSelector(final ParameterExpression parameter, - final List<Integer> fields, List<Integer> usedFields, - JavaRowFormat targetFormat) { - final PhysType targetPhysType = - project(fields, true, targetFormat); - final List<Expression> expressions = Lists.newArrayList(); - for (Ord<Integer> ord : Ord.zip(fields)) { - final Integer field = ord.e; - if (usedFields.contains(field)) { - expressions.add(fieldReference(parameter, field)); - } else { - final Primitive primitive = - Primitive.of(targetPhysType.fieldClass(ord.i)); - expressions.add( - Expressions.constant( - primitive != null ? primitive.defaultValue : null)); - } - } - for (Integer field : fields) { - expressions.add(Expressions.constant(!usedFields.contains(field))); - } - return Expressions.lambda(Function1.class, - targetPhysType.record(expressions), parameter); - } - - public Pair<Type, List<Expression>> selector( - ParameterExpression parameter, - List<Integer> fields, - JavaRowFormat targetFormat) { - // Optimize target format - switch (fields.size()) { - case 0: - targetFormat = JavaRowFormat.LIST; - break; - case 1: - targetFormat = JavaRowFormat.SCALAR; - break; - } - final PhysType targetPhysType = - project(fields, targetFormat); - switch (format) { - case SCALAR: - return Pair.of(parameter.getType(), Collections.<Expression>singletonList(parameter)); - default: - return Pair.of(targetPhysType.getJavaRowType(), fieldReferences(parameter, fields)); - } - } - - public List<Expression> accessors(Expression v1, List<Integer> argList) { - final List<Expression> expressions = new ArrayList<>(); - for (int field : argList) { - expressions.add( - Types.castIfNecessary( - fieldClass(field), - fieldReference(v1, field))); - } - return expressions; - } - - public PhysType makeNullable(boolean nullable) { - if (!nullable) { - return this; - } - return new PhysTypeImpl(typeFactory, - typeFactory.createTypeWithNullability(rowType, true), - Primitive.box(javaRowClass), format); - } - - public Expression convertTo(Expression exp, PhysType targetPhysType) { - final JavaRowFormat targetFormat = targetPhysType.getFormat(); - if (format == targetFormat) { - return exp; - } - final ParameterExpression o_ = - Expressions.parameter(javaRowClass, "o"); - final int fieldCount = rowType.getFieldCount(); - return Expressions.call(exp, BuiltInMethod.SELECT.method, - generateSelector(o_, Util.range(fieldCount), targetFormat)); - } - - public Pair<Expression, Expression> generateCollationKey( - final List<RelFieldCollation> collations) { - final Expression selector; - if (collations.size() == 1) { - RelFieldCollation collation = collations.get(0); - ParameterExpression parameter = - Expressions.parameter(javaRowClass, "v"); - selector = - Expressions.lambda( - Function1.class, - fieldReference(parameter, collation.getFieldIndex()), - parameter); - return Pair.<Expression, Expression>of( - selector, - Expressions.call( - BuiltInMethod.NULLS_COMPARATOR.method, - Expressions.constant( - collation.nullDirection - == RelFieldCollation.NullDirection.FIRST), - Expressions.constant( - collation.getDirection() - == RelFieldCollation.Direction.DESCENDING))); - } - selector = - Expressions.call(BuiltInMethod.IDENTITY_SELECTOR.method); - - // int c; - // c = Utilities.compare(v0, v1); - // if (c != 0) return c; // or -c if descending - // ... - // return 0; - BlockBuilder body = new BlockBuilder(); - final ParameterExpression parameterV0 = - Expressions.parameter(javaRowClass, "v0"); - final ParameterExpression parameterV1 = - Expressions.parameter(javaRowClass, "v1"); - final ParameterExpression parameterC = - Expressions.parameter(int.class, "c"); - final int mod = collations.size() == 1 ? Modifier.FINAL : 0; - body.add(Expressions.declare(mod, parameterC, null)); - for (RelFieldCollation collation : collations) { - final int index = collation.getFieldIndex(); - Expression arg0 = fieldReference(parameterV0, index); - Expression arg1 = fieldReference(parameterV1, index); - switch (Primitive.flavor(fieldClass(index))) { - case OBJECT: - arg0 = Types.castIfNecessary(Comparable.class, arg0); - arg1 = Types.castIfNecessary(Comparable.class, arg1); - } - final boolean nullsFirst = - collation.nullDirection - == RelFieldCollation.NullDirection.FIRST; - final boolean descending = - collation.getDirection() - == RelFieldCollation.Direction.DESCENDING; - final Method method = (fieldNullable(index) - ? (nullsFirst ^ descending - ? BuiltInMethod.COMPARE_NULLS_FIRST - : BuiltInMethod.COMPARE_NULLS_LAST) - : BuiltInMethod.COMPARE).method; - body.add( - Expressions.statement( - Expressions.assign( - parameterC, - Expressions.call(method.getDeclaringClass(), - method.getName(), - arg0, - arg1)))); - body.add( - Expressions.ifThen( - Expressions.notEqual( - parameterC, Expressions.constant(0)), - Expressions.return_( - null, - descending - ? Expressions.negate(parameterC) - : parameterC))); - } - body.add( - Expressions.return_(null, Expressions.constant(0))); - - final List<MemberDeclaration> memberDeclarations = - Expressions.<MemberDeclaration>list( - Expressions.methodDecl( - Modifier.PUBLIC, - int.class, - "compare", - ImmutableList.of( - parameterV0, parameterV1), - body.toBlock())); - - if (EnumerableRules.BRIDGE_METHODS) { - final ParameterExpression parameterO0 = - Expressions.parameter(Object.class, "o0"); - final ParameterExpression parameterO1 = - Expressions.parameter(Object.class, "o1"); - BlockBuilder bridgeBody = new BlockBuilder(); - bridgeBody.add( - Expressions.return_( - null, - Expressions.call( - Expressions.parameter( - Comparable.class, "this"), - BuiltInMethod.COMPARATOR_COMPARE.method, - Expressions.convert_( - parameterO0, - javaRowClass), - Expressions.convert_( - parameterO1, - javaRowClass)))); - memberDeclarations.add( - overridingMethodDecl( - BuiltInMethod.COMPARATOR_COMPARE.method, - ImmutableList.of(parameterO0, parameterO1), - bridgeBody.toBlock())); - } - return Pair.<Expression, Expression>of( - selector, - Expressions.new_( - Comparator.class, - Collections.<Expression>emptyList(), - memberDeclarations)); - } - - public Expression generateComparator(RelCollation collation) { - // int c; - // c = Utilities.compare(v0, v1); - // if (c != 0) return c; // or -c if descending - // ... - // return 0; - BlockBuilder body = new BlockBuilder(); - final Type javaRowClass = Primitive.box(this.javaRowClass); - final ParameterExpression parameterV0 = - Expressions.parameter(javaRowClass, "v0"); - final ParameterExpression parameterV1 = - Expressions.parameter(javaRowClass, "v1"); - final ParameterExpression parameterC = - Expressions.parameter(int.class, "c"); - final int mod = - collation.getFieldCollations().size() == 1 ? Modifier.FINAL : 0; - body.add(Expressions.declare(mod, parameterC, null)); - for (RelFieldCollation fieldCollation : collation.getFieldCollations()) { - final int index = fieldCollation.getFieldIndex(); - Expression arg0 = fieldReference(parameterV0, index); - Expression arg1 = fieldReference(parameterV1, index); - switch (Primitive.flavor(fieldClass(index))) { - case OBJECT: - arg0 = Types.castIfNecessary(Comparable.class, arg0); - arg1 = Types.castIfNecessary(Comparable.class, arg1); - } - final boolean nullsFirst = - fieldCollation.nullDirection - == RelFieldCollation.NullDirection.FIRST; - final boolean descending = - fieldCollation.getDirection() - == RelFieldCollation.Direction.DESCENDING; - body.add( - Expressions.statement( - Expressions.assign( - parameterC, - Expressions.call( - Utilities.class, - fieldNullable(index) - ? (nullsFirst != descending - ? "compareNullsFirst" - : "compareNullsLast") - : "compare", - arg0, - arg1)))); - body.add( - Expressions.ifThen( - Expressions.notEqual( - parameterC, Expressions.constant(0)), - Expressions.return_( - null, - descending - ? Expressions.negate(parameterC) - : parameterC))); - } - body.add( - Expressions.return_(null, Expressions.constant(0))); - - final List<MemberDeclaration> memberDeclarations = - Expressions.<MemberDeclaration>list( - Expressions.methodDecl( - Modifier.PUBLIC, - int.class, - "compare", - ImmutableList.of(parameterV0, parameterV1), - body.toBlock())); - - if (EnumerableRules.BRIDGE_METHODS) { - final ParameterExpression parameterO0 = - Expressions.parameter(Object.class, "o0"); - final ParameterExpression parameterO1 = - Expressions.parameter(Object.class, "o1"); - BlockBuilder bridgeBody = new BlockBuilder(); - bridgeBody.add( - Expressions.return_( - null, - Expressions.call( - Expressions.parameter( - Comparable.class, "this"), - BuiltInMethod.COMPARATOR_COMPARE.method, - Expressions.convert_( - parameterO0, - javaRowClass), - Expressions.convert_( - parameterO1, - javaRowClass)))); - memberDeclarations.add( - overridingMethodDecl( - BuiltInMethod.COMPARATOR_COMPARE.method, - ImmutableList.of(parameterO0, parameterO1), - bridgeBody.toBlock())); - } - return Expressions.new_( - Comparator.class, - Collections.<Expression>emptyList(), - memberDeclarations); - } - - public RelDataType getRowType() { - return rowType; - } - - public Expression record(List<Expression> expressions) { - return format.record(javaRowClass, expressions); - } - - public Type getJavaRowType() { - return javaRowClass; - } - - public Type getJavaFieldType(int index) { - return format.javaFieldClass(typeFactory, rowType, index); - } - - public PhysType component(int fieldOrdinal) { - final RelDataTypeField field = rowType.getFieldList().get(fieldOrdinal); - return PhysTypeImpl.of(typeFactory, - toStruct(field.getType().getComponentType()), format, false); - } - - public PhysType field(int ordinal) { - final RelDataTypeField field = rowType.getFieldList().get(ordinal); - final RelDataType type = field.getType(); - return PhysTypeImpl.of(typeFactory, toStruct(type), format, false); - } - - private RelDataType toStruct(RelDataType type) { - if (type.isStruct()) { - return type; - } - return typeFactory.builder() - .add(SqlUtil.deriveAliasFromOrdinal(0), type) - .build(); - } - - public Expression comparer() { - return format.comparer(); - } - - private List<Expression> fieldReferences( - final Expression parameter, final List<Integer> fields) { - return new AbstractList<Expression>() { - public Expression get(int index) { - return fieldReference(parameter, fields.get(index)); - } - - public int size() { - return fields.size(); - } - }; - } - - public Class fieldClass(int field) { - return fieldClasses.get(field); - } - - public boolean fieldNullable(int field) { - return rowType.getFieldList().get(field).getType().isNullable(); - } - - public Expression generateAccessor( - List<Integer> fields) { - ParameterExpression v1 = - Expressions.parameter(javaRowClass, "v1"); - switch (fields.size()) { - case 0: - return Expressions.lambda( - Function1.class, - Expressions.field( - null, - BuiltInMethod.COMPARABLE_EMPTY_LIST.field), - v1); - case 1: - int field0 = fields.get(0); - - // new Function1<Employee, Res> { - // public Res apply(Employee v1) { - // return v1.<fieldN>; - // } - // } - Class returnType = fieldClasses.get(field0); - Expression fieldReference = - Types.castIfNecessary( - returnType, - fieldReference(v1, field0)); - return Expressions.lambda( - Function1.class, - fieldReference, - v1); - default: - // new Function1<Employee, List> { - // public List apply(Employee v1) { - // return Arrays.asList( - // new Object[] {v1.<fieldN>, v1.<fieldM>}); - // } - // } - Expressions.FluentList<Expression> list = Expressions.list(); - for (int field : fields) { - list.add(fieldReference(v1, field)); - } - switch (list.size()) { - case 2: - return Expressions.lambda( - Function1.class, - Expressions.call( - List.class, - null, - BuiltInMethod.LIST2.method, - list), - v1); - case 3: - return Expressions.lambda( - Function1.class, - Expressions.call( - List.class, - null, - BuiltInMethod.LIST3.method, - list), - v1); - case 4: - return Expressions.lambda( - Function1.class, - Expressions.call( - List.class, - null, - BuiltInMethod.LIST4.method, - list), - v1); - case 5: - return Expressions.lambda( - Function1.class, - Expressions.call( - List.class, - null, - BuiltInMethod.LIST5.method, - list), - v1); - case 6: - return Expressions.lambda( - Function1.class, - Expressions.call( - List.class, - null, - BuiltInMethod.LIST6.method, - list), - v1); - default: - return Expressions.lambda( - Function1.class, - Expressions.call( - List.class, - null, - BuiltInMethod.LIST_N.method, - Expressions.newArrayInit( - Comparable.class, - list)), - v1); - } - } - } - - public Expression fieldReference( - Expression expression, int field) { - return fieldReference(expression, field, null); - } - - public Expression fieldReference( - Expression expression, int field, Type storageType) { - if (storageType == null) { - storageType = fieldClass(field); - } - return format.field(expression, field, storageType); - } -} - -// End PhysTypeImpl.java