From d242af3a75b9a422f3ef4d5d509cc6fcd877ec09 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 10 Nov 2024 13:27:48 +0300 Subject: [PATCH 01/48] fix(sql): tmp queryservice default option --- sql.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql.go b/sql.go index 0ec78b964..b7b3d73c1 100644 --- a/sql.go +++ b/sql.go @@ -171,7 +171,8 @@ func Connector(parent *Driver, opts ...ConnectorOption) (SQLConnector, error) { ), xsql.WithOnClose(d.detach), xsql.WithTraceRetry(parent.config.TraceRetry()), - xsql.WithretryBudget(parent.config.RetryBudget()), + xsql.WithRetryBudget(parent.config.RetryBudget()), + xsql.OverQueryService(), )..., ) if err != nil { From ef54737a22a7a59b9f33ec7117ffef3a1022f9ac Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 30 Oct 2024 13:10:10 +0300 Subject: [PATCH 02/48] feat(internal/query/xsql): conn boilerplate --- internal/query/xsql/conn.go | 120 ++++++++++++++++++++++++++++++++++ internal/query/xsql/errors.go | 9 +++ 2 files changed, 129 insertions(+) create mode 100644 internal/query/xsql/conn.go create mode 100644 internal/query/xsql/errors.go diff --git a/internal/query/xsql/conn.go b/internal/query/xsql/conn.go new file mode 100644 index 000000000..eabdb8f8d --- /dev/null +++ b/internal/query/xsql/conn.go @@ -0,0 +1,120 @@ +package xsql + +import ( + "context" + "database/sql/driver" + "sync/atomic" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" + internalxsql "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql" + "github.com/ydb-platform/ydb-go-sdk/v3/query" + "github.com/ydb-platform/ydb-go-sdk/v3/table/options" + "github.com/ydb-platform/ydb-go-sdk/v3/trace" +) + +type connOption func(*conn) + +type currentTx interface { + tx.Identifier + driver.Tx + driver.ExecerContext + driver.QueryerContext + driver.ConnPrepareContext +} + +type beginTxFunc func(ctx context.Context, txOptions driver.TxOptions) (currentTx, error) + +type conn struct { + ctx context.Context + + connector *internalxsql.Connector + trace *trace.DatabaseSQL + session query.ClosableSession + + beginTxFuncs map[internalxsql.QueryMode]beginTxFunc + + closed atomic.Bool + lastUsage atomic.Int64 + defaultQueryMode internalxsql.QueryMode + + defaultTxControl *query.TransactionControl + dataOpts []options.ExecuteDataQueryOption + + scanOpts []options.ExecuteScanQueryOption + + currentTx currentTx +} + +var ( + _ driver.Conn = &conn{} + _ driver.ConnPrepareContext = &conn{} + _ driver.ConnBeginTx = &conn{} + _ driver.ExecerContext = &conn{} + _ driver.QueryerContext = &conn{} + _ driver.Pinger = &conn{} + _ driver.Validator = &conn{} + _ driver.NamedValueChecker = &conn{} +) + +type resultNoRows struct{} + +func (resultNoRows) LastInsertId() (int64, error) { return 0, ErrUnsupported } +func (resultNoRows) RowsAffected() (int64, error) { return 0, ErrUnsupported } + +var ( + _ driver.Result = resultNoRows{} +) + +func newConn(ctx context.Context, c *internalxsql.Connector, opts ...connOption) *conn { + panic("unimplemented") +} + +// CheckNamedValue implements driver.NamedValueChecker. +func (c *conn) CheckNamedValue(*driver.NamedValue) error { + panic("unimplemented") +} + +// IsValid implements driver.Validator. +func (c *conn) IsValid() bool { + panic("unimplemented") +} + +// Ping implements driver.Pinger. +func (c *conn) Ping(ctx context.Context) error { + panic("unimplemented") +} + +// QueryContext implements driver.QueryerContext. +func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { + panic("unimplemented") +} + +// ExecContext implements driver.ExecerContext. +func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { + panic("unimplemented") +} + +// BeginTx implements driver.ConnBeginTx. +func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { + panic("unimplemented") +} + +// PrepareContext implements driver.ConnPrepareContext. +func (c *conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { + panic("unimplemented") +} + +// Begin implements driver.Conn. +func (c *conn) Begin() (driver.Tx, error) { + panic("unimplemented") +} + +// Close implements driver.Conn. +func (c *conn) Close() error { + panic("unimplemented") +} + +// Prepare implements driver.Conn. +func (c *conn) Prepare(query string) (driver.Stmt, error) { + panic("unimplemented") +} diff --git a/internal/query/xsql/errors.go b/internal/query/xsql/errors.go new file mode 100644 index 000000000..a86889761 --- /dev/null +++ b/internal/query/xsql/errors.go @@ -0,0 +1,9 @@ +package xsql + +import ( + "database/sql/driver" +) + +var ( + ErrUnsupported = driver.ErrSkip +) From 152fd71a424ba0bbe48c790929e8d7a7655e3454 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 10 Nov 2024 13:28:27 +0300 Subject: [PATCH 03/48] feat(internal/query/conn): driver initial implemetations --- internal/query/conn/conn.go | 102 +++++++++++++++++++++ internal/query/conn/driver.impls.go | 133 ++++++++++++++++++++++++++++ internal/query/conn/errors.go | 15 ++++ 3 files changed, 250 insertions(+) create mode 100644 internal/query/conn/conn.go create mode 100644 internal/query/conn/driver.impls.go create mode 100644 internal/query/conn/errors.go diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go new file mode 100644 index 000000000..5adf38a9a --- /dev/null +++ b/internal/query/conn/conn.go @@ -0,0 +1,102 @@ +package conn + +import ( + "context" + "database/sql/driver" + "sync/atomic" + + "github.com/jonboulle/clockwork" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/query" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/session" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "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/retry/budget" + "github.com/ydb-platform/ydb-go-sdk/v3/trace" +) + +type ( + Parent interface { + Query() *query.Client + Trace() *trace.DatabaseSQL + TraceRetry() *trace.Retry + RetryBudget() budget.Budget + Bindings() bind.Bindings + Clock() clockwork.Clock + } + currentTx interface { + Rollback() error + } + Conn struct { + currentTx + ctx context.Context //nolint:containedctx + parent Parent + session *query.Session + onClose []func() + closed atomic.Bool + lastUsage atomic.Int64 + } +) + +func New(ctx context.Context, parent Parent, s *query.Session, opts ...Option) *Conn { + cc := &Conn{ + ctx: ctx, + parent: parent, + session: s, + } + + for _, opt := range opts { + if opt != nil { + opt(cc) + } + } + + return cc +} + +func (c *Conn) isReady() bool { + return c.session.Status() == session.StatusIdle.String() +} + +func (c *Conn) execContext( + ctx context.Context, + query string, + args []driver.NamedValue, +) (_ driver.Result, finalErr error) { + defer func() { + c.lastUsage.Store(c.parent.Clock().Now().Unix()) + }() + + if !c.isReady() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + // TODO tx + // if c.currentTx != nil { + // return c.currentTx.ExecContext(ctx, query, args) + // } + + m := queryModeFromContext(ctx, c.defaultQueryMode) + onDone := trace.DatabaseSQLOnConnExec(c.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).execContext"), + query, m.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), + ) + defer func() { + onDone(finalErr) + }() + + c.session.Exec() + // switch m { + // case DataQueryMode: + // return c.executeDataQuery(ctx, query, args) + // case SchemeQueryMode: + // return c.executeSchemeQuery(ctx, query) + // case ScriptingQueryMode: + // return c.executeScriptingQuery(ctx, query, args) + // default: + // return nil, fmt.Errorf("unsupported query mode '%s' for execute query", m) + // } +} diff --git a/internal/query/conn/driver.impls.go b/internal/query/conn/driver.impls.go new file mode 100644 index 000000000..f56125c3a --- /dev/null +++ b/internal/query/conn/driver.impls.go @@ -0,0 +1,133 @@ +package conn + +import ( + "context" + "database/sql/driver" + "time" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "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/trace" +) + +var ( + _ driver.Conn = &Conn{} + _ driver.ConnPrepareContext = &Conn{} + _ driver.ConnBeginTx = &Conn{} + _ driver.ExecerContext = &Conn{} + _ driver.QueryerContext = &Conn{} + _ driver.Pinger = &Conn{} + _ driver.Validator = &Conn{} + _ driver.NamedValueChecker = &Conn{} +) + +func (c *Conn) ID() string { + return c.session.ID() +} + +func (c *Conn) IsValid() bool { + return c.isReady() +} + +func (c *Conn) CheckNamedValue(value *driver.NamedValue) error { + //TODO implement me + panic("implement me") +} + +func (c *Conn) Ping(ctx context.Context) (finalErr error) { + onDone := trace.DatabaseSQLOnConnPing(c.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).Ping"), + ) + defer func() { + onDone(finalErr) + }() + + if !c.isReady() { + return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + if !c.session.Core.IsAlive() { + return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + err := c.session.Exec(ctx, "select 1") + + return err +} + +func (c *Conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { + //TODO implement me + panic("implement me") +} + +func (c *Conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { + //TODO implement me + panic("implement me") +} + +func (c *Conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { + if !c.IsValid() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + // TODO TX + // if c.currentTx != nil { + // return c.currentTx.ExecContext(ctx, query, args) + // } + + return c.execContext(ctx, query, args) +} + +func (c *Conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { + //TODO implement me + panic("implement me") +} + +func (c *Conn) Prepare(query string) (driver.Stmt, error) { + //TODO implement me + panic("implement me") +} + +func (c *Conn) Close() (finalErr error) { + if !c.closed.CompareAndSwap(false, true) { + return badconn.Map(xerrors.WithStackTrace(errConnClosedEarly)) + } + + defer func() { + for _, onClose := range c.onClose { + onClose() + } + }() + + var ( + ctx = c.ctx + onDone = trace.DatabaseSQLOnConnClose( + c.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).Close"), + ) + ) + defer func() { + onDone(finalErr) + }() + if c.currentTx != nil { + _ = c.currentTx.Rollback() + } + err := c.session.Close(xcontext.ValueOnly(ctx)) + if err != nil { + return badconn.Map(xerrors.WithStackTrace(err)) + } + + return nil +} + +func (c *Conn) Begin() (driver.Tx, error) { + //TODO implement me + panic("implement me") +} + +func (c *Conn) LastUsage() time.Time { + //TODO implement me + panic("implement me") +} diff --git a/internal/query/conn/errors.go b/internal/query/conn/errors.go new file mode 100644 index 000000000..bc4f7d505 --- /dev/null +++ b/internal/query/conn/errors.go @@ -0,0 +1,15 @@ +package conn + +import ( + "database/sql/driver" + "errors" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" +) + +var ( + ErrUnsupported = driver.ErrSkip + errDeprecated = driver.ErrSkip + errConnClosedEarly = xerrors.Retryable(errors.New("Conn closed early"), xerrors.InvalidObject()) + errNotReadyConn = xerrors.Retryable(errors.New("Conn not ready"), xerrors.InvalidObject()) +) From 6ee564be3623761146d7ac2c0bef57d89f2fb94a Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 10 Nov 2024 22:13:08 +0300 Subject: [PATCH 04/48] feat(internal/query/conn): normalize & execContext fns --- internal/query/conn/conn.go | 49 ++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index 5adf38a9a..a0fa19671 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -8,9 +8,12 @@ import ( "github.com/jonboulle/clockwork" "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/query" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/session" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" + tableConn "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xcontext" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" @@ -18,6 +21,15 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +type resultNoRows struct{} + +func (resultNoRows) LastInsertId() (int64, error) { return 0, ErrUnsupported } +func (resultNoRows) RowsAffected() (int64, error) { return 0, ErrUnsupported } + +var ( + _ driver.Result = resultNoRows{} +) + type ( Parent interface { Query() *query.Client @@ -61,6 +73,15 @@ func (c *Conn) isReady() bool { return c.session.Status() == session.StatusIdle.String() } +func (c *Conn) normalize(q string, args ...driver.NamedValue) (query string, _ params.Parameters, _ error) { + queryArgs := make([]any, len(args)) + for i := range args { + queryArgs[i] = args[i] + } + + return c.parent.Bindings().RewriteQuery(q, queryArgs...) +} + func (c *Conn) execContext( ctx context.Context, query string, @@ -79,24 +100,24 @@ func (c *Conn) execContext( // return c.currentTx.ExecContext(ctx, query, args) // } - m := queryModeFromContext(ctx, c.defaultQueryMode) onDone := trace.DatabaseSQLOnConnExec(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).execContext"), - query, m.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).execContext"), + query, tableConn.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), ) defer func() { onDone(finalErr) }() - c.session.Exec() - // switch m { - // case DataQueryMode: - // return c.executeDataQuery(ctx, query, args) - // case SchemeQueryMode: - // return c.executeSchemeQuery(ctx, query) - // case ScriptingQueryMode: - // return c.executeScriptingQuery(ctx, query, args) - // default: - // return nil, fmt.Errorf("unsupported query mode '%s' for execute query", m) - // } + normalizedQuery, params, err := c.normalize(query, args...) + + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + err = c.session.Exec(ctx, normalizedQuery, options.WithParameters(¶ms)) + if err != nil { + return nil, badconn.Map(xerrors.WithStackTrace(err)) + } + + return resultNoRows{}, nil } From 0732759e17a00ebbc83ff0b931c5461d9567c723 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 10 Nov 2024 23:29:57 +0300 Subject: [PATCH 05/48] feat(internal/query/xsql): tx options transform --- internal/query/conn/isolation/isolation.go | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 internal/query/conn/isolation/isolation.go diff --git a/internal/query/conn/isolation/isolation.go b/internal/query/conn/isolation/isolation.go new file mode 100644 index 000000000..a69180158 --- /dev/null +++ b/internal/query/conn/isolation/isolation.go @@ -0,0 +1,29 @@ +package isolation + +import ( + "database/sql" + "database/sql/driver" + "fmt" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/tx" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/query" +) + +func ToYDB(opts driver.TxOptions) (txcControl tx.Option, err error) { + level := sql.IsolationLevel(opts.Isolation) + switch level { + case sql.LevelDefault, sql.LevelSerializable: + if !opts.ReadOnly { + return query.WithSerializableReadWrite(), nil + } + case sql.LevelSnapshot: + if opts.ReadOnly { + return query.WithSnapshotReadOnly(), nil + } + } + + return nil, xerrors.WithStackTrace(fmt.Errorf( + "unsupported transaction options: %+v", opts, + )) +} From 4ca5144ce01c64c7b0eb1cfb35cd49c2d9ba2694 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 11 Nov 2024 00:38:36 +0300 Subject: [PATCH 06/48] feat(internal/query/xsql): tx initials --- internal/query/conn/conn.go | 34 +++++++ internal/query/conn/driver.impls.go | 11 +- internal/query/conn/tx.go | 153 ++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 internal/query/conn/tx.go diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index a0fa19671..8f87a8896 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -15,6 +15,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" tableConn "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "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/retry/budget" @@ -39,9 +40,15 @@ type ( Bindings() bind.Bindings Clock() clockwork.Clock } + currentTx interface { + tx.Identifier + driver.Tx + driver.ExecerContext + driver.QueryerContext Rollback() error } + Conn struct { currentTx ctx context.Context //nolint:containedctx @@ -82,6 +89,33 @@ func (c *Conn) normalize(q string, args ...driver.NamedValue) (query string, _ p return c.parent.Bindings().RewriteQuery(q, queryArgs...) } +func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx currentTx, finalErr error) { + onDone := trace.DatabaseSQLOnConnBegin(c.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).beginTx"), + ) + defer func() { + onDone(tx, finalErr) + }() + + if c.currentTx != nil { + return nil, badconn.Map( + xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())), + ) + } + + // TODO: fake tx + /* tx, err := beginFakeTx(...) */ + + tx, err := beginTx(ctx, c, txOptions) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + c.currentTx = tx + + return tx, nil +} + func (c *Conn) execContext( ctx context.Context, query string, diff --git a/internal/query/conn/driver.impls.go b/internal/query/conn/driver.impls.go index f56125c3a..db76988a6 100644 --- a/internal/query/conn/driver.impls.go +++ b/internal/query/conn/driver.impls.go @@ -53,7 +53,6 @@ func (c *Conn) Ping(ctx context.Context) (finalErr error) { } err := c.session.Exec(ctx, "select 1") - return err } @@ -62,9 +61,13 @@ func (c *Conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, e panic("implement me") } -func (c *Conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { - //TODO implement me - panic("implement me") +func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (driver.Tx, error) { + tx, err := c.beginTx(ctx, txOptions) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return tx, nil } func (c *Conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { diff --git a/internal/query/conn/tx.go b/internal/query/conn/tx.go new file mode 100644 index 000000000..99e0f4d4c --- /dev/null +++ b/internal/query/conn/tx.go @@ -0,0 +1,153 @@ +package conn + +import ( + "context" + "database/sql/driver" + "fmt" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn/isolation" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/query" + "github.com/ydb-platform/ydb-go-sdk/v3/trace" +) + +type transaction struct { + tx.Identifier + + conn *Conn + ctx context.Context //nolint:containedctx + tx query.Transaction +} + +var ( + _ driver.Tx = &transaction{} + _ driver.ExecerContext = &transaction{} + _ driver.QueryerContext = &transaction{} + _ tx.Identifier = &transaction{} +) + +func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (currentTx, error) { + txc, err := isolation.ToYDB(txOptions) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + nativeTx, err := c.session.Begin(ctx, query.TxSettings(txc)) + if err != nil { + return nil, badconn.Map(xerrors.WithStackTrace(err)) + } + + return &transaction{ + Identifier: tx.ID(nativeTx.ID()), + conn: c, + ctx: ctx, + tx: nativeTx, + }, nil +} + +func (tx *transaction) checkTxState() error { + if tx.conn.currentTx == tx { + return nil + } + + if tx.conn.currentTx == nil { + return fmt.Errorf("broken conn state: tx=%q not related to conn=%q", + tx.ID(), tx.conn.ID(), + ) + } + + return fmt.Errorf("broken conn state: tx=%s not related to conn=%q (conn have current tx=%q)", + tx.conn.currentTx.ID(), tx.conn.ID(), tx.ID(), + ) +} + +func (tx *transaction) Commit() (finalErr error) { + var ( + ctx = tx.ctx + onDone = trace.DatabaseSQLOnTxCommit(tx.conn.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*transaction).Commit"), + tx, + ) + ) + defer func() { + onDone(finalErr) + }() + if err := tx.checkTxState(); err != nil { + return badconn.Map(xerrors.WithStackTrace(err)) + } + defer func() { + tx.conn.currentTx = nil + }() + if err := tx.tx.CommitTx(tx.ctx); err != nil { + return badconn.Map(xerrors.WithStackTrace(err)) + } + + return nil +} + +func (tx *transaction) Rollback() (finalErr error) { + var ( + ctx = tx.ctx + onDone = trace.DatabaseSQLOnTxRollback(tx.conn.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*transaction).Rollback"), + tx, + ) + ) + defer func() { + onDone(finalErr) + }() + if err := tx.checkTxState(); err != nil { + return badconn.Map(xerrors.WithStackTrace(err)) + } + defer func() { + tx.conn.currentTx = nil + }() + err := tx.tx.Rollback(tx.ctx) + if err != nil { + return badconn.Map(xerrors.WithStackTrace(err)) + } + + return err +} + +func (tx *transaction) QueryContext(ctx context.Context, query string, args []driver.NamedValue) ( + _ driver.Rows, finalErr error, +) { + onDone := trace.DatabaseSQLOnTxQuery(tx.conn.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*transaction).QueryContext"), + tx.ctx, tx, query, + ) + defer func() { + onDone(finalErr) + }() + + query, parameters, err := tx.conn.normalize(query, args...) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + res, err := tx.tx.Query(ctx, + query, options.WithParameters(¶meters), + ) + if err != nil { + return nil, badconn.Map(xerrors.WithStackTrace(err)) + } + + return &rows{ + conn: tx.conn, + result: res, + }, nil +} + +func (tx *transaction) ExecContext(ctx context.Context, query string, args []driver.NamedValue) ( + _ driver.Result, finalErr error, +) { + panic("not implemented") +} + +func (tx *transaction) PrepareContext(ctx context.Context, query string) (_ driver.Stmt, finalErr error) { + panic("not implemented") +} From 2678662db26aaf08ae1c4872a6eb0768e134fb7b Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 13 Nov 2024 13:10:27 +0300 Subject: [PATCH 07/48] feat(intenral/query/xsql): rows impls --- internal/query/conn/rows.go | 139 ++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 internal/query/conn/rows.go diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go new file mode 100644 index 000000000..06d040273 --- /dev/null +++ b/internal/query/conn/rows.go @@ -0,0 +1,139 @@ +package conn + +import ( + "context" + "database/sql" + "database/sql/driver" + "errors" + "io" + "sync" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/result" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" +) + +var ( + _ driver.Rows = &rows{} + _ driver.RowsNextResultSet = &rows{} + _ driver.RowsColumnTypeDatabaseTypeName = &rows{} + _ driver.RowsColumnTypeNullable = &rows{} + _ driver.Rows = &single{} + ignoreColumnPrefixName = "__discard_column_" +) + +type rows struct { + conn *Conn + result result.Result + + firstNextSet sync.Once + nextSet result.Set + nextErr error +} + +func (r *rows) LastInsertId() (int64, error) { return 0, ErrUnsupported } +func (r *rows) RowsAffected() (int64, error) { return 0, ErrUnsupported } + +func (r *rows) loadFirstNextSet() { + ctx := context.Background() + res, err := r.result.NextResultSet(ctx) + r.nextErr = err + r.nextSet = res +} + +func (r *rows) Columns() []string { + r.firstNextSet.Do(r.loadFirstNextSet) + if r.nextErr != nil { + panic(r.nextErr) + } + return r.nextSet.Columns() +} + +func (r *rows) ColumnTypeDatabaseTypeName(index int) string { + r.firstNextSet.Do(r.loadFirstNextSet) + if r.nextErr != nil { + panic(r.nextErr) + } + return r.nextSet.ColumnTypes()[index].String() +} + +func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) { + r.firstNextSet.Do(r.loadFirstNextSet) + if r.nextErr != nil { + panic(r.nextErr) + } + _, castResult := r.nextSet.ColumnTypes()[index].(interface{ IsOptional() }) + return castResult, castResult +} + +func (r *rows) NextResultSet() (finalErr error) { + r.firstNextSet.Do(r.loadFirstNextSet) + + ctx := context.Background() + res, err := r.result.NextResultSet(ctx) + r.nextErr = err + if err != nil { + return err + } + + r.nextSet = res + return err +} + +func (r *rows) HasNextResultSet() bool { + return r.nextSet != nil +} + +func (r *rows) Next(dst []driver.Value) error { + r.firstNextSet.Do(r.loadFirstNextSet) + ctx := context.Background() + + nextRow, err := r.nextSet.NextRow(ctx) + + if err != nil { + if errors.Is(err, io.EOF) { + return err + } + return badconn.Map(xerrors.WithStackTrace(err)) + } + + if err = nextRow.Scan(dst); err != nil { + return badconn.Map(xerrors.WithStackTrace(err)) + } + + return nil +} + +func (r *rows) Close() error { + ctx := context.Background() + return r.result.Close(ctx) +} + +type single struct { + values []sql.NamedArg + readAll bool +} + +func (r *single) Columns() (columns []string) { + for i := range r.values { + columns = append(columns, r.values[i].Name) + } + + return columns +} + +func (r *single) Close() error { + return nil +} + +func (r *single) Next(dst []driver.Value) error { + if r.values == nil || r.readAll { + return io.EOF + } + for i := range r.values { + dst[i] = r.values[i].Value + } + r.readAll = true + + return nil +} From ff26c0b0d35abedf6f04ee8c1be4c77faf951125 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 15 Nov 2024 23:00:43 +0300 Subject: [PATCH 08/48] feat(internal/query/conn): stmts --- internal/query/conn/stmt.go | 82 +++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 internal/query/conn/stmt.go diff --git a/internal/query/conn/stmt.go b/internal/query/conn/stmt.go new file mode 100644 index 000000000..5ca5b988b --- /dev/null +++ b/internal/query/conn/stmt.go @@ -0,0 +1,82 @@ +package conn + +import ( + "context" + "database/sql/driver" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/trace" +) + +type stmt struct { + conn *Conn + processor interface { + driver.ExecerContext + driver.QueryerContext + } + query string + ctx context.Context //nolint:containedctx +} + +var ( + _ driver.Stmt = &stmt{} + _ driver.StmtQueryContext = &stmt{} + _ driver.StmtExecContext = &stmt{} +) + +func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ driver.Rows, finalErr error) { + onDone := trace.DatabaseSQLOnStmtQuery(stmt.conn.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*stmt).QueryContext"), + stmt.ctx, stmt.query, + ) + defer func() { + onDone(finalErr) + }() + if !stmt.conn.isReady() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + return stmt.processor.QueryContext(ctx, stmt.query, args) +} + +func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ driver.Result, finalErr error) { + onDone := trace.DatabaseSQLOnStmtExec(stmt.conn.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*stmt).ExecContext"), + stmt.ctx, stmt.query, + ) + defer func() { + onDone(finalErr) + }() + if !stmt.conn.isReady() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + return stmt.processor.ExecContext(ctx, stmt.query, args) +} + +func (stmt *stmt) NumInput() int { + return -1 +} + +func (stmt *stmt) Close() (finalErr error) { + var ( + ctx = stmt.ctx + onDone = trace.DatabaseSQLOnStmtClose(stmt.conn.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*stmt).Close"), + ) + ) + defer func() { + onDone(finalErr) + }() + + return nil +} + +func (stmt *stmt) Exec([]driver.Value) (driver.Result, error) { + return nil, errDeprecated +} + +func (stmt *stmt) Query([]driver.Value) (driver.Rows, error) { + return nil, errDeprecated +} From 29d44ebbb09b60b9ebc4b12e901070f201053476 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 15 Nov 2024 23:01:04 +0300 Subject: [PATCH 09/48] feat(internal/query/conn/tx): ExecContext, PrepareContext impls --- internal/query/conn/tx.go | 44 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/internal/query/conn/tx.go b/internal/query/conn/tx.go index 99e0f4d4c..f598d5876 100644 --- a/internal/query/conn/tx.go +++ b/internal/query/conn/tx.go @@ -36,6 +36,10 @@ func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (currentT return nil, xerrors.WithStackTrace(err) } + if txc == nil { + return nil, nil + } + nativeTx, err := c.session.Begin(ctx, query.TxSettings(txc)) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) @@ -145,9 +149,45 @@ func (tx *transaction) QueryContext(ctx context.Context, query string, args []dr func (tx *transaction) ExecContext(ctx context.Context, query string, args []driver.NamedValue) ( _ driver.Result, finalErr error, ) { - panic("not implemented") + onDone := trace.DatabaseSQLOnTxExec(tx.conn.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*transaction).ExecContext"), + tx.ctx, tx, query, + ) + defer func() { + onDone(finalErr) + }() + + query, parameters, err := tx.conn.normalize(query, args...) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + err = tx.tx.Exec(ctx, + query, options.WithParameters(¶meters), + ) + + if err != nil { + return nil, badconn.Map(xerrors.WithStackTrace(err)) + } + + return resultNoRows{}, nil } func (tx *transaction) PrepareContext(ctx context.Context, query string) (_ driver.Stmt, finalErr error) { - panic("not implemented") + onDone := trace.DatabaseSQLOnTxPrepare(tx.conn.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*transaction).PrepareContext"), + tx.ctx, tx, query, + ) + defer func() { + onDone(finalErr) + }() + if !tx.conn.isReady() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + return &stmt{ + conn: tx.conn, + processor: tx, + ctx: ctx, + query: query, + }, nil } From 2d20df58df8d87b901d1c4fda61306c44e262a9c Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 15 Nov 2024 23:10:08 +0300 Subject: [PATCH 10/48] feat(internal/query/conn): PrepareContext impl --- internal/query/conn/driver.impls.go | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/internal/query/conn/driver.impls.go b/internal/query/conn/driver.impls.go index db76988a6..3fd0ddde2 100644 --- a/internal/query/conn/driver.impls.go +++ b/internal/query/conn/driver.impls.go @@ -32,8 +32,7 @@ func (c *Conn) IsValid() bool { } func (c *Conn) CheckNamedValue(value *driver.NamedValue) error { - //TODO implement me - panic("implement me") + return nil } func (c *Conn) Ping(ctx context.Context) (finalErr error) { @@ -56,9 +55,29 @@ func (c *Conn) Ping(ctx context.Context) (finalErr error) { return err } -func (c *Conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { - //TODO implement me - panic("implement me") +func (c *Conn) PrepareContext(ctx context.Context, query string) (_ driver.Stmt, finalErr error) { + if c.currentTx != nil { + return c.currentTx.PrepareContext(ctx, query) + } + + onDone := trace.DatabaseSQLOnConnPrepare(c.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).PrepareContext"), + query, + ) + defer func() { + onDone(finalErr) + }() + + if !c.isReady() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + return &stmt{ + conn: c, + processor: c, + ctx: ctx, + query: query, + }, nil } func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (driver.Tx, error) { From e750be4d8801a4ac6f60e442b58fc902a40cb2e3 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 17 Nov 2024 17:07:51 +0300 Subject: [PATCH 11/48] fix(sql): xsql renamed --- sql.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sql.go b/sql.go index 451aef452..322f2fdc0 100644 --- a/sql.go +++ b/sql.go @@ -163,10 +163,9 @@ func Connector(parent *Driver, opts ...ConnectorOption) (SQLConnector, error) { parent.databaseSQLOptions, opts..., ), - xsql.WithOnClose(d.detach), - xsql.WithTraceRetry(parent.config.TraceRetry()), - xsql.WithRetryBudget(parent.config.RetryBudget()), - xsql.OverQueryService(), + connector.WithOnClose(d.detach), + connector.WithTraceRetry(parent.config.TraceRetry()), + connector.WithRetryBudget(parent.config.RetryBudget()), )..., ) if err != nil { From f756a76ea608c8a7d84d946d9d52f0fd0bf8eaab Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 17 Nov 2024 17:11:08 +0300 Subject: [PATCH 12/48] fix(internal/query/conn): currentTx interface --- internal/query/conn/conn.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index 8f87a8896..99e3a3ef4 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -31,8 +31,7 @@ var ( _ driver.Result = resultNoRows{} ) -type ( - Parent interface { +type Parent interface { Query() *query.Client Trace() *trace.DatabaseSQL TraceRetry() *trace.Retry @@ -41,15 +40,16 @@ type ( Clock() clockwork.Clock } - currentTx interface { +type currentTx interface { tx.Identifier driver.Tx driver.ExecerContext driver.QueryerContext + driver.ConnPrepareContext Rollback() error } - Conn struct { +type Conn struct { currentTx ctx context.Context //nolint:containedctx parent Parent @@ -58,7 +58,6 @@ type ( closed atomic.Bool lastUsage atomic.Int64 } -) func New(ctx context.Context, parent Parent, s *query.Session, opts ...Option) *Conn { cc := &Conn{ @@ -129,10 +128,9 @@ func (c *Conn) execContext( return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } - // TODO tx - // if c.currentTx != nil { - // return c.currentTx.ExecContext(ctx, query, args) - // } + if c.currentTx != nil { + return c.currentTx.ExecContext(ctx, query, args) + } onDone := trace.DatabaseSQLOnConnExec(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).execContext"), From c1d27acf393df69fc69f74ff9d27ec1826c6b3aa Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 17 Nov 2024 17:13:32 +0300 Subject: [PATCH 13/48] fix(internal/query): xsql rm --- internal/query/xsql/conn.go | 120 ---------------------------------- internal/query/xsql/errors.go | 9 --- 2 files changed, 129 deletions(-) delete mode 100644 internal/query/xsql/conn.go delete mode 100644 internal/query/xsql/errors.go diff --git a/internal/query/xsql/conn.go b/internal/query/xsql/conn.go deleted file mode 100644 index eabdb8f8d..000000000 --- a/internal/query/xsql/conn.go +++ /dev/null @@ -1,120 +0,0 @@ -package xsql - -import ( - "context" - "database/sql/driver" - "sync/atomic" - - "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" - internalxsql "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql" - "github.com/ydb-platform/ydb-go-sdk/v3/query" - "github.com/ydb-platform/ydb-go-sdk/v3/table/options" - "github.com/ydb-platform/ydb-go-sdk/v3/trace" -) - -type connOption func(*conn) - -type currentTx interface { - tx.Identifier - driver.Tx - driver.ExecerContext - driver.QueryerContext - driver.ConnPrepareContext -} - -type beginTxFunc func(ctx context.Context, txOptions driver.TxOptions) (currentTx, error) - -type conn struct { - ctx context.Context - - connector *internalxsql.Connector - trace *trace.DatabaseSQL - session query.ClosableSession - - beginTxFuncs map[internalxsql.QueryMode]beginTxFunc - - closed atomic.Bool - lastUsage atomic.Int64 - defaultQueryMode internalxsql.QueryMode - - defaultTxControl *query.TransactionControl - dataOpts []options.ExecuteDataQueryOption - - scanOpts []options.ExecuteScanQueryOption - - currentTx currentTx -} - -var ( - _ driver.Conn = &conn{} - _ driver.ConnPrepareContext = &conn{} - _ driver.ConnBeginTx = &conn{} - _ driver.ExecerContext = &conn{} - _ driver.QueryerContext = &conn{} - _ driver.Pinger = &conn{} - _ driver.Validator = &conn{} - _ driver.NamedValueChecker = &conn{} -) - -type resultNoRows struct{} - -func (resultNoRows) LastInsertId() (int64, error) { return 0, ErrUnsupported } -func (resultNoRows) RowsAffected() (int64, error) { return 0, ErrUnsupported } - -var ( - _ driver.Result = resultNoRows{} -) - -func newConn(ctx context.Context, c *internalxsql.Connector, opts ...connOption) *conn { - panic("unimplemented") -} - -// CheckNamedValue implements driver.NamedValueChecker. -func (c *conn) CheckNamedValue(*driver.NamedValue) error { - panic("unimplemented") -} - -// IsValid implements driver.Validator. -func (c *conn) IsValid() bool { - panic("unimplemented") -} - -// Ping implements driver.Pinger. -func (c *conn) Ping(ctx context.Context) error { - panic("unimplemented") -} - -// QueryContext implements driver.QueryerContext. -func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { - panic("unimplemented") -} - -// ExecContext implements driver.ExecerContext. -func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { - panic("unimplemented") -} - -// BeginTx implements driver.ConnBeginTx. -func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { - panic("unimplemented") -} - -// PrepareContext implements driver.ConnPrepareContext. -func (c *conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { - panic("unimplemented") -} - -// Begin implements driver.Conn. -func (c *conn) Begin() (driver.Tx, error) { - panic("unimplemented") -} - -// Close implements driver.Conn. -func (c *conn) Close() error { - panic("unimplemented") -} - -// Prepare implements driver.Conn. -func (c *conn) Prepare(query string) (driver.Stmt, error) { - panic("unimplemented") -} diff --git a/internal/query/xsql/errors.go b/internal/query/xsql/errors.go deleted file mode 100644 index a86889761..000000000 --- a/internal/query/xsql/errors.go +++ /dev/null @@ -1,9 +0,0 @@ -package xsql - -import ( - "database/sql/driver" -) - -var ( - ErrUnsupported = driver.ErrSkip -) From ed723c4d8f88e93a5be263a92522f63b09e1db5e Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 17 Nov 2024 17:29:47 +0300 Subject: [PATCH 14/48] feat(internal/query/conn): QueryContext impl --- internal/query/conn/conn.go | 82 +++++++++++++++++++++-------- internal/query/conn/driver.impls.go | 17 +++--- 2 files changed, 72 insertions(+), 27 deletions(-) diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index 99e3a3ef4..ca5d38fa1 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -32,32 +32,32 @@ var ( ) type Parent interface { - Query() *query.Client - Trace() *trace.DatabaseSQL - TraceRetry() *trace.Retry - RetryBudget() budget.Budget - Bindings() bind.Bindings - Clock() clockwork.Clock - } + Query() *query.Client + Trace() *trace.DatabaseSQL + TraceRetry() *trace.Retry + RetryBudget() budget.Budget + Bindings() bind.Bindings + Clock() clockwork.Clock +} type currentTx interface { - tx.Identifier - driver.Tx - driver.ExecerContext - driver.QueryerContext + tx.Identifier + driver.Tx + driver.ExecerContext + driver.QueryerContext driver.ConnPrepareContext - Rollback() error - } + Rollback() error +} type Conn struct { - currentTx - ctx context.Context //nolint:containedctx - parent Parent - session *query.Session - onClose []func() - closed atomic.Bool - lastUsage atomic.Int64 - } + currentTx + ctx context.Context //nolint:containedctx + parent Parent + session *query.Session + onClose []func() + closed atomic.Bool + lastUsage atomic.Int64 +} func New(ctx context.Context, parent Parent, s *query.Session, opts ...Option) *Conn { cc := &Conn{ @@ -153,3 +153,43 @@ func (c *Conn) execContext( return resultNoRows{}, nil } + +func (c *Conn) queryContext(ctx context.Context, query string, args []driver.NamedValue) ( + _ driver.Rows, finalErr error, +) { + defer func() { + c.lastUsage.Store(c.parent.Clock().Now().Unix()) + }() + + if !c.isReady() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + if c.currentTx != nil { + return c.currentTx.QueryContext(ctx, query, args) + } + + var onDone = trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).queryContext"), + query, tableConn.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), + ) + + defer func() { + onDone(finalErr) + }() + + normalizedQuery, parameters, err := c.normalize(query, args...) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + res, err := c.session.Query(ctx, normalizedQuery, options.WithParameters(¶meters)) + if err != nil { + return nil, badconn.Map(xerrors.WithStackTrace(err)) + } + + return &rows{ + conn: c, + result: res, + }, nil +} diff --git a/internal/query/conn/driver.impls.go b/internal/query/conn/driver.impls.go index 3fd0ddde2..dab962920 100644 --- a/internal/query/conn/driver.impls.go +++ b/internal/query/conn/driver.impls.go @@ -94,17 +94,22 @@ func (c *Conn) ExecContext(ctx context.Context, query string, args []driver.Name return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } - // TODO TX - // if c.currentTx != nil { - // return c.currentTx.ExecContext(ctx, query, args) - // } + if c.currentTx != nil { + return c.currentTx.ExecContext(ctx, query, args) + } return c.execContext(ctx, query, args) } func (c *Conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { - //TODO implement me - panic("implement me") + if !c.isReady() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + if c.currentTx != nil { + return c.currentTx.QueryContext(ctx, query, args) + } + + return c.queryContext(ctx, query, args) } func (c *Conn) Prepare(query string) (driver.Stmt, error) { From 10c3bd4e4ee5bf3fabfa2be13f5da0c268c860f0 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 17 Nov 2024 17:36:05 +0300 Subject: [PATCH 15/48] chore(internal/query/conn): linted --- internal/query/conn/conn.go | 7 ++----- internal/query/conn/driver.impls.go | 6 +++--- internal/query/conn/rows.go | 1 - internal/query/conn/tx.go | 1 - 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index ca5d38fa1..b6bce8451 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -27,9 +27,7 @@ type resultNoRows struct{} func (resultNoRows) LastInsertId() (int64, error) { return 0, ErrUnsupported } func (resultNoRows) RowsAffected() (int64, error) { return 0, ErrUnsupported } -var ( - _ driver.Result = resultNoRows{} -) +var _ driver.Result = resultNoRows{} type Parent interface { Query() *query.Client @@ -141,7 +139,6 @@ func (c *Conn) execContext( }() normalizedQuery, params, err := c.normalize(query, args...) - if err != nil { return nil, xerrors.WithStackTrace(err) } @@ -169,7 +166,7 @@ func (c *Conn) queryContext(ctx context.Context, query string, args []driver.Nam return c.currentTx.QueryContext(ctx, query, args) } - var onDone = trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, + onDone := trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).queryContext"), query, tableConn.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), ) diff --git a/internal/query/conn/driver.impls.go b/internal/query/conn/driver.impls.go index dab962920..2d9998007 100644 --- a/internal/query/conn/driver.impls.go +++ b/internal/query/conn/driver.impls.go @@ -113,7 +113,7 @@ func (c *Conn) QueryContext(ctx context.Context, query string, args []driver.Nam } func (c *Conn) Prepare(query string) (driver.Stmt, error) { - //TODO implement me + // TODO implement me panic("implement me") } @@ -150,11 +150,11 @@ func (c *Conn) Close() (finalErr error) { } func (c *Conn) Begin() (driver.Tx, error) { - //TODO implement me + // TODO implement me panic("implement me") } func (c *Conn) LastUsage() time.Time { - //TODO implement me + // TODO implement me panic("implement me") } diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index 06d040273..2195fca83 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -89,7 +89,6 @@ func (r *rows) Next(dst []driver.Value) error { ctx := context.Background() nextRow, err := r.nextSet.NextRow(ctx) - if err != nil { if errors.Is(err, io.EOF) { return err diff --git a/internal/query/conn/tx.go b/internal/query/conn/tx.go index f598d5876..4a16f261c 100644 --- a/internal/query/conn/tx.go +++ b/internal/query/conn/tx.go @@ -164,7 +164,6 @@ func (tx *transaction) ExecContext(ctx context.Context, query string, args []dri err = tx.tx.Exec(ctx, query, options.WithParameters(¶meters), ) - if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } From 28cd1982efcfab6add2bb408584913c90883e443 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 17 Nov 2024 17:37:44 +0300 Subject: [PATCH 16/48] feat(internal/query/conn): remained impls --- internal/query/conn/driver.impls.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/internal/query/conn/driver.impls.go b/internal/query/conn/driver.impls.go index 2d9998007..4381a146b 100644 --- a/internal/query/conn/driver.impls.go +++ b/internal/query/conn/driver.impls.go @@ -113,8 +113,7 @@ func (c *Conn) QueryContext(ctx context.Context, query string, args []driver.Nam } func (c *Conn) Prepare(query string) (driver.Stmt, error) { - // TODO implement me - panic("implement me") + return nil, errDeprecated } func (c *Conn) Close() (finalErr error) { @@ -150,11 +149,9 @@ func (c *Conn) Close() (finalErr error) { } func (c *Conn) Begin() (driver.Tx, error) { - // TODO implement me - panic("implement me") + return nil, errDeprecated } func (c *Conn) LastUsage() time.Time { - // TODO implement me - panic("implement me") + return time.Unix(c.lastUsage.Load(), 0) } From fc8993562b060c259e752336a099538aeeec845e Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 17 Nov 2024 17:46:39 +0300 Subject: [PATCH 17/48] chore(internal/query/conn): linted --- internal/query/conn/conn.go | 3 --- internal/query/conn/driver.impls.go | 1 + internal/query/conn/rows.go | 17 +++++++++++------ internal/query/conn/stmt.go | 1 + 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index b6bce8451..dfe5bc21e 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -100,9 +100,6 @@ func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx curr ) } - // TODO: fake tx - /* tx, err := beginFakeTx(...) */ - tx, err := beginTx(ctx, c, txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) diff --git a/internal/query/conn/driver.impls.go b/internal/query/conn/driver.impls.go index 4381a146b..613d5170b 100644 --- a/internal/query/conn/driver.impls.go +++ b/internal/query/conn/driver.impls.go @@ -52,6 +52,7 @@ func (c *Conn) Ping(ctx context.Context) (finalErr error) { } err := c.session.Exec(ctx, "select 1") + return err } diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index 2195fca83..4cee54b60 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -14,12 +14,11 @@ import ( ) var ( - _ driver.Rows = &rows{} - _ driver.RowsNextResultSet = &rows{} - _ driver.RowsColumnTypeDatabaseTypeName = &rows{} - _ driver.RowsColumnTypeNullable = &rows{} - _ driver.Rows = &single{} - ignoreColumnPrefixName = "__discard_column_" + _ driver.Rows = &rows{} + _ driver.RowsNextResultSet = &rows{} + _ driver.RowsColumnTypeDatabaseTypeName = &rows{} + _ driver.RowsColumnTypeNullable = &rows{} + _ driver.Rows = &single{} ) type rows struct { @@ -46,6 +45,7 @@ func (r *rows) Columns() []string { if r.nextErr != nil { panic(r.nextErr) } + return r.nextSet.Columns() } @@ -54,6 +54,7 @@ func (r *rows) ColumnTypeDatabaseTypeName(index int) string { if r.nextErr != nil { panic(r.nextErr) } + return r.nextSet.ColumnTypes()[index].String() } @@ -63,6 +64,7 @@ func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) { panic(r.nextErr) } _, castResult := r.nextSet.ColumnTypes()[index].(interface{ IsOptional() }) + return castResult, castResult } @@ -77,6 +79,7 @@ func (r *rows) NextResultSet() (finalErr error) { } r.nextSet = res + return err } @@ -93,6 +96,7 @@ func (r *rows) Next(dst []driver.Value) error { if errors.Is(err, io.EOF) { return err } + return badconn.Map(xerrors.WithStackTrace(err)) } @@ -105,6 +109,7 @@ func (r *rows) Next(dst []driver.Value) error { func (r *rows) Close() error { ctx := context.Background() + return r.result.Close(ctx) } diff --git a/internal/query/conn/stmt.go b/internal/query/conn/stmt.go index 5ca5b988b..5d43952e1 100644 --- a/internal/query/conn/stmt.go +++ b/internal/query/conn/stmt.go @@ -52,6 +52,7 @@ func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ if !stmt.conn.isReady() { return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } + return stmt.processor.ExecContext(ctx, stmt.query, args) } From f479b3e1429ba2a2ab3909064a8d3d4925348d71 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Tue, 19 Nov 2024 12:19:14 +0300 Subject: [PATCH 18/48] added YDB_DATABASE_SQL_OVER_QUERY_SERVICE env for run database/sql over query-service + fix rows.Scan --- internal/connector/connector.go | 13 ++++++++++--- internal/query/conn/rows.go | 5 ++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/internal/connector/connector.go b/internal/connector/connector.go index 72c25a039..44475b95f 100644 --- a/internal/connector/connector.go +++ b/internal/connector/connector.go @@ -4,6 +4,7 @@ import ( "context" "database/sql/driver" "io" + "os" "time" "github.com/google/uuid" @@ -184,9 +185,15 @@ func (c *Connector) Close() error { func Open(parent ydbDriver, balancer grpc.ClientConnInterface, opts ...Option) (_ *Connector, err error) { c := &Connector{ - parent: parent, - balancer: balancer, - queryProcessor: TABLE_SERVICE, + parent: parent, + balancer: balancer, + queryProcessor: func() queryProcessor { + if v, has := os.LookupEnv("YDB_DATABASE_SQL_OVER_QUERY_SERVICE"); has && v != "" { + return QUERY_SERVICE + } + + return TABLE_SERVICE + }(), clock: clockwork.NewRealClock(), done: make(chan struct{}), trace: &trace.DatabaseSQL{}, diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index 4cee54b60..6b91bc8a9 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -5,6 +5,7 @@ import ( "database/sql" "database/sql/driver" "errors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xslices" "io" "sync" @@ -100,7 +101,9 @@ func (r *rows) Next(dst []driver.Value) error { return badconn.Map(xerrors.WithStackTrace(err)) } - if err = nextRow.Scan(dst); err != nil { + if err = nextRow.Scan(xslices.Transform(dst, func(v driver.Value) any { + return &v + })...); err != nil { return badconn.Map(xerrors.WithStackTrace(err)) } From 1370a720c4b0f2bdd014aad922f1cf31d577df8f Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 19 Nov 2024 14:04:51 +0300 Subject: [PATCH 19/48] chore(internal/query/conn/rows): linted --- internal/query/conn/rows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index 6b91bc8a9..3d180ba2c 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -5,13 +5,13 @@ import ( "database/sql" "database/sql/driver" "errors" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xslices" "io" "sync" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/result" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xslices" ) var ( From f976dd6db000e073fa851c6a5aba2896bee975bd Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 19 Nov 2024 14:44:33 +0300 Subject: [PATCH 20/48] fix(internal/query/conn/tx): nil txc rm --- internal/query/conn/tx.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/internal/query/conn/tx.go b/internal/query/conn/tx.go index 4a16f261c..ffa2aab11 100644 --- a/internal/query/conn/tx.go +++ b/internal/query/conn/tx.go @@ -36,10 +36,6 @@ func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (currentT return nil, xerrors.WithStackTrace(err) } - if txc == nil { - return nil, nil - } - nativeTx, err := c.session.Begin(ctx, query.TxSettings(txc)) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) From 6ad28a9ab800d863eb35b8d9b413c0a421720869 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 19 Nov 2024 15:28:00 +0300 Subject: [PATCH 21/48] fix(internal/query/conn/rows/Next): correct dst pointers array --- internal/query/conn/rows.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index 3d180ba2c..c4fa3eecd 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -11,7 +11,6 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/result" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xslices" ) var ( @@ -101,9 +100,12 @@ func (r *rows) Next(dst []driver.Value) error { return badconn.Map(xerrors.WithStackTrace(err)) } - if err = nextRow.Scan(xslices.Transform(dst, func(v driver.Value) any { - return &v - })...); err != nil { + ptrs := make([]any, len(dst)) + for i := range dst { + ptrs[i] = &dst[i] + } + + if err = nextRow.Scan(ptrs...); err != nil { return badconn.Map(xerrors.WithStackTrace(err)) } From 380baacf27c0ce6e89bfea8f97fb6c655e48eccb Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 19 Nov 2024 22:53:58 +0300 Subject: [PATCH 22/48] fix(internal/query/conn/rows): nextResultSets check & columns cache --- internal/query/conn/rows.go | 49 ++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index c4fa3eecd..a84e55961 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -10,6 +10,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/result" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/types" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) @@ -28,6 +29,10 @@ type rows struct { firstNextSet sync.Once nextSet result.Set nextErr error + + columnsFetchError error + columns []string + columnsType []types.Type } func (r *rows) LastInsertId() (int64, error) { return 0, ErrUnsupported } @@ -42,26 +47,26 @@ func (r *rows) loadFirstNextSet() { func (r *rows) Columns() []string { r.firstNextSet.Do(r.loadFirstNextSet) - if r.nextErr != nil { - panic(r.nextErr) + if r.columnsFetchError != nil { + panic(badconn.Map(xerrors.WithStackTrace(r.columnsFetchError))) } - return r.nextSet.Columns() + return r.columns } func (r *rows) ColumnTypeDatabaseTypeName(index int) string { r.firstNextSet.Do(r.loadFirstNextSet) - if r.nextErr != nil { - panic(r.nextErr) + if r.columnsFetchError != nil { + panic(badconn.Map(xerrors.WithStackTrace(r.columnsFetchError))) } - return r.nextSet.ColumnTypes()[index].String() + return r.columnsType[index].String() } func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) { r.firstNextSet.Do(r.loadFirstNextSet) - if r.nextErr != nil { - panic(r.nextErr) + if r.columnsFetchError != nil { + panic(badconn.Map(xerrors.WithStackTrace(r.columnsFetchError))) } _, castResult := r.nextSet.ColumnTypes()[index].(interface{ IsOptional() }) @@ -71,26 +76,42 @@ func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) { func (r *rows) NextResultSet() (finalErr error) { r.firstNextSet.Do(r.loadFirstNextSet) + if errors.Is(r.nextErr, io.EOF) { + return r.nextErr + } + + if r.nextErr != nil { + return badconn.Map(xerrors.WithStackTrace(r.nextErr)) + } + + r.columns = r.nextSet.Columns() + r.columnsType = r.nextSet.ColumnTypes() + r.columnsFetchError = r.nextErr + ctx := context.Background() res, err := r.result.NextResultSet(ctx) r.nextErr = err - if err != nil { - return err - } - r.nextSet = res - return err + return nil } func (r *rows) HasNextResultSet() bool { - return r.nextSet != nil + return r.nextErr == nil } func (r *rows) Next(dst []driver.Value) error { r.firstNextSet.Do(r.loadFirstNextSet) ctx := context.Background() + if errors.Is(r.nextErr, io.EOF) { + return r.nextErr + } + + if r.nextErr != nil { + return badconn.Map(xerrors.WithStackTrace(r.nextErr)) + } + nextRow, err := r.nextSet.NextRow(ctx) if err != nil { if errors.Is(err, io.EOF) { From a0cc5a0cbe19de6e6a21f90beee2b59729ea2222 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 19 Nov 2024 22:54:45 +0300 Subject: [PATCH 23/48] refactor(internal/table/context): public QueryModeFromContext --- internal/table/conn/conn.go | 6 +++--- internal/table/conn/context.go | 4 ++-- internal/table/conn/stmt.go | 4 ++-- internal/table/conn/tx.go | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/table/conn/conn.go b/internal/table/conn/conn.go index 3d1e96853..3028791ca 100644 --- a/internal/table/conn/conn.go +++ b/internal/table/conn/conn.go @@ -162,7 +162,7 @@ func (c *Conn) execContext( return c.currentTx.ExecContext(ctx, query, args) } - m := queryModeFromContext(ctx, c.defaultQueryMode) + m := QueryModeFromContext(ctx, c.defaultQueryMode) onDone := trace.DatabaseSQLOnConnExec(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).execContext"), query, m.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), @@ -285,7 +285,7 @@ func (c *Conn) queryContext(ctx context.Context, query string, args []driver.Nam } var ( - queryMode = queryModeFromContext(ctx, c.defaultQueryMode) + queryMode = QueryModeFromContext(ctx, c.defaultQueryMode) onDone = trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).queryContext"), query, queryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), @@ -462,7 +462,7 @@ func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx curr ) } - m := queryModeFromContext(ctx, c.defaultQueryMode) + m := QueryModeFromContext(ctx, c.defaultQueryMode) if slices.Contains(c.fakeTxModes, m) { return beginTxFake(ctx, c), nil diff --git a/internal/table/conn/context.go b/internal/table/conn/context.go index 2526a330c..2fa479d72 100644 --- a/internal/table/conn/context.go +++ b/internal/table/conn/context.go @@ -26,8 +26,8 @@ func WithQueryMode(ctx context.Context, m QueryMode) context.Context { return context.WithValue(ctx, ctxModeTypeKey{}, m) } -// queryModeFromContext returns defined QueryMode or DefaultQueryMode -func queryModeFromContext(ctx context.Context, defaultQueryMode QueryMode) QueryMode { +// QueryModeFromContext returns defined QueryMode or DefaultQueryMode +func QueryModeFromContext(ctx context.Context, defaultQueryMode QueryMode) QueryMode { if m, ok := ctx.Value(ctxModeTypeKey{}).(QueryMode); ok { return m } diff --git a/internal/table/conn/stmt.go b/internal/table/conn/stmt.go index 34075ea82..d7ae8235f 100644 --- a/internal/table/conn/stmt.go +++ b/internal/table/conn/stmt.go @@ -38,7 +38,7 @@ func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ if !stmt.conn.isReady() { return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } - switch m := queryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { + switch m := QueryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { case DataQueryMode: return stmt.processor.QueryContext(stmt.conn.withKeepInCache(ctx), stmt.query, args) default: @@ -57,7 +57,7 @@ func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ if !stmt.conn.isReady() { return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } - switch m := queryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { + switch m := QueryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { case DataQueryMode: return stmt.processor.ExecContext(stmt.conn.withKeepInCache(ctx), stmt.query, args) default: diff --git a/internal/table/conn/tx.go b/internal/table/conn/tx.go index d879be18e..f4a9da7cb 100644 --- a/internal/table/conn/tx.go +++ b/internal/table/conn/tx.go @@ -121,7 +121,7 @@ func (tx *transaction) QueryContext(ctx context.Context, query string, args []dr defer func() { onDone(finalErr) }() - m := queryModeFromContext(ctx, tx.conn.defaultQueryMode) + m := QueryModeFromContext(ctx, tx.conn.defaultQueryMode) if m != DataQueryMode { return nil, badconn.Map( xerrors.WithStackTrace( @@ -163,7 +163,7 @@ func (tx *transaction) ExecContext(ctx context.Context, query string, args []dri defer func() { onDone(finalErr) }() - m := queryModeFromContext(ctx, tx.conn.defaultQueryMode) + m := QueryModeFromContext(ctx, tx.conn.defaultQueryMode) if m != DataQueryMode { return nil, badconn.Map( xerrors.WithStackTrace( From b292289a343a90f37ae0ee2836bef72e688f5789 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 19 Nov 2024 22:55:19 +0300 Subject: [PATCH 24/48] feat(internal/query/conn): explain mode support --- internal/query/conn/conn.go | 50 +++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index dfe5bc21e..e01a6dc34 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -2,6 +2,7 @@ package conn import ( "context" + "database/sql" "database/sql/driver" "sync/atomic" @@ -13,6 +14,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/session" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/stats" tableConn "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" @@ -148,7 +150,7 @@ func (c *Conn) execContext( return resultNoRows{}, nil } -func (c *Conn) queryContext(ctx context.Context, query string, args []driver.NamedValue) ( +func (c *Conn) queryContext(ctx context.Context, queryString string, args []driver.NamedValue) ( _ driver.Rows, finalErr error, ) { defer func() { @@ -160,24 +162,38 @@ func (c *Conn) queryContext(ctx context.Context, query string, args []driver.Nam } if c.currentTx != nil { - return c.currentTx.QueryContext(ctx, query, args) + return c.currentTx.QueryContext(ctx, queryString, args) } onDone := trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).queryContext"), - query, tableConn.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), + queryString, tableConn.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), ) defer func() { onDone(finalErr) }() - normalizedQuery, parameters, err := c.normalize(query, args...) + normalizedQuery, parameters, err := c.normalize(queryString, args...) if err != nil { return nil, xerrors.WithStackTrace(err) } - res, err := c.session.Query(ctx, normalizedQuery, options.WithParameters(¶meters)) + queryMode := tableConn.QueryModeFromContext(ctx, tableConn.UnknownQueryMode) + + if queryMode == tableConn.ExplainQueryMode { + return c.queryContextExplain(ctx, normalizedQuery, parameters) + } else { + return c.queryContextOther(ctx, normalizedQuery, parameters) + } +} + +func (c *Conn) queryContextOther(ctx context.Context, queryString string, parameters params.Parameters) (driver.Rows, error) { + res, err := c.session.Query( + ctx, queryString, + options.WithParameters(¶meters), + ) + if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } @@ -187,3 +203,27 @@ func (c *Conn) queryContext(ctx context.Context, query string, args []driver.Nam result: res, }, nil } + +func (c *Conn) queryContextExplain(ctx context.Context, queryString string, parameters params.Parameters) (driver.Rows, error) { + var ast, plan string + _, err := c.session.Query( + ctx, queryString, + options.WithParameters(¶meters), + options.WithExecMode(options.ExecModeExplain), + options.WithStatsMode(options.StatsModeNone, func(stats stats.QueryStats) { + ast = stats.QueryAST() + plan = stats.QueryPlan() + }), + ) + + if err != nil { + return nil, badconn.Map(xerrors.WithStackTrace(err)) + } + + return &single{ + values: []sql.NamedArg{ + sql.Named("AST", ast), + sql.Named("Plan", plan), + }, + }, nil +} From 8e5eaabffac332b9ca754dd90222d0d0778c3acd Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 19 Nov 2024 23:47:22 +0300 Subject: [PATCH 25/48] fix(internal/query/conn/rows): pure eof returning & NextResultSet fix --- internal/query/conn/rows.go | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index a84e55961..6df055cf0 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -43,6 +43,12 @@ func (r *rows) loadFirstNextSet() { res, err := r.result.NextResultSet(ctx) r.nextErr = err r.nextSet = res + + if err == nil { + r.columns = r.nextSet.Columns() + r.columnsType = r.nextSet.ColumnTypes() + r.columnsFetchError = r.nextErr + } } func (r *rows) Columns() []string { @@ -74,10 +80,15 @@ func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) { } func (r *rows) NextResultSet() (finalErr error) { - r.firstNextSet.Do(r.loadFirstNextSet) + r.firstNextSet.Do(func() {}) + + ctx := context.Background() + res, err := r.result.NextResultSet(ctx) + r.nextErr = err + r.nextSet = res if errors.Is(r.nextErr, io.EOF) { - return r.nextErr + return io.EOF } if r.nextErr != nil { @@ -88,15 +99,11 @@ func (r *rows) NextResultSet() (finalErr error) { r.columnsType = r.nextSet.ColumnTypes() r.columnsFetchError = r.nextErr - ctx := context.Background() - res, err := r.result.NextResultSet(ctx) - r.nextErr = err - r.nextSet = res - return nil } func (r *rows) HasNextResultSet() bool { + r.firstNextSet.Do(r.loadFirstNextSet) return r.nextErr == nil } @@ -104,18 +111,17 @@ func (r *rows) Next(dst []driver.Value) error { r.firstNextSet.Do(r.loadFirstNextSet) ctx := context.Background() - if errors.Is(r.nextErr, io.EOF) { - return r.nextErr - } - if r.nextErr != nil { + if errors.Is(r.nextErr, io.EOF) { + return io.EOF + } return badconn.Map(xerrors.WithStackTrace(r.nextErr)) } nextRow, err := r.nextSet.NextRow(ctx) if err != nil { if errors.Is(err, io.EOF) { - return err + return io.EOF } return badconn.Map(xerrors.WithStackTrace(err)) From 9f78824b0ea713d86deb9fa6ffecd37523aaf49d Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 19 Nov 2024 23:48:56 +0300 Subject: [PATCH 26/48] chore(internal/query/conn): linted --- internal/query/conn/conn.go | 18 ++++++++++++------ internal/query/conn/rows.go | 2 ++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index e01a6dc34..22627509c 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -183,17 +183,20 @@ func (c *Conn) queryContext(ctx context.Context, queryString string, args []driv if queryMode == tableConn.ExplainQueryMode { return c.queryContextExplain(ctx, normalizedQuery, parameters) - } else { - return c.queryContextOther(ctx, normalizedQuery, parameters) } + + return c.queryContextOther(ctx, normalizedQuery, parameters) } -func (c *Conn) queryContextOther(ctx context.Context, queryString string, parameters params.Parameters) (driver.Rows, error) { +func (c *Conn) queryContextOther( + ctx context.Context, + queryString string, + parameters params.Parameters, +) (driver.Rows, error) { res, err := c.session.Query( ctx, queryString, options.WithParameters(¶meters), ) - if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } @@ -204,7 +207,11 @@ func (c *Conn) queryContextOther(ctx context.Context, queryString string, parame }, nil } -func (c *Conn) queryContextExplain(ctx context.Context, queryString string, parameters params.Parameters) (driver.Rows, error) { +func (c *Conn) queryContextExplain( + ctx context.Context, + queryString string, + parameters params.Parameters, +) (driver.Rows, error) { var ast, plan string _, err := c.session.Query( ctx, queryString, @@ -215,7 +222,6 @@ func (c *Conn) queryContextExplain(ctx context.Context, queryString string, para plan = stats.QueryPlan() }), ) - if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index 6df055cf0..fc6531cbe 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -104,6 +104,7 @@ func (r *rows) NextResultSet() (finalErr error) { func (r *rows) HasNextResultSet() bool { r.firstNextSet.Do(r.loadFirstNextSet) + return r.nextErr == nil } @@ -115,6 +116,7 @@ func (r *rows) Next(dst []driver.Value) error { if errors.Is(r.nextErr, io.EOF) { return io.EOF } + return badconn.Map(xerrors.WithStackTrace(r.nextErr)) } From a9f83c17962bd08e6df24aad09cab83fe2e9ee39 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Wed, 20 Nov 2024 02:49:17 +0300 Subject: [PATCH 27/48] added YDB_DATABASE_SQL_OVER_QUERY_SERVICE env to experimental tests --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 13f05d176..3708ba47e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -133,6 +133,7 @@ jobs: YDB_CONNECTION_STRING_SECURE: grpcs://localhost:2135/local YDB_SSL_ROOT_CERTIFICATES_FILE: /tmp/ydb_certs/ca.pem YDB_SESSIONS_SHUTDOWN_URLS: http://localhost:8765/actors/kqp_proxy?force_shutdown=all + YDB_DATABASE_SQL_OVER_QUERY_SERVICE: 1 HIDE_APPLICATION_OUTPUT: 1 steps: - name: Checkout code From cc37fad2d7042e365e7b33be5cae0955049598db Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 20 Nov 2024 14:45:09 +0300 Subject: [PATCH 28/48] feat(internal/value): driver.Value force cast --- internal/value/cast.go | 19 ++++++++++++++++++- internal/value/value.go | 5 ++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/internal/value/cast.go b/internal/value/cast.go index 7106b62fd..66e5bf990 100644 --- a/internal/value/cast.go +++ b/internal/value/cast.go @@ -1,5 +1,11 @@ package value +import ( + "database/sql/driver" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" +) + func CastTo(v Value, dst interface{}) error { if dst == nil { return errNilDestination @@ -10,5 +16,16 @@ func CastTo(v Value, dst interface{}) error { return nil } - return v.castTo(dst) + err := v.castTo(dst) + + if err == nil { + return nil + } + + if ptr, has := dst.(*driver.Value); has { + *ptr = v + return nil + } + + return xerrors.WithStackTrace(err) } diff --git a/internal/value/value.go b/internal/value/value.go index f791caf83..b5abc12c6 100644 --- a/internal/value/value.go +++ b/internal/value/value.go @@ -2422,7 +2422,10 @@ func (v *variantValue) Value() Value { } func (v *variantValue) castTo(dst any) error { - return v.value.castTo(dst) + return xerrors.WithStackTrace(fmt.Errorf( + "%w '%s' to '%T' destination", + ErrCannotCast, v.Type().Yql(), dst, + )) } func (v *variantValue) Yql() string { From c7e7a045b59aa4779bc15f01ceab8ab5c3fba37e Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 20 Nov 2024 14:45:53 +0300 Subject: [PATCH 29/48] fix(internal/query): resultSetIndex overflow check --- internal/query/result.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/query/result.go b/internal/query/result.go index 315d71e27..ede423443 100644 --- a/internal/query/result.go +++ b/internal/query/result.go @@ -262,6 +262,9 @@ func (r *streamResult) nextResultSet(ctx context.Context) (_ *resultSet, err err } if part.GetResultSetIndex() < r.resultSetIndex { r.closeOnce() + if part.GetResultSetIndex() <= 0 && r.resultSetIndex > 0 { + return nil, xerrors.WithStackTrace(io.EOF) + } return nil, xerrors.WithStackTrace(fmt.Errorf( "next result set rowIndex %d less than last result set index %d: %w", From f4a2325de9d257ed0e3d15634697ee1d00ea1693 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Wed, 20 Nov 2024 15:41:48 +0300 Subject: [PATCH 30/48] Apply suggestions from code review --- internal/value/cast.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/internal/value/cast.go b/internal/value/cast.go index 66e5bf990..2ced5f21c 100644 --- a/internal/value/cast.go +++ b/internal/value/cast.go @@ -16,14 +16,13 @@ func CastTo(v Value, dst interface{}) error { return nil } - err := v.castTo(dst) - - if err == nil { + if err := v.castTo(dst); err == nil { return nil } if ptr, has := dst.(*driver.Value); has { *ptr = v + return nil } From dbac1d71a8c4c012e11a1b280e515f6b6377eb4d Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 21 Nov 2024 00:13:06 +0300 Subject: [PATCH 31/48] fix(internal/value): cast error joining --- internal/value/cast.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/value/cast.go b/internal/value/cast.go index 2ced5f21c..1da45a9f1 100644 --- a/internal/value/cast.go +++ b/internal/value/cast.go @@ -2,6 +2,7 @@ package value import ( "database/sql/driver" + "fmt" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) @@ -16,7 +17,9 @@ func CastTo(v Value, dst interface{}) error { return nil } - if err := v.castTo(dst); err == nil { + var err error + + if err = v.castTo(dst); err == nil { return nil } @@ -26,5 +29,10 @@ func CastTo(v Value, dst interface{}) error { return nil } - return xerrors.WithStackTrace(err) + return xerrors.WithStackTrace( + xerrors.Join( + err, + fmt.Errorf("cannot cast %T to driver.Value", dst), + ), + ) } From 2f1071ae9c05738eb861a0b1ec381b5085e0fa3d Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 21 Nov 2024 00:15:19 +0300 Subject: [PATCH 32/48] fix(internal/value/castTo): inner castTo calling revert --- internal/value/value.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/internal/value/value.go b/internal/value/value.go index b5abc12c6..f791caf83 100644 --- a/internal/value/value.go +++ b/internal/value/value.go @@ -2422,10 +2422,7 @@ func (v *variantValue) Value() Value { } func (v *variantValue) castTo(dst any) error { - return xerrors.WithStackTrace(fmt.Errorf( - "%w '%s' to '%T' destination", - ErrCannotCast, v.Type().Yql(), dst, - )) + return v.value.castTo(dst) } func (v *variantValue) Yql() string { From 410e804317da882b9f7e2bd305a057c33fd591c7 Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 21 Nov 2024 00:49:01 +0300 Subject: [PATCH 33/48] fix(internal/value/castTo): Value.CastTo error wrapping --- internal/value/cast.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/internal/value/cast.go b/internal/value/cast.go index 1da45a9f1..ab20bcdde 100644 --- a/internal/value/cast.go +++ b/internal/value/cast.go @@ -30,9 +30,6 @@ func CastTo(v Value, dst interface{}) error { } return xerrors.WithStackTrace( - xerrors.Join( - err, - fmt.Errorf("cannot cast %T to driver.Value", dst), - ), + fmt.Errorf("%w and cannot cast %T to driver.Value", err, dst), ) } From dc27c84b8f59b32de1fb1899db201d7271a6ff9f Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 24 Nov 2024 01:08:49 +0300 Subject: [PATCH 34/48] refactor: QueryModes & querymodes funtions transfered to xcontext --- dsn.go | 7 ++-- internal/query/conn/conn.go | 9 ++--- internal/table/conn/conn.go | 6 +-- internal/table/conn/context.go | 14 ------- internal/table/conn/mode.go | 55 ++++++-------------------- internal/table/conn/stmt.go | 5 ++- internal/table/conn/tx.go | 5 ++- internal/xcontext/query_modes.go | 68 ++++++++++++++++++++++++++++++++ sql.go | 3 +- 9 files changed, 99 insertions(+), 73 deletions(-) create mode 100644 internal/xcontext/query_modes.go diff --git a/dsn.go b/dsn.go index 054b84f71..ac48e7f3d 100644 --- a/dsn.go +++ b/dsn.go @@ -12,6 +12,7 @@ import ( "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/xcontext" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) @@ -60,13 +61,13 @@ func parseConnectionString(dataSourceName string) (opts []Option, _ error) { opts = append(opts, WithBalancer(balancers.FromConfig(balancer))) } if queryMode := info.Params.Get("go_query_mode"); queryMode != "" { - mode := tableSql.QueryModeFromString(queryMode) + mode := xcontext.QueryModeFromString(queryMode) if mode == tableSql.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } opts = append(opts, withConnectorOptions(connector.WithDefaultQueryMode(mode))) } else if queryMode := info.Params.Get("query_mode"); queryMode != "" { - mode := tableSql.QueryModeFromString(queryMode) + mode := xcontext.QueryModeFromString(queryMode) if mode == tableSql.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } @@ -74,7 +75,7 @@ func parseConnectionString(dataSourceName string) (opts []Option, _ error) { } if fakeTx := info.Params.Get("go_fake_tx"); fakeTx != "" { for _, queryMode := range strings.Split(fakeTx, ",") { - mode := tableSql.QueryModeFromString(queryMode) + mode := xcontext.QueryModeFromString(queryMode) if mode == tableSql.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index 22627509c..8671bda46 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -15,7 +15,6 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/session" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stats" - tableConn "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xcontext" @@ -131,7 +130,7 @@ func (c *Conn) execContext( onDone := trace.DatabaseSQLOnConnExec(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).execContext"), - query, tableConn.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), + query, xcontext.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), ) defer func() { onDone(finalErr) @@ -167,7 +166,7 @@ func (c *Conn) queryContext(ctx context.Context, queryString string, args []driv onDone := trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).queryContext"), - queryString, tableConn.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), + queryString, xcontext.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), ) defer func() { @@ -179,9 +178,9 @@ func (c *Conn) queryContext(ctx context.Context, queryString string, args []driv return nil, xerrors.WithStackTrace(err) } - queryMode := tableConn.QueryModeFromContext(ctx, tableConn.UnknownQueryMode) + queryMode := xcontext.QueryModeFromContext(ctx, xcontext.UnknownQueryMode) - if queryMode == tableConn.ExplainQueryMode { + if queryMode == xcontext.ExplainQueryMode { return c.queryContextExplain(ctx, normalizedQuery, parameters) } diff --git a/internal/table/conn/conn.go b/internal/table/conn/conn.go index 3028791ca..759245e69 100644 --- a/internal/table/conn/conn.go +++ b/internal/table/conn/conn.go @@ -162,7 +162,7 @@ func (c *Conn) execContext( return c.currentTx.ExecContext(ctx, query, args) } - m := QueryModeFromContext(ctx, c.defaultQueryMode) + m := xcontext.QueryModeFromContext(ctx, c.defaultQueryMode) onDone := trace.DatabaseSQLOnConnExec(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).execContext"), query, m.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), @@ -285,7 +285,7 @@ func (c *Conn) queryContext(ctx context.Context, query string, args []driver.Nam } var ( - queryMode = QueryModeFromContext(ctx, c.defaultQueryMode) + queryMode = xcontext.QueryModeFromContext(ctx, c.defaultQueryMode) onDone = trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).queryContext"), query, queryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), @@ -462,7 +462,7 @@ func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx curr ) } - m := QueryModeFromContext(ctx, c.defaultQueryMode) + m := xcontext.mContext(ctx, c.defaultQueryMode) if slices.Contains(c.fakeTxModes, m) { return beginTxFake(ctx, c), nil diff --git a/internal/table/conn/context.go b/internal/table/conn/context.go index 2fa479d72..339aa5a87 100644 --- a/internal/table/conn/context.go +++ b/internal/table/conn/context.go @@ -21,20 +21,6 @@ func WithTxControlHook(ctx context.Context, hook txControlHook) context.Context return context.WithValue(ctx, ctxTxControlHookKey{}, hook) } -// WithQueryMode returns a copy of context with given QueryMode -func WithQueryMode(ctx context.Context, m QueryMode) context.Context { - return context.WithValue(ctx, ctxModeTypeKey{}, m) -} - -// QueryModeFromContext returns defined QueryMode or DefaultQueryMode -func QueryModeFromContext(ctx context.Context, defaultQueryMode QueryMode) QueryMode { - if m, ok := ctx.Value(ctxModeTypeKey{}).(QueryMode); ok { - return m - } - - return defaultQueryMode -} - func WithTxControl(ctx context.Context, txc *table.TransactionControl) context.Context { return context.WithValue(ctx, ctxTransactionControlKey{}, txc) } diff --git a/internal/table/conn/mode.go b/internal/table/conn/mode.go index 5a877e073..34c3caf69 100644 --- a/internal/table/conn/mode.go +++ b/internal/table/conn/mode.go @@ -1,49 +1,18 @@ package conn -import "fmt" +import ( + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xcontext" +) -type QueryMode int +type QueryMode = xcontext.QueryMode const ( - UnknownQueryMode = QueryMode(iota) - DataQueryMode - ExplainQueryMode - ScanQueryMode - SchemeQueryMode - ScriptingQueryMode - - DefaultQueryMode = DataQueryMode -) - -var ( - typeToString = map[QueryMode]string{ - DataQueryMode: "data", - ScanQueryMode: "scan", - ExplainQueryMode: "explain", - SchemeQueryMode: "scheme", - ScriptingQueryMode: "scripting", - } - stringToType = map[string]QueryMode{ - "data": DataQueryMode, - "scan": ScanQueryMode, - "explain": ExplainQueryMode, - "scheme": SchemeQueryMode, - "scripting": ScriptingQueryMode, - } + UnknownQueryMode = xcontext.UnknownQueryMode + DataQueryMode = xcontext.DataQueryMode + ExplainQueryMode = xcontext.ExplainQueryMode + ScanQueryMode = xcontext.ScanQueryMode + SchemeQueryMode = xcontext.SchemeQueryMode + ScriptingQueryMode = xcontext.UnknownQueryMode + + DefaultQueryMode = xcontext.UnknownQueryMode ) - -func (t QueryMode) String() string { - if s, ok := typeToString[t]; ok { - return s - } - - return fmt.Sprintf("unknown_mode_%d", t) -} - -func QueryModeFromString(s string) QueryMode { - if t, ok := stringToType[s]; ok { - return t - } - - return UnknownQueryMode -} diff --git a/internal/table/conn/stmt.go b/internal/table/conn/stmt.go index d7ae8235f..566194f8d 100644 --- a/internal/table/conn/stmt.go +++ b/internal/table/conn/stmt.go @@ -7,6 +7,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "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/trace" ) @@ -38,7 +39,7 @@ func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ if !stmt.conn.isReady() { return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } - switch m := QueryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { + switch m := xcontext.QueryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { case DataQueryMode: return stmt.processor.QueryContext(stmt.conn.withKeepInCache(ctx), stmt.query, args) default: @@ -57,7 +58,7 @@ func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ if !stmt.conn.isReady() { return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } - switch m := QueryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { + switch m := xcontext.QueryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { case DataQueryMode: return stmt.processor.ExecContext(stmt.conn.withKeepInCache(ctx), stmt.query, args) default: diff --git a/internal/table/conn/tx.go b/internal/table/conn/tx.go index f4a9da7cb..aa776afe2 100644 --- a/internal/table/conn/tx.go +++ b/internal/table/conn/tx.go @@ -9,6 +9,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" + "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/table" "github.com/ydb-platform/ydb-go-sdk/v3/trace" @@ -121,7 +122,7 @@ func (tx *transaction) QueryContext(ctx context.Context, query string, args []dr defer func() { onDone(finalErr) }() - m := QueryModeFromContext(ctx, tx.conn.defaultQueryMode) + m := xcontext.QueryModeFromContext(ctx, tx.conn.defaultQueryMode) if m != DataQueryMode { return nil, badconn.Map( xerrors.WithStackTrace( @@ -163,7 +164,7 @@ func (tx *transaction) ExecContext(ctx context.Context, query string, args []dri defer func() { onDone(finalErr) }() - m := QueryModeFromContext(ctx, tx.conn.defaultQueryMode) + m := xcontext.QueryModeFromContext(ctx, tx.conn.defaultQueryMode) if m != DataQueryMode { return nil, badconn.Map( xerrors.WithStackTrace( diff --git a/internal/xcontext/query_modes.go b/internal/xcontext/query_modes.go new file mode 100644 index 000000000..1c32bb6bf --- /dev/null +++ b/internal/xcontext/query_modes.go @@ -0,0 +1,68 @@ +package xcontext + +import ( + "context" + "fmt" +) + +type QueryMode int + +type ctxModeTypeKey struct{} + +const ( + UnknownQueryMode = QueryMode(iota) + DataQueryMode + ExplainQueryMode + ScanQueryMode + SchemeQueryMode + ScriptingQueryMode + + DefaultQueryMode = DataQueryMode +) + +// QueryModeFromContext returns defined QueryMode or DefaultQueryMode +func QueryModeFromContext(ctx context.Context, defaultQueryMode QueryMode) QueryMode { + if m, ok := ctx.Value(ctxModeTypeKey{}).(QueryMode); ok { + return m + } + + return defaultQueryMode +} + +// WithQueryMode returns a copy of context with given QueryMode +func WithQueryMode(ctx context.Context, m QueryMode) context.Context { + return context.WithValue(ctx, ctxModeTypeKey{}, m) +} + +var ( + typeToString = map[QueryMode]string{ + DataQueryMode: "data", + ScanQueryMode: "scan", + ExplainQueryMode: "explain", + SchemeQueryMode: "scheme", + ScriptingQueryMode: "scripting", + } + stringToType = map[string]QueryMode{ + "data": DataQueryMode, + "scan": ScanQueryMode, + "explain": ExplainQueryMode, + "scheme": SchemeQueryMode, + "scripting": ScriptingQueryMode, + } +) + +func (t QueryMode) String() string { + if s, ok := typeToString[t]; ok { + return s + } + + return fmt.Sprintf("unknown_mode_%d", t) +} + +func QueryModeFromString(s string) QueryMode { + if t, ok := stringToType[s]; ok { + return t + } + + return UnknownQueryMode +} diff --git a/sql.go b/sql.go index 322f2fdc0..a7f7ff273 100644 --- a/sql.go +++ b/sql.go @@ -9,6 +9,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector" tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn" + "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/xsync" "github.com/ydb-platform/ydb-go-sdk/v3/table" @@ -89,7 +90,7 @@ const ( ) func WithQueryMode(ctx context.Context, mode QueryMode) context.Context { - return tableSql.WithQueryMode(ctx, mode) + return xcontext.WithQueryMode(ctx, mode) } func WithTxControl(ctx context.Context, txc *table.TransactionControl) context.Context { From 2ffc4906ed8d35b73d0a46b918e9a46f8e7a1443 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 24 Nov 2024 01:11:32 +0300 Subject: [PATCH 35/48] chore(internal/table/conn): linted --- internal/table/conn/conn.go | 2 +- internal/table/conn/context.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/table/conn/conn.go b/internal/table/conn/conn.go index 759245e69..b7ca21092 100644 --- a/internal/table/conn/conn.go +++ b/internal/table/conn/conn.go @@ -462,7 +462,7 @@ func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx curr ) } - m := xcontext.mContext(ctx, c.defaultQueryMode) + m := xcontext.QueryModeFromContext(ctx, c.defaultQueryMode) if slices.Contains(c.fakeTxModes, m) { return beginTxFake(ctx, c), nil diff --git a/internal/table/conn/context.go b/internal/table/conn/context.go index 339aa5a87..7772e5881 100644 --- a/internal/table/conn/context.go +++ b/internal/table/conn/context.go @@ -11,7 +11,6 @@ type ( ctxTransactionControlKey struct{} ctxDataQueryOptionsKey struct{} ctxScanQueryOptionsKey struct{} - ctxModeTypeKey struct{} ctxTxControlHookKey struct{} txControlHook func(txControl *table.TransactionControl) From b7e83f1cab042767ca4511690bfe190f7c093ccf Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 24 Nov 2024 01:18:50 +0300 Subject: [PATCH 36/48] fix(internal/query/conn): badconn rm --- internal/query/conn/conn.go | 15 ++++++--------- internal/query/conn/driver.impls.go | 15 +++++++-------- internal/query/conn/rows.go | 15 +++++++-------- internal/query/conn/stmt.go | 5 ++--- internal/query/conn/tx.go | 17 ++++++++--------- 5 files changed, 30 insertions(+), 37 deletions(-) diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index 8671bda46..4f54e5b5d 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -15,7 +15,6 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/session" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stats" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xcontext" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" @@ -96,9 +95,7 @@ func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx curr }() if c.currentTx != nil { - return nil, badconn.Map( - xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())), - ) + return nil, xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())) } tx, err := beginTx(ctx, c, txOptions) @@ -121,7 +118,7 @@ func (c *Conn) execContext( }() if !c.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + return nil, xerrors.WithStackTrace(errNotReadyConn) } if c.currentTx != nil { @@ -143,7 +140,7 @@ func (c *Conn) execContext( err = c.session.Exec(ctx, normalizedQuery, options.WithParameters(¶ms)) if err != nil { - return nil, badconn.Map(xerrors.WithStackTrace(err)) + return nil, xerrors.WithStackTrace(err) } return resultNoRows{}, nil @@ -157,7 +154,7 @@ func (c *Conn) queryContext(ctx context.Context, queryString string, args []driv }() if !c.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + return nil, xerrors.WithStackTrace(errNotReadyConn) } if c.currentTx != nil { @@ -197,7 +194,7 @@ func (c *Conn) queryContextOther( options.WithParameters(¶meters), ) if err != nil { - return nil, badconn.Map(xerrors.WithStackTrace(err)) + return nil, xerrors.WithStackTrace(err) } return &rows{ @@ -222,7 +219,7 @@ func (c *Conn) queryContextExplain( }), ) if err != nil { - return nil, badconn.Map(xerrors.WithStackTrace(err)) + return nil, xerrors.WithStackTrace(err) } return &single{ diff --git a/internal/query/conn/driver.impls.go b/internal/query/conn/driver.impls.go index 613d5170b..0db36ed3f 100644 --- a/internal/query/conn/driver.impls.go +++ b/internal/query/conn/driver.impls.go @@ -6,7 +6,6 @@ import ( "time" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "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/trace" @@ -44,11 +43,11 @@ func (c *Conn) Ping(ctx context.Context) (finalErr error) { }() if !c.isReady() { - return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + return xerrors.WithStackTrace(errNotReadyConn) } if !c.session.Core.IsAlive() { - return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + return xerrors.WithStackTrace(errNotReadyConn) } err := c.session.Exec(ctx, "select 1") @@ -70,7 +69,7 @@ func (c *Conn) PrepareContext(ctx context.Context, query string) (_ driver.Stmt, }() if !c.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + return nil, xerrors.WithStackTrace(errNotReadyConn) } return &stmt{ @@ -92,7 +91,7 @@ func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (driver. func (c *Conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { if !c.IsValid() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + return nil, xerrors.WithStackTrace(errNotReadyConn) } if c.currentTx != nil { @@ -104,7 +103,7 @@ func (c *Conn) ExecContext(ctx context.Context, query string, args []driver.Name func (c *Conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { if !c.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + return nil, xerrors.WithStackTrace(errNotReadyConn) } if c.currentTx != nil { return c.currentTx.QueryContext(ctx, query, args) @@ -119,7 +118,7 @@ func (c *Conn) Prepare(query string) (driver.Stmt, error) { func (c *Conn) Close() (finalErr error) { if !c.closed.CompareAndSwap(false, true) { - return badconn.Map(xerrors.WithStackTrace(errConnClosedEarly)) + return xerrors.WithStackTrace(errConnClosedEarly) } defer func() { @@ -143,7 +142,7 @@ func (c *Conn) Close() (finalErr error) { } err := c.session.Close(xcontext.ValueOnly(ctx)) if err != nil { - return badconn.Map(xerrors.WithStackTrace(err)) + return xerrors.WithStackTrace(err) } return nil diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index fc6531cbe..8e42674c6 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -9,7 +9,6 @@ import ( "sync" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/result" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/types" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) @@ -54,7 +53,7 @@ func (r *rows) loadFirstNextSet() { func (r *rows) Columns() []string { r.firstNextSet.Do(r.loadFirstNextSet) if r.columnsFetchError != nil { - panic(badconn.Map(xerrors.WithStackTrace(r.columnsFetchError))) + panic(xerrors.WithStackTrace(r.columnsFetchError)) } return r.columns @@ -63,7 +62,7 @@ func (r *rows) Columns() []string { func (r *rows) ColumnTypeDatabaseTypeName(index int) string { r.firstNextSet.Do(r.loadFirstNextSet) if r.columnsFetchError != nil { - panic(badconn.Map(xerrors.WithStackTrace(r.columnsFetchError))) + panic(xerrors.WithStackTrace(r.columnsFetchError)) } return r.columnsType[index].String() @@ -72,7 +71,7 @@ func (r *rows) ColumnTypeDatabaseTypeName(index int) string { func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) { r.firstNextSet.Do(r.loadFirstNextSet) if r.columnsFetchError != nil { - panic(badconn.Map(xerrors.WithStackTrace(r.columnsFetchError))) + panic(xerrors.WithStackTrace(r.columnsFetchError)) } _, castResult := r.nextSet.ColumnTypes()[index].(interface{ IsOptional() }) @@ -92,7 +91,7 @@ func (r *rows) NextResultSet() (finalErr error) { } if r.nextErr != nil { - return badconn.Map(xerrors.WithStackTrace(r.nextErr)) + return xerrors.WithStackTrace(r.nextErr) } r.columns = r.nextSet.Columns() @@ -117,7 +116,7 @@ func (r *rows) Next(dst []driver.Value) error { return io.EOF } - return badconn.Map(xerrors.WithStackTrace(r.nextErr)) + return xerrors.WithStackTrace(r.nextErr) } nextRow, err := r.nextSet.NextRow(ctx) @@ -126,7 +125,7 @@ func (r *rows) Next(dst []driver.Value) error { return io.EOF } - return badconn.Map(xerrors.WithStackTrace(err)) + return xerrors.WithStackTrace(err) } ptrs := make([]any, len(dst)) @@ -135,7 +134,7 @@ func (r *rows) Next(dst []driver.Value) error { } if err = nextRow.Scan(ptrs...); err != nil { - return badconn.Map(xerrors.WithStackTrace(err)) + return xerrors.WithStackTrace(err) } return nil diff --git a/internal/query/conn/stmt.go b/internal/query/conn/stmt.go index 5d43952e1..f84554de2 100644 --- a/internal/query/conn/stmt.go +++ b/internal/query/conn/stmt.go @@ -5,7 +5,6 @@ import ( "database/sql/driver" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) @@ -35,7 +34,7 @@ func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ onDone(finalErr) }() if !stmt.conn.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + return nil, xerrors.WithStackTrace(errNotReadyConn) } return stmt.processor.QueryContext(ctx, stmt.query, args) @@ -50,7 +49,7 @@ func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ onDone(finalErr) }() if !stmt.conn.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + return nil, xerrors.WithStackTrace(errNotReadyConn) } return stmt.processor.ExecContext(ctx, stmt.query, args) diff --git a/internal/query/conn/tx.go b/internal/query/conn/tx.go index ffa2aab11..9ba187fa8 100644 --- a/internal/query/conn/tx.go +++ b/internal/query/conn/tx.go @@ -8,7 +8,6 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/query" @@ -38,7 +37,7 @@ func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (currentT nativeTx, err := c.session.Begin(ctx, query.TxSettings(txc)) if err != nil { - return nil, badconn.Map(xerrors.WithStackTrace(err)) + return nil, xerrors.WithStackTrace(err) } return &transaction{ @@ -77,13 +76,13 @@ func (tx *transaction) Commit() (finalErr error) { onDone(finalErr) }() if err := tx.checkTxState(); err != nil { - return badconn.Map(xerrors.WithStackTrace(err)) + return xerrors.WithStackTrace(err) } defer func() { tx.conn.currentTx = nil }() if err := tx.tx.CommitTx(tx.ctx); err != nil { - return badconn.Map(xerrors.WithStackTrace(err)) + return xerrors.WithStackTrace(err) } return nil @@ -101,14 +100,14 @@ func (tx *transaction) Rollback() (finalErr error) { onDone(finalErr) }() if err := tx.checkTxState(); err != nil { - return badconn.Map(xerrors.WithStackTrace(err)) + return xerrors.WithStackTrace(err) } defer func() { tx.conn.currentTx = nil }() err := tx.tx.Rollback(tx.ctx) if err != nil { - return badconn.Map(xerrors.WithStackTrace(err)) + return xerrors.WithStackTrace(err) } return err @@ -133,7 +132,7 @@ func (tx *transaction) QueryContext(ctx context.Context, query string, args []dr query, options.WithParameters(¶meters), ) if err != nil { - return nil, badconn.Map(xerrors.WithStackTrace(err)) + return nil, xerrors.WithStackTrace(err) } return &rows{ @@ -161,7 +160,7 @@ func (tx *transaction) ExecContext(ctx context.Context, query string, args []dri query, options.WithParameters(¶meters), ) if err != nil { - return nil, badconn.Map(xerrors.WithStackTrace(err)) + return nil, xerrors.WithStackTrace(err) } return resultNoRows{}, nil @@ -176,7 +175,7 @@ func (tx *transaction) PrepareContext(ctx context.Context, query string) (_ driv onDone(finalErr) }() if !tx.conn.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + return nil, xerrors.WithStackTrace(errNotReadyConn) } return &stmt{ From a948510d267252e27e96ba1f2c9f613ba496c5f4 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 24 Nov 2024 14:45:15 +0300 Subject: [PATCH 37/48] refactor(internal/value): force ptr value set in missing type casts --- internal/value/cast.go | 23 +------- internal/value/value.go | 117 ++++++++++++++++++++++++++++++---------- 2 files changed, 89 insertions(+), 51 deletions(-) diff --git a/internal/value/cast.go b/internal/value/cast.go index ab20bcdde..7106b62fd 100644 --- a/internal/value/cast.go +++ b/internal/value/cast.go @@ -1,12 +1,5 @@ package value -import ( - "database/sql/driver" - "fmt" - - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" -) - func CastTo(v Value, dst interface{}) error { if dst == nil { return errNilDestination @@ -17,19 +10,5 @@ func CastTo(v Value, dst interface{}) error { return nil } - var err error - - if err = v.castTo(dst); err == nil { - return nil - } - - if ptr, has := dst.(*driver.Value); has { - *ptr = v - - return nil - } - - return xerrors.WithStackTrace( - fmt.Errorf("%w and cannot cast %T to driver.Value", err, dst), - ) + return v.castTo(dst) } diff --git a/internal/value/value.go b/internal/value/value.go index f791caf83..985158da9 100644 --- a/internal/value/value.go +++ b/internal/value/value.go @@ -508,10 +508,17 @@ type DecimalValuer interface { } func (v *decimalValue) castTo(dst any) error { - return xerrors.WithStackTrace(fmt.Errorf( - "%w '%+v' to '%T' destination", - ErrCannotCast, v, dst, - )) + switch dstValue := dst.(type) { + case *driver.Value: + *dstValue = v + + return nil + default: + return xerrors.WithStackTrace(fmt.Errorf( + "%w '%s(%+v)' to '%T' destination", + ErrCannotCast, v.Type().Yql(), v, dstValue, + )) + } } func (v *decimalValue) Yql() string { @@ -597,10 +604,17 @@ func (v *dictValue) DictValues() map[Value]Value { } func (v *dictValue) castTo(dst any) error { - return xerrors.WithStackTrace(fmt.Errorf( - "%w '%+v' to '%T' destination", - ErrCannotCast, v, dst, - )) + switch dstValue := dst.(type) { + case *driver.Value: + *dstValue = v + + return nil + default: + return xerrors.WithStackTrace(fmt.Errorf( + "%w '%s(%+v)' to '%T' destination", + ErrCannotCast, v.Type().Yql(), v, dstValue, + )) + } } func (v *dictValue) Yql() string { @@ -1266,10 +1280,17 @@ func (v *listValue) ListItems() []Value { } func (v *listValue) castTo(dst any) error { - return xerrors.WithStackTrace(fmt.Errorf( - "%w '%s(%+v)' to '%T' destination", - ErrCannotCast, v.Type().Yql(), v, dst, - )) + switch dstValue := dst.(type) { + case *driver.Value: + *dstValue = v + + return nil + default: + return xerrors.WithStackTrace(fmt.Errorf( + "%w '%s(%+v)' to '%T' destination", + ErrCannotCast, v.Type().Yql(), v, dstValue, + )) + } } func (v *listValue) Yql() string { @@ -1326,10 +1347,17 @@ type pgValue struct { } func (v pgValue) castTo(dst any) error { - return xerrors.WithStackTrace(fmt.Errorf( - "%w PgType to '%T' destination", - ErrCannotCast, dst, - )) + switch dstValue := dst.(type) { + case *driver.Value: + *dstValue = v + + return nil + default: + return xerrors.WithStackTrace(fmt.Errorf( + "%w '%s(%+v)' to '%T' destination", + ErrCannotCast, v.Type().Yql(), v, dstValue, + )) + } } func (v pgValue) Type() types.Type { @@ -1359,10 +1387,17 @@ type setValue struct { } func (v *setValue) castTo(dst any) error { - return xerrors.WithStackTrace(fmt.Errorf( - "%w '%+v' to '%T' destination", - ErrCannotCast, v, dst, - )) + switch dstValue := dst.(type) { + case *driver.Value: + *dstValue = v + + return nil + default: + return xerrors.WithStackTrace(fmt.Errorf( + "%w '%s(%+v)' to '%T' destination", + ErrCannotCast, v.Type().Yql(), v, dstValue, + )) + } } func (v *setValue) Yql() string { @@ -1535,10 +1570,17 @@ func (v *structValue) StructFields() map[string]Value { } func (v *structValue) castTo(dst any) error { - return xerrors.WithStackTrace(fmt.Errorf( - "%w '%+v' to '%T' destination", - ErrCannotCast, v, dst, - )) + switch dstValue := dst.(type) { + case *driver.Value: + *dstValue = v + + return nil + default: + return xerrors.WithStackTrace(fmt.Errorf( + "%w '%s(%+v)' to '%T' destination", + ErrCannotCast, v.Type().Yql(), v, dstValue, + )) + } } func (v *structValue) Yql() string { @@ -2422,7 +2464,17 @@ func (v *variantValue) Value() Value { } func (v *variantValue) castTo(dst any) error { - return v.value.castTo(dst) + switch dstValue := dst.(type) { + case *driver.Value: + *dstValue = v + + return nil + default: + return xerrors.WithStackTrace(fmt.Errorf( + "%w '%s(%+v)' to '%T' destination", + ErrCannotCast, v.Type().Yql(), v, dstValue, + )) + } } func (v *variantValue) Yql() string { @@ -2504,10 +2556,17 @@ func VariantValueStruct(v Value, name string, t types.Type) *variantValue { type voidValue struct{} func (v voidValue) castTo(dst any) error { - return xerrors.WithStackTrace(fmt.Errorf( - "%w '%s' to '%T' destination", - ErrCannotCast, v.Type().Yql(), dst, - )) + switch dstValue := dst.(type) { + case *driver.Value: + *dstValue = v + + return nil + default: + return xerrors.WithStackTrace(fmt.Errorf( + "%w '%s(%+v)' to '%T' destination", + ErrCannotCast, v.Type().Yql(), v, dstValue, + )) + } } func (v voidValue) Yql() string { From 60f2b54a3b144c38f5e085e65209af469490a400 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 24 Nov 2024 16:41:50 +0300 Subject: [PATCH 38/48] fix(internal/query/conn): yql type & castResult --- internal/query/conn/rows.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index 8e42674c6..f22d240b0 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -64,8 +64,7 @@ func (r *rows) ColumnTypeDatabaseTypeName(index int) string { if r.columnsFetchError != nil { panic(xerrors.WithStackTrace(r.columnsFetchError)) } - - return r.columnsType[index].String() + return r.columnsType[index].Yql() } func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) { @@ -75,7 +74,7 @@ func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) { } _, castResult := r.nextSet.ColumnTypes()[index].(interface{ IsOptional() }) - return castResult, castResult + return castResult, true } func (r *rows) NextResultSet() (finalErr error) { From 75c70610ef48edb2ed89e184989d8ff70d015be5 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 24 Nov 2024 16:42:42 +0300 Subject: [PATCH 39/48] feat(interna/value/tupleValue.castTo): driver.Value switch --- internal/value/value.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/internal/value/value.go b/internal/value/value.go index 985158da9..7f673894d 100644 --- a/internal/value/value.go +++ b/internal/value/value.go @@ -1696,10 +1696,17 @@ func (v *tupleValue) castTo(dst any) error { return v.items[0].castTo(dst) } - return xerrors.WithStackTrace(fmt.Errorf( - "%w '%+v' to '%T' destination", - ErrCannotCast, v, dst, - )) + switch dstValue := dst.(type) { + case *driver.Value: + *dstValue = v + + return nil + default: + return xerrors.WithStackTrace(fmt.Errorf( + "%w '%s(%+v)' to '%T' destination", + ErrCannotCast, v.Type().Yql(), v, dstValue, + )) + } } func (v *tupleValue) Yql() string { From 5c472296edea9aa1cfe99fa959d37c3d156b48a2 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 24 Nov 2024 17:08:10 +0300 Subject: [PATCH 40/48] feat(internal/query/conn/rows): discarded columns support --- internal/query/conn/rows.go | 56 ++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index f22d240b0..a203b0539 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -5,7 +5,9 @@ import ( "database/sql" "database/sql/driver" "errors" + "fmt" "io" + "strings" "sync" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/result" @@ -19,6 +21,8 @@ var ( _ driver.RowsColumnTypeDatabaseTypeName = &rows{} _ driver.RowsColumnTypeNullable = &rows{} _ driver.Rows = &single{} + + ignoreColumnPrefixName = "__discard_column_" ) type rows struct { @@ -29,9 +33,26 @@ type rows struct { nextSet result.Set nextErr error - columnsFetchError error - columns []string - columnsType []types.Type + columnsFetchError error + allColumns, columns []string + columnsType []types.Type + discarded []bool +} + +func (r *rows) updateColumns() { + if r.nextErr == nil { + r.allColumns = r.nextSet.Columns() + r.columns = make([]string, 0, len(r.allColumns)) + r.discarded = make([]bool, len(r.allColumns)) + for i, v := range r.allColumns { + r.discarded[i] = strings.HasPrefix(v, ignoreColumnPrefixName) + if !r.discarded[i] { + r.columns = append(r.columns, v) + } + } + r.columnsType = r.nextSet.ColumnTypes() + r.columnsFetchError = r.nextErr + } } func (r *rows) LastInsertId() (int64, error) { return 0, ErrUnsupported } @@ -42,12 +63,7 @@ func (r *rows) loadFirstNextSet() { res, err := r.result.NextResultSet(ctx) r.nextErr = err r.nextSet = res - - if err == nil { - r.columns = r.nextSet.Columns() - r.columnsType = r.nextSet.ColumnTypes() - r.columnsFetchError = r.nextErr - } + r.updateColumns() } func (r *rows) Columns() []string { @@ -55,7 +71,7 @@ func (r *rows) Columns() []string { if r.columnsFetchError != nil { panic(xerrors.WithStackTrace(r.columnsFetchError)) } - + fmt.Println(r.columns) return r.columns } @@ -92,10 +108,7 @@ func (r *rows) NextResultSet() (finalErr error) { if r.nextErr != nil { return xerrors.WithStackTrace(r.nextErr) } - - r.columns = r.nextSet.Columns() - r.columnsType = r.nextSet.ColumnTypes() - r.columnsFetchError = r.nextErr + r.updateColumns() return nil } @@ -127,15 +140,24 @@ func (r *rows) Next(dst []driver.Value) error { return xerrors.WithStackTrace(err) } - ptrs := make([]any, len(dst)) - for i := range dst { - ptrs[i] = &dst[i] + dstBuf := make([]driver.Value, len(r.allColumns)) + ptrs := make([]any, len(dstBuf)) + for i := range dstBuf { + ptrs[i] = &dstBuf[i] } if err = nextRow.Scan(ptrs...); err != nil { return xerrors.WithStackTrace(err) } + dstI := 0 + for i := range dstBuf { + if !r.discarded[i] { + dst[dstI] = dstBuf[i] + dstI++ + } + } + return nil } From 756153b2db14f731de334676ff57244f07605542 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 24 Nov 2024 17:09:01 +0300 Subject: [PATCH 41/48] ci(database_sql_with_tx_control_test): temporary query service support added --- .../database_sql_with_tx_control_test.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/integration/database_sql_with_tx_control_test.go b/tests/integration/database_sql_with_tx_control_test.go index d5b63011b..499a34b55 100644 --- a/tests/integration/database_sql_with_tx_control_test.go +++ b/tests/integration/database_sql_with_tx_control_test.go @@ -6,6 +6,7 @@ package integration import ( "context" "database/sql" + "os" "testing" "github.com/stretchr/testify/require" @@ -26,6 +27,11 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { ydb.WithAutoDeclare(), ) ) + overQueryService := false + + if v, has := os.LookupEnv("YDB_DATABASE_SQL_OVER_QUERY_SERVICE"); has && v != "" { + overQueryService = true + } t.Run("default", func(t *testing.T) { var hookCalled bool @@ -42,7 +48,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { return err }, )) - require.True(t, hookCalled) + require.True(t, hookCalled || overQueryService) }) t.Run("SerializableReadWriteTxControl", func(t *testing.T) { @@ -60,7 +66,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { return err }, )) - require.True(t, hookCalled) + require.True(t, hookCalled || overQueryService) }) t.Run("SnapshotReadOnlyTxControl", func(t *testing.T) { @@ -78,7 +84,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { return err }, )) - require.True(t, hookCalled) + require.True(t, hookCalled || overQueryService) }) t.Run("StaleReadOnlyTxControl", func(t *testing.T) { @@ -96,7 +102,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { return err }, )) - require.True(t, hookCalled) + require.True(t, hookCalled || overQueryService) }) t.Run("OnlineReadOnlyTxControl{AllowInconsistentReads:false}", func(t *testing.T) { @@ -114,7 +120,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { return err }, )) - require.True(t, hookCalled) + require.True(t, hookCalled || overQueryService) }) t.Run("OnlineReadOnlyTxControl{AllowInconsistentReads:true})", func(t *testing.T) { @@ -132,6 +138,6 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { return err }, )) - require.True(t, hookCalled) + require.True(t, hookCalled || overQueryService) }) } From 9f8f7063e1ef12349f4429360d188d5ed7edef3c Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 24 Nov 2024 17:53:46 +0300 Subject: [PATCH 42/48] fix(internal/table/conn): query modes definitions --- internal/table/conn/mode.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/table/conn/mode.go b/internal/table/conn/mode.go index 34c3caf69..8f9178ef9 100644 --- a/internal/table/conn/mode.go +++ b/internal/table/conn/mode.go @@ -12,7 +12,7 @@ const ( ExplainQueryMode = xcontext.ExplainQueryMode ScanQueryMode = xcontext.ScanQueryMode SchemeQueryMode = xcontext.SchemeQueryMode - ScriptingQueryMode = xcontext.UnknownQueryMode + ScriptingQueryMode = xcontext.ScriptingQueryMode - DefaultQueryMode = xcontext.UnknownQueryMode + DefaultQueryMode = xcontext.DefaultQueryMode ) From 85da81d93c1c4ec221de69dc07fd4cb461715889 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 24 Nov 2024 17:58:27 +0300 Subject: [PATCH 43/48] chore(internal/query/conn): linted --- internal/query/conn/rows.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index a203b0539..5d34601f2 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -5,7 +5,6 @@ import ( "database/sql" "database/sql/driver" "errors" - "fmt" "io" "strings" "sync" @@ -71,7 +70,7 @@ func (r *rows) Columns() []string { if r.columnsFetchError != nil { panic(xerrors.WithStackTrace(r.columnsFetchError)) } - fmt.Println(r.columns) + return r.columns } @@ -80,6 +79,7 @@ func (r *rows) ColumnTypeDatabaseTypeName(index int) string { if r.columnsFetchError != nil { panic(xerrors.WithStackTrace(r.columnsFetchError)) } + return r.columnsType[index].Yql() } From 3d61b6554ef3aaf478ea9d432a21aff41c62d9bd Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Mon, 9 Dec 2024 20:44:27 +0300 Subject: [PATCH 44/48] fixed parameters --- internal/query/conn/conn.go | 15 +++++++++++---- internal/query/conn/tx.go | 4 ++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index 4f54e5b5d..2a5c4b4d4 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -83,7 +83,14 @@ func (c *Conn) normalize(q string, args ...driver.NamedValue) (query string, _ p queryArgs[i] = args[i] } - return c.parent.Bindings().RewriteQuery(q, queryArgs...) + sql, parameters, err := c.parent.Bindings().RewriteQuery(q, queryArgs...) + if err != nil { + return "", nil, xerrors.WithStackTrace(err) + } + + params := params.Params(parameters) + + return sql, ¶ms, nil } func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx currentTx, finalErr error) { @@ -138,7 +145,7 @@ func (c *Conn) execContext( return nil, xerrors.WithStackTrace(err) } - err = c.session.Exec(ctx, normalizedQuery, options.WithParameters(¶ms)) + err = c.session.Exec(ctx, normalizedQuery, options.WithParameters(params)) if err != nil { return nil, xerrors.WithStackTrace(err) } @@ -191,7 +198,7 @@ func (c *Conn) queryContextOther( ) (driver.Rows, error) { res, err := c.session.Query( ctx, queryString, - options.WithParameters(¶meters), + options.WithParameters(parameters), ) if err != nil { return nil, xerrors.WithStackTrace(err) @@ -211,7 +218,7 @@ func (c *Conn) queryContextExplain( var ast, plan string _, err := c.session.Query( ctx, queryString, - options.WithParameters(¶meters), + options.WithParameters(parameters), options.WithExecMode(options.ExecModeExplain), options.WithStatsMode(options.StatsModeNone, func(stats stats.QueryStats) { ast = stats.QueryAST() diff --git a/internal/query/conn/tx.go b/internal/query/conn/tx.go index 9ba187fa8..56e6e4e8e 100644 --- a/internal/query/conn/tx.go +++ b/internal/query/conn/tx.go @@ -129,7 +129,7 @@ func (tx *transaction) QueryContext(ctx context.Context, query string, args []dr return nil, xerrors.WithStackTrace(err) } res, err := tx.tx.Query(ctx, - query, options.WithParameters(¶meters), + query, options.WithParameters(parameters), ) if err != nil { return nil, xerrors.WithStackTrace(err) @@ -157,7 +157,7 @@ func (tx *transaction) ExecContext(ctx context.Context, query string, args []dri return nil, xerrors.WithStackTrace(err) } err = tx.tx.Exec(ctx, - query, options.WithParameters(¶meters), + query, options.WithParameters(parameters), ) if err != nil { return nil, xerrors.WithStackTrace(err) From 9f7962d481293a34d4a82ce4a9c44a994878af04 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Mon, 9 Dec 2024 21:19:26 +0300 Subject: [PATCH 45/48] extracted ExplainQueryMode to internal/connector, other query modes moved from xcontext to internal/table/conn --- dsn.go | 7 ++-- internal/connector/conn.go | 54 +++++++++++++++++++++++++ internal/connector/context.go | 15 +++++++ internal/query/conn/conn.go | 54 +++++++++---------------- internal/query/conn/rows.go | 31 --------------- internal/table/conn/conn.go | 32 ++++++--------- internal/table/conn/mode.go | 64 +++++++++++++++++++++++++----- internal/table/conn/rows.go | 31 --------------- internal/table/conn/stmt.go | 5 +-- internal/table/conn/tx.go | 5 +-- internal/xcontext/query_modes.go | 68 -------------------------------- sql.go | 26 ++++++++---- 12 files changed, 179 insertions(+), 213 deletions(-) create mode 100644 internal/connector/context.go delete mode 100644 internal/xcontext/query_modes.go diff --git a/dsn.go b/dsn.go index ac48e7f3d..054b84f71 100644 --- a/dsn.go +++ b/dsn.go @@ -12,7 +12,6 @@ import ( "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/xcontext" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) @@ -61,13 +60,13 @@ func parseConnectionString(dataSourceName string) (opts []Option, _ error) { opts = append(opts, WithBalancer(balancers.FromConfig(balancer))) } if queryMode := info.Params.Get("go_query_mode"); queryMode != "" { - mode := xcontext.QueryModeFromString(queryMode) + mode := tableSql.QueryModeFromString(queryMode) if mode == tableSql.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } opts = append(opts, withConnectorOptions(connector.WithDefaultQueryMode(mode))) } else if queryMode := info.Params.Get("query_mode"); queryMode != "" { - mode := xcontext.QueryModeFromString(queryMode) + mode := tableSql.QueryModeFromString(queryMode) if mode == tableSql.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } @@ -75,7 +74,7 @@ func parseConnectionString(dataSourceName string) (opts []Option, _ error) { } if fakeTx := info.Params.Get("go_fake_tx"); fakeTx != "" { for _, queryMode := range strings.Split(fakeTx, ",") { - mode := xcontext.QueryModeFromString(queryMode) + mode := tableSql.QueryModeFromString(queryMode) if mode == tableSql.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } diff --git a/internal/connector/conn.go b/internal/connector/conn.go index 432d64b6f..6f19a2c5d 100644 --- a/internal/connector/conn.go +++ b/internal/connector/conn.go @@ -2,8 +2,10 @@ package connector import ( "context" + "database/sql" "database/sql/driver" "fmt" + "io" "path" "strings" "time" @@ -31,6 +33,8 @@ type ( driver.Validator driver.NamedValueChecker + Explain(ctx context.Context, sql string) (ast string, plan string, err error) + LastUsage() time.Time ID() string } @@ -39,8 +43,58 @@ type ( connector *Connector } + singleRow struct { + values []sql.NamedArg + readAll bool + } ) +func (r *singleRow) Columns() (columns []string) { + for i := range r.values { + columns = append(columns, r.values[i].Name) + } + + return columns +} + +func (r *singleRow) Close() error { + return nil +} + +func (r *singleRow) Next(dst []driver.Value) error { + if r.values == nil || r.readAll { + return io.EOF + } + for i := range r.values { + dst[i] = r.values[i].Value + } + r.readAll = true + + return nil +} + +func (c *connWrapper) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { + if isExplain(ctx) { + ast, plan, err := c.conn.Explain(ctx, query) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return &singleRow{ + values: []sql.NamedArg{ + sql.Named("AST", ast), + sql.Named("Plan", plan), + }, + }, nil + } + + return c.conn.QueryContext(ctx, query, args) +} + +func (c *connWrapper) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { + return c.conn.ExecContext(ctx, query, args) +} + func (c *connWrapper) GetDatabaseName() string { return c.connector.Name() } diff --git a/internal/connector/context.go b/internal/connector/context.go new file mode 100644 index 000000000..19d0ab2c1 --- /dev/null +++ b/internal/connector/context.go @@ -0,0 +1,15 @@ +package connector + +import "context" + +type ctxExplainQueryModeKey struct{} + +func WithExplain(ctx context.Context) context.Context { + return context.WithValue(ctx, ctxExplainQueryModeKey{}, true) +} + +func isExplain(ctx context.Context) bool { + v, has := ctx.Value(ctxExplainQueryModeKey{}).(bool) + + return has && v +} diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index 2a5c4b4d4..823afd81a 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -2,7 +2,6 @@ package conn import ( "context" - "database/sql" "database/sql/driver" "sync/atomic" @@ -57,6 +56,22 @@ type Conn struct { lastUsage atomic.Int64 } +func (c *Conn) Explain(ctx context.Context, sql string) (ast string, plan string, _ error) { + _, err := c.session.Query( + ctx, sql, + options.WithExecMode(options.ExecModeExplain), + options.WithStatsMode(options.StatsModeNone, func(stats stats.QueryStats) { + ast = stats.QueryAST() + plan = stats.QueryPlan() + }), + ) + if err != nil { + return "", "", xerrors.WithStackTrace(err) + } + + return ast, plan, nil +} + func New(ctx context.Context, parent Parent, s *query.Session, opts ...Option) *Conn { cc := &Conn{ ctx: ctx, @@ -134,7 +149,7 @@ func (c *Conn) execContext( onDone := trace.DatabaseSQLOnConnExec(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).execContext"), - query, xcontext.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), + query, "query", xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), ) defer func() { onDone(finalErr) @@ -170,7 +185,7 @@ func (c *Conn) queryContext(ctx context.Context, queryString string, args []driv onDone := trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).queryContext"), - queryString, xcontext.UnknownQueryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), + queryString, "query", xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), ) defer func() { @@ -182,12 +197,6 @@ func (c *Conn) queryContext(ctx context.Context, queryString string, args []driv return nil, xerrors.WithStackTrace(err) } - queryMode := xcontext.QueryModeFromContext(ctx, xcontext.UnknownQueryMode) - - if queryMode == xcontext.ExplainQueryMode { - return c.queryContextExplain(ctx, normalizedQuery, parameters) - } - return c.queryContextOther(ctx, normalizedQuery, parameters) } @@ -209,30 +218,3 @@ func (c *Conn) queryContextOther( result: res, }, nil } - -func (c *Conn) queryContextExplain( - ctx context.Context, - queryString string, - parameters params.Parameters, -) (driver.Rows, error) { - var ast, plan string - _, err := c.session.Query( - ctx, queryString, - options.WithParameters(parameters), - options.WithExecMode(options.ExecModeExplain), - options.WithStatsMode(options.StatsModeNone, func(stats stats.QueryStats) { - ast = stats.QueryAST() - plan = stats.QueryPlan() - }), - ) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - return &single{ - values: []sql.NamedArg{ - sql.Named("AST", ast), - sql.Named("Plan", plan), - }, - }, nil -} diff --git a/internal/query/conn/rows.go b/internal/query/conn/rows.go index 5d34601f2..f8bdb35aa 100644 --- a/internal/query/conn/rows.go +++ b/internal/query/conn/rows.go @@ -2,7 +2,6 @@ package conn import ( "context" - "database/sql" "database/sql/driver" "errors" "io" @@ -19,7 +18,6 @@ var ( _ driver.RowsNextResultSet = &rows{} _ driver.RowsColumnTypeDatabaseTypeName = &rows{} _ driver.RowsColumnTypeNullable = &rows{} - _ driver.Rows = &single{} ignoreColumnPrefixName = "__discard_column_" ) @@ -166,32 +164,3 @@ func (r *rows) Close() error { return r.result.Close(ctx) } - -type single struct { - values []sql.NamedArg - readAll bool -} - -func (r *single) Columns() (columns []string) { - for i := range r.values { - columns = append(columns, r.values[i].Name) - } - - return columns -} - -func (r *single) Close() error { - return nil -} - -func (r *single) Next(dst []driver.Value) error { - if r.values == nil || r.readAll { - return io.EOF - } - for i := range r.values { - dst[i] = r.values[i].Value - } - r.readAll = true - - return nil -} diff --git a/internal/table/conn/conn.go b/internal/table/conn/conn.go index 50e391445..96e9cde7f 100644 --- a/internal/table/conn/conn.go +++ b/internal/table/conn/conn.go @@ -2,7 +2,6 @@ package conn import ( "context" - "database/sql" "database/sql/driver" "fmt" "io" @@ -60,6 +59,15 @@ type ( } ) +func (c *Conn) Explain(ctx context.Context, sql string) (ast string, plan string, err error) { + exp, err := c.session.Explain(ctx, sql) + if err != nil { + return "", "", badconn.Map(xerrors.WithStackTrace(err)) + } + + return exp.AST, exp.Plan, nil +} + func (c *Conn) LastUsage() time.Time { return time.Unix(c.lastUsage.Load(), 0) } @@ -162,7 +170,7 @@ func (c *Conn) execContext( return c.currentTx.ExecContext(ctx, query, args) } - m := xcontext.QueryModeFromContext(ctx, c.defaultQueryMode) + m := queryModeFromContext(ctx, c.defaultQueryMode) onDone := trace.DatabaseSQLOnConnExec(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).execContext"), query, m.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), @@ -285,7 +293,7 @@ func (c *Conn) queryContext(ctx context.Context, query string, args []driver.Nam } var ( - queryMode = xcontext.QueryModeFromContext(ctx, c.defaultQueryMode) + queryMode = queryModeFromContext(ctx, c.defaultQueryMode) onDone = trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).queryContext"), query, queryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), @@ -305,8 +313,6 @@ func (c *Conn) queryContext(ctx context.Context, query string, args []driver.Nam return c.execDataQuery(ctx, normalizedQuery, parameters) case ScanQueryMode: return c.execScanQuery(ctx, normalizedQuery, parameters) - case ExplainQueryMode: - return c.explainQuery(ctx, normalizedQuery) case ScriptingQueryMode: return c.execScriptingQuery(ctx, normalizedQuery, parameters) default: @@ -349,20 +355,6 @@ func (c *Conn) execScanQuery(ctx context.Context, query string, params params.Pa }, nil } -func (c *Conn) explainQuery(ctx context.Context, query string) (driver.Rows, error) { - exp, err := c.session.Explain(ctx, query) - if err != nil { - return nil, badconn.Map(xerrors.WithStackTrace(err)) - } - - return &single{ - values: []sql.NamedArg{ - sql.Named("AST", exp.AST), - sql.Named("Plan", exp.Plan), - }, - }, nil -} - 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 { @@ -462,7 +454,7 @@ func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx curr ) } - m := xcontext.QueryModeFromContext(ctx, c.defaultQueryMode) + m := queryModeFromContext(ctx, c.defaultQueryMode) if slices.Contains(c.fakeTxModes, m) { return beginTxFake(ctx, c), nil diff --git a/internal/table/conn/mode.go b/internal/table/conn/mode.go index 8f9178ef9..2909e1874 100644 --- a/internal/table/conn/mode.go +++ b/internal/table/conn/mode.go @@ -1,18 +1,62 @@ package conn import ( - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xcontext" + "context" + "fmt" ) -type QueryMode = xcontext.QueryMode +type ( + QueryMode int + ctxQueryModeTypeKey struct{} +) const ( - UnknownQueryMode = xcontext.UnknownQueryMode - DataQueryMode = xcontext.DataQueryMode - ExplainQueryMode = xcontext.ExplainQueryMode - ScanQueryMode = xcontext.ScanQueryMode - SchemeQueryMode = xcontext.SchemeQueryMode - ScriptingQueryMode = xcontext.ScriptingQueryMode - - DefaultQueryMode = xcontext.DefaultQueryMode + UnknownQueryMode = QueryMode(iota) + DataQueryMode + ScanQueryMode + SchemeQueryMode + ScriptingQueryMode +) + +func WithQueryMode(ctx context.Context, mode QueryMode) context.Context { + return context.WithValue(ctx, ctxQueryModeTypeKey{}, mode) +} + +func queryModeFromContext(ctx context.Context, defaultMode QueryMode) QueryMode { + if mode, ok := ctx.Value(ctxQueryModeTypeKey{}).(QueryMode); ok { + return mode + } + + return defaultMode +} + +var ( + typeToString = map[QueryMode]string{ + DataQueryMode: "data", + ScanQueryMode: "scan", + SchemeQueryMode: "scheme", + ScriptingQueryMode: "scripting", + } + stringToType = map[string]QueryMode{ + "data": DataQueryMode, + "scan": ScanQueryMode, + "scheme": SchemeQueryMode, + "scripting": ScriptingQueryMode, + } ) + +func (t QueryMode) String() string { + if s, ok := typeToString[t]; ok { + return s + } + + return fmt.Sprintf("unknown_mode_%d", t) +} + +func QueryModeFromString(s string) QueryMode { + if t, ok := stringToType[s]; ok { + return t + } + + return UnknownQueryMode +} diff --git a/internal/table/conn/rows.go b/internal/table/conn/rows.go index 6b1601d98..d455975d9 100644 --- a/internal/table/conn/rows.go +++ b/internal/table/conn/rows.go @@ -2,7 +2,6 @@ package conn import ( "context" - "database/sql" "database/sql/driver" "fmt" "io" @@ -22,7 +21,6 @@ var ( _ driver.RowsNextResultSet = &rows{} _ driver.RowsColumnTypeDatabaseTypeName = &rows{} _ driver.RowsColumnTypeNullable = &rows{} - _ driver.Rows = &single{} _ scanner.Scanner = &valuer{} @@ -146,32 +144,3 @@ func (r *rows) Next(dst []driver.Value) error { func (r *rows) Close() error { return r.result.Close() } - -type single struct { - values []sql.NamedArg - readAll bool -} - -func (r *single) Columns() (columns []string) { - for i := range r.values { - columns = append(columns, r.values[i].Name) - } - - return columns -} - -func (r *single) Close() error { - return nil -} - -func (r *single) Next(dst []driver.Value) error { - if r.values == nil || r.readAll { - return io.EOF - } - for i := range r.values { - dst[i] = r.values[i].Value - } - r.readAll = true - - return nil -} diff --git a/internal/table/conn/stmt.go b/internal/table/conn/stmt.go index 566194f8d..34075ea82 100644 --- a/internal/table/conn/stmt.go +++ b/internal/table/conn/stmt.go @@ -7,7 +7,6 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" - "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/trace" ) @@ -39,7 +38,7 @@ func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ if !stmt.conn.isReady() { return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } - switch m := xcontext.QueryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { + switch m := queryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { case DataQueryMode: return stmt.processor.QueryContext(stmt.conn.withKeepInCache(ctx), stmt.query, args) default: @@ -58,7 +57,7 @@ func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ if !stmt.conn.isReady() { return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } - switch m := xcontext.QueryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { + switch m := queryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { case DataQueryMode: return stmt.processor.ExecContext(stmt.conn.withKeepInCache(ctx), stmt.query, args) default: diff --git a/internal/table/conn/tx.go b/internal/table/conn/tx.go index aa776afe2..d879be18e 100644 --- a/internal/table/conn/tx.go +++ b/internal/table/conn/tx.go @@ -9,7 +9,6 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" - "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/table" "github.com/ydb-platform/ydb-go-sdk/v3/trace" @@ -122,7 +121,7 @@ func (tx *transaction) QueryContext(ctx context.Context, query string, args []dr defer func() { onDone(finalErr) }() - m := xcontext.QueryModeFromContext(ctx, tx.conn.defaultQueryMode) + m := queryModeFromContext(ctx, tx.conn.defaultQueryMode) if m != DataQueryMode { return nil, badconn.Map( xerrors.WithStackTrace( @@ -164,7 +163,7 @@ func (tx *transaction) ExecContext(ctx context.Context, query string, args []dri defer func() { onDone(finalErr) }() - m := xcontext.QueryModeFromContext(ctx, tx.conn.defaultQueryMode) + m := queryModeFromContext(ctx, tx.conn.defaultQueryMode) if m != DataQueryMode { return nil, badconn.Map( xerrors.WithStackTrace( diff --git a/internal/xcontext/query_modes.go b/internal/xcontext/query_modes.go deleted file mode 100644 index 1c32bb6bf..000000000 --- a/internal/xcontext/query_modes.go +++ /dev/null @@ -1,68 +0,0 @@ -package xcontext - -import ( - "context" - "fmt" -) - -type QueryMode int - -type ctxModeTypeKey struct{} - -const ( - UnknownQueryMode = QueryMode(iota) - DataQueryMode - ExplainQueryMode - ScanQueryMode - SchemeQueryMode - ScriptingQueryMode - - DefaultQueryMode = DataQueryMode -) - -// QueryModeFromContext returns defined QueryMode or DefaultQueryMode -func QueryModeFromContext(ctx context.Context, defaultQueryMode QueryMode) QueryMode { - if m, ok := ctx.Value(ctxModeTypeKey{}).(QueryMode); ok { - return m - } - - return defaultQueryMode -} - -// WithQueryMode returns a copy of context with given QueryMode -func WithQueryMode(ctx context.Context, m QueryMode) context.Context { - return context.WithValue(ctx, ctxModeTypeKey{}, m) -} - -var ( - typeToString = map[QueryMode]string{ - DataQueryMode: "data", - ScanQueryMode: "scan", - ExplainQueryMode: "explain", - SchemeQueryMode: "scheme", - ScriptingQueryMode: "scripting", - } - stringToType = map[string]QueryMode{ - "data": DataQueryMode, - "scan": ScanQueryMode, - "explain": ExplainQueryMode, - "scheme": SchemeQueryMode, - "scripting": ScriptingQueryMode, - } -) - -func (t QueryMode) String() string { - if s, ok := typeToString[t]; ok { - return s - } - - return fmt.Sprintf("unknown_mode_%d", t) -} - -func QueryModeFromString(s string) QueryMode { - if t, ok := stringToType[s]; ok { - return t - } - - return UnknownQueryMode -} diff --git a/sql.go b/sql.go index a7f7ff273..fdaf55bd8 100644 --- a/sql.go +++ b/sql.go @@ -9,7 +9,6 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector" tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn" - "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/xsync" "github.com/ydb-platform/ydb-go-sdk/v3/table" @@ -82,15 +81,28 @@ func (d *sqlDriver) detach(c *connector.Connector) { type QueryMode = tableSql.QueryMode const ( - DataQueryMode = tableSql.DataQueryMode - ExplainQueryMode = tableSql.ExplainQueryMode - ScanQueryMode = tableSql.ScanQueryMode - SchemeQueryMode = tableSql.SchemeQueryMode - ScriptingQueryMode = tableSql.ScriptingQueryMode + DataQueryMode = iota + 1 + ExplainQueryMode + ScanQueryMode + SchemeQueryMode + ScriptingQueryMode ) func WithQueryMode(ctx context.Context, mode QueryMode) context.Context { - return xcontext.WithQueryMode(ctx, mode) + switch mode { + case ExplainQueryMode: + return connector.WithExplain(ctx) + case DataQueryMode: + return tableSql.WithQueryMode(ctx, tableSql.DataQueryMode) + case ScanQueryMode: + return tableSql.WithQueryMode(ctx, tableSql.ScanQueryMode) + case SchemeQueryMode: + return tableSql.WithQueryMode(ctx, tableSql.SchemeQueryMode) + case ScriptingQueryMode: + return tableSql.WithQueryMode(ctx, tableSql.ScriptingQueryMode) + default: + return ctx + } } func WithTxControl(ctx context.Context, txc *table.TransactionControl) context.Context { From 1ebcc3c89e9381ae8341c0ff1f4e6e34b2386329 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Tue, 10 Dec 2024 22:03:36 +0300 Subject: [PATCH 46/48] extraced internal/{table,query}/conn/stmt.go into internal/connector as common implementaion without Prepare call --- internal/connector/conn.go | 189 +++++++++--- internal/connector/conn_test.go | 22 +- internal/connector/connector.go | 14 +- internal/connector/errors.go | 4 + internal/connector/iface/conn.go | 22 ++ internal/connector/iface/tx.go | 18 ++ internal/{query/conn => connector}/stmt.go | 49 ++-- internal/connector/tx.go | 144 ++++++++++ internal/connector/unwrap.go | 4 +- internal/query/conn/conn.go | 199 +++++-------- internal/query/conn/driver.impls.go | 157 ---------- internal/query/conn/tx.go | 170 ++--------- internal/table/conn/conn.go | 317 +++++---------------- internal/table/conn/context.go | 4 - internal/table/conn/errors.go | 1 - internal/table/conn/options.go | 2 +- internal/table/conn/stmt.go | 92 ------ internal/table/conn/tx.go | 185 +++--------- internal/table/conn/tx_fake.go | 112 ++------ 19 files changed, 622 insertions(+), 1083 deletions(-) create mode 100644 internal/connector/iface/conn.go create mode 100644 internal/connector/iface/tx.go rename internal/{query/conn => connector}/stmt.go (55%) create mode 100644 internal/connector/tx.go delete mode 100644 internal/query/conn/driver.impls.go delete mode 100644 internal/table/conn/stmt.go diff --git a/internal/connector/conn.go b/internal/connector/conn.go index 6f19a2c5d..117bb57fa 100644 --- a/internal/connector/conn.go +++ b/internal/connector/conn.go @@ -10,38 +10,33 @@ import ( "strings" "time" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/scheme/helpers" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" internalTable "github.com/ydb-platform/ydb-go-sdk/v3/internal/table" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/config" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xslices" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsync" "github.com/ydb-platform/ydb-go-sdk/v3/retry" "github.com/ydb-platform/ydb-go-sdk/v3/scheme" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) -type ( - conn interface { - driver.Conn - driver.ConnPrepareContext - driver.ConnBeginTx - driver.ExecerContext - driver.QueryerContext - driver.Pinger - driver.Validator - driver.NamedValueChecker - - Explain(ctx context.Context, sql string) (ast string, plan string, err error) +var ( + _ driver.ConnBeginTx = (*conn)(nil) + _ driver.NamedValueChecker = (*conn)(nil) + _ driver.Pinger = (*conn)(nil) +) - LastUsage() time.Time - ID() string - } - connWrapper struct { - conn +type ( + conn struct { + cc iface.Conn connector *Connector + lastUsage xsync.LastUsage } singleRow struct { values []sql.NamedArg @@ -49,6 +44,56 @@ type ( } ) +func (c *conn) Ping(ctx context.Context) error { + return c.cc.Ping(ctx) +} + +func (c *conn) CheckNamedValue(value *driver.NamedValue) error { + // on this stage allows all values + return nil +} + +func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { + tx, err := c.cc.BeginTx(ctx, opts) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return &txWrapper{ + conn: c, + ctx: ctx, + tx: tx, + }, nil +} + +func (c *conn) Close() error { + err := c.cc.Close() + if err != nil { + return xerrors.WithStackTrace(err) + } + + return nil +} + +func (c *conn) Begin() (driver.Tx, error) { + return nil, xerrors.WithStackTrace(errDeprecated) +} + +func rowByAstPlan(ast, plan string) *singleRow { + return &singleRow{ + values: []sql.NamedArg{ + { + Name: "Ast", + Value: ast, + }, + { + Name: "Plan", + Value: plan, + }, + }, + } +} + func (r *singleRow) Columns() (columns []string) { for i := range r.values { columns = append(columns, r.values[i].Name) @@ -73,39 +118,95 @@ func (r *singleRow) Next(dst []driver.Value) error { return nil } -func (c *connWrapper) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { +func (c *conn) Prepare(string) (driver.Stmt, error) { + return nil, errDeprecated +} + +func (c *conn) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, finalErr error) { + onDone := trace.DatabaseSQLOnConnPrepare(c.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*conn).PrepareContext"), + sql, + ) + defer func() { + onDone(finalErr) + }() + + if !c.cc.IsValid() { + return nil, xerrors.WithStackTrace(errNotReadyConn) + } + + return &stmt{ + conn: c, + processor: c.cc, + ctx: ctx, + sql: sql, + }, nil +} + +func (c *conn) LastUsage() time.Time { + return c.lastUsage.Get() +} + +func (c *conn) normalize(q string, args ...driver.NamedValue) (query string, _ *params.Params, _ error) { + queryArgs := make([]any, len(args)) + for i := range args { + queryArgs[i] = args[i] + } + + sql, parameters, err := c.connector.Bindings().RewriteQuery(q, queryArgs...) + if err != nil { + return "", nil, xerrors.WithStackTrace(err) + } + + params := params.Params(parameters) + + return sql, ¶ms, nil +} + +func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { + done := c.lastUsage.Start() + defer done() + + query, params, err := c.normalize(query, args...) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + if isExplain(ctx) { - ast, plan, err := c.conn.Explain(ctx, query) + ast, plan, err := c.cc.Explain(ctx, query, params) if err != nil { return nil, xerrors.WithStackTrace(err) } - return &singleRow{ - values: []sql.NamedArg{ - sql.Named("AST", ast), - sql.Named("Plan", plan), - }, - }, nil + return rowByAstPlan(ast, plan), nil } - return c.conn.QueryContext(ctx, query, args) + return c.cc.Query(ctx, query, params) } -func (c *connWrapper) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { - return c.conn.ExecContext(ctx, query, args) +func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { + done := c.lastUsage.Start() + defer done() + + query, params, err := c.normalize(query, args...) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return c.cc.Exec(ctx, query, params) } -func (c *connWrapper) GetDatabaseName() string { +func (c *conn) GetDatabaseName() string { return c.connector.Name() } -func (c *connWrapper) normalizePath(tableName string) string { +func (c *conn) normalizePath(tableName string) string { return c.connector.pathNormalizer.NormalizePath(tableName) } -func (c *connWrapper) tableDescription(ctx context.Context, tableName string) (d options.Description, _ error) { +func (c *conn) tableDescription(ctx context.Context, tableName string) (d options.Description, _ error) { d, err := retry.RetryWithResult(ctx, func(ctx context.Context) (options.Description, error) { - return internalTable.Session(c.ID(), c.connector.balancer, config.New()).DescribeTable(ctx, tableName) + return internalTable.Session(c.cc.ID(), c.connector.balancer, config.New()).DescribeTable(ctx, tableName) }, retry.WithIdempotent(true), retry.WithBudget(c.connector.retryBudget), retry.WithTrace(c.connector.traceRetry)) if err != nil { return d, xerrors.WithStackTrace(err) @@ -114,7 +215,7 @@ func (c *connWrapper) tableDescription(ctx context.Context, tableName string) (d return d, nil } -func (c *connWrapper) GetColumns(ctx context.Context, tableName string) (columns []string, _ error) { +func (c *conn) GetColumns(ctx context.Context, tableName string) (columns []string, _ error) { d, err := c.tableDescription(ctx, c.normalizePath(tableName)) if err != nil { return nil, xerrors.WithStackTrace(err) @@ -127,7 +228,7 @@ func (c *connWrapper) GetColumns(ctx context.Context, tableName string) (columns return columns, nil } -func (c *connWrapper) GetColumnType(ctx context.Context, tableName, columnName string) (dataType string, _ error) { +func (c *conn) GetColumnType(ctx context.Context, tableName, columnName string) (dataType string, _ error) { d, err := c.tableDescription(ctx, c.normalizePath(tableName)) if err != nil { return "", xerrors.WithStackTrace(err) @@ -142,7 +243,7 @@ func (c *connWrapper) GetColumnType(ctx context.Context, tableName, columnName s return "", xerrors.WithStackTrace(fmt.Errorf("column '%s' not exist in table '%s'", columnName, tableName)) } -func (c *connWrapper) GetPrimaryKeys(ctx context.Context, tableName string) ([]string, error) { +func (c *conn) GetPrimaryKeys(ctx context.Context, tableName string) ([]string, error) { d, err := c.tableDescription(ctx, c.normalizePath(tableName)) if err != nil { return nil, xerrors.WithStackTrace(err) @@ -151,7 +252,7 @@ func (c *connWrapper) GetPrimaryKeys(ctx context.Context, tableName string) ([]s return d.PrimaryKey, nil } -func (c *connWrapper) IsPrimaryKey(ctx context.Context, tableName, columnName string) (ok bool, _ error) { +func (c *conn) IsPrimaryKey(ctx context.Context, tableName, columnName string) (ok bool, _ error) { d, err := c.tableDescription(ctx, c.normalizePath(tableName)) if err != nil { return false, xerrors.WithStackTrace(err) @@ -166,7 +267,7 @@ func (c *connWrapper) IsPrimaryKey(ctx context.Context, tableName, columnName st return false, nil } -func (c *connWrapper) Version(_ context.Context) (_ string, _ error) { +func (c *conn) Version(_ context.Context) (_ string, _ error) { const version = "default" return version, nil @@ -185,7 +286,7 @@ func isSysDir(databaseName, dirAbsPath string) bool { return false } -func (c *connWrapper) getTables(ctx context.Context, absPath string, recursive, excludeSysDirs bool) ( +func (c *conn) getTables(ctx context.Context, absPath string, recursive, excludeSysDirs bool) ( tables []string, _ error, ) { if excludeSysDirs && isSysDir(c.connector.Name(), absPath) { @@ -219,7 +320,7 @@ func (c *connWrapper) getTables(ctx context.Context, absPath string, recursive, return tables, nil } -func (c *connWrapper) GetTables(ctx context.Context, folder string, recursive, excludeSysDirs bool) ( +func (c *conn) GetTables(ctx context.Context, folder string, recursive, excludeSysDirs bool) ( tables []string, _ error, ) { absPath := c.normalizePath(folder) @@ -248,7 +349,7 @@ func (c *connWrapper) GetTables(ctx context.Context, folder string, recursive, e } } -func (c *connWrapper) GetIndexes(ctx context.Context, tableName string) (indexes []string, _ error) { +func (c *conn) GetIndexes(ctx context.Context, tableName string) (indexes []string, _ error) { d, err := c.tableDescription(ctx, c.normalizePath(tableName)) if err != nil { return nil, xerrors.WithStackTrace(err) @@ -259,7 +360,7 @@ func (c *connWrapper) GetIndexes(ctx context.Context, tableName string) (indexes }), nil } -func (c *connWrapper) GetIndexColumns(ctx context.Context, tableName, indexName string) (columns []string, _ error) { +func (c *conn) GetIndexColumns(ctx context.Context, tableName, indexName string) (columns []string, _ error) { d, err := c.tableDescription(ctx, c.normalizePath(tableName)) if err != nil { return nil, xerrors.WithStackTrace(err) @@ -274,7 +375,7 @@ func (c *connWrapper) GetIndexColumns(ctx context.Context, tableName, indexName return xslices.Uniq(columns), nil } -func (c *connWrapper) IsColumnExists(ctx context.Context, tableName, columnName string) (columnExists bool, _ error) { +func (c *conn) IsColumnExists(ctx context.Context, tableName, columnName string) (columnExists bool, _ error) { d, err := c.tableDescription(ctx, c.normalizePath(tableName)) if err != nil { return false, xerrors.WithStackTrace(err) @@ -289,10 +390,10 @@ func (c *connWrapper) IsColumnExists(ctx context.Context, tableName, columnName return false, nil } -func (c *connWrapper) IsTableExists(ctx context.Context, tableName string) (tableExists bool, finalErr error) { +func (c *conn) IsTableExists(ctx context.Context, tableName string) (tableExists bool, finalErr error) { tableName = c.normalizePath(tableName) onDone := trace.DatabaseSQLOnConnIsTableExists(c.connector.trace, &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*connWrapper).IsTableExists"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*conn).IsTableExists"), tableName, ) defer func() { diff --git a/internal/connector/conn_test.go b/internal/connector/conn_test.go index 07dff50f3..c9f02ba79 100644 --- a/internal/connector/conn_test.go +++ b/internal/connector/conn_test.go @@ -5,45 +5,45 @@ import "context" var ( _ interface { GetDatabaseName() string - } = (*connWrapper)(nil) + } = (*conn)(nil) _ interface { Version(ctx context.Context) (version string, err error) - } = (*connWrapper)(nil) + } = (*conn)(nil) _ interface { IsTableExists(ctx context.Context, tableName string) (tableExists bool, err error) - } = (*connWrapper)(nil) + } = (*conn)(nil) _ interface { IsColumnExists(ctx context.Context, tableName string, columnName string) (columnExists bool, err error) - } = (*connWrapper)(nil) + } = (*conn)(nil) _ interface { IsPrimaryKey(ctx context.Context, tableName string, columnName string) (ok bool, err error) - } = (*connWrapper)(nil) + } = (*conn)(nil) _ interface { GetColumns(ctx context.Context, tableName string) (columns []string, err error) - } = (*connWrapper)(nil) + } = (*conn)(nil) _ interface { GetColumnType(ctx context.Context, tableName string, columnName string) (dataType string, err error) - } = (*connWrapper)(nil) + } = (*conn)(nil) _ interface { GetPrimaryKeys(ctx context.Context, tableName string) (pkCols []string, err error) - } = (*connWrapper)(nil) + } = (*conn)(nil) _ interface { GetTables(ctx context.Context, folder string, recursive bool, excludeSysDirs bool) (tables []string, err error) - } = (*connWrapper)(nil) + } = (*conn)(nil) _ interface { GetIndexes(ctx context.Context, tableName string) (indexes []string, err error) - } = (*connWrapper)(nil) + } = (*conn)(nil) _ interface { GetIndexColumns(ctx context.Context, tableName string, indexName string) (columns []string, err error) - } = (*connWrapper)(nil) + } = (*conn)(nil) ) diff --git a/internal/connector/connector.go b/internal/connector/connector.go index 44475b95f..6f88955df 100644 --- a/internal/connector/connector.go +++ b/internal/connector/connector.go @@ -45,7 +45,7 @@ type ( clock clockwork.Clock idleThreshold time.Duration - conns xsync.Map[uuid.UUID, *connWrapper] + conns xsync.Map[uuid.UUID, *conn] done chan struct{} trace *trace.DatabaseSQL traceRetry *trace.Retry @@ -121,14 +121,15 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() - conn := &connWrapper{ - conn: querySql.New(ctx, c, s, append( + conn := &conn{ + cc: querySql.New(ctx, c, s, append( c.QueryOpts, querySql.WithOnClose(func() { c.conns.Delete(id) }))..., ), connector: c, + lastUsage: xsync.NewLastUsage(xsync.WithClock(c.Clock())), } c.conns.Set(id, conn) @@ -143,13 +144,14 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() - conn := &connWrapper{ - conn: tableSql.New(ctx, c, s, append(c.TableOpts, + conn := &conn{ + cc: tableSql.New(ctx, c, s, append(c.TableOpts, tableSql.WithOnClose(func() { c.conns.Delete(id) }))..., ), connector: c, + lastUsage: xsync.NewLastUsage(xsync.WithClock(c.Clock())), } c.conns.Set(id, conn) @@ -222,7 +224,7 @@ func Open(parent ydbDriver, balancer grpc.ClientConnInterface, opts ...Option) ( return case <-idleThresholdTimer.Chan(): idleThresholdTimer.Stop() // no really need, stop for common style only - c.conns.Range(func(_ uuid.UUID, cc *connWrapper) bool { + c.conns.Range(func(_ uuid.UUID, cc *conn) bool { if c.clock.Since(cc.LastUsage()) > c.idleThreshold { _ = cc.Close() } diff --git a/internal/connector/errors.go b/internal/connector/errors.go index 33581f0a6..c7adeef7f 100644 --- a/internal/connector/errors.go +++ b/internal/connector/errors.go @@ -3,10 +3,14 @@ package connector import ( "database/sql/driver" "errors" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) var ( ErrUnsupported = driver.ErrSkip + errDeprecated = driver.ErrSkip errAlreadyClosed = errors.New("already closed") errWrongQueryProcessor = errors.New("wrong query processor") + errNotReadyConn = xerrors.Retryable(errors.New("conn not ready"), xerrors.InvalidObject()) ) diff --git a/internal/connector/iface/conn.go b/internal/connector/iface/conn.go new file mode 100644 index 000000000..c1a100f82 --- /dev/null +++ b/internal/connector/iface/conn.go @@ -0,0 +1,22 @@ +package iface + +import ( + "context" + "database/sql/driver" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" +) + +type Conn interface { + driver.Validator + driver.Pinger + + ID() string + + Exec(ctx context.Context, sql string, params *params.Params) (result driver.Result, err error) + Query(ctx context.Context, sql string, params *params.Params) (result driver.RowsNextResultSet, err error) + Explain(ctx context.Context, sql string, params *params.Params) (ast string, plan string, err error) + BeginTx(ctx context.Context, opts driver.TxOptions) (Tx, error) + + Close() error +} diff --git a/internal/connector/iface/tx.go b/internal/connector/iface/tx.go new file mode 100644 index 000000000..d75dd8d83 --- /dev/null +++ b/internal/connector/iface/tx.go @@ -0,0 +1,18 @@ +package iface + +import ( + "context" + "database/sql/driver" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" +) + +type Tx interface { + ID() string + + Exec(ctx context.Context, sql string, params *params.Params) (driver.Result, error) + Query(ctx context.Context, sql string, params *params.Params) (driver.RowsNextResultSet, error) + + Rollback(ctx context.Context) error + Commit(ctx context.Context) error +} diff --git a/internal/query/conn/stmt.go b/internal/connector/stmt.go similarity index 55% rename from internal/query/conn/stmt.go rename to internal/connector/stmt.go index f84554de2..6ad6fcf59 100644 --- a/internal/query/conn/stmt.go +++ b/internal/connector/stmt.go @@ -1,22 +1,23 @@ -package conn +package connector import ( "context" "database/sql/driver" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) type stmt struct { - conn *Conn + conn *conn processor interface { - driver.ExecerContext - driver.QueryerContext + Exec(ctx context.Context, sql string, params *params.Params) (driver.Result, error) + Query(ctx context.Context, sql string, params *params.Params) (driver.RowsNextResultSet, error) } - query string - ctx context.Context //nolint:containedctx + sql string + ctx context.Context //nolint:containedctx } var ( @@ -26,33 +27,45 @@ var ( ) func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ driver.Rows, finalErr error) { - onDone := trace.DatabaseSQLOnStmtQuery(stmt.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*stmt).QueryContext"), - stmt.ctx, stmt.query, + onDone := trace.DatabaseSQLOnStmtQuery(stmt.conn.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*stmt).QueryContext"), + stmt.ctx, stmt.sql, ) defer func() { onDone(finalErr) }() - if !stmt.conn.isReady() { + + if !stmt.conn.cc.IsValid() { return nil, xerrors.WithStackTrace(errNotReadyConn) } - return stmt.processor.QueryContext(ctx, stmt.query, args) + sql, params, err := stmt.conn.normalize(stmt.sql, args...) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return stmt.processor.Query(ctx, sql, params) } func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ driver.Result, finalErr error) { - onDone := trace.DatabaseSQLOnStmtExec(stmt.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*stmt).ExecContext"), - stmt.ctx, stmt.query, + onDone := trace.DatabaseSQLOnStmtExec(stmt.conn.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*stmt).ExecContext"), + stmt.ctx, stmt.sql, ) defer func() { onDone(finalErr) }() - if !stmt.conn.isReady() { + + if !stmt.conn.cc.IsValid() { return nil, xerrors.WithStackTrace(errNotReadyConn) } - return stmt.processor.ExecContext(ctx, stmt.query, args) + sql, params, err := stmt.conn.normalize(stmt.sql, args...) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return stmt.processor.Exec(ctx, sql, params) } func (stmt *stmt) NumInput() int { @@ -62,8 +75,8 @@ func (stmt *stmt) NumInput() int { func (stmt *stmt) Close() (finalErr error) { var ( ctx = stmt.ctx - onDone = trace.DatabaseSQLOnStmtClose(stmt.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*stmt).Close"), + onDone = trace.DatabaseSQLOnStmtClose(stmt.conn.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*stmt).Close"), ) ) defer func() { diff --git a/internal/connector/tx.go b/internal/connector/tx.go new file mode 100644 index 000000000..c260739e0 --- /dev/null +++ b/internal/connector/tx.go @@ -0,0 +1,144 @@ +package connector + +import ( + "context" + "database/sql/driver" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/trace" +) + +type txWrapper struct { + conn *conn + tx iface.Tx + ctx context.Context //nolint:containedctx +} + +func (tx *txWrapper) ID() string { + return tx.tx.ID() +} + +var ( + _ driver.Tx = &txWrapper{} + _ driver.ExecerContext = &txWrapper{} + _ driver.QueryerContext = &txWrapper{} +) + +func (tx *txWrapper) Commit() (finalErr error) { + var ( + ctx = tx.ctx + onDone = trace.DatabaseSQLOnTxCommit(tx.conn.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*txWrapper).Commit"), + tx, + ) + ) + defer func() { + onDone(finalErr) + }() + + if err := tx.tx.Commit(tx.ctx); err != nil { + return xerrors.WithStackTrace(err) + } + + return nil +} + +func (tx *txWrapper) Rollback() (finalErr error) { + var ( + ctx = tx.ctx + onDone = trace.DatabaseSQLOnTxRollback(tx.conn.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*txWrapper).Rollback"), + tx, + ) + ) + defer func() { + onDone(finalErr) + }() + + err := tx.tx.Rollback(tx.ctx) + if err != nil { + return xerrors.WithStackTrace(err) + } + + return err +} + +func (tx *txWrapper) QueryContext(ctx context.Context, query string, args []driver.NamedValue) ( + _ driver.Rows, finalErr error, +) { + onDone := trace.DatabaseSQLOnTxQuery(tx.conn.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*txWrapper).QueryContext"), + tx.ctx, tx, query, + ) + defer func() { + onDone(finalErr) + }() + + query, params, err := tx.conn.normalize(query, args...) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + if isExplain(ctx) { + ast, plan, err := tx.conn.cc.Explain(ctx, query, params) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return rowByAstPlan(ast, plan), nil + } + + rows, err := tx.tx.Query(ctx, query, params) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return rows, nil +} + +func (tx *txWrapper) ExecContext(ctx context.Context, query string, args []driver.NamedValue) ( + _ driver.Result, finalErr error, +) { + onDone := trace.DatabaseSQLOnTxExec(tx.conn.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*txWrapper).ExecContext"), + tx.ctx, tx, query, + ) + defer func() { + onDone(finalErr) + }() + + query, params, err := tx.conn.normalize(query, args...) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + result, err := tx.tx.Exec(ctx, query, params) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return result, nil +} + +func (tx *txWrapper) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, finalErr error) { + onDone := trace.DatabaseSQLOnTxPrepare(tx.conn.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*txWrapper).PrepareContext"), + tx.ctx, tx, sql, + ) + defer func() { + onDone(finalErr) + }() + if !tx.conn.cc.IsValid() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + return &stmt{ + conn: tx.conn, + processor: tx.tx, + ctx: ctx, + sql: sql, + }, nil +} diff --git a/internal/connector/unwrap.go b/internal/connector/unwrap.go index eedb2bf8f..c0321dfb0 100644 --- a/internal/connector/unwrap.go +++ b/internal/connector/unwrap.go @@ -18,13 +18,13 @@ func Unwrap[T *sql.DB | *sql.Conn](v T) (connector *Connector, _ error) { return nil, xerrors.WithStackTrace(fmt.Errorf("%T is not a *driverWrapper", v)) case *sql.Conn: if err := vv.Raw(func(driverConn interface{}) error { - if cc, ok := driverConn.(*connWrapper); ok { + if cc, ok := driverConn.(*conn); ok { connector = cc.connector return nil } - return xerrors.WithStackTrace(fmt.Errorf("%T is not a *connWrapper", driverConn)) + return xerrors.WithStackTrace(fmt.Errorf("%T is not a *conn", driverConn)) }); err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } diff --git a/internal/query/conn/conn.go b/internal/query/conn/conn.go index 823afd81a..6a7ae2e3a 100644 --- a/internal/query/conn/conn.go +++ b/internal/query/conn/conn.go @@ -5,20 +5,14 @@ import ( "database/sql/driver" "sync/atomic" - "github.com/jonboulle/clockwork" - - "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/session" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stats" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "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/retry/budget" - "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) type resultNoRows struct{} @@ -30,33 +24,60 @@ var _ driver.Result = resultNoRows{} type Parent interface { Query() *query.Client - Trace() *trace.DatabaseSQL - TraceRetry() *trace.Retry - RetryBudget() budget.Budget - Bindings() bind.Bindings - Clock() clockwork.Clock } -type currentTx interface { - tx.Identifier - driver.Tx - driver.ExecerContext - driver.QueryerContext - driver.ConnPrepareContext - Rollback() error +type Conn struct { + ctx context.Context //nolint:containedctx + parent Parent + session *query.Session + onClose []func() + closed atomic.Bool } -type Conn struct { - currentTx - ctx context.Context //nolint:containedctx - parent Parent - session *query.Session - onClose []func() - closed atomic.Bool - lastUsage atomic.Int64 +func (c *Conn) Exec(ctx context.Context, sql string, params *params.Params) ( + result driver.Result, finalErr error, +) { + if !c.IsValid() { + return nil, xerrors.WithStackTrace(errNotReadyConn) + } + + if !c.isReady() { + return nil, xerrors.WithStackTrace(errNotReadyConn) + } + + err := c.session.Exec(ctx, sql, options.WithParameters(params)) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return resultNoRows{}, nil +} + +func (c *Conn) Query(ctx context.Context, sql string, params *params.Params) ( + result driver.RowsNextResultSet, finalErr error, +) { + if !c.isReady() { + return nil, xerrors.WithStackTrace(errNotReadyConn) + } + + if !c.isReady() { + return nil, xerrors.WithStackTrace(errNotReadyConn) + } + + res, err := c.session.Query(ctx, sql, + options.WithParameters(params), + ) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return &rows{ + conn: c, + result: res, + }, nil } -func (c *Conn) Explain(ctx context.Context, sql string) (ast string, plan string, _ error) { +func (c *Conn) Explain(ctx context.Context, sql string, _ *params.Params) (ast string, plan string, _ error) { _, err := c.session.Query( ctx, sql, options.WithExecMode(options.ExecModeExplain), @@ -92,129 +113,65 @@ func (c *Conn) isReady() bool { return c.session.Status() == session.StatusIdle.String() } -func (c *Conn) normalize(q string, args ...driver.NamedValue) (query string, _ params.Parameters, _ error) { - queryArgs := make([]any, len(args)) - for i := range args { - queryArgs[i] = args[i] - } - - sql, parameters, err := c.parent.Bindings().RewriteQuery(q, queryArgs...) - if err != nil { - return "", nil, xerrors.WithStackTrace(err) - } - - params := params.Params(parameters) - - return sql, ¶ms, nil -} - -func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx currentTx, finalErr error) { - onDone := trace.DatabaseSQLOnConnBegin(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).beginTx"), - ) - defer func() { - onDone(tx, finalErr) - }() - - if c.currentTx != nil { - return nil, xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())) - } - +func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx iface.Tx, finalErr error) { tx, err := beginTx(ctx, c, txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) } - c.currentTx = tx - return tx, nil } -func (c *Conn) execContext( - ctx context.Context, - query string, - args []driver.NamedValue, -) (_ driver.Result, finalErr error) { - defer func() { - c.lastUsage.Store(c.parent.Clock().Now().Unix()) - }() +func (c *Conn) ID() string { + return c.session.ID() +} + +func (c *Conn) IsValid() bool { + return c.isReady() +} +func (c *Conn) Ping(ctx context.Context) (finalErr error) { if !c.isReady() { - return nil, xerrors.WithStackTrace(errNotReadyConn) + return xerrors.WithStackTrace(errNotReadyConn) } - if c.currentTx != nil { - return c.currentTx.ExecContext(ctx, query, args) + if !c.session.Core.IsAlive() { + return xerrors.WithStackTrace(errNotReadyConn) } - onDone := trace.DatabaseSQLOnConnExec(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).execContext"), - query, "query", xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), - ) - defer func() { - onDone(finalErr) - }() + err := c.session.Exec(ctx, "select 1") - normalizedQuery, params, err := c.normalize(query, args...) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } + return err +} - err = c.session.Exec(ctx, normalizedQuery, options.WithParameters(params)) +func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (iface.Tx, error) { + tx, err := c.beginTx(ctx, txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) } - return resultNoRows{}, nil + return tx, nil } -func (c *Conn) queryContext(ctx context.Context, queryString string, args []driver.NamedValue) ( - _ driver.Rows, finalErr error, -) { - defer func() { - c.lastUsage.Store(c.parent.Clock().Now().Unix()) - }() - - if !c.isReady() { - return nil, xerrors.WithStackTrace(errNotReadyConn) +func (c *Conn) Close() (finalErr error) { + if !c.closed.CompareAndSwap(false, true) { + return xerrors.WithStackTrace(errConnClosedEarly) } - if c.currentTx != nil { - return c.currentTx.QueryContext(ctx, queryString, args) - } - - onDone := trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).queryContext"), - queryString, "query", xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), - ) - defer func() { - onDone(finalErr) + for _, onClose := range c.onClose { + onClose() + } }() - normalizedQuery, parameters, err := c.normalize(queryString, args...) + err := c.session.Close(xcontext.ValueOnly(c.ctx)) if err != nil { - return nil, xerrors.WithStackTrace(err) + return xerrors.WithStackTrace(err) } - return c.queryContextOther(ctx, normalizedQuery, parameters) + return nil } -func (c *Conn) queryContextOther( - ctx context.Context, - queryString string, - parameters params.Parameters, -) (driver.Rows, error) { - res, err := c.session.Query( - ctx, queryString, - options.WithParameters(parameters), - ) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - return &rows{ - conn: c, - result: res, - }, nil +func (c *Conn) Begin() (driver.Tx, error) { + return nil, errDeprecated } diff --git a/internal/query/conn/driver.impls.go b/internal/query/conn/driver.impls.go deleted file mode 100644 index 0db36ed3f..000000000 --- a/internal/query/conn/driver.impls.go +++ /dev/null @@ -1,157 +0,0 @@ -package conn - -import ( - "context" - "database/sql/driver" - "time" - - "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" - "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/trace" -) - -var ( - _ driver.Conn = &Conn{} - _ driver.ConnPrepareContext = &Conn{} - _ driver.ConnBeginTx = &Conn{} - _ driver.ExecerContext = &Conn{} - _ driver.QueryerContext = &Conn{} - _ driver.Pinger = &Conn{} - _ driver.Validator = &Conn{} - _ driver.NamedValueChecker = &Conn{} -) - -func (c *Conn) ID() string { - return c.session.ID() -} - -func (c *Conn) IsValid() bool { - return c.isReady() -} - -func (c *Conn) CheckNamedValue(value *driver.NamedValue) error { - return nil -} - -func (c *Conn) Ping(ctx context.Context) (finalErr error) { - onDone := trace.DatabaseSQLOnConnPing(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).Ping"), - ) - defer func() { - onDone(finalErr) - }() - - if !c.isReady() { - return xerrors.WithStackTrace(errNotReadyConn) - } - - if !c.session.Core.IsAlive() { - return xerrors.WithStackTrace(errNotReadyConn) - } - - err := c.session.Exec(ctx, "select 1") - - return err -} - -func (c *Conn) PrepareContext(ctx context.Context, query string) (_ driver.Stmt, finalErr error) { - if c.currentTx != nil { - return c.currentTx.PrepareContext(ctx, query) - } - - onDone := trace.DatabaseSQLOnConnPrepare(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).PrepareContext"), - query, - ) - defer func() { - onDone(finalErr) - }() - - if !c.isReady() { - return nil, xerrors.WithStackTrace(errNotReadyConn) - } - - return &stmt{ - conn: c, - processor: c, - ctx: ctx, - query: query, - }, nil -} - -func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (driver.Tx, error) { - tx, err := c.beginTx(ctx, txOptions) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - return tx, nil -} - -func (c *Conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { - if !c.IsValid() { - return nil, xerrors.WithStackTrace(errNotReadyConn) - } - - if c.currentTx != nil { - return c.currentTx.ExecContext(ctx, query, args) - } - - return c.execContext(ctx, query, args) -} - -func (c *Conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { - if !c.isReady() { - return nil, xerrors.WithStackTrace(errNotReadyConn) - } - if c.currentTx != nil { - return c.currentTx.QueryContext(ctx, query, args) - } - - return c.queryContext(ctx, query, args) -} - -func (c *Conn) Prepare(query string) (driver.Stmt, error) { - return nil, errDeprecated -} - -func (c *Conn) Close() (finalErr error) { - if !c.closed.CompareAndSwap(false, true) { - return xerrors.WithStackTrace(errConnClosedEarly) - } - - defer func() { - for _, onClose := range c.onClose { - onClose() - } - }() - - var ( - ctx = c.ctx - onDone = trace.DatabaseSQLOnConnClose( - c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*Conn).Close"), - ) - ) - defer func() { - onDone(finalErr) - }() - if c.currentTx != nil { - _ = c.currentTx.Rollback() - } - err := c.session.Close(xcontext.ValueOnly(ctx)) - if err != nil { - return xerrors.WithStackTrace(err) - } - - return nil -} - -func (c *Conn) Begin() (driver.Tx, error) { - return nil, errDeprecated -} - -func (c *Conn) LastUsage() time.Time { - return time.Unix(c.lastUsage.Load(), 0) -} diff --git a/internal/query/conn/tx.go b/internal/query/conn/tx.go index 56e6e4e8e..95c60575e 100644 --- a/internal/query/conn/tx.go +++ b/internal/query/conn/tx.go @@ -3,133 +3,36 @@ package conn import ( "context" "database/sql/driver" - "fmt" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/query" - "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) type transaction struct { - tx.Identifier - conn *Conn - ctx context.Context //nolint:containedctx tx query.Transaction } -var ( - _ driver.Tx = &transaction{} - _ driver.ExecerContext = &transaction{} - _ driver.QueryerContext = &transaction{} - _ tx.Identifier = &transaction{} -) - -func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (currentTx, error) { - txc, err := isolation.ToYDB(txOptions) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - nativeTx, err := c.session.Begin(ctx, query.TxSettings(txc)) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - return &transaction{ - Identifier: tx.ID(nativeTx.ID()), - conn: c, - ctx: ctx, - tx: nativeTx, - }, nil -} - -func (tx *transaction) checkTxState() error { - if tx.conn.currentTx == tx { - return nil - } - - if tx.conn.currentTx == nil { - return fmt.Errorf("broken conn state: tx=%q not related to conn=%q", - tx.ID(), tx.conn.ID(), - ) - } - - return fmt.Errorf("broken conn state: tx=%s not related to conn=%q (conn have current tx=%q)", - tx.conn.currentTx.ID(), tx.conn.ID(), tx.ID(), - ) -} - -func (tx *transaction) Commit() (finalErr error) { - var ( - ctx = tx.ctx - onDone = trace.DatabaseSQLOnTxCommit(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*transaction).Commit"), - tx, - ) - ) - defer func() { - onDone(finalErr) - }() - if err := tx.checkTxState(); err != nil { - return xerrors.WithStackTrace(err) - } - defer func() { - tx.conn.currentTx = nil - }() - if err := tx.tx.CommitTx(tx.ctx); err != nil { - return xerrors.WithStackTrace(err) - } - - return nil +func (tx *transaction) ID() string { + return tx.tx.ID() } -func (tx *transaction) Rollback() (finalErr error) { - var ( - ctx = tx.ctx - onDone = trace.DatabaseSQLOnTxRollback(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*transaction).Rollback"), - tx, - ) - ) - defer func() { - onDone(finalErr) - }() - if err := tx.checkTxState(); err != nil { - return xerrors.WithStackTrace(err) - } - defer func() { - tx.conn.currentTx = nil - }() - err := tx.tx.Rollback(tx.ctx) +func (tx *transaction) Exec(ctx context.Context, sql string, params *params.Params) (driver.Result, error) { + err := tx.tx.Exec(ctx, sql, options.WithParameters(params)) if err != nil { - return xerrors.WithStackTrace(err) + return nil, xerrors.WithStackTrace(err) } - return err + return resultNoRows{}, nil } -func (tx *transaction) QueryContext(ctx context.Context, query string, args []driver.NamedValue) ( - _ driver.Rows, finalErr error, -) { - onDone := trace.DatabaseSQLOnTxQuery(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*transaction).QueryContext"), - tx.ctx, tx, query, - ) - defer func() { - onDone(finalErr) - }() - - query, parameters, err := tx.conn.normalize(query, args...) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } +func (tx *transaction) Query(ctx context.Context, sql string, params *params.Params) (driver.RowsNextResultSet, error) { res, err := tx.tx.Query(ctx, - query, options.WithParameters(parameters), + sql, options.WithParameters(params), ) if err != nil { return nil, xerrors.WithStackTrace(err) @@ -141,47 +44,36 @@ func (tx *transaction) QueryContext(ctx context.Context, query string, args []dr }, nil } -func (tx *transaction) ExecContext(ctx context.Context, query string, args []driver.NamedValue) ( - _ driver.Result, finalErr error, -) { - onDone := trace.DatabaseSQLOnTxExec(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*transaction).ExecContext"), - tx.ctx, tx, query, - ) - defer func() { - onDone(finalErr) - }() - - query, parameters, err := tx.conn.normalize(query, args...) +func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (iface.Tx, error) { + txc, err := isolation.ToYDB(txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) } - err = tx.tx.Exec(ctx, - query, options.WithParameters(parameters), - ) + + nativeTx, err := c.session.Begin(ctx, query.TxSettings(txc)) if err != nil { return nil, xerrors.WithStackTrace(err) } - return resultNoRows{}, nil + return &transaction{ + conn: c, + tx: nativeTx, + }, nil } -func (tx *transaction) PrepareContext(ctx context.Context, query string) (_ driver.Stmt, finalErr error) { - onDone := trace.DatabaseSQLOnTxPrepare(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn.(*transaction).PrepareContext"), - tx.ctx, tx, query, - ) - defer func() { - onDone(finalErr) - }() - if !tx.conn.isReady() { - return nil, xerrors.WithStackTrace(errNotReadyConn) +func (tx *transaction) Commit(ctx context.Context) (finalErr error) { + if err := tx.tx.CommitTx(ctx); err != nil { + return xerrors.WithStackTrace(err) } - return &stmt{ - conn: tx.conn, - processor: tx, - ctx: ctx, - query: query, - }, nil + return nil +} + +func (tx *transaction) Rollback(ctx context.Context) (finalErr error) { + err := tx.tx.Rollback(ctx) + if err != nil { + return xerrors.WithStackTrace(err) + } + + return err } diff --git a/internal/table/conn/conn.go b/internal/table/conn/conn.go index 96e9cde7f..4618ff817 100644 --- a/internal/table/conn/conn.go +++ b/internal/table/conn/conn.go @@ -9,32 +9,20 @@ import ( "sync/atomic" "time" - "github.com/jonboulle/clockwork" - - "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "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/retry/budget" "github.com/ydb-platform/ydb-go-sdk/v3/scripting" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" - "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) type ( Parent interface { Table() table.Client Scripting() scripting.Client - - Trace() *trace.DatabaseSQL - TraceRetry() *trace.Retry - RetryBudget() budget.Budget - Bindings() bind.Bindings - Clock() clockwork.Clock } Conn struct { ctx context.Context //nolint:containedctx @@ -45,7 +33,6 @@ type ( fakeTxModes []QueryMode closed atomic.Bool - lastUsage atomic.Int64 defaultQueryMode QueryMode defaultTxControl *table.TransactionControl @@ -53,13 +40,50 @@ type ( scanOpts []options.ExecuteScanQueryOption - currentTx currentTx idleThreshold time.Duration onClose []func() } ) -func (c *Conn) Explain(ctx context.Context, sql string) (ast string, plan string, err error) { +func (c *Conn) Exec(ctx context.Context, sql string, params *params.Params) (result driver.Result, err error) { + if !c.isReady() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + m := queryModeFromContext(ctx, c.defaultQueryMode) + + switch m { + case DataQueryMode: + return c.executeDataQuery(ctx, sql, params) + case SchemeQueryMode: + return c.executeSchemeQuery(ctx, sql) + case ScriptingQueryMode: + return c.executeScriptingQuery(ctx, sql, params) + default: + return nil, fmt.Errorf("unsupported query mode '%s' for execute query", m) + } +} + +func (c *Conn) Query(ctx context.Context, sql string, params *params.Params) ( + result driver.RowsNextResultSet, finalErr error, +) { + if !c.isReady() { + return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + switch queryMode := queryModeFromContext(ctx, c.defaultQueryMode); queryMode { + case DataQueryMode: + return c.execDataQuery(ctx, sql, params) + case ScanQueryMode: + return c.execScanQuery(ctx, sql, params) + case ScriptingQueryMode: + return c.execScriptingQuery(ctx, sql, params) + default: + return nil, fmt.Errorf("unsupported query mode '%s' on conn query", queryMode) + } +} + +func (c *Conn) Explain(ctx context.Context, sql string, _ *params.Params) (ast string, plan string, err error) { exp, err := c.session.Explain(ctx, sql) if err != nil { return "", "", badconn.Map(xerrors.WithStackTrace(err)) @@ -68,10 +92,6 @@ func (c *Conn) Explain(ctx context.Context, sql string) (ast string, plan string return exp.AST, exp.Plan, nil } -func (c *Conn) LastUsage() time.Time { - return time.Unix(c.lastUsage.Load(), 0) -} - func (c *Conn) CheckNamedValue(*driver.NamedValue) error { // on this stage allows all values return nil @@ -81,32 +101,11 @@ func (c *Conn) IsValid() bool { return c.isReady() } -type currentTx interface { - tx.Identifier - driver.Tx - driver.ExecerContext - driver.QueryerContext - driver.ConnPrepareContext -} - type resultNoRows struct{} func (resultNoRows) LastInsertId() (int64, error) { return 0, ErrUnsupported } func (resultNoRows) RowsAffected() (int64, error) { return 0, ErrUnsupported } -var ( - _ driver.Conn = &Conn{} - _ driver.ConnPrepareContext = &Conn{} - _ driver.ConnBeginTx = &Conn{} - _ driver.ExecerContext = &Conn{} - _ driver.QueryerContext = &Conn{} - _ driver.Pinger = &Conn{} - _ driver.Validator = &Conn{} - _ driver.NamedValueChecker = &Conn{} - - _ driver.Result = resultNoRows{} -) - func New(ctx context.Context, parent Parent, s table.ClosableSession, opts ...Option) *Conn { cc := &Conn{ ctx: ctx, @@ -114,6 +113,9 @@ func New(ctx context.Context, parent Parent, s table.ClosableSession, opts ...Op session: s, defaultQueryMode: DataQueryMode, defaultTxControl: table.DefaultTxControl(), + dataOpts: []options.ExecuteDataQueryOption{ + options.WithKeepInCache(true), + }, } for _, opt := range opts { @@ -129,77 +131,10 @@ func (c *Conn) isReady() bool { return c.session.Status() == table.SessionReady } -func (c *Conn) PrepareContext(ctx context.Context, query string) (_ driver.Stmt, finalErr error) { - if c.currentTx != nil { - return c.currentTx.PrepareContext(ctx, query) - } - onDone := trace.DatabaseSQLOnConnPrepare(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).PrepareContext"), - query, - ) - defer func() { - onDone(finalErr) - }() - - if !c.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) - } - - return &stmt{ - conn: c, - processor: c, - ctx: ctx, - query: query, - }, nil -} - -func (c *Conn) execContext( - ctx context.Context, - query string, - args []driver.NamedValue, -) (_ driver.Result, finalErr error) { - defer func() { - c.lastUsage.Store(c.parent.Clock().Now().Unix()) - }() - - if !c.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) - } - - if c.currentTx != nil { - return c.currentTx.ExecContext(ctx, query, args) - } - - m := queryModeFromContext(ctx, c.defaultQueryMode) - onDone := trace.DatabaseSQLOnConnExec(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).execContext"), - query, m.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), - ) - defer func() { - onDone(finalErr) - }() - - switch m { - case DataQueryMode: - return c.executeDataQuery(ctx, query, args) - case SchemeQueryMode: - return c.executeSchemeQuery(ctx, query) - case ScriptingQueryMode: - return c.executeScriptingQuery(ctx, query, args) - default: - return nil, fmt.Errorf("unsupported query mode '%s' for execute query", m) - } -} - -func (c *Conn) executeDataQuery(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { - normalizedQuery, parameters, err := c.normalize(query, args...) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - +func (c *Conn) executeDataQuery(ctx context.Context, sql string, params *params.Params) (driver.Result, error) { _, res, err := c.session.Execute(ctx, txControl(ctx, c.defaultTxControl), - normalizedQuery, ¶meters, c.dataQueryOptions(ctx)..., + sql, params, c.dataQueryOptions(ctx)..., ) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) @@ -216,30 +151,18 @@ func (c *Conn) executeDataQuery(ctx context.Context, query string, args []driver return resultNoRows{}, nil } -func (c *Conn) executeSchemeQuery(ctx context.Context, query string) (driver.Result, error) { - normalizedQuery, _, err := c.normalize(query) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - if err := c.session.ExecuteSchemeQuery(ctx, normalizedQuery); err != nil { +func (c *Conn) executeSchemeQuery(ctx context.Context, sql string) (driver.Result, error) { + if err := c.session.ExecuteSchemeQuery(ctx, sql); err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } return resultNoRows{}, nil } -func (c *Conn) executeScriptingQuery( - ctx context.Context, - query string, - args []driver.NamedValue, -) (driver.Result, error) { - normalizedQuery, parameters, err := c.normalize(query, args...) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - res, err := c.parent.Scripting().StreamExecute(ctx, normalizedQuery, ¶meters) +func (c *Conn) executeScriptingQuery(ctx context.Context, sql string, params *params.Params) ( + driver.Result, error, +) { + res, err := c.parent.Scripting().StreamExecute(ctx, sql, params) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } @@ -255,75 +178,12 @@ func (c *Conn) executeScriptingQuery( return resultNoRows{}, nil } -func (c *Conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (_ driver.Result, _ error) { - if !c.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) - } - if c.currentTx != nil { - return c.currentTx.ExecContext(ctx, query, args) - } - - return c.execContext(ctx, query, args) -} - -func (c *Conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (_ driver.Rows, _ error) { - if !c.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) - } - if c.currentTx != nil { - return c.currentTx.QueryContext(ctx, query, args) - } - - return c.queryContext(ctx, query, args) -} - -func (c *Conn) queryContext(ctx context.Context, query string, args []driver.NamedValue) ( - _ driver.Rows, finalErr error, +func (c *Conn) execDataQuery(ctx context.Context, query string, params *params.Params) ( + driver.RowsNextResultSet, error, ) { - defer func() { - c.lastUsage.Store(c.parent.Clock().Now().Unix()) - }() - - if !c.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) - } - - if c.currentTx != nil { - return c.currentTx.QueryContext(ctx, query, args) - } - - var ( - queryMode = queryModeFromContext(ctx, c.defaultQueryMode) - onDone = trace.DatabaseSQLOnConnQuery(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).queryContext"), - query, queryMode.String(), xcontext.IsIdempotent(ctx), c.parent.Clock().Since(c.LastUsage()), - ) - ) - defer func() { - onDone(finalErr) - }() - - normalizedQuery, parameters, err := c.normalize(query, args...) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - switch queryMode { - case DataQueryMode: - return c.execDataQuery(ctx, normalizedQuery, parameters) - case ScanQueryMode: - return c.execScanQuery(ctx, normalizedQuery, parameters) - case ScriptingQueryMode: - return c.execScriptingQuery(ctx, normalizedQuery, parameters) - default: - return nil, fmt.Errorf("unsupported query mode '%s' on conn query", queryMode) - } -} - -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)..., + query, params, c.dataQueryOptions(ctx)..., ) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) @@ -338,9 +198,11 @@ func (c *Conn) execDataQuery(ctx context.Context, query string, params params.Pa }, nil } -func (c *Conn) execScanQuery(ctx context.Context, query string, params params.Params) (driver.Rows, error) { +func (c *Conn) execScanQuery(ctx context.Context, query string, params *params.Params) ( + driver.RowsNextResultSet, error, +) { res, err := c.session.StreamExecuteScanQuery(ctx, - query, ¶ms, c.scanQueryOptions(ctx)..., + query, params, c.scanQueryOptions(ctx)..., ) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) @@ -355,8 +217,10 @@ func (c *Conn) execScanQuery(ctx context.Context, query string, params params.Pa }, nil } -func (c *Conn) execScriptingQuery(ctx context.Context, query string, params params.Params) (driver.Rows, error) { - res, err := c.parent.Scripting().StreamExecute(ctx, query, ¶ms) +func (c *Conn) execScriptingQuery(ctx context.Context, query string, params *params.Params) ( + driver.RowsNextResultSet, error, +) { + res, err := c.parent.Scripting().StreamExecute(ctx, query, params) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } @@ -371,12 +235,6 @@ func (c *Conn) execScriptingQuery(ctx context.Context, query string, params para } func (c *Conn) Ping(ctx context.Context) (finalErr error) { - onDone := trace.DatabaseSQLOnConnPing(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).Ping"), - ) - defer func() { - onDone(finalErr) - }() if !c.isReady() { return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } @@ -398,19 +256,7 @@ func (c *Conn) Close() (finalErr error) { } }() - var ( - ctx = c.ctx - onDone = trace.DatabaseSQLOnConnClose(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).Close"), - ) - ) - defer func() { - onDone(finalErr) - }() - if c.currentTx != nil { - _ = c.currentTx.Rollback() - } - err := c.session.Close(xcontext.ValueOnly(ctx)) + err := c.session.Close(xcontext.ValueOnly(c.ctx)) if err != nil { return badconn.Map(xerrors.WithStackTrace(err)) } @@ -418,42 +264,11 @@ func (c *Conn) Close() (finalErr error) { return nil } -func (c *Conn) Prepare(string) (driver.Stmt, error) { - return nil, errDeprecated -} - -func (c *Conn) Begin() (driver.Tx, error) { - return nil, errDeprecated -} - -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]) - } - - return ii - }()...) -} - func (c *Conn) ID() string { return c.session.ID() } -func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx currentTx, finalErr error) { - onDone := trace.DatabaseSQLOnConnBegin(c.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*Conn).beginTx"), - ) - defer func() { - onDone(tx, finalErr) - }() - - if c.currentTx != nil { - return nil, badconn.Map( - xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())), - ) - } - +func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx iface.Tx, finalErr error) { m := queryModeFromContext(ctx, c.defaultQueryMode) if slices.Contains(c.fakeTxModes, m) { @@ -465,12 +280,10 @@ func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx curr return nil, xerrors.WithStackTrace(err) } - c.currentTx = tx - return tx, nil } -func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (driver.Tx, error) { +func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (iface.Tx, error) { tx, err := c.beginTx(ctx, txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) diff --git a/internal/table/conn/context.go b/internal/table/conn/context.go index 7772e5881..e8b455d6d 100644 --- a/internal/table/conn/context.go +++ b/internal/table/conn/context.go @@ -72,7 +72,3 @@ func (c *Conn) dataQueryOptions(ctx context.Context) []options.ExecuteDataQueryO return c.dataOpts } - -func (c *Conn) withKeepInCache(ctx context.Context) context.Context { - return c.WithDataQueryOptions(ctx, options.WithKeepInCache(true)) -} diff --git a/internal/table/conn/errors.go b/internal/table/conn/errors.go index 6dc9e29de..cf3370206 100644 --- a/internal/table/conn/errors.go +++ b/internal/table/conn/errors.go @@ -9,7 +9,6 @@ import ( var ( ErrUnsupported = driver.ErrSkip - errDeprecated = driver.ErrSkip errConnClosedEarly = xerrors.Retryable(errors.New("conn closed early"), xerrors.InvalidObject()) errNotReadyConn = xerrors.Retryable(errors.New("conn not ready"), xerrors.InvalidObject()) ) diff --git a/internal/table/conn/options.go b/internal/table/conn/options.go index 9d5f77ed7..c99558f46 100644 --- a/internal/table/conn/options.go +++ b/internal/table/conn/options.go @@ -20,7 +20,7 @@ func WithFakeTxModes(modes ...QueryMode) Option { func WithDataOpts(dataOpts ...options.ExecuteDataQueryOption) Option { return func(c *Conn) { - c.dataOpts = dataOpts + c.dataOpts = append(c.dataOpts, dataOpts...) } } diff --git a/internal/table/conn/stmt.go b/internal/table/conn/stmt.go deleted file mode 100644 index 34075ea82..000000000 --- a/internal/table/conn/stmt.go +++ /dev/null @@ -1,92 +0,0 @@ -package conn - -import ( - "context" - "database/sql/driver" - "fmt" - - "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" - "github.com/ydb-platform/ydb-go-sdk/v3/trace" -) - -type stmt struct { - conn *Conn - processor interface { - driver.ExecerContext - driver.QueryerContext - } - query string - ctx context.Context //nolint:containedctx -} - -var ( - _ driver.Stmt = &stmt{} - _ driver.StmtQueryContext = &stmt{} - _ driver.StmtExecContext = &stmt{} -) - -func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ driver.Rows, finalErr error) { - onDone := trace.DatabaseSQLOnStmtQuery(stmt.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*stmt).QueryContext"), - stmt.ctx, stmt.query, - ) - defer func() { - onDone(finalErr) - }() - if !stmt.conn.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) - } - switch m := queryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { - case DataQueryMode: - return stmt.processor.QueryContext(stmt.conn.withKeepInCache(ctx), stmt.query, args) - default: - return nil, fmt.Errorf("unsupported query mode '%s' for execute query on prepared statement", m) - } -} - -func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ driver.Result, finalErr error) { - onDone := trace.DatabaseSQLOnStmtExec(stmt.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*stmt).ExecContext"), - stmt.ctx, stmt.query, - ) - defer func() { - onDone(finalErr) - }() - if !stmt.conn.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) - } - switch m := queryModeFromContext(ctx, stmt.conn.defaultQueryMode); m { - case DataQueryMode: - return stmt.processor.ExecContext(stmt.conn.withKeepInCache(ctx), stmt.query, args) - default: - return nil, fmt.Errorf("unsupported query mode '%s' for execute query on prepared statement", m) - } -} - -func (stmt *stmt) NumInput() int { - return -1 -} - -func (stmt *stmt) Close() (finalErr error) { - var ( - ctx = stmt.ctx - onDone = trace.DatabaseSQLOnStmtClose(stmt.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*stmt).Close"), - ) - ) - defer func() { - onDone(finalErr) - }() - - return nil -} - -func (stmt *stmt) Exec([]driver.Value) (driver.Result, error) { - return nil, errDeprecated -} - -func (stmt *stmt) Query([]driver.Value) (driver.Rows, error) { - return nil, errDeprecated -} diff --git a/internal/table/conn/tx.go b/internal/table/conn/tx.go index d879be18e..4b04c9d34 100644 --- a/internal/table/conn/tx.go +++ b/internal/table/conn/tx.go @@ -5,122 +5,47 @@ import ( "database/sql/driver" "fmt" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/isolation" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/table" - "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) -type transaction struct { - tx.Identifier +var _ iface.Tx = (*transaction)(nil) +type transaction struct { conn *Conn - ctx context.Context //nolint:containedctx tx table.Transaction } -var ( - _ driver.Tx = &transaction{} - _ driver.ExecerContext = &transaction{} - _ driver.QueryerContext = &transaction{} - _ tx.Identifier = &transaction{} -) - -func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (currentTx, error) { - txc, err := isolation.ToYDB(txOptions) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - nativeTx, err := c.session.BeginTransaction(ctx, table.TxSettings(txc)) - if err != nil { - return nil, badconn.Map(xerrors.WithStackTrace(err)) - } - - return &transaction{ - Identifier: tx.ID(nativeTx.ID()), - conn: c, - ctx: ctx, - tx: nativeTx, - }, nil +func (tx *transaction) ID() string { + return tx.tx.ID() } -func (tx *transaction) checkTxState() error { - if tx.conn.currentTx == tx { - return nil - } - if tx.conn.currentTx == nil { - return fmt.Errorf("broken conn state: tx=%q not related to conn=%q", - tx.ID(), tx.conn.ID(), - ) - } - - return fmt.Errorf("broken conn state: tx=%s not related to conn=%q (conn have current tx=%q)", - tx.conn.currentTx.ID(), tx.conn.ID(), tx.ID(), - ) -} - -func (tx *transaction) Commit() (finalErr error) { - var ( - ctx = tx.ctx - onDone = trace.DatabaseSQLOnTxCommit(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*transaction).Commit"), - tx, - ) - ) - defer func() { - onDone(finalErr) - }() - if err := tx.checkTxState(); err != nil { - return badconn.Map(xerrors.WithStackTrace(err)) - } - defer func() { - tx.conn.currentTx = nil - }() - if _, err := tx.tx.CommitTx(tx.ctx); err != nil { - return badconn.Map(xerrors.WithStackTrace(err)) - } - - return nil -} - -func (tx *transaction) Rollback() (finalErr error) { - var ( - ctx = tx.ctx - onDone = trace.DatabaseSQLOnTxRollback(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*transaction).Rollback"), - tx, +func (tx *transaction) Exec(ctx context.Context, sql string, params *params.Params) (driver.Result, error) { + m := queryModeFromContext(ctx, tx.conn.defaultQueryMode) + if m != DataQueryMode { + return nil, badconn.Map( + xerrors.WithStackTrace( + xerrors.Retryable( + fmt.Errorf("wrong query mode: %s", m.String()), + xerrors.InvalidObject(), + xerrors.WithName("WRONG_QUERY_MODE"), + ), + ), ) - ) - defer func() { - onDone(finalErr) - }() - if err := tx.checkTxState(); err != nil { - return badconn.Map(xerrors.WithStackTrace(err)) } - defer func() { - tx.conn.currentTx = nil - }() - err := tx.tx.Rollback(tx.ctx) + _, err := tx.tx.Execute(ctx, sql, params, tx.conn.dataQueryOptions(ctx)...) if err != nil { - return badconn.Map(xerrors.WithStackTrace(err)) + return nil, badconn.Map(xerrors.WithStackTrace(err)) } - return err + return resultNoRows{}, nil } -func (tx *transaction) QueryContext(ctx context.Context, query string, args []driver.NamedValue) ( - _ driver.Rows, finalErr error, -) { - onDone := trace.DatabaseSQLOnTxQuery(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*transaction).QueryContext"), - tx.ctx, tx, query, - ) - defer func() { - onDone(finalErr) - }() +func (tx *transaction) Query(ctx context.Context, sql string, params *params.Params) (driver.RowsNextResultSet, error) { m := queryModeFromContext(ctx, tx.conn.defaultQueryMode) if m != DataQueryMode { return nil, badconn.Map( @@ -133,16 +58,13 @@ func (tx *transaction) QueryContext(ctx context.Context, query string, args []dr ), ) } - query, parameters, err := tx.conn.normalize(query, args...) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } res, err := tx.tx.Execute(ctx, - query, ¶meters, tx.conn.dataQueryOptions(ctx)..., + sql, params, tx.conn.dataQueryOptions(ctx)..., ) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } + if err = res.Err(); err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } @@ -153,58 +75,35 @@ func (tx *transaction) QueryContext(ctx context.Context, query string, args []dr }, nil } -func (tx *transaction) ExecContext(ctx context.Context, query string, args []driver.NamedValue) ( - _ driver.Result, finalErr error, -) { - onDone := trace.DatabaseSQLOnTxExec(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*transaction).ExecContext"), - tx.ctx, tx, query, - ) - defer func() { - onDone(finalErr) - }() - m := queryModeFromContext(ctx, tx.conn.defaultQueryMode) - if m != DataQueryMode { - return nil, badconn.Map( - xerrors.WithStackTrace( - xerrors.Retryable( - fmt.Errorf("wrong query mode: %s", m.String()), - xerrors.InvalidObject(), - xerrors.WithName("WRONG_QUERY_MODE"), - ), - ), - ) +func (tx *transaction) Rollback(ctx context.Context) error { + err := tx.tx.Rollback(ctx) + if err != nil { + return badconn.Map(xerrors.WithStackTrace(err)) } - query, parameters, err := tx.conn.normalize(query, args...) + + return err +} + +func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (iface.Tx, error) { + txc, err := isolation.ToYDB(txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) } - _, err = tx.tx.Execute(ctx, - query, ¶meters, tx.conn.dataQueryOptions(ctx)..., - ) + nativeTx, err := c.session.BeginTransaction(ctx, table.TxSettings(txc)) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } - return resultNoRows{}, nil + return &transaction{ + conn: c, + tx: nativeTx, + }, nil } -func (tx *transaction) PrepareContext(ctx context.Context, query string) (_ driver.Stmt, finalErr error) { - onDone := trace.DatabaseSQLOnTxPrepare(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*transaction).PrepareContext"), - tx.ctx, tx, query, - ) - defer func() { - onDone(finalErr) - }() - if !tx.conn.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) +func (tx *transaction) Commit(ctx context.Context) (finalErr error) { + if _, err := tx.tx.CommitTx(ctx); err != nil { + return badconn.Map(xerrors.WithStackTrace(err)) } - return &stmt{ - conn: tx.conn, - processor: tx, - ctx: ctx, - query: query, - }, nil + return nil } diff --git a/internal/table/conn/tx_fake.go b/internal/table/conn/tx_fake.go index f87073c8c..9a58bef66 100644 --- a/internal/table/conn/tx_fake.go +++ b/internal/table/conn/tx_fake.go @@ -4,49 +4,39 @@ import ( "context" "database/sql/driver" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" - "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) type txFake struct { tx.Identifier - beginCtx context.Context //nolint:containedctx - conn *Conn - ctx context.Context //nolint:containedctx + conn *Conn + ctx context.Context //nolint:containedctx } -func (tx *txFake) PrepareContext(ctx context.Context, query string) (_ driver.Stmt, finalErr error) { - onDone := trace.DatabaseSQLOnTxPrepare(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*txFake).PrepareContext"), - tx.beginCtx, tx, query, - ) - defer func() { - onDone(finalErr) - }() - if !tx.conn.isReady() { - return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) +func (tx *txFake) Exec(ctx context.Context, sql string, params *params.Params) (driver.Result, error) { + result, err := tx.conn.Exec(ctx, sql, params) + if err != nil { + return nil, xerrors.WithStackTrace(err) } - return &stmt{ - conn: tx.conn, - processor: tx, - ctx: ctx, - query: query, - }, nil + return result, nil } -var ( - _ driver.Tx = &txFake{} - _ driver.ExecerContext = &txFake{} - _ driver.QueryerContext = &txFake{} - _ tx.Identifier = &txFake{} -) +func (tx *txFake) Query(ctx context.Context, sql string, params *params.Params) (driver.RowsNextResultSet, error) { + rows, err := tx.conn.Query(ctx, sql, params) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return rows, nil +} -func beginTxFake(ctx context.Context, c *Conn) currentTx { +func beginTxFake(ctx context.Context, c *Conn) iface.Tx { return &txFake{ Identifier: tx.ID("FAKE"), conn: c, @@ -54,20 +44,7 @@ func beginTxFake(ctx context.Context, c *Conn) currentTx { } } -func (tx *txFake) Commit() (err error) { - var ( - ctx = tx.ctx - onDone = trace.DatabaseSQLOnTxCommit(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*txFake).Commit"), - tx, - ) - ) - defer func() { - onDone(err) - }() - defer func() { - tx.conn.currentTx = nil - }() +func (tx *txFake) Commit(ctx context.Context) (err error) { if !tx.conn.isReady() { return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } @@ -75,59 +52,10 @@ func (tx *txFake) Commit() (err error) { return nil } -func (tx *txFake) Rollback() (err error) { - var ( - ctx = tx.ctx - onDone = trace.DatabaseSQLOnTxRollback(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*txFake).Rollback"), - tx, - ) - ) - defer func() { - onDone(err) - }() - defer func() { - tx.conn.currentTx = nil - }() +func (tx *txFake) Rollback(ctx context.Context) (err error) { if !tx.conn.isReady() { return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } return err } - -func (tx *txFake) QueryContext(ctx context.Context, query string, args []driver.NamedValue) ( - rows driver.Rows, err error, -) { - onDone := trace.DatabaseSQLOnTxQuery(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*txFake).QueryContext"), - tx.ctx, tx, query, - ) - defer func() { - onDone(err) - }() - rows, err = tx.conn.QueryContext(ctx, query, args) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - return rows, nil -} - -func (tx *txFake) ExecContext(ctx context.Context, query string, args []driver.NamedValue) ( - result driver.Result, err error, -) { - onDone := trace.DatabaseSQLOnTxExec(tx.conn.parent.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn.(*txFake).ExecContext"), - tx.ctx, tx, query, - ) - defer func() { - onDone(err) - }() - result, err = tx.conn.ExecContext(ctx, query, args) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - return result, nil -} From e52398c0cb9d0914fcff180a7c3c549acc0e4f62 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Tue, 10 Dec 2024 22:18:52 +0300 Subject: [PATCH 47/48] moved internal/{table,query}/conn to internal/connector/{table,query} --- dsn.go | 2 +- dsn_test.go | 30 +++++++++---------- internal/connector/connector.go | 16 +++++----- internal/connector/options.go | 24 +++++++-------- internal/{ => connector}/query/conn/conn.go | 0 internal/{ => connector}/query/conn/errors.go | 0 .../query/conn/isolation/isolation.go | 0 .../{ => connector}/query/conn/options.go | 0 internal/{ => connector}/query/conn/rows.go | 0 internal/{ => connector}/query/conn/tx.go | 2 +- .../table/conn/badconn/badconn.go | 0 .../table/conn/badconn/badconn_test.go | 0 internal/{ => connector}/table/conn/conn.go | 2 +- .../{ => connector}/table/conn/context.go | 0 internal/{ => connector}/table/conn/errors.go | 0 .../table/conn/isolation/isolation.go | 0 .../table/conn/isolation/isolation_test.go | 0 internal/{ => connector}/table/conn/mode.go | 0 .../{ => connector}/table/conn/options.go | 0 internal/{ => connector}/table/conn/rows.go | 2 +- internal/{ => connector}/table/conn/tx.go | 4 +-- .../{ => connector}/table/conn/tx_fake.go | 2 +- internal/{ => connector}/table/conn/valuer.go | 0 internal/connector/tx.go | 2 +- internal/connector/unwrap.go | 2 +- retry/errors.go | 2 +- retry/sql_test.go | 2 +- sql.go | 24 +++++++-------- .../database_sql_regression_test.go | 2 +- .../database_sql_with_tx_control_test.go | 2 +- 30 files changed, 60 insertions(+), 60 deletions(-) rename internal/{ => connector}/query/conn/conn.go (100%) rename internal/{ => connector}/query/conn/errors.go (100%) rename internal/{ => connector}/query/conn/isolation/isolation.go (100%) rename internal/{ => connector}/query/conn/options.go (100%) rename internal/{ => connector}/query/conn/rows.go (100%) rename internal/{ => connector}/query/conn/tx.go (95%) rename internal/{ => connector}/table/conn/badconn/badconn.go (100%) rename internal/{ => connector}/table/conn/badconn/badconn_test.go (100%) rename internal/{ => connector}/table/conn/conn.go (98%) rename internal/{ => connector}/table/conn/context.go (100%) rename internal/{ => connector}/table/conn/errors.go (100%) rename internal/{ => connector}/table/conn/isolation/isolation.go (100%) rename internal/{ => connector}/table/conn/isolation/isolation_test.go (100%) rename internal/{ => connector}/table/conn/mode.go (100%) rename internal/{ => connector}/table/conn/options.go (100%) rename internal/{ => connector}/table/conn/rows.go (97%) rename internal/{ => connector}/table/conn/tx.go (94%) rename internal/{ => connector}/table/conn/tx_fake.go (94%) rename internal/{ => connector}/table/conn/valuer.go (100%) diff --git a/dsn.go b/dsn.go index 054b84f71..32f311740 100644 --- a/dsn.go +++ b/dsn.go @@ -10,8 +10,8 @@ import ( "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" + tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" "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" ) diff --git a/dsn_test.go b/dsn_test.go index a2fa0c789..8afa5b41d 100644 --- a/dsn_test.go +++ b/dsn_test.go @@ -9,8 +9,8 @@ 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/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" + conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/query/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" ) func TestParse(t *testing.T) { @@ -26,11 +26,11 @@ func TestParse(t *testing.T) { return c } - newTableConn := func(opts ...tableSql.Option) *tableSql.Conn { - return tableSql.New(context.Background(), nil, nil, opts...) + newTableConn := func(opts ...conn.Option) *conn.Conn { + return conn.New(context.Background(), nil, nil, opts...) } - newQueryConn := func(opts ...querySql.Option) *querySql.Conn { - return querySql.New(context.Background(), nil, nil, opts...) + newQueryConn := func(opts ...conn2.Option) *conn2.Conn { + return conn2.New(context.Background(), nil, nil, opts...) } compareConfigs := func(t *testing.T, lhs, rhs *config.Config) { require.Equal(t, lhs.Secure(), rhs.Secure()) @@ -71,7 +71,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode), + connector.WithDefaultQueryMode(conn.ScriptingQueryMode), }, err: nil, }, @@ -83,7 +83,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode), + connector.WithDefaultQueryMode(conn.ScriptingQueryMode), connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), }, err: nil, @@ -96,7 +96,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode), + connector.WithDefaultQueryMode(conn.ScriptingQueryMode), connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), connector.WithQueryBind(bind.NumericArgs{}), }, @@ -110,7 +110,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode), + connector.WithDefaultQueryMode(conn.ScriptingQueryMode), connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), connector.WithQueryBind(bind.PositionalArgs{}), }, @@ -124,7 +124,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode), + connector.WithDefaultQueryMode(conn.ScriptingQueryMode), connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), connector.WithQueryBind(bind.AutoDeclare{}), }, @@ -138,7 +138,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode), + connector.WithDefaultQueryMode(conn.ScriptingQueryMode), connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), }, err: nil, @@ -151,7 +151,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(tableSql.ScriptingQueryMode), + connector.WithDefaultQueryMode(conn.ScriptingQueryMode), connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), connector.WithQueryBind(bind.PositionalArgs{}), connector.WithQueryBind(bind.AutoDeclare{}), @@ -166,8 +166,8 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []connector.Option{ - connector.WithFakeTx(tableSql.ScriptingQueryMode), - connector.WithFakeTx(tableSql.SchemeQueryMode), + connector.WithFakeTx(conn.ScriptingQueryMode), + connector.WithFakeTx(conn.SchemeQueryMode), }, err: nil, }, diff --git a/internal/connector/connector.go b/internal/connector/connector.go index 6f88955df..cab364df1 100644 --- a/internal/connector/connector.go +++ b/internal/connector/connector.go @@ -12,9 +12,9 @@ import ( "google.golang.org/grpc" "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" + conn3 "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/query/conn" + conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query" - querySql "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn" - tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn" "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/xsync" @@ -38,8 +38,8 @@ type ( queryProcessor queryProcessor - TableOpts []tableSql.Option - QueryOpts []querySql.Option + TableOpts []conn2.Option + QueryOpts []conn3.Option disableServerBalancer bool onCLose []func(*Connector) @@ -122,9 +122,9 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() conn := &conn{ - cc: querySql.New(ctx, c, s, append( + cc: conn3.New(ctx, c, s, append( c.QueryOpts, - querySql.WithOnClose(func() { + conn3.WithOnClose(func() { c.conns.Delete(id) }))..., ), @@ -145,8 +145,8 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() conn := &conn{ - cc: tableSql.New(ctx, c, s, append(c.TableOpts, - tableSql.WithOnClose(func() { + cc: conn2.New(ctx, c, s, append(c.TableOpts, + conn2.WithOnClose(func() { c.conns.Delete(id) }))..., ), diff --git a/internal/connector/options.go b/internal/connector/options.go index 8efa24d1c..979dc7e1f 100644 --- a/internal/connector/options.go +++ b/internal/connector/options.go @@ -4,8 +4,8 @@ import ( "time" "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" - querySql "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn" - tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn" + querySql "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/query/conn" + conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/retry/budget" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) @@ -22,7 +22,7 @@ type ( bind.TablePathPrefix } tableQueryOptionsOption struct { - tableOps []tableSql.Option + tableOps []conn2.Option queryOpts []querySql.Option } traceDatabaseSQLOption struct { @@ -146,31 +146,31 @@ func WithQueryBind(bind bind.Bind) QueryBindOption { } } -func WithDefaultQueryMode(mode tableSql.QueryMode) Option { +func WithDefaultQueryMode(mode conn2.QueryMode) Option { return tableQueryOptionsOption{ - tableOps: []tableSql.Option{ - tableSql.WithDefaultQueryMode(mode), + tableOps: []conn2.Option{ + conn2.WithDefaultQueryMode(mode), }, } } -func WithFakeTx(modes ...tableSql.QueryMode) Option { +func WithFakeTx(modes ...conn2.QueryMode) Option { return tableQueryOptionsOption{ - tableOps: []tableSql.Option{ - tableSql.WithFakeTxModes(modes...), + tableOps: []conn2.Option{ + conn2.WithFakeTxModes(modes...), }, } } func WithIdleThreshold(idleThreshold time.Duration) Option { return tableQueryOptionsOption{ - tableOps: []tableSql.Option{ - tableSql.WithIdleThreshold(idleThreshold), + tableOps: []conn2.Option{ + conn2.WithIdleThreshold(idleThreshold), }, } } -func WithTableOptions(opts ...tableSql.Option) Option { +func WithTableOptions(opts ...conn2.Option) Option { return tableQueryOptionsOption{ tableOps: opts, } diff --git a/internal/query/conn/conn.go b/internal/connector/query/conn/conn.go similarity index 100% rename from internal/query/conn/conn.go rename to internal/connector/query/conn/conn.go diff --git a/internal/query/conn/errors.go b/internal/connector/query/conn/errors.go similarity index 100% rename from internal/query/conn/errors.go rename to internal/connector/query/conn/errors.go diff --git a/internal/query/conn/isolation/isolation.go b/internal/connector/query/conn/isolation/isolation.go similarity index 100% rename from internal/query/conn/isolation/isolation.go rename to internal/connector/query/conn/isolation/isolation.go diff --git a/internal/query/conn/options.go b/internal/connector/query/conn/options.go similarity index 100% rename from internal/query/conn/options.go rename to internal/connector/query/conn/options.go diff --git a/internal/query/conn/rows.go b/internal/connector/query/conn/rows.go similarity index 100% rename from internal/query/conn/rows.go rename to internal/connector/query/conn/rows.go diff --git a/internal/query/conn/tx.go b/internal/connector/query/conn/tx.go similarity index 95% rename from internal/query/conn/tx.go rename to internal/connector/query/conn/tx.go index 95c60575e..854e02913 100644 --- a/internal/query/conn/tx.go +++ b/internal/connector/query/conn/tx.go @@ -5,8 +5,8 @@ import ( "database/sql/driver" "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/query/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/query" diff --git a/internal/table/conn/badconn/badconn.go b/internal/connector/table/conn/badconn/badconn.go similarity index 100% rename from internal/table/conn/badconn/badconn.go rename to internal/connector/table/conn/badconn/badconn.go diff --git a/internal/table/conn/badconn/badconn_test.go b/internal/connector/table/conn/badconn/badconn_test.go similarity index 100% rename from internal/table/conn/badconn/badconn_test.go rename to internal/connector/table/conn/badconn/badconn_test.go diff --git a/internal/table/conn/conn.go b/internal/connector/table/conn/conn.go similarity index 98% rename from internal/table/conn/conn.go rename to internal/connector/table/conn/conn.go index 4618ff817..41dca682a 100644 --- a/internal/table/conn/conn.go +++ b/internal/connector/table/conn/conn.go @@ -10,8 +10,8 @@ import ( "time" "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "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/scripting" diff --git a/internal/table/conn/context.go b/internal/connector/table/conn/context.go similarity index 100% rename from internal/table/conn/context.go rename to internal/connector/table/conn/context.go diff --git a/internal/table/conn/errors.go b/internal/connector/table/conn/errors.go similarity index 100% rename from internal/table/conn/errors.go rename to internal/connector/table/conn/errors.go diff --git a/internal/table/conn/isolation/isolation.go b/internal/connector/table/conn/isolation/isolation.go similarity index 100% rename from internal/table/conn/isolation/isolation.go rename to internal/connector/table/conn/isolation/isolation.go diff --git a/internal/table/conn/isolation/isolation_test.go b/internal/connector/table/conn/isolation/isolation_test.go similarity index 100% rename from internal/table/conn/isolation/isolation_test.go rename to internal/connector/table/conn/isolation/isolation_test.go diff --git a/internal/table/conn/mode.go b/internal/connector/table/conn/mode.go similarity index 100% rename from internal/table/conn/mode.go rename to internal/connector/table/conn/mode.go diff --git a/internal/table/conn/options.go b/internal/connector/table/conn/options.go similarity index 100% rename from internal/table/conn/options.go rename to internal/connector/table/conn/options.go diff --git a/internal/table/conn/rows.go b/internal/connector/table/conn/rows.go similarity index 97% rename from internal/table/conn/rows.go rename to internal/connector/table/conn/rows.go index d455975d9..60644511f 100644 --- a/internal/table/conn/rows.go +++ b/internal/connector/table/conn/rows.go @@ -8,8 +8,8 @@ import ( "strings" "sync" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/scanner" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" "github.com/ydb-platform/ydb-go-sdk/v3/table/result" diff --git a/internal/table/conn/tx.go b/internal/connector/table/conn/tx.go similarity index 94% rename from internal/table/conn/tx.go rename to internal/connector/table/conn/tx.go index 4b04c9d34..a28cec5c4 100644 --- a/internal/table/conn/tx.go +++ b/internal/connector/table/conn/tx.go @@ -6,9 +6,9 @@ import ( "fmt" "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/table" ) diff --git a/internal/table/conn/tx_fake.go b/internal/connector/table/conn/tx_fake.go similarity index 94% rename from internal/table/conn/tx_fake.go rename to internal/connector/table/conn/tx_fake.go index 9a58bef66..8ad22715b 100644 --- a/internal/table/conn/tx_fake.go +++ b/internal/connector/table/conn/tx_fake.go @@ -5,8 +5,8 @@ import ( "database/sql/driver" "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) diff --git a/internal/table/conn/valuer.go b/internal/connector/table/conn/valuer.go similarity index 100% rename from internal/table/conn/valuer.go rename to internal/connector/table/conn/valuer.go diff --git a/internal/connector/tx.go b/internal/connector/tx.go index c260739e0..31b37ec9c 100644 --- a/internal/connector/tx.go +++ b/internal/connector/tx.go @@ -5,8 +5,8 @@ import ( "database/sql/driver" "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) diff --git a/internal/connector/unwrap.go b/internal/connector/unwrap.go index c0321dfb0..0d900eabc 100644 --- a/internal/connector/unwrap.go +++ b/internal/connector/unwrap.go @@ -4,7 +4,7 @@ import ( "database/sql" "fmt" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) diff --git a/retry/errors.go b/retry/errors.go index 64366f01c..91e8149ae 100644 --- a/retry/errors.go +++ b/retry/errors.go @@ -1,7 +1,7 @@ package retry import ( - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) diff --git a/retry/sql_test.go b/retry/sql_test.go index d327c120a..5ed29dc3d 100644 --- a/retry/sql_test.go +++ b/retry/sql_test.go @@ -11,8 +11,8 @@ import ( "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3/internal/backoff" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) diff --git a/sql.go b/sql.go index fdaf55bd8..c5bc92f43 100644 --- a/sql.go +++ b/sql.go @@ -8,7 +8,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector" - tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsync" "github.com/ydb-platform/ydb-go-sdk/v3/table" @@ -78,7 +78,7 @@ func (d *sqlDriver) detach(c *connector.Connector) { d.connectors.Delete(c) } -type QueryMode = tableSql.QueryMode +type QueryMode = conn.QueryMode const ( DataQueryMode = iota + 1 @@ -93,20 +93,20 @@ func WithQueryMode(ctx context.Context, mode QueryMode) context.Context { case ExplainQueryMode: return connector.WithExplain(ctx) case DataQueryMode: - return tableSql.WithQueryMode(ctx, tableSql.DataQueryMode) + return conn.WithQueryMode(ctx, conn.DataQueryMode) case ScanQueryMode: - return tableSql.WithQueryMode(ctx, tableSql.ScanQueryMode) + return conn.WithQueryMode(ctx, conn.ScanQueryMode) case SchemeQueryMode: - return tableSql.WithQueryMode(ctx, tableSql.SchemeQueryMode) + return conn.WithQueryMode(ctx, conn.SchemeQueryMode) case ScriptingQueryMode: - return tableSql.WithQueryMode(ctx, tableSql.ScriptingQueryMode) + return conn.WithQueryMode(ctx, conn.ScriptingQueryMode) default: return ctx } } func WithTxControl(ctx context.Context, txc *table.TransactionControl) context.Context { - return tableSql.WithTxControl(ctx, txc) + return conn.WithTxControl(ctx, txc) } type ConnectorOption = connector.Option @@ -117,11 +117,11 @@ type QueryBindConnectorOption interface { } func WithDefaultQueryMode(mode QueryMode) ConnectorOption { - return connector.WithTableOptions(tableSql.WithDefaultQueryMode(mode)) + return connector.WithTableOptions(conn.WithDefaultQueryMode(mode)) } func WithFakeTx(mode QueryMode) ConnectorOption { - return connector.WithTableOptions(tableSql.WithFakeTxModes(mode)) + return connector.WithTableOptions(conn.WithFakeTxModes(mode)) } func WithTablePathPrefix(tablePathPrefix string) QueryBindConnectorOption { @@ -141,15 +141,15 @@ func WithNumericArgs() QueryBindConnectorOption { } func WithDefaultTxControl(txControl *table.TransactionControl) ConnectorOption { - return connector.WithTableOptions(tableSql.WithDefaultTxControl(txControl)) + return connector.WithTableOptions(conn.WithDefaultTxControl(txControl)) } func WithDefaultDataQueryOptions(opts ...options.ExecuteDataQueryOption) ConnectorOption { - return connector.WithTableOptions(tableSql.WithDataOpts(opts...)) + return connector.WithTableOptions(conn.WithDataOpts(opts...)) } func WithDefaultScanQueryOptions(opts ...options.ExecuteScanQueryOption) ConnectorOption { - return connector.WithTableOptions(tableSql.WithScanOpts(opts...)) + return connector.WithTableOptions(conn.WithScanOpts(opts...)) } func WithDatabaseSQLTrace( diff --git a/tests/integration/database_sql_regression_test.go b/tests/integration/database_sql_regression_test.go index aeb6d6054..7d67e8908 100644 --- a/tests/integration/database_sql_regression_test.go +++ b/tests/integration/database_sql_regression_test.go @@ -18,7 +18,7 @@ import ( "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/retry" diff --git a/tests/integration/database_sql_with_tx_control_test.go b/tests/integration/database_sql_with_tx_control_test.go index 499a34b55..d25cd6b3e 100644 --- a/tests/integration/database_sql_with_tx_control_test.go +++ b/tests/integration/database_sql_with_tx_control_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3" - tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/conn" + tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/retry" "github.com/ydb-platform/ydb-go-sdk/v3/table" From 46b1007a47d937b143b4fdee88dd523aa2481f6b Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Tue, 10 Dec 2024 22:29:33 +0300 Subject: [PATCH 48/48] rename internal/connector to internal/xsql --- driver.go | 4 +- dsn.go | 20 +++--- dsn_test.go | 68 +++++++++---------- internal/{connector => xsql}/conn.go | 8 +-- internal/{connector => xsql}/conn_test.go | 2 +- internal/{connector => xsql}/connector.go | 6 +- internal/{connector => xsql}/context.go | 2 +- internal/{connector => xsql}/errors.go | 2 +- internal/{connector => xsql}/iface/conn.go | 0 internal/{connector => xsql}/iface/tx.go | 0 internal/{connector => xsql}/options.go | 6 +- .../{connector => xsql}/query/conn/conn.go | 2 +- .../{connector => xsql}/query/conn/errors.go | 0 .../query/conn/isolation/isolation.go | 0 .../{connector => xsql}/query/conn/options.go | 0 .../{connector => xsql}/query/conn/rows.go | 0 internal/{connector => xsql}/query/conn/tx.go | 4 +- internal/{connector => xsql}/stmt.go | 8 +-- .../table/conn/badconn/badconn.go | 0 .../table/conn/badconn/badconn_test.go | 0 .../{connector => xsql}/table/conn/conn.go | 4 +- .../{connector => xsql}/table/conn/context.go | 0 .../{connector => xsql}/table/conn/errors.go | 0 .../table/conn/isolation/isolation.go | 0 .../table/conn/isolation/isolation_test.go | 0 .../{connector => xsql}/table/conn/mode.go | 0 .../{connector => xsql}/table/conn/options.go | 0 .../{connector => xsql}/table/conn/rows.go | 2 +- internal/{connector => xsql}/table/conn/tx.go | 6 +- .../{connector => xsql}/table/conn/tx_fake.go | 4 +- .../{connector => xsql}/table/conn/valuer.go | 0 internal/{connector => xsql}/tx.go | 16 ++--- internal/{connector => xsql}/unwrap.go | 4 +- options.go | 6 +- retry/errors.go | 2 +- retry/sql_test.go | 2 +- sql.go | 48 ++++++------- sql_unwrap.go | 4 +- .../database_sql_regression_test.go | 2 +- .../database_sql_with_tx_control_test.go | 2 +- 40 files changed, 117 insertions(+), 117 deletions(-) rename internal/{connector => xsql}/conn.go (98%) rename internal/{connector => xsql}/conn_test.go (98%) rename internal/{connector => xsql}/connector.go (96%) rename internal/{connector => xsql}/context.go (94%) rename internal/{connector => xsql}/errors.go (95%) rename internal/{connector => xsql}/iface/conn.go (100%) rename internal/{connector => xsql}/iface/tx.go (100%) rename internal/{connector => xsql}/options.go (95%) rename internal/{connector => xsql}/query/conn/conn.go (98%) rename internal/{connector => xsql}/query/conn/errors.go (100%) rename internal/{connector => xsql}/query/conn/isolation/isolation.go (100%) rename internal/{connector => xsql}/query/conn/options.go (100%) rename internal/{connector => xsql}/query/conn/rows.go (100%) rename internal/{connector => xsql}/query/conn/tx.go (92%) rename internal/{connector => xsql}/stmt.go (95%) rename internal/{connector => xsql}/table/conn/badconn/badconn.go (100%) rename internal/{connector => xsql}/table/conn/badconn/badconn_test.go (100%) rename internal/{connector => xsql}/table/conn/conn.go (98%) rename internal/{connector => xsql}/table/conn/context.go (100%) rename internal/{connector => xsql}/table/conn/errors.go (100%) rename internal/{connector => xsql}/table/conn/isolation/isolation.go (100%) rename internal/{connector => xsql}/table/conn/isolation/isolation_test.go (100%) rename internal/{connector => xsql}/table/conn/mode.go (100%) rename internal/{connector => xsql}/table/conn/options.go (100%) rename internal/{connector => xsql}/table/conn/rows.go (97%) rename internal/{connector => xsql}/table/conn/tx.go (92%) rename internal/{connector => xsql}/table/conn/tx_fake.go (89%) rename internal/{connector => xsql}/table/conn/valuer.go (100%) rename internal/{connector => xsql}/tx.go (89%) rename internal/{connector => xsql}/unwrap.go (89%) diff --git a/driver.go b/driver.go index da2122a56..6b51f109a 100644 --- a/driver.go +++ b/driver.go @@ -14,7 +14,6 @@ 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" @@ -37,6 +36,7 @@ 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" @@ -93,7 +93,7 @@ type ( topic *xsync.Once[*topicclientinternal.Client] topicOptions []topicoptions.TopicOption - databaseSQLOptions []connector.Option + databaseSQLOptions []xsql.Option pool *conn.Pool diff --git a/dsn.go b/dsn.go index 32f311740..40ef9e4e2 100644 --- a/dsn.go +++ b/dsn.go @@ -9,10 +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" - tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/dsn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql" + tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn" ) const tablePathPrefixTransformer = "table_path_prefix" @@ -64,13 +64,13 @@ func parseConnectionString(dataSourceName string) (opts []Option, _ error) { if mode == tableSql.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } - opts = append(opts, withConnectorOptions(connector.WithDefaultQueryMode(mode))) + opts = append(opts, withConnectorOptions(xsql.WithDefaultQueryMode(mode))) } else if queryMode := info.Params.Get("query_mode"); queryMode != "" { mode := tableSql.QueryModeFromString(queryMode) if mode == tableSql.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } - opts = append(opts, withConnectorOptions(connector.WithDefaultQueryMode(mode))) + opts = append(opts, withConnectorOptions(xsql.WithDefaultQueryMode(mode))) } if fakeTx := info.Params.Get("go_fake_tx"); fakeTx != "" { for _, queryMode := range strings.Split(fakeTx, ",") { @@ -78,27 +78,27 @@ func parseConnectionString(dataSourceName string) (opts []Option, _ error) { if mode == tableSql.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } - opts = append(opts, withConnectorOptions(connector.WithFakeTx(mode))) + opts = append(opts, withConnectorOptions(xsql.WithFakeTx(mode))) } } if info.Params.Has("go_query_bind") { - var binders []connector.Option + var binders []xsql.Option queryTransformers := strings.Split(info.Params.Get("go_query_bind"), ",") for _, transformer := range queryTransformers { switch transformer { case "declare": - binders = append(binders, connector.WithQueryBind(bind.AutoDeclare{})) + binders = append(binders, xsql.WithQueryBind(bind.AutoDeclare{})) case "positional": - binders = append(binders, connector.WithQueryBind(bind.PositionalArgs{})) + binders = append(binders, xsql.WithQueryBind(bind.PositionalArgs{})) case "numeric": - binders = append(binders, connector.WithQueryBind(bind.NumericArgs{})) + binders = append(binders, xsql.WithQueryBind(bind.NumericArgs{})) default: if strings.HasPrefix(transformer, tablePathPrefixTransformer) { prefix, err := extractTablePathPrefixFromBinderName(transformer) if err != nil { return nil, xerrors.WithStackTrace(err) } - binders = append(binders, connector.WithQueryBind(bind.TablePathPrefix(prefix))) + binders = append(binders, xsql.WithQueryBind(bind.TablePathPrefix(prefix))) } else { return nil, xerrors.WithStackTrace( fmt.Errorf("unknown query rewriter: %s", transformer), diff --git a/dsn_test.go b/dsn_test.go index 8afa5b41d..a64859aa5 100644 --- a/dsn_test.go +++ b/dsn_test.go @@ -8,14 +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/connector" - conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/query/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql" + conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/query/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn" ) func TestParse(t *testing.T) { - newConnector := func(opts ...connector.Option) *connector.Connector { - c := &connector.Connector{} + newConnector := func(opts ...xsql.Option) *xsql.Connector { + c := &xsql.Connector{} for _, opt := range opts { if opt != nil { if err := opt.Apply(c); err != nil { @@ -40,7 +40,7 @@ func TestParse(t *testing.T) { for _, tt := range []struct { dsn string opts []config.Option - connectorOpts []connector.Option + connectorOpts []xsql.Option err error }{ { @@ -70,8 +70,8 @@ func TestParse(t *testing.T) { config.WithEndpoint("localhost:2135"), config.WithDatabase("/local"), }, - connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(conn.ScriptingQueryMode), + connectorOpts: []xsql.Option{ + xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), }, err: nil, }, @@ -82,9 +82,9 @@ func TestParse(t *testing.T) { config.WithEndpoint("localhost:2135"), config.WithDatabase("/local"), }, - connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(conn.ScriptingQueryMode), - connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), + connectorOpts: []xsql.Option{ + xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), }, err: nil, }, @@ -95,10 +95,10 @@ func TestParse(t *testing.T) { config.WithEndpoint("localhost:2135"), config.WithDatabase("/local"), }, - connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(conn.ScriptingQueryMode), - connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), - connector.WithQueryBind(bind.NumericArgs{}), + connectorOpts: []xsql.Option{ + xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), + xsql.WithQueryBind(bind.NumericArgs{}), }, err: nil, }, @@ -109,10 +109,10 @@ func TestParse(t *testing.T) { config.WithEndpoint("localhost:2135"), config.WithDatabase("/local"), }, - connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(conn.ScriptingQueryMode), - connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), - connector.WithQueryBind(bind.PositionalArgs{}), + connectorOpts: []xsql.Option{ + xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), + xsql.WithQueryBind(bind.PositionalArgs{}), }, err: nil, }, @@ -123,10 +123,10 @@ func TestParse(t *testing.T) { config.WithEndpoint("localhost:2135"), config.WithDatabase("/local"), }, - connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(conn.ScriptingQueryMode), - connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), - connector.WithQueryBind(bind.AutoDeclare{}), + connectorOpts: []xsql.Option{ + xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), + xsql.WithQueryBind(bind.AutoDeclare{}), }, err: nil, }, @@ -137,9 +137,9 @@ func TestParse(t *testing.T) { config.WithEndpoint("localhost:2135"), config.WithDatabase("/local"), }, - connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(conn.ScriptingQueryMode), - connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), + connectorOpts: []xsql.Option{ + xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), }, err: nil, }, @@ -150,11 +150,11 @@ func TestParse(t *testing.T) { config.WithEndpoint("localhost:2135"), config.WithDatabase("/local"), }, - connectorOpts: []connector.Option{ - connector.WithDefaultQueryMode(conn.ScriptingQueryMode), - connector.WithQueryBind(bind.TablePathPrefix("path/to/tables")), - connector.WithQueryBind(bind.PositionalArgs{}), - connector.WithQueryBind(bind.AutoDeclare{}), + connectorOpts: []xsql.Option{ + xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), + xsql.WithQueryBind(bind.PositionalArgs{}), + xsql.WithQueryBind(bind.AutoDeclare{}), }, err: nil, }, @@ -165,9 +165,9 @@ func TestParse(t *testing.T) { config.WithEndpoint("localhost:2135"), config.WithDatabase("/local"), }, - connectorOpts: []connector.Option{ - connector.WithFakeTx(conn.ScriptingQueryMode), - connector.WithFakeTx(conn.SchemeQueryMode), + connectorOpts: []xsql.Option{ + xsql.WithFakeTx(conn.ScriptingQueryMode), + xsql.WithFakeTx(conn.SchemeQueryMode), }, err: nil, }, diff --git a/internal/connector/conn.go b/internal/xsql/conn.go similarity index 98% rename from internal/connector/conn.go rename to internal/xsql/conn.go index 117bb57fa..0faf6f607 100644 --- a/internal/connector/conn.go +++ b/internal/xsql/conn.go @@ -1,4 +1,4 @@ -package connector +package xsql import ( "context" @@ -10,7 +10,6 @@ import ( "strings" "time" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/scheme/helpers" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" @@ -18,6 +17,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/config" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xslices" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsync" "github.com/ydb-platform/ydb-go-sdk/v3/retry" "github.com/ydb-platform/ydb-go-sdk/v3/scheme" @@ -124,7 +124,7 @@ func (c *conn) Prepare(string) (driver.Stmt, error) { func (c *conn) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, finalErr error) { onDone := trace.DatabaseSQLOnConnPrepare(c.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*conn).PrepareContext"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*conn).PrepareContext"), sql, ) defer func() { @@ -393,7 +393,7 @@ func (c *conn) IsColumnExists(ctx context.Context, tableName, columnName string) func (c *conn) IsTableExists(ctx context.Context, tableName string) (tableExists bool, finalErr error) { tableName = c.normalizePath(tableName) onDone := trace.DatabaseSQLOnConnIsTableExists(c.connector.trace, &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*conn).IsTableExists"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*conn).IsTableExists"), tableName, ) defer func() { diff --git a/internal/connector/conn_test.go b/internal/xsql/conn_test.go similarity index 98% rename from internal/connector/conn_test.go rename to internal/xsql/conn_test.go index c9f02ba79..ac8da4fdf 100644 --- a/internal/connector/conn_test.go +++ b/internal/xsql/conn_test.go @@ -1,4 +1,4 @@ -package connector +package xsql import "context" diff --git a/internal/connector/connector.go b/internal/xsql/connector.go similarity index 96% rename from internal/connector/connector.go rename to internal/xsql/connector.go index cab364df1..26581664e 100644 --- a/internal/connector/connector.go +++ b/internal/xsql/connector.go @@ -1,4 +1,4 @@ -package connector +package xsql import ( "context" @@ -12,11 +12,11 @@ import ( "google.golang.org/grpc" "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" - conn3 "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/query/conn" - conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xcontext" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + conn3 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/query/conn" + conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsync" "github.com/ydb-platform/ydb-go-sdk/v3/retry/budget" "github.com/ydb-platform/ydb-go-sdk/v3/scheme" diff --git a/internal/connector/context.go b/internal/xsql/context.go similarity index 94% rename from internal/connector/context.go rename to internal/xsql/context.go index 19d0ab2c1..15c7dc86b 100644 --- a/internal/connector/context.go +++ b/internal/xsql/context.go @@ -1,4 +1,4 @@ -package connector +package xsql import "context" diff --git a/internal/connector/errors.go b/internal/xsql/errors.go similarity index 95% rename from internal/connector/errors.go rename to internal/xsql/errors.go index c7adeef7f..252485975 100644 --- a/internal/connector/errors.go +++ b/internal/xsql/errors.go @@ -1,4 +1,4 @@ -package connector +package xsql import ( "database/sql/driver" diff --git a/internal/connector/iface/conn.go b/internal/xsql/iface/conn.go similarity index 100% rename from internal/connector/iface/conn.go rename to internal/xsql/iface/conn.go diff --git a/internal/connector/iface/tx.go b/internal/xsql/iface/tx.go similarity index 100% rename from internal/connector/iface/tx.go rename to internal/xsql/iface/tx.go diff --git a/internal/connector/options.go b/internal/xsql/options.go similarity index 95% rename from internal/connector/options.go rename to internal/xsql/options.go index 979dc7e1f..c6b2d8964 100644 --- a/internal/connector/options.go +++ b/internal/xsql/options.go @@ -1,11 +1,11 @@ -package connector +package xsql import ( "time" "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" - querySql "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/query/conn" - conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" + querySql "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/query/conn" + conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/retry/budget" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) diff --git a/internal/connector/query/conn/conn.go b/internal/xsql/query/conn/conn.go similarity index 98% rename from internal/connector/query/conn/conn.go rename to internal/xsql/query/conn/conn.go index 6a7ae2e3a..ed10f67c6 100644 --- a/internal/connector/query/conn/conn.go +++ b/internal/xsql/query/conn/conn.go @@ -5,7 +5,6 @@ import ( "database/sql/driver" "sync/atomic" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" @@ -13,6 +12,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/stats" "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/iface" ) type resultNoRows struct{} diff --git a/internal/connector/query/conn/errors.go b/internal/xsql/query/conn/errors.go similarity index 100% rename from internal/connector/query/conn/errors.go rename to internal/xsql/query/conn/errors.go diff --git a/internal/connector/query/conn/isolation/isolation.go b/internal/xsql/query/conn/isolation/isolation.go similarity index 100% rename from internal/connector/query/conn/isolation/isolation.go rename to internal/xsql/query/conn/isolation/isolation.go diff --git a/internal/connector/query/conn/options.go b/internal/xsql/query/conn/options.go similarity index 100% rename from internal/connector/query/conn/options.go rename to internal/xsql/query/conn/options.go diff --git a/internal/connector/query/conn/rows.go b/internal/xsql/query/conn/rows.go similarity index 100% rename from internal/connector/query/conn/rows.go rename to internal/xsql/query/conn/rows.go diff --git a/internal/connector/query/conn/tx.go b/internal/xsql/query/conn/tx.go similarity index 92% rename from internal/connector/query/conn/tx.go rename to internal/xsql/query/conn/tx.go index 854e02913..d45f7d751 100644 --- a/internal/connector/query/conn/tx.go +++ b/internal/xsql/query/conn/tx.go @@ -4,11 +4,11 @@ import ( "context" "database/sql/driver" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/query/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/query/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/query" ) diff --git a/internal/connector/stmt.go b/internal/xsql/stmt.go similarity index 95% rename from internal/connector/stmt.go rename to internal/xsql/stmt.go index 6ad6fcf59..6bf400ea9 100644 --- a/internal/connector/stmt.go +++ b/internal/xsql/stmt.go @@ -1,4 +1,4 @@ -package connector +package xsql import ( "context" @@ -28,7 +28,7 @@ var ( func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ driver.Rows, finalErr error) { onDone := trace.DatabaseSQLOnStmtQuery(stmt.conn.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*stmt).QueryContext"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*stmt).QueryContext"), stmt.ctx, stmt.sql, ) defer func() { @@ -49,7 +49,7 @@ func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ driver.Result, finalErr error) { onDone := trace.DatabaseSQLOnStmtExec(stmt.conn.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*stmt).ExecContext"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*stmt).ExecContext"), stmt.ctx, stmt.sql, ) defer func() { @@ -76,7 +76,7 @@ func (stmt *stmt) Close() (finalErr error) { var ( ctx = stmt.ctx onDone = trace.DatabaseSQLOnStmtClose(stmt.conn.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*stmt).Close"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*stmt).Close"), ) ) defer func() { diff --git a/internal/connector/table/conn/badconn/badconn.go b/internal/xsql/table/conn/badconn/badconn.go similarity index 100% rename from internal/connector/table/conn/badconn/badconn.go rename to internal/xsql/table/conn/badconn/badconn.go diff --git a/internal/connector/table/conn/badconn/badconn_test.go b/internal/xsql/table/conn/badconn/badconn_test.go similarity index 100% rename from internal/connector/table/conn/badconn/badconn_test.go rename to internal/xsql/table/conn/badconn/badconn_test.go diff --git a/internal/connector/table/conn/conn.go b/internal/xsql/table/conn/conn.go similarity index 98% rename from internal/connector/table/conn/conn.go rename to internal/xsql/table/conn/conn.go index 41dca682a..1b09539e9 100644 --- a/internal/connector/table/conn/conn.go +++ b/internal/xsql/table/conn/conn.go @@ -9,11 +9,11 @@ import ( "sync/atomic" "time" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "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/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/scripting" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" diff --git a/internal/connector/table/conn/context.go b/internal/xsql/table/conn/context.go similarity index 100% rename from internal/connector/table/conn/context.go rename to internal/xsql/table/conn/context.go diff --git a/internal/connector/table/conn/errors.go b/internal/xsql/table/conn/errors.go similarity index 100% rename from internal/connector/table/conn/errors.go rename to internal/xsql/table/conn/errors.go diff --git a/internal/connector/table/conn/isolation/isolation.go b/internal/xsql/table/conn/isolation/isolation.go similarity index 100% rename from internal/connector/table/conn/isolation/isolation.go rename to internal/xsql/table/conn/isolation/isolation.go diff --git a/internal/connector/table/conn/isolation/isolation_test.go b/internal/xsql/table/conn/isolation/isolation_test.go similarity index 100% rename from internal/connector/table/conn/isolation/isolation_test.go rename to internal/xsql/table/conn/isolation/isolation_test.go diff --git a/internal/connector/table/conn/mode.go b/internal/xsql/table/conn/mode.go similarity index 100% rename from internal/connector/table/conn/mode.go rename to internal/xsql/table/conn/mode.go diff --git a/internal/connector/table/conn/options.go b/internal/xsql/table/conn/options.go similarity index 100% rename from internal/connector/table/conn/options.go rename to internal/xsql/table/conn/options.go diff --git a/internal/connector/table/conn/rows.go b/internal/xsql/table/conn/rows.go similarity index 97% rename from internal/connector/table/conn/rows.go rename to internal/xsql/table/conn/rows.go index 60644511f..ed95f3acc 100644 --- a/internal/connector/table/conn/rows.go +++ b/internal/xsql/table/conn/rows.go @@ -8,9 +8,9 @@ import ( "strings" "sync" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/scanner" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" "github.com/ydb-platform/ydb-go-sdk/v3/table/result" "github.com/ydb-platform/ydb-go-sdk/v3/table/result/indexed" diff --git a/internal/connector/table/conn/tx.go b/internal/xsql/table/conn/tx.go similarity index 92% rename from internal/connector/table/conn/tx.go rename to internal/xsql/table/conn/tx.go index a28cec5c4..417566f50 100644 --- a/internal/connector/table/conn/tx.go +++ b/internal/xsql/table/conn/tx.go @@ -5,11 +5,11 @@ import ( "database/sql/driver" "fmt" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/table" ) diff --git a/internal/connector/table/conn/tx_fake.go b/internal/xsql/table/conn/tx_fake.go similarity index 89% rename from internal/connector/table/conn/tx_fake.go rename to internal/xsql/table/conn/tx_fake.go index 8ad22715b..1fcd3d790 100644 --- a/internal/connector/table/conn/tx_fake.go +++ b/internal/xsql/table/conn/tx_fake.go @@ -4,11 +4,11 @@ import ( "context" "database/sql/driver" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/params" "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn/badconn" ) type txFake struct { diff --git a/internal/connector/table/conn/valuer.go b/internal/xsql/table/conn/valuer.go similarity index 100% rename from internal/connector/table/conn/valuer.go rename to internal/xsql/table/conn/valuer.go diff --git a/internal/connector/tx.go b/internal/xsql/tx.go similarity index 89% rename from internal/connector/tx.go rename to internal/xsql/tx.go index 31b37ec9c..5605de590 100644 --- a/internal/connector/tx.go +++ b/internal/xsql/tx.go @@ -1,13 +1,13 @@ -package connector +package xsql import ( "context" "database/sql/driver" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/iface" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) @@ -31,7 +31,7 @@ func (tx *txWrapper) Commit() (finalErr error) { var ( ctx = tx.ctx onDone = trace.DatabaseSQLOnTxCommit(tx.conn.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*txWrapper).Commit"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*txWrapper).Commit"), tx, ) ) @@ -50,7 +50,7 @@ func (tx *txWrapper) Rollback() (finalErr error) { var ( ctx = tx.ctx onDone = trace.DatabaseSQLOnTxRollback(tx.conn.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*txWrapper).Rollback"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*txWrapper).Rollback"), tx, ) ) @@ -70,7 +70,7 @@ func (tx *txWrapper) QueryContext(ctx context.Context, query string, args []driv _ driver.Rows, finalErr error, ) { onDone := trace.DatabaseSQLOnTxQuery(tx.conn.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*txWrapper).QueryContext"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*txWrapper).QueryContext"), tx.ctx, tx, query, ) defer func() { @@ -103,7 +103,7 @@ func (tx *txWrapper) ExecContext(ctx context.Context, query string, args []drive _ driver.Result, finalErr error, ) { onDone := trace.DatabaseSQLOnTxExec(tx.conn.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*txWrapper).ExecContext"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*txWrapper).ExecContext"), tx.ctx, tx, query, ) defer func() { @@ -125,7 +125,7 @@ func (tx *txWrapper) ExecContext(ctx context.Context, query string, args []drive func (tx *txWrapper) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, finalErr error) { onDone := trace.DatabaseSQLOnTxPrepare(tx.conn.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/connector.(*txWrapper).PrepareContext"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*txWrapper).PrepareContext"), tx.ctx, tx, sql, ) defer func() { diff --git a/internal/connector/unwrap.go b/internal/xsql/unwrap.go similarity index 89% rename from internal/connector/unwrap.go rename to internal/xsql/unwrap.go index 0d900eabc..7301f5b3e 100644 --- a/internal/connector/unwrap.go +++ b/internal/xsql/unwrap.go @@ -1,11 +1,11 @@ -package connector +package xsql import ( "database/sql" "fmt" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn/badconn" ) func Unwrap[T *sql.DB | *sql.Conn](v T) (connector *Connector, _ error) { diff --git a/options.go b/options.go index bf4ca7058..850bffde7 100644 --- a/options.go +++ b/options.go @@ -14,7 +14,6 @@ import ( balancerConfig "github.com/ydb-platform/ydb-go-sdk/v3/internal/balancer/config" "github.com/ydb-platform/ydb-go-sdk/v3/internal/certificates" "github.com/ydb-platform/ydb-go-sdk/v3/internal/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector" coordinationConfig "github.com/ydb-platform/ydb-go-sdk/v3/internal/coordination/config" discoveryConfig "github.com/ydb-platform/ydb-go-sdk/v3/internal/discovery/config" "github.com/ydb-platform/ydb-go-sdk/v3/internal/dsn" @@ -24,6 +23,7 @@ import ( scriptingConfig "github.com/ydb-platform/ydb-go-sdk/v3/internal/scripting/config" tableConfig "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/config" "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/log" "github.com/ydb-platform/ydb-go-sdk/v3/retry/budget" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topicoptions" @@ -549,7 +549,7 @@ func WithSessionPoolIdleThreshold(idleThreshold time.Duration) Option { return func(ctx context.Context, d *Driver) error { d.tableOptions = append(d.tableOptions, tableConfig.WithIdleThreshold(idleThreshold)) d.databaseSQLOptions = append(d.databaseSQLOptions, - connector.WithIdleThreshold(idleThreshold), + xsql.WithIdleThreshold(idleThreshold), ) return nil @@ -801,7 +801,7 @@ func WithTraceTopic(t trace.Topic, opts ...trace.TopicComposeOption) Option { // func WithTraceDatabaseSQL(t trace.DatabaseSQL, opts ...trace.DatabaseSQLComposeOption) Option { //nolint:gocritic return func(ctx context.Context, d *Driver) error { d.databaseSQLOptions = append(d.databaseSQLOptions, - connector.WithTrace( + xsql.WithTrace( &t, append( []trace.DatabaseSQLComposeOption{ diff --git a/retry/errors.go b/retry/errors.go index 91e8149ae..5f19bed13 100644 --- a/retry/errors.go +++ b/retry/errors.go @@ -1,8 +1,8 @@ package retry import ( - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn/badconn" ) func unwrapErrBadConn(err error) error { diff --git a/retry/sql_test.go b/retry/sql_test.go index 5ed29dc3d..5f6027105 100644 --- a/retry/sql_test.go +++ b/retry/sql_test.go @@ -11,9 +11,9 @@ import ( "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3/internal/backoff" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn/badconn" ) type mockConnector struct { diff --git a/sql.go b/sql.go index c5bc92f43..f222b6a2e 100644 --- a/sql.go +++ b/sql.go @@ -7,9 +7,9 @@ import ( "fmt" "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/connector/table/conn" "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/xsql/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsync" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" @@ -32,7 +32,7 @@ func withConnectorOptions(opts ...ConnectorOption) Option { } type sqlDriver struct { - connectors xsync.Map[*connector.Connector, *Driver] + connectors xsync.Map[*xsql.Connector, *Driver] } var ( @@ -42,7 +42,7 @@ var ( func (d *sqlDriver) Close() error { var errs []error - d.connectors.Range(func(c *connector.Connector, _ *Driver) bool { + d.connectors.Range(func(c *xsql.Connector, _ *Driver) bool { if err := c.Close(); err != nil { errs = append(errs, err) } @@ -58,7 +58,7 @@ func (d *sqlDriver) Close() error { // Open returns a new Driver to the ydb. func (d *sqlDriver) Open(string) (driver.Conn, error) { - return nil, connector.ErrUnsupported + return nil, xsql.ErrUnsupported } func (d *sqlDriver) OpenConnector(dataSourceName string) (driver.Connector, error) { @@ -70,11 +70,11 @@ func (d *sqlDriver) OpenConnector(dataSourceName string) (driver.Connector, erro return Connector(db, db.databaseSQLOptions...) } -func (d *sqlDriver) attach(c *connector.Connector, parent *Driver) { +func (d *sqlDriver) attach(c *xsql.Connector, parent *Driver) { d.connectors.Set(c, parent) } -func (d *sqlDriver) detach(c *connector.Connector) { +func (d *sqlDriver) detach(c *xsql.Connector) { d.connectors.Delete(c) } @@ -91,7 +91,7 @@ const ( func WithQueryMode(ctx context.Context, mode QueryMode) context.Context { switch mode { case ExplainQueryMode: - return connector.WithExplain(ctx) + return xsql.WithExplain(ctx) case DataQueryMode: return conn.WithQueryMode(ctx, conn.DataQueryMode) case ScanQueryMode: @@ -109,7 +109,7 @@ func WithTxControl(ctx context.Context, txc *table.TransactionControl) context.C return conn.WithTxControl(ctx, txc) } -type ConnectorOption = connector.Option +type ConnectorOption = xsql.Option type QueryBindConnectorOption interface { ConnectorOption @@ -117,50 +117,50 @@ type QueryBindConnectorOption interface { } func WithDefaultQueryMode(mode QueryMode) ConnectorOption { - return connector.WithTableOptions(conn.WithDefaultQueryMode(mode)) + return xsql.WithTableOptions(conn.WithDefaultQueryMode(mode)) } func WithFakeTx(mode QueryMode) ConnectorOption { - return connector.WithTableOptions(conn.WithFakeTxModes(mode)) + return xsql.WithTableOptions(conn.WithFakeTxModes(mode)) } func WithTablePathPrefix(tablePathPrefix string) QueryBindConnectorOption { - return connector.WithTablePathPrefix(tablePathPrefix) + return xsql.WithTablePathPrefix(tablePathPrefix) } func WithAutoDeclare() QueryBindConnectorOption { - return connector.WithQueryBind(bind.AutoDeclare{}) + return xsql.WithQueryBind(bind.AutoDeclare{}) } func WithPositionalArgs() QueryBindConnectorOption { - return connector.WithQueryBind(bind.PositionalArgs{}) + return xsql.WithQueryBind(bind.PositionalArgs{}) } func WithNumericArgs() QueryBindConnectorOption { - return connector.WithQueryBind(bind.NumericArgs{}) + return xsql.WithQueryBind(bind.NumericArgs{}) } func WithDefaultTxControl(txControl *table.TransactionControl) ConnectorOption { - return connector.WithTableOptions(conn.WithDefaultTxControl(txControl)) + return xsql.WithTableOptions(conn.WithDefaultTxControl(txControl)) } func WithDefaultDataQueryOptions(opts ...options.ExecuteDataQueryOption) ConnectorOption { - return connector.WithTableOptions(conn.WithDataOpts(opts...)) + return xsql.WithTableOptions(conn.WithDataOpts(opts...)) } func WithDefaultScanQueryOptions(opts ...options.ExecuteScanQueryOption) ConnectorOption { - return connector.WithTableOptions(conn.WithScanOpts(opts...)) + return xsql.WithTableOptions(conn.WithScanOpts(opts...)) } func WithDatabaseSQLTrace( t trace.DatabaseSQL, //nolint:gocritic opts ...trace.DatabaseSQLComposeOption, ) ConnectorOption { - return connector.WithTrace(&t, opts...) + return xsql.WithTrace(&t, opts...) } func WithDisableServerBalancer() ConnectorOption { - return connector.WithDisableServerBalancer() + return xsql.WithDisableServerBalancer() } type SQLConnector interface { @@ -170,15 +170,15 @@ type SQLConnector interface { } func Connector(parent *Driver, opts ...ConnectorOption) (SQLConnector, error) { - c, err := connector.Open(parent, parent.metaBalancer, + c, err := xsql.Open(parent, parent.metaBalancer, append( append( parent.databaseSQLOptions, opts..., ), - connector.WithOnClose(d.detach), - connector.WithTraceRetry(parent.config.TraceRetry()), - connector.WithRetryBudget(parent.config.RetryBudget()), + xsql.WithOnClose(d.detach), + xsql.WithTraceRetry(parent.config.TraceRetry()), + xsql.WithRetryBudget(parent.config.RetryBudget()), )..., ) if err != nil { diff --git a/sql_unwrap.go b/sql_unwrap.go index 9c1df829a..f183dcf28 100644 --- a/sql_unwrap.go +++ b/sql_unwrap.go @@ -3,12 +3,12 @@ package ydb import ( "database/sql" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql" ) func Unwrap[T *sql.DB | *sql.Conn](v T) (*Driver, error) { - c, err := connector.Unwrap(v) + c, err := xsql.Unwrap(v) if err != nil { return nil, xerrors.WithStackTrace(err) } diff --git a/tests/integration/database_sql_regression_test.go b/tests/integration/database_sql_regression_test.go index 7d67e8908..7edc8685f 100644 --- a/tests/integration/database_sql_regression_test.go +++ b/tests/integration/database_sql_regression_test.go @@ -18,8 +18,8 @@ import ( "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/retry" "github.com/ydb-platform/ydb-go-sdk/v3/table" diff --git a/tests/integration/database_sql_with_tx_control_test.go b/tests/integration/database_sql_with_tx_control_test.go index d25cd6b3e..c709a3aa7 100644 --- a/tests/integration/database_sql_with_tx_control_test.go +++ b/tests/integration/database_sql_with_tx_control_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3" - tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/connector/table/conn" + tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/retry" "github.com/ydb-platform/ydb-go-sdk/v3/table"