Skip to content

Commit 5cb0c26

Browse files
authored
feat(spanner): add support of checking row not found errors from ReadRow and ReadRowUsingIndex (#10405)
* feat(spanner): add support of checking row not found errors from ReadRow and ReadRowUsingIndex * incorporate suggestions * fix error message * fix error message
1 parent 1d28ac6 commit 5cb0c26

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

spanner/errors.go

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package spanner
1818

1919
import (
2020
"context"
21+
"errors"
2122
"fmt"
2223

2324
"github.com/googleapis/gax-go/v2/apierror"
@@ -26,6 +27,11 @@ import (
2627
"google.golang.org/grpc/status"
2728
)
2829

30+
var (
31+
// ErrRowNotFound row not found error
32+
ErrRowNotFound = errors.New("row not found")
33+
)
34+
2935
// Error is the structured error returned by Cloud Spanner client.
3036
//
3137
// Deprecated: Unwrap any error that is returned by the Spanner client as an APIError

spanner/integration_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,9 @@ func TestIntegration_Reads(t *testing.T) {
17311731
if ErrCode(err) != codes.NotFound {
17321732
t.Fatalf("got %v, want NotFound", err)
17331733
}
1734+
if !errors.Is(err, ErrRowNotFound) {
1735+
t.Fatalf("got %v, want spanner.ErrRowNotFound", err)
1736+
}
17341737
verifyDirectPathRemoteAddress(t)
17351738

17361739
// Index point read.
@@ -1751,6 +1754,9 @@ func TestIntegration_Reads(t *testing.T) {
17511754
if ErrCode(err) != codes.NotFound {
17521755
t.Fatalf("got %v, want NotFound", err)
17531756
}
1757+
if !errors.Is(err, ErrRowNotFound) {
1758+
t.Fatalf("got %v, want spanner.ErrRowNotFound", err)
1759+
}
17541760
verifyDirectPathRemoteAddress(t)
17551761
rangeReads(ctx, t, client)
17561762
indexRangeReads(ctx, t, client)

spanner/transaction.go

+26-4
Original file line numberDiff line numberDiff line change
@@ -326,12 +326,16 @@ func (t *txReadOnly) ReadWithOptions(ctx context.Context, table string, keys Key
326326
// errRowNotFound returns error for not being able to read the row identified by
327327
// key.
328328
func errRowNotFound(table string, key Key) error {
329-
return spannerErrorf(codes.NotFound, "row not found(Table: %v, PrimaryKey: %v)", table, key)
329+
err := spannerErrorf(codes.NotFound, "row not found(Table: %v, PrimaryKey: %v)", table, key)
330+
err.(*Error).err = ErrRowNotFound
331+
return err
330332
}
331333

332334
// errRowNotFoundByIndex returns error for not being able to read the row by index.
333335
func errRowNotFoundByIndex(table string, key Key, index string) error {
334-
return spannerErrorf(codes.NotFound, "row not found(Table: %v, IndexKey: %v, Index: %v)", table, key, index)
336+
err := spannerErrorf(codes.NotFound, "row not found(Table: %v, IndexKey: %v, Index: %v)", table, key, index)
337+
err.(*Error).err = ErrRowNotFound
338+
return err
335339
}
336340

337341
// errMultipleRowsFound returns error for receiving more than one row when reading a single row using an index.
@@ -346,8 +350,14 @@ func errInlineBeginTransactionFailed() error {
346350

347351
// ReadRow reads a single row from the database.
348352
//
349-
// If no row is present with the given key, then ReadRow returns an error where
353+
// If no row is present with the given key, then ReadRow returns an error(spanner.ErrRowNotFound) where
350354
// spanner.ErrCode(err) is codes.NotFound.
355+
//
356+
// To check if the error is spanner.ErrRowNotFound:
357+
//
358+
// if errors.Is(err, spanner.ErrRowNotFound) {
359+
// ...
360+
// }
351361
func (t *txReadOnly) ReadRow(ctx context.Context, table string, key Key, columns []string) (*Row, error) {
352362
return t.ReadRowWithOptions(ctx, table, key, columns, nil)
353363
}
@@ -356,6 +366,12 @@ func (t *txReadOnly) ReadRow(ctx context.Context, table string, key Key, columns
356366
//
357367
// If no row is present with the given key, then ReadRowWithOptions returns an error where
358368
// spanner.ErrCode(err) is codes.NotFound.
369+
//
370+
// To check if the error is spanner.ErrRowNotFound:
371+
//
372+
// if errors.Is(err, spanner.ErrRowNotFound) {
373+
// ...
374+
// }
359375
func (t *txReadOnly) ReadRowWithOptions(ctx context.Context, table string, key Key, columns []string, opts *ReadOptions) (*Row, error) {
360376
iter := t.ReadWithOptions(ctx, table, key, columns, opts)
361377
defer iter.Stop()
@@ -373,7 +389,13 @@ func (t *txReadOnly) ReadRowWithOptions(ctx context.Context, table string, key K
373389
// ReadRowUsingIndex reads a single row from the database using an index.
374390
//
375391
// If no row is present with the given index, then ReadRowUsingIndex returns an
376-
// error where spanner.ErrCode(err) is codes.NotFound.
392+
// error(spanner.ErrRowNotFound) where spanner.ErrCode(err) is codes.NotFound.
393+
//
394+
// To check if the error is spanner.ErrRowNotFound:
395+
//
396+
// if errors.Is(err, spanner.ErrRowNotFound) {
397+
// ...
398+
// }
377399
//
378400
// If more than one row received with the given index, then ReadRowUsingIndex
379401
// returns an error where spanner.ErrCode(err) is codes.FailedPrecondition.

0 commit comments

Comments
 (0)