github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/query/result_test.go (about)

     1  package query
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"io"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/require"
    11  	"github.com/ydb-platform/ydb-go-genproto/Ydb_Query_V1"
    12  	"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
    13  	"github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Query"
    14  	"github.com/ydb-platform/ydb-go-genproto/protos/Ydb_TableStats"
    15  	"go.uber.org/mock/gomock"
    16  
    17  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/stats"
    18  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
    19  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest"
    20  	"github.com/ydb-platform/ydb-go-sdk/v3/query"
    21  	"github.com/ydb-platform/ydb-go-sdk/v3/trace"
    22  )
    23  
    24  func TestResultNextResultSet(t *testing.T) {
    25  	t.Run("HappyWay", func(t *testing.T) {
    26  		ctx, cancel := context.WithCancel(xtest.Context(t))
    27  		defer cancel()
    28  		ctrl := gomock.NewController(t)
    29  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
    30  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
    31  			Status:         Ydb.StatusIds_SUCCESS,
    32  			ResultSetIndex: 0,
    33  			ResultSet: &Ydb.ResultSet{
    34  				Columns: []*Ydb.Column{
    35  					{
    36  						Name: "a",
    37  						Type: &Ydb.Type{
    38  							Type: &Ydb.Type_TypeId{
    39  								TypeId: Ydb.Type_UINT64,
    40  							},
    41  						},
    42  					},
    43  					{
    44  						Name: "b",
    45  						Type: &Ydb.Type{
    46  							Type: &Ydb.Type_TypeId{
    47  								TypeId: Ydb.Type_UTF8,
    48  							},
    49  						},
    50  					},
    51  				},
    52  				Rows: []*Ydb.Value{
    53  					{
    54  						Items: []*Ydb.Value{{
    55  							Value: &Ydb.Value_Uint64Value{
    56  								Uint64Value: 1,
    57  							},
    58  						}, {
    59  							Value: &Ydb.Value_TextValue{
    60  								TextValue: "1",
    61  							},
    62  						}},
    63  					},
    64  					{
    65  						Items: []*Ydb.Value{{
    66  							Value: &Ydb.Value_Uint64Value{
    67  								Uint64Value: 2,
    68  							},
    69  						}, {
    70  							Value: &Ydb.Value_TextValue{
    71  								TextValue: "2",
    72  							},
    73  						}},
    74  					},
    75  					{
    76  						Items: []*Ydb.Value{{
    77  							Value: &Ydb.Value_Uint64Value{
    78  								Uint64Value: 3,
    79  							},
    80  						}, {
    81  							Value: &Ydb.Value_TextValue{
    82  								TextValue: "3",
    83  							},
    84  						}},
    85  					},
    86  				},
    87  			},
    88  		}, nil)
    89  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
    90  			Status:         Ydb.StatusIds_SUCCESS,
    91  			ResultSetIndex: 0,
    92  			ResultSet: &Ydb.ResultSet{
    93  				Rows: []*Ydb.Value{
    94  					{
    95  						Items: []*Ydb.Value{{
    96  							Value: &Ydb.Value_Uint64Value{
    97  								Uint64Value: 4,
    98  							},
    99  						}, {
   100  							Value: &Ydb.Value_TextValue{
   101  								TextValue: "4",
   102  							},
   103  						}},
   104  					},
   105  					{
   106  						Items: []*Ydb.Value{{
   107  							Value: &Ydb.Value_Uint64Value{
   108  								Uint64Value: 5,
   109  							},
   110  						}, {
   111  							Value: &Ydb.Value_TextValue{
   112  								TextValue: "5",
   113  							},
   114  						}},
   115  					},
   116  				},
   117  			},
   118  		}, nil)
   119  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   120  			Status:         Ydb.StatusIds_SUCCESS,
   121  			ResultSetIndex: 1,
   122  			ResultSet: &Ydb.ResultSet{
   123  				Columns: []*Ydb.Column{
   124  					{
   125  						Name: "c",
   126  						Type: &Ydb.Type{
   127  							Type: &Ydb.Type_TypeId{
   128  								TypeId: Ydb.Type_UINT64,
   129  							},
   130  						},
   131  					},
   132  					{
   133  						Name: "d",
   134  						Type: &Ydb.Type{
   135  							Type: &Ydb.Type_TypeId{
   136  								TypeId: Ydb.Type_UTF8,
   137  							},
   138  						},
   139  					},
   140  					{
   141  						Name: "e",
   142  						Type: &Ydb.Type{
   143  							Type: &Ydb.Type_TypeId{
   144  								TypeId: Ydb.Type_BOOL,
   145  							},
   146  						},
   147  					},
   148  				},
   149  				Rows: []*Ydb.Value{
   150  					{
   151  						Items: []*Ydb.Value{{
   152  							Value: &Ydb.Value_Uint64Value{
   153  								Uint64Value: 1,
   154  							},
   155  						}, {
   156  							Value: &Ydb.Value_TextValue{
   157  								TextValue: "1",
   158  							},
   159  						}, {
   160  							Value: &Ydb.Value_BoolValue{
   161  								BoolValue: true,
   162  							},
   163  						}},
   164  					},
   165  					{
   166  						Items: []*Ydb.Value{{
   167  							Value: &Ydb.Value_Uint64Value{
   168  								Uint64Value: 2,
   169  							},
   170  						}, {
   171  							Value: &Ydb.Value_TextValue{
   172  								TextValue: "2",
   173  							},
   174  						}, {
   175  							Value: &Ydb.Value_BoolValue{
   176  								BoolValue: false,
   177  							},
   178  						}},
   179  					},
   180  				},
   181  			},
   182  		}, nil)
   183  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   184  			Status:         Ydb.StatusIds_SUCCESS,
   185  			ResultSetIndex: 1,
   186  			ResultSet: &Ydb.ResultSet{
   187  				Rows: []*Ydb.Value{
   188  					{
   189  						Items: []*Ydb.Value{{
   190  							Value: &Ydb.Value_Uint64Value{
   191  								Uint64Value: 3,
   192  							},
   193  						}, {
   194  							Value: &Ydb.Value_TextValue{
   195  								TextValue: "3",
   196  							},
   197  						}, {
   198  							Value: &Ydb.Value_BoolValue{
   199  								BoolValue: true,
   200  							},
   201  						}},
   202  					},
   203  					{
   204  						Items: []*Ydb.Value{{
   205  							Value: &Ydb.Value_Uint64Value{
   206  								Uint64Value: 4,
   207  							},
   208  						}, {
   209  							Value: &Ydb.Value_TextValue{
   210  								TextValue: "4",
   211  							},
   212  						}, {
   213  							Value: &Ydb.Value_BoolValue{
   214  								BoolValue: false,
   215  							},
   216  						}},
   217  					},
   218  					{
   219  						Items: []*Ydb.Value{{
   220  							Value: &Ydb.Value_Uint64Value{
   221  								Uint64Value: 5,
   222  							},
   223  						}, {
   224  							Value: &Ydb.Value_TextValue{
   225  								TextValue: "5",
   226  							},
   227  						}, {
   228  							Value: &Ydb.Value_BoolValue{
   229  								BoolValue: false,
   230  							},
   231  						}},
   232  					},
   233  				},
   234  			},
   235  		}, nil)
   236  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   237  			Status:         Ydb.StatusIds_SUCCESS,
   238  			ResultSetIndex: 2,
   239  			ResultSet: &Ydb.ResultSet{
   240  				Columns: []*Ydb.Column{
   241  					{
   242  						Name: "c",
   243  						Type: &Ydb.Type{
   244  							Type: &Ydb.Type_TypeId{
   245  								TypeId: Ydb.Type_UINT64,
   246  							},
   247  						},
   248  					},
   249  					{
   250  						Name: "d",
   251  						Type: &Ydb.Type{
   252  							Type: &Ydb.Type_TypeId{
   253  								TypeId: Ydb.Type_UTF8,
   254  							},
   255  						},
   256  					},
   257  					{
   258  						Name: "e",
   259  						Type: &Ydb.Type{
   260  							Type: &Ydb.Type_TypeId{
   261  								TypeId: Ydb.Type_BOOL,
   262  							},
   263  						},
   264  					},
   265  				},
   266  				Rows: []*Ydb.Value{
   267  					{
   268  						Items: []*Ydb.Value{{
   269  							Value: &Ydb.Value_Uint64Value{
   270  								Uint64Value: 1,
   271  							},
   272  						}, {
   273  							Value: &Ydb.Value_TextValue{
   274  								TextValue: "1",
   275  							},
   276  						}, {
   277  							Value: &Ydb.Value_BoolValue{
   278  								BoolValue: true,
   279  							},
   280  						}},
   281  					},
   282  					{
   283  						Items: []*Ydb.Value{{
   284  							Value: &Ydb.Value_Uint64Value{
   285  								Uint64Value: 2,
   286  							},
   287  						}, {
   288  							Value: &Ydb.Value_TextValue{
   289  								TextValue: "2",
   290  							},
   291  						}, {
   292  							Value: &Ydb.Value_BoolValue{
   293  								BoolValue: false,
   294  							},
   295  						}},
   296  					},
   297  				},
   298  			},
   299  		}, nil)
   300  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   301  			Status:         Ydb.StatusIds_SUCCESS,
   302  			ResultSetIndex: 2,
   303  			ResultSet: &Ydb.ResultSet{
   304  				Rows: []*Ydb.Value{
   305  					{
   306  						Items: []*Ydb.Value{{
   307  							Value: &Ydb.Value_Uint64Value{
   308  								Uint64Value: 3,
   309  							},
   310  						}, {
   311  							Value: &Ydb.Value_TextValue{
   312  								TextValue: "3",
   313  							},
   314  						}, {
   315  							Value: &Ydb.Value_BoolValue{
   316  								BoolValue: true,
   317  							},
   318  						}},
   319  					},
   320  					{
   321  						Items: []*Ydb.Value{{
   322  							Value: &Ydb.Value_Uint64Value{
   323  								Uint64Value: 4,
   324  							},
   325  						}, {
   326  							Value: &Ydb.Value_TextValue{
   327  								TextValue: "4",
   328  							},
   329  						}, {
   330  							Value: &Ydb.Value_BoolValue{
   331  								BoolValue: false,
   332  							},
   333  						}},
   334  					},
   335  					{
   336  						Items: []*Ydb.Value{{
   337  							Value: &Ydb.Value_Uint64Value{
   338  								Uint64Value: 5,
   339  							},
   340  						}, {
   341  							Value: &Ydb.Value_TextValue{
   342  								TextValue: "5",
   343  							},
   344  						}, {
   345  							Value: &Ydb.Value_BoolValue{
   346  								BoolValue: false,
   347  							},
   348  						}},
   349  					},
   350  				},
   351  			},
   352  		}, nil)
   353  		stream.EXPECT().Recv().Return(nil, io.EOF)
   354  		r, err := newResult(ctx, stream, nil)
   355  		require.NoError(t, err)
   356  		defer r.Close(ctx)
   357  		{
   358  			t.Log("nextResultSet")
   359  			rs, err := r.nextResultSet(ctx)
   360  			require.NoError(t, err)
   361  			require.EqualValues(t, 0, rs.Index())
   362  			{
   363  				t.Log("next (row=1)")
   364  				_, err := rs.nextRow(ctx)
   365  				require.NoError(t, err)
   366  				require.EqualValues(t, 0, rs.rowIndex)
   367  			}
   368  			{
   369  				t.Log("next (row=2)")
   370  				_, err := rs.nextRow(ctx)
   371  				require.NoError(t, err)
   372  				require.EqualValues(t, 1, rs.rowIndex)
   373  			}
   374  			{
   375  				t.Log("next (row=3)")
   376  				_, err := rs.nextRow(ctx)
   377  				require.NoError(t, err)
   378  				require.EqualValues(t, 2, rs.rowIndex)
   379  			}
   380  			{
   381  				t.Log("next (row=4)")
   382  				_, err := rs.nextRow(ctx)
   383  				require.NoError(t, err)
   384  				require.EqualValues(t, 0, rs.rowIndex)
   385  			}
   386  			{
   387  				t.Log("next (row=5)")
   388  				_, err := rs.nextRow(ctx)
   389  				require.NoError(t, err)
   390  				require.EqualValues(t, 1, rs.rowIndex)
   391  			}
   392  			{
   393  				t.Log("next (row=6)")
   394  				_, err := rs.nextRow(ctx)
   395  				require.ErrorIs(t, err, io.EOF)
   396  			}
   397  		}
   398  		{
   399  			t.Log("nextResultSet")
   400  			rs, err := r.nextResultSet(ctx)
   401  			require.NoError(t, err)
   402  			require.EqualValues(t, 1, rs.Index())
   403  		}
   404  		{
   405  			t.Log("nextResultSet")
   406  			rs, err := r.nextResultSet(ctx)
   407  			require.NoError(t, err)
   408  			require.EqualValues(t, 2, rs.Index())
   409  			{
   410  				t.Log("next (row=1)")
   411  				_, err := rs.nextRow(ctx)
   412  				require.NoError(t, err)
   413  				require.EqualValues(t, 0, rs.rowIndex)
   414  			}
   415  			{
   416  				t.Log("next (row=2)")
   417  				_, err := rs.nextRow(ctx)
   418  				require.NoError(t, err)
   419  				require.EqualValues(t, 1, rs.rowIndex)
   420  			}
   421  			{
   422  				t.Log("next (row=3)")
   423  				_, err := rs.nextRow(ctx)
   424  				require.NoError(t, err)
   425  				require.EqualValues(t, 0, rs.rowIndex)
   426  			}
   427  			{
   428  				t.Log("next (row=4)")
   429  				_, err := rs.nextRow(ctx)
   430  				require.NoError(t, err)
   431  				require.EqualValues(t, 1, rs.rowIndex)
   432  			}
   433  			{
   434  				t.Log("next (row=5)")
   435  				_, err := rs.nextRow(ctx)
   436  				require.NoError(t, err)
   437  				require.EqualValues(t, 2, rs.rowIndex)
   438  			}
   439  			{
   440  				t.Log("next (row=6)")
   441  				_, err := rs.nextRow(ctx)
   442  				require.ErrorIs(t, err, io.EOF)
   443  			}
   444  		}
   445  		{
   446  			t.Log("close result")
   447  			r.Close(context.Background())
   448  		}
   449  		{
   450  			t.Log("nextResultSet")
   451  			rs, err := r.nextResultSet(context.Background())
   452  			require.ErrorIs(t, err, io.EOF)
   453  			require.Nil(t, rs)
   454  			require.Equal(t, -1, rs.Index())
   455  		}
   456  	})
   457  	t.Run("InterruptStream", func(t *testing.T) {
   458  		ctx, cancel := context.WithCancel(xtest.Context(t))
   459  		defer cancel()
   460  		ctrl := gomock.NewController(t)
   461  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
   462  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   463  			Status:         Ydb.StatusIds_SUCCESS,
   464  			ResultSetIndex: 0,
   465  			ResultSet: &Ydb.ResultSet{
   466  				Columns: []*Ydb.Column{
   467  					{
   468  						Name: "a",
   469  						Type: &Ydb.Type{
   470  							Type: &Ydb.Type_TypeId{
   471  								TypeId: Ydb.Type_UINT64,
   472  							},
   473  						},
   474  					},
   475  					{
   476  						Name: "b",
   477  						Type: &Ydb.Type{
   478  							Type: &Ydb.Type_TypeId{
   479  								TypeId: Ydb.Type_UTF8,
   480  							},
   481  						},
   482  					},
   483  				},
   484  				Rows: []*Ydb.Value{
   485  					{
   486  						Items: []*Ydb.Value{{
   487  							Value: &Ydb.Value_Uint64Value{
   488  								Uint64Value: 1,
   489  							},
   490  						}, {
   491  							Value: &Ydb.Value_TextValue{
   492  								TextValue: "1",
   493  							},
   494  						}},
   495  					},
   496  					{
   497  						Items: []*Ydb.Value{{
   498  							Value: &Ydb.Value_Uint64Value{
   499  								Uint64Value: 2,
   500  							},
   501  						}, {
   502  							Value: &Ydb.Value_TextValue{
   503  								TextValue: "2",
   504  							},
   505  						}},
   506  					},
   507  					{
   508  						Items: []*Ydb.Value{{
   509  							Value: &Ydb.Value_Uint64Value{
   510  								Uint64Value: 3,
   511  							},
   512  						}, {
   513  							Value: &Ydb.Value_TextValue{
   514  								TextValue: "3",
   515  							},
   516  						}},
   517  					},
   518  				},
   519  			},
   520  		}, nil)
   521  		r, err := newResult(ctx, stream, nil)
   522  		require.NoError(t, err)
   523  		defer r.Close(ctx)
   524  		{
   525  			t.Log("nextResultSet")
   526  			rs, err := r.nextResultSet(ctx)
   527  			require.NoError(t, err)
   528  			require.EqualValues(t, 0, rs.Index())
   529  			{
   530  				t.Log("next (row=1)")
   531  				_, err := rs.nextRow(ctx)
   532  				require.NoError(t, err)
   533  				require.EqualValues(t, 0, rs.rowIndex)
   534  			}
   535  			{
   536  				t.Log("next (row=2)")
   537  				_, err := rs.nextRow(ctx)
   538  				require.NoError(t, err)
   539  				require.EqualValues(t, 1, rs.rowIndex)
   540  			}
   541  			t.Log("explicit interrupt stream")
   542  			r.closeOnce()
   543  			{
   544  				t.Log("next (row=3)")
   545  				_, err := rs.nextRow(context.Background())
   546  				require.NoError(t, err)
   547  				require.EqualValues(t, 2, rs.rowIndex)
   548  			}
   549  			{
   550  				t.Log("next (row=4)")
   551  				_, err := rs.nextRow(context.Background())
   552  				require.ErrorIs(t, err, io.EOF)
   553  			}
   554  		}
   555  		{
   556  			t.Log("nextResultSet")
   557  			_, err := r.nextResultSet(context.Background())
   558  			require.ErrorIs(t, err, io.EOF)
   559  		}
   560  	})
   561  	t.Run("WrongResultSetIndex", func(t *testing.T) {
   562  		ctx, cancel := context.WithCancel(xtest.Context(t))
   563  		defer cancel()
   564  		ctrl := gomock.NewController(t)
   565  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
   566  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   567  			Status:         Ydb.StatusIds_SUCCESS,
   568  			ResultSetIndex: 0,
   569  			ResultSet: &Ydb.ResultSet{
   570  				Columns: []*Ydb.Column{
   571  					{
   572  						Name: "a",
   573  						Type: &Ydb.Type{
   574  							Type: &Ydb.Type_TypeId{
   575  								TypeId: Ydb.Type_UINT64,
   576  							},
   577  						},
   578  					},
   579  					{
   580  						Name: "b",
   581  						Type: &Ydb.Type{
   582  							Type: &Ydb.Type_TypeId{
   583  								TypeId: Ydb.Type_UTF8,
   584  							},
   585  						},
   586  					},
   587  				},
   588  				Rows: []*Ydb.Value{
   589  					{
   590  						Items: []*Ydb.Value{{
   591  							Value: &Ydb.Value_Uint64Value{
   592  								Uint64Value: 1,
   593  							},
   594  						}, {
   595  							Value: &Ydb.Value_TextValue{
   596  								TextValue: "1",
   597  							},
   598  						}},
   599  					},
   600  					{
   601  						Items: []*Ydb.Value{{
   602  							Value: &Ydb.Value_Uint64Value{
   603  								Uint64Value: 2,
   604  							},
   605  						}, {
   606  							Value: &Ydb.Value_TextValue{
   607  								TextValue: "2",
   608  							},
   609  						}},
   610  					},
   611  					{
   612  						Items: []*Ydb.Value{{
   613  							Value: &Ydb.Value_Uint64Value{
   614  								Uint64Value: 3,
   615  							},
   616  						}, {
   617  							Value: &Ydb.Value_TextValue{
   618  								TextValue: "3",
   619  							},
   620  						}},
   621  					},
   622  				},
   623  			},
   624  		}, nil)
   625  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   626  			Status:         Ydb.StatusIds_SUCCESS,
   627  			ResultSetIndex: 0,
   628  			ResultSet: &Ydb.ResultSet{
   629  				Rows: []*Ydb.Value{
   630  					{
   631  						Items: []*Ydb.Value{{
   632  							Value: &Ydb.Value_Uint64Value{
   633  								Uint64Value: 4,
   634  							},
   635  						}, {
   636  							Value: &Ydb.Value_TextValue{
   637  								TextValue: "4",
   638  							},
   639  						}},
   640  					},
   641  					{
   642  						Items: []*Ydb.Value{{
   643  							Value: &Ydb.Value_Uint64Value{
   644  								Uint64Value: 5,
   645  							},
   646  						}, {
   647  							Value: &Ydb.Value_TextValue{
   648  								TextValue: "5",
   649  							},
   650  						}},
   651  					},
   652  				},
   653  			},
   654  		}, nil)
   655  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   656  			Status:         Ydb.StatusIds_SUCCESS,
   657  			ResultSetIndex: 2,
   658  			ResultSet: &Ydb.ResultSet{
   659  				Columns: []*Ydb.Column{
   660  					{
   661  						Name: "c",
   662  						Type: &Ydb.Type{
   663  							Type: &Ydb.Type_TypeId{
   664  								TypeId: Ydb.Type_UINT64,
   665  							},
   666  						},
   667  					},
   668  					{
   669  						Name: "d",
   670  						Type: &Ydb.Type{
   671  							Type: &Ydb.Type_TypeId{
   672  								TypeId: Ydb.Type_UTF8,
   673  							},
   674  						},
   675  					},
   676  					{
   677  						Name: "e",
   678  						Type: &Ydb.Type{
   679  							Type: &Ydb.Type_TypeId{
   680  								TypeId: Ydb.Type_BOOL,
   681  							},
   682  						},
   683  					},
   684  				},
   685  				Rows: []*Ydb.Value{
   686  					{
   687  						Items: []*Ydb.Value{{
   688  							Value: &Ydb.Value_Uint64Value{
   689  								Uint64Value: 1,
   690  							},
   691  						}, {
   692  							Value: &Ydb.Value_TextValue{
   693  								TextValue: "1",
   694  							},
   695  						}, {
   696  							Value: &Ydb.Value_BoolValue{
   697  								BoolValue: true,
   698  							},
   699  						}},
   700  					},
   701  					{
   702  						Items: []*Ydb.Value{{
   703  							Value: &Ydb.Value_Uint64Value{
   704  								Uint64Value: 2,
   705  							},
   706  						}, {
   707  							Value: &Ydb.Value_TextValue{
   708  								TextValue: "2",
   709  							},
   710  						}, {
   711  							Value: &Ydb.Value_BoolValue{
   712  								BoolValue: false,
   713  							},
   714  						}},
   715  					},
   716  				},
   717  			},
   718  		}, nil)
   719  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   720  			Status:         Ydb.StatusIds_SUCCESS,
   721  			ResultSetIndex: 2,
   722  			ResultSet: &Ydb.ResultSet{
   723  				Rows: []*Ydb.Value{
   724  					{
   725  						Items: []*Ydb.Value{{
   726  							Value: &Ydb.Value_Uint64Value{
   727  								Uint64Value: 3,
   728  							},
   729  						}, {
   730  							Value: &Ydb.Value_TextValue{
   731  								TextValue: "3",
   732  							},
   733  						}, {
   734  							Value: &Ydb.Value_BoolValue{
   735  								BoolValue: true,
   736  							},
   737  						}},
   738  					},
   739  					{
   740  						Items: []*Ydb.Value{{
   741  							Value: &Ydb.Value_Uint64Value{
   742  								Uint64Value: 4,
   743  							},
   744  						}, {
   745  							Value: &Ydb.Value_TextValue{
   746  								TextValue: "4",
   747  							},
   748  						}, {
   749  							Value: &Ydb.Value_BoolValue{
   750  								BoolValue: false,
   751  							},
   752  						}},
   753  					},
   754  					{
   755  						Items: []*Ydb.Value{{
   756  							Value: &Ydb.Value_Uint64Value{
   757  								Uint64Value: 5,
   758  							},
   759  						}, {
   760  							Value: &Ydb.Value_TextValue{
   761  								TextValue: "5",
   762  							},
   763  						}, {
   764  							Value: &Ydb.Value_BoolValue{
   765  								BoolValue: false,
   766  							},
   767  						}},
   768  					},
   769  				},
   770  			},
   771  		}, nil)
   772  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   773  			Status:         Ydb.StatusIds_SUCCESS,
   774  			ResultSetIndex: 1,
   775  			ResultSet: &Ydb.ResultSet{
   776  				Columns: []*Ydb.Column{
   777  					{
   778  						Name: "c",
   779  						Type: &Ydb.Type{
   780  							Type: &Ydb.Type_TypeId{
   781  								TypeId: Ydb.Type_UINT64,
   782  							},
   783  						},
   784  					},
   785  					{
   786  						Name: "d",
   787  						Type: &Ydb.Type{
   788  							Type: &Ydb.Type_TypeId{
   789  								TypeId: Ydb.Type_UTF8,
   790  							},
   791  						},
   792  					},
   793  					{
   794  						Name: "e",
   795  						Type: &Ydb.Type{
   796  							Type: &Ydb.Type_TypeId{
   797  								TypeId: Ydb.Type_BOOL,
   798  							},
   799  						},
   800  					},
   801  				},
   802  				Rows: []*Ydb.Value{
   803  					{
   804  						Items: []*Ydb.Value{{
   805  							Value: &Ydb.Value_Uint64Value{
   806  								Uint64Value: 1,
   807  							},
   808  						}, {
   809  							Value: &Ydb.Value_TextValue{
   810  								TextValue: "1",
   811  							},
   812  						}, {
   813  							Value: &Ydb.Value_BoolValue{
   814  								BoolValue: true,
   815  							},
   816  						}},
   817  					},
   818  					{
   819  						Items: []*Ydb.Value{{
   820  							Value: &Ydb.Value_Uint64Value{
   821  								Uint64Value: 2,
   822  							},
   823  						}, {
   824  							Value: &Ydb.Value_TextValue{
   825  								TextValue: "2",
   826  							},
   827  						}, {
   828  							Value: &Ydb.Value_BoolValue{
   829  								BoolValue: false,
   830  							},
   831  						}},
   832  					},
   833  				},
   834  			},
   835  		}, nil)
   836  		r, err := newResult(ctx, stream, nil)
   837  		require.NoError(t, err)
   838  		defer r.Close(ctx)
   839  		{
   840  			t.Log("nextResultSet")
   841  			rs, err := r.nextResultSet(ctx)
   842  			require.NoError(t, err)
   843  			require.EqualValues(t, 0, rs.Index())
   844  			{
   845  				t.Log("next (row=1)")
   846  				_, err := rs.nextRow(ctx)
   847  				require.NoError(t, err)
   848  				require.EqualValues(t, 0, rs.rowIndex)
   849  			}
   850  			{
   851  				t.Log("next (row=2)")
   852  				_, err := rs.nextRow(ctx)
   853  				require.NoError(t, err)
   854  				require.EqualValues(t, 1, rs.rowIndex)
   855  			}
   856  			{
   857  				t.Log("next (row=3)")
   858  				_, err := rs.nextRow(ctx)
   859  				require.NoError(t, err)
   860  				require.EqualValues(t, 2, rs.rowIndex)
   861  			}
   862  			{
   863  				t.Log("next (row=4)")
   864  				_, err := rs.nextRow(ctx)
   865  				require.NoError(t, err)
   866  				require.EqualValues(t, 0, rs.rowIndex)
   867  			}
   868  			{
   869  				t.Log("next (row=5)")
   870  				_, err := rs.nextRow(ctx)
   871  				require.NoError(t, err)
   872  				require.EqualValues(t, 1, rs.rowIndex)
   873  			}
   874  			{
   875  				t.Log("next (row=6)")
   876  				_, err := rs.nextRow(ctx)
   877  				require.ErrorIs(t, err, io.EOF)
   878  			}
   879  		}
   880  		{
   881  			t.Log("nextResultSet")
   882  			rs, err := r.nextResultSet(ctx)
   883  			require.NoError(t, err)
   884  			require.EqualValues(t, 2, rs.Index())
   885  		}
   886  		{
   887  			t.Log("nextResultSet")
   888  			_, err := r.nextResultSet(ctx)
   889  			require.ErrorIs(t, err, errWrongNextResultSetIndex)
   890  		}
   891  	})
   892  }
   893  
   894  func TestExactlyOneRowFromResult(t *testing.T) {
   895  	ctx := xtest.Context(t)
   896  	t.Run("HappyWay", func(t *testing.T) {
   897  		ctrl := gomock.NewController(t)
   898  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
   899  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   900  			Status: Ydb.StatusIds_SUCCESS,
   901  			TxMeta: &Ydb_Query.TransactionMeta{
   902  				Id: "456",
   903  			},
   904  			ResultSetIndex: 0,
   905  			ResultSet: &Ydb.ResultSet{
   906  				Columns: []*Ydb.Column{
   907  					{
   908  						Name: "a",
   909  						Type: &Ydb.Type{
   910  							Type: &Ydb.Type_TypeId{
   911  								TypeId: Ydb.Type_UINT64,
   912  							},
   913  						},
   914  					},
   915  					{
   916  						Name: "b",
   917  						Type: &Ydb.Type{
   918  							Type: &Ydb.Type_TypeId{
   919  								TypeId: Ydb.Type_UTF8,
   920  							},
   921  						},
   922  					},
   923  				},
   924  				Rows: []*Ydb.Value{
   925  					{
   926  						Items: []*Ydb.Value{{
   927  							Value: &Ydb.Value_Uint64Value{
   928  								Uint64Value: 1,
   929  							},
   930  						}, {
   931  							Value: &Ydb.Value_TextValue{
   932  								TextValue: "1",
   933  							},
   934  						}},
   935  					},
   936  				},
   937  			},
   938  		}, nil)
   939  		stream.EXPECT().Recv().Return(nil, io.EOF)
   940  		r, err := newResult(ctx, stream, nil)
   941  		require.NoError(t, err)
   942  
   943  		row, err := exactlyOneRowFromResult(ctx, r)
   944  		require.NoError(t, err)
   945  		var (
   946  			a uint64
   947  			b string
   948  		)
   949  		err = row.Scan(&a, &b)
   950  		require.NoError(t, err)
   951  		require.EqualValues(t, 1, a)
   952  		require.EqualValues(t, "1", b)
   953  	})
   954  	t.Run("MoreThanOneRow", func(t *testing.T) {
   955  		ctrl := gomock.NewController(t)
   956  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
   957  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
   958  			Status: Ydb.StatusIds_SUCCESS,
   959  			TxMeta: &Ydb_Query.TransactionMeta{
   960  				Id: "456",
   961  			},
   962  			ResultSetIndex: 0,
   963  			ResultSet: &Ydb.ResultSet{
   964  				Columns: []*Ydb.Column{
   965  					{
   966  						Name: "a",
   967  						Type: &Ydb.Type{
   968  							Type: &Ydb.Type_TypeId{
   969  								TypeId: Ydb.Type_UINT64,
   970  							},
   971  						},
   972  					},
   973  					{
   974  						Name: "b",
   975  						Type: &Ydb.Type{
   976  							Type: &Ydb.Type_TypeId{
   977  								TypeId: Ydb.Type_UTF8,
   978  							},
   979  						},
   980  					},
   981  				},
   982  				Rows: []*Ydb.Value{
   983  					{
   984  						Items: []*Ydb.Value{{
   985  							Value: &Ydb.Value_Uint64Value{
   986  								Uint64Value: 1,
   987  							},
   988  						}, {
   989  							Value: &Ydb.Value_TextValue{
   990  								TextValue: "1",
   991  							},
   992  						}},
   993  					},
   994  					{
   995  						Items: []*Ydb.Value{{
   996  							Value: &Ydb.Value_Uint64Value{
   997  								Uint64Value: 2,
   998  							},
   999  						}, {
  1000  							Value: &Ydb.Value_TextValue{
  1001  								TextValue: "2",
  1002  							},
  1003  						}},
  1004  					},
  1005  				},
  1006  			},
  1007  		}, nil)
  1008  		r, err := newResult(ctx, stream, nil)
  1009  		require.NoError(t, err)
  1010  
  1011  		row, err := exactlyOneRowFromResult(ctx, r)
  1012  		require.ErrorIs(t, err, errMoreThanOneRow)
  1013  		require.Nil(t, row)
  1014  	})
  1015  	t.Run("MoreThanOneRowErrorOnNextRow", func(t *testing.T) {
  1016  		ctrl := gomock.NewController(t)
  1017  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  1018  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1019  			Status: Ydb.StatusIds_SUCCESS,
  1020  			TxMeta: &Ydb_Query.TransactionMeta{
  1021  				Id: "456",
  1022  			},
  1023  			ResultSetIndex: 0,
  1024  			ResultSet: &Ydb.ResultSet{
  1025  				Columns: []*Ydb.Column{
  1026  					{
  1027  						Name: "a",
  1028  						Type: &Ydb.Type{
  1029  							Type: &Ydb.Type_TypeId{
  1030  								TypeId: Ydb.Type_UINT64,
  1031  							},
  1032  						},
  1033  					},
  1034  					{
  1035  						Name: "b",
  1036  						Type: &Ydb.Type{
  1037  							Type: &Ydb.Type_TypeId{
  1038  								TypeId: Ydb.Type_UTF8,
  1039  							},
  1040  						},
  1041  					},
  1042  				},
  1043  				Rows: []*Ydb.Value{
  1044  					{
  1045  						Items: []*Ydb.Value{{
  1046  							Value: &Ydb.Value_Uint64Value{
  1047  								Uint64Value: 1,
  1048  							},
  1049  						}, {
  1050  							Value: &Ydb.Value_TextValue{
  1051  								TextValue: "1",
  1052  							},
  1053  						}},
  1054  					},
  1055  				},
  1056  			},
  1057  		}, nil)
  1058  		testErr := errors.New("test-err")
  1059  		stream.EXPECT().Recv().Return(nil, testErr)
  1060  		r, err := newResult(ctx, stream, nil)
  1061  		require.NoError(t, err)
  1062  
  1063  		row, err := exactlyOneRowFromResult(ctx, r)
  1064  		require.ErrorIs(t, err, testErr)
  1065  		require.Nil(t, row)
  1066  	})
  1067  	t.Run("MoreThanOneResultSet", func(t *testing.T) {
  1068  		ctrl := gomock.NewController(t)
  1069  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  1070  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1071  			Status: Ydb.StatusIds_SUCCESS,
  1072  			TxMeta: &Ydb_Query.TransactionMeta{
  1073  				Id: "456",
  1074  			},
  1075  			ResultSetIndex: 0,
  1076  			ResultSet: &Ydb.ResultSet{
  1077  				Columns: []*Ydb.Column{
  1078  					{
  1079  						Name: "a",
  1080  						Type: &Ydb.Type{
  1081  							Type: &Ydb.Type_TypeId{
  1082  								TypeId: Ydb.Type_UINT64,
  1083  							},
  1084  						},
  1085  					},
  1086  					{
  1087  						Name: "b",
  1088  						Type: &Ydb.Type{
  1089  							Type: &Ydb.Type_TypeId{
  1090  								TypeId: Ydb.Type_UTF8,
  1091  							},
  1092  						},
  1093  					},
  1094  				},
  1095  				Rows: []*Ydb.Value{
  1096  					{
  1097  						Items: []*Ydb.Value{{
  1098  							Value: &Ydb.Value_Uint64Value{
  1099  								Uint64Value: 1,
  1100  							},
  1101  						}, {
  1102  							Value: &Ydb.Value_TextValue{
  1103  								TextValue: "1",
  1104  							},
  1105  						}},
  1106  					},
  1107  				},
  1108  			},
  1109  		}, nil)
  1110  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1111  			Status: Ydb.StatusIds_SUCCESS,
  1112  			TxMeta: &Ydb_Query.TransactionMeta{
  1113  				Id: "456",
  1114  			},
  1115  			ResultSetIndex: 1,
  1116  			ResultSet: &Ydb.ResultSet{
  1117  				Columns: []*Ydb.Column{
  1118  					{
  1119  						Name: "a",
  1120  						Type: &Ydb.Type{
  1121  							Type: &Ydb.Type_TypeId{
  1122  								TypeId: Ydb.Type_UINT64,
  1123  							},
  1124  						},
  1125  					},
  1126  					{
  1127  						Name: "b",
  1128  						Type: &Ydb.Type{
  1129  							Type: &Ydb.Type_TypeId{
  1130  								TypeId: Ydb.Type_UTF8,
  1131  							},
  1132  						},
  1133  					},
  1134  				},
  1135  				Rows: []*Ydb.Value{
  1136  					{
  1137  						Items: []*Ydb.Value{{
  1138  							Value: &Ydb.Value_Uint64Value{
  1139  								Uint64Value: 1,
  1140  							},
  1141  						}, {
  1142  							Value: &Ydb.Value_TextValue{
  1143  								TextValue: "1",
  1144  							},
  1145  						}},
  1146  					},
  1147  				},
  1148  			},
  1149  		}, nil)
  1150  		r, err := newResult(ctx, stream, nil)
  1151  		require.NoError(t, err)
  1152  
  1153  		row, err := exactlyOneResultSetFromResult(ctx, r)
  1154  		require.ErrorIs(t, err, errMoreThanOneResultSet)
  1155  		require.Nil(t, row)
  1156  	})
  1157  	t.Run("MoreThanOneResultSetErrorOnNextResultSet", func(t *testing.T) {
  1158  		ctrl := gomock.NewController(t)
  1159  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  1160  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1161  			Status: Ydb.StatusIds_SUCCESS,
  1162  			TxMeta: &Ydb_Query.TransactionMeta{
  1163  				Id: "456",
  1164  			},
  1165  			ResultSetIndex: 0,
  1166  			ResultSet: &Ydb.ResultSet{
  1167  				Columns: []*Ydb.Column{
  1168  					{
  1169  						Name: "a",
  1170  						Type: &Ydb.Type{
  1171  							Type: &Ydb.Type_TypeId{
  1172  								TypeId: Ydb.Type_UINT64,
  1173  							},
  1174  						},
  1175  					},
  1176  					{
  1177  						Name: "b",
  1178  						Type: &Ydb.Type{
  1179  							Type: &Ydb.Type_TypeId{
  1180  								TypeId: Ydb.Type_UTF8,
  1181  							},
  1182  						},
  1183  					},
  1184  				},
  1185  				Rows: []*Ydb.Value{
  1186  					{
  1187  						Items: []*Ydb.Value{{
  1188  							Value: &Ydb.Value_Uint64Value{
  1189  								Uint64Value: 1,
  1190  							},
  1191  						}, {
  1192  							Value: &Ydb.Value_TextValue{
  1193  								TextValue: "1",
  1194  							},
  1195  						}},
  1196  					},
  1197  				},
  1198  			},
  1199  		}, nil)
  1200  		testErr := errors.New("test-err")
  1201  		stream.EXPECT().Recv().Return(nil, testErr)
  1202  		r, err := newResult(ctx, stream, nil)
  1203  		require.NoError(t, err)
  1204  
  1205  		row, err := exactlyOneRowFromResult(ctx, r)
  1206  		require.ErrorIs(t, err, testErr)
  1207  		require.Nil(t, row)
  1208  	})
  1209  }
  1210  
  1211  func TestExactlyOneResultSetFromResult(t *testing.T) {
  1212  	ctx := xtest.Context(t)
  1213  	t.Run("HappyWay", func(t *testing.T) {
  1214  		ctrl := gomock.NewController(t)
  1215  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  1216  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1217  			Status: Ydb.StatusIds_SUCCESS,
  1218  			TxMeta: &Ydb_Query.TransactionMeta{
  1219  				Id: "456",
  1220  			},
  1221  			ResultSetIndex: 0,
  1222  			ResultSet: &Ydb.ResultSet{
  1223  				Columns: []*Ydb.Column{
  1224  					{
  1225  						Name: "a",
  1226  						Type: &Ydb.Type{
  1227  							Type: &Ydb.Type_TypeId{
  1228  								TypeId: Ydb.Type_UINT64,
  1229  							},
  1230  						},
  1231  					},
  1232  					{
  1233  						Name: "b",
  1234  						Type: &Ydb.Type{
  1235  							Type: &Ydb.Type_TypeId{
  1236  								TypeId: Ydb.Type_UTF8,
  1237  							},
  1238  						},
  1239  					},
  1240  				},
  1241  				Rows: []*Ydb.Value{
  1242  					{
  1243  						Items: []*Ydb.Value{{
  1244  							Value: &Ydb.Value_Uint64Value{
  1245  								Uint64Value: 1,
  1246  							},
  1247  						}, {
  1248  							Value: &Ydb.Value_TextValue{
  1249  								TextValue: "1",
  1250  							},
  1251  						}},
  1252  					},
  1253  					{
  1254  						Items: []*Ydb.Value{{
  1255  							Value: &Ydb.Value_Uint64Value{
  1256  								Uint64Value: 2,
  1257  							},
  1258  						}, {
  1259  							Value: &Ydb.Value_TextValue{
  1260  								TextValue: "2",
  1261  							},
  1262  						}},
  1263  					},
  1264  				},
  1265  			},
  1266  		}, nil)
  1267  		stream.EXPECT().Recv().Return(nil, io.EOF)
  1268  		r, err := newResult(ctx, stream, nil)
  1269  		require.NoError(t, err)
  1270  
  1271  		rs, err := exactlyOneResultSetFromResult(ctx, r)
  1272  		require.NoError(t, err)
  1273  		var (
  1274  			a uint64
  1275  			b string
  1276  		)
  1277  		r1, err1 := rs.NextRow(ctx)
  1278  		require.NoError(t, err1)
  1279  		require.NotNil(t, r1)
  1280  		scanErr1 := r1.Scan(&a, &b)
  1281  		require.NoError(t, scanErr1)
  1282  		require.EqualValues(t, 1, a)
  1283  		require.EqualValues(t, "1", b)
  1284  		r2, err2 := rs.NextRow(ctx)
  1285  		require.NoError(t, err2)
  1286  		require.NotNil(t, r2)
  1287  		scanErr2 := r2.Scan(&a, &b)
  1288  		require.NoError(t, scanErr2)
  1289  		require.EqualValues(t, 2, a)
  1290  		require.EqualValues(t, "2", b)
  1291  		r3, err3 := rs.NextRow(ctx)
  1292  		require.ErrorIs(t, err3, io.EOF)
  1293  		require.Nil(t, r3)
  1294  	})
  1295  	t.Run("MoreThanOneResultSet", func(t *testing.T) {
  1296  		ctrl := gomock.NewController(t)
  1297  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  1298  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1299  			Status: Ydb.StatusIds_SUCCESS,
  1300  			TxMeta: &Ydb_Query.TransactionMeta{
  1301  				Id: "456",
  1302  			},
  1303  			ResultSetIndex: 0,
  1304  			ResultSet: &Ydb.ResultSet{
  1305  				Columns: []*Ydb.Column{
  1306  					{
  1307  						Name: "a",
  1308  						Type: &Ydb.Type{
  1309  							Type: &Ydb.Type_TypeId{
  1310  								TypeId: Ydb.Type_UINT64,
  1311  							},
  1312  						},
  1313  					},
  1314  					{
  1315  						Name: "b",
  1316  						Type: &Ydb.Type{
  1317  							Type: &Ydb.Type_TypeId{
  1318  								TypeId: Ydb.Type_UTF8,
  1319  							},
  1320  						},
  1321  					},
  1322  				},
  1323  				Rows: []*Ydb.Value{
  1324  					{
  1325  						Items: []*Ydb.Value{{
  1326  							Value: &Ydb.Value_Uint64Value{
  1327  								Uint64Value: 1,
  1328  							},
  1329  						}, {
  1330  							Value: &Ydb.Value_TextValue{
  1331  								TextValue: "1",
  1332  							},
  1333  						}},
  1334  					},
  1335  				},
  1336  			},
  1337  		}, nil)
  1338  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1339  			Status: Ydb.StatusIds_SUCCESS,
  1340  			TxMeta: &Ydb_Query.TransactionMeta{
  1341  				Id: "456",
  1342  			},
  1343  			ResultSetIndex: 1,
  1344  			ResultSet: &Ydb.ResultSet{
  1345  				Columns: []*Ydb.Column{
  1346  					{
  1347  						Name: "a",
  1348  						Type: &Ydb.Type{
  1349  							Type: &Ydb.Type_TypeId{
  1350  								TypeId: Ydb.Type_UINT64,
  1351  							},
  1352  						},
  1353  					},
  1354  					{
  1355  						Name: "b",
  1356  						Type: &Ydb.Type{
  1357  							Type: &Ydb.Type_TypeId{
  1358  								TypeId: Ydb.Type_UTF8,
  1359  							},
  1360  						},
  1361  					},
  1362  				},
  1363  				Rows: []*Ydb.Value{
  1364  					{
  1365  						Items: []*Ydb.Value{{
  1366  							Value: &Ydb.Value_Uint64Value{
  1367  								Uint64Value: 1,
  1368  							},
  1369  						}, {
  1370  							Value: &Ydb.Value_TextValue{
  1371  								TextValue: "1",
  1372  							},
  1373  						}},
  1374  					},
  1375  				},
  1376  			},
  1377  		}, nil)
  1378  		r, err := newResult(ctx, stream, nil)
  1379  		require.NoError(t, err)
  1380  
  1381  		rs, err := exactlyOneResultSetFromResult(ctx, r)
  1382  		require.ErrorIs(t, err, errMoreThanOneResultSet)
  1383  		require.Nil(t, rs)
  1384  	})
  1385  	t.Run("MoreThanOneResultSetErrorOnNextResultSet", func(t *testing.T) {
  1386  		ctrl := gomock.NewController(t)
  1387  		stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  1388  		stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1389  			Status: Ydb.StatusIds_SUCCESS,
  1390  			TxMeta: &Ydb_Query.TransactionMeta{
  1391  				Id: "456",
  1392  			},
  1393  			ResultSetIndex: 0,
  1394  			ResultSet: &Ydb.ResultSet{
  1395  				Columns: []*Ydb.Column{
  1396  					{
  1397  						Name: "a",
  1398  						Type: &Ydb.Type{
  1399  							Type: &Ydb.Type_TypeId{
  1400  								TypeId: Ydb.Type_UINT64,
  1401  							},
  1402  						},
  1403  					},
  1404  					{
  1405  						Name: "b",
  1406  						Type: &Ydb.Type{
  1407  							Type: &Ydb.Type_TypeId{
  1408  								TypeId: Ydb.Type_UTF8,
  1409  							},
  1410  						},
  1411  					},
  1412  				},
  1413  				Rows: []*Ydb.Value{
  1414  					{
  1415  						Items: []*Ydb.Value{{
  1416  							Value: &Ydb.Value_Uint64Value{
  1417  								Uint64Value: 1,
  1418  							},
  1419  						}, {
  1420  							Value: &Ydb.Value_TextValue{
  1421  								TextValue: "1",
  1422  							},
  1423  						}},
  1424  					},
  1425  				},
  1426  			},
  1427  		}, nil)
  1428  		testErr := errors.New("test-err")
  1429  		stream.EXPECT().Recv().Return(nil, testErr)
  1430  		r, err := newResult(ctx, stream, nil)
  1431  		require.NoError(t, err)
  1432  
  1433  		rs, err := exactlyOneResultSetFromResult(ctx, r)
  1434  		require.ErrorIs(t, err, testErr)
  1435  		require.Nil(t, rs)
  1436  	})
  1437  }
  1438  
  1439  func TestCloseResultOnCloseClosableResultSet(t *testing.T) {
  1440  	ctx := xtest.Context(t)
  1441  	ctrl := gomock.NewController(t)
  1442  	stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  1443  	stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1444  		Status: Ydb.StatusIds_SUCCESS,
  1445  		TxMeta: &Ydb_Query.TransactionMeta{
  1446  			Id: "456",
  1447  		},
  1448  		ResultSetIndex: 0,
  1449  		ResultSet: &Ydb.ResultSet{
  1450  			Columns: []*Ydb.Column{
  1451  				{
  1452  					Name: "a",
  1453  					Type: &Ydb.Type{
  1454  						Type: &Ydb.Type_TypeId{
  1455  							TypeId: Ydb.Type_UINT64,
  1456  						},
  1457  					},
  1458  				},
  1459  				{
  1460  					Name: "b",
  1461  					Type: &Ydb.Type{
  1462  						Type: &Ydb.Type_TypeId{
  1463  							TypeId: Ydb.Type_UTF8,
  1464  						},
  1465  					},
  1466  				},
  1467  			},
  1468  			Rows: []*Ydb.Value{
  1469  				{
  1470  					Items: []*Ydb.Value{{
  1471  						Value: &Ydb.Value_Uint64Value{
  1472  							Uint64Value: 1,
  1473  						},
  1474  					}, {
  1475  						Value: &Ydb.Value_TextValue{
  1476  							TextValue: "1",
  1477  						},
  1478  					}},
  1479  				},
  1480  				{
  1481  					Items: []*Ydb.Value{{
  1482  						Value: &Ydb.Value_Uint64Value{
  1483  							Uint64Value: 2,
  1484  						},
  1485  					}, {
  1486  						Value: &Ydb.Value_TextValue{
  1487  							TextValue: "2",
  1488  						},
  1489  					}},
  1490  				},
  1491  			},
  1492  		},
  1493  	}, nil)
  1494  	stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1495  		Status: Ydb.StatusIds_SUCCESS,
  1496  		TxMeta: &Ydb_Query.TransactionMeta{
  1497  			Id: "456",
  1498  		},
  1499  		ResultSetIndex: 0,
  1500  		ResultSet: &Ydb.ResultSet{
  1501  			Columns: []*Ydb.Column{
  1502  				{
  1503  					Name: "a",
  1504  					Type: &Ydb.Type{
  1505  						Type: &Ydb.Type_TypeId{
  1506  							TypeId: Ydb.Type_UINT64,
  1507  						},
  1508  					},
  1509  				},
  1510  				{
  1511  					Name: "b",
  1512  					Type: &Ydb.Type{
  1513  						Type: &Ydb.Type_TypeId{
  1514  							TypeId: Ydb.Type_UTF8,
  1515  						},
  1516  					},
  1517  				},
  1518  			},
  1519  			Rows: []*Ydb.Value{
  1520  				{
  1521  					Items: []*Ydb.Value{{
  1522  						Value: &Ydb.Value_Uint64Value{
  1523  							Uint64Value: 1,
  1524  						},
  1525  					}, {
  1526  						Value: &Ydb.Value_TextValue{
  1527  							TextValue: "1",
  1528  						},
  1529  					}},
  1530  				},
  1531  				{
  1532  					Items: []*Ydb.Value{{
  1533  						Value: &Ydb.Value_Uint64Value{
  1534  							Uint64Value: 2,
  1535  						},
  1536  					}, {
  1537  						Value: &Ydb.Value_TextValue{
  1538  							TextValue: "2",
  1539  						},
  1540  					}},
  1541  				},
  1542  			},
  1543  		},
  1544  	}, nil)
  1545  	stream.EXPECT().Recv().Return(nil, io.EOF)
  1546  	var closed bool
  1547  	r, err := newResult(ctx, stream, withTrace(&trace.Query{
  1548  		OnResultClose: func(info trace.QueryResultCloseStartInfo) func(info trace.QueryResultCloseDoneInfo) {
  1549  			require.False(t, closed)
  1550  			closed = true
  1551  
  1552  			return nil
  1553  		},
  1554  	}))
  1555  
  1556  	require.NoError(t, err)
  1557  
  1558  	rs, err := readResultSet(ctx, r)
  1559  	require.NoError(t, err)
  1560  	var (
  1561  		a uint64
  1562  		b string
  1563  	)
  1564  	r1, err1 := rs.NextRow(ctx)
  1565  	require.NoError(t, err1)
  1566  	require.NotNil(t, r1)
  1567  	scanErr1 := r1.Scan(&a, &b)
  1568  	require.NoError(t, scanErr1)
  1569  	require.EqualValues(t, 1, a)
  1570  	require.EqualValues(t, "1", b)
  1571  	r2, err2 := rs.NextRow(ctx)
  1572  	require.NoError(t, err2)
  1573  	require.NotNil(t, r2)
  1574  	scanErr2 := r2.Scan(&a, &b)
  1575  	require.NoError(t, scanErr2)
  1576  	require.EqualValues(t, 2, a)
  1577  	require.EqualValues(t, "2", b)
  1578  	r3, err3 := rs.NextRow(ctx)
  1579  	require.ErrorIs(t, err3, io.EOF)
  1580  	require.Nil(t, r3)
  1581  	err = rs.Close(ctx)
  1582  	require.NoError(t, err)
  1583  	require.True(t, closed)
  1584  }
  1585  
  1586  func TestResultStats(t *testing.T) {
  1587  	t.Run("Stats", func(t *testing.T) {
  1588  		t.Run("Never", func(t *testing.T) {
  1589  			ctx, cancel := context.WithCancel(xtest.Context(t))
  1590  			defer cancel()
  1591  			ctrl := gomock.NewController(t)
  1592  			stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  1593  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1594  				Status:         Ydb.StatusIds_SUCCESS,
  1595  				ResultSetIndex: 0,
  1596  				ResultSet: &Ydb.ResultSet{
  1597  					Columns: []*Ydb.Column{
  1598  						{
  1599  							Name: "a",
  1600  							Type: &Ydb.Type{
  1601  								Type: &Ydb.Type_TypeId{
  1602  									TypeId: Ydb.Type_UINT64,
  1603  								},
  1604  							},
  1605  						},
  1606  						{
  1607  							Name: "b",
  1608  							Type: &Ydb.Type{
  1609  								Type: &Ydb.Type_TypeId{
  1610  									TypeId: Ydb.Type_UTF8,
  1611  								},
  1612  							},
  1613  						},
  1614  					},
  1615  					Rows: []*Ydb.Value{
  1616  						{
  1617  							Items: []*Ydb.Value{{
  1618  								Value: &Ydb.Value_Uint64Value{
  1619  									Uint64Value: 1,
  1620  								},
  1621  							}, {
  1622  								Value: &Ydb.Value_TextValue{
  1623  									TextValue: "1",
  1624  								},
  1625  							}},
  1626  						},
  1627  						{
  1628  							Items: []*Ydb.Value{{
  1629  								Value: &Ydb.Value_Uint64Value{
  1630  									Uint64Value: 2,
  1631  								},
  1632  							}, {
  1633  								Value: &Ydb.Value_TextValue{
  1634  									TextValue: "2",
  1635  								},
  1636  							}},
  1637  						},
  1638  						{
  1639  							Items: []*Ydb.Value{{
  1640  								Value: &Ydb.Value_Uint64Value{
  1641  									Uint64Value: 3,
  1642  								},
  1643  							}, {
  1644  								Value: &Ydb.Value_TextValue{
  1645  									TextValue: "3",
  1646  								},
  1647  							}},
  1648  						},
  1649  					},
  1650  				},
  1651  			}, nil)
  1652  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1653  				Status:         Ydb.StatusIds_SUCCESS,
  1654  				ResultSetIndex: 0,
  1655  				ResultSet: &Ydb.ResultSet{
  1656  					Rows: []*Ydb.Value{
  1657  						{
  1658  							Items: []*Ydb.Value{{
  1659  								Value: &Ydb.Value_Uint64Value{
  1660  									Uint64Value: 4,
  1661  								},
  1662  							}, {
  1663  								Value: &Ydb.Value_TextValue{
  1664  									TextValue: "4",
  1665  								},
  1666  							}},
  1667  						},
  1668  						{
  1669  							Items: []*Ydb.Value{{
  1670  								Value: &Ydb.Value_Uint64Value{
  1671  									Uint64Value: 5,
  1672  								},
  1673  							}, {
  1674  								Value: &Ydb.Value_TextValue{
  1675  									TextValue: "5",
  1676  								},
  1677  							}},
  1678  						},
  1679  					},
  1680  				},
  1681  			}, nil)
  1682  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1683  				Status:         Ydb.StatusIds_SUCCESS,
  1684  				ResultSetIndex: 1,
  1685  				ResultSet: &Ydb.ResultSet{
  1686  					Columns: []*Ydb.Column{
  1687  						{
  1688  							Name: "c",
  1689  							Type: &Ydb.Type{
  1690  								Type: &Ydb.Type_TypeId{
  1691  									TypeId: Ydb.Type_UINT64,
  1692  								},
  1693  							},
  1694  						},
  1695  						{
  1696  							Name: "d",
  1697  							Type: &Ydb.Type{
  1698  								Type: &Ydb.Type_TypeId{
  1699  									TypeId: Ydb.Type_UTF8,
  1700  								},
  1701  							},
  1702  						},
  1703  						{
  1704  							Name: "e",
  1705  							Type: &Ydb.Type{
  1706  								Type: &Ydb.Type_TypeId{
  1707  									TypeId: Ydb.Type_BOOL,
  1708  								},
  1709  							},
  1710  						},
  1711  					},
  1712  					Rows: []*Ydb.Value{
  1713  						{
  1714  							Items: []*Ydb.Value{{
  1715  								Value: &Ydb.Value_Uint64Value{
  1716  									Uint64Value: 1,
  1717  								},
  1718  							}, {
  1719  								Value: &Ydb.Value_TextValue{
  1720  									TextValue: "1",
  1721  								},
  1722  							}, {
  1723  								Value: &Ydb.Value_BoolValue{
  1724  									BoolValue: true,
  1725  								},
  1726  							}},
  1727  						},
  1728  						{
  1729  							Items: []*Ydb.Value{{
  1730  								Value: &Ydb.Value_Uint64Value{
  1731  									Uint64Value: 2,
  1732  								},
  1733  							}, {
  1734  								Value: &Ydb.Value_TextValue{
  1735  									TextValue: "2",
  1736  								},
  1737  							}, {
  1738  								Value: &Ydb.Value_BoolValue{
  1739  									BoolValue: false,
  1740  								},
  1741  							}},
  1742  						},
  1743  					},
  1744  				},
  1745  			}, nil)
  1746  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1747  				Status:         Ydb.StatusIds_SUCCESS,
  1748  				ResultSetIndex: 1,
  1749  				ResultSet: &Ydb.ResultSet{
  1750  					Rows: []*Ydb.Value{
  1751  						{
  1752  							Items: []*Ydb.Value{{
  1753  								Value: &Ydb.Value_Uint64Value{
  1754  									Uint64Value: 3,
  1755  								},
  1756  							}, {
  1757  								Value: &Ydb.Value_TextValue{
  1758  									TextValue: "3",
  1759  								},
  1760  							}, {
  1761  								Value: &Ydb.Value_BoolValue{
  1762  									BoolValue: true,
  1763  								},
  1764  							}},
  1765  						},
  1766  						{
  1767  							Items: []*Ydb.Value{{
  1768  								Value: &Ydb.Value_Uint64Value{
  1769  									Uint64Value: 4,
  1770  								},
  1771  							}, {
  1772  								Value: &Ydb.Value_TextValue{
  1773  									TextValue: "4",
  1774  								},
  1775  							}, {
  1776  								Value: &Ydb.Value_BoolValue{
  1777  									BoolValue: false,
  1778  								},
  1779  							}},
  1780  						},
  1781  						{
  1782  							Items: []*Ydb.Value{{
  1783  								Value: &Ydb.Value_Uint64Value{
  1784  									Uint64Value: 5,
  1785  								},
  1786  							}, {
  1787  								Value: &Ydb.Value_TextValue{
  1788  									TextValue: "5",
  1789  								},
  1790  							}, {
  1791  								Value: &Ydb.Value_BoolValue{
  1792  									BoolValue: false,
  1793  								},
  1794  							}},
  1795  						},
  1796  					},
  1797  				},
  1798  			}, nil)
  1799  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1800  				Status:         Ydb.StatusIds_SUCCESS,
  1801  				ResultSetIndex: 2,
  1802  				ResultSet: &Ydb.ResultSet{
  1803  					Columns: []*Ydb.Column{
  1804  						{
  1805  							Name: "c",
  1806  							Type: &Ydb.Type{
  1807  								Type: &Ydb.Type_TypeId{
  1808  									TypeId: Ydb.Type_UINT64,
  1809  								},
  1810  							},
  1811  						},
  1812  						{
  1813  							Name: "d",
  1814  							Type: &Ydb.Type{
  1815  								Type: &Ydb.Type_TypeId{
  1816  									TypeId: Ydb.Type_UTF8,
  1817  								},
  1818  							},
  1819  						},
  1820  						{
  1821  							Name: "e",
  1822  							Type: &Ydb.Type{
  1823  								Type: &Ydb.Type_TypeId{
  1824  									TypeId: Ydb.Type_BOOL,
  1825  								},
  1826  							},
  1827  						},
  1828  					},
  1829  					Rows: []*Ydb.Value{
  1830  						{
  1831  							Items: []*Ydb.Value{{
  1832  								Value: &Ydb.Value_Uint64Value{
  1833  									Uint64Value: 1,
  1834  								},
  1835  							}, {
  1836  								Value: &Ydb.Value_TextValue{
  1837  									TextValue: "1",
  1838  								},
  1839  							}, {
  1840  								Value: &Ydb.Value_BoolValue{
  1841  									BoolValue: true,
  1842  								},
  1843  							}},
  1844  						},
  1845  						{
  1846  							Items: []*Ydb.Value{{
  1847  								Value: &Ydb.Value_Uint64Value{
  1848  									Uint64Value: 2,
  1849  								},
  1850  							}, {
  1851  								Value: &Ydb.Value_TextValue{
  1852  									TextValue: "2",
  1853  								},
  1854  							}, {
  1855  								Value: &Ydb.Value_BoolValue{
  1856  									BoolValue: false,
  1857  								},
  1858  							}},
  1859  						},
  1860  					},
  1861  				},
  1862  			}, nil)
  1863  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1864  				Status:         Ydb.StatusIds_SUCCESS,
  1865  				ResultSetIndex: 2,
  1866  				ResultSet: &Ydb.ResultSet{
  1867  					Rows: []*Ydb.Value{
  1868  						{
  1869  							Items: []*Ydb.Value{{
  1870  								Value: &Ydb.Value_Uint64Value{
  1871  									Uint64Value: 3,
  1872  								},
  1873  							}, {
  1874  								Value: &Ydb.Value_TextValue{
  1875  									TextValue: "3",
  1876  								},
  1877  							}, {
  1878  								Value: &Ydb.Value_BoolValue{
  1879  									BoolValue: true,
  1880  								},
  1881  							}},
  1882  						},
  1883  						{
  1884  							Items: []*Ydb.Value{{
  1885  								Value: &Ydb.Value_Uint64Value{
  1886  									Uint64Value: 4,
  1887  								},
  1888  							}, {
  1889  								Value: &Ydb.Value_TextValue{
  1890  									TextValue: "4",
  1891  								},
  1892  							}, {
  1893  								Value: &Ydb.Value_BoolValue{
  1894  									BoolValue: false,
  1895  								},
  1896  							}},
  1897  						},
  1898  						{
  1899  							Items: []*Ydb.Value{{
  1900  								Value: &Ydb.Value_Uint64Value{
  1901  									Uint64Value: 5,
  1902  								},
  1903  							}, {
  1904  								Value: &Ydb.Value_TextValue{
  1905  									TextValue: "5",
  1906  								},
  1907  							}, {
  1908  								Value: &Ydb.Value_BoolValue{
  1909  									BoolValue: false,
  1910  								},
  1911  							}},
  1912  						},
  1913  					},
  1914  				},
  1915  			}, nil)
  1916  			stream.EXPECT().Recv().Return(nil, io.EOF)
  1917  			var s stats.QueryStats
  1918  			result, err := newResult(ctx, stream, withStatsCallback(func(queryStats stats.QueryStats) {
  1919  				s = queryStats
  1920  			}))
  1921  			require.NoError(t, err)
  1922  			require.NotNil(t, result)
  1923  			defer result.Close(ctx)
  1924  			for {
  1925  				resultSet, err := result.nextResultSet(ctx)
  1926  				if err != nil && xerrors.Is(err, io.EOF) {
  1927  					break
  1928  				}
  1929  				for {
  1930  					_, err := resultSet.nextRow(ctx)
  1931  					if err != nil && xerrors.Is(err, io.EOF) {
  1932  						break
  1933  					}
  1934  				}
  1935  			}
  1936  			require.Nil(t, s)
  1937  		})
  1938  		t.Run("SeparatedLastPart", func(t *testing.T) {
  1939  			ctx, cancel := context.WithCancel(xtest.Context(t))
  1940  			defer cancel()
  1941  			ctrl := gomock.NewController(t)
  1942  			stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  1943  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  1944  				Status:         Ydb.StatusIds_SUCCESS,
  1945  				ResultSetIndex: 0,
  1946  				ResultSet: &Ydb.ResultSet{
  1947  					Columns: []*Ydb.Column{
  1948  						{
  1949  							Name: "a",
  1950  							Type: &Ydb.Type{
  1951  								Type: &Ydb.Type_TypeId{
  1952  									TypeId: Ydb.Type_UINT64,
  1953  								},
  1954  							},
  1955  						},
  1956  						{
  1957  							Name: "b",
  1958  							Type: &Ydb.Type{
  1959  								Type: &Ydb.Type_TypeId{
  1960  									TypeId: Ydb.Type_UTF8,
  1961  								},
  1962  							},
  1963  						},
  1964  					},
  1965  					Rows: []*Ydb.Value{
  1966  						{
  1967  							Items: []*Ydb.Value{{
  1968  								Value: &Ydb.Value_Uint64Value{
  1969  									Uint64Value: 1,
  1970  								},
  1971  							}, {
  1972  								Value: &Ydb.Value_TextValue{
  1973  									TextValue: "1",
  1974  								},
  1975  							}},
  1976  						},
  1977  						{
  1978  							Items: []*Ydb.Value{{
  1979  								Value: &Ydb.Value_Uint64Value{
  1980  									Uint64Value: 2,
  1981  								},
  1982  							}, {
  1983  								Value: &Ydb.Value_TextValue{
  1984  									TextValue: "2",
  1985  								},
  1986  							}},
  1987  						},
  1988  						{
  1989  							Items: []*Ydb.Value{{
  1990  								Value: &Ydb.Value_Uint64Value{
  1991  									Uint64Value: 3,
  1992  								},
  1993  							}, {
  1994  								Value: &Ydb.Value_TextValue{
  1995  									TextValue: "3",
  1996  								},
  1997  							}},
  1998  						},
  1999  					},
  2000  				},
  2001  			}, nil)
  2002  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2003  				Status:         Ydb.StatusIds_SUCCESS,
  2004  				ResultSetIndex: 0,
  2005  				ResultSet: &Ydb.ResultSet{
  2006  					Rows: []*Ydb.Value{
  2007  						{
  2008  							Items: []*Ydb.Value{{
  2009  								Value: &Ydb.Value_Uint64Value{
  2010  									Uint64Value: 4,
  2011  								},
  2012  							}, {
  2013  								Value: &Ydb.Value_TextValue{
  2014  									TextValue: "4",
  2015  								},
  2016  							}},
  2017  						},
  2018  						{
  2019  							Items: []*Ydb.Value{{
  2020  								Value: &Ydb.Value_Uint64Value{
  2021  									Uint64Value: 5,
  2022  								},
  2023  							}, {
  2024  								Value: &Ydb.Value_TextValue{
  2025  									TextValue: "5",
  2026  								},
  2027  							}},
  2028  						},
  2029  					},
  2030  				},
  2031  			}, nil)
  2032  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2033  				Status:         Ydb.StatusIds_SUCCESS,
  2034  				ResultSetIndex: 1,
  2035  				ResultSet: &Ydb.ResultSet{
  2036  					Columns: []*Ydb.Column{
  2037  						{
  2038  							Name: "c",
  2039  							Type: &Ydb.Type{
  2040  								Type: &Ydb.Type_TypeId{
  2041  									TypeId: Ydb.Type_UINT64,
  2042  								},
  2043  							},
  2044  						},
  2045  						{
  2046  							Name: "d",
  2047  							Type: &Ydb.Type{
  2048  								Type: &Ydb.Type_TypeId{
  2049  									TypeId: Ydb.Type_UTF8,
  2050  								},
  2051  							},
  2052  						},
  2053  						{
  2054  							Name: "e",
  2055  							Type: &Ydb.Type{
  2056  								Type: &Ydb.Type_TypeId{
  2057  									TypeId: Ydb.Type_BOOL,
  2058  								},
  2059  							},
  2060  						},
  2061  					},
  2062  					Rows: []*Ydb.Value{
  2063  						{
  2064  							Items: []*Ydb.Value{{
  2065  								Value: &Ydb.Value_Uint64Value{
  2066  									Uint64Value: 1,
  2067  								},
  2068  							}, {
  2069  								Value: &Ydb.Value_TextValue{
  2070  									TextValue: "1",
  2071  								},
  2072  							}, {
  2073  								Value: &Ydb.Value_BoolValue{
  2074  									BoolValue: true,
  2075  								},
  2076  							}},
  2077  						},
  2078  						{
  2079  							Items: []*Ydb.Value{{
  2080  								Value: &Ydb.Value_Uint64Value{
  2081  									Uint64Value: 2,
  2082  								},
  2083  							}, {
  2084  								Value: &Ydb.Value_TextValue{
  2085  									TextValue: "2",
  2086  								},
  2087  							}, {
  2088  								Value: &Ydb.Value_BoolValue{
  2089  									BoolValue: false,
  2090  								},
  2091  							}},
  2092  						},
  2093  					},
  2094  				},
  2095  			}, nil)
  2096  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2097  				Status:         Ydb.StatusIds_SUCCESS,
  2098  				ResultSetIndex: 1,
  2099  				ResultSet: &Ydb.ResultSet{
  2100  					Rows: []*Ydb.Value{
  2101  						{
  2102  							Items: []*Ydb.Value{{
  2103  								Value: &Ydb.Value_Uint64Value{
  2104  									Uint64Value: 3,
  2105  								},
  2106  							}, {
  2107  								Value: &Ydb.Value_TextValue{
  2108  									TextValue: "3",
  2109  								},
  2110  							}, {
  2111  								Value: &Ydb.Value_BoolValue{
  2112  									BoolValue: true,
  2113  								},
  2114  							}},
  2115  						},
  2116  						{
  2117  							Items: []*Ydb.Value{{
  2118  								Value: &Ydb.Value_Uint64Value{
  2119  									Uint64Value: 4,
  2120  								},
  2121  							}, {
  2122  								Value: &Ydb.Value_TextValue{
  2123  									TextValue: "4",
  2124  								},
  2125  							}, {
  2126  								Value: &Ydb.Value_BoolValue{
  2127  									BoolValue: false,
  2128  								},
  2129  							}},
  2130  						},
  2131  						{
  2132  							Items: []*Ydb.Value{{
  2133  								Value: &Ydb.Value_Uint64Value{
  2134  									Uint64Value: 5,
  2135  								},
  2136  							}, {
  2137  								Value: &Ydb.Value_TextValue{
  2138  									TextValue: "5",
  2139  								},
  2140  							}, {
  2141  								Value: &Ydb.Value_BoolValue{
  2142  									BoolValue: false,
  2143  								},
  2144  							}},
  2145  						},
  2146  					},
  2147  				},
  2148  			}, nil)
  2149  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2150  				Status:         Ydb.StatusIds_SUCCESS,
  2151  				ResultSetIndex: 2,
  2152  				ResultSet: &Ydb.ResultSet{
  2153  					Columns: []*Ydb.Column{
  2154  						{
  2155  							Name: "c",
  2156  							Type: &Ydb.Type{
  2157  								Type: &Ydb.Type_TypeId{
  2158  									TypeId: Ydb.Type_UINT64,
  2159  								},
  2160  							},
  2161  						},
  2162  						{
  2163  							Name: "d",
  2164  							Type: &Ydb.Type{
  2165  								Type: &Ydb.Type_TypeId{
  2166  									TypeId: Ydb.Type_UTF8,
  2167  								},
  2168  							},
  2169  						},
  2170  						{
  2171  							Name: "e",
  2172  							Type: &Ydb.Type{
  2173  								Type: &Ydb.Type_TypeId{
  2174  									TypeId: Ydb.Type_BOOL,
  2175  								},
  2176  							},
  2177  						},
  2178  					},
  2179  					Rows: []*Ydb.Value{
  2180  						{
  2181  							Items: []*Ydb.Value{{
  2182  								Value: &Ydb.Value_Uint64Value{
  2183  									Uint64Value: 1,
  2184  								},
  2185  							}, {
  2186  								Value: &Ydb.Value_TextValue{
  2187  									TextValue: "1",
  2188  								},
  2189  							}, {
  2190  								Value: &Ydb.Value_BoolValue{
  2191  									BoolValue: true,
  2192  								},
  2193  							}},
  2194  						},
  2195  						{
  2196  							Items: []*Ydb.Value{{
  2197  								Value: &Ydb.Value_Uint64Value{
  2198  									Uint64Value: 2,
  2199  								},
  2200  							}, {
  2201  								Value: &Ydb.Value_TextValue{
  2202  									TextValue: "2",
  2203  								},
  2204  							}, {
  2205  								Value: &Ydb.Value_BoolValue{
  2206  									BoolValue: false,
  2207  								},
  2208  							}},
  2209  						},
  2210  					},
  2211  				},
  2212  			}, nil)
  2213  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2214  				Status:         Ydb.StatusIds_SUCCESS,
  2215  				ResultSetIndex: 2,
  2216  				ResultSet: &Ydb.ResultSet{
  2217  					Rows: []*Ydb.Value{
  2218  						{
  2219  							Items: []*Ydb.Value{{
  2220  								Value: &Ydb.Value_Uint64Value{
  2221  									Uint64Value: 3,
  2222  								},
  2223  							}, {
  2224  								Value: &Ydb.Value_TextValue{
  2225  									TextValue: "3",
  2226  								},
  2227  							}, {
  2228  								Value: &Ydb.Value_BoolValue{
  2229  									BoolValue: true,
  2230  								},
  2231  							}},
  2232  						},
  2233  						{
  2234  							Items: []*Ydb.Value{{
  2235  								Value: &Ydb.Value_Uint64Value{
  2236  									Uint64Value: 4,
  2237  								},
  2238  							}, {
  2239  								Value: &Ydb.Value_TextValue{
  2240  									TextValue: "4",
  2241  								},
  2242  							}, {
  2243  								Value: &Ydb.Value_BoolValue{
  2244  									BoolValue: false,
  2245  								},
  2246  							}},
  2247  						},
  2248  						{
  2249  							Items: []*Ydb.Value{{
  2250  								Value: &Ydb.Value_Uint64Value{
  2251  									Uint64Value: 5,
  2252  								},
  2253  							}, {
  2254  								Value: &Ydb.Value_TextValue{
  2255  									TextValue: "5",
  2256  								},
  2257  							}, {
  2258  								Value: &Ydb.Value_BoolValue{
  2259  									BoolValue: false,
  2260  								},
  2261  							}},
  2262  						},
  2263  					},
  2264  				},
  2265  			}, nil)
  2266  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2267  				Status:         Ydb.StatusIds_SUCCESS,
  2268  				ResultSetIndex: 0,
  2269  				ExecStats: &Ydb_TableStats.QueryStats{
  2270  					ProcessCpuTimeUs: 300,
  2271  					QueryPlan:        "123",
  2272  					QueryAst:         "456",
  2273  					TotalDurationUs:  100,
  2274  					TotalCpuTimeUs:   200,
  2275  				},
  2276  			}, nil)
  2277  			stream.EXPECT().Recv().Return(nil, io.EOF)
  2278  			var s stats.QueryStats
  2279  			result, err := newResult(ctx, stream, withStatsCallback(func(queryStats stats.QueryStats) {
  2280  				s = queryStats
  2281  			}))
  2282  			require.NoError(t, err)
  2283  			require.NotNil(t, result)
  2284  			defer result.Close(ctx)
  2285  			for {
  2286  				resultSet, err := result.nextResultSet(ctx)
  2287  				if err != nil && xerrors.Is(err, io.EOF) {
  2288  					break
  2289  				}
  2290  				for {
  2291  					_, err := resultSet.nextRow(ctx)
  2292  					if err != nil && xerrors.Is(err, io.EOF) {
  2293  						break
  2294  					}
  2295  				}
  2296  			}
  2297  			require.NotNil(t, s)
  2298  			require.Equal(t, "123", s.QueryPlan())
  2299  			require.Equal(t, "456", s.QueryAST())
  2300  			require.Equal(t, time.Microsecond*100, s.TotalDuration())
  2301  			require.Equal(t, time.Microsecond*200, s.TotalCPUTime())
  2302  			require.Equal(t, time.Microsecond*300, s.ProcessCPUTime())
  2303  		})
  2304  		t.Run("WithLastPart", func(t *testing.T) {
  2305  			ctx, cancel := context.WithCancel(xtest.Context(t))
  2306  			defer cancel()
  2307  			ctrl := gomock.NewController(t)
  2308  			stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  2309  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2310  				Status:         Ydb.StatusIds_SUCCESS,
  2311  				ResultSetIndex: 0,
  2312  				ResultSet: &Ydb.ResultSet{
  2313  					Columns: []*Ydb.Column{
  2314  						{
  2315  							Name: "a",
  2316  							Type: &Ydb.Type{
  2317  								Type: &Ydb.Type_TypeId{
  2318  									TypeId: Ydb.Type_UINT64,
  2319  								},
  2320  							},
  2321  						},
  2322  						{
  2323  							Name: "b",
  2324  							Type: &Ydb.Type{
  2325  								Type: &Ydb.Type_TypeId{
  2326  									TypeId: Ydb.Type_UTF8,
  2327  								},
  2328  							},
  2329  						},
  2330  					},
  2331  					Rows: []*Ydb.Value{
  2332  						{
  2333  							Items: []*Ydb.Value{{
  2334  								Value: &Ydb.Value_Uint64Value{
  2335  									Uint64Value: 1,
  2336  								},
  2337  							}, {
  2338  								Value: &Ydb.Value_TextValue{
  2339  									TextValue: "1",
  2340  								},
  2341  							}},
  2342  						},
  2343  						{
  2344  							Items: []*Ydb.Value{{
  2345  								Value: &Ydb.Value_Uint64Value{
  2346  									Uint64Value: 2,
  2347  								},
  2348  							}, {
  2349  								Value: &Ydb.Value_TextValue{
  2350  									TextValue: "2",
  2351  								},
  2352  							}},
  2353  						},
  2354  						{
  2355  							Items: []*Ydb.Value{{
  2356  								Value: &Ydb.Value_Uint64Value{
  2357  									Uint64Value: 3,
  2358  								},
  2359  							}, {
  2360  								Value: &Ydb.Value_TextValue{
  2361  									TextValue: "3",
  2362  								},
  2363  							}},
  2364  						},
  2365  					},
  2366  				},
  2367  			}, nil)
  2368  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2369  				Status:         Ydb.StatusIds_SUCCESS,
  2370  				ResultSetIndex: 0,
  2371  				ResultSet: &Ydb.ResultSet{
  2372  					Rows: []*Ydb.Value{
  2373  						{
  2374  							Items: []*Ydb.Value{{
  2375  								Value: &Ydb.Value_Uint64Value{
  2376  									Uint64Value: 4,
  2377  								},
  2378  							}, {
  2379  								Value: &Ydb.Value_TextValue{
  2380  									TextValue: "4",
  2381  								},
  2382  							}},
  2383  						},
  2384  						{
  2385  							Items: []*Ydb.Value{{
  2386  								Value: &Ydb.Value_Uint64Value{
  2387  									Uint64Value: 5,
  2388  								},
  2389  							}, {
  2390  								Value: &Ydb.Value_TextValue{
  2391  									TextValue: "5",
  2392  								},
  2393  							}},
  2394  						},
  2395  					},
  2396  				},
  2397  			}, nil)
  2398  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2399  				Status:         Ydb.StatusIds_SUCCESS,
  2400  				ResultSetIndex: 1,
  2401  				ResultSet: &Ydb.ResultSet{
  2402  					Columns: []*Ydb.Column{
  2403  						{
  2404  							Name: "c",
  2405  							Type: &Ydb.Type{
  2406  								Type: &Ydb.Type_TypeId{
  2407  									TypeId: Ydb.Type_UINT64,
  2408  								},
  2409  							},
  2410  						},
  2411  						{
  2412  							Name: "d",
  2413  							Type: &Ydb.Type{
  2414  								Type: &Ydb.Type_TypeId{
  2415  									TypeId: Ydb.Type_UTF8,
  2416  								},
  2417  							},
  2418  						},
  2419  						{
  2420  							Name: "e",
  2421  							Type: &Ydb.Type{
  2422  								Type: &Ydb.Type_TypeId{
  2423  									TypeId: Ydb.Type_BOOL,
  2424  								},
  2425  							},
  2426  						},
  2427  					},
  2428  					Rows: []*Ydb.Value{
  2429  						{
  2430  							Items: []*Ydb.Value{{
  2431  								Value: &Ydb.Value_Uint64Value{
  2432  									Uint64Value: 1,
  2433  								},
  2434  							}, {
  2435  								Value: &Ydb.Value_TextValue{
  2436  									TextValue: "1",
  2437  								},
  2438  							}, {
  2439  								Value: &Ydb.Value_BoolValue{
  2440  									BoolValue: true,
  2441  								},
  2442  							}},
  2443  						},
  2444  						{
  2445  							Items: []*Ydb.Value{{
  2446  								Value: &Ydb.Value_Uint64Value{
  2447  									Uint64Value: 2,
  2448  								},
  2449  							}, {
  2450  								Value: &Ydb.Value_TextValue{
  2451  									TextValue: "2",
  2452  								},
  2453  							}, {
  2454  								Value: &Ydb.Value_BoolValue{
  2455  									BoolValue: false,
  2456  								},
  2457  							}},
  2458  						},
  2459  					},
  2460  				},
  2461  			}, nil)
  2462  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2463  				Status:         Ydb.StatusIds_SUCCESS,
  2464  				ResultSetIndex: 1,
  2465  				ResultSet: &Ydb.ResultSet{
  2466  					Rows: []*Ydb.Value{
  2467  						{
  2468  							Items: []*Ydb.Value{{
  2469  								Value: &Ydb.Value_Uint64Value{
  2470  									Uint64Value: 3,
  2471  								},
  2472  							}, {
  2473  								Value: &Ydb.Value_TextValue{
  2474  									TextValue: "3",
  2475  								},
  2476  							}, {
  2477  								Value: &Ydb.Value_BoolValue{
  2478  									BoolValue: true,
  2479  								},
  2480  							}},
  2481  						},
  2482  						{
  2483  							Items: []*Ydb.Value{{
  2484  								Value: &Ydb.Value_Uint64Value{
  2485  									Uint64Value: 4,
  2486  								},
  2487  							}, {
  2488  								Value: &Ydb.Value_TextValue{
  2489  									TextValue: "4",
  2490  								},
  2491  							}, {
  2492  								Value: &Ydb.Value_BoolValue{
  2493  									BoolValue: false,
  2494  								},
  2495  							}},
  2496  						},
  2497  						{
  2498  							Items: []*Ydb.Value{{
  2499  								Value: &Ydb.Value_Uint64Value{
  2500  									Uint64Value: 5,
  2501  								},
  2502  							}, {
  2503  								Value: &Ydb.Value_TextValue{
  2504  									TextValue: "5",
  2505  								},
  2506  							}, {
  2507  								Value: &Ydb.Value_BoolValue{
  2508  									BoolValue: false,
  2509  								},
  2510  							}},
  2511  						},
  2512  					},
  2513  				},
  2514  			}, nil)
  2515  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2516  				Status:         Ydb.StatusIds_SUCCESS,
  2517  				ResultSetIndex: 2,
  2518  				ResultSet: &Ydb.ResultSet{
  2519  					Columns: []*Ydb.Column{
  2520  						{
  2521  							Name: "c",
  2522  							Type: &Ydb.Type{
  2523  								Type: &Ydb.Type_TypeId{
  2524  									TypeId: Ydb.Type_UINT64,
  2525  								},
  2526  							},
  2527  						},
  2528  						{
  2529  							Name: "d",
  2530  							Type: &Ydb.Type{
  2531  								Type: &Ydb.Type_TypeId{
  2532  									TypeId: Ydb.Type_UTF8,
  2533  								},
  2534  							},
  2535  						},
  2536  						{
  2537  							Name: "e",
  2538  							Type: &Ydb.Type{
  2539  								Type: &Ydb.Type_TypeId{
  2540  									TypeId: Ydb.Type_BOOL,
  2541  								},
  2542  							},
  2543  						},
  2544  					},
  2545  					Rows: []*Ydb.Value{
  2546  						{
  2547  							Items: []*Ydb.Value{{
  2548  								Value: &Ydb.Value_Uint64Value{
  2549  									Uint64Value: 1,
  2550  								},
  2551  							}, {
  2552  								Value: &Ydb.Value_TextValue{
  2553  									TextValue: "1",
  2554  								},
  2555  							}, {
  2556  								Value: &Ydb.Value_BoolValue{
  2557  									BoolValue: true,
  2558  								},
  2559  							}},
  2560  						},
  2561  						{
  2562  							Items: []*Ydb.Value{{
  2563  								Value: &Ydb.Value_Uint64Value{
  2564  									Uint64Value: 2,
  2565  								},
  2566  							}, {
  2567  								Value: &Ydb.Value_TextValue{
  2568  									TextValue: "2",
  2569  								},
  2570  							}, {
  2571  								Value: &Ydb.Value_BoolValue{
  2572  									BoolValue: false,
  2573  								},
  2574  							}},
  2575  						},
  2576  					},
  2577  				},
  2578  			}, nil)
  2579  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2580  				Status:         Ydb.StatusIds_SUCCESS,
  2581  				ResultSetIndex: 2,
  2582  				ResultSet: &Ydb.ResultSet{
  2583  					Rows: []*Ydb.Value{
  2584  						{
  2585  							Items: []*Ydb.Value{{
  2586  								Value: &Ydb.Value_Uint64Value{
  2587  									Uint64Value: 3,
  2588  								},
  2589  							}, {
  2590  								Value: &Ydb.Value_TextValue{
  2591  									TextValue: "3",
  2592  								},
  2593  							}, {
  2594  								Value: &Ydb.Value_BoolValue{
  2595  									BoolValue: true,
  2596  								},
  2597  							}},
  2598  						},
  2599  						{
  2600  							Items: []*Ydb.Value{{
  2601  								Value: &Ydb.Value_Uint64Value{
  2602  									Uint64Value: 4,
  2603  								},
  2604  							}, {
  2605  								Value: &Ydb.Value_TextValue{
  2606  									TextValue: "4",
  2607  								},
  2608  							}, {
  2609  								Value: &Ydb.Value_BoolValue{
  2610  									BoolValue: false,
  2611  								},
  2612  							}},
  2613  						},
  2614  						{
  2615  							Items: []*Ydb.Value{{
  2616  								Value: &Ydb.Value_Uint64Value{
  2617  									Uint64Value: 5,
  2618  								},
  2619  							}, {
  2620  								Value: &Ydb.Value_TextValue{
  2621  									TextValue: "5",
  2622  								},
  2623  							}, {
  2624  								Value: &Ydb.Value_BoolValue{
  2625  									BoolValue: false,
  2626  								},
  2627  							}},
  2628  						},
  2629  					},
  2630  				},
  2631  				ExecStats: &Ydb_TableStats.QueryStats{
  2632  					ProcessCpuTimeUs: 300,
  2633  					QueryPlan:        "123",
  2634  					QueryAst:         "456",
  2635  					TotalDurationUs:  100,
  2636  					TotalCpuTimeUs:   200,
  2637  				},
  2638  			}, nil)
  2639  			stream.EXPECT().Recv().Return(nil, io.EOF)
  2640  			var s stats.QueryStats
  2641  			result, err := newResult(ctx, stream, withStatsCallback(func(queryStats stats.QueryStats) {
  2642  				s = queryStats
  2643  			}))
  2644  			require.NoError(t, err)
  2645  			require.NotNil(t, result)
  2646  			defer result.Close(ctx)
  2647  			for {
  2648  				resultSet, err := result.nextResultSet(ctx)
  2649  				if err != nil && xerrors.Is(err, io.EOF) {
  2650  					break
  2651  				}
  2652  				for {
  2653  					_, err := resultSet.nextRow(ctx)
  2654  					if err != nil && xerrors.Is(err, io.EOF) {
  2655  						break
  2656  					}
  2657  				}
  2658  			}
  2659  			require.NotNil(t, s)
  2660  			require.Equal(t, "123", s.QueryPlan())
  2661  			require.Equal(t, "456", s.QueryAST())
  2662  			require.Equal(t, time.Microsecond*100, s.TotalDuration())
  2663  			require.Equal(t, time.Microsecond*200, s.TotalCPUTime())
  2664  			require.Equal(t, time.Microsecond*300, s.ProcessCPUTime())
  2665  		})
  2666  		t.Run("EveryPart", func(t *testing.T) {
  2667  			ctx, cancel := context.WithCancel(xtest.Context(t))
  2668  			defer cancel()
  2669  			ctrl := gomock.NewController(t)
  2670  			stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  2671  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2672  				Status:         Ydb.StatusIds_SUCCESS,
  2673  				ResultSetIndex: 0,
  2674  				ResultSet: &Ydb.ResultSet{
  2675  					Columns: []*Ydb.Column{
  2676  						{
  2677  							Name: "a",
  2678  							Type: &Ydb.Type{
  2679  								Type: &Ydb.Type_TypeId{
  2680  									TypeId: Ydb.Type_UINT64,
  2681  								},
  2682  							},
  2683  						},
  2684  						{
  2685  							Name: "b",
  2686  							Type: &Ydb.Type{
  2687  								Type: &Ydb.Type_TypeId{
  2688  									TypeId: Ydb.Type_UTF8,
  2689  								},
  2690  							},
  2691  						},
  2692  					},
  2693  					Rows: []*Ydb.Value{
  2694  						{
  2695  							Items: []*Ydb.Value{{
  2696  								Value: &Ydb.Value_Uint64Value{
  2697  									Uint64Value: 1,
  2698  								},
  2699  							}, {
  2700  								Value: &Ydb.Value_TextValue{
  2701  									TextValue: "1",
  2702  								},
  2703  							}},
  2704  						},
  2705  						{
  2706  							Items: []*Ydb.Value{{
  2707  								Value: &Ydb.Value_Uint64Value{
  2708  									Uint64Value: 2,
  2709  								},
  2710  							}, {
  2711  								Value: &Ydb.Value_TextValue{
  2712  									TextValue: "2",
  2713  								},
  2714  							}},
  2715  						},
  2716  						{
  2717  							Items: []*Ydb.Value{{
  2718  								Value: &Ydb.Value_Uint64Value{
  2719  									Uint64Value: 3,
  2720  								},
  2721  							}, {
  2722  								Value: &Ydb.Value_TextValue{
  2723  									TextValue: "3",
  2724  								},
  2725  							}},
  2726  						},
  2727  					},
  2728  				},
  2729  				ExecStats: &Ydb_TableStats.QueryStats{
  2730  					ProcessCpuTimeUs: 1,
  2731  					QueryPlan:        "sdsd",
  2732  					QueryAst:         "sdffds",
  2733  					TotalDurationUs:  2,
  2734  					TotalCpuTimeUs:   3,
  2735  				},
  2736  			}, nil)
  2737  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2738  				Status:         Ydb.StatusIds_SUCCESS,
  2739  				ResultSetIndex: 0,
  2740  				ResultSet: &Ydb.ResultSet{
  2741  					Rows: []*Ydb.Value{
  2742  						{
  2743  							Items: []*Ydb.Value{{
  2744  								Value: &Ydb.Value_Uint64Value{
  2745  									Uint64Value: 4,
  2746  								},
  2747  							}, {
  2748  								Value: &Ydb.Value_TextValue{
  2749  									TextValue: "4",
  2750  								},
  2751  							}},
  2752  						},
  2753  						{
  2754  							Items: []*Ydb.Value{{
  2755  								Value: &Ydb.Value_Uint64Value{
  2756  									Uint64Value: 5,
  2757  								},
  2758  							}, {
  2759  								Value: &Ydb.Value_TextValue{
  2760  									TextValue: "5",
  2761  								},
  2762  							}},
  2763  						},
  2764  					},
  2765  				},
  2766  				ExecStats: &Ydb_TableStats.QueryStats{
  2767  					ProcessCpuTimeUs: 332400,
  2768  					QueryPlan:        "12wesfse3",
  2769  					QueryAst:         "sedfefs",
  2770  					TotalDurationUs:  10324320,
  2771  					TotalCpuTimeUs:   234,
  2772  				},
  2773  			}, nil)
  2774  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2775  				Status:         Ydb.StatusIds_SUCCESS,
  2776  				ResultSetIndex: 1,
  2777  				ResultSet: &Ydb.ResultSet{
  2778  					Columns: []*Ydb.Column{
  2779  						{
  2780  							Name: "c",
  2781  							Type: &Ydb.Type{
  2782  								Type: &Ydb.Type_TypeId{
  2783  									TypeId: Ydb.Type_UINT64,
  2784  								},
  2785  							},
  2786  						},
  2787  						{
  2788  							Name: "d",
  2789  							Type: &Ydb.Type{
  2790  								Type: &Ydb.Type_TypeId{
  2791  									TypeId: Ydb.Type_UTF8,
  2792  								},
  2793  							},
  2794  						},
  2795  						{
  2796  							Name: "e",
  2797  							Type: &Ydb.Type{
  2798  								Type: &Ydb.Type_TypeId{
  2799  									TypeId: Ydb.Type_BOOL,
  2800  								},
  2801  							},
  2802  						},
  2803  					},
  2804  					Rows: []*Ydb.Value{
  2805  						{
  2806  							Items: []*Ydb.Value{{
  2807  								Value: &Ydb.Value_Uint64Value{
  2808  									Uint64Value: 1,
  2809  								},
  2810  							}, {
  2811  								Value: &Ydb.Value_TextValue{
  2812  									TextValue: "1",
  2813  								},
  2814  							}, {
  2815  								Value: &Ydb.Value_BoolValue{
  2816  									BoolValue: true,
  2817  								},
  2818  							}},
  2819  						},
  2820  						{
  2821  							Items: []*Ydb.Value{{
  2822  								Value: &Ydb.Value_Uint64Value{
  2823  									Uint64Value: 2,
  2824  								},
  2825  							}, {
  2826  								Value: &Ydb.Value_TextValue{
  2827  									TextValue: "2",
  2828  								},
  2829  							}, {
  2830  								Value: &Ydb.Value_BoolValue{
  2831  									BoolValue: false,
  2832  								},
  2833  							}},
  2834  						},
  2835  					},
  2836  				},
  2837  				ExecStats: &Ydb_TableStats.QueryStats{
  2838  					ProcessCpuTimeUs: 323400,
  2839  					QueryPlan:        "sdfgrdg",
  2840  					QueryAst:         "sdgsrg",
  2841  					TotalDurationUs:  43554,
  2842  					TotalCpuTimeUs:   235643,
  2843  				},
  2844  			}, nil)
  2845  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2846  				Status:         Ydb.StatusIds_SUCCESS,
  2847  				ResultSetIndex: 1,
  2848  				ResultSet: &Ydb.ResultSet{
  2849  					Rows: []*Ydb.Value{
  2850  						{
  2851  							Items: []*Ydb.Value{{
  2852  								Value: &Ydb.Value_Uint64Value{
  2853  									Uint64Value: 3,
  2854  								},
  2855  							}, {
  2856  								Value: &Ydb.Value_TextValue{
  2857  									TextValue: "3",
  2858  								},
  2859  							}, {
  2860  								Value: &Ydb.Value_BoolValue{
  2861  									BoolValue: true,
  2862  								},
  2863  							}},
  2864  						},
  2865  						{
  2866  							Items: []*Ydb.Value{{
  2867  								Value: &Ydb.Value_Uint64Value{
  2868  									Uint64Value: 4,
  2869  								},
  2870  							}, {
  2871  								Value: &Ydb.Value_TextValue{
  2872  									TextValue: "4",
  2873  								},
  2874  							}, {
  2875  								Value: &Ydb.Value_BoolValue{
  2876  									BoolValue: false,
  2877  								},
  2878  							}},
  2879  						},
  2880  						{
  2881  							Items: []*Ydb.Value{{
  2882  								Value: &Ydb.Value_Uint64Value{
  2883  									Uint64Value: 5,
  2884  								},
  2885  							}, {
  2886  								Value: &Ydb.Value_TextValue{
  2887  									TextValue: "5",
  2888  								},
  2889  							}, {
  2890  								Value: &Ydb.Value_BoolValue{
  2891  									BoolValue: false,
  2892  								},
  2893  							}},
  2894  						},
  2895  					},
  2896  				},
  2897  				ExecStats: &Ydb_TableStats.QueryStats{
  2898  					ProcessCpuTimeUs: 3034564570,
  2899  					QueryPlan:        "sdgsrgsg",
  2900  					QueryAst:         "dghytjf",
  2901  					TotalDurationUs:  45676,
  2902  					TotalCpuTimeUs:   4562342,
  2903  				},
  2904  			}, nil)
  2905  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  2906  				Status:         Ydb.StatusIds_SUCCESS,
  2907  				ResultSetIndex: 2,
  2908  				ResultSet: &Ydb.ResultSet{
  2909  					Columns: []*Ydb.Column{
  2910  						{
  2911  							Name: "c",
  2912  							Type: &Ydb.Type{
  2913  								Type: &Ydb.Type_TypeId{
  2914  									TypeId: Ydb.Type_UINT64,
  2915  								},
  2916  							},
  2917  						},
  2918  						{
  2919  							Name: "d",
  2920  							Type: &Ydb.Type{
  2921  								Type: &Ydb.Type_TypeId{
  2922  									TypeId: Ydb.Type_UTF8,
  2923  								},
  2924  							},
  2925  						},
  2926  						{
  2927  							Name: "e",
  2928  							Type: &Ydb.Type{
  2929  								Type: &Ydb.Type_TypeId{
  2930  									TypeId: Ydb.Type_BOOL,
  2931  								},
  2932  							},
  2933  						},
  2934  					},
  2935  					Rows: []*Ydb.Value{
  2936  						{
  2937  							Items: []*Ydb.Value{{
  2938  								Value: &Ydb.Value_Uint64Value{
  2939  									Uint64Value: 1,
  2940  								},
  2941  							}, {
  2942  								Value: &Ydb.Value_TextValue{
  2943  									TextValue: "1",
  2944  								},
  2945  							}, {
  2946  								Value: &Ydb.Value_BoolValue{
  2947  									BoolValue: true,
  2948  								},
  2949  							}},
  2950  						},
  2951  						{
  2952  							Items: []*Ydb.Value{{
  2953  								Value: &Ydb.Value_Uint64Value{
  2954  									Uint64Value: 2,
  2955  								},
  2956  							}, {
  2957  								Value: &Ydb.Value_TextValue{
  2958  									TextValue: "2",
  2959  								},
  2960  							}, {
  2961  								Value: &Ydb.Value_BoolValue{
  2962  									BoolValue: false,
  2963  								},
  2964  							}},
  2965  						},
  2966  					},
  2967  				},
  2968  				ExecStats: &Ydb_TableStats.QueryStats{
  2969  					ProcessCpuTimeUs: 300,
  2970  					QueryPlan:        "123",
  2971  					QueryAst:         "456",
  2972  					TotalDurationUs:  100,
  2973  					TotalCpuTimeUs:   200,
  2974  				},
  2975  			}, nil)
  2976  			stream.EXPECT().Recv().Return(nil, io.EOF)
  2977  			var s stats.QueryStats
  2978  			result, err := newResult(ctx, stream, withStatsCallback(func(queryStats stats.QueryStats) {
  2979  				s = queryStats
  2980  			}))
  2981  			require.NoError(t, err)
  2982  			require.NotNil(t, result)
  2983  			defer result.Close(ctx)
  2984  			for {
  2985  				resultSet, err := result.nextResultSet(ctx)
  2986  				if err != nil && xerrors.Is(err, io.EOF) {
  2987  					break
  2988  				}
  2989  				for {
  2990  					_, err := resultSet.nextRow(ctx)
  2991  					if err != nil && xerrors.Is(err, io.EOF) {
  2992  						break
  2993  					}
  2994  				}
  2995  			}
  2996  			require.NotNil(t, s)
  2997  			require.Equal(t, "123", s.QueryPlan())
  2998  			require.Equal(t, "456", s.QueryAST())
  2999  			require.Equal(t, time.Microsecond*100, s.TotalDuration())
  3000  			require.Equal(t, time.Microsecond*200, s.TotalCPUTime())
  3001  			require.Equal(t, time.Microsecond*300, s.ProcessCPUTime())
  3002  		})
  3003  	})
  3004  }
  3005  
  3006  func TestMaterializedResultStats(t *testing.T) {
  3007  	newResult := func(
  3008  		ctx context.Context,
  3009  		stream Ydb_Query_V1.QueryService_ExecuteQueryClient,
  3010  		opts ...resultOption,
  3011  	) (query.Result, error) {
  3012  		r, err := newResult(ctx, stream, opts...)
  3013  		if err != nil {
  3014  			return nil, err
  3015  		}
  3016  
  3017  		return r, nil
  3018  	}
  3019  	t.Run("Stats", func(t *testing.T) {
  3020  		t.Run("Never", func(t *testing.T) {
  3021  			ctx, cancel := context.WithCancel(xtest.Context(t))
  3022  			defer cancel()
  3023  			ctrl := gomock.NewController(t)
  3024  			stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  3025  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3026  				Status:         Ydb.StatusIds_SUCCESS,
  3027  				ResultSetIndex: 0,
  3028  				ResultSet: &Ydb.ResultSet{
  3029  					Columns: []*Ydb.Column{
  3030  						{
  3031  							Name: "a",
  3032  							Type: &Ydb.Type{
  3033  								Type: &Ydb.Type_TypeId{
  3034  									TypeId: Ydb.Type_UINT64,
  3035  								},
  3036  							},
  3037  						},
  3038  						{
  3039  							Name: "b",
  3040  							Type: &Ydb.Type{
  3041  								Type: &Ydb.Type_TypeId{
  3042  									TypeId: Ydb.Type_UTF8,
  3043  								},
  3044  							},
  3045  						},
  3046  					},
  3047  					Rows: []*Ydb.Value{
  3048  						{
  3049  							Items: []*Ydb.Value{{
  3050  								Value: &Ydb.Value_Uint64Value{
  3051  									Uint64Value: 1,
  3052  								},
  3053  							}, {
  3054  								Value: &Ydb.Value_TextValue{
  3055  									TextValue: "1",
  3056  								},
  3057  							}},
  3058  						},
  3059  						{
  3060  							Items: []*Ydb.Value{{
  3061  								Value: &Ydb.Value_Uint64Value{
  3062  									Uint64Value: 2,
  3063  								},
  3064  							}, {
  3065  								Value: &Ydb.Value_TextValue{
  3066  									TextValue: "2",
  3067  								},
  3068  							}},
  3069  						},
  3070  						{
  3071  							Items: []*Ydb.Value{{
  3072  								Value: &Ydb.Value_Uint64Value{
  3073  									Uint64Value: 3,
  3074  								},
  3075  							}, {
  3076  								Value: &Ydb.Value_TextValue{
  3077  									TextValue: "3",
  3078  								},
  3079  							}},
  3080  						},
  3081  					},
  3082  				},
  3083  			}, nil)
  3084  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3085  				Status:         Ydb.StatusIds_SUCCESS,
  3086  				ResultSetIndex: 0,
  3087  				ResultSet: &Ydb.ResultSet{
  3088  					Rows: []*Ydb.Value{
  3089  						{
  3090  							Items: []*Ydb.Value{{
  3091  								Value: &Ydb.Value_Uint64Value{
  3092  									Uint64Value: 4,
  3093  								},
  3094  							}, {
  3095  								Value: &Ydb.Value_TextValue{
  3096  									TextValue: "4",
  3097  								},
  3098  							}},
  3099  						},
  3100  						{
  3101  							Items: []*Ydb.Value{{
  3102  								Value: &Ydb.Value_Uint64Value{
  3103  									Uint64Value: 5,
  3104  								},
  3105  							}, {
  3106  								Value: &Ydb.Value_TextValue{
  3107  									TextValue: "5",
  3108  								},
  3109  							}},
  3110  						},
  3111  					},
  3112  				},
  3113  			}, nil)
  3114  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3115  				Status:         Ydb.StatusIds_SUCCESS,
  3116  				ResultSetIndex: 1,
  3117  				ResultSet: &Ydb.ResultSet{
  3118  					Columns: []*Ydb.Column{
  3119  						{
  3120  							Name: "c",
  3121  							Type: &Ydb.Type{
  3122  								Type: &Ydb.Type_TypeId{
  3123  									TypeId: Ydb.Type_UINT64,
  3124  								},
  3125  							},
  3126  						},
  3127  						{
  3128  							Name: "d",
  3129  							Type: &Ydb.Type{
  3130  								Type: &Ydb.Type_TypeId{
  3131  									TypeId: Ydb.Type_UTF8,
  3132  								},
  3133  							},
  3134  						},
  3135  						{
  3136  							Name: "e",
  3137  							Type: &Ydb.Type{
  3138  								Type: &Ydb.Type_TypeId{
  3139  									TypeId: Ydb.Type_BOOL,
  3140  								},
  3141  							},
  3142  						},
  3143  					},
  3144  					Rows: []*Ydb.Value{
  3145  						{
  3146  							Items: []*Ydb.Value{{
  3147  								Value: &Ydb.Value_Uint64Value{
  3148  									Uint64Value: 1,
  3149  								},
  3150  							}, {
  3151  								Value: &Ydb.Value_TextValue{
  3152  									TextValue: "1",
  3153  								},
  3154  							}, {
  3155  								Value: &Ydb.Value_BoolValue{
  3156  									BoolValue: true,
  3157  								},
  3158  							}},
  3159  						},
  3160  						{
  3161  							Items: []*Ydb.Value{{
  3162  								Value: &Ydb.Value_Uint64Value{
  3163  									Uint64Value: 2,
  3164  								},
  3165  							}, {
  3166  								Value: &Ydb.Value_TextValue{
  3167  									TextValue: "2",
  3168  								},
  3169  							}, {
  3170  								Value: &Ydb.Value_BoolValue{
  3171  									BoolValue: false,
  3172  								},
  3173  							}},
  3174  						},
  3175  					},
  3176  				},
  3177  			}, nil)
  3178  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3179  				Status:         Ydb.StatusIds_SUCCESS,
  3180  				ResultSetIndex: 1,
  3181  				ResultSet: &Ydb.ResultSet{
  3182  					Rows: []*Ydb.Value{
  3183  						{
  3184  							Items: []*Ydb.Value{{
  3185  								Value: &Ydb.Value_Uint64Value{
  3186  									Uint64Value: 3,
  3187  								},
  3188  							}, {
  3189  								Value: &Ydb.Value_TextValue{
  3190  									TextValue: "3",
  3191  								},
  3192  							}, {
  3193  								Value: &Ydb.Value_BoolValue{
  3194  									BoolValue: true,
  3195  								},
  3196  							}},
  3197  						},
  3198  						{
  3199  							Items: []*Ydb.Value{{
  3200  								Value: &Ydb.Value_Uint64Value{
  3201  									Uint64Value: 4,
  3202  								},
  3203  							}, {
  3204  								Value: &Ydb.Value_TextValue{
  3205  									TextValue: "4",
  3206  								},
  3207  							}, {
  3208  								Value: &Ydb.Value_BoolValue{
  3209  									BoolValue: false,
  3210  								},
  3211  							}},
  3212  						},
  3213  						{
  3214  							Items: []*Ydb.Value{{
  3215  								Value: &Ydb.Value_Uint64Value{
  3216  									Uint64Value: 5,
  3217  								},
  3218  							}, {
  3219  								Value: &Ydb.Value_TextValue{
  3220  									TextValue: "5",
  3221  								},
  3222  							}, {
  3223  								Value: &Ydb.Value_BoolValue{
  3224  									BoolValue: false,
  3225  								},
  3226  							}},
  3227  						},
  3228  					},
  3229  				},
  3230  			}, nil)
  3231  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3232  				Status:         Ydb.StatusIds_SUCCESS,
  3233  				ResultSetIndex: 2,
  3234  				ResultSet: &Ydb.ResultSet{
  3235  					Columns: []*Ydb.Column{
  3236  						{
  3237  							Name: "c",
  3238  							Type: &Ydb.Type{
  3239  								Type: &Ydb.Type_TypeId{
  3240  									TypeId: Ydb.Type_UINT64,
  3241  								},
  3242  							},
  3243  						},
  3244  						{
  3245  							Name: "d",
  3246  							Type: &Ydb.Type{
  3247  								Type: &Ydb.Type_TypeId{
  3248  									TypeId: Ydb.Type_UTF8,
  3249  								},
  3250  							},
  3251  						},
  3252  						{
  3253  							Name: "e",
  3254  							Type: &Ydb.Type{
  3255  								Type: &Ydb.Type_TypeId{
  3256  									TypeId: Ydb.Type_BOOL,
  3257  								},
  3258  							},
  3259  						},
  3260  					},
  3261  					Rows: []*Ydb.Value{
  3262  						{
  3263  							Items: []*Ydb.Value{{
  3264  								Value: &Ydb.Value_Uint64Value{
  3265  									Uint64Value: 1,
  3266  								},
  3267  							}, {
  3268  								Value: &Ydb.Value_TextValue{
  3269  									TextValue: "1",
  3270  								},
  3271  							}, {
  3272  								Value: &Ydb.Value_BoolValue{
  3273  									BoolValue: true,
  3274  								},
  3275  							}},
  3276  						},
  3277  						{
  3278  							Items: []*Ydb.Value{{
  3279  								Value: &Ydb.Value_Uint64Value{
  3280  									Uint64Value: 2,
  3281  								},
  3282  							}, {
  3283  								Value: &Ydb.Value_TextValue{
  3284  									TextValue: "2",
  3285  								},
  3286  							}, {
  3287  								Value: &Ydb.Value_BoolValue{
  3288  									BoolValue: false,
  3289  								},
  3290  							}},
  3291  						},
  3292  					},
  3293  				},
  3294  			}, nil)
  3295  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3296  				Status:         Ydb.StatusIds_SUCCESS,
  3297  				ResultSetIndex: 2,
  3298  				ResultSet: &Ydb.ResultSet{
  3299  					Rows: []*Ydb.Value{
  3300  						{
  3301  							Items: []*Ydb.Value{{
  3302  								Value: &Ydb.Value_Uint64Value{
  3303  									Uint64Value: 3,
  3304  								},
  3305  							}, {
  3306  								Value: &Ydb.Value_TextValue{
  3307  									TextValue: "3",
  3308  								},
  3309  							}, {
  3310  								Value: &Ydb.Value_BoolValue{
  3311  									BoolValue: true,
  3312  								},
  3313  							}},
  3314  						},
  3315  						{
  3316  							Items: []*Ydb.Value{{
  3317  								Value: &Ydb.Value_Uint64Value{
  3318  									Uint64Value: 4,
  3319  								},
  3320  							}, {
  3321  								Value: &Ydb.Value_TextValue{
  3322  									TextValue: "4",
  3323  								},
  3324  							}, {
  3325  								Value: &Ydb.Value_BoolValue{
  3326  									BoolValue: false,
  3327  								},
  3328  							}},
  3329  						},
  3330  						{
  3331  							Items: []*Ydb.Value{{
  3332  								Value: &Ydb.Value_Uint64Value{
  3333  									Uint64Value: 5,
  3334  								},
  3335  							}, {
  3336  								Value: &Ydb.Value_TextValue{
  3337  									TextValue: "5",
  3338  								},
  3339  							}, {
  3340  								Value: &Ydb.Value_BoolValue{
  3341  									BoolValue: false,
  3342  								},
  3343  							}},
  3344  						},
  3345  					},
  3346  				},
  3347  			}, nil)
  3348  			stream.EXPECT().Recv().Return(nil, io.EOF)
  3349  			var s stats.QueryStats
  3350  			result, err := newResult(ctx, stream, withStatsCallback(func(queryStats stats.QueryStats) {
  3351  				s = queryStats
  3352  			}))
  3353  			require.NoError(t, err)
  3354  			require.NotNil(t, result)
  3355  			defer result.Close(ctx)
  3356  			for {
  3357  				resultSet, err := result.NextResultSet(ctx)
  3358  				if err != nil && xerrors.Is(err, io.EOF) {
  3359  					break
  3360  				}
  3361  				for {
  3362  					_, err := resultSet.NextRow(ctx)
  3363  					if err != nil && xerrors.Is(err, io.EOF) {
  3364  						break
  3365  					}
  3366  				}
  3367  			}
  3368  			require.Nil(t, s)
  3369  		})
  3370  		t.Run("SeparatedLastPart", func(t *testing.T) {
  3371  			ctx, cancel := context.WithCancel(xtest.Context(t))
  3372  			defer cancel()
  3373  			ctrl := gomock.NewController(t)
  3374  			stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  3375  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3376  				Status:         Ydb.StatusIds_SUCCESS,
  3377  				ResultSetIndex: 0,
  3378  				ResultSet: &Ydb.ResultSet{
  3379  					Columns: []*Ydb.Column{
  3380  						{
  3381  							Name: "a",
  3382  							Type: &Ydb.Type{
  3383  								Type: &Ydb.Type_TypeId{
  3384  									TypeId: Ydb.Type_UINT64,
  3385  								},
  3386  							},
  3387  						},
  3388  						{
  3389  							Name: "b",
  3390  							Type: &Ydb.Type{
  3391  								Type: &Ydb.Type_TypeId{
  3392  									TypeId: Ydb.Type_UTF8,
  3393  								},
  3394  							},
  3395  						},
  3396  					},
  3397  					Rows: []*Ydb.Value{
  3398  						{
  3399  							Items: []*Ydb.Value{{
  3400  								Value: &Ydb.Value_Uint64Value{
  3401  									Uint64Value: 1,
  3402  								},
  3403  							}, {
  3404  								Value: &Ydb.Value_TextValue{
  3405  									TextValue: "1",
  3406  								},
  3407  							}},
  3408  						},
  3409  						{
  3410  							Items: []*Ydb.Value{{
  3411  								Value: &Ydb.Value_Uint64Value{
  3412  									Uint64Value: 2,
  3413  								},
  3414  							}, {
  3415  								Value: &Ydb.Value_TextValue{
  3416  									TextValue: "2",
  3417  								},
  3418  							}},
  3419  						},
  3420  						{
  3421  							Items: []*Ydb.Value{{
  3422  								Value: &Ydb.Value_Uint64Value{
  3423  									Uint64Value: 3,
  3424  								},
  3425  							}, {
  3426  								Value: &Ydb.Value_TextValue{
  3427  									TextValue: "3",
  3428  								},
  3429  							}},
  3430  						},
  3431  					},
  3432  				},
  3433  			}, nil)
  3434  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3435  				Status:         Ydb.StatusIds_SUCCESS,
  3436  				ResultSetIndex: 0,
  3437  				ResultSet: &Ydb.ResultSet{
  3438  					Rows: []*Ydb.Value{
  3439  						{
  3440  							Items: []*Ydb.Value{{
  3441  								Value: &Ydb.Value_Uint64Value{
  3442  									Uint64Value: 4,
  3443  								},
  3444  							}, {
  3445  								Value: &Ydb.Value_TextValue{
  3446  									TextValue: "4",
  3447  								},
  3448  							}},
  3449  						},
  3450  						{
  3451  							Items: []*Ydb.Value{{
  3452  								Value: &Ydb.Value_Uint64Value{
  3453  									Uint64Value: 5,
  3454  								},
  3455  							}, {
  3456  								Value: &Ydb.Value_TextValue{
  3457  									TextValue: "5",
  3458  								},
  3459  							}},
  3460  						},
  3461  					},
  3462  				},
  3463  			}, nil)
  3464  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3465  				Status:         Ydb.StatusIds_SUCCESS,
  3466  				ResultSetIndex: 1,
  3467  				ResultSet: &Ydb.ResultSet{
  3468  					Columns: []*Ydb.Column{
  3469  						{
  3470  							Name: "c",
  3471  							Type: &Ydb.Type{
  3472  								Type: &Ydb.Type_TypeId{
  3473  									TypeId: Ydb.Type_UINT64,
  3474  								},
  3475  							},
  3476  						},
  3477  						{
  3478  							Name: "d",
  3479  							Type: &Ydb.Type{
  3480  								Type: &Ydb.Type_TypeId{
  3481  									TypeId: Ydb.Type_UTF8,
  3482  								},
  3483  							},
  3484  						},
  3485  						{
  3486  							Name: "e",
  3487  							Type: &Ydb.Type{
  3488  								Type: &Ydb.Type_TypeId{
  3489  									TypeId: Ydb.Type_BOOL,
  3490  								},
  3491  							},
  3492  						},
  3493  					},
  3494  					Rows: []*Ydb.Value{
  3495  						{
  3496  							Items: []*Ydb.Value{{
  3497  								Value: &Ydb.Value_Uint64Value{
  3498  									Uint64Value: 1,
  3499  								},
  3500  							}, {
  3501  								Value: &Ydb.Value_TextValue{
  3502  									TextValue: "1",
  3503  								},
  3504  							}, {
  3505  								Value: &Ydb.Value_BoolValue{
  3506  									BoolValue: true,
  3507  								},
  3508  							}},
  3509  						},
  3510  						{
  3511  							Items: []*Ydb.Value{{
  3512  								Value: &Ydb.Value_Uint64Value{
  3513  									Uint64Value: 2,
  3514  								},
  3515  							}, {
  3516  								Value: &Ydb.Value_TextValue{
  3517  									TextValue: "2",
  3518  								},
  3519  							}, {
  3520  								Value: &Ydb.Value_BoolValue{
  3521  									BoolValue: false,
  3522  								},
  3523  							}},
  3524  						},
  3525  					},
  3526  				},
  3527  			}, nil)
  3528  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3529  				Status:         Ydb.StatusIds_SUCCESS,
  3530  				ResultSetIndex: 1,
  3531  				ResultSet: &Ydb.ResultSet{
  3532  					Rows: []*Ydb.Value{
  3533  						{
  3534  							Items: []*Ydb.Value{{
  3535  								Value: &Ydb.Value_Uint64Value{
  3536  									Uint64Value: 3,
  3537  								},
  3538  							}, {
  3539  								Value: &Ydb.Value_TextValue{
  3540  									TextValue: "3",
  3541  								},
  3542  							}, {
  3543  								Value: &Ydb.Value_BoolValue{
  3544  									BoolValue: true,
  3545  								},
  3546  							}},
  3547  						},
  3548  						{
  3549  							Items: []*Ydb.Value{{
  3550  								Value: &Ydb.Value_Uint64Value{
  3551  									Uint64Value: 4,
  3552  								},
  3553  							}, {
  3554  								Value: &Ydb.Value_TextValue{
  3555  									TextValue: "4",
  3556  								},
  3557  							}, {
  3558  								Value: &Ydb.Value_BoolValue{
  3559  									BoolValue: false,
  3560  								},
  3561  							}},
  3562  						},
  3563  						{
  3564  							Items: []*Ydb.Value{{
  3565  								Value: &Ydb.Value_Uint64Value{
  3566  									Uint64Value: 5,
  3567  								},
  3568  							}, {
  3569  								Value: &Ydb.Value_TextValue{
  3570  									TextValue: "5",
  3571  								},
  3572  							}, {
  3573  								Value: &Ydb.Value_BoolValue{
  3574  									BoolValue: false,
  3575  								},
  3576  							}},
  3577  						},
  3578  					},
  3579  				},
  3580  			}, nil)
  3581  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3582  				Status:         Ydb.StatusIds_SUCCESS,
  3583  				ResultSetIndex: 2,
  3584  				ResultSet: &Ydb.ResultSet{
  3585  					Columns: []*Ydb.Column{
  3586  						{
  3587  							Name: "c",
  3588  							Type: &Ydb.Type{
  3589  								Type: &Ydb.Type_TypeId{
  3590  									TypeId: Ydb.Type_UINT64,
  3591  								},
  3592  							},
  3593  						},
  3594  						{
  3595  							Name: "d",
  3596  							Type: &Ydb.Type{
  3597  								Type: &Ydb.Type_TypeId{
  3598  									TypeId: Ydb.Type_UTF8,
  3599  								},
  3600  							},
  3601  						},
  3602  						{
  3603  							Name: "e",
  3604  							Type: &Ydb.Type{
  3605  								Type: &Ydb.Type_TypeId{
  3606  									TypeId: Ydb.Type_BOOL,
  3607  								},
  3608  							},
  3609  						},
  3610  					},
  3611  					Rows: []*Ydb.Value{
  3612  						{
  3613  							Items: []*Ydb.Value{{
  3614  								Value: &Ydb.Value_Uint64Value{
  3615  									Uint64Value: 1,
  3616  								},
  3617  							}, {
  3618  								Value: &Ydb.Value_TextValue{
  3619  									TextValue: "1",
  3620  								},
  3621  							}, {
  3622  								Value: &Ydb.Value_BoolValue{
  3623  									BoolValue: true,
  3624  								},
  3625  							}},
  3626  						},
  3627  						{
  3628  							Items: []*Ydb.Value{{
  3629  								Value: &Ydb.Value_Uint64Value{
  3630  									Uint64Value: 2,
  3631  								},
  3632  							}, {
  3633  								Value: &Ydb.Value_TextValue{
  3634  									TextValue: "2",
  3635  								},
  3636  							}, {
  3637  								Value: &Ydb.Value_BoolValue{
  3638  									BoolValue: false,
  3639  								},
  3640  							}},
  3641  						},
  3642  					},
  3643  				},
  3644  			}, nil)
  3645  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3646  				Status:         Ydb.StatusIds_SUCCESS,
  3647  				ResultSetIndex: 2,
  3648  				ResultSet: &Ydb.ResultSet{
  3649  					Rows: []*Ydb.Value{
  3650  						{
  3651  							Items: []*Ydb.Value{{
  3652  								Value: &Ydb.Value_Uint64Value{
  3653  									Uint64Value: 3,
  3654  								},
  3655  							}, {
  3656  								Value: &Ydb.Value_TextValue{
  3657  									TextValue: "3",
  3658  								},
  3659  							}, {
  3660  								Value: &Ydb.Value_BoolValue{
  3661  									BoolValue: true,
  3662  								},
  3663  							}},
  3664  						},
  3665  						{
  3666  							Items: []*Ydb.Value{{
  3667  								Value: &Ydb.Value_Uint64Value{
  3668  									Uint64Value: 4,
  3669  								},
  3670  							}, {
  3671  								Value: &Ydb.Value_TextValue{
  3672  									TextValue: "4",
  3673  								},
  3674  							}, {
  3675  								Value: &Ydb.Value_BoolValue{
  3676  									BoolValue: false,
  3677  								},
  3678  							}},
  3679  						},
  3680  						{
  3681  							Items: []*Ydb.Value{{
  3682  								Value: &Ydb.Value_Uint64Value{
  3683  									Uint64Value: 5,
  3684  								},
  3685  							}, {
  3686  								Value: &Ydb.Value_TextValue{
  3687  									TextValue: "5",
  3688  								},
  3689  							}, {
  3690  								Value: &Ydb.Value_BoolValue{
  3691  									BoolValue: false,
  3692  								},
  3693  							}},
  3694  						},
  3695  					},
  3696  				},
  3697  			}, nil)
  3698  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3699  				Status:         Ydb.StatusIds_SUCCESS,
  3700  				ResultSetIndex: 0,
  3701  				ExecStats: &Ydb_TableStats.QueryStats{
  3702  					ProcessCpuTimeUs: 300,
  3703  					QueryPlan:        "123",
  3704  					QueryAst:         "456",
  3705  					TotalDurationUs:  100,
  3706  					TotalCpuTimeUs:   200,
  3707  				},
  3708  			}, nil)
  3709  			stream.EXPECT().Recv().Return(nil, io.EOF)
  3710  			var s stats.QueryStats
  3711  			result, err := newResult(ctx, stream, withStatsCallback(func(queryStats stats.QueryStats) {
  3712  				s = queryStats
  3713  			}))
  3714  			require.NoError(t, err)
  3715  			require.NotNil(t, result)
  3716  			defer result.Close(ctx)
  3717  			for {
  3718  				resultSet, err := result.NextResultSet(ctx)
  3719  				if err != nil && xerrors.Is(err, io.EOF) {
  3720  					break
  3721  				}
  3722  				for {
  3723  					_, err := resultSet.NextRow(ctx)
  3724  					if err != nil && xerrors.Is(err, io.EOF) {
  3725  						break
  3726  					}
  3727  				}
  3728  			}
  3729  			require.NotNil(t, s)
  3730  			require.Equal(t, "123", s.QueryPlan())
  3731  			require.Equal(t, "456", s.QueryAST())
  3732  			require.Equal(t, time.Microsecond*100, s.TotalDuration())
  3733  			require.Equal(t, time.Microsecond*200, s.TotalCPUTime())
  3734  			require.Equal(t, time.Microsecond*300, s.ProcessCPUTime())
  3735  		})
  3736  		t.Run("WithLastPart", func(t *testing.T) {
  3737  			ctx, cancel := context.WithCancel(xtest.Context(t))
  3738  			defer cancel()
  3739  			ctrl := gomock.NewController(t)
  3740  			stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  3741  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3742  				Status:         Ydb.StatusIds_SUCCESS,
  3743  				ResultSetIndex: 0,
  3744  				ResultSet: &Ydb.ResultSet{
  3745  					Columns: []*Ydb.Column{
  3746  						{
  3747  							Name: "a",
  3748  							Type: &Ydb.Type{
  3749  								Type: &Ydb.Type_TypeId{
  3750  									TypeId: Ydb.Type_UINT64,
  3751  								},
  3752  							},
  3753  						},
  3754  						{
  3755  							Name: "b",
  3756  							Type: &Ydb.Type{
  3757  								Type: &Ydb.Type_TypeId{
  3758  									TypeId: Ydb.Type_UTF8,
  3759  								},
  3760  							},
  3761  						},
  3762  					},
  3763  					Rows: []*Ydb.Value{
  3764  						{
  3765  							Items: []*Ydb.Value{{
  3766  								Value: &Ydb.Value_Uint64Value{
  3767  									Uint64Value: 1,
  3768  								},
  3769  							}, {
  3770  								Value: &Ydb.Value_TextValue{
  3771  									TextValue: "1",
  3772  								},
  3773  							}},
  3774  						},
  3775  						{
  3776  							Items: []*Ydb.Value{{
  3777  								Value: &Ydb.Value_Uint64Value{
  3778  									Uint64Value: 2,
  3779  								},
  3780  							}, {
  3781  								Value: &Ydb.Value_TextValue{
  3782  									TextValue: "2",
  3783  								},
  3784  							}},
  3785  						},
  3786  						{
  3787  							Items: []*Ydb.Value{{
  3788  								Value: &Ydb.Value_Uint64Value{
  3789  									Uint64Value: 3,
  3790  								},
  3791  							}, {
  3792  								Value: &Ydb.Value_TextValue{
  3793  									TextValue: "3",
  3794  								},
  3795  							}},
  3796  						},
  3797  					},
  3798  				},
  3799  			}, nil)
  3800  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3801  				Status:         Ydb.StatusIds_SUCCESS,
  3802  				ResultSetIndex: 0,
  3803  				ResultSet: &Ydb.ResultSet{
  3804  					Rows: []*Ydb.Value{
  3805  						{
  3806  							Items: []*Ydb.Value{{
  3807  								Value: &Ydb.Value_Uint64Value{
  3808  									Uint64Value: 4,
  3809  								},
  3810  							}, {
  3811  								Value: &Ydb.Value_TextValue{
  3812  									TextValue: "4",
  3813  								},
  3814  							}},
  3815  						},
  3816  						{
  3817  							Items: []*Ydb.Value{{
  3818  								Value: &Ydb.Value_Uint64Value{
  3819  									Uint64Value: 5,
  3820  								},
  3821  							}, {
  3822  								Value: &Ydb.Value_TextValue{
  3823  									TextValue: "5",
  3824  								},
  3825  							}},
  3826  						},
  3827  					},
  3828  				},
  3829  			}, nil)
  3830  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3831  				Status:         Ydb.StatusIds_SUCCESS,
  3832  				ResultSetIndex: 1,
  3833  				ResultSet: &Ydb.ResultSet{
  3834  					Columns: []*Ydb.Column{
  3835  						{
  3836  							Name: "c",
  3837  							Type: &Ydb.Type{
  3838  								Type: &Ydb.Type_TypeId{
  3839  									TypeId: Ydb.Type_UINT64,
  3840  								},
  3841  							},
  3842  						},
  3843  						{
  3844  							Name: "d",
  3845  							Type: &Ydb.Type{
  3846  								Type: &Ydb.Type_TypeId{
  3847  									TypeId: Ydb.Type_UTF8,
  3848  								},
  3849  							},
  3850  						},
  3851  						{
  3852  							Name: "e",
  3853  							Type: &Ydb.Type{
  3854  								Type: &Ydb.Type_TypeId{
  3855  									TypeId: Ydb.Type_BOOL,
  3856  								},
  3857  							},
  3858  						},
  3859  					},
  3860  					Rows: []*Ydb.Value{
  3861  						{
  3862  							Items: []*Ydb.Value{{
  3863  								Value: &Ydb.Value_Uint64Value{
  3864  									Uint64Value: 1,
  3865  								},
  3866  							}, {
  3867  								Value: &Ydb.Value_TextValue{
  3868  									TextValue: "1",
  3869  								},
  3870  							}, {
  3871  								Value: &Ydb.Value_BoolValue{
  3872  									BoolValue: true,
  3873  								},
  3874  							}},
  3875  						},
  3876  						{
  3877  							Items: []*Ydb.Value{{
  3878  								Value: &Ydb.Value_Uint64Value{
  3879  									Uint64Value: 2,
  3880  								},
  3881  							}, {
  3882  								Value: &Ydb.Value_TextValue{
  3883  									TextValue: "2",
  3884  								},
  3885  							}, {
  3886  								Value: &Ydb.Value_BoolValue{
  3887  									BoolValue: false,
  3888  								},
  3889  							}},
  3890  						},
  3891  					},
  3892  				},
  3893  			}, nil)
  3894  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3895  				Status:         Ydb.StatusIds_SUCCESS,
  3896  				ResultSetIndex: 1,
  3897  				ResultSet: &Ydb.ResultSet{
  3898  					Rows: []*Ydb.Value{
  3899  						{
  3900  							Items: []*Ydb.Value{{
  3901  								Value: &Ydb.Value_Uint64Value{
  3902  									Uint64Value: 3,
  3903  								},
  3904  							}, {
  3905  								Value: &Ydb.Value_TextValue{
  3906  									TextValue: "3",
  3907  								},
  3908  							}, {
  3909  								Value: &Ydb.Value_BoolValue{
  3910  									BoolValue: true,
  3911  								},
  3912  							}},
  3913  						},
  3914  						{
  3915  							Items: []*Ydb.Value{{
  3916  								Value: &Ydb.Value_Uint64Value{
  3917  									Uint64Value: 4,
  3918  								},
  3919  							}, {
  3920  								Value: &Ydb.Value_TextValue{
  3921  									TextValue: "4",
  3922  								},
  3923  							}, {
  3924  								Value: &Ydb.Value_BoolValue{
  3925  									BoolValue: false,
  3926  								},
  3927  							}},
  3928  						},
  3929  						{
  3930  							Items: []*Ydb.Value{{
  3931  								Value: &Ydb.Value_Uint64Value{
  3932  									Uint64Value: 5,
  3933  								},
  3934  							}, {
  3935  								Value: &Ydb.Value_TextValue{
  3936  									TextValue: "5",
  3937  								},
  3938  							}, {
  3939  								Value: &Ydb.Value_BoolValue{
  3940  									BoolValue: false,
  3941  								},
  3942  							}},
  3943  						},
  3944  					},
  3945  				},
  3946  			}, nil)
  3947  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  3948  				Status:         Ydb.StatusIds_SUCCESS,
  3949  				ResultSetIndex: 2,
  3950  				ResultSet: &Ydb.ResultSet{
  3951  					Columns: []*Ydb.Column{
  3952  						{
  3953  							Name: "c",
  3954  							Type: &Ydb.Type{
  3955  								Type: &Ydb.Type_TypeId{
  3956  									TypeId: Ydb.Type_UINT64,
  3957  								},
  3958  							},
  3959  						},
  3960  						{
  3961  							Name: "d",
  3962  							Type: &Ydb.Type{
  3963  								Type: &Ydb.Type_TypeId{
  3964  									TypeId: Ydb.Type_UTF8,
  3965  								},
  3966  							},
  3967  						},
  3968  						{
  3969  							Name: "e",
  3970  							Type: &Ydb.Type{
  3971  								Type: &Ydb.Type_TypeId{
  3972  									TypeId: Ydb.Type_BOOL,
  3973  								},
  3974  							},
  3975  						},
  3976  					},
  3977  					Rows: []*Ydb.Value{
  3978  						{
  3979  							Items: []*Ydb.Value{{
  3980  								Value: &Ydb.Value_Uint64Value{
  3981  									Uint64Value: 1,
  3982  								},
  3983  							}, {
  3984  								Value: &Ydb.Value_TextValue{
  3985  									TextValue: "1",
  3986  								},
  3987  							}, {
  3988  								Value: &Ydb.Value_BoolValue{
  3989  									BoolValue: true,
  3990  								},
  3991  							}},
  3992  						},
  3993  						{
  3994  							Items: []*Ydb.Value{{
  3995  								Value: &Ydb.Value_Uint64Value{
  3996  									Uint64Value: 2,
  3997  								},
  3998  							}, {
  3999  								Value: &Ydb.Value_TextValue{
  4000  									TextValue: "2",
  4001  								},
  4002  							}, {
  4003  								Value: &Ydb.Value_BoolValue{
  4004  									BoolValue: false,
  4005  								},
  4006  							}},
  4007  						},
  4008  					},
  4009  				},
  4010  			}, nil)
  4011  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  4012  				Status:         Ydb.StatusIds_SUCCESS,
  4013  				ResultSetIndex: 2,
  4014  				ResultSet: &Ydb.ResultSet{
  4015  					Rows: []*Ydb.Value{
  4016  						{
  4017  							Items: []*Ydb.Value{{
  4018  								Value: &Ydb.Value_Uint64Value{
  4019  									Uint64Value: 3,
  4020  								},
  4021  							}, {
  4022  								Value: &Ydb.Value_TextValue{
  4023  									TextValue: "3",
  4024  								},
  4025  							}, {
  4026  								Value: &Ydb.Value_BoolValue{
  4027  									BoolValue: true,
  4028  								},
  4029  							}},
  4030  						},
  4031  						{
  4032  							Items: []*Ydb.Value{{
  4033  								Value: &Ydb.Value_Uint64Value{
  4034  									Uint64Value: 4,
  4035  								},
  4036  							}, {
  4037  								Value: &Ydb.Value_TextValue{
  4038  									TextValue: "4",
  4039  								},
  4040  							}, {
  4041  								Value: &Ydb.Value_BoolValue{
  4042  									BoolValue: false,
  4043  								},
  4044  							}},
  4045  						},
  4046  						{
  4047  							Items: []*Ydb.Value{{
  4048  								Value: &Ydb.Value_Uint64Value{
  4049  									Uint64Value: 5,
  4050  								},
  4051  							}, {
  4052  								Value: &Ydb.Value_TextValue{
  4053  									TextValue: "5",
  4054  								},
  4055  							}, {
  4056  								Value: &Ydb.Value_BoolValue{
  4057  									BoolValue: false,
  4058  								},
  4059  							}},
  4060  						},
  4061  					},
  4062  				},
  4063  				ExecStats: &Ydb_TableStats.QueryStats{
  4064  					ProcessCpuTimeUs: 300,
  4065  					QueryPlan:        "123",
  4066  					QueryAst:         "456",
  4067  					TotalDurationUs:  100,
  4068  					TotalCpuTimeUs:   200,
  4069  				},
  4070  			}, nil)
  4071  			stream.EXPECT().Recv().Return(nil, io.EOF)
  4072  			var s stats.QueryStats
  4073  			result, err := newResult(ctx, stream, withStatsCallback(func(queryStats stats.QueryStats) {
  4074  				s = queryStats
  4075  			}))
  4076  			require.NoError(t, err)
  4077  			require.NotNil(t, result)
  4078  			defer result.Close(ctx)
  4079  			for {
  4080  				resultSet, err := result.NextResultSet(ctx)
  4081  				if err != nil && xerrors.Is(err, io.EOF) {
  4082  					break
  4083  				}
  4084  				for {
  4085  					_, err := resultSet.NextRow(ctx)
  4086  					if err != nil && xerrors.Is(err, io.EOF) {
  4087  						break
  4088  					}
  4089  				}
  4090  			}
  4091  			require.NotNil(t, s)
  4092  			require.Equal(t, "123", s.QueryPlan())
  4093  			require.Equal(t, "456", s.QueryAST())
  4094  			require.Equal(t, time.Microsecond*100, s.TotalDuration())
  4095  			require.Equal(t, time.Microsecond*200, s.TotalCPUTime())
  4096  			require.Equal(t, time.Microsecond*300, s.ProcessCPUTime())
  4097  		})
  4098  		t.Run("EveryPart", func(t *testing.T) {
  4099  			ctx, cancel := context.WithCancel(xtest.Context(t))
  4100  			defer cancel()
  4101  			ctrl := gomock.NewController(t)
  4102  			stream := NewMockQueryService_ExecuteQueryClient(ctrl)
  4103  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  4104  				Status:         Ydb.StatusIds_SUCCESS,
  4105  				ResultSetIndex: 0,
  4106  				ResultSet: &Ydb.ResultSet{
  4107  					Columns: []*Ydb.Column{
  4108  						{
  4109  							Name: "a",
  4110  							Type: &Ydb.Type{
  4111  								Type: &Ydb.Type_TypeId{
  4112  									TypeId: Ydb.Type_UINT64,
  4113  								},
  4114  							},
  4115  						},
  4116  						{
  4117  							Name: "b",
  4118  							Type: &Ydb.Type{
  4119  								Type: &Ydb.Type_TypeId{
  4120  									TypeId: Ydb.Type_UTF8,
  4121  								},
  4122  							},
  4123  						},
  4124  					},
  4125  					Rows: []*Ydb.Value{
  4126  						{
  4127  							Items: []*Ydb.Value{{
  4128  								Value: &Ydb.Value_Uint64Value{
  4129  									Uint64Value: 1,
  4130  								},
  4131  							}, {
  4132  								Value: &Ydb.Value_TextValue{
  4133  									TextValue: "1",
  4134  								},
  4135  							}},
  4136  						},
  4137  						{
  4138  							Items: []*Ydb.Value{{
  4139  								Value: &Ydb.Value_Uint64Value{
  4140  									Uint64Value: 2,
  4141  								},
  4142  							}, {
  4143  								Value: &Ydb.Value_TextValue{
  4144  									TextValue: "2",
  4145  								},
  4146  							}},
  4147  						},
  4148  						{
  4149  							Items: []*Ydb.Value{{
  4150  								Value: &Ydb.Value_Uint64Value{
  4151  									Uint64Value: 3,
  4152  								},
  4153  							}, {
  4154  								Value: &Ydb.Value_TextValue{
  4155  									TextValue: "3",
  4156  								},
  4157  							}},
  4158  						},
  4159  					},
  4160  				},
  4161  				ExecStats: &Ydb_TableStats.QueryStats{
  4162  					ProcessCpuTimeUs: 1,
  4163  					QueryPlan:        "sdsd",
  4164  					QueryAst:         "sdffds",
  4165  					TotalDurationUs:  2,
  4166  					TotalCpuTimeUs:   3,
  4167  				},
  4168  			}, nil)
  4169  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  4170  				Status:         Ydb.StatusIds_SUCCESS,
  4171  				ResultSetIndex: 0,
  4172  				ResultSet: &Ydb.ResultSet{
  4173  					Rows: []*Ydb.Value{
  4174  						{
  4175  							Items: []*Ydb.Value{{
  4176  								Value: &Ydb.Value_Uint64Value{
  4177  									Uint64Value: 4,
  4178  								},
  4179  							}, {
  4180  								Value: &Ydb.Value_TextValue{
  4181  									TextValue: "4",
  4182  								},
  4183  							}},
  4184  						},
  4185  						{
  4186  							Items: []*Ydb.Value{{
  4187  								Value: &Ydb.Value_Uint64Value{
  4188  									Uint64Value: 5,
  4189  								},
  4190  							}, {
  4191  								Value: &Ydb.Value_TextValue{
  4192  									TextValue: "5",
  4193  								},
  4194  							}},
  4195  						},
  4196  					},
  4197  				},
  4198  				ExecStats: &Ydb_TableStats.QueryStats{
  4199  					ProcessCpuTimeUs: 332400,
  4200  					QueryPlan:        "12wesfse3",
  4201  					QueryAst:         "sedfefs",
  4202  					TotalDurationUs:  10324320,
  4203  					TotalCpuTimeUs:   234,
  4204  				},
  4205  			}, nil)
  4206  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  4207  				Status:         Ydb.StatusIds_SUCCESS,
  4208  				ResultSetIndex: 1,
  4209  				ResultSet: &Ydb.ResultSet{
  4210  					Columns: []*Ydb.Column{
  4211  						{
  4212  							Name: "c",
  4213  							Type: &Ydb.Type{
  4214  								Type: &Ydb.Type_TypeId{
  4215  									TypeId: Ydb.Type_UINT64,
  4216  								},
  4217  							},
  4218  						},
  4219  						{
  4220  							Name: "d",
  4221  							Type: &Ydb.Type{
  4222  								Type: &Ydb.Type_TypeId{
  4223  									TypeId: Ydb.Type_UTF8,
  4224  								},
  4225  							},
  4226  						},
  4227  						{
  4228  							Name: "e",
  4229  							Type: &Ydb.Type{
  4230  								Type: &Ydb.Type_TypeId{
  4231  									TypeId: Ydb.Type_BOOL,
  4232  								},
  4233  							},
  4234  						},
  4235  					},
  4236  					Rows: []*Ydb.Value{
  4237  						{
  4238  							Items: []*Ydb.Value{{
  4239  								Value: &Ydb.Value_Uint64Value{
  4240  									Uint64Value: 1,
  4241  								},
  4242  							}, {
  4243  								Value: &Ydb.Value_TextValue{
  4244  									TextValue: "1",
  4245  								},
  4246  							}, {
  4247  								Value: &Ydb.Value_BoolValue{
  4248  									BoolValue: true,
  4249  								},
  4250  							}},
  4251  						},
  4252  						{
  4253  							Items: []*Ydb.Value{{
  4254  								Value: &Ydb.Value_Uint64Value{
  4255  									Uint64Value: 2,
  4256  								},
  4257  							}, {
  4258  								Value: &Ydb.Value_TextValue{
  4259  									TextValue: "2",
  4260  								},
  4261  							}, {
  4262  								Value: &Ydb.Value_BoolValue{
  4263  									BoolValue: false,
  4264  								},
  4265  							}},
  4266  						},
  4267  					},
  4268  				},
  4269  				ExecStats: &Ydb_TableStats.QueryStats{
  4270  					ProcessCpuTimeUs: 323400,
  4271  					QueryPlan:        "sdfgrdg",
  4272  					QueryAst:         "sdgsrg",
  4273  					TotalDurationUs:  43554,
  4274  					TotalCpuTimeUs:   235643,
  4275  				},
  4276  			}, nil)
  4277  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  4278  				Status:         Ydb.StatusIds_SUCCESS,
  4279  				ResultSetIndex: 1,
  4280  				ResultSet: &Ydb.ResultSet{
  4281  					Rows: []*Ydb.Value{
  4282  						{
  4283  							Items: []*Ydb.Value{{
  4284  								Value: &Ydb.Value_Uint64Value{
  4285  									Uint64Value: 3,
  4286  								},
  4287  							}, {
  4288  								Value: &Ydb.Value_TextValue{
  4289  									TextValue: "3",
  4290  								},
  4291  							}, {
  4292  								Value: &Ydb.Value_BoolValue{
  4293  									BoolValue: true,
  4294  								},
  4295  							}},
  4296  						},
  4297  						{
  4298  							Items: []*Ydb.Value{{
  4299  								Value: &Ydb.Value_Uint64Value{
  4300  									Uint64Value: 4,
  4301  								},
  4302  							}, {
  4303  								Value: &Ydb.Value_TextValue{
  4304  									TextValue: "4",
  4305  								},
  4306  							}, {
  4307  								Value: &Ydb.Value_BoolValue{
  4308  									BoolValue: false,
  4309  								},
  4310  							}},
  4311  						},
  4312  						{
  4313  							Items: []*Ydb.Value{{
  4314  								Value: &Ydb.Value_Uint64Value{
  4315  									Uint64Value: 5,
  4316  								},
  4317  							}, {
  4318  								Value: &Ydb.Value_TextValue{
  4319  									TextValue: "5",
  4320  								},
  4321  							}, {
  4322  								Value: &Ydb.Value_BoolValue{
  4323  									BoolValue: false,
  4324  								},
  4325  							}},
  4326  						},
  4327  					},
  4328  				},
  4329  				ExecStats: &Ydb_TableStats.QueryStats{
  4330  					ProcessCpuTimeUs: 3034564570,
  4331  					QueryPlan:        "sdgsrgsg",
  4332  					QueryAst:         "dghytjf",
  4333  					TotalDurationUs:  45676,
  4334  					TotalCpuTimeUs:   4562342,
  4335  				},
  4336  			}, nil)
  4337  			stream.EXPECT().Recv().Return(&Ydb_Query.ExecuteQueryResponsePart{
  4338  				Status:         Ydb.StatusIds_SUCCESS,
  4339  				ResultSetIndex: 2,
  4340  				ResultSet: &Ydb.ResultSet{
  4341  					Columns: []*Ydb.Column{
  4342  						{
  4343  							Name: "c",
  4344  							Type: &Ydb.Type{
  4345  								Type: &Ydb.Type_TypeId{
  4346  									TypeId: Ydb.Type_UINT64,
  4347  								},
  4348  							},
  4349  						},
  4350  						{
  4351  							Name: "d",
  4352  							Type: &Ydb.Type{
  4353  								Type: &Ydb.Type_TypeId{
  4354  									TypeId: Ydb.Type_UTF8,
  4355  								},
  4356  							},
  4357  						},
  4358  						{
  4359  							Name: "e",
  4360  							Type: &Ydb.Type{
  4361  								Type: &Ydb.Type_TypeId{
  4362  									TypeId: Ydb.Type_BOOL,
  4363  								},
  4364  							},
  4365  						},
  4366  					},
  4367  					Rows: []*Ydb.Value{
  4368  						{
  4369  							Items: []*Ydb.Value{{
  4370  								Value: &Ydb.Value_Uint64Value{
  4371  									Uint64Value: 1,
  4372  								},
  4373  							}, {
  4374  								Value: &Ydb.Value_TextValue{
  4375  									TextValue: "1",
  4376  								},
  4377  							}, {
  4378  								Value: &Ydb.Value_BoolValue{
  4379  									BoolValue: true,
  4380  								},
  4381  							}},
  4382  						},
  4383  						{
  4384  							Items: []*Ydb.Value{{
  4385  								Value: &Ydb.Value_Uint64Value{
  4386  									Uint64Value: 2,
  4387  								},
  4388  							}, {
  4389  								Value: &Ydb.Value_TextValue{
  4390  									TextValue: "2",
  4391  								},
  4392  							}, {
  4393  								Value: &Ydb.Value_BoolValue{
  4394  									BoolValue: false,
  4395  								},
  4396  							}},
  4397  						},
  4398  					},
  4399  				},
  4400  				ExecStats: &Ydb_TableStats.QueryStats{
  4401  					ProcessCpuTimeUs: 300,
  4402  					QueryPlan:        "123",
  4403  					QueryAst:         "456",
  4404  					TotalDurationUs:  100,
  4405  					TotalCpuTimeUs:   200,
  4406  				},
  4407  			}, nil)
  4408  			stream.EXPECT().Recv().Return(nil, io.EOF)
  4409  			var s stats.QueryStats
  4410  			result, err := newResult(ctx, stream, withStatsCallback(func(queryStats stats.QueryStats) {
  4411  				s = queryStats
  4412  			}))
  4413  			require.NoError(t, err)
  4414  			require.NotNil(t, result)
  4415  			defer result.Close(ctx)
  4416  			for {
  4417  				resultSet, err := result.NextResultSet(ctx)
  4418  				if err != nil && xerrors.Is(err, io.EOF) {
  4419  					break
  4420  				}
  4421  				for {
  4422  					_, err := resultSet.NextRow(ctx)
  4423  					if err != nil && xerrors.Is(err, io.EOF) {
  4424  						break
  4425  					}
  4426  				}
  4427  			}
  4428  			require.NotNil(t, s)
  4429  			require.Equal(t, "123", s.QueryPlan())
  4430  			require.Equal(t, "456", s.QueryAST())
  4431  			require.Equal(t, time.Microsecond*100, s.TotalDuration())
  4432  			require.Equal(t, time.Microsecond*200, s.TotalCPUTime())
  4433  			require.Equal(t, time.Microsecond*300, s.ProcessCPUTime())
  4434  		})
  4435  	})
  4436  }