@Test public void testToString() { assertThat(KeyRange.closedOpen(Key.of("a"), Key.of("b")).toString()).isEqualTo("[[a],[b])"); assertThat(KeyRange.closedClosed(Key.of("a"), Key.of("b")).toString()).isEqualTo("[[a],[b]]"); assertThat(KeyRange.openOpen(Key.of("a"), Key.of("b")).toString()).isEqualTo("([a],[b])"); assertThat(KeyRange.openClosed(Key.of("a"), Key.of("b")).toString()).isEqualTo("([a],[b]]"); assertThat(KeyRange.closedClosed(Key.of(), Key.of()).toString()).isEqualTo("[[],[]]"); }
public KeyRange build() { checkState(start != null, "Missing required call to start(Key)"); checkState(end != null, "Missing required call to end(Key)"); return new KeyRange(start, startType, end, endType); } }
@Test public void rangeReads() { checkRange(Source.BASE_TABLE, KeySet.singleKey(Key.of("k1")), 1); checkRange(Source.BASE_TABLE, KeyRange.closedOpen(Key.of("k3"), Key.of("k5")), 3, 4); checkRange(Source.BASE_TABLE, KeyRange.closedClosed(Key.of("k3"), Key.of("k5")), 3, 4, 5); checkRange(Source.BASE_TABLE, KeyRange.openClosed(Key.of("k3"), Key.of("k5")), 4, 5); checkRange(Source.BASE_TABLE, KeyRange.openOpen(Key.of("k3"), Key.of("k5")), 4); // Partial key specification. checkRange(Source.BASE_TABLE, KeyRange.closedClosed(Key.of("k7"), Key.of()), 7, 8, 9); checkRange(Source.BASE_TABLE, KeyRange.openClosed(Key.of("k7"), Key.of()), 8, 9); checkRange(Source.BASE_TABLE, KeyRange.closedOpen(Key.of(), Key.of("k11")), 0, 1, 10); checkRange(Source.BASE_TABLE, KeyRange.closedClosed(Key.of(), Key.of("k11")), 0, 1, 10, 11); // The following produce empty ranges. // TODO(user): Consider a multi-part key to illustrate partial key behavior. checkRange(Source.BASE_TABLE, KeyRange.closedOpen(Key.of("k7"), Key.of())); checkRange(Source.BASE_TABLE, KeyRange.openOpen(Key.of("k7"), Key.of())); checkRange(Source.BASE_TABLE, KeyRange.openOpen(Key.of(), Key.of("k11"))); checkRange(Source.BASE_TABLE, KeyRange.openClosed(Key.of(), Key.of("k11"))); // Prefix is component-wise, not string prefix. checkRange(Source.BASE_TABLE, KeyRange.prefix(Key.of("k1")), 1); checkRange( Source.BASE_TABLE, KeyRange.closedOpen(Key.of("k1"), Key.of("k2")), 1, 10, 11, 12, 13, 14); checkRange(Source.BASE_TABLE, KeySet.all(), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); }
@Test public void testBatchableMutationFilterFn_size() { Mutation all = Mutation.delete("test", KeySet.all()); Mutation prefix = Mutation.delete("test", KeySet.prefixRange(Key.of(1L))); Mutation range = Mutation.delete( "test", KeySet.range(KeyRange.openOpen(Key.of(1L), Key.newBuilder().build()))); MutationGroup[] mutationGroups = new MutationGroup[] {
Timestamp.ofTimeSecondsAndNanos(1, 2), Date.fromYearMonthDay(2017, 04, 17)))); reserializeAndAssert(Mutation.delete("test", KeySet.all())); reserializeAndAssert( Mutation.delete( "test", KeySet.newBuilder() .addRange(KeyRange.closedClosed(Key.of("one", 2, null), Key.of("two", 3, null))) .build())); reserializeAndAssert( Mutation.delete( "test", KeySet.newBuilder() .addRange(KeyRange.closedOpen(Key.of("one", 2, null), Key.of("two", 3, null))) .build())); reserializeAndAssert( "test", KeySet.newBuilder() .addRange(KeyRange.openClosed(Key.of("one", 2, null), Key.of("two", 3, null))) .build())); reserializeAndAssert( "test", KeySet.newBuilder() .addRange(KeyRange.openOpen(Key.of("one", 2, null), Key.of("two", 3, null))) .build()));
@Test public void equalsAndHashCode() { EqualsTester tester = new EqualsTester(); // Test factory method vs builder with defaults vs builder with all parts explicit. tester.addEqualityGroup( KeyRange.closedOpen(Key.of(1), Key.of(2)), KeyRange.newBuilder().setStart(Key.of(1)).setEnd(Key.of(2)).build(), KeyRange.newBuilder() .setStart(Key.of(1)) .setStartType(CLOSED) .setEnd(Key.of(2)) .setEndType(OPEN) .build()); // Differing endpoint types. tester.addEqualityGroup(KeyRange.closedClosed(Key.of(1), Key.of(2))); tester.addEqualityGroup(KeyRange.openOpen(Key.of(1), Key.of(2))); tester.addEqualityGroup(KeyRange.openClosed(Key.of(1), Key.of(2))); // Differing start/end keys. tester.addEqualityGroup(KeyRange.closedOpen(Key.of(2), Key.of(1))); tester.addEqualityGroup(KeyRange.closedClosed(Key.of(), Key.of())); // Prefix range. tester.addEqualityGroup( KeyRange.prefix(Key.of(1, 2)), KeyRange.closedClosed(Key.of(1, 2), Key.of(1, 2))); tester.testEquals(); }
@Override public Status scan( String table, String startKey, int recordCount, Set<String> fields, Vector<HashMap<String, ByteIterator>> result) { if (queriesForReads) { return scanUsingQuery(table, startKey, recordCount, fields, result); } Iterable<String> columns = fields == null ? STANDARD_FIELDS : fields; KeySet keySet = KeySet.newBuilder().addRange(KeyRange.closedClosed(Key.of(startKey), Key.of())).build(); try (ResultSet resultSet = dbClient.singleUse(timestampBound) .read(table, keySet, columns, Options.limit(recordCount))) { while (resultSet.next()) { HashMap<String, ByteIterator> row = new HashMap<>(); decodeStruct(columns, resultSet, row); result.add(row); } return Status.OK; } catch (Exception e) { LOGGER.log(Level.INFO, "scan()", e); return Status.ERROR; } }
@Test public void serializationMulti() { KeySet keySet = KeySet.newBuilder() .addKey(Key.of("d", 1)) .addRange(KeyRange.closedOpen(Key.of("m"), Key.of("p"))) .addKey(Key.of("a", 1)) .addRange(KeyRange.closedClosed(Key.of("a"), Key.of("d"))) .build(); checkProto( keySet, "keys { values { string_value: 'd' } values { string_value: '1' } }" + " keys { values { string_value: 'a' } values { string_value:'1' } }" + " ranges { start_closed { values { string_value: 'm' } }" + " end_open { values { string_value: 'p' } } }" + " ranges { start_closed { values { string_value: 'a' } }" + " end_closed { values { string_value: 'd' } } }"); }
@Test public void serializationSingleRangeClosedClosed() { KeySet keySet = KeySet.range(KeyRange.closedClosed(Key.of("a"), Key.of("z"))); checkProto( keySet, "ranges { start_closed { values { string_value: 'a' } }" + " end_closed { values { string_value: 'z' } } }"); }
@Test public void toProtoCoalescingDelete() { List<Mutation> mutations = Arrays.asList( Mutation.delete("T", Key.of("k1")), Mutation.delete("T", Key.of("k2")), Mutation.delete("T", KeySet.range(KeyRange.closedOpen(Key.of("ka"), Key.of("kb")))), Mutation.delete("T", KeySet.range(KeyRange.closedClosed(Key.of("kc"), Key.of("kd"))))); List<com.google.spanner.v1.Mutation> proto = new ArrayList<>(); Mutation.toProto(mutations, proto); assertThat(proto.size()).isEqualTo(1); MatcherAssert.assertThat( proto.get(0), matchesProto( "delete {" + " table: 'T'" + " key_set {" + " keys { values { string_value: 'k1' } }" + " keys { values { string_value: 'k2' } }" + " ranges { start_closed { values { string_value: 'ka' } } " + " end_open { values { string_value: 'kb' } } }" + " ranges { start_closed { values { string_value: 'kc' } } " + " end_closed { values { string_value: 'kd' } } }" + " }" + "} ")); }
@Test public void limitRead() { checkRangeWithLimit( Source.BASE_TABLE, 2, KeyRange.closedClosed(Key.of("k3"), Key.of("k7")), 3, 4); checkRangeWithLimit( Source.BASE_TABLE, 0, KeyRange.closedClosed(Key.of("k3"), Key.of("k7")), 3, 4, 5, 6, 7); }
private static void checkKeyRange( KeyRange r, Key start, KeyRange.Endpoint startType, Key end, KeyRange.Endpoint endType) { assertThat(r.getStartType()).isEqualTo(startType); assertThat(r.geEndType()).isEqualTo(endType); assertThat(r.getStart()).isEqualTo(start); assertThat(r.getEnd()).isEqualTo(end); KeyRange fromBuilder = KeyRange.newBuilder() .setStart(start) .setStartType(startType) .setEnd(end) .setEndType(endType) .build(); assertThat(fromBuilder.getStartType()).isEqualTo(startType); assertThat(fromBuilder.geEndType()).isEqualTo(endType); assertThat(fromBuilder.getStart()).isEqualTo(start); assertThat(fromBuilder.getEnd()).isEqualTo(end); assertThat(fromBuilder).isEqualTo(r); assertThat(fromBuilder.hashCode()).isEqualTo(fromBuilder.hashCode()); }
/** * Returns a key range that covers all keys where the first {@code prefix.size()} components match * {@code prefix} exactly. */ public static KeyRange prefix(Key prefix) { return closedClosed(prefix, prefix); }
@Override public String toString() { StringBuilder b = new StringBuilder(); toString(b); return b.toString(); }