use of com.apple.foundationdb.record.EvaluationContext in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreQueryTest method testParameterQuery1.
/**
* Verify that index lookups work with parameterized queries.
*/
@DualPlannerTest
void testParameterQuery1() throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").equalsParameter("1"), Query.field("num_value_2").equalsParameter("2"))).build();
// Index(multi_index [EQUALS $1, EQUALS $2])
RecordQueryPlan plan = planner.plan(query);
assertMatchesExactly(plan, indexPlan().where(indexName("multi_index")).and(scanComparisons(range("[EQUALS $1, EQUALS $2]"))));
assertEquals(584809367, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1148926968, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1148926968, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
for (int attempt = 1; attempt <= 2; attempt++) {
String strValue;
int numValue2;
switch(attempt) {
case 1:
strValue = "even";
numValue2 = 1;
break;
case 2:
default:
strValue = "odd";
numValue2 = 2;
break;
}
Bindings.Builder bindings = Bindings.newBuilder();
bindings.set("1", strValue);
bindings.set("2", numValue2);
EvaluationContext evaluationContext = EvaluationContext.forBindings(bindings.build());
int i = 0;
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = plan.execute(recordStore, evaluationContext).asIterator()) {
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
myrec.mergeFrom(rec.getRecord());
assertEquals(strValue, myrec.getStrValueIndexed());
assertTrue((myrec.getNumValue2() % 3) == numValue2);
i++;
}
}
assertEquals(16, i);
}
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.EvaluationContext in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreQueryTestBase method querySimpleRecordStoreWithContinuation.
/**
* A query execution utility that can handle continuations. This is very similar to the above {@link #querySimpleRecordStore}
* with the additional support for {@link ExecuteProperties} and continuation.
* This method returns the last result encountered. In the case where the row limit was encountered, this would be the one
* result that contains the continuation that should be used on the next call.
* @param recordMetaDataHook Metadata hook to invoke while opening store
* @param plan the plan to execute
* @param contextSupplier provider method to get execution context
* @param continuation execution continuation
* @param executeProperties execution properties to pass into the execute method
* @param checkNumRecords Consumer that verifies correct number of records returned
* @param checkRecord Consumer that asserts every record retrieved
* @param checkDiscarded Consumer that asserts the number of discarded records
* @return the last result from the cursor
* @throws Throwable any thrown exception, or its cause if the exception is a {@link ExecutionException}
*/
protected RecordCursorResult<FDBQueriedRecord<Message>> querySimpleRecordStoreWithContinuation(@Nonnull RecordMetaDataHook recordMetaDataHook, @Nonnull RecordQueryPlan plan, @Nonnull Supplier<EvaluationContext> contextSupplier, @Nullable byte[] continuation, @Nonnull ExecuteProperties executeProperties, @Nonnull Consumer<Integer> checkNumRecords, @Nonnull Consumer<TestRecords1Proto.MySimpleRecord.Builder> checkRecord, @Nonnull Consumer<FDBRecordContext> checkDiscarded) throws Throwable {
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, recordMetaDataHook);
AtomicInteger i = new AtomicInteger(0);
CompletableFuture<RecordCursorResult<FDBQueriedRecord<Message>>> lastResult;
RecordCursor<FDBQueriedRecord<Message>> cursor = plan.execute(recordStore, contextSupplier.get(), continuation, executeProperties);
lastResult = cursor.forEachResult(result -> {
TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
myrec.mergeFrom(result.get().getRecord());
checkRecord.accept(myrec);
i.incrementAndGet();
});
lastResult.get();
checkNumRecords.accept(i.get());
checkDiscarded.accept(context);
// TODO a hack until this gets refactored properly
clearStoreCounter(context);
return lastResult.get();
} catch (ExecutionException ex) {
throw ex.getCause();
}
}
use of com.apple.foundationdb.record.EvaluationContext in project fdb-record-layer by FoundationDB.
the class FDBSimpleJoinQueryTest method joinChildToParent.
/**
* Verify that simple binding joins in parent/child relationships work.
*/
@Test
public void joinChildToParent() throws Exception {
createJoinRecords(false);
RecordQuery parentQuery = RecordQuery.newBuilder().setRecordType("MyParentRecord").setFilter(Query.field("str_value_indexed").equalsValue("even")).build();
RecordQuery childQuery = RecordQuery.newBuilder().setRecordType("MyChildRecord").setFilter(Query.field("parent_rec_no").equalsParameter("parent")).build();
RecordQueryPlan parentPlan = planner.plan(parentQuery);
RecordQueryPlan childPlan = planner.plan(childQuery);
try (FDBRecordContext context = openContext()) {
openJoinRecordStore(context);
RecordCursor<FDBQueriedRecord<Message>> childCursor = RecordCursor.flatMapPipelined(ignore -> recordStore.executeQuery(parentPlan), (rec, ignore) -> {
TestRecordsParentChildRelationshipProto.MyParentRecord.Builder parentRec = TestRecordsParentChildRelationshipProto.MyParentRecord.newBuilder();
parentRec.mergeFrom(rec.getRecord());
EvaluationContext childContext = EvaluationContext.forBinding("parent", parentRec.getRecNo());
return childPlan.execute(recordStore, childContext);
}, null, 10);
RecordCursor<String> resultsCursor = childCursor.map(rec -> {
TestRecordsParentChildRelationshipProto.MyChildRecord.Builder childRec = TestRecordsParentChildRelationshipProto.MyChildRecord.newBuilder();
childRec.mergeFrom(rec.getRecord());
return childRec.getStrValue();
});
assertEquals(Arrays.asList("2.1", "2.2", "2.3", "4.1", "4.2", "4.3"), resultsCursor.asList().join());
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.EvaluationContext in project fdb-record-layer by FoundationDB.
the class FDBSimpleJoinQueryTest method joinParentToChild.
/**
* Verify that simple binding joins in parent/child relationships work.
*/
@Test
public void joinParentToChild() throws Exception {
createJoinRecords(true);
RecordQuery parentQuery = RecordQuery.newBuilder().setRecordType("MyParentRecord").setFilter(Query.field("str_value_indexed").equalsValue("even")).build();
RecordQueryPlan parentPlan = planner.plan(parentQuery);
RecordQueryPlan childPlan = new RecordQueryLoadByKeysPlan("children");
try (FDBRecordContext context = openContext()) {
openJoinRecordStore(context);
RecordCursor<FDBQueriedRecord<Message>> parentCursor = recordStore.executeQuery(parentPlan);
RecordCursor<FDBQueriedRecord<Message>> childCursor = RecordCursor.flatMapPipelined(ignore -> recordStore.executeQuery(parentPlan), (rec, ignore) -> {
TestRecordsParentChildRelationshipProto.MyParentRecord.Builder parentRec = TestRecordsParentChildRelationshipProto.MyParentRecord.newBuilder();
parentRec.mergeFrom(rec.getRecord());
EvaluationContext childContext = EvaluationContext.forBinding("children", parentRec.getChildRecNosList().stream().map(Tuple::from).collect(Collectors.toList()));
return childPlan.execute(recordStore, childContext);
}, null, 10);
RecordCursor<String> resultsCursor = childCursor.map(rec -> {
TestRecordsParentChildRelationshipProto.MyChildRecord.Builder childRec = TestRecordsParentChildRelationshipProto.MyChildRecord.newBuilder();
childRec.mergeFrom(rec.getRecord());
return childRec.getStrValue();
});
assertEquals(Arrays.asList("2.1", "2.2", "2.3", "4.1", "4.2", "4.3"), resultsCursor.asList().join());
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.EvaluationContext in project fdb-record-layer by FoundationDB.
the class FDBSortQueryIndexSelectionTest method sortWithScannableFilterOnIndex.
/**
* Verify that if the sort matches an index that can satisfy a filter that the index is used.
*/
@ParameterizedTest
@MethodSource("hooks")
void sortWithScannableFilterOnIndex(RecordMetaDataHook hook, PlannableIndexTypes indexTypes) throws Exception {
setupSimpleRecordStore(hook, (i, builder) -> builder.setRecNo(i).setNumValue2(i % 2).setNumValue3Indexed(i % 3));
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_3_indexed").greaterThanOrEquals(2)).setSort(field("num_value_3_indexed")).build();
setupPlanner(indexTypes);
// Index(MySimpleRecord$num_value_3_indexed [[2],>)
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), bounds(hasTupleString("[[2],>")))));
assertEquals(1008857205, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-2059045225, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1347749581, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
AtomicInteger lastNumValue3 = new AtomicInteger(Integer.MIN_VALUE);
int returned = querySimpleRecordStore(hook, plan, EvaluationContext::empty, builder -> {
assertThat(builder.getNumValue3Indexed(), greaterThanOrEqualTo(2));
assertThat(builder.getNumValue3Indexed(), greaterThanOrEqualTo(lastNumValue3.get()));
lastNumValue3.set(builder.getNumValue3Indexed());
}, TestHelpers::assertDiscardedNone);
assertEquals(33, returned);
// reset planner
setupPlanner(null);
}
Aggregations