Cloud Spanner - Package cloud.google.com/go/spanner (v1.15.0)

Package spanner provides a client for reading and writing to Cloud Spanner databases. See the packages under admin for clients that operate on databases and instances.

See https://cloud.google.com/spanner/docs/getting-started/go/ for an introduction to Cloud Spanner and additional help on using this API.

See https://godoc.org/cloud.google.com/go for authentication, timeouts, connection pooling and similar aspects of this package.

Creating a Client

To start working with this package, create a client that refers to the database of interest:

 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 "projects/P/instances/I/databases/D" 
 ) 
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
 } 
 defer 
  
 client 
 . 
 Close 
 () 

Remember to close the client after use to free up the sessions in the session pool.

Simple Reads and Writes

Two Client methods, Apply and Single, work well for simple reads and writes. As a quick introduction, here we write a new row to the database and read it back:

 _ 
 , 
  
 err 
  
 := 
  
 client 
 . 
 Apply 
 ( 
 ctx 
 , 
  
 [] 
 * 
 spanner 
 . 
 Mutation 
 { 
  
 spanner 
 . 
 Insert 
 ( 
 "Users" 
 , 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "email" 
 }, 
  
 [] 
 interface 
 {}{ 
 "alice" 
 , 
  
 "a@example.com" 
 })}) 
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
 } 
 row 
 , 
  
 err 
  
 := 
  
 client 
 . 
 Single 
 (). 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Users" 
 , 
  
 spanner 
 . 
 Key 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "email" 
 }) 
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
 } 

All the methods used above are discussed in more detail below.

Keys

Every Cloud Spanner row has a unique key, composed of one or more columns. Construct keys with a literal of type Key:

 key1 
  
 := 
  
 spanner 
 . 
 Key 
 { 
 "alice" 
 } 

KeyRanges

The keys of a Cloud Spanner table are ordered. You can specify ranges of keys using the KeyRange type:

 kr1 
  
 := 
  
 spanner 
 . 
 KeyRange 
 { 
 Start 
 : 
  
 key1 
 , 
  
 End 
 : 
  
 key2 
 } 

By default, a KeyRange includes its start key but not its end key. Use the Kind field to specify other boundary conditions:

 // include both keys 
 kr2 
  
 := 
  
 spanner 
 . 
 KeyRange 
 { 
 Start 
 : 
  
 key1 
 , 
  
 End 
 : 
  
 key2 
 , 
  
 Kind 
 : 
  
 spanner 
 . 
 ClosedClosed 
 } 

KeySets

A KeySet represents a set of keys. A single Key or KeyRange can act as a KeySet. Use the KeySets function to build the union of several KeySets:

 ks1 
  
 := 
  
 spanner 
 . 
 KeySets 
 ( 
 key1 
 , 
  
 key2 
 , 
  
 kr1 
 , 
  
 kr2 
 ) 

AllKeys returns a KeySet that refers to all the keys in a table:

 ks2 
  
 := 
  
 spanner 
 . 
 AllKeys 
 () 

Transactions

All Cloud Spanner reads and writes occur inside transactions. There are two types of transactions, read-only and read-write. Read-only transactions cannot change the database, do not acquire locks, and may access either the current database state or states in the past. Read-write transactions can read the database before writing to it, and always apply to the most recent database state.

Single Reads

The simplest and fastest transaction is a ReadOnlyTransaction that supports a single read operation. Use Client.Single to create such a transaction. You can chain the call to Single with a call to a Read method.

When you only want one row whose key you know, use ReadRow. Provide the table name, key, and the columns you want to read:

 row 
 , 
  
 err 
  
 := 
  
 client 
 . 
 Single 
 (). 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
 Key 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "balance" 
 }) 

Read multiple rows with the Read method. It takes a table name, KeySet, and list of columns:

 iter 
  
 := 
  
 client 
 . 
 Single 
 (). 
 Read 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 keyset1 
 , 
  
 columns 
 ) 

Read returns a RowIterator. You can call the Do method on the iterator and pass a callback:

 err 
  
 := 
  
 iter 
 . 
 Do 
 ( 
 func 
 ( 
 row 
  
 * 
 Row 
 ) 
  
 error 
  
 { 
  
 // TODO: use row 
  
 return 
  
 nil 
 }) 

RowIterator also follows the standard pattern for the Google Cloud Client Libraries:

 defer 
  
 iter 
 . 
 Stop 
 () 
 for 
  
 { 
  
 row 
 , 
  
 err 
  
 := 
  
 iter 
 . 
 Next 
 () 
  
 if 
  
 err 
  
 == 
  
 iterator 
 . 
 Done 
  
 { 
  
 break 
  
 } 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 // TODO: use row 
 } 

Always call Stop when you finish using an iterator this way, whether or not you iterate to the end. (Failing to call Stop could lead you to exhaust the database's session quota.)

To read rows with an index, use ReadUsingIndex.

Statements

The most general form of reading uses SQL statements. Construct a Statement with NewStatement, setting any parameters using the Statement's Params map:

 stmt 
  
 := 
  
 spanner 
 . 
 NewStatement 
 ( 
 "SELECT First, Last FROM SINGERS WHERE Last >= @start" 
 ) 
 stmt 
 . 
 Params 
 [ 
 "start" 
 ] 
  
 = 
  
 "Dylan" 

You can also construct a Statement directly with a struct literal, providing your own map of parameters.

Use the Query method to run the statement and obtain an iterator:

 iter 
  
 := 
  
 client 
 . 
 Single 
 (). 
 Query 
 ( 
 ctx 
 , 
  
 stmt 
 ) 

Rows

Once you have a Row, via an iterator or a call to ReadRow, you can extract column values in several ways. Pass in a pointer to a Go variable of the appropriate type when you extract a value.

You can extract by column position or name:

 err 
  
 := 
  
 row 
 . 
 Column 
 ( 
 0 
 , 
  
& name 
 ) 
 err 
  
 = 
  
 row 
 . 
 ColumnByName 
 ( 
 "balance" 
 , 
  
& balance 
 ) 

You can extract all the columns at once:

 err 
  
 = 
  
 row 
 . 
 Columns 
 ( 
& name 
 , 
  
& balance 
 ) 

Or you can define a Go struct that corresponds to your columns, and extract into that:

 var 
  
 s 
  
 struct 
  
 { 
  
 Name 
  
 string 
 ; 
  
 Balance 
  
 int64 
  
 } 
 err 
  
 = 
  
 row 
 . 
 ToStruct 
 ( 
& s 
 ) 

For Cloud Spanner columns that may contain NULL, use one of the NullXXX types, like NullString:

 var 
  
 ns 
  
 spanner 
 . 
 NullString 
 if 
  
 err 
  
 := 
  
 row 
 . 
 Column 
 ( 
 0 
 , 
  
& ns 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
 } 
 if 
  
 ns 
 . 
 Valid 
  
 { 
  
 fmt 
 . 
 Println 
 ( 
 ns 
 . 
 StringVal 
 ) 
 } 
  
 else 
  
 { 
  
 fmt 
 . 
 Println 
 ( 
 "column is NULL" 
 ) 
 } 

Multiple Reads

To perform more than one read in a transaction, use ReadOnlyTransaction:

 txn 
  
 := 
  
 client 
 . 
 ReadOnlyTransaction 
 () 
 defer 
  
 txn 
 . 
 Close 
 () 
 iter 
  
 := 
  
 txn 
 . 
 Query 
 ( 
 ctx 
 , 
  
 stmt1 
 ) 
 // ... 
 iter 
  
 = 
  
 txn 
 . 
 Query 
 ( 
 ctx 
 , 
  
 stmt2 
 ) 
 // ... 

You must call Close when you are done with the transaction.

Timestamps and Timestamp Bounds

Cloud Spanner read-only transactions conceptually perform all their reads at a single moment in time, called the transaction's read timestamp. Once a read has started, you can call ReadOnlyTransaction's Timestamp method to obtain the read timestamp.

By default, a transaction will pick the most recent time (a time where all previously committed transactions are visible) for its reads. This provides the freshest data, but may involve some delay. You can often get a quicker response if you are willing to tolerate "stale" data. You can control the read timestamp selected by a transaction by calling the WithTimestampBound method on the transaction before using it. For example, to perform a query on data that is at most one minute stale, use

 client 
 . 
 Single 
 (). 
  
 WithTimestampBound 
 ( 
 spanner 
 . 
 MaxStaleness 
 ( 
 1 
 * 
 time 
 . 
 Minute 
 )). 
  
 Query 
 ( 
 ctx 
 , 
  
 stmt 
 ) 

See the documentation of TimestampBound for more details.

Mutations

To write values to a Cloud Spanner database, construct a Mutation. The spanner package has functions for inserting, updating and deleting rows. Except for the Delete methods, which take a Key or KeyRange, each mutation-building function comes in three varieties.

One takes lists of columns and values along with the table name:

 m1 
  
 := 
  
 spanner 
 . 
 Insert 
 ( 
 "Users" 
 , 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "email" 
 }, 
  
 [] 
 interface 
 {}{ 
 "alice" 
 , 
  
 "a@example.com" 
 }) 

One takes a map from column names to values:

 m2 
  
 := 
  
 spanner 
 . 
 InsertMap 
 ( 
 "Users" 
 , 
  
 map 
 [ 
 string 
 ] 
 interface 
 {}{ 
  
 "name" 
 : 
  
 "alice" 
 , 
  
 "email" 
 : 
  
 "a@example.com" 
 , 
 }) 

And the third accepts a struct value, and determines the columns from the struct field names:

 type 
  
 User 
  
 struct 
  
 { 
  
 Name 
 , 
  
 Email 
  
 string 
  
 } 
 u 
  
 := 
  
 User 
 { 
 Name 
 : 
  
 "alice" 
 , 
  
 Email 
 : 
  
 "a@example.com" 
 } 
 m3 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 InsertStruct 
 ( 
 "Users" 
 , 
  
 u 
 ) 

Writes

To apply a list of mutations to the database, use Apply:

 _ 
 , 
  
 err 
  
 := 
  
 client 
 . 
 Apply 
 ( 
 ctx 
 , 
  
 [] 
 * 
 spanner 
 . 
 Mutation 
 { 
 m1 
 , 
  
 m2 
 , 
  
 m3 
 }) 

If you need to read before writing in a single transaction, use a ReadWriteTransaction. ReadWriteTransactions may be aborted automatically by the backend and need to be retried. You pass in a function to ReadWriteTransaction, and the client will handle the retries automatically. Use the transaction's BufferWrite method to buffer mutations, which will all be executed at the end of the transaction:

 _ 
 , 
  
 err 
  
 := 
  
 client 
 . 
 ReadWriteTransaction 
 ( 
 ctx 
 , 
  
 func 
 ( 
 ctx 
  
 context 
 . 
 Context 
 , 
  
 txn 
  
 * 
 spanner 
 . 
 ReadWriteTransaction 
 ) 
  
 error 
  
 { 
  
 var 
  
 balance 
  
 int64 
  
 row 
 , 
  
 err 
  
 := 
  
 txn 
 . 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
 Key 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // The transaction function will be called again if the error code 
  
 // of this error is Aborted. The backend may automatically abort 
  
 // any read/write transaction if it detects a deadlock or other 
  
 // problems. 
  
 return 
  
 err 
  
 } 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
 Column 
 ( 
 0 
 , 
  
& balance 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 if 
  
 balance 
  
< = 
  
 10 
  
 { 
  
 return 
  
 errors 
 . 
 New 
 ( 
 "insufficient funds in account" 
 ) 
  
 } 
  
 balance 
  
 -= 
  
 10 
  
 m 
  
 := 
  
 spanner 
 . 
 Update 
 ( 
 "Accounts" 
 , 
  
 [] 
 string 
 { 
 "user" 
 , 
  
 "balance" 
 }, 
  
 [] 
 interface 
 {}{ 
 "alice" 
 , 
  
 balance 
 }) 
  
 txn 
 . 
 BufferWrite 
 ([] 
 * 
 spanner 
 . 
 Mutation 
 { 
 m 
 }) 
  
 // The buffered mutation will be committed.  If the commit 
  
 // fails with an Aborted error, this function will be called 
  
 // again. 
  
 return 
  
 nil 
 }) 

Structs

