Skip to content

Commit 84dac72

Browse files
authored
Merge pull request #1697 from ydb-platform/bind-params-from-map
* Added bindings elipsis into `ydb.ParamsFromMap` for bind wide time types
2 parents 9a07784 + bec6603 commit 84dac72

File tree

12 files changed

+154
-21
lines changed

12 files changed

+154
-21
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
* Added bindings options into `ydb.ParamsFromMap` for bind wide time types
2+
* Changed `ydb.WithWideTimeTypes(bool)` for allow boolean argument
3+
14
## v3.104.1
25
* Added export of advanced metric information for QueryService calls
36

dsn.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func parseConnectionString(dataSourceName string) (opts []Option, _ error) {
115115
case "numeric":
116116
binders = append(binders, xsql.WithQueryBind(bind.NumericArgs{}))
117117
case "wide_time_types":
118-
binders = append(binders, xsql.WithQueryBind(bind.WideTimeTypes{}))
118+
binders = append(binders, xsql.WithQueryBind(bind.WideTimeTypes(true)))
119119
default:
120120
if strings.HasPrefix(transformer, tablePathPrefixTransformer) {
121121
prefix, err := extractTablePathPrefixFromBinderName(transformer)

dsn_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ func TestParse(t *testing.T) {
182182
xsql.WithDefaultQueryMode(xtable.ScriptingQueryMode),
183183
xsql.WithQueryBind(bind.PositionalArgs{}),
184184
xsql.WithQueryBind(bind.AutoDeclare{}),
185-
xsql.WithQueryBind(bind.WideTimeTypes{}),
185+
xsql.WithQueryBind(bind.WideTimeTypes(true)),
186186
},
187187
err: nil,
188188
},

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: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,39 @@
11
package bind
22

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

67
"github.com/ydb-platform/ydb-go-sdk/v3/internal/value"
78
)
89

