You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

669 lines
17 KiB

  1. /*
  2. Copyright 2017 Google LLC
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package spanner_test
  14. import (
  15. "context"
  16. "errors"
  17. "fmt"
  18. "sync"
  19. "time"
  20. "cloud.google.com/go/spanner"
  21. "google.golang.org/api/iterator"
  22. sppb "google.golang.org/genproto/googleapis/spanner/v1"
  23. )
  24. func ExampleNewClient() {
  25. ctx := context.Background()
  26. const myDB = "projects/my-project/instances/my-instance/database/my-db"
  27. client, err := spanner.NewClient(ctx, myDB)
  28. if err != nil {
  29. // TODO: Handle error.
  30. }
  31. _ = client // TODO: Use client.
  32. }
  33. const myDB = "projects/my-project/instances/my-instance/database/my-db"
  34. func ExampleNewClientWithConfig() {
  35. ctx := context.Background()
  36. const myDB = "projects/my-project/instances/my-instance/database/my-db"
  37. client, err := spanner.NewClientWithConfig(ctx, myDB, spanner.ClientConfig{
  38. NumChannels: 10,
  39. })
  40. if err != nil {
  41. // TODO: Handle error.
  42. }
  43. _ = client // TODO: Use client.
  44. client.Close() // Close client when done.
  45. }
  46. func ExampleClient_Single() {
  47. ctx := context.Background()
  48. client, err := spanner.NewClient(ctx, myDB)
  49. if err != nil {
  50. // TODO: Handle error.
  51. }
  52. iter := client.Single().Query(ctx, spanner.NewStatement("SELECT FirstName FROM Singers"))
  53. _ = iter // TODO: iterate using Next or Do.
  54. }
  55. func ExampleClient_ReadOnlyTransaction() {
  56. ctx := context.Background()
  57. client, err := spanner.NewClient(ctx, myDB)
  58. if err != nil {
  59. // TODO: Handle error.
  60. }
  61. t := client.ReadOnlyTransaction()
  62. defer t.Close()
  63. // TODO: Read with t using Read, ReadRow, ReadUsingIndex, or Query.
  64. }
  65. func ExampleClient_ReadWriteTransaction() {
  66. ctx := context.Background()
  67. client, err := spanner.NewClient(ctx, myDB)
  68. if err != nil {
  69. // TODO: Handle error.
  70. }
  71. _, err = client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error {
  72. var balance int64
  73. row, err := txn.ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"balance"})
  74. if err != nil {
  75. // This function will be called again if this is an
  76. // IsAborted error.
  77. return err
  78. }
  79. if err := row.Column(0, &balance); err != nil {
  80. return err
  81. }
  82. if balance <= 10 {
  83. return errors.New("insufficient funds in account")
  84. }
  85. balance -= 10
  86. m := spanner.Update("Accounts", []string{"user", "balance"}, []interface{}{"alice", balance})
  87. return txn.BufferWrite([]*spanner.Mutation{m})
  88. // The buffered mutation will be committed. If the commit
  89. // fails with an IsAborted error, this function will be called
  90. // again.
  91. })
  92. if err != nil {
  93. // TODO: Handle error.
  94. }
  95. }
  96. func ExampleUpdate() {
  97. ctx := context.Background()
  98. client, err := spanner.NewClient(ctx, myDB)
  99. if err != nil {
  100. // TODO: Handle error.
  101. }
  102. _, err = client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error {
  103. row, err := txn.ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"balance"})
  104. if err != nil {
  105. return err
  106. }
  107. var balance int64
  108. if err := row.Column(0, &balance); err != nil {
  109. return err
  110. }
  111. return txn.BufferWrite([]*spanner.Mutation{
  112. spanner.Update("Accounts", []string{"user", "balance"}, []interface{}{"alice", balance + 10}),
  113. })
  114. })
  115. if err != nil {
  116. // TODO: Handle error.
  117. }
  118. }
  119. // This example is the same as the one for Update, except for the use of UpdateMap.
  120. func ExampleUpdateMap() {
  121. ctx := context.Background()
  122. client, err := spanner.NewClient(ctx, myDB)
  123. if err != nil {
  124. // TODO: Handle error.
  125. }
  126. _, err = client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error {
  127. row, err := txn.ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"balance"})
  128. if err != nil {
  129. return err
  130. }
  131. var balance int64
  132. if err := row.Column(0, &balance); err != nil {
  133. return err
  134. }
  135. return txn.BufferWrite([]*spanner.Mutation{
  136. spanner.UpdateMap("Accounts", map[string]interface{}{
  137. "user": "alice",
  138. "balance": balance + 10,
  139. }),
  140. })
  141. })
  142. if err != nil {
  143. // TODO: Handle error.
  144. }
  145. }
  146. // This example is the same as the one for Update, except for the use of UpdateStruct.
  147. func ExampleUpdateStruct() {
  148. ctx := context.Background()
  149. client, err := spanner.NewClient(ctx, myDB)
  150. if err != nil {
  151. // TODO: Handle error.
  152. }
  153. type account struct {
  154. User string `spanner:"user"`
  155. Balance int64 `spanner:"balance"`
  156. }
  157. _, err = client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error {
  158. row, err := txn.ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"balance"})
  159. if err != nil {
  160. return err
  161. }
  162. var balance int64
  163. if err := row.Column(0, &balance); err != nil {
  164. return err
  165. }
  166. m, err := spanner.UpdateStruct("Accounts", account{
  167. User: "alice",
  168. Balance: balance + 10,
  169. })
  170. if err != nil {
  171. return err
  172. }
  173. return txn.BufferWrite([]*spanner.Mutation{m})
  174. })
  175. if err != nil {
  176. // TODO: Handle error.
  177. }
  178. }
  179. func ExampleClient_Apply() {
  180. ctx := context.Background()
  181. client, err := spanner.NewClient(ctx, myDB)
  182. if err != nil {
  183. // TODO: Handle error.
  184. }
  185. m := spanner.Update("Users", []string{"name", "email"}, []interface{}{"alice", "a@example.com"})
  186. _, err = client.Apply(ctx, []*spanner.Mutation{m})
  187. if err != nil {
  188. // TODO: Handle error.
  189. }
  190. }
  191. func ExampleInsert() {
  192. m := spanner.Insert("Users", []string{"name", "email"}, []interface{}{"alice", "a@example.com"})
  193. _ = m // TODO: use with Client.Apply or in a ReadWriteTransaction.
  194. }
  195. func ExampleInsertMap() {
  196. m := spanner.InsertMap("Users", map[string]interface{}{
  197. "name": "alice",
  198. "email": "a@example.com",
  199. })
  200. _ = m // TODO: use with Client.Apply or in a ReadWriteTransaction.
  201. }
  202. func ExampleInsertStruct() {
  203. type User struct {
  204. Name, Email string
  205. }
  206. u := User{Name: "alice", Email: "a@example.com"}
  207. m, err := spanner.InsertStruct("Users", u)
  208. if err != nil {
  209. // TODO: Handle error.
  210. }
  211. _ = m // TODO: use with Client.Apply or in a ReadWriteTransaction.
  212. }
  213. func ExampleDelete() {
  214. m := spanner.Delete("Users", spanner.Key{"alice"})
  215. _ = m // TODO: use with Client.Apply or in a ReadWriteTransaction.
  216. }
  217. func ExampleDelete_keyRange() {
  218. m := spanner.Delete("Users", spanner.KeyRange{
  219. Start: spanner.Key{"alice"},
  220. End: spanner.Key{"bob"},
  221. Kind: spanner.ClosedClosed,
  222. })
  223. _ = m // TODO: use with Client.Apply or in a ReadWriteTransaction.
  224. }
  225. func ExampleRowIterator_Next() {
  226. ctx := context.Background()
  227. client, err := spanner.NewClient(ctx, myDB)
  228. if err != nil {
  229. // TODO: Handle error.
  230. }
  231. iter := client.Single().Query(ctx, spanner.NewStatement("SELECT FirstName FROM Singers"))
  232. defer iter.Stop()
  233. for {
  234. row, err := iter.Next()
  235. if err == iterator.Done {
  236. break
  237. }
  238. if err != nil {
  239. // TODO: Handle error.
  240. }
  241. var firstName string
  242. if err := row.Column(0, &firstName); err != nil {
  243. // TODO: Handle error.
  244. }
  245. fmt.Println(firstName)
  246. }
  247. }
  248. func ExampleRowIterator_Do() {
  249. ctx := context.Background()
  250. client, err := spanner.NewClient(ctx, myDB)
  251. if err != nil {
  252. // TODO: Handle error.
  253. }
  254. iter := client.Single().Query(ctx, spanner.NewStatement("SELECT FirstName FROM Singers"))
  255. err = iter.Do(func(r *spanner.Row) error {
  256. var firstName string
  257. if err := r.Column(0, &firstName); err != nil {
  258. return err
  259. }
  260. fmt.Println(firstName)
  261. return nil
  262. })
  263. if err != nil {
  264. // TODO: Handle error.
  265. }
  266. }
  267. func ExampleRow_Size() {
  268. ctx := context.Background()
  269. client, err := spanner.NewClient(ctx, myDB)
  270. if err != nil {
  271. // TODO: Handle error.
  272. }
  273. row, err := client.Single().ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"name", "balance"})
  274. if err != nil {
  275. // TODO: Handle error.
  276. }
  277. fmt.Println(row.Size()) // size is 2
  278. }
  279. func ExampleRow_ColumnName() {
  280. ctx := context.Background()
  281. client, err := spanner.NewClient(ctx, myDB)
  282. if err != nil {
  283. // TODO: Handle error.
  284. }
  285. row, err := client.Single().ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"name", "balance"})
  286. if err != nil {
  287. // TODO: Handle error.
  288. }
  289. fmt.Println(row.ColumnName(1)) // prints "balance"
  290. }
  291. func ExampleRow_ColumnIndex() {
  292. ctx := context.Background()
  293. client, err := spanner.NewClient(ctx, myDB)
  294. if err != nil {
  295. // TODO: Handle error.
  296. }
  297. row, err := client.Single().ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"name", "balance"})
  298. if err != nil {
  299. // TODO: Handle error.
  300. }
  301. index, err := row.ColumnIndex("balance")
  302. if err != nil {
  303. // TODO: Handle error.
  304. }
  305. fmt.Println(index)
  306. }
  307. func ExampleRow_ColumnNames() {
  308. ctx := context.Background()
  309. client, err := spanner.NewClient(ctx, myDB)
  310. if err != nil {
  311. // TODO: Handle error.
  312. }
  313. row, err := client.Single().ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"name", "balance"})
  314. if err != nil {
  315. // TODO: Handle error.
  316. }
  317. fmt.Println(row.ColumnNames())
  318. }
  319. func ExampleRow_ColumnByName() {
  320. ctx := context.Background()
  321. client, err := spanner.NewClient(ctx, myDB)
  322. if err != nil {
  323. // TODO: Handle error.
  324. }
  325. row, err := client.Single().ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"name", "balance"})
  326. if err != nil {
  327. // TODO: Handle error.
  328. }
  329. var balance int64
  330. if err := row.ColumnByName("balance", &balance); err != nil {
  331. // TODO: Handle error.
  332. }
  333. fmt.Println(balance)
  334. }
  335. func ExampleRow_Columns() {
  336. ctx := context.Background()
  337. client, err := spanner.NewClient(ctx, myDB)
  338. if err != nil {
  339. // TODO: Handle error.
  340. }
  341. row, err := client.Single().ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"name", "balance"})
  342. if err != nil {
  343. // TODO: Handle error.
  344. }
  345. var name string
  346. var balance int64
  347. if err := row.Columns(&name, &balance); err != nil {
  348. // TODO: Handle error.
  349. }
  350. fmt.Println(name, balance)
  351. }
  352. func ExampleRow_ToStruct() {
  353. ctx := context.Background()
  354. client, err := spanner.NewClient(ctx, myDB)
  355. if err != nil {
  356. // TODO: Handle error.
  357. }
  358. row, err := client.Single().ReadRow(ctx, "Accounts", spanner.Key{"alice"}, []string{"name", "balance"})
  359. if err != nil {
  360. // TODO: Handle error.
  361. }
  362. type Account struct {
  363. Name string
  364. Balance int64
  365. }
  366. var acct Account
  367. if err := row.ToStruct(&acct); err != nil {
  368. // TODO: Handle error.
  369. }
  370. fmt.Println(acct)
  371. }
  372. func ExampleReadOnlyTransaction_Read() {
  373. ctx := context.Background()
  374. client, err := spanner.NewClient(ctx, myDB)
  375. if err != nil {
  376. // TODO: Handle error.
  377. }
  378. iter := client.Single().Read(ctx, "Users",
  379. spanner.KeySets(spanner.Key{"alice"}, spanner.Key{"bob"}),
  380. []string{"name", "email"})
  381. _ = iter // TODO: iterate using Next or Do.
  382. }
  383. func ExampleReadOnlyTransaction_ReadUsingIndex() {
  384. ctx := context.Background()
  385. client, err := spanner.NewClient(ctx, myDB)
  386. if err != nil {
  387. // TODO: Handle error.
  388. }
  389. iter := client.Single().ReadUsingIndex(ctx, "Users",
  390. "UsersByEmail",
  391. spanner.KeySets(spanner.Key{"a@example.com"}, spanner.Key{"b@example.com"}),
  392. []string{"name", "email"})
  393. _ = iter // TODO: iterate using Next or Do.
  394. }
  395. func ExampleReadOnlyTransaction_ReadWithOptions() {
  396. ctx := context.Background()
  397. client, err := spanner.NewClient(ctx, myDB)
  398. if err != nil {
  399. // TODO: Handle error.
  400. }
  401. // Use an index, and limit to 100 rows at most.
  402. iter := client.Single().ReadWithOptions(ctx, "Users",
  403. spanner.KeySets(spanner.Key{"a@example.com"}, spanner.Key{"b@example.com"}),
  404. []string{"name", "email"}, &spanner.ReadOptions{
  405. Index: "UsersByEmail",
  406. Limit: 100,
  407. })
  408. _ = iter // TODO: iterate using Next or Do.
  409. }
  410. func ExampleReadOnlyTransaction_ReadRow() {
  411. ctx := context.Background()
  412. client, err := spanner.NewClient(ctx, myDB)
  413. if err != nil {
  414. // TODO: Handle error.
  415. }
  416. row, err := client.Single().ReadRow(ctx, "Users", spanner.Key{"alice"},
  417. []string{"name", "email"})
  418. if err != nil {
  419. // TODO: Handle error.
  420. }
  421. _ = row // TODO: use row
  422. }
  423. func ExampleReadOnlyTransaction_Query() {
  424. ctx := context.Background()
  425. client, err := spanner.NewClient(ctx, myDB)
  426. if err != nil {
  427. // TODO: Handle error.
  428. }
  429. iter := client.Single().Query(ctx, spanner.NewStatement("SELECT FirstName FROM Singers"))
  430. _ = iter // TODO: iterate using Next or Do.
  431. }
  432. func ExampleNewStatement() {
  433. stmt := spanner.NewStatement("SELECT FirstName, LastName FROM SINGERS WHERE LastName >= @start")
  434. stmt.Params["start"] = "Dylan"
  435. // TODO: Use stmt in Query.
  436. }
  437. func ExampleNewStatement_structLiteral() {
  438. stmt := spanner.Statement{
  439. SQL: `SELECT FirstName, LastName FROM SINGERS WHERE LastName = ("Lea", "Martin")`,
  440. }
  441. _ = stmt // TODO: Use stmt in Query.
  442. }
  443. func ExampleStructParam() {
  444. stmt := spanner.Statement{
  445. SQL: "SELECT * FROM SINGERS WHERE (FirstName, LastName) = @singerinfo",
  446. Params: map[string]interface{}{
  447. "singerinfo": struct {
  448. FirstName string
  449. LastName string
  450. }{"Bob", "Dylan"},
  451. },
  452. }
  453. _ = stmt // TODO: Use stmt in Query.
  454. }
  455. func ExampleArrayOfStructParam() {
  456. stmt := spanner.Statement{
  457. SQL: "SELECT * FROM SINGERS WHERE (FirstName, LastName) IN UNNEST(@singerinfo)",
  458. Params: map[string]interface{}{
  459. "singerinfo": []struct {
  460. FirstName string
  461. LastName string
  462. }{
  463. {"Ringo", "Starr"},
  464. {"John", "Lennon"},
  465. },
  466. },
  467. }
  468. _ = stmt // TODO: Use stmt in Query.
  469. }
  470. func ExampleReadOnlyTransaction_Timestamp() {
  471. ctx := context.Background()
  472. client, err := spanner.NewClient(ctx, myDB)
  473. if err != nil {
  474. // TODO: Handle error.
  475. }
  476. txn := client.Single()
  477. row, err := txn.ReadRow(ctx, "Users", spanner.Key{"alice"},
  478. []string{"name", "email"})
  479. if err != nil {
  480. // TODO: Handle error.
  481. }
  482. readTimestamp, err := txn.Timestamp()
  483. if err != nil {
  484. // TODO: Handle error.
  485. }
  486. fmt.Println("read happened at", readTimestamp)
  487. _ = row // TODO: use row
  488. }
  489. func ExampleReadOnlyTransaction_WithTimestampBound() {
  490. ctx := context.Background()
  491. client, err := spanner.NewClient(ctx, myDB)
  492. if err != nil {
  493. // TODO: Handle error.
  494. }
  495. txn := client.Single().WithTimestampBound(spanner.MaxStaleness(30 * time.Second))
  496. row, err := txn.ReadRow(ctx, "Users", spanner.Key{"alice"}, []string{"name", "email"})
  497. if err != nil {
  498. // TODO: Handle error.
  499. }
  500. _ = row // TODO: use row
  501. readTimestamp, err := txn.Timestamp()
  502. if err != nil {
  503. // TODO: Handle error.
  504. }
  505. fmt.Println("read happened at", readTimestamp)
  506. }
  507. func ExampleGenericColumnValue_Decode() {
  508. // In real applications, rows can be retrieved by methods like client.Single().ReadRow().
  509. row, err := spanner.NewRow([]string{"intCol", "strCol"}, []interface{}{42, "my-text"})
  510. if err != nil {
  511. // TODO: Handle error.
  512. }
  513. for i := 0; i < row.Size(); i++ {
  514. var col spanner.GenericColumnValue
  515. if err := row.Column(i, &col); err != nil {
  516. // TODO: Handle error.
  517. }
  518. switch col.Type.Code {
  519. case sppb.TypeCode_INT64:
  520. var v int64
  521. if err := col.Decode(&v); err != nil {
  522. // TODO: Handle error.
  523. }
  524. fmt.Println("int", v)
  525. case sppb.TypeCode_STRING:
  526. var v string
  527. if err := col.Decode(&v); err != nil {
  528. // TODO: Handle error.
  529. }
  530. fmt.Println("string", v)
  531. }
  532. }
  533. // Output:
  534. // int 42
  535. // string my-text
  536. }
  537. func ExampleClient_BatchReadOnlyTransaction() {
  538. ctx := context.Background()
  539. var (
  540. client *spanner.Client
  541. txn *spanner.BatchReadOnlyTransaction
  542. err error
  543. )
  544. if client, err = spanner.NewClient(ctx, myDB); err != nil {
  545. // TODO: Handle error.
  546. }
  547. defer client.Close()
  548. if txn, err = client.BatchReadOnlyTransaction(ctx, spanner.StrongRead()); err != nil {
  549. // TODO: Handle error.
  550. }
  551. defer txn.Close()
  552. // Singer represents the elements in a row from the Singers table.
  553. type Singer struct {
  554. SingerID int64
  555. FirstName string
  556. LastName string
  557. SingerInfo []byte
  558. }
  559. stmt := spanner.Statement{SQL: "SELECT * FROM Singers;"}
  560. partitions, err := txn.PartitionQuery(ctx, stmt, spanner.PartitionOptions{})
  561. if err != nil {
  562. // TODO: Handle error.
  563. }
  564. // Note: here we use multiple goroutines, but you should use separate processes/machines.
  565. wg := sync.WaitGroup{}
  566. for i, p := range partitions {
  567. wg.Add(1)
  568. go func(i int, p *spanner.Partition) {
  569. defer wg.Done()
  570. iter := txn.Execute(ctx, p)
  571. defer iter.Stop()
  572. for {
  573. row, err := iter.Next()
  574. if err == iterator.Done {
  575. break
  576. } else if err != nil {
  577. // TODO: Handle error.
  578. }
  579. var s Singer
  580. if err := row.ToStruct(&s); err != nil {
  581. // TODO: Handle error.
  582. }
  583. _ = s // TODO: Process the row.
  584. }
  585. }(i, p)
  586. }
  587. wg.Wait()
  588. }
  589. func ExampleCommitTimestamp() {
  590. ctx := context.Background()
  591. client, err := spanner.NewClient(ctx, myDB)
  592. if err != nil {
  593. // TODO: Handle error.
  594. }
  595. type account struct {
  596. User string
  597. Creation spanner.NullTime // time.Time can also be used if column is NOT NULL
  598. }
  599. a := account{User: "Joe", Creation: spanner.NullTime{spanner.CommitTimestamp, true}}
  600. m, err := spanner.InsertStruct("Accounts", a)
  601. if err != nil {
  602. // TODO: Handle error.
  603. }
  604. _, err = client.Apply(ctx, []*spanner.Mutation{m}, spanner.ApplyAtLeastOnce())
  605. if err != nil {
  606. // TODO: Handle error.
  607. }
  608. if r, e := client.Single().ReadRow(ctx, "Accounts", spanner.Key{"Joe"}, []string{"User", "Creation"}); e != nil {
  609. // TODO: Handle error.
  610. } else {
  611. var got account
  612. if err := r.ToStruct(&got); err != nil {
  613. // TODO: Handle error.
  614. }
  615. _ = got // TODO: Process row.
  616. }
  617. }