Skip to content

Commit c07b187

Browse files
feat: Add documentation for Snapshot and Transaction for lockHint (#8612)
* Add documentation for Snapshot and Transaction for lockHint
1 parent 9af781f commit c07b187

5 files changed

Lines changed: 187 additions & 2 deletions

File tree

Spanner/src/Database.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2040,7 +2040,7 @@ public function executePartitionedUpdate($statement, array $options = [])
20402040
* @type int $orderBy Set the OrderBy option for the ReadRequest.
20412041
* {@see \Google\Cloud\Spanner\V1\ReadRequest} and {@see \Google\Cloud\Spanner\V1\ReadRequest\OrderBy}
20422042
* for more information and available options.
2043-
* @type int $lockHint Set the LockHint option for the ReadRequest.
2043+
* @type int $lockHint Set the LockHint option for the ReadRequest. Only available when transactionType is read/write.
20442044
* {@see \Google\Cloud\Spanner\V1\ReadRequest} and {@see \Google\Cloud\Spanner\V1\ReadRequest\LockHint}
20452045
* for more information and available options.
20462046
* }

Spanner/src/TransactionalReadTrait.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,13 @@ public function execute($sql, array $options = [])
351351
* {@see \Google\Cloud\Spanner\V1\DirectedReadOptions}
352352
* If using the `replicaSelection::type` setting, utilize the constants available in
353353
* {@see \Google\Cloud\Spanner\V1\DirectedReadOptions\ReplicaSelection\Type} to set a value.
354+
* @type int $orderBy Set the OrderBy option for the ReadRequest.
355+
* {@see \Google\Cloud\Spanner\V1\ReadRequest} and {@see \Google\Cloud\Spanner\V1\ReadRequest\OrderBy}
356+
* for more information and available options.
357+
* @type int $lockHint Set the LockHint option for the ReadRequest. Only available for ReadWrite transactions
358+
* and not Snapshots.
359+
* {@see \Google\Cloud\Spanner\V1\ReadRequest} and {@see \Google\Cloud\Spanner\V1\ReadRequest\LockHint}
360+
* for more information and available options.
354361
* }
355362
* @return Result
356363
*/

Spanner/tests/System/ReadTest.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@
1717

1818
namespace Google\Cloud\Spanner\Tests\System;
1919

20+
use Google\Cloud\Core\Exception\BadRequestException;
2021
use Google\Cloud\Core\Exception\ConflictException;
2122
use Google\Cloud\Core\Exception\DeadlineExceededException;
2223
use Google\Cloud\Core\Exception\NotFoundException;
2324
use Google\Cloud\Spanner\KeyRange;
2425
use Google\Cloud\Spanner\KeySet;
26+
use Google\Cloud\Spanner\Session\SessionPoolInterface;
27+
use Google\Cloud\Spanner\V1\ReadRequest\LockHint;
2528
use Google\Cloud\Spanner\V1\ReadRequest\OrderBy;
2629

2730
/**
@@ -241,6 +244,36 @@ public function testOrderByReturnsRowsOrderedById()
241244
}
242245
}
243246

247+
public function testLockHintReadWriteTransaction()
248+
{
249+
$db = self::$database;
250+
$limit = 10;
251+
252+
$res = $db->read(self::$rangeTableName, new KeySet(['all' => true]), array_keys(self::$dataset[0]), [
253+
'begin' => true,
254+
'transactionType' => SessionPoolInterface::CONTEXT_READWRITE,
255+
'lockHint' => LockHint::LOCK_HINT_EXCLUSIVE,
256+
'limit' => $limit,
257+
]);
258+
259+
$rows = iterator_to_array($res->rows());
260+
$this->assertNotEmpty($rows);
261+
$this->assertEquals($limit, count($rows));
262+
}
263+
264+
public function testLockHintOnReadOnlyThrowsAnError()
265+
{
266+
$this->skipEmulatorTests();
267+
$db = self::$database;
268+
$this->expectException(BadRequestException::class);
269+
270+
$res = $db->read(self::$rangeTableName, new KeySet(['all' => true]), array_keys(self::$dataset[0]), [
271+
'lockHint' => LockHint::LOCK_HINT_EXCLUSIVE
272+
]);
273+
274+
iterator_to_array($res->rows());
275+
}
276+
244277
/**
245278
* covers 9
246279
*/
@@ -552,7 +585,7 @@ private function insertUnorderedBatch()
552585
$json = json_decode($e->getMessage(), true);
553586

554587
if ($json['status'] == 'ALREADY_EXISTS') {
555-
$this->insertUnorderedBatch($data);
588+
$this->insertUnorderedBatch();
556589
} else {
557590
throw $e;
558591
}

Spanner/tests/System/SnapshotTest.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@
1717

1818
namespace Google\Cloud\Spanner\Tests\System;
1919

20+
use Google\Cloud\Core\Exception\BadRequestException;
21+
use Google\Cloud\Spanner\Date;
2022
use Google\Cloud\Spanner\Duration;
23+
use Google\Cloud\Spanner\KeySet;
2124
use Google\Cloud\Spanner\Timestamp;
25+
use Google\Cloud\Spanner\V1\ReadRequest\LockHint;
26+
use Google\Cloud\Spanner\V1\ReadRequest\OrderBy;
2227

