/** * Adds a child to this expression. * * @param child child to add */ public void addChild(SargExpr child) { assert (child.getDataType() == dataType); if (setOp == SargSetOperator.COMPLEMENT) { assert (children.isEmpty()); } children.add(child); }
/** * Creates a relational expression which projects an array of expressions, and optionally * optimizes. * * <p>The result may not be a {@link ProjectRel}. If the projection is trivial, <code>child</code> * is returned directly; and future versions may return other formulations of expressions, such as * {@link CalcRel}. * * @param child input relational expression * @param exprs list of expressions for the input columns * @param fieldNames aliases of the expressions, or null to generate * @param optimize Whether to return <code>child</code> unchanged if the projections are trivial. */ public static RelNode createProject( RelNode child, List<RexNode> exprs, List<String> fieldNames, boolean optimize) { final RelOptCluster cluster = child.getCluster(); final RexProgram program = RexProgram.create(child.getRowType(), exprs, null, fieldNames, cluster.getRexBuilder()); final List<RelCollation> collationList = program.getCollations(child.getCollationList()); if (DeprecateProjectAndFilter) { return new CalcRel( cluster, child.getTraitSet(), child, program.getOutputRowType(), program, collationList); } else { final RelDataType rowType = RexUtil.createStructType(cluster.getTypeFactory(), exprs, fieldNames); if (optimize && RemoveTrivialProjectRule.isIdentity(exprs, rowType, child.getRowType())) { return child; } return new ProjectRel( cluster, cluster.traitSetOf( collationList.isEmpty() ? RelCollationImpl.EMPTY : collationList.get(0)), child, exprs, rowType, ProjectRelBase.Flags.Boxed); } }
/** * Creates a relational expression which projects an array of expressions, and optionally * optimizes. * * <p>The result may not be a {@link ProjectRel}. If the projection is trivial, <code>child</code> * is returned directly; and future versions may return other formulations of expressions, such as * {@link CalcRel}. * * @param child input relational expression * @param exprs list of expressions for the input columns * @param fieldNames aliases of the expressions, or null to generate * @param optimize Whether to return <code>child</code> unchanged if the projections are trivial. */ public static RelNode createProject( RelNode child, List<RexNode> exprs, List<String> fieldNames, boolean optimize) { final RelOptCluster cluster = child.getCluster(); final RexProgram program = RexProgram.create(child.getRowType(), exprs, null, fieldNames, cluster.getRexBuilder()); final List<RelCollation> collationList = program.getCollations(child.getCollationList()); if (DEPRECATE_PROJECT_AND_FILTER) { return new CalcRel( cluster, child.getTraitSet(), child, program.getOutputRowType(), program, collationList); } else { final RelDataType rowType = RexUtil.createStructType( cluster.getTypeFactory(), exprs, fieldNames == null ? null : SqlValidatorUtil.uniquify(fieldNames, SqlValidatorUtil.F_SUGGESTER)); if (optimize && RemoveTrivialProjectRule.isIdentity(exprs, rowType, child.getRowType())) { return child; } return new ProjectRel( cluster, cluster.traitSetOf( collationList.isEmpty() ? RelCollationImpl.EMPTY : collationList.get(0)), child, exprs, rowType, ProjectRelBase.Flags.BOXED); } }
/** Variant of {@link #trimFields(RelNode, BitSet, Set)} for {@link TableFunctionRel}. */ public TrimResult trimFields( TableFunctionRel tabFun, BitSet fieldsUsed, Set<RelDataTypeField> extraFields) { final RelDataType rowType = tabFun.getRowType(); final int fieldCount = rowType.getFieldCount(); List<RelNode> newInputs = new ArrayList<RelNode>(); for (RelNode input : tabFun.getInputs()) { final int inputFieldCount = input.getRowType().getFieldCount(); BitSet inputFieldsUsed = Util.bitSetBetween(0, inputFieldCount); // Create input with trimmed columns. final Set<RelDataTypeField> inputExtraFields = Collections.emptySet(); TrimResult trimResult = trimChildRestore(tabFun, input, inputFieldsUsed, inputExtraFields); assert trimResult.right.isIdentity(); newInputs.add(trimResult.left); } TableFunctionRel newTabFun = tabFun; if (!tabFun.getInputs().equals(newInputs)) { newTabFun = tabFun.copy(tabFun.getTraitSet(), newInputs); } assert newTabFun.getClass() == tabFun.getClass(); // Always project all fields. Mapping mapping = Mappings.createIdentity(fieldCount); return new TrimResult(newTabFun, mapping); }
private List<Expression> translateList(List<RexNode> operandList) { final List<Expression> list = new ArrayList<Expression>(); for (RexNode rex : operandList) { list.add(translate(rex)); } return list; }
private List<SqlNode> toSql(RexProgram program, List<RexNode> operandList) { final List<SqlNode> list = new ArrayList<SqlNode>(); for (RexNode rex : operandList) { list.add(toSql(program, rex)); } return list; }
/** * Determines if a filter condition is a simple one and returns the parameters corresponding to * the simple filters. * * @param calcRel original CalcRel * @param filterExprs filter expression being analyzed * @param filterList returns the list of filter ordinals in the simple expression * @param literals returns the list of literals to be used in the simple comparisons * @param op returns the operator to be used in the simple comparison * @return true if the filter condition is simple */ private boolean isConditionSimple( CalcRel calcRel, RexNode filterExprs, List<Integer> filterList, List<RexLiteral> literals, List<CompOperatorEnum> op) { SargFactory sargFactory = new SargFactory(calcRel.getCluster().getRexBuilder()); SargRexAnalyzer rexAnalyzer = sargFactory.newRexAnalyzer(true); List<SargBinding> sargBindingList = rexAnalyzer.analyzeAll(filterExprs); // Currently, it's all or nothing. So, if there are filters rejected // by the analyzer, we can't process a subset using the reshape // exec stream if (rexAnalyzer.getNonSargFilterRexNode() != null) { return false; } List<RexInputRef> filterCols = new ArrayList<RexInputRef>(); List<RexNode> filterOperands = new ArrayList<RexNode>(); if (FennelRelUtil.extractSimplePredicates(sargBindingList, filterCols, filterOperands, op)) { for (RexInputRef filterCol : filterCols) { filterList.add(filterCol.getIndex()); } for (RexNode operand : filterOperands) { literals.add((RexLiteral) operand); } return true; } else { return false; } }
private List<Expression> translate(List<Statement> list, List<RexLocalRef> rexList) { // First pass. Count how many times each sub-expression is used. this.list = null; for (RexNode rexExpr : rexList) { translate(rexExpr); } // Mark expressions as inline if they are not used more than once. for (Map.Entry<RexNode, Slot> entry : map.entrySet()) { if (entry.getValue().count < 2 || entry.getKey() instanceof RexLiteral) { inlineRexSet.add(entry.getKey()); } } // Second pass. When translating each expression, if it is used more // than once, the first time it is encountered, add a declaration to the // list and set its usage count to 0. this.list = list; this.map.clear(); List<Expression> translateds = new ArrayList<Expression>(); for (RexNode rexExpr : rexList) { translateds.add(translate(rexExpr)); } return translateds; }
private void analyzeCall(RexCall call, Constancy callConstancy) { parentCallTypeStack.add(call.getOperator()); // visit operands, pushing their states onto stack super.visitCall(call); // look for NON_CONSTANT operands int nOperands = call.getOperands().length; List<Constancy> operandStack = stack.subList(stack.size() - nOperands, stack.size()); for (Constancy operandConstancy : operandStack) { if (operandConstancy == Constancy.NON_CONSTANT) { callConstancy = Constancy.NON_CONSTANT; } } // Even if all operands are constant, the call itself may // be non-deterministic. if (!call.getOperator().isDeterministic()) { callConstancy = Constancy.NON_CONSTANT; } else if (call.getOperator().isDynamicFunction()) { // We can reduce the call to a constant, but we can't // cache the plan if the function is dynamic preparingStmt.disableStatementCaching(); } // Row operator itself can't be reduced to a literal, but if // the operands are constants, we still want to reduce those if ((callConstancy == Constancy.REDUCIBLE_CONSTANT) && (call.getOperator() instanceof SqlRowOperator)) { callConstancy = Constancy.NON_CONSTANT; } if (callConstancy == Constancy.NON_CONSTANT) { // any REDUCIBLE_CONSTANT children are now known to be maximal // reducible subtrees, so they can be added to the result // list for (int iOperand = 0; iOperand < nOperands; ++iOperand) { Constancy constancy = operandStack.get(iOperand); if (constancy == Constancy.REDUCIBLE_CONSTANT) { addResult(call.getOperands()[iOperand]); } } // if this cast expression can't be reduced to a literal, // then see if we can remove the cast if (call.getOperator() == SqlStdOperatorTable.castFunc) { reduceCasts(call); } } // pop operands off of the stack operandStack.clear(); // pop this parent call operator off the stack parentCallTypeStack.remove(parentCallTypeStack.size() - 1); // push constancy result for this call onto stack stack.add(callConstancy); }
private SqlNode createLeftCall(SqlOperator op, List<SqlNode> nodeList) { if (nodeList.size() == 2) { return op.createCall(new SqlNodeList(nodeList, POS)); } final List<SqlNode> butLast = Util.skipLast(nodeList); final SqlNode last = nodeList.get(nodeList.size() - 1); final SqlNode call = createLeftCall(op, butLast); return op.createCall(new SqlNodeList(ImmutableList.of(call, last), POS)); }
private List<SargIntervalSequence> evaluateChildren(SargSetExpr setExpr) { List<SargIntervalSequence> list = new ArrayList<SargIntervalSequence>(); for (SargExpr child : setExpr.children) { SargIntervalSequence newSeq = child.evaluate(); list.add(newSeq); } return list; }
/** * Variant of {@link #trimFields(RelNode, BitSet, Set)} for {@link SetOpRel} (including UNION and * UNION ALL). */ public TrimResult trimFields( SetOpRel setOp, BitSet fieldsUsed, Set<RelDataTypeField> extraFields) { final RelDataType rowType = setOp.getRowType(); final int fieldCount = rowType.getFieldCount(); int changeCount = 0; // Fennel abhors an empty row type, so pretend that the parent rel // wants the last field. (The last field is the least likely to be a // system field.) if (fieldsUsed.isEmpty()) { fieldsUsed.set(rowType.getFieldCount() - 1); } // Compute the desired field mapping. Give the consumer the fields they // want, in the order that they appear in the bitset. final Mapping mapping = createMapping(fieldsUsed, fieldCount); // Create input with trimmed columns. final List<RelNode> newInputs = new ArrayList<RelNode>(); for (RelNode input : setOp.getInputs()) { TrimResult trimResult = trimChild(setOp, input, fieldsUsed, extraFields); RelNode newInput = trimResult.left; final Mapping inputMapping = trimResult.right; // We want "mapping", the input gave us "inputMapping", compute // "remaining" mapping. // | | | // |---------------- mapping ---------->| // |-- inputMapping -->| | // | |-- remaining -->| // // For instance, suppose we have columns [a, b, c, d], // the consumer asked for mapping = [b, d], // and the transformed input has columns inputMapping = [d, a, b]. // remaining will permute [b, d] to [d, a, b]. Mapping remaining = Mappings.divide(mapping, inputMapping); // Create a projection; does nothing if remaining is identity. newInput = CalcRel.projectMapping(newInput, remaining, null); if (input != newInput) { ++changeCount; } newInputs.add(newInput); } // If the input is unchanged, and we need to project all columns, // there's to do. if (changeCount == 0 && mapping.isIdentity()) { return new TrimResult(setOp, mapping); } RelNode newSetOp = setOp.copy(setOp.getTraitSet(), newInputs); return new TrimResult(newSetOp, mapping); }
public void onMatch(RelOptRuleCall call) { CalcRel calc = (CalcRel) call.getRels()[0]; RexProgram program = calc.getProgram(); final List<RexNode> exprList = program.getExprList(); // Form a list of expressions with sub-expressions fully // expanded. final List<RexNode> expandedExprList = new ArrayList<RexNode>(exprList.size()); final RexShuttle shuttle = new RexShuttle() { public RexNode visitLocalRef(RexLocalRef localRef) { return expandedExprList.get(localRef.getIndex()); } }; for (RexNode expr : exprList) { expandedExprList.add(expr.accept(shuttle)); } if (reduceExpressions(calc, expandedExprList)) { final RexProgramBuilder builder = new RexProgramBuilder( calc.getChild().getRowType(), calc.getCluster().getRexBuilder()); List<RexLocalRef> list = new ArrayList<RexLocalRef>(); for (RexNode expr : expandedExprList) { list.add(builder.registerInput(expr)); } if (program.getCondition() != null) { final int conditionIndex = program.getCondition().getIndex(); final RexNode newConditionExp = expandedExprList.get(conditionIndex); if (newConditionExp.isAlwaysTrue()) { // condition is always TRUE - drop it } else if ((newConditionExp instanceof RexLiteral) || RexUtil.isNullLiteral(newConditionExp, true)) { // condition is always NULL or FALSE - replace calc // with empty call.transformTo(new EmptyRel(calc.getCluster(), calc.getRowType())); return; } else { builder.addCondition(list.get(conditionIndex)); } } int k = 0; for (RexLocalRef projectExpr : program.getProjectList()) { final int index = projectExpr.getIndex(); builder.addProject( list.get(index).getIndex(), program.getOutputRowType().getFieldList().get(k++).getName()); } call.transformTo( new CalcRel( calc.getCluster(), calc.getTraits(), calc.getChild(), calc.getRowType(), builder.getProgram(), calc.getCollationList())); // New plan is absolutely better than old plan. call.getPlanner().setImportance(calc, 0.0); } }
/** Splits a condition into conjunctions that do or do not intersect with a given bit set. */ static void split( RexNode condition, BitSet bitSet, List<RexNode> intersecting, List<RexNode> nonIntersecting) { for (RexNode node : RelOptUtil.conjunctions(condition)) { BitSet inputBitSet = RelOptUtil.InputFinder.bits(node); if (bitSet.intersects(inputBitSet)) { intersecting.add(node); } else { nonIntersecting.add(node); } } }
/** Converts a call to an aggregate function to an expression. */ public SqlNode toSql(AggregateCall aggCall) { SqlOperator op = (SqlAggFunction) aggCall.getAggregation(); final List<SqlNode> operands = Expressions.list(); for (int arg : aggCall.getArgList()) { operands.add(field(arg)); } return op.createCall( aggCall.isDistinct() ? SqlSelectKeyword.DISTINCT.symbol(POS) : null, POS, operands.toArray(new SqlNode[operands.size()])); }
public static Expression translateCondition( List<Expression> inputs, RexProgram program, JavaTypeFactory typeFactory, List<Statement> list) { List<Expression> x = new RexToLixTranslator(program, typeFactory, inputs) .translate(list, Collections.singletonList(program.getCondition())); assert x.size() == 1; return x.get(0); }
/** * Gets the expression for an input and counts it. * * @param index Input ordinal * @return Expression to which an input should be translated */ private Expression getInput(int index) { Slot slot = inputSlots.get(index); if (list == null) { slot.count++; } else { if (slot.count > 1 && slot.parameterExpression == null) { slot.parameterExpression = Expressions.parameter(slot.expression.type, "current" + index); list.add(Expressions.declare(Modifier.FINAL, slot.parameterExpression, slot.expression)); } } return slot.parameterExpression != null ? slot.parameterExpression : slot.expression; }
public void onMatch(RelOptRuleCall call) { JoinRel origJoinRel = (JoinRel) call.rels[0]; RelNode left = call.rels[1]; RelNode right = call.rels[2]; // combine the children MultiJoinRel inputs into an array of inputs // for the new MultiJoinRel List<BitSet> projFieldsList = new ArrayList<BitSet>(); List<int[]> joinFieldRefCountsList = new ArrayList<int[]>(); RelNode[] newInputs = combineInputs(origJoinRel, left, right, projFieldsList, joinFieldRefCountsList); // combine the outer join information from the left and right // inputs, and include the outer join information from the current // join, if it's a left/right outer join RexNode[] newOuterJoinConds = new RexNode[newInputs.length]; JoinRelType[] joinTypes = new JoinRelType[newInputs.length]; combineOuterJoins(origJoinRel, newInputs, left, right, newOuterJoinConds, joinTypes); // pull up the join filters from the children MultiJoinRels and // combine them with the join filter associated with this JoinRel to // form the join filter for the new MultiJoinRel RexNode newJoinFilter = combineJoinFilters(origJoinRel, left, right); // add on the join field reference counts for the join condition // associated with this JoinRel Map<Integer, int[]> newJoinFieldRefCountsMap = new HashMap<Integer, int[]>(); addOnJoinFieldRefCounts( newInputs, origJoinRel.getRowType().getFieldCount(), origJoinRel.getCondition(), joinFieldRefCountsList, newJoinFieldRefCountsMap); RexNode newPostJoinFilter = combinePostJoinFilters(origJoinRel, left, right); RelNode multiJoin = new MultiJoinRel( origJoinRel.getCluster(), newInputs, newJoinFilter, origJoinRel.getRowType(), (origJoinRel.getJoinType() == JoinRelType.FULL), newOuterJoinConds, joinTypes, projFieldsList.toArray(new BitSet[projFieldsList.size()]), newJoinFieldRefCountsMap, newPostJoinFilter); call.transformTo(multiJoin); }
/** * Locates expressions that can be reduced to literals or converted to expressions with redundant * casts removed. * * @param preparingStmt the statement containing the expressions * @param exps list of candidate expressions to be examined for reduction * @param constExps returns the list of expressions that can be constant reduced * @param addCasts indicator for each expression that can be constant reduced, whether a cast of * the resulting reduced expression is potentially necessary * @param removableCasts returns the list of cast expressions where the cast can be removed */ private static void findReducibleExps( FarragoSessionPreparingStmt preparingStmt, List<RexNode> exps, List<RexNode> constExps, List<Boolean> addCasts, List<RexNode> removableCasts) { ReducibleExprLocator gardener = new ReducibleExprLocator(preparingStmt, constExps, addCasts, removableCasts); for (RexNode exp : exps) { gardener.analyze(exp); } assert (constExps.size() == addCasts.size()); }
/** * Reconstructs a rex predicate from a list of SargBindings which are AND'ed together. * * @param sargBindingList list of SargBindings to be converted. * @return the rex predicate reconstructed from the list of SargBindings. */ public RexNode getSargBindingListToRexNode(List<SargBinding> sargBindingList) { if (sargBindingList.isEmpty()) { return null; } RexNode newAndNode = sarg2RexMap.get(sargBindingList.get(0).getExpr()); for (int i = 1; i < sargBindingList.size(); i++) { RexNode nextNode = sarg2RexMap.get(sargBindingList.get(i).getExpr()); newAndNode = factory.getRexBuilder().makeCall(SqlStdOperatorTable.andOperator, newAndNode, nextNode); } return newAndNode; }
public Boolean areColumnsUnique(ProjectRelBase rel, BitSet columns, boolean ignoreNulls) { // ProjectRel maps a set of rows to a different set; // Without knowledge of the mapping function(whether it // preserves uniqueness), it is only safe to derive uniqueness // info from the child of a project when the mapping is f(a) => a. // // Also need to map the input column set to the corresponding child // references List<RexNode> projExprs = rel.getProjects(); BitSet childColumns = new BitSet(); for (int bit : BitSets.toIter(columns)) { RexNode projExpr = projExprs.get(bit); if (projExpr instanceof RexInputRef) { childColumns.set(((RexInputRef) projExpr).getIndex()); } else if (projExpr instanceof RexCall && ignoreNulls) { // If the expression is a cast such that the types are the same // except for the nullability, then if we're ignoring nulls, // it doesn't matter whether the underlying column reference // is nullable. Check that the types are the same by making a // nullable copy of both types and then comparing them. RexCall call = (RexCall) projExpr; if (call.getOperator() != SqlStdOperatorTable.CAST) { continue; } RexNode castOperand = call.getOperands().get(0); if (!(castOperand instanceof RexInputRef)) { continue; } RelDataTypeFactory typeFactory = rel.getCluster().getTypeFactory(); RelDataType castType = typeFactory.createTypeWithNullability(projExpr.getType(), true); RelDataType origType = typeFactory.createTypeWithNullability(castOperand.getType(), true); if (castType.equals(origType)) { childColumns.set(((RexInputRef) castOperand).getIndex()); } } else { // If the expression will not influence uniqueness of the // projection, then skip it. continue; } } // If no columns can affect uniqueness, then return unknown if (childColumns.cardinality() == 0) { return null; } return RelMetadataQuery.areColumnsUnique(rel.getChild(), childColumns, ignoreNulls); }
/** * Combines the inputs into a JoinRel into an array of inputs. * * @param join original join * @param left left input into join * @param right right input into join * @param projFieldsList returns a list of the new combined projection fields * @param joinFieldRefCountsList returns a list of the new combined join field reference counts * @return combined left and right inputs in an array */ private RelNode[] combineInputs( JoinRel join, RelNode left, RelNode right, List<BitSet> projFieldsList, List<int[]> joinFieldRefCountsList) { // leave the null generating sides of an outer join intact; don't // pull up those children inputs into the array we're constructing int nInputs; int nInputsOnLeft; MultiJoinRel leftMultiJoin = null; JoinRelType joinType = join.getJoinType(); boolean combineLeft = canCombine(left, joinType.generatesNullsOnLeft()); if (combineLeft) { leftMultiJoin = (MultiJoinRel) left; nInputs = left.getInputs().length; nInputsOnLeft = nInputs; } else { nInputs = 1; nInputsOnLeft = 1; } MultiJoinRel rightMultiJoin = null; boolean combineRight = canCombine(right, joinType.generatesNullsOnRight()); if (combineRight) { rightMultiJoin = (MultiJoinRel) right; nInputs += right.getInputs().length; } else { nInputs += 1; } RelNode[] newInputs = new RelNode[nInputs]; int i = 0; if (combineLeft) { for (; i < left.getInputs().length; i++) { newInputs[i] = leftMultiJoin.getInput(i); projFieldsList.add(((MultiJoinRel) left).getProjFields()[i]); joinFieldRefCountsList.add(((MultiJoinRel) left).getJoinFieldRefCountsMap().get(i)); } } else { newInputs[0] = left; i = 1; projFieldsList.add(null); joinFieldRefCountsList.add(new int[left.getRowType().getFieldCount()]); } if (combineRight) { for (; i < nInputs; i++) { newInputs[i] = rightMultiJoin.getInput(i - nInputsOnLeft); projFieldsList.add(((MultiJoinRel) right).getProjFields()[i - nInputsOnLeft]); joinFieldRefCountsList.add( ((MultiJoinRel) right).getJoinFieldRefCountsMap().get(i - nInputsOnLeft)); } } else { newInputs[i] = right; projFieldsList.add(null); joinFieldRefCountsList.add(new int[right.getRowType().getFieldCount()]); } return newInputs; }
// implement RelOptRule public void onMatch(RelOptRuleCall call) { ProjectRel origProj = call.rel(0); JoinRel joinRel = call.rel(1); // locate all fields referenced in the projection and join condition; // determine which inputs are referenced in the projection and // join condition; if all fields are being referenced and there are no // special expressions, no point in proceeding any further PushProjector pushProject = new PushProjector(origProj, joinRel.getCondition(), joinRel, preserveExprCondition); if (pushProject.locateAllRefs()) { return; } // create left and right projections, projecting only those // fields referenced on each side RelNode leftProjRel = pushProject.createProjectRefsAndExprs(joinRel.getLeft(), true, false); RelNode rightProjRel = pushProject.createProjectRefsAndExprs(joinRel.getRight(), true, true); // convert the join condition to reference the projected columns RexNode newJoinFilter = null; int[] adjustments = pushProject.getAdjustments(); if (joinRel.getCondition() != null) { List<RelDataTypeField> projJoinFieldList = new ArrayList<RelDataTypeField>(); projJoinFieldList.addAll(joinRel.getSystemFieldList()); projJoinFieldList.addAll(leftProjRel.getRowType().getFieldList()); projJoinFieldList.addAll(rightProjRel.getRowType().getFieldList()); newJoinFilter = pushProject.convertRefsAndExprs(joinRel.getCondition(), projJoinFieldList, adjustments); } // create a new joinrel with the projected children JoinRel newJoinRel = new JoinRel( joinRel.getCluster(), leftProjRel, rightProjRel, newJoinFilter, joinRel.getJoinType(), Collections.<String>emptySet(), joinRel.isSemiJoinDone(), joinRel.getSystemFieldList()); // put the original project on top of the join, converting it to // reference the modified projection list ProjectRel topProject = pushProject.createNewProject(newJoinRel, adjustments); call.transformTo(topProject); }
/** * Returns a relational expression which has the same fields as the underlying expression, but the * fields have different names. * * @param rel Relational expression * @param fieldNames Field names * @return Renamed relational expression */ public static RelNode createRename(RelNode rel, List<String> fieldNames) { final List<RelDataTypeField> fields = rel.getRowType().getFieldList(); assert fieldNames.size() == fields.size(); final List<Pair<RexNode, String>> refs = new AbstractList<Pair<RexNode, String>>() { public int size() { return fields.size(); } public Pair<RexNode, String> get(int index) { return RexInputRef.of2(index, fields); } }; return createProject(rel, refs, true); }
public void analyze(RexNode exp) { assert (stack.isEmpty()); exp.accept(this); // Deal with top of stack assert (stack.size() == 1); assert (parentCallTypeStack.isEmpty()); Constancy rootConstancy = stack.get(0); if (rootConstancy == Constancy.REDUCIBLE_CONSTANT) { // The entire subtree was constant, so add it to the result. addResult(exp); } stack.clear(); }
public SqlNode field(int ordinal) { for (Pair<String, RelDataType> alias : aliases) { final List<RelDataTypeField> fields = alias.right.getFieldList(); if (ordinal < fields.size()) { RelDataTypeField field = fields.get(ordinal); return new SqlIdentifier( !qualified ? ImmutableList.of(field.getName()) : ImmutableList.of(alias.left, field.getName()), POS); } ordinal -= fields.size(); } throw new AssertionError("field ordinal " + ordinal + " out of range " + aliases); }
private SargIntervalSequence evaluateIntersection(List<SargIntervalSequence> list) { SargIntervalSequence seq = null; if (list.isEmpty()) { // Counterintuitive but true: intersection of no sets is the // universal set (kinda like 2^0=1). One way to prove this to // yourself is to apply DeMorgan's law. The union of no sets is // certainly the empty set. So the complement of that union is the // universal set. That's equivalent to the intersection of the // complements of no sets, which is the intersection of no sets. // QED. seq = new SargIntervalSequence(); seq.addInterval(new SargInterval(factory, getDataType())); return seq; } // The way we evaluate the intersection is to start with the first // entry as a baseline, and then keep deleting stuff from it by // intersecting the other entrie in turn. Whatever makes it through // this filtering remains as the final result. for (SargIntervalSequence newSeq : list) { if (seq == null) { // first child seq = newSeq; continue; } intersectSequences(seq, newSeq); } return seq; }
/** * Reconstructs a rex predicate from the non-sargable filter predicates which are AND'ed together. * * @return the rex predicate reconstructed from the non-sargable predicates. */ public RexNode getNonSargFilterRexNode() { if (nonSargFilterList.isEmpty()) { return null; } RexNode newAndNode = nonSargFilterList.get(0); for (int i = 1; i < nonSargFilterList.size(); i++) { newAndNode = factory .getRexBuilder() .makeCall(SqlStdOperatorTable.andOperator, newAndNode, nonSargFilterList.get(i)); } return newAndNode; }
/** @return true if all tuples match rowType; otherwise, assert on mismatch */ private boolean assertRowType() { for (List<RexLiteral> tuple : tuples) { assert tuple.size() == rowType.getFieldCount(); for (Pair<RexLiteral, RelDataTypeField> pair : Pair.zip(tuple, rowType.getFieldList())) { RexLiteral literal = pair.left; RelDataType fieldType = pair.right.getType(); // TODO jvs 19-Feb-2006: strengthen this a bit. For example, // overflow, rounding, and padding/truncation must already have // been dealt with. if (!RexLiteral.isNullLiteral(literal)) { assert (SqlTypeUtil.canAssignFrom(fieldType, literal.getType())); } } } return true; }
private RexToLixTranslator( RexProgram program, JavaTypeFactory typeFactory, List<Expression> inputs) { this.program = program; this.typeFactory = typeFactory; for (Expression input : inputs) { inputSlots.add(new Slot(null, input)); } }