use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class FDBFilterCoalescingQueryTest method versionRangeCoalesce.
/**
* Validate that a query for all values within a given range of versions will be coalesced into a single scan.
* This is similar to the {@link #simpleRangeCoalesce()} test above, but it is for version key expressions in
* particular.
*/
@Test
public void versionRangeCoalesce() throws Exception {
Index versionIndex = new Index("MySimpleRecord$version", VersionKeyExpression.VERSION, IndexTypes.VERSION);
RecordMetaDataHook hook = metaData -> {
metaData.setStoreRecordVersions(true);
metaData.addIndex("MySimpleRecord", versionIndex);
};
complexQuerySetup(hook);
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
long readVersion = context.getReadVersion();
FDBRecordVersion lowBoundary = FDBRecordVersion.firstInDBVersion(0);
FDBRecordVersion highBoundary = FDBRecordVersion.lastInDBVersion(readVersion);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.version().greaterThan(lowBoundary), Query.version().lessThan(highBoundary))).build();
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName(versionIndex.getName()), bounds(hasTupleString("([" + lowBoundary.toVersionstamp() + "],[" + highBoundary.toVersionstamp() + "])")))));
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
int i = 0;
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
FDBRecordVersion version = rec.getVersion();
assertNotNull(version);
assertThat(version, allOf(lessThan(highBoundary), greaterThan(lowBoundary)));
i++;
}
assertEquals(100, i);
assertDiscardedNone(context);
}
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method scanIndexWithValue.
/**
* Verify that explicit (i.e. bypassing the planner) index scans work .
*/
@Test
public void scanIndexWithValue() throws Exception {
RecordMetaDataHook hook = metaData -> {
metaData.removeIndex("MySimpleRecord$num_value_unique");
metaData.addIndex("MySimpleRecord", new Index("multi_index_value", Key.Expressions.field("num_value_unique"), Key.Expressions.field("num_value_2"), IndexTypes.VALUE, IndexOptions.UNIQUE_OPTIONS));
};
complexQuerySetup(hook);
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
int i = 0;
try (RecordCursorIterator<IndexEntry> cursor = recordStore.scanIndex(recordStore.getRecordMetaData().getIndex("multi_index_value"), IndexScanType.BY_VALUE, new TupleRange(Tuple.from(900L), Tuple.from(950L), EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_INCLUSIVE), null, ScanProperties.FORWARD_SCAN).asIterator()) {
while (cursor.hasNext()) {
IndexEntry tuples = cursor.next();
Tuple key = tuples.getKey();
Tuple value = tuples.getValue();
assertEquals(2, key.size());
assertEquals(1, value.size());
assertTrue(key.getLong(0) >= 900);
assertTrue(key.getLong(0) <= 950);
assertTrue(value.getLong(0) == (999 - i) % 3);
i++;
}
}
assertEquals(50, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreNullQueryTest method testProto3.
// Proto3 scalar fields do not distinguish missing from default value, even if set explicitly.
// They both return false for hasField, which means they look like null by default.
// Key.Evaluated.NullStandin.NOT_NULL gives consistent behavior for Proto 2 and Proto 3.
@ParameterizedTest(name = "testProto3({0})")
@MethodSource("testProto3Params")
public void testProto3(String testName, boolean buildDynamic, boolean scalarFieldsNotNull) {
try (FDBRecordContext context = openContext()) {
createOrOpenRecordStore(context, scalarFieldsNotNull ? proto3ScalarNotNullMetaData() : proto3MetaData());
saveTestRecords(buildDynamic ? FDBRecordStoreNullQueryTest::buildRecord3Dynamic : FDBRecordStoreNullQueryTest::buildRecord3);
assertThat(executeQuery(RecordQuery.newBuilder().setRecordType("MyNullRecord").setFilter(Query.field("int_value").equalsValue(2)).build()), is(Collections.singletonList("two")));
assertThat(executeQuery(RecordQuery.newBuilder().setRecordType("MyNullRecord").setFilter(Query.field("string_value").equalsValue("B")).build()), is(Collections.singletonList("two")));
assertThat(executeQuery(RecordQuery.newBuilder().setRecordType("MyNullRecord").setFilter(Query.field("int_value").isNull()).build()), is(scalarFieldsNotNull ? Collections.emptyList() : isProto3() ? Arrays.asList("default", "empty") : Collections.singletonList("empty")));
assertThat(executeQuery(RecordQuery.newBuilder().setRecordType("MyNullRecord").setFilter(Query.field("int_value").equalsValue(0)).build()), is(scalarFieldsNotNull ? Arrays.asList("default", "empty") : isProto3() ? Collections.emptyList() : Collections.singletonList("default")));
assertThat(executeQuery(RecordQuery.newBuilder().setRecordType("MyNullRecord").setFilter(Query.field("string_value").isNull()).build()), is(scalarFieldsNotNull ? Collections.emptyList() : isProto3() ? Arrays.asList("default", "empty") : Collections.singletonList("empty")));
assertThat(executeQuery(RecordQuery.newBuilder().setRecordType("MyNullRecord").setFilter(Query.field("string_value").equalsValue("")).build()), is(scalarFieldsNotNull ? Arrays.asList("default", "empty") : isProto3() ? Collections.emptyList() : Collections.singletonList("default")));
assertThat(executeQuery(RecordQuery.newBuilder().setRecordType("MyNullRecord").setSort(Key.Expressions.field("int_value")).build()), is(scalarFieldsNotNull ? Arrays.asList("minus", "default", "empty", "one", "two") : isProto3() ? Arrays.asList("default", "empty", "minus", "one", "two") : Arrays.asList("empty", "minus", "default", "one", "two")));
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreNullQueryTest method testTupleFields.
@Test
public void testTupleFields() throws Exception {
final UUID nullId = UUID.randomUUID();
final UUID emptyId = UUID.randomUUID();
final UUID defaultId = UUID.randomUUID();
final UUID otherId = UUID.randomUUID();
final TestRecordsTupleFieldsProto.MyFieldsRecord nullRecord = TestRecordsTupleFieldsProto.MyFieldsRecord.newBuilder().setUuid(TupleFieldsHelper.toProto(nullId)).build();
final TestRecordsTupleFieldsProto.MyFieldsRecord emptyRecord = TestRecordsTupleFieldsProto.MyFieldsRecord.newBuilder().setUuid(TupleFieldsHelper.toProto(emptyId)).setFdouble(TupleFieldsProto.NullableDouble.getDefaultInstance()).setFfloat(TupleFieldsProto.NullableFloat.getDefaultInstance()).setFint32(TupleFieldsProto.NullableInt32.getDefaultInstance()).setFint64(TupleFieldsProto.NullableInt64.getDefaultInstance()).setFbool(TupleFieldsProto.NullableBool.getDefaultInstance()).setFstring(TupleFieldsProto.NullableString.getDefaultInstance()).setFbytes(TupleFieldsProto.NullableBytes.getDefaultInstance()).build();
final TestRecordsTupleFieldsProto.MyFieldsRecord defaultRecord = TestRecordsTupleFieldsProto.MyFieldsRecord.newBuilder().setUuid(TupleFieldsHelper.toProto(defaultId)).setFdouble(TupleFieldsHelper.toProto(0.0)).setFfloat(TupleFieldsHelper.toProto(0.0f)).setFint32(TupleFieldsHelper.toProto(0)).setFint64(TupleFieldsHelper.toProto(0L)).setFbool(TupleFieldsHelper.toProto(false)).setFstring(TupleFieldsHelper.toProto("")).setFbytes(TupleFieldsHelper.toProto(ByteString.EMPTY)).build();
final TestRecordsTupleFieldsProto.MyFieldsRecord otherRecord = TestRecordsTupleFieldsProto.MyFieldsRecord.newBuilder().setUuid(TupleFieldsHelper.toProto(otherId)).setFdouble(TupleFieldsHelper.toProto(1.0)).setFfloat(TupleFieldsHelper.toProto(1.0f)).setFint32(TupleFieldsHelper.toProto(1)).setFint64(TupleFieldsHelper.toProto(1L)).setFbool(TupleFieldsHelper.toProto(true)).setFstring(TupleFieldsHelper.toProto(" ")).setFbytes(TupleFieldsHelper.toProto(ByteString.copyFrom(" ", "UTF-8"))).build();
try (FDBRecordContext context = openContext()) {
createOrOpenRecordStore(context, tupleFieldsMetaData());
recordStore.saveRecord(nullRecord);
recordStore.saveRecord(emptyRecord);
recordStore.saveRecord(defaultRecord);
recordStore.saveRecord(otherRecord);
context.commit();
}
try (FDBRecordContext context = openContext()) {
createOrOpenRecordStore(context, tupleFieldsMetaData());
assertEquals(nullId, fieldsRecordId(recordStore.loadRecord(Tuple.from(nullId))));
assertEquals(otherId, fieldsRecordId(recordStore.loadRecord(Tuple.from(otherId))));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fdouble").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("ffloat").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fint32").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fint64").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fbool").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fstring").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fbytes").isNull()));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fdouble").equalsValue(0.0)));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("ffloat").equalsValue(0.0f)));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fint32").equalsValue(0)));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fint64").equalsValue(0L)));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fbool").equalsValue(false)));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fstring").equalsValue("")));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fbytes").equalsValue(ByteString.EMPTY)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fdouble").equalsValue(1.0)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("ffloat").equalsValue(1.0f)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fint32").equalsValue(1)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fint64").equalsValue(1L)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fbool").equalsValue(true)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fstring").equalsValue(" ")));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fbytes").equalsValue(ByteString.copyFrom(" ", "UTF-8"))));
{
final RecordQueryPlan coveringPlan = planner.plan(RecordQuery.newBuilder().setRecordType("MyFieldsRecord").setFilter(Query.field("fint64").greaterThan(0L)).setRequiredResults(Stream.of("uuid", "fint64").map(Key.Expressions::field).collect(Collectors.toList())).build());
assertThat(coveringPlan, PlanMatchers.coveringIndexScan(PlanMatchers.indexScan(PlanMatchers.indexName("MyFieldsRecord$fint64"))));
final List<Pair<UUID, Long>> results = recordStore.executeQuery(coveringPlan).map(rec -> {
final TestRecordsTupleFieldsProto.MyFieldsRecord myrec = TestRecordsTupleFieldsProto.MyFieldsRecord.newBuilder().mergeFrom(rec.getRecord()).build();
return Pair.of(TupleFieldsHelper.fromProto(myrec.getUuid()), TupleFieldsHelper.fromProto(myrec.getFint64()));
}).asList().join();
assertEquals(Collections.singletonList(Pair.of(otherId, 1L)), results);
}
context.commit();
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreQueryTest method query.
@DualPlannerTest
void query() throws Exception {
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
for (int i = 0; i < 100; i++) {
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(i);
recBuilder.setStrValueIndexed((i & 1) == 1 ? "odd" : "even");
recBuilder.setNumValueUnique(i + 1000);
recordStore.saveRecord(recBuilder.build());
}
commit(context);
}
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("str_value_indexed").equalsValue("even")).build();
RecordQueryPlan plan = planner.plan(query);
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
int i = 0;
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = Objects.requireNonNull(cursor.next());
TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
myrec.mergeFrom(rec.getRecord());
assertEquals(0, myrec.getNumValueUnique() % 2);
i++;
}
}
assertEquals(50, i);
assertDiscardedNone(context);
}
}
Aggregations