use of com.apple.foundationdb.record.RecordCoreException in project fdb-record-layer by FoundationDB.
the class RecordQueryPlanner method planNoFilter.
@Nullable
private RecordQueryPlan planNoFilter(PlanContext planContext, KeyExpression sort, boolean sortReverse) {
ScoredPlan bestPlan = null;
Index bestIndex = null;
if (sort == null) {
bestPlan = planNoFilterNoSort(planContext, null);
} else if (planContext.commonPrimaryKey != null) {
bestPlan = planSortOnly(new CandidateScan(planContext, null, sortReverse), planContext.commonPrimaryKey, sort);
}
for (Index index : planContext.indexes) {
ScoredPlan p;
if (sort == null) {
p = planNoFilterNoSort(planContext, index);
} else {
p = planSortOnly(new CandidateScan(planContext, index, sortReverse), indexKeyExpressionForPlan(planContext.commonPrimaryKey, index), sort);
}
if (p != null) {
if (bestPlan == null || p.score > bestPlan.score || (p.score == bestPlan.score && compareIndexes(planContext, index, bestIndex) > 0)) {
bestPlan = p;
bestIndex = index;
}
}
}
if (bestPlan != null) {
bestPlan = planRemoveDuplicates(planContext, bestPlan);
if (bestPlan == null) {
throw new RecordCoreException("A common primary key is required to remove duplicates");
}
return bestPlan.plan;
}
return null;
}
use of com.apple.foundationdb.record.RecordCoreException in project fdb-record-layer by FoundationDB.
the class RecordQueryInUnionPlan method executePlan.
@Nonnull
@Override
public <M extends Message> RecordCursor<QueryResult> executePlan(@Nonnull final FDBRecordStoreBase<M> store, @Nonnull final EvaluationContext context, @Nullable final byte[] continuation, @Nonnull final ExecuteProperties executeProperties) {
int size = getValuesSize(context);
if (size > maxNumberOfValuesAllowed) {
throw new RecordCoreException("too many IN values").addLogInfo("size", size);
}
if (size == 0) {
return RecordCursor.empty();
}
final RecordQueryPlan childPlan = getInnerPlan();
if (size == 1) {
final EvaluationContext childContext = getValuesContexts(context).get(0);
return childPlan.executePlan(store, childContext, continuation, executeProperties);
}
final ExecuteProperties childExecuteProperties;
// Can pass the limit down to all sides, since that is the most we'll take total.
if (executeProperties.getSkip() > 0) {
childExecuteProperties = executeProperties.clearSkipAndAdjustLimit();
} else {
childExecuteProperties = executeProperties;
}
final List<Function<byte[], RecordCursor<FDBQueriedRecord<M>>>> childCursorFunctions = getValuesContexts(context).stream().map(childContext -> (Function<byte[], RecordCursor<FDBQueriedRecord<M>>>) childContinuation -> childPlan.execute(store, childContext, childContinuation, childExecuteProperties)).collect(Collectors.toList());
return UnionCursor.create(store, comparisonKey, reverse, childCursorFunctions, continuation).skipThenLimit(executeProperties.getSkip(), executeProperties.getReturnedRowLimit()).map(QueryResult::of);
}
use of com.apple.foundationdb.record.RecordCoreException in project fdb-record-layer by FoundationDB.
the class TextScan method getTokenList.
// Get the comparand as a list of strings. This might involve tokenizing the
// query string if the comparison didn't do that already.
private List<String> getTokenList(@Nonnull FDBRecordStoreBase<?> store, @Nonnull EvaluationContext context, boolean removeStopWords) {
final Object comparand = textComparison.getComparand(store, context);
List<String> tokenList;
if (comparand instanceof List<?>) {
tokenList = ((List<?>) comparand).stream().map(Object::toString).collect(Collectors.toList());
} else if (comparand instanceof String) {
TextTokenizer tokenizer = TextIndexMaintainer.getTokenizer(index);
int tokenizerVersion = TextIndexMaintainer.getIndexTokenizerVersion(index);
tokenList = tokenizer.tokenizeToList((String) comparand, tokenizerVersion, TextTokenizer.TokenizerMode.QUERY);
} else {
throw new RecordCoreException("Comparand for text query of incompatible type: " + (comparand == null ? "null" : comparand.getClass()));
}
if (removeStopWords && tokenList.contains("")) {
// Remove all stop words from this list
tokenList = tokenList.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
}
return tokenList;
}
use of com.apple.foundationdb.record.RecordCoreException in project fdb-record-layer by FoundationDB.
the class RankedSetIndexHelper method groupPrefix.
@Nullable
private static Tuple groupPrefix(int groupPrefixSize, @Nonnull TupleRange rankRange, @Nonnull Subspace rankSubspace) {
if (groupPrefixSize > 0) {
Tuple lowRank = rankRange.getLow();
Tuple highRank = rankRange.getHigh();
if (lowRank == null || lowRank.size() < groupPrefixSize || highRank == null || highRank.size() < groupPrefixSize) {
throw new RecordCoreException("Ranked scan range does not include group", "rankRange", rankRange, "rankSubspace", ByteArrayUtil2.loggable(rankSubspace.getKey()));
}
Tuple prefix = Tuple.fromList(lowRank.getItems().subList(0, groupPrefixSize));
Tuple highPrefix = Tuple.fromList(highRank.getItems().subList(0, groupPrefixSize));
if (!prefix.equals(highPrefix)) {
throw new RecordCoreException("Ranked scan range crosses groups", "rankRange", rankRange, "rankSubspace", ByteArrayUtil2.loggable(rankSubspace.getKey()));
}
return prefix;
} else {
return null;
}
}
use of com.apple.foundationdb.record.RecordCoreException in project fdb-record-layer by FoundationDB.
the class TextIndexMaintainer method scan.
/**
* Scan this index between a range of tokens. This index type requires that it be scanned only
* by text token. The range to scan can otherwise be between any two entries in the list, and
* scans over a prefix are supported by passing a value of <code>range</code> that uses
* {@link com.apple.foundationdb.record.EndpointType#PREFIX_STRING PREFIX_STRING} as both endpoint types.
* The keys returned in the index entry will include the token that was found in the index
* when scanning in the column that is used for the text field of the index's root expression.
* The value portion of each index entry will be a tuple whose first element is the position
* list for that entry within its associated record's field.
*
* @param scanType the {@link IndexScanType type} of scan to perform
* @param range the range to scan
* @param continuation any continuation from a previous scan invocation
* @param scanProperties skip, limit and other properties of the scan
* @return a cursor over all index entries in <code>range</code>
* @throws RecordCoreException if <code>scanType</code> is not {@link IndexScanType#BY_TEXT_TOKEN}
* @see TextCursor
*/
@Nonnull
@Override
// not closing the returned cursor
@SuppressWarnings("squid:S2095")
public RecordCursor<IndexEntry> scan(@Nonnull IndexScanType scanType, @Nonnull TupleRange range, @Nullable byte[] continuation, @Nonnull ScanProperties scanProperties) {
if (scanType != IndexScanType.BY_TEXT_TOKEN) {
throw new RecordCoreException("Can only scan text index by text token.");
}
int textPosition = textFieldPosition(state.index.getRootExpression());
TextSubspaceSplitter subspaceSplitter = new TextSubspaceSplitter(state.indexSubspace, textPosition + 1);
Range byteRange = range.toRange();
ScanProperties withAdjustedLimit = scanProperties.with(ExecuteProperties::clearSkipAndAdjustLimit);
ExecuteProperties adjustedExecuteProperties = withAdjustedLimit.getExecuteProperties();
// Callback for updating the byte scan limit
final ByteScanLimiter byteScanLimiter = adjustedExecuteProperties.getState().getByteScanLimiter();
final Consumer<KeyValue> callback = keyValue -> byteScanLimiter.registerScannedBytes(keyValue.getKey().length + keyValue.getValue().length);
BunchedMapMultiIterator<Tuple, List<Integer>, Tuple> iterator = getBunchedMap(state.context).scanMulti(state.context.readTransaction(adjustedExecuteProperties.getIsolationLevel().isSnapshot()), state.indexSubspace, subspaceSplitter, byteRange.begin, byteRange.end, continuation, adjustedExecuteProperties.getReturnedRowLimit(), callback, scanProperties.isReverse());
RecordCursor<IndexEntry> cursor = new TextCursor(iterator, state.store.getExecutor(), state.context, withAdjustedLimit, state.index);
if (scanProperties.getExecuteProperties().getSkip() != 0) {
cursor = cursor.skip(scanProperties.getExecuteProperties().getSkip());
}
return cursor;
}
Aggregations