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.
 
 
 

1926 lines
59 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
  14. import (
  15. "errors"
  16. "flag"
  17. "fmt"
  18. "log"
  19. "math"
  20. "os"
  21. "reflect"
  22. "strings"
  23. "sync"
  24. "testing"
  25. "time"
  26. "cloud.google.com/go/civil"
  27. "cloud.google.com/go/internal/testutil"
  28. database "cloud.google.com/go/spanner/admin/database/apiv1"
  29. "golang.org/x/net/context"
  30. "google.golang.org/api/iterator"
  31. "google.golang.org/api/option"
  32. "google.golang.org/grpc/codes"
  33. adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
  34. )
  35. var (
  36. // testProjectID specifies the project used for testing.
  37. // It can be changed by setting environment variable GCLOUD_TESTS_GOLANG_PROJECT_ID.
  38. testProjectID = testutil.ProjID()
  39. // testInstanceID specifies the Cloud Spanner instance used for testing.
  40. testInstanceID = "go-integration-test"
  41. // admin is a spanner.DatabaseAdminClient.
  42. admin *database.DatabaseAdminClient
  43. )
  44. var (
  45. singerDBStatements = []string{
  46. `CREATE TABLE Singers (
  47. SingerId INT64 NOT NULL,
  48. FirstName STRING(1024),
  49. LastName STRING(1024),
  50. SingerInfo BYTES(MAX)
  51. ) PRIMARY KEY (SingerId)`,
  52. `CREATE INDEX SingerByName ON Singers(FirstName, LastName)`,
  53. `CREATE TABLE Accounts (
  54. AccountId INT64 NOT NULL,
  55. Nickname STRING(100),
  56. Balance INT64 NOT NULL,
  57. ) PRIMARY KEY (AccountId)`,
  58. `CREATE INDEX AccountByNickname ON Accounts(Nickname) STORING (Balance)`,
  59. `CREATE TABLE Types (
  60. RowID INT64 NOT NULL,
  61. String STRING(MAX),
  62. StringArray ARRAY<STRING(MAX)>,
  63. Bytes BYTES(MAX),
  64. BytesArray ARRAY<BYTES(MAX)>,
  65. Int64a INT64,
  66. Int64Array ARRAY<INT64>,
  67. Bool BOOL,
  68. BoolArray ARRAY<BOOL>,
  69. Float64 FLOAT64,
  70. Float64Array ARRAY<FLOAT64>,
  71. Date DATE,
  72. DateArray ARRAY<DATE>,
  73. Timestamp TIMESTAMP,
  74. TimestampArray ARRAY<TIMESTAMP>,
  75. ) PRIMARY KEY (RowID)`,
  76. }
  77. readDBStatements = []string{
  78. `CREATE TABLE TestTable (
  79. Key STRING(MAX) NOT NULL,
  80. StringValue STRING(MAX)
  81. ) PRIMARY KEY (Key)`,
  82. `CREATE INDEX TestTableByValue ON TestTable(StringValue)`,
  83. `CREATE INDEX TestTableByValueDesc ON TestTable(StringValue DESC)`,
  84. }
  85. simpleDBStatements = []string{
  86. `CREATE TABLE test (
  87. a STRING(1024),
  88. b STRING(1024),
  89. ) PRIMARY KEY (a)`,
  90. }
  91. simpleDBTableColumns = []string{"a", "b"}
  92. ctsDBStatements = []string{
  93. `CREATE TABLE TestTable (
  94. Key STRING(MAX) NOT NULL,
  95. Ts TIMESTAMP OPTIONS (allow_commit_timestamp = true),
  96. ) PRIMARY KEY (Key)`,
  97. }
  98. )
  99. const (
  100. str1 = "alice"
  101. str2 = "a@example.com"
  102. )
  103. type testTableRow struct{ Key, StringValue string }
  104. func TestMain(m *testing.M) {
  105. initIntegrationTest()
  106. os.Exit(m.Run())
  107. }
  108. func initIntegrationTest() {
  109. flag.Parse() // needed for testing.Short()
  110. if testing.Short() {
  111. return
  112. }
  113. if testProjectID == "" {
  114. log.Print("Integration tests skipped: GCLOUD_TESTS_GOLANG_PROJECT_ID is missing")
  115. return
  116. }
  117. ctx := context.Background()
  118. ts := testutil.TokenSource(ctx, AdminScope, Scope)
  119. if ts == nil {
  120. log.Printf("Integration test skipped: cannot get service account credential from environment variable %v", "GCLOUD_TESTS_GOLANG_KEY")
  121. return
  122. }
  123. var err error
  124. // Create Admin client and Data client.
  125. admin, err = database.NewDatabaseAdminClient(ctx, option.WithTokenSource(ts), option.WithEndpoint(endpoint))
  126. if err != nil {
  127. log.Fatalf("cannot create admin client: %v", err)
  128. }
  129. }
  130. var (
  131. mu sync.Mutex
  132. count int
  133. now = time.Now()
  134. )
  135. // prepare initializes Cloud Spanner testing DB and clients.
  136. func prepare(ctx context.Context, t *testing.T, statements []string) (client *Client, dbPath string, tearDown func()) {
  137. if admin == nil {
  138. t.Skip("Integration tests skipped")
  139. }
  140. // Construct a unique test DB name.
  141. mu.Lock()
  142. dbName := fmt.Sprintf("gotest_%d_%d", now.UnixNano(), count)
  143. count++
  144. mu.Unlock()
  145. dbPath = fmt.Sprintf("projects/%v/instances/%v/databases/%v", testProjectID, testInstanceID, dbName)
  146. // Create database and tables.
  147. op, err := admin.CreateDatabase(ctx, &adminpb.CreateDatabaseRequest{
  148. Parent: fmt.Sprintf("projects/%v/instances/%v", testProjectID, testInstanceID),
  149. CreateStatement: "CREATE DATABASE " + dbName,
  150. ExtraStatements: statements,
  151. })
  152. if err != nil {
  153. t.Fatalf("cannot create testing DB %v: %v", dbPath, err)
  154. }
  155. if _, err := op.Wait(ctx); err != nil {
  156. t.Fatalf("cannot create testing DB %v: %v", dbPath, err)
  157. }
  158. client, err = NewClientWithConfig(ctx, dbPath, ClientConfig{
  159. SessionPoolConfig: SessionPoolConfig{WriteSessions: 0.2},
  160. }, option.WithTokenSource(testutil.TokenSource(ctx, Scope)), option.WithEndpoint(endpoint))
  161. if err != nil {
  162. t.Fatalf("cannot create data client on DB %v: %v", dbPath, err)
  163. }
  164. return client, dbPath, func() {
  165. client.Close()
  166. if err := admin.DropDatabase(ctx, &adminpb.DropDatabaseRequest{Database: dbPath}); err != nil {
  167. t.Logf("failed to drop database %s (error %v), might need a manual removal",
  168. dbPath, err)
  169. }
  170. }
  171. }
  172. // Test SingleUse transaction.
  173. func TestSingleUse(t *testing.T) {
  174. t.Parallel()
  175. ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
  176. defer cancel()
  177. // Set up testing environment.
  178. client, _, tearDown := prepare(ctx, t, singerDBStatements)
  179. defer tearDown()
  180. writes := []struct {
  181. row []interface{}
  182. ts time.Time
  183. }{
  184. {row: []interface{}{1, "Marc", "Foo"}},
  185. {row: []interface{}{2, "Tars", "Bar"}},
  186. {row: []interface{}{3, "Alpha", "Beta"}},
  187. {row: []interface{}{4, "Last", "End"}},
  188. }
  189. // Try to write four rows through the Apply API.
  190. for i, w := range writes {
  191. var err error
  192. m := InsertOrUpdate("Singers",
  193. []string{"SingerId", "FirstName", "LastName"},
  194. w.row)
  195. if writes[i].ts, err = client.Apply(ctx, []*Mutation{m}, ApplyAtLeastOnce()); err != nil {
  196. t.Fatal(err)
  197. }
  198. }
  199. // For testing timestamp bound staleness.
  200. <-time.After(time.Second)
  201. // Test reading rows with different timestamp bounds.
  202. for i, test := range []struct {
  203. want [][]interface{}
  204. tb TimestampBound
  205. checkTs func(time.Time) error
  206. }{
  207. {
  208. // strong
  209. [][]interface{}{{int64(1), "Marc", "Foo"}, {int64(3), "Alpha", "Beta"}, {int64(4), "Last", "End"}},
  210. StrongRead(),
  211. func(ts time.Time) error {
  212. // writes[3] is the last write, all subsequent strong read should have a timestamp larger than that.
  213. if ts.Before(writes[3].ts) {
  214. return fmt.Errorf("read got timestamp %v, want it to be no later than %v", ts, writes[3].ts)
  215. }
  216. return nil
  217. },
  218. },
  219. {
  220. // min_read_timestamp
  221. [][]interface{}{{int64(1), "Marc", "Foo"}, {int64(3), "Alpha", "Beta"}, {int64(4), "Last", "End"}},
  222. MinReadTimestamp(writes[3].ts),
  223. func(ts time.Time) error {
  224. if ts.Before(writes[3].ts) {
  225. return fmt.Errorf("read got timestamp %v, want it to be no later than %v", ts, writes[3].ts)
  226. }
  227. return nil
  228. },
  229. },
  230. {
  231. // max_staleness
  232. [][]interface{}{{int64(1), "Marc", "Foo"}, {int64(3), "Alpha", "Beta"}, {int64(4), "Last", "End"}},
  233. MaxStaleness(time.Second),
  234. func(ts time.Time) error {
  235. if ts.Before(writes[3].ts) {
  236. return fmt.Errorf("read got timestamp %v, want it to be no later than %v", ts, writes[3].ts)
  237. }
  238. return nil
  239. },
  240. },
  241. {
  242. // read_timestamp
  243. [][]interface{}{{int64(1), "Marc", "Foo"}, {int64(3), "Alpha", "Beta"}},
  244. ReadTimestamp(writes[2].ts),
  245. func(ts time.Time) error {
  246. if ts != writes[2].ts {
  247. return fmt.Errorf("read got timestamp %v, want %v", ts, writes[2].ts)
  248. }
  249. return nil
  250. },
  251. },
  252. {
  253. // exact_staleness
  254. nil,
  255. // Specify a staleness which should be already before this test because
  256. // context timeout is set to be 10s.
  257. ExactStaleness(11 * time.Second),
  258. func(ts time.Time) error {
  259. if ts.After(writes[0].ts) {
  260. return fmt.Errorf("read got timestamp %v, want it to be no earlier than %v", ts, writes[0].ts)
  261. }
  262. return nil
  263. },
  264. },
  265. } {
  266. // SingleUse.Query
  267. su := client.Single().WithTimestampBound(test.tb)
  268. got, err := readAll(su.Query(
  269. ctx,
  270. Statement{
  271. "SELECT SingerId, FirstName, LastName FROM Singers WHERE SingerId IN (@id1, @id3, @id4)",
  272. map[string]interface{}{"id1": int64(1), "id3": int64(3), "id4": int64(4)},
  273. }))
  274. if err != nil {
  275. t.Errorf("%d: SingleUse.Query returns error %v, want nil", i, err)
  276. }
  277. if !testEqual(got, test.want) {
  278. t.Errorf("%d: got unexpected result from SingleUse.Query: %v, want %v", i, got, test.want)
  279. }
  280. rts, err := su.Timestamp()
  281. if err != nil {
  282. t.Errorf("%d: SingleUse.Query doesn't return a timestamp, error: %v", i, err)
  283. }
  284. if err := test.checkTs(rts); err != nil {
  285. t.Errorf("%d: SingleUse.Query doesn't return expected timestamp: %v", i, err)
  286. }
  287. // SingleUse.Read
  288. su = client.Single().WithTimestampBound(test.tb)
  289. got, err = readAll(su.Read(ctx, "Singers", KeySets(Key{1}, Key{3}, Key{4}), []string{"SingerId", "FirstName", "LastName"}))
  290. if err != nil {
  291. t.Errorf("%d: SingleUse.Read returns error %v, want nil", i, err)
  292. }
  293. if !testEqual(got, test.want) {
  294. t.Errorf("%d: got unexpected result from SingleUse.Read: %v, want %v", i, got, test.want)
  295. }
  296. rts, err = su.Timestamp()
  297. if err != nil {
  298. t.Errorf("%d: SingleUse.Read doesn't return a timestamp, error: %v", i, err)
  299. }
  300. if err := test.checkTs(rts); err != nil {
  301. t.Errorf("%d: SingleUse.Read doesn't return expected timestamp: %v", i, err)
  302. }
  303. // SingleUse.ReadRow
  304. got = nil
  305. for _, k := range []Key{{1}, {3}, {4}} {
  306. su = client.Single().WithTimestampBound(test.tb)
  307. r, err := su.ReadRow(ctx, "Singers", k, []string{"SingerId", "FirstName", "LastName"})
  308. if err != nil {
  309. continue
  310. }
  311. v, err := rowToValues(r)
  312. if err != nil {
  313. continue
  314. }
  315. got = append(got, v)
  316. rts, err = su.Timestamp()
  317. if err != nil {
  318. t.Errorf("%d: SingleUse.ReadRow(%v) doesn't return a timestamp, error: %v", i, k, err)
  319. }
  320. if err := test.checkTs(rts); err != nil {
  321. t.Errorf("%d: SingleUse.ReadRow(%v) doesn't return expected timestamp: %v", i, k, err)
  322. }
  323. }
  324. if !testEqual(got, test.want) {
  325. t.Errorf("%d: got unexpected results from SingleUse.ReadRow: %v, want %v", i, got, test.want)
  326. }
  327. // SingleUse.ReadUsingIndex
  328. su = client.Single().WithTimestampBound(test.tb)
  329. got, err = readAll(su.ReadUsingIndex(ctx, "Singers", "SingerByName", KeySets(Key{"Marc", "Foo"}, Key{"Alpha", "Beta"}, Key{"Last", "End"}), []string{"SingerId", "FirstName", "LastName"}))
  330. if err != nil {
  331. t.Errorf("%d: SingleUse.ReadUsingIndex returns error %v, want nil", i, err)
  332. }
  333. // The results from ReadUsingIndex is sorted by the index rather than primary key.
  334. if len(got) != len(test.want) {
  335. t.Errorf("%d: got unexpected result from SingleUse.ReadUsingIndex: %v, want %v", i, got, test.want)
  336. }
  337. for j, g := range got {
  338. if j > 0 {
  339. prev := got[j-1][1].(string) + got[j-1][2].(string)
  340. curr := got[j][1].(string) + got[j][2].(string)
  341. if strings.Compare(prev, curr) > 0 {
  342. t.Errorf("%d: SingleUse.ReadUsingIndex fails to order rows by index keys, %v should be after %v", i, got[j-1], got[j])
  343. }
  344. }
  345. found := false
  346. for _, w := range test.want {
  347. if testEqual(g, w) {
  348. found = true
  349. }
  350. }
  351. if !found {
  352. t.Errorf("%d: got unexpected result from SingleUse.ReadUsingIndex: %v, want %v", i, got, test.want)
  353. break
  354. }
  355. }
  356. rts, err = su.Timestamp()
  357. if err != nil {
  358. t.Errorf("%d: SingleUse.ReadUsingIndex doesn't return a timestamp, error: %v", i, err)
  359. }
  360. if err := test.checkTs(rts); err != nil {
  361. t.Errorf("%d: SingleUse.ReadUsingIndex doesn't return expected timestamp: %v", i, err)
  362. }
  363. }
  364. // Reading with limit.
  365. su := client.Single()
  366. const limit = 1
  367. gotRows, err := readAll(su.ReadWithOptions(ctx, "Singers", KeySets(Key{1}, Key{3}, Key{4}),
  368. []string{"SingerId", "FirstName", "LastName"}, &ReadOptions{Limit: limit}))
  369. if err != nil {
  370. t.Errorf("SingleUse.ReadWithOptions returns error %v, want nil", err)
  371. }
  372. if got, want := len(gotRows), limit; got != want {
  373. t.Errorf("got %d, want %d", got, want)
  374. }
  375. }
  376. // Test ReadOnlyTransaction. The testsuite is mostly like SingleUse, except it
  377. // also tests for a single timestamp across multiple reads.
  378. func TestReadOnlyTransaction(t *testing.T) {
  379. t.Parallel()
  380. ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
  381. defer cancel()
  382. // Set up testing environment.
  383. client, _, tearDown := prepare(ctx, t, singerDBStatements)
  384. defer tearDown()
  385. writes := []struct {
  386. row []interface{}
  387. ts time.Time
  388. }{
  389. {row: []interface{}{1, "Marc", "Foo"}},
  390. {row: []interface{}{2, "Tars", "Bar"}},
  391. {row: []interface{}{3, "Alpha", "Beta"}},
  392. {row: []interface{}{4, "Last", "End"}},
  393. }
  394. // Try to write four rows through the Apply API.
  395. for i, w := range writes {
  396. var err error
  397. m := InsertOrUpdate("Singers",
  398. []string{"SingerId", "FirstName", "LastName"},
  399. w.row)
  400. if writes[i].ts, err = client.Apply(ctx, []*Mutation{m}, ApplyAtLeastOnce()); err != nil {
  401. t.Fatal(err)
  402. }
  403. }
  404. // For testing timestamp bound staleness.
  405. <-time.After(time.Second)
  406. // Test reading rows with different timestamp bounds.
  407. for i, test := range []struct {
  408. want [][]interface{}
  409. tb TimestampBound
  410. checkTs func(time.Time) error
  411. }{
  412. // Note: min_read_timestamp and max_staleness are not supported by ReadOnlyTransaction. See
  413. // API document for more details.
  414. {
  415. // strong
  416. [][]interface{}{{int64(1), "Marc", "Foo"}, {int64(3), "Alpha", "Beta"}, {int64(4), "Last", "End"}},
  417. StrongRead(),
  418. func(ts time.Time) error {
  419. if ts.Before(writes[3].ts) {
  420. return fmt.Errorf("read got timestamp %v, want it to be no later than %v", ts, writes[3].ts)
  421. }
  422. return nil
  423. },
  424. },
  425. {
  426. // read_timestamp
  427. [][]interface{}{{int64(1), "Marc", "Foo"}, {int64(3), "Alpha", "Beta"}},
  428. ReadTimestamp(writes[2].ts),
  429. func(ts time.Time) error {
  430. if ts != writes[2].ts {
  431. return fmt.Errorf("read got timestamp %v, expect %v", ts, writes[2].ts)
  432. }
  433. return nil
  434. },
  435. },
  436. {
  437. // exact_staleness
  438. nil,
  439. // Specify a staleness which should be already before this test because
  440. // context timeout is set to be 10s.
  441. ExactStaleness(11 * time.Second),
  442. func(ts time.Time) error {
  443. if ts.After(writes[0].ts) {
  444. return fmt.Errorf("read got timestamp %v, want it to be no earlier than %v", ts, writes[0].ts)
  445. }
  446. return nil
  447. },
  448. },
  449. } {
  450. // ReadOnlyTransaction.Query
  451. ro := client.ReadOnlyTransaction().WithTimestampBound(test.tb)
  452. got, err := readAll(ro.Query(
  453. ctx,
  454. Statement{
  455. "SELECT SingerId, FirstName, LastName FROM Singers WHERE SingerId IN (@id1, @id3, @id4)",
  456. map[string]interface{}{"id1": int64(1), "id3": int64(3), "id4": int64(4)},
  457. }))
  458. if err != nil {
  459. t.Errorf("%d: ReadOnlyTransaction.Query returns error %v, want nil", i, err)
  460. }
  461. if !testEqual(got, test.want) {
  462. t.Errorf("%d: got unexpected result from ReadOnlyTransaction.Query: %v, want %v", i, got, test.want)
  463. }
  464. rts, err := ro.Timestamp()
  465. if err != nil {
  466. t.Errorf("%d: ReadOnlyTransaction.Query doesn't return a timestamp, error: %v", i, err)
  467. }
  468. if err := test.checkTs(rts); err != nil {
  469. t.Errorf("%d: ReadOnlyTransaction.Query doesn't return expected timestamp: %v", i, err)
  470. }
  471. roTs := rts
  472. // ReadOnlyTransaction.Read
  473. got, err = readAll(ro.Read(ctx, "Singers", KeySets(Key{1}, Key{3}, Key{4}), []string{"SingerId", "FirstName", "LastName"}))
  474. if err != nil {
  475. t.Errorf("%d: ReadOnlyTransaction.Read returns error %v, want nil", i, err)
  476. }
  477. if !testEqual(got, test.want) {
  478. t.Errorf("%d: got unexpected result from ReadOnlyTransaction.Read: %v, want %v", i, got, test.want)
  479. }
  480. rts, err = ro.Timestamp()
  481. if err != nil {
  482. t.Errorf("%d: ReadOnlyTransaction.Read doesn't return a timestamp, error: %v", i, err)
  483. }
  484. if err := test.checkTs(rts); err != nil {
  485. t.Errorf("%d: ReadOnlyTransaction.Read doesn't return expected timestamp: %v", i, err)
  486. }
  487. if roTs != rts {
  488. t.Errorf("%d: got two read timestamps: %v, %v, want ReadOnlyTransaction to return always the same read timestamp", i, roTs, rts)
  489. }
  490. // ReadOnlyTransaction.ReadRow
  491. got = nil
  492. for _, k := range []Key{{1}, {3}, {4}} {
  493. r, err := ro.ReadRow(ctx, "Singers", k, []string{"SingerId", "FirstName", "LastName"})
  494. if err != nil {
  495. continue
  496. }
  497. v, err := rowToValues(r)
  498. if err != nil {
  499. continue
  500. }
  501. got = append(got, v)
  502. rts, err = ro.Timestamp()
  503. if err != nil {
  504. t.Errorf("%d: ReadOnlyTransaction.ReadRow(%v) doesn't return a timestamp, error: %v", i, k, err)
  505. }
  506. if err := test.checkTs(rts); err != nil {
  507. t.Errorf("%d: ReadOnlyTransaction.ReadRow(%v) doesn't return expected timestamp: %v", i, k, err)
  508. }
  509. if roTs != rts {
  510. t.Errorf("%d: got two read timestamps: %v, %v, want ReadOnlyTransaction to return always the same read timestamp", i, roTs, rts)
  511. }
  512. }
  513. if !testEqual(got, test.want) {
  514. t.Errorf("%d: got unexpected results from ReadOnlyTransaction.ReadRow: %v, want %v", i, got, test.want)
  515. }
  516. // SingleUse.ReadUsingIndex
  517. got, err = readAll(ro.ReadUsingIndex(ctx, "Singers", "SingerByName", KeySets(Key{"Marc", "Foo"}, Key{"Alpha", "Beta"}, Key{"Last", "End"}), []string{"SingerId", "FirstName", "LastName"}))
  518. if err != nil {
  519. t.Errorf("%d: ReadOnlyTransaction.ReadUsingIndex returns error %v, want nil", i, err)
  520. }
  521. // The results from ReadUsingIndex is sorted by the index rather than primary key.
  522. if len(got) != len(test.want) {
  523. t.Errorf("%d: got unexpected result from ReadOnlyTransaction.ReadUsingIndex: %v, want %v", i, got, test.want)
  524. }
  525. for j, g := range got {
  526. if j > 0 {
  527. prev := got[j-1][1].(string) + got[j-1][2].(string)
  528. curr := got[j][1].(string) + got[j][2].(string)
  529. if strings.Compare(prev, curr) > 0 {
  530. t.Errorf("%d: ReadOnlyTransaction.ReadUsingIndex fails to order rows by index keys, %v should be after %v", i, got[j-1], got[j])
  531. }
  532. }
  533. found := false
  534. for _, w := range test.want {
  535. if testEqual(g, w) {
  536. found = true
  537. }
  538. }
  539. if !found {
  540. t.Errorf("%d: got unexpected result from ReadOnlyTransaction.ReadUsingIndex: %v, want %v", i, got, test.want)
  541. break
  542. }
  543. }
  544. rts, err = ro.Timestamp()
  545. if err != nil {
  546. t.Errorf("%d: ReadOnlyTransaction.ReadUsingIndex doesn't return a timestamp, error: %v", i, err)
  547. }
  548. if err := test.checkTs(rts); err != nil {
  549. t.Errorf("%d: ReadOnlyTransaction.ReadUsingIndex doesn't return expected timestamp: %v", i, err)
  550. }
  551. if roTs != rts {
  552. t.Errorf("%d: got two read timestamps: %v, %v, want ReadOnlyTransaction to return always the same read timestamp", i, roTs, rts)
  553. }
  554. ro.Close()
  555. }
  556. }
  557. // Test ReadOnlyTransaction with different timestamp bound when there's an update at the same time.
  558. func TestUpdateDuringRead(t *testing.T) {
  559. t.Parallel()
  560. ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
  561. defer cancel()
  562. client, _, tearDown := prepare(ctx, t, singerDBStatements)
  563. defer tearDown()
  564. for i, tb := range []TimestampBound{
  565. StrongRead(),
  566. ReadTimestamp(time.Now().Add(-time.Minute * 30)), // version GC is 1 hour
  567. ExactStaleness(time.Minute * 30),
  568. } {
  569. ro := client.ReadOnlyTransaction().WithTimestampBound(tb)
  570. _, err := ro.ReadRow(ctx, "Singers", Key{i}, []string{"SingerId"})
  571. if ErrCode(err) != codes.NotFound {
  572. t.Errorf("%d: ReadOnlyTransaction.ReadRow before write returns error: %v, want NotFound", i, err)
  573. }
  574. m := InsertOrUpdate("Singers", []string{"SingerId"}, []interface{}{i})
  575. if _, err := client.Apply(ctx, []*Mutation{m}, ApplyAtLeastOnce()); err != nil {
  576. t.Fatal(err)
  577. }
  578. _, err = ro.ReadRow(ctx, "Singers", Key{i}, []string{"SingerId"})
  579. if ErrCode(err) != codes.NotFound {
  580. t.Errorf("%d: ReadOnlyTransaction.ReadRow after write returns error: %v, want NotFound", i, err)
  581. }
  582. }
  583. }
  584. // Test ReadWriteTransaction.
  585. func TestReadWriteTransaction(t *testing.T) {
  586. t.Parallel()
  587. // Give a longer deadline because of transaction backoffs.
  588. ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
  589. defer cancel()
  590. client, _, tearDown := prepare(ctx, t, singerDBStatements)
  591. defer tearDown()
  592. // Set up two accounts
  593. accounts := []*Mutation{
  594. Insert("Accounts", []string{"AccountId", "Nickname", "Balance"}, []interface{}{int64(1), "Foo", int64(50)}),
  595. Insert("Accounts", []string{"AccountId", "Nickname", "Balance"}, []interface{}{int64(2), "Bar", int64(1)}),
  596. }
  597. if _, err := client.Apply(ctx, accounts, ApplyAtLeastOnce()); err != nil {
  598. t.Fatal(err)
  599. }
  600. wg := sync.WaitGroup{}
  601. readBalance := func(iter *RowIterator) (int64, error) {
  602. defer iter.Stop()
  603. var bal int64
  604. for {
  605. row, err := iter.Next()
  606. if err == iterator.Done {
  607. return bal, nil
  608. }
  609. if err != nil {
  610. return 0, err
  611. }
  612. if err := row.Column(0, &bal); err != nil {
  613. return 0, err
  614. }
  615. }
  616. }
  617. for i := 0; i < 20; i++ {
  618. wg.Add(1)
  619. go func(iter int) {
  620. defer wg.Done()
  621. _, err := client.ReadWriteTransaction(ctx, func(ctx context.Context, tx *ReadWriteTransaction) error {
  622. // Query Foo's balance and Bar's balance.
  623. bf, e := readBalance(tx.Query(ctx,
  624. Statement{"SELECT Balance FROM Accounts WHERE AccountId = @id", map[string]interface{}{"id": int64(1)}}))
  625. if e != nil {
  626. return e
  627. }
  628. bb, e := readBalance(tx.Read(ctx, "Accounts", KeySets(Key{int64(2)}), []string{"Balance"}))
  629. if e != nil {
  630. return e
  631. }
  632. if bf <= 0 {
  633. return nil
  634. }
  635. bf--
  636. bb++
  637. return tx.BufferWrite([]*Mutation{
  638. Update("Accounts", []string{"AccountId", "Balance"}, []interface{}{int64(1), bf}),
  639. Update("Accounts", []string{"AccountId", "Balance"}, []interface{}{int64(2), bb}),
  640. })
  641. })
  642. if err != nil {
  643. t.Fatalf("%d: failed to execute transaction: %v", iter, err)
  644. }
  645. }(i)
  646. }
  647. // Because of context timeout, all goroutines will eventually return.
  648. wg.Wait()
  649. _, err := client.ReadWriteTransaction(ctx, func(ctx context.Context, tx *ReadWriteTransaction) error {
  650. var bf, bb int64
  651. r, e := tx.ReadRow(ctx, "Accounts", Key{int64(1)}, []string{"Balance"})
  652. if e != nil {
  653. return e
  654. }
  655. if ce := r.Column(0, &bf); ce != nil {
  656. return ce
  657. }
  658. bb, e = readBalance(tx.ReadUsingIndex(ctx, "Accounts", "AccountByNickname", KeySets(Key{"Bar"}), []string{"Balance"}))
  659. if e != nil {
  660. return e
  661. }
  662. if bf != 30 || bb != 21 {
  663. t.Errorf("Foo's balance is now %v and Bar's balance is now %v, want %v and %v", bf, bb, 30, 21)
  664. }
  665. return nil
  666. })
  667. if err != nil {
  668. t.Errorf("failed to check balances: %v", err)
  669. }
  670. }
  671. const (
  672. testTable = "TestTable"
  673. testTableIndex = "TestTableByValue"
  674. )
  675. var testTableColumns = []string{"Key", "StringValue"}
  676. func TestReads(t *testing.T) {
  677. t.Parallel()
  678. ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
  679. defer cancel()
  680. // Set up testing environment.
  681. client, _, tearDown := prepare(ctx, t, readDBStatements)
  682. defer tearDown()
  683. // Includes k0..k14. Strings sort lexically, eg "k1" < "k10" < "k2".
  684. var ms []*Mutation
  685. for i := 0; i < 15; i++ {
  686. ms = append(ms, InsertOrUpdate(testTable,
  687. testTableColumns,
  688. []interface{}{fmt.Sprintf("k%d", i), fmt.Sprintf("v%d", i)}))
  689. }
  690. // Don't use ApplyAtLeastOnce, so we can test the other code path.
  691. if _, err := client.Apply(ctx, ms); err != nil {
  692. t.Fatal(err)
  693. }
  694. // Empty read.
  695. rows, err := readAllTestTable(client.Single().Read(ctx, testTable,
  696. KeyRange{Start: Key{"k99"}, End: Key{"z"}}, testTableColumns))
  697. if err != nil {
  698. t.Fatal(err)
  699. }
  700. if got, want := len(rows), 0; got != want {
  701. t.Errorf("got %d, want %d", got, want)
  702. }
  703. // Index empty read.
  704. rows, err = readAllTestTable(client.Single().ReadUsingIndex(ctx, testTable, testTableIndex,
  705. KeyRange{Start: Key{"v99"}, End: Key{"z"}}, testTableColumns))
  706. if err != nil {
  707. t.Fatal(err)
  708. }
  709. if got, want := len(rows), 0; got != want {
  710. t.Errorf("got %d, want %d", got, want)
  711. }
  712. // Point read.
  713. row, err := client.Single().ReadRow(ctx, testTable, Key{"k1"}, testTableColumns)
  714. if err != nil {
  715. t.Fatal(err)
  716. }
  717. var got testTableRow
  718. if err := row.ToStruct(&got); err != nil {
  719. t.Fatal(err)
  720. }
  721. if want := (testTableRow{"k1", "v1"}); got != want {
  722. t.Errorf("got %v, want %v", got, want)
  723. }
  724. // Point read not found.
  725. _, err = client.Single().ReadRow(ctx, testTable, Key{"k999"}, testTableColumns)
  726. if ErrCode(err) != codes.NotFound {
  727. t.Fatalf("got %v, want NotFound", err)
  728. }
  729. // No index point read not found, because Go does not have ReadRowUsingIndex.
  730. rangeReads(ctx, t, client)
  731. indexRangeReads(ctx, t, client)
  732. }
  733. func rangeReads(ctx context.Context, t *testing.T, client *Client) {
  734. checkRange := func(ks KeySet, wantNums ...int) {
  735. if msg, ok := compareRows(client.Single().Read(ctx, testTable, ks, testTableColumns), wantNums); !ok {
  736. t.Errorf("key set %+v: %s", ks, msg)
  737. }
  738. }
  739. checkRange(Key{"k1"}, 1)
  740. checkRange(KeyRange{Key{"k3"}, Key{"k5"}, ClosedOpen}, 3, 4)
  741. checkRange(KeyRange{Key{"k3"}, Key{"k5"}, ClosedClosed}, 3, 4, 5)
  742. checkRange(KeyRange{Key{"k3"}, Key{"k5"}, OpenClosed}, 4, 5)
  743. checkRange(KeyRange{Key{"k3"}, Key{"k5"}, OpenOpen}, 4)
  744. // Partial key specification.
  745. checkRange(KeyRange{Key{"k7"}, Key{}, ClosedClosed}, 7, 8, 9)
  746. checkRange(KeyRange{Key{"k7"}, Key{}, OpenClosed}, 8, 9)
  747. checkRange(KeyRange{Key{}, Key{"k11"}, ClosedOpen}, 0, 1, 10)
  748. checkRange(KeyRange{Key{}, Key{"k11"}, ClosedClosed}, 0, 1, 10, 11)
  749. // The following produce empty ranges.
  750. // TODO(jba): Consider a multi-part key to illustrate partial key behavior.
  751. // checkRange(KeyRange{Key{"k7"}, Key{}, ClosedOpen})
  752. // checkRange(KeyRange{Key{"k7"}, Key{}, OpenOpen})
  753. // checkRange(KeyRange{Key{}, Key{"k11"}, OpenOpen})
  754. // checkRange(KeyRange{Key{}, Key{"k11"}, OpenClosed})
  755. // Prefix is component-wise, not string prefix.
  756. checkRange(Key{"k1"}.AsPrefix(), 1)
  757. checkRange(KeyRange{Key{"k1"}, Key{"k2"}, ClosedOpen}, 1, 10, 11, 12, 13, 14)
  758. checkRange(AllKeys(), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
  759. }
  760. func indexRangeReads(ctx context.Context, t *testing.T, client *Client) {
  761. checkRange := func(ks KeySet, wantNums ...int) {
  762. if msg, ok := compareRows(client.Single().ReadUsingIndex(ctx, testTable, testTableIndex, ks, testTableColumns),
  763. wantNums); !ok {
  764. t.Errorf("key set %+v: %s", ks, msg)
  765. }
  766. }
  767. checkRange(Key{"v1"}, 1)
  768. checkRange(KeyRange{Key{"v3"}, Key{"v5"}, ClosedOpen}, 3, 4)
  769. checkRange(KeyRange{Key{"v3"}, Key{"v5"}, ClosedClosed}, 3, 4, 5)
  770. checkRange(KeyRange{Key{"v3"}, Key{"v5"}, OpenClosed}, 4, 5)
  771. checkRange(KeyRange{Key{"v3"}, Key{"v5"}, OpenOpen}, 4)
  772. // // Partial key specification.
  773. checkRange(KeyRange{Key{"v7"}, Key{}, ClosedClosed}, 7, 8, 9)
  774. checkRange(KeyRange{Key{"v7"}, Key{}, OpenClosed}, 8, 9)
  775. checkRange(KeyRange{Key{}, Key{"v11"}, ClosedOpen}, 0, 1, 10)
  776. checkRange(KeyRange{Key{}, Key{"v11"}, ClosedClosed}, 0, 1, 10, 11)
  777. // // The following produce empty ranges.
  778. // checkRange(KeyRange{Key{"v7"}, Key{}, ClosedOpen})
  779. // checkRange(KeyRange{Key{"v7"}, Key{}, OpenOpen})
  780. // checkRange(KeyRange{Key{}, Key{"v11"}, OpenOpen})
  781. // checkRange(KeyRange{Key{}, Key{"v11"}, OpenClosed})
  782. // // Prefix is component-wise, not string prefix.
  783. checkRange(Key{"v1"}.AsPrefix(), 1)
  784. checkRange(KeyRange{Key{"v1"}, Key{"v2"}, ClosedOpen}, 1, 10, 11, 12, 13, 14)
  785. checkRange(AllKeys(), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
  786. // Read from an index with DESC ordering.
  787. wantNums := []int{14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
  788. if msg, ok := compareRows(client.Single().ReadUsingIndex(ctx, testTable, "TestTableByValueDesc", AllKeys(), testTableColumns),
  789. wantNums); !ok {
  790. t.Errorf("desc: %s", msg)
  791. }
  792. }
  793. func compareRows(iter *RowIterator, wantNums []int) (string, bool) {
  794. rows, err := readAllTestTable(iter)
  795. if err != nil {
  796. return err.Error(), false
  797. }
  798. want := map[string]string{}
  799. for _, n := range wantNums {
  800. want[fmt.Sprintf("k%d", n)] = fmt.Sprintf("v%d", n)
  801. }
  802. got := map[string]string{}
  803. for _, r := range rows {
  804. got[r.Key] = r.StringValue
  805. }
  806. if !testEqual(got, want) {
  807. return fmt.Sprintf("got %v, want %v", got, want), false
  808. }
  809. return "", true
  810. }
  811. func TestEarlyTimestamp(t *testing.T) {
  812. t.Parallel()
  813. // Test that we can get the timestamp from a read-only transaction as
  814. // soon as we have read at least one row.
  815. ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
  816. defer cancel()
  817. // Set up testing environment.
  818. client, _, tearDown := prepare(ctx, t, readDBStatements)
  819. defer tearDown()
  820. var ms []*Mutation
  821. for i := 0; i < 3; i++ {
  822. ms = append(ms, InsertOrUpdate(testTable,
  823. testTableColumns,
  824. []interface{}{fmt.Sprintf("k%d", i), fmt.Sprintf("v%d", i)}))
  825. }
  826. if _, err := client.Apply(ctx, ms, ApplyAtLeastOnce()); err != nil {
  827. t.Fatal(err)
  828. }
  829. txn := client.Single()
  830. iter := txn.Read(ctx, testTable, AllKeys(), testTableColumns)
  831. defer iter.Stop()
  832. // In single-use transaction, we should get an error before reading anything.
  833. if _, err := txn.Timestamp(); err == nil {
  834. t.Error("wanted error, got nil")
  835. }
  836. // After reading one row, the timestamp should be available.
  837. _, err := iter.Next()
  838. if err != nil {
  839. t.Fatal(err)
  840. }
  841. if _, err := txn.Timestamp(); err != nil {
  842. t.Errorf("got %v, want nil", err)
  843. }
  844. txn = client.ReadOnlyTransaction()
  845. defer txn.Close()
  846. iter = txn.Read(ctx, testTable, AllKeys(), testTableColumns)
  847. defer iter.Stop()
  848. // In an ordinary read-only transaction, the timestamp should be
  849. // available immediately.
  850. if _, err := txn.Timestamp(); err != nil {
  851. t.Errorf("got %v, want nil", err)
  852. }
  853. }
  854. func TestNestedTransaction(t *testing.T) {
  855. t.Parallel()
  856. // You cannot use a transaction from inside a read-write transaction.
  857. ctx := context.Background()
  858. client, _, tearDown := prepare(ctx, t, singerDBStatements)
  859. defer tearDown()
  860. _, err := client.ReadWriteTransaction(ctx, func(ctx context.Context, tx *ReadWriteTransaction) error {
  861. _, err := client.ReadWriteTransaction(ctx,
  862. func(context.Context, *ReadWriteTransaction) error { return nil })
  863. if ErrCode(err) != codes.FailedPrecondition {
  864. t.Fatalf("got %v, want FailedPrecondition", err)
  865. }
  866. _, err = client.Single().ReadRow(ctx, "Singers", Key{1}, []string{"SingerId"})
  867. if ErrCode(err) != codes.FailedPrecondition {
  868. t.Fatalf("got %v, want FailedPrecondition", err)
  869. }
  870. rot := client.ReadOnlyTransaction()
  871. defer rot.Close()
  872. _, err = rot.ReadRow(ctx, "Singers", Key{1}, []string{"SingerId"})
  873. if ErrCode(err) != codes.FailedPrecondition {
  874. t.Fatalf("got %v, want FailedPrecondition", err)
  875. }
  876. return nil
  877. })
  878. if err != nil {
  879. t.Fatal(err)
  880. }
  881. }
  882. // Test client recovery on database recreation.
  883. func TestDbRemovalRecovery(t *testing.T) {
  884. t.Parallel()
  885. ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
  886. defer cancel()
  887. client, dbPath, tearDown := prepare(ctx, t, singerDBStatements)
  888. defer tearDown()
  889. // Drop the testing database.
  890. if err := admin.DropDatabase(ctx, &adminpb.DropDatabaseRequest{Database: dbPath}); err != nil {
  891. t.Fatalf("failed to drop testing database %v: %v", dbPath, err)
  892. }
  893. // Now, send the query.
  894. iter := client.Single().Query(ctx, Statement{SQL: "SELECT SingerId FROM Singers"})
  895. defer iter.Stop()
  896. if _, err := iter.Next(); err == nil {
  897. t.Errorf("client sends query to removed database successfully, want it to fail")
  898. }
  899. // Recreate database and table.
  900. dbName := dbPath[strings.LastIndex(dbPath, "/")+1:]
  901. op, err := admin.CreateDatabase(ctx, &adminpb.CreateDatabaseRequest{
  902. Parent: fmt.Sprintf("projects/%v/instances/%v", testProjectID, testInstanceID),
  903. CreateStatement: "CREATE DATABASE " + dbName,
  904. ExtraStatements: []string{
  905. `CREATE TABLE Singers (
  906. SingerId INT64 NOT NULL,
  907. FirstName STRING(1024),
  908. LastName STRING(1024),
  909. SingerInfo BYTES(MAX)
  910. ) PRIMARY KEY (SingerId)`,
  911. },
  912. })
  913. if err != nil {
  914. t.Fatalf("cannot recreate testing DB %v: %v", dbPath, err)
  915. }
  916. if _, err := op.Wait(ctx); err != nil {
  917. t.Fatalf("cannot recreate testing DB %v: %v", dbPath, err)
  918. }
  919. // Now, send the query again.
  920. iter = client.Single().Query(ctx, Statement{SQL: "SELECT SingerId FROM Singers"})
  921. defer iter.Stop()
  922. _, err = iter.Next()
  923. if err != nil && err != iterator.Done {
  924. t.Errorf("failed to send query to database %v: %v", dbPath, err)
  925. }
  926. }
  927. // Test encoding/decoding non-struct Cloud Spanner types.
  928. func TestBasicTypes(t *testing.T) {
  929. t.Parallel()
  930. ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
  931. defer cancel()
  932. client, _, tearDown := prepare(ctx, t, singerDBStatements)
  933. defer tearDown()
  934. t1, _ := time.Parse(time.RFC3339Nano, "2016-11-15T15:04:05.999999999Z")
  935. // Boundaries
  936. t2, _ := time.Parse(time.RFC3339Nano, "0001-01-01T00:00:00.000000000Z")
  937. t3, _ := time.Parse(time.RFC3339Nano, "9999-12-31T23:59:59.999999999Z")
  938. d1, _ := civil.ParseDate("2016-11-15")
  939. // Boundaries
  940. d2, _ := civil.ParseDate("0001-01-01")
  941. d3, _ := civil.ParseDate("9999-12-31")
  942. tests := []struct {
  943. col string
  944. val interface{}
  945. want interface{}
  946. }{
  947. {col: "String", val: ""},
  948. {col: "String", val: "", want: NullString{"", true}},
  949. {col: "String", val: "foo"},
  950. {col: "String", val: "foo", want: NullString{"foo", true}},
  951. {col: "String", val: NullString{"bar", true}, want: "bar"},
  952. {col: "String", val: NullString{"bar", false}, want: NullString{"", false}},
  953. {col: "StringArray", val: []string(nil), want: []NullString(nil)},
  954. {col: "StringArray", val: []string{}, want: []NullString{}},
  955. {col: "StringArray", val: []string{"foo", "bar"}, want: []NullString{{"foo", true}, {"bar", true}}},
  956. {col: "StringArray", val: []NullString(nil)},
  957. {col: "StringArray", val: []NullString{}},
  958. {col: "StringArray", val: []NullString{{"foo", true}, {}}},
  959. {col: "Bytes", val: []byte{}},
  960. {col: "Bytes", val: []byte{1, 2, 3}},
  961. {col: "Bytes", val: []byte(nil)},
  962. {col: "BytesArray", val: [][]byte(nil)},
  963. {col: "BytesArray", val: [][]byte{}},
  964. {col: "BytesArray", val: [][]byte{{1}, {2, 3}}},
  965. {col: "Int64a", val: 0, want: int64(0)},
  966. {col: "Int64a", val: -1, want: int64(-1)},
  967. {col: "Int64a", val: 2, want: int64(2)},
  968. {col: "Int64a", val: int64(3)},
  969. {col: "Int64a", val: 4, want: NullInt64{4, true}},
  970. {col: "Int64a", val: NullInt64{5, true}, want: int64(5)},
  971. {col: "Int64a", val: NullInt64{6, true}, want: int64(6)},
  972. {col: "Int64a", val: NullInt64{7, false}, want: NullInt64{0, false}},
  973. {col: "Int64Array", val: []int(nil), want: []NullInt64(nil)},
  974. {col: "Int64Array", val: []int{}, want: []NullInt64{}},
  975. {col: "Int64Array", val: []int{1, 2}, want: []NullInt64{{1, true}, {2, true}}},
  976. {col: "Int64Array", val: []int64(nil), want: []NullInt64(nil)},
  977. {col: "Int64Array", val: []int64{}, want: []NullInt64{}},
  978. {col: "Int64Array", val: []int64{1, 2}, want: []NullInt64{{1, true}, {2, true}}},
  979. {col: "Int64Array", val: []NullInt64(nil)},
  980. {col: "Int64Array", val: []NullInt64{}},
  981. {col: "Int64Array", val: []NullInt64{{1, true}, {}}},
  982. {col: "Bool", val: false},
  983. {col: "Bool", val: true},
  984. {col: "Bool", val: false, want: NullBool{false, true}},
  985. {col: "Bool", val: true, want: NullBool{true, true}},
  986. {col: "Bool", val: NullBool{true, true}},
  987. {col: "Bool", val: NullBool{false, false}},
  988. {col: "BoolArray", val: []bool(nil), want: []NullBool(nil)},
  989. {col: "BoolArray", val: []bool{}, want: []NullBool{}},
  990. {col: "BoolArray", val: []bool{true, false}, want: []NullBool{{true, true}, {false, true}}},
  991. {col: "BoolArray", val: []NullBool(nil)},
  992. {col: "BoolArray", val: []NullBool{}},
  993. {col: "BoolArray", val: []NullBool{{false, true}, {true, true}, {}}},
  994. {col: "Float64", val: 0.0},
  995. {col: "Float64", val: 3.14},
  996. {col: "Float64", val: math.NaN()},
  997. {col: "Float64", val: math.Inf(1)},
  998. {col: "Float64", val: math.Inf(-1)},
  999. {col: "Float64", val: 2.78, want: NullFloat64{2.78, true}},
  1000. {col: "Float64", val: NullFloat64{2.71, true}, want: 2.71},
  1001. {col: "Float64", val: NullFloat64{1.41, true}, want: NullFloat64{1.41, true}},
  1002. {col: "Float64", val: NullFloat64{0, false}},
  1003. {col: "Float64Array", val: []float64(nil), want: []NullFloat64(nil)},
  1004. {col: "Float64Array", val: []float64{}, want: []NullFloat64{}},
  1005. {col: "Float64Array", val: []float64{2.72, 3.14, math.Inf(1)}, want: []NullFloat64{{2.72, true}, {3.14, true}, {math.Inf(1), true}}},
  1006. {col: "Float64Array", val: []NullFloat64(nil)},
  1007. {col: "Float64Array", val: []NullFloat64{}},
  1008. {col: "Float64Array", val: []NullFloat64{{2.72, true}, {math.Inf(1), true}, {}}},
  1009. {col: "Date", val: d1},
  1010. {col: "Date", val: d1, want: NullDate{d1, true}},
  1011. {col: "Date", val: NullDate{d1, true}},
  1012. {col: "Date", val: NullDate{d1, true}, want: d1},
  1013. {col: "Date", val: NullDate{civil.Date{}, false}},
  1014. {col: "DateArray", val: []civil.Date(nil), want: []NullDate(nil)},
  1015. {col: "DateArray", val: []civil.Date{}, want: []NullDate{}},
  1016. {col: "DateArray", val: []civil.Date{d1, d2, d3}, want: []NullDate{{d1, true}, {d2, true}, {d3, true}}},
  1017. {col: "Timestamp", val: t1},
  1018. {col: "Timestamp", val: t1, want: NullTime{t1, true}},
  1019. {col: "Timestamp", val: NullTime{t1, true}},
  1020. {col: "Timestamp", val: NullTime{t1, true}, want: t1},
  1021. {col: "Timestamp", val: NullTime{}},
  1022. {col: "TimestampArray", val: []time.Time(nil), want: []NullTime(nil)},
  1023. {col: "TimestampArray", val: []time.Time{}, want: []NullTime{}},
  1024. {col: "TimestampArray", val: []time.Time{t1, t2, t3}, want: []NullTime{{t1, true}, {t2, true}, {t3, true}}},
  1025. }
  1026. // Write rows into table first.
  1027. var muts []*Mutation
  1028. for i, test := range tests {
  1029. muts = append(muts, InsertOrUpdate("Types", []string{"RowID", test.col}, []interface{}{i, test.val}))
  1030. }
  1031. if _, err := client.Apply(ctx, muts, ApplyAtLeastOnce()); err != nil {
  1032. t.Fatal(err)
  1033. }
  1034. for i, test := range tests {
  1035. row, err := client.Single().ReadRow(ctx, "Types", []interface{}{i}, []string{test.col})
  1036. if err != nil {
  1037. t.Fatalf("Unable to fetch row %v: %v", i, err)
  1038. }
  1039. // Create new instance of type of test.want.
  1040. want := test.want
  1041. if want == nil {
  1042. want = test.val
  1043. }
  1044. gotp := reflect.New(reflect.TypeOf(want))
  1045. if err := row.Column(0, gotp.Interface()); err != nil {
  1046. t.Errorf("%d: col:%v val:%#v, %v", i, test.col, test.val, err)
  1047. continue
  1048. }
  1049. got := reflect.Indirect(gotp).Interface()
  1050. // One of the test cases is checking NaN handling. Given
  1051. // NaN!=NaN, we can't use reflect to test for it.
  1052. if isNaN(got) && isNaN(want) {
  1053. continue
  1054. }
  1055. // Check non-NaN cases.
  1056. if !testEqual(got, want) {
  1057. t.Errorf("%d: col:%v val:%#v, got %#v, want %#v", i, test.col, test.val, got, want)
  1058. continue
  1059. }
  1060. }
  1061. }
  1062. // Test decoding Cloud Spanner STRUCT type.
  1063. func TestStructTypes(t *testing.T) {
  1064. t.Parallel()
  1065. ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
  1066. defer cancel()
  1067. client, _, tearDown := prepare(ctx, t, singerDBStatements)
  1068. defer tearDown()
  1069. tests := []struct {
  1070. q Statement
  1071. want func(r *Row) error
  1072. }{
  1073. {
  1074. q: Statement{SQL: `SELECT ARRAY(SELECT STRUCT(1, 2))`},
  1075. want: func(r *Row) error {
  1076. // Test STRUCT ARRAY decoding to []NullRow.
  1077. var rows []NullRow
  1078. if err := r.Column(0, &rows); err != nil {
  1079. return err
  1080. }
  1081. if len(rows) != 1 {
  1082. return fmt.Errorf("len(rows) = %d; want 1", len(rows))
  1083. }
  1084. if !rows[0].Valid {
  1085. return fmt.Errorf("rows[0] is NULL")
  1086. }
  1087. var i, j int64
  1088. if err := rows[0].Row.Columns(&i, &j); err != nil {
  1089. return err
  1090. }
  1091. if i != 1 || j != 2 {
  1092. return fmt.Errorf("got (%d,%d), want (1,2)", i, j)
  1093. }
  1094. return nil
  1095. },
  1096. },
  1097. {
  1098. q: Statement{SQL: `SELECT ARRAY(SELECT STRUCT(1 as foo, 2 as bar)) as col1`},
  1099. want: func(r *Row) error {
  1100. // Test Row.ToStruct.
  1101. s := struct {
  1102. Col1 []*struct {
  1103. Foo int64 `spanner:"foo"`
  1104. Bar int64 `spanner:"bar"`
  1105. } `spanner:"col1"`
  1106. }{}
  1107. if err := r.ToStruct(&s); err != nil {
  1108. return err
  1109. }
  1110. want := struct {
  1111. Col1 []*struct {
  1112. Foo int64 `spanner:"foo"`
  1113. Bar int64 `spanner:"bar"`
  1114. } `spanner:"col1"`
  1115. }{
  1116. Col1: []*struct {
  1117. Foo int64 `spanner:"foo"`
  1118. Bar int64 `spanner:"bar"`
  1119. }{
  1120. {
  1121. Foo: 1,
  1122. Bar: 2,
  1123. },
  1124. },
  1125. }
  1126. if !testEqual(want, s) {
  1127. return fmt.Errorf("unexpected decoding result: %v, want %v", s, want)
  1128. }
  1129. return nil
  1130. },
  1131. },
  1132. }
  1133. for i, test := range tests {
  1134. iter := client.Single().Query(ctx, test.q)
  1135. defer iter.Stop()
  1136. row, err := iter.Next()
  1137. if err != nil {
  1138. t.Errorf("%d: %v", i, err)
  1139. continue
  1140. }
  1141. if err := test.want(row); err != nil {
  1142. t.Errorf("%d: %v", i, err)
  1143. continue
  1144. }
  1145. }
  1146. }
  1147. func TestStructParametersUnsupported(t *testing.T) {
  1148. t.Parallel()
  1149. ctx := context.Background()
  1150. client, _, tearDown := prepare(ctx, t, nil)
  1151. defer tearDown()
  1152. for _, test := range []struct {
  1153. param interface{}
  1154. wantCode codes.Code
  1155. wantMsgPart string
  1156. }{
  1157. {
  1158. struct {
  1159. Field int
  1160. }{10},
  1161. codes.Unimplemented,
  1162. "Unsupported query shape: " +
  1163. "A struct value cannot be returned as a column value. " +
  1164. "Rewrite the query to flatten the struct fields in the result.",
  1165. },
  1166. {
  1167. []struct {
  1168. Field int
  1169. }{{10}, {20}},
  1170. codes.Unimplemented,
  1171. "Unsupported query shape: " +
  1172. "This query can return a null-valued array of struct, " +
  1173. "which is not supported by Spanner.",
  1174. },
  1175. } {
  1176. iter := client.Single().Query(ctx, Statement{
  1177. SQL: "SELECT @p",
  1178. Params: map[string]interface{}{"p": test.param},
  1179. })
  1180. _, err := iter.Next()
  1181. iter.Stop()
  1182. if msg, ok := matchError(err, test.wantCode, test.wantMsgPart); !ok {
  1183. t.Fatal(msg)
  1184. }
  1185. }
  1186. }
  1187. // Test queries of the form "SELECT expr".
  1188. func TestQueryExpressions(t *testing.T) {
  1189. t.Parallel()
  1190. ctx := context.Background()
  1191. client, _, tearDown := prepare(ctx, t, nil)
  1192. defer tearDown()
  1193. newRow := func(vals []interface{}) *Row {
  1194. row, err := NewRow(make([]string, len(vals)), vals)
  1195. if err != nil {
  1196. t.Fatal(err)
  1197. }
  1198. return row
  1199. }
  1200. tests := []struct {
  1201. expr string
  1202. want interface{}
  1203. }{
  1204. {"1", int64(1)},
  1205. {"[1, 2, 3]", []NullInt64{{1, true}, {2, true}, {3, true}}},
  1206. {"[1, NULL, 3]", []NullInt64{{1, true}, {0, false}, {3, true}}},
  1207. {"IEEE_DIVIDE(1, 0)", math.Inf(1)},
  1208. {"IEEE_DIVIDE(-1, 0)", math.Inf(-1)},
  1209. {"IEEE_DIVIDE(0, 0)", math.NaN()},
  1210. // TODO(jba): add IEEE_DIVIDE(0, 0) to the following array when we have a better equality predicate.
  1211. {"[IEEE_DIVIDE(1, 0), IEEE_DIVIDE(-1, 0)]", []NullFloat64{{math.Inf(1), true}, {math.Inf(-1), true}}},
  1212. {"ARRAY(SELECT AS STRUCT * FROM (SELECT 'a', 1) WHERE 0 = 1)", []NullRow{}},
  1213. {"ARRAY(SELECT STRUCT(1, 2))", []NullRow{{Row: *newRow([]interface{}{1, 2}), Valid: true}}},
  1214. }
  1215. for _, test := range tests {
  1216. iter := client.Single().Query(ctx, Statement{SQL: "SELECT " + test.expr})
  1217. defer iter.Stop()
  1218. row, err := iter.Next()
  1219. if err != nil {
  1220. t.Errorf("%q: %v", test.expr, err)
  1221. continue
  1222. }
  1223. // Create new instance of type of test.want.
  1224. gotp := reflect.New(reflect.TypeOf(test.want))
  1225. if err := row.Column(0, gotp.Interface()); err != nil {
  1226. t.Errorf("%q: Column returned error %v", test.expr, err)
  1227. continue
  1228. }
  1229. got := reflect.Indirect(gotp).Interface()
  1230. // TODO(jba): remove isNaN special case when we have a better equality predicate.
  1231. if isNaN(got) && isNaN(test.want) {
  1232. continue
  1233. }
  1234. if !testEqual(got, test.want) {
  1235. t.Errorf("%q\n got %#v\nwant %#v", test.expr, got, test.want)
  1236. }
  1237. }
  1238. }
  1239. func TestQueryStats(t *testing.T) {
  1240. t.Parallel()
  1241. ctx := context.Background()
  1242. client, _, tearDown := prepare(ctx, t, singerDBStatements)
  1243. defer tearDown()
  1244. accounts := []*Mutation{
  1245. Insert("Accounts", []string{"AccountId", "Nickname", "Balance"}, []interface{}{int64(1), "Foo", int64(50)}),
  1246. Insert("Accounts", []string{"AccountId", "Nickname", "Balance"}, []interface{}{int64(2), "Bar", int64(1)}),
  1247. }
  1248. if _, err := client.Apply(ctx, accounts, ApplyAtLeastOnce()); err != nil {
  1249. t.Fatal(err)
  1250. }
  1251. const sql = "SELECT Balance FROM Accounts"
  1252. qp, err := client.Single().AnalyzeQuery(ctx, Statement{sql, nil})
  1253. if err != nil {
  1254. t.Fatal(err)
  1255. }
  1256. if len(qp.PlanNodes) == 0 {
  1257. t.Error("got zero plan nodes, expected at least one")
  1258. }
  1259. iter := client.Single().QueryWithStats(ctx, Statement{sql, nil})
  1260. defer iter.Stop()
  1261. for {
  1262. _, err := iter.Next()
  1263. if err == iterator.Done {
  1264. break
  1265. }
  1266. if err != nil {
  1267. t.Fatal(err)
  1268. }
  1269. }
  1270. if iter.QueryPlan == nil {
  1271. t.Error("got nil QueryPlan, expected one")
  1272. }
  1273. if iter.QueryStats == nil {
  1274. t.Error("got nil QueryStats, expected some")
  1275. }
  1276. }
  1277. func isNaN(x interface{}) bool {
  1278. f, ok := x.(float64)
  1279. if !ok {
  1280. return false
  1281. }
  1282. return math.IsNaN(f)
  1283. }
  1284. func TestInvalidDatabase(t *testing.T) {
  1285. t.Parallel()
  1286. if testing.Short() {
  1287. t.Skip("Integration tests skipped in short mode")
  1288. }
  1289. if testProjectID == "" {
  1290. t.Skip("Integration tests skipped: GCLOUD_TESTS_GOLANG_PROJECT_ID is missing")
  1291. }
  1292. ctx := context.Background()
  1293. ts := testutil.TokenSource(ctx, Scope)
  1294. if ts == nil {
  1295. t.Skip("Integration test skipped: cannot get service account credential from environment variable GCLOUD_TESTS_GOLANG_KEY")
  1296. }
  1297. db := fmt.Sprintf("projects/%v/instances/%v/databases/invalid", testProjectID, testInstanceID)
  1298. c, err := NewClient(ctx, db, option.WithTokenSource(ts))
  1299. // Client creation should succeed even if the database is invalid.
  1300. if err != nil {
  1301. t.Fatal(err)
  1302. }
  1303. _, err = c.Single().ReadRow(ctx, "TestTable", Key{1}, []string{"col1"})
  1304. if msg, ok := matchError(err, codes.NotFound, ""); !ok {
  1305. t.Fatal(msg)
  1306. }
  1307. }
  1308. func TestReadErrors(t *testing.T) {
  1309. t.Parallel()
  1310. ctx := context.Background()
  1311. client, _, tearDown := prepare(ctx, t, readDBStatements)
  1312. defer tearDown()
  1313. // Read over invalid table fails
  1314. _, err := client.Single().ReadRow(ctx, "badTable", Key{1}, []string{"StringValue"})
  1315. if msg, ok := matchError(err, codes.NotFound, "badTable"); !ok {
  1316. t.Error(msg)
  1317. }
  1318. // Read over invalid column fails
  1319. _, err = client.Single().ReadRow(ctx, "TestTable", Key{1}, []string{"badcol"})
  1320. if msg, ok := matchError(err, codes.NotFound, "badcol"); !ok {
  1321. t.Error(msg)
  1322. }
  1323. // Invalid query fails
  1324. iter := client.Single().Query(ctx, Statement{SQL: "SELECT Apples AND Oranges"})
  1325. defer iter.Stop()
  1326. _, err = iter.Next()
  1327. if msg, ok := matchError(err, codes.InvalidArgument, "unrecognized name"); !ok {
  1328. t.Error(msg)
  1329. }
  1330. // Read should fail on cancellation.
  1331. cctx, cancel := context.WithCancel(ctx)
  1332. cancel()
  1333. _, err = client.Single().ReadRow(cctx, "TestTable", Key{1}, []string{"StringValue"})
  1334. if msg, ok := matchError(err, codes.Canceled, ""); !ok {
  1335. t.Error(msg)
  1336. }
  1337. // Read should fail if deadline exceeded.
  1338. dctx, _ := context.WithTimeout(ctx, time.Nanosecond)
  1339. <-dctx.Done()
  1340. _, err = client.Single().ReadRow(dctx, "TestTable", Key{1}, []string{"StringValue"})
  1341. if msg, ok := matchError(err, codes.DeadlineExceeded, ""); !ok {
  1342. t.Error(msg)
  1343. }
  1344. }
  1345. func matchError(got error, wantCode codes.Code, wantMsgPart string) (string, bool) {
  1346. if ErrCode(got) != wantCode || !strings.Contains(strings.ToLower(ErrDesc(got)), strings.ToLower(wantMsgPart)) {
  1347. return fmt.Sprintf("got error <%v>\n"+`want <code = %q, "...%s...">`, got, wantCode, wantMsgPart), false
  1348. }
  1349. return "", true
  1350. }
  1351. func rowToValues(r *Row) ([]interface{}, error) {
  1352. var x int64
  1353. var y, z string
  1354. if err := r.Column(0, &x); err != nil {
  1355. return nil, err
  1356. }
  1357. if err := r.Column(1, &y); err != nil {
  1358. return nil, err
  1359. }
  1360. if err := r.Column(2, &z); err != nil {
  1361. return nil, err
  1362. }
  1363. return []interface{}{x, y, z}, nil
  1364. }
  1365. func readAll(iter *RowIterator) ([][]interface{}, error) {
  1366. defer iter.Stop()
  1367. var vals [][]interface{}
  1368. for {
  1369. row, err := iter.Next()
  1370. if err == iterator.Done {
  1371. return vals, nil
  1372. }
  1373. if err != nil {
  1374. return nil, err
  1375. }
  1376. v, err := rowToValues(row)
  1377. if err != nil {
  1378. return nil, err
  1379. }
  1380. vals = append(vals, v)
  1381. }
  1382. }
  1383. func readAllTestTable(iter *RowIterator) ([]testTableRow, error) {
  1384. defer iter.Stop()
  1385. var vals []testTableRow
  1386. for {
  1387. row, err := iter.Next()
  1388. if err == iterator.Done {
  1389. return vals, nil
  1390. }
  1391. if err != nil {
  1392. return nil, err
  1393. }
  1394. var ttr testTableRow
  1395. if err := row.ToStruct(&ttr); err != nil {
  1396. return nil, err
  1397. }
  1398. vals = append(vals, ttr)
  1399. }
  1400. }
  1401. // Test TransactionRunner. Test that transactions are aborted and retried as expected.
  1402. func TestTransactionRunner(t *testing.T) {
  1403. t.Parallel()
  1404. ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
  1405. defer cancel()
  1406. client, _, tearDown := prepare(ctx, t, singerDBStatements)
  1407. defer tearDown()
  1408. // Test 1: User error should abort the transaction.
  1409. _, _ = client.ReadWriteTransaction(ctx, func(ctx context.Context, tx *ReadWriteTransaction) error {
  1410. tx.BufferWrite([]*Mutation{
  1411. Insert("Accounts", []string{"AccountId", "Nickname", "Balance"}, []interface{}{int64(1), "Foo", int64(50)})})
  1412. return errors.New("user error")
  1413. })
  1414. // Empty read.
  1415. rows, err := readAllTestTable(client.Single().Read(ctx, "Accounts", Key{1}, []string{"AccountId", "Nickname", "Balance"}))
  1416. if err != nil {
  1417. t.Fatal(err)
  1418. }
  1419. if got, want := len(rows), 0; got != want {
  1420. t.Errorf("Empty read, got %d, want %d.", got, want)
  1421. }
  1422. // Test 2: Expect abort and retry.
  1423. // We run two ReadWriteTransactions concurrently and make txn1 abort txn2 by committing writes to the column txn2 have read,
  1424. // and expect the following read to abort and txn2 retries.
  1425. // Set up two accounts
  1426. accounts := []*Mutation{
  1427. Insert("Accounts", []string{"AccountId", "Balance"}, []interface{}{int64(1), int64(0)}),
  1428. Insert("Accounts", []string{"AccountId", "Balance"}, []interface{}{int64(2), int64(1)}),
  1429. }
  1430. if _, err := client.Apply(ctx, accounts, ApplyAtLeastOnce()); err != nil {
  1431. t.Fatal(err)
  1432. }
  1433. var (
  1434. cTxn1Start = make(chan struct{})
  1435. cTxn1Commit = make(chan struct{})
  1436. cTxn2Start = make(chan struct{})
  1437. wg sync.WaitGroup
  1438. )
  1439. // read balance, check error if we don't expect abort.
  1440. readBalance := func(tx interface {
  1441. ReadRow(ctx context.Context, table string, key Key, columns []string) (*Row, error)
  1442. }, key int64, expectAbort bool) (int64, error) {
  1443. var b int64
  1444. r, e := tx.ReadRow(ctx, "Accounts", Key{int64(key)}, []string{"Balance"})
  1445. if e != nil {
  1446. if expectAbort && !isAbortErr(e) {
  1447. t.Errorf("ReadRow got %v, want Abort error.", e)
  1448. }
  1449. return b, e
  1450. }
  1451. if ce := r.Column(0, &b); ce != nil {
  1452. return b, ce
  1453. }
  1454. return b, nil
  1455. }
  1456. wg.Add(2)
  1457. // Txn 1
  1458. go func() {
  1459. defer wg.Done()
  1460. var once sync.Once
  1461. _, e := client.ReadWriteTransaction(ctx, func(ctx context.Context, tx *ReadWriteTransaction) error {
  1462. b, e := readBalance(tx, 1, false)
  1463. if e != nil {
  1464. return e
  1465. }
  1466. // txn 1 can abort, in that case we skip closing the channel on retry.
  1467. once.Do(func() { close(cTxn1Start) })
  1468. e = tx.BufferWrite([]*Mutation{
  1469. Update("Accounts", []string{"AccountId", "Balance"}, []interface{}{int64(1), int64(b + 1)})})
  1470. if e != nil {
  1471. return e
  1472. }
  1473. // Wait for second transaction.
  1474. <-cTxn2Start
  1475. return nil
  1476. })
  1477. close(cTxn1Commit)
  1478. if e != nil {
  1479. t.Errorf("Transaction 1 commit, got %v, want nil.", e)
  1480. }
  1481. }()
  1482. // Txn 2
  1483. go func() {
  1484. // Wait until txn 1 starts.
  1485. <-cTxn1Start
  1486. defer wg.Done()
  1487. var (
  1488. once sync.Once
  1489. b1 int64
  1490. b2 int64
  1491. e error
  1492. )
  1493. _, e = client.ReadWriteTransaction(ctx, func(ctx context.Context, tx *ReadWriteTransaction) error {
  1494. if b1, e = readBalance(tx, 1, false); e != nil {
  1495. return e
  1496. }
  1497. // Skip closing channel on retry.
  1498. once.Do(func() { close(cTxn2Start) })
  1499. // Wait until txn 1 successfully commits.
  1500. <-cTxn1Commit
  1501. // Txn1 has committed and written a balance to the account.
  1502. // Now this transaction (txn2) reads and re-writes the balance.
  1503. // The first time through, it will abort because it overlaps with txn1.
  1504. // Then it will retry after txn1 commits, and succeed.
  1505. if b2, e = readBalance(tx, 2, true); e != nil {
  1506. return e
  1507. }
  1508. return tx.BufferWrite([]*Mutation{
  1509. Update("Accounts", []string{"AccountId", "Balance"}, []interface{}{int64(2), int64(b1 + b2)})})
  1510. })
  1511. if e != nil {
  1512. t.Errorf("Transaction 2 commit, got %v, want nil.", e)
  1513. }
  1514. }()
  1515. wg.Wait()
  1516. // Check that both transactions' effects are visible.
  1517. for i := int64(1); i <= int64(2); i++ {
  1518. if b, e := readBalance(client.Single(), i, false); e != nil {
  1519. t.Fatalf("ReadBalance for key %d error %v.", i, e)
  1520. } else if b != i {
  1521. t.Errorf("Balance for key %d, got %d, want %d.", i, b, i)
  1522. }
  1523. }
  1524. }
  1525. // createClient creates Cloud Spanner data client.
  1526. func createClient(ctx context.Context, dbPath string) (client *Client, err error) {
  1527. client, err = NewClientWithConfig(ctx, dbPath, ClientConfig{
  1528. SessionPoolConfig: SessionPoolConfig{WriteSessions: 0.2},
  1529. }, option.WithTokenSource(testutil.TokenSource(ctx, Scope)), option.WithEndpoint(endpoint))
  1530. if err != nil {
  1531. return nil, fmt.Errorf("cannot create data client on DB %v: %v", dbPath, err)
  1532. }
  1533. return client, nil
  1534. }
  1535. // populate prepares the database with some data.
  1536. func populate(ctx context.Context, client *Client) error {
  1537. // Populate data
  1538. var err error
  1539. m := InsertMap("test", map[string]interface{}{
  1540. "a": str1,
  1541. "b": str2,
  1542. })
  1543. _, err = client.Apply(ctx, []*Mutation{m})
  1544. return err
  1545. }
  1546. // Test PartitionQuery of BatchReadOnlyTransaction, create partitions then
  1547. // serialize and deserialize both transaction and partition to be used in
  1548. // execution on another client, and compare results.
  1549. func TestBatchQuery(t *testing.T) {
  1550. t.Parallel()
  1551. // Set up testing environment.
  1552. var (
  1553. client2 *Client
  1554. err error
  1555. )
  1556. ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
  1557. defer cancel()
  1558. client, dbPath, tearDown := prepare(ctx, t, simpleDBStatements)
  1559. defer tearDown()
  1560. if err = populate(ctx, client); err != nil {
  1561. t.Fatal(err)
  1562. }
  1563. if client2, err = createClient(ctx, dbPath); err != nil {
  1564. t.Fatal(err)
  1565. }
  1566. defer client2.Close()
  1567. // PartitionQuery
  1568. var (
  1569. txn *BatchReadOnlyTransaction
  1570. partitions []*Partition
  1571. stmt = Statement{SQL: "SELECT * FROM test;"}
  1572. )
  1573. if txn, err = client.BatchReadOnlyTransaction(ctx, StrongRead()); err != nil {
  1574. t.Fatal(err)
  1575. }
  1576. defer txn.Cleanup(ctx)
  1577. if partitions, err = txn.PartitionQuery(ctx, stmt, PartitionOptions{0, 3}); err != nil {
  1578. t.Fatal(err)
  1579. }
  1580. // Reconstruct BatchReadOnlyTransactionID and execute partitions
  1581. var (
  1582. tid2 BatchReadOnlyTransactionID
  1583. data []byte
  1584. gotResult bool // if we get matching result from two separate txns
  1585. )
  1586. if data, err = txn.ID.MarshalBinary(); err != nil {
  1587. t.Fatalf("encoding failed %v", err)
  1588. }
  1589. if err = tid2.UnmarshalBinary(data); err != nil {
  1590. t.Fatalf("decoding failed %v", err)
  1591. }
  1592. txn2 := client2.BatchReadOnlyTransactionFromID(tid2)
  1593. // Execute Partitions and compare results
  1594. for i, p := range partitions {
  1595. iter := txn.Execute(ctx, p)
  1596. defer iter.Stop()
  1597. p2 := serdesPartition(t, i, p)
  1598. iter2 := txn2.Execute(ctx, &p2)
  1599. defer iter2.Stop()
  1600. row1, err1 := iter.Next()
  1601. row2, err2 := iter2.Next()
  1602. if err1 != err2 {
  1603. t.Fatalf("execution failed for different reasons: %v, %v", err1, err2)
  1604. continue
  1605. }
  1606. if !testEqual(row1, row2) {
  1607. t.Fatalf("execution returned different values: %v, %v", row1, row2)
  1608. continue
  1609. }
  1610. if row1 == nil {
  1611. continue
  1612. }
  1613. var a, b string
  1614. if err = row1.Columns(&a, &b); err != nil {
  1615. t.Fatalf("failed to parse row %v", err)
  1616. continue
  1617. }
  1618. if a == str1 && b == str2 {
  1619. gotResult = true
  1620. }
  1621. }
  1622. if !gotResult {
  1623. t.Fatalf("execution didn't return expected values")
  1624. }
  1625. }
  1626. // Test PartitionRead of BatchReadOnlyTransaction, similar to TestBatchQuery
  1627. func TestBatchRead(t *testing.T) {
  1628. t.Parallel()
  1629. // Set up testing environment.
  1630. var (
  1631. client2 *Client
  1632. err error
  1633. )
  1634. ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
  1635. defer cancel()
  1636. client, dbPath, tearDown := prepare(ctx, t, simpleDBStatements)
  1637. defer tearDown()
  1638. if err = populate(ctx, client); err != nil {
  1639. t.Fatal(err)
  1640. }
  1641. if client2, err = createClient(ctx, dbPath); err != nil {
  1642. t.Fatal(err)
  1643. }
  1644. defer client2.Close()
  1645. // PartitionRead
  1646. var (
  1647. txn *BatchReadOnlyTransaction
  1648. partitions []*Partition
  1649. )
  1650. if txn, err = client.BatchReadOnlyTransaction(ctx, StrongRead()); err != nil {
  1651. t.Fatal(err)
  1652. }
  1653. defer txn.Cleanup(ctx)
  1654. if partitions, err = txn.PartitionRead(ctx, "test", AllKeys(), simpleDBTableColumns, PartitionOptions{0, 3}); err != nil {
  1655. t.Fatal(err)
  1656. }
  1657. // Reconstruct BatchReadOnlyTransactionID and execute partitions
  1658. var (
  1659. tid2 BatchReadOnlyTransactionID
  1660. data []byte
  1661. gotResult bool // if we get matching result from two separate txns
  1662. )
  1663. if data, err = txn.ID.MarshalBinary(); err != nil {
  1664. t.Fatalf("encoding failed %v", err)
  1665. }
  1666. if err = tid2.UnmarshalBinary(data); err != nil {
  1667. t.Fatalf("decoding failed %v", err)
  1668. }
  1669. txn2 := client2.BatchReadOnlyTransactionFromID(tid2)
  1670. // Execute Partitions and compare results
  1671. for i, p := range partitions {
  1672. iter := txn.Execute(ctx, p)
  1673. defer iter.Stop()
  1674. p2 := serdesPartition(t, i, p)
  1675. iter2 := txn2.Execute(ctx, &p2)
  1676. defer iter2.Stop()
  1677. row1, err1 := iter.Next()
  1678. row2, err2 := iter2.Next()
  1679. if err1 != err2 {
  1680. t.Fatalf("execution failed for different reasons: %v, %v", err1, err2)
  1681. continue
  1682. }
  1683. if !testEqual(row1, row2) {
  1684. t.Fatalf("execution returned different values: %v, %v", row1, row2)
  1685. continue
  1686. }
  1687. if row1 == nil {
  1688. continue
  1689. }
  1690. var a, b string
  1691. if err = row1.Columns(&a, &b); err != nil {
  1692. t.Fatalf("failed to parse row %v", err)
  1693. continue
  1694. }
  1695. if a == str1 && b == str2 {
  1696. gotResult = true
  1697. }
  1698. }
  1699. if !gotResult {
  1700. t.Fatalf("execution didn't return expected values")
  1701. }
  1702. }
  1703. // Test normal txReadEnv method on BatchReadOnlyTransaction.
  1704. func TestBROTNormal(t *testing.T) {
  1705. t.Parallel()
  1706. // Set up testing environment and create txn.
  1707. var (
  1708. txn *BatchReadOnlyTransaction
  1709. err error
  1710. row *Row
  1711. i int64
  1712. )
  1713. ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
  1714. defer cancel()
  1715. client, _, tearDown := prepare(ctx, t, simpleDBStatements)
  1716. defer tearDown()
  1717. if txn, err = client.BatchReadOnlyTransaction(ctx, StrongRead()); err != nil {
  1718. t.Fatal(err)
  1719. }
  1720. defer txn.Cleanup(ctx)
  1721. if _, err := txn.PartitionRead(ctx, "test", AllKeys(), simpleDBTableColumns, PartitionOptions{0, 3}); err != nil {
  1722. t.Fatal(err)
  1723. }
  1724. // Normal query should work with BatchReadOnlyTransaction
  1725. stmt2 := Statement{SQL: "SELECT 1"}
  1726. iter := txn.Query(ctx, stmt2)
  1727. defer iter.Stop()
  1728. row, err = iter.Next()
  1729. if err != nil {
  1730. t.Errorf("query failed with %v", err)
  1731. }
  1732. if err = row.Columns(&i); err != nil {
  1733. t.Errorf("failed to parse row %v", err)
  1734. }
  1735. }
  1736. func TestCommitTimestamp(t *testing.T) {
  1737. t.Parallel()
  1738. ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
  1739. defer cancel()
  1740. client, _, tearDown := prepare(ctx, t, ctsDBStatements)
  1741. defer tearDown()
  1742. type testTableRow struct {
  1743. Key string
  1744. Ts NullTime
  1745. }
  1746. var (
  1747. cts1, cts2, ts1, ts2 time.Time
  1748. err error
  1749. )
  1750. // Apply mutation in sequence, expect to see commit timestamp in good order, check also the commit timestamp returned
  1751. for _, it := range []struct {
  1752. k string
  1753. t *time.Time
  1754. }{
  1755. {"a", &cts1},
  1756. {"b", &cts2},
  1757. } {
  1758. tt := testTableRow{Key: it.k, Ts: NullTime{CommitTimestamp, true}}
  1759. m, err := InsertStruct("TestTable", tt)
  1760. if err != nil {
  1761. t.Fatal(err)
  1762. }
  1763. *it.t, err = client.Apply(ctx, []*Mutation{m}, ApplyAtLeastOnce())
  1764. if err != nil {
  1765. t.Fatal(err)
  1766. }
  1767. }
  1768. txn := client.ReadOnlyTransaction()
  1769. for _, it := range []struct {
  1770. k string
  1771. t *time.Time
  1772. }{
  1773. {"a", &ts1},
  1774. {"b", &ts2},
  1775. } {
  1776. if r, e := txn.ReadRow(ctx, "TestTable", Key{it.k}, []string{"Ts"}); e != nil {
  1777. t.Fatal(err)
  1778. } else {
  1779. var got testTableRow
  1780. if err := r.ToStruct(&got); err != nil {
  1781. t.Fatal(err)
  1782. }
  1783. *it.t = got.Ts.Time
  1784. }
  1785. }
  1786. if !cts1.Equal(ts1) {
  1787. t.Errorf("Expect commit timestamp returned and read to match for txn1, got %v and %v.", cts1, ts1)
  1788. }
  1789. if !cts2.Equal(ts2) {
  1790. t.Errorf("Expect commit timestamp returned and read to match for txn2, got %v and %v.", cts2, ts2)
  1791. }
  1792. // Try writing a timestamp in the future to commit timestamp, expect error
  1793. _, err = client.Apply(ctx, []*Mutation{InsertOrUpdate("TestTable", []string{"Key", "Ts"}, []interface{}{"a", time.Now().Add(time.Hour)})}, ApplyAtLeastOnce())
  1794. if msg, ok := matchError(err, codes.FailedPrecondition, "Cannot write timestamps in the future"); !ok {
  1795. t.Error(msg)
  1796. }
  1797. }