use of com.apple.test.BooleanSource in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQuery2.
/**
* Verify that queries with an OR of a mix of equality and inequality predicates on the same field are implemented
* using a union of indexes.
*/
@DualPlannerTest
@ParameterizedTest
@BooleanSource
void testOrQuery2(boolean shouldDeferFetch) throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("num_value_3_indexed").equalsValue(1), Query.field("num_value_3_indexed").equalsValue(2), Query.field("num_value_3_indexed").greaterThan(3))).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
// Fetch(Covering(Index(MySimpleRecord$num_value_3_indexed [[1],[1]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]) ∪[Field { 'num_value_3_indexed' None}, Field { 'rec_no' None}] Covering(Index(MySimpleRecord$num_value_3_indexed [[2],[2]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]) ∪[Field { 'num_value_3_indexed' None}, Field { 'rec_no' None}] Covering(Index(MySimpleRecord$num_value_3_indexed ([3],>) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]))
RecordQueryPlan plan = planner.plan(query);
if (shouldDeferFetch || planner instanceof CascadesPlanner) {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = fetchFromPartialRecordPlan(unionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[1],[1]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[2],[2]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([3],>")))))).where(comparisonKey(concat(field("num_value_3_indexed"), primaryKey("MySimpleRecord")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(504228282, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1520996708, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(2080970598, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = unionPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[1],[1]]"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[2],[2]]"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([3],>")))).where(comparisonKey(concat(field("num_value_3_indexed"), primaryKey("MySimpleRecord"))));
assertMatchesExactly(plan, planMatcher);
assertEquals(1299166123, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-700473135, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-140499245, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
int i = 0;
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
assertTrue(myrec.getNumValue3Indexed() == 1 || myrec.getNumValue3Indexed() == 2 || myrec.getNumValue3Indexed() > 3);
i++;
}
}
assertEquals(20 + 20 + 20, i);
assertDiscardedNone(context);
}
}
use of com.apple.test.BooleanSource in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQuery5.
/**
* Verify that an OR of inequalities on different fields uses an unordered union, since there is no compatible ordering.
*/
@DualPlannerTest
@ParameterizedTest(name = "testOrQuery5 [removesDuplicates = {0}]")
@BooleanSource
void testOrQuery5(boolean removesDuplicates) throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("str_value_indexed").lessThan("m"), Query.field("num_value_3_indexed").greaterThan(3))).setRemoveDuplicates(removesDuplicates).build();
// Unordered(Index(MySimpleRecord$str_value_indexed ([null],[m])) ∪ Index(MySimpleRecord$num_value_3_indexed ([3],>))
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof CascadesPlanner) {
BindingMatcher<? extends RecordQueryPlan> planMatcher = unorderedUnionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("([null],[m])"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([3],>"))))));
if (removesDuplicates) {
planMatcher = fetchFromPartialRecordPlan(unorderedPrimaryKeyDistinctPlan(planMatcher));
} else {
planMatcher = fetchFromPartialRecordPlan(planMatcher);
}
assertMatchesExactly(plan, planMatcher);
assertEquals(removesDuplicates ? 1898767693 : 1898767686, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(removesDuplicates ? -583062018 : 212117636, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(removesDuplicates ? 1864525478 : -1635262164, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
BindingMatcher<? extends RecordQueryPlan> planMatcher = unorderedUnionPlan(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("([null],[m])"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([3],>"))));
if (removesDuplicates) {
planMatcher = unorderedPrimaryKeyDistinctPlan(planMatcher);
}
assertMatchesExactly(plan, planMatcher);
assertEquals(removesDuplicates ? -1569447744 : -1569447745, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(removesDuplicates ? 1558364455 : -1941423187, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(removesDuplicates ? -289015345 : 506164309, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
try (FDBRecordContext context = openContext()) {
Objects.requireNonNull(context.getTimer()).reset();
openSimpleRecordStore(context, hook);
int i = 0;
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
assertTrue(myrec.getStrValueIndexed().compareTo("m") < 0 || myrec.getNumValue3Indexed() > 3);
i++;
}
}
if (removesDuplicates) {
assertEquals(50 + 10, i);
assertDiscardedAtMost(10, context);
} else {
assertEquals(70, i);
assertDiscardedNone(context);
}
}
}
use of com.apple.test.BooleanSource in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method countClearWhenZero.
@ParameterizedTest
@BooleanSource
public void countClearWhenZero(boolean clearWhenZero) throws Exception {
final GroupingKeyExpression byKey = new GroupingKeyExpression(field("str_value_indexed"), 0);
final RecordMetaDataHook hook = md -> md.addIndex("MySimpleRecord", new Index("count_by_str", byKey, IndexTypes.COUNT, ImmutableMap.of(IndexOptions.CLEAR_WHEN_ZERO, Boolean.toString(clearWhenZero))));
final List<String> types = Collections.singletonList("MySimpleRecord");
final IndexAggregateFunction perKey = new IndexAggregateFunction(FunctionNames.COUNT, byKey, null);
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
for (int i = 0; i < 10; i++) {
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(i);
recBuilder.setStrValueIndexed((i & 1) == 1 ? "odd" : "even");
recordStore.saveRecord(recBuilder.build());
}
commit(context);
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
assertEquals(5, recordStore.evaluateAggregateFunction(types, perKey, Key.Evaluated.scalar("even"), IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(5, recordStore.evaluateAggregateFunction(types, perKey, Key.Evaluated.scalar("odd"), IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(ImmutableMap.of("even", 5L, "odd", 5L), recordStore.scanIndex(recordStore.getRecordMetaData().getIndex("count_by_str"), IndexScanType.BY_GROUP, TupleRange.ALL, null, ScanProperties.FORWARD_SCAN).map(i -> Pair.of(i.getKey().get(0), i.getValue().get(0))).asList().join().stream().collect(Collectors.toMap(Pair::getLeft, Pair::getRight)));
commit(context);
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
for (int i = 0; i < 10; i += 2) {
recordStore.deleteRecord(Tuple.from(i));
}
commit(context);
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
assertEquals(0, recordStore.evaluateAggregateFunction(types, perKey, Key.Evaluated.scalar("even"), IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(5, recordStore.evaluateAggregateFunction(types, perKey, Key.Evaluated.scalar("odd"), IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(clearWhenZero ? ImmutableMap.of("odd", 5L) : ImmutableMap.of("even", 0L, "odd", 5L), recordStore.scanIndex(recordStore.getRecordMetaData().getIndex("count_by_str"), IndexScanType.BY_GROUP, TupleRange.ALL, null, ScanProperties.FORWARD_SCAN).map(i -> Pair.of(i.getKey().get(0), i.getValue().get(0))).asList().join().stream().collect(Collectors.toMap(Pair::getLeft, Pair::getRight)));
commit(context);
}
}
use of com.apple.test.BooleanSource in project fdb-record-layer by FoundationDB.
the class SplitHelperTest method scanMultipleRecords.
@ParameterizedTest(name = "scanMultipleRecords [reverse = {0}]")
@BooleanSource
public void scanMultipleRecords(boolean reverse) throws Exception {
final ScanProperties scanProperties = reverse ? ScanProperties.REVERSE_SCAN : ScanProperties.FORWARD_SCAN;
List<FDBRawRecord> rawRecords = writeDummyRecords();
try (FDBRecordContext context = openContext()) {
KeyValueCursor kvCursor = KeyValueCursor.Builder.withSubspace(subspace).setContext(context).setRange(TupleRange.ALL).setScanProperties(scanProperties).build();
List<FDBRawRecord> readRecords = new SplitHelper.KeyValueUnsplitter(context, subspace, kvCursor, false, null, scanProperties).asList().get();
if (reverse) {
readRecords = Lists.reverse(readRecords);
}
assertEquals(rawRecords.size(), readRecords.size());
for (int i = 0; i < rawRecords.size(); i++) {
assertEquals(rawRecords.get(i), readRecords.get(i));
}
assertEquals(rawRecords, readRecords);
commit(context);
}
}
use of com.apple.test.BooleanSource in project fdb-record-layer by FoundationDB.
the class FDBReturnedRecordLimitQueryTest method testComplexLimits2.
/**
* Verify that a returned record limit works properly against a query with a filter on one field and a sort on another,
* when the filter field is un-indexed and the sort is in reverse order.
*/
@ParameterizedTest
@BooleanSource
void testComplexLimits2(final boolean shouldOptimizeForIndexFilters) throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
final QueryComponent filter = Query.field("num_value_2").equalsValue(0);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(filter).setSort(field("str_value_indexed"), true).build();
setOptimizeForIndexFilters(shouldOptimizeForIndexFilters);
// Index(MySimpleRecord$str_value_indexed <,> REVERSE) | num_value_2 EQUALS 0
// Fetch(Covering(Index(multi_index <,> REVERSE) -> [num_value_2: KEY[1], num_value_3_indexed: KEY[2], rec_no: KEY[3], str_value_indexed: KEY[0]]) | num_value_2 EQUALS 0)
RecordQueryPlan plan = planner.plan(query);
if (shouldOptimizeForIndexFilters) {
assertThat(plan, fetch(filter(filter, coveringIndexScan(indexScan(allOf(indexName("multi_index"), unbounded()))))));
assertTrue(plan.isReverse());
assertEquals(-1143466156, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(915163788, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1279091452, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, filter(filter, indexScan(allOf(indexName("MySimpleRecord$str_value_indexed"), unbounded()))));
assertTrue(plan.isReverse());
assertEquals(-384998859, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1575402371, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(525309685, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
int i = 0;
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan, null, ExecuteProperties.newBuilder().setReturnedRowLimit(10).build()).asIterator()) {
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
assertEquals(0, myrec.getNumValue2());
assertEquals("odd", myrec.getStrValueIndexed());
i += 1;
}
}
assertEquals(10, i);
assertDiscardedAtMost(34, context);
}
}
Aggregations