@@ -4995,6 +4995,258 @@ func TestPostgreSQLDialect(t *testing.T) {
49954995 }
49964996}
49974997
4998+ func TestReturnResultSetMetadata (t * testing.T ) {
4999+ t .Parallel ()
5000+
5001+ db , _ , teardown := setupTestDBConnection (t )
5002+ defer teardown ()
5003+ rows , err := db .QueryContext (context .Background (), testutil .SelectFooFromBar , ExecOptions {ReturnResultSetMetadata : true })
5004+ if err != nil {
5005+ t .Fatal (err )
5006+ }
5007+ defer func () { _ = rows .Close () }()
5008+
5009+ // Verify that the first result set contains the ResultSetMetadata.
5010+ if ! rows .Next () {
5011+ t .Fatal ("no rows" )
5012+ }
5013+ var meta * sppb.ResultSetMetadata
5014+ if err := rows .Scan (& meta ); err != nil {
5015+ t .Fatalf ("failed to scan metadata: %v" , err )
5016+ }
5017+ if g , w := len (meta .RowType .Fields ), 1 ; g != w {
5018+ t .Fatalf ("cols count mismatch\n Got: %v\n Want: %v" , g , w )
5019+ }
5020+ if rows .Next () {
5021+ t .Fatal ("more rows than expected" )
5022+ }
5023+
5024+ // Move to the next result set, which should contain the data.
5025+ if ! rows .NextResultSet () {
5026+ t .Fatal ("no more result sets found" )
5027+ }
5028+
5029+ for want := int64 (1 ); rows .Next (); want ++ {
5030+ cols , err := rows .Columns ()
5031+ if err != nil {
5032+ t .Fatal (err )
5033+ }
5034+ if ! cmp .Equal (cols , []string {"FOO" }) {
5035+ t .Fatalf ("cols mismatch\n Got: %v\n Want: %v" , cols , []string {"FOO" })
5036+ }
5037+ var got int64
5038+ err = rows .Scan (& got )
5039+ if err != nil {
5040+ t .Fatal (err )
5041+ }
5042+ if got != want {
5043+ t .Fatalf ("value mismatch\n Got: %v\n Want: %v" , got , want )
5044+ }
5045+ }
5046+ if rows .Err () != nil {
5047+ t .Fatal (rows .Err ())
5048+ }
5049+
5050+ // There should be no more result sets.
5051+ if rows .NextResultSet () {
5052+ t .Fatal ("more result sets than expected" )
5053+ }
5054+ }
5055+
5056+ func TestReturnResultSetMetadataError (t * testing.T ) {
5057+ t .Parallel ()
5058+
5059+ db , server , teardown := setupTestDBConnection (t )
5060+ defer teardown ()
5061+ query := "select * from non_existing_table"
5062+ _ = server .TestSpanner .PutStatementResult (query , & testutil.StatementResult {
5063+ Type : testutil .StatementResultError ,
5064+ Err : gstatus .Error (codes .NotFound , "Table not found" ),
5065+ })
5066+ rows , err := db .QueryContext (context .Background (), query , ExecOptions {ReturnResultSetMetadata : true })
5067+ if err != nil {
5068+ t .Fatal (err )
5069+ }
5070+ defer func () { _ = rows .Close () }()
5071+
5072+ if rows .Next () {
5073+ t .Fatal ("Next should fail" )
5074+ }
5075+ var meta * sppb.ResultSetMetadata
5076+ if err := rows .Scan (& meta ); err == nil {
5077+ t .Fatal ("missing error when scanning metadata" )
5078+ } else {
5079+ if g , w := spanner .ErrCode (err ), codes .NotFound ; g != w {
5080+ t .Fatalf ("error code mismatch\n Got: %v\n Want: %v" , g , w )
5081+ }
5082+ }
5083+
5084+ // Moving to the next result set fails because the query failed.
5085+ if rows .NextResultSet () {
5086+ t .Fatal ("got unexpected next result set" )
5087+ }
5088+ }
5089+
5090+ func TestReturnResultSetStats (t * testing.T ) {
5091+ t .Parallel ()
5092+
5093+ db , server , teardown := setupTestDBConnection (t )
5094+ defer teardown ()
5095+ query := "insert into singers (name) values ('test') then return id"
5096+ resultSet := testutil .CreateSingleColumnInt64ResultSet ([]int64 {42598 }, "id" )
5097+ _ = server .TestSpanner .PutStatementResult (query , & testutil.StatementResult {
5098+ Type : testutil .StatementResultResultSet ,
5099+ ResultSet : resultSet ,
5100+ UpdateCount : 1 ,
5101+ })
5102+
5103+ rows , err := db .QueryContext (context .Background (), query , ExecOptions {ReturnResultSetStats : true })
5104+ if err != nil {
5105+ t .Fatal (err )
5106+ }
5107+ defer func () { _ = rows .Close () }()
5108+
5109+ // The first result set should contain the data.
5110+ for want := int64 (42598 ); rows .Next (); want ++ {
5111+ cols , err := rows .Columns ()
5112+ if err != nil {
5113+ t .Fatal (err )
5114+ }
5115+ if ! cmp .Equal (cols , []string {"id" }) {
5116+ t .Fatalf ("cols mismatch\n Got: %v\n Want: %v" , cols , []string {"id" })
5117+ }
5118+ var got int64
5119+ err = rows .Scan (& got )
5120+ if err != nil {
5121+ t .Fatal (err )
5122+ }
5123+ if got != want {
5124+ t .Fatalf ("value mismatch\n Got: %v\n Want: %v" , got , want )
5125+ }
5126+ }
5127+ if rows .Err () != nil {
5128+ t .Fatal (rows .Err ())
5129+ }
5130+
5131+ // The next result set should contain the stats.
5132+ if ! rows .NextResultSet () {
5133+ t .Fatal ("missing stats result set" )
5134+ }
5135+
5136+ // Get the stats.
5137+ if ! rows .Next () {
5138+ t .Fatal ("no stats rows" )
5139+ }
5140+ var stats * sppb.ResultSetStats
5141+ if err := rows .Scan (& stats ); err != nil {
5142+ t .Fatalf ("failed to scan stats: %v" , err )
5143+ }
5144+ if g , w := stats .GetRowCountExact (), int64 (1 ); g != w {
5145+ t .Fatalf ("row count mismatch\n Got: %v\n Want: %v" , g , w )
5146+ }
5147+ if rows .Next () {
5148+ t .Fatal ("more rows than expected" )
5149+ }
5150+
5151+ // There should be no more result sets.
5152+ if rows .NextResultSet () {
5153+ t .Fatal ("more result sets than expected" )
5154+ }
5155+ }
5156+
5157+ func TestReturnResultSetMetadataAndStats (t * testing.T ) {
5158+ t .Parallel ()
5159+
5160+ db , server , teardown := setupTestDBConnection (t )
5161+ defer teardown ()
5162+
5163+ query := "insert into singers (name) values ('test') then return id"
5164+ resultSet := testutil .CreateSingleColumnInt64ResultSet ([]int64 {42598 }, "id" )
5165+ _ = server .TestSpanner .PutStatementResult (query , & testutil.StatementResult {
5166+ Type : testutil .StatementResultResultSet ,
5167+ ResultSet : resultSet ,
5168+ UpdateCount : 1 ,
5169+ })
5170+
5171+ rows , err := db .QueryContext (context .Background (), query , ExecOptions {
5172+ ReturnResultSetMetadata : true ,
5173+ ReturnResultSetStats : true ,
5174+ })
5175+ if err != nil {
5176+ t .Fatal (err )
5177+ }
5178+ defer func () { _ = rows .Close () }()
5179+
5180+ // Verify that the first result set contains the ResultSetMetadata.
5181+ if ! rows .Next () {
5182+ t .Fatal ("no rows" )
5183+ }
5184+ var meta * sppb.ResultSetMetadata
5185+ if err := rows .Scan (& meta ); err != nil {
5186+ t .Fatalf ("failed to scan metadata: %v" , err )
5187+ }
5188+ if g , w := len (meta .RowType .Fields ), 1 ; g != w {
5189+ t .Fatalf ("cols count mismatch\n Got: %v\n Want: %v" , g , w )
5190+ }
5191+ if g , w := meta .RowType .Fields [0 ].Name , "id" ; g != w {
5192+ t .Fatalf ("column name mismatch\n Got: %v\n Want: %v" , g , w )
5193+ }
5194+ if rows .Next () {
5195+ t .Fatal ("more rows than expected" )
5196+ }
5197+
5198+ // Move to the next result set, which should contain the data.
5199+ if ! rows .NextResultSet () {
5200+ t .Fatal ("no more result sets found" )
5201+ }
5202+
5203+ for want := int64 (42598 ); rows .Next (); want ++ {
5204+ cols , err := rows .Columns ()
5205+ if err != nil {
5206+ t .Fatal (err )
5207+ }
5208+ if ! cmp .Equal (cols , []string {"id" }) {
5209+ t .Fatalf ("cols mismatch\n Got: %v\n Want: %v" , cols , []string {"id" })
5210+ }
5211+ var got int64
5212+ err = rows .Scan (& got )
5213+ if err != nil {
5214+ t .Fatal (err )
5215+ }
5216+ if got != want {
5217+ t .Fatalf ("value mismatch\n Got: %v\n Want: %v" , got , want )
5218+ }
5219+ }
5220+ if rows .Err () != nil {
5221+ t .Fatal (rows .Err ())
5222+ }
5223+
5224+ // The next result set should contain the stats.
5225+ if ! rows .NextResultSet () {
5226+ t .Fatal ("missing stats result set" )
5227+ }
5228+
5229+ // Get the stats.
5230+ if ! rows .Next () {
5231+ t .Fatal ("no stats rows" )
5232+ }
5233+ var stats * sppb.ResultSetStats
5234+ if err := rows .Scan (& stats ); err != nil {
5235+ t .Fatalf ("failed to scan stats: %v" , err )
5236+ }
5237+ if g , w := stats .GetRowCountExact (), int64 (1 ); g != w {
5238+ t .Fatalf ("row count mismatch\n Got: %v\n Want: %v" , g , w )
5239+ }
5240+ if rows .Next () {
5241+ t .Fatal ("more rows than expected" )
5242+ }
5243+
5244+ // There should be no more result sets.
5245+ if rows .NextResultSet () {
5246+ t .Fatal ("more result sets than expected" )
5247+ }
5248+ }
5249+
49985250func numeric (v string ) big.Rat {
49995251 res , _ := big .NewRat (1 , 1 ).SetString (v )
50005252 return * res
0 commit comments