@@ -4747,6 +4747,258 @@ func TestPostgreSQLDialect(t *testing.T) {
47474747 }
47484748}
47494749
4750+ func TestReturnResultSetMetadata (t * testing.T ) {
4751+ t .Parallel ()
4752+
4753+ db , _ , teardown := setupTestDBConnection (t )
4754+ defer teardown ()
4755+ rows , err := db .QueryContext (context .Background (), testutil .SelectFooFromBar , ExecOptions {ReturnResultSetMetadata : true })
4756+ if err != nil {
4757+ t .Fatal (err )
4758+ }
4759+ defer func () { _ = rows .Close () }()
4760+
4761+ // Verify that the first result set contains the ResultSetMetadata.
4762+ if ! rows .Next () {
4763+ t .Fatal ("no rows" )
4764+ }
4765+ var meta * sppb.ResultSetMetadata
4766+ if err := rows .Scan (& meta ); err != nil {
4767+ t .Fatalf ("failed to scan metadata: %v" , err )
4768+ }
4769+ if g , w := len (meta .RowType .Fields ), 1 ; g != w {
4770+ t .Fatalf ("cols count mismatch\n Got: %v\n Want: %v" , g , w )
4771+ }
4772+ if rows .Next () {
4773+ t .Fatal ("more rows than expected" )
4774+ }
4775+
4776+ // Move to the next result set, which should contain the data.
4777+ if ! rows .NextResultSet () {
4778+ t .Fatal ("no more result sets found" )
4779+ }
4780+
4781+ for want := int64 (1 ); rows .Next (); want ++ {
4782+ cols , err := rows .Columns ()
4783+ if err != nil {
4784+ t .Fatal (err )
4785+ }
4786+ if ! cmp .Equal (cols , []string {"FOO" }) {
4787+ t .Fatalf ("cols mismatch\n Got: %v\n Want: %v" , cols , []string {"FOO" })
4788+ }
4789+ var got int64
4790+ err = rows .Scan (& got )
4791+ if err != nil {
4792+ t .Fatal (err )
4793+ }
4794+ if got != want {
4795+ t .Fatalf ("value mismatch\n Got: %v\n Want: %v" , got , want )
4796+ }
4797+ }
4798+ if rows .Err () != nil {
4799+ t .Fatal (rows .Err ())
4800+ }
4801+
4802+ // There should be no more result sets.
4803+ if rows .NextResultSet () {
4804+ t .Fatal ("more result sets than expected" )
4805+ }
4806+ }
4807+
4808+ func TestReturnResultSetMetadataError (t * testing.T ) {
4809+ t .Parallel ()
4810+
4811+ db , server , teardown := setupTestDBConnection (t )
4812+ defer teardown ()
4813+ query := "select * from non_existing_table"
4814+ _ = server .TestSpanner .PutStatementResult (query , & testutil.StatementResult {
4815+ Type : testutil .StatementResultError ,
4816+ Err : gstatus .Error (codes .NotFound , "Table not found" ),
4817+ })
4818+ rows , err := db .QueryContext (context .Background (), query , ExecOptions {ReturnResultSetMetadata : true })
4819+ if err != nil {
4820+ t .Fatal (err )
4821+ }
4822+ defer func () { _ = rows .Close () }()
4823+
4824+ if rows .Next () {
4825+ t .Fatal ("Next should fail" )
4826+ }
4827+ var meta * sppb.ResultSetMetadata
4828+ if err := rows .Scan (& meta ); err == nil {
4829+ t .Fatal ("missing error when scanning metadata" )
4830+ } else {
4831+ if g , w := spanner .ErrCode (err ), codes .NotFound ; g != w {
4832+ t .Fatalf ("error code mismatch\n Got: %v\n Want: %v" , g , w )
4833+ }
4834+ }
4835+
4836+ // Moving to the next result set fails because the query failed.
4837+ if rows .NextResultSet () {
4838+ t .Fatal ("got unexpected next result set" )
4839+ }
4840+ }
4841+
4842+ func TestReturnResultSetStats (t * testing.T ) {
4843+ t .Parallel ()
4844+
4845+ db , server , teardown := setupTestDBConnection (t )
4846+ defer teardown ()
4847+ query := "insert into singers (name) values ('test') then return id"
4848+ resultSet := testutil .CreateSingleColumnInt64ResultSet ([]int64 {42598 }, "id" )
4849+ _ = server .TestSpanner .PutStatementResult (query , & testutil.StatementResult {
4850+ Type : testutil .StatementResultResultSet ,
4851+ ResultSet : resultSet ,
4852+ UpdateCount : 1 ,
4853+ })
4854+
4855+ rows , err := db .QueryContext (context .Background (), query , ExecOptions {ReturnResultSetStats : true })
4856+ if err != nil {
4857+ t .Fatal (err )
4858+ }
4859+ defer func () { _ = rows .Close () }()
4860+
4861+ // The first result set should contain the data.
4862+ for want := int64 (42598 ); rows .Next (); want ++ {
4863+ cols , err := rows .Columns ()
4864+ if err != nil {
4865+ t .Fatal (err )
4866+ }
4867+ if ! cmp .Equal (cols , []string {"id" }) {
4868+ t .Fatalf ("cols mismatch\n Got: %v\n Want: %v" , cols , []string {"id" })
4869+ }
4870+ var got int64
4871+ err = rows .Scan (& got )
4872+ if err != nil {
4873+ t .Fatal (err )
4874+ }
4875+ if got != want {
4876+ t .Fatalf ("value mismatch\n Got: %v\n Want: %v" , got , want )
4877+ }
4878+ }
4879+ if rows .Err () != nil {
4880+ t .Fatal (rows .Err ())
4881+ }
4882+
4883+ // The next result set should contain the stats.
4884+ if ! rows .NextResultSet () {
4885+ t .Fatal ("missing stats result set" )
4886+ }
4887+
4888+ // Get the stats.
4889+ if ! rows .Next () {
4890+ t .Fatal ("no stats rows" )
4891+ }
4892+ var stats * sppb.ResultSetStats
4893+ if err := rows .Scan (& stats ); err != nil {
4894+ t .Fatalf ("failed to scan stats: %v" , err )
4895+ }
4896+ if g , w := stats .GetRowCountExact (), int64 (1 ); g != w {
4897+ t .Fatalf ("row count mismatch\n Got: %v\n Want: %v" , g , w )
4898+ }
4899+ if rows .Next () {
4900+ t .Fatal ("more rows than expected" )
4901+ }
4902+
4903+ // There should be no more result sets.
4904+ if rows .NextResultSet () {
4905+ t .Fatal ("more result sets than expected" )
4906+ }
4907+ }
4908+
4909+ func TestReturnResultSetMetadataAndStats (t * testing.T ) {
4910+ t .Parallel ()
4911+
4912+ db , server , teardown := setupTestDBConnection (t )
4913+ defer teardown ()
4914+
4915+ query := "insert into singers (name) values ('test') then return id"
4916+ resultSet := testutil .CreateSingleColumnInt64ResultSet ([]int64 {42598 }, "id" )
4917+ _ = server .TestSpanner .PutStatementResult (query , & testutil.StatementResult {
4918+ Type : testutil .StatementResultResultSet ,
4919+ ResultSet : resultSet ,
4920+ UpdateCount : 1 ,
4921+ })
4922+
4923+ rows , err := db .QueryContext (context .Background (), query , ExecOptions {
4924+ ReturnResultSetMetadata : true ,
4925+ ReturnResultSetStats : true ,
4926+ })
4927+ if err != nil {
4928+ t .Fatal (err )
4929+ }
4930+ defer func () { _ = rows .Close () }()
4931+
4932+ // Verify that the first result set contains the ResultSetMetadata.
4933+ if ! rows .Next () {
4934+ t .Fatal ("no rows" )
4935+ }
4936+ var meta * sppb.ResultSetMetadata
4937+ if err := rows .Scan (& meta ); err != nil {
4938+ t .Fatalf ("failed to scan metadata: %v" , err )
4939+ }
4940+ if g , w := len (meta .RowType .Fields ), 1 ; g != w {
4941+ t .Fatalf ("cols count mismatch\n Got: %v\n Want: %v" , g , w )
4942+ }
4943+ if g , w := meta .RowType .Fields [0 ].Name , "id" ; g != w {
4944+ t .Fatalf ("column name mismatch\n Got: %v\n Want: %v" , g , w )
4945+ }
4946+ if rows .Next () {
4947+ t .Fatal ("more rows than expected" )
4948+ }
4949+
4950+ // Move to the next result set, which should contain the data.
4951+ if ! rows .NextResultSet () {
4952+ t .Fatal ("no more result sets found" )
4953+ }
4954+
4955+ for want := int64 (42598 ); rows .Next (); want ++ {
4956+ cols , err := rows .Columns ()
4957+ if err != nil {
4958+ t .Fatal (err )
4959+ }
4960+ if ! cmp .Equal (cols , []string {"id" }) {
4961+ t .Fatalf ("cols mismatch\n Got: %v\n Want: %v" , cols , []string {"id" })
4962+ }
4963+ var got int64
4964+ err = rows .Scan (& got )
4965+ if err != nil {
4966+ t .Fatal (err )
4967+ }
4968+ if got != want {
4969+ t .Fatalf ("value mismatch\n Got: %v\n Want: %v" , got , want )
4970+ }
4971+ }
4972+ if rows .Err () != nil {
4973+ t .Fatal (rows .Err ())
4974+ }
4975+
4976+ // The next result set should contain the stats.
4977+ if ! rows .NextResultSet () {
4978+ t .Fatal ("missing stats result set" )
4979+ }
4980+
4981+ // Get the stats.
4982+ if ! rows .Next () {
4983+ t .Fatal ("no stats rows" )
4984+ }
4985+ var stats * sppb.ResultSetStats
4986+ if err := rows .Scan (& stats ); err != nil {
4987+ t .Fatalf ("failed to scan stats: %v" , err )
4988+ }
4989+ if g , w := stats .GetRowCountExact (), int64 (1 ); g != w {
4990+ t .Fatalf ("row count mismatch\n Got: %v\n Want: %v" , g , w )
4991+ }
4992+ if rows .Next () {
4993+ t .Fatal ("more rows than expected" )
4994+ }
4995+
4996+ // There should be no more result sets.
4997+ if rows .NextResultSet () {
4998+ t .Fatal ("more result sets than expected" )
4999+ }
5000+ }
5001+
47505002func numeric (v string ) big.Rat {
47515003 res , _ := big .NewRat (1 , 1 ).SetString (v )
47525004 return * res
0 commit comments