func TestQueryAbortedHalfway_WithDifferentResultsInFirstHalf(t *testing.T) {
	t.Parallel()

	db, server, teardown := setupTestDBConnection(t)
	defer teardown()
	// Ensure that the second call to Next() will fail with an Aborted error.
	server.TestSpanner.AddPartialResultSetError(testutil.SelectFooFromBar, testutil.PartialResultSetExecutionTime{
		ResumeToken: testutil.EncodeResumeToken(2),
		Err:         status.Error(codes.Aborted, "Aborted"),
	})

	ctx := context.Background()
	tx, err := db.BeginTx(ctx, &sql.TxOptions{})
	if err != nil {
		t.Fatalf("begin failed: %v", err)
	}
	rows, err := tx.QueryContext(ctx, testutil.SelectFooFromBar)
	if err != nil {
		t.Fatalf("query failed: %v", err)
	}

	// The first row should succeed.
	next := rows.Next()
	if !next {
		t.Fatalf("next result mismatch\nGot: %v\nWant: %v", next, true)
	}
	err = rows.Err()
	if err != nil {
		t.Fatalf("next failed: %v", err)
	}
	var val int64
	err = rows.Scan(&val)
	if err != nil {
		t.Fatalf("scan failed: %v", err)
	}
	if g, w := val, int64(1); g != w {
		t.Fatalf("value mismatch\nGot: %v\nWant: %v", g, w)
	}
	// Replace the original query result with a new one with a different value
	// for the first row. This should cause the transaction to fail with an
	// ErrAbortedDueToConcurrentModification error.
	server.TestSpanner.PutStatementResult(testutil.SelectFooFromBar, &testutil.StatementResult{
		Type:      testutil.StatementResultResultSet,
		ResultSet: testutil.CreateSingleColumnResultSet([]int64{2, 2}, "FOO"),
	})

	// This should now fail with an ErrAbortedDueToConcurrentModification error.
	next = rows.Next()
	if next {
		t.Fatalf("next result mismatch\nGot: %v\nWant: %v", next, false)
	}
	if g, w := rows.Err(), ErrAbortedDueToConcurrentModification; g != w {
		t.Fatalf("next error mismatch\nGot: %v\nWant: %v", g, w)
	}

	reqs := drainRequestsFromServer(server.TestSpanner)
	execReqs := requestsOfType(reqs, reflect.TypeOf(&sppb.ExecuteSqlRequest{}))
	if g, w := len(execReqs), 2; g != w {
		t.Fatalf("execute request count mismatch\nGot: %v\nWant: %v", g, w)
	}
}
// Tests that a query that is aborted halfway the stream will be retried,
// but that the retry will fail if the results in the part of the result
// set that has already been seen will fail the retry.
Tests that a query that is aborted halfway the stream will be retried,
but that the retry will fail if the results in the part of the result
set that has already been seen will fail the retry.
// Tests that a query that is aborted halfway the stream will be retried // but that the retry will fail if the results in the part of the result // set that has already been seen will fail the retry .
func TestQueryAbortedHalfway_WithDifferentResultsInFirstHalf(t *testing.T) {
	t.Parallel()
	db, server, teardown := setupTestDBConnection(t)
	defer teardown()
	server.TestSpanner.AddPartialResultSetError(testutil.SelectFooFromBar, testutil.PartialResultSetExecutionTime{
		ResumeToken: testutil.EncodeResumeToken(2),
		Err:         status.Error(codes.Aborted, "Aborted"),
	})
	ctx := context.Background()
	tx, err := db.BeginTx(ctx, &sql.TxOptions{})
	if err != nil {
		t.Fatalf("begin failed: %v", err)
	}
	rows, err := tx.QueryContext(ctx, testutil.SelectFooFromBar)
	if err != nil {
		t.Fatalf("query failed: %v", err)
	}
	next := rows.Next()
	if !next {
		t.Fatalf("next result mismatch\nGot: %v\nWant: %v", next, true)
	}
	err = rows.Err()
	if err != nil {
		t.Fatalf("next failed: %v", err)
	}
	var val int64
	err = rows.Scan(&val)
	if err != nil {
		t.Fatalf("scan failed: %v", err)
	}
	if g, w := val, int64(1); g != w {
		t.Fatalf("value mismatch\nGot: %v\nWant: %v", g, w)
	}
	server.TestSpanner.PutStatementResult(testutil.SelectFooFromBar, &testutil.StatementResult{
		Type:      testutil.StatementResultResultSet,
		ResultSet: testutil.CreateSingleColumnResultSet([]int64{2, 2}, "FOO"),
	})
	next = rows.Next()
	if next {
		t.Fatalf("next result mismatch\nGot: %v\nWant: %v", next, false)
	}
	if g, w := rows.Err(), ErrAbortedDueToConcurrentModification; g != w {
		t.Fatalf("next error mismatch\nGot: %v\nWant: %v", g, w)
	}
	reqs := drainRequestsFromServer(server.TestSpanner)
	execReqs := requestsOfType(reqs, reflect.TypeOf(&sppb.ExecuteSqlRequest{}))
	if g, w := len(execReqs), 2; g != w {
		t.Fatalf("execute request count mismatch\nGot: %v\nWant: %v", g, w)
	}
}
func TestQueryAbortedHalfway_WithDifferentResultsInFirstHalf ( t * testing . T ) { t . Parallel ( ) db , server , teardown := setupTestDBConnection ( t ) defer teardown ( ) server . TestSpanner . AddPartialResultSetError ( testutil . SelectFooFromBar , testutil . PartialResultSetExecutionTime { ResumeToken : testutil . EncodeResumeToken ( 2 ) , Err : status . Error ( codes . Aborted , " " ) , } ) ctx := context . Background ( ) tx , err := db . BeginTx ( ctx , & sql . TxOptions { } ) if err != nil { t . Fatalf ( " " , err ) } rows , err := tx . QueryContext ( ctx , testutil . SelectFooFromBar ) if err != nil { t . Fatalf ( " " , err ) } next := rows . Next ( ) if ! next { t . Fatalf ( " \n \n " , next , true ) } err = rows . Err ( ) if err != nil { t . Fatalf ( " " , err ) } var val int64 err = rows . Scan ( & val ) if err != nil { t . Fatalf ( " " , err ) } if g , w := val , int64 ( 1 ) ; g != w { t . Fatalf ( " \n \n " , g , w ) } server . TestSpanner . PutStatementResult ( testutil . SelectFooFromBar , & testutil . StatementResult { Type : testutil . StatementResultResultSet , ResultSet : testutil . CreateSingleColumnResultSet ( [ ] int64 { 2 , 2 } , " " ) , } ) next = rows . Next ( ) if next { t . Fatalf ( " \n \n " , next , false ) } if g , w := rows . Err ( ) , ErrAbortedDueToConcurrentModification ; g != w { t . Fatalf ( " \n \n " , g , w ) } reqs := drainRequestsFromServer ( server . TestSpanner ) execReqs := requestsOfType ( reqs , reflect . TypeOf ( & sppb . ExecuteSqlRequest { } ) ) if g , w := len ( execReqs ) , 2 ; g != w { t . Fatalf ( " \n \n " , g , w ) } }
Tests that a query that is aborted halfway the stream will be retried,
but that the retry will fail if the results in the part of the result
set that has already been seen will fail the retry.
Tests that a query that is aborted halfway the stream will be retried but that the retry will fail if the results in the part of the result set that has already been seen will fail the retry .
// Ensure that the second call to Next() will fail with an Aborted error. // The first row should succeed. // Replace the original query result with a new one with a different value // for the first row. This should cause the transaction to fail with an // ErrAbortedDueToConcurrentModification error. // This should now fail with an ErrAbortedDueToConcurrentModification error.