Cloud Spanner STRUCT (aka STRUCT) values ( https://cloud.google.com/spanner/docs/data-types#struct-type ) can be represented by a Go struct value.

A proto StructType is built from the field types and field tag information of the Go struct. If a field in the struct type definition has a "spanner:<field_name>" tag, then the value of the "spanner" key in the tag is used as the name for that field in the built StructType, otherwise the field name in the struct definition is used. To specify a field with an empty field name in a Cloud Spanner STRUCT type, use the spanner:&quot;&quot; tag annotation against the corresponding field in the Go struct's type definition.

A STRUCT value can contain STRUCT-typed and Array-of-STRUCT typed fields and these can be specified using named struct-typed and []struct-typed fields inside a Go struct. However, embedded struct fields are not allowed. Unexported struct fields are ignored.

NULL STRUCT values in Cloud Spanner are typed. A nil pointer to a Go struct value can be used to specify a NULL STRUCT value of the corresponding StructType. Nil and empty slices of a Go STRUCT type can be used to specify NULL and empty array values respectively of the corresponding StructType. A slice of pointers to a Go struct type can be used to specify an array of NULL-able STRUCT values.

DML and Partitioned DML

Spanner supports DML statements like INSERT, UPDATE and DELETE. Use ReadWriteTransaction.Update to run DML statements. It returns the number of rows affected. (You can call use ReadWriteTransaction.Query with a DML statement. The first call to Next on the resulting RowIterator will return iterator.Done, and the RowCount field of the iterator will hold the number of affected rows.)

For large databases, it may be more efficient to partition the DML statement. Use client.PartitionedUpdate to run a DML statement in this way. Not all DML statements can be partitioned.

Tracing

This client has been instrumented to use OpenCensus tracing ( http://opencensus.io ). To enable tracing, see "Enabling Tracing for a Program" at https://godoc.org/go.opencensus.io/trace . OpenCensus tracing requires Go 1.8 or higher.

Constants

Scope, AdminScope

  const 
  
 ( 
  
 // Scope is the scope for Cloud Spanner Data API. 
  
 Scope 
  
 = 
  
 "https://www.googleapis.com/auth/spanner.data" 
  
 // AdminScope is the scope for Cloud Spanner Admin APIs. 
  
 AdminScope 
  
 = 
  
 "https://www.googleapis.com/auth/spanner.admin" 
 ) 
 

NumericPrecisionDigits, NumericScaleDigits

  const 
  
 ( 
  
 // NumericPrecisionDigits is the maximum number of digits in a NUMERIC 
  
 // value. 
  
 NumericPrecisionDigits 
  
 = 
  
 38 
  
 // NumericScaleDigits is the maximum number of digits after the decimal 
  
 // point in a NUMERIC value. 
  
 NumericScaleDigits 
  
 = 
  
 9 
 ) 
 

Variables

OpenSessionCount, OpenSessionCountView, MaxAllowedSessionsCount, MaxAllowedSessionsCountView, SessionsCount, SessionsCountView, MaxInUseSessionsCount, MaxInUseSessionsCountView, GetSessionTimeoutsCount, GetSessionTimeoutsCountView, AcquiredSessionsCount, AcquiredSessionsCountView, ReleasedSessionsCount, ReleasedSessionsCountView

  var 
  
 ( 
  
 // OpenSessionCount is a measure of the number of sessions currently opened. 
  
 // It is EXPERIMENTAL and subject to change or removal without notice. 
  
 OpenSessionCount 
  
 = 
  
  stats 
 
 . 
  Int64 
 
 ( 
  
 statsPrefix 
 + 
 "open_session_count" 
 , 
  
 "Number of sessions currently opened" 
 , 
  
  stats 
 
 . 
  UnitDimensionless 
 
 , 
  
 ) 
  
 // OpenSessionCountView is a view of the last value of OpenSessionCount. 
  
 // It is EXPERIMENTAL and subject to change or removal without notice. 
  
 OpenSessionCountView 
  
 = 
  
&  view 
 
 . 
  View 
 
 { 
  
 Measure 
 : 
  
  OpenSessionCount 
 
 , 
  
 Aggregation 
 : 
  
  view 
 
 . 
  LastValue 
 
 (), 
  
 TagKeys 
 : 
  
 tagCommonKeys 
 , 
  
 } 
  
 // MaxAllowedSessionsCount is a measure of the maximum number of sessions 
  
 // allowed. Configurable by the user. 
  
 MaxAllowedSessionsCount 
  
 = 
  
  stats 
 
 . 
  Int64 
 
 ( 
  
 statsPrefix 
 + 
 "max_allowed_sessions" 
 , 
  
 "The maximum number of sessions allowed. Configurable by the user." 
 , 
  
  stats 
 
 . 
  UnitDimensionless 
 
 , 
  
 ) 
  
 // MaxAllowedSessionsCountView is a view of the last value of 
  
 // MaxAllowedSessionsCount. 
  
 MaxAllowedSessionsCountView 
  
 = 
  
&  view 
 
 . 
  View 
 
 { 
  
 Measure 
 : 
  
  MaxAllowedSessionsCount 
 
 , 
  
 Aggregation 
 : 
  
  view 
 
 . 
  LastValue 
 
 (), 
  
 TagKeys 
 : 
  
 tagCommonKeys 
 , 
  
 } 
  
 // SessionsCount is a measure of the number of sessions in the pool 
  
 // including both in-use, idle, and being prepared. 
  
 SessionsCount 
  
 = 
  
  stats 
 
 . 
  Int64 
 
 ( 
  
 statsPrefix 
 + 
 "num_sessions_in_pool" 
 , 
  
 "The number of sessions currently in use." 
 , 
  
  stats 
 
 . 
  UnitDimensionless 
 
 , 
  
 ) 
  
 // SessionsCountView is a view of the last value of SessionsCount. 
  
 SessionsCountView 
  
 = 
  
&  view 
 
 . 
  View 
 
 { 
  
 Measure 
 : 
  
  SessionsCount 
 
 , 
  
 Aggregation 
 : 
  
  view 
 
 . 
  LastValue 
 
 (), 
  
 TagKeys 
 : 
  
  append 
 
 ( 
 tagCommonKeys 
 , 
  
 tagKeyType 
 ), 
  
 } 
  
 // MaxInUseSessionsCount is a measure of the maximum number of sessions 
  
 // in use during the last 10 minute interval. 
  
 MaxInUseSessionsCount 
  
 = 
  
  stats 
 
 . 
  Int64 
 
 ( 
  
 statsPrefix 
 + 
 "max_in_use_sessions" 
 , 
  
 "The maximum number of sessions in use during the last 10 minute interval." 
 , 
  
  stats 
 
 . 
  UnitDimensionless 
 
 , 
  
 ) 
  
 // MaxInUseSessionsCountView is a view of the last value of 
  
 // MaxInUseSessionsCount. 
  
 MaxInUseSessionsCountView 
  
 = 
  
&  view 
 
 . 
  View 
 
 { 
  
 Measure 
 : 
  
  MaxInUseSessionsCount 
 
 , 
  
 Aggregation 
 : 
  
  view 
 
 . 
  LastValue 
 
 (), 
  
 TagKeys 
 : 
  
 tagCommonKeys 
 , 
  
 } 
  
 // GetSessionTimeoutsCount is a measure of the number of get sessions 
  
 // timeouts due to pool exhaustion. 
  
 GetSessionTimeoutsCount 
  
 = 
  
  stats 
 
 . 
  Int64 
 
 ( 
  
 statsPrefix 
 + 
 "get_session_timeouts" 
 , 
  
 "The number of get sessions timeouts due to pool exhaustion." 
 , 
  
  stats 
 
 . 
  UnitDimensionless 
 
 , 
  
 ) 
  
 // GetSessionTimeoutsCountView is a view of the last value of 
  
 // GetSessionTimeoutsCount. 
  
 GetSessionTimeoutsCountView 
  
 = 
  
&  view 
 
 . 
  View 
 
 { 
  
 Measure 
 : 
  
  GetSessionTimeoutsCount 
 
 , 
  
 Aggregation 
 : 
  
  view 
 
 . 
  Count 
 
 (), 
  
 TagKeys 
 : 
  
 tagCommonKeys 
 , 
  
 } 
  
 // AcquiredSessionsCount is the number of sessions acquired from 
  
 // the session pool. 
  
 AcquiredSessionsCount 
  
 = 
  
  stats 
 
 . 
  Int64 
 
 ( 
  
 statsPrefix 
 + 
 "num_acquired_sessions" 
 , 
  
 "The number of sessions acquired from the session pool." 
 , 
  
  stats 
 
 . 
  UnitDimensionless 
 
 , 
  
 ) 
  
 // AcquiredSessionsCountView is a view of the last value of 
  
 // AcquiredSessionsCount. 
  
 AcquiredSessionsCountView 
  
 = 
  
&  view 
 
 . 
  View 
 
 { 
  
 Measure 
 : 
  
  AcquiredSessionsCount 
 
 , 
  
 Aggregation 
 : 
  
  view 
 
 . 
  Count 
 
 (), 
  
 TagKeys 
 : 
  
 tagCommonKeys 
 , 
  
 } 
  
 // ReleasedSessionsCount is the number of sessions released by the user 
  
 // and pool maintainer. 
  
 ReleasedSessionsCount 
  
 = 
  
  stats 
 
 . 
  Int64 
 
 ( 
  
 statsPrefix 
 + 
 "num_released_sessions" 
 , 
  
 "The number of sessions released by the user and pool maintainer." 
 , 
  
  stats 
 
 . 
  UnitDimensionless 
 
 , 
  
 ) 
  
 // ReleasedSessionsCountView is a view of the last value of 
  
 // ReleasedSessionsCount. 
  
 ReleasedSessionsCountView 
  
 = 
  
&  view 
 
 . 
  View 
 
 { 
  
 Measure 
 : 
  
  ReleasedSessionsCount 
 
 , 
  
 Aggregation 
 : 
  
  view 
 
 . 
  Count 
 
 (), 
  
 TagKeys 
 : 
  
 tagCommonKeys 
 , 
  
 } 
 ) 
 

CommitTimestamp

  var 
  
 ( 
  
 // CommitTimestamp is a special value used to tell Cloud Spanner to insert 
  
 // the commit timestamp of the transaction into a column. It can be used in 
  
 // a Mutation, or directly used in InsertStruct or InsertMap. See 
  
 // ExampleCommitTimestamp. This is just a placeholder and the actual value 
  
 // stored in this variable has no meaning. 
  
 CommitTimestamp 
  
 = 
  
 commitTimestamp 
 ) 
 

DefaultRetryBackoff

  var 
  
 DefaultRetryBackoff 
  
 = 
  
 gax 
 . 
 Backoff 
 { 
  
 Initial 
 : 
  
 20 
  
 * 
  
  time 
 
 . 
  Millisecond 
 
 , 
  
 Max 
 : 
  
 32 
  
 * 
  
  time 
 
 . 
  Second 
 
 , 
  
 Multiplier 
 : 
  
 1.3 
 , 
 } 
 

DefaultRetryBackoff is used for retryers as a fallback value when the server did not return any retry information.

DefaultSessionPoolConfig

  var 
  
 DefaultSessionPoolConfig 
  
 = 
  
  SessionPoolConfig 
 
 { 
  
 MinOpened 
 : 
  
 100 
 , 
  
 MaxOpened 
 : 
  
 numChannels 
  
 * 
  
 100 
 , 
  
 MaxBurst 
 : 
  
 10 
 , 
  
 WriteSessions 
 : 
  
 0.2 
 , 
  
 HealthCheckWorkers 
 : 
  
 10 
 , 
  
 HealthCheckInterval 
 : 
  
 healthCheckIntervalMins 
  
 * 
  
  time 
 
 . 
  Minute 
 
 , 
  
 // contains filtered or unexported fields 
 } 
 

DefaultSessionPoolConfig is the default configuration for the session pool that will be used for a Spanner client, unless the user supplies a specific session pool config.

Functions

func EnableStatViews

  func 
  
 EnableStatViews 
 () 
  
  error 
 
 

EnableStatViews enables all views of metrics relate to session management.

func ErrCode

  func 
  
 ErrCode 
 ( 
 err 
  
  error 
 
 ) 
  
  codes 
 
 . 
  Code 
 
 

ErrCode extracts the canonical error code from a Go error.

func ErrDesc

  func 
  
 ErrDesc 
 ( 
 err 
  
  error 
 
 ) 
  
  string 
 
 

ErrDesc extracts the Cloud Spanner error description from a Go error.

func ExtractRetryDelay

  func 
  
 ExtractRetryDelay 
 ( 
 err 
  
  error 
 
 ) 
  
 ( 
  time 
 
 . 
  Duration 
 
 , 
  
  bool 
 
 ) 
 

ExtractRetryDelay extracts retry backoff from a *spanner.Error if present.

func NumericString

  func 
  
 NumericString 
 ( 
 r 
  
 * 
  big 
 
 . 
  Rat 
 
 ) 
  
  string 
 
 

NumericString returns a string representing a *big.Rat in a format compatible with Spanner SQL. It returns a floating-point literal with 9 digits after the decimal point.

func ToSpannerError

  func 
  
 ToSpannerError 
 ( 
 err 
  
  error 
 
 ) 
  
  error 
 
 

ToSpannerError converts a general Go error to *spanner.Error. If the given error is already a *spanner.Error, the original error will be returned.

Spanner Errors are normally created by the Spanner client library from the returned status of a RPC. This method can also be used to create Spanner errors for use in tests. The recommended way to create test errors is calling this method with a status error, e.g. ToSpannerError(status.New(codes.NotFound, "Table not found").Err())

ApplyOption

  type 
  
 ApplyOption 
  
 func 
 ( 
 * 
 applyOption 
 ) 
 

An ApplyOption is an optional argument to Apply.

func ApplyAtLeastOnce

  func 
  
 ApplyAtLeastOnce 
 () 
  
  ApplyOption 
 
 

ApplyAtLeastOnce returns an ApplyOption that removes replay protection.

With this option, Apply may attempt to apply mutations more than once; if the mutations are not idempotent, this may lead to a failure being reported when the mutation was applied more than once. For example, an insert may fail with ALREADY_EXISTS even though the row did not exist before Apply was called. For this reason, most users of the library will prefer not to use this option. However, ApplyAtLeastOnce requires only a single RPC, whereas Apply's default replay protection may require an additional RPC. So this option may be appropriate for latency sensitive and/or high throughput blind writing.

BatchReadOnlyTransaction

  type 
  
 BatchReadOnlyTransaction 
  
 struct 
  
 { 
  
  ReadOnlyTransaction 
 
  
 ID 
  
  BatchReadOnlyTransactionID 
 
 } 
 

BatchReadOnlyTransaction is a ReadOnlyTransaction that allows for exporting arbitrarily large amounts of data from Cloud Spanner databases. BatchReadOnlyTransaction partitions a read/query request. Read/query request can then be executed independently over each partition while observing the same snapshot of the database. BatchReadOnlyTransaction can also be shared across multiple clients by passing around the BatchReadOnlyTransactionID and then recreating the transaction using Client.BatchReadOnlyTransactionFromID.

Note: if a client is used only to run partitions, you can create it using a ClientConfig with both MinOpened and MaxIdle set to zero to avoid creating unnecessary sessions. You can also avoid excess gRPC channels by setting ClientConfig.NumChannels to the number of concurrently active BatchReadOnlyTransactions you expect to have.

func (*BatchReadOnlyTransaction) AnalyzeQuery

AnalyzeQuery returns the query plan for statement.

func (*BatchReadOnlyTransaction) Cleanup

Cleanup cleans up all the resources used by this transaction and makes it unusable. Once this method is invoked, the transaction is no longer usable anywhere, including other clients/processes with which this transaction was shared.

Calling Cleanup is optional, but recommended. If Cleanup is not called, the transaction's resources will be freed when the session expires on the backend and is deleted. For more information about recycled sessions, see https://cloud.google.com/spanner/docs/sessions .

func (*BatchReadOnlyTransaction) Close

  func 
  
 ( 
 t 
  
 * 
  BatchReadOnlyTransaction 
 
 ) 
  
 Close 
 () 
 

Close marks the txn as closed.

func (*BatchReadOnlyTransaction) Execute

Execute runs a single Partition obtained from PartitionRead or PartitionQuery.

func (*BatchReadOnlyTransaction) PartitionQuery

PartitionQuery returns a list of Partitions that can be used to execute a query against the database.

func (*BatchReadOnlyTransaction) PartitionQueryWithOptions

  func 
  
 ( 
 t 
  
 * 
  BatchReadOnlyTransaction 
 
 ) 
  
 PartitionQueryWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 , 
  
 opt 
  
  PartitionOptions 
 
 , 
  
 qOpts 
  
  QueryOptions 
 
 ) 
  
 ([] 
 * 
  Partition 
 
 , 
  
  error 
 
 ) 
 

PartitionQueryWithOptions returns a list of Partitions that can be used to execute a query against the database. The sql query execution will be optimized based on the given query options.

func (*BatchReadOnlyTransaction) PartitionRead

  func 
  
 ( 
 t 
  
 * 
  BatchReadOnlyTransaction 
 
 ) 
  
 PartitionRead 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 , 
  
 opt 
  
  PartitionOptions 
 
 ) 
  
 ([] 
 * 
  Partition 
 
 , 
  
  error 
 
 ) 
 

PartitionRead returns a list of Partitions that can be used to read rows from the database. These partitions can be executed across multiple processes, even across different machines. The partition size and count hints can be configured using PartitionOptions.

func (*BatchReadOnlyTransaction) PartitionReadUsingIndex

  func 
  
 ( 
 t 
  
 * 
  BatchReadOnlyTransaction 
 
 ) 
  
 PartitionReadUsingIndex 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
 , 
  
 index 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 , 
  
 opt 
  
  PartitionOptions 
 
 ) 
  
 ([] 
 * 
  Partition 
 
 , 
  
  error 
 
 ) 
 

PartitionReadUsingIndex returns a list of Partitions that can be used to read rows from the database using an index.

func (*BatchReadOnlyTransaction) Query

Query executes a query against the database. It returns a RowIterator for retrieving the resulting rows.

Query returns only row data, without a query plan or execution statistics. Use QueryWithStats to get rows along with the plan and statistics. Use AnalyzeQuery to get just the plan.

func (*BatchReadOnlyTransaction) QueryWithOptions

  func 
  
 ( 
 t 
  
 * 
  BatchReadOnlyTransaction 
 
 ) 
  
 QueryWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 , 
  
 opts 
  
  QueryOptions 
 
 ) 
  
 * 
  RowIterator 
 
 

QueryWithOptions executes a SQL statment against the database. It returns a RowIterator for retrieving the resulting rows. The sql query execution will be optimized based on the given query options.

func (*BatchReadOnlyTransaction) QueryWithStats

  func 
  
 ( 
 t 
  
 * 
  BatchReadOnlyTransaction 
 
 ) 
  
 QueryWithStats 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 ) 
  
 * 
  RowIterator 
 
 

QueryWithStats executes a SQL statement against the database. It returns a RowIterator for retrieving the resulting rows. The RowIterator will also be populated with a query plan and execution statistics.

func (*BatchReadOnlyTransaction) Read

Read returns a RowIterator for reading multiple rows from the database.

func (*BatchReadOnlyTransaction) ReadRow

  func 
  
 ( 
 t 
  
 * 
  BatchReadOnlyTransaction 
 
 ) 
  
 ReadRow 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 key 
  
  Key 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 * 
  Row 
 
 , 
  
  error 
 
 ) 
 

ReadRow reads a single row from the database.

If no row is present with the given key, then ReadRow returns an error where spanner.ErrCode(err) is codes.NotFound.

func (*BatchReadOnlyTransaction) ReadRowUsingIndex

  func 
  
 ( 
 t 
  
 * 
  BatchReadOnlyTransaction 
 
 ) 
  
 ReadRowUsingIndex 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 index 
  
  string 
 
 , 
  
 key 
  
  Key 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 * 
  Row 
 
 , 
  
  error 
 
 ) 
 

ReadRowUsingIndex reads a single row from the database using an index.

If no row is present with the given index, then ReadRowUsingIndex returns an error where spanner.ErrCode(err) is codes.NotFound.

If more than one row received with the given index, then ReadRowUsingIndex returns an error where spanner.ErrCode(err) is codes.FailedPrecondition.

func (*BatchReadOnlyTransaction) ReadUsingIndex

  func 
  
 ( 
 t 
  
 * 
  BatchReadOnlyTransaction 
 
 ) 
  
 ReadUsingIndex 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
 , 
  
 index 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 ri 
  
 * 
  RowIterator 
 
 ) 
 

ReadUsingIndex calls ReadWithOptions with ReadOptions{Index: index}.

func (*BatchReadOnlyTransaction) ReadWithOptions

  func 
  
 ( 
 t 
  
 * 
  BatchReadOnlyTransaction 
 
 ) 
  
 ReadWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 , 
  
 opts 
  
 * 
  ReadOptions 
 
 ) 
  
 ( 
 ri 
  
 * 
  RowIterator 
 
 ) 
 

ReadWithOptions returns a RowIterator for reading multiple rows from the database. Pass a ReadOptions to modify the read operation.

BatchReadOnlyTransactionID

  type 
  
 BatchReadOnlyTransactionID 
  
 struct 
  
 { 
  
 // contains filtered or unexported fields 
 } 
 

BatchReadOnlyTransactionID is a unique identifier for a BatchReadOnlyTransaction. It can be used to re-create a BatchReadOnlyTransaction on a different machine or process by calling Client.BatchReadOnlyTransactionFromID.

func (BatchReadOnlyTransactionID) MarshalBinary

  func 
  
 ( 
 tid 
  
  BatchReadOnlyTransactionID 
 
 ) 
  
 MarshalBinary 
 () 
  
 ( 
 data 
  
 [] 
  byte 
 
 , 
  
 err 
  
  error 
 
 ) 
 

MarshalBinary implements BinaryMarshaler.

func (*BatchReadOnlyTransactionID) UnmarshalBinary

  func 
  
 ( 
 tid 
  
 * 
  BatchReadOnlyTransactionID 
 
 ) 
  
 UnmarshalBinary 
 ( 
 data 
  
 [] 
  byte 
 
 ) 
  
  error 
 
 

