diff --git a/CHANGELOG.md b/CHANGELOG.md index 5709af527..a6e449b40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +* Removed experimental helper `ydb.MustParamsFromMap` +* Changed result of experimental helper `ydb.ParamsFromMap` from tuple <`params.Parameters`, `error`> to `params.Parameters` only + ## v3.93.1 * Published `query.ExecuteOption` as alias to `internal/query/options.Execute` diff --git a/example_test.go b/example_test.go index b597fe665..2bebec81b 100644 --- a/example_test.go +++ b/example_test.go @@ -511,8 +511,7 @@ func ExampleOpen_advanced() { fmt.Printf("connected to %s, database '%s'", db.Endpoint(), db.Name()) } -// func ExampleParamsMap -func ExampleMustParamsFromMap() { +func ExampleParamsFromMap() { ctx := context.TODO() db, err := ydb.Open( ctx, @@ -532,14 +531,16 @@ func ExampleMustParamsFromMap() { fmt.Printf("connected to %s, database '%s'", db.Endpoint(), db.Name()) res, err := db.Query().QueryRow(ctx, ` -DECLARE $textArg AS Text; -DECLARE $intArg AS Int64; - -SELECT $textArg AS TextField, $intArg AS IntField -`, query.WithParameters(ydb.MustParamsFromMap(map[string]any{ - "$textArg": "asd", - "$intArg": int64(123), - }))) + DECLARE $textArg AS Text; + DECLARE $intArg AS Int64; + + SELECT $textArg AS TextField, $intArg AS IntField + `, + query.WithParameters(ydb.ParamsFromMap(map[string]any{ + "$textArg": "asd", + "$intArg": int64(123), + })), + ) if err != nil { fmt.Printf("query failed") } diff --git a/internal/bind/params.go b/internal/bind/params.go index cf75f89d0..0e394b126 100644 --- a/internal/bind/params.go +++ b/internal/bind/params.go @@ -204,7 +204,7 @@ func Params(args ...interface{}) ([]*params.Parameter, error) { } newParam, err = toYdbParam(x.Name, x.Value) newParams = append(newParams, newParam) - case *params.Parameters: + case *params.Params: if len(args) > 1 { return nil, xerrors.WithStackTrace(errMultipleQueryParameters) } @@ -230,7 +230,7 @@ func Params(args ...interface{}) ([]*params.Parameter, error) { func paramHandleNamedValue(arg driver.NamedValue, paramNumber, argsLen int) ([]*params.Parameter, error) { if arg.Name == "" { switch x := arg.Value.(type) { - case *params.Parameters: + case *params.Params: if argsLen > 1 { return nil, xerrors.WithStackTrace(errMultipleQueryParameters) } diff --git a/internal/params/builder.go b/internal/params/builder.go index ce8421fb0..e98ddfe02 100644 --- a/internal/params/builder.go +++ b/internal/params/builder.go @@ -2,11 +2,11 @@ package params type ( Builder struct { - params Parameters + params Params } ) -func (b Builder) Build() *Parameters { +func (b Builder) Build() *Params { return &b.params } diff --git a/internal/params/builder_test.go b/internal/params/builder_test.go index 1ffe69636..d9f630cd0 100644 --- a/internal/params/builder_test.go +++ b/internal/params/builder_test.go @@ -417,7 +417,7 @@ func TestBuilder(t *testing.T) { result, ok := xtest.CallMethod(item, tc.method, tc.args...)[0].(Builder) require.True(t, ok) - params := result.Build().ToYDB(a) + params := result.Build().toYDB(a) require.Equal(t, xtest.ToJSON( diff --git a/internal/params/dict_test.go b/internal/params/dict_test.go index 387793b84..abf117445 100644 --- a/internal/params/dict_test.go +++ b/internal/params/dict_test.go @@ -440,7 +440,7 @@ func TestDict(t *testing.T) { d, ok := xtest.CallMethod(addedKey, val.method, val.args...)[0].(*dict) require.True(t, ok) - params := d.EndDict().Build().ToYDB(a) + params := d.EndDict().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ "$x": { @@ -482,7 +482,7 @@ func TestDict_AddPairs(t *testing.T) { }, } - params := Builder{}.Param("$x").BeginDict().AddPairs(pairs...).EndDict().Build().ToYDB(a) + params := Builder{}.Param("$x").BeginDict().AddPairs(pairs...).EndDict().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ diff --git a/internal/params/list_test.go b/internal/params/list_test.go index be9f5b293..ba5621dd1 100644 --- a/internal/params/list_test.go +++ b/internal/params/list_test.go @@ -435,7 +435,7 @@ func TestList(t *testing.T) { result, ok := xtest.CallMethod(item, tc.method, tc.args...)[0].(*list) require.True(t, ok) - params := result.EndList().Build().ToYDB(a) + params := result.EndList().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ "$x": { @@ -462,7 +462,7 @@ func TestList_AddItems(t *testing.T) { defer a.Free() params := Builder{}.Param("$x").BeginList(). AddItems(value.Uint64Value(123), value.Uint64Value(321)). - EndList().Build().ToYDB(a) + EndList().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ "$x": { diff --git a/internal/params/optional_test.go b/internal/params/optional_test.go index 61f3bbf18..25754bd6a 100644 --- a/internal/params/optional_test.go +++ b/internal/params/optional_test.go @@ -435,7 +435,7 @@ func TestOptional(t *testing.T) { result, ok := xtest.CallMethod(item, tc.method, tc.args...)[0].(*optionalBuilder) require.True(t, ok) - params := result.EndOptional().Build().ToYDB(a) + params := result.EndOptional().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ "$x": { diff --git a/internal/params/parameters.go b/internal/params/parameters.go index c0cdbfa62..75516c3d3 100644 --- a/internal/params/parameters.go +++ b/internal/params/parameters.go @@ -23,9 +23,14 @@ type ( name string value value.Value } - Parameters []*Parameter + Parameters interface { + ToYDB(a *allocator.Allocator) (map[string]*Ydb.TypedValue, error) + } + Params []*Parameter ) +var _ Parameters = (*Params)(nil) + func Named(name string, value value.Value) *Parameter { return &Parameter{ name: name, @@ -41,7 +46,7 @@ func (p *Parameter) Value() value.Value { return p.value } -func (p *Parameters) String() string { +func (p *Params) String() string { buffer := xstring.Buffer() defer buffer.Free() @@ -62,7 +67,20 @@ func (p *Parameters) String() string { return buffer.String() } -func (p *Parameters) ToYDB(a *allocator.Allocator) map[string]*Ydb.TypedValue { +func (p *Params) ToYDB(a *allocator.Allocator) (map[string]*Ydb.TypedValue, error) { + if p == nil { + return nil, nil //nolint:nilnil + } + + parameters := make(map[string]*Ydb.TypedValue, len(*p)) + for _, param := range *p { + parameters[param.name] = value.ToYDB(param.value, a) + } + + return parameters, nil +} + +func (p *Params) toYDB(a *allocator.Allocator) map[string]*Ydb.TypedValue { if p == nil { return nil } @@ -74,7 +92,7 @@ func (p *Parameters) ToYDB(a *allocator.Allocator) map[string]*Ydb.TypedValue { return parameters } -func (p *Parameters) Each(it func(name string, v value.Value)) { +func (p *Params) Each(it func(name string, v value.Value)) { if p == nil { return } @@ -83,7 +101,7 @@ func (p *Parameters) Each(it func(name string, v value.Value)) { } } -func (p *Parameters) Count() int { +func (p *Params) Count() int { if p == nil { return 0 } @@ -91,7 +109,7 @@ func (p *Parameters) Count() int { return len(*p) } -func (p *Parameters) Add(params ...NamedValue) { +func (p *Params) Add(params ...NamedValue) { for _, param := range params { *p = append(*p, Named(param.Name(), param.Value())) } diff --git a/internal/params/parameters_test.go b/internal/params/parameters_test.go index 1c49c3f45..9d163a695 100644 --- a/internal/params/parameters_test.go +++ b/internal/params/parameters_test.go @@ -18,7 +18,7 @@ func TestParameter(t *testing.T) { } func TestParameters(t *testing.T) { - p := &Parameters{} + p := &Params{} p.Add( Named("x", value.TextValue("X")), Named("y", value.TextValue("Y")), @@ -39,7 +39,7 @@ func TestParameters(t *testing.T) { func TestNil(t *testing.T) { for _, tt := range []struct { name string - p *Parameters + p *Params }{ { name: xtest.CurrentFileLine(), @@ -47,7 +47,7 @@ func TestNil(t *testing.T) { }, { name: xtest.CurrentFileLine(), - p: &Parameters{}, + p: &Params{}, }, { name: xtest.CurrentFileLine(), @@ -64,7 +64,7 @@ func TestNil(t *testing.T) { require.Empty(t, visited) a := allocator.New() defer a.Free() - require.Empty(t, tt.p.ToYDB(a)) + require.Empty(t, tt.p.toYDB(a)) }) } } diff --git a/internal/params/pg_test.go b/internal/params/pg_test.go index ce470864c..1eb2af755 100644 --- a/internal/params/pg_test.go +++ b/internal/params/pg_test.go @@ -86,7 +86,7 @@ func TestPg(t *testing.T) { result, ok := xtest.CallMethod(item, tc.method, tc.args...)[0].(Builder) require.True(t, ok) - params := result.Build().ToYDB(a) + params := result.Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ diff --git a/internal/params/set_test.go b/internal/params/set_test.go index e31cc4476..fb54c5339 100644 --- a/internal/params/set_test.go +++ b/internal/params/set_test.go @@ -435,7 +435,7 @@ func TestSet(t *testing.T) { result, ok := xtest.CallMethod(item, tc.method, tc.args...)[0].(*set) require.True(t, ok) - params := result.EndSet().Build().ToYDB(a) + params := result.EndSet().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ "$x": { @@ -470,7 +470,7 @@ func TestSet_AddItems(t *testing.T) { defer a.Free() params := Builder{}.Param("$x").BeginSet(). AddItems(value.Uint64Value(123), value.Uint64Value(321)). - EndSet().Build().ToYDB(a) + EndSet().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ "$x": { diff --git a/internal/params/struct_test.go b/internal/params/struct_test.go index 8fed54aeb..2872786db 100644 --- a/internal/params/struct_test.go +++ b/internal/params/struct_test.go @@ -951,7 +951,7 @@ func TestStruct(t *testing.T) { t.Run(tt.name, func(t *testing.T) { a := allocator.New() defer a.Free() - params := tt.builder.Build().ToYDB(a) + params := tt.builder.Build().toYDB(a) require.Equal(t, xtest.ToJSON(tt.params), xtest.ToJSON(params)) }) } diff --git a/internal/params/tuple_test.go b/internal/params/tuple_test.go index af272aba7..008158930 100644 --- a/internal/params/tuple_test.go +++ b/internal/params/tuple_test.go @@ -435,7 +435,7 @@ func TestTuple(t *testing.T) { result, ok := xtest.CallMethod(item, tc.method, tc.args...)[0].(*tuple) require.True(t, ok) - params := result.EndTuple().Build().ToYDB(a) + params := result.EndTuple().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ "$x": { @@ -464,7 +464,7 @@ func TestTuple_AddItems(t *testing.T) { defer a.Free() params := Builder{}.Param("$x").BeginTuple(). AddItems(value.Uint64Value(123), value.Uint64Value(321)). - EndTuple().Build().ToYDB(a) + EndTuple().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ "$x": { diff --git a/internal/params/variant_struct_test.go b/internal/params/variant_struct_test.go index 3873c8ee0..fc9947587 100644 --- a/internal/params/variant_struct_test.go +++ b/internal/params/variant_struct_test.go @@ -467,7 +467,7 @@ func TestVariantStruct(t *testing.T) { builder, ok := xtest.CallMethod(vs.Name("key"), tc.method, tc.itemArgs...)[0].(*variantStructBuilder) require.True(t, ok) - params := builder.EndStruct().EndVariant().Build().ToYDB(a) + params := builder.EndStruct().EndVariant().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ @@ -519,7 +519,7 @@ func TestVariantStruct_AddFields(t *testing.T) { T: types.Text, }, }...).Name("key3").Text("Hello, World!").EndStruct(). - EndVariant().Build().ToYDB(a) + EndVariant().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ diff --git a/internal/params/variant_tuple_test.go b/internal/params/variant_tuple_test.go index 2ce05af61..64a174bdc 100644 --- a/internal/params/variant_tuple_test.go +++ b/internal/params/variant_tuple_test.go @@ -466,7 +466,7 @@ func TestVariantTuple(t *testing.T) { builder, ok := xtest.CallMethod(types.Index(0), tc.method, tc.itemArgs...)[0].(*variantTupleBuilder) require.True(t, ok) - params := builder.EndTuple().EndVariant().Build().ToYDB(a) + params := builder.EndTuple().EndVariant().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ @@ -503,7 +503,7 @@ func TestVariantTuple_AddTypes(t *testing.T) { Types().AddTypes(types.Int64, types.Bool). Index(1). Bool(true). - EndTuple().EndVariant().Build().ToYDB(a) + EndTuple().EndVariant().Build().toYDB(a) require.Equal(t, xtest.ToJSON( map[string]*Ydb.TypedValue{ diff --git a/internal/query/client.go b/internal/query/client.go index aad2545de..a7193103f 100644 --- a/internal/query/client.go +++ b/internal/query/client.go @@ -174,7 +174,10 @@ func (c *Client) ExecuteScript( ), } - request, grpcOpts := executeQueryScriptRequest(a, q, settings) + request, grpcOpts, err := executeQueryScriptRequest(a, q, settings) + if err != nil { + return op, xerrors.WithStackTrace(err) + } op, err = executeScript(ctx, c.client, request, grpcOpts...) if err != nil { diff --git a/internal/query/execute_query.go b/internal/query/execute_query.go index 3db10cad9..36c5cfcbd 100644 --- a/internal/query/execute_query.go +++ b/internal/query/execute_query.go @@ -27,7 +27,7 @@ type executeSettings interface { StatsCallback() func(stats stats.QueryStats) TxControl() *query.TransactionControl Syntax() options.Syntax - Params() *params.Parameters + Params() params.Parameters CallOptions() []grpc.CallOption RetryOpts() []retry.Option ResourcePool() string @@ -44,7 +44,13 @@ type executeScriptConfig interface { func executeQueryScriptRequest(a *allocator.Allocator, q string, cfg executeScriptConfig) ( *Ydb_Query.ExecuteScriptRequest, []grpc.CallOption, + error, ) { + params, err := cfg.Params().ToYDB(a) + if err != nil { + return nil, nil, xerrors.WithStackTrace(err) + } + request := &Ydb_Query.ExecuteScriptRequest{ OperationParams: &Ydb_Operations.OperationParams{ OperationMode: 0, @@ -55,32 +61,38 @@ func executeQueryScriptRequest(a *allocator.Allocator, q string, cfg executeScri }, ExecMode: Ydb_Query.ExecMode(cfg.ExecMode()), ScriptContent: queryQueryContent(a, Ydb_Query.Syntax(cfg.Syntax()), q), - Parameters: cfg.Params().ToYDB(a), + Parameters: params, StatsMode: Ydb_Query.StatsMode(cfg.StatsMode()), ResultsTtl: durationpb.New(cfg.ResultsTTL()), PoolId: cfg.ResourcePool(), } - return request, cfg.CallOptions() + return request, cfg.CallOptions(), nil } func executeQueryRequest(a *allocator.Allocator, sessionID, q string, cfg executeSettings) ( *Ydb_Query.ExecuteQueryRequest, []grpc.CallOption, + error, ) { + params, err := cfg.Params().ToYDB(a) + if err != nil { + return nil, nil, xerrors.WithStackTrace(err) + } + request := a.QueryExecuteQueryRequest() request.SessionId = sessionID request.ExecMode = Ydb_Query.ExecMode(cfg.ExecMode()) request.TxControl = cfg.TxControl().ToYDB(a) request.Query = queryFromText(a, q, Ydb_Query.Syntax(cfg.Syntax())) - request.Parameters = cfg.Params().ToYDB(a) + request.Parameters = params request.StatsMode = Ydb_Query.StatsMode(cfg.StatsMode()) request.ConcurrentResultSets = false request.PoolId = cfg.ResourcePool() request.ResponsePartLimitBytes = cfg.ResponsePartLimitSizeBytes() - return request, cfg.CallOptions() + return request, cfg.CallOptions(), nil } func queryQueryContent(a *allocator.Allocator, syntax Ydb_Query.Syntax, q string) *Ydb_Query.QueryContent { @@ -109,7 +121,10 @@ func execute( a := allocator.New() defer a.Free() - request, callOptions := executeQueryRequest(a, sessionID, q, settings) + request, callOptions, err := executeQueryRequest(a, sessionID, q, settings) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } executeCtx := xcontext.ValueOnly(ctx) diff --git a/internal/query/execute_query_test.go b/internal/query/execute_query_test.go index 5698ded92..8d4e2ab7f 100644 --- a/internal/query/execute_query_test.go +++ b/internal/query/execute_query_test.go @@ -1008,7 +1008,8 @@ func TestExecuteQueryRequest(t *testing.T) { }, } { t.Run(tt.name, func(t *testing.T) { - request, callOptions := executeQueryRequest(a, tt.name, tt.name, options.ExecuteSettings(tt.opts...)) + request, callOptions, err := executeQueryRequest(a, tt.name, tt.name, options.ExecuteSettings(tt.opts...)) + require.NoError(t, err) require.Equal(t, request.String(), tt.request.String()) require.Equal(t, tt.callOptions, callOptions) }) diff --git a/internal/query/options/execute.go b/internal/query/options/execute.go index 5489b4a21..c066e701c 100644 --- a/internal/query/options/execute.go +++ b/internal/query/options/execute.go @@ -52,10 +52,12 @@ type ( callOptionsOption []grpc.CallOption txCommitOption struct{} resourcePool string - parametersOption params.Parameters - txControlOption tx.Control - syntaxOption = Syntax - statsModeOption struct { + parametersOption struct { + params params.Parameters + } + txControlOption tx.Control + syntaxOption = Syntax + statsModeOption struct { mode StatsMode callback func(stats.QueryStats) } @@ -94,8 +96,8 @@ const ( SyntaxPostgreSQL = Syntax(Ydb_Query.Syntax_SYNTAX_PG) ) -func (params parametersOption) applyExecuteOption(s *executeSettings) { - s.params = append(s.params, params...) +func (opt parametersOption) applyExecuteOption(s *executeSettings) { + s.params = opt.params } func (opts callOptionsOption) applyExecuteOption(s *executeSettings) { @@ -130,6 +132,7 @@ func defaultExecuteSettings() executeSettings { execMode: ExecModeExecute, statsMode: StatsModeNone, txControl: tx.DefaultTxControl(), + params: ¶ms.Params{}, } } @@ -169,20 +172,18 @@ func (s *executeSettings) ResourcePool() string { return s.resourcePool } -func (s *executeSettings) Params() *params.Parameters { - if len(s.params) == 0 { - return nil - } - - return &s.params +func (s *executeSettings) Params() params.Parameters { + return s.params } func (s *executeSettings) ResponsePartLimitSizeBytes() int64 { return s.responsePartLimitBytes } -func WithParameters(parameters *params.Parameters) parametersOption { - return parametersOption(*parameters) +func WithParameters(params params.Parameters) parametersOption { + return parametersOption{ + params: params, + } } var ( diff --git a/internal/query/options/execute_test.go b/internal/query/options/execute_test.go index 19603e6f0..fc9367a9c 100644 --- a/internal/query/options/execute_test.go +++ b/internal/query/options/execute_test.go @@ -38,6 +38,7 @@ func TestExecuteSettings(t *testing.T) { statsMode: StatsModeNone, txControl: internal.NewControl(internal.WithTxID("test")), syntax: SyntaxYQL, + params: ¶ms.Params{}, }, }, { @@ -50,6 +51,7 @@ func TestExecuteSettings(t *testing.T) { statsMode: StatsModeFull, txControl: internal.NewControl(internal.WithTxID("")), syntax: SyntaxYQL, + params: ¶ms.Params{}, }, }, { @@ -62,6 +64,7 @@ func TestExecuteSettings(t *testing.T) { statsMode: StatsModeNone, txControl: internal.NewControl(internal.WithTxID("")), syntax: SyntaxYQL, + params: ¶ms.Params{}, }, }, { @@ -74,6 +77,7 @@ func TestExecuteSettings(t *testing.T) { statsMode: StatsModeNone, txControl: internal.NewControl(internal.WithTxID("")), syntax: SyntaxPostgreSQL, + params: ¶ms.Params{}, }, }, { @@ -86,6 +90,7 @@ func TestExecuteSettings(t *testing.T) { statsMode: StatsModeNone, txControl: internal.NewControl(internal.WithTxID("")), syntax: SyntaxYQL, + params: ¶ms.Params{}, callOptions: []grpc.CallOption{ grpc.CallContentSubtype("test"), }, @@ -103,7 +108,7 @@ func TestExecuteSettings(t *testing.T) { statsMode: StatsModeNone, txControl: internal.NewControl(internal.WithTxID("")), syntax: SyntaxYQL, - params: *params.Builder{}.Param("$a").Text("A").Build(), + params: params.Builder{}.Param("$a").Text("A").Build(), }, }, { @@ -116,7 +121,7 @@ func TestExecuteSettings(t *testing.T) { statsMode: StatsModeNone, txControl: internal.NewControl(internal.WithTxID(""), internal.CommitTx()), syntax: SyntaxYQL, - params: nil, + params: ¶ms.Params{}, }, }, { @@ -129,6 +134,7 @@ func TestExecuteSettings(t *testing.T) { statsMode: StatsModeNone, txControl: internal.NewControl(internal.WithTxID("")), syntax: SyntaxYQL, + params: ¶ms.Params{}, resourcePool: "test-pool-id", }, }, @@ -146,8 +152,16 @@ func TestExecuteSettings(t *testing.T) { require.Equal(t, tt.settings.StatsMode(), settings.StatsMode()) require.Equal(t, tt.settings.ResourcePool(), settings.ResourcePool()) require.Equal(t, tt.settings.TxControl().ToYDB(a).String(), settings.TxControl().ToYDB(a).String()) - require.Equal(t, tt.settings.Params().ToYDB(a), settings.Params().ToYDB(a)) + require.Equal(t, must(tt.settings.Params().ToYDB(a)), must(settings.Params().ToYDB(a))) require.Equal(t, tt.settings.CallOptions(), settings.CallOptions()) }) } } + +func must[T any](v T, err error) T { + if err != nil { + panic(err) + } + + return v +} diff --git a/internal/scripting/client.go b/internal/scripting/client.go index cee01de25..9b2147c77 100644 --- a/internal/scripting/client.go +++ b/internal/scripting/client.go @@ -42,7 +42,7 @@ type ( func (c *Client) Execute( ctx context.Context, query string, - parameters *params.Parameters, + parameters *params.Params, ) (r result.Result, err error) { if c == nil { return r, xerrors.WithStackTrace(errNilClient) @@ -69,7 +69,7 @@ func (c *Client) Execute( func (c *Client) execute( ctx context.Context, query string, - parameters *params.Parameters, + parameters *params.Params, ) (r result.Result, err error) { var ( onDone = trace.ScriptingOnExecute(c.config.Trace(), &ctx, @@ -78,8 +78,7 @@ func (c *Client) execute( ) a = allocator.New() request = &Ydb_Scripting.ExecuteYqlRequest{ - Script: query, - Parameters: parameters.ToYDB(a), + Script: query, OperationParams: operation.Params( ctx, c.config.OperationTimeout(), @@ -94,6 +93,14 @@ func (c *Client) execute( a.Free() onDone(r, err) }() + + params, err := parameters.ToYDB(a) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + request.Parameters = params + response, err = c.service.ExecuteYql(ctx, request) if err != nil { return nil, xerrors.WithStackTrace(err) @@ -197,7 +204,7 @@ func (c *Client) explain( func (c *Client) StreamExecute( ctx context.Context, query string, - params *params.Parameters, + params *params.Params, ) (r result.StreamResult, err error) { if c == nil { return r, xerrors.WithStackTrace(errNilClient) @@ -225,7 +232,7 @@ func (c *Client) StreamExecute( func (c *Client) streamExecute( ctx context.Context, query string, - parameters *params.Parameters, + parameters *params.Params, ) (r result.StreamResult, err error) { var ( onIntermediate = trace.ScriptingOnStreamExecute(c.config.Trace(), &ctx, @@ -234,8 +241,7 @@ func (c *Client) streamExecute( ) a = allocator.New() request = &Ydb_Scripting.ExecuteYqlRequest{ - Script: query, - Parameters: parameters.ToYDB(a), + Script: query, OperationParams: operation.Params( ctx, c.config.OperationTimeout(), @@ -251,6 +257,13 @@ func (c *Client) streamExecute( } }() + params, err := parameters.ToYDB(a) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + request.Parameters = params + ctx, cancel := xcontext.WithCancel(ctx) stream, err := c.service.StreamExecuteYql(ctx, request) diff --git a/internal/table/conn/conn.go b/internal/table/conn/conn.go index 3d1e96853..e56b71961 100644 --- a/internal/table/conn/conn.go +++ b/internal/table/conn/conn.go @@ -314,7 +314,7 @@ func (c *Conn) queryContext(ctx context.Context, query string, args []driver.Nam } } -func (c *Conn) execDataQuery(ctx context.Context, query string, params params.Parameters) (driver.Rows, error) { +func (c *Conn) execDataQuery(ctx context.Context, query string, params params.Params) (driver.Rows, error) { _, res, err := c.session.Execute(ctx, txControl(ctx, c.defaultTxControl), query, ¶ms, c.dataQueryOptions(ctx)..., @@ -332,7 +332,7 @@ func (c *Conn) execDataQuery(ctx context.Context, query string, params params.Pa }, nil } -func (c *Conn) execScanQuery(ctx context.Context, query string, params params.Parameters) (driver.Rows, error) { +func (c *Conn) execScanQuery(ctx context.Context, query string, params params.Params) (driver.Rows, error) { res, err := c.session.StreamExecuteScanQuery(ctx, query, ¶ms, c.scanQueryOptions(ctx)..., ) @@ -363,7 +363,7 @@ func (c *Conn) explainQuery(ctx context.Context, query string) (driver.Rows, err }, nil } -func (c *Conn) execScriptingQuery(ctx context.Context, query string, params params.Parameters) (driver.Rows, error) { +func (c *Conn) execScriptingQuery(ctx context.Context, query string, params params.Params) (driver.Rows, error) { res, err := c.parent.Scripting().StreamExecute(ctx, query, ¶ms) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) @@ -434,7 +434,7 @@ func (c *Conn) Begin() (driver.Tx, error) { return nil, errDeprecated } -func (c *Conn) normalize(q string, args ...driver.NamedValue) (query string, _ params.Parameters, _ error) { +func (c *Conn) normalize(q string, args ...driver.NamedValue) (query string, _ params.Params, _ error) { return c.parent.Bindings().RewriteQuery(q, func() (ii []interface{}) { for i := range args { ii = append(ii, args[i]) diff --git a/internal/table/session.go b/internal/table/session.go index 6c7bff42a..86c9a216c 100644 --- a/internal/table/session.go +++ b/internal/table/session.go @@ -796,7 +796,7 @@ func (s *session) Execute( ctx context.Context, txControl *table.TransactionControl, query string, - parameters *params.Parameters, + parameters *params.Params, opts ...options.ExecuteDataQueryOption, ) ( txr table.Transaction, r result.Result, err error, @@ -812,9 +812,14 @@ func (s *session) Execute( ) defer a.Free() + params, err := parameters.ToYDB(a) + if err != nil { + return nil, nil, xerrors.WithStackTrace(err) + } + request.SessionId = s.id request.TxControl = txControl.Desc() - request.Parameters = parameters.ToYDB(a) + request.Parameters = params request.Query = q.toYDB(a) request.QueryCachePolicy = a.TableQueryCachePolicy() request.QueryCachePolicy.KeepInCache = len(request.Parameters) > 0 @@ -1189,7 +1194,7 @@ func (s *session) ReadRows( func (s *session) StreamExecuteScanQuery( ctx context.Context, query string, - parameters *params.Parameters, + parameters *params.Params, opts ...options.ExecuteScanQueryOption, ) (_ result.StreamResult, err error) { var ( @@ -1201,9 +1206,8 @@ func (s *session) StreamExecuteScanQuery( s, q, parameters, ) request = Ydb_Table.ExecuteScanQueryRequest{ - Query: q.toYDB(a), - Parameters: parameters.ToYDB(a), - Mode: Ydb_Table.ExecuteScanQueryRequest_MODE_EXEC, // set default + Query: q.toYDB(a), + Mode: Ydb_Table.ExecuteScanQueryRequest_MODE_EXEC, // set default } stream Ydb_Table_V1.TableService_StreamExecuteScanQueryClient callOptions []grpc.CallOption @@ -1213,6 +1217,13 @@ func (s *session) StreamExecuteScanQuery( onDone(xerrors.HideEOF(err)) }() + params, err := parameters.ToYDB(a) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + request.Parameters = params + for _, opt := range opts { if opt != nil { callOptions = append(callOptions, opt.ApplyExecuteScanQueryOption((*options.ExecuteScanQueryDesc)(&request))...) diff --git a/internal/table/statement.go b/internal/table/statement.go index acb77465b..e89ef3a5e 100644 --- a/internal/table/statement.go +++ b/internal/table/statement.go @@ -27,7 +27,7 @@ type statement struct { // Execute executes prepared data query. func (s *statement) Execute( ctx context.Context, txControl *table.TransactionControl, - parameters *params.Parameters, + parameters *params.Params, opts ...options.ExecuteDataQueryOption, ) ( txr table.Transaction, r result.Result, err error, @@ -42,9 +42,14 @@ func (s *statement) Execute( ) defer a.Free() + params, err := parameters.ToYDB(a) + if err != nil { + return nil, nil, xerrors.WithStackTrace(err) + } + request.SessionId = s.session.id request.TxControl = txControl.Desc() - request.Parameters = parameters.ToYDB(a) + request.Parameters = params request.Query = s.query.toYDB(a) request.QueryCachePolicy = a.TableQueryCachePolicy() request.QueryCachePolicy.KeepInCache = len(request.Parameters) > 0 diff --git a/internal/table/transaction.go b/internal/table/transaction.go index 818210f4f..e005dcc10 100644 --- a/internal/table/transaction.go +++ b/internal/table/transaction.go @@ -58,7 +58,7 @@ type transaction struct { // Execute executes query represented by text within transaction tx. func (tx *transaction) Execute( ctx context.Context, - query string, parameters *params.Parameters, + query string, parameters *params.Params, opts ...options.ExecuteDataQueryOption, ) (r result.Result, err error) { onDone := trace.TableOnTxExecute( @@ -92,7 +92,7 @@ func (tx *transaction) Execute( // ExecuteStatement executes prepared statement stmt within transaction tx. func (tx *transaction) ExecuteStatement( ctx context.Context, - stmt table.Statement, parameters *params.Parameters, + stmt table.Statement, parameters *params.Params, opts ...options.ExecuteDataQueryOption, ) (r result.Result, err error) { a := allocator.New() diff --git a/params_map.go b/params_map.go index 9cf350959..3c36ff4da 100644 --- a/params_map.go +++ b/params_map.go @@ -2,33 +2,35 @@ package ydb import ( "database/sql/driver" - "fmt" + "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/bind" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) -// MustParamsFromMap build parameters from named map, panic if error -// -// Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental -func MustParamsFromMap(m map[string]any) *params.Parameters { - p, err := ParamsFromMap(m) - if err != nil { - panic(fmt.Sprintf("ydb: MustParamsFromMap failed with error: %v", err)) - } +type wrongParameters struct { + err error +} - return p +func (p wrongParameters) ToYDB(a *allocator.Allocator) (map[string]*Ydb.TypedValue, error) { + return nil, xerrors.WithStackTrace(p.err) } // ParamsFromMap build parameters from named map // // Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental -func ParamsFromMap(m map[string]any) (*params.Parameters, error) { +func ParamsFromMap(m map[string]any) params.Parameters { namedParameters := make([]any, 0, len(m)) for name, val := range m { namedParameters = append(namedParameters, driver.NamedValue{Name: name, Value: val}) } p, err := bind.Params(namedParameters...) + if err != nil { + return wrongParameters{err: xerrors.WithStackTrace(err)} + } - return (*params.Parameters)(&p), err + return (*params.Params)(&p) } diff --git a/query/execute_options.go b/query/execute_options.go index d82355d97..cd9042b73 100644 --- a/query/execute_options.go +++ b/query/execute_options.go @@ -29,7 +29,7 @@ const ( StatsModeProfile = options.StatsModeProfile ) -func WithParameters(parameters *params.Parameters) ExecuteOption { +func WithParameters(parameters params.Parameters) ExecuteOption { return options.WithParameters(parameters) } diff --git a/scripting/scripting.go b/scripting/scripting.go index 048529fee..df76a9c32 100644 --- a/scripting/scripting.go +++ b/scripting/scripting.go @@ -22,7 +22,7 @@ type Client interface { Execute( ctx context.Context, query string, - params *params.Parameters, + params *params.Params, ) (result.Result, error) Explain( ctx context.Context, @@ -32,6 +32,6 @@ type Client interface { StreamExecute( ctx context.Context, query string, - params *params.Parameters, + params *params.Params, ) (result.StreamResult, error) } diff --git a/sugar/params.go b/sugar/params.go index 4285969a5..c9025b903 100644 --- a/sugar/params.go +++ b/sugar/params.go @@ -13,7 +13,7 @@ import ( ) type constraint interface { - params.Parameters | []*params.Parameter | *table.QueryParameters | []table.ParameterOption | []sql.NamedArg + params.Params | []*params.Parameter | *table.QueryParameters | []table.ParameterOption | []sql.NamedArg } // GenerateDeclareSection generates DECLARE section text in YQL query by params @@ -24,7 +24,7 @@ type constraint interface { // Read about versioning policy: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#deprecated func GenerateDeclareSection[T constraint](parameters T) (string, error) { switch v := any(parameters).(type) { - case *params.Parameters: + case *params.Params: return parametersToDeclares(*v), nil case []*params.Parameter: return parametersToDeclares(v), nil diff --git a/table/table.go b/table/table.go index 961a994c3..f43ff1572 100644 --- a/table/table.go +++ b/table/table.go @@ -160,7 +160,7 @@ type Session interface { ctx context.Context, tx *TransactionControl, query string, - params *params.Parameters, + params *params.Params, opts ...options.ExecuteDataQueryOption, ) (txr Transaction, r result.Result, err error) @@ -183,7 +183,7 @@ type Session interface { StreamExecuteScanQuery( ctx context.Context, query string, - params *params.Parameters, + params *params.Params, opts ...options.ExecuteScanQueryOption, ) (_ result.StreamResult, err error) @@ -258,13 +258,13 @@ type TransactionActor interface { Execute( ctx context.Context, query string, - params *params.Parameters, + params *params.Params, opts ...options.ExecuteDataQueryOption, ) (result.Result, error) ExecuteStatement( ctx context.Context, stmt Statement, - params *params.Parameters, + params *params.Params, opts ...options.ExecuteDataQueryOption, ) (result.Result, error) } @@ -285,7 +285,7 @@ type Statement interface { Execute( ctx context.Context, tx *TransactionControl, - params *params.Parameters, + params *params.Params, opts ...options.ExecuteDataQueryOption, ) (txr Transaction, r result.Result, err error) NumInput() int @@ -471,7 +471,7 @@ func SnapshotReadOnlyTxControl() *TransactionControl { // QueryParameters type ( ParameterOption = params.NamedValue - QueryParameters = params.Parameters + QueryParameters = params.Params ) func NewQueryParameters(opts ...ParameterOption) *QueryParameters { diff --git a/topic/topictypes/topictypes_test.go b/topic/topictypes/topictypes_test.go index 606e07610..3dc9f16da 100644 --- a/topic/topictypes/topictypes_test.go +++ b/topic/topictypes/topictypes_test.go @@ -152,7 +152,6 @@ func TestTopicDescriptionFromRaw(t *testing.T) { } for _, v := range testData { - v := v t.Run( v.testName, func(t *testing.T) { d := TopicDescription{} @@ -322,7 +321,6 @@ func TestTopicConsumerDescriptionFromRaw(t *testing.T) { }, } for _, v := range testData { - v := v t.Run( v.testName, func(t *testing.T) { d := TopicConsumerDescription{}