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

     1  package params
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/google/uuid"
     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/allocator"
    12  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/types"
    13  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest"
    14  )
    15  
    16  func TestVariantStruct(t *testing.T) {
    17  	type expected struct {
    18  		Type  *Ydb.Type
    19  		Value *Ydb.Value
    20  	}
    21  
    22  	tests := []struct {
    23  		method string
    24  
    25  		typeArgs []any
    26  		itemArgs []any
    27  
    28  		expected expected
    29  	}{
    30  		{
    31  			method:   "Uint64",
    32  			itemArgs: []any{uint64(123)},
    33  
    34  			expected: expected{
    35  				Type: &Ydb.Type{
    36  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT64},
    37  				},
    38  				Value: &Ydb.Value{
    39  					Value: &Ydb.Value_Uint64Value{
    40  						Uint64Value: 123,
    41  					},
    42  					VariantIndex: 0,
    43  				},
    44  			},
    45  		},
    46  		{
    47  			method:   "Int64",
    48  			itemArgs: []any{int64(123)},
    49  
    50  			expected: expected{
    51  				Type: &Ydb.Type{
    52  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT64},
    53  				},
    54  				Value: &Ydb.Value{
    55  					Value: &Ydb.Value_Int64Value{
    56  						Int64Value: 123,
    57  					},
    58  					VariantIndex: 0,
    59  				},
    60  			},
    61  		},
    62  		{
    63  			method:   "Uint32",
    64  			itemArgs: []any{uint32(123)},
    65  
    66  			expected: expected{
    67  				Type: &Ydb.Type{
    68  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT32},
    69  				},
    70  				Value: &Ydb.Value{
    71  					Value: &Ydb.Value_Uint32Value{
    72  						Uint32Value: 123,
    73  					},
    74  					VariantIndex: 0,
    75  				},
    76  			},
    77  		},
    78  		{
    79  			method:   "Int32",
    80  			itemArgs: []any{int32(123)},
    81  
    82  			expected: expected{
    83  				Type: &Ydb.Type{
    84  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT32},
    85  				},
    86  				Value: &Ydb.Value{
    87  					Value: &Ydb.Value_Int32Value{
    88  						Int32Value: 123,
    89  					},
    90  					VariantIndex: 0,
    91  				},
    92  			},
    93  		},
    94  		{
    95  			method:   "Uint16",
    96  			itemArgs: []any{uint16(123)},
    97  
    98  			expected: expected{
    99  				Type: &Ydb.Type{
   100  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT16},
   101  				},
   102  				Value: &Ydb.Value{
   103  					Value: &Ydb.Value_Uint32Value{
   104  						Uint32Value: 123,
   105  					},
   106  					VariantIndex: 0,
   107  				},
   108  			},
   109  		},
   110  		{
   111  			method:   "Int16",
   112  			itemArgs: []any{int16(123)},
   113  
   114  			expected: expected{
   115  				Type: &Ydb.Type{
   116  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT16},
   117  				},
   118  				Value: &Ydb.Value{
   119  					Value: &Ydb.Value_Int32Value{
   120  						Int32Value: 123,
   121  					},
   122  					VariantIndex: 0,
   123  				},
   124  			},
   125  		},
   126  		{
   127  			method:   "Uint8",
   128  			itemArgs: []any{uint8(123)},
   129  
   130  			expected: expected{
   131  				Type: &Ydb.Type{
   132  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT8},
   133  				},
   134  				Value: &Ydb.Value{
   135  					Value: &Ydb.Value_Uint32Value{
   136  						Uint32Value: 123,
   137  					},
   138  					VariantIndex: 0,
   139  				},
   140  			},
   141  		},
   142  		{
   143  			method:   "Int8",
   144  			itemArgs: []any{int8(123)},
   145  
   146  			expected: expected{
   147  				Type: &Ydb.Type{
   148  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT8},
   149  				},
   150  				Value: &Ydb.Value{
   151  					Value: &Ydb.Value_Int32Value{
   152  						Int32Value: 123,
   153  					},
   154  					VariantIndex: 0,
   155  				},
   156  			},
   157  		},
   158  		{
   159  			method:   "Bool",
   160  			itemArgs: []any{true},
   161  
   162  			expected: expected{
   163  				Type: &Ydb.Type{
   164  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_BOOL},
   165  				},
   166  				Value: &Ydb.Value{
   167  					Value: &Ydb.Value_BoolValue{
   168  						BoolValue: true,
   169  					},
   170  					VariantIndex: 0,
   171  				},
   172  			},
   173  		},
   174  		{
   175  			method:   "Text",
   176  			itemArgs: []any{"test"},
   177  
   178  			expected: expected{
   179  				Type: &Ydb.Type{
   180  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UTF8},
   181  				},
   182  				Value: &Ydb.Value{
   183  					Value: &Ydb.Value_TextValue{
   184  						TextValue: "test",
   185  					},
   186  					VariantIndex: 0,
   187  				},
   188  			},
   189  		},
   190  		{
   191  			method:   "Bytes",
   192  			itemArgs: []any{[]byte("test")},
   193  
   194  			expected: expected{
   195  				Type: &Ydb.Type{
   196  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_STRING},
   197  				},
   198  				Value: &Ydb.Value{
   199  					Value: &Ydb.Value_BytesValue{
   200  						BytesValue: []byte("test"),
   201  					},
   202  					VariantIndex: 0,
   203  				},
   204  			},
   205  		},
   206  		{
   207  			method:   "Float",
   208  			itemArgs: []any{float32(123)},
   209  
   210  			expected: expected{
   211  				Type: &Ydb.Type{
   212  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_FLOAT},
   213  				},
   214  				Value: &Ydb.Value{
   215  					Value: &Ydb.Value_FloatValue{
   216  						FloatValue: float32(123),
   217  					},
   218  					VariantIndex: 0,
   219  				},
   220  			},
   221  		},
   222  		{
   223  			method:   "Double",
   224  			itemArgs: []any{float64(123)},
   225  
   226  			expected: expected{
   227  				Type: &Ydb.Type{
   228  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DOUBLE},
   229  				},
   230  				Value: &Ydb.Value{
   231  					Value: &Ydb.Value_DoubleValue{
   232  						DoubleValue: float64(123),
   233  					},
   234  					VariantIndex: 0,
   235  				},
   236  			},
   237  		},
   238  		{
   239  			method:   "Interval",
   240  			itemArgs: []any{time.Second},
   241  
   242  			expected: expected{
   243  				Type: &Ydb.Type{
   244  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INTERVAL},
   245  				},
   246  				Value: &Ydb.Value{
   247  					Value: &Ydb.Value_Int64Value{
   248  						Int64Value: 1000000,
   249  					},
   250  					VariantIndex: 0,
   251  				},
   252  			},
   253  		},
   254  		{
   255  			method:   "Datetime",
   256  			itemArgs: []any{time.Unix(123456789, 456)},
   257  
   258  			expected: expected{
   259  				Type: &Ydb.Type{
   260  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATETIME},
   261  				},
   262  				Value: &Ydb.Value{
   263  					Value: &Ydb.Value_Uint32Value{
   264  						Uint32Value: 123456789,
   265  					},
   266  					VariantIndex: 0,
   267  				},
   268  			},
   269  		},
   270  		{
   271  			method:   "Date",
   272  			itemArgs: []any{time.Unix(123456789, 456)},
   273  
   274  			expected: expected{
   275  				Type: &Ydb.Type{
   276  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATE},
   277  				},
   278  				Value: &Ydb.Value{
   279  					Value: &Ydb.Value_Uint32Value{
   280  						Uint32Value: 1428,
   281  					},
   282  					VariantIndex: 0,
   283  				},
   284  			},
   285  		},
   286  		{
   287  			method:   "Timestamp",
   288  			itemArgs: []any{time.Unix(123456789, 456)},
   289  
   290  			expected: expected{
   291  				Type: &Ydb.Type{
   292  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TIMESTAMP},
   293  				},
   294  				Value: &Ydb.Value{
   295  					Value: &Ydb.Value_Uint64Value{
   296  						Uint64Value: 123456789000000,
   297  					},
   298  					VariantIndex: 0,
   299  				},
   300  			},
   301  		},
   302  		{
   303  			method:   "Decimal",
   304  			typeArgs: []any{uint32(22), uint32(9)},
   305  			itemArgs: []any{[...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}, uint32(22), uint32(9)},
   306  
   307  			expected: expected{
   308  				Type: &Ydb.Type{
   309  					Type: &Ydb.Type_DecimalType{
   310  						DecimalType: &Ydb.DecimalType{
   311  							Precision: 22,
   312  							Scale:     9,
   313  						},
   314  					},
   315  				},
   316  				Value: &Ydb.Value{
   317  					High_128: 72623859790382856,
   318  					Value: &Ydb.Value_Low_128{
   319  						Low_128: 648519454493508870,
   320  					},
   321  					VariantIndex: 0,
   322  				},
   323  			},
   324  		},
   325  		{
   326  			method:   "JSON",
   327  			itemArgs: []any{`{"a": 1,"b": "B"}`},
   328  
   329  			expected: expected{
   330  				Type: &Ydb.Type{
   331  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_JSON},
   332  				},
   333  				Value: &Ydb.Value{
   334  					Value: &Ydb.Value_TextValue{
   335  						TextValue: `{"a": 1,"b": "B"}`,
   336  					},
   337  					VariantIndex: 0,
   338  				},
   339  			},
   340  		},
   341  		{
   342  			method:   "JSONDocument",
   343  			itemArgs: []any{`{"a": 1,"b": "B"}`},
   344  
   345  			expected: expected{
   346  				Type: &Ydb.Type{
   347  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_JSON_DOCUMENT},
   348  				},
   349  				Value: &Ydb.Value{
   350  					Value: &Ydb.Value_TextValue{
   351  						TextValue: `{"a": 1,"b": "B"}`,
   352  					},
   353  					VariantIndex: 0,
   354  				},
   355  			},
   356  		},
   357  		{
   358  			method:   "YSON",
   359  			itemArgs: []any{[]byte(`{"a": 1,"b": "B"}`)},
   360  
   361  			expected: expected{
   362  				Type: &Ydb.Type{
   363  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_YSON},
   364  				},
   365  				Value: &Ydb.Value{
   366  					Value: &Ydb.Value_BytesValue{
   367  						BytesValue: []byte(`{"a": 1,"b": "B"}`),
   368  					},
   369  					VariantIndex: 0,
   370  				},
   371  			},
   372  		},
   373  		{
   374  			method:   "Uuid",
   375  			itemArgs: []any{uuid.UUID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}},
   376  
   377  			expected: expected{
   378  				Type: &Ydb.Type{
   379  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UUID},
   380  				},
   381  				Value: &Ydb.Value{
   382  					Value: &Ydb.Value_Low_128{
   383  						Low_128: 506660481424032516,
   384  					},
   385  					High_128:     1157159078456920585,
   386  					VariantIndex: 0,
   387  				},
   388  			},
   389  		},
   390  		{
   391  			method:   "UUIDWithIssue1501Value",
   392  			itemArgs: []any{[...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}},
   393  
   394  			expected: expected{
   395  				Type: &Ydb.Type{
   396  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UUID},
   397  				},
   398  				Value: &Ydb.Value{
   399  					Value: &Ydb.Value_Low_128{
   400  						Low_128: 651345242494996240,
   401  					},
   402  					High_128:     72623859790382856,
   403  					VariantIndex: 0,
   404  				},
   405  			},
   406  		},
   407  		{
   408  			method:   "TzDatetime",
   409  			itemArgs: []any{time.Unix(123456789, 456).UTC()},
   410  
   411  			expected: expected{
   412  				Type: &Ydb.Type{
   413  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TZ_DATETIME},
   414  				},
   415  				Value: &Ydb.Value{
   416  					Value: &Ydb.Value_TextValue{
   417  						TextValue: "1973-11-29T21:33:09Z",
   418  					},
   419  					VariantIndex: 0,
   420  				},
   421  			},
   422  		},
   423  		{
   424  			method:   "TzDate",
   425  			itemArgs: []any{time.Unix(123456789, 456).UTC()},
   426  
   427  			expected: expected{
   428  				Type: &Ydb.Type{
   429  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TZ_DATE},
   430  				},
   431  				Value: &Ydb.Value{
   432  					Value: &Ydb.Value_TextValue{
   433  						TextValue: "1973-11-29",
   434  					},
   435  					VariantIndex: 0,
   436  				},
   437  			},
   438  		},
   439  		{
   440  			method:   "TzTimestamp",
   441  			itemArgs: []any{time.Unix(123456789, 456).UTC()},
   442  
   443  			expected: expected{
   444  				Type: &Ydb.Type{
   445  					Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TZ_TIMESTAMP},
   446  				},
   447  				Value: &Ydb.Value{
   448  					Value: &Ydb.Value_TextValue{
   449  						TextValue: "1973-11-29T21:33:09.000000Z",
   450  					},
   451  					VariantIndex: 0,
   452  				},
   453  			},
   454  		},
   455  	}
   456  
   457  	for _, tc := range tests {
   458  		t.Run(tc.method, func(t *testing.T) {
   459  			a := allocator.New()
   460  			defer a.Free()
   461  
   462  			item := Builder{}.Param("$x").BeginVariant().BeginStruct().Field("key")
   463  
   464  			vs, ok := xtest.CallMethod(item, tc.method, tc.typeArgs...)[0].(*variantStruct)
   465  			require.True(t, ok)
   466  
   467  			builder, ok := xtest.CallMethod(vs.Name("key"), tc.method, tc.itemArgs...)[0].(*variantStructBuilder)
   468  			require.True(t, ok)
   469  
   470  			params := builder.EndStruct().EndVariant().Build().ToYDB(a)
   471  
   472  			require.Equal(t, xtest.ToJSON(
   473  				map[string]*Ydb.TypedValue{
   474  					"$x": {
   475  						Type: &Ydb.Type{
   476  							Type: &Ydb.Type_VariantType{
   477  								VariantType: &Ydb.VariantType{
   478  									Type: &Ydb.VariantType_StructItems{
   479  										StructItems: &Ydb.StructType{
   480  											Members: []*Ydb.StructMember{
   481  												{
   482  													Name: "key",
   483  													Type: tc.expected.Type,
   484  												},
   485  											},
   486  										},
   487  									},
   488  								},
   489  							},
   490  						},
   491  						Value: &Ydb.Value{
   492  							Value: &Ydb.Value_NestedValue{
   493  								NestedValue: tc.expected.Value,
   494  							},
   495  							VariantIndex: 0,
   496  						},
   497  					},
   498  				}), xtest.ToJSON(params))
   499  		})
   500  	}
   501  }
   502  
   503  func TestVariantStruct_AddFields(t *testing.T) {
   504  	a := allocator.New()
   505  	defer a.Free()
   506  
   507  	params := Builder{}.Param("$x").BeginVariant().BeginStruct().
   508  		AddFields([]types.StructField{
   509  			{
   510  				Name: "key1",
   511  				T:    types.Bool,
   512  			},
   513  			{
   514  				Name: "key2",
   515  				T:    types.Uint64,
   516  			},
   517  			{
   518  				Name: "key3",
   519  				T:    types.Text,
   520  			},
   521  		}...).Name("key3").Text("Hello, World!").EndStruct().
   522  		EndVariant().Build().ToYDB(a)
   523  
   524  	require.Equal(t, xtest.ToJSON(
   525  		map[string]*Ydb.TypedValue{
   526  			"$x": {
   527  				Type: &Ydb.Type{
   528  					Type: &Ydb.Type_VariantType{
   529  						VariantType: &Ydb.VariantType{
   530  							Type: &Ydb.VariantType_StructItems{
   531  								StructItems: &Ydb.StructType{
   532  									Members: []*Ydb.StructMember{
   533  										{
   534  											Name: "key1",
   535  											Type: &Ydb.Type{
   536  												Type: &Ydb.Type_TypeId{
   537  													TypeId: Ydb.Type_BOOL,
   538  												},
   539  											},
   540  										},
   541  										{
   542  											Name: "key2",
   543  											Type: &Ydb.Type{
   544  												Type: &Ydb.Type_TypeId{
   545  													TypeId: Ydb.Type_UINT64,
   546  												},
   547  											},
   548  										},
   549  										{
   550  											Name: "key3",
   551  											Type: &Ydb.Type{
   552  												Type: &Ydb.Type_TypeId{
   553  													TypeId: Ydb.Type_UTF8,
   554  												},
   555  											},
   556  										},
   557  									},
   558  								},
   559  							},
   560  						},
   561  					},
   562  				},
   563  				Value: &Ydb.Value{
   564  					Value: &Ydb.Value_NestedValue{
   565  						NestedValue: &Ydb.Value{
   566  							Value: &Ydb.Value_TextValue{
   567  								TextValue: "Hello, World!",
   568  							},
   569  						},
   570  					},
   571  					VariantIndex: 2,
   572  				},
   573  			},
   574  		}), xtest.ToJSON(params))
   575  }