UnmarshalBinary implements BinaryUnmarshaler.

Client

  type 
  
 Client 
  
 struct 
  
 { 
  
 // contains filtered or unexported fields 
 } 
 

Client is a client for reading and writing data to a Cloud Spanner database. A client is safe to use concurrently, except for its Close method.

func NewClient

  func 
  
 NewClient 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 database 
  
  string 
 
 , 
  
 opts 
  
 ... 
  option 
 
 . 
  ClientOption 
 
 ) 
  
 ( 
 * 
  Client 
 
 , 
  
  error 
 
 ) 
 

NewClient creates a client to a database. A valid database name has the form projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID. It uses a default configuration.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 _ 
  
 = 
  
 client 
  
 // TODO: Use client. 
 } 
 

func NewClientWithConfig

  func 
  
 NewClientWithConfig 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 database 
  
  string 
 
 , 
  
 config 
  
  ClientConfig 
 
 , 
  
 opts 
  
 ... 
  option 
 
 . 
  ClientOption 
 
 ) 
  
 ( 
 c 
  
 * 
  Client 
 
 , 
  
 err 
  
  error 
 
 ) 
 

NewClientWithConfig creates a client to a database. A valid database name has the form projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
  NewClientWithConfig 
 
 ( 
 ctx 
 , 
  
 myDB 
 , 
  
 spanner 
 . 
  ClientConfig 
 
 { 
  
 NumChannels 
 : 
  
 10 
 , 
  
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 _ 
  
 = 
  
 client 
  
 // TODO: Use client. 
  
 client 
 . 
 Close 
 () 
  
 // Close client when done. 
 } 
 

func (*Client) Apply

  func 
  
 ( 
 c 
  
 * 
  Client 
 
 ) 
  
 Apply 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 ms 
  
 [] 
 * 
  Mutation 
 
 , 
  
 opts 
  
 ... 
  ApplyOption 
 
 ) 
  
 ( 
 commitTimestamp 
  
  time 
 
 . 
  Time 
 
 , 
  
 err 
  
  error 
 
 ) 
 

Apply applies a list of mutations atomically to the database.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 m 
  
 := 
  
 spanner 
 . 
 Update 
 ( 
 "Users" 
 , 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "email" 
 }, 
  
 [] 
 interface 
 {}{ 
 "alice" 
 , 
  
 "a@example.com" 
 }) 
  
 _ 
 , 
  
 err 
  
 = 
  
 client 
 . 
  Apply 
 
 ( 
 ctx 
 , 
  
 [] 
 * 
 spanner 
 . 
 Mutation 
 { 
 m 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
 } 
 

func (*Client) BatchReadOnlyTransaction

  func 
  
 ( 
 c 
  
 * 
  Client 
 
 ) 
  
 BatchReadOnlyTransaction 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 tb 
  
  TimestampBound 
 
 ) 
  
 ( 
 * 
  BatchReadOnlyTransaction 
 
 , 
  
  error 
 
 ) 
 

BatchReadOnlyTransaction returns a BatchReadOnlyTransaction that can be used for partitioned reads or queries from a snapshot of the database. This is useful in batch processing pipelines where one wants to divide the work of reading from the database across multiple machines.

Note: This transaction does not use the underlying session pool but creates a new session each time, and the session is reused across clients.

You should call Close() after the txn is no longer needed on local client, and call Cleanup() when the txn is finished for all clients, to free the session.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "sync" 
  
 "cloud.google.com/go/spanner" 
  
 "google.golang.org/api/iterator" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 var 
  
 ( 
  
 client 
  
 * 
 spanner 
 . 
 Client 
  
 txn 
  
 * 
 spanner 
 . 
 BatchReadOnlyTransaction 
  
 err 
  
 error 
  
 ) 
  
 if 
  
 client 
 , 
  
 err 
  
 = 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 defer 
  
 client 
 . 
 Close 
 () 
  
 if 
  
 txn 
 , 
  
 err 
  
 = 
  
 client 
 . 
 BatchReadOnlyTransaction 
 ( 
 ctx 
 , 
  
 spanner 
 . 
  StrongRead 
 
 ()); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 defer 
  
 txn 
 . 
 Close 
 () 
  
 // Singer represents the elements in a row from the Singers table. 
  
 type 
  
 Singer 
  
 struct 
  
 { 
  
 SingerID 
  
 int64 
  
 FirstName 
  
 string 
  
 LastName 
  
 string 
  
 SingerInfo 
  
 [] 
 byte 
  
 } 
  
 stmt 
  
 := 
  
 spanner 
 . 
  Statement 
 
 { 
 SQL 
 : 
  
 "SELECT * FROM Singers;" 
 } 
  
 partitions 
 , 
  
 err 
  
 := 
  
 txn 
 . 
 PartitionQuery 
 ( 
 ctx 
 , 
  
 stmt 
 , 
  
 spanner 
 . 
 PartitionOptions 
 {}) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 // Note: here we use multiple goroutines, but you should use separate 
  
 // processes/machines. 
  
 wg 
  
 := 
  
 sync 
 . 
 WaitGroup 
 {} 
  
 for 
  
 i 
 , 
  
 p 
  
 := 
  
 range 
  
 partitions 
  
 { 
  
 wg 
 . 
  Add 
 
 ( 
 1 
 ) 
  
 go 
  
 func 
 ( 
 i 
  
 int 
 , 
  
 p 
  
 * 
 spanner 
 . 
 Partition 
 ) 
  
 { 
  
 defer 
  
 wg 
 . 
 Done 
 () 
  
 iter 
  
 := 
  
 txn 
 . 
  Execute 
 
 ( 
 ctx 
 , 
  
 p 
 ) 
  
 defer 
  
 iter 
 . 
 Stop 
 () 
  
 for 
  
 { 
  
 row 
 , 
  
 err 
  
 := 
  
 iter 
 . 
 Next 
 () 
  
 if 
  
 err 
  
 == 
  
 iterator 
 . 
 Done 
  
 { 
  
 break 
  
 } 
  
 else 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 var 
  
 s 
  
 Singer 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  ToStruct 
 
 ( 
& s 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 _ 
  
 = 
  
 s 
  
 // TODO: Process the row. 
  
 } 
  
 }( 
 i 
 , 
  
 p 
 ) 
  
 } 
  
 wg 
 . 
 Wait 
 () 
 } 
 

func (*Client) BatchReadOnlyTransactionFromID

  func 
  
 ( 
 c 
  
 * 
  Client 
 
 ) 
  
 BatchReadOnlyTransactionFromID 
 ( 
 tid 
  
  BatchReadOnlyTransactionID 
 
 ) 
  
 * 
  BatchReadOnlyTransaction 
 
 

BatchReadOnlyTransactionFromID reconstruct a BatchReadOnlyTransaction from BatchReadOnlyTransactionID

func (*Client) Close

  func 
  
 ( 
 c 
  
 * 
  Client 
 
 ) 
  
 Close 
 () 
 

Close closes the client.

func (*Client) PartitionedUpdate

  func 
  
 ( 
 c 
  
 * 
  Client 
 
 ) 
  
 PartitionedUpdate 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 ) 
  
 ( 
 count 
  
  int64 
 
 , 
  
 err 
  
  error 
 
 ) 
 

PartitionedUpdate executes a DML statement in parallel across the database, using separate, internal transactions that commit independently. The DML statement must be fully partitionable: it must be expressible as the union of many statements each of which accesses only a single row of the table. The statement should also be idempotent, because it may be applied more than once.

PartitionedUpdate returns an estimated count of the number of rows affected. The actual number of affected rows may be greater than the estimate.

func (*Client) PartitionedUpdateWithOptions

  func 
  
 ( 
 c 
  
 * 
  Client 
 
 ) 
  
 PartitionedUpdateWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 , 
  
 opts 
  
  QueryOptions 
 
 ) 
  
 ( 
 count 
  
  int64 
 
 , 
  
 err 
  
  error 
 
 ) 
 

PartitionedUpdateWithOptions executes a DML statement in parallel across the database, using separate, internal transactions that commit independently. The sql query execution will be optimized based on the given query options.

func (*Client) ReadOnlyTransaction

  func 
  
 ( 
 c 
  
 * 
  Client 
 
 ) 
  
 ReadOnlyTransaction 
 () 
  
 * 
  ReadOnlyTransaction 
 
 

ReadOnlyTransaction returns a ReadOnlyTransaction that can be used for multiple reads from the database. You must call Close() when the ReadOnlyTransaction is no longer needed to release resources on the server.

ReadOnlyTransaction will use a strong TimestampBound by default. Use ReadOnlyTransaction.WithTimestampBound to specify a different TimestampBound. A non-strong bound can be used to reduce latency, or "time-travel" to prior versions of the database, see the documentation of TimestampBound for details.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 t 
  
 := 
  
 client 
 . 
 ReadOnlyTransaction 
 () 
  
 defer 
  
 t 
 . 
 Close 
 () 
  
 // TODO: Read with t using Read, ReadRow, ReadUsingIndex, or Query. 
 } 
 

func (*Client) ReadWriteTransaction

  func 
  
 ( 
 c 
  
 * 
  Client 
 
 ) 
  
 ReadWriteTransaction 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 f 
  
 func 
 ( 
  context 
 
 . 
  Context 
 
 , 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
  error 
 
 ) 
  
 ( 
 commitTimestamp 
  
  time 
 
 . 
  Time 
 
 , 
  
 err 
  
  error 
 
 ) 
 

ReadWriteTransaction executes a read-write transaction, with retries as necessary.

The function f will be called one or more times. It must not maintain any state between calls.

If the transaction cannot be committed or if f returns an ABORTED error, ReadWriteTransaction will call f again. It will continue to call f until the transaction can be committed or the Context times out or is cancelled. If f returns an error other than ABORTED, ReadWriteTransaction will abort the transaction and return the error.

To limit the number of retries, set a deadline on the Context rather than using a fixed limit on the number of attempts. ReadWriteTransaction will retry as needed until that deadline is met.

See https://godoc.org/cloud.google.com/go/spanner#ReadWriteTransaction for more details.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "errors" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 _ 
 , 
  
 err 
  
 = 
  
 client 
 . 
 ReadWriteTransaction 
 ( 
 ctx 
 , 
  
 func 
 ( 
 ctx 
  
 context 
 . 
 Context 
 , 
  
 txn 
  
 * 
 spanner 
 . 
 ReadWriteTransaction 
 ) 
  
 error 
  
 { 
  
 var 
  
 balance 
  
 int64 
  
 row 
 , 
  
 err 
  
 := 
  
 txn 
 . 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // This function will be called again if this is an IsAborted error. 
  
 return 
  
 err 
  
 } 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  Column 
 
 ( 
 0 
 , 
  
& balance 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 if 
  
 balance 
  
< = 
  
 10 
  
 { 
  
 return 
  
 errors 
 . 
 New 
 ( 
 "insufficient funds in account" 
 ) 
  
 } 
  
 balance 
  
 -= 
  
 10 
  
 m 
  
 := 
  
 spanner 
 . 
 Update 
 ( 
 "Accounts" 
 , 
  
 [] 
 string 
 { 
 "user" 
 , 
  
 "balance" 
 }, 
  
 [] 
 interface 
 {}{ 
 "alice" 
 , 
  
 balance 
 }) 
  
 return 
  
 txn 
 . 
  BufferWrite 
 
 ([] 
 * 
 spanner 
 . 
 Mutation 
 { 
 m 
 }) 
  
 // The buffered mutation will be committed. If the commit fails with an 
  
 // IsAborted error, this function will be called again. 
  
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
 } 
 

func (*Client) ReadWriteTransactionWithOptions

  func 
  
 ( 
 c 
  
 * 
  Client 
 
 ) 
  
 ReadWriteTransactionWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 f 
  
 func 
 ( 
  context 
 
 . 
  Context 
 
 , 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
  error 
 
 , 
  
 options 
  
  TransactionOptions 
 
 ) 
  
 ( 
 resp 
  
  CommitResponse 
 
 , 
  
 err 
  
  error 
 
 ) 
 

ReadWriteTransactionWithOptions executes a read-write transaction with configurable options, with retries as necessary.

ReadWriteTransactionWithOptions is a configurable ReadWriteTransaction.

See https://godoc.org/cloud.google.com/go/spanner#ReadWriteTransaction for more details.

func (*Client) Single

  func 
  
 ( 
 c 
  
 * 
  Client 
 
 ) 
  
 Single 
 () 
  
 * 
  ReadOnlyTransaction 
 
 

Single provides a read-only snapshot transaction optimized for the case where only a single read or query is needed. This is more efficient than using ReadOnlyTransaction() for a single read or query.

Single will use a strong TimestampBound by default. Use ReadOnlyTransaction.WithTimestampBound to specify a different TimestampBound. A non-strong bound can be used to reduce latency, or "time-travel" to prior versions of the database, see the documentation of TimestampBound for details.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 iter 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 Query 
 ( 
 ctx 
 , 
  
 spanner 
 . 
  NewStatement 
 
 ( 
 "SELECT FirstName FROM Singers" 
 )) 
  
 _ 
  
 = 
  
 iter 
  
 // TODO: iterate using Next or Do. 
 } 
 

ClientConfig

  type 
  
 ClientConfig 
  
 struct 
  
 { 
  
 // NumChannels is the number of gRPC channels. 
  
 // If zero, a reasonable default is used based on the execution environment. 
  
 // 
  
 // Deprecated: The Spanner client now uses a pool of gRPC connections. Use 
  
 // option.WithGRPCConnectionPool(numConns) instead to specify the number of 
  
 // connections the client should use. The client will default to a 
  
 // reasonable default if this option is not specified. 
  
 NumChannels 
  
  int 
 
  
 // SessionPoolConfig is the configuration for session pool. 
  
  SessionPoolConfig 
 
  
 // SessionLabels for the sessions created by this client. 
  
 // See https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#session 
  
 // for more info. 
  
 SessionLabels 
  
 map 
 [ 
  string 
 
 ] 
  string 
 
  
 // QueryOptions is the configuration for executing a sql query. 
  
 QueryOptions 
  
  QueryOptions 
 
  
 // CallOptions is the configuration for providing custom retry settings that 
  
 // override the default values. 
  
 CallOptions 
  
 * 
  vkit 
 
 . 
  CallOptions 
 
  
 // contains filtered or unexported fields 
 } 
 

ClientConfig has configurations for the client.

CommitOptions

  type 
  
 CommitOptions 
  
 struct 
  
 { 
  
 ReturnCommitStats 
  
  bool 
 
 } 
 

CommitOptions provides options for commiting a transaction in a database.

CommitResponse

  type 
  
 CommitResponse 
  
 struct 
  
 { 
  
 // CommitTs is the commit time for a transaction. 
  
 CommitTs 
  
  time 
 
 . 
  Time 
 
  
 // CommitStats is the commit statistics for a transaction. 
  
 CommitStats 
  
 * 
  sppb 
 
 . 
  CommitResponse_CommitStats 
 
 } 
 

CommitResponse provides a response of a transaction commit in a database.

Decoder

  type 
  
 Decoder 
  
 interface 
  
 { 
  
 DecodeSpanner 
 ( 
 input 
  
 interface 
 {}) 
  
  error 
 
 } 
 

Decoder is the interface implemented by a custom type that can be decoded from a supported type by Spanner. A code example:

type customField struct { Prefix string Suffix string }

// Convert a string to a customField value func (cf *customField) DecodeSpanner(val interface{}) (err error) { strVal, ok := val.(string) if !ok { return fmt.Errorf("failed to decode customField: %v", val) } s := strings.Split(strVal, "-") if len(s) > 1 { cf.Prefix = s[0] cf.Suffix = s[1] } return nil }

Encoder

  type 
  
 Encoder 
  
 interface 
  
 { 
  
 EncodeSpanner 
 () 
  
 ( 
 interface 
 {}, 
  
  error 
 
 ) 
 } 
 

Encoder is the interface implemented by a custom type that can be encoded to a supported type by Spanner. A code example:

type customField struct { Prefix string Suffix string }

// Convert a customField value to a string func (cf customField) EncodeSpanner() (interface{}, error) { var b bytes.Buffer b.WriteString(cf.Prefix) b.WriteString("-") b.WriteString(cf.Suffix) return b.String(), nil }

Error

  type 
  
 Error 
  
 struct 
  
 { 
  
 // Code is the canonical error code for describing the nature of a 
  
 // particular error. 
  
 // 
  
 // Deprecated: The error code should be extracted from the wrapped error by 
  
 // calling ErrCode(err error). This field will be removed in a future 
  
 // release. 
  
 Code 
  
  codes 
 
 . 
  Code 
 
  
 // Desc explains more details of the error. 
  
 Desc 
  
  string 
 
  
 // contains filtered or unexported fields 
 } 
 

Error is the structured error returned by Cloud Spanner client.

func (*Error) Error

  func 
  
 ( 
 e 
  
 * 
  Error 
 
 ) 
  
 Error 
 () 
  
  string 
 
 

Error implements error.Error.

func (*Error) GRPCStatus

  func 
  
 ( 
 e 
  
 * 
  Error 
 
 ) 
  
 GRPCStatus 
 () 
  
 * 
  status 
 
 . 
  Status 
 
 

