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;
body.add(
Expressions.statement(
Expressions.assign(
parameterC,