/**
* 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.qp.operator.API;
import com.foundationdb.qp.operator.API.Ordering;
import com.foundationdb.qp.operator.QueryBindings;
import com.foundationdb.qp.operator.QueryContext;
import com.foundationdb.qp.row.Row;
import com.foundationdb.qp.row.ValuesHolderRow;
import com.foundationdb.qp.rowtype.RowType;
import com.foundationdb.server.types.TInstance;
import com.persistit.Key;
import com.persistit.Value;
import java.util.ArrayList;
import java.util.List;
abstract class SorterAdapter<S,E,V> {
protected SorterAdapter(SortKeyAdapter<S,E> sortKeyAdapter) {
this.sortKeyAdapter = sortKeyAdapter;
keyTarget = sortKeyAdapter.createTarget("sort");
}
public void init(RowType rowType, Ordering ordering, Key key, Value value, QueryContext context, QueryBindings bindings,
API.SortOption sortOption)
{
this.keyTarget.attach(key);
int rowFields = rowType.nFields();
this.tFieldTypes = tinstances(rowFields);
for (int i = 0; i < rowFields; i++) {
initTypes(rowType, tFieldTypes, i);
}
attachValueTarget(value);
preserveDuplicates = sortOption == API.SortOption.PRESERVE_DUPLICATES;
if (preserveDuplicates) {
// Append a count field as a sort key, to ensure key uniqueness for Persisit. By setting
// the ascending flag equal to that of some other sort field, we don't change an all-ASC or all-DESC sort
// into a less efficient mixed-mode sort.
appendDummy(ordering);
}
int nsort = ordering.sortColumns();
this.evaluations = new ArrayList<>(nsort);
this.tOrderingTypes = tinstances(nsort);
for (int i = 0; i < nsort; i++) {
initTypes(ordering, i, tOrderingTypes);
V evaluation = evaluation(ordering, context, bindings, i);
evaluations.add(evaluation);
}
}
protected abstract void appendDummy(Ordering ordering);
protected abstract TInstance[] tinstances(int size);
public void evaluateToKey(Row row, int i) {
V evaluation = evaluations.get(i);
S keySource = evaluateRow(evaluation, row);
keyTarget.append(keySource, i, tOrderingTypes);
}
public TInstance[] tFieldTypes() {
return tFieldTypes;
}
public boolean preserveDuplicates() {
return preserveDuplicates;
}
protected abstract void initTypes(RowType rowType, TInstance[] tFieldTypes, int i);
protected abstract void initTypes(Ordering ordering, int i, TInstance[] tInstances);
protected abstract V evaluation(Ordering ordering, QueryContext context, QueryBindings bindings, int i);
protected abstract S evaluateRow(V evaluation, Row row);
protected abstract void attachValueTarget(Value value);
protected abstract PersistitValueSourceAdapter createValueAdapter();
private final SortKeyAdapter<S,E> sortKeyAdapter;
private final SortKeyTarget<S> keyTarget;
private boolean preserveDuplicates;
//private AkCollator orderingCollators[];
private TInstance tFieldTypes[], tOrderingTypes[];
private List<V> evaluations;
public void evaluateToTarget(Row row, int i) {
S field = sortKeyAdapter.get(row, i);
putFieldToTarget(field, i, tFieldTypes);
}
protected abstract void putFieldToTarget(S value, int i, TInstance[] tFieldTypes);
public interface PersistitValueSourceAdapter {
void attach(Value value);
void putToHolders(ValuesHolderRow row, int i, TInstance[] fieldTypes);
}
}