@@ -737,14 +737,16 @@ public synchronized void bufferMutations(List<Mutation> mutations) throws Spanne
737737 }
738738
739739 /** Execute a batch of updates in a read-write transaction. */
740- public synchronized long [] executeBatchDml (@ Nonnull List < Statement > stmts )
741- throws SpannerException {
740+ public synchronized long [] executeBatchDml (
741+ @ Nonnull List < Statement > stmts , Options . UpdateOption ... options ) throws SpannerException {
742742 for (int i = 0 ; i < stmts .size (); i ++) {
743743 LOGGER .log (
744744 Level .INFO , String .format ("executeBatchDml [%d]: %s" , i + 1 , stmts .get (i ).toString ()));
745745 }
746+ List <Options .UpdateOption > allOptions = new ArrayList <>(java .util .Arrays .asList (options ));
747+ allOptions .add (Options .tag ("batch-update-transaction-tag" ));
746748 return getTransactionForWrite ()
747- .batchUpdate (stmts , Options . tag ( "batch-update-transaction-tag" ));
749+ .batchUpdate (stmts , allOptions . toArray ( new Options . UpdateOption [ 0 ] ));
748750 }
749751
750752 /** Finish active transaction in given finishMode, then send outcome back to client. */
@@ -2199,13 +2201,54 @@ private Status executeGenerateDbPartitionsRead(
21992201 }
22002202
22012203 /** Execute action that generates database partitions for the given query. */
2204+ private Options .ReadQueryUpdateTransactionOption buildSecureContextOption (
2205+ Map <String , com .google .spanner .executor .v1 .Value > secureContextMap ) {
2206+ if (secureContextMap != null && !secureContextMap .isEmpty ()) {
2207+ com .google .spanner .v1 .RequestOptions .ClientContext .Builder clientContextBuilder =
2208+ com .google .spanner .v1 .RequestOptions .ClientContext .newBuilder ();
2209+ for (Map .Entry <String , com .google .spanner .executor .v1 .Value > entry :
2210+ secureContextMap .entrySet ()) {
2211+ com .google .protobuf .Value .Builder valueBuilder = com .google .protobuf .Value .newBuilder ();
2212+ if (entry .getValue ().getValueTypeCase ()
2213+ == com .google .spanner .executor .v1 .Value .ValueTypeCase .IS_NULL
2214+ && entry .getValue ().getIsNull ()) {
2215+ valueBuilder .setNullValue (com .google .protobuf .NullValue .NULL_VALUE );
2216+ } else if (entry .getValue ().getValueTypeCase ()
2217+ == com .google .spanner .executor .v1 .Value .ValueTypeCase .STRING_VALUE ) {
2218+ valueBuilder .setStringValue (entry .getValue ().getStringValue ());
2219+ } else {
2220+ throw new IllegalArgumentException (
2221+ "Unsupported secure parameter value type in executor proxy" );
2222+ }
2223+ clientContextBuilder .putSecureContext (entry .getKey (), valueBuilder .build ());
2224+ }
2225+ return Options .clientContext (clientContextBuilder .build ());
2226+ }
2227+ return null ;
2228+ }
2229+
2230+ @ SuppressWarnings ("unchecked" )
2231+ private <T > void addSecureContextOption (
2232+ Map <String , com .google .spanner .executor .v1 .Value > secureContextMap ,
2233+ List <T > optionsList ,
2234+ Class <?> optionClass ) {
2235+ Options .ReadQueryUpdateTransactionOption secureContextOption =
2236+ buildSecureContextOption (secureContextMap );
2237+ if (secureContextOption != null && optionClass .isInstance (secureContextOption )) {
2238+ optionsList .add ((T ) secureContextOption );
2239+ }
2240+ }
2241+
22022242 private Status executeGenerateDbPartitionsQuery (
22032243 GenerateDbPartitionsForQueryAction action ,
22042244 OutcomeSender sender ,
22052245 ExecutionFlowContext executionContext ) {
22062246 try {
22072247 BatchReadOnlyTransaction batchTxn = executionContext .getBatchTxn ();
22082248 Statement .Builder stmt = Statement .newBuilder (action .getQuery ().getSql ());
2249+ List <Options .QueryOption > queryOptions = new ArrayList <>();
2250+ addSecureContextOption (
2251+ action .getQuery ().getSecureContextMap (), queryOptions , Options .QueryOption .class );
22092252 for (int i = 0 ; i < action .getQuery ().getParamsCount (); ++i ) {
22102253 stmt .bind (action .getQuery ().getParams (i ).getName ())
22112254 .to (
@@ -2217,7 +2260,9 @@ private Status executeGenerateDbPartitionsQuery(
22172260 PartitionOptions .newBuilder ()
22182261 .setPartitionSizeBytes (action .getDesiredBytesPerPartition ())
22192262 .build ();
2220- List <Partition > parts = batchTxn .partitionQuery (partitionOptions , stmt .build ());
2263+ List <Partition > parts =
2264+ batchTxn .partitionQuery (
2265+ partitionOptions , stmt .build (), queryOptions .toArray (new Options .QueryOption [0 ]));
22212266 List <BatchPartition > batchPartitions = new ArrayList <>();
22222267 for (Partition part : parts ) {
22232268 batchPartitions .add (
@@ -2283,11 +2328,15 @@ private Status executePartitionedUpdate(
22832328 PartitionedUpdateAction action , DatabaseClient dbClient , OutcomeSender sender ) {
22842329 try {
22852330 ExecutePartitionedUpdateOptions options = action .getOptions ();
2331+ List <Options .UpdateOption > optionsList = new ArrayList <>();
2332+ optionsList .add (Options .tag (options .getTag ()));
2333+ optionsList .add (Options .priority (RpcPriority .fromProto (options .getRpcPriority ())));
2334+ addSecureContextOption (
2335+ action .getUpdate ().getSecureContextMap (), optionsList , Options .UpdateOption .class );
22862336 Long count =
22872337 dbClient .executePartitionedUpdate (
22882338 Statement .of (action .getUpdate ().getSql ()),
2289- Options .tag (options .getTag ()),
2290- Options .priority (RpcPriority .fromProto (options .getRpcPriority ())));
2339+ optionsList .toArray (new Options .UpdateOption [0 ]));
22912340 SpannerActionOutcome outcome =
22922341 SpannerActionOutcome .newBuilder ()
22932342 .setStatus (toProto (Status .OK ))
@@ -2740,7 +2789,11 @@ private Status executeQuery(
27402789 String .format (
27412790 "Finish query building, ready to execute %s\n " ,
27422791 executionContext .getTransactionSeed ()));
2743- ResultSet result = txn .executeQuery (stmt .build (), Options .tag ("query-tag" ));
2792+ List <Options .QueryOption > queryOptions = new ArrayList <>();
2793+ queryOptions .add (Options .tag ("query-tag" ));
2794+ addSecureContextOption (action .getSecureContextMap (), queryOptions , Options .QueryOption .class );
2795+ ResultSet result =
2796+ txn .executeQuery (stmt .build (), queryOptions .toArray (new Options .QueryOption [0 ]));
27442797 LOGGER .log (
27452798 Level .INFO ,
27462799 String .format ("Parsing query result %s\n " , executionContext .getTransactionSeed ()));
@@ -2770,10 +2823,14 @@ private Status executeCloudDmlUpdate(
27702823 update .getParams (i ).getType (), update .getParams (i ).getValue ()));
27712824 }
27722825 sender .initForQuery ();
2826+ List <Options .QueryOption > queryOptions = new ArrayList <>();
2827+ queryOptions .add (Options .tag ("dml-transaction-tag" ));
2828+ addSecureContextOption (
2829+ action .getUpdate ().getSecureContextMap (), queryOptions , Options .QueryOption .class );
27732830 ResultSet result =
27742831 executionContext
27752832 .getTransactionForWrite ()
2776- .executeQuery (stmt .build (), Options . tag ( "dml-transaction-tag" ));
2833+ .executeQuery (stmt .build (), queryOptions . toArray ( new Options . QueryOption [ 0 ] ));
27772834 LOGGER .log (
27782835 Level .INFO ,
27792836 String .format ("Parsing Dml result %s\n " , executionContext .getTransactionSeed ()));
@@ -2804,7 +2861,16 @@ private Status executeCloudBatchDmlUpdates(
28042861 }
28052862 queries .add (stmt .build ());
28062863 }
2807- long [] rowCounts = executionContext .executeBatchDml (queries );
2864+ Map <String , com .google .spanner .executor .v1 .Value > secureContextMap =
2865+ new java .util .HashMap <>();
2866+ for (int i = 0 ; i < action .getUpdatesCount (); ++i ) {
2867+ secureContextMap .putAll (action .getUpdates (i ).getSecureContextMap ());
2868+ }
2869+ List <Options .UpdateOption > optionsList = new ArrayList <>();
2870+ addSecureContextOption (secureContextMap , optionsList , Options .UpdateOption .class );
2871+ long [] rowCounts =
2872+ executionContext .executeBatchDml (
2873+ queries , optionsList .toArray (new Options .UpdateOption [0 ]));
28082874 sender .initForQuery ();
28092875 for (long rowCount : rowCounts ) {
28102876 sender .appendRowsModifiedInDml (rowCount );
0 commit comments