GRPCStatus returns the corresponding gRPC Status of this Spanner error. This allows the error to be converted to a gRPC status using status.Convert(error) .

func (*Error) Unwrap

  func 
  
 ( 
 e 
  
 * 
  Error 
 
 ) 
  
 Unwrap 
 () 
  
  error 
 
 

Unwrap returns the wrapped error (if any).

GenericColumnValue

  type 
  
 GenericColumnValue 
  
 struct 
  
 { 
  
 Type 
  
 * 
  sppb 
 
 . 
  Type 
 
  
 Value 
  
 * 
  proto3 
 
 . 
  Value 
 
 } 
 

GenericColumnValue represents the generic encoded value and type of the column. See google.spanner.v1.ResultSet proto for details. This can be useful for proxying query results when the result types are not known in advance.

If you populate a GenericColumnValue from a row using Row.Column or related methods, do not modify the contents of Type and Value.

func (GenericColumnValue) Decode

  func 
  
 ( 
 v 
  
  GenericColumnValue 
 
 ) 
  
 Decode 
 ( 
 ptr 
  
 interface 
 {}) 
  
  error 
 
 

Decode decodes a GenericColumnValue. The ptr argument should be a pointer to a Go value that can accept v.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
  
 sppb 
  
 "google.golang.org/genproto/googleapis/spanner/v1" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 // In real applications, rows can be retrieved by methods like client.Single().ReadRow(). 
  
 row 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
  NewRow 
 
 ([] 
 string 
 { 
 "intCol" 
 , 
  
 "strCol" 
 }, 
  
 [] 
 interface 
 {}{ 
 42 
 , 
  
 "my-text" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 for 
  
 i 
  
 := 
  
 0 
 ; 
  
 i 
 < 
 row 
 . 
  Size 
 
 (); 
  
 i 
 ++ 
  
 { 
  
 var 
  
 col 
  
 spanner 
 . 
  GenericColumnValue 
 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  Column 
 
 ( 
 i 
 , 
  
& col 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 switch 
  
 col 
 . 
 Type 
 . 
 Code 
  
 { 
  
 case 
  
 sppb 
 . 
  TypeCode_INT64 
 
 : 
  
 var 
  
 v 
  
 int64 
  
 if 
  
 err 
  
 := 
  
 col 
 . 
  Decode 
 
 ( 
& v 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 "int" 
 , 
  
 v 
 ) 
  
 case 
  
 sppb 
 . 
  TypeCode_STRING 
 
 : 
  
 var 
  
 v 
  
 string 
  
 if 
  
 err 
  
 := 
  
 col 
 . 
  Decode 
 
 ( 
& v 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 "string" 
 , 
  
 v 
 ) 
  
 } 
  
 } 
 } 
 

Key

  type 
  
 Key 
  
 [] 
 interface 
 {} 
 

A Key can be either a Cloud Spanner row's primary key or a secondary index key. It is essentially an interface{} array, which represents a set of Cloud Spanner columns. A Key can be used as:

  • A primary key which uniquely identifies a Cloud Spanner row.
  • A secondary index key which maps to a set of Cloud Spanner rows indexed under it.
  • An endpoint of primary key/secondary index ranges; see the KeyRange type.

Rows that are identified by the Key type are outputs of read operation or targets of delete operation in a mutation. Note that for Insert/Update/InsertOrUpdate/Update mutation types, although they don't require a primary key explicitly, the column list provided must contain enough columns that can comprise a primary key.

Keys are easy to construct. For example, suppose you have a table with a primary key of username and product ID. To make a key for this table:

 key := spanner.Key{"john", 16} 

See the description of Row and Mutation types for how Go types are mapped to Cloud Spanner types. For convenience, Key type supports a wide range of Go types:

  • int, int8, int16, int32, int64, and NullInt64 are mapped to Cloud Spanner's INT64 type.
  • uint8, uint16 and uint32 are also mapped to Cloud Spanner's INT64 type.
  • float32, float64, NullFloat64 are mapped to Cloud Spanner's FLOAT64 type.
  • bool and NullBool are mapped to Cloud Spanner's BOOL type.
  • []byte is mapped to Cloud Spanner's BYTES type.
  • string and NullString are mapped to Cloud Spanner's STRING type.
  • time.Time and NullTime are mapped to Cloud Spanner's TIMESTAMP type.
  • civil.Date and NullDate are mapped to Cloud Spanner's DATE type.

func (Key) AsPrefix

  func 
  
 ( 
 key 
  
  Key 
 
 ) 
  
 AsPrefix 
 () 
  
  KeyRange 
 
 

AsPrefix returns a KeyRange for all keys where k is the prefix.

func (Key) String

  func 
  
 ( 
 key 
  
  Key 
 
 ) 
  
 String 
 () 
  
  string 
 
 

String implements fmt.Stringer for Key. For string, []byte and NullString, it prints the uninterpreted bytes of their contents, leaving caller with the opportunity to escape the output.

KeyRange

  type 
  
 KeyRange 
  
 struct 
  
 { 
  
 // Start specifies the left boundary of the key range; End specifies 
  
 // the right boundary of the key range. 
  
 Start 
 , 
  
 End 
  
  Key 
 
  
 // Kind describes whether the boundaries of the key range include 
  
 // their keys. 
  
 Kind 
  
  KeyRangeKind 
 
 } 
 

A KeyRange represents a range of rows in a table or index.

A range has a Start key and an End key. IncludeStart and IncludeEnd indicate whether the Start and End keys are included in the range.

For example, consider the following table definition:

 CREATE TABLE UserEvents (
  UserName STRING(MAX),
  EventDate STRING(10),
) PRIMARY KEY(UserName, EventDate); 

The following keys name rows in this table:

 spanner.Key{"Bob", "2014-09-23"}
spanner.Key{"Alfred", "2015-06-12"} 

Since the UserEvents table's PRIMARY KEY clause names two columns, each UserEvents key has two elements; the first is the UserName, and the second is the EventDate.

Key ranges with multiple components are interpreted lexicographically by component using the table or index key's declared sort order. For example, the following range returns all events for user "Bob" that occurred in the year 2015:

 spanner.KeyRange{
    Start: spanner.Key{"Bob", "2015-01-01"},
    End:   spanner.Key{"Bob", "2015-12-31"},
    Kind:  ClosedClosed,
} 

Start and end keys can omit trailing key components. This affects the inclusion and exclusion of rows that exactly match the provided key components: if IncludeStart is true, then rows that exactly match the provided components of the Start key are included; if IncludeStart is false then rows that exactly match are not included. IncludeEnd and End key behave in the same fashion.

For example, the following range includes all events for "Bob" that occurred during and after the year 2000:

 spanner.KeyRange{
    Start: spanner.Key{"Bob", "2000-01-01"},
    End:   spanner.Key{"Bob"},
    Kind:  ClosedClosed,
} 

The next example retrieves all events for "Bob":

 spanner.Key{"Bob"}.AsPrefix() 

To retrieve events before the year 2000:

 spanner.KeyRange{
    Start: spanner.Key{"Bob"},
    End:   spanner.Key{"Bob", "2000-01-01"},
    Kind:  ClosedOpen,
} 

Although we specified a Kind for this KeyRange, we didn't need to, because the default is ClosedOpen. In later examples we'll omit Kind if it is ClosedOpen.

The following range includes all rows in a table or under a index:

 spanner.AllKeys() 

This range returns all users whose UserName begins with any character from A to C:

 spanner.KeyRange{
    Start: spanner.Key{"A"},
    End:   spanner.Key{"D"},
} 

This range returns all users whose UserName begins with B:

 spanner.KeyRange{
    Start: spanner.Key{"B"},
    End:   spanner.Key{"C"},
} 

Key ranges honor column sort order. For example, suppose a table is defined as follows:

 CREATE TABLE DescendingSortedTable {
  Key INT64,
  ...
) PRIMARY KEY(Key DESC); 

The following range retrieves all rows with key values between 1 and 100 inclusive:

 spanner.KeyRange{
    Start: spanner.Key{100},
    End:   spanner.Key{1},
    Kind:  ClosedClosed,
} 

Note that 100 is passed as the start, and 1 is passed as the end, because Key is a descending column in the schema.

func (KeyRange) String

  func 
  
 ( 
 r 
  
  KeyRange 
 
 ) 
  
 String 
 () 
  
  string 
 
 

String implements fmt.Stringer for KeyRange type.

KeyRangeKind

  type 
  
 KeyRangeKind 
  
  int 
 
 

KeyRangeKind describes the kind of interval represented by a KeyRange: whether it is open or closed on the left and right.

ClosedOpen, ClosedClosed, OpenClosed, OpenOpen

  const 
  
 ( 
  
 // ClosedOpen is closed on the left and open on the right: the Start 
  
 // key is included, the End key is excluded. 
  
 ClosedOpen 
  
  KeyRangeKind 
 
  
 = 
  
  iota 
 
  
 // ClosedClosed is closed on the left and the right: both keys are included. 
  
 ClosedClosed 
  
 // OpenClosed is open on the left and closed on the right: the Start 
  
 // key is excluded, the End key is included. 
  
 OpenClosed 
  
 // OpenOpen is open on the left and the right: neither key is included. 
  
 OpenOpen 
 ) 
 

KeySet

  type 
  
 KeySet 
  
 interface 
  
 { 
  
 // contains filtered or unexported methods 
 } 
 

A KeySet defines a collection of Cloud Spanner keys and/or key ranges. All the keys are expected to be in the same table or index. The keys need not be sorted in any particular way.

An individual Key can act as a KeySet, as can a KeyRange. Use the KeySets function to create a KeySet consisting of multiple Keys and KeyRanges. To obtain an empty KeySet, call KeySets with no arguments.

If the same key is specified multiple times in the set (for example if two ranges, two keys, or a key and a range overlap), the Cloud Spanner backend behaves as if the key were only specified once.

func AllKeys

  func 
  
 AllKeys 
 () 
  
  KeySet 
 
 

AllKeys returns a KeySet that represents all Keys of a table or a index.

func KeySetFromKeys

  func 
  
 KeySetFromKeys 
 ( 
 keys 
  
 ... 
  Key 
 
 ) 
  
  KeySet 
 
 

KeySetFromKeys returns a KeySet containing the given slice of keys.

func KeySets

  func 
  
 KeySets 
 ( 
 keySets 
  
 ... 
  KeySet 
 
 ) 
  
  KeySet 
 
 

KeySets returns the union of the KeySets. If any of the KeySets is AllKeys, then the resulting KeySet will be equivalent to AllKeys.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
  
 "google.golang.org/api/iterator" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 // Get some rows from the Accounts table using a secondary index. In this case we get all users who are in Georgia. 
  
 iter 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadUsingIndex 
 ( 
 context 
 . 
 Background 
 (), 
  
 "Accounts" 
 , 
  
 "idx_state" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "GA" 
 }, 
  
 [] 
 string 
 { 
 "state" 
 }) 
  
 // Create a empty KeySet by calling the KeySets function with no parameters. 
  
 ks 
  
 := 
  
 spanner 
 . 
  KeySets 
 
 () 
  
 // Loop the results of a previous query iterator. 
  
 for 
  
 { 
  
 row 
 , 
  
 err 
  
 := 
  
 iter 
 . 
 Next 
 () 
  
 if 
  
 err 
  
 == 
  
 iterator 
 . 
 Done 
  
 { 
  
 break 
  
 } 
  
 else 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 var 
  
 id 
  
 string 
  
 err 
  
 = 
  
 row 
 . 
  ColumnByName 
 
 ( 
 "User" 
 , 
  
& id 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 ks 
  
 = 
  
 spanner 
 . 
  KeySets 
 
 ( 
 spanner 
 . 
  KeySets 
 
 ( 
 spanner 
 . 
  Key 
 
 { 
 id 
 }, 
  
 ks 
 )) 
  
 } 
  
 _ 
  
 = 
  
 ks 
  
 //TODO: Go use the KeySet in another query. 
 } 
 

Mutation

  type 
  
 Mutation 
  
 struct 
  
 { 
  
 // contains filtered or unexported fields 
 } 
 

A Mutation describes a modification to one or more Cloud Spanner rows. The mutation represents an insert, update, delete, etc on a table.

Many mutations can be applied in a single atomic commit. For purposes of constraint checking (such as foreign key constraints), the operations can be viewed as applying in the same order as the mutations are provided (so that, e.g., a row and its logical "child" can be inserted in the same commit).

The Apply function applies series of mutations. For example,

 m := spanner.Insert("User",
     []string{"user_id", "profile"},
     []interface{}{UserID, profile})
 _, err := client.Apply(ctx, []*spanner.Mutation{m}) 

inserts a new row into the User table. The primary key for the new row is UserID (presuming that "user_id" has been declared as the primary key of the "User" table).

To apply a series of mutations as part of an atomic read-modify-write operation, use ReadWriteTransaction.

Updating a row

Changing the values of columns in an existing row is very similar to inserting a new row:

 m := spanner.Update("User",
    []string{"user_id", "profile"},
    []interface{}{UserID, profile})
_, err := client.Apply(ctx, []*spanner.Mutation{m}) 

Deleting a row

To delete a row, use spanner.Delete:

 m := spanner.Delete("User", spanner.Key{UserId})
_, err := client.Apply(ctx, []*spanner.Mutation{m}) 

spanner.Delete accepts a KeySet, so you can also pass in a KeyRange, or use the spanner.KeySets function to build any combination of Keys and KeyRanges.

Note that deleting a row in a table may also delete rows from other tables if cascading deletes are specified in those tables' schemas. Delete does nothing if the named row does not exist (does not yield an error).

Deleting a field

To delete/clear a field within a row, use spanner.Update with the value nil:

 m := spanner.Update("User",
    []string{"user_id", "profile"},
    []interface{}{UserID, nil})
_, err := client.Apply(ctx, []*spanner.Mutation{m}) 

The valid Go types and their corresponding Cloud Spanner types that can be used in the Insert/Update/InsertOrUpdate functions are:

 string, *string, NullString - STRING
[]string, []*string, []NullString - STRING ARRAY
[]byte - BYTES
[][]byte - BYTES ARRAY
int, int64, *int64, NullInt64 - INT64
[]int, []int64, []*int64, []NullInt64 - INT64 ARRAY
bool, *bool, NullBool - BOOL
[]bool, []*bool, []NullBool - BOOL ARRAY
float64, *float64, NullFloat64 - FLOAT64
[]float64, []*float64, []NullFloat64 - FLOAT64 ARRAY
time.Time, *time.Time, NullTime - TIMESTAMP
[]time.Time, []*time.Time, []NullTime - TIMESTAMP ARRAY
Date, *Date, NullDate - DATE
[]Date, []*Date, []NullDate - DATE ARRAY
big.Rat, *big.Rat, NullNumeric - NUMERIC
[]big.Rat, []*big.Rat, []NullNumeric - NUMERIC ARRAY 

To compare two Mutations for testing purposes, use reflect.DeepEqual.

func Delete

  func 
  
 Delete 
 ( 
 table 
  
  string 
 
 , 
  
 ks 
  
  KeySet 
 
 ) 
  
 * 
  Mutation 
 
 

Delete removes the rows described by the KeySet from the table. It succeeds whether or not the keys were present.

Examples

  package 
  
 main 
 import 
  
 ( 
  
 "cloud.google.com/go/spanner" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 m 
  
 := 
  
 spanner 
 . 
 Delete 
 ( 
 "Users" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }) 
  
 _ 
  
 = 
  
 m 
  
 // TODO: use with Client.Apply or in a ReadWriteTransaction. 
 } 
 
keyRange
  package 
  
 main 
 import 
  
 ( 
  
 "cloud.google.com/go/spanner" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 m 
  
 := 
  
 spanner 
 . 
 Delete 
 ( 
 "Users" 
 , 
  
 spanner 
 . 
 KeyRange 
 { 
  
 Start 
 : 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 End 
 : 
  
 spanner 
 . 
  Key 
 
 { 
 "bob" 
 }, 
  
 Kind 
 : 
  
 spanner 
 . 
  ClosedClosed 
 
 , 
  
 }) 
  
 _ 
  
 = 
  
 m 
  
 // TODO: use with Client.Apply or in a ReadWriteTransaction. 
 } 
 

func Insert

  func 
  
 Insert 
 ( 
 table 
  
  string 
 
 , 
  
 cols 
  
 [] 
  string 
 
 , 
  
 vals 
  
 [] 
 interface 
 {}) 
  
 * 
  Mutation 
 
 

Insert returns a Mutation to insert a row into a table. If the row already exists, the write or transaction fails with codes.AlreadyExists.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "cloud.google.com/go/spanner" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 m 
  
 := 
  
 spanner 
 . 
 Insert 
 ( 
 "Users" 
 , 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "email" 
 }, 
  
 [] 
 interface 
 {}{ 
 "alice" 
 , 
  
 "a@example.com" 
 }) 
  
 _ 
  
 = 
  
 m 
  
 // TODO: use with Client.Apply or in a ReadWriteTransaction. 
 } 
 

func InsertMap

  func 
  
 InsertMap 
 ( 
 table 
  
  string 
 
 , 
  
 in 
  
 map 
 [ 
  string 
 
 ] 
 interface 
 {}) 
  
 * 
  Mutation 
 
 