9-
type WideTimeTypes struct{}
10+
type WideTimeTypes bool
11+
12+
func (b WideTimeTypes) ToYdb(sql string, args ...any) (yql string, newArgs []any, _ error) {
13+
if !b {
14+
return sql, args, nil
15+
}
1016

11-
func (m WideTimeTypes) ToYdb(sql string, args ...any) (yql string, newArgs []any, _ error) {
1217
newArgs = make([]any, 0, len(args))
1318
for _, arg := range args {
1419
switch t := arg.(type) {
20+
case driver.NamedValue:
21+
switch tt := t.Value.(type) {
22+
case time.Time:
23+
newArgs = append(newArgs, driver.NamedValue{
24+
Name: t.Name,
25+
Ordinal: t.Ordinal,
26+
Value: value.Timestamp64ValueFromTime(tt),
27+
})
28+
case time.Duration:
29+
newArgs = append(newArgs, driver.NamedValue{
30+
Name: t.Name,
31+
Ordinal: t.Ordinal,
32+
Value: value.Interval64ValueFromDuration(tt),
33+
})
34+
default:
35+
newArgs = append(newArgs, arg)
36+
}
1537
case time.Time:
1638
newArgs = append(newArgs, value.Timestamp64ValueFromTime(t))
1739
case time.Duration:
@@ -24,6 +46,6 @@ func (m WideTimeTypes) ToYdb(sql string, args ...any) (yql string, newArgs []any
2446
return sql, newArgs, nil
2547
}
2648

27-
func (m WideTimeTypes) blockID() blockID {
49+
func (b WideTimeTypes) blockID() blockID {
2850
return blockCastArgs
2951
}

internal/bind/wide_time_types_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func TestWideTimeTypesBind(t *testing.T) {
5858
},
5959
},
6060
{
61-
bind: WideTimeTypes{},
61+
bind: WideTimeTypes(true),
6262
sql: `SELECT ?, ?`,
6363
args: []any{
6464
100,
@@ -71,7 +71,7 @@ func TestWideTimeTypesBind(t *testing.T) {
7171
},
7272
},
7373
{
74-
bind: WideTimeTypes{},
74+
bind: WideTimeTypes(true),
7575
sql: `SELECT ?, ?`,
7676
args: []any{
7777
time.Unix(123, 456),
@@ -84,7 +84,7 @@ func TestWideTimeTypesBind(t *testing.T) {
8484
},
8585
},
8686
{
87-
bind: WideTimeTypes{},
87+
bind: WideTimeTypes(true),
8888
sql: `SELECT ?, ?`,
8989
args: []any{
9090
time.Duration(123) * time.Millisecond,

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: 88 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,89 @@ 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,
233+
fmt.Sprintf("%+v", map[string]*Ydb.TypedValue{
234+
"$a": {
235+
Type: &Ydb.Type{
236+
Type: &Ydb.Type_TypeId{
237+
TypeId: Ydb.Type_TIMESTAMP,
238+
},
239+
},
240+
Value: &Ydb.Value{
241+
Value: &Ydb.Value_Uint64Value{
242+
Uint64Value: 123000000,
243+
},
244+
},
245+
},
246+
"$b": {
247+
Type: &Ydb.Type{
248+
Type: &Ydb.Type_TypeId{
249+
TypeId: Ydb.Type_INTERVAL,
250+
},
251+
},
252+
Value: &Ydb.Value{
253+
Value: &Ydb.Value_Int64Value{
254+
Int64Value: 123,
255+
},
256+
},
257+
},
258+
}),
259+
fmt.Sprintf("%+v", pp),
260+
)
261+
})
262+
t.Run("BindWideTimeTypes", func(t *testing.T) {
263+
params := ydb.ParamsFromMap(map[string]any{
264+
"a": time.Date(1900, 1, 1, 0, 0, 0, 123456, time.UTC),
265+
"b": time.Duration(123) * time.Nanosecond,
266+
}, ydb.WithWideTimeTypes(true))
267+
pp, err := params.ToYDB(&allocator.Allocator{})
268+
require.NoError(t, err)
269+
require.EqualValues(t,
270+
fmt.Sprintf("%+v", map[string]*Ydb.TypedValue{
271+
"$a": {
272+
Type: &Ydb.Type{
273+
Type: &Ydb.Type_TypeId{
274+
TypeId: Ydb.Type_TIMESTAMP64,
275+
},
276+
},
277+
Value: &Ydb.Value{
278+
Value: &Ydb.Value_Int64Value{
279+
Int64Value: -2208988799999877,
280+
},
281+
},
282+
},
283+
"$b": {
284+
Type: &Ydb.Type{
285+
Type: &Ydb.Type_TypeId{
286+
TypeId: Ydb.Type_INTERVAL64,
287+
},
288+
},
289+
Value: &Ydb.Value{
290+
Value: &Ydb.Value_Int64Value{
291+
Int64Value: 123,
292+
},
293+
},
294+
},
295+
}),
296+
fmt.Sprintf("%+v", pp),
297+
)
298+
})
299+
t.Run("WrongBindings", func(t *testing.T) {
300+
params := ydb.ParamsFromMap(map[string]any{
301+
"a": time.Unix(123, 456),
302+
"b": time.Duration(123),
303+
}, ydb.WithTablePathPrefix(""))
304+
pp, err := params.ToYDB(&allocator.Allocator{})
305+
require.ErrorIs(t, err, bind.ErrUnsupportedBindingType)
306+
require.Nil(t, pp)
307+
})
308+
}

query_bind_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ SELECT $p0;`,
583583
b: testutil.QueryBind(
584584
ydb.WithAutoDeclare(),
585585
ydb.WithPositionalArgs(),
586-
ydb.WithWideTimeTypes(),
586+
ydb.WithWideTimeTypes(true),
587587
),
588588
sql: `SELECT ?;`,
589589
args: []interface{}{time.Unix(123, 456)},

sql.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,8 @@ func WithPositionalArgs() QueryBindConnectorOption {
189189
return xsql.WithQueryBind(bind.PositionalArgs{})
190190
}
191191

192-
func WithWideTimeTypes() QueryBindConnectorOption {
193-
return xsql.WithQueryBind(bind.WideTimeTypes{})
192+
func WithWideTimeTypes(b bool) QueryBindConnectorOption {
193+
return xsql.WithQueryBind(bind.WideTimeTypes(b))
194194
}
195195

196196
func WithNumericArgs() QueryBindConnectorOption {

0 commit comments

Comments
 (0)