21 files changed

+423
-178
lines changed
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,54 @@
406406
<className>com/google/cloud/spanner/AbstractLazyInitializer</className>
407407
<method>java.lang.Object initialize()</method>
408408
</difference>
409-
409+
410+
<!-- TransactionOptions and UpdateOptions -->
411+
<difference>
412+
<differenceType>7004</differenceType>
413+
<className>com/google/cloud/spanner/DatabaseClient</className>
414+
<method>long executePartitionedUpdate(com.google.cloud.spanner.Statement)</method>
415+
</difference>
416+
<difference>
417+
<differenceType>7004</differenceType>
418+
<className>com/google/cloud/spanner/DatabaseClient</className>
419+
<method>com.google.cloud.spanner.TransactionRunner readWriteTransaction()</method>
420+
</difference>
421+
<difference>
422+
<differenceType>7004</differenceType>
423+
<className>com/google/cloud/spanner/DatabaseClient</className>
424+
<method>com.google.cloud.spanner.AsyncRunner runAsync()</method>
425+
</difference>
426+
<difference>
427+
<differenceType>7004</differenceType>
428+
<className>com/google/cloud/spanner/DatabaseClient</className>
429+
<method>com.google.cloud.spanner.TransactionManager transactionManager()</method>
430+
</difference>
431+
<difference>
432+
<differenceType>7004</differenceType>
433+
<className>com/google/cloud/spanner/DatabaseClient</className>
434+
<method>com.google.cloud.spanner.AsyncTransactionManager transactionManagerAsync()</method>
435+
</difference>
436+
<difference>
437+
<differenceType>7004</differenceType>
438+
<className>com/google/cloud/spanner/TransactionContext</className>
439+
<method>long[] batchUpdate(java.lang.Iterable)</method>
440+
</difference>
441+
<difference>
442+
<differenceType>7004</differenceType>
443+
<className>com/google/cloud/spanner/TransactionContext</className>
444+
<method>com.google.api.core.ApiFuture batchUpdateAsync(java.lang.Iterable)</method>
445+
</difference>
446+
<difference>
447+
<differenceType>7004</differenceType>
448+
<className>com/google/cloud/spanner/TransactionContext</className>
449+
<method>long executeUpdate(com.google.cloud.spanner.Statement)</method>
450+
</difference>
451+
<difference>
452+
<differenceType>7004</differenceType>
453+
<className>com/google/cloud/spanner/TransactionContext</className>
454+
<method>com.google.api.core.ApiFuture executeUpdateAsync(com.google.cloud.spanner.Statement)</method>
455+
</difference>
456+
410457
<difference>
411458
<differenceType>7013</differenceType>
412459
<className>com/google/cloud/spanner/InstanceInfo$Builder</className>
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,8 @@ QueryOptions buildQueryOptions(QueryOptions requestOptions) {
554554
return builder.build();
555555
}
556556

