Skip to content

Commit db21d28

Browse files
committed
WIP
1 parent b8b7dda commit db21d28

File tree

10 files changed

+181
-118
lines changed

10 files changed

+181
-118
lines changed

Spanner/src/Database.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,6 @@ public function runTransaction(callable $operation, array $options = []): mixed
932932

933933
$attempt = 0;
934934
$startTransactionFn = function ($session, $options) use (&$attempt) {
935-
936935
// Initial attempt requires to set `begin` options (ILB).
937936
if ($attempt === 0) {
938937
// Partitioned DML does not support ILB.

Spanner/src/Operation.php

Lines changed: 118 additions & 87 deletions
Large diffs are not rendered by default.

Spanner/src/Serializer.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
namespace Google\Cloud\Spanner;
44

5+
use Google\ApiCore\GPBType;
56
use Google\ApiCore\Serializer as ApiCoreSerializer;
67
use Google\Cloud\Core\ApiHelperTrait;
78
use Google\Cloud\Spanner\V1\PartialResultSet;
89
use Google\Cloud\Spanner\V1\Type;
10+
use Google\Protobuf\Internal\MapField;
911
use Google\Protobuf\Internal\RepeatedField as DeprecatedRepeatedField;
1012
use Google\Protobuf\RepeatedField;
13+
use Google\Protobuf\Struct;
1114
use Google\Protobuf\Value;
1215

1316
/**
@@ -60,7 +63,19 @@ public function __construct()
6063
}
6164

6265
return $keySet;
63-
}
66+
},
67+
'google.protobuf.Struct' => function ($v) {
68+
if (!isset($v['fields'])) {
69+
return ['fields' => $v];
70+
}
71+
return $v;
72+
},
73+
'google.protobuf.Value' => function ($v) {
74+
if (!is_array($v)) {
75+
return $this->formatValueForApi($v);
76+
}
77+
return $v;
78+
},
6479
];
6580
$customEncoders = [
6681
// A custom encoder that short-circuits the encodeMessage in Serializer class,

Spanner/src/Snapshot.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Snapshot implements TransactionalReadInterface
5252
* {@see \Google\Cloud\Spanner\V1\DirectedReadOptions}
5353
* If using the `replicaSelection::type` setting, utilize the constants available in
5454
* {@see \Google\Cloud\Spanner\V1\DirectedReadOptions\ReplicaSelection\Type} to set a value.
55+
* @type array $transactonOptions
5556
* }
5657
* @throws \InvalidArgumentException if a tag is specified as this is a read-only transaction.
5758
*/

Spanner/src/SnapshotTrait.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Google\ApiCore\ArrayTrait;
2121
use Google\Cloud\Spanner\Session\Session;
2222
use Google\Cloud\Spanner\Session\SessionPoolInterface;
23+
use Google\Cloud\Spanner\V1\TransactionOptions;
2324

2425
/**
2526
* Common methods for Read-Only transactions (i.e. Snapshots)
@@ -79,7 +80,7 @@ private function initialize(
7980
(array) $options,
8081
array_flip(['singleUse', 'begin'])
8182
);
82-
$this->transactionOptions = $options['transactionOptions'] ?? [];
83+
$this->transactionOptions = $options['transactionOptions'] ?? new TransactionOptions();
8384
}
8485

8586
/**

Spanner/src/Transaction.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
use Google\Cloud\Core\Exception\AbortedException;
2222
use Google\Cloud\Spanner\Session\Session;
2323
use Google\Cloud\Spanner\Session\SessionPoolInterface;
24+
use Google\Cloud\Spanner\V1\RequestOptions;
25+
use Google\Cloud\Spanner\V1\TransactionOptions;
2426
use Google\Protobuf\Duration;
2527

2628
/**
@@ -72,7 +74,7 @@ class Transaction implements TransactionalReadInterface
7274
private array $commitStats = [];
7375
private array $mutations = [];
7476
private bool $isRetry;
75-
private array $requestOptions;
77+
private array|RequestOptions $requestOptions;
7678

7779
/**
7880
* @param Operation $operation The Operation instance.
@@ -87,6 +89,7 @@ class Transaction implements TransactionalReadInterface
8789
* use this as the transaction tag.
8890
* @type array $begin The begin Transaction options, for using inline begin transactions.
8991
* See {@see V1\TransactionOptions}.
92+
* @type array $singleUse The singleUse Transaction options. See {@see V1\TransactionOptions}.
9093
* @type array $requestOptions See {@see V1\RequestOptions}.
9194
* @type array $transactionOptions See {@see V1\TransactionOptions}.
9295
* }
@@ -118,7 +121,7 @@ public function __construct(
118121
array_flip(['singleUse', 'begin'])
119122
);
120123
$this->requestOptions = $options['requestOptions'] ?? [];
121-
$this->transactionOptions = $options['transactionOptions'] ?? [];
124+
$this->transactionOptions = $options['transactionOptions'] ?? new TransactionOptions();
122125

123126
if (!is_null($mapper)) {
124127
$this->mapper = $mapper;
@@ -415,11 +418,11 @@ public function commit(array $options = []): Timestamp
415418
// For commit, A transaction ID is mandatory for non-single-use transactions,
416419
// and the `begin` option is not supported (because `begin` is only used in "inline begin transactions")
417420
if (empty($this->transactionId) && isset($this->transactionSelector['begin'])) {
418-
$operationTransactionOptions = [
421+
$operationTransactionOptions = array_filter([
419422
'requestOptions' => $this->requestOptions,
420423
'transactionOptions' => $this->transactionOptions,
421424
'singleUse' => $this->transactionSelector['singleUse'] ?? null,
422-
];
425+
]);
423426
// Execute the beginTransaction RPC.
424427
$transaction = $this->operation->transaction($this->session, $operationTransactionOptions);
425428
// Set the transaction ID of the current transaction.
@@ -519,6 +522,7 @@ private function buildUpdateOptions(array $options): array
519522
} else {
520523
$options['transactionId'] = $this->transactionId;
521524
}
525+
522526
$selector = $this->transactionSelector($options);
523527
$options['transaction'] = $selector[0];
524528

Spanner/src/TransactionConfigurationTrait.php

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
use Google\ApiCore\ArrayTrait;
2121
use Google\Cloud\Spanner\Session\SessionPoolInterface;
22+
use Google\Cloud\Spanner\V1\TransactionOptions;
23+
use Google\Cloud\Spanner\V1\TransactionOptions\PBReadOnly;
2224
use Google\Protobuf\Duration;
2325

2426
/**
@@ -39,10 +41,10 @@ trait TransactionConfigurationTrait
3941
* @see V1\TransactionSelector
4042
*
4143
* @param array $options call options.
42-
* @param array $previousReadOnlyOptions Previously given call options (for single-use snapshots).
44+
* @param PBReadOnly $previousReadOnlyOptions Previously given call options (for single-use snapshots).
4345
* @return array [(array) transaction selector, (string) context]
4446
*/
45-
private function transactionSelector(array &$options, array $previousReadOnlyOptions = []): array
47+
private function transactionSelector(array &$options, ?PBReadOnly $previousReadOnlyOptions = null): array
4648
{
4749
$options += [
4850
'begin' => false,
@@ -74,15 +76,15 @@ private function transactionSelector(array &$options, array $previousReadOnlyOpt
7476
*
7577
* @param array $options call options
7678
*
77-
* @param array $previousReadOnlyOptions Previously given call options (for single-use snapshots).
79+
* @param PBReadOnly $previousReadOnlyOptions Previously given call options (for single-use snapshots).
7880
* @return array [(array) transaction options, (string) transaction type, (string) context]
7981
*/
80-
private function transactionOptions(array &$options, array $previousReadOnlyOptions = []): array
82+
private function transactionOptions(array &$options, ?PBReadOnly $previousReadOnlyOptions = null): array
8183
{
8284
// @TODO: Remove $options being passed by reference
8385

8486
$type = null;
85-
$begin = $options['begin'] ?? false;
87+
$begin = $options['begin'] ?? [];
8688
$context = $options['transactionType'] ?? SessionPoolInterface::CONTEXT_READWRITE;
8789
$id = $options['transactionId'] ?? null;
8890

@@ -103,7 +105,8 @@ private function transactionOptions(array &$options, array $previousReadOnlyOpti
103105
$transactionOptions = $this->configureReadOnlyTransactionOptions($options, $previousReadOnlyOptions);
104106
} elseif ($context === SessionPoolInterface::CONTEXT_READWRITE) {
105107
$transactionOptions = $this->configureReadWriteTransactionOptions(
106-
$type == 'begin' && is_array($begin) ? $begin : []
108+
// TODO: Find out when $begin is a bool and fix it
109+
$type == 'begin' && !is_bool($begin) ? $begin : []
107110
);
108111
} else {
109112
throw new \BadMethodCallException(sprintf(
@@ -140,11 +143,14 @@ private function initReadWriteTransactionOptions(): array
140143
return ['readWrite' => []];
141144
}
142145

143-
private function configureReadWriteTransactionOptions(array $options = []): array
146+
private function configureReadWriteTransactionOptions(array|TransactionOptions $options): array
144147
{
145-
return array_intersect_key($options, array_flip([
146-
'excludeTxnFromChangeStreams',
147-
])) + $this->initReadWriteTransactionOptions();
148+
$excludeTxn = $options instanceof TransactionOptions
149+
? $options->getExcludeTxnFromChangeStreams()
150+
: $options['excludeTxnFromChangeStreams'] ?? null;
151+
return array_filter([
152+
'excludeTxnFromChangeStreams' => $excludeTxn,
153+
]) + $this->initReadWriteTransactionOptions();
148154
}
149155

150156
/**
@@ -180,10 +186,10 @@ private function configureReadWriteTransactionOptions(array $options = []): arra
180186
* "single-use", and may be used for only a single operation.
181187
* **Defaults to** `false`.
182188
* }
183-
* @param array $previousReadOnlyOptions Previously given call options (for single-use snapshots).
189+
* @param PBReadOnly $previousReadOnlyOptions Previously given call options (for single-use snapshots).
184190
* @return array
185191
*/
186-
private function configureReadOnlyTransactionOptions(array $options, array $previousReadOnlyOptions = []): array
192+
private function configureReadOnlyTransactionOptions(array $options, ?PBReadOnly $previousReadOnlyOptions = null): array
187193
{
188194
// select only the PBReadOnly fields from $options
189195
$readOnly = array_intersect_key($options, array_flip([
@@ -216,7 +222,8 @@ private function configureReadOnlyTransactionOptions(array $options, array $prev
216222
);
217223
}
218224

219-
$readOnly += $previousReadOnlyOptions;
225+
// Removing this for now - not sure why it's here
226+
// $readOnly += $previousReadOnlyOptions;
220227

221228
if (empty($readOnly)) {
222229
$readOnly['strong'] = true;

Spanner/src/TransactionalReadTrait.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
use Google\Cloud\Spanner\Session\Session;
2121
use Google\Cloud\Spanner\Session\SessionPoolInterface;
22+
use Google\Cloud\Spanner\V1\TransactionOptions;
23+
use Google\Cloud\Spanner\V1\TransactionOptions\PBReadOnly;
2224

2325
/**
2426
* Shared methods for reads inside a transaction.
@@ -42,7 +44,7 @@ trait TransactionalReadTrait
4244
/**
4345
* @see V1\TransactionOptions
4446
*/
45-
private array $transactionOptions = [];
47+
private TransactionOptions $transactionOptions;
4648
private int $seqno = 1;
4749
private string|null $tag = null;
4850
private array $directedReadOptions = [];
@@ -256,10 +258,8 @@ public function execute(string $sql, array $options = []): Result
256258
$executeSqlOptions['seqno'] = $this->seqno;
257259
$this->seqno++;
258260

259-
$selector = $this->transactionSelector(
260-
$executeSqlOptions,
261-
$this->transactionOptions['readOnly'] ?? []
262-
);
261+
$readOnly = $this->transactionOptions->getReadOnly();
262+
$selector = $this->transactionSelector($executeSqlOptions, $readOnly);
263263

264264
$executeSqlOptions['transaction'] = $selector[0];
265265

@@ -341,11 +341,10 @@ public function read(string $table, KeySet $keySet, array $columns, array $optio
341341
} else {
342342
$options['transactionId'] = $this->transactionId;
343343
}
344+
344345
$options['transactionType'] = $this->context;
345-
$selector = $this->transactionSelector(
346-
$options,
347-
$this->transactionOptions['readOnly'] ?? []
348-
);
346+
$readOnly = $this->transactionOptions->getReadOnly();
347+
$selector = $this->transactionSelector($options, $readOnly);
349348

350349
$options['transaction'] = $selector[0];
351350

Spanner/tests/Unit/TransactionConfigurationTraitTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public function testTransactionSelectorReadWrite()
7979
$args = ['transactionType' => SessionPoolInterface::CONTEXT_READWRITE];
8080
$res = $this->impl->transactionSelector($args);
8181
$this->assertEquals(SessionPoolInterface::CONTEXT_READWRITE, $res[1]);
82-
$this->assertEquals($this->impl->configureReadWriteTransactionOptions(), $res[0]['singleUse']);
82+
$this->assertEquals($this->impl->configureReadWriteTransactionOptions([]), $res[0]['singleUse']);
8383
}
8484

8585
public function testTransactionSelectorReadOnly()

Spanner/tests/Unit/TransactionTypeTest.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ public function testDatabaseRunTransactionSingleUse()
160160
$this->spannerClient->commit(
161161
Argument::that(function (CommitRequest $request) {
162162
$this->assertEquals(
163+
$this->createTransactionOptions(),
163164
$request->getSingleUseTransaction(),
164-
$this->createTransactionOptions()
165165
);
166166
return true;
167167
}),
@@ -975,6 +975,12 @@ private function serializerForStreamingSql(array $chunks, array $expectedTransac
975975
->shouldBeCalledOnce()
976976
->willReturn(new ExecuteSqlRequest());
977977

978+
$this->serializer->decodeMessage(
979+
Argument::type(BeginTransactionRequest::class),
980+
Argument::type('array')
981+
)
982+
->willReturn(new BeginTransactionRequest());
983+
978984
foreach ($chunks as $chunk) {
979985
$result = new PartialResultSet();
980986
$result->mergeFromJsonString($chunk);

0 commit comments

Comments
 (0)