com.google.cloud.spanner.Struct Java Examples
The following examples show how to use
com.google.cloud.spanner.Struct.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SpannerConverters.java From DataflowTemplates with Apache License 2.0 | 7 votes |
/** Function to get all column names from the table. */ private LinkedHashMap<String, String> getAllColumns(ReadContext context, String tableName) { LinkedHashMap<String, String> columns = Maps.newLinkedHashMap(); ResultSet resultSet = context.executeQuery( Statement.newBuilder( "SELECT COLUMN_NAME, SPANNER_TYPE FROM INFORMATION_SCHEMA.COLUMNS " + "WHERE TABLE_NAME=@table_name ORDER BY ORDINAL_POSITION") .bind("table_name") .to(tableName) .build()); LOG.info("Got schema information. Reading columns."); while (resultSet.next()) { Struct currentRow = resultSet.getCurrentRowAsStruct(); columns.put(currentRow.getString(0), currentRow.getString(1)); } return columns; }
Example #2
Source File: DatabaseClientSnippets.java From google-cloud-java with Apache License 2.0 | 6 votes |
/** Example of using {@link TransactionManager}. */ // [TARGET transactionManager()] // [VARIABLE my_singer_id] public void transactionManager(final long singerId) throws InterruptedException { // [START transactionManager] try (TransactionManager manager = dbClient.transactionManager()) { TransactionContext txn = manager.begin(); while (true) { try { String column = "FirstName"; Struct row = txn.readRow("Singers", Key.of(singerId), Collections.singleton(column)); String name = row.getString(column); txn.buffer( Mutation.newUpdateBuilder("Singers").set(column).to(name.toUpperCase()).build()); manager.commit(); break; } catch (AbortedException e) { Thread.sleep(e.getRetryDelayInMillis() / 1000); txn = manager.resetForRetry(); } } } // [END transactionManager] }
Example #3
Source File: SpannerConverters.java From DataflowTemplates with Apache License 2.0 | 6 votes |
/** * Prints Struct as a CSV String. * * @param struct Spanner Struct. * @return Spanner Struct encoded as a CSV String. */ public String print(Struct struct) { StringWriter stringWriter = new StringWriter(); try { CSVPrinter printer = new CSVPrinter(stringWriter, CSVFormat.DEFAULT.withRecordSeparator("") .withQuoteMode(QuoteMode.ALL_NON_NULL)); LinkedHashMap<String, BiFunction<Struct, String, String>> parsers = Maps.newLinkedHashMap(); parsers.putAll(mapColumnParsers(struct.getType().getStructFields())); List<String> values = parseResultSet(struct, parsers); printer.printRecord(values); } catch (IOException e) { throw new RuntimeException(e); } return stringWriter.toString(); }
Example #4
Source File: ConverterAwareMappingSpannerEntityReaderTests.java From spring-cloud-gcp with Apache License 2.0 | 6 votes |
@Test public void readSingularArrayMismatchTest() { this.expectedEx.expect(SpannerDataException.class); this.expectedEx.expectMessage("The value in column with name innerLengths could not be converted " + "to the corresponding property in the entity. The property's type is class java.lang.Integer."); Struct colStruct = Struct.newBuilder().set("string_col").to(Value.string("value")) .build(); Struct rowStruct = Struct.newBuilder().set("id").to(Value.string("key1")) .set("innerLengths") .toStructArray(Type.struct(StructField.of("string_col", Type.string())), Arrays.asList(colStruct)) .build(); new ConverterAwareMappingSpannerEntityReader(new SpannerMappingContext(), new SpannerReadConverter(Arrays.asList(new Converter<Struct, Integer>() { @Nullable @Override public Integer convert(Struct source) { return source.getString("string_col").length(); } }))).read(OuterTestEntityFlatFaulty.class, rowStruct); }
Example #5
Source File: DatabaseClientSnippets.java From google-cloud-java with Apache License 2.0 | 6 votes |
/** Example of read only transaction. */ // [TARGET readOnlyTransaction()] // [VARIABLE my_singer_id] // [VARIABLE my_album_id] public String readOnlyTransaction(long singerId, long albumId) { // [START readOnlyTransaction] String singerColumn = "FirstName"; String albumColumn = "AlbumTitle"; String albumTitle = null; // ReadOnlyTransaction should be closed to prevent resource leak. try (ReadOnlyTransaction txn = dbClient.readOnlyTransaction()) { Struct singerRow = txn.readRow("Singers", Key.of(singerId), Collections.singleton(singerColumn)); Struct albumRow = txn.readRow("Albums", Key.of(singerId, albumId), Collections.singleton(albumColumn)); singerRow.getString(singerColumn); albumTitle = albumRow.getString(albumColumn); } // [END readOnlyTransaction] return albumTitle; }
Example #6
Source File: ConverterAwareMappingSpannerEntityReaderTests.java From spring-cloud-gcp with Apache License 2.0 | 6 votes |
@Test public void readNestedStructWithConstructor() { Struct innerStruct = Struct.newBuilder().set("value").to(Value.string("value")) .build(); Struct outerStruct = Struct.newBuilder().set("id").to(Value.string("key1")) .set("innerTestEntities") .toStructArray(Type.struct(StructField.of("value", Type.string())), Arrays.asList(innerStruct)) .build(); TestEntities.OuterTestEntityWithConstructor result = this.spannerEntityReader .read(TestEntities.OuterTestEntityWithConstructor.class, outerStruct, null, true); assertThat(result.id).isEqualTo("key1"); assertThat(result.innerTestEntities).hasSize(1); assertThat(result.innerTestEntities.get(0).value).isEqualTo("value"); }
Example #7
Source File: DatabaseClientSnippets.java From google-cloud-java with Apache License 2.0 | 6 votes |
/** Example of a read write transaction. */ // [TARGET readWriteTransaction()] // [VARIABLE my_singer_id] public void readWriteTransaction(final long singerId) { // [START readWriteTransaction] TransactionRunner runner = dbClient.readWriteTransaction(); runner.run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws Exception { String column = "FirstName"; Struct row = transaction.readRow("Singers", Key.of(singerId), Collections.singleton(column)); String name = row.getString(column); transaction.buffer( Mutation.newUpdateBuilder("Singers").set(column).to(name.toUpperCase()).build()); return null; } }); // [END readWriteTransaction] }
Example #8
Source File: ConverterAwareMappingSpannerEntityReaderTests.java From spring-cloud-gcp with Apache License 2.0 | 6 votes |
@Test public void readConvertedNestedStructTest() { Struct colStruct = Struct.newBuilder().set("string_col").to(Value.string("value")) .build(); Struct rowStruct = Struct.newBuilder().set("id").to(Value.string("key1")) .set("innerLengths") .toStructArray(Type.struct(StructField.of("string_col", Type.string())), Arrays.asList(colStruct)) .build(); OuterTestEntityFlat result = new ConverterAwareMappingSpannerEntityReader( new SpannerMappingContext(), new SpannerReadConverter(Arrays.asList(new Converter<Struct, Integer>() { @Nullable @Override public Integer convert(Struct source) { return source.getString("string_col").length(); } }))).read(OuterTestEntityFlat.class, rowStruct); assertThat(result.id).isEqualTo("key1"); assertThat(result.innerLengths).hasSize(1); assertThat(result.innerLengths.get(0)).isEqualTo(5); }
Example #9
Source File: NaiveSpannerRead.java From beam with Apache License 2.0 | 6 votes |
@Override public PCollection<Struct> expand(PCollection<ReadOperation> input) { PCollectionView<Transaction> txView = getTxView(); if (txView == null) { Pipeline begin = input.getPipeline(); SpannerIO.CreateTransaction createTx = SpannerIO.createTransaction() .withSpannerConfig(getSpannerConfig()) .withTimestampBound(getTimestampBound()); txView = begin.apply(createTx); } return input.apply( "Naive read from Cloud Spanner", ParDo.of(new NaiveSpannerReadFn(getSpannerConfig(), txView)).withSideInputs(txView)); }
Example #10
Source File: ConverterAwareMappingSpannerEntityReaderTests.java From spring-cloud-gcp with Apache License 2.0 | 6 votes |
@Test public void readNestedStructsAsStructsTest() { Struct innerStruct = Struct.newBuilder().set("value") .to(Value.string("inner-value")).build(); Struct outerStruct = Struct.newBuilder().set("id").to(Value.string("key1")) .set("innerStructs") .toStructArray(Type.struct(StructField.of("value", Type.string())), Arrays.asList(innerStruct)) .build(); OuterTestHoldingStructsEntity result = this.spannerEntityReader .read(OuterTestHoldingStructsEntity.class, outerStruct); assertThat(result.id).isEqualTo("key1"); assertThat(result.innerStructs).hasSize(1); assertThat(result.innerStructs.get(0).getString("value")).isEqualTo("inner-value"); }
Example #11
Source File: ReadSpannerSchemaTest.java From beam with Apache License 2.0 | 6 votes |
private void prepareColumnMetadata(ReadOnlyTransaction tx, List<Struct> rows) { Type type = Type.struct( Type.StructField.of("table_name", Type.string()), Type.StructField.of("column_name", Type.string()), Type.StructField.of("spanner_type", Type.string()), Type.StructField.of("cells_mutated", Type.int64())); when(tx.executeQuery( argThat( new ArgumentMatcher<Statement>() { @Override public boolean matches(Statement argument) { if (!(argument instanceof Statement)) { return false; } Statement st = (Statement) argument; return st.getSql().contains("information_schema.columns"); } }))) .thenReturn(ResultSets.forRows(type, rows)); }
Example #12
Source File: SpannerIOWriteTest.java From beam with Apache License 2.0 | 6 votes |
private void prepareColumnMetadata(ReadOnlyTransaction tx, List<Struct> rows) { Type type = Type.struct( Type.StructField.of("table_name", Type.string()), Type.StructField.of("column_name", Type.string()), Type.StructField.of("spanner_type", Type.string()), Type.StructField.of("cells_mutated", Type.int64())); when(tx.executeQuery( argThat( new ArgumentMatcher<Statement>() { @Override public boolean matches(Statement argument) { if (!(argument instanceof Statement)) { return false; } Statement st = (Statement) argument; return st.getSql().contains("information_schema.columns"); } }))) .thenReturn(ResultSets.forRows(type, rows)); }
Example #13
Source File: SpannerRecordConverterTest.java From DataflowTemplates with Apache License 2.0 | 6 votes |
@Test public void dateTimestamp() { Ddl ddl = Ddl.builder() .createTable("users") .column("id").int64().notNull().endColumn() .column("date").date().endColumn() .column("ts").timestamp().endColumn() .primaryKey().asc("id").end() .endTable() .build(); Schema schema = converter.convert(ddl).iterator().next(); SpannerRecordConverter recordConverter = new SpannerRecordConverter(schema); Struct struct = Struct.newBuilder() .set("id").to(1L) .set("date").to(Date.fromYearMonthDay(2018, 2, 2)) .set("ts").to(Timestamp.ofTimeMicroseconds(10)) .build(); GenericRecord avroRecord = recordConverter.convert(struct); assertThat(avroRecord.get("id"), equalTo(1L)); assertThat(avroRecord.get("date"), equalTo("2018-02-02")); assertThat(avroRecord.get("ts"), equalTo("1970-01-01T00:00:00.000010000Z")); }
Example #14
Source File: RunningOperationsStore.java From spanner-jdbc with MIT License | 6 votes |
/** * * @return A result set of all DDL operations that have been issued on this connection since the * last clear operation. * @throws SQLException If a database error occurs */ ResultSet getOperations(CloudSpannerStatement statement) throws SQLException { List<Struct> rows = new ArrayList<>(operations.size()); for (DdlOperation op : operations) { op.operation = op.operation.reload(); String exception = null; try { op.operation.getResult(); } catch (Exception e) { exception = e.getMessage(); } for (String ddl : op.sql) { rows.add(Struct.newBuilder().set("NAME").to(Value.string(op.operation.getName())) .set("TIME_STARTED").to(Value.timestamp(op.timeStarted)).set("STATEMENT") .to(Value.string(ddl)).set("DONE").to(Value.bool(op.operation.isDone())) .set("EXCEPTION").to(Value.string(exception)).build()); } } com.google.cloud.spanner.ResultSet rs = ResultSets.forRows(Type.struct(StructField.of("NAME", Type.string()), StructField.of("TIME_STARTED", Type.timestamp()), StructField.of("STATEMENT", Type.string()), StructField.of("DONE", Type.bool()), StructField.of("EXCEPTION", Type.string())), rows); return new CloudSpannerResultSet(statement, rs, null); }
Example #15
Source File: SpannerIOWriteTest.java From beam with Apache License 2.0 | 6 votes |
private void preparePkMetadata(ReadOnlyTransaction tx, List<Struct> rows) { Type type = Type.struct( Type.StructField.of("table_name", Type.string()), Type.StructField.of("column_name", Type.string()), Type.StructField.of("column_ordering", Type.string())); when(tx.executeQuery( argThat( new ArgumentMatcher<Statement>() { @Override public boolean matches(Statement argument) { if (!(argument instanceof Statement)) { return false; } Statement st = (Statement) argument; return st.getSql().contains("information_schema.index_columns"); } }))) .thenReturn(ResultSets.forRows(type, rows)); }
Example #16
Source File: SpannerStatementQueryExecutor.java From spring-cloud-gcp with Apache License 2.0 | 6 votes |
/** * Creates a Cloud Spanner statement. * @param sql the SQL string with tags. * @param tags the tags that appear in the SQL string. * @param paramStructConvertFunc a function to use to convert params to {@link Struct} * objects if they cannot be directly mapped to Cloud Spanner supported param types. * If null then this last-attempt conversion is skipped. * @param spannerCustomConverter a converter used to convert params that aren't Cloud * Spanner native types. if {@code null} then this conversion is not attempted. * @param params the parameters to substitute the tags. The ordering must be the same as * the tags. * @param queryMethodParams the parameter metadata from Query Method if available. * @return an SQL statement ready to use with Spanner. * @throws IllegalArgumentException if the number of tags does not match the number of * params, or if a param of an unsupported type is given. */ public static Statement buildStatementFromSqlWithArgs(String sql, List<String> tags, Function<Object, Struct> paramStructConvertFunc, SpannerCustomConverter spannerCustomConverter, Object[] params, Map<String, Parameter> queryMethodParams) { if (tags == null && params == null) { return Statement.of(sql); } if (tags == null || params == null || tags.size() != params.length) { throw new IllegalArgumentException( "The number of tags does not match the number of params."); } Statement.Builder builder = Statement.newBuilder(sql); for (int i = 0; i < tags.size(); i++) { bindParameter(builder.bind(tags.get(i)), paramStructConvertFunc, spannerCustomConverter, params[i], queryMethodParams == null ? null : queryMethodParams.get(tags.get(i))); } return builder.build(); }
Example #17
Source File: SpannerStructReadMethodCoverageTests.java From spring-cloud-gcp with Apache License 2.0 | 6 votes |
@Test public void allKnownMappingTypesTest() throws NoSuchFieldException { for (Method method : Struct.class.getMethods()) { String methodName = method.getName(); // ignoring private methods, ones not named like a getter. Getters must also // only take the column index or name if (!Modifier.isPublic(method.getModifiers()) || !methodName.startsWith("get") || method.getParameterCount() != 1 || DISREGARDED_METHOD_NAMES.contains(methodName)) { continue; } Class returnType = ConversionUtils.boxIfNeeded(method.getReturnType()); if (ConversionUtils.isIterableNonByteArrayType(returnType)) { Class innerReturnType = (Class) ((ParameterizedType) method .getGenericReturnType()).getActualTypeArguments()[0]; assertThat(StructAccessor.readIterableMapping.keySet()).contains(innerReturnType); } else { assertThat(StructAccessor.singleItemReadMethodMapping.keySet()).contains(returnType); } } }
Example #18
Source File: SpannerSample.java From java-docs-samples with Apache License 2.0 | 6 votes |
static void updateUsingDmlWithStruct(DatabaseClient dbClient) { Struct name = Struct.newBuilder().set("FirstName").to("Timothy").set("LastName").to("Campbell").build(); Statement s = Statement.newBuilder( "UPDATE Singers SET LastName = 'Grant' " + "WHERE STRUCT<FirstName STRING, LastName STRING>(FirstName, LastName) " + "= @name") .bind("name") .to(name) .build(); dbClient .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws Exception { long rowCount = transaction.executeUpdate(s); System.out.printf("%d record updated.\n", rowCount); return null; } }); }
Example #19
Source File: ReadContextSnippets.java From google-cloud-java with Apache License 2.0 | 5 votes |
Struct readRowUsingIndex() { // [START read_context_read_index] ReadContext readContext = dbClient.singleUse(); Struct row = readContext.readRowUsingIndex( "Albums", "AlbumsByAlbumId", Key.of(1, "Green"), Arrays.asList("AlbumId", "AlbumTitle")); // [END read_context_read_index] return row; }
Example #20
Source File: ConverterAwareMappingSpannerEntityReaderTests.java From spring-cloud-gcp with Apache License 2.0 | 5 votes |
@Test public void testPartialConstructor() { Struct struct = Struct.newBuilder().set("id").to(Value.string("key1")) .set("custom_col").to(Value.string("string1")).set("booleanField") .to(Value.bool(true)).set("longField").to(Value.int64(3L)) .set("doubleField").to(Value.float64(3.14)).build(); this.spannerEntityReader.read(TestEntities.PartialConstructor.class, struct); }
Example #21
Source File: BatchSpannerRead.java From beam with Apache License 2.0 | 5 votes |
@ProcessElement public void processElement(ProcessContext c) throws Exception { Transaction tx = c.sideInput(txView); BatchReadOnlyTransaction batchTx = spannerAccessor.getBatchClient().batchReadOnlyTransaction(tx.transactionId()); Partition p = c.element(); try (ResultSet resultSet = batchTx.execute(p)) { while (resultSet.next()) { Struct s = resultSet.getCurrentRowAsStruct(); c.output(s); } } }
Example #22
Source File: ConverterAwareMappingSpannerEntityReaderTests.java From spring-cloud-gcp with Apache License 2.0 | 5 votes |
@Test public void ensureConstructorArgsAreReadOnce() { Struct row = mock(Struct.class); when(row.getString("id")).thenReturn("1234"); when(row.getType()).thenReturn( Type.struct(Arrays.asList(Type.StructField.of("id", Type.string())))); when(row.getColumnType("id")).thenReturn(Type.string()); TestEntities.SimpleConstructorTester result = this.spannerEntityReader .read(TestEntities.SimpleConstructorTester.class, row); assertThat(result.id).isEqualTo("1234"); verify(row, times(1)).getString("id"); }
Example #23
Source File: CloudSpannerConnection.java From spanner-jdbc with MIT License | 5 votes |
private ResultSet createResultSet(CloudSpannerStatement statement, Map<String, String> values) throws SQLException { List<Struct> rows = new ArrayList<>(values.size()); for (Entry<String, String> entry : values.entrySet()) { rows.add(Struct.newBuilder().set("NAME").to(Value.string(entry.getKey())).set("VALUE") .to(Value.string(entry.getValue())).build()); } com.google.cloud.spanner.ResultSet rs = ResultSets.forRows( Type.struct(StructField.of("NAME", Type.string()), StructField.of("VALUE", Type.string())), rows); return new CloudSpannerResultSet(statement, rs, null); }
Example #24
Source File: ConverterAwareMappingSpannerEntityReaderTests.java From spring-cloud-gcp with Apache License 2.0 | 5 votes |
@Test public void shouldReadEntityWithNoDefaultConstructor() { Struct row = Struct.newBuilder().set("id").to(Value.string("1234")).build(); TestEntities.SimpleConstructorTester result = this.spannerEntityReader .read(TestEntities.SimpleConstructorTester.class, row); assertThat(result.id).isEqualTo("1234"); }
Example #25
Source File: SpannerDatabaseAdminTemplate.java From spring-cloud-gcp with Apache License 2.0 | 5 votes |
/** * Return a map where key is the table name and the value is the parent table name. If * the table name in the key has no parent then the value is null. * @return the map of the table names. */ public Map<String, String> getChildParentTablesMap() { Map<String, String> relationships = new HashMap<>(); try (ResultSet results = this.databaseClientProvider.get().singleUse() .executeQuery(TABLE_AND_PARENT_QUERY)) { while (results.next()) { Struct row = results.getCurrentRowAsStruct(); relationships.put(row.getString(TABLE_NAME_COL_NAME), row.isNull(PARENT_TABLE_NAME_COL_NAME) ? null : row.getString(PARENT_TABLE_NAME_COL_NAME)); } return relationships; } }
Example #26
Source File: CloudSpannerResultSetMetaDataTest.java From spanner-jdbc with MIT License | 5 votes |
private CloudSpannerResultSet createFooPrimaryKeysResultSet(CloudSpannerStatement statement) throws SQLException { List<Struct> rows = new ArrayList<>(1); rows.add(Struct.newBuilder().set("COLUMN_NAME").to(Value.string(tableColumns().get(0).name)) .build()); ResultSet rs = ResultSets.forRows(Type.struct(StructField.of("COLUMN_NAME", Type.string())), rows); return new CloudSpannerResultSet(statement, rs, null); }
Example #27
Source File: ConverterAwareMappingSpannerEntityReaderTests.java From spring-cloud-gcp with Apache License 2.0 | 5 votes |
@Test public void readNestedStructAsStructTest() { Struct innerStruct = Struct.newBuilder().set("value") .to(Value.string("inner-value")).build(); Struct outerStruct = Struct.newBuilder().set("id").to(Value.string("key1")) .set("innerStruct").to(innerStruct).build(); OuterTestHoldingStructEntity result = this.spannerEntityReader .read(OuterTestHoldingStructEntity.class, outerStruct); assertThat(result.id).isEqualTo("key1"); assertThat(result.innerStruct.getString("value")).isEqualTo("inner-value"); }
Example #28
Source File: SpannerRecordConverterTest.java From DataflowTemplates with Apache License 2.0 | 5 votes |
@Test public void arrays() { Ddl ddl = Ddl.builder() .createTable("users") .column("id").int64().notNull().endColumn() .column("ints").type(Type.array(Type.int64())).endColumn() .column("strings").type(Type.array(Type.string())).max().endColumn() .column("ts").type(Type.array(Type.timestamp())).endColumn() .column("date").type(Type.array(Type.date())).endColumn() .primaryKey().asc("id").end() .endTable() .build(); Schema schema = converter.convert(ddl).iterator().next(); SpannerRecordConverter recordConverter = new SpannerRecordConverter(schema); Struct struct = Struct.newBuilder() .set("id").to(1L) .set("ints").toInt64Array(Lists.newArrayList(1L, null, 2L)) .set("strings").toStringArray(Lists.newArrayList(null, null, "one")) .set("ts").toTimestampArray(Lists.newArrayList(null, null, Timestamp.ofTimeMicroseconds(10L))) .set("date").toDateArray(Lists.newArrayList(null, null, Date.fromYearMonthDay(2018, 2, 2))) .build(); GenericRecord avroRecord = recordConverter.convert(struct); assertThat(avroRecord.get("id"), equalTo(1L)); assertThat(avroRecord.get("ints"), equalTo(Arrays.asList(1L, null, 2L))); assertThat(avroRecord.get("strings"), equalTo(Arrays.asList(null, null, "one"))); assertThat(avroRecord.get("date"), equalTo(Arrays.asList(null, null, "2018-02-02"))); assertThat(avroRecord.get("ts"), equalTo(Arrays.asList(null, null, "1970-01-01T00:00:00.000010000Z"))); }
Example #29
Source File: DatabaseClientSnippets.java From google-cloud-java with Apache License 2.0 | 5 votes |
/** Example of single use with timestamp bound. */ // [TARGET singleUse(TimestampBound)] // [VARIABLE my_singer_id] public String singleUseStale(long singerId) { // [START singleUseStale] String column = "FirstName"; Struct row = dbClient .singleUse(TimestampBound.ofMaxStaleness(10, TimeUnit.SECONDS)) .readRow("Singers", Key.of(singerId), Collections.singleton(column)); String firstName = row.getString(column); // [END singleUseStale] return firstName; }
Example #30
Source File: SpannerIO.java From beam with Apache License 2.0 | 5 votes |
@Override public PCollection<Struct> expand(PCollection<ReadOperation> input) { PTransform<PCollection<ReadOperation>, PCollection<Struct>> readTransform; if (getBatching()) { readTransform = BatchSpannerRead.create(getSpannerConfig(), getTransaction(), getTimestampBound()); } else { readTransform = NaiveSpannerRead.create(getSpannerConfig(), getTransaction(), getTimestampBound()); } return input .apply("Reshuffle", Reshuffle.viaRandomKey()) .apply("Read from Cloud Spanner", readTransform); }