1/*
2Copyright 2017 Google LLC
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17/*
18Package spanner provides a client for reading and writing to Cloud Spanner
19databases. See the packages under admin for clients that operate on databases
20and instances.
21
22See https://cloud.google.com/spanner/docs/getting-started/go/ for an
23introduction to Cloud Spanner and additional help on using this API.
24
25See https://godoc.org/cloud.google.com/go for authentication, timeouts,
26connection pooling and similar aspects of this package.
27
28
29Creating a Client
30
31To start working with this package, create a client that refers to the database
32of interest:
33
34    ctx := context.Background()
35    client, err := spanner.NewClient(ctx, "projects/P/instances/I/databases/D")
36    if err != nil {
37        // TODO: Handle error.
38    }
39    defer client.Close()
40
41Remember to close the client after use to free up the sessions in the session
42pool.
43
44
45Simple Reads and Writes
46
47Two Client methods, Apply and Single, work well for simple reads and writes. As
48a quick introduction, here we write a new row to the database and read it back:
49
50    _, err := client.Apply(ctx, []*spanner.Mutation{
51        spanner.Insert("Users",
52            []string{"name", "email"},
53            []interface{}{"alice", "a@example.com"})})
54    if err != nil {
55        // TODO: Handle error.
56    }
57    row, err := client.Single().ReadRow(ctx, "Users",
58        spanner.Key{"alice"}, []string{"email"})
59    if err != nil {
60        // TODO: Handle error.
61    }
62
63All the methods used above are discussed in more detail below.
64
65
66Keys
67
68Every Cloud Spanner row has a unique key, composed of one or more columns.
69Construct keys with a literal of type Key:
70
71   key1 := spanner.Key{"alice"}
72
73
74KeyRanges
75
76The keys of a Cloud Spanner table are ordered. You can specify ranges of keys
77using the KeyRange type:
78
79    kr1 := spanner.KeyRange{Start: key1, End: key2}
80
81By default, a KeyRange includes its start key but not its end key. Use
82the Kind field to specify other boundary conditions:
83
84    // include both keys
85    kr2 := spanner.KeyRange{Start: key1, End: key2, Kind: spanner.ClosedClosed}
86
87
88KeySets
89
90A KeySet represents a set of keys. A single Key or KeyRange can act as a KeySet.
91Use the KeySets function to build the union of several KeySets:
92
93    ks1 := spanner.KeySets(key1, key2, kr1, kr2)
94
95AllKeys returns a KeySet that refers to all the keys in a table:
96
97    ks2 := spanner.AllKeys()
98
99
100Transactions
101
102All Cloud Spanner reads and writes occur inside transactions. There are two
103types of transactions, read-only and read-write. Read-only transactions cannot
104change the database, do not acquire locks, and may access either the current
105database state or states in the past. Read-write transactions can read the
106database before writing to it, and always apply to the most recent database
107state.
108
109
110Single Reads
111
112The simplest and fastest transaction is a ReadOnlyTransaction that supports a
113single read operation. Use Client.Single to create such a transaction. You can
114chain the call to Single with a call to a Read method.
115
116When you only want one row whose key you know, use ReadRow. Provide the table
117name, key, and the columns you want to read:
118
119    row, err := client.Single().ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"balance"})
120
121Read multiple rows with the Read method. It takes a table name, KeySet, and list
122of columns:
123
124    iter := client.Single().Read(ctx, "Accounts", keyset1, columns)
125
126Read returns a RowIterator. You can call the Do method on the iterator and pass
127a callback:
128
129    err := iter.Do(func(row *Row) error {
130       // TODO: use row
131       return nil
132    })
133
134RowIterator also follows the standard pattern for the Google
135Cloud Client Libraries:
136
137    defer iter.Stop()
138    for {
139        row, err := iter.Next()
140        if err == iterator.Done {
141            break
142        }
143        if err != nil {
144            // TODO: Handle error.
145        }
146        // TODO: use row
147    }
148
149Always call Stop when you finish using an iterator this way, whether or not you
150iterate to the end. (Failing to call Stop could lead you to exhaust the
151database's session quota.)
152
153To read rows with an index, use ReadUsingIndex.
154
155Statements
156
157The most general form of reading uses SQL statements. Construct a Statement
158with NewStatement, setting any parameters using the Statement's Params map:
159
160    stmt := spanner.NewStatement("SELECT First, Last FROM SINGERS WHERE Last >= @start")
161    stmt.Params["start"] = "Dylan"
162
163You can also construct a Statement directly with a struct literal, providing
164your own map of parameters.
165
166Use the Query method to run the statement and obtain an iterator:
167
168    iter := client.Single().Query(ctx, stmt)
169
170
171Rows
172
173Once you have a Row, via an iterator or a call to ReadRow, you can extract
174column values in several ways. Pass in a pointer to a Go variable of the
175appropriate type when you extract a value.
176
177You can extract by column position or name:
178
179   err := row.Column(0, &name)
180   err = row.ColumnByName("balance", &balance)
181
182You can extract all the columns at once:
183
184   err = row.Columns(&name, &balance)
185
186Or you can define a Go struct that corresponds to your columns, and extract
187into that:
188
189   var s struct { Name string; Balance int64 }
190   err = row.ToStruct(&s)
191
192
193For Cloud Spanner columns that may contain NULL, use one of the NullXXX types,
194like NullString:
195
196    var ns spanner.NullString
197    if err := row.Column(0, &ns); err != nil {
198        // TODO: Handle error.
199    }
200    if ns.Valid {
201        fmt.Println(ns.StringVal)
202    } else {
203        fmt.Println("column is NULL")
204    }
205
206
207Multiple Reads
208
209To perform more than one read in a transaction, use ReadOnlyTransaction:
210
211    txn := client.ReadOnlyTransaction()
212    defer txn.Close()
213    iter := txn.Query(ctx, stmt1)
214    // ...
215    iter =  txn.Query(ctx, stmt2)
216    // ...
217
218You must call Close when you are done with the transaction.
219
220
221Timestamps and Timestamp Bounds
222
223Cloud Spanner read-only transactions conceptually perform all their reads at a
224single moment in time, called the transaction's read timestamp. Once a read has
225started, you can call ReadOnlyTransaction's Timestamp method to obtain the read
226timestamp.
227
228By default, a transaction will pick the most recent time (a time where all
229previously committed transactions are visible) for its reads. This provides the
230freshest data, but may involve some delay. You can often get a quicker response
231if you are willing to tolerate "stale" data. You can control the read timestamp
232selected by a transaction by calling the WithTimestampBound method on the
233transaction before using it. For example, to perform a query on data that is at
234most one minute stale, use
235
236    client.Single().
237        WithTimestampBound(spanner.MaxStaleness(1*time.Minute)).
238        Query(ctx, stmt)
239
240See the documentation of TimestampBound for more details.
241
242
243Mutations
244
245To write values to a Cloud Spanner database, construct a Mutation. The spanner
246package has functions for inserting, updating and deleting rows. Except for the
247Delete methods, which take a Key or KeyRange, each mutation-building function
248comes in three varieties.
249
250One takes lists of columns and values along with the table name:
251
252    m1 := spanner.Insert("Users",
253        []string{"name", "email"},
254        []interface{}{"alice", "a@example.com"})
255
256One takes a map from column names to values:
257
258    m2 := spanner.InsertMap("Users", map[string]interface{}{
259        "name":  "alice",
260        "email": "a@example.com",
261    })
262
263And the third accepts a struct value, and determines the columns from the
264struct field names:
265
266    type User struct { Name, Email string }
267    u := User{Name: "alice", Email: "a@example.com"}
268    m3, err := spanner.InsertStruct("Users", u)
269
270
271Writes
272
273To apply a list of mutations to the database, use Apply:
274
275    _, err := client.Apply(ctx, []*spanner.Mutation{m1, m2, m3})
276
277If you need to read before writing in a single transaction, use a
278ReadWriteTransaction. ReadWriteTransactions may abort and need to be retried.
279You pass in a function to ReadWriteTransaction, and the client will handle the
280retries automatically. Use the transaction's BufferWrite method to buffer
281mutations, which will all be executed at the end of the transaction:
282
283    _, err := client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error {
284        var balance int64
285        row, err := txn.ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"balance"})
286        if err != nil {
287            // This function will be called again if this is an IsAborted error.
288            return err
289        }
290        if err := row.Column(0, &balance); err != nil {
291            return err
292        }
293
294        if balance <= 10 {
295            return errors.New("insufficient funds in account")
296        }
297        balance -= 10
298        m := spanner.Update("Accounts", []string{"user", "balance"}, []interface{}{"alice", balance})
299        txn.BufferWrite([]*spanner.Mutation{m})
300
301        // The buffered mutation will be committed.  If the commit
302        // fails with an IsAborted error, this function will be called
303        // again.
304        return nil
305    })
306
307
308Structs
309
310Cloud Spanner STRUCT (aka STRUCT) values
311(https://cloud.google.com/spanner/docs/data-types#struct-type) can be
312represented by a Go struct value.
313
314A proto StructType is built from the field types and field tag information of
315the Go struct. If a field in the struct type definition has a
316"spanner:<field_name>" tag, then the value of the "spanner" key in the tag is
317used as the name for that field in the built StructType, otherwise the field
318name in the struct definition is used. To specify a field with an empty field
319name in a Cloud Spanner STRUCT type, use the `spanner:""` tag annotation against
320the corresponding field in the Go struct's type definition.
321
322A STRUCT value can contain STRUCT-typed and Array-of-STRUCT typed fields and
323these can be specified using named struct-typed and []struct-typed fields inside
324a Go struct. However, embedded struct fields are not allowed. Unexported struct
325fields are ignored.
326
327NULL STRUCT values in Cloud Spanner are typed. A nil pointer to a Go struct
328value can be used to specify a NULL STRUCT value of the corresponding
329StructType.  Nil and empty slices of a Go STRUCT type can be used to specify
330NULL and empty array values respectively of the corresponding StructType. A
331slice of pointers to a Go struct type can be used to specify an array of
332NULL-able STRUCT values.
333
334
335DML and Partitioned DML
336
337Spanner supports DML statements like INSERT, UPDATE and DELETE. Use
338ReadWriteTransaction.Update to run DML statements. It returns the number of rows
339affected. (You can call use ReadWriteTransaction.Query with a DML statement. The
340first call to Next on the resulting RowIterator will return iterator.Done, and
341the RowCount field of the iterator will hold the number of affected rows.)
342
343For large databases, it may be more efficient to partition the DML statement.
344Use client.PartitionedUpdate to run a DML statement in this way. Not all DML
345statements can be partitioned.
346
347
348Tracing
349
350This client has been instrumented to use OpenCensus tracing
351(http://opencensus.io). To enable tracing, see "Enabling Tracing for a Program"
352at https://godoc.org/go.opencensus.io/trace. OpenCensus tracing requires Go 1.8
353or higher.
354*/
355package spanner // import "cloud.google.com/go/spanner"
356