Skip to content

Commit

Permalink
Merge pull request #1535 from ydb-platform/xsql
Browse files Browse the repository at this point in the history
* Refactored `database/sql` driver internals for query-service client support in the future
  • Loading branch information
asmyasnikov authored Nov 5, 2024
2 parents 21fab94 + cf02c93 commit b538748
Show file tree
Hide file tree
Showing 45 changed files with 1,782 additions and 1,596 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
* Refactored `database/sql` driver internals for query-service client support in the future

## v3.89.5
* Fixed nil pointer dereference in metabalancer initialization

Expand Down
4 changes: 2 additions & 2 deletions driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/ydb-platform/ydb-go-sdk/v3/discovery"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/balancer"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/conn"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/connector"
internalCoordination "github.com/ydb-platform/ydb-go-sdk/v3/internal/coordination"
coordinationConfig "github.com/ydb-platform/ydb-go-sdk/v3/internal/coordination/config"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials"
Expand All @@ -36,7 +37,6 @@ import (
"github.com/ydb-platform/ydb-go-sdk/v3/internal/topic/topicclientinternal"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xcontext"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xsync"
"github.com/ydb-platform/ydb-go-sdk/v3/log"
"github.com/ydb-platform/ydb-go-sdk/v3/operation"
Expand Down Expand Up @@ -93,7 +93,7 @@ type (
topic *xsync.Once[*topicclientinternal.Client]
topicOptions []topicoptions.TopicOption

databaseSQLOptions []xsql.ConnectorOption
databaseSQLOptions []connector.Option

pool *conn.Pool

Expand Down
31 changes: 16 additions & 15 deletions dsn.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import (
"github.com/ydb-platform/ydb-go-sdk/v3/balancers"
"github.com/ydb-platform/ydb-go-sdk/v3/credentials"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/bind"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/connector"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/dsn"
tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql"
)

const tablePathPrefixTransformer = "table_path_prefix"
Expand Down Expand Up @@ -59,45 +60,45 @@ func parseConnectionString(dataSourceName string) (opts []Option, _ error) {
opts = append(opts, WithBalancer(balancers.FromConfig(balancer)))
}
if queryMode := info.Params.Get("go_query_mode"); queryMode != "" {
mode := xsql.QueryModeFromString(queryMode)
if mode == xsql.UnknownQueryMode {
mode := tableSql.QueryModeFromString(queryMode)
if mode == tableSql.UnknownQueryMode {
return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode))
}
opts = append(opts, withConnectorOptions(xsql.WithDefaultQueryMode(mode)))
opts = append(opts, withConnectorOptions(connector.WithDefaultQueryMode(mode)))
} else if queryMode := info.Params.Get("query_mode"); queryMode != "" {
mode := xsql.QueryModeFromString(queryMode)
if mode == xsql.UnknownQueryMode {
mode := tableSql.QueryModeFromString(queryMode)
if mode == tableSql.UnknownQueryMode {
return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode))
}
opts = append(opts, withConnectorOptions(xsql.WithDefaultQueryMode(mode)))
opts = append(opts, withConnectorOptions(connector.WithDefaultQueryMode(mode)))
}
if fakeTx := info.Params.Get("go_fake_tx"); fakeTx != "" {
for _, queryMode := range strings.Split(fakeTx, ",") {
mode := xsql.QueryModeFromString(queryMode)
if mode == xsql.UnknownQueryMode {
mode := tableSql.QueryModeFromString(queryMode)
if mode == tableSql.UnknownQueryMode {
return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode))
}
opts = append(opts, withConnectorOptions(xsql.WithFakeTx(mode)))
opts = append(opts, withConnectorOptions(connector.WithFakeTx(mode)))
}
}
if info.Params.Has("go_query_bind") {
var binders []xsql.ConnectorOption
var binders []connector.Option
queryTransformers := strings.Split(info.Params.Get("go_query_bind"), ",")
for _, transformer := range queryTransformers {
switch transformer {
case "declare":
binders = append(binders, xsql.WithQueryBind(bind.AutoDeclare{}))
binders = append(binders, connector.WithQueryBind(bind.AutoDeclare{}))
case "positional":
binders = append(binders, xsql.WithQueryBind(bind.PositionalArgs{}))
binders = append(binders, connector.WithQueryBind(bind.PositionalArgs{}))
case "numeric":
binders = append(binders, xsql.WithQueryBind(bind.NumericArgs{}))
binders = append(binders, connector.WithQueryBind(bind.NumericArgs{}))
default:
if strings.HasPrefix(transformer, tablePathPrefixTransformer) {
prefix, err := extractTablePathPrefixFromBinderName(transformer)
if err != nil {
return nil, xerrors.WithStackTrace(err)
}
binders = append(binders, xsql.WithTablePathPrefix(prefix))
binders = append(binders, connector.WithQueryBind(bind.TablePathPrefix(prefix)))
} else {
return nil, xerrors.WithStackTrace(
fmt.Errorf("unknown query rewriter: %s", transformer),
Expand Down
107 changes: 64 additions & 43 deletions dsn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import (

"github.com/ydb-platform/ydb-go-sdk/v3/config"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/bind"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql"
"github.com/ydb-platform/ydb-go-sdk/v3/internal/connector"
querySql "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn"
tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn"
)

func TestParse(t *testing.T) {
newConnector := func(opts ...xsql.ConnectorOption) *xsql.Connector {
c := &xsql.Connector{}
newConnector := func(opts ...connector.Option) *connector.Connector {
c := &connector.Connector{}
for _, opt := range opts {
if opt != nil {
if err := opt.Apply(c); err != nil {
Expand All @@ -24,6 +26,12 @@ func TestParse(t *testing.T) {

return c
}
newTableConn := func(opts ...tableSql.Option) *tableSql.Conn {
return tableSql.New(context.Background(), nil, nil, opts...)
}
newQueryConn := func(opts ...querySql.Option) *querySql.Conn {
return querySql.New(context.Background(), nil, nil, opts...)
}
compareConfigs := func(t *testing.T, lhs, rhs *config.Config) {
require.Equal(t, lhs.Secure(), rhs.Secure())
require.Equal(t, lhs.Endpoint(), rhs.Endpoint())
Expand All @@ -32,22 +40,9 @@ func TestParse(t *testing.T) {
for _, tt := range []struct {
dsn string
opts []config.Option
connectorOpts []xsql.ConnectorOption
connectorOpts []connector.Option
err error
}{
{
dsn: "grpc://localhost:2135/local?go_fake_tx=scripting,scheme",
opts: []config.Option{
config.WithSecure(false),
config.WithEndpoint("localhost:2135"),
config.WithDatabase("/local"),
},
connectorOpts: []xsql.ConnectorOption{
xsql.WithFakeTx(xsql.ScriptingQueryMode),
xsql.WithFakeTx(xsql.SchemeQueryMode),
},
err: nil,
},
{
dsn: "grpc://localhost:2135/local",
opts: []config.Option{
Expand Down Expand Up @@ -75,8 +70,8 @@ func TestParse(t *testing.T) {
config.WithEndpoint("localhost:2135"),
config.WithDatabase("/local"),
},
connectorOpts: []xsql.ConnectorOption{
xsql.WithDefaultQueryMode(xsql.ScriptingQueryMode),
connectorOpts: []connector.Option{
connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode),
},
err: nil,
},
Expand All @@ -87,9 +82,9 @@ func TestParse(t *testing.T) {
config.WithEndpoint("localhost:2135"),
config.WithDatabase("/local"),
},
connectorOpts: []xsql.ConnectorOption{
xsql.WithDefaultQueryMode(xsql.ScriptingQueryMode),
xsql.WithTablePathPrefix("path/to/tables"),
connectorOpts: []connector.Option{
connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode),
connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")),
},
err: nil,
},
Expand All @@ -100,10 +95,10 @@ func TestParse(t *testing.T) {
config.WithEndpoint("localhost:2135"),
config.WithDatabase("/local"),
},
connectorOpts: []xsql.ConnectorOption{
xsql.WithDefaultQueryMode(xsql.ScriptingQueryMode),
xsql.WithTablePathPrefix("path/to/tables"),
xsql.WithQueryBind(bind.NumericArgs{}),
connectorOpts: []connector.Option{
connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode),
connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")),
connector.WithQueryBind(bind.NumericArgs{}),
},
err: nil,
},
Expand All @@ -114,10 +109,10 @@ func TestParse(t *testing.T) {
config.WithEndpoint("localhost:2135"),
config.WithDatabase("/local"),
},
connectorOpts: []xsql.ConnectorOption{
xsql.WithDefaultQueryMode(xsql.ScriptingQueryMode),
xsql.WithTablePathPrefix("path/to/tables"),
xsql.WithQueryBind(bind.PositionalArgs{}),
connectorOpts: []connector.Option{
connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode),
connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")),
connector.WithQueryBind(bind.PositionalArgs{}),
},
err: nil,
},
Expand All @@ -128,10 +123,10 @@ func TestParse(t *testing.T) {
config.WithEndpoint("localhost:2135"),
config.WithDatabase("/local"),
},
connectorOpts: []xsql.ConnectorOption{
xsql.WithDefaultQueryMode(xsql.ScriptingQueryMode),
xsql.WithTablePathPrefix("path/to/tables"),
xsql.WithQueryBind(bind.AutoDeclare{}),
connectorOpts: []connector.Option{
connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode),
connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")),
connector.WithQueryBind(bind.AutoDeclare{}),
},
err: nil,
},
Expand All @@ -142,9 +137,9 @@ func TestParse(t *testing.T) {
config.WithEndpoint("localhost:2135"),
config.WithDatabase("/local"),
},
connectorOpts: []xsql.ConnectorOption{
xsql.WithDefaultQueryMode(xsql.ScriptingQueryMode),
xsql.WithTablePathPrefix("path/to/tables"),
connectorOpts: []connector.Option{
connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode),
connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")),
},
err: nil,
},
Expand All @@ -155,11 +150,24 @@ func TestParse(t *testing.T) {
config.WithEndpoint("localhost:2135"),
config.WithDatabase("/local"),
},
connectorOpts: []xsql.ConnectorOption{
xsql.WithDefaultQueryMode(xsql.ScriptingQueryMode),
xsql.WithTablePathPrefix("path/to/tables"),
xsql.WithQueryBind(bind.PositionalArgs{}),
xsql.WithQueryBind(bind.AutoDeclare{}),
connectorOpts: []connector.Option{
connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode),
connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")),
connector.WithQueryBind(bind.PositionalArgs{}),
connector.WithQueryBind(bind.AutoDeclare{}),
},
err: nil,
},
{
dsn: "grpc://localhost:2135/local?go_fake_tx=scripting,scheme",
opts: []config.Option{
config.WithSecure(false),
config.WithEndpoint("localhost:2135"),
config.WithDatabase("/local"),
},
connectorOpts: []connector.Option{
connector.WithFakeTx(tableSql.ScriptingQueryMode),
connector.WithFakeTx(tableSql.SchemeQueryMode),
},
err: nil,
},
Expand All @@ -172,7 +180,20 @@ func TestParse(t *testing.T) {
require.NoError(t, err)
d, err := newConnectionFromOptions(context.Background(), opts...)
require.NoError(t, err)
require.Equal(t, newConnector(tt.connectorOpts...), newConnector(d.databaseSQLOptions...))
exp := newConnector(tt.connectorOpts...)
act := newConnector(d.databaseSQLOptions...)
t.Run("tableOptions", func(t *testing.T) {
require.Equal(t, newTableConn(exp.TableOpts...), newTableConn(act.TableOpts...))
})
t.Run("queryOptions", func(t *testing.T) {
require.Equal(t, newQueryConn(exp.QueryOpts...), newQueryConn(act.QueryOpts...))
})
exp.TableOpts = nil
exp.QueryOpts = nil
act.TableOpts = nil
act.QueryOpts = nil
require.Equal(t, exp.Bindings(), act.Bindings())
require.Equal(t, exp, act)
compareConfigs(t, config.New(tt.opts...), d.config)
}
})
Expand Down
Loading

0 comments on commit b538748

Please sign in to comment.