557-
ExecuteSqlRequest.Builder getExecuteSqlRequestBuilder(Statement statement, QueryMode queryMode) {
557+
ExecuteSqlRequest.Builder getExecuteSqlRequestBuilder(
558+
Statement statement, QueryMode queryMode, Options options) {
558559
ExecuteSqlRequest.Builder builder =
559560
ExecuteSqlRequest.newBuilder()
560561
.setSql(statement.getSql())
@@ -577,7 +578,8 @@ ExecuteSqlRequest.Builder getExecuteSqlRequestBuilder(Statement statement, Query
577578
return builder;
578579
}
579580

580-
ExecuteBatchDmlRequest.Builder getExecuteBatchDmlRequestBuilder(Iterable<Statement> statements) {
581+
ExecuteBatchDmlRequest.Builder getExecuteBatchDmlRequestBuilder(
582+
Iterable<Statement> statements, Options options) {
581583
ExecuteBatchDmlRequest.Builder builder =
582584
ExecuteBatchDmlRequest.newBuilder().setSession(session.getName());
583585
int idx = 0;
@@ -609,7 +611,7 @@ ExecuteBatchDmlRequest.Builder getExecuteBatchDmlRequestBuilder(Iterable<Stateme
609611
ResultSet executeQueryInternalWithOptions(
610612
final Statement statement,
611613
final com.google.spanner.v1.ExecuteSqlRequest.QueryMode queryMode,
612-
Options options,
614+
final Options options,
613615
final ByteString partitionToken) {
614616
beforeReadOrQuery();
615617
final int prefetchChunks =
@@ -620,7 +622,7 @@ ResultSet executeQueryInternalWithOptions(
620622
CloseableIterator<PartialResultSet> startStream(@Nullable ByteString resumeToken) {
621623
GrpcStreamIterator stream = new GrpcStreamIterator(statement, prefetchChunks);
622624
final ExecuteSqlRequest.Builder request =
623-
getExecuteSqlRequestBuilder(statement, queryMode);
625+
getExecuteSqlRequestBuilder(statement, queryMode, options);
624626
if (partitionToken != null) {
625627
request.setPartitionToken(partitionToken);
626628
}
@@ -707,7 +709,7 @@ ResultSet readInternalWithOptions(
707709
@Nullable String index,
708710
KeySet keys,
709711
Iterable<String> columns,
710-
Options readOptions,
712+
final Options readOptions,
711713
ByteString partitionToken) {
712714
beforeReadOrQuery();
713715
final ReadRequest.Builder builder =
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.api.core.ApiFutures;
2323
import com.google.api.core.SettableApiFuture;
2424
import com.google.cloud.Timestamp;
25+
import com.google.cloud.spanner.Options.TransactionOption;
2526
import com.google.cloud.spanner.SessionImpl.SessionTransaction;
2627
import com.google.cloud.spanner.TransactionContextFutureImpl.CommittableAsyncTransactionManager;
2728
import com.google.cloud.spanner.TransactionManager.TransactionState;
@@ -40,14 +41,16 @@ final class AsyncTransactionManagerImpl
4041

4142
private final SessionImpl session;
4243
private Span span;
44+
private final Options options;
4345

4446
private TransactionRunnerImpl.TransactionContextImpl txn;
4547
private TransactionState txnState;
4648
private final SettableApiFuture<Timestamp> commitTimestamp = SettableApiFuture.create();
4749

48-
AsyncTransactionManagerImpl(SessionImpl session, Span span) {
50+
AsyncTransactionManagerImpl(SessionImpl session, Span span, TransactionOption... options) {
4951
this.session = session;
5052
this.span = span;
53+
this.options = Options.fromTransactionOptions(options);
5154
}
5255

5356
@Override
@@ -82,7 +85,7 @@ public TransactionContextFutureImpl beginAsync() {
8285

8386
private ApiFuture<TransactionContext> internalBeginAsync(boolean firstAttempt) {
8487
txnState = TransactionState.STARTED;
85-
txn = session.newTransaction();
88+
txn = session.newTransaction(options);
8689
if (firstAttempt) {
8790
session.setActive(this);
8891
}
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.google.cloud.Timestamp;
2020
import com.google.cloud.spanner.Options.TransactionOption;
21+
import com.google.cloud.spanner.Options.UpdateOption;
2122

2223
/**
2324
* Interface for all the APIs that are used to read/write data into a Cloud Spanner database. An
@@ -308,7 +309,7 @@ CommitResponse writeAtLeastOnceWithOptions(
308309
* });
309310
* </code></pre>
310311
*/
311-
TransactionRunner readWriteTransaction();
312+
TransactionRunner readWriteTransaction(TransactionOption... options);
312313

313314
/**
314315
* Returns a transaction manager which allows manual management of transaction lifecycle. This API
@@ -338,7 +339,7 @@ CommitResponse writeAtLeastOnceWithOptions(
338339
* }
339340
* }</pre>
340341
*/
341-
TransactionManager transactionManager();
342+
TransactionManager transactionManager(TransactionOption... options);
342343

343344
/**
344345
* Returns an asynchronous transaction runner for executing a single logical transaction with
@@ -371,7 +372,7 @@ CommitResponse writeAtLeastOnceWithOptions(
371372
* executor);
372373
* </code></pre>
373374
*/
374-
AsyncRunner runAsync();
375+
AsyncRunner runAsync(TransactionOption... options);
375376

376377
/**
377378
* Returns an asynchronous transaction manager which allows manual management of transaction
@@ -459,7 +460,7 @@ CommitResponse writeAtLeastOnceWithOptions(
459460
* }
460461
* }</pre>
461462
*/
462-
AsyncTransactionManager transactionManagerAsync();
463+
AsyncTransactionManager transactionManagerAsync(TransactionOption... options);
463464

464465
/**
465466
* Returns the lower bound of rows modified by this DML statement.
@@ -508,5 +509,5 @@ CommitResponse writeAtLeastOnceWithOptions(
508509
* <p>Given the above, Partitioned DML is good fit for large, database-wide, operations that are
509510
* idempotent, such as deleting old rows from a very large table.
510511
*/
511-
long executePartitionedUpdate(Statement stmt);
512+
long executePartitionedUpdate(Statement stmt, UpdateOption... options);
512513
}
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.google.cloud.Timestamp;
2020
import com.google.cloud.spanner.Options.TransactionOption;
21+
import com.google.cloud.spanner.Options.UpdateOption;
2122
import com.google.cloud.spanner.SessionPool.PooledSessionFuture;
2223
import com.google.cloud.spanner.SpannerImpl.ClosedException;
2324
import com.google.common.annotations.VisibleForTesting;
@@ -54,13 +55,20 @@ PooledSessionFuture getSession() {
5455

5556
@Override
5657
public Timestamp write(final Iterable<Mutation> mutations) throws SpannerException {
58+
return writeWithOptions(mutations).getCommitTimestamp();
59+
}
60+
61+
@Override
62+
public CommitResponse writeWithOptions(
63+
final Iterable<Mutation> mutations, final TransactionOption... options)
64+
throws SpannerException {
5765
Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan();
5866
try (Scope s = tracer.withSpan(span)) {
5967
return runWithSessionRetry(
60-
new Function<Session, Timestamp>() {
68+
new Function<Session, CommitResponse>() {
6169
@Override
62-
public Timestamp apply(Session session) {
63-
return session.write(mutations);
70+
public CommitResponse apply(Session session) {
71+
return session.writeWithOptions(mutations, options);
6472
}
6573
});
6674
} catch (RuntimeException e) {
@@ -72,21 +80,21 @@ public Timestamp apply(Session session) {
7280
}
7381

7482
@Override
75-
public CommitResponse writeWithOptions(Iterable<Mutation> mutations, TransactionOption... options)
76-
throws SpannerException {
77-
final Timestamp commitTimestamp = write(mutations);
78-
return new CommitResponse(commitTimestamp);
83+
public Timestamp writeAtLeastOnce(final Iterable<Mutation> mutations) throws SpannerException {
84+
return writeAtLeastOnceWithOptions(mutations).getCommitTimestamp();
7985
}
8086

8187
@Override
82-
public Timestamp writeAtLeastOnce(final Iterable<Mutation> mutations) throws SpannerException {
88+
public CommitResponse writeAtLeastOnceWithOptions(
89+
final Iterable<Mutation> mutations, final TransactionOption... options)
90+
throws SpannerException {
8391
Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan();
8492
try (Scope s = tracer.withSpan(span)) {
8593
return runWithSessionRetry(
86-
new Function<Session, Timestamp>() {
94+
new Function<Session, CommitResponse>() {
8795
@Override
88-
public Timestamp apply(Session session) {
89-
return session.writeAtLeastOnce(mutations);
96+
public CommitResponse apply(Session session) {
97+
return session.writeAtLeastOnceWithOptions(mutations, options);
9098
}
9199
});
92100
} catch (RuntimeException e) {
@@ -97,13 +105,6 @@ public Timestamp apply(Session session) {
97105
}
98106
}
99107

100-
@Override
101-
public CommitResponse writeAtLeastOnceWithOptions(
102-
Iterable<Mutation> mutations, TransactionOption... options) throws SpannerException {
103-
final Timestamp commitTimestamp = writeAtLeastOnce(mutations);
104-
return new CommitResponse(commitTimestamp);
105-
}
106-
107108
@Override
108109
public ReadContext singleUse() {
109110
Span span = tracer.spanBuilder(READ_ONLY_TRANSACTION).startSpan();
@@ -171,10 +172,10 @@ public ReadOnlyTransaction readOnlyTransaction(TimestampBound bound) {
171172
}
172173

173174
@Override
174-
public TransactionRunner readWriteTransaction() {
175+
public TransactionRunner readWriteTransaction(TransactionOption... options) {
175176
Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan();
176177
try (Scope s = tracer.withSpan(span)) {
177-
return getSession().readWriteTransaction();
178+
return getSession().readWriteTransaction(options);
178179
} catch (RuntimeException e) {
179180
TraceUtil.endSpanWithFailure(span, e);
180181
throw e;
@@ -184,47 +185,47 @@ public TransactionRunner readWriteTransaction() {
184185
}
185186

186187
@Override
187-
public TransactionManager transactionManager() {
188+
public TransactionManager transactionManager(TransactionOption... options) {
188189
Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan();
189190
try (Scope s = tracer.withSpan(span)) {
190-
return getSession().transactionManager();
191+
return getSession().transactionManager(options);
191192
} catch (RuntimeException e) {
192193
TraceUtil.endSpanWithFailure(span, e);
193194
throw e;
194195
}
195196
}
196197

197198
@Override
198-
public AsyncRunner runAsync() {
199+
public AsyncRunner runAsync(TransactionOption... options) {
199200
Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan();
200201
try (Scope s = tracer.withSpan(span)) {
201-
return getSession().runAsync();
202+
return getSession().runAsync(options);
202203
} catch (RuntimeException e) {
203204
TraceUtil.endSpanWithFailure(span, e);
204205
throw e;
205206
}
206207
}
207208

208209
@Override
209-
public AsyncTransactionManager transactionManagerAsync() {
210+
public AsyncTransactionManager transactionManagerAsync(TransactionOption... options) {
210211
Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan();
211212
try (Scope s = tracer.withSpan(span)) {
212-
return getSession().transactionManagerAsync();
213+
return getSession().transactionManagerAsync(options);
213214
} catch (RuntimeException e) {
214215
TraceUtil.endSpanWithFailure(span, e);
215216
throw e;
216217
}
217218
}
218219

219220
@Override
220-
public long executePartitionedUpdate(final Statement stmt) {
221+
public long executePartitionedUpdate(final Statement stmt, final UpdateOption... options) {
221222
Span span = tracer.spanBuilder(PARTITION_DML_TRANSACTION).startSpan();
222223
try (Scope s = tracer.withSpan(span)) {
223224
return runWithSessionRetry(
224225
new Function<Session, Long>() {
225226
@Override
226227
public Long apply(Session session) {
227-
return session.executePartitionedUpdate(stmt);
228+
return session.executePartitionedUpdate(stmt, options);
228229
}
229230
});
230231
} catch (RuntimeException e) {
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,19 @@ public interface ReadAndQueryOption extends ReadOption, QueryOption {}
3030
/** Marker interface to mark options applicable to read operation */
3131
public interface ReadOption {}
3232

33+
/** Marker interface to mark options applicable to Read, Query, Update and Write operations */
34+
public interface ReadQueryUpdateTransactionOption
35+
extends ReadOption, QueryOption, UpdateOption, TransactionOption {}
36+
3337
/** Marker interface to mark options applicable to query operation. */
3438
public interface QueryOption {}
3539

3640
/** Marker interface to mark options applicable to write operations */
3741
public interface TransactionOption {}
3842

43+
/** Marker interface to mark options applicable to update operation. */
44+
public interface UpdateOption {}
45+
3946
/** Marker interface to mark options applicable to list operations in admin API. */
4047
public interface ListOption {}
4148

@@ -287,6 +294,26 @@ static Options fromQueryOptions(QueryOption... options) {
287294
return readOptions;
288295
}
289296

297+
static Options fromUpdateOptions(UpdateOption... options) {
298+
Options updateOptions = new Options();
299+
for (UpdateOption option : options) {
300+
if (option instanceof InternalOption) {
301+
((InternalOption) option).appendToOptions(updateOptions);
302+
}
303+
}
304+
return updateOptions;
305+
}
306+
307+
static Options fromTransactionOptions(TransactionOption... options) {
308+
Options transactionOptions = new Options();
309+
for (TransactionOption option : options) {
310+
if (option instanceof InternalOption) {
311+
((InternalOption) option).appendToOptions(transactionOptions);
312+
}
313+
}
314+
return transactionOptions;
315+
}
316+
290317
static Options fromListOptions(ListOption... options) {
291318
Options listOptions = new Options();
292319
for (ListOption option : options) {

0 commit comments

Comments
 (0)