use of org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class EnumerableWindow method translateBound.
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);
}
use of org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class EnumerableWindow method implementResult.
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) {
// 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;
}
use of org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class EnumerableCorrelate method implement.
public Result implement(EnumerableRelImplementor implementor, Prefer pref) {
final BlockBuilder builder = new BlockBuilder();
final Result leftResult = implementor.visitChild(this, 0, (EnumerableRel) left, pref);
Expression leftExpression = builder.append("left", leftResult.block);
final BlockBuilder corrBlock = new BlockBuilder();
Type corrVarType = leftResult.physType.getJavaRowType();
// correlate to be used in inner loop
ParameterExpression corrRef;
// argument to correlate lambda (must be boxed)
ParameterExpression corrArg;
if (!Primitive.is(corrVarType)) {
corrArg = Expressions.parameter(Modifier.FINAL, corrVarType, getCorrelVariable());
corrRef = corrArg;
} else {
corrArg = Expressions.parameter(Modifier.FINAL, Primitive.box(corrVarType), "$box" + getCorrelVariable());
corrRef = (ParameterExpression) corrBlock.append(getCorrelVariable(), Expressions.unbox(corrArg));
}
implementor.registerCorrelVariable(getCorrelVariable(), corrRef, corrBlock, leftResult.physType);
final Result rightResult = implementor.visitChild(this, 1, (EnumerableRel) right, pref);
implementor.clearCorrelVariable(getCorrelVariable());
corrBlock.add(rightResult.block);
final PhysType physType = PhysTypeImpl.of(implementor.getTypeFactory(), getRowType(), pref.prefer(JavaRowFormat.CUSTOM));
Expression selector = EnumUtils.joinSelector(joinType.returnsJustFirstInput() ? joinType.toJoinType() : JoinRelType.INNER, physType, ImmutableList.of(leftResult.physType, rightResult.physType));
builder.append(Expressions.call(leftExpression, BuiltInMethod.CORRELATE_JOIN.method, Expressions.constant(joinType.toLinq4j()), Expressions.lambda(corrBlock.toBlock(), corrArg), selector));
return implementor.result(physType, builder.toBlock());
}
use of org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class SqlUserDefinedTableMacro method coerce.
private static Object coerce(Object o, RelDataType type) {
if (o == null) {
return null;
}
if (!(type instanceof RelDataTypeFactoryImpl.JavaType)) {
return null;
}
final RelDataTypeFactoryImpl.JavaType javaType = (RelDataTypeFactoryImpl.JavaType) type;
final Class clazz = javaType.getJavaClass();
// noinspection unchecked
if (clazz.isAssignableFrom(o.getClass())) {
return o;
}
if (clazz == String.class && o instanceof NlsString) {
return ((NlsString) o).getValue();
}
// We need optimization here for constant folding.
// Not all the expressions can be interpreted (e.g. ternary), so
// we rely on optimization capabilities to fold non-interpretable
// expressions.
BlockBuilder bb = new BlockBuilder();
final Expression expr = RexToLixTranslator.convert(Expressions.constant(o), clazz);
bb.add(Expressions.return_(null, expr));
final FunctionExpression convert = Expressions.lambda(bb.toBlock(), Collections.<ParameterExpression>emptyList());
return convert.compile().dynamicInvoke();
}
use of org.apache.calcite.linq4j.tree.Expression in project calcite by apache.
the class JdbcToSparkConverter method implementSpark.
public SparkRel.Result implementSpark(SparkRel.Implementor implementor) {
// Generate:
// ResultSetEnumerable.of(schema.getDataSource(), "select ...")
final BlockBuilder list = new BlockBuilder();
final JdbcRel child = (JdbcRel) getInput();
final PhysType physType = PhysTypeImpl.of(implementor.getTypeFactory(), getRowType(), JavaRowFormat.CUSTOM);
final JdbcConvention jdbcConvention = (JdbcConvention) child.getConvention();
String sql = generateSql(jdbcConvention.dialect);
if (CalcitePrepareImpl.DEBUG) {
System.out.println("[" + sql + "]");
}
final Expression sqlLiteral = list.append("sql", Expressions.constant(sql));
final List<Primitive> primitives = new ArrayList<Primitive>();
for (int i = 0; i < getRowType().getFieldCount(); i++) {
final Primitive primitive = Primitive.ofBoxOr(physType.fieldClass(i));
primitives.add(primitive != null ? primitive : Primitive.OTHER);
}
final Expression primitivesLiteral = list.append("primitives", Expressions.constant(primitives.toArray(new Primitive[primitives.size()])));
final Expression enumerable = list.append("enumerable", Expressions.call(BuiltInMethod.RESULT_SET_ENUMERABLE_OF.method, Expressions.call(Expressions.convert_(jdbcConvention.expression, JdbcSchema.class), BuiltInMethod.JDBC_SCHEMA_DATA_SOURCE.method), sqlLiteral, primitivesLiteral));
list.add(Expressions.return_(null, enumerable));
return implementor.result(physType, list.toBlock());
}
Aggregations