@Test public void all() { KeySet set = KeySet.all(); assertThat(set.isAll()).isTrue(); assertThat(set.getKeys()).isEmpty(); assertThat(set.getRanges()).isEmpty(); }
@Test public void singleKey() { KeySet set = KeySet.singleKey(Key.of("a", "b", "c")); assertThat(set.isAll()).isFalse(); assertThat(set.getKeys()).containsExactly(Key.of("a", "b", "c")); assertThat(set.getRanges()).isEmpty(); }
@Test public void prefixRange() { KeySet set = KeySet.prefixRange(Key.of("a", "b")); assertThat(set.isAll()).isFalse(); assertThat(set.getKeys()).isEmpty(); assertThat(set.getRanges()).containsExactly(KeyRange.prefix(Key.of("a", "b"))); }
@Test public void range() { KeySet set = KeySet.range(KeyRange.closedOpen(Key.of("a"), Key.of("b"))); assertThat(set.isAll()).isFalse(); assertThat(set.getKeys()).isEmpty(); assertThat(set.getRanges()).containsExactly(KeyRange.closedOpen(Key.of("a"), Key.of("b"))); }
@Test public void toBuilder() { KeySet set = KeySet.singleKey(Key.of(1)).toBuilder().addKey(Key.of(2)).build(); assertThat(set.isAll()).isFalse(); assertThat(set.getKeys()).containsExactly(Key.of(1), Key.of(2)).inOrder(); assertThat(set.getRanges()).isEmpty(); set = KeySet.range(KeyRange.closedOpen(Key.of("a"), Key.of("b"))) .toBuilder() .addRange(KeyRange.closedOpen(Key.of("c"), Key.of("d"))) .build(); assertThat(set.isAll()).isFalse(); assertThat(set.getKeys()).isEmpty(); assertThat(set.getRanges()) .containsExactly( KeyRange.closedOpen(Key.of("a"), Key.of("b")), KeyRange.closedOpen(Key.of("c"), Key.of("d"))) .inOrder(); set = KeySet.all().toBuilder().addKey(Key.of(1)).build(); assertThat(set.isAll()).isTrue(); assertThat(set.getKeys()).containsExactly(Key.of(1)); assertThat(set.getRanges()).isEmpty(); }
@Test public void builder() { KeySet set = KeySet.newBuilder() .addKey(Key.of("k1")) .addKey(Key.of("k2")) .addRange(KeyRange.closedOpen(Key.of("r1"), Key.of("rr1"))) .addRange(KeyRange.closedOpen(Key.of("r2"), Key.of("rr2"))) .build(); assertThat(set.isAll()).isFalse(); // Order isn't strictly important to the API, but it's helpful to preserve it. assertThat(set.getKeys()).containsExactly(Key.of("k1"), Key.of("k2")).inOrder(); assertThat(set.getRanges()) .containsExactly( KeyRange.closedOpen(Key.of("r1"), Key.of("rr1")), KeyRange.closedOpen(Key.of("r2"), Key.of("rr2"))) .inOrder(); assertThat(set.toString()).isEqualTo("{[k1],[k2],[[r1],[rr1]),[[r2],[rr2])}"); }
/** * Check if the mutation is a delete by a single primary key operation. * * @param m mutation * @return true if mutation is a point delete */ public static boolean isPointDelete(Mutation m) { return m.getOperation() == Mutation.Op.DELETE && Iterables.isEmpty(m.getKeySet().getRanges()) && Iterables.size(m.getKeySet().getKeys()) == 1; } }
private static long sizeOf(KeySet keySet) { long result = 0; for (Key k : keySet.getKeys()) { result += sizeOf(k); } for (KeyRange kr : keySet.getRanges()) { result += sizeOf(kr); } return result; }
/** * Builds a lexicographically sortable binary key based on a primary key descriptor. * * @param m a spanner mutation. * @return a binary string that preserves the ordering of the primary key. */ public byte[] encodeTableNameAndKey(Mutation m) { OrderedCode orderedCode = new OrderedCode(); orderedCode.writeBytes(m.getTable().getBytes(StandardCharsets.UTF_8)); if (m.getOperation() == Op.DELETE) { if (isPointDelete(m)) { Key next = m.getKeySet().getKeys().iterator().next(); encodeKey(orderedCode, m.getTable(), next); } else { // The key is left empty for non-point deletes, since there is no general way to batch them. } } else { encodeKey(orderedCode, m); } return orderedCode.getEncodedBytes(); }
/** Count the number of cells modified by {@link MutationGroup}. */ public static long countOf(SpannerSchema spannerSchema, MutationGroup mutationGroup) { long mutatedCells = 0L; for (Mutation mutation : mutationGroup) { if (mutation.getOperation() == Op.DELETE) { // For single key deletes sum up all the columns in the schema. // There is no clear way to estimate range deletes, so they are ignored. if (isPointDelete(mutation)) { final KeySet keySet = mutation.getKeySet(); final long rows = Iterables.size(keySet.getKeys()); mutatedCells += rows * spannerSchema.getCellsMutatedPerRow(mutation.getTable()); } } else { // sum the cells of the columns included in the mutation for (String column : mutation.getColumns()) { mutatedCells += spannerSchema.getCellsMutatedPerColumn(mutation.getTable(), column); } } } return mutatedCells; } }