private static Set<Integer> getCommonPartitionCols(List<RexNode> projections) { RexOver overClause; boolean firstOverClause = true; Set<Integer> commonPartitionKeys = new HashSet<Integer>(); for (RexNode expr : projections) { if (expr instanceof RexOver) { overClause = (RexOver) expr; if (firstOverClause) { firstOverClause = false; commonPartitionKeys.addAll(getPartitionCols(overClause.getWindow().partitionKeys)); } else { commonPartitionKeys.retainAll(getPartitionCols(overClause.getWindow().partitionKeys)); } } } return commonPartitionKeys; }
/** * Since the project under aggregate maybe reduce expressions by {@link org.apache.kylin.query.optrule.AggregateProjectReduceRule}, * consider the count of expressions into cost, the reduced project will be used. * * Made RexOver much more expensive so we can transform into {@link org.apache.kylin.query.relnode.OLAPWindowRel} * by rules in {@link org.apache.calcite.rel.rules.ProjectToWindowRule} */ @Override public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) { boolean hasRexOver = RexOver.containsOver(getProjects(), null); RelOptCost relOptCost = super.computeSelfCost(planner, mq).multiplyBy(.05) .multiplyBy(getProjects().size() * (hasRexOver ? 50 : 1)) .plus(planner.getCostFactory().makeCost(0.1 * caseCount, 0, 0)); return planner.getCostFactory().makeCost(relOptCost.getRows(), 0, 0); }
RexOver rexOverNode = (RexOver) r; for (RexNode operand : rexOverNode.getOperands()) { if (operand instanceof RexInputRef && ((RexInputRef)operand).getIndex() >= groupingFields) { for (RexNode partitionKey : rexOverNode.getWindow().partitionKeys) { if (partitionKey instanceof RexInputRef && ((RexInputRef)partitionKey).getIndex() >= groupingFields) { for (RexFieldCollation orderKey : rexOverNode.getWindow().orderKeys) { if (orderKey.left instanceof RexInputRef && ((RexInputRef)orderKey.left).getIndex() >= groupingFields) {
public RexNode visitOver(RexOver over) { boolean[] update = {false}; List<RexNode> clonedOperands = visitList(over.operands, update); RexWindow window = visitWindow(over.getWindow()); if (update[0] || (window != over.getWindow())) { // REVIEW jvs 8-Mar-2005: This doesn't take into account // the fact that a rewrite may have changed the result type. // To do that, we would need to take a RexBuilder and // watch out for special operators like CAST and NEW where // the type is embedded in the original call. return new RexOver( over.getType(), over.getAggOperator(), clonedOperands, window, over.isDistinct()); } else { return over; } }
private SqlCall toSql(RexProgram program, RexOver rexOver) { final RexWindow rexWindow = rexOver.getWindow(); final SqlNodeList partitionList = new SqlNodeList( toSql(program, rexWindow.partitionKeys), POS); ImmutableList.Builder<SqlNode> orderNodes = ImmutableList.builder(); if (rexWindow.orderKeys != null) { for (RexFieldCollation rfc : rexWindow.orderKeys) { orderNodes.add(toSql(program, rfc)); } } final SqlNodeList orderList = new SqlNodeList(orderNodes.build(), POS); final SqlLiteral isRows = SqlLiteral.createBoolean(rexWindow.isRows(), POS); final SqlNode lowerBound = createSqlWindowBound(rexWindow.getLowerBound()); final SqlNode upperBound = createSqlWindowBound(rexWindow.getUpperBound()); // null defaults to true. // During parsing the allowPartial == false (e.g. disallow partial) // is expand into CASE expression and is handled as a such. // Not sure if we can collapse this CASE expression back into // "disallow partial" and set the allowPartial = false. final SqlLiteral allowPartial = null; final SqlWindow sqlWindow = SqlWindow.create(null, null, partitionList, orderList, isRows, lowerBound, upperBound, allowPartial, POS); final List<SqlNode> nodeList = toSql(program, rexOver.getOperands()); return createOverCall(rexOver.getAggOperator(), nodeList, sqlWindow); }
if (agg instanceof RexOver) { final RexOver origOver = (RexOver) agg; final RexOver newOver = (RexOver) origOver.accept(replaceConstants); origToNewOver.put(origOver, newOver); addWindows(windowMap, newOver, inputFieldCount); final RexWinAggCall aggCall = new RexWinAggCall( over.getAggOperator(), over.getType(), toInputRefs(over.operands), aggMap.size(), over.isDistinct()); aggCalls.add(aggCall); aggMap.put(over, aggCall);
/** * Indicates if the given OVER clause has a window frame that is automatically added by * Calcite if the frame is not specified. */ public static boolean hasDefaultFrame(RexOver over) { // When Calcite parses an OVER clause with no frame, // it inject a 'default' frame depending on the function. // 1. For ROW_NUMBER(), it generates ROWS UNBOUNDED PRECEDING and CURRENT ROW. // 2. For others, it generates RANGE UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING if unsorted. // 3. If it's not ROW_NUMBER(), and it is sorted, Calcite uses RANGE UNBOUNDED PRECEDING AND CURRENT ROW // Adding these unnecessary frames cause some RDBMSes (eg SQL Server) to fail. // // This code happens in SqlToRelConverter.convertOver(), SqlValidatorImpl.resolveWindow(), // and SqlWindow.create()/SqlWindow.populateBounds(). return // Note: intentionally not simplifying this boolean for clarity. (over.getAggOperator() == SqlStdOperatorTable.ROW_NUMBER && over.getWindow().isRows() && over.getWindow().getLowerBound().isUnbounded() && over.getWindow().getLowerBound().isPreceding() && over.getWindow().getUpperBound().isCurrentRow()) // First condition. || (!over.getWindow().isRows() && over.getWindow().orderKeys.isEmpty() && over.getWindow().getLowerBound().isUnbounded() && over.getWindow().getLowerBound().isPreceding() && over.getWindow().getUpperBound().isUnbounded() && over.getWindow().getUpperBound().isFollowing()) // Second condition. || (!over.getWindow().isRows() && !over.getWindow().orderKeys.isEmpty() && over.getWindow().getLowerBound().isUnbounded() && over.getWindow().getLowerBound().isPreceding() && !over.getWindow().getUpperBound().isUnbounded() && over.getWindow().getUpperBound().isCurrentRow()); // Third condition. } }
@Override public Boolean visitOver(RexOver over) { return list(over.getOperands()); }
public RexNode visitOver(RexOver over) { // Look up the aggCall which this expr was translated to. final Window.RexWinAggCall aggCall = aggMap.get(origToNewOver.get(over)); assert aggCall != null; assert RelOptUtil.eq( "over", over.getType(), "aggCall", aggCall.getType(), Litmus.THROW); // Find the index of the aggCall among all partitions of all // groups. final int aggCallIndex = flattenedAggCallList.indexOf(aggCall); assert aggCallIndex >= 0; // Replace expression with a reference to the window slot. final int index = inputFieldCount + aggCallIndex; assert RelOptUtil.eq( "over", over.getType(), "intermed", intermediateRowType.getFieldList().get(index).getType(), Litmus.THROW); return new RexInputRef( index, over.getType()); }
upperBound, physical); final RexOver over = new RexOver(type, operator, exprs, window, distinct); RexNode result = over; makeCall( SqlStdOperatorTable.GREATER_THAN, new RexOver( bigintType, SqlStdOperatorTable.COUNT, SqlTypeName.DECIMAL)), new RexOver(typeFactory.createTypeWithNullability(type, false), operator, exprs, window, distinct), false), makeCall( SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, new RexOver( bigintType, SqlStdOperatorTable.COUNT,
@Override public RexNode visitOver(RexOver over, P arg) { boolean[] update = {false}; List<RexNode> clonedOperands = visitList(over.operands, update, arg); RexWindow window = visitWindow(over.getWindow(), arg); if (update[0] || (window != over.getWindow())) { // REVIEW jvs 8-Mar-2005: This doesn't take into account // the fact that a rewrite may have changed the result type. // To do that, we would need to take a RexBuilder and // watch out for special operators like CAST and NEW where // the type is embedded in the original call. return new RexOver( over.getType(), over.getAggOperator(), clonedOperands, window, over.isDistinct()); } else { return over; } }
private SqlCall toSql(RexProgram program, RexOver rexOver) { final RexWindow rexWindow = rexOver.getWindow(); final SqlNodeList partitionList = new SqlNodeList( toSql(program, rexWindow.partitionKeys), POS); orderList, isRows, lowerBound, upperBound, allowPartial, POS); final List<SqlNode> nodeList = toSql(program, rexOver.getOperands()); final SqlCall aggFunctionCall = rexOver.getAggOperator().createCall(POS, nodeList);
if (agg instanceof RexOver) { final RexOver origOver = (RexOver) agg; final RexOver newOver = (RexOver) origOver.accept(replaceConstants); origToNewOver.put(origOver, newOver); addWindows(windowMap, newOver, inputFieldCount); final RexWinAggCall aggCall = new RexWinAggCall( over.getAggOperator(), over.getType(), toInputRefs(over.operands), aggMap.size(), over.isDistinct()); aggCalls.add(aggCall); aggMap.put(over, aggCall);
public RexNode visitOver(RexOver over) { // Look up the aggCall which this expr was translated to. final Window.RexWinAggCall aggCall = aggMap.get(origToNewOver.get(over)); assert aggCall != null; assert RelOptUtil.eq( "over", over.getType(), "aggCall", aggCall.getType(), Litmus.THROW); // Find the index of the aggCall among all partitions of all // groups. final int aggCallIndex = flattenedAggCallList.indexOf(aggCall); assert aggCallIndex >= 0; // Replace expression with a reference to the window slot. final int index = inputFieldCount + aggCallIndex; assert RelOptUtil.eq( "over", over.getType(), "intermed", intermediateRowType.getFieldList().get(index).getType(), Litmus.THROW); return new RexInputRef( index, over.getType()); }
upperBound, physical); final RexOver over = new RexOver(type, operator, exprs, window, distinct); RexNode result = over; makeCall( SqlStdOperatorTable.GREATER_THAN, new RexOver( bigintType, SqlStdOperatorTable.COUNT, SqlTypeName.DECIMAL)), new RexOver(typeFactory.createTypeWithNullability(type, false), operator, exprs, window, distinct), false), makeCall( SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, new RexOver( bigintType, SqlStdOperatorTable.COUNT,
public RexNode visitOver(RexOver over) { boolean[] update = {false}; List<RexNode> clonedOperands = visitList(over.operands, update); RexWindow window = visitWindow(over.getWindow()); if (update[0] || (window != over.getWindow())) { // REVIEW jvs 8-Mar-2005: This doesn't take into account // the fact that a rewrite may have changed the result type. // To do that, we would need to take a RexBuilder and // watch out for special operators like CAST and NEW where // the type is embedded in the original call. return new RexOver( over.getType(), over.getAggOperator(), clonedOperands, window, over.isDistinct()); } else { return over; } }
if (RexOver.containsOver(origproject.getProjects(), null)) { RexNode origFilterCond = filterCondToPushBelowProj; filterCondToPushBelowProj = null;
private static Set<Integer> getCommonPartitionCols(List<RexNode> projections) { RexOver overClause; boolean firstOverClause = true; Set<Integer> commonPartitionKeys = new HashSet<Integer>(); for (RexNode expr : projections) { if (expr instanceof RexOver) { overClause = (RexOver) expr; if (firstOverClause) { firstOverClause = false; commonPartitionKeys.addAll(getPartitionCols(overClause.getWindow().partitionKeys)); } else { commonPartitionKeys.retainAll(getPartitionCols(overClause.getWindow().partitionKeys)); } } } return commonPartitionKeys; }