Package com.foundationdb.qp.storeadapter.indexcursor

Source Code of com.foundationdb.qp.storeadapter.indexcursor.IndexCursorSpatial_NearPoint

/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.foundationdb.qp.storeadapter.indexcursor;

import com.foundationdb.ais.model.Index;
import com.foundationdb.server.types.value.ValueRecord;
import com.foundationdb.qp.expression.IndexBound;
import com.foundationdb.qp.expression.IndexKeyRange;
import com.foundationdb.qp.operator.API;
import com.foundationdb.qp.operator.BindingsAwareCursor;
import com.foundationdb.qp.operator.QueryBindings;
import com.foundationdb.qp.operator.QueryContext;
import com.foundationdb.qp.row.Row;
import com.foundationdb.qp.rowtype.IndexRowType;
import com.foundationdb.qp.rowtype.InternalIndexTypes;
import com.foundationdb.server.api.dml.IndexRowPrefixSelector;
import com.foundationdb.server.types.TInstance;
import com.foundationdb.server.types.common.types.TBigDecimal;
import com.foundationdb.server.types.value.Value;
import com.foundationdb.server.types.value.ValueSource;
import com.foundationdb.server.types.texpressions.TPreparedExpression;
import com.foundationdb.server.spatial.Spatial;
import com.geophile.z.Space;

import java.math.BigDecimal;

import static java.lang.Math.abs;

// An IndexCursorSpatial_NearPoint yields points near a given point in z-order. This requires a merge
// of those with a lower z-value and those with a higher z-value.

class IndexCursorSpatial_NearPoint extends IndexCursor
{
    @Override
    public void open()
    {
        super.open();
        // iterationHelper.closeIteration() closes the PersistitIndexCursor, releasing its Exchange.
        iterationHelper.closeIteration();
        geCursor.open();
        geNeedToAdvance = true;
        ltCursor.open();
        ltNeedToAdvance = true;
    }

    @Override
    public Row next()
    {
        Row next;
        super.next();
        if (geNeedToAdvance) {
            geRow = geCursor.next();
            geDistance = distanceFromStart(geRow);
            geNeedToAdvance = false;
        }
        if (ltNeedToAdvance) {
            ltRow = ltCursor.next();
            ltDistance = distanceFromStart(ltRow);
            ltNeedToAdvance = false;
        }
        if (ltDistance < geDistance) {
            next = ltRow;
            ltNeedToAdvance = true;
        } else {
            next = geRow;
            geNeedToAdvance = true;
        }
        if (next == null) {
            setIdle();
        }
        return next;
    }

    @Override
    public void close()
    {
        if (isActive()) {
            super.close();
            geCursor.close();
            ltCursor.close();
        }
    }

    @Override
    public void rebind(QueryBindings bindings)
    {
        super.rebind(bindings);
        geCursor.rebind(bindings);
        ltCursor.rebind(bindings);
    }

    // IndexCursorSpatial_InBox interface

    public static IndexCursorSpatial_NearPoint create(QueryContext context,
                                                      IterationHelper iterationHelper,
                                                      IndexKeyRange keyRange)
    {
        return new IndexCursorSpatial_NearPoint(context, iterationHelper, keyRange);
    }

    // For use by this class

    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,
                                                               geRowState,
                                                               geKeyRange,
                                                               upOrdering,
                                                               ValueSortKeyAdapter.INSTANCE);
        ltCursor = new IndexCursorUnidirectional<>(context,
                                                               ltRowState,
                                                               ltKeyRange,
                                                               downOrdering,
                                                               ValueSortKeyAdapter.INSTANCE);
    }

    // For use by this class

    private long distanceFromStart(Row row)
    {
        long distance;
        if (row == null) {
            distance = Long.MAX_VALUE;
        } else {
            long z = row.value(zPosition).getInt64();
            distance = abs(z - zStart);
        }
        return distance;
    }

    // Object state

    // Iteration control is slightly convoluted. lt/geNeedToAdvance are set to indicate if the lt/geCursor
    // need to be advanced on the *next* iteration. This simplifies row management. It would be simpler to advance
    // in next() after determining the next row. But then the state carrying next gets advanced and next doesn't
    // have the state that it should.

    private final int zPosition;
    private final IterationHelper iterationHelper;
    private long zStart;
    private BindingsAwareCursor geCursor;
    private Row geRow;
    private long geDistance;
    private boolean geNeedToAdvance;
    private BindingsAwareCursor ltCursor;
    private Row ltRow;
    private long ltDistance;
    private boolean ltNeedToAdvance;
}
TOP

Related Classes of com.foundationdb.qp.storeadapter.indexcursor.IndexCursorSpatial_NearPoint

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.