use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.linq4j.tree.Expression in project storm by apache.
the class RexNodeToJavaCodeCompiler method compileToBlock.
private BlockBuilder compileToBlock(final RexProgram program, ParameterExpression context, ParameterExpression outputValues) {
RelDataType inputRowType = program.getInputRowType();
final BlockBuilder builder = new BlockBuilder();
final JavaTypeFactoryImpl javaTypeFactory = new JavaTypeFactoryImpl(rexBuilder.getTypeFactory().getTypeSystem());
final RexToLixTranslator.InputGetter inputGetter = new RexToLixTranslator.InputGetterImpl(ImmutableList.of(Pair.<Expression, PhysType>of(Expressions.field(context, BuiltInMethod.CONTEXT_VALUES.field), PhysTypeImpl.of(javaTypeFactory, inputRowType, JavaRowFormat.ARRAY, false))));
final Function1<String, RexToLixTranslator.InputGetter> correlates = new Function1<String, RexToLixTranslator.InputGetter>() {
@Override
public RexToLixTranslator.InputGetter apply(String a0) {
throw new UnsupportedOperationException();
}
};
final Expression root = Expressions.field(context, BuiltInMethod.CONTEXT_ROOT.field);
final List<Expression> list = RexToLixTranslator.translateProjects(program, javaTypeFactory, builder, null, root, inputGetter, correlates);
for (int i = 0; i < list.size(); i++) {
builder.add(Expressions.statement(Expressions.assign(Expressions.arrayIndex(outputValues, Expressions.constant(i)), list.get(i))));
}
return builder;
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.linq4j.tree.Expression in project storm by apache.
the class RexNodeToJavaCodeCompiler method baz.
/**
* Given a method that implements {@link ExecutableExpression#execute(Context, Object[])}, adds a bridge method that
* implements {@link ExecutableExpression#execute(Context)}, and compiles.
*/
static String baz(ParameterExpression context, ParameterExpression outputValues, BlockStatement block, String className) {
final List<MemberDeclaration> declarations = Lists.newArrayList();
// public void execute(Context, Object[] outputValues)
declarations.add(Expressions.methodDecl(Modifier.PUBLIC, void.class, StormBuiltInMethod.EXPR_EXECUTE2.method.getName(), ImmutableList.of(context, outputValues), block));
// public Object execute(Context)
final BlockBuilder builder = new BlockBuilder();
final Expression values_ = builder.append("values", Expressions.newArrayBounds(Object.class, 1, Expressions.constant(1)));
builder.add(Expressions.statement(Expressions.call(Expressions.parameter(ExecutableExpression.class, "this"), StormBuiltInMethod.EXPR_EXECUTE2.method, context, values_)));
builder.add(Expressions.return_(null, Expressions.arrayIndex(values_, Expressions.constant(0))));
declarations.add(Expressions.methodDecl(Modifier.PUBLIC, Object.class, StormBuiltInMethod.EXPR_EXECUTE1.method.getName(), ImmutableList.of(context), builder.toBlock()));
final ClassDeclaration classDeclaration = Expressions.classDecl(Modifier.PUBLIC, className, null, ImmutableList.<Type>of(ExecutableExpression.class), declarations);
return Expressions.toString(Lists.newArrayList(classDeclaration), "\n", false);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.linq4j.tree.Expression in project beam by apache.
the class CalcRelSplitter method chooseLevels.
/**
* Figures out which expressions to calculate at which level.
*
* @param exprs Array of expressions
* @param conditionOrdinal Ordinal of the condition expression, or -1 if no condition
* @param exprLevels Level ordinal for each expression (output)
* @param levelTypeOrdinals The type of each level (output)
* @return Number of levels required
*/
private int chooseLevels(final RexNode[] exprs, int conditionOrdinal, int[] exprLevels, int[] levelTypeOrdinals) {
final int inputFieldCount = program.getInputRowType().getFieldCount();
int levelCount = 0;
final MaxInputFinder maxInputFinder = new MaxInputFinder(exprLevels);
boolean[] relTypesPossibleForTopLevel = new boolean[relTypes.length];
Arrays.fill(relTypesPossibleForTopLevel, true);
// Compute the order in which to visit expressions.
final List<Set<Integer>> cohorts = getCohorts();
final List<Integer> permutation = computeTopologicalOrdering(exprs, cohorts);
for (int i : permutation) {
RexNode expr = exprs[i];
final boolean condition = i == conditionOrdinal;
if (i < inputFieldCount) {
assert expr instanceof RexInputRef;
exprLevels[i] = -1;
continue;
}
// Deduce the minimum level of the expression. An expression must
// be at a level greater than or equal to all of its inputs.
int level = maxInputFinder.maxInputFor(expr);
// If the expression is in a cohort, it can occur no lower than the
// levels of other expressions in the same cohort.
Set<Integer> cohort = findCohort(cohorts, i);
if (cohort != null) {
for (Integer exprOrdinal : cohort) {
if (exprOrdinal == i) {
// of effort to repeat.
continue;
}
final RexNode cohortExpr = exprs[exprOrdinal];
int cohortLevel = maxInputFinder.maxInputFor(cohortExpr);
if (cohortLevel > level) {
level = cohortLevel;
}
}
}
// If that is not possible, try to implement it at higher levels.
levelLoop: for (; ; ++level) {
if (level >= levelCount) {
// This is a new level. We can use any type we like.
for (int relTypeOrdinal = 0; relTypeOrdinal < relTypes.length; relTypeOrdinal++) {
if (!relTypesPossibleForTopLevel[relTypeOrdinal]) {
continue;
}
if (relTypes[relTypeOrdinal].canImplement(expr, condition)) {
// Success. We have found a type where we can
// implement this expression.
exprLevels[i] = level;
levelTypeOrdinals[level] = relTypeOrdinal;
assert (level == 0) || (levelTypeOrdinals[level - 1] != levelTypeOrdinals[level]) : "successive levels of same type";
// Previous reltypes are not possible.
for (int j = 0; j < relTypeOrdinal; ++j) {
relTypesPossibleForTopLevel[j] = false;
}
// Successive reltypes may be possible.
for (int j = relTypeOrdinal + 1; j < relTypes.length; ++j) {
if (relTypesPossibleForTopLevel[j]) {
relTypesPossibleForTopLevel[j] = relTypes[j].canImplement(expr, condition);
}
}
// Move to next level.
levelTypeOrdinals[levelCount] = firstSet(relTypesPossibleForTopLevel);
++levelCount;
Arrays.fill(relTypesPossibleForTopLevel, true);
break levelLoop;
}
}
// level, with all options open?
if (count(relTypesPossibleForTopLevel) >= relTypes.length) {
// Cannot implement for any type.
throw new AssertionError("cannot implement " + expr);
}
levelTypeOrdinals[levelCount] = firstSet(relTypesPossibleForTopLevel);
++levelCount;
Arrays.fill(relTypesPossibleForTopLevel, true);
} else {
final int levelTypeOrdinal = levelTypeOrdinals[level];
if (!relTypes[levelTypeOrdinal].canImplement(expr, condition)) {
// continue to next level.
continue;
}
exprLevels[i] = level;
break;
}
}
}
if (levelCount == 0) {
// At least one level is always required.
levelCount = 1;
}
return levelCount;
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.linq4j.tree.Expression in project beam by apache.
the class CalcRelSplitter method execute.
// ~ Methods ----------------------------------------------------------------
public RelNode execute() {
// expressions to the left.
assert program.isValid(Litmus.THROW, null);
final List<RexNode> exprList = program.getExprList();
final RexNode[] exprs = exprList.toArray(new RexNode[0]);
assert !RexUtil.containComplexExprs(exprList);
// Figure out what level each expression belongs to.
int[] exprLevels = new int[exprs.length];
// The type of a level is given by
// relTypes[levelTypeOrdinals[level]].
int[] levelTypeOrdinals = new int[exprs.length];
int levelCount = chooseLevels(exprs, -1, exprLevels, levelTypeOrdinals);
// For each expression, figure out which is the highest level where it
// is used.
int[] exprMaxUsingLevelOrdinals = new HighestUsageFinder(exprs, exprLevels).getMaxUsingLevelOrdinals();
// If expressions are used as outputs, mark them as higher than that.
final List<RexLocalRef> projectRefList = program.getProjectList();
final RexLocalRef conditionRef = program.getCondition();
for (RexLocalRef projectRef : projectRefList) {
exprMaxUsingLevelOrdinals[projectRef.getIndex()] = levelCount;
}
if (conditionRef != null) {
exprMaxUsingLevelOrdinals[conditionRef.getIndex()] = levelCount;
}
// Print out what we've got.
if (RULE_LOGGER.isTraceEnabled()) {
traceLevelExpressions(exprs, exprLevels, levelTypeOrdinals, levelCount);
}
// Now build the calcs.
RelNode rel = child;
final int inputFieldCount = program.getInputRowType().getFieldCount();
int[] inputExprOrdinals = identityArray(inputFieldCount);
boolean doneCondition = false;
for (int level = 0; level < levelCount; level++) {
final int[] projectExprOrdinals;
final RelDataType outputRowType;
if (level == (levelCount - 1)) {
outputRowType = program.getOutputRowType();
projectExprOrdinals = new int[projectRefList.size()];
for (int i = 0; i < projectExprOrdinals.length; i++) {
projectExprOrdinals[i] = projectRefList.get(i).getIndex();
}
} else {
outputRowType = null;
// Project the expressions which are computed at this level or
// before, and will be used at later levels.
List<Integer> projectExprOrdinalList = new ArrayList<>();
for (int i = 0; i < exprs.length; i++) {
RexNode expr = exprs[i];
if (expr instanceof RexLiteral) {
// Don't project literals. They are always created in
// the level where they are used.
exprLevels[i] = -1;
continue;
}
if ((exprLevels[i] <= level) && (exprMaxUsingLevelOrdinals[i] > level)) {
projectExprOrdinalList.add(i);
}
}
projectExprOrdinals = Ints.toArray(projectExprOrdinalList);
}
final RelType relType = relTypes[levelTypeOrdinals[level]];
// Can we do the condition this level?
int conditionExprOrdinal = -1;
if ((conditionRef != null) && !doneCondition) {
conditionExprOrdinal = conditionRef.getIndex();
if ((exprLevels[conditionExprOrdinal] > level) || !relType.supportsCondition()) {
// stand down -- we're not ready to do the condition yet
conditionExprOrdinal = -1;
} else {
doneCondition = true;
}
}
RexProgram program1 = createProgramForLevel(level, levelCount, rel.getRowType(), exprs, exprLevels, inputExprOrdinals, projectExprOrdinals, conditionExprOrdinal, outputRowType);
rel = relType.makeRel(cluster, traits, relBuilder, rel, program1);
rel = handle(rel);
// The outputs of this level will be the inputs to the next level.
inputExprOrdinals = projectExprOrdinals;
}
Preconditions.checkArgument(doneCondition || (conditionRef == null), "unhandled condition");
return rel;
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.linq4j.tree.Expression in project beam by apache.
the class CalcRelSplitter method computeTopologicalOrdering.
/**
* Computes the order in which to visit expressions, so that we decide the level of an expression
* only after the levels of lower expressions have been decided.
*
* <p>First, we need to ensure that an expression is visited after all of its inputs.
*
* <p>Further, if the expression is a member of a cohort, we need to visit it after the inputs of
* all other expressions in that cohort. With this condition, expressions in the same cohort will
* very likely end up in the same level.
*
* <p>Note that if there are no cohorts, the expressions from the {@link RexProgram} are already
* in a suitable order. We perform the topological sort just to ensure that the code path is
* well-trodden.
*
* @param exprs Expressions
* @param cohorts List of cohorts, each of which is a set of expr ordinals
* @return Expression ordinals in topological order
*/
private static List<Integer> computeTopologicalOrdering(RexNode[] exprs, List<Set<Integer>> cohorts) {
final DirectedGraph<Integer, DefaultEdge> graph = DefaultDirectedGraph.create();
for (int i = 0; i < exprs.length; i++) {
graph.addVertex(i);
}
for (int i = 0; i < exprs.length; i++) {
final RexNode expr = exprs[i];
final Set<Integer> cohort = findCohort(cohorts, i);
final Set<Integer> targets;
if (cohort == null) {
targets = Collections.singleton(i);
} else {
targets = cohort;
}
expr.accept(new RexVisitorImpl<Void>(true) {
@Override
public Void visitLocalRef(RexLocalRef localRef) {
for (Integer target : targets) {
graph.addEdge(localRef.getIndex(), target);
}
return null;
}
});
}
TopologicalOrderIterator<Integer, DefaultEdge> iter = new TopologicalOrderIterator<>(graph);
final List<Integer> permutation = new ArrayList<>();
while (iter.hasNext()) {
permutation.add(iter.next());
}
return permutation;
}
Aggregations