Skip to content

Commit f3da289

Browse files
committed
* Added bindings elipsis into ydb.ParamsFromMap for bind wide time types
1 parent 9a07784 commit f3da289

File tree

7 files changed

+132
-10
lines changed

7 files changed

+132
-10
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
* Added bindings elipsis into `ydb.ParamsFromMap` for bind wide time types
2+
13
## v3.104.1
24
* Added export of advanced metric information for QueryService calls
35

internal/bind/bind.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ func (bindings Bindings) ToYdb(sql string, args ...any) (
4444
defer buffer.Free()
4545

4646
for i := range bindings {
47-
var e error
48-
sql, args, e = bindings[len(bindings)-1-i].ToYdb(sql, args...)
49-
if e != nil {
50-
return "", nil, xerrors.WithStackTrace(e)
47+
var err error
48+
sql, args, err = bindings[len(bindings)-1-i].ToYdb(sql, args...)
49+
if err != nil {
50+
return "", nil, xerrors.WithStackTrace(err)
5151
}
5252
}
5353

internal/bind/errors.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ import "errors"
55
var (
66
ErrInconsistentArgs = errors.New("inconsistent args")
77
ErrUnexpectedNumericArgZero = errors.New("unexpected numeric arg $0. Allowed only $1 and greater")
8+
ErrUnsupportedBindingType = errors.New("unsupported binding type")
89
)

internal/bind/wide_time_types.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package bind
22

33
import (
4+
"database/sql/driver"
45
"time"
56

67
"github.com/ydb-platform/ydb-go-sdk/v3/internal/value"
@@ -12,6 +13,23 @@ func (m WideTimeTypes) ToYdb(sql string, args ...any) (yql string, newArgs []any
1213
newArgs = make([]any, 0, len(args))
1314
for _, arg := range args {
1415
switch t := arg.(type) {
16+
case driver.NamedValue:
17+
switch tt := t.Value.(type) {
18+
case time.Time:
19+
newArgs = append(newArgs, driver.NamedValue{
20+
Name: t.Name,
21+
Ordinal: t.Ordinal,
22+
Value: value.Timestamp64ValueFromTime(tt),
23+
})
24+
case time.Duration:
25+
newArgs = append(newArgs, driver.NamedValue{
26+
Name: t.Name,
27+
Ordinal: t.Ordinal,
28+
Value: value.Interval64ValueFromDuration(tt),
29+
})
30+
default:
31+
newArgs = append(newArgs, arg)
32+
}
1533
case time.Time:
1634
newArgs = append(newArgs, value.Timestamp64ValueFromTime(t))
1735
case time.Duration:

internal/xsql/options.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type (
3838
retryBudgetOption struct {
3939
budget budget.Budget
4040
}
41-
bindOption struct {
41+
BindOption struct {
4242
bind.Bind
4343
}
4444
queryProcessorOption Engine
@@ -57,7 +57,7 @@ func (processor queryProcessorOption) Apply(c *Connector) error {
5757
return nil
5858
}
5959

60-
func (opt bindOption) Apply(c *Connector) error {
60+
func (opt BindOption) Apply(c *Connector) error {
6161
c.bindings = bind.Sort(append(c.bindings, opt.Bind))
6262

6363
return nil
@@ -141,7 +141,7 @@ func WithTablePathPrefix(tablePathPrefix string) QueryBindOption {
141141
}
142142

143143
func WithQueryBind(bind bind.Bind) QueryBindOption {
144-
return bindOption{
144+
return BindOption{
145145
Bind: bind,
146146
}
147147
}

params_map.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package ydb
22

33
import (
44
"database/sql/driver"
5+
"fmt"
56

67
"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
78

89
"github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator"
910
"github.com/ydb-platform/ydb-go-sdk/v3/internal/bind"
1011
"github.com/ydb-platform/ydb-go-sdk/v3/internal/params"
1112
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
13+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql"
1214
)
1315

1416
type wrongParameters struct {
@@ -20,15 +22,32 @@ func (p wrongParameters) ToYDB(a *allocator.Allocator) (map[string]*Ydb.TypedVal
2022
}
2123

2224
// ParamsFromMap build parameters from named map
23-
func ParamsFromMap(m map[string]any) params.Parameters {
25+
func ParamsFromMap(m map[string]any, bindings ...bind.Bind) params.Parameters {
26+
for _, b := range bindings {
27+
switch bb := b.(type) {
28+
case xsql.BindOption:
29+
switch bb.Bind.(type) {
30+
case bind.WideTimeTypes:
31+
continue
32+
default:
33+
return wrongParameters{
34+
err: xerrors.WithStackTrace(fmt.Errorf("%T: %w", b, bind.ErrUnsupportedBindingType)),
35+
}
36+
}
37+
default:
38+
return wrongParameters{
39+
err: xerrors.WithStackTrace(fmt.Errorf("%T: %w", b, bind.ErrUnsupportedBindingType)),
40+
}
41+
}
42+
}
2443
namedParameters := make([]any, 0, len(m))
2544
for name, val := range m {
2645
namedParameters = append(namedParameters, driver.NamedValue{Name: name, Value: val})
2746
}
28-
p, err := bind.Params(namedParameters...)
47+
_, pp, err := bind.Bindings(bindings).ToYdb("", namedParameters...)
2948
if err != nil {
3049
return wrongParameters{err: xerrors.WithStackTrace(err)}
3150
}
3251

33-
return (*params.Params)(&p)
52+
return &pp
3453
}

params_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package ydb_test
33
import (
44
"fmt"
55
"testing"
6+
"time"
67

78
"github.com/google/uuid"
89
"github.com/stretchr/testify/require"
910
"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
1011

1112
"github.com/ydb-platform/ydb-go-sdk/v3"
1213
"github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator"
14+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/bind"
1315
"github.com/ydb-platform/ydb-go-sdk/v3/internal/params"
1416
"github.com/ydb-platform/ydb-go-sdk/v3/table"
1517
"github.com/ydb-platform/ydb-go-sdk/v3/table/types"
@@ -218,3 +220,83 @@ func BenchmarkParams(b *testing.B) {
218220
}
219221
})
220222
}
223+
224+
func TestParamsFromMap(t *testing.T) {
225+
t.Run("DefaultTimeTypes", func(t *testing.T) {
226+
params := ydb.ParamsFromMap(map[string]any{
227+
"a": time.Unix(123, 456),
228+
"b": time.Duration(123) * time.Microsecond,
229+
})
230+
pp, err := params.ToYDB(&allocator.Allocator{})
231+
require.NoError(t, err)
232+
require.EqualValues(t, map[string]*Ydb.TypedValue{
233+
"$a": {
234+
Type: &Ydb.Type{
235+
Type: &Ydb.Type_TypeId{
236+
TypeId: Ydb.Type_TIMESTAMP,
237+
},
238+
},
239+
Value: &Ydb.Value{
240+
Value: &Ydb.Value_Uint64Value{
241+
Uint64Value: 123000000,
242+
},
243+
},
244+
},
245+
"$b": {
246+
Type: &Ydb.Type{
247+
Type: &Ydb.Type_TypeId{
248+
TypeId: Ydb.Type_INTERVAL,
249+
},
250+
},
251+
Value: &Ydb.Value{
252+
Value: &Ydb.Value_Int64Value{
253+
Int64Value: 123,
254+
},
255+
},
256+
},
257+
}, pp)
258+
})
259+
t.Run("BindWideTimeTypes", func(t *testing.T) {
260+
params := ydb.ParamsFromMap(map[string]any{
261+
"a": time.Date(1900, 1, 1, 0, 0, 0, 123456, time.UTC),
262+
"b": time.Duration(123) * time.Nanosecond,
263+
}, ydb.WithWideTimeTypes())
264+
pp, err := params.ToYDB(&allocator.Allocator{})
265+
require.NoError(t, err)
266+
require.EqualValues(t, map[string]*Ydb.TypedValue{
267+
"$a": {
268+
Type: &Ydb.Type{
269+
Type: &Ydb.Type_TypeId{
270+
TypeId: Ydb.Type_TIMESTAMP64,
271+
},
272+
},
273+
Value: &Ydb.Value{
274+
Value: &Ydb.Value_Int64Value{
275+
Int64Value: -2208988799999877,
276+
},
277+
},
278+
},
279+
"$b": {
280+
Type: &Ydb.Type{
281+
Type: &Ydb.Type_TypeId{
282+
TypeId: Ydb.Type_INTERVAL64,
283+
},
284+
},
285+
Value: &Ydb.Value{
286+
Value: &Ydb.Value_Int64Value{
287+
Int64Value: 123,
288+
},
289+
},
290+
},
291+
}, pp)
292+
})
293+
t.Run("WrongBindings", func(t *testing.T) {
294+
params := ydb.ParamsFromMap(map[string]any{
295+
"a": time.Unix(123, 456),
296+
"b": time.Duration(123),
297+
}, ydb.WithTablePathPrefix(""))
298+
pp, err := params.ToYDB(&allocator.Allocator{})
299+
require.ErrorIs(t, err, bind.ErrUnsupportedBindingType)
300+
require.Nil(t, pp)
301+
})
302+
}

0 commit comments

Comments
 (0)