2328
/**
2429
* @group spanner
@@ -237,6 +242,66 @@ public function testSnapshotMaxStalenessFails()
237242
]);
238243
}
239244

245+
public function testOrderByInSnapshot()
246+
{
247+
$db = self::$database;
248+
249+
$db->insertBatch(self::$tableName, [
250+
[
251+
'id' => rand(1, 346464),
252+
'number' => 1
253+
],
254+
[
255+
'id' => rand(1, 346464),
256+
'number' => 2
257+
]
258+
]);
259+
260+
$keySet = new KeySet([
261+
'all' => true
262+
]);
263+
$cols = ['id', 'number'];
264+
$options = [
265+
'orderBy' => OrderBy::ORDER_BY_PRIMARY_KEY,
266+
'limit' => 2,
267+
];
268+
269+
$snapshot = $db->snapshot();
270+
$res = $snapshot->read(self::$tableName, $keySet, $cols, $options);
271+
$rows = iterator_to_array($res->rows());
272+
273+
// Assert that the returned rows are sorted by the 'id' property.
274+
for ($i = 0; $i < count($rows) - 1; $i++) {
275+
$this->assertLessThanOrEqual(
276+
$rows[$i + 1]['id'],
277+
$rows[$i]['id'],
278+
'The array is not sorted by id in ascending order.'
279+
);
280+
}
281+
}
282+
283+
public function testLockHintInSnapshotThrowsAnException()
284+
{
285+
$this->skipEmulatorTests();
286+
$this->expectException(BadRequestException::class);
287+
$db = self::$database;
288+
289+
$keySet = new KeySet([
290+
'all' => true
291+
]);
292+
$cols = ['id', 'number'];
293+
294+
// LockHint is only for read-write transactions
295+
$options = [
296+
'lockHint' => LockHint::LOCK_HINT_EXCLUSIVE,
297+
'limit' => 2,
298+
];
299+
300+
$snapshot = $db->snapshot();
301+
$res = $snapshot->read(self::$tableName, $keySet, $cols, $options);
302+
$rows = iterator_to_array($res->rows());
303+
}
304+
240305
private function getRow($client, $id)
241306
{
242307
$result = $client->execute('SELECT * FROM ' . self::$tableName . ' WHERE id=@id', [

Spanner/tests/System/TransactionTest.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
use Google\Cloud\Core\Exception\ServiceException;
2323
use Google\Cloud\Spanner\Timestamp;
2424
use Google\Cloud\Spanner\V1\DirectedReadOptions\ReplicaSelection\Type as ReplicaType;
25+
use Google\Cloud\Spanner\V1\ReadRequest\LockHint;
26+
use Google\Cloud\Spanner\V1\ReadRequest\OrderBy;
2527

2628
/**
2729
* @group spanner
@@ -450,6 +452,67 @@ public function testRunTransactionILBWithMultipleOperations()
450452
$this->assertEquals([1], $res->rowCounts());
451453
}
452454

455+
public function testOrderByOnTransaction()
456+
{
457+
$db = self::$database;
458+
$transaction = $db->transaction();
459+
$limit = 10;
460+
461+
$db->insertBatch(self::TEST_TABLE_NAME, $this->getMultipleRows($limit));
462+
463+
$options = [
464+
'orderBy' => OrderBy::ORDER_BY_PRIMARY_KEY,
465+
'limit' => $limit,
466+
];
467+
468+
$rows = iterator_to_array(
469+
$transaction->read(
470+
self::TEST_TABLE_NAME,
471+
new KeySet([
472+
'all' => true,
473+
]),
474+
array_keys(self::$row),
475+
$options,
476+
)->rows()
477+
);
478+
479+
$this->assertEquals($limit, count($rows));
480+
$transaction->rollback();
481+
482+
for ($i = 0; $i < count($rows) - 1; $i++) {
483+
$this->assertLessThanOrEqual(
484+
$rows[$i + 1]['id'],
485+
$rows[$i]['id'],
486+
'The array is not sorted by id in ascending order.'
487+
);
488+
}
489+
}
490+
491+
public function testLockHintOnTransaction()
492+
{
493+
$db = self::$database;
494+
$transaction = $db->transaction();
495+
$limit = 10;
496+
497+
$db->insertBatch(self::TEST_TABLE_NAME, $this->getMultipleRows($limit));
498+
499+
$options = [
500+
'lockHint' => LockHint::LOCK_HINT_EXCLUSIVE,
501+
'limit' => $limit,
502+
];
503+
504+
$rows = $transaction->read(
505+
self::TEST_TABLE_NAME,
506+
new KeySet([
507+
'all' => true
508+
]),
509+
array_keys(self::$row),
510+
$options,
511+
)->rows();
512+
513+
$this->assertEquals($limit, count(iterator_to_array($rows)));
514+
}
515+
453516
public function getDirectedReadOptions()
454517
{
455518
return
@@ -503,4 +566,21 @@ private function getRow()
503566

504567
return $res->rows()->current();
505568
}
569+
570+
private function getMultipleRows(int $total)
571+
{
572+
$rows = [];
573+
574+
// Keeping the < total as the setup already inserts one.
575+
// if $total is 10, then we will generate 9 rows.
576+
for ($i = 0; $i < $total; $i++) {
577+
$rows[] = [
578+
'id' => rand(1, 346464),
579+
'name' => uniqid(self::TESTING_PREFIX),
580+
'birthday' => new Date(new \DateTime('2000-01-01'))
581+
];
582+
}
583+
584+
return $rows;
585+
}
506586
}

0 commit comments

Comments
 (0)