InsertMap returns a Mutation to insert a row into a table, specified by a map of column name to value. If the row already exists, the write or transaction fails with codes.AlreadyExists.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "cloud.google.com/go/spanner" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 m 
  
 := 
  
 spanner 
 . 
  InsertMap 
 
 ( 
 "Users" 
 , 
  
 map 
 [ 
 string 
 ] 
 interface 
 {}{ 
  
 "name" 
 : 
  
 "alice" 
 , 
  
 "email" 
 : 
  
 "a@example.com" 
 , 
  
 }) 
  
 _ 
  
 = 
  
 m 
  
 // TODO: use with Client.Apply or in a ReadWriteTransaction. 
 } 
 

func InsertOrUpdate

  func 
  
 InsertOrUpdate 
 ( 
 table 
  
  string 
 
 , 
  
 cols 
  
 [] 
  string 
 
 , 
  
 vals 
  
 [] 
 interface 
 {}) 
  
 * 
  Mutation 
 
 

InsertOrUpdate returns a Mutation to insert a row into a table. If the row already exists, it updates it instead. Any column values not explicitly written are preserved.

For a similar example, See Update.

func InsertOrUpdateMap

  func 
  
 InsertOrUpdateMap 
 ( 
 table 
  
  string 
 
 , 
  
 in 
  
 map 
 [ 
  string 
 
 ] 
 interface 
 {}) 
  
 * 
  Mutation 
 
 

InsertOrUpdateMap returns a Mutation to insert a row into a table, specified by a map of column to value. If the row already exists, it updates it instead. Any column values not explicitly written are preserved.

For a similar example, See UpdateMap.

func InsertOrUpdateStruct

  func 
  
 InsertOrUpdateStruct 
 ( 
 table 
  
  string 
 
 , 
  
 in 
  
 interface 
 {}) 
  
 ( 
 * 
  Mutation 
 
 , 
  
  error 
 
 ) 
 

InsertOrUpdateStruct returns a Mutation to insert a row into a table, specified by a Go struct. If the row already exists, it updates it instead. Any column values not explicitly written are preserved.

The in argument must be a struct or a pointer to a struct. Its exported fields specify the column names and values. Use a field tag like "spanner:name" to provide an alternative column name, or use "spanner:-" to ignore the field.

For a similar example, See UpdateStruct.

func InsertStruct

  func 
  
 InsertStruct 
 ( 
 table 
  
  string 
 
 , 
  
 in 
  
 interface 
 {}) 
  
 ( 
 * 
  Mutation 
 
 , 
  
  error 
 
 ) 
 

InsertStruct returns a Mutation to insert a row into a table, specified by a Go struct. If the row already exists, the write or transaction fails with codes.AlreadyExists.

The in argument must be a struct or a pointer to a struct. Its exported fields specify the column names and values. Use a field tag like "spanner:name" to provide an alternative column name, or use "spanner:-" to ignore the field.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "cloud.google.com/go/spanner" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 type 
  
 User 
  
 struct 
  
 { 
  
 Name 
 , 
  
 Email 
  
 string 
  
 } 
  
 u 
  
 := 
  
 User 
 { 
 Name 
 : 
  
 "alice" 
 , 
  
 Email 
 : 
  
 "a@example.com" 
 } 
  
 m 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
  InsertStruct 
 
 ( 
 "Users" 
 , 
  
 u 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 _ 
  
 = 
  
 m 
  
 // TODO: use with Client.Apply or in a ReadWriteTransaction. 
 } 
 

func Replace

  func 
  
 Replace 
 ( 
 table 
  
  string 
 
 , 
  
 cols 
  
 [] 
  string 
 
 , 
  
 vals 
  
 [] 
 interface 
 {}) 
  
 * 
  Mutation 
 
 

Replace returns a Mutation to insert a row into a table, deleting any existing row. Unlike InsertOrUpdate, this means any values not explicitly written become NULL.

For a similar example, See Update.

func ReplaceMap

  func 
  
 ReplaceMap 
 ( 
 table 
  
  string 
 
 , 
  
 in 
  
 map 
 [ 
  string 
 
 ] 
 interface 
 {}) 
  
 * 
  Mutation 
 
 

ReplaceMap returns a Mutation to insert a row into a table, deleting any existing row. Unlike InsertOrUpdateMap, this means any values not explicitly written become NULL. The row is specified by a map of column to value.

For a similar example, See UpdateMap.

func ReplaceStruct

  func 
  
 ReplaceStruct 
 ( 
 table 
  
  string 
 
 , 
  
 in 
  
 interface 
 {}) 
  
 ( 
 * 
  Mutation 
 
 , 
  
  error 
 
 ) 
 

ReplaceStruct returns a Mutation to insert a row into a table, deleting any existing row. Unlike InsertOrUpdateMap, this means any values not explicitly written become NULL. The row is specified by a Go struct.

The in argument must be a struct or a pointer to a struct. Its exported fields specify the column names and values. Use a field tag like "spanner:name" to provide an alternative column name, or use "spanner:-" to ignore the field.

For a similar example, See UpdateStruct.

func Update

  func 
  
 Update 
 ( 
 table 
  
  string 
 
 , 
  
 cols 
  
 [] 
  string 
 
 , 
  
 vals 
  
 [] 
 interface 
 {}) 
  
 * 
  Mutation 
 
 

Update returns a Mutation to update a row in a table. If the row does not already exist, the write or transaction fails.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 _ 
 , 
  
 err 
  
 = 
  
 client 
 . 
 ReadWriteTransaction 
 ( 
 ctx 
 , 
  
 func 
 ( 
 ctx 
  
 context 
 . 
 Context 
 , 
  
 txn 
  
 * 
 spanner 
 . 
 ReadWriteTransaction 
 ) 
  
 error 
  
 { 
  
 row 
 , 
  
 err 
  
 := 
  
 txn 
 . 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 var 
  
 balance 
  
 int64 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  Column 
 
 ( 
 0 
 , 
  
& balance 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 return 
  
 txn 
 . 
  BufferWrite 
 
 ([] 
 * 
 spanner 
 . 
 Mutation 
 { 
  
 spanner 
 . 
 Update 
 ( 
 "Accounts" 
 , 
  
 [] 
 string 
 { 
 "user" 
 , 
  
 "balance" 
 }, 
  
 [] 
 interface 
 {}{ 
 "alice" 
 , 
  
 balance 
  
 + 
  
 10 
 }), 
  
 }) 
  
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
 } 
 

func UpdateMap

  func 
  
 UpdateMap 
 ( 
 table 
  
  string 
 
 , 
  
 in 
  
 map 
 [ 
  string 
 
 ] 
 interface 
 {}) 
  
 * 
  Mutation 
 
 

UpdateMap returns a Mutation to update a row in a table, specified by a map of column to value. If the row does not already exist, the write or transaction fails.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 _ 
 , 
  
 err 
  
 = 
  
 client 
 . 
 ReadWriteTransaction 
 ( 
 ctx 
 , 
  
 func 
 ( 
 ctx 
  
 context 
 . 
 Context 
 , 
  
 txn 
  
 * 
 spanner 
 . 
 ReadWriteTransaction 
 ) 
  
 error 
  
 { 
  
 row 
 , 
  
 err 
  
 := 
  
 txn 
 . 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 var 
  
 balance 
  
 int64 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  Column 
 
 ( 
 0 
 , 
  
& balance 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 return 
  
 txn 
 . 
  BufferWrite 
 
 ([] 
 * 
 spanner 
 . 
 Mutation 
 { 
  
 spanner 
 . 
  UpdateMap 
 
 ( 
 "Accounts" 
 , 
  
 map 
 [ 
 string 
 ] 
 interface 
 {}{ 
  
 "user" 
 : 
  
 "alice" 
 , 
  
 "balance" 
 : 
  
 balance 
  
 + 
  
 10 
 , 
  
 }), 
  
 }) 
  
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
 } 
 

func UpdateStruct

  func 
  
 UpdateStruct 
 ( 
 table 
  
  string 
 
 , 
  
 in 
  
 interface 
 {}) 
  
 ( 
 * 
  Mutation 
 
 , 
  
  error 
 
 ) 
 

UpdateStruct returns a Mutation to update a row in a table, specified by a Go struct. If the row does not already exist, the write or transaction fails.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 type 
  
 account 
  
 struct 
  
 { 
  
 User 
  
 string 
  
 `spanner:"user"` 
  
 Balance 
  
 int64 
  
 `spanner:"balance"` 
  
 } 
  
 _ 
 , 
  
 err 
  
 = 
  
 client 
 . 
 ReadWriteTransaction 
 ( 
 ctx 
 , 
  
 func 
 ( 
 ctx 
  
 context 
 . 
 Context 
 , 
  
 txn 
  
 * 
 spanner 
 . 
 ReadWriteTransaction 
 ) 
  
 error 
  
 { 
  
 row 
 , 
  
 err 
  
 := 
  
 txn 
 . 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 var 
  
 balance 
  
 int64 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  Column 
 
 ( 
 0 
 , 
  
& balance 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 m 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
  UpdateStruct 
 
 ( 
 "Accounts" 
 , 
  
 account 
 { 
  
 User 
 : 
  
 "alice" 
 , 
  
 Balance 
 : 
  
 balance 
  
 + 
  
 10 
 , 
  
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 return 
  
 txn 
 . 
  BufferWrite 
 
 ([] 
 * 
 spanner 
 . 
 Mutation 
 { 
 m 
 }) 
  
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
 } 
 

NullBool

  type 
  
 NullBool 
  
 struct 
  
 { 
  
 Bool 
  
  bool 
 
  
 // Bool contains the value when it is non-NULL, and false when NULL. 
  
 Valid 
  
  bool 
 
  
 // Valid is true if Bool is not NULL. 
 } 
 

NullBool represents a Cloud Spanner BOOL that may be NULL.

func (NullBool) IsNull

  func 
  
 ( 
 n 
  
  NullBool 
 
 ) 
  
 IsNull 
 () 
  
  bool 
 
 

IsNull implements NullableValue.IsNull for NullBool.

func (NullBool) MarshalJSON

  func 
  
 ( 
 n 
  
  NullBool 
 
 ) 
  
 MarshalJSON 
 () 
  
 ([] 
  byte 
 
 , 
  
  error 
 
 ) 
 

MarshalJSON implements json.Marshaler.MarshalJSON for NullBool.

func (NullBool) String

  func 
  
 ( 
 n 
  
  NullBool 
 
 ) 
  
 String 
 () 
  
  string 
 
 

String implements Stringer.String for NullBool

func (*NullBool) UnmarshalJSON

  func 
  
 ( 
 n 
  
 * 
  NullBool 
 
 ) 
  
 UnmarshalJSON 
 ( 
 payload 
  
 [] 
  byte 
 
 ) 
  
  error 
 
 

UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON for NullBool.

NullDate

  type 
  
 NullDate 
  
 struct 
  
 { 
  
 Date 
  
  civil 
 
 . 
  Date 
 
  
 // Date contains the value when it is non-NULL, and a zero civil.Date when NULL. 
  
 Valid 
  
  bool 
 
  
 // Valid is true if Date is not NULL. 
 } 
 

NullDate represents a Cloud Spanner DATE that may be null.

func (NullDate) IsNull

  func 
  
 ( 
 n 
  
  NullDate 
 
 ) 
  
 IsNull 
 () 
  
  bool 
 
 

IsNull implements NullableValue.IsNull for NullDate.

func (NullDate) MarshalJSON

  func 
  
 ( 
 n 
  
  NullDate 
 
 ) 
  
 MarshalJSON 
 () 
  
 ([] 
  byte 
 
 , 
  
  error 
 
 ) 
 

MarshalJSON implements json.Marshaler.MarshalJSON for NullDate.

func (NullDate) String

  func 
  
 ( 
 n 
  
  NullDate 
 
 ) 
  
 String 
 () 
  
  string 
 
 

String implements Stringer.String for NullDate

func (*NullDate) UnmarshalJSON

  func 
  
 ( 
 n 
  
 * 
  NullDate 
 
 ) 
  
 UnmarshalJSON 
 ( 
 payload 
  
 [] 
  byte 
 
 ) 
  
  error 
 
 

UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON for NullDate.

NullFloat64

  type 
  
 NullFloat64 
  
 struct 
  
 { 
  
 Float64 
  
  float64 
 
  
 // Float64 contains the value when it is non-NULL, and zero when NULL. 
  
 Valid 
  
  bool 
 
  
 // Valid is true if Float64 is not NULL. 
 } 
 

NullFloat64 represents a Cloud Spanner FLOAT64 that may be NULL.

func (NullFloat64) IsNull

  func 
  
 ( 
 n 
  
  NullFloat64 
 
 ) 
  
 IsNull 
 () 
  
  bool 
 
 

IsNull implements NullableValue.IsNull for NullFloat64.

func (NullFloat64) MarshalJSON

  func 
  
 ( 
 n 
  
  NullFloat64 
 
 ) 
  
 MarshalJSON 
 () 
  
 ([] 
  byte 
 
 , 
  
  error 
 
 ) 
 

MarshalJSON implements json.Marshaler.MarshalJSON for NullFloat64.

func (NullFloat64) String

  func 
  
 ( 
 n 
  
  NullFloat64 
 
 ) 
  
 String 
 () 
  
  string 
 
 

String implements Stringer.String for NullFloat64

func (*NullFloat64) UnmarshalJSON

  func 
  
 ( 
 n 
  
 * 
  NullFloat64 
 
 ) 
  
 UnmarshalJSON 
 ( 
 payload 
  
 [] 
  byte 
 
 ) 
  
  error 
 
 

UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON for NullFloat64.

NullInt64

  type 
  
 NullInt64 
  
 struct 
  
 { 
  
 Int64 
  
  int64 
 
  
 // Int64 contains the value when it is non-NULL, and zero when NULL. 
  
 Valid 
  
  bool 
 
  
 // Valid is true if Int64 is not NULL. 
 } 
 

NullInt64 represents a Cloud Spanner INT64 that may be NULL.

func (NullInt64) IsNull

  func 
  
 ( 
 n 
  
  NullInt64 
 
 ) 
  
 IsNull 
 () 
  
  bool 
 
 

IsNull implements NullableValue.IsNull for NullInt64.

func (NullInt64) MarshalJSON

  func 
  
 ( 
 n 
  
  NullInt64 
 
 ) 
  
 MarshalJSON 
 () 
  
 ([] 
  byte 
 
 , 
  
  error 
 
 ) 
 

MarshalJSON implements json.Marshaler.MarshalJSON for NullInt64.

func (NullInt64) String

  func 
  
 ( 
 n 
  
  NullInt64 
 
 ) 
  
 String 
 () 
  
  string 
 
 

String implements Stringer.String for NullInt64

func (*NullInt64) UnmarshalJSON

  func 
  
 ( 
 n 
  
 * 
  NullInt64 
 
 ) 
  
 UnmarshalJSON 
 ( 
 payload 
  
 [] 
  byte 
 
 ) 
  
  error 
 
 

UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON for NullInt64.

NullNumeric

  type 
  
 NullNumeric 
  
 struct 
  
 { 
  
 Numeric 
  
  big 
 
 . 
  Rat 
 
  
 // Numeric contains the value when it is non-NULL, and a zero big.Rat when NULL. 
  
 Valid 
  
  bool 
 
  
 // Valid is true if Numeric is not NULL. 
 } 
 

NullNumeric represents a Cloud Spanner Numeric that may be NULL.

func (NullNumeric) IsNull

  func 
  
 ( 
 n 
  
  NullNumeric 
 
 ) 
  
 IsNull 
 () 
  
  bool 
 
 

IsNull implements NullableValue.IsNull for NullNumeric.

func (NullNumeric) MarshalJSON

  func 
  
 ( 
 n 
  
  NullNumeric 
 
 ) 
  
 MarshalJSON 
 () 
  
 ([] 
  byte 
 
 , 
  
  error 
 
 ) 
 

MarshalJSON implements json.Marshaler.MarshalJSON for NullNumeric.

func (NullNumeric) String

  func 
  
 ( 
 n 
  
  NullNumeric 
 
 ) 
  
 String 
 () 
  
  string 
 
 

String implements Stringer.String for NullNumeric

func (*NullNumeric) UnmarshalJSON

  func 
  
 ( 
 n 
  
 * 
  NullNumeric 
 
 ) 
  
 UnmarshalJSON 
 ( 
 payload 
  
 [] 
  byte 
 
 ) 
  
  error 
 
 

UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON for NullNumeric.

NullRow

  type 
  
 NullRow 
  
 struct 
  
 { 
  
 Row 
  
  Row 
 
  
 // Row contains the value when it is non-NULL, and a zero Row when NULL. 
  
 Valid 
  
  bool 
 
  
 // Valid is true if Row is not NULL. 
 } 
 

NullRow represents a Cloud Spanner STRUCT that may be NULL. See also the document for Row. Note that NullRow is not a valid Cloud Spanner column Type.

NullString

  type 
  
 NullString 
  
 struct 
  
 { 
  
 StringVal 
  
  string 
 
  
 // StringVal contains the value when it is non-NULL, and an empty string when NULL. 
  
 Valid 
  
  bool 
 
  
 // Valid is true if StringVal is not NULL. 
 } 
 

NullString represents a Cloud Spanner STRING that may be NULL.

func (NullString) IsNull

  func 
  
 ( 
 n 
  
  NullString 
 
 ) 
  
 IsNull 
 () 
  
  bool 
 
 

IsNull implements NullableValue.IsNull for NullString.

func (NullString) MarshalJSON

  func 
  
 ( 
 n 
  
  NullString 
 
 ) 
  
 MarshalJSON 
 () 
  
 ([] 
  byte 
 
 , 
  
  error 
 
 ) 
 

MarshalJSON implements json.Marshaler.MarshalJSON for NullString.

func (NullString) String

  func 
  
 ( 
 n 
  
  NullString 
 
 ) 
  
 String 
 () 
  
  string 
 
 

String implements Stringer.String for NullString

func (*NullString) UnmarshalJSON

  func 
  
 ( 
 n 
  
 * 
  NullString 
 
 ) 
  
 UnmarshalJSON 
 ( 
 payload 
  
 [] 
  byte 
 
 ) 
  
  error 
 
 

UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON for NullString.

NullTime

  type 
  
 NullTime 
  
 struct 
  
 { 
  
 Time 
  
  time 
 
 . 
  Time 
 
  
 // Time contains the value when it is non-NULL, and a zero time.Time when NULL. 
  
 Valid 
  
  bool 
 
  
 // Valid is true if Time is not NULL. 
 } 
 

NullTime represents a Cloud Spanner TIMESTAMP that may be null.

func (NullTime) IsNull

  func 
  
 ( 
 n 
  
  NullTime 
 
 ) 
  
 IsNull 
 () 
  
  bool 
 
 

IsNull implements NullableValue.IsNull for NullTime.

func (NullTime) MarshalJSON

  func 
  
 ( 
 n 
  
  NullTime 
 
 ) 
  
 MarshalJSON 
 () 
  
 ([] 
  byte 
 
 , 
  
  error 
 
 ) 
 

MarshalJSON implements json.Marshaler.MarshalJSON for NullTime.

func (NullTime) String

  func 
  
 ( 
 n 
  
  NullTime 
 
 ) 
  
 String 
 () 
  
  string 
 
 

String implements Stringer.String for NullTime

func (*NullTime) UnmarshalJSON

  func 
  
 ( 
 n 
  
 * 
  NullTime 
 
 ) 
  
 UnmarshalJSON 
 ( 
 payload 
  
 [] 
  byte 
 
 ) 
  
  error 
 
 

UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON for NullTime.

NullableValue

  type 
  
 NullableValue 
  
 interface 
  
 { 
  
 // IsNull returns true if the underlying database value is null. 
  
 IsNull 
 () 
  
  bool 
 
 } 
 

NullableValue is the interface implemented by all null value wrapper types.

Partition

  type 
  
 Partition 
  
 struct 
  
 { 
  
 // contains filtered or unexported fields 
 } 
 

Partition defines a segment of data to be read in a batch read or query. A partition can be serialized and processed across several different machines or processes.

func (Partition) MarshalBinary

  func 
  
 ( 
 p 
  
  Partition 
 
 ) 
  
 MarshalBinary 
 () 
  
 ( 
 data 
  
 [] 
  byte 
 
 , 
  
 err 
  
  error 
 
 ) 
 

MarshalBinary implements BinaryMarshaler.

func (*Partition) UnmarshalBinary

  func 
  
 ( 
 p 
  
 * 
  Partition 
 
 ) 
  
 UnmarshalBinary 
 ( 
 data 
  
 [] 
  byte 
 
 ) 
  
  error 
 
 

UnmarshalBinary implements BinaryUnmarshaler.

PartitionOptions

  type 
  
 PartitionOptions 
  
 struct 
  
 { 
  
 // The desired data size for each partition generated. 
  
 PartitionBytes 
  
  int64 
 
  
 // The desired maximum number of partitions to return. 
  
 MaxPartitions 
  
  int64 
 
 } 
 

PartitionOptions specifies options for a PartitionQueryRequest and PartitionReadRequest. See https://godoc.org/google.golang.org/genproto/googleapis/spanner/v1#PartitionOptions for more details.

QueryOptions

QueryOptions provides options for executing a sql query from a database.

ReadOnlyTransaction

  type 
  
 ReadOnlyTransaction 
  
 struct 
  
 { 
  
 // contains filtered or unexported fields 
 } 
 

ReadOnlyTransaction provides a snapshot transaction with guaranteed consistency across reads, but does not allow writes. Read-only transactions can be configured to read at timestamps in the past.

Read-only transactions do not take locks. Instead, they work by choosing a Cloud Spanner timestamp, then executing all reads at that timestamp. Since they do not acquire locks, they do not block concurrent read-write transactions.

Unlike locking read-write transactions, read-only transactions never abort. They can fail if the chosen read timestamp is garbage collected; however, the default garbage collection policy is generous enough that most applications do not need to worry about this in practice. See the documentation of TimestampBound for more details.

A ReadOnlyTransaction consumes resources on the server until Close is called.

func (*ReadOnlyTransaction) AnalyzeQuery

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 AnalyzeQuery 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 ) 
  
 ( 
 * 
  sppb 
 
 . 
  QueryPlan 
 
 , 
  
  error 
 
 ) 
 

AnalyzeQuery returns the query plan for statement.

func (*ReadOnlyTransaction) Close

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 Close 
 () 
 

Close closes a ReadOnlyTransaction, the transaction cannot perform any reads after being closed.

func (*ReadOnlyTransaction) Query

Query executes a query against the database. It returns a RowIterator for retrieving the resulting rows.

Query returns only row data, without a query plan or execution statistics. Use QueryWithStats to get rows along with the plan and statistics. Use AnalyzeQuery to get just the plan.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 iter 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 Query 
 ( 
 ctx 
 , 
  
 spanner 
 . 
  NewStatement 
 
 ( 
 "SELECT FirstName FROM Singers" 
 )) 
  
 _ 
  
 = 
  
 iter 
  
 // TODO: iterate using Next or Do. 
 } 
 

func (*ReadOnlyTransaction) QueryWithOptions

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 QueryWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 , 
  
 opts 
  
  QueryOptions 
 
 ) 
  
 * 
  RowIterator 
 
 

QueryWithOptions executes a SQL statment against the database. It returns a RowIterator for retrieving the resulting rows. The sql query execution will be optimized based on the given query options.

func (*ReadOnlyTransaction) QueryWithStats

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 QueryWithStats 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 ) 
  
 * 
  RowIterator 
 
 

QueryWithStats executes a SQL statement against the database. It returns a RowIterator for retrieving the resulting rows. The RowIterator will also be populated with a query plan and execution statistics.

func (*ReadOnlyTransaction) Read

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 Read 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 * 
  RowIterator 
 
 

Read returns a RowIterator for reading multiple rows from the database.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 iter 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 Read 
 ( 
 ctx 
 , 
  
 "Users" 
 , 
  
 spanner 
 . 
  KeySets 
 
 ( 
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 spanner 
 . 
  Key 
 
 { 
 "bob" 
 }), 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "email" 
 }) 
  
 _ 
  
 = 
  
 iter 
  
 // TODO: iterate using Next or Do. 
 } 
 

func (*ReadOnlyTransaction) ReadRow

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 ReadRow 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 key 
  
  Key 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 * 
  Row 
 
 , 
  
  error 
 
 ) 
 

ReadRow reads a single row from the database.

If no row is present with the given key, then ReadRow returns an error where spanner.ErrCode(err) is codes.NotFound.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 row 
 , 
  
 err 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Users" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "email" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 _ 
  
 = 
  
 row 
  
 // TODO: use row 
 } 
 

