3737use Google \Cloud \Spanner \Session \Session ;
3838use Google \Cloud \Spanner \Session \SessionPoolInterface ;
3939use Google \Cloud \Spanner \V1 \SpannerClient as GapicSpannerClient ;
40+ use Google \Cloud \Spanner \V1 \TransactionOptions ;
41+ use Google \Cloud \Spanner \V1 \TransactionOptions \IsolationLevel ;
4042use Google \Cloud \Spanner \V1 \TypeCode ;
4143use Google \Rpc \Code ;
4244
@@ -192,6 +194,11 @@ class Database
192194 */
193195 private $ returnInt64AsObject ;
194196
197+ /**
198+ * @var int
199+ */
200+ private int $ isolationLevel ;
201+
195202 /**
196203 * Create an object representing a Database.
197204 *
@@ -210,6 +217,8 @@ class Database
210217 * be returned as a {@see \Google\Cloud\Core\Int64} object for 32 bit
211218 * platform compatibility. **Defaults to** false.
212219 * @param string $databaseRole The user created database role which creates the session.
220+ * @param int $isolationLevel The level of Isolation for the transactions executed by this Client's instance.
221+ * **Defaults to** IsolationLevel::ISOLATION_LEVEL_UNSPECIFIED
213222 */
214223 public function __construct (
215224 ConnectionInterface $ connection ,
@@ -221,7 +230,8 @@ public function __construct(
221230 ?SessionPoolInterface $ sessionPool = null ,
222231 $ returnInt64AsObject = false ,
223232 array $ info = [],
224- $ databaseRole = ''
233+ $ databaseRole = '' ,
234+ $ isolationLevel = IsolationLevel::ISOLATION_LEVEL_UNSPECIFIED
225235 ) {
226236 $ this ->connection = $ connection ;
227237 $ this ->instance = $ instance ;
@@ -239,6 +249,7 @@ public function __construct(
239249 $ this ->databaseRole = $ databaseRole ;
240250 $ this ->directedReadOptions = $ instance ->directedReadOptions ();
241251 $ this ->returnInt64AsObject = $ returnInt64AsObject ;
252+ $ this ->isolationLevel = $ isolationLevel ;
242253 }
243254
244255 /**
@@ -799,6 +810,8 @@ public function snapshot(array $options = [])
799810 * Session labels may be applied using the `labels` key.
800811 * @type string $tag A transaction tag. Requests made using this transaction will
801812 * use this as the transaction tag.
813+ * @type int $isolationLevel The level of Isolation for the transactions executed by this Client's instance.
814+ * **Defaults to** IsolationLevel::ISOLATION_LEVEL_UNSPECIFIED
802815 * }
803816 * @return Transaction
804817 * @throws \BadMethodCallException If attempting to call this method within
@@ -811,7 +824,9 @@ public function transaction(array $options = [])
811824 }
812825
813826 // Configure readWrite options here. Any nested options for readWrite should be added to this call
814- $ options ['transactionOptions ' ] = $ this ->configureTransactionOptions ($ options ['transactionOptions ' ] ?? []);
827+ $ options ['transactionOptions ' ] = $ this ->configureTransactionOptions ($ options ['transactionOptions ' ] ?? [
828+ 'isolationLevel ' => $ options ['isolationLevel ' ] ?? $ this ->isolationLevel
829+ ]);
815830
816831 $ session = $ this ->selectSession (
817832 SessionPoolInterface::CONTEXT_READWRITE ,
@@ -900,6 +915,9 @@ public function transaction(array $options = [])
900915 * Session labels may be applied using the `labels` key.
901916 * @type string $tag A transaction tag. Requests made using this transaction will
902917 * use this as the transaction tag.
918+ * @type array transactionOptions Options for the transaction.
919+ * {@see \Google\Cloud\Spanner\V1\TransactionOptions}
920+ * for available options
903921 * }
904922 * @return mixed The return value of `$operation`.
905923 * @throws \RuntimeException If a transaction is not committed or rolled back.
@@ -916,7 +934,11 @@ public function runTransaction(callable $operation, array $options = [])
916934 'maxRetries ' => self ::MAX_RETRIES ,
917935 ];
918936
919- $ options ['transactionOptions ' ] = $ this ->configureTransactionOptions ($ options ['transactionOptions ' ] ?? []);
937+ $ transactionOptions = (isset ($ options ['transactionOptions ' ])) ? $ options ['transactionOptions ' ] : [];
938+
939+ $ options ['transactionOptions ' ] = $ this ->configureTransactionOptions ([
940+ 'isolationLevel ' => $ options ['transactionOptions ' ]['isolationLevel ' ] ?? $ this ->isolationLevel
941+ ] + $ transactionOptions );
920942
921943 $ session = $ this ->selectSession (
922944 SessionPoolInterface::CONTEXT_READWRITE ,
@@ -928,6 +950,10 @@ public function runTransaction(callable $operation, array $options = [])
928950
929951 // Initial attempt requires to set `begin` options (ILB).
930952 if ($ attempt === 0 ) {
953+ if (!isset ($ options ['transactionOptions ' ]['isolationLevel ' ])) {
954+ $ options ['transactionOptions ' ]['isolationLevel ' ] = IsolationLevel::ISOLATION_LEVEL_UNSPECIFIED ;
955+ }
956+
931957 // Partitioned DML does not support ILB.
932958 if (!isset ($ options ['transactionOptions ' ]['partitionedDml ' ])) {
933959 $ options ['begin ' ] = $ options ['transactionOptions ' ];
@@ -1626,11 +1652,12 @@ public function delete($table, KeySet $keySet, array $options = [])
16261652 * timestamp.
16271653 * @type Duration $exactStaleness Represents a number of seconds. Executes
16281654 * all reads at a timestamp that is $exactStaleness old.
1629- * @type bool $begin If true, will begin a new transaction. If a
1655+ * @type bool|array $begin If true, will begin a new transaction. If a
16301656 * read/write transaction is desired, set the value of
16311657 * $transactionType. If a transaction or snapshot is created, it
16321658 * will be returned as `$result->transaction()` or
16331659 * `$result->snapshot()`. **Defaults to** `false`.
1660+ * If $begin is an array {@see TransactionOptions}
16341661 * @type string $transactionType One of `SessionPoolInterface::CONTEXT_READ`
16351662 * or `SessionPoolInterface::CONTEXT_READWRITE`. If read/write is
16361663 * chosen, any snapshot options will be disregarded. If `$begin`
@@ -1681,6 +1708,10 @@ public function execute($sql, array $options = [])
16811708 ) = $ this ->transactionSelector ($ options );
16821709 $ options = $ this ->addLarHeader ($ options , true , $ options ['transactionContext ' ]);
16831710
1711+ if (isset ($ options ['transaction ' ]['readWrite ' ])) {
1712+ $ options ['transaction ' ]['begin ' ]['isolationLevel ' ] ??= $ this ->isolationLevel ;
1713+ }
1714+
16841715 $ options ['directedReadOptions ' ] = $ this ->configureDirectedReadOptions (
16851716 $ options ,
16861717 $ this ->directedReadOptions ?? []
@@ -1745,7 +1776,7 @@ public function mutationGroup()
17451776 * transactions.
17461777 * }
17471778 *
1748- * @retur \Generator {@see \Google\Cloud\Spanner\V1\BatchWriteResponse}
1779+ * @return \Generator {@see \Google\Cloud\Spanner\V1\BatchWriteResponse}
17491780 *
17501781 * @throws ApiException if the remote call fails
17511782 */
@@ -1889,23 +1920,33 @@ public function batchWrite(array $mutationGroups, array $options = [])
18891920 * Please note, if using the `priority` setting you may utilize the constants available
18901921 * on {@see \Google\Cloud\Spanner\V1\RequestOptions\Priority} to set a value.
18911922 * Please note, the `transactionTag` setting will be ignored as it is not supported for partitioned DML.
1923+ * @type array $transactionOptions Transaction options.
1924+ * {@see V1\TransactionOptions}
18921925 * }
18931926 * @return int The number of rows modified.
1927+ * @throws ValidationException
18941928 */
18951929 public function executePartitionedUpdate ($ statement , array $ options = [])
18961930 {
18971931 unset($ options ['requestOptions ' ]['transactionTag ' ]);
1932+
1933+ if (isset ($ options ['transactionOptions ' ]['isolationLevel ' ])) {
1934+ throw new ValidationException ('Partitioned DML cannot be configured with an isolation level ' );
1935+ }
1936+
18981937 $ session = $ this ->selectSession (SessionPoolInterface::CONTEXT_READWRITE );
18991938
19001939 $ beginTransactionOptions = [
19011940 'transactionOptions ' => [
19021941 'partitionedDml ' => [],
19031942 ]
19041943 ];
1944+
19051945 if (isset ($ options ['transactionOptions ' ]['excludeTxnFromChangeStreams ' ])) {
19061946 $ beginTransactionOptions ['transactionOptions ' ]['excludeTxnFromChangeStreams ' ] =
19071947 $ options ['transactionOptions ' ]['excludeTxnFromChangeStreams ' ];
19081948 }
1949+
19091950 $ transaction = $ this ->operation ->transaction ($ session , $ beginTransactionOptions );
19101951
19111952 $ options = $ this ->addLarHeader ($ options );
0 commit comments