diff --git a/CHANGELOG.md b/CHANGELOG.md index 66ca02337..4b76e41ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +* Added `Tuple` support for `Variant` in `ydb.ParamsBuilder()` + ## v3.60.1 * Added additional traces for coordination service client internals diff --git a/internal/params/parameters.go b/internal/params/parameters.go index 7faa23041..aae4e38d0 100644 --- a/internal/params/parameters.go +++ b/internal/params/parameters.go @@ -141,6 +141,13 @@ func (p *Parameter) BeginStruct() *structure { } } +func (p *Parameter) BeginVariant() *variant { + return &variant{ + parent: p.parent, + name: p.name, + } +} + func (p *Parameter) Text(v string) Builder { p.value = value.TextValue(v) p.parent.params = append(p.parent.params, p) diff --git a/internal/params/tuple.go b/internal/params/tuple.go index 0762cdb05..7718a5026 100644 --- a/internal/params/tuple.go +++ b/internal/params/tuple.go @@ -170,3 +170,21 @@ func (t *tupleItem) UUID(v [16]byte) *tuple { return t.parent } + +func (t *tupleItem) TzDate(v time.Time) *tuple { + t.parent.values = append(t.parent.values, value.TzDateValueFromTime(v)) + + return t.parent +} + +func (t *tupleItem) TzTimestamp(v time.Time) *tuple { + t.parent.values = append(t.parent.values, value.TzTimestampValueFromTime(v)) + + return t.parent +} + +func (t *tupleItem) TzDatetime(v time.Time) *tuple { + t.parent.values = append(t.parent.values, value.TzDatetimeValueFromTime(v)) + + return t.parent +} diff --git a/internal/params/tuple_test.go b/internal/params/tuple_test.go index 67732efeb..1c6510603 100644 --- a/internal/params/tuple_test.go +++ b/internal/params/tuple_test.go @@ -13,723 +13,476 @@ import ( ) func TestTuple(t *testing.T) { - for _, tt := range []struct { - name string - builder Builder - params map[string]*Ydb.TypedValue + type expected struct { + Type *Ydb.Type + Value *Ydb.Value + } + + tests := []struct { + method string + args []any + + expected expected }{ { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Uint64(123).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_UINT64, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Uint64Value{ - Uint64Value: 123, - }, - }, - }, + method: "Uint64", + args: []any{uint64(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT64}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint64Value{ + Uint64Value: 123, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Int64(123).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_INT64, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Int64Value{ - Int64Value: 123, - }, - }, - }, + method: "Int64", + args: []any{int64(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT64}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Int64Value{ + Int64Value: 123, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Uint32(123).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_UINT32, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Uint32Value{ - Uint32Value: 123, - }, - }, - }, + method: "Uint32", + args: []any{uint32(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT32}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Int32(123).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_INT32, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Int32Value{ - Int32Value: 123, - }, - }, - }, + method: "Int32", + args: []any{int32(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT32}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Int32Value{ + Int32Value: 123, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Uint16(123).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_UINT16, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Uint32Value{ - Uint32Value: 123, - }, - }, - }, + method: "Uint16", + args: []any{uint16(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT16}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Int16(123).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_INT16, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Int32Value{ - Int32Value: 123, - }, - }, - }, + method: "Int16", + args: []any{int16(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT16}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Int32Value{ + Int32Value: 123, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Uint8(123).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_UINT8, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Uint32Value{ - Uint32Value: 123, - }, - }, - }, + method: "Uint8", + args: []any{uint8(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT8}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Int8(123).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_INT8, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Int32Value{ - Int32Value: 123, - }, - }, - }, + method: "Int8", + args: []any{int8(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT8}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Int32Value{ + Int32Value: 123, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Bool(true).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_BOOL, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_BoolValue{ - BoolValue: true, - }, - }, - }, + method: "Bool", + args: []any{true}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_BOOL}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_BoolValue{ + BoolValue: true, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Text("test").EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_UTF8, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_TextValue{ - TextValue: "test", - }, - }, - }, + method: "Text", + args: []any{"test"}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UTF8}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: "test", }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Bytes([]byte("test")).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_STRING, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_BytesValue{ - BytesValue: []byte("test"), - }, - }, - }, + method: "Bytes", + args: []any{[]byte("test")}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_STRING}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_BytesValue{ + BytesValue: []byte("test"), }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Float(123).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_FLOAT, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_FloatValue{ - FloatValue: 123, - }, - }, - }, + method: "Float", + args: []any{float32(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_FLOAT}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_FloatValue{ + FloatValue: float32(123), }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Double(123).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_DOUBLE, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_DoubleValue{ - DoubleValue: 123, - }, - }, - }, + method: "Double", + args: []any{float64(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DOUBLE}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_DoubleValue{ + DoubleValue: float64(123), }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Interval(time.Second).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_INTERVAL, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Int64Value{ - Int64Value: 1000000, - }, - }, - }, + method: "Interval", + args: []any{time.Second}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INTERVAL}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Int64Value{ + Int64Value: 1000000, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Datetime(time.Unix(123456789, 456)).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_DATETIME, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Uint32Value{ - Uint32Value: 123456789, - }, - }, - }, + method: "Datetime", + args: []any{time.Unix(123456789, 456)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATETIME}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123456789, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Date(time.Unix(123456789, 456)).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_DATE, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Uint32Value{ - Uint32Value: 1428, - }, - }, - }, + method: "Date", + args: []any{time.Unix(123456789, 456)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATE}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 1428, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Timestamp(time.Unix(123456789, 456)).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_TIMESTAMP, - }, - }, - }, - }, - }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Uint64Value{ - Uint64Value: 123456789000000, - }, - }, - }, + method: "Timestamp", + args: []any{time.Unix(123456789, 456)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TIMESTAMP}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint64Value{ + Uint64Value: 123456789000000, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().Decimal([...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}, 22, 9).EndTuple(), //nolint:lll - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_DecimalType{ - DecimalType: &Ydb.DecimalType{ - Precision: 22, - Scale: 9, - }, - }, - }, - }, - }, + method: "Decimal", + args: []any{[...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}, uint32(22), uint32(9)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_DecimalType{ + DecimalType: &Ydb.DecimalType{ + Precision: 22, + Scale: 9, }, }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - High_128: 72623859790382856, - Value: &Ydb.Value_Low_128{ - Low_128: 648519454493508870, - }, - }, - }, + }, + Value: &Ydb.Value{ + High_128: 72623859790382856, + Value: &Ydb.Value_Low_128{ + Low_128: 648519454493508870, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().JSON(`{"a": 1,"b": "B"}`).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_JSON, - }, - }, - }, - }, - }, + method: "JSON", + args: []any{`{"a": 1,"b": "B"}`}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_JSON}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: `{"a": 1,"b": "B"}`, }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_TextValue{ - TextValue: `{"a": 1,"b": "B"}`, - }, - }, - }, + }, + }, + }, + { + method: "JSONDocument", + args: []any{`{"a": 1,"b": "B"}`}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_JSON_DOCUMENT}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: `{"a": 1,"b": "B"}`, }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().JSONDocument(`{"a": 1,"b": "B"}`).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_JSON_DOCUMENT, - }, - }, - }, - }, - }, + method: "YSON", + args: []any{[]byte(`{"a": 1,"b": "B"}`)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_YSON}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_BytesValue{ + BytesValue: []byte(`{"a": 1,"b": "B"}`), }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_TextValue{ - TextValue: `{"a": 1,"b": "B"}`, - }, - }, - }, + }, + }, + }, + { + method: "UUID", + args: []any{[...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UUID}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Low_128{ + Low_128: 651345242494996240, }, + High_128: 72623859790382856, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add().YSON([]byte(`[ 1; 2; 3; 4; 5 ]`)).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_YSON, - }, - }, - }, - }, - }, + method: "TzDatetime", + args: []any{time.Unix(123456789, 456).UTC()}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TZ_DATETIME}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: "1973-11-29T21:33:09Z", }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_BytesValue{ - BytesValue: []byte(`[ 1; 2; 3; 4; 5 ]`), - }, - }, - }, + }, + }, + }, + { + method: "TzDate", + args: []any{time.Unix(123456789, 456).UTC()}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TZ_DATE}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: "1973-11-29", }, }, }, }, { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().Add(). - UUID([...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_UUID, - }, + method: "TzTimestamp", + args: []any{time.Unix(123456789, 456).UTC()}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TZ_TIMESTAMP}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: "1973-11-29T21:33:09.000000Z", + }, + }, + }, + }, + } + + for _, tc := range tests { + t.Run(tc.method, func(t *testing.T) { + a := allocator.New() + defer a.Free() + + item := Builder{}.Param("$x").BeginTuple().Add() + + result, ok := xtest.CallMethod(item, tc.method, tc.args...)[0].(*tuple) + require.True(t, ok) + + params := result.EndTuple().Build().ToYDB(a) + require.Equal(t, xtest.ToJSON( + map[string]*Ydb.TypedValue{ + "$x": { + Type: &Ydb.Type{ + Type: &Ydb.Type_TupleType{ + TupleType: &Ydb.TupleType{ + Elements: []*Ydb.Type{ + tc.expected.Type, }, }, }, }, - }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Low_128{ - Low_128: 651345242494996240, - }, - High_128: 72623859790382856, + Value: &Ydb.Value{ + Items: []*Ydb.Value{ + tc.expected.Value, }, }, }, - }, - }, - }, - { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").BeginTuple().AddItems(value.Uint64Value(123), value.Uint64Value(321)).EndTuple(), - params: map[string]*Ydb.TypedValue{ - "$x": { - Type: &Ydb.Type{ - Type: &Ydb.Type_TupleType{ - TupleType: &Ydb.TupleType{ - Elements: []*Ydb.Type{ - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_UINT64, - }, + }), xtest.ToJSON(params)) + }) + } +} + +func TestTuple_AddItems(t *testing.T) { + a := allocator.New() + defer a.Free() + params := Builder{}.Param("$x").BeginTuple(). + AddItems(value.Uint64Value(123), value.Uint64Value(321)). + EndTuple().Build().ToYDB(a) + require.Equal(t, xtest.ToJSON( + map[string]*Ydb.TypedValue{ + "$x": { + Type: &Ydb.Type{ + Type: &Ydb.Type_TupleType{ + TupleType: &Ydb.TupleType{ + Elements: []*Ydb.Type{ + { + Type: &Ydb.Type_TypeId{ + TypeId: Ydb.Type_UINT64, }, - { - Type: &Ydb.Type_TypeId{ - TypeId: Ydb.Type_UINT64, - }, + }, + { + Type: &Ydb.Type_TypeId{ + TypeId: Ydb.Type_UINT64, }, }, }, }, }, - Value: &Ydb.Value{ - Items: []*Ydb.Value{ - { - Value: &Ydb.Value_Uint64Value{ - Uint64Value: 123, - }, + }, + Value: &Ydb.Value{ + Items: []*Ydb.Value{ + { + Value: &Ydb.Value_Uint64Value{ + Uint64Value: 123, }, - { - Value: &Ydb.Value_Uint64Value{ - Uint64Value: 321, - }, + }, + { + Value: &Ydb.Value_Uint64Value{ + Uint64Value: 321, }, }, }, }, }, - }, - } { - t.Run(tt.name, func(t *testing.T) { - a := allocator.New() - defer a.Free() - params := tt.builder.Build().ToYDB(a) - require.Equal(t, xtest.ToJSON(tt.params), xtest.ToJSON(params)) - }) - } + }), xtest.ToJSON(params)) } diff --git a/internal/params/variant.go b/internal/params/variant.go new file mode 100644 index 000000000..8a5f1b444 --- /dev/null +++ b/internal/params/variant.go @@ -0,0 +1,31 @@ +package params + +import "github.com/ydb-platform/ydb-go-sdk/v3/internal/value" + +type ( + variant struct { + parent Builder + name string + value value.Value + } + + variantBuilder struct { + variant *variant + } +) + +func (vb *variantBuilder) EndVariant() Builder { + vb.variant.parent.params = append(vb.variant.parent.params, &Parameter{ + parent: vb.variant.parent, + name: vb.variant.name, + value: vb.variant.value, + }) + + return vb.variant.parent +} + +func (v *variant) Tuple() *variantTuple { + return &variantTuple{ + parent: v, + } +} diff --git a/internal/params/variant_tuple.go b/internal/params/variant_tuple.go new file mode 100644 index 000000000..9fea4fdaa --- /dev/null +++ b/internal/params/variant_tuple.go @@ -0,0 +1,412 @@ +package params + +import ( + "time" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/types" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/value" +) + +type ( + variantTuple struct { + parent *variant + + types []types.Type + index uint32 + value value.Value + } + + variantTupleTypes struct { + tuple *variantTuple + } + + variantTupleItem struct { + tuple *variantTuple + } + + variantTupleBuilder struct { + tuple *variantTuple + } +) + +func (vt *variantTuple) Types() *variantTupleTypes { + return &variantTupleTypes{ + tuple: vt, + } +} + +func (vtt *variantTupleTypes) AddTypes(args ...types.Type) *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, args...) + + return vtt +} + +func (vtt *variantTupleTypes) Text() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Text) + + return vtt +} + +func (vtt *variantTupleTypes) Bytes() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Bytes) + + return vtt +} + +func (vtt *variantTupleTypes) Bool() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Bool) + + return vtt +} + +func (vtt *variantTupleTypes) Uint64() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Uint64) + + return vtt +} + +func (vtt *variantTupleTypes) Int64() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Int64) + + return vtt +} + +func (vtt *variantTupleTypes) Uint32() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Uint32) + + return vtt +} + +func (vtt *variantTupleTypes) Int32() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Int32) + + return vtt +} + +func (vtt *variantTupleTypes) Uint16() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Uint16) + + return vtt +} + +func (vtt *variantTupleTypes) Int16() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Int16) + + return vtt +} + +func (vtt *variantTupleTypes) Uint8() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Uint8) + + return vtt +} + +func (vtt *variantTupleTypes) Int8() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Int8) + + return vtt +} + +func (vtt *variantTupleTypes) Float() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Float) + + return vtt +} + +func (vtt *variantTupleTypes) Double() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Double) + + return vtt +} + +func (vtt *variantTupleTypes) Decimal(precision, scale uint32) *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.NewDecimal(precision, scale)) + + return vtt +} + +func (vtt *variantTupleTypes) Timestamp() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Timestamp) + + return vtt +} + +func (vtt *variantTupleTypes) Date() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Date) + + return vtt +} + +func (vtt *variantTupleTypes) Datetime() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Datetime) + + return vtt +} + +func (vtt *variantTupleTypes) Interval() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.Interval) + + return vtt +} + +func (vtt *variantTupleTypes) JSON() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.JSON) + + return vtt +} + +func (vtt *variantTupleTypes) JSONDocument() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.JSONDocument) + + return vtt +} + +func (vtt *variantTupleTypes) YSON() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.YSON) + + return vtt +} + +func (vtt *variantTupleTypes) UUID() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.UUID) + + return vtt +} + +func (vtt *variantTupleTypes) TzDate() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.TzDate) + + return vtt +} + +func (vtt *variantTupleTypes) TzTimestamp() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.TzTimestamp) + + return vtt +} + +func (vtt *variantTupleTypes) TzDatetime() *variantTupleTypes { + vtt.tuple.types = append(vtt.tuple.types, types.TzDatetime) + + return vtt +} + +func (vtt *variantTupleTypes) Index(i uint32) *variantTupleItem { + vtt.tuple.index = i + + return &variantTupleItem{ + tuple: vtt.tuple, + } +} + +func (vti *variantTupleItem) Text(v string) *variantTupleBuilder { + vti.tuple.value = value.TextValue(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Bytes(v []byte) *variantTupleBuilder { + vti.tuple.value = value.BytesValue(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Bool(v bool) *variantTupleBuilder { + vti.tuple.value = value.BoolValue(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Uint64(v uint64) *variantTupleBuilder { + vti.tuple.value = value.Uint64Value(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Int64(v int64) *variantTupleBuilder { + vti.tuple.value = value.Int64Value(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Uint32(v uint32) *variantTupleBuilder { + vti.tuple.value = value.Uint32Value(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Int32(v int32) *variantTupleBuilder { + vti.tuple.value = value.Int32Value(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Uint16(v uint16) *variantTupleBuilder { + vti.tuple.value = value.Uint16Value(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Int16(v int16) *variantTupleBuilder { + vti.tuple.value = value.Int16Value(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Uint8(v uint8) *variantTupleBuilder { + vti.tuple.value = value.Uint8Value(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Int8(v int8) *variantTupleBuilder { + vti.tuple.value = value.Int8Value(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Float(v float32) *variantTupleBuilder { + vti.tuple.value = value.FloatValue(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Double(v float64) *variantTupleBuilder { + vti.tuple.value = value.DoubleValue(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Decimal(v [16]byte, precision, scale uint32) *variantTupleBuilder { + vti.tuple.value = value.DecimalValue(v, precision, scale) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Timestamp(v time.Time) *variantTupleBuilder { + vti.tuple.value = value.TimestampValueFromTime(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Date(v time.Time) *variantTupleBuilder { + vti.tuple.value = value.DateValueFromTime(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Datetime(v time.Time) *variantTupleBuilder { + vti.tuple.value = value.DatetimeValueFromTime(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) Interval(v time.Duration) *variantTupleBuilder { + vti.tuple.value = value.IntervalValueFromDuration(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) JSON(v string) *variantTupleBuilder { + vti.tuple.value = value.JSONValue(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) JSONDocument(v string) *variantTupleBuilder { + vti.tuple.value = value.JSONDocumentValue(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) YSON(v []byte) *variantTupleBuilder { + vti.tuple.value = value.YSONValue(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) UUID(v [16]byte) *variantTupleBuilder { + vti.tuple.value = value.UUIDValue(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) TzDate(v time.Time) *variantTupleBuilder { + vti.tuple.value = value.TzDateValueFromTime(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) TzTimestamp(v time.Time) *variantTupleBuilder { + vti.tuple.value = value.TzTimestampValueFromTime(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vti *variantTupleItem) TzDatetime(v time.Time) *variantTupleBuilder { + vti.tuple.value = value.TzDatetimeValueFromTime(v) + + return &variantTupleBuilder{ + tuple: vti.tuple, + } +} + +func (vtb *variantTupleBuilder) EndTuple() *variantBuilder { + vtb.tuple.parent.value = value.VariantValueTuple( + vtb.tuple.value, + vtb.tuple.index, + types.NewVariantTuple(vtb.tuple.types...), + ) + + return &variantBuilder{ + variant: vtb.tuple.parent, + } +} diff --git a/internal/params/variant_tuple_test.go b/internal/params/variant_tuple_test.go new file mode 100644 index 000000000..1ae4356d1 --- /dev/null +++ b/internal/params/variant_tuple_test.go @@ -0,0 +1,528 @@ +package params + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/types" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" +) + +func TestVariantTuple(t *testing.T) { + type expected struct { + Type *Ydb.Type + Value *Ydb.Value + } + + tests := []struct { + method string + + typeArgs []any + itemArgs []any + + expected expected + }{ + { + method: "Uint64", + itemArgs: []any{uint64(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT64}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint64Value{ + Uint64Value: 123, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Int64", + itemArgs: []any{int64(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT64}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Int64Value{ + Int64Value: 123, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Uint32", + itemArgs: []any{uint32(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT32}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Int32", + itemArgs: []any{int32(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT32}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Int32Value{ + Int32Value: 123, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Uint16", + itemArgs: []any{uint16(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT16}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Int16", + itemArgs: []any{int16(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT16}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Int32Value{ + Int32Value: 123, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Uint8", + itemArgs: []any{uint8(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT8}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Int8", + itemArgs: []any{int8(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT8}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Int32Value{ + Int32Value: 123, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Bool", + itemArgs: []any{true}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_BOOL}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_BoolValue{ + BoolValue: true, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Text", + itemArgs: []any{"test"}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UTF8}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: "test", + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Bytes", + itemArgs: []any{[]byte("test")}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_STRING}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_BytesValue{ + BytesValue: []byte("test"), + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Float", + itemArgs: []any{float32(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_FLOAT}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_FloatValue{ + FloatValue: float32(123), + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Double", + itemArgs: []any{float64(123)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DOUBLE}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_DoubleValue{ + DoubleValue: float64(123), + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Interval", + itemArgs: []any{time.Second}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INTERVAL}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Int64Value{ + Int64Value: 1000000, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Datetime", + itemArgs: []any{time.Unix(123456789, 456)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATETIME}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123456789, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Date", + itemArgs: []any{time.Unix(123456789, 456)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATE}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 1428, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Timestamp", + itemArgs: []any{time.Unix(123456789, 456)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TIMESTAMP}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Uint64Value{ + Uint64Value: 123456789000000, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "Decimal", + typeArgs: []any{uint32(22), uint32(9)}, + itemArgs: []any{[...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}, uint32(22), uint32(9)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_DecimalType{ + DecimalType: &Ydb.DecimalType{ + Precision: 22, + Scale: 9, + }, + }, + }, + Value: &Ydb.Value{ + High_128: 72623859790382856, + Value: &Ydb.Value_Low_128{ + Low_128: 648519454493508870, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "JSON", + itemArgs: []any{`{"a": 1,"b": "B"}`}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_JSON}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: `{"a": 1,"b": "B"}`, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "JSONDocument", + itemArgs: []any{`{"a": 1,"b": "B"}`}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_JSON_DOCUMENT}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: `{"a": 1,"b": "B"}`, + }, + VariantIndex: 0, + }, + }, + }, + { + method: "YSON", + itemArgs: []any{[]byte(`{"a": 1,"b": "B"}`)}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_YSON}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_BytesValue{ + BytesValue: []byte(`{"a": 1,"b": "B"}`), + }, + VariantIndex: 0, + }, + }, + }, + { + method: "UUID", + itemArgs: []any{[...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UUID}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_Low_128{ + Low_128: 651345242494996240, + }, + High_128: 72623859790382856, + VariantIndex: 0, + }, + }, + }, + { + method: "TzDatetime", + itemArgs: []any{time.Unix(123456789, 456).UTC()}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TZ_DATETIME}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: "1973-11-29T21:33:09Z", + }, + VariantIndex: 0, + }, + }, + }, + { + method: "TzDate", + itemArgs: []any{time.Unix(123456789, 456).UTC()}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TZ_DATE}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: "1973-11-29", + }, + VariantIndex: 0, + }, + }, + }, + { + method: "TzTimestamp", + itemArgs: []any{time.Unix(123456789, 456).UTC()}, + + expected: expected{ + Type: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TZ_TIMESTAMP}, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: "1973-11-29T21:33:09.000000Z", + }, + VariantIndex: 0, + }, + }, + }, + } + + for _, tc := range tests { + t.Run(tc.method, func(t *testing.T) { + a := allocator.New() + defer a.Free() + + item := Builder{}.Param("$x").BeginVariant().Tuple().Types() + + types, ok := xtest.CallMethod(item, tc.method, tc.typeArgs...)[0].(*variantTupleTypes) + require.True(t, ok) + + builder, ok := xtest.CallMethod(types.Index(0), tc.method, tc.itemArgs...)[0].(*variantTupleBuilder) + require.True(t, ok) + + params := builder.EndTuple().EndVariant().Build().ToYDB(a) + + require.Equal(t, xtest.ToJSON( + map[string]*Ydb.TypedValue{ + "$x": { + Type: &Ydb.Type{ + Type: &Ydb.Type_VariantType{ + VariantType: &Ydb.VariantType{ + Type: &Ydb.VariantType_TupleItems{ + TupleItems: &Ydb.TupleType{ + Elements: []*Ydb.Type{ + tc.expected.Type, + }, + }, + }, + }, + }, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_NestedValue{ + NestedValue: tc.expected.Value, + }, + }, + }, + }), xtest.ToJSON(params)) + }) + } +} + +func TestVariantTuple_AddTypes(t *testing.T) { + a := allocator.New() + defer a.Free() + + params := Builder{}.Param("$x").BeginVariant().Tuple(). + Types().AddTypes(types.Int64, types.Bool). + Index(1). + Bool(true). + EndTuple().EndVariant().Build().ToYDB(a) + + require.Equal(t, xtest.ToJSON( + map[string]*Ydb.TypedValue{ + "$x": { + Type: &Ydb.Type{ + Type: &Ydb.Type_VariantType{ + VariantType: &Ydb.VariantType{ + Type: &Ydb.VariantType_TupleItems{ + TupleItems: &Ydb.TupleType{ + Elements: []*Ydb.Type{ + { + Type: &Ydb.Type_TypeId{ + TypeId: Ydb.Type_INT64, + }, + }, + { + Type: &Ydb.Type_TypeId{ + TypeId: Ydb.Type_BOOL, + }, + }, + }, + }, + }, + }, + }, + }, + Value: &Ydb.Value{ + Value: &Ydb.Value_NestedValue{ + NestedValue: &Ydb.Value{ + Value: &Ydb.Value_BoolValue{ + BoolValue: true, + }, + }, + }, + VariantIndex: 1, + }, + }, + }), xtest.ToJSON(params)) +}