func (*ReadOnlyTransaction) ReadRowUsingIndex

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 ReadRowUsingIndex 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 index 
  
  string 
 
 , 
  
 key 
  
  Key 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 * 
  Row 
 
 , 
  
  error 
 
 ) 
 

ReadRowUsingIndex reads a single row from the database using an index.

If no row is present with the given index, then ReadRowUsingIndex returns an error where spanner.ErrCode(err) is codes.NotFound.

If more than one row received with the given index, then ReadRowUsingIndex returns an error where spanner.ErrCode(err) is codes.FailedPrecondition.

func (*ReadOnlyTransaction) ReadUsingIndex

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 ReadUsingIndex 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
 , 
  
 index 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 ri 
  
 * 
  RowIterator 
 
 ) 
 

ReadUsingIndex calls ReadWithOptions with ReadOptions{Index: index}.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 iter 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadUsingIndex 
 ( 
 ctx 
 , 
  
 "Users" 
 , 
  
 "UsersByEmail" 
 , 
  
 spanner 
 . 
  KeySets 
 
 ( 
 spanner 
 . 
  Key 
 
 { 
 "a@example.com" 
 }, 
  
 spanner 
 . 
  Key 
 
 { 
 "b@example.com" 
 }), 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "email" 
 }) 
  
 _ 
  
 = 
  
 iter 
  
 // TODO: iterate using Next or Do. 
 } 
 

func (*ReadOnlyTransaction) ReadWithOptions

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 ReadWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 , 
  
 opts 
  
 * 
  ReadOptions 
 
 ) 
  
 ( 
 ri 
  
 * 
  RowIterator 
 
 ) 
 

ReadWithOptions returns a RowIterator for reading multiple rows from the database. Pass a ReadOptions to modify the read operation.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 // Use an index, and limit to 100 rows at most. 
  
 iter 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadWithOptions 
 ( 
 ctx 
 , 
  
 "Users" 
 , 
  
 spanner 
 . 
  KeySets 
 
 ( 
 spanner 
 . 
  Key 
 
 { 
 "a@example.com" 
 }, 
  
 spanner 
 . 
  Key 
 
 { 
 "b@example.com" 
 }), 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "email" 
 }, 
  
& spanner 
 . 
  ReadOptions 
 
 { 
  
 Index 
 : 
  
 "UsersByEmail" 
 , 
  
 Limit 
 : 
  
 100 
 , 
  
 }) 
  
 _ 
  
 = 
  
 iter 
  
 // TODO: iterate using Next or Do. 
 } 
 

func (*ReadOnlyTransaction) Timestamp

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 Timestamp 
 () 
  
 ( 
  time 
 
 . 
  Time 
 
 , 
  
  error 
 
 ) 
 

Timestamp returns the timestamp chosen to perform reads and queries in this transaction. The value can only be read after some read or query has either returned some data or completed without returning any data.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 txn 
  
 := 
  
 client 
 . 
  Single 
 
 () 
  
 row 
 , 
  
 err 
  
 := 
  
 txn 
 . 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Users" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "email" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 readTimestamp 
 , 
  
 err 
  
 := 
  
 txn 
 . 
 Timestamp 
 () 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 "read happened at" 
 , 
  
 readTimestamp 
 ) 
  
 _ 
  
 = 
  
 row 
  
 // TODO: use row 
 } 
 

func (*ReadOnlyTransaction) WithTimestampBound

  func 
  
 ( 
 t 
  
 * 
  ReadOnlyTransaction 
 
 ) 
  
 WithTimestampBound 
 ( 
 tb 
  
  TimestampBound 
 
 ) 
  
 * 
  ReadOnlyTransaction 
 
 

WithTimestampBound specifies the TimestampBound to use for read or query. This can only be used before the first read or query is invoked. Note: bounded staleness is not available with general ReadOnlyTransactions; use a single-use ReadOnlyTransaction instead.

The returned value is the ReadOnlyTransaction so calls can be chained.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "time" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 txn 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
  WithTimestampBound 
 
 ( 
 spanner 
 . 
  MaxStaleness 
 
 ( 
 30 
  
 * 
  
 time 
 . 
 Second 
 )) 
  
 row 
 , 
  
 err 
  
 := 
  
 txn 
 . 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Users" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "email" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 _ 
  
 = 
  
 row 
  
 // TODO: use row 
  
 readTimestamp 
 , 
  
 err 
  
 := 
  
 txn 
 . 
 Timestamp 
 () 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 "read happened at" 
 , 
  
 readTimestamp 
 ) 
 } 
 

ReadOptions

  type 
  
 ReadOptions 
  
 struct 
  
 { 
  
 // The index to use for reading. If non-empty, you can only read columns 
  
 // that are part of the index key, part of the primary key, or stored in the 
  
 // index due to a STORING clause in the index definition. 
  
 Index 
  
  string 
 
  
 // The maximum number of rows to read. A limit value less than 1 means no 
  
 // limit. 
  
 Limit 
  
  int 
 
 } 
 

ReadOptions provides options for reading rows from a database.

ReadWriteStmtBasedTransaction

  type 
  
 ReadWriteStmtBasedTransaction 
  
 struct 
  
 { 
  
 // ReadWriteTransaction contains methods for performing transactional reads. 
  
  ReadWriteTransaction 
 
  
 // contains filtered or unexported fields 
 } 
 

ReadWriteStmtBasedTransaction provides a wrapper of ReadWriteTransaction in order to run a read-write transaction in a statement-based way.

This struct is returned by NewReadWriteStmtBasedTransaction and contains Commit() and Rollback() methods to end a transaction.

func NewReadWriteStmtBasedTransaction

  func 
  
 NewReadWriteStmtBasedTransaction 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 c 
  
 * 
  Client 
 
 ) 
  
 ( 
 * 
  ReadWriteStmtBasedTransaction 
 
 , 
  
  error 
 
 ) 
 

NewReadWriteStmtBasedTransaction starts a read-write transaction. Commit() or Rollback() must be called to end a transaction. If Commit() or Rollback() is not called, the session that is used by the transaction will not be returned to the pool and cause a session leak.

This method should only be used when manual error handling and retry management is needed. Cloud Spanner may abort a read/write transaction at any moment, and each statement that is executed on the transaction should be checked for an Aborted error, including queries and read operations.

For most use cases, client.ReadWriteTransaction should be used, as it will handle all Aborted and 'Session not found' errors automatically.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "errors" 
  
 "time" 
  
 "cloud.google.com/go/spanner" 
  
 "google.golang.org/grpc/codes" 
  
 "google.golang.org/grpc/status" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 defer 
  
 client 
 . 
 Close 
 () 
  
 f 
  
 := 
  
 func 
 ( 
 tx 
  
 * 
 spanner 
 . 
  ReadWriteStmtBasedTransaction 
 
 ) 
  
 error 
  
 { 
  
 var 
  
 balance 
  
 int64 
  
 row 
 , 
  
 err 
  
 := 
  
 tx 
 . 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  Column 
 
 ( 
 0 
 , 
  
& balance 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 if 
  
 balance 
  
< = 
  
 10 
  
 { 
  
 return 
  
 errors 
 . 
 New 
 ( 
 "insufficient funds in account" 
 ) 
  
 } 
  
 balance 
  
 -= 
  
 10 
  
 m 
  
 := 
  
 spanner 
 . 
 Update 
 ( 
 "Accounts" 
 , 
  
 [] 
 string 
 { 
 "user" 
 , 
  
 "balance" 
 }, 
  
 [] 
 interface 
 {}{ 
 "alice" 
 , 
  
 balance 
 }) 
  
 return 
  
 tx 
 . 
  BufferWrite 
 
 ([] 
 * 
 spanner 
 . 
 Mutation 
 { 
 m 
 }) 
  
 } 
  
 for 
  
 { 
  
 tx 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
  NewReadWriteStmtBasedTransaction 
 
 ( 
 ctx 
 , 
  
 client 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 break 
  
 } 
  
 err 
  
 = 
  
 f 
 ( 
 tx 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
 && 
 status 
 . 
 Code 
 ( 
 err 
 ) 
  
 != 
  
 codes 
 . 
 Aborted 
  
 { 
  
 tx 
 . 
 Rollback 
 ( 
 ctx 
 ) 
  
 // TODO: Handle error. 
  
 break 
  
 } 
  
 else 
  
 if 
  
 err 
  
 == 
  
 nil 
  
 { 
  
 _ 
 , 
  
 err 
  
 = 
  
 tx 
 . 
 Commit 
 ( 
 ctx 
 ) 
  
 if 
  
 err 
  
 == 
  
 nil 
  
 { 
  
 break 
  
 } 
  
 else 
  
 if 
  
 status 
 . 
 Code 
 ( 
 err 
 ) 
  
 != 
  
 codes 
 . 
 Aborted 
  
 { 
  
 // TODO: Handle error. 
  
 break 
  
 } 
  
 } 
  
 // Set a default sleep time if the server delay is absent. 
  
 delay 
  
 := 
  
 10 
  
 * 
  
 time 
 . 
 Millisecond 
  
 if 
  
 serverDelay 
 , 
  
 hasServerDelay 
  
 := 
  
 spanner 
 . 
  ExtractRetryDelay 
 
 ( 
 err 
 ); 
  
 hasServerDelay 
  
 { 
  
 delay 
  
 = 
  
 serverDelay 
  
 } 
  
 time 
 . 
 Sleep 
 ( 
 delay 
 ) 
  
 } 
 } 
 

func NewReadWriteStmtBasedTransactionWithOptions

  func 
  
 NewReadWriteStmtBasedTransactionWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 c 
  
 * 
  Client 
 
 , 
  
 options 
  
  TransactionOptions 
 
 ) 
  
 ( 
 * 
  ReadWriteStmtBasedTransaction 
 
 , 
  
  error 
 
 ) 
 

