private Field<?> createField(String name, FieldType.Type type, Object value) { switch (type) { case BYTES: return Fields.bytesField(name, (byte[]) value); case LONG: return Fields.longField(name, (Long) value); case INTEGER: return Fields.intField(name, (Integer) value); case DOUBLE: return Fields.doubleField(name, (Double) value); case FLOAT: return Fields.floatField(name, (Float) value); case STRING: return Fields.stringField(name, (String) value); default: throw new IllegalStateException("Unknown field type " + type); } }
private List<Field<?>> extractKeys() { List<Field<?>> result = new ArrayList<>(); for (String key : tableSchema.getPrimaryKeys()) { // the NullPointerException should never be thrown since the primary keys must always have a type FieldType.Type type = tableSchema.getType(key); switch (Objects.requireNonNull(type)) { case INTEGER: result.add(Fields.intField(key, (int) columns.get(key))); break; case LONG: result.add(Fields.longField(key, (long) columns.get(key))); break; case STRING: result.add(Fields.stringField(key, (String) columns.get(key))); break; case BYTES: result.add(Fields.bytesField(key, (byte[]) columns.get(key))); break; default: // this should never happen since all the keys are from the table schema and should never contain other types throw new IllegalStateException( String.format("The type %s of the primary key %s is not a valid key type", type, key)); } } return result; }
private Set<Field<?>> generateFieldsSet() { return ImmutableSet.of( Fields.bytesField("bytes", Bytes.toBytes("bytesval")), Fields.stringField("string", "strval"), Fields.doubleField("double", 100.0), Fields.intField("int", 30), Fields.bytesField("double-bytes", Bytes.toBytes(100.0)), Fields.bytesField("long-bytes", Bytes.toBytes(600L)) ); } }
private PluginKeyPrefix(String parentArtifactNamespace, String parentArtifactName, String type, String name) { this.keys = Arrays.asList( Fields.stringField(StoreDefinition.ArtifactStore.PARENT_NAMESPACE_FIELD, parentArtifactNamespace), Fields.stringField(StoreDefinition.ArtifactStore.PARENT_NAME_FIELD, parentArtifactName), Fields.stringField(StoreDefinition.ArtifactStore.PLUGIN_TYPE_FIELD, type), Fields.stringField(StoreDefinition.ArtifactStore.PLUGIN_NAME_FIELD, name) ); }
validator.validatePrimaryKeys(Arrays.asList(Fields.intField(KEY, 10), Fields.longField(KEY2, 100L), Fields.stringField(KEY3, "s")), false); validator.validatePrimaryKeys(Arrays.asList(Fields.intField(KEY, 10), Fields.longField(KEY2, 100L)), true); validator.validatePrimaryKeys(Collections.singletonList(Fields.intField(KEY, 10)), true); validator.validatePrimaryKeys(Arrays.asList(Fields.floatField(KEY, 10.0f), Fields.longField(KEY2, 100L), Fields.stringField(KEY3, "s")), false); Assert.fail("Expected InvalidFieldException"); } catch (InvalidFieldException e) { validator.validatePrimaryKeys(Arrays.asList(Fields.intField(KEY, 10), Fields.longField(KEY2, 100L)), false); Assert.fail("Expected InvalidFieldException");
private void deleteSimpleStructuredRows(int max) throws Exception { for (int i = 0; i < max; i++) { Field<Integer> key = Fields.intField(KEY, i); Field<Long> key2 = Fields.longField(KEY2, (long) i); getTransactionRunner().run(context -> { StructuredTable table = context.getTable(SIMPLE_TABLE); table.delete(ImmutableList.of(key, key2)); }); } }
@Test public void testCompareAndSwapNonExistent() throws Exception { // Compare and swap a non-existent row Collection<Field<?>> nonExistentKeys = Arrays.asList(Fields.intField(KEY, -100), Fields.longField(KEY2, -10L)); // Verify row does not exist first getTransactionRunner().run(context -> { StructuredTable table = context.getTable(SIMPLE_TABLE); Optional<StructuredRow> row = table.read(nonExistentKeys); Assert.assertFalse(row.isPresent()); }); getTransactionRunner().run(context -> { StructuredTable table = context.getTable(SIMPLE_TABLE); boolean result = table.compareAndSwap(nonExistentKeys, Fields.stringField(STRING_COL, "non-existent"), Fields.stringField(STRING_COL, "new-val")); Assert.assertFalse(result); result = table.compareAndSwap(nonExistentKeys, Fields.stringField(STRING_COL, null), Fields.stringField(STRING_COL, "new-val")); Assert.assertTrue(result); }); // Read and verify getTransactionRunner().run(context -> { StructuredTable table = context.getTable(SIMPLE_TABLE); Optional<StructuredRow> row = table.read(nonExistentKeys); Assert.assertTrue(row.isPresent()); Assert.assertEquals("new-val", row.get().getString(STRING_COL)); }); }
@BeforeClass public static void init() { StructuredTableSpecification spec = new StructuredTableSpecification.Builder() .withId(SIMPLE_TABLE) .withFields(Fields.intType(KEY), Fields.longType(KEY2), Fields.stringType(KEY3), Fields.stringType(STRING_COL)) .withPrimaryKeys(KEY, KEY2, KEY3) .build(); schema = new StructuredTableSchema(spec); }
@Test public void testSimpleScan() throws Exception { int max = 100; List<Collection<Field<?>>> expected = writeSimpleStructuredRows(max, ""); List<Collection<Field<?>>> actual = scanSimpleStructuredRows( Range.create(Collections.singleton(Fields.intField(KEY, 5)), Range.Bound.INCLUSIVE, Collections.singleton(Fields.intField(KEY, 15)), Range.Bound.EXCLUSIVE), max); Assert.assertEquals(expected.subList(5, 15), actual); actual = scanSimpleStructuredRows( Range.create(Collections.singleton(Fields.intField(KEY, 5)), Range.Bound.EXCLUSIVE, Collections.singleton(Fields.intField(KEY, 15)), Range.Bound.INCLUSIVE), max); Assert.assertEquals(expected.subList(6, 16), actual); actual = scanSimpleStructuredRows( Range.singleton(Collections.singleton(Fields.intField(KEY, 46))), max); Assert.assertEquals(expected.subList(46, 47), actual); // TODO: test invalid range // TODO: test begin only range // TODO: test end only range }
throw new InvalidFieldException(tableId, primaryKey); if (!Fields.isPrimaryKeyType(type)) { throw new InvalidFieldException(tableId, primaryKey, "is not defined as primary key column");
int intVal = splitter.getInt(); builder.put(key, intVal); keys.add(Fields.intField(key, intVal)); break; case LONG: long longVal = splitter.getLong(); builder.put(key, longVal); keys.add(Fields.longField(key, longVal)); break; case STRING: String stringVal = splitter.getString(); keys.add(Fields.stringField(key, stringVal)); builder.put(key, stringVal); break; case BYTES: byte[] bytesVal = splitter.getBytes(); keys.add(Fields.bytesField(key, bytesVal)); builder.put(key, bytesVal); break;
private UniversalPluginKeyPrefix(String namespace, String type, String name) { this.keys = Arrays.asList( Fields.stringField(StoreDefinition.ArtifactStore.NAMESPACE_FIELD, namespace), Fields.stringField(StoreDefinition.ArtifactStore.PLUGIN_TYPE_FIELD, type), Fields.stringField(StoreDefinition.ArtifactStore.PLUGIN_NAME_FIELD, name) ); } }
@Test public void testMultipleKeyScan() throws Exception { int max = 10; // Write rows and read them, the rows will have keys (0, 0L), (2, 2L), ..., (9, 9L) List<Collection<Field<?>>> expected = writeSimpleStructuredRows(max, ""); List<Collection<Field<?>>> actual = readSimpleStructuredRows(max); Assert.assertEquals(expected, actual); // scan from (1, 8L) inclusive to (3, 3L) inclusive, should return (2, 2L) and (3, 3L) actual = scanSimpleStructuredRows( Range.create(ImmutableList.of(Fields.intField(KEY, 1), Fields.longField(KEY2, 8L)), Range.Bound.INCLUSIVE, ImmutableList.of(Fields.intField(KEY, 3), Fields.longField(KEY2, 3L)), Range.Bound.INCLUSIVE), max); Assert.assertEquals(expected.subList(2, 4), actual); // scan from (1, 8L) inclusive to (3, 3L) exclusive, should only return (2, 2L) actual = scanSimpleStructuredRows( Range.create(ImmutableList.of(Fields.intField(KEY, 1), Fields.longField(KEY2, 8L)), Range.Bound.INCLUSIVE, ImmutableList.of(Fields.intField(KEY, 3), Fields.longField(KEY2, 3L)), Range.Bound.EXCLUSIVE), max); Assert.assertEquals(expected.subList(2, 3), actual); }
private List<Collection<Field<?>>> writeSimpleStructuredRows(int max, String suffix) throws Exception { List<Collection<Field<?>>> expected = new ArrayList<>(max); for (int i = 0; i < max; i++) { List<Field<?>> fields = Arrays.asList(Fields.intField(KEY, i), Fields.longField(KEY2, (long) i), Fields.stringField(STRING_COL, VAL + i + suffix), Fields.doubleField(DOUBLE_COL, (double) i), Fields.floatField(FLOAT_COL, (float) i), Fields.bytesField(BYTES_COL, Bytes.toBytes("bytes-" + i))); expected.add(fields); getTransactionRunner().run(context -> { StructuredTable table = context.getTable(SIMPLE_TABLE); table.upsert(fields); }); } return expected; }
AppClassKey(NamespaceId namespace, String className) { this.keys = Arrays.asList( Fields.stringField(StoreDefinition.ArtifactStore.NAMESPACE_FIELD, namespace.getNamespace()), Fields.stringField(StoreDefinition.ArtifactStore.CLASS_NAME_FIELD, className) ); } }
private List<Collection<Field<?>>> readSimpleStructuredRows(int max, List<String> extraColumns) throws Exception { List<String> columns = new ArrayList<>(ImmutableList.of(STRING_COL, DOUBLE_COL, FLOAT_COL, BYTES_COL)); columns.addAll(extraColumns); List<String> fields = new ArrayList<>(ImmutableSet.of(KEY, KEY2, STRING_COL, DOUBLE_COL, FLOAT_COL, BYTES_COL)); fields.addAll(extraColumns); List<Collection<Field<?>>> actual = new ArrayList<>(max); for (int i = 0; i < max; i++) { Field<Integer> key = Fields.intField(KEY, i); Field<Long> key2 = Fields.longField(KEY2, (long) i); final AtomicReference<Optional<StructuredRow>> rowRef = new AtomicReference<>(); getTransactionRunner().run(context -> { StructuredTable table = context.getTable(SIMPLE_TABLE); rowRef.set(table.read(ImmutableList.of(key, key2), columns)); }); Optional<StructuredRow> row = rowRef.get(); row.ifPresent( structuredRow -> actual.add( convertRowToFields(structuredRow, fields))); } return actual; }
private List<Field<?>> convertRowToFields(StructuredRow row, List<String> columns) { List<Field<?>> fields = new ArrayList<>(); for (String name : columns) { FieldType.Type type = SIMPLE_SCHEMA.getType(name); if (type == null) { throw new InvalidFieldException(SIMPLE_TABLE, name); } switch (type) { case BYTES: fields.add(Fields.bytesField(name, row.getBytes(name))); break; case STRING: fields.add(Fields.stringField(name, row.getString(name))); break; case FLOAT: fields.add(Fields.floatField(name, row.getFloat(name))); break; case DOUBLE: fields.add(Fields.doubleField(name, row.getDouble(name))); break; case INTEGER: fields.add(Fields.intField(name, row.getInteger(name))); break; case LONG: fields.add(Fields.longField(name, row.getLong(name))); break; } } return fields; }
private Range createUniversalPluginScanRange(String namespace, @Nullable String type) { List<Field<?>> keys = new ArrayList<>(); keys.add(Fields.stringField(StoreDefinition.ArtifactStore.NAMESPACE_FIELD, namespace)); if (type != null) { keys.add(Fields.stringField(StoreDefinition.ArtifactStore.PLUGIN_TYPE_FIELD, type)); } return Range.singleton(keys); }
getTransactionRunner().run(context -> { StructuredTable table = context.getTable(SIMPLE_TABLE); Range range = Range.create(Arrays.asList(Fields.intField(KEY, 6), Fields.longField(KEY2, 6L)), Range.Bound.INCLUSIVE, Arrays.asList(Fields.intField(KEY, 8), Fields.longField(KEY2, 8L)), Range.Bound.INCLUSIVE); table.deleteAll(range); getTransactionRunner().run(context -> { StructuredTable table = context.getTable(SIMPLE_TABLE); Range range = Range.create(Collections.singletonList(Fields.intField(KEY, 2)), Range.Bound.INCLUSIVE, Collections.singletonList(Fields.intField(KEY, 5)), Range.Bound.EXCLUSIVE); table.deleteAll(range); }); Range range = Range.create(Collections.singletonList(Fields.intField(KEY, max + 1)), Range.Bound.INCLUSIVE, Collections.singletonList(Fields.intField(KEY, max + 5)), Range.Bound.EXCLUSIVE); table.deleteAll(range); });
private List<Collection<Field<?>>> scanSimpleStructuredRows(Range range, int max) throws Exception { List<Collection<Field<?>>> actual = new ArrayList<>(max); getTransactionRunner().run(context -> { StructuredTable table = context.getTable(SIMPLE_TABLE); try (CloseableIterator<StructuredRow> iterator = table.scan(range, max)) { while (iterator.hasNext()) { StructuredRow row = iterator.next(); actual.add(Arrays.asList(Fields.intField(KEY, row.getInteger(KEY)), Fields.longField(KEY2, row.getLong(KEY2)), Fields.stringField(STRING_COL, row.getString(STRING_COL)), Fields.doubleField(DOUBLE_COL, row.getDouble(DOUBLE_COL)), Fields.floatField(FLOAT_COL, row.getFloat(FLOAT_COL)), Fields.bytesField(BYTES_COL, row.getBytes(BYTES_COL)))); } } }); return actual; } }