/** * 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.row; import com.foundationdb.ais.model.Column; import com.foundationdb.ais.model.Index; import com.foundationdb.ais.model.IndexRowComposition; import com.foundationdb.qp.rowtype.IndexRowType; import com.foundationdb.qp.rowtype.RowType; import com.foundationdb.qp.storeadapter.indexcursor.SortKeyAdapter; import com.foundationdb.qp.storeadapter.indexcursor.SortKeyTarget; import com.foundationdb.qp.storeadapter.indexcursor.ValueSortKeyAdapter; import com.foundationdb.qp.storeadapter.indexrow.SpatialColumnHandler; import com.foundationdb.qp.util.PersistitKey; import com.foundationdb.server.service.session.Session; import com.foundationdb.server.types.TInstance; import com.foundationdb.server.types.texpressions.TPreparedExpression; import com.foundationdb.server.types.value.ValueSource; import com.persistit.Key; import com.persistit.Value; public class WriteIndexRow extends AbstractRow { @Override public RowType rowType() { return indexRowType; } public void initialize (Row row, Key hKey, SpatialColumnHandler spatialColumnHandler, long zValue) { pKeyAppends = 0; int indexField = 0; IndexRowComposition indexRowComp = index.indexRowComposition(); while (indexField < indexRowComp.getLength()) { // handleSpatialColumn will increment pKeyAppends once for all spatial columns if (spatialColumnHandler != null && spatialColumnHandler.handleSpatialColumn(this, indexField, zValue)) { if (indexField == index.firstSpatialArgument()) { pKeyAppends++; } } else { if (indexRowComp.isInRowData(indexField)) { int position = indexRowComp.getFieldPosition(indexField); Column column = row.rowType().table().getColumnsIncludingInternal().get(position); ValueSource source = row.value(column.getPosition()); pKeyTarget().append(source, column.getType()); } else if (indexRowComp.isInHKey(indexField)) { PersistitKey.appendFieldFromKey(pKey(), hKey, indexRowComp.getHKeyPosition(indexField), index .getIndexName()); } else { throw new IllegalStateException("Invalid IndexRowComposition: " + indexRowComp); } pKeyAppends++; } indexField++; } } public void close(Session session, boolean forInsert) { //If we've written too many fields to the key (iKey), make sure to put the extra fields // into the value (iValue) for writing. if (pValueTarget != null) { iValue.clear(); iValue.putByteArray(iKeyExtended.getEncodedBytes(), 0, iKeyExtended.getEncodedSize()); } } public Key pKey() { if (pKeyAppends < pKeyFields) { return iKey; } return iKeyExtended; } @SuppressWarnings("unchecked") private <S> SortKeyTarget<S> pKeyTarget() { if (pKeyAppends < pKeyFields) { return pKeyTarget; } return pValueTarget; } public void resetForWrite(Index index, Key createKey) { resetForWrite(index, createKey, null); } public void resetForWrite(Index index, Key createKey, Value value) { this.index = index; this.iKey = createKey; this.iValue = value; this.index = index; if (index.isSpatial()) { this.pKeyFields = index.getAllColumns().size() - index.spatialColumns() + 1; } else { this.pKeyFields = index.getAllColumns().size(); } if (this.pKeyTarget == null) { this.pKeyTarget = SORT_KEY_ADAPTER.createTarget(index.getIndexName()); } this.pKeyTarget.attach(createKey); } // Group Index Row only - table bitmap stored in index value public void tableBitmap(long bitmap) { iValue.put(bitmap); } public long tableBitmap() { throw new UnsupportedOperationException(); } @SuppressWarnings("unchecked") public <S> void append(S source, TInstance type) { pKeyTarget.append(source, type); } public WriteIndexRow () { } private Index index; private Key iKey; private Key iKeyExtended; private Value iValue; private IndexRowType indexRowType; private SortKeyTarget pKeyTarget; private SortKeyTarget pValueTarget; private int pKeyAppends = 0; private int pKeyFields; private final SortKeyAdapter<ValueSource, TPreparedExpression> SORT_KEY_ADAPTER = ValueSortKeyAdapter.INSTANCE; @Override public HKey hKey() { throw new UnsupportedOperationException(); } @Override protected ValueSource uncheckedValue(int i) { throw new UnsupportedOperationException(); } }