NewReadWriteStmtBasedTransactionWithOptions starts a read-write transaction with configurable options. Commit() or Rollback() must be called to end a transaction. If Commit() or Rollback() is not called, the session that is used by the transaction will not be returned to the pool and cause a session leak.

NewReadWriteStmtBasedTransactionWithOptions is a configurable version of NewReadWriteStmtBasedTransaction.

func (*ReadWriteStmtBasedTransaction) AnalyzeQuery

AnalyzeQuery returns the query plan for statement.

func (*ReadWriteStmtBasedTransaction) Commit

Commit tries to commit a readwrite transaction to Cloud Spanner. It also returns the commit timestamp for the transactions.

func (*ReadWriteStmtBasedTransaction) CommitWithReturnResp

CommitWithReturnResp tries to commit a readwrite transaction. It also returns the commit timestamp and stats for the transactions.

func (*ReadWriteStmtBasedTransaction) Query

Query executes a query against the database. It returns a RowIterator for retrieving the resulting rows.

Query returns only row data, without a query plan or execution statistics. Use QueryWithStats to get rows along with the plan and statistics. Use AnalyzeQuery to get just the plan.

func (*ReadWriteStmtBasedTransaction) QueryWithOptions

QueryWithOptions executes a SQL statment against the database. It returns a RowIterator for retrieving the resulting rows. The sql query execution will be optimized based on the given query options.

func (*ReadWriteStmtBasedTransaction) QueryWithStats

QueryWithStats executes a SQL statement against the database. It returns a RowIterator for retrieving the resulting rows. The RowIterator will also be populated with a query plan and execution statistics.

func (*ReadWriteStmtBasedTransaction) Read

Read returns a RowIterator for reading multiple rows from the database.

func (*ReadWriteStmtBasedTransaction) ReadRow

  func 
  
 ( 
 t 
  
 * 
  ReadWriteStmtBasedTransaction 
 
 ) 
  
 ReadRow 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 key 
  
  Key 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 * 
  Row 
 
 , 
  
  error 
 
 ) 
 

ReadRow reads a single row from the database.

If no row is present with the given key, then ReadRow returns an error where spanner.ErrCode(err) is codes.NotFound.

func (*ReadWriteStmtBasedTransaction) ReadRowUsingIndex

  func 
  
 ( 
 t 
  
 * 
  ReadWriteStmtBasedTransaction 
 
 ) 
  
 ReadRowUsingIndex 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 index 
  
  string 
 
 , 
  
 key 
  
  Key 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 * 
  Row 
 
 , 
  
  error 
 
 ) 
 

ReadRowUsingIndex reads a single row from the database using an index.

If no row is present with the given index, then ReadRowUsingIndex returns an error where spanner.ErrCode(err) is codes.NotFound.

If more than one row received with the given index, then ReadRowUsingIndex returns an error where spanner.ErrCode(err) is codes.FailedPrecondition.

func (*ReadWriteStmtBasedTransaction) ReadUsingIndex

  func 
  
 ( 
 t 
  
 * 
  ReadWriteStmtBasedTransaction 
 
 ) 
  
 ReadUsingIndex 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
 , 
  
 index 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 ri 
  
 * 
  RowIterator 
 
 ) 
 

ReadUsingIndex calls ReadWithOptions with ReadOptions{Index: index}.

func (*ReadWriteStmtBasedTransaction) ReadWithOptions

  func 
  
 ( 
 t 
  
 * 
  ReadWriteStmtBasedTransaction 
 
 ) 
  
 ReadWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 , 
  
 opts 
  
 * 
  ReadOptions 
 
 ) 
  
 ( 
 ri 
  
 * 
  RowIterator 
 
 ) 
 

ReadWithOptions returns a RowIterator for reading multiple rows from the database. Pass a ReadOptions to modify the read operation.

func (*ReadWriteStmtBasedTransaction) Rollback

Rollback is called to cancel the ongoing transaction that has not been committed yet.

ReadWriteTransaction

  type 
  
 ReadWriteTransaction 
  
 struct 
  
 { 
  
 // contains filtered or unexported fields 
 } 
 

ReadWriteTransaction provides a locking read-write transaction.

This type of transaction is the only way to write data into Cloud Spanner; ( Client).Apply, ( Client).ApplyAtLeastOnce, ( Client).PartitionedUpdate use transactions internally. These transactions rely on pessimistic locking and, if necessary, two-phase commit. Locking read-write transactions may abort, requiring the application to retry. However, the interface exposed by ( Client).ReadWriteTransaction eliminates the need for applications to write retry loops explicitly.

Locking transactions may be used to atomically read-modify-write data anywhere in a database. This type of transaction is externally consistent.

Clients should attempt to minimize the amount of time a transaction is active. Faster transactions commit with higher probability and cause less contention. Cloud Spanner attempts to keep read locks active as long as the transaction continues to do reads. Long periods of inactivity at the client may cause Cloud Spanner to release a transaction's locks and abort it.

Reads performed within a transaction acquire locks on the data being read. Writes can only be done at commit time, after all reads have been completed. Conceptually, a read-write transaction consists of zero or more reads or SQL queries followed by a commit.

See (*Client).ReadWriteTransaction for an example.

Semantics

Cloud Spanner can commit the transaction if all read locks it acquired are still valid at commit time, and it is able to acquire write locks for all writes. Cloud Spanner can abort the transaction for any reason. If a commit attempt returns ABORTED, Cloud Spanner guarantees that the transaction has not modified any user data in Cloud Spanner.

Unless the transaction commits, Cloud Spanner makes no guarantees about how long the transaction's locks were held for. It is an error to use Cloud Spanner locks for any sort of mutual exclusion other than between Cloud Spanner transactions themselves.

Aborted transactions

Application code does not need to retry explicitly; RunInTransaction will automatically retry a transaction if an attempt results in an abort. The lock priority of a transaction increases after each prior aborted transaction, meaning that the next attempt has a slightly better chance of success than before.

Under some circumstances (e.g., many transactions attempting to modify the same row(s)), a transaction can abort many times in a short period before successfully committing. Thus, it is not a good idea to cap the number of retries a transaction can attempt; instead, it is better to limit the total amount of wall time spent retrying.

Idle transactions

A transaction is considered idle if it has no outstanding reads or SQL queries and has not started a read or SQL query within the last 10 seconds. Idle transactions can be aborted by Cloud Spanner so that they don't hold on to locks indefinitely. In that case, the commit will fail with error ABORTED.

If this behavior is undesirable, periodically executing a simple SQL query in the transaction (e.g., SELECT 1) prevents the transaction from becoming idle.

func (*ReadWriteTransaction) AnalyzeQuery

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 AnalyzeQuery 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 ) 
  
 ( 
 * 
  sppb 
 
 . 
  QueryPlan 
 
 , 
  
  error 
 
 ) 
 

AnalyzeQuery returns the query plan for statement.

func (*ReadWriteTransaction) BatchUpdate

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 BatchUpdate 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 stmts 
  
 [] 
  Statement 
 
 ) 
  
 ( 
 _ 
  
 [] 
  int64 
 
 , 
  
 err 
  
  error 
 
 ) 
 

BatchUpdate groups one or more DML statements and sends them to Spanner in a single RPC. This is an efficient way to execute multiple DML statements.

A slice of counts is returned, where each count represents the number of affected rows for the given query at the same index. If an error occurs, counts will be returned up to the query that encountered the error.

func (*ReadWriteTransaction) BufferWrite

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 BufferWrite 
 ( 
 ms 
  
 [] 
 * 
  Mutation 
 
 ) 
  
  error 
 
 

BufferWrite adds a list of mutations to the set of updates that will be applied when the transaction is committed. It does not actually apply the write until the transaction is committed, so the operation does not block. The effects of the write won't be visible to any reads (including reads done in the same transaction) until the transaction commits.

See the example for Client.ReadWriteTransaction.

func (*ReadWriteTransaction) Query

Query executes a query against the database. It returns a RowIterator for retrieving the resulting rows.

Query returns only row data, without a query plan or execution statistics. Use QueryWithStats to get rows along with the plan and statistics. Use AnalyzeQuery to get just the plan.

func (*ReadWriteTransaction) QueryWithOptions

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 QueryWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 , 
  
 opts 
  
  QueryOptions 
 
 ) 
  
 * 
  RowIterator 
 
 

QueryWithOptions executes a SQL statment against the database. It returns a RowIterator for retrieving the resulting rows. The sql query execution will be optimized based on the given query options.

func (*ReadWriteTransaction) QueryWithStats

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 QueryWithStats 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 statement 
  
  Statement 
 
 ) 
  
 * 
  RowIterator 
 
 

QueryWithStats executes a SQL statement against the database. It returns a RowIterator for retrieving the resulting rows. The RowIterator will also be populated with a query plan and execution statistics.

func (*ReadWriteTransaction) Read

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 Read 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 * 
  RowIterator 
 
 

Read returns a RowIterator for reading multiple rows from the database.

func (*ReadWriteTransaction) ReadRow

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 ReadRow 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 key 
  
  Key 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 * 
  Row 
 
 , 
  
  error 
 
 ) 
 

ReadRow reads a single row from the database.

If no row is present with the given key, then ReadRow returns an error where spanner.ErrCode(err) is codes.NotFound.

func (*ReadWriteTransaction) ReadRowUsingIndex

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 ReadRowUsingIndex 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 index 
  
  string 
 
 , 
  
 key 
  
  Key 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 * 
  Row 
 
 , 
  
  error 
 
 ) 
 

ReadRowUsingIndex reads a single row from the database using an index.

If no row is present with the given index, then ReadRowUsingIndex returns an error where spanner.ErrCode(err) is codes.NotFound.

If more than one row received with the given index, then ReadRowUsingIndex returns an error where spanner.ErrCode(err) is codes.FailedPrecondition.

func (*ReadWriteTransaction) ReadUsingIndex

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 ReadUsingIndex 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
 , 
  
 index 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 ) 
  
 ( 
 ri 
  
 * 
  RowIterator 
 
 ) 
 

ReadUsingIndex calls ReadWithOptions with ReadOptions{Index: index}.

func (*ReadWriteTransaction) ReadWithOptions

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 ReadWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 table 
  
  string 
 
 , 
  
 keys 
  
  KeySet 
 
 , 
  
 columns 
  
 [] 
  string 
 
 , 
  
 opts 
  
 * 
  ReadOptions 
 
 ) 
  
 ( 
 ri 
  
 * 
  RowIterator 
 
 ) 
 

ReadWithOptions returns a RowIterator for reading multiple rows from the database. Pass a ReadOptions to modify the read operation.

func (*ReadWriteTransaction) Update

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 Update 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 stmt 
  
  Statement 
 
 ) 
  
 ( 
 rowCount 
  
  int64 
 
 , 
  
 err 
  
  error 
 
 ) 
 

Update executes a DML statement against the database. It returns the number of affected rows. Update returns an error if the statement is a query. However, the query is executed, and any data read will be validated upon commit.

func (*ReadWriteTransaction) UpdateWithOptions

  func 
  
 ( 
 t 
  
 * 
  ReadWriteTransaction 
 
 ) 
  
 UpdateWithOptions 
 ( 
 ctx 
  
  context 
 
 . 
  Context 
 
 , 
  
 stmt 
  
  Statement 
 
 , 
  
 opts 
  
  QueryOptions 
 
 ) 
  
 ( 
 rowCount 
  
  int64 
 
 , 
  
 err 
  
  error 
 
 ) 
 

UpdateWithOptions executes a DML statement against the database. It returns the number of affected rows. The sql query execution will be optimized based on the given query options.

Row

  type 
  
 Row 
  
 struct 
  
 { 
  
 // contains filtered or unexported fields 
 } 
 

A Row is a view of a row of data returned by a Cloud Spanner read. It consists of a number of columns; the number depends on the columns used to construct the read.

The column values can be accessed by index. For instance, if the read specified []string{"photo_id", "caption"}, then each row will contain two columns: "photo_id" with index 0, and "caption" with index 1.

Column values are decoded by using one of the Column, ColumnByName, or Columns methods. The valid values passed to these methods depend on the column type. For example:

 var photoID int64
err := row.Column(0, &photoID) // Decode column 0 as an integer.

var caption string
err := row.Column(1, &caption) // Decode column 1 as a string.

// Decode all the columns.
err := row.Columns(&photoID, &caption) 

Supported types and their corresponding Cloud Spanner column type(s) are:

 *string(not NULL), *NullString - STRING
*[]string, *[]NullString - STRING ARRAY
*[]byte - BYTES
*[][]byte - BYTES ARRAY
*int64(not NULL), *NullInt64 - INT64
*[]int64, *[]NullInt64 - INT64 ARRAY
*bool(not NULL), *NullBool - BOOL
*[]bool, *[]NullBool - BOOL ARRAY
*float64(not NULL), *NullFloat64 - FLOAT64
*[]float64, *[]NullFloat64 - FLOAT64 ARRAY
*time.Time(not NULL), *NullTime - TIMESTAMP
*[]time.Time, *[]NullTime - TIMESTAMP ARRAY
*Date(not NULL), *NullDate - DATE
*[]civil.Date, *[]NullDate - DATE ARRAY
*[]*some_go_struct, *[]NullRow - STRUCT ARRAY
*GenericColumnValue - any Cloud Spanner type 

For TIMESTAMP columns, the returned time.Time object will be in UTC.

To fetch an array of BYTES, pass a [][]byte. To fetch an array of (sub)rows, pass a *[]spanner.NullRow or a *[] some_go_struct where some_go_struct holds all information of the subrow, see spanner.Row.ToStruct for the mapping between a Cloud Spanner row and a Go struct. To fetch an array of other types, pass a *[]spanner.NullXXX type of the appropriate type. Use GenericColumnValue when you don't know in advance what column type to expect.

Row decodes the row contents lazily; as a result, each call to a getter has a chance of returning an error.

A column value may be NULL if the corresponding value is not present in Cloud Spanner. The spanner.NullXXX types (spanner.NullInt64 et al.) allow fetching values that may be null. A NULL BYTES can be fetched into a *[]byte as nil. It is an error to fetch a NULL value into any other type.

func NewRow

  func 
  
 NewRow 
 ( 
 columnNames 
  
 [] 
  string 
 
 , 
  
 columnValues 
  
 [] 
 interface 
 {}) 
  
 ( 
 * 
  Row 
 
 , 
  
  error 
 
 ) 
 

NewRow returns a Row containing the supplied data. This can be useful for mocking Cloud Spanner Read and Query responses for unit testing.

func (*Row) Column

  func 
  
 ( 
 r 
  
 * 
  Row 
 
 ) 
  
 Column 
 ( 
 i 
  
  int 
 
 , 
  
 ptr 
  
 interface 
 {}) 
  
  error 
 
 

Column fetches the value from the ith column, decoding it into ptr. See the Row documentation for the list of acceptable argument types. see Client.ReadWriteTransaction for an example.

func (*Row) ColumnByName

  func 
  
 ( 
 r 
  
 * 
  Row 
 
 ) 
  
 ColumnByName 
 ( 
 name 
  
  string 
 
 , 
  
 ptr 
  
 interface 
 {}) 
  
  error 
 
 

ColumnByName fetches the value from the named column, decoding it into ptr. See the Row documentation for the list of acceptable argument types.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 row 
 , 
  
 err 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 var 
  
 balance 
  
 int64 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  ColumnByName 
 
 ( 
 "balance" 
 , 
  
& balance 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 balance 
 ) 
 } 
 

func (*Row) ColumnIndex

  func 
  
 ( 
 r 
  
 * 
  Row 
 
 ) 
  
 ColumnIndex 
 ( 
 name 
  
  string 
 
 ) 
  
 ( 
  int 
 
 , 
  
  error 
 
 ) 
 

ColumnIndex returns the index of the column with the given name. The comparison is case-sensitive.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 row 
 , 
  
 err 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 index 
 , 
  
 err 
  
 := 
  
 row 
 . 
  ColumnIndex 
 
 ( 
 "balance" 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 index 
 ) 
 } 
 

func (*Row) ColumnName

  func 
  
 ( 
 r 
  
 * 
  Row 
 
 ) 
  
 ColumnName 
 ( 
 i 
  
  int 
 
 ) 
  
  string 
 
 

ColumnName returns the name of column i, or empty string for invalid column.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 row 
 , 
  
 err 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 row 
 . 
  ColumnName 
 
 ( 
 1 
 )) 
  
 // "balance" 
 } 
 

func (*Row) ColumnNames

  func 
  
 ( 
 r 
  
 * 
  Row 
 
 ) 
  
 ColumnNames 
 () 
  
 [] 
  string 
 
 

ColumnNames returns all column names of the row.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 row 
 , 
  
 err 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 row 
 . 
  ColumnNames 
 
 ()) 
 } 
 

func (*Row) Columns

  func 
  
 ( 
 r 
  
 * 
  Row 
 
 ) 
  
 Columns 
 ( 
 ptrs 
  
 ... 
 interface 
 {}) 
  
  error 
 
 

Columns fetches all the columns in the row at once.

