use of org.apache.calcite.sql.validate.SqlMonotonicity in project flink by apache.
the class RankProcessStrategy method analyzeRankProcessStrategies.
/**
* Gets {@link RankProcessStrategy} based on input, partitionKey and orderKey.
*/
static List<RankProcessStrategy> analyzeRankProcessStrategies(StreamPhysicalRel rank, ImmutableBitSet partitionKey, RelCollation orderKey) {
FlinkRelMetadataQuery mq = (FlinkRelMetadataQuery) rank.getCluster().getMetadataQuery();
List<RelFieldCollation> fieldCollations = orderKey.getFieldCollations();
boolean isUpdateStream = !ChangelogPlanUtils.inputInsertOnly(rank);
RelNode input = rank.getInput(0);
if (isUpdateStream) {
Set<ImmutableBitSet> upsertKeys = mq.getUpsertKeysInKeyGroupRange(input, partitionKey.toArray());
if (upsertKeys == null || upsertKeys.isEmpty() || // upsert key should contains partition key
upsertKeys.stream().noneMatch(k -> k.contains(partitionKey))) {
// and we fall back to using retract rank
return Collections.singletonList(RETRACT_STRATEGY);
} else {
FlinkRelMetadataQuery fmq = FlinkRelMetadataQuery.reuseOrCreate(mq);
RelModifiedMonotonicity monotonicity = fmq.getRelModifiedMonotonicity(input);
boolean isMonotonic = false;
if (monotonicity != null && !fieldCollations.isEmpty()) {
isMonotonic = fieldCollations.stream().allMatch(collation -> {
SqlMonotonicity fieldMonotonicity = monotonicity.fieldMonotonicities()[collation.getFieldIndex()];
RelFieldCollation.Direction direction = collation.direction;
if ((fieldMonotonicity == SqlMonotonicity.DECREASING || fieldMonotonicity == SqlMonotonicity.STRICTLY_DECREASING) && direction == RelFieldCollation.Direction.ASCENDING) {
// is decreasing
return true;
} else if ((fieldMonotonicity == SqlMonotonicity.INCREASING || fieldMonotonicity == SqlMonotonicity.STRICTLY_INCREASING) && direction == RelFieldCollation.Direction.DESCENDING) {
// is increasing
return true;
} else {
// it is monotonic
return fieldMonotonicity == SqlMonotonicity.CONSTANT;
}
});
}
if (isMonotonic) {
// TODO: choose a set of primary key
return Arrays.asList(new UpdateFastStrategy(upsertKeys.iterator().next().toArray()), RETRACT_STRATEGY);
} else {
return Collections.singletonList(RETRACT_STRATEGY);
}
}
} else {
return Collections.singletonList(APPEND_FAST_STRATEGY);
}
}
use of org.apache.calcite.sql.validate.SqlMonotonicity in project calcite by apache.
the class RelMdCollation method project.
/**
* Helper method to determine a {@link Project}'s collation.
*/
public static List<RelCollation> project(RelMetadataQuery mq, RelNode input, List<? extends RexNode> projects) {
final SortedSet<RelCollation> collations = new TreeSet<>();
final List<RelCollation> inputCollations = mq.collations(input);
if (inputCollations == null || inputCollations.isEmpty()) {
return ImmutableList.of();
}
final Multimap<Integer, Integer> targets = LinkedListMultimap.create();
final Map<Integer, SqlMonotonicity> targetsWithMonotonicity = new HashMap<>();
for (Ord<RexNode> project : Ord.<RexNode>zip(projects)) {
if (project.e instanceof RexInputRef) {
targets.put(((RexInputRef) project.e).getIndex(), project.i);
} else if (project.e instanceof RexCall) {
final RexCall call = (RexCall) project.e;
final RexCallBinding binding = RexCallBinding.create(input.getCluster().getTypeFactory(), call, inputCollations);
targetsWithMonotonicity.put(project.i, call.getOperator().getMonotonicity(binding));
}
}
final List<RelFieldCollation> fieldCollations = new ArrayList<>();
loop: for (RelCollation ic : inputCollations) {
if (ic.getFieldCollations().isEmpty()) {
continue;
}
fieldCollations.clear();
for (RelFieldCollation ifc : ic.getFieldCollations()) {
final Collection<Integer> integers = targets.get(ifc.getFieldIndex());
if (integers.isEmpty()) {
// cannot do this collation
continue loop;
}
fieldCollations.add(ifc.copy(integers.iterator().next()));
}
assert !fieldCollations.isEmpty();
collations.add(RelCollations.of(fieldCollations));
}
final List<RelFieldCollation> fieldCollationsForRexCalls = new ArrayList<>();
for (Map.Entry<Integer, SqlMonotonicity> entry : targetsWithMonotonicity.entrySet()) {
final SqlMonotonicity value = entry.getValue();
switch(value) {
case NOT_MONOTONIC:
case CONSTANT:
break;
default:
fieldCollationsForRexCalls.add(new RelFieldCollation(entry.getKey(), RelFieldCollation.Direction.of(value)));
break;
}
}
if (!fieldCollationsForRexCalls.isEmpty()) {
collations.add(RelCollations.of(fieldCollationsForRexCalls));
}
return ImmutableList.copyOf(collations);
}
use of org.apache.calcite.sql.validate.SqlMonotonicity in project calcite by apache.
the class SqlTesterImpl method checkMonotonic.
public void checkMonotonic(String query, SqlMonotonicity expectedMonotonicity) {
SqlValidator validator = getValidator();
SqlNode n = parseAndValidate(validator, query);
final RelDataType rowType = validator.getValidatedNodeType(n);
final SqlValidatorNamespace selectNamespace = validator.getNamespace(n);
final String field0 = rowType.getFieldList().get(0).getName();
final SqlMonotonicity monotonicity = selectNamespace.getMonotonicity(field0);
assertThat(monotonicity, equalTo(expectedMonotonicity));
}
Aggregations