use of com.apple.foundationdb.record.metadata.RecordTypeBuilder in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method minMaxOptional.
@ParameterizedTest(name = "minMaxLongOptional({0})")
@EnumSource(MinMaxIndexTypes.class)
public void minMaxOptional(MinMaxIndexTypes indexTypes) throws Exception {
final KeyExpression key = field("num_value_3_indexed").ungrouped();
final RecordMetaDataHook hook = md -> {
RecordTypeBuilder type = md.getRecordType("MySimpleRecord");
md.addIndex(type, new Index("min", key, indexTypes.min()));
md.addIndex(type, new Index("max", key, indexTypes.max()));
};
final IndexAggregateFunction minOverall = new IndexAggregateFunction(FunctionNames.MIN_EVER, key, null);
final IndexAggregateFunction maxOverall = new IndexAggregateFunction(FunctionNames.MAX_EVER, key, null);
List<String> types = Collections.singletonList("MySimpleRecord");
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(1066L);
recordStore.saveRecord(recBuilder.build());
commit(context);
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
final Tuple expected = indexTypes == MinMaxIndexTypes.TUPLE ? Tuple.fromList(Collections.singletonList(null)) : null;
assertEquals(expected, recordStore.evaluateAggregateFunction(types, minOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertEquals(expected, recordStore.evaluateAggregateFunction(types, maxOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
commit(context);
}
}
use of com.apple.foundationdb.record.metadata.RecordTypeBuilder in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method minMaxTupleRepeated.
@Test
public void minMaxTupleRepeated() throws Exception {
final FieldKeyExpression fieldKey = field("repeater", FanType.FanOut);
final GroupingKeyExpression indexKey = fieldKey.ungrouped();
final RecordMetaDataHook hook = md -> {
RecordTypeBuilder type = md.getRecordType("MySimpleRecord");
md.addIndex(type, new Index("min", indexKey, IndexTypes.MIN_EVER_TUPLE));
md.addIndex(type, new Index("max", indexKey, IndexTypes.MAX_EVER_TUPLE));
};
final IndexAggregateFunction min = new IndexAggregateFunction(FunctionNames.MIN_EVER, indexKey, null);
final IndexAggregateFunction max = new IndexAggregateFunction(FunctionNames.MAX_EVER, indexKey, null);
List<String> types = Collections.singletonList("MySimpleRecord");
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
assertNull(recordStore.evaluateAggregateFunction(types, min, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, max, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(1);
recordStore.saveRecord(recBuilder.build());
assertNull(recordStore.evaluateAggregateFunction(types, min, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, max, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
recBuilder.addRepeater(1);
recordStore.saveRecord(recBuilder.build());
assertEquals(Tuple.from(1L), recordStore.evaluateAggregateFunction(types, min, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertEquals(Tuple.from(1L), recordStore.evaluateAggregateFunction(types, max, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
recBuilder.clearRepeater();
recBuilder.addRepeater(2);
recBuilder.addRepeater(3);
recordStore.saveRecord(recBuilder.build());
assertEquals(Tuple.from(1L), recordStore.evaluateAggregateFunction(types, min, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertEquals(Tuple.from(3L), recordStore.evaluateAggregateFunction(types, max, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
recBuilder.clearRepeater();
recBuilder.addRepeater(-1);
recordStore.saveRecord(recBuilder.build());
assertEquals(Tuple.from(-1L), recordStore.evaluateAggregateFunction(types, min, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertEquals(Tuple.from(3L), recordStore.evaluateAggregateFunction(types, max, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
commit(context);
}
}
use of com.apple.foundationdb.record.metadata.RecordTypeBuilder in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method minMaxIndex.
@ParameterizedTest(name = "minMaxIndex({0})")
@EnumSource(MinMaxIndexTypes.class)
public void minMaxIndex(MinMaxIndexTypes indexTypes) throws Exception {
final FieldKeyExpression recno = field("rec_no");
final GroupingKeyExpression byKey = recno.groupBy(field("num_value_3_indexed"));
final RecordMetaDataHook hook = md -> {
RecordTypeBuilder type = md.getRecordType("MySimpleRecord");
md.addIndex(type, new Index("min", byKey, indexTypes.min()));
md.addIndex(type, new Index("max", byKey, indexTypes.max()));
};
final IndexAggregateFunction minOverall = new IndexAggregateFunction(FunctionNames.MIN_EVER, recno, null);
final IndexAggregateFunction maxOverall = new IndexAggregateFunction(FunctionNames.MAX_EVER, recno, null);
final IndexAggregateFunction minByKey = new IndexAggregateFunction(FunctionNames.MIN_EVER, byKey, null);
final IndexAggregateFunction maxByKey = new IndexAggregateFunction(FunctionNames.MAX_EVER, byKey, null);
List<String> types = Collections.singletonList("MySimpleRecord");
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
assertNull(recordStore.evaluateAggregateFunction(types, minOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, maxOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, minByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, maxByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join());
for (int i = 0; i < 100; i++) {
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(i);
recBuilder.setNumValue3Indexed(i % 5);
recordStore.saveRecord(recBuilder.build());
}
commit(context);
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
assertEquals(0, recordStore.evaluateAggregateFunction(types, minOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(99, recordStore.evaluateAggregateFunction(types, maxOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(1, recordStore.evaluateAggregateFunction(types, minByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(96, recordStore.evaluateAggregateFunction(types, maxByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join().getLong(0));
commit(context);
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
recordStore.deleteRecord(Tuple.from(0));
recordStore.deleteRecord(Tuple.from(99));
assertEquals(0, recordStore.evaluateAggregateFunction(types, minOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(99, recordStore.evaluateAggregateFunction(types, maxOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join().getLong(0));
commit(context);
}
// verify that negatives do not appear in min/max
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(-1);
recBuilder.setNumValue3Indexed(1);
recordStore.saveRecord(recBuilder.build());
if (!indexTypes.shouldAllowNegative()) {
fail("should have thrown exception");
}
} catch (RecordCoreException e) {
if (indexTypes.shouldAllowNegative()) {
throw e;
}
assertEquals(e.getMessage(), "Attempted update of MAX_EVER_LONG or MIN_EVER_LONG index with negative value");
}
}
use of com.apple.foundationdb.record.metadata.RecordTypeBuilder in project fdb-record-layer by FoundationDB.
the class FunctionKeyIndexTest method openRecordStore.
protected void openRecordStore(FDBRecordContext context, Index... indexes) throws Exception {
RecordMetaDataBuilder metaDataBuilder = RecordMetaData.newBuilder().setRecords(TestDataTypesProto.getDescriptor());
RecordTypeBuilder scalarRecordType = metaDataBuilder.getRecordType("TypesRecord");
for (Index index : indexes) {
metaDataBuilder.addIndex(scalarRecordType, index);
}
createOrOpenRecordStore(context, metaDataBuilder.getRecordMetaData());
}
use of com.apple.foundationdb.record.metadata.RecordTypeBuilder in project fdb-record-layer by FoundationDB.
the class FunctionKeyRecordTest method testCoveringIndexFunction.
@Test
public void testCoveringIndexFunction() throws Exception {
// This index parses each entry of str_array_field of the form "X:Y:Z" and produces a keyWithValue
// index of the form X -> (Y, Z).
final Index index = new Index("covering", keyWithValue(function("regex", concat(field("str_array_field", KeyExpression.FanType.FanOut), value("(\\d+):(\\w+):(\\d+)"), value("LONG"), value("STRING"), value("LONG"))), 1));
final RecordMetaDataHook hook = metadata -> {
RecordTypeBuilder type = metadata.getRecordType("StringRecordId");
type.setPrimaryKey(field("rec_id"));
metadata.addIndex(type, index);
};
final BiFunction<Integer, Integer, String> makeId = (id1, id2) -> id1 + ":" + Character.toString((char) ('a' + id2)) + ":" + id2;
// Create some records
try (FDBRecordContext context = openContext()) {
openRecordStore(context, hook);
for (int i = 0; i < 5; i++) {
TestRecords8Proto.StringRecordId.Builder builder = TestRecords8Proto.StringRecordId.newBuilder().setRecId("record_" + i).setIntValue(i);
for (int j = 0; j < 4; j++) {
builder.addStrArrayField(makeId.apply((i * 4) + j, j));
}
recordStore.saveRecord(builder.build());
}
commit(context);
}
Function<FDBIndexedRecord<Message>, TestRecords8Proto.StringRecordId> validate = message -> {
final Tuple key = message.getIndexEntry().getKey();
final Tuple value = message.getIndexEntry().getValue();
// Key is X,<record_id> where X is the first part of the str_array_field
Assertions.assertEquals(2, key.size());
// Value is the last two pieces of the str_array_field
Assertions.assertEquals(2, value.size());
// Check the record itself
final TestRecords8Proto.StringRecordId record = TestRecords8Proto.StringRecordId.newBuilder().mergeFrom(message.getRecord()).build();
// Get the portions of the key and the value that are needed to reconstruct the
// full value that is supposed to be stored in the str_array_field.
final int id1 = (int) key.getLong(0);
final int id2 = (int) value.getLong(1);
final int recordId = (id1 / 4);
Assertions.assertEquals(recordId, record.getIntValue());
Assertions.assertEquals("record_" + recordId, record.getRecId());
Assertions.assertTrue(record.getStrArrayFieldList().contains(makeId.apply(id1, id2)), "str_array_field does not contain entry");
Assertions.assertEquals(Character.toString((char) ('a' + id2)), value.getString(0));
return record;
};
// let's just scan all of the records
try (FDBRecordContext context = openContext()) {
openRecordStore(context, hook);
List<FDBIndexedRecord<Message>> messages = recordStore.getRecordContext().asyncToSync(FDBStoreTimer.Waits.WAIT_SCAN_INDEX_RECORDS, recordStore.scanIndexRecords(index.getName(), IndexScanType.BY_VALUE, TupleRange.ALL, null, ScanProperties.FORWARD_SCAN).asList());
Assertions.assertEquals(20, messages.size(), "Wrong record count");
for (FDBIndexedRecord<Message> message : messages) {
validate.apply(message);
}
}
// Next, scan a subset of them based upon the first value of the covering index
try (FDBRecordContext context = openContext()) {
openRecordStore(context, hook);
TupleRange range = new TupleRange(Tuple.from(2), Tuple.from(4), EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_EXCLUSIVE);
List<FDBIndexedRecord<Message>> messages = recordStore.getRecordContext().asyncToSync(FDBStoreTimer.Waits.WAIT_SCAN_INDEX_RECORDS, recordStore.scanIndexRecords(index.getName(), IndexScanType.BY_VALUE, range, null, ScanProperties.FORWARD_SCAN).asList());
Assertions.assertEquals(2, messages.size(), "Wrong record count");
for (FDBIndexedRecord<Message> message : messages) {
TestRecords8Proto.StringRecordId record = validate.apply(message);
Assertions.assertTrue(record.getIntValue() == 0, "Invalid int value");
}
}
}
Aggregations