The value of the kth column will be decoded into the kth argument to Columns. See Row for the list of acceptable argument types. The number of arguments must be equal to the number of columns. Pass nil to specify that a column should be ignored.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 row 
 , 
  
 err 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 var 
  
 name 
  
 string 
  
 var 
  
 balance 
  
 int64 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  Columns 
 
 ( 
& name 
 , 
  
& balance 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 name 
 , 
  
 balance 
 ) 
 } 
 

func (*Row) Size

  func 
  
 ( 
 r 
  
 * 
  Row 
 
 ) 
  
 Size 
 () 
  
  int 
 
 

Size is the number of columns in the row.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 row 
 , 
  
 err 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 row 
 . 
  Size 
 
 ()) 
  
 // 2 
 } 
 

func (*Row) ToStruct

  func 
  
 ( 
 r 
  
 * 
  Row 
 
 ) 
  
 ToStruct 
 ( 
 p 
  
 interface 
 {}) 
  
  error 
 
 

ToStruct fetches the columns in a row into the fields of a struct. The rules for mapping a row's columns into a struct's exported fields are:

  1. If a field has a spanner: "column_name" tag, then decode column 'column_name' into the field. A special case is the spanner: "-" tag, which instructs ToStruct to ignore the field during decoding.

  2. Otherwise, if the name of a field matches the name of a column (ignoring case), decode the column into the field.

The fields of the destination struct can be of any type that is acceptable to spanner.Row.Column.

Slice and pointer fields will be set to nil if the source column is NULL, and a non-nil value if the column is not NULL. To decode NULL values of other types, use one of the spanner.NullXXX types as the type of the destination field.

If ToStruct returns an error, the contents of p are undefined. Some fields may have been successfully populated, while others were not; you should not use any of the fields.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 row 
 , 
  
 err 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 ReadRow 
 ( 
 ctx 
 , 
  
 "Accounts" 
 , 
  
 spanner 
 . 
  Key 
 
 { 
 "alice" 
 }, 
  
 [] 
 string 
 { 
 "name" 
 , 
  
 "balance" 
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 type 
  
 Account 
  
 struct 
  
 { 
  
 Name 
  
 string 
  
 Balance 
  
 int64 
  
 } 
  
 var 
  
 acct 
  
 Account 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  ToStruct 
 
 ( 
& acct 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 acct 
 ) 
 } 
 

RowIterator

  type 
  
 RowIterator 
  
 struct 
  
 { 
  
 // The plan for the query. Available after RowIterator.Next returns 
  
 // iterator.Done if QueryWithStats was called. 
  
 QueryPlan 
  
 * 
  sppb 
 
 . 
  QueryPlan 
 
  
 // Execution statistics for the query. Available after RowIterator.Next 
  
 // returns iterator.Done if QueryWithStats was called. 
  
 QueryStats 
  
 map 
 [ 
  string 
 
 ] 
 interface 
 {} 
  
 // For a DML statement, the number of rows affected. For PDML, this is a 
  
 // lower bound. Available for DML statements after RowIterator.Next returns 
  
 // iterator.Done. 
  
 RowCount 
  
  int64 
 
  
 // The metadata of the results of the query. The metadata are available 
  
 // after the first call to RowIterator.Next(), unless the first call to 
  
 // RowIterator.Next() returned an error that is not equal to iterator.Done. 
  
 Metadata 
  
 * 
  sppb 
 
 . 
  ResultSetMetadata 
 
  
 // contains filtered or unexported fields 
 } 
 

RowIterator is an iterator over Rows.

func (*RowIterator) Do

  func 
  
 ( 
 r 
  
 * 
  RowIterator 
 
 ) 
  
 Do 
 ( 
 f 
  
 func 
 ( 
 r 
  
 * 
  Row 
 
 ) 
  
  error 
 
 ) 
  
  error 
 
 

Do calls the provided function once in sequence for each row in the iteration. If the function returns a non-nil error, Do immediately returns that error.

If there are no rows in the iterator, Do will return nil without calling the provided function.

Do always calls Stop on the iterator.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 iter 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 Query 
 ( 
 ctx 
 , 
  
 spanner 
 . 
  NewStatement 
 
 ( 
 "SELECT FirstName FROM Singers" 
 )) 
  
 err 
  
 = 
  
 iter 
 . 
 Do 
 ( 
 func 
 ( 
 r 
  
 * 
 spanner 
 . 
  Row 
 
 ) 
  
 error 
  
 { 
  
 var 
  
 firstName 
  
 string 
  
 if 
  
 err 
  
 := 
  
 r 
 . 
  Column 
 
 ( 
 0 
 , 
  
& firstName 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 err 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 firstName 
 ) 
  
 return 
  
 nil 
  
 }) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
 } 
 

func (*RowIterator) Next

  func 
  
 ( 
 r 
  
 * 
  RowIterator 
 
 ) 
  
 Next 
 () 
  
 ( 
 * 
  Row 
 
 , 
  
  error 
 
 ) 
 

Next returns the next result. Its second return value is iterator.Done if there are no more results. Once Next returns Done, all subsequent calls will return Done.

Example

  package 
  
 main 
 import 
  
 ( 
  
 "context" 
  
 "fmt" 
  
 "cloud.google.com/go/spanner" 
  
 "google.golang.org/api/iterator" 
 ) 
 const 
  
 myDB 
  
 = 
  
 "projects/my-project/instances/my-instance/database/my-db" 
 func 
  
 main 
 () 
  
 { 
  
 ctx 
  
 := 
  
 context 
 . 
 Background 
 () 
  
 client 
 , 
  
 err 
  
 := 
  
 spanner 
 . 
 NewClient 
 ( 
 ctx 
 , 
  
 myDB 
 ) 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 iter 
  
 := 
  
 client 
 . 
  Single 
 
 (). 
 Query 
 ( 
 ctx 
 , 
  
 spanner 
 . 
  NewStatement 
 
 ( 
 "SELECT FirstName FROM Singers" 
 )) 
  
 defer 
  
 iter 
 . 
 Stop 
 () 
  
 for 
  
 { 
  
 row 
 , 
  
 err 
  
 := 
  
 iter 
 . 
 Next 
 () 
  
 if 
  
 err 
  
 == 
  
 iterator 
 . 
 Done 
  
 { 
  
 break 
  
 } 
  
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 var 
  
 firstName 
  
 string 
  
 if 
  
 err 
  
 := 
  
 row 
 . 
  Column 
 
 ( 
 0 
 , 
  
& firstName 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 // TODO: Handle error. 
  
 } 
  
 fmt 
 . 
 Println 
 ( 
 firstName 
 ) 
  
 } 
 } 
 

func (*RowIterator) Stop

  func 
  
 ( 
 r 
  
 * 
  RowIterator 
 
 ) 
  
 Stop 
 () 
 

Stop terminates the iteration. It should be called after you finish using the iterator.

SessionPoolConfig

  type 
  
 SessionPoolConfig 
  
 struct 
  
 { 
  
 // MaxOpened is the maximum number of opened sessions allowed by the session 
  
 // pool. If the client tries to open a session and there are already 
  
 // MaxOpened sessions, it will block until one becomes available or the 
  
 // context passed to the client method is canceled or times out. 
  
 // 
  
 // Defaults to NumChannels * 100. 
  
 MaxOpened 
  
  uint64 
 
  
 // MinOpened is the minimum number of opened sessions that the session pool 
  
 // tries to maintain. Session pool won't continue to expire sessions if 
  
 // number of opened connections drops below MinOpened. However, if a session 
  
 // is found to be broken, it will still be evicted from the session pool, 
  
 // therefore it is posssible that the number of opened sessions drops below 
  
 // MinOpened. 
  
 // 
  
 // Defaults to 100. 
  
 MinOpened 
  
  uint64 
 
  
 // MaxIdle is the maximum number of idle sessions, pool is allowed to keep. 
  
 // 
  
 // Defaults to 0. 
  
 MaxIdle 
  
  uint64 
 
  
 // MaxBurst is the maximum number of concurrent session creation requests. 
  
 // 
  
 // Defaults to 10. 
  
 MaxBurst 
  
  uint64 
 
  
 // WriteSessions is the fraction of sessions we try to keep prepared for 
  
 // write. 
  
 // 
  
 // Defaults to 0.2. 
  
 WriteSessions 
  
  float64 
 
  
 // HealthCheckWorkers is number of workers used by health checker for this 
  
 // pool. 
  
 // 
  
 // Defaults to 10. 
  
 HealthCheckWorkers 
  
  int 
 
  
 // HealthCheckInterval is how often the health checker pings a session. 
  
 // 
  
 // Defaults to 5m. 
  
 HealthCheckInterval 
  
  time 
 
 . 
  Duration 
 
  
 // TrackSessionHandles determines whether the session pool will keep track 
  
 // of the stacktrace of the goroutines that take sessions from the pool. 
  
 // This setting can be used to track down session leak problems. 
  
 // 
  
 // Defaults to false. 
  
 TrackSessionHandles 
  
  bool 
 
  
 // contains filtered or unexported fields 
 } 
 

SessionPoolConfig stores configurations of a session pool.

Statement

  type 
  
 Statement 
  
 struct 
  
 { 
  
 SQL 
  
  string 
 
  
 Params 
  
 map 
 [ 
  string 
 
 ] 
 interface 
 {} 
 } 
 

A Statement is a SQL query with named parameters.

A parameter placeholder consists of '@' followed by the parameter name. The parameter name is an identifier which must conform to the naming requirements in https://cloud.google.com/spanner/docs/lexical#identifiers . Parameters may appear anywhere that a literal value is expected. The same parameter name may be used more than once. It is an error to execute a statement with unbound parameters. On the other hand, it is allowable to bind parameter names that are not used.

See the documentation of the Row type for how Go types are mapped to Cloud Spanner types.

Example

regexpContains

  package 
  
 main 
 import 
  
 ( 
  
 "cloud.google.com/go/spanner" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 // Search for accounts with valid emails using regexp as per: 
  
 //   https://cloud.google.com/spanner/docs/functions-and-operators#regexp_contains 
  
 stmt 
  
 := 
  
 spanner 
 . 
  Statement 
 
 { 
  
 SQL 
 : 
  
 `SELECT * FROM users WHERE REGEXP_CONTAINS(email, @valid_email)` 
 , 
  
 Params 
 : 
  
 map 
 [ 
 string 
 ] 
 interface 
 {}{ 
  
 "valid_email" 
 : 
  
 `\Q@\E` 
 , 
  
 }, 
  
 } 
  
 _ 
  
 = 
  
 stmt 
  
 // TODO: Use stmt in a query. 
 } 
 

func NewStatement

  func 
  
 NewStatement 
 ( 
 sql 
  
  string 
 
 ) 
  
  Statement 
 
 

NewStatement returns a Statement with the given SQL and an empty Params map.

Examples

  package 
  
 main 
 import 
  
 ( 
  
 "cloud.google.com/go/spanner" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 stmt 
  
 := 
  
 spanner 
 . 
  NewStatement 
 
 ( 
 "SELECT FirstName, LastName FROM SINGERS WHERE LastName >= @start" 
 ) 
  
 stmt 
 . 
 Params 
 [ 
 "start" 
 ] 
  
 = 
  
 "Dylan" 
  
 // TODO: Use stmt in Query. 
 } 
 
structLiteral
  package 
  
 main 
 import 
  
 ( 
  
 "cloud.google.com/go/spanner" 
 ) 
 func 
  
 main 
 () 
  
 { 
  
 stmt 
  
 := 
  
 spanner 
 . 
  Statement 
 
 { 
  
 SQL 
 : 
  
 `SELECT FirstName, LastName FROM SINGERS WHERE LastName = ("Lea", "Martin")` 
 , 
  
 } 
  
 _ 
  
 = 
  
 stmt 
  
 // TODO: Use stmt in Query. 
 } 
 

TimestampBound

  type 
  
 TimestampBound 
  
 struct 
  
 { 
  
 // contains filtered or unexported fields 
 } 
 

TimestampBound defines how Cloud Spanner will choose a timestamp for a single read/query or read-only transaction.

There are three types of timestamp bound: strong, bounded staleness and exact staleness. Strong is the default.

If the Cloud Spanner database to be read is geographically distributed, stale read-only transactions can execute more quickly than strong or read-write transactions, because they are able to execute far from the leader replica.

Each type of timestamp bound is discussed in detail below. A TimestampBound can be specified when creating transactions, see the documentation of spanner.Client for an example.

Strong reads

Strong reads are guaranteed to see the effects of all transactions that have committed before the start of the read. Furthermore, all rows yielded by a single read are consistent with each other: if any part of the read observes a transaction, all parts of the read see the transaction.

Strong reads are not repeatable: two consecutive strong read-only transactions might return inconsistent results if there are concurrent writes. If consistency across reads is required, the reads should be executed within a transaction or at an exact read timestamp.

Use StrongRead to create a bound of this type.

Exact staleness

An exact staleness timestamp bound executes reads at a user-specified timestamp. Reads at a timestamp are guaranteed to see a consistent prefix of the global transaction history: they observe modifications done by all transactions with a commit timestamp less than or equal to the read timestamp, and observe none of the modifications done by transactions with a larger commit timestamp. They will block until all conflicting transactions that may be assigned commit timestamps less than or equal to the read timestamp have finished.

The timestamp can either be expressed as an absolute Cloud Spanner commit timestamp or a staleness relative to the current time.

These modes do not require a "negotiation phase" to pick a timestamp. As a result, they execute slightly faster than the equivalent boundedly stale concurrency modes. On the other hand, boundedly stale reads usually return fresher results.

Use ReadTimestamp and ExactStaleness to create a bound of this type.

Bounded staleness

Bounded staleness modes allow Cloud Spanner to pick the read timestamp, subject to a user-provided staleness bound. Cloud Spanner chooses the newest timestamp within the staleness bound that allows execution of the reads at the closest available replica without blocking.

All rows yielded are consistent with each other: if any part of the read observes a transaction, all parts of the read see the transaction. Boundedly stale reads are not repeatable: two stale reads, even if they use the same staleness bound, can execute at different timestamps and thus return inconsistent results.

Boundedly stale reads execute in two phases. The first phase negotiates a timestamp among all replicas needed to serve the read. In the second phase, reads are executed at the negotiated timestamp.

As a result of this two-phase execution, bounded staleness reads are usually a little slower than comparable exact staleness reads. However, they are typically able to return fresher results, and are more likely to execute at the closest replica.

Because the timestamp negotiation requires up-front knowledge of which rows will be read, it can only be used with single-use reads and single-use read-only transactions.

Use MinReadTimestamp and MaxStaleness to create a bound of this type.

Old read timestamps and garbage collection

Cloud Spanner continuously garbage collects deleted and overwritten data in the background to reclaim storage space. This process is known as "version GC". By default, version GC reclaims versions after they are one hour old. Because of this, Cloud Spanner cannot perform reads at read timestamps more than one hour in the past. This restriction also applies to in-progress reads and/or SQL queries whose timestamps become too old while executing. Reads and SQL queries with too-old read timestamps fail with the error ErrorCode.FAILED_PRECONDITION.

func ExactStaleness

  func 
  
 ExactStaleness 
 ( 
 d 
  
  time 
 
 . 
  Duration 
 
 ) 
  
  TimestampBound 
 
 

ExactStaleness returns a TimestampBound that will perform reads and queries at an exact staleness.

func MaxStaleness

  func 
  
 MaxStaleness 
 ( 
 d 
  
  time 
 
 . 
  Duration 
 
 ) 
  
  TimestampBound 
 
 

MaxStaleness returns a TimestampBound that will perform reads and queries at a time chosen to be at most "d" stale.

func MinReadTimestamp

  func 
  
 MinReadTimestamp 
 ( 
 t 
  
  time 
 
 . 
  Time 
 
 ) 
  
  TimestampBound 
 
 

MinReadTimestamp returns a TimestampBound that bound that will perform reads and queries at a time chosen to be at least "t".

func ReadTimestamp

  func 
  
 ReadTimestamp 
 ( 
 t 
  
  time 
 
 . 
  Time 
 
 ) 
  
  TimestampBound 
 
 

ReadTimestamp returns a TimestampBound that will peform reads and queries at the given time.

func StrongRead

  func 
  
 StrongRead 
 () 
  
  TimestampBound 
 
 

StrongRead returns a TimestampBound that will perform reads and queries at a timestamp where all previously committed transactions are visible.

func (TimestampBound) String

  func 
  
 ( 
 tb 
  
  TimestampBound 
 
 ) 
  
 String 
 () 
  
  string 
 
 

TransactionOptions

  type 
  
 TransactionOptions 
  
 struct 
  
 { 
  
 CommitOptions 
  
  CommitOptions 
 
 } 
 

TransactionOptions provides options for a transaction.

TransactionOutcomeUnknownError

  type 
  
 TransactionOutcomeUnknownError 
  
 struct 
  
 { 
  
 // contains filtered or unexported fields 
 } 
 

TransactionOutcomeUnknownError is wrapped in a Spanner error when the error occurred during a transaction, and the outcome of the transaction is unknown as a result of the error. This could be the case if a timeout or canceled error occurs after a Commit request has been sent, but before the client has received a response from the server.

func (*TransactionOutcomeUnknownError) Error

Error implements error.Error.

func (*TransactionOutcomeUnknownError) Unwrap

Unwrap returns the wrapped error (if any).

Create a Mobile Website
View Site in Mobile | Classic
Share by: