github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/query/scanner/indexed_test.go (about)

     1  package scanner
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/require"
     9  	"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
    10  
    11  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/value"
    12  )
    13  
    14  func TestIndexed(t *testing.T) {
    15  	for _, tt := range []struct {
    16  		name string
    17  		s    IndexedScanner
    18  		dst  [][]interface{}
    19  		exp  [][]interface{}
    20  	}{
    21  		{
    22  			name: "Ydb.Type_UTF8",
    23  			s: Indexed(Data(
    24  				[]*Ydb.Column{
    25  					{
    26  						Type: &Ydb.Type{
    27  							Type: &Ydb.Type_TypeId{
    28  								TypeId: Ydb.Type_UTF8,
    29  							},
    30  						},
    31  					},
    32  				},
    33  				[]*Ydb.Value{
    34  					{
    35  						Value: &Ydb.Value_TextValue{
    36  							TextValue: "test",
    37  						},
    38  					},
    39  				},
    40  			)),
    41  			dst: [][]interface{}{
    42  				{func(v string) *string { return &v }("")},
    43  				{func(v []byte) *[]byte { return &v }([]byte(""))},
    44  			},
    45  			exp: [][]interface{}{
    46  				{func(v string) *string { return &v }("test")},
    47  				{func(v []byte) *[]byte { return &v }([]byte("test"))},
    48  			},
    49  		},
    50  		{
    51  			name: "Ydb.Type_STRING",
    52  			s: Indexed(Data(
    53  				[]*Ydb.Column{
    54  					{
    55  						Type: &Ydb.Type{
    56  							Type: &Ydb.Type_TypeId{
    57  								TypeId: Ydb.Type_STRING,
    58  							},
    59  						},
    60  					},
    61  				},
    62  				[]*Ydb.Value{
    63  					{
    64  						Value: &Ydb.Value_BytesValue{
    65  							BytesValue: []byte("test"),
    66  						},
    67  					},
    68  				},
    69  			)),
    70  			dst: [][]interface{}{
    71  				{func(v string) *string { return &v }("")},
    72  				{func(v []byte) *[]byte { return &v }([]byte(""))},
    73  			},
    74  			exp: [][]interface{}{
    75  				{func(v string) *string { return &v }("test")},
    76  				{func(v []byte) *[]byte { return &v }([]byte("test"))},
    77  			},
    78  		},
    79  		{
    80  			name: "Ydb.Type_UINT64",
    81  			s: Indexed(Data(
    82  				[]*Ydb.Column{
    83  					{
    84  						Type: &Ydb.Type{
    85  							Type: &Ydb.Type_TypeId{
    86  								TypeId: Ydb.Type_UINT64,
    87  							},
    88  						},
    89  					},
    90  				},
    91  				[]*Ydb.Value{
    92  					{
    93  						Value: &Ydb.Value_Uint64Value{
    94  							Uint64Value: 123,
    95  						},
    96  					},
    97  				},
    98  			)),
    99  			dst: [][]interface{}{
   100  				{func(v uint64) *uint64 { return &v }(0)},
   101  			},
   102  			exp: [][]interface{}{
   103  				{func(v uint64) *uint64 { return &v }(123)},
   104  			},
   105  		},
   106  		{
   107  			name: "Ydb.Type_INT64",
   108  			s: Indexed(Data(
   109  				[]*Ydb.Column{
   110  					{
   111  						Type: &Ydb.Type{
   112  							Type: &Ydb.Type_TypeId{
   113  								TypeId: Ydb.Type_INT64,
   114  							},
   115  						},
   116  					},
   117  				},
   118  				[]*Ydb.Value{
   119  					{
   120  						Value: &Ydb.Value_Int64Value{
   121  							Int64Value: 123,
   122  						},
   123  					},
   124  				},
   125  			)),
   126  			dst: [][]interface{}{
   127  				{func(v int64) *int64 { return &v }(0)},
   128  			},
   129  			exp: [][]interface{}{
   130  				{func(v int64) *int64 { return &v }(123)},
   131  			},
   132  		},
   133  		{
   134  			name: "Ydb.Type_UINT32",
   135  			s: Indexed(Data(
   136  				[]*Ydb.Column{
   137  					{
   138  						Type: &Ydb.Type{
   139  							Type: &Ydb.Type_TypeId{
   140  								TypeId: Ydb.Type_UINT32,
   141  							},
   142  						},
   143  					},
   144  				},
   145  				[]*Ydb.Value{
   146  					{
   147  						Value: &Ydb.Value_Uint32Value{
   148  							Uint32Value: 123,
   149  						},
   150  					},
   151  				},
   152  			)),
   153  			dst: [][]interface{}{
   154  				{func(v uint64) *uint64 { return &v }(0)},
   155  				{func(v int64) *int64 { return &v }(0)},
   156  				{func(v uint32) *uint32 { return &v }(0)},
   157  				{func(v float64) *float64 { return &v }(0)},
   158  			},
   159  			exp: [][]interface{}{
   160  				{func(v uint64) *uint64 { return &v }(123)},
   161  				{func(v int64) *int64 { return &v }(123)},
   162  				{func(v uint32) *uint32 { return &v }(123)},
   163  				{func(v float64) *float64 { return &v }(123)},
   164  			},
   165  		},
   166  		{
   167  			name: "Ydb.Type_INT32",
   168  			s: Indexed(Data(
   169  				[]*Ydb.Column{
   170  					{
   171  						Type: &Ydb.Type{
   172  							Type: &Ydb.Type_TypeId{
   173  								TypeId: Ydb.Type_INT32,
   174  							},
   175  						},
   176  					},
   177  				},
   178  				[]*Ydb.Value{
   179  					{
   180  						Value: &Ydb.Value_Int32Value{
   181  							Int32Value: 123,
   182  						},
   183  					},
   184  				},
   185  			)),
   186  			dst: [][]interface{}{
   187  				{func(v int64) *int64 { return &v }(0)},
   188  				{func(v int32) *int32 { return &v }(0)},
   189  				{func(v int) *int { return &v }(0)},
   190  				{func(v float32) *float32 { return &v }(0)},
   191  				{func(v float64) *float64 { return &v }(0)},
   192  			},
   193  			exp: [][]interface{}{
   194  				{func(v int64) *int64 { return &v }(123)},
   195  				{func(v int32) *int32 { return &v }(123)},
   196  				{func(v int) *int { return &v }(123)},
   197  				{func(v float32) *float32 { return &v }(123)},
   198  				{func(v float64) *float64 { return &v }(123)},
   199  			},
   200  		},
   201  		{
   202  			name: "Ydb.Type_UINT16",
   203  			s: Indexed(Data(
   204  				[]*Ydb.Column{
   205  					{
   206  						Type: &Ydb.Type{
   207  							Type: &Ydb.Type_TypeId{
   208  								TypeId: Ydb.Type_UINT16,
   209  							},
   210  						},
   211  					},
   212  				},
   213  				[]*Ydb.Value{
   214  					{
   215  						Value: &Ydb.Value_Uint32Value{
   216  							Uint32Value: 123,
   217  						},
   218  					},
   219  				},
   220  			)),
   221  			dst: [][]interface{}{
   222  				{func(v uint64) *uint64 { return &v }(0)},
   223  				{func(v int64) *int64 { return &v }(0)},
   224  				{func(v uint32) *uint32 { return &v }(0)},
   225  				{func(v int32) *int32 { return &v }(0)},
   226  				{func(v float32) *float32 { return &v }(0)},
   227  				{func(v float64) *float64 { return &v }(0)},
   228  			},
   229  			exp: [][]interface{}{
   230  				{func(v uint64) *uint64 { return &v }(123)},
   231  				{func(v int64) *int64 { return &v }(123)},
   232  				{func(v uint32) *uint32 { return &v }(123)},
   233  				{func(v int32) *int32 { return &v }(123)},
   234  				{func(v float32) *float32 { return &v }(123)},
   235  				{func(v float64) *float64 { return &v }(123)},
   236  			},
   237  		},
   238  		{
   239  			name: "Ydb.Type_INT16",
   240  			s: Indexed(Data(
   241  				[]*Ydb.Column{
   242  					{
   243  						Type: &Ydb.Type{
   244  							Type: &Ydb.Type_TypeId{
   245  								TypeId: Ydb.Type_INT16,
   246  							},
   247  						},
   248  					},
   249  				},
   250  				[]*Ydb.Value{
   251  					{
   252  						Value: &Ydb.Value_Int32Value{
   253  							Int32Value: 123,
   254  						},
   255  					},
   256  				},
   257  			)),
   258  			dst: [][]interface{}{
   259  				{func(v int64) *int64 { return &v }(0)},
   260  				{func(v int32) *int32 { return &v }(0)},
   261  				{func(v float32) *float32 { return &v }(0)},
   262  				{func(v float64) *float64 { return &v }(0)},
   263  			},
   264  			exp: [][]interface{}{
   265  				{func(v int64) *int64 { return &v }(123)},
   266  				{func(v int32) *int32 { return &v }(123)},
   267  				{func(v float32) *float32 { return &v }(123)},
   268  				{func(v float64) *float64 { return &v }(123)},
   269  			},
   270  		},
   271  		{
   272  			name: "Ydb.Type_UINT8",
   273  			s: Indexed(Data(
   274  				[]*Ydb.Column{
   275  					{
   276  						Type: &Ydb.Type{
   277  							Type: &Ydb.Type_TypeId{
   278  								TypeId: Ydb.Type_UINT8,
   279  							},
   280  						},
   281  					},
   282  				},
   283  				[]*Ydb.Value{
   284  					{
   285  						Value: &Ydb.Value_Uint32Value{
   286  							Uint32Value: 123,
   287  						},
   288  					},
   289  				},
   290  			)),
   291  			dst: [][]interface{}{
   292  				{func(v uint64) *uint64 { return &v }(0)},
   293  				{func(v int64) *int64 { return &v }(0)},
   294  				{func(v uint32) *uint32 { return &v }(0)},
   295  				{func(v int32) *int32 { return &v }(0)},
   296  				{func(v uint8) *uint8 { return &v }(0)},
   297  				{func(v float32) *float32 { return &v }(0)},
   298  				{func(v float64) *float64 { return &v }(0)},
   299  			},
   300  			exp: [][]interface{}{
   301  				{func(v uint64) *uint64 { return &v }(123)},
   302  				{func(v int64) *int64 { return &v }(123)},
   303  				{func(v uint32) *uint32 { return &v }(123)},
   304  				{func(v int32) *int32 { return &v }(123)},
   305  				{func(v uint8) *uint8 { return &v }(123)},
   306  				{func(v float32) *float32 { return &v }(123)},
   307  				{func(v float64) *float64 { return &v }(123)},
   308  			},
   309  		},
   310  		{
   311  			name: "Ydb.Type_INT8",
   312  			s: Indexed(Data(
   313  				[]*Ydb.Column{
   314  					{
   315  						Type: &Ydb.Type{
   316  							Type: &Ydb.Type_TypeId{
   317  								TypeId: Ydb.Type_INT8,
   318  							},
   319  						},
   320  					},
   321  				},
   322  				[]*Ydb.Value{
   323  					{
   324  						Value: &Ydb.Value_Int32Value{
   325  							Int32Value: 123,
   326  						},
   327  					},
   328  				},
   329  			)),
   330  			dst: [][]interface{}{
   331  				{func(v int64) *int64 { return &v }(0)},
   332  				{func(v int32) *int32 { return &v }(0)},
   333  				{func(v int8) *int8 { return &v }(0)},
   334  				{func(v float32) *float32 { return &v }(0)},
   335  				{func(v float64) *float64 { return &v }(0)},
   336  			},
   337  			exp: [][]interface{}{
   338  				{func(v int64) *int64 { return &v }(123)},
   339  				{func(v int32) *int32 { return &v }(123)},
   340  				{func(v int8) *int8 { return &v }(123)},
   341  				{func(v float32) *float32 { return &v }(123)},
   342  				{func(v float64) *float64 { return &v }(123)},
   343  			},
   344  		},
   345  		{
   346  			name: "Ydb.Type_BOOL",
   347  			s: Indexed(Data(
   348  				[]*Ydb.Column{
   349  					{
   350  						Type: &Ydb.Type{
   351  							Type: &Ydb.Type_TypeId{
   352  								TypeId: Ydb.Type_BOOL,
   353  							},
   354  						},
   355  					},
   356  				},
   357  				[]*Ydb.Value{
   358  					{
   359  						Value: &Ydb.Value_BoolValue{
   360  							BoolValue: true,
   361  						},
   362  					},
   363  				},
   364  			)),
   365  			dst: [][]interface{}{
   366  				{func(v bool) *bool { return &v }(false)},
   367  			},
   368  			exp: [][]interface{}{
   369  				{func(v bool) *bool { return &v }(true)},
   370  			},
   371  		},
   372  		{
   373  			name: "Ydb.Type_DATE",
   374  			s: Indexed(Data(
   375  				[]*Ydb.Column{
   376  					{
   377  						Type: &Ydb.Type{
   378  							Type: &Ydb.Type_TypeId{
   379  								TypeId: Ydb.Type_DATE,
   380  							},
   381  						},
   382  					},
   383  				},
   384  				[]*Ydb.Value{
   385  					{
   386  						Value: &Ydb.Value_Uint32Value{
   387  							Uint32Value: 100500,
   388  						},
   389  					},
   390  				},
   391  			)),
   392  			dst: [][]interface{}{
   393  				{func(v uint64) *uint64 { return &v }(0)},
   394  				{func(v int64) *int64 { return &v }(0)},
   395  				{func(v int32) *int32 { return &v }(0)},
   396  				{func(v time.Time) *time.Time { return &v }(time.Unix(0, 0))},
   397  			},
   398  			exp: [][]interface{}{
   399  				{func(v uint64) *uint64 { return &v }(100500)},
   400  				{func(v int64) *int64 { return &v }(100500)},
   401  				{func(v int32) *int32 { return &v }(100500)},
   402  				{func(v time.Time) *time.Time { return &v }(time.Unix(8683200000, 0))},
   403  			},
   404  		},
   405  		{
   406  			name: "Ydb.Type_DATETIME",
   407  			s: Indexed(Data(
   408  				[]*Ydb.Column{
   409  					{
   410  						Type: &Ydb.Type{
   411  							Type: &Ydb.Type_TypeId{
   412  								TypeId: Ydb.Type_DATETIME,
   413  							},
   414  						},
   415  					},
   416  				},
   417  				[]*Ydb.Value{
   418  					{
   419  						Value: &Ydb.Value_Uint32Value{
   420  							Uint32Value: 100500,
   421  						},
   422  					},
   423  				},
   424  			)),
   425  			dst: [][]interface{}{
   426  				{func(v uint64) *uint64 { return &v }(0)},
   427  				{func(v int64) *int64 { return &v }(0)},
   428  				{func(v uint32) *uint32 { return &v }(0)},
   429  				{func(v time.Time) *time.Time { return &v }(time.Unix(0, 0))},
   430  			},
   431  			exp: [][]interface{}{
   432  				{func(v uint64) *uint64 { return &v }(100500)},
   433  				{func(v int64) *int64 { return &v }(100500)},
   434  				{func(v uint32) *uint32 { return &v }(100500)},
   435  				{func(v time.Time) *time.Time { return &v }(time.Unix(100500, 0))},
   436  			},
   437  		},
   438  		{
   439  			name: "Ydb.Type_TIMESTAMP",
   440  			s: Indexed(Data(
   441  				[]*Ydb.Column{
   442  					{
   443  						Type: &Ydb.Type{
   444  							Type: &Ydb.Type_TypeId{
   445  								TypeId: Ydb.Type_TIMESTAMP,
   446  							},
   447  						},
   448  					},
   449  				},
   450  				[]*Ydb.Value{
   451  					{
   452  						Value: &Ydb.Value_Uint64Value{
   453  							Uint64Value: 12345678987654321,
   454  						},
   455  					},
   456  				},
   457  			)),
   458  			dst: [][]interface{}{
   459  				{func(v uint64) *uint64 { return &v }(0)},
   460  				{func(v time.Time) *time.Time { return &v }(time.Unix(0, 0))},
   461  			},
   462  			exp: [][]interface{}{
   463  				{func(v uint64) *uint64 { return &v }(12345678987654321)},
   464  				{func(v time.Time) *time.Time { return &v }(time.Unix(12345678987, 654321000))},
   465  			},
   466  		},
   467  		{
   468  			name: "Ydb.Type_INTERVAL",
   469  			s: Indexed(Data(
   470  				[]*Ydb.Column{
   471  					{
   472  						Type: &Ydb.Type{
   473  							Type: &Ydb.Type_TypeId{
   474  								TypeId: Ydb.Type_INTERVAL,
   475  							},
   476  						},
   477  					},
   478  				},
   479  				[]*Ydb.Value{
   480  					{
   481  						Value: &Ydb.Value_Int64Value{
   482  							Int64Value: 100500,
   483  						},
   484  					},
   485  				},
   486  			)),
   487  			dst: [][]interface{}{
   488  				{func(v int64) *int64 { return &v }(0)},
   489  				{func(v time.Duration) *time.Duration { return &v }(time.Duration(0))},
   490  			},
   491  			exp: [][]interface{}{
   492  				{func(v int64) *int64 { return &v }(100500)},
   493  				{func(v time.Duration) *time.Duration { return &v }(time.Duration(100500000))},
   494  			},
   495  		},
   496  	} {
   497  		for i := range tt.dst {
   498  			t.Run(tt.name+"→"+reflect.TypeOf(tt.dst[i][0]).Elem().String(), func(t *testing.T) {
   499  				err := tt.s.Scan(tt.dst[i]...)
   500  				require.NoError(t, err)
   501  				require.Equal(t, tt.exp[i], tt.dst[i])
   502  			})
   503  		}
   504  	}
   505  }
   506  
   507  func TestIndexedIncompatibleColumnsAndDestinations(t *testing.T) {
   508  	scanner := &IndexedScanner{data: Data(
   509  		[]*Ydb.Column{
   510  			{
   511  				Name: "a",
   512  				Type: &Ydb.Type{
   513  					Type: &Ydb.Type_TypeId{
   514  						TypeId: Ydb.Type_UTF8,
   515  					},
   516  				},
   517  			},
   518  		},
   519  		[]*Ydb.Value{
   520  			{
   521  				Value: &Ydb.Value_TextValue{
   522  					TextValue: "test",
   523  				},
   524  			},
   525  		},
   526  	)}
   527  	var (
   528  		B string
   529  		C string
   530  	)
   531  	err := scanner.Scan(&B, &C)
   532  	require.ErrorIs(t, err, errIncompatibleColumnsAndDestinations)
   533  }
   534  
   535  func TestIndexedCastFailed(t *testing.T) {
   536  	scanner := Indexed(Data(
   537  		[]*Ydb.Column{
   538  			{
   539  				Name: "a",
   540  				Type: &Ydb.Type{
   541  					Type: &Ydb.Type_TypeId{
   542  						TypeId: Ydb.Type_UTF8,
   543  					},
   544  				},
   545  			},
   546  		},
   547  		[]*Ydb.Value{
   548  			{
   549  				Value: &Ydb.Value_TextValue{
   550  					TextValue: "test",
   551  				},
   552  			},
   553  		},
   554  	))
   555  	var A uint64
   556  	err := scanner.Scan(&A)
   557  	require.ErrorIs(t, err, value.ErrCannotCast)
   558  }