private IndexCursorSpatial_NearPoint(QueryContext context, IterationHelper iterationHelper, IndexKeyRange keyRange)
{
super(context, iterationHelper);
assert keyRange.spatial();
this.iterationHelper = iterationHelper;
IndexRowType physicalIndexRowType = keyRange.indexRowType().physicalRowType();
Index index = keyRange.indexRowType().index();
Space space = index.space();
int latColumn = index.firstSpatialArgument();
int lonColumn = latColumn + 1;
// The index column selector needs to select all the columns before the z column, and the z column itself.
IndexRowPrefixSelector indexColumnSelector = new IndexRowPrefixSelector(latColumn + 1);
IndexBound loBound = keyRange.lo();
ValueRecord loExpressions = loBound.boundExpressions(context, bindings);
// Compute z-value at beginning of forward and backward scans
TInstance latInstance = index.getAllColumns().get(latColumn).getColumn().getType();
TInstance lonInstance = index.getAllColumns().get(lonColumn).getColumn().getType();
BigDecimal lat = TBigDecimal.getWrapper(loExpressions.value(latColumn), latInstance).asBigDecimal();
BigDecimal lon = TBigDecimal.getWrapper(loExpressions.value(lonColumn), lonInstance).asBigDecimal();
zStart = Spatial.shuffle(space, lat.doubleValue(), lon.doubleValue());
// Cursors going forward from starting z value (inclusive), and backward from the same z value (exclusive)
int indexRowFields = physicalIndexRowType.nFields();
SpatialIndexValueRecord zForwardRow = new SpatialIndexValueRecord(indexRowFields);
SpatialIndexValueRecord zBackwardRow = new SpatialIndexValueRecord(indexRowFields);
SpatialIndexValueRecord zMaxRow = new SpatialIndexValueRecord(indexRowFields);
SpatialIndexValueRecord zMinRow = new SpatialIndexValueRecord(indexRowFields);
IndexBound zForward = new IndexBound(zForwardRow, indexColumnSelector);
IndexBound zBackward = new IndexBound(zBackwardRow, indexColumnSelector);
IndexBound zMax = new IndexBound(zMaxRow, indexColumnSelector);
IndexBound zMin = new IndexBound(zMinRow, indexColumnSelector);
// Take care of any equality restrictions before the spatial fields
zPosition = latColumn;
for (int f = 0; f < zPosition; f++) {
ValueSource eqValueSource = loExpressions.value(f);
zForwardRow.value(f, eqValueSource);
zBackwardRow.value(f, eqValueSource);
zMaxRow.value(f, eqValueSource);
zMinRow.value(f, eqValueSource);
}
// Z-value part of bounds
Value startValue = new Value(InternalIndexTypes.LONG.instance(false));
Value maxValue = new Value(InternalIndexTypes.LONG.instance(false));
Value minValue = new Value(InternalIndexTypes.LONG.instance(false));
startValue.putInt64(zStart);
maxValue.putInt64(Long.MAX_VALUE);
minValue.putInt64(Long.MIN_VALUE);
zForwardRow.value(zPosition, startValue);
zBackwardRow.value(zPosition, startValue);
zMaxRow.value(zPosition, maxValue);
zMinRow.value(zPosition, minValue);
IndexKeyRange geKeyRange = IndexKeyRange.bounded(physicalIndexRowType, zForward, true, zMax, false);
IndexKeyRange ltKeyRange = IndexKeyRange.bounded(physicalIndexRowType, zMin, false, zBackward, false);
IterationHelper geRowState = adapter.createIterationHelper(keyRange.indexRowType());
IterationHelper ltRowState = adapter.createIterationHelper(keyRange.indexRowType());
API.Ordering upOrdering = new API.Ordering();
API.Ordering downOrdering = new API.Ordering();
for (int f = 0; f < physicalIndexRowType.nFields(); f++) {
// TODO: This seems like an API hack
upOrdering.append((TPreparedExpression)null, true);
downOrdering.append((TPreparedExpression)null, false);
}
geCursor = new IndexCursorUnidirectional<>(context,