}
public QueryResult performQuery(Query query) throws IOException {
validateQuery(query);
final StructBuilder fromKeyStructBuilder = new StructBuilder();
final StructBuilder toKeyStructBuilder = new StructBuilder();
// Construct from and to keys
final List<Object> fromKeyComponents = new ArrayList<Object>(definition.getFields().size());
byte[] fromKey = null;
byte[] toKey = null;
final Query.RangeCondition rangeCond = query.getRangeCondition();
boolean rangeCondSet = false;
int usedConditionsCount = 0;
int definedFieldsIndex = 0;
// loop through all defined index fields, and see if they occur in the query
for (; definedFieldsIndex < definition.getFields().size(); definedFieldsIndex++) {
final IndexFieldDefinition fieldDef = definition.getFields().get(definedFieldsIndex);
final Query.EqualsCondition eqCond = query.getCondition(fieldDef.getName());
if (eqCond != null) {
// there is an equality condition for this field
checkQueryValueType(fieldDef, eqCond.getValue());
final RowKey key = fieldDef.asRowKey();
key.setTermination(Termination.MUST);
fromKeyStructBuilder.add(key);
fromKeyComponents.add(eqCond.getValue());
usedConditionsCount++;
} else if (rangeCond != null) {
// no equality condition for this field, but there is a range condition
if (!rangeCond.getName().equals(fieldDef.getName())) {
throw new MalformedQueryException("Query defines range condition on field " + rangeCond.getName() +
" but has no equals condition on field " + fieldDef.getName() +
" which comes earlier in the index definition.");
}
final List<Object> toKeyComponents = new ArrayList<Object>(fromKeyComponents.size() + 1);
toKeyComponents.addAll(fromKeyComponents);
for (RowKey rowKey : fromKeyStructBuilder.getFields()) {
toKeyStructBuilder.add(rowKey);
}
final Object fromValue = query.getRangeCondition().getFromValue();
final Object toValue = query.getRangeCondition().getToValue();
if (fromValue == Query.MIN_VALUE) {
// just leave of the value, a shorter key is smaller than anything else
} else {
checkQueryValueType(fieldDef, fromValue);
fromKeyComponents.add(fromValue);
fromKeyStructBuilder.add(fieldDef.asRowKeyWithoutTermination());
}
if (toValue == Query.MAX_VALUE) {
// Searching to max value is equal to a prefix search (assumes always exclusive interval,
// since max value is bigger than anything else)
// So, append nothing to the search key.
} else {
checkQueryValueType(fieldDef, toValue);
toKeyComponents.add(toValue);
toKeyStructBuilder.add(fieldDef.asRowKeyWithoutTermination());
}
final StructRowKey frk = fromKeyStructBuilder.toRowKey();
fromKey = frk.serialize(fromKeyComponents.toArray());
final StructRowKey trk = toKeyStructBuilder.toRowKey();
toKey = trk.serialize(toKeyComponents.toArray());
rangeCondSet = true;
usedConditionsCount++;