if (startKey != null) {
if (startBoundColumns == 0) {
startKey.append(startBoundary);
} else {
// Check constraints on start and end
ValueRecord loExpressions = lo.boundExpressions(context, bindings);
ValueRecord hiExpressions = hi.boundExpressions(context, bindings);
for (int f = 0; f < endBoundColumns - 1; f++) {
keyAdapter.checkConstraints(loExpressions, hiExpressions, f, null, types);
}
/*
Null bounds are slightly tricky. An index restriction is described by an IndexKeyRange which contains
two IndexBounds. The IndexBound wraps an index row. The fields of the row that are being restricted are
described by the IndexBound's ColumnSelector. The only index restrictions supported specify:
a) equality for zero or more fields of the index,
b) 0-1 inequality, and
c) any remaining columns unbounded.
By the time we get here, we've stopped paying attention to part c. Parts a and b occupy the first
orderingColumns columns of the index. Now about the nulls: For each field of parts a and b, we have a
lo value and a hi value. There are four cases:
- both lo and hi are non-null: Just write the field values into startKey and endKey.
- lo is null: Write null into the startKey.
- hi is null, lo is not null: This restriction says that we want everything to the right of
the lo value. Persistit ranks null lower than anything, so instead of writing null to endKey,
we write Key.AFTER.
- lo and hi are both null: This is NOT an unbounded case. This means that we are restricting both
lo and hi to be null, so write null, not Key.AFTER to endKey.
*/
// Construct start and end keys
ValueRecord startExpressions = start.boundExpressions(context, bindings);
ValueRecord endExpressions = end.boundExpressions(context, bindings);
// startBoundColumns == endBoundColumns because jump() hasn't been called.
// If it had we'd be in reevaluateBoundaries, not here.
assert startBoundColumns == endBoundColumns;
S[] startValues = keyAdapter.createSourceArray(startBoundColumns);
S[] endValues = keyAdapter.createSourceArray(endBoundColumns);