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 }