From d242af3a75b9a422f3ef4d5d509cc6fcd877ec09 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 10 Nov 2024 13:27:48 +0300 Subject: [PATCH 01/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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/62] 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" From 92aeba7f40e52c7dfde9c34ad6889d82ec85bdd6 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Wed, 11 Dec 2024 08:06:56 +0300 Subject: [PATCH 49/62] renamed internal/xsql/iface to internal/xsql/conn + moved internal/xsql/{table,query} into internal/xsql/conn --- dsn.go | 2 +- dsn_test.go | 30 ++++----- internal/xsql/conn.go | 66 +++++++++---------- internal/xsql/{iface => conn}/conn.go | 2 +- internal/xsql/{ => conn}/query/conn/conn.go | 6 +- internal/xsql/{ => conn}/query/conn/errors.go | 0 .../query/conn/isolation/isolation.go | 0 .../xsql/{ => conn}/query/conn/options.go | 0 internal/xsql/{ => conn}/query/conn/rows.go | 0 internal/xsql/{ => conn}/query/conn/tx.go | 6 +- .../{ => conn}/table/conn/badconn/badconn.go | 0 .../table/conn/badconn/badconn_test.go | 0 internal/xsql/{ => conn}/table/conn/conn.go | 8 +-- .../xsql/{ => conn}/table/conn/context.go | 0 internal/xsql/{ => conn}/table/conn/errors.go | 0 .../table/conn/isolation/isolation.go | 0 .../table/conn/isolation/isolation_test.go | 0 internal/xsql/{ => conn}/table/conn/mode.go | 0 .../xsql/{ => conn}/table/conn/options.go | 0 internal/xsql/{ => conn}/table/conn/rows.go | 2 +- internal/xsql/{ => conn}/table/conn/tx.go | 10 +-- .../xsql/{ => conn}/table/conn/tx_fake.go | 6 +- internal/xsql/{ => conn}/table/conn/valuer.go | 0 internal/xsql/{iface => conn}/tx.go | 2 +- internal/xsql/conn_test.go | 22 +++---- internal/xsql/connector.go | 24 +++---- internal/xsql/errors.go | 2 +- internal/xsql/options.go | 24 +++---- internal/xsql/stmt.go | 2 +- internal/xsql/tx.go | 8 +-- internal/xsql/unwrap.go | 6 +- 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 +- topic/topictypes/topictypes_test.go | 2 - 37 files changed, 130 insertions(+), 132 deletions(-) rename internal/xsql/{iface => conn}/conn.go (97%) rename internal/xsql/{ => conn}/query/conn/conn.go (96%) rename internal/xsql/{ => conn}/query/conn/errors.go (100%) rename internal/xsql/{ => conn}/query/conn/isolation/isolation.go (100%) rename internal/xsql/{ => conn}/query/conn/options.go (100%) rename internal/xsql/{ => conn}/query/conn/rows.go (100%) rename internal/xsql/{ => conn}/query/conn/tx.go (90%) rename internal/xsql/{ => conn}/table/conn/badconn/badconn.go (100%) rename internal/xsql/{ => conn}/table/conn/badconn/badconn_test.go (100%) rename internal/xsql/{ => conn}/table/conn/conn.go (97%) rename internal/xsql/{ => conn}/table/conn/context.go (100%) rename internal/xsql/{ => conn}/table/conn/errors.go (100%) rename internal/xsql/{ => conn}/table/conn/isolation/isolation.go (100%) rename internal/xsql/{ => conn}/table/conn/isolation/isolation_test.go (100%) rename internal/xsql/{ => conn}/table/conn/mode.go (100%) rename internal/xsql/{ => conn}/table/conn/options.go (100%) rename internal/xsql/{ => conn}/table/conn/rows.go (97%) rename internal/xsql/{ => conn}/table/conn/tx.go (89%) rename internal/xsql/{ => conn}/table/conn/tx_fake.go (86%) rename internal/xsql/{ => conn}/table/conn/valuer.go (100%) rename internal/xsql/{iface => conn}/tx.go (96%) diff --git a/dsn.go b/dsn.go index 40ef9e4e2..243ad311f 100644 --- a/dsn.go +++ b/dsn.go @@ -12,7 +12,7 @@ import ( "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" + tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn" ) const tablePathPrefixTransformer = "table_path_prefix" diff --git a/dsn_test.go b/dsn_test.go index a64859aa5..2871553a5 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/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" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query/conn" + conn3 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn" ) func TestParse(t *testing.T) { @@ -26,11 +26,11 @@ func TestParse(t *testing.T) { return c } - newTableConn := func(opts ...conn.Option) *conn.Conn { - return conn.New(context.Background(), nil, nil, opts...) + newTableConn := func(opts ...conn3.Option) *conn3.Conn { + return conn3.New(context.Background(), nil, nil, opts...) } - newQueryConn := func(opts ...conn2.Option) *conn2.Conn { - return conn2.New(context.Background(), nil, nil, opts...) + newQueryConn := func(opts ...conn.Option) *conn.Conn { + return conn.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: []xsql.Option{ - xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), }, err: nil, }, @@ -83,7 +83,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), }, err: nil, @@ -96,7 +96,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.NumericArgs{}), }, @@ -110,7 +110,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.PositionalArgs{}), }, @@ -124,7 +124,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.AutoDeclare{}), }, @@ -138,7 +138,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), }, err: nil, @@ -151,7 +151,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn.ScriptingQueryMode), + xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.PositionalArgs{}), xsql.WithQueryBind(bind.AutoDeclare{}), @@ -166,8 +166,8 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithFakeTx(conn.ScriptingQueryMode), - xsql.WithFakeTx(conn.SchemeQueryMode), + xsql.WithFakeTx(conn3.ScriptingQueryMode), + xsql.WithFakeTx(conn3.SchemeQueryMode), }, err: nil, }, diff --git a/internal/xsql/conn.go b/internal/xsql/conn.go index 0faf6f607..682e97eaa 100644 --- a/internal/xsql/conn.go +++ b/internal/xsql/conn.go @@ -17,7 +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/xsql/conn" "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" @@ -26,14 +26,14 @@ import ( ) var ( - _ driver.ConnBeginTx = (*conn)(nil) - _ driver.NamedValueChecker = (*conn)(nil) - _ driver.Pinger = (*conn)(nil) + _ driver.ConnBeginTx = (*connWrapper)(nil) + _ driver.NamedValueChecker = (*connWrapper)(nil) + _ driver.Pinger = (*connWrapper)(nil) ) type ( - conn struct { - cc iface.Conn + connWrapper struct { + cc conn.Conn connector *Connector lastUsage xsync.LastUsage @@ -44,16 +44,16 @@ type ( } ) -func (c *conn) Ping(ctx context.Context) error { +func (c *connWrapper) Ping(ctx context.Context) error { return c.cc.Ping(ctx) } -func (c *conn) CheckNamedValue(value *driver.NamedValue) error { +func (c *connWrapper) 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) { +func (c *connWrapper) 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) @@ -66,7 +66,7 @@ func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, e }, nil } -func (c *conn) Close() error { +func (c *connWrapper) Close() error { err := c.cc.Close() if err != nil { return xerrors.WithStackTrace(err) @@ -75,7 +75,7 @@ func (c *conn) Close() error { return nil } -func (c *conn) Begin() (driver.Tx, error) { +func (c *connWrapper) Begin() (driver.Tx, error) { return nil, xerrors.WithStackTrace(errDeprecated) } @@ -118,13 +118,13 @@ func (r *singleRow) Next(dst []driver.Value) error { return nil } -func (c *conn) Prepare(string) (driver.Stmt, error) { +func (c *connWrapper) Prepare(string) (driver.Stmt, error) { return nil, errDeprecated } -func (c *conn) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, finalErr error) { +func (c *connWrapper) 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/xsql.(*conn).PrepareContext"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*connWrapper).PrepareContext"), sql, ) defer func() { @@ -143,11 +143,11 @@ func (c *conn) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, f }, nil } -func (c *conn) LastUsage() time.Time { +func (c *connWrapper) LastUsage() time.Time { return c.lastUsage.Get() } -func (c *conn) normalize(q string, args ...driver.NamedValue) (query string, _ *params.Params, _ error) { +func (c *connWrapper) normalize(q string, args ...driver.NamedValue) (query string, _ *params.Params, _ error) { queryArgs := make([]any, len(args)) for i := range args { queryArgs[i] = args[i] @@ -163,7 +163,7 @@ func (c *conn) normalize(q string, args ...driver.NamedValue) (query string, _ * return sql, ¶ms, nil } -func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { +func (c *connWrapper) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { done := c.lastUsage.Start() defer done() @@ -184,7 +184,7 @@ func (c *conn) QueryContext(ctx context.Context, query string, args []driver.Nam return c.cc.Query(ctx, query, params) } -func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { +func (c *connWrapper) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { done := c.lastUsage.Start() defer done() @@ -196,15 +196,15 @@ func (c *conn) ExecContext(ctx context.Context, query string, args []driver.Name return c.cc.Exec(ctx, query, params) } -func (c *conn) GetDatabaseName() string { +func (c *connWrapper) GetDatabaseName() string { return c.connector.Name() } -func (c *conn) normalizePath(tableName string) string { +func (c *connWrapper) normalizePath(tableName string) string { return c.connector.pathNormalizer.NormalizePath(tableName) } -func (c *conn) tableDescription(ctx context.Context, tableName string) (d options.Description, _ error) { +func (c *connWrapper) 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.cc.ID(), c.connector.balancer, config.New()).DescribeTable(ctx, tableName) }, retry.WithIdempotent(true), retry.WithBudget(c.connector.retryBudget), retry.WithTrace(c.connector.traceRetry)) @@ -215,7 +215,7 @@ func (c *conn) tableDescription(ctx context.Context, tableName string) (d option return d, nil } -func (c *conn) GetColumns(ctx context.Context, tableName string) (columns []string, _ error) { +func (c *connWrapper) 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) @@ -228,7 +228,7 @@ func (c *conn) GetColumns(ctx context.Context, tableName string) (columns []stri return columns, nil } -func (c *conn) GetColumnType(ctx context.Context, tableName, columnName string) (dataType string, _ error) { +func (c *connWrapper) 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) @@ -243,7 +243,7 @@ func (c *conn) GetColumnType(ctx context.Context, tableName, columnName string) return "", xerrors.WithStackTrace(fmt.Errorf("column '%s' not exist in table '%s'", columnName, tableName)) } -func (c *conn) GetPrimaryKeys(ctx context.Context, tableName string) ([]string, error) { +func (c *connWrapper) GetPrimaryKeys(ctx context.Context, tableName string) ([]string, error) { d, err := c.tableDescription(ctx, c.normalizePath(tableName)) if err != nil { return nil, xerrors.WithStackTrace(err) @@ -252,7 +252,7 @@ func (c *conn) GetPrimaryKeys(ctx context.Context, tableName string) ([]string, return d.PrimaryKey, nil } -func (c *conn) IsPrimaryKey(ctx context.Context, tableName, columnName string) (ok bool, _ error) { +func (c *connWrapper) 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) @@ -267,7 +267,7 @@ func (c *conn) IsPrimaryKey(ctx context.Context, tableName, columnName string) ( return false, nil } -func (c *conn) Version(_ context.Context) (_ string, _ error) { +func (c *connWrapper) Version(_ context.Context) (_ string, _ error) { const version = "default" return version, nil @@ -286,7 +286,7 @@ func isSysDir(databaseName, dirAbsPath string) bool { return false } -func (c *conn) getTables(ctx context.Context, absPath string, recursive, excludeSysDirs bool) ( +func (c *connWrapper) getTables(ctx context.Context, absPath string, recursive, excludeSysDirs bool) ( tables []string, _ error, ) { if excludeSysDirs && isSysDir(c.connector.Name(), absPath) { @@ -320,7 +320,7 @@ func (c *conn) getTables(ctx context.Context, absPath string, recursive, exclude return tables, nil } -func (c *conn) GetTables(ctx context.Context, folder string, recursive, excludeSysDirs bool) ( +func (c *connWrapper) GetTables(ctx context.Context, folder string, recursive, excludeSysDirs bool) ( tables []string, _ error, ) { absPath := c.normalizePath(folder) @@ -349,7 +349,7 @@ func (c *conn) GetTables(ctx context.Context, folder string, recursive, excludeS } } -func (c *conn) GetIndexes(ctx context.Context, tableName string) (indexes []string, _ error) { +func (c *connWrapper) 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) @@ -360,7 +360,7 @@ func (c *conn) GetIndexes(ctx context.Context, tableName string) (indexes []stri }), nil } -func (c *conn) GetIndexColumns(ctx context.Context, tableName, indexName string) (columns []string, _ error) { +func (c *connWrapper) 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) @@ -375,7 +375,7 @@ func (c *conn) GetIndexColumns(ctx context.Context, tableName, indexName string) return xslices.Uniq(columns), nil } -func (c *conn) IsColumnExists(ctx context.Context, tableName, columnName string) (columnExists bool, _ error) { +func (c *connWrapper) 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) @@ -390,10 +390,10 @@ func (c *conn) IsColumnExists(ctx context.Context, tableName, columnName string) return false, nil } -func (c *conn) IsTableExists(ctx context.Context, tableName string) (tableExists bool, finalErr error) { +func (c *connWrapper) 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/xsql.(*conn).IsTableExists"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*connWrapper).IsTableExists"), tableName, ) defer func() { diff --git a/internal/xsql/iface/conn.go b/internal/xsql/conn/conn.go similarity index 97% rename from internal/xsql/iface/conn.go rename to internal/xsql/conn/conn.go index c1a100f82..a490d8abb 100644 --- a/internal/xsql/iface/conn.go +++ b/internal/xsql/conn/conn.go @@ -1,4 +1,4 @@ -package iface +package conn import ( "context" diff --git a/internal/xsql/query/conn/conn.go b/internal/xsql/conn/query/conn/conn.go similarity index 96% rename from internal/xsql/query/conn/conn.go rename to internal/xsql/conn/query/conn/conn.go index ed10f67c6..c7c7b0809 100644 --- a/internal/xsql/query/conn/conn.go +++ b/internal/xsql/conn/query/conn/conn.go @@ -12,7 +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" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn" ) type resultNoRows struct{} @@ -113,7 +113,7 @@ func (c *Conn) isReady() bool { return c.session.Status() == session.StatusIdle.String() } -func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx iface.Tx, finalErr error) { +func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx conn.Tx, finalErr error) { tx, err := beginTx(ctx, c, txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) @@ -144,7 +144,7 @@ func (c *Conn) Ping(ctx context.Context) (finalErr error) { return err } -func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (iface.Tx, error) { +func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (conn.Tx, error) { tx, err := c.beginTx(ctx, txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) diff --git a/internal/xsql/query/conn/errors.go b/internal/xsql/conn/query/conn/errors.go similarity index 100% rename from internal/xsql/query/conn/errors.go rename to internal/xsql/conn/query/conn/errors.go diff --git a/internal/xsql/query/conn/isolation/isolation.go b/internal/xsql/conn/query/conn/isolation/isolation.go similarity index 100% rename from internal/xsql/query/conn/isolation/isolation.go rename to internal/xsql/conn/query/conn/isolation/isolation.go diff --git a/internal/xsql/query/conn/options.go b/internal/xsql/conn/query/conn/options.go similarity index 100% rename from internal/xsql/query/conn/options.go rename to internal/xsql/conn/query/conn/options.go diff --git a/internal/xsql/query/conn/rows.go b/internal/xsql/conn/query/conn/rows.go similarity index 100% rename from internal/xsql/query/conn/rows.go rename to internal/xsql/conn/query/conn/rows.go diff --git a/internal/xsql/query/conn/tx.go b/internal/xsql/conn/query/conn/tx.go similarity index 90% rename from internal/xsql/query/conn/tx.go rename to internal/xsql/conn/query/conn/tx.go index d45f7d751..0574726a6 100644 --- a/internal/xsql/query/conn/tx.go +++ b/internal/xsql/conn/query/conn/tx.go @@ -7,8 +7,8 @@ import ( "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/internal/xsql/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/query" ) @@ -44,7 +44,7 @@ func (tx *transaction) Query(ctx context.Context, sql string, params *params.Par }, nil } -func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (iface.Tx, error) { +func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (conn.Tx, error) { txc, err := isolation.ToYDB(txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) diff --git a/internal/xsql/table/conn/badconn/badconn.go b/internal/xsql/conn/table/conn/badconn/badconn.go similarity index 100% rename from internal/xsql/table/conn/badconn/badconn.go rename to internal/xsql/conn/table/conn/badconn/badconn.go diff --git a/internal/xsql/table/conn/badconn/badconn_test.go b/internal/xsql/conn/table/conn/badconn/badconn_test.go similarity index 100% rename from internal/xsql/table/conn/badconn/badconn_test.go rename to internal/xsql/conn/table/conn/badconn/badconn_test.go diff --git a/internal/xsql/table/conn/conn.go b/internal/xsql/conn/table/conn/conn.go similarity index 97% rename from internal/xsql/table/conn/conn.go rename to internal/xsql/conn/table/conn/conn.go index 1b09539e9..fec413a30 100644 --- a/internal/xsql/table/conn/conn.go +++ b/internal/xsql/conn/table/conn/conn.go @@ -12,8 +12,8 @@ import ( "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/internal/xsql/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/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" @@ -268,7 +268,7 @@ func (c *Conn) ID() string { return c.session.ID() } -func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx iface.Tx, finalErr error) { +func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx conn.Tx, finalErr error) { m := queryModeFromContext(ctx, c.defaultQueryMode) if slices.Contains(c.fakeTxModes, m) { @@ -283,7 +283,7 @@ func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx ifac return tx, nil } -func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (iface.Tx, error) { +func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (conn.Tx, error) { tx, err := c.beginTx(ctx, txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) diff --git a/internal/xsql/table/conn/context.go b/internal/xsql/conn/table/conn/context.go similarity index 100% rename from internal/xsql/table/conn/context.go rename to internal/xsql/conn/table/conn/context.go diff --git a/internal/xsql/table/conn/errors.go b/internal/xsql/conn/table/conn/errors.go similarity index 100% rename from internal/xsql/table/conn/errors.go rename to internal/xsql/conn/table/conn/errors.go diff --git a/internal/xsql/table/conn/isolation/isolation.go b/internal/xsql/conn/table/conn/isolation/isolation.go similarity index 100% rename from internal/xsql/table/conn/isolation/isolation.go rename to internal/xsql/conn/table/conn/isolation/isolation.go diff --git a/internal/xsql/table/conn/isolation/isolation_test.go b/internal/xsql/conn/table/conn/isolation/isolation_test.go similarity index 100% rename from internal/xsql/table/conn/isolation/isolation_test.go rename to internal/xsql/conn/table/conn/isolation/isolation_test.go diff --git a/internal/xsql/table/conn/mode.go b/internal/xsql/conn/table/conn/mode.go similarity index 100% rename from internal/xsql/table/conn/mode.go rename to internal/xsql/conn/table/conn/mode.go diff --git a/internal/xsql/table/conn/options.go b/internal/xsql/conn/table/conn/options.go similarity index 100% rename from internal/xsql/table/conn/options.go rename to internal/xsql/conn/table/conn/options.go diff --git a/internal/xsql/table/conn/rows.go b/internal/xsql/conn/table/conn/rows.go similarity index 97% rename from internal/xsql/table/conn/rows.go rename to internal/xsql/conn/table/conn/rows.go index ed95f3acc..65ed52973 100644 --- a/internal/xsql/table/conn/rows.go +++ b/internal/xsql/conn/table/conn/rows.go @@ -10,7 +10,7 @@ import ( "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/internal/xsql/conn/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/xsql/table/conn/tx.go b/internal/xsql/conn/table/conn/tx.go similarity index 89% rename from internal/xsql/table/conn/tx.go rename to internal/xsql/conn/table/conn/tx.go index 417566f50..2c9cc411f 100644 --- a/internal/xsql/table/conn/tx.go +++ b/internal/xsql/conn/table/conn/tx.go @@ -7,13 +7,13 @@ import ( "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/internal/xsql/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/table" ) -var _ iface.Tx = (*transaction)(nil) +var _ conn.Tx = (*transaction)(nil) type transaction struct { conn *Conn @@ -84,7 +84,7 @@ func (tx *transaction) Rollback(ctx context.Context) error { return err } -func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (iface.Tx, error) { +func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (conn.Tx, error) { txc, err := isolation.ToYDB(txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) diff --git a/internal/xsql/table/conn/tx_fake.go b/internal/xsql/conn/table/conn/tx_fake.go similarity index 86% rename from internal/xsql/table/conn/tx_fake.go rename to internal/xsql/conn/table/conn/tx_fake.go index 1fcd3d790..6917185b5 100644 --- a/internal/xsql/table/conn/tx_fake.go +++ b/internal/xsql/conn/table/conn/tx_fake.go @@ -7,8 +7,8 @@ import ( "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" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" ) type txFake struct { @@ -36,7 +36,7 @@ func (tx *txFake) Query(ctx context.Context, sql string, params *params.Params) return rows, nil } -func beginTxFake(ctx context.Context, c *Conn) iface.Tx { +func beginTxFake(ctx context.Context, c *Conn) conn.Tx { return &txFake{ Identifier: tx.ID("FAKE"), conn: c, diff --git a/internal/xsql/table/conn/valuer.go b/internal/xsql/conn/table/conn/valuer.go similarity index 100% rename from internal/xsql/table/conn/valuer.go rename to internal/xsql/conn/table/conn/valuer.go diff --git a/internal/xsql/iface/tx.go b/internal/xsql/conn/tx.go similarity index 96% rename from internal/xsql/iface/tx.go rename to internal/xsql/conn/tx.go index d75dd8d83..a9fe25012 100644 --- a/internal/xsql/iface/tx.go +++ b/internal/xsql/conn/tx.go @@ -1,4 +1,4 @@ -package iface +package conn import ( "context" diff --git a/internal/xsql/conn_test.go b/internal/xsql/conn_test.go index ac8da4fdf..9d3e1d4d1 100644 --- a/internal/xsql/conn_test.go +++ b/internal/xsql/conn_test.go @@ -5,45 +5,45 @@ import "context" var ( _ interface { GetDatabaseName() string - } = (*conn)(nil) + } = (*connWrapper)(nil) _ interface { Version(ctx context.Context) (version string, err error) - } = (*conn)(nil) + } = (*connWrapper)(nil) _ interface { IsTableExists(ctx context.Context, tableName string) (tableExists bool, err error) - } = (*conn)(nil) + } = (*connWrapper)(nil) _ interface { IsColumnExists(ctx context.Context, tableName string, columnName string) (columnExists bool, err error) - } = (*conn)(nil) + } = (*connWrapper)(nil) _ interface { IsPrimaryKey(ctx context.Context, tableName string, columnName string) (ok bool, err error) - } = (*conn)(nil) + } = (*connWrapper)(nil) _ interface { GetColumns(ctx context.Context, tableName string) (columns []string, err error) - } = (*conn)(nil) + } = (*connWrapper)(nil) _ interface { GetColumnType(ctx context.Context, tableName string, columnName string) (dataType string, err error) - } = (*conn)(nil) + } = (*connWrapper)(nil) _ interface { GetPrimaryKeys(ctx context.Context, tableName string) (pkCols []string, err error) - } = (*conn)(nil) + } = (*connWrapper)(nil) _ interface { GetTables(ctx context.Context, folder string, recursive bool, excludeSysDirs bool) (tables []string, err error) - } = (*conn)(nil) + } = (*connWrapper)(nil) _ interface { GetIndexes(ctx context.Context, tableName string) (indexes []string, err error) - } = (*conn)(nil) + } = (*connWrapper)(nil) _ interface { GetIndexColumns(ctx context.Context, tableName string, indexName string) (columns []string, err error) - } = (*conn)(nil) + } = (*connWrapper)(nil) ) diff --git a/internal/xsql/connector.go b/internal/xsql/connector.go index 26581664e..12cc9db2d 100644 --- a/internal/xsql/connector.go +++ b/internal/xsql/connector.go @@ -15,8 +15,8 @@ import ( "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" + conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query/conn" + conn4 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/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" @@ -38,14 +38,14 @@ type ( queryProcessor queryProcessor - TableOpts []conn2.Option - QueryOpts []conn3.Option + TableOpts []conn4.Option + QueryOpts []conn2.Option disableServerBalancer bool onCLose []func(*Connector) clock clockwork.Clock idleThreshold time.Duration - conns xsync.Map[uuid.UUID, *conn] + conns xsync.Map[uuid.UUID, *connWrapper] done chan struct{} trace *trace.DatabaseSQL traceRetry *trace.Retry @@ -121,10 +121,10 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() - conn := &conn{ - cc: conn3.New(ctx, c, s, append( + conn := &connWrapper{ + cc: conn2.New(ctx, c, s, append( c.QueryOpts, - conn3.WithOnClose(func() { + conn2.WithOnClose(func() { c.conns.Delete(id) }))..., ), @@ -144,9 +144,9 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() - conn := &conn{ - cc: conn2.New(ctx, c, s, append(c.TableOpts, - conn2.WithOnClose(func() { + conn := &connWrapper{ + cc: conn4.New(ctx, c, s, append(c.TableOpts, + conn4.WithOnClose(func() { c.conns.Delete(id) }))..., ), @@ -224,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 *conn) bool { + c.conns.Range(func(_ uuid.UUID, cc *connWrapper) bool { if c.clock.Since(cc.LastUsage()) > c.idleThreshold { _ = cc.Close() } diff --git a/internal/xsql/errors.go b/internal/xsql/errors.go index 252485975..f564b005c 100644 --- a/internal/xsql/errors.go +++ b/internal/xsql/errors.go @@ -12,5 +12,5 @@ var ( errDeprecated = driver.ErrSkip errAlreadyClosed = errors.New("already closed") errWrongQueryProcessor = errors.New("wrong query processor") - errNotReadyConn = xerrors.Retryable(errors.New("conn not ready"), xerrors.InvalidObject()) + errNotReadyConn = xerrors.Retryable(errors.New("connWrapper not ready"), xerrors.InvalidObject()) ) diff --git a/internal/xsql/options.go b/internal/xsql/options.go index c6b2d8964..ad41666fa 100644 --- a/internal/xsql/options.go +++ b/internal/xsql/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/xsql/query/conn" - conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/table/conn" + querySql "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query/conn" + conn3 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/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 []conn2.Option + tableOps []conn3.Option queryOpts []querySql.Option } traceDatabaseSQLOption struct { @@ -146,31 +146,31 @@ func WithQueryBind(bind bind.Bind) QueryBindOption { } } -func WithDefaultQueryMode(mode conn2.QueryMode) Option { +func WithDefaultQueryMode(mode conn3.QueryMode) Option { return tableQueryOptionsOption{ - tableOps: []conn2.Option{ - conn2.WithDefaultQueryMode(mode), + tableOps: []conn3.Option{ + conn3.WithDefaultQueryMode(mode), }, } } -func WithFakeTx(modes ...conn2.QueryMode) Option { +func WithFakeTx(modes ...conn3.QueryMode) Option { return tableQueryOptionsOption{ - tableOps: []conn2.Option{ - conn2.WithFakeTxModes(modes...), + tableOps: []conn3.Option{ + conn3.WithFakeTxModes(modes...), }, } } func WithIdleThreshold(idleThreshold time.Duration) Option { return tableQueryOptionsOption{ - tableOps: []conn2.Option{ - conn2.WithIdleThreshold(idleThreshold), + tableOps: []conn3.Option{ + conn3.WithIdleThreshold(idleThreshold), }, } } -func WithTableOptions(opts ...conn2.Option) Option { +func WithTableOptions(opts ...conn3.Option) Option { return tableQueryOptionsOption{ tableOps: opts, } diff --git a/internal/xsql/stmt.go b/internal/xsql/stmt.go index 6bf400ea9..75fde9100 100644 --- a/internal/xsql/stmt.go +++ b/internal/xsql/stmt.go @@ -11,7 +11,7 @@ import ( ) type stmt struct { - conn *conn + conn *connWrapper processor interface { Exec(ctx context.Context, sql string, params *params.Params) (driver.Result, error) Query(ctx context.Context, sql string, params *params.Params) (driver.RowsNextResultSet, error) diff --git a/internal/xsql/tx.go b/internal/xsql/tx.go index 5605de590..3cf83c1ac 100644 --- a/internal/xsql/tx.go +++ b/internal/xsql/tx.go @@ -6,14 +6,14 @@ import ( "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/internal/xsql/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) type txWrapper struct { - conn *conn - tx iface.Tx + conn *connWrapper + tx conn.Tx ctx context.Context //nolint:containedctx } diff --git a/internal/xsql/unwrap.go b/internal/xsql/unwrap.go index 7301f5b3e..882e242a7 100644 --- a/internal/xsql/unwrap.go +++ b/internal/xsql/unwrap.go @@ -5,7 +5,7 @@ import ( "fmt" "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/xsql/conn/table/conn/badconn" ) func Unwrap[T *sql.DB | *sql.Conn](v T) (connector *Connector, _ error) { @@ -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.(*conn); ok { + if cc, ok := driverConn.(*connWrapper); ok { connector = cc.connector return nil } - return xerrors.WithStackTrace(fmt.Errorf("%T is not a *conn", driverConn)) + return xerrors.WithStackTrace(fmt.Errorf("%T is not a *connWrapper", driverConn)) }); err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } diff --git a/retry/errors.go b/retry/errors.go index 5f19bed13..0f5b81923 100644 --- a/retry/errors.go +++ b/retry/errors.go @@ -2,7 +2,7 @@ package retry import ( "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/xsql/conn/table/conn/badconn" ) func unwrapErrBadConn(err error) error { diff --git a/retry/sql_test.go b/retry/sql_test.go index 5f6027105..d324f69c8 100644 --- a/retry/sql_test.go +++ b/retry/sql_test.go @@ -13,7 +13,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/backoff" "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" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" ) type mockConnector struct { diff --git a/sql.go b/sql.go index f222b6a2e..9a7e9aa14 100644 --- a/sql.go +++ b/sql.go @@ -9,7 +9,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" "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" + conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/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" @@ -78,7 +78,7 @@ func (d *sqlDriver) detach(c *xsql.Connector) { d.connectors.Delete(c) } -type QueryMode = conn.QueryMode +type QueryMode = conn2.QueryMode const ( DataQueryMode = iota + 1 @@ -93,20 +93,20 @@ func WithQueryMode(ctx context.Context, mode QueryMode) context.Context { case ExplainQueryMode: return xsql.WithExplain(ctx) case DataQueryMode: - return conn.WithQueryMode(ctx, conn.DataQueryMode) + return conn2.WithQueryMode(ctx, conn2.DataQueryMode) case ScanQueryMode: - return conn.WithQueryMode(ctx, conn.ScanQueryMode) + return conn2.WithQueryMode(ctx, conn2.ScanQueryMode) case SchemeQueryMode: - return conn.WithQueryMode(ctx, conn.SchemeQueryMode) + return conn2.WithQueryMode(ctx, conn2.SchemeQueryMode) case ScriptingQueryMode: - return conn.WithQueryMode(ctx, conn.ScriptingQueryMode) + return conn2.WithQueryMode(ctx, conn2.ScriptingQueryMode) default: return ctx } } func WithTxControl(ctx context.Context, txc *table.TransactionControl) context.Context { - return conn.WithTxControl(ctx, txc) + return conn2.WithTxControl(ctx, txc) } type ConnectorOption = xsql.Option @@ -117,11 +117,11 @@ type QueryBindConnectorOption interface { } func WithDefaultQueryMode(mode QueryMode) ConnectorOption { - return xsql.WithTableOptions(conn.WithDefaultQueryMode(mode)) + return xsql.WithTableOptions(conn2.WithDefaultQueryMode(mode)) } func WithFakeTx(mode QueryMode) ConnectorOption { - return xsql.WithTableOptions(conn.WithFakeTxModes(mode)) + return xsql.WithTableOptions(conn2.WithFakeTxModes(mode)) } func WithTablePathPrefix(tablePathPrefix string) QueryBindConnectorOption { @@ -141,15 +141,15 @@ func WithNumericArgs() QueryBindConnectorOption { } func WithDefaultTxControl(txControl *table.TransactionControl) ConnectorOption { - return xsql.WithTableOptions(conn.WithDefaultTxControl(txControl)) + return xsql.WithTableOptions(conn2.WithDefaultTxControl(txControl)) } func WithDefaultDataQueryOptions(opts ...options.ExecuteDataQueryOption) ConnectorOption { - return xsql.WithTableOptions(conn.WithDataOpts(opts...)) + return xsql.WithTableOptions(conn2.WithDataOpts(opts...)) } func WithDefaultScanQueryOptions(opts ...options.ExecuteScanQueryOption) ConnectorOption { - return xsql.WithTableOptions(conn.WithScanOpts(opts...)) + return xsql.WithTableOptions(conn2.WithScanOpts(opts...)) } func WithDatabaseSQLTrace( diff --git a/tests/integration/database_sql_regression_test.go b/tests/integration/database_sql_regression_test.go index 7edc8685f..62f6d993f 100644 --- a/tests/integration/database_sql_regression_test.go +++ b/tests/integration/database_sql_regression_test.go @@ -19,7 +19,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3" "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/xsql/conn/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 c709a3aa7..b2b9ca725 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/xsql/table/conn" + tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/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" diff --git a/topic/topictypes/topictypes_test.go b/topic/topictypes/topictypes_test.go index 606e07610..3dc9f16da 100644 --- a/topic/topictypes/topictypes_test.go +++ b/topic/topictypes/topictypes_test.go @@ -152,7 +152,6 @@ func TestTopicDescriptionFromRaw(t *testing.T) { } for _, v := range testData { - v := v t.Run( v.testName, func(t *testing.T) { d := TopicDescription{} @@ -322,7 +321,6 @@ func TestTopicConsumerDescriptionFromRaw(t *testing.T) { }, } for _, v := range testData { - v := v t.Run( v.testName, func(t *testing.T) { d := TopicConsumerDescription{} From 3f5638b1da06f8b50eb9b8ecc942f1fbea1ad9e2 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Wed, 11 Dec 2024 08:50:36 +0300 Subject: [PATCH 50/62] refactoring --- dsn.go | 14 ++-- dsn_test.go | 30 +++---- examples/ddl/ddl.go | 4 +- internal/bind/auto_declare.go | 6 +- internal/bind/bind.go | 16 ++-- internal/bind/numeric_args.go | 2 +- internal/bind/numeric_args_test.go | 2 +- internal/bind/positional_args.go | 2 +- internal/bind/positional_args_test.go | 2 +- internal/bind/table_path_prefix.go | 4 +- internal/scripting/client.go | 62 ++++++-------- internal/table/data_query.go | 14 ++-- internal/table/session.go | 39 +++------ internal/table/transaction.go | 8 +- internal/xsql/conn.go | 22 +++-- internal/xsql/conn/context.go | 15 ++++ internal/xsql/conn/query/{conn => }/conn.go | 2 +- internal/xsql/conn/query/{conn => }/errors.go | 2 +- .../query/{conn/isolation => }/isolation.go | 4 +- .../xsql/conn/query/{conn => }/options.go | 2 +- internal/xsql/conn/query/{conn => }/rows.go | 2 +- internal/xsql/conn/query/{conn => }/tx.go | 5 +- .../conn/table/{conn => }/badconn/badconn.go | 0 .../table/{conn => }/badconn/badconn_test.go | 0 internal/xsql/conn/table/{conn => }/conn.go | 19 ++--- .../xsql/conn/table/{conn => }/context.go | 37 +-------- internal/xsql/conn/table/{conn => }/errors.go | 2 +- .../table/{conn/isolation => }/isolation.go | 6 +- .../{conn/isolation => }/isolation_test.go | 4 +- internal/xsql/conn/table/{conn => }/mode.go | 2 +- .../xsql/conn/table/{conn => }/options.go | 2 +- internal/xsql/conn/table/{conn => }/rows.go | 4 +- internal/xsql/conn/table/{conn => }/tx.go | 7 +- .../xsql/conn/table/{conn => }/tx_fake.go | 4 +- internal/xsql/conn/table/{conn => }/valuer.go | 2 +- internal/xsql/connector.go | 16 ++-- internal/xsql/options.go | 28 +++---- internal/xsql/stmt.go | 4 +- internal/xsql/tx.go | 20 ++--- internal/xsql/unwrap.go | 2 +- query/client.go | 18 ++--- query_bind_test.go | 5 +- retry/errors.go | 2 +- retry/sql_test.go | 26 +++--- scripting/scripting.go | 18 +---- sql.go | 24 +++--- sugar/params_test.go | 4 +- table/table.go | 80 +++++-------------- .../database_sql_regression_test.go | 2 +- .../database_sql_with_tx_control_test.go | 2 +- 50 files changed, 245 insertions(+), 354 deletions(-) create mode 100644 internal/xsql/conn/context.go rename internal/xsql/conn/query/{conn => }/conn.go (99%) rename internal/xsql/conn/query/{conn => }/errors.go (96%) rename internal/xsql/conn/query/{conn/isolation => }/isolation.go (88%) rename internal/xsql/conn/query/{conn => }/options.go (90%) rename internal/xsql/conn/query/{conn => }/rows.go (99%) rename internal/xsql/conn/query/{conn => }/tx.go (92%) rename internal/xsql/conn/table/{conn => }/badconn/badconn.go (100%) rename internal/xsql/conn/table/{conn => }/badconn/badconn_test.go (100%) rename internal/xsql/conn/table/{conn => }/conn.go (92%) rename internal/xsql/conn/table/{conn => }/context.go (51%) rename internal/xsql/conn/table/{conn => }/errors.go (96%) rename internal/xsql/conn/table/{conn/isolation => }/isolation.go (85%) rename internal/xsql/conn/table/{conn/isolation => }/isolation_test.go (98%) rename internal/xsql/conn/table/{conn => }/mode.go (98%) rename internal/xsql/conn/table/{conn => }/options.go (98%) rename internal/xsql/conn/table/{conn => }/rows.go (99%) rename internal/xsql/conn/table/{conn => }/tx.go (94%) rename internal/xsql/conn/table/{conn => }/tx_fake.go (98%) rename internal/xsql/conn/table/{conn => }/valuer.go (94%) diff --git a/dsn.go b/dsn.go index 243ad311f..466bbf87a 100644 --- a/dsn.go +++ b/dsn.go @@ -12,7 +12,7 @@ import ( "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/conn/table/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" ) const tablePathPrefixTransformer = "table_path_prefix" @@ -60,22 +60,22 @@ 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) - if mode == tableSql.UnknownQueryMode { + mode := table.QueryModeFromString(queryMode) + if mode == table.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } opts = append(opts, withConnectorOptions(xsql.WithDefaultQueryMode(mode))) } else if queryMode := info.Params.Get("query_mode"); queryMode != "" { - mode := tableSql.QueryModeFromString(queryMode) - if mode == tableSql.UnknownQueryMode { + mode := table.QueryModeFromString(queryMode) + if mode == table.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } opts = append(opts, withConnectorOptions(xsql.WithDefaultQueryMode(mode))) } if fakeTx := info.Params.Get("go_fake_tx"); fakeTx != "" { for _, queryMode := range strings.Split(fakeTx, ",") { - mode := tableSql.QueryModeFromString(queryMode) - if mode == tableSql.UnknownQueryMode { + mode := table.QueryModeFromString(queryMode) + if mode == table.UnknownQueryMode { return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } opts = append(opts, withConnectorOptions(xsql.WithFakeTx(mode))) diff --git a/dsn_test.go b/dsn_test.go index 2871553a5..217df60bd 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/xsql" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query/conn" - conn3 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" ) func TestParse(t *testing.T) { @@ -26,11 +26,11 @@ func TestParse(t *testing.T) { return c } - newTableConn := func(opts ...conn3.Option) *conn3.Conn { - return conn3.New(context.Background(), nil, nil, opts...) + newTableConn := func(opts ...table.Option) *table.Conn { + return table.New(context.Background(), nil, nil, opts...) } - newQueryConn := func(opts ...conn.Option) *conn.Conn { - return conn.New(context.Background(), nil, nil, opts...) + newQueryConn := func(opts ...query.Option) *query.Conn { + return query.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: []xsql.Option{ - xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), + xsql.WithDefaultQueryMode(table.ScriptingQueryMode), }, err: nil, }, @@ -83,7 +83,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), + xsql.WithDefaultQueryMode(table.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), }, err: nil, @@ -96,7 +96,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), + xsql.WithDefaultQueryMode(table.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.NumericArgs{}), }, @@ -110,7 +110,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), + xsql.WithDefaultQueryMode(table.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.PositionalArgs{}), }, @@ -124,7 +124,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), + xsql.WithDefaultQueryMode(table.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.AutoDeclare{}), }, @@ -138,7 +138,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), + xsql.WithDefaultQueryMode(table.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), }, err: nil, @@ -151,7 +151,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(conn3.ScriptingQueryMode), + xsql.WithDefaultQueryMode(table.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.PositionalArgs{}), xsql.WithQueryBind(bind.AutoDeclare{}), @@ -166,8 +166,8 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithFakeTx(conn3.ScriptingQueryMode), - xsql.WithFakeTx(conn3.SchemeQueryMode), + xsql.WithFakeTx(table.ScriptingQueryMode), + xsql.WithFakeTx(table.SchemeQueryMode), }, err: nil, }, diff --git a/examples/ddl/ddl.go b/examples/ddl/ddl.go index 9e0d4725a..d602e919b 100644 --- a/examples/ddl/ddl.go +++ b/examples/ddl/ddl.go @@ -67,10 +67,10 @@ ALTER TABLE small_table3 SET (TTL = Interval("PT3H") ON d); ` ) -func executeQuery(ctx context.Context, c table.Client, prefix, query string) (err error) { +func executeQuery(ctx context.Context, c table.Client, prefix, sql string) (err error) { err = c.Do(ctx, func(ctx context.Context, s table.Session) error { - err = s.ExecuteSchemeQuery(ctx, fmt.Sprintf(query, prefix)) + err = s.ExecuteSchemeQuery(ctx, fmt.Sprintf(sql, prefix)) return err }, diff --git a/internal/bind/auto_declare.go b/internal/bind/auto_declare.go index a3c07c4f7..5fcf3eaf3 100644 --- a/internal/bind/auto_declare.go +++ b/internal/bind/auto_declare.go @@ -13,7 +13,7 @@ func (m AutoDeclare) blockID() blockID { return blockDeclare } -func (m AutoDeclare) RewriteQuery(query string, args ...interface{}) ( +func (m AutoDeclare) ToYdb(sql string, args ...interface{}) ( yql string, newArgs []interface{}, err error, ) { params, err := Params(args...) @@ -22,7 +22,7 @@ func (m AutoDeclare) RewriteQuery(query string, args ...interface{}) ( } if len(params) == 0 { - return query, args, nil + return sql, args, nil } var ( @@ -46,7 +46,7 @@ func (m AutoDeclare) RewriteQuery(query string, args ...interface{}) ( buffer.WriteByte('\n') - buffer.WriteString(query) + buffer.WriteString(sql) for _, param := range params { newArgs = append(newArgs, param) diff --git a/internal/bind/bind.go b/internal/bind/bind.go index c6d1111c6..a489d2faf 100644 --- a/internal/bind/bind.go +++ b/internal/bind/bind.go @@ -17,7 +17,7 @@ const ( ) type Bind interface { - RewriteQuery(sql string, args ...interface{}) ( + ToYdb(sql string, args ...interface{}) ( yql string, newArgs []interface{}, _ error, ) @@ -26,16 +26,16 @@ type Bind interface { type Bindings []Bind -func (bindings Bindings) RewriteQuery(query string, args ...interface{}) ( - yql string, parameters []*params.Parameter, err error, +func (bindings Bindings) ToYdb(sql string, args ...interface{}) ( + yql string, params params.Params, err error, ) { if len(bindings) == 0 { - parameters, err = Params(args...) + params, err = Params(args...) if err != nil { return "", nil, xerrors.WithStackTrace(err) } - return query, parameters, nil + return sql, params, nil } buffer := xstring.Buffer() @@ -43,18 +43,18 @@ func (bindings Bindings) RewriteQuery(query string, args ...interface{}) ( for i := range bindings { var e error - query, args, e = bindings[len(bindings)-1-i].RewriteQuery(query, args...) + sql, args, e = bindings[len(bindings)-1-i].ToYdb(sql, args...) if e != nil { return "", nil, xerrors.WithStackTrace(e) } } - parameters, err = Params(args...) + params, err = Params(args...) if err != nil { return "", nil, xerrors.WithStackTrace(err) } - return query, parameters, nil + return sql, params, nil } func Sort(bindings []Bind) []Bind { diff --git a/internal/bind/numeric_args.go b/internal/bind/numeric_args.go index 75319449a..3d5488357 100644 --- a/internal/bind/numeric_args.go +++ b/internal/bind/numeric_args.go @@ -17,7 +17,7 @@ func (m NumericArgs) blockID() blockID { return blockYQL } -func (m NumericArgs) RewriteQuery(sql string, args ...interface{}) (yql string, newArgs []interface{}, err error) { +func (m NumericArgs) ToYdb(sql string, args ...interface{}) (yql string, newArgs []interface{}, err error) { l := &sqlLexer{ src: sql, stateFn: numericArgsStateFn, diff --git a/internal/bind/numeric_args_test.go b/internal/bind/numeric_args_test.go index 4f40da6c0..9b32166fb 100644 --- a/internal/bind/numeric_args_test.go +++ b/internal/bind/numeric_args_test.go @@ -314,7 +314,7 @@ SELECT $p0, $p1`, }, } { t.Run("", func(t *testing.T) { - yql, params, err := b.RewriteQuery(tt.sql, tt.args...) + yql, params, err := b.ToYdb(tt.sql, tt.args...) if tt.err != nil { require.Error(t, err) require.ErrorIs(t, err, tt.err) diff --git a/internal/bind/positional_args.go b/internal/bind/positional_args.go index e3c0afa13..997ddfda5 100644 --- a/internal/bind/positional_args.go +++ b/internal/bind/positional_args.go @@ -16,7 +16,7 @@ func (m PositionalArgs) blockID() blockID { return blockYQL } -func (m PositionalArgs) RewriteQuery(sql string, args ...interface{}) ( +func (m PositionalArgs) ToYdb(sql string, args ...interface{}) ( yql string, newArgs []interface{}, err error, ) { l := &sqlLexer{ diff --git a/internal/bind/positional_args_test.go b/internal/bind/positional_args_test.go index f1224730e..a7d65d18a 100644 --- a/internal/bind/positional_args_test.go +++ b/internal/bind/positional_args_test.go @@ -238,7 +238,7 @@ SELECT $p0, $p1`, }, } { t.Run("", func(t *testing.T) { - yql, params, err := b.RewriteQuery(tt.sql, tt.args...) + yql, params, err := b.ToYdb(tt.sql, tt.args...) if tt.err != nil { require.Error(t, err) require.ErrorIs(t, err, tt.err) diff --git a/internal/bind/table_path_prefix.go b/internal/bind/table_path_prefix.go index 84cf3f05f..acfcd3ed5 100644 --- a/internal/bind/table_path_prefix.go +++ b/internal/bind/table_path_prefix.go @@ -24,7 +24,7 @@ func (tablePathPrefix TablePathPrefix) NormalizePath(folderOrTable string) strin } } -func (tablePathPrefix TablePathPrefix) RewriteQuery(query string, args ...interface{}) ( +func (tablePathPrefix TablePathPrefix) ToYdb(sql string, args ...interface{}) ( yql string, newArgs []interface{}, err error, ) { buffer := xstring.Buffer() @@ -34,7 +34,7 @@ func (tablePathPrefix TablePathPrefix) RewriteQuery(query string, args ...interf buffer.WriteString("PRAGMA TablePathPrefix(\"") buffer.WriteString(string(tablePathPrefix)) buffer.WriteString("\");\n\n") - buffer.WriteString(query) + buffer.WriteString(sql) return buffer.String(), args, nil } diff --git a/internal/scripting/client.go b/internal/scripting/client.go index 9b2147c77..d2eaaff9a 100644 --- a/internal/scripting/client.go +++ b/internal/scripting/client.go @@ -39,16 +39,12 @@ type ( } ) -func (c *Client) Execute( - ctx context.Context, - query string, - parameters *params.Params, -) (r result.Result, err error) { +func (c *Client) Execute(ctx context.Context, sql string, parameters *params.Params) (r result.Result, err error) { if c == nil { return r, xerrors.WithStackTrace(errNilClient) } call := func(ctx context.Context) error { - r, err = c.execute(ctx, query, parameters) + r, err = c.execute(ctx, sql, parameters) return xerrors.WithStackTrace(err) } @@ -66,19 +62,15 @@ func (c *Client) Execute( return r, xerrors.WithStackTrace(err) } -func (c *Client) execute( - ctx context.Context, - query string, - parameters *params.Params, -) (r result.Result, err error) { +func (c *Client) execute(ctx context.Context, sql string, parameters *params.Params) (r result.Result, err error) { var ( onDone = trace.ScriptingOnExecute(c.config.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/scripting.(*Client).execute"), - query, parameters, + sql, parameters, ) a = allocator.New() request = &Ydb_Scripting.ExecuteYqlRequest{ - Script: query, + Script: sql, OperationParams: operation.Params( ctx, c.config.OperationTimeout(), @@ -125,16 +117,14 @@ func mode2mode(mode scripting.ExplainMode) Ydb_Scripting.ExplainYqlRequest_Mode } } -func (c *Client) Explain( - ctx context.Context, - query string, - mode scripting.ExplainMode, -) (e table.ScriptingYQLExplanation, err error) { +func (c *Client) Explain(ctx context.Context, sql string, mode scripting.ExplainMode) ( + e table.ScriptingYQLExplanation, err error, +) { if c == nil { return e, xerrors.WithStackTrace(errNilClient) } call := func(ctx context.Context) error { - e, err = c.explain(ctx, query, mode) + e, err = c.explain(ctx, sql, mode) return xerrors.WithStackTrace(err) } @@ -153,18 +143,16 @@ func (c *Client) Explain( return e, xerrors.WithStackTrace(err) } -func (c *Client) explain( - ctx context.Context, - query string, - mode scripting.ExplainMode, -) (e table.ScriptingYQLExplanation, err error) { +func (c *Client) explain(ctx context.Context, sql string, mode scripting.ExplainMode) ( + e table.ScriptingYQLExplanation, err error, +) { var ( onDone = trace.ScriptingOnExplain(c.config.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/scripting.(*Client).explain"), - query, + sql, ) request = &Ydb_Scripting.ExplainYqlRequest{ - Script: query, + Script: sql, Mode: mode2mode(mode), OperationParams: operation.Params( ctx, @@ -201,16 +189,14 @@ func (c *Client) explain( return e, nil } -func (c *Client) StreamExecute( - ctx context.Context, - query string, - params *params.Params, -) (r result.StreamResult, err error) { +func (c *Client) StreamExecute(ctx context.Context, sql string, params *params.Params) ( + r result.StreamResult, err error, +) { if c == nil { return r, xerrors.WithStackTrace(errNilClient) } call := func(ctx context.Context) error { - r, err = c.streamExecute(ctx, query, params) + r, err = c.streamExecute(ctx, sql, params) return xerrors.WithStackTrace(err) } @@ -229,19 +215,17 @@ func (c *Client) StreamExecute( } //nolint:funlen -func (c *Client) streamExecute( - ctx context.Context, - query string, - parameters *params.Params, -) (r result.StreamResult, err error) { +func (c *Client) streamExecute(ctx context.Context, sql string, parameters *params.Params) ( + r result.StreamResult, err error, +) { var ( onIntermediate = trace.ScriptingOnStreamExecute(c.config.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/scripting.(*Client).streamExecute"), - query, parameters, + sql, parameters, ) a = allocator.New() request = &Ydb_Scripting.ExecuteYqlRequest{ - Script: query, + Script: sql, OperationParams: operation.Params( ctx, c.config.OperationTimeout(), diff --git a/internal/table/data_query.go b/internal/table/data_query.go index f918b7192..7a8dfc0cb 100644 --- a/internal/table/data_query.go +++ b/internal/table/data_query.go @@ -16,8 +16,8 @@ type ( } textDataQuery string preparedDataQuery struct { - id string - query string + id string + sql string } ) @@ -41,7 +41,7 @@ func (q textDataQuery) toYDB(a *allocator.Allocator) *Ydb_Table.Query { } func (q preparedDataQuery) String() string { - return q.query + return q.sql } func (q preparedDataQuery) ID() string { @@ -49,7 +49,7 @@ func (q preparedDataQuery) ID() string { } func (q preparedDataQuery) YQL() string { - return q.query + return q.sql } func (q preparedDataQuery) toYDB(a *allocator.Allocator) *Ydb_Table.Query { @@ -63,9 +63,9 @@ func queryFromText(s string) query { return textDataQuery(s) } -func queryPrepared(id, query string) query { +func queryPrepared(id, sql string) query { return preparedDataQuery{ - id: id, - query: query, + id: id, + sql: sql, } } diff --git a/internal/table/session.go b/internal/table/session.go index 86c9a216c..6110e88e3 100644 --- a/internal/table/session.go +++ b/internal/table/session.go @@ -688,20 +688,14 @@ func (s *session) RenameTables( } // Explain explains data query represented by text. -func (s *session) Explain( - ctx context.Context, - query string, -) ( - exp table.DataQueryExplanation, - err error, -) { +func (s *session) Explain(ctx context.Context, sql string) (exp table.DataQueryExplanation, err error) { var ( result Ydb_Table.ExplainQueryResult response *Ydb_Table.ExplainDataQueryResponse onDone = trace.TableOnSessionQueryExplain( s.config.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table.(*session).Explain"), - s, query, + s, sql, ) ) defer func() { @@ -715,7 +709,7 @@ func (s *session) Explain( response, err = s.client.ExplainDataQuery(ctx, &Ydb_Table.ExplainDataQueryRequest{ SessionId: s.id, - YqlText: query, + YqlText: sql, OperationParams: operation.Params( ctx, s.config.OperationTimeout(), @@ -792,18 +786,14 @@ func (s *session) Prepare(ctx context.Context, queryText string) (_ table.Statem } // Execute executes given data query represented by text. -func (s *session) Execute( - ctx context.Context, - txControl *table.TransactionControl, - query string, - parameters *params.Params, +func (s *session) Execute(ctx context.Context, txControl *table.TransactionControl, sql string, params *params.Params, opts ...options.ExecuteDataQueryOption, ) ( txr table.Transaction, r result.Result, err error, ) { var ( a = allocator.New() - q = queryFromText(query) + q = queryFromText(sql) request = options.ExecuteDataQueryDesc{ ExecuteDataQueryRequest: a.TableExecuteDataQueryRequest(), IgnoreTruncated: s.config.IgnoreTruncated(), @@ -812,14 +802,14 @@ func (s *session) Execute( ) defer a.Free() - params, err := parameters.ToYDB(a) + parameters, err := params.ToYDB(a) if err != nil { return nil, nil, xerrors.WithStackTrace(err) } request.SessionId = s.id request.TxControl = txControl.Desc() - request.Parameters = params + request.Parameters = parameters request.Query = q.toYDB(a) request.QueryCachePolicy = a.TableQueryCachePolicy() request.QueryCachePolicy.KeepInCache = len(request.Parameters) > 0 @@ -838,7 +828,7 @@ func (s *session) Execute( onDone := trace.TableOnSessionQueryExecute( s.config.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table.(*session).Execute"), - s, q, parameters, + s, q, params, request.QueryCachePolicy.GetKeepInCache(), ) defer func() { @@ -907,14 +897,12 @@ func (s *session) executeDataQuery( } // ExecuteSchemeQuery executes scheme query. -func (s *session) ExecuteSchemeQuery( - ctx context.Context, - query string, +func (s *session) ExecuteSchemeQuery(ctx context.Context, sql string, opts ...options.ExecuteSchemeQueryOption, ) (err error) { request := Ydb_Table.ExecuteSchemeQueryRequest{ SessionId: s.id, - YqlText: query, + YqlText: sql, OperationParams: operation.Params( ctx, s.config.OperationTimeout(), @@ -1191,15 +1179,12 @@ func (s *session) ReadRows( // via Close() call or fully drained by sequential NextResultSet() calls. // //nolint:funlen -func (s *session) StreamExecuteScanQuery( - ctx context.Context, - query string, - parameters *params.Params, +func (s *session) StreamExecuteScanQuery(ctx context.Context, sql string, parameters *params.Params, opts ...options.ExecuteScanQueryOption, ) (_ result.StreamResult, err error) { var ( a = allocator.New() - q = queryFromText(query) + q = queryFromText(sql) onDone = trace.TableOnSessionQueryStreamExecute( s.config.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table.(*session).StreamExecuteScanQuery"), diff --git a/internal/table/transaction.go b/internal/table/transaction.go index e005dcc10..d221f1183 100644 --- a/internal/table/transaction.go +++ b/internal/table/transaction.go @@ -56,15 +56,13 @@ type transaction struct { } // Execute executes query represented by text within transaction tx. -func (tx *transaction) Execute( - ctx context.Context, - query string, parameters *params.Params, +func (tx *transaction) Execute(ctx context.Context, sql string, params *params.Params, opts ...options.ExecuteDataQueryOption, ) (r result.Result, err error) { onDone := trace.TableOnTxExecute( tx.s.config.Trace(), &ctx, stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/table.(*transaction).Execute"), - tx.s, tx, queryFromText(query), parameters, + tx.s, tx, queryFromText(sql), params, ) defer func() { onDone(r, err) @@ -76,7 +74,7 @@ func (tx *transaction) Execute( case txStateRollbacked: return nil, xerrors.WithStackTrace(errTxRollbackedEarly) default: - _, r, err = tx.s.Execute(ctx, tx.control, query, parameters, opts...) + _, r, err = tx.s.Execute(ctx, tx.control, sql, params, opts...) if err != nil { return nil, xerrors.WithStackTrace(err) } diff --git a/internal/xsql/conn.go b/internal/xsql/conn.go index 682e97eaa..769e1c95b 100644 --- a/internal/xsql/conn.go +++ b/internal/xsql/conn.go @@ -147,33 +147,31 @@ func (c *connWrapper) LastUsage() time.Time { return c.lastUsage.Get() } -func (c *connWrapper) normalize(q string, args ...driver.NamedValue) (query string, _ *params.Params, _ error) { +func (c *connWrapper) toYdb(sql string, args ...driver.NamedValue) (yql 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...) + yql, params, err := c.connector.Bindings().ToYdb(sql, queryArgs...) if err != nil { return "", nil, xerrors.WithStackTrace(err) } - params := params.Params(parameters) - - return sql, ¶ms, nil + return yql, ¶ms, nil } -func (c *connWrapper) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { +func (c *connWrapper) QueryContext(ctx context.Context, sql string, args []driver.NamedValue) (driver.Rows, error) { done := c.lastUsage.Start() defer done() - query, params, err := c.normalize(query, args...) + sql, params, err := c.toYdb(sql, args...) if err != nil { return nil, xerrors.WithStackTrace(err) } if isExplain(ctx) { - ast, plan, err := c.cc.Explain(ctx, query, params) + ast, plan, err := c.cc.Explain(ctx, sql, params) if err != nil { return nil, xerrors.WithStackTrace(err) } @@ -181,19 +179,19 @@ func (c *connWrapper) QueryContext(ctx context.Context, query string, args []dri return rowByAstPlan(ast, plan), nil } - return c.cc.Query(ctx, query, params) + return c.cc.Query(ctx, sql, params) } -func (c *connWrapper) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { +func (c *connWrapper) ExecContext(ctx context.Context, sql string, args []driver.NamedValue) (driver.Result, error) { done := c.lastUsage.Start() defer done() - query, params, err := c.normalize(query, args...) + sql, params, err := c.toYdb(sql, args...) if err != nil { return nil, xerrors.WithStackTrace(err) } - return c.cc.Exec(ctx, query, params) + return c.cc.Exec(ctx, sql, params) } func (c *connWrapper) GetDatabaseName() string { diff --git a/internal/xsql/conn/context.go b/internal/xsql/conn/context.go new file mode 100644 index 000000000..76f927199 --- /dev/null +++ b/internal/xsql/conn/context.go @@ -0,0 +1,15 @@ +package conn + +import "context" + +type ctxPreparedStatementKey struct{} + +func WithPreparedStatement(ctx context.Context) context.Context { + return context.WithValue(ctx, ctxPreparedStatementKey{}, true) +} + +func IsPreparedStatement(ctx context.Context) bool { + _, ok := ctx.Value(ctxPreparedStatementKey{}).(bool) + + return ok +} diff --git a/internal/xsql/conn/query/conn/conn.go b/internal/xsql/conn/query/conn.go similarity index 99% rename from internal/xsql/conn/query/conn/conn.go rename to internal/xsql/conn/query/conn.go index c7c7b0809..01edaf783 100644 --- a/internal/xsql/conn/query/conn/conn.go +++ b/internal/xsql/conn/query/conn.go @@ -1,4 +1,4 @@ -package conn +package query import ( "context" diff --git a/internal/xsql/conn/query/conn/errors.go b/internal/xsql/conn/query/errors.go similarity index 96% rename from internal/xsql/conn/query/conn/errors.go rename to internal/xsql/conn/query/errors.go index bc4f7d505..2748ba298 100644 --- a/internal/xsql/conn/query/conn/errors.go +++ b/internal/xsql/conn/query/errors.go @@ -1,4 +1,4 @@ -package conn +package query import ( "database/sql/driver" diff --git a/internal/xsql/conn/query/conn/isolation/isolation.go b/internal/xsql/conn/query/isolation.go similarity index 88% rename from internal/xsql/conn/query/conn/isolation/isolation.go rename to internal/xsql/conn/query/isolation.go index a69180158..56bcf57e4 100644 --- a/internal/xsql/conn/query/conn/isolation/isolation.go +++ b/internal/xsql/conn/query/isolation.go @@ -1,4 +1,4 @@ -package isolation +package query import ( "database/sql" @@ -10,7 +10,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/query" ) -func ToYDB(opts driver.TxOptions) (txcControl tx.Option, err error) { +func toYDB(opts driver.TxOptions) (txcControl tx.Option, err error) { level := sql.IsolationLevel(opts.Isolation) switch level { case sql.LevelDefault, sql.LevelSerializable: diff --git a/internal/xsql/conn/query/conn/options.go b/internal/xsql/conn/query/options.go similarity index 90% rename from internal/xsql/conn/query/conn/options.go rename to internal/xsql/conn/query/options.go index 82f167f44..683f30899 100644 --- a/internal/xsql/conn/query/conn/options.go +++ b/internal/xsql/conn/query/options.go @@ -1,4 +1,4 @@ -package conn +package query type Option func(c *Conn) diff --git a/internal/xsql/conn/query/conn/rows.go b/internal/xsql/conn/query/rows.go similarity index 99% rename from internal/xsql/conn/query/conn/rows.go rename to internal/xsql/conn/query/rows.go index f8bdb35aa..faeffedce 100644 --- a/internal/xsql/conn/query/conn/rows.go +++ b/internal/xsql/conn/query/rows.go @@ -1,4 +1,4 @@ -package conn +package query import ( "context" diff --git a/internal/xsql/conn/query/conn/tx.go b/internal/xsql/conn/query/tx.go similarity index 92% rename from internal/xsql/conn/query/conn/tx.go rename to internal/xsql/conn/query/tx.go index 0574726a6..6cb2ce1f6 100644 --- a/internal/xsql/conn/query/conn/tx.go +++ b/internal/xsql/conn/query/tx.go @@ -1,4 +1,4 @@ -package conn +package query import ( "context" @@ -8,7 +8,6 @@ import ( "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/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query/conn/isolation" "github.com/ydb-platform/ydb-go-sdk/v3/query" ) @@ -45,7 +44,7 @@ func (tx *transaction) Query(ctx context.Context, sql string, params *params.Par } func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (conn.Tx, error) { - txc, err := isolation.ToYDB(txOptions) + txc, err := toYDB(txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) } diff --git a/internal/xsql/conn/table/conn/badconn/badconn.go b/internal/xsql/conn/table/badconn/badconn.go similarity index 100% rename from internal/xsql/conn/table/conn/badconn/badconn.go rename to internal/xsql/conn/table/badconn/badconn.go diff --git a/internal/xsql/conn/table/conn/badconn/badconn_test.go b/internal/xsql/conn/table/badconn/badconn_test.go similarity index 100% rename from internal/xsql/conn/table/conn/badconn/badconn_test.go rename to internal/xsql/conn/table/badconn/badconn_test.go diff --git a/internal/xsql/conn/table/conn/conn.go b/internal/xsql/conn/table/conn.go similarity index 92% rename from internal/xsql/conn/table/conn/conn.go rename to internal/xsql/conn/table/conn.go index fec413a30..8713a7fa3 100644 --- a/internal/xsql/conn/table/conn/conn.go +++ b/internal/xsql/conn/table/conn.go @@ -1,4 +1,4 @@ -package conn +package table import ( "context" @@ -13,7 +13,7 @@ import ( "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/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/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" @@ -113,9 +113,6 @@ 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 { @@ -178,12 +175,12 @@ func (c *Conn) executeScriptingQuery(ctx context.Context, sql string, params *pa return resultNoRows{}, nil } -func (c *Conn) execDataQuery(ctx context.Context, query string, params *params.Params) ( +func (c *Conn) execDataQuery(ctx context.Context, sql string, params *params.Params) ( driver.RowsNextResultSet, error, ) { _, res, err := c.session.Execute(ctx, txControl(ctx, c.defaultTxControl), - query, params, c.dataQueryOptions(ctx)..., + sql, params, c.dataQueryOptions(ctx)..., ) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) @@ -198,11 +195,11 @@ func (c *Conn) execDataQuery(ctx context.Context, query string, params *params.P }, nil } -func (c *Conn) execScanQuery(ctx context.Context, query string, params *params.Params) ( +func (c *Conn) execScanQuery(ctx context.Context, sql string, params *params.Params) ( driver.RowsNextResultSet, error, ) { res, err := c.session.StreamExecuteScanQuery(ctx, - query, params, c.scanQueryOptions(ctx)..., + sql, params, c.scanOpts..., ) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) @@ -217,10 +214,10 @@ func (c *Conn) execScanQuery(ctx context.Context, query string, params *params.P }, nil } -func (c *Conn) execScriptingQuery(ctx context.Context, query string, params *params.Params) ( +func (c *Conn) execScriptingQuery(ctx context.Context, sql string, params *params.Params) ( driver.RowsNextResultSet, error, ) { - res, err := c.parent.Scripting().StreamExecute(ctx, query, params) + res, err := c.parent.Scripting().StreamExecute(ctx, sql, params) if err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } diff --git a/internal/xsql/conn/table/conn/context.go b/internal/xsql/conn/table/context.go similarity index 51% rename from internal/xsql/conn/table/conn/context.go rename to internal/xsql/conn/table/context.go index e8b455d6d..716a5439e 100644 --- a/internal/xsql/conn/table/conn/context.go +++ b/internal/xsql/conn/table/context.go @@ -1,16 +1,15 @@ -package conn +package table import ( "context" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" ) type ( ctxTransactionControlKey struct{} - ctxDataQueryOptionsKey struct{} - ctxScanQueryOptionsKey struct{} ctxTxControlHookKey struct{} txControlHook func(txControl *table.TransactionControl) @@ -37,37 +36,9 @@ func txControl(ctx context.Context, defaultTxControl *table.TransactionControl) return defaultTxControl } -func (c *Conn) WithScanQueryOptions(ctx context.Context, opts ...options.ExecuteScanQueryOption) context.Context { - return context.WithValue(ctx, - ctxScanQueryOptionsKey{}, - append( - append([]options.ExecuteScanQueryOption{}, c.scanQueryOptions(ctx)...), - opts..., - ), - ) -} - -func (c *Conn) scanQueryOptions(ctx context.Context) []options.ExecuteScanQueryOption { - if opts, ok := ctx.Value(ctxScanQueryOptionsKey{}).([]options.ExecuteScanQueryOption); ok { - return append(c.scanOpts, opts...) - } - - return c.scanOpts -} - -func (c *Conn) WithDataQueryOptions(ctx context.Context, opts ...options.ExecuteDataQueryOption) context.Context { - return context.WithValue(ctx, - ctxDataQueryOptionsKey{}, - append( - append([]options.ExecuteDataQueryOption{}, c.dataQueryOptions(ctx)...), - opts..., - ), - ) -} - func (c *Conn) dataQueryOptions(ctx context.Context) []options.ExecuteDataQueryOption { - if opts, ok := ctx.Value(ctxDataQueryOptionsKey{}).([]options.ExecuteDataQueryOption); ok { - return append(c.dataOpts, opts...) + if conn.IsPreparedStatement(ctx) { + return append(c.dataOpts, options.WithKeepInCache(true)) } return c.dataOpts diff --git a/internal/xsql/conn/table/conn/errors.go b/internal/xsql/conn/table/errors.go similarity index 96% rename from internal/xsql/conn/table/conn/errors.go rename to internal/xsql/conn/table/errors.go index cf3370206..060e95e3a 100644 --- a/internal/xsql/conn/table/conn/errors.go +++ b/internal/xsql/conn/table/errors.go @@ -1,4 +1,4 @@ -package conn +package table import ( "database/sql/driver" diff --git a/internal/xsql/conn/table/conn/isolation/isolation.go b/internal/xsql/conn/table/isolation.go similarity index 85% rename from internal/xsql/conn/table/conn/isolation/isolation.go rename to internal/xsql/conn/table/isolation.go index e7f6a7b9d..367c855b9 100644 --- a/internal/xsql/conn/table/conn/isolation/isolation.go +++ b/internal/xsql/conn/table/isolation.go @@ -1,4 +1,4 @@ -package isolation +package table import ( "database/sql" @@ -9,11 +9,11 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/table" ) -// ToYDB maps driver transaction options to ydb transaction Option or query transaction control. +// toYDB maps driver transaction options to ydb transaction Option or query transaction control. // This caused by ydb logic that prevents start actual transaction with OnlineReadOnly mode and ReadCommitted // and ReadUncommitted isolation levels should use tx_control in every query request. // It returns error on unsupported options. -func ToYDB(opts driver.TxOptions) (txcControl table.TxOption, err error) { +func toYDB(opts driver.TxOptions) (txcControl table.TxOption, err error) { level := sql.IsolationLevel(opts.Isolation) switch level { case sql.LevelDefault, sql.LevelSerializable: diff --git a/internal/xsql/conn/table/conn/isolation/isolation_test.go b/internal/xsql/conn/table/isolation_test.go similarity index 98% rename from internal/xsql/conn/table/conn/isolation/isolation_test.go rename to internal/xsql/conn/table/isolation_test.go index 9f4b0ed89..afb534b72 100644 --- a/internal/xsql/conn/table/conn/isolation/isolation_test.go +++ b/internal/xsql/conn/table/isolation_test.go @@ -1,4 +1,4 @@ -package isolation +package table import ( "database/sql" @@ -154,7 +154,7 @@ func TestToYDB(t *testing.T) { }, } { t.Run(tt.name, func(t *testing.T) { - toYDB, err := ToYDB(tt.txOptions) + toYDB, err := toYDB(tt.txOptions) if !tt.err { require.NoError(t, err) require.Equal(t, table.TxSettings(tt.txControl).Settings(), table.TxSettings(toYDB).Settings()) diff --git a/internal/xsql/conn/table/conn/mode.go b/internal/xsql/conn/table/mode.go similarity index 98% rename from internal/xsql/conn/table/conn/mode.go rename to internal/xsql/conn/table/mode.go index 2909e1874..2f4de9ebb 100644 --- a/internal/xsql/conn/table/conn/mode.go +++ b/internal/xsql/conn/table/mode.go @@ -1,4 +1,4 @@ -package conn +package table import ( "context" diff --git a/internal/xsql/conn/table/conn/options.go b/internal/xsql/conn/table/options.go similarity index 98% rename from internal/xsql/conn/table/conn/options.go rename to internal/xsql/conn/table/options.go index c99558f46..784e31ca7 100644 --- a/internal/xsql/conn/table/conn/options.go +++ b/internal/xsql/conn/table/options.go @@ -1,4 +1,4 @@ -package conn +package table import ( "slices" diff --git a/internal/xsql/conn/table/conn/rows.go b/internal/xsql/conn/table/rows.go similarity index 99% rename from internal/xsql/conn/table/conn/rows.go rename to internal/xsql/conn/table/rows.go index 65ed52973..7071ef9da 100644 --- a/internal/xsql/conn/table/conn/rows.go +++ b/internal/xsql/conn/table/rows.go @@ -1,4 +1,4 @@ -package conn +package table import ( "context" @@ -10,7 +10,7 @@ import ( "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/conn/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/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/xsql/conn/table/conn/tx.go b/internal/xsql/conn/table/tx.go similarity index 94% rename from internal/xsql/conn/table/conn/tx.go rename to internal/xsql/conn/table/tx.go index 2c9cc411f..86e8a6b0f 100644 --- a/internal/xsql/conn/table/conn/tx.go +++ b/internal/xsql/conn/table/tx.go @@ -1,4 +1,4 @@ -package conn +package table import ( "context" @@ -8,8 +8,7 @@ import ( "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/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/isolation" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/table" ) @@ -85,7 +84,7 @@ func (tx *transaction) Rollback(ctx context.Context) error { } func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (conn.Tx, error) { - txc, err := isolation.ToYDB(txOptions) + txc, err := toYDB(txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) } diff --git a/internal/xsql/conn/table/conn/tx_fake.go b/internal/xsql/conn/table/tx_fake.go similarity index 98% rename from internal/xsql/conn/table/conn/tx_fake.go rename to internal/xsql/conn/table/tx_fake.go index 6917185b5..277f9f95f 100644 --- a/internal/xsql/conn/table/conn/tx_fake.go +++ b/internal/xsql/conn/table/tx_fake.go @@ -1,4 +1,4 @@ -package conn +package table import ( "context" @@ -8,7 +8,7 @@ import ( "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/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" ) type txFake struct { diff --git a/internal/xsql/conn/table/conn/valuer.go b/internal/xsql/conn/table/valuer.go similarity index 94% rename from internal/xsql/conn/table/conn/valuer.go rename to internal/xsql/conn/table/valuer.go index 6338af124..de4253b0f 100644 --- a/internal/xsql/conn/table/conn/valuer.go +++ b/internal/xsql/conn/table/valuer.go @@ -1,4 +1,4 @@ -package conn +package table import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/scanner" diff --git a/internal/xsql/connector.go b/internal/xsql/connector.go index 12cc9db2d..530cafe07 100644 --- a/internal/xsql/connector.go +++ b/internal/xsql/connector.go @@ -15,8 +15,8 @@ import ( "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" - conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query/conn" - conn4 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn" + query2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query" + table2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" "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" @@ -38,8 +38,8 @@ type ( queryProcessor queryProcessor - TableOpts []conn4.Option - QueryOpts []conn2.Option + TableOpts []table2.Option + QueryOpts []query2.Option disableServerBalancer bool onCLose []func(*Connector) @@ -122,9 +122,9 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() conn := &connWrapper{ - cc: conn2.New(ctx, c, s, append( + cc: query2.New(ctx, c, s, append( c.QueryOpts, - conn2.WithOnClose(func() { + query2.WithOnClose(func() { c.conns.Delete(id) }))..., ), @@ -145,8 +145,8 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() conn := &connWrapper{ - cc: conn4.New(ctx, c, s, append(c.TableOpts, - conn4.WithOnClose(func() { + cc: table2.New(ctx, c, s, append(c.TableOpts, + table2.WithOnClose(func() { c.conns.Delete(id) }))..., ), diff --git a/internal/xsql/options.go b/internal/xsql/options.go index ad41666fa..9a6b7a3c6 100644 --- a/internal/xsql/options.go +++ b/internal/xsql/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/xsql/conn/query/conn" - conn3 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" "github.com/ydb-platform/ydb-go-sdk/v3/retry/budget" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) @@ -22,8 +22,8 @@ type ( bind.TablePathPrefix } tableQueryOptionsOption struct { - tableOps []conn3.Option - queryOpts []querySql.Option + tableOps []table.Option + queryOpts []query.Option } traceDatabaseSQLOption struct { t *trace.DatabaseSQL @@ -146,37 +146,37 @@ func WithQueryBind(bind bind.Bind) QueryBindOption { } } -func WithDefaultQueryMode(mode conn3.QueryMode) Option { +func WithDefaultQueryMode(mode table.QueryMode) Option { return tableQueryOptionsOption{ - tableOps: []conn3.Option{ - conn3.WithDefaultQueryMode(mode), + tableOps: []table.Option{ + table.WithDefaultQueryMode(mode), }, } } -func WithFakeTx(modes ...conn3.QueryMode) Option { +func WithFakeTx(modes ...table.QueryMode) Option { return tableQueryOptionsOption{ - tableOps: []conn3.Option{ - conn3.WithFakeTxModes(modes...), + tableOps: []table.Option{ + table.WithFakeTxModes(modes...), }, } } func WithIdleThreshold(idleThreshold time.Duration) Option { return tableQueryOptionsOption{ - tableOps: []conn3.Option{ - conn3.WithIdleThreshold(idleThreshold), + tableOps: []table.Option{ + table.WithIdleThreshold(idleThreshold), }, } } -func WithTableOptions(opts ...conn3.Option) Option { +func WithTableOptions(opts ...table.Option) Option { return tableQueryOptionsOption{ tableOps: opts, } } -func WithQueryOptions(opts ...querySql.Option) Option { +func WithQueryOptions(opts ...query.Option) Option { return tableQueryOptionsOption{ queryOpts: opts, } diff --git a/internal/xsql/stmt.go b/internal/xsql/stmt.go index 75fde9100..392eaabde 100644 --- a/internal/xsql/stmt.go +++ b/internal/xsql/stmt.go @@ -39,7 +39,7 @@ func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ return nil, xerrors.WithStackTrace(errNotReadyConn) } - sql, params, err := stmt.conn.normalize(stmt.sql, args...) + sql, params, err := stmt.conn.toYdb(stmt.sql, args...) if err != nil { return nil, xerrors.WithStackTrace(err) } @@ -60,7 +60,7 @@ func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ return nil, xerrors.WithStackTrace(errNotReadyConn) } - sql, params, err := stmt.conn.normalize(stmt.sql, args...) + sql, params, err := stmt.conn.toYdb(stmt.sql, args...) if err != nil { return nil, xerrors.WithStackTrace(err) } diff --git a/internal/xsql/tx.go b/internal/xsql/tx.go index 3cf83c1ac..7dc92338a 100644 --- a/internal/xsql/tx.go +++ b/internal/xsql/tx.go @@ -7,7 +7,7 @@ import ( "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/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) @@ -66,24 +66,24 @@ func (tx *txWrapper) Rollback() (finalErr error) { return err } -func (tx *txWrapper) QueryContext(ctx context.Context, query string, args []driver.NamedValue) ( +func (tx *txWrapper) QueryContext(ctx context.Context, sql 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/xsql.(*txWrapper).QueryContext"), - tx.ctx, tx, query, + tx.ctx, tx, sql, ) defer func() { onDone(finalErr) }() - query, params, err := tx.conn.normalize(query, args...) + sql, params, err := tx.conn.toYdb(sql, args...) if err != nil { return nil, xerrors.WithStackTrace(err) } if isExplain(ctx) { - ast, plan, err := tx.conn.cc.Explain(ctx, query, params) + ast, plan, err := tx.conn.cc.Explain(ctx, sql, params) if err != nil { return nil, xerrors.WithStackTrace(err) } @@ -91,7 +91,7 @@ func (tx *txWrapper) QueryContext(ctx context.Context, query string, args []driv return rowByAstPlan(ast, plan), nil } - rows, err := tx.tx.Query(ctx, query, params) + rows, err := tx.tx.Query(ctx, sql, params) if err != nil { return nil, xerrors.WithStackTrace(err) } @@ -99,23 +99,23 @@ func (tx *txWrapper) QueryContext(ctx context.Context, query string, args []driv return rows, nil } -func (tx *txWrapper) ExecContext(ctx context.Context, query string, args []driver.NamedValue) ( +func (tx *txWrapper) ExecContext(ctx context.Context, sql 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/xsql.(*txWrapper).ExecContext"), - tx.ctx, tx, query, + tx.ctx, tx, sql, ) defer func() { onDone(finalErr) }() - query, params, err := tx.conn.normalize(query, args...) + sql, params, err := tx.conn.toYdb(sql, args...) if err != nil { return nil, xerrors.WithStackTrace(err) } - result, err := tx.tx.Exec(ctx, query, params) + result, err := tx.tx.Exec(ctx, sql, params) if err != nil { return nil, xerrors.WithStackTrace(err) } diff --git a/internal/xsql/unwrap.go b/internal/xsql/unwrap.go index 882e242a7..1f483b090 100644 --- a/internal/xsql/unwrap.go +++ b/internal/xsql/unwrap.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" ) func Unwrap[T *sql.DB | *sql.Conn](v T) (connector *Connector, _ error) { diff --git a/query/client.go b/query/client.go index d86b11c03..08946eda7 100644 --- a/query/client.go +++ b/query/client.go @@ -17,25 +17,25 @@ type ( // // Exec used by default: // - DefaultTxControl - Exec(ctx context.Context, query string, opts ...ExecuteOption) error + Exec(ctx context.Context, sql string, opts ...ExecuteOption) error // Query execute query with result // // Exec used by default: // - DefaultTxControl - Query(ctx context.Context, query string, opts ...ExecuteOption) (Result, error) + Query(ctx context.Context, sql string, opts ...ExecuteOption) (Result, error) // QueryResultSet execute query and take the exactly single materialized result set from result // // Exec used by default: // - DefaultTxControl - QueryResultSet(ctx context.Context, query string, opts ...ExecuteOption) (ClosableResultSet, error) + QueryResultSet(ctx context.Context, sql string, opts ...ExecuteOption) (ClosableResultSet, error) // QueryRow execute query and take the exactly single row from exactly single result set from result // // Exec used by default: // - DefaultTxControl - QueryRow(ctx context.Context, query string, opts ...ExecuteOption) (Row, error) + QueryRow(ctx context.Context, sql string, opts ...ExecuteOption) (Row, error) } // Client defines API of query client Client interface { @@ -68,7 +68,7 @@ type ( // // Exec used by default: // - DefaultTxControl - Exec(ctx context.Context, query string, opts ...ExecuteOption) error + Exec(ctx context.Context, sql string, opts ...ExecuteOption) error // Query execute query with materialized result // @@ -76,23 +76,23 @@ type ( // // Exec used by default: // - DefaultTxControl - Query(ctx context.Context, query string, opts ...ExecuteOption) (Result, error) + Query(ctx context.Context, sql string, opts ...ExecuteOption) (Result, error) // QueryResultSet is a helper which read all rows from first result set in result // // Warning: the large result set from query will be materialized and can happened to "OOM killed" problem - QueryResultSet(ctx context.Context, query string, opts ...ExecuteOption) (ClosableResultSet, error) + QueryResultSet(ctx context.Context, sql string, opts ...ExecuteOption) (ClosableResultSet, error) // QueryRow is a helper which read only one row from first result set in result // // ReadRow returns error if result contains more than one result set or more than one row - QueryRow(ctx context.Context, query string, opts ...ExecuteOption) (Row, error) + QueryRow(ctx context.Context, sql string, opts ...ExecuteOption) (Row, error) // ExecuteScript starts long executing script with polling results later // // Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental ExecuteScript( - ctx context.Context, query string, ttl time.Duration, ops ...ExecuteOption, + ctx context.Context, sql string, ttl time.Duration, ops ...ExecuteOption, ) (*options.ExecuteScriptOperation, error) // FetchScriptResults fetching the script results diff --git a/query_bind_test.go b/query_bind_test.go index 395a275a0..31deaa9da 100644 --- a/query_bind_test.go +++ b/query_bind_test.go @@ -9,7 +9,6 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3" "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/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" "github.com/ydb-platform/ydb-go-sdk/v3/testutil" @@ -568,14 +567,14 @@ SELECT $param1, $param2`, }, } { t.Run("", func(t *testing.T) { - yql, parameters, err := tt.b.RewriteQuery(tt.sql, tt.args...) + yql, parameters, err := tt.b.ToYdb(tt.sql, tt.args...) if tt.err != nil { require.Error(t, err) require.ErrorIs(t, err, tt.err) } else { require.NoError(t, err) require.Equal(t, tt.yql, yql) - require.Equal(t, []*params.Parameter(*tt.params), parameters) + require.Equal(t, *tt.params, parameters) } }) } diff --git a/retry/errors.go b/retry/errors.go index 0f5b81923..22ea2a465 100644 --- a/retry/errors.go +++ b/retry/errors.go @@ -2,7 +2,7 @@ package retry import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" ) func unwrapErrBadConn(err error) error { diff --git a/retry/sql_test.go b/retry/sql_test.go index d324f69c8..9c76b40ff 100644 --- a/retry/sql_test.go +++ b/retry/sql_test.go @@ -13,7 +13,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/backoff" "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/conn/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" ) type mockConnector struct { @@ -63,22 +63,22 @@ var ( _ driver.QueryerContext = &mockConn{} ) -func (m *mockConn) Prepare(query string) (driver.Stmt, error) { +func (m *mockConn) Prepare(string) (driver.Stmt, error) { m.t.Log(stack.Record(0)) return nil, driver.ErrSkip } -func (m *mockConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { +func (m *mockConn) PrepareContext(ctx context.Context, sql string) (driver.Stmt, error) { m.t.Log(stack.Record(0)) if m.closed { return nil, driver.ErrBadConn } return &mockStmt{ - t: m.t, - conn: m, - query: query, + t: m.t, + conn: m, + sql: sql, }, nil } @@ -104,7 +104,7 @@ func (m *mockConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.T return m, nil } -func (m *mockConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { +func (m *mockConn) QueryContext(ctx context.Context, sql string, args []driver.NamedValue) (driver.Rows, error) { m.t.Log(stack.Record(0)) if !xerrors.IsRetryObjectValid(m.execErr) { m.closed = true @@ -113,7 +113,7 @@ func (m *mockConn) QueryContext(ctx context.Context, query string, args []driver return nil, m.queryErr } -func (m *mockConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { +func (m *mockConn) ExecContext(ctx context.Context, sql string, args []driver.NamedValue) (driver.Result, error) { m.t.Log(stack.Record(0)) if !xerrors.IsRetryObjectValid(m.execErr) { m.closed = true @@ -135,9 +135,9 @@ func (m *mockConn) Rollback() error { } type mockStmt struct { - t testing.TB - conn *mockConn - query string + t testing.TB + conn *mockConn + sql string } var ( @@ -167,7 +167,7 @@ func (m *mockStmt) Exec(args []driver.Value) (driver.Result, error) { func (m *mockStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { m.t.Log(stack.Record(0)) - return m.conn.ExecContext(ctx, m.query, args) + return m.conn.ExecContext(ctx, m.sql, args) } func (m *mockStmt) Query(args []driver.Value) (driver.Rows, error) { @@ -179,7 +179,7 @@ func (m *mockStmt) Query(args []driver.Value) (driver.Rows, error) { func (m *mockStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { m.t.Log(stack.Record(0)) - return m.conn.QueryContext(ctx, m.query, args) + return m.conn.QueryContext(ctx, m.sql, args) } func TestDoTx(t *testing.T) { diff --git a/scripting/scripting.go b/scripting/scripting.go index df76a9c32..3bf986a68 100644 --- a/scripting/scripting.go +++ b/scripting/scripting.go @@ -19,19 +19,7 @@ const ( ) type Client interface { - Execute( - ctx context.Context, - query string, - params *params.Params, - ) (result.Result, error) - Explain( - ctx context.Context, - query string, - mode ExplainMode, - ) (table.ScriptingYQLExplanation, error) - StreamExecute( - ctx context.Context, - query string, - params *params.Params, - ) (result.StreamResult, error) + Execute(ctx context.Context, sql string, params *params.Params) (result.Result, error) + Explain(ctx context.Context, sql string, mode ExplainMode) (table.ScriptingYQLExplanation, error) + StreamExecute(ctx context.Context, sql string, params *params.Params) (result.StreamResult, error) } diff --git a/sql.go b/sql.go index 9a7e9aa14..4fbe59f04 100644 --- a/sql.go +++ b/sql.go @@ -9,7 +9,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql" - conn2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn" + table2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" "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" @@ -78,7 +78,7 @@ func (d *sqlDriver) detach(c *xsql.Connector) { d.connectors.Delete(c) } -type QueryMode = conn2.QueryMode +type QueryMode = table2.QueryMode const ( DataQueryMode = iota + 1 @@ -93,20 +93,20 @@ func WithQueryMode(ctx context.Context, mode QueryMode) context.Context { case ExplainQueryMode: return xsql.WithExplain(ctx) case DataQueryMode: - return conn2.WithQueryMode(ctx, conn2.DataQueryMode) + return table2.WithQueryMode(ctx, table2.DataQueryMode) case ScanQueryMode: - return conn2.WithQueryMode(ctx, conn2.ScanQueryMode) + return table2.WithQueryMode(ctx, table2.ScanQueryMode) case SchemeQueryMode: - return conn2.WithQueryMode(ctx, conn2.SchemeQueryMode) + return table2.WithQueryMode(ctx, table2.SchemeQueryMode) case ScriptingQueryMode: - return conn2.WithQueryMode(ctx, conn2.ScriptingQueryMode) + return table2.WithQueryMode(ctx, table2.ScriptingQueryMode) default: return ctx } } func WithTxControl(ctx context.Context, txc *table.TransactionControl) context.Context { - return conn2.WithTxControl(ctx, txc) + return table2.WithTxControl(ctx, txc) } type ConnectorOption = xsql.Option @@ -117,11 +117,11 @@ type QueryBindConnectorOption interface { } func WithDefaultQueryMode(mode QueryMode) ConnectorOption { - return xsql.WithTableOptions(conn2.WithDefaultQueryMode(mode)) + return xsql.WithTableOptions(table2.WithDefaultQueryMode(mode)) } func WithFakeTx(mode QueryMode) ConnectorOption { - return xsql.WithTableOptions(conn2.WithFakeTxModes(mode)) + return xsql.WithTableOptions(table2.WithFakeTxModes(mode)) } func WithTablePathPrefix(tablePathPrefix string) QueryBindConnectorOption { @@ -141,15 +141,15 @@ func WithNumericArgs() QueryBindConnectorOption { } func WithDefaultTxControl(txControl *table.TransactionControl) ConnectorOption { - return xsql.WithTableOptions(conn2.WithDefaultTxControl(txControl)) + return xsql.WithTableOptions(table2.WithDefaultTxControl(txControl)) } func WithDefaultDataQueryOptions(opts ...options.ExecuteDataQueryOption) ConnectorOption { - return xsql.WithTableOptions(conn2.WithDataOpts(opts...)) + return xsql.WithTableOptions(table2.WithDataOpts(opts...)) } func WithDefaultScanQueryOptions(opts ...options.ExecuteScanQueryOption) ConnectorOption { - return xsql.WithTableOptions(conn2.WithScanOpts(opts...)) + return xsql.WithTableOptions(table2.WithScanOpts(opts...)) } func WithDatabaseSQLTrace( diff --git a/sugar/params_test.go b/sugar/params_test.go index 8ef2d46bb..350b1ea36 100644 --- a/sugar/params_test.go +++ b/sugar/params_test.go @@ -215,7 +215,7 @@ func TestGenerateDeclareSection_ParameterOption(t *testing.T) { }, } { t.Run("", func(t *testing.T) { - yql, _, err := b.RewriteQuery("", tt.params...) + yql, _, err := b.ToYdb("", tt.params...) require.NoError(t, err) require.Equal(t, tt.declares, getDeclares(yql)) }) @@ -363,7 +363,7 @@ func TestGenerateDeclareSection_NamedArg(t *testing.T) { }, } { t.Run("", func(t *testing.T) { - yql, _, err := b.RewriteQuery("", tt.params...) + yql, _, err := b.ToYdb("", tt.params...) require.NoError(t, err) require.Equal(t, tt.declares, getDeclares(yql)) }) diff --git a/table/table.go b/table/table.go index f43ff1572..37675200a 100644 --- a/table/table.go +++ b/table/table.go @@ -98,118 +98,76 @@ type SessionInfo interface { type Session interface { SessionInfo - CreateTable( - ctx context.Context, - path string, + CreateTable(ctx context.Context, path string, opts ...options.CreateTableOption, ) (err error) - DescribeTable( - ctx context.Context, - path string, + DescribeTable(ctx context.Context, path string, opts ...options.DescribeTableOption, ) (desc options.Description, err error) - DropTable( - ctx context.Context, - path string, + DropTable(ctx context.Context, path string, opts ...options.DropTableOption, ) (err error) - AlterTable( - ctx context.Context, - path string, + AlterTable(ctx context.Context, path string, opts ...options.AlterTableOption, ) (err error) // Deprecated: use CopyTables method instead // Will be removed after Oct 2024. // Read about versioning policy: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#deprecated - CopyTable( - ctx context.Context, - dst, src string, + CopyTable(ctx context.Context, dst, src string, opts ...options.CopyTableOption, ) (err error) - CopyTables( - ctx context.Context, + CopyTables(ctx context.Context, opts ...options.CopyTablesOption, ) (err error) - RenameTables( - ctx context.Context, + RenameTables(ctx context.Context, opts ...options.RenameTablesOption, ) (err error) - Explain( - ctx context.Context, - query string, - ) (exp DataQueryExplanation, err error) + Explain(ctx context.Context, sql string) (exp DataQueryExplanation, err error) // Prepare prepares query for executing in the future - Prepare( - ctx context.Context, - query string, - ) (stmt Statement, err error) + Prepare(ctx context.Context, sql string) (stmt Statement, err error) // Execute executes query. // // By default, Execute have a flag options.WithKeepInCache(true) if params is not empty. For redefine behavior - // append option options.WithKeepInCache(false) - Execute( - ctx context.Context, - tx *TransactionControl, - query string, - params *params.Params, + Execute(ctx context.Context, tx *TransactionControl, sql string, params *params.Params, opts ...options.ExecuteDataQueryOption, ) (txr Transaction, r result.Result, err error) - ExecuteSchemeQuery( - ctx context.Context, - query string, + ExecuteSchemeQuery(ctx context.Context, sql string, opts ...options.ExecuteSchemeQueryOption, ) (err error) - DescribeTableOptions( - ctx context.Context, - ) (desc options.TableOptionsDescription, err error) + DescribeTableOptions(ctx context.Context) (desc options.TableOptionsDescription, err error) - StreamReadTable( - ctx context.Context, - path string, + StreamReadTable(ctx context.Context, path string, opts ...options.ReadTableOption, ) (r result.StreamResult, err error) - StreamExecuteScanQuery( - ctx context.Context, - query string, - params *params.Params, + StreamExecuteScanQuery(ctx context.Context, sql string, params *params.Params, opts ...options.ExecuteScanQueryOption, ) (_ result.StreamResult, err error) // Deprecated: use Client instance instead. - BulkUpsert( - ctx context.Context, - table string, - rows value.Value, + BulkUpsert(ctx context.Context, table string, rows value.Value, opts ...options.BulkUpsertOption, ) (err error) - ReadRows( - ctx context.Context, - path string, - keys value.Value, + ReadRows(ctx context.Context, path string, keys value.Value, opts ...options.ReadRowsOption, ) (_ result.Result, err error) - BeginTransaction( - ctx context.Context, - tx *TransactionSettings, - ) (x Transaction, err error) + BeginTransaction(ctx context.Context, tx *TransactionSettings) (x Transaction, err error) - KeepAlive( - ctx context.Context, - ) error + KeepAlive(ctx context.Context) error } type TransactionSettings struct { @@ -257,7 +215,7 @@ type TransactionActor interface { Execute( ctx context.Context, - query string, + sql string, params *params.Params, opts ...options.ExecuteDataQueryOption, ) (result.Result, error) diff --git a/tests/integration/database_sql_regression_test.go b/tests/integration/database_sql_regression_test.go index 62f6d993f..01a63576b 100644 --- a/tests/integration/database_sql_regression_test.go +++ b/tests/integration/database_sql_regression_test.go @@ -19,7 +19,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/conn/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/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 b2b9ca725..07d9b7473 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/xsql/conn/table/conn" + tableSql "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" "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 43abd71250d7d98421e457abc1689a7590dc3e02 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Wed, 11 Dec 2024 17:49:02 +0300 Subject: [PATCH 51/62] refactoring + fixes --- internal/tx/id.go | 1 + internal/xsql/conn.go | 21 +++- internal/xsql/conn/query/conn.go | 5 + internal/xsql/conn/query/options.go | 6 ++ internal/xsql/conn/query/tx_fake.go | 62 ++++++++++++ internal/xsql/conn/table/errors.go | 1 + internal/xsql/conn/table/tx.go | 10 +- internal/xsql/conn/table/tx_fake.go | 27 +++--- internal/xsql/connector.go | 16 ++-- internal/xsql/errors.go | 2 +- internal/xsql/options.go | 16 ++++ internal/xsql/tx.go | 8 ++ sql.go | 85 +++++++++++++--- .../database_sql_ddl_in_transaction_test.go | 96 +++++++++++++++++++ 14 files changed, 308 insertions(+), 48 deletions(-) create mode 100644 internal/xsql/conn/query/tx_fake.go create mode 100644 tests/integration/database_sql_ddl_in_transaction_test.go diff --git a/internal/tx/id.go b/internal/tx/id.go index e43406bbc..d7113978b 100644 --- a/internal/tx/id.go +++ b/internal/tx/id.go @@ -4,6 +4,7 @@ var _ Identifier = LazyID{} const ( LazyTxID = "LAZY_TX" + FakeTxID = "FAKE_TX" ) type ( diff --git a/internal/xsql/conn.go b/internal/xsql/conn.go index 769e1c95b..69490966e 100644 --- a/internal/xsql/conn.go +++ b/internal/xsql/conn.go @@ -33,7 +33,8 @@ var ( type ( connWrapper struct { - cc conn.Conn + cc conn.Conn + currentTx *txWrapper connector *Connector lastUsage xsync.LastUsage @@ -54,16 +55,22 @@ func (c *connWrapper) CheckNamedValue(value *driver.NamedValue) error { } func (c *connWrapper) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { + if c.currentTx != nil { + return nil, xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())) + } + tx, err := c.cc.BeginTx(ctx, opts) if err != nil { return nil, xerrors.WithStackTrace(err) } - return &txWrapper{ + c.currentTx = &txWrapper{ conn: c, ctx: ctx, tx: tx, - }, nil + } + + return c.currentTx, nil } func (c *connWrapper) Close() error { @@ -179,6 +186,10 @@ func (c *connWrapper) QueryContext(ctx context.Context, sql string, args []drive return rowByAstPlan(ast, plan), nil } + if c.currentTx != nil { + return c.currentTx.tx.Query(ctx, sql, params) + } + return c.cc.Query(ctx, sql, params) } @@ -191,6 +202,10 @@ func (c *connWrapper) ExecContext(ctx context.Context, sql string, args []driver return nil, xerrors.WithStackTrace(err) } + if c.currentTx != nil { + return c.currentTx.tx.Exec(ctx, sql, params) + } + return c.cc.Exec(ctx, sql, params) } diff --git a/internal/xsql/conn/query/conn.go b/internal/xsql/conn/query/conn.go index 01edaf783..18169044d 100644 --- a/internal/xsql/conn/query/conn.go +++ b/internal/xsql/conn/query/conn.go @@ -32,6 +32,7 @@ type Conn struct { session *query.Session onClose []func() closed atomic.Bool + fakeTx bool } func (c *Conn) Exec(ctx context.Context, sql string, params *params.Params) ( @@ -114,6 +115,10 @@ func (c *Conn) isReady() bool { } func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx conn.Tx, finalErr error) { + if c.fakeTx { + return beginTxFake(ctx, c), nil + } + tx, err := beginTx(ctx, c, txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) diff --git a/internal/xsql/conn/query/options.go b/internal/xsql/conn/query/options.go index 683f30899..2c3a1a94d 100644 --- a/internal/xsql/conn/query/options.go +++ b/internal/xsql/conn/query/options.go @@ -7,3 +7,9 @@ func WithOnClose(onClose func()) Option { c.onClose = append(c.onClose, onClose) } } + +func WithFakeTx() Option { + return func(c *Conn) { + c.fakeTx = true + } +} diff --git a/internal/xsql/conn/query/tx_fake.go b/internal/xsql/conn/query/tx_fake.go new file mode 100644 index 000000000..9f55c0f6c --- /dev/null +++ b/internal/xsql/conn/query/tx_fake.go @@ -0,0 +1,62 @@ +package query + +import ( + "context" + "database/sql/driver" + + "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/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" +) + +type txFake struct { + conn *Conn + ctx context.Context //nolint:containedctx +} + +func (t *txFake) Exec(ctx context.Context, sql string, params *params.Params) (driver.Result, error) { + result, err := t.conn.Exec(ctx, sql, params) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return result, nil +} + +func (t *txFake) Query(ctx context.Context, sql string, params *params.Params) (driver.RowsNextResultSet, error) { + rows, err := t.conn.Query(ctx, sql, params) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return rows, nil +} + +func (t *txFake) ID() string { + return tx.FakeTxID +} + +func beginTxFake(ctx context.Context, c *Conn) conn.Tx { + return &txFake{ + conn: c, + ctx: ctx, + } +} + +func (t *txFake) Commit(ctx context.Context) (err error) { + if !t.conn.isReady() { + return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + return nil +} + +func (t *txFake) Rollback(ctx context.Context) (err error) { + if !t.conn.isReady() { + return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) + } + + return err +} diff --git a/internal/xsql/conn/table/errors.go b/internal/xsql/conn/table/errors.go index 060e95e3a..90db8c026 100644 --- a/internal/xsql/conn/table/errors.go +++ b/internal/xsql/conn/table/errors.go @@ -11,4 +11,5 @@ var ( ErrUnsupported = driver.ErrSkip errConnClosedEarly = xerrors.Retryable(errors.New("conn closed early"), xerrors.InvalidObject()) errNotReadyConn = xerrors.Retryable(errors.New("conn not ready"), xerrors.InvalidObject()) + ErrWrongQueryMode = errors.New("wrong query mode") ) diff --git a/internal/xsql/conn/table/tx.go b/internal/xsql/conn/table/tx.go index 86e8a6b0f..762dcdf4e 100644 --- a/internal/xsql/conn/table/tx.go +++ b/internal/xsql/conn/table/tx.go @@ -26,15 +26,7 @@ func (tx *transaction) ID() string { 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"), - ), - ), - ) + return nil, xerrors.WithStackTrace(fmt.Errorf("%q: %w", m.String(), ErrWrongQueryMode)) } _, err := tx.tx.Execute(ctx, sql, params, tx.conn.dataQueryOptions(ctx)...) if err != nil { diff --git a/internal/xsql/conn/table/tx_fake.go b/internal/xsql/conn/table/tx_fake.go index 277f9f95f..505ca7919 100644 --- a/internal/xsql/conn/table/tx_fake.go +++ b/internal/xsql/conn/table/tx_fake.go @@ -12,14 +12,12 @@ import ( ) type txFake struct { - tx.Identifier - conn *Conn ctx context.Context //nolint:containedctx } -func (tx *txFake) Exec(ctx context.Context, sql string, params *params.Params) (driver.Result, error) { - result, err := tx.conn.Exec(ctx, sql, params) +func (t *txFake) Exec(ctx context.Context, sql string, params *params.Params) (driver.Result, error) { + result, err := t.conn.Exec(ctx, sql, params) if err != nil { return nil, xerrors.WithStackTrace(err) } @@ -27,8 +25,8 @@ func (tx *txFake) Exec(ctx context.Context, sql string, params *params.Params) ( return result, nil } -func (tx *txFake) Query(ctx context.Context, sql string, params *params.Params) (driver.RowsNextResultSet, error) { - rows, err := tx.conn.Query(ctx, sql, params) +func (t *txFake) Query(ctx context.Context, sql string, params *params.Params) (driver.RowsNextResultSet, error) { + rows, err := t.conn.Query(ctx, sql, params) if err != nil { return nil, xerrors.WithStackTrace(err) } @@ -36,24 +34,27 @@ func (tx *txFake) Query(ctx context.Context, sql string, params *params.Params) return rows, nil } +func (t *txFake) ID() string { + return tx.FakeTxID +} + func beginTxFake(ctx context.Context, c *Conn) conn.Tx { return &txFake{ - Identifier: tx.ID("FAKE"), - conn: c, - ctx: ctx, + conn: c, + ctx: ctx, } } -func (tx *txFake) Commit(ctx context.Context) (err error) { - if !tx.conn.isReady() { +func (t *txFake) Commit(ctx context.Context) (err error) { + if !t.conn.isReady() { return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } return nil } -func (tx *txFake) Rollback(ctx context.Context) (err error) { - if !tx.conn.isReady() { +func (t *txFake) Rollback(ctx context.Context) (err error) { + if !t.conn.isReady() { return badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } diff --git a/internal/xsql/connector.go b/internal/xsql/connector.go index 530cafe07..3f65d3588 100644 --- a/internal/xsql/connector.go +++ b/internal/xsql/connector.go @@ -15,8 +15,8 @@ import ( "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" - query2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query" - table2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" + connOverQueryServiceClient "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query" + connOverTableServiceClient "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" "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" @@ -38,8 +38,8 @@ type ( queryProcessor queryProcessor - TableOpts []table2.Option - QueryOpts []query2.Option + TableOpts []connOverTableServiceClient.Option + QueryOpts []connOverQueryServiceClient.Option disableServerBalancer bool onCLose []func(*Connector) @@ -122,9 +122,9 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() conn := &connWrapper{ - cc: query2.New(ctx, c, s, append( + cc: connOverQueryServiceClient.New(ctx, c, s, append( c.QueryOpts, - query2.WithOnClose(func() { + connOverQueryServiceClient.WithOnClose(func() { c.conns.Delete(id) }))..., ), @@ -145,8 +145,8 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() conn := &connWrapper{ - cc: table2.New(ctx, c, s, append(c.TableOpts, - table2.WithOnClose(func() { + cc: connOverTableServiceClient.New(ctx, c, s, append(c.TableOpts, + connOverTableServiceClient.WithOnClose(func() { c.conns.Delete(id) }))..., ), diff --git a/internal/xsql/errors.go b/internal/xsql/errors.go index f564b005c..252485975 100644 --- a/internal/xsql/errors.go +++ b/internal/xsql/errors.go @@ -12,5 +12,5 @@ var ( errDeprecated = driver.ErrSkip errAlreadyClosed = errors.New("already closed") errWrongQueryProcessor = errors.New("wrong query processor") - errNotReadyConn = xerrors.Retryable(errors.New("connWrapper not ready"), xerrors.InvalidObject()) + errNotReadyConn = xerrors.Retryable(errors.New("conn not ready"), xerrors.InvalidObject()) ) diff --git a/internal/xsql/options.go b/internal/xsql/options.go index 9a6b7a3c6..f15e98403 100644 --- a/internal/xsql/options.go +++ b/internal/xsql/options.go @@ -170,6 +170,22 @@ func WithIdleThreshold(idleThreshold time.Duration) Option { } } +type mergedOptions []Option + +func (opts mergedOptions) Apply(c *Connector) error { + for _, opt := range opts { + if err := opt.Apply(c); err != nil { + return err + } + } + + return nil +} + +func Merge(opts ...Option) Option { + return mergedOptions(opts) +} + func WithTableOptions(opts ...table.Option) Option { return tableQueryOptionsOption{ tableOps: opts, diff --git a/internal/xsql/tx.go b/internal/xsql/tx.go index 7dc92338a..9652da89d 100644 --- a/internal/xsql/tx.go +++ b/internal/xsql/tx.go @@ -28,6 +28,10 @@ var ( ) func (tx *txWrapper) Commit() (finalErr error) { + defer func() { + tx.conn.currentTx = nil + }() + var ( ctx = tx.ctx onDone = trace.DatabaseSQLOnTxCommit(tx.conn.connector.Trace(), &ctx, @@ -47,6 +51,10 @@ func (tx *txWrapper) Commit() (finalErr error) { } func (tx *txWrapper) Rollback() (finalErr error) { + defer func() { + tx.conn.currentTx = nil + }() + var ( ctx = tx.ctx onDone = trace.DatabaseSQLOnTxRollback(tx.conn.connector.Trace(), &ctx, diff --git a/sql.go b/sql.go index 4fbe59f04..42373018c 100644 --- a/sql.go +++ b/sql.go @@ -9,7 +9,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql" - table2 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" + connOverQueryServiceClient "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query" + connOverTableServiceClient "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" "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" @@ -78,35 +79,40 @@ func (d *sqlDriver) detach(c *xsql.Connector) { d.connectors.Delete(c) } -type QueryMode = table2.QueryMode +type QueryMode int const ( - DataQueryMode = iota + 1 + _ = QueryMode(iota) + DataQueryMode ExplainQueryMode ScanQueryMode SchemeQueryMode ScriptingQueryMode + QueryExecuteQueryMode ) +// WithQueryMode set query mode for legacy database/sql driver +// +// For actual database/sql driver works over query service client and no needs query mode func WithQueryMode(ctx context.Context, mode QueryMode) context.Context { switch mode { case ExplainQueryMode: return xsql.WithExplain(ctx) case DataQueryMode: - return table2.WithQueryMode(ctx, table2.DataQueryMode) + return connOverTableServiceClient.WithQueryMode(ctx, connOverTableServiceClient.DataQueryMode) case ScanQueryMode: - return table2.WithQueryMode(ctx, table2.ScanQueryMode) + return connOverTableServiceClient.WithQueryMode(ctx, connOverTableServiceClient.ScanQueryMode) case SchemeQueryMode: - return table2.WithQueryMode(ctx, table2.SchemeQueryMode) + return connOverTableServiceClient.WithQueryMode(ctx, connOverTableServiceClient.SchemeQueryMode) case ScriptingQueryMode: - return table2.WithQueryMode(ctx, table2.ScriptingQueryMode) + return connOverTableServiceClient.WithQueryMode(ctx, connOverTableServiceClient.ScriptingQueryMode) default: return ctx } } func WithTxControl(ctx context.Context, txc *table.TransactionControl) context.Context { - return table2.WithTxControl(ctx, txc) + return connOverTableServiceClient.WithTxControl(ctx, txc) } type ConnectorOption = xsql.Option @@ -116,12 +122,63 @@ type QueryBindConnectorOption interface { bind.Bind } +func modeToMode(mode QueryMode) connOverTableServiceClient.QueryMode { + switch mode { + case ScanQueryMode: + return connOverTableServiceClient.ScanQueryMode + case SchemeQueryMode: + return connOverTableServiceClient.SchemeQueryMode + case ScriptingQueryMode: + return connOverTableServiceClient.ScriptingQueryMode + default: + return connOverTableServiceClient.DataQueryMode + } +} + func WithDefaultQueryMode(mode QueryMode) ConnectorOption { - return xsql.WithTableOptions(table2.WithDefaultQueryMode(mode)) + return xsql.WithTableOptions( + connOverTableServiceClient.WithDefaultQueryMode(modeToMode(mode)), + ) } -func WithFakeTx(mode QueryMode) ConnectorOption { - return xsql.WithTableOptions(table2.WithFakeTxModes(mode)) +func WithFakeTx(modes ...QueryMode) ConnectorOption { + opts := make([]ConnectorOption, 0, len(modes)) + + for _, mode := range modes { + switch mode { + case DataQueryMode: + opts = append(opts, + xsql.WithTableOptions(connOverTableServiceClient.WithFakeTxModes( + connOverTableServiceClient.DataQueryMode, + )), + ) + case ScanQueryMode: + opts = append(opts, + xsql.WithTableOptions(connOverTableServiceClient.WithFakeTxModes( + connOverTableServiceClient.ScanQueryMode, + )), + ) + case SchemeQueryMode: + opts = append(opts, + xsql.WithTableOptions(connOverTableServiceClient.WithFakeTxModes( + connOverTableServiceClient.SchemeQueryMode, + )), + ) + case ScriptingQueryMode: + opts = append(opts, + xsql.WithTableOptions(connOverTableServiceClient.WithFakeTxModes( + connOverTableServiceClient.DataQueryMode, + )), + ) + case QueryExecuteQueryMode: + opts = append(opts, + xsql.WithQueryOptions(connOverQueryServiceClient.WithFakeTx()), + ) + default: + } + } + + return xsql.Merge(opts...) } func WithTablePathPrefix(tablePathPrefix string) QueryBindConnectorOption { @@ -141,15 +198,15 @@ func WithNumericArgs() QueryBindConnectorOption { } func WithDefaultTxControl(txControl *table.TransactionControl) ConnectorOption { - return xsql.WithTableOptions(table2.WithDefaultTxControl(txControl)) + return xsql.WithTableOptions(connOverTableServiceClient.WithDefaultTxControl(txControl)) } func WithDefaultDataQueryOptions(opts ...options.ExecuteDataQueryOption) ConnectorOption { - return xsql.WithTableOptions(table2.WithDataOpts(opts...)) + return xsql.WithTableOptions(connOverTableServiceClient.WithDataOpts(opts...)) } func WithDefaultScanQueryOptions(opts ...options.ExecuteScanQueryOption) ConnectorOption { - return xsql.WithTableOptions(table2.WithScanOpts(opts...)) + return xsql.WithTableOptions(connOverTableServiceClient.WithScanOpts(opts...)) } func WithDatabaseSQLTrace( diff --git a/tests/integration/database_sql_ddl_in_transaction_test.go b/tests/integration/database_sql_ddl_in_transaction_test.go new file mode 100644 index 000000000..7c2057e12 --- /dev/null +++ b/tests/integration/database_sql_ddl_in_transaction_test.go @@ -0,0 +1,96 @@ +//go:build integration +// +build integration + +package integration + +import ( + "context" + "database/sql" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3/retry" +) + +func TestDatabaseSqlDDLInTransaction(t *testing.T) { + var ( + scope = newScope(t) + db = scope.SQLDriverWithFolder() + ) + + defer func() { + _ = db.Close() + }() + + f := func(ctx context.Context, tx *sql.Tx) (err error) { + _, err = tx.ExecContext( + ydb.WithQueryMode(ctx, ydb.SchemeQueryMode), + `DROP TABLE IF EXISTS test`, + ) + if err != nil { + return err + } + + _, err = tx.ExecContext(ctx, `CREATE TABLE test (id Uint64, PRIMARY KEY (id))`) + if err != nil { + return err + } + + return err + } + + t.Run("InTransaction", func(t *testing.T) { + t.Run("WrongQueryMode", func(t *testing.T) { + err := retry.DoTx(scope.Ctx, db, f, + retry.WithIdempotent(true), retry.WithTxOptions(&sql.TxOptions{ + Isolation: sql.LevelSnapshot, + ReadOnly: true, + }), + ) + require.Error(t, err) + }) + t.Run("SnapshotROIsolation", func(t *testing.T) { + err := retry.DoTx(scope.Ctx, db, f, + retry.WithIdempotent(true), retry.WithTxOptions(&sql.TxOptions{ + Isolation: sql.LevelSnapshot, + ReadOnly: true, + }), + ) + require.Error(t, err) + }) + t.Run("SerializableRWIsolation", func(t *testing.T) { + err := retry.DoTx(scope.Ctx, db, + f, retry.WithIdempotent(true), retry.WithTxOptions(&sql.TxOptions{ + Isolation: sql.LevelSerializable, + ReadOnly: false, + }), + ) + require.Error(t, err) + }) + t.Run("FakeTx", func(t *testing.T) { + connector, err := ydb.Connector(scope.Driver(), + ydb.WithTablePathPrefix(scope.Folder()), + ydb.WithFakeTx( + ydb.SchemeQueryMode, + ydb.QueryExecuteQueryMode, + ), + ) + require.NoError(t, err) + + db := sql.OpenDB(connector) + + err = db.PingContext(scope.Ctx) + require.NoError(t, err) + + err = retry.DoTx(ydb.WithQueryMode(scope.Ctx, ydb.SchemeQueryMode), db, + f, retry.WithIdempotent(true), retry.WithTxOptions(&sql.TxOptions{ + Isolation: sql.LevelSerializable, + ReadOnly: false, + }), + ) + require.NoError(t, err) + }) + }) +} From 7de1f3b6992ea28729c66fc870b3dc86689e3b46 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Wed, 11 Dec 2024 18:44:05 +0300 Subject: [PATCH 52/62] fixes --- internal/xsql/conn.go | 10 ++++++++ internal/xsql/conn/query/errors.go | 4 ++-- internal/xsql/connector.go | 15 +++++++----- internal/xsql/options.go | 4 ++-- retry/sql.go | 4 ++-- sql.go | 8 +++++++ tests/integration/helpers_test.go | 24 +++++++++++++++++++ tests/integration/table_truncated_err_test.go | 8 ++++++- 8 files changed, 64 insertions(+), 13 deletions(-) diff --git a/internal/xsql/conn.go b/internal/xsql/conn.go index 69490966e..329449a34 100644 --- a/internal/xsql/conn.go +++ b/internal/xsql/conn.go @@ -33,6 +33,8 @@ var ( type ( connWrapper struct { + processor Engine + cc conn.Conn currentTx *txWrapper @@ -45,6 +47,10 @@ type ( } ) +func (c *connWrapper) Engine() Engine { + return c.processor +} + func (c *connWrapper) Ping(ctx context.Context) error { return c.cc.Ping(ctx) } @@ -82,6 +88,10 @@ func (c *connWrapper) Close() error { return nil } +func (c *connWrapper) Connector() *Connector { + return c.connector +} + func (c *connWrapper) Begin() (driver.Tx, error) { return nil, xerrors.WithStackTrace(errDeprecated) } diff --git a/internal/xsql/conn/query/errors.go b/internal/xsql/conn/query/errors.go index 2748ba298..e23313c1e 100644 --- a/internal/xsql/conn/query/errors.go +++ b/internal/xsql/conn/query/errors.go @@ -10,6 +10,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()) + errConnClosedEarly = xerrors.Retryable(errors.New("conn closed early"), xerrors.InvalidObject()) + errNotReadyConn = xerrors.Retryable(errors.New("conn not ready"), xerrors.InvalidObject()) ) diff --git a/internal/xsql/connector.go b/internal/xsql/connector.go index 3f65d3588..1c38591fb 100644 --- a/internal/xsql/connector.go +++ b/internal/xsql/connector.go @@ -5,6 +5,7 @@ import ( "database/sql/driver" "io" "os" + "strconv" "time" "github.com/google/uuid" @@ -31,12 +32,12 @@ var ( ) type ( - queryProcessor uint8 - Connector struct { + Engine uint8 + Connector struct { parent ydbDriver balancer grpc.ClientConnInterface - queryProcessor queryProcessor + processor Engine TableOpts []connOverTableServiceClient.Option QueryOpts []connOverQueryServiceClient.Option @@ -112,7 +113,7 @@ func (c *Connector) Open(name string) (driver.Conn, error) { } func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { - switch c.queryProcessor { + switch c.processor { case QUERY_SERVICE: s, err := query.CreateSession(ctx, c.Query()) if err != nil { @@ -122,6 +123,7 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() conn := &connWrapper{ + processor: QUERY_SERVICE, cc: connOverQueryServiceClient.New(ctx, c, s, append( c.QueryOpts, connOverQueryServiceClient.WithOnClose(func() { @@ -145,6 +147,7 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() conn := &connWrapper{ + processor: TABLE_SERVICE, cc: connOverTableServiceClient.New(ctx, c, s, append(c.TableOpts, connOverTableServiceClient.WithOnClose(func() { c.conns.Delete(id) @@ -189,8 +192,8 @@ func Open(parent ydbDriver, balancer grpc.ClientConnInterface, opts ...Option) ( c := &Connector{ parent: parent, balancer: balancer, - queryProcessor: func() queryProcessor { - if v, has := os.LookupEnv("YDB_DATABASE_SQL_OVER_QUERY_SERVICE"); has && v != "" { + processor: func() Engine { + if overQueryService, _ := strconv.ParseBool(os.Getenv("YDB_DATABASE_SQL_OVER_QUERY_SERVICE")); overQueryService { return QUERY_SERVICE } diff --git a/internal/xsql/options.go b/internal/xsql/options.go index f15e98403..c2a813d5a 100644 --- a/internal/xsql/options.go +++ b/internal/xsql/options.go @@ -41,7 +41,7 @@ type ( bindOption struct { bind.Bind } - queryProcessorOption queryProcessor + queryProcessorOption Engine ) func (t tablePathPrefixOption) Apply(c *Connector) error { @@ -52,7 +52,7 @@ func (t tablePathPrefixOption) Apply(c *Connector) error { } func (processor queryProcessorOption) Apply(c *Connector) error { - c.queryProcessor = queryProcessor(processor) + c.processor = Engine(processor) return nil } diff --git a/retry/sql.go b/retry/sql.go index 9ba31cca3..29ddeb6b2 100644 --- a/retry/sql.go +++ b/retry/sql.go @@ -40,7 +40,7 @@ func WithDoRetryOptions(opts ...Option) doRetryOptionsOption { return opts } -// Do is a retryer of database/sql Conn with fallbacks on errors +// Do is a retryer of database/sql conn with fallbacks on errors func Do(ctx context.Context, db *sql.DB, op func(ctx context.Context, cc *sql.Conn) error, opts ...doOption) error { _, err := DoWithResult(ctx, db, func(ctx context.Context, cc *sql.Conn) (*struct{}, error) { err := op(ctx, cc) @@ -57,7 +57,7 @@ func Do(ctx context.Context, db *sql.DB, op func(ctx context.Context, cc *sql.Co return nil } -// DoWithResult is a retryer of database/sql Conn with fallbacks on errors +// DoWithResult is a retryer of database/sql conn with fallbacks on errors // // Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental func DoWithResult[T any](ctx context.Context, db *sql.DB, diff --git a/sql.go b/sql.go index 42373018c..ecf0d3af9 100644 --- a/sql.go +++ b/sql.go @@ -141,6 +141,14 @@ func WithDefaultQueryMode(mode QueryMode) ConnectorOption { ) } +// OverQueryService is an experimental flag for create database/sql driver over query service client +// +// By default database/sql driver works over table service client +// Default will be changed to `OverQueryService` after March 2025 +func OverQueryService() ConnectorOption { + return xsql.OverQueryService() +} + func WithFakeTx(modes ...QueryMode) ConnectorOption { opts := make([]ConnectorOption, 0, len(modes)) diff --git a/tests/integration/helpers_test.go b/tests/integration/helpers_test.go index 91f1c892d..6fe4db905 100644 --- a/tests/integration/helpers_test.go +++ b/tests/integration/helpers_test.go @@ -21,6 +21,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/config" + "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/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/log" @@ -443,3 +444,26 @@ func (t *testLogger) flush() { t.test.Log(message) }) } + +func driverEngine(db *sql.DB) (engine xsql.Engine) { + cc, err := db.Conn(context.Background()) + if err != nil { + return engine + } + + defer func() { + _ = cc.Close() + }() + + cc.Raw(func(driverConn any) error { + if ccc, has := driverConn.(interface { + Engine() xsql.Engine + }); has { + engine = ccc.Engine() + } + + return nil + }) + + return engine +} diff --git a/tests/integration/table_truncated_err_test.go b/tests/integration/table_truncated_err_test.go index 605475e00..93d7986d6 100644 --- a/tests/integration/table_truncated_err_test.go +++ b/tests/integration/table_truncated_err_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql" "github.com/ydb-platform/ydb-go-sdk/v3/retry" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" @@ -133,7 +134,12 @@ func TestIssue798TruncatedError(t *testing.T) { } return rows.Err() }, retry.WithIdempotent(true)) - scope.Require.ErrorIs(err, result.ErrTruncated) + switch driverEngine(db) { + case xsql.TABLE_SERVICE: + scope.Require.ErrorIs(err, result.ErrTruncated) + case xsql.QUERY_SERVICE: + scope.Require.NoError(err) + } } // select all rows without truncated result error From 6a8c400a7e09efbcf0b4bef1247ea1b2f6cdf3ff Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Wed, 11 Dec 2024 19:12:42 +0300 Subject: [PATCH 53/62] fixed matrics for unit and integration tests --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 34e13785e..cfb460df1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: [1.21.x, 1.22.x, 1.23.x] + go-version: [1.22.x, 1.23.x] os: [ubuntu, windows, macOS] env: OS: ${{ matrix.os }}-latest @@ -52,8 +52,8 @@ jobs: strategy: fail-fast: false matrix: - go-version: [1.21.x, 1.22.x, 1.23.x] - ydb-version: [23.3, 24.1, 24.2] + go-version: [1.22.x, 1.23.x] + ydb-version: [24.1, 24.2, 24.3] os: [ubuntu] services: ydb: From 5bd342d4137af929ccb5c1d77a1ac973621e0ef5 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Wed, 11 Dec 2024 20:16:39 +0300 Subject: [PATCH 54/62] fixed integration tests after removed ydb 23.3 from matrix --- tests/integration/driver_test.go | 4 --- .../integration/query_execute_script_test.go | 5 ---- tests/integration/query_execute_test.go | 12 --------- .../query_multi_result_sets_test.go | 6 ----- tests/integration/query_range_test.go | 5 ---- tests/integration/query_read_row_test.go | 5 ---- tests/integration/query_regression_test.go | 10 ------- tests/integration/query_tx_execute_test.go | 14 ---------- tests/integration/retry_budget_test.go | 27 +++++++++---------- tests/integration/sugar_result_test.go | 5 ---- .../sugar_unmarhall_result_set_test.go | 6 ----- tests/integration/sugar_unmarhall_row_test.go | 6 ----- tests/integration/topic_client_test.go | 12 ++------- tests/integration/topic_helpers_test.go | 5 ---- 14 files changed, 14 insertions(+), 108 deletions(-) diff --git a/tests/integration/driver_test.go b/tests/integration/driver_test.go index efe2a3078..3334e0461 100644 --- a/tests/integration/driver_test.go +++ b/tests/integration/driver_test.go @@ -32,7 +32,6 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/config" "github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials" "github.com/ydb-platform/ydb-go-sdk/v3/internal/meta" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/log" "github.com/ydb-platform/ydb-go-sdk/v3/retry" @@ -172,9 +171,6 @@ func TestDriver(sourceTest *testing.T) { } }() t.RunSynced("WithStaticCredentials", func(t *xtest.SyncedTest) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("read rows not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } db, err := ydb.Open(ctx, os.Getenv("YDB_CONNECTION_STRING"), ydb.WithAccessTokenCredentials( diff --git a/tests/integration/query_execute_script_test.go b/tests/integration/query_execute_script_test.go index 4a81c2b56..913767364 100644 --- a/tests/integration/query_execute_script_test.go +++ b/tests/integration/query_execute_script_test.go @@ -14,17 +14,12 @@ import ( "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) func TestQueryExecuteScript(sourceTest *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - sourceTest.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - t := xtest.MakeSyncedTest(sourceTest) var ( folder = t.Name() diff --git a/tests/integration/query_execute_test.go b/tests/integration/query_execute_test.go index 9125cbaaf..113da45fc 100644 --- a/tests/integration/query_execute_test.go +++ b/tests/integration/query_execute_test.go @@ -29,10 +29,6 @@ import ( ) func TestQueryExecute(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - ctx, cancel := context.WithCancel(xtest.Context(t)) defer cancel() @@ -297,10 +293,6 @@ func TestQueryExecute(t *testing.T) { // https://github.com/ydb-platform/ydb-go-sdk/issues/1456 func TestIssue1456TooManyUnknownTransactions(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - ctx, cancel := context.WithCancel(xtest.Context(t)) defer cancel() @@ -411,10 +403,6 @@ func TestIssue1456TooManyUnknownTransactions(t *testing.T) { } func TestQueryResultSet(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - t.Run("OK", func(t *testing.T) { scope := newScope(t) diff --git a/tests/integration/query_multi_result_sets_test.go b/tests/integration/query_multi_result_sets_test.go index 108186afe..f09857b9d 100644 --- a/tests/integration/query_multi_result_sets_test.go +++ b/tests/integration/query_multi_result_sets_test.go @@ -8,18 +8,12 @@ import ( "errors" "fmt" "io" - "os" "testing" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/query" ) func TestQueryMultiResultSets(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - scope := newScope(t) var i, j, k int db := scope.Driver() diff --git a/tests/integration/query_range_test.go b/tests/integration/query_range_test.go index 13d5fdac3..03505e30e 100644 --- a/tests/integration/query_range_test.go +++ b/tests/integration/query_range_test.go @@ -15,16 +15,11 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/internal/value" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/query" ) func TestQueryRange(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - ctx, cancel := context.WithCancel(xtest.Context(t)) defer cancel() diff --git a/tests/integration/query_read_row_test.go b/tests/integration/query_read_row_test.go index 670adbf78..94793a874 100644 --- a/tests/integration/query_read_row_test.go +++ b/tests/integration/query_read_row_test.go @@ -12,7 +12,6 @@ import ( "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/log" "github.com/ydb-platform/ydb-go-sdk/v3/query" @@ -20,10 +19,6 @@ import ( ) func TestQueryReadRow(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - ctx, cancel := context.WithCancel(xtest.Context(t)) defer cancel() diff --git a/tests/integration/query_regression_test.go b/tests/integration/query_regression_test.go index 8e80e23c8..2293d792d 100644 --- a/tests/integration/query_regression_test.go +++ b/tests/integration/query_regression_test.go @@ -8,7 +8,6 @@ import ( "errors" "fmt" "io" - "os" "strconv" "strings" "testing" @@ -19,7 +18,6 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/options" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/tx" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" @@ -277,10 +275,6 @@ SELECT $val`, // https://github.com/ydb-platform/ydb-go-sdk/issues/1506 func TestIssue1506TypedNullPushdown(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - scope := newScope(t) ctx := scope.Ctx db := scope.Driver() @@ -312,10 +306,6 @@ SELECT CAST($arg1 AS Utf8) AS v1, CAST($arg2 AS Utf8) AS v2 } func TestReadTwoPartsIntoMemoryIssue1559(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - scope := newScope(t) var readPartCount int diff --git a/tests/integration/query_tx_execute_test.go b/tests/integration/query_tx_execute_test.go index b537f285f..8733427c8 100644 --- a/tests/integration/query_tx_execute_test.go +++ b/tests/integration/query_tx_execute_test.go @@ -7,7 +7,6 @@ import ( "context" "errors" "fmt" - "os" "testing" "github.com/stretchr/testify/require" @@ -16,15 +15,10 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3" internalQuery "github.com/ydb-platform/ydb-go-sdk/v3/internal/query" baseTx "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/query" ) func TestQueryTxExecute(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - scope := newScope(t) t.Run("Default", func(t *testing.T) { @@ -243,10 +237,6 @@ func TestQueryTxExecute(t *testing.T) { } func TestQueryLazyTxExecute(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - scope := newScope(t) var ( @@ -457,10 +447,6 @@ func TestQueryLazyTxExecute(t *testing.T) { } func TestQueryWithCommitTxFlag(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - scope := newScope(t) var count uint64 err := scope.DriverWithLogs().Query().Do(scope.Ctx, func(ctx context.Context, s query.Session) error { diff --git a/tests/integration/retry_budget_test.go b/tests/integration/retry_budget_test.go index 36e847401..92fd2531e 100644 --- a/tests/integration/retry_budget_test.go +++ b/tests/integration/retry_budget_test.go @@ -14,7 +14,6 @@ import ( "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/retry" @@ -91,18 +90,16 @@ func TestRetryBudget(t *testing.T) { }, table.WithRetryBudget(retryBudget)) require.ErrorIs(t, err, budget.ErrNoQuota) }) - if version.Gte(os.Getenv("YDB_VERSION"), "24.1") { - t.Run("db.Query().Do", func(t *testing.T) { - err := nativeDriver.Query().Do(ctx, func(ctx context.Context, s query.Session) error { - return retry.RetryableError(errors.New("custom error")) - }, query.WithRetryBudget(retryBudget)) - require.ErrorIs(t, err, budget.ErrNoQuota) - }) - t.Run("db.Query().DoTx", func(t *testing.T) { - err := nativeDriver.Query().DoTx(ctx, func(ctx context.Context, tx query.TxActor) error { - return retry.RetryableError(errors.New("custom error")) - }, query.WithRetryBudget(retryBudget)) - require.ErrorIs(t, err, budget.ErrNoQuota) - }) - } + t.Run("db.Query().Do", func(t *testing.T) { + err := nativeDriver.Query().Do(ctx, func(ctx context.Context, s query.Session) error { + return retry.RetryableError(errors.New("custom error")) + }, query.WithRetryBudget(retryBudget)) + require.ErrorIs(t, err, budget.ErrNoQuota) + }) + t.Run("db.Query().DoTx", func(t *testing.T) { + err := nativeDriver.Query().DoTx(ctx, func(ctx context.Context, tx query.TxActor) error { + return retry.RetryableError(errors.New("custom error")) + }, query.WithRetryBudget(retryBudget)) + require.ErrorIs(t, err, budget.ErrNoQuota) + }) } diff --git a/tests/integration/sugar_result_test.go b/tests/integration/sugar_result_test.go index 6a2324b9e..3564eb704 100644 --- a/tests/integration/sugar_result_test.go +++ b/tests/integration/sugar_result_test.go @@ -12,7 +12,6 @@ import ( "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/query" "github.com/ydb-platform/ydb-go-sdk/v3/sugar" "github.com/ydb-platform/ydb-go-sdk/v3/table" @@ -21,10 +20,6 @@ import ( ) func TestSugarResult(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - ctx, cancel := context.WithCancel(context.Background()) defer cancel() diff --git a/tests/integration/sugar_unmarhall_result_set_test.go b/tests/integration/sugar_unmarhall_result_set_test.go index 68a43c7d8..26ef254a4 100644 --- a/tests/integration/sugar_unmarhall_result_set_test.go +++ b/tests/integration/sugar_unmarhall_result_set_test.go @@ -5,22 +5,16 @@ package integration import ( "context" - "os" "testing" "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/scanner" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/sugar" ) func TestSugarUnmarshallResultSet(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - ctx, cancel := context.WithCancel(xtest.Context(t)) defer cancel() diff --git a/tests/integration/sugar_unmarhall_row_test.go b/tests/integration/sugar_unmarhall_row_test.go index dadbfab42..30761d010 100644 --- a/tests/integration/sugar_unmarhall_row_test.go +++ b/tests/integration/sugar_unmarhall_row_test.go @@ -5,22 +5,16 @@ package integration import ( "context" - "os" "testing" "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3/internal/query/scanner" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/sugar" ) func TestSugarUnmarshallRow(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("query service not allowed in YDB version '" + os.Getenv("YDB_VERSION") + "'") - } - ctx, cancel := context.WithCancel(xtest.Context(t)) defer cancel() diff --git a/tests/integration/topic_client_test.go b/tests/integration/topic_client_test.go index 677ca074c..6425efbbe 100644 --- a/tests/integration/topic_client_test.go +++ b/tests/integration/topic_client_test.go @@ -17,7 +17,6 @@ import ( ydb "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/config" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topicoptions" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topictypes" @@ -144,17 +143,13 @@ func TestDescribeTopicConsumer(t *testing.T) { ctx := xtest.Context(t) db := connect(t) topicName := "test-topic-" + t.Name() - setImportant := true - if os.Getenv("YDB_VERSION") != "nightly" && version.Lt(os.Getenv("YDB_VERSION"), "24.1.1") { - setImportant = false - } var ( supportedCodecs = []topictypes.Codec{topictypes.CodecRaw, topictypes.CodecGzip} minActivePartitions = int64(2) consumers = []topictypes.Consumer{ { Name: "c1", - Important: setImportant, + Important: true, SupportedCodecs: []topictypes.Codec{topictypes.CodecRaw, topictypes.CodecGzip}, ReadFrom: time.Date(2022, 9, 11, 10, 1, 2, 0, time.UTC), }, @@ -184,7 +179,7 @@ func TestDescribeTopicConsumer(t *testing.T) { Path: path.Join(topicName, "c1"), Consumer: topictypes.Consumer{ Name: "c1", - Important: setImportant, + Important: true, SupportedCodecs: []topictypes.Codec{topictypes.CodecRaw, topictypes.CodecGzip}, ReadFrom: time.Date(2022, 9, 11, 10, 1, 2, 0, time.UTC), Attributes: map[string]string{ @@ -276,9 +271,6 @@ func TestSchemeList(t *testing.T) { func TestReaderWithoutConsumer(t *testing.T) { t.Run("OK", func(t *testing.T) { - if version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("Read topic without consumer implemented since YDB 24.1, test ran for '" + os.Getenv("YDB_VERSION") + "'") - } scope := newScope(t) ctx := scope.Ctx diff --git a/tests/integration/topic_helpers_test.go b/tests/integration/topic_helpers_test.go index 84d4d3220..0d216463a 100644 --- a/tests/integration/topic_helpers_test.go +++ b/tests/integration/topic_helpers_test.go @@ -8,14 +8,12 @@ import ( "encoding/json" "fmt" "io" - "os" "path" "strings" "testing" "github.com/stretchr/testify/require" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topicoptions" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topicsugar" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topicwriter" @@ -116,9 +114,6 @@ func TestMessageJsonUnmarshalIterator(t *testing.T) { } func TestCDCReaderIterator(t *testing.T) { - if os.Getenv("YDB_VERSION") != "nightly" && version.Lt(os.Getenv("YDB_VERSION"), "24.1") { - t.Skip("require minimum version 24.1 for work with within yql") - } scope := newScope(t) ctx := scope.Ctx From 33ae9524d01f2cfc229c54cf6f100816a806c977 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Wed, 11 Dec 2024 20:30:37 +0300 Subject: [PATCH 55/62] fixed integration tests with database/sql driver over query service --- .../database_sql_regression_test.go | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/tests/integration/database_sql_regression_test.go b/tests/integration/database_sql_regression_test.go index 01a63576b..3cd0dc646 100644 --- a/tests/integration/database_sql_regression_test.go +++ b/tests/integration/database_sql_regression_test.go @@ -19,6 +19,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3" "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/conn/table/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" "github.com/ydb-platform/ydb-go-sdk/v3/retry" @@ -234,7 +235,12 @@ func TestUUIDSerializationDatabaseSQLIssue1501(t *testing.T) { var res [16]byte err := row.Scan(&res) - require.Error(t, err) + switch driverEngine(db) { + case xsql.TABLE_SERVICE: + require.Error(t, err) + case xsql.QUERY_SERVICE: + require.NoError(t, err) + } }) t.Run("old-receive-to-bytes-with-force-wrapper", func(t *testing.T) { // test old behavior - for test way of safe work with data, written with bagged API version @@ -256,10 +262,14 @@ func TestUUIDSerializationDatabaseSQLIssue1501(t *testing.T) { var res types.UUIDBytesWithIssue1501Type err := row.Scan(&res) - require.NoError(t, err) - - resUUID := uuid.UUID(res.AsBytesArray()) - require.Equal(t, expectedResultWithBug, resUUID.String()) + switch driverEngine(db) { + case xsql.TABLE_SERVICE: + require.NoError(t, err) + resUUID := uuid.UUID(res.AsBytesArray()) + require.Equal(t, expectedResultWithBug, resUUID.String()) + case xsql.QUERY_SERVICE: + require.Error(t, err) + } }) t.Run("old-receive-to-string", func(t *testing.T) { @@ -341,11 +351,14 @@ func TestUUIDSerializationDatabaseSQLIssue1501(t *testing.T) { var resBytes types.UUIDBytesWithIssue1501Type err := row.Scan(&resBytes) - require.NoError(t, err) - - resUUID := uuid.UUID(resBytes.AsBytesArray()) - - require.Equal(t, id, resUUID) + switch driverEngine(db) { + case xsql.TABLE_SERVICE: + require.NoError(t, err) + resUUID := uuid.UUID(resBytes.AsBytesArray()) + require.Equal(t, id, resUUID) + case xsql.QUERY_SERVICE: + require.Error(t, err) + } }) t.Run("old-send-uuid-receive-error-bad-request", func(t *testing.T) { var ( @@ -405,12 +418,16 @@ func TestUUIDSerializationDatabaseSQLIssue1501(t *testing.T) { var resFromDB types.UUIDBytesWithIssue1501Type err := row.Scan(&resFromDB) - require.NoError(t, err) - - resUUID := resFromDB.PublicRevertReorderForIssue1501() + switch driverEngine(db) { + case xsql.TABLE_SERVICE: + require.NoError(t, err) + resUUID := resFromDB.PublicRevertReorderForIssue1501() + resString := strings.ToUpper(resUUID.String()) + require.Equal(t, idString, resString) + case xsql.QUERY_SERVICE: + require.Error(t, err) + } - resString := strings.ToUpper(resUUID.String()) - require.Equal(t, idString, resString) }) t.Run("good-send-receive", func(t *testing.T) { var ( From 09192eee9d0c80ae92edbd25f29aa84707348388 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Wed, 11 Dec 2024 21:28:52 +0300 Subject: [PATCH 56/62] fixed tracing over database/sql --- internal/xsql/conn.go | 74 +++++++++++++++++++++++++++++++++----- internal/xsql/connector.go | 13 +++++++ 2 files changed, 78 insertions(+), 9 deletions(-) diff --git a/internal/xsql/conn.go b/internal/xsql/conn.go index 329449a34..a0c607fa2 100644 --- a/internal/xsql/conn.go +++ b/internal/xsql/conn.go @@ -15,6 +15,7 @@ import ( "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/xcontext" "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/conn" @@ -37,6 +38,7 @@ type ( cc conn.Conn currentTx *txWrapper + ctx context.Context //nolint:containedctx connector *Connector lastUsage xsync.LastUsage @@ -60,10 +62,13 @@ func (c *connWrapper) CheckNamedValue(value *driver.NamedValue) error { return nil } -func (c *connWrapper) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { - if c.currentTx != nil { - return nil, xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())) - } +func BeginTx(ctx context.Context, c *connWrapper, opts driver.TxOptions) (_ driver.Tx, finalErr error) { + onDone := trace.DatabaseSQLOnConnBegin(c.connector.trace, &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.BeginTx"), + ) + defer func() { + onDone(c.currentTx, finalErr) + }() tx, err := c.cc.BeginTx(ctx, opts) if err != nil { @@ -79,7 +84,22 @@ func (c *connWrapper) BeginTx(ctx context.Context, opts driver.TxOptions) (drive return c.currentTx, nil } -func (c *connWrapper) Close() error { +func (c *connWrapper) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { + if c.currentTx != nil { + return nil, xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())) + } + + return BeginTx(ctx, c, opts) +} + +func Close(c *connWrapper) (finalErr error) { + onDone := trace.DatabaseSQLOnConnClose(c.connector.Trace(), &c.ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.Close"), + ) + defer func() { + onDone(finalErr) + }() + err := c.cc.Close() if err != nil { return xerrors.WithStackTrace(err) @@ -88,6 +108,10 @@ func (c *connWrapper) Close() error { return nil } +func (c *connWrapper) Close() (finalErr error) { + return Close(c) +} + func (c *connWrapper) Connector() *Connector { return c.connector } @@ -139,9 +163,9 @@ func (c *connWrapper) Prepare(string) (driver.Stmt, error) { return nil, errDeprecated } -func (c *connWrapper) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, finalErr error) { +func PrepareContext(ctx context.Context, c *connWrapper, sql string) (_ driver.Stmt, finalErr error) { onDone := trace.DatabaseSQLOnConnPrepare(c.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*connWrapper).PrepareContext"), + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.PrepareContext"), sql, ) defer func() { @@ -160,6 +184,10 @@ func (c *connWrapper) PrepareContext(ctx context.Context, sql string) (_ driver. }, nil } +func (c *connWrapper) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, finalErr error) { + return PrepareContext(ctx, c, sql) +} + func (c *connWrapper) LastUsage() time.Time { return c.lastUsage.Get() } @@ -178,7 +206,17 @@ func (c *connWrapper) toYdb(sql string, args ...driver.NamedValue) (yql string, return yql, ¶ms, nil } -func (c *connWrapper) QueryContext(ctx context.Context, sql string, args []driver.NamedValue) (driver.Rows, error) { +func QueryContext(ctx context.Context, c *connWrapper, sql string, args []driver.NamedValue) ( + _ driver.Rows, finalErr error, +) { + onDone := trace.DatabaseSQLOnConnQuery(c.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.QueryContext"), + sql, c.connector.processor.String(), xcontext.IsIdempotent(ctx), c.connector.clock.Since(c.lastUsage.Get()), + ) + defer func() { + onDone(finalErr) + }() + done := c.lastUsage.Start() defer done() @@ -203,7 +241,21 @@ func (c *connWrapper) QueryContext(ctx context.Context, sql string, args []drive return c.cc.Query(ctx, sql, params) } -func (c *connWrapper) ExecContext(ctx context.Context, sql string, args []driver.NamedValue) (driver.Result, error) { +func (c *connWrapper) QueryContext(ctx context.Context, sql string, args []driver.NamedValue) (driver.Rows, error) { + return QueryContext(ctx, c, sql, args) +} + +func ExecContext(ctx context.Context, c *connWrapper, sql string, args []driver.NamedValue) ( + _ driver.Result, finalErr error, +) { + onDone := trace.DatabaseSQLOnConnExec(c.connector.Trace(), &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.ExecContext"), + sql, c.connector.processor.String(), xcontext.IsIdempotent(ctx), c.connector.clock.Since(c.lastUsage.Get()), + ) + defer func() { + onDone(finalErr) + }() + done := c.lastUsage.Start() defer done() @@ -219,6 +271,10 @@ func (c *connWrapper) ExecContext(ctx context.Context, sql string, args []driver return c.cc.Exec(ctx, sql, params) } +func (c *connWrapper) ExecContext(ctx context.Context, sql string, args []driver.NamedValue) (driver.Result, error) { + return ExecContext(ctx, c, sql, args) +} + func (c *connWrapper) GetDatabaseName() string { return c.connector.Name() } diff --git a/internal/xsql/connector.go b/internal/xsql/connector.go index 1c38591fb..dd279e726 100644 --- a/internal/xsql/connector.go +++ b/internal/xsql/connector.go @@ -63,6 +63,17 @@ type ( } ) +func (e Engine) String() string { + switch e { + case TABLE_SERVICE: + return "TABLE_SERVICE" + case QUERY_SERVICE: + return "QUERY_SERVICE" + default: + return "UNKNOWN" + } +} + func (c *Connector) RetryBudget() budget.Budget { return c.retryBudget } @@ -130,6 +141,7 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { c.conns.Delete(id) }))..., ), + ctx: ctx, connector: c, lastUsage: xsync.NewLastUsage(xsync.WithClock(c.Clock())), } @@ -153,6 +165,7 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { c.conns.Delete(id) }))..., ), + ctx: ctx, connector: c, lastUsage: xsync.NewLastUsage(xsync.WithClock(c.Clock())), } From 6022f09d2c1d52ca4ba58fb1960d87568ab0d8ae Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Thu, 12 Dec 2024 22:02:29 +0300 Subject: [PATCH 57/62] added record option info stack.FunctionID --- internal/stack/function_id.go | 4 ++-- internal/stack/record.go | 38 ++++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/internal/stack/function_id.go b/internal/stack/function_id.go index 141b91f50..5726ec4b8 100644 --- a/internal/stack/function_id.go +++ b/internal/stack/function_id.go @@ -12,10 +12,10 @@ func (id functionID) String() string { return string(id) } -func FunctionID(id string) Caller { +func FunctionID(id string, opts ...recordOption) Caller { if id != "" { return functionID(id) } - return Call(1) + return Call(1, opts...) } diff --git a/internal/stack/record.go b/internal/stack/record.go index 8d3445429..2d8341ecc 100644 --- a/internal/stack/record.go +++ b/internal/stack/record.go @@ -10,6 +10,7 @@ import ( ) type recordOptions struct { + packageAlias string packagePath bool packageName bool structName bool @@ -71,23 +72,33 @@ func PackagePath(b bool) recordOption { } } +func Package(alias string) recordOption { + return func(opts *recordOptions) { + opts.packageAlias = alias + } +} + var _ Caller = call{} type call struct { function uintptr file string line int + opts []recordOption } -func Call(depth int) (c call) { +func Call(depth int, opts ...recordOption) (c call) { c.function, c.file, c.line, _ = runtime.Caller(depth + 1) + c.opts = opts + return c } func (c call) Record(opts ...recordOption) string { optionsHolder := recordOptions{ packagePath: true, + packageAlias: "", packageName: true, structName: true, functionName: true, @@ -95,6 +106,7 @@ func (c call) Record(opts ...recordOption) string { line: true, lambdas: true, } + for _, opt := range opts { if opt != nil { opt(&optionsHolder) @@ -151,14 +163,22 @@ func buildRecordString( ) string { buffer := xstring.Buffer() defer buffer.Free() - if optionsHolder.packagePath { - buffer.WriteString(fnDetails.pkgPath) - } - if optionsHolder.packageName { - if buffer.Len() > 0 { - buffer.WriteByte('/') + if optionsHolder.packageAlias != "" { + buffer.WriteString(optionsHolder.packageAlias) + } else { + if optionsHolder.packagePath { + if optionsHolder.packageAlias != "" { + buffer.WriteString(optionsHolder.packageAlias) + } else { + buffer.WriteString(fnDetails.pkgPath) + } + } + if optionsHolder.packageName { + if buffer.Len() > 0 { + buffer.WriteByte('/') + } + buffer.WriteString(fnDetails.pkgName) } - buffer.WriteString(fnDetails.pkgName) } if optionsHolder.structName && len(fnDetails.structName) > 0 { if buffer.Len() > 0 { @@ -198,7 +218,7 @@ func buildRecordString( } func (c call) String() string { - return c.Record(Lambda(false), FileName(false)) + return c.Record(append(c.opts, Lambda(false), FileName(false))...) } func Record(depth int, opts ...recordOption) string { From fd4142df6e70e949cc2b141bdc358d27473f69f9 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Thu, 12 Dec 2024 22:34:55 +0300 Subject: [PATCH 58/62] * Added implementation of `database/sql` driver over query service client * Added `ydb.WithQueryService(bool)` option to explicitly enable `database/sql` driver over query service client * Added environment parameter `YDB_DATABASE_SQL_OVER_QUERY_SERVICE` to enable `database/sql` driver over query service client without code rewriting --- CHANGELOG.md | 4 + dsn.go | 42 +- dsn_test.go | 42 +- internal/stack/record.go | 2 +- internal/xsql/conn.go | 408 ++---------- internal/xsql/conn/query/errors.go | 15 - internal/xsql/conn/table/errors.go | 15 - internal/xsql/conn_helpers.go | 275 ++++++++ .../{conn_test.go => conn_helpers_test.go} | 40 +- internal/xsql/connector.go | 38 +- internal/xsql/errors.go | 2 +- internal/xsql/{conn => iface}/conn.go | 2 +- internal/xsql/{conn => iface}/context.go | 2 +- internal/xsql/{conn => iface}/tx.go | 2 +- .../{conn/table => legacy}/badconn/badconn.go | 0 .../table => legacy}/badconn/badconn_test.go | 0 internal/xsql/{conn/table => legacy}/conn.go | 12 +- .../xsql/{conn/table => legacy}/context.go | 6 +- internal/xsql/legacy/errors.go | 15 + .../xsql/{conn/table => legacy}/isolation.go | 2 +- .../{conn/table => legacy}/isolation_test.go | 2 +- internal/xsql/{conn/table => legacy}/mode.go | 30 +- .../xsql/{conn/table => legacy}/options.go | 2 +- internal/xsql/{conn/table => legacy}/rows.go | 4 +- internal/xsql/{conn/table => legacy}/tx.go | 10 +- .../xsql/{conn/query => legacy}/tx_fake.go | 8 +- .../xsql/{conn/table => legacy}/valuer.go | 2 +- internal/xsql/options.go | 60 +- internal/xsql/{conn/query => propose}/conn.go | 8 +- internal/xsql/propose/errors.go | 15 + .../xsql/{conn/query => propose}/isolation.go | 2 +- .../xsql/{conn/query => propose}/options.go | 2 +- internal/xsql/{conn/query => propose}/rows.go | 2 +- internal/xsql/{conn/query => propose}/tx.go | 6 +- .../xsql/{conn/table => propose}/tx_fake.go | 8 +- internal/xsql/rows.go | 51 ++ internal/xsql/stmt.go | 28 +- internal/xsql/tx.go | 40 +- internal/xsql/unwrap.go | 6 +- retry/errors.go | 2 +- retry/sql_test.go | 2 +- spans/helpers.go | 4 +- spans/sql.go | 615 +++++++++++------- sql.go | 60 +- .../database_sql_regression_test.go | 10 +- .../database_sql_with_tx_control_test.go | 14 +- tests/integration/table_truncated_err_test.go | 2 +- trace/sql.go | 74 +++ trace/sql_gtrace.go | 278 ++++++++ 49 files changed, 1411 insertions(+), 860 deletions(-) delete mode 100644 internal/xsql/conn/query/errors.go delete mode 100644 internal/xsql/conn/table/errors.go create mode 100644 internal/xsql/conn_helpers.go rename internal/xsql/{conn_test.go => conn_helpers_test.go} (69%) rename internal/xsql/{conn => iface}/conn.go (97%) rename internal/xsql/{conn => iface}/context.go (95%) rename internal/xsql/{conn => iface}/tx.go (96%) rename internal/xsql/{conn/table => legacy}/badconn/badconn.go (100%) rename internal/xsql/{conn/table => legacy}/badconn/badconn_test.go (100%) rename internal/xsql/{conn/table => legacy}/conn.go (95%) rename internal/xsql/{conn/table => legacy}/context.go (90%) create mode 100644 internal/xsql/legacy/errors.go rename internal/xsql/{conn/table => legacy}/isolation.go (98%) rename internal/xsql/{conn/table => legacy}/isolation_test.go (99%) rename internal/xsql/{conn/table => legacy}/mode.go (58%) rename internal/xsql/{conn/table => legacy}/options.go (98%) rename internal/xsql/{conn/table => legacy}/rows.go (97%) rename internal/xsql/{conn/table => legacy}/tx.go (91%) rename internal/xsql/{conn/query => legacy}/tx_fake.go (85%) rename internal/xsql/{conn/table => legacy}/valuer.go (94%) rename internal/xsql/{conn/query => propose}/conn.go (96%) create mode 100644 internal/xsql/propose/errors.go rename internal/xsql/{conn/query => propose}/isolation.go (97%) rename internal/xsql/{conn/query => propose}/options.go (93%) rename internal/xsql/{conn/query => propose}/rows.go (99%) rename internal/xsql/{conn/query => propose}/tx.go (94%) rename internal/xsql/{conn/table => propose}/tx_fake.go (85%) create mode 100644 internal/xsql/rows.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 830e53d58..7ada620dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +* Added implementation of `database/sql` driver over query service client +* Added `ydb.WithQueryService(bool)` option to explicitly enable `database/sql` driver over query service client +* Added environment parameter `YDB_DATABASE_SQL_OVER_QUERY_SERVICE` to enable `database/sql` driver over query service client without code rewriting + ## v3.94.0 * Refactored golang types mapping into ydb types using `ydb.ParamsFromMap` and `database/sql` query arguments * Small breaking change: type mapping for `ydb.ParamsFromMap` and `database/sql` type `uuid.UUID` changed from ydb type `Text` to ydb type `UUID` diff --git a/dsn.go b/dsn.go index 466bbf87a..ea9702f31 100644 --- a/dsn.go +++ b/dsn.go @@ -12,7 +12,6 @@ import ( "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" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" ) const tablePathPrefixTransformer = "table_path_prefix" @@ -44,6 +43,22 @@ func UnregisterDsnParser(registrationID int) { dsnParsers[registrationID] = nil } +var stringToType = map[string]QueryMode{ + "data": DataQueryMode, + "scan": ScanQueryMode, + "scheme": SchemeQueryMode, + "scripting": ScriptingQueryMode, + "query": QueryExecuteQueryMode, +} + +func queryModeFromString(s string) QueryMode { + if t, ok := stringToType[s]; ok { + return t + } + + return unknownQueryMode +} + //nolint:funlen func parseConnectionString(dataSourceName string) (opts []Option, _ error) { info, err := dsn.Parse(dataSourceName) @@ -60,25 +75,32 @@ func parseConnectionString(dataSourceName string) (opts []Option, _ error) { opts = append(opts, WithBalancer(balancers.FromConfig(balancer))) } if queryMode := info.Params.Get("go_query_mode"); queryMode != "" { - mode := table.QueryModeFromString(queryMode) - if mode == table.UnknownQueryMode { + switch mode := queryModeFromString(queryMode); mode { + case QueryExecuteQueryMode: + opts = append(opts, withConnectorOptions(xsql.WithQueryService(true))) + case unknownQueryMode: return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) + default: + opts = append(opts, withConnectorOptions(xsql.WithDefaultQueryMode(modeToMode(mode)))) } - opts = append(opts, withConnectorOptions(xsql.WithDefaultQueryMode(mode))) } else if queryMode := info.Params.Get("query_mode"); queryMode != "" { - mode := table.QueryModeFromString(queryMode) - if mode == table.UnknownQueryMode { + switch mode := queryModeFromString(queryMode); mode { + case QueryExecuteQueryMode: + opts = append(opts, withConnectorOptions(xsql.WithQueryService(true))) + case unknownQueryMode: return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) + default: + opts = append(opts, withConnectorOptions(xsql.WithDefaultQueryMode(modeToMode(mode)))) } - opts = append(opts, withConnectorOptions(xsql.WithDefaultQueryMode(mode))) } if fakeTx := info.Params.Get("go_fake_tx"); fakeTx != "" { for _, queryMode := range strings.Split(fakeTx, ",") { - mode := table.QueryModeFromString(queryMode) - if mode == table.UnknownQueryMode { + switch mode := queryModeFromString(queryMode); mode { + case unknownQueryMode: return nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) + default: + opts = append(opts, withConnectorOptions(WithFakeTx(mode))) } - opts = append(opts, withConnectorOptions(xsql.WithFakeTx(mode))) } } if info.Params.Has("go_query_bind") { diff --git a/dsn_test.go b/dsn_test.go index 217df60bd..f70fe4cc3 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/xsql" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/propose" ) func TestParse(t *testing.T) { @@ -26,11 +26,11 @@ func TestParse(t *testing.T) { return c } - newTableConn := func(opts ...table.Option) *table.Conn { - return table.New(context.Background(), nil, nil, opts...) + newLegacyConn := func(opts ...legacy.Option) *legacy.Conn { + return legacy.New(context.Background(), nil, nil, opts...) } - newQueryConn := func(opts ...query.Option) *query.Conn { - return query.New(context.Background(), nil, nil, opts...) + newQueryConn := func(opts ...propose.Option) *propose.Conn { + return propose.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: []xsql.Option{ - xsql.WithDefaultQueryMode(table.ScriptingQueryMode), + xsql.WithDefaultQueryMode(legacy.ScriptingQueryMode), }, err: nil, }, @@ -83,7 +83,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(table.ScriptingQueryMode), + xsql.WithDefaultQueryMode(legacy.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), }, err: nil, @@ -96,7 +96,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(table.ScriptingQueryMode), + xsql.WithDefaultQueryMode(legacy.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.NumericArgs{}), }, @@ -110,7 +110,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(table.ScriptingQueryMode), + xsql.WithDefaultQueryMode(legacy.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.PositionalArgs{}), }, @@ -124,7 +124,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(table.ScriptingQueryMode), + xsql.WithDefaultQueryMode(legacy.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.AutoDeclare{}), }, @@ -138,7 +138,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(table.ScriptingQueryMode), + xsql.WithDefaultQueryMode(legacy.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), }, err: nil, @@ -151,7 +151,7 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithDefaultQueryMode(table.ScriptingQueryMode), + xsql.WithDefaultQueryMode(legacy.ScriptingQueryMode), xsql.WithQueryBind(bind.TablePathPrefix("path/to/tables")), xsql.WithQueryBind(bind.PositionalArgs{}), xsql.WithQueryBind(bind.AutoDeclare{}), @@ -166,8 +166,8 @@ func TestParse(t *testing.T) { config.WithDatabase("/local"), }, connectorOpts: []xsql.Option{ - xsql.WithFakeTx(table.ScriptingQueryMode), - xsql.WithFakeTx(table.SchemeQueryMode), + WithFakeTx(ScriptingQueryMode), + WithFakeTx(SchemeQueryMode), }, err: nil, }, @@ -183,15 +183,15 @@ func TestParse(t *testing.T) { exp := newConnector(tt.connectorOpts...) act := newConnector(d.databaseSQLOptions...) t.Run("tableOptions", func(t *testing.T) { - require.Equal(t, newTableConn(exp.TableOpts...), newTableConn(act.TableOpts...)) + require.Equal(t, newLegacyConn(exp.LegacyOpts...), newLegacyConn(act.LegacyOpts...)) }) t.Run("queryOptions", func(t *testing.T) { - require.Equal(t, newQueryConn(exp.QueryOpts...), newQueryConn(act.QueryOpts...)) + require.Equal(t, newQueryConn(exp.Options...), newQueryConn(act.Options...)) }) - exp.TableOpts = nil - exp.QueryOpts = nil - act.TableOpts = nil - act.QueryOpts = nil + exp.LegacyOpts = nil + exp.Options = nil + act.LegacyOpts = nil + act.Options = nil require.Equal(t, exp.Bindings(), act.Bindings()) require.Equal(t, exp, act) compareConfigs(t, config.New(tt.opts...), d.config) diff --git a/internal/stack/record.go b/internal/stack/record.go index 2d8341ecc..1cfde1618 100644 --- a/internal/stack/record.go +++ b/internal/stack/record.go @@ -163,7 +163,7 @@ func buildRecordString( ) string { buffer := xstring.Buffer() defer buffer.Free() - if optionsHolder.packageAlias != "" { + if optionsHolder.packageAlias != "" { //nolint:nestif buffer.WriteString(optionsHolder.packageAlias) } else { if optionsHolder.packagePath { diff --git a/internal/xsql/conn.go b/internal/xsql/conn.go index a0c607fa2..a59e2b1cc 100644 --- a/internal/xsql/conn.go +++ b/internal/xsql/conn.go @@ -2,80 +2,69 @@ package xsql import ( "context" - "database/sql" "database/sql/driver" - "fmt" - "io" - "path" - "strings" - "time" - - "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/xcontext" "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/conn" + "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" - "github.com/ydb-platform/ydb-go-sdk/v3/table/options" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) -var ( - _ driver.ConnBeginTx = (*connWrapper)(nil) - _ driver.NamedValueChecker = (*connWrapper)(nil) - _ driver.Pinger = (*connWrapper)(nil) -) - -type ( - connWrapper struct { - processor Engine +type Conn struct { + processor Engine - cc conn.Conn - currentTx *txWrapper - ctx context.Context //nolint:containedctx + cc iface.Conn + currentTx *Tx + ctx context.Context //nolint:containedctx - connector *Connector - lastUsage xsync.LastUsage - } - singleRow struct { - values []sql.NamedArg - readAll bool - } -) - -func (c *connWrapper) Engine() Engine { - return c.processor + connector *Connector + lastUsage xsync.LastUsage } -func (c *connWrapper) Ping(ctx context.Context) error { +func (c *Conn) Ping(ctx context.Context) (finalErr error) { + onDone := trace.DatabaseSQLOnConnPing(c.connector.trace, &c.ctx, + stack.FunctionID("", stack.Package("database/sql")), + ) + defer func() { + onDone(finalErr) + }() + return c.cc.Ping(ctx) } -func (c *connWrapper) CheckNamedValue(value *driver.NamedValue) error { +func (c *Conn) CheckNamedValue(value *driver.NamedValue) (finalErr error) { + onDone := trace.DatabaseSQLOnConnCheckNamedValue(c.connector.trace, &c.ctx, + stack.FunctionID("", stack.Package("database/sql")), + value, + ) + defer func() { + onDone(finalErr) + }() + // on this stage allows all values return nil } -func BeginTx(ctx context.Context, c *connWrapper, opts driver.TxOptions) (_ driver.Tx, finalErr error) { - onDone := trace.DatabaseSQLOnConnBegin(c.connector.trace, &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.BeginTx"), +func (c *Conn) BeginTx(ctx context.Context, opts driver.TxOptions) (_ driver.Tx, finalErr error) { + onDone := trace.DatabaseSQLOnConnBeginTx(c.connector.trace, &ctx, + stack.FunctionID("", stack.Package("database/sql")), ) defer func() { onDone(c.currentTx, finalErr) }() + if c.currentTx != nil { + return nil, xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())) + } + tx, err := c.cc.BeginTx(ctx, opts) if err != nil { return nil, xerrors.WithStackTrace(err) } - c.currentTx = &txWrapper{ + c.currentTx = &Tx{ conn: c, ctx: ctx, tx: tx, @@ -84,17 +73,9 @@ func BeginTx(ctx context.Context, c *connWrapper, opts driver.TxOptions) (_ driv return c.currentTx, nil } -func (c *connWrapper) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { - if c.currentTx != nil { - return nil, xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())) - } - - return BeginTx(ctx, c, opts) -} - -func Close(c *connWrapper) (finalErr error) { +func (c *Conn) Close() (finalErr error) { onDone := trace.DatabaseSQLOnConnClose(c.connector.Trace(), &c.ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.Close"), + stack.FunctionID("", stack.Package("database/sql")), ) defer func() { onDone(finalErr) @@ -108,64 +89,28 @@ func Close(c *connWrapper) (finalErr error) { return nil } -func (c *connWrapper) Close() (finalErr error) { - return Close(c) -} - -func (c *connWrapper) Connector() *Connector { - return c.connector -} - -func (c *connWrapper) 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) - } - - return columns -} - -func (r *singleRow) Close() error { - return nil -} +func (c *Conn) Begin() (_ driver.Tx, finalErr error) { + onDone := trace.DatabaseSQLOnConnBegin(c.connector.trace, &c.ctx, + stack.FunctionID("", stack.Package("database/sql")), + ) + defer func() { + onDone(c.currentTx, finalErr) + }() -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 + if c.currentTx != nil { + return nil, xerrors.WithStackTrace(xerrors.AlreadyHasTx(c.currentTx.ID())) } - r.readAll = true - return nil + return nil, xerrors.WithStackTrace(errDeprecated) } -func (c *connWrapper) Prepare(string) (driver.Stmt, error) { +func (c *Conn) Prepare(string) (driver.Stmt, error) { return nil, errDeprecated } -func PrepareContext(ctx context.Context, c *connWrapper, sql string) (_ driver.Stmt, finalErr 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/xsql.PrepareContext"), + stack.FunctionID("", stack.Package("database/sql")), sql, ) defer func() { @@ -176,7 +121,7 @@ func PrepareContext(ctx context.Context, c *connWrapper, sql string) (_ driver.S return nil, xerrors.WithStackTrace(errNotReadyConn) } - return &stmt{ + return &Stmt{ conn: c, processor: c.cc, ctx: ctx, @@ -184,33 +129,11 @@ func PrepareContext(ctx context.Context, c *connWrapper, sql string) (_ driver.S }, nil } -func (c *connWrapper) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, finalErr error) { - return PrepareContext(ctx, c, sql) -} - -func (c *connWrapper) LastUsage() time.Time { - return c.lastUsage.Get() -} - -func (c *connWrapper) toYdb(sql string, args ...driver.NamedValue) (yql string, _ *params.Params, _ error) { - queryArgs := make([]any, len(args)) - for i := range args { - queryArgs[i] = args[i] - } - - yql, params, err := c.connector.Bindings().ToYdb(sql, queryArgs...) - if err != nil { - return "", nil, xerrors.WithStackTrace(err) - } - - return yql, ¶ms, nil -} - -func QueryContext(ctx context.Context, c *connWrapper, sql string, args []driver.NamedValue) ( +func (c *Conn) QueryContext(ctx context.Context, sql string, args []driver.NamedValue) ( _ driver.Rows, finalErr error, ) { onDone := trace.DatabaseSQLOnConnQuery(c.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.QueryContext"), + stack.FunctionID("", stack.Package("database/sql")), sql, c.connector.processor.String(), xcontext.IsIdempotent(ctx), c.connector.clock.Since(c.lastUsage.Get()), ) defer func() { @@ -241,15 +164,11 @@ func QueryContext(ctx context.Context, c *connWrapper, sql string, args []driver return c.cc.Query(ctx, sql, params) } -func (c *connWrapper) QueryContext(ctx context.Context, sql string, args []driver.NamedValue) (driver.Rows, error) { - return QueryContext(ctx, c, sql, args) -} - -func ExecContext(ctx context.Context, c *connWrapper, sql string, args []driver.NamedValue) ( +func (c *Conn) ExecContext(ctx context.Context, sql string, args []driver.NamedValue) ( _ driver.Result, finalErr error, ) { onDone := trace.DatabaseSQLOnConnExec(c.connector.Trace(), &ctx, - stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.ExecContext"), + stack.FunctionID("", stack.Package("database/sql")), sql, c.connector.processor.String(), xcontext.IsIdempotent(ctx), c.connector.clock.Since(c.lastUsage.Get()), ) defer func() { @@ -270,222 +189,3 @@ func ExecContext(ctx context.Context, c *connWrapper, sql string, args []driver. return c.cc.Exec(ctx, sql, params) } - -func (c *connWrapper) ExecContext(ctx context.Context, sql string, args []driver.NamedValue) (driver.Result, error) { - return ExecContext(ctx, c, sql, args) -} - -func (c *connWrapper) GetDatabaseName() string { - return c.connector.Name() -} - -func (c *connWrapper) normalizePath(tableName string) string { - return c.connector.pathNormalizer.NormalizePath(tableName) -} - -func (c *connWrapper) 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.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) - } - - return d, nil -} - -func (c *connWrapper) 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) - } - - for i := range d.Columns { - columns = append(columns, d.Columns[i].Name) - } - - return columns, nil -} - -func (c *connWrapper) 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) - } - - for i := range d.Columns { - if d.Columns[i].Name == columnName { - return d.Columns[i].Type.Yql(), nil - } - } - - 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) { - d, err := c.tableDescription(ctx, c.normalizePath(tableName)) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - return d.PrimaryKey, nil -} - -func (c *connWrapper) 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) - } - - for _, pkCol := range d.PrimaryKey { - if pkCol == columnName { - return true, nil - } - } - - return false, nil -} - -func (c *connWrapper) Version(_ context.Context) (_ string, _ error) { - const version = "default" - - return version, nil -} - -func isSysDir(databaseName, dirAbsPath string) bool { - for _, sysDir := range [...]string{ - path.Join(databaseName, ".sys"), - path.Join(databaseName, ".sys_health"), - } { - if strings.HasPrefix(dirAbsPath, sysDir) { - return true - } - } - - return false -} - -func (c *connWrapper) getTables(ctx context.Context, absPath string, recursive, excludeSysDirs bool) ( - tables []string, _ error, -) { - if excludeSysDirs && isSysDir(c.connector.Name(), absPath) { - return nil, nil - } - - d, err := c.connector.Scheme().ListDirectory(ctx, absPath) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - if !d.IsDirectory() && !d.IsDatabase() { - return nil, xerrors.WithStackTrace(fmt.Errorf("'%s' is not a folder", absPath)) - } - - for i := range d.Children { - switch d.Children[i].Type { - case scheme.EntryTable, scheme.EntryColumnTable: - tables = append(tables, path.Join(absPath, d.Children[i].Name)) - case scheme.EntryDirectory, scheme.EntryDatabase: - if recursive { - childTables, err := c.getTables(ctx, path.Join(absPath, d.Children[i].Name), recursive, excludeSysDirs) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - tables = append(tables, childTables...) - } - } - } - - return tables, nil -} - -func (c *connWrapper) GetTables(ctx context.Context, folder string, recursive, excludeSysDirs bool) ( - tables []string, _ error, -) { - absPath := c.normalizePath(folder) - - e, err := c.connector.Scheme().DescribePath(ctx, absPath) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - switch e.Type { - case scheme.EntryTable, scheme.EntryColumnTable: - return []string{e.Name}, err - case scheme.EntryDirectory, scheme.EntryDatabase: - tables, err = c.getTables(ctx, absPath, recursive, excludeSysDirs) - if err != nil { - return nil, xerrors.WithStackTrace(err) - } - - return xslices.Transform(tables, func(tbl string) string { - return strings.TrimPrefix(tbl, absPath+"/") - }), nil - default: - return nil, xerrors.WithStackTrace( - fmt.Errorf("'%s' is not a table or directory (%s)", folder, e.Type.String()), - ) - } -} - -func (c *connWrapper) 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) - } - - return xslices.Transform(d.Indexes, func(idx options.IndexDescription) string { - return idx.Name - }), nil -} - -func (c *connWrapper) 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) - } - - for i := range d.Indexes { - if d.Indexes[i].Name == indexName { - columns = append(columns, d.Indexes[i].IndexColumns...) - } - } - - return xslices.Uniq(columns), nil -} - -func (c *connWrapper) 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) - } - - for i := range d.Columns { - if d.Columns[i].Name == columnName { - return true, nil - } - } - - return false, nil -} - -func (c *connWrapper) 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/xsql.(*connWrapper).IsTableExists"), - tableName, - ) - defer func() { - onDone(tableExists, finalErr) - }() - - tableExists, err := helpers.IsEntryExists(ctx, - c.connector.parent.Scheme(), tableName, - scheme.EntryTable, scheme.EntryColumnTable, - ) - if err != nil { - return false, xerrors.WithStackTrace(err) - } - - return tableExists, nil -} diff --git a/internal/xsql/conn/query/errors.go b/internal/xsql/conn/query/errors.go deleted file mode 100644 index e23313c1e..000000000 --- a/internal/xsql/conn/query/errors.go +++ /dev/null @@ -1,15 +0,0 @@ -package query - -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()) -) diff --git a/internal/xsql/conn/table/errors.go b/internal/xsql/conn/table/errors.go deleted file mode 100644 index 90db8c026..000000000 --- a/internal/xsql/conn/table/errors.go +++ /dev/null @@ -1,15 +0,0 @@ -package table - -import ( - "database/sql/driver" - "errors" - - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" -) - -var ( - ErrUnsupported = driver.ErrSkip - errConnClosedEarly = xerrors.Retryable(errors.New("conn closed early"), xerrors.InvalidObject()) - errNotReadyConn = xerrors.Retryable(errors.New("conn not ready"), xerrors.InvalidObject()) - ErrWrongQueryMode = errors.New("wrong query mode") -) diff --git a/internal/xsql/conn_helpers.go b/internal/xsql/conn_helpers.go new file mode 100644 index 000000000..ccd47b0ef --- /dev/null +++ b/internal/xsql/conn_helpers.go @@ -0,0 +1,275 @@ +package xsql + +import ( + "context" + "database/sql/driver" + "fmt" + "path" + "strings" + "time" + + "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/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" +) + +func (c *Conn) toYdb(sql string, args ...driver.NamedValue) (yql string, _ *params.Params, _ error) { + queryArgs := make([]any, len(args)) + for i := range args { + queryArgs[i] = args[i] + } + + yql, params, err := c.connector.Bindings().ToYdb(sql, queryArgs...) + if err != nil { + return "", nil, xerrors.WithStackTrace(err) + } + + return yql, ¶ms, nil +} + +func (c *Conn) LastUsage() time.Time { + return c.lastUsage.Get() +} + +func (c *Conn) Engine() Engine { + return c.processor +} + +func (c *Conn) GetDatabaseName() string { + return c.connector.Name() +} + +func (c *Conn) normalizePath(tableName string) string { + return c.connector.pathNormalizer.NormalizePath(tableName) +} + +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.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) + } + + return d, nil +} + +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) + } + + for i := range d.Columns { + columns = append(columns, d.Columns[i].Name) + } + + return columns, nil +} + +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) + } + + for i := range d.Columns { + if d.Columns[i].Name == columnName { + return d.Columns[i].Type.Yql(), nil + } + } + + return "", xerrors.WithStackTrace(fmt.Errorf("column '%s' not exist in table '%s'", columnName, tableName)) +} + +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) + } + + return d.PrimaryKey, nil +} + +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) + } + + for _, pkCol := range d.PrimaryKey { + if pkCol == columnName { + return true, nil + } + } + + return false, nil +} + +func (c *Conn) Version(_ context.Context) (_ string, _ error) { + const version = "default" + + return version, nil +} + +func isSysDir(databaseName, dirAbsPath string) bool { + for _, sysDir := range [...]string{ + path.Join(databaseName, ".sys"), + path.Join(databaseName, ".sys_health"), + } { + if strings.HasPrefix(dirAbsPath, sysDir) { + return true + } + } + + return false +} + +func (c *Conn) getTables(ctx context.Context, absPath string, recursive, excludeSysDirs bool) ( + tables []string, _ error, +) { + if excludeSysDirs && isSysDir(c.connector.Name(), absPath) { + return nil, nil + } + + d, err := c.connector.Scheme().ListDirectory(ctx, absPath) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + if !d.IsDirectory() && !d.IsDatabase() { + return nil, xerrors.WithStackTrace(fmt.Errorf("'%s' is not a folder", absPath)) + } + + for i := range d.Children { + switch d.Children[i].Type { + case scheme.EntryTable, scheme.EntryColumnTable: + tables = append(tables, path.Join(absPath, d.Children[i].Name)) + case scheme.EntryDirectory, scheme.EntryDatabase: + if recursive { + childTables, err := c.getTables(ctx, path.Join(absPath, d.Children[i].Name), recursive, excludeSysDirs) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + tables = append(tables, childTables...) + } + } + } + + return tables, nil +} + +func (c *Conn) GetTables(ctx context.Context, folder string, recursive, excludeSysDirs bool) ( + tables []string, _ error, +) { + absPath := c.normalizePath(folder) + + e, err := c.connector.Scheme().DescribePath(ctx, absPath) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + switch e.Type { + case scheme.EntryTable, scheme.EntryColumnTable: + return []string{e.Name}, err + case scheme.EntryDirectory, scheme.EntryDatabase: + tables, err = c.getTables(ctx, absPath, recursive, excludeSysDirs) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + return xslices.Transform(tables, func(tbl string) string { + return strings.TrimPrefix(tbl, absPath+"/") + }), nil + default: + return nil, xerrors.WithStackTrace( + fmt.Errorf("'%s' is not a table or directory (%s)", folder, e.Type.String()), + ) + } +} + +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) + } + + return xslices.Transform(d.Indexes, func(idx options.IndexDescription) string { + return idx.Name + }), nil +} + +func (c *Conn) GetIndexColumns(ctx context.Context, tableName, indexName string) (columns []string, finalErr error) { + tableName = c.normalizePath(tableName) + onDone := trace.DatabaseSQLOnConnGetIndexColumns(c.connector.trace, &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*Conn).GetIndexColumns"), + tableName, indexName, + ) + defer func() { + onDone(columns, finalErr) + }() + d, err := c.tableDescription(ctx, tableName) + if err != nil { + return nil, xerrors.WithStackTrace(err) + } + + for i := range d.Indexes { + if d.Indexes[i].Name == indexName { + columns = append(columns, d.Indexes[i].IndexColumns...) + } + } + + return xslices.Uniq(columns), nil +} + +func (c *Conn) IsColumnExists(ctx context.Context, tableName, columnName string) (columnExists bool, finalErr error) { + tableName = c.normalizePath(tableName) + onDone := trace.DatabaseSQLOnConnIsColumnExists(c.connector.trace, &ctx, + stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql.(*Conn).IsColumnExists"), + tableName, columnName, + ) + defer func() { + onDone(columnExists, finalErr) + }() + d, err := c.tableDescription(ctx, tableName) + if err != nil { + return false, xerrors.WithStackTrace(err) + } + + for i := range d.Columns { + if d.Columns[i].Name == columnName { + return true, nil + } + } + + return false, nil +} + +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/xsql.(*Conn).IsTableExists"), + tableName, + ) + defer func() { + onDone(tableExists, finalErr) + }() + + tableExists, err := helpers.IsEntryExists(ctx, + c.connector.parent.Scheme(), tableName, + scheme.EntryTable, scheme.EntryColumnTable, + ) + if err != nil { + return false, xerrors.WithStackTrace(err) + } + + return tableExists, nil +} diff --git a/internal/xsql/conn_test.go b/internal/xsql/conn_helpers_test.go similarity index 69% rename from internal/xsql/conn_test.go rename to internal/xsql/conn_helpers_test.go index 9d3e1d4d1..0abe6307f 100644 --- a/internal/xsql/conn_test.go +++ b/internal/xsql/conn_helpers_test.go @@ -1,49 +1,65 @@ package xsql -import "context" +import ( + "context" + "database/sql/driver" + "time" +) var ( + _ driver.ConnBeginTx = (*Conn)(nil) + _ driver.NamedValueChecker = (*Conn)(nil) + _ driver.Pinger = (*Conn)(nil) + + _ interface { + Engine() Engine + } = (*Conn)(nil) + + _ interface { + LastUsage() time.Time + } = (*Conn)(nil) + _ 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/xsql/connector.go b/internal/xsql/connector.go index dd279e726..340311b70 100644 --- a/internal/xsql/connector.go +++ b/internal/xsql/connector.go @@ -16,8 +16,8 @@ import ( "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" - connOverQueryServiceClient "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query" - connOverTableServiceClient "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy" + propose "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/propose" "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" @@ -39,14 +39,14 @@ type ( processor Engine - TableOpts []connOverTableServiceClient.Option - QueryOpts []connOverQueryServiceClient.Option + LegacyOpts []legacy.Option + Options []propose.Option disableServerBalancer bool onCLose []func(*Connector) 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 @@ -65,8 +65,8 @@ type ( func (e Engine) String() string { switch e { - case TABLE_SERVICE: - return "TABLE_SERVICE" + case LEGACY: + return "LEGACY" case QUERY_SERVICE: return "QUERY_SERVICE" default: @@ -116,7 +116,7 @@ func (c *Connector) Scheme() scheme.Client { const ( QUERY_SERVICE = iota + 1 //nolint:revive,stylecheck - TABLE_SERVICE //nolint:revive,stylecheck + LEGACY //nolint:revive,stylecheck ) func (c *Connector) Open(name string) (driver.Conn, error) { @@ -133,11 +133,11 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() - conn := &connWrapper{ + conn := &Conn{ processor: QUERY_SERVICE, - cc: connOverQueryServiceClient.New(ctx, c, s, append( - c.QueryOpts, - connOverQueryServiceClient.WithOnClose(func() { + cc: propose.New(ctx, c, s, append( + c.Options, + propose.WithOnClose(func() { c.conns.Delete(id) }))..., ), @@ -150,7 +150,7 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { return conn, nil - case TABLE_SERVICE: + case LEGACY: s, err := c.Table().CreateSession(ctx) //nolint:staticcheck if err != nil { return nil, xerrors.WithStackTrace(err) @@ -158,10 +158,10 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { id := uuid.New() - conn := &connWrapper{ - processor: TABLE_SERVICE, - cc: connOverTableServiceClient.New(ctx, c, s, append(c.TableOpts, - connOverTableServiceClient.WithOnClose(func() { + conn := &Conn{ + processor: LEGACY, + cc: legacy.New(ctx, c, s, append(c.LegacyOpts, + legacy.WithOnClose(func() { c.conns.Delete(id) }))..., ), @@ -210,7 +210,7 @@ func Open(parent ydbDriver, balancer grpc.ClientConnInterface, opts ...Option) ( return QUERY_SERVICE } - return TABLE_SERVICE + return LEGACY }(), clock: clockwork.NewRealClock(), done: make(chan struct{}), @@ -240,7 +240,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/xsql/errors.go b/internal/xsql/errors.go index 252485975..719d62522 100644 --- a/internal/xsql/errors.go +++ b/internal/xsql/errors.go @@ -12,5 +12,5 @@ var ( errDeprecated = driver.ErrSkip errAlreadyClosed = errors.New("already closed") errWrongQueryProcessor = errors.New("wrong query processor") - errNotReadyConn = xerrors.Retryable(errors.New("conn not ready"), xerrors.InvalidObject()) + errNotReadyConn = xerrors.Retryable(errors.New("iface not ready"), xerrors.InvalidObject()) ) diff --git a/internal/xsql/conn/conn.go b/internal/xsql/iface/conn.go similarity index 97% rename from internal/xsql/conn/conn.go rename to internal/xsql/iface/conn.go index a490d8abb..c1a100f82 100644 --- a/internal/xsql/conn/conn.go +++ b/internal/xsql/iface/conn.go @@ -1,4 +1,4 @@ -package conn +package iface import ( "context" diff --git a/internal/xsql/conn/context.go b/internal/xsql/iface/context.go similarity index 95% rename from internal/xsql/conn/context.go rename to internal/xsql/iface/context.go index 76f927199..741c930e0 100644 --- a/internal/xsql/conn/context.go +++ b/internal/xsql/iface/context.go @@ -1,4 +1,4 @@ -package conn +package iface import "context" diff --git a/internal/xsql/conn/tx.go b/internal/xsql/iface/tx.go similarity index 96% rename from internal/xsql/conn/tx.go rename to internal/xsql/iface/tx.go index a9fe25012..d75dd8d83 100644 --- a/internal/xsql/conn/tx.go +++ b/internal/xsql/iface/tx.go @@ -1,4 +1,4 @@ -package conn +package iface import ( "context" diff --git a/internal/xsql/conn/table/badconn/badconn.go b/internal/xsql/legacy/badconn/badconn.go similarity index 100% rename from internal/xsql/conn/table/badconn/badconn.go rename to internal/xsql/legacy/badconn/badconn.go diff --git a/internal/xsql/conn/table/badconn/badconn_test.go b/internal/xsql/legacy/badconn/badconn_test.go similarity index 100% rename from internal/xsql/conn/table/badconn/badconn_test.go rename to internal/xsql/legacy/badconn/badconn_test.go diff --git a/internal/xsql/conn/table/conn.go b/internal/xsql/legacy/conn.go similarity index 95% rename from internal/xsql/conn/table/conn.go rename to internal/xsql/legacy/conn.go index 8713a7fa3..06d6d78d3 100644 --- a/internal/xsql/conn/table/conn.go +++ b/internal/xsql/legacy/conn.go @@ -1,4 +1,4 @@ -package table +package legacy import ( "context" @@ -12,8 +12,8 @@ import ( "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/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy/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" @@ -79,7 +79,7 @@ func (c *Conn) Query(ctx context.Context, sql string, params *params.Params) ( case ScriptingQueryMode: return c.execScriptingQuery(ctx, sql, params) default: - return nil, fmt.Errorf("unsupported query mode '%s' on conn query", queryMode) + return nil, fmt.Errorf("unsupported query mode '%s' on iface query", queryMode) } } @@ -265,7 +265,7 @@ func (c *Conn) ID() string { return c.session.ID() } -func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx conn.Tx, finalErr error) { +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) { @@ -280,7 +280,7 @@ func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx conn return tx, nil } -func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (conn.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/xsql/conn/table/context.go b/internal/xsql/legacy/context.go similarity index 90% rename from internal/xsql/conn/table/context.go rename to internal/xsql/legacy/context.go index 716a5439e..ef2b4289d 100644 --- a/internal/xsql/conn/table/context.go +++ b/internal/xsql/legacy/context.go @@ -1,9 +1,9 @@ -package table +package legacy import ( "context" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" ) @@ -37,7 +37,7 @@ func txControl(ctx context.Context, defaultTxControl *table.TransactionControl) } func (c *Conn) dataQueryOptions(ctx context.Context) []options.ExecuteDataQueryOption { - if conn.IsPreparedStatement(ctx) { + if iface.IsPreparedStatement(ctx) { return append(c.dataOpts, options.WithKeepInCache(true)) } diff --git a/internal/xsql/legacy/errors.go b/internal/xsql/legacy/errors.go new file mode 100644 index 000000000..6190332a3 --- /dev/null +++ b/internal/xsql/legacy/errors.go @@ -0,0 +1,15 @@ +package legacy + +import ( + "database/sql/driver" + "errors" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" +) + +var ( + ErrUnsupported = driver.ErrSkip + errConnClosedEarly = xerrors.Retryable(errors.New("iface closed early"), xerrors.InvalidObject()) + errNotReadyConn = xerrors.Retryable(errors.New("iface not ready"), xerrors.InvalidObject()) + ErrWrongQueryMode = errors.New("wrong query mode") +) diff --git a/internal/xsql/conn/table/isolation.go b/internal/xsql/legacy/isolation.go similarity index 98% rename from internal/xsql/conn/table/isolation.go rename to internal/xsql/legacy/isolation.go index 367c855b9..a254a875c 100644 --- a/internal/xsql/conn/table/isolation.go +++ b/internal/xsql/legacy/isolation.go @@ -1,4 +1,4 @@ -package table +package legacy import ( "database/sql" diff --git a/internal/xsql/conn/table/isolation_test.go b/internal/xsql/legacy/isolation_test.go similarity index 99% rename from internal/xsql/conn/table/isolation_test.go rename to internal/xsql/legacy/isolation_test.go index afb534b72..0fbf30ae8 100644 --- a/internal/xsql/conn/table/isolation_test.go +++ b/internal/xsql/legacy/isolation_test.go @@ -1,4 +1,4 @@ -package table +package legacy import ( "database/sql" diff --git a/internal/xsql/conn/table/mode.go b/internal/xsql/legacy/mode.go similarity index 58% rename from internal/xsql/conn/table/mode.go rename to internal/xsql/legacy/mode.go index 2f4de9ebb..8ecf0e0b4 100644 --- a/internal/xsql/conn/table/mode.go +++ b/internal/xsql/legacy/mode.go @@ -1,4 +1,4 @@ -package table +package legacy import ( "context" @@ -30,20 +30,12 @@ func queryModeFromContext(ctx context.Context, defaultMode QueryMode) QueryMode 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, - } -) +var typeToString = map[QueryMode]string{ + DataQueryMode: "data", + ScanQueryMode: "scan", + SchemeQueryMode: "scheme", + ScriptingQueryMode: "scripting", +} func (t QueryMode) String() string { if s, ok := typeToString[t]; ok { @@ -52,11 +44,3 @@ func (t QueryMode) String() string { 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/xsql/conn/table/options.go b/internal/xsql/legacy/options.go similarity index 98% rename from internal/xsql/conn/table/options.go rename to internal/xsql/legacy/options.go index 784e31ca7..e1ee5604b 100644 --- a/internal/xsql/conn/table/options.go +++ b/internal/xsql/legacy/options.go @@ -1,4 +1,4 @@ -package table +package legacy import ( "slices" diff --git a/internal/xsql/conn/table/rows.go b/internal/xsql/legacy/rows.go similarity index 97% rename from internal/xsql/conn/table/rows.go rename to internal/xsql/legacy/rows.go index 7071ef9da..677d876a4 100644 --- a/internal/xsql/conn/table/rows.go +++ b/internal/xsql/legacy/rows.go @@ -1,4 +1,4 @@ -package table +package legacy import ( "context" @@ -10,7 +10,7 @@ import ( "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/conn/table/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy/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/xsql/conn/table/tx.go b/internal/xsql/legacy/tx.go similarity index 91% rename from internal/xsql/conn/table/tx.go rename to internal/xsql/legacy/tx.go index 762dcdf4e..b5da7d142 100644 --- a/internal/xsql/conn/table/tx.go +++ b/internal/xsql/legacy/tx.go @@ -1,4 +1,4 @@ -package table +package legacy import ( "context" @@ -7,12 +7,12 @@ import ( "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/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/table" ) -var _ conn.Tx = (*transaction)(nil) +var _ iface.Tx = (*transaction)(nil) type transaction struct { conn *Conn @@ -75,7 +75,7 @@ func (tx *transaction) Rollback(ctx context.Context) error { return err } -func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (conn.Tx, error) { +func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (iface.Tx, error) { txc, err := toYDB(txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) diff --git a/internal/xsql/conn/query/tx_fake.go b/internal/xsql/legacy/tx_fake.go similarity index 85% rename from internal/xsql/conn/query/tx_fake.go rename to internal/xsql/legacy/tx_fake.go index 9f55c0f6c..460400a07 100644 --- a/internal/xsql/conn/query/tx_fake.go +++ b/internal/xsql/legacy/tx_fake.go @@ -1,4 +1,4 @@ -package query +package legacy import ( "context" @@ -7,8 +7,8 @@ import ( "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/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy/badconn" ) type txFake struct { @@ -38,7 +38,7 @@ func (t *txFake) ID() string { return tx.FakeTxID } -func beginTxFake(ctx context.Context, c *Conn) conn.Tx { +func beginTxFake(ctx context.Context, c *Conn) iface.Tx { return &txFake{ conn: c, ctx: ctx, diff --git a/internal/xsql/conn/table/valuer.go b/internal/xsql/legacy/valuer.go similarity index 94% rename from internal/xsql/conn/table/valuer.go rename to internal/xsql/legacy/valuer.go index de4253b0f..c5167fb25 100644 --- a/internal/xsql/conn/table/valuer.go +++ b/internal/xsql/legacy/valuer.go @@ -1,4 +1,4 @@ -package table +package legacy import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/scanner" diff --git a/internal/xsql/options.go b/internal/xsql/options.go index c2a813d5a..cd3755cad 100644 --- a/internal/xsql/options.go +++ b/internal/xsql/options.go @@ -4,8 +4,8 @@ import ( "time" "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/propose" "github.com/ydb-platform/ydb-go-sdk/v3/retry/budget" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) @@ -21,9 +21,9 @@ type ( tablePathPrefixOption struct { bind.TablePathPrefix } - tableQueryOptionsOption struct { - tableOps []table.Option - queryOpts []query.Option + legacyOptionsOption struct { + legacyOps []legacy.Option + options []propose.Option } traceDatabaseSQLOption struct { t *trace.DatabaseSQL @@ -93,9 +93,9 @@ func (opt traceDatabaseSQLOption) Apply(c *Connector) error { return nil } -func (opt tableQueryOptionsOption) Apply(c *Connector) error { - c.QueryOpts = append(c.QueryOpts, opt.queryOpts...) - c.TableOpts = append(c.TableOpts, opt.tableOps...) +func (opt legacyOptionsOption) Apply(c *Connector) error { + c.Options = append(c.Options, opt.options...) + c.LegacyOpts = append(c.LegacyOpts, opt.legacyOps...) return nil } @@ -146,26 +146,26 @@ func WithQueryBind(bind bind.Bind) QueryBindOption { } } -func WithDefaultQueryMode(mode table.QueryMode) Option { - return tableQueryOptionsOption{ - tableOps: []table.Option{ - table.WithDefaultQueryMode(mode), +func WithDefaultQueryMode(mode legacy.QueryMode) Option { + return legacyOptionsOption{ + legacyOps: []legacy.Option{ + legacy.WithDefaultQueryMode(mode), }, } } -func WithFakeTx(modes ...table.QueryMode) Option { - return tableQueryOptionsOption{ - tableOps: []table.Option{ - table.WithFakeTxModes(modes...), +func WithFakeTx(modes ...legacy.QueryMode) Option { + return legacyOptionsOption{ + legacyOps: []legacy.Option{ + legacy.WithFakeTxModes(modes...), }, } } func WithIdleThreshold(idleThreshold time.Duration) Option { - return tableQueryOptionsOption{ - tableOps: []table.Option{ - table.WithIdleThreshold(idleThreshold), + return legacyOptionsOption{ + legacyOps: []legacy.Option{ + legacy.WithIdleThreshold(idleThreshold), }, } } @@ -186,22 +186,22 @@ func Merge(opts ...Option) Option { return mergedOptions(opts) } -func WithTableOptions(opts ...table.Option) Option { - return tableQueryOptionsOption{ - tableOps: opts, +func WithTableOptions(opts ...legacy.Option) Option { + return legacyOptionsOption{ + legacyOps: opts, } } -func WithQueryOptions(opts ...query.Option) Option { - return tableQueryOptionsOption{ - queryOpts: opts, +func WithQueryOptions(opts ...propose.Option) Option { + return legacyOptionsOption{ + options: opts, } } -func OverQueryService() Option { - return queryProcessorOption(QUERY_SERVICE) -} +func WithQueryService(b bool) Option { + if b { + return queryProcessorOption(QUERY_SERVICE) + } -func OverTableService() Option { - return queryProcessorOption(TABLE_SERVICE) + return queryProcessorOption(LEGACY) } diff --git a/internal/xsql/conn/query/conn.go b/internal/xsql/propose/conn.go similarity index 96% rename from internal/xsql/conn/query/conn.go rename to internal/xsql/propose/conn.go index 18169044d..cc98f1052 100644 --- a/internal/xsql/conn/query/conn.go +++ b/internal/xsql/propose/conn.go @@ -1,4 +1,4 @@ -package query +package propose import ( "context" @@ -12,7 +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/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" ) type resultNoRows struct{} @@ -114,7 +114,7 @@ func (c *Conn) isReady() bool { return c.session.Status() == session.StatusIdle.String() } -func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx conn.Tx, finalErr error) { +func (c *Conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (tx iface.Tx, finalErr error) { if c.fakeTx { return beginTxFake(ctx, c), nil } @@ -149,7 +149,7 @@ func (c *Conn) Ping(ctx context.Context) (finalErr error) { return err } -func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (conn.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/xsql/propose/errors.go b/internal/xsql/propose/errors.go new file mode 100644 index 000000000..226e68744 --- /dev/null +++ b/internal/xsql/propose/errors.go @@ -0,0 +1,15 @@ +package propose + +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("iface closed early"), xerrors.InvalidObject()) + errNotReadyConn = xerrors.Retryable(errors.New("iface not ready"), xerrors.InvalidObject()) +) diff --git a/internal/xsql/conn/query/isolation.go b/internal/xsql/propose/isolation.go similarity index 97% rename from internal/xsql/conn/query/isolation.go rename to internal/xsql/propose/isolation.go index 56bcf57e4..6a8b5666a 100644 --- a/internal/xsql/conn/query/isolation.go +++ b/internal/xsql/propose/isolation.go @@ -1,4 +1,4 @@ -package query +package propose import ( "database/sql" diff --git a/internal/xsql/conn/query/options.go b/internal/xsql/propose/options.go similarity index 93% rename from internal/xsql/conn/query/options.go rename to internal/xsql/propose/options.go index 2c3a1a94d..7368b385b 100644 --- a/internal/xsql/conn/query/options.go +++ b/internal/xsql/propose/options.go @@ -1,4 +1,4 @@ -package query +package propose type Option func(c *Conn) diff --git a/internal/xsql/conn/query/rows.go b/internal/xsql/propose/rows.go similarity index 99% rename from internal/xsql/conn/query/rows.go rename to internal/xsql/propose/rows.go index faeffedce..85d77f279 100644 --- a/internal/xsql/conn/query/rows.go +++ b/internal/xsql/propose/rows.go @@ -1,4 +1,4 @@ -package query +package propose import ( "context" diff --git a/internal/xsql/conn/query/tx.go b/internal/xsql/propose/tx.go similarity index 94% rename from internal/xsql/conn/query/tx.go rename to internal/xsql/propose/tx.go index 6cb2ce1f6..2118e550e 100644 --- a/internal/xsql/conn/query/tx.go +++ b/internal/xsql/propose/tx.go @@ -1,4 +1,4 @@ -package query +package propose import ( "context" @@ -7,7 +7,7 @@ import ( "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/conn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" "github.com/ydb-platform/ydb-go-sdk/v3/query" ) @@ -43,7 +43,7 @@ func (tx *transaction) Query(ctx context.Context, sql string, params *params.Par }, nil } -func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (conn.Tx, error) { +func beginTx(ctx context.Context, c *Conn, txOptions driver.TxOptions) (iface.Tx, error) { txc, err := toYDB(txOptions) if err != nil { return nil, xerrors.WithStackTrace(err) diff --git a/internal/xsql/conn/table/tx_fake.go b/internal/xsql/propose/tx_fake.go similarity index 85% rename from internal/xsql/conn/table/tx_fake.go rename to internal/xsql/propose/tx_fake.go index 505ca7919..679cc7d08 100644 --- a/internal/xsql/conn/table/tx_fake.go +++ b/internal/xsql/propose/tx_fake.go @@ -1,4 +1,4 @@ -package table +package propose import ( "context" @@ -7,8 +7,8 @@ import ( "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/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy/badconn" ) type txFake struct { @@ -38,7 +38,7 @@ func (t *txFake) ID() string { return tx.FakeTxID } -func beginTxFake(ctx context.Context, c *Conn) conn.Tx { +func beginTxFake(ctx context.Context, c *Conn) iface.Tx { return &txFake{ conn: c, ctx: ctx, diff --git a/internal/xsql/rows.go b/internal/xsql/rows.go new file mode 100644 index 000000000..1b42dc950 --- /dev/null +++ b/internal/xsql/rows.go @@ -0,0 +1,51 @@ +package xsql + +import ( + "database/sql" + "database/sql/driver" + "io" +) + +type singleRow struct { + values []sql.NamedArg + readAll bool +} + +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) + } + + 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 +} diff --git a/internal/xsql/stmt.go b/internal/xsql/stmt.go index 392eaabde..4afe2d4d5 100644 --- a/internal/xsql/stmt.go +++ b/internal/xsql/stmt.go @@ -10,8 +10,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) -type stmt struct { - conn *connWrapper +type Stmt struct { + conn *Conn processor interface { Exec(ctx context.Context, sql string, params *params.Params) (driver.Result, error) Query(ctx context.Context, sql string, params *params.Params) (driver.RowsNextResultSet, error) @@ -21,14 +21,14 @@ type stmt struct { } var ( - _ driver.Stmt = &stmt{} - _ driver.StmtQueryContext = &stmt{} - _ driver.StmtExecContext = &stmt{} + _ driver.Stmt = &Stmt{} + _ driver.StmtQueryContext = &Stmt{} + _ driver.StmtExecContext = &Stmt{} ) -func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ driver.Rows, finalErr error) { +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/xsql.(*stmt).QueryContext"), + stack.FunctionID("", stack.Package("database/sql")), stmt.ctx, stmt.sql, ) defer func() { @@ -47,9 +47,9 @@ func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ return stmt.processor.Query(ctx, sql, params) } -func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ driver.Result, finalErr error) { +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/xsql.(*stmt).ExecContext"), + stack.FunctionID("", stack.Package("database/sql")), stmt.ctx, stmt.sql, ) defer func() { @@ -68,15 +68,15 @@ func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ return stmt.processor.Exec(ctx, sql, params) } -func (stmt *stmt) NumInput() int { +func (stmt *Stmt) NumInput() int { return -1 } -func (stmt *stmt) Close() (finalErr error) { +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/xsql.(*stmt).Close"), + stack.FunctionID("", stack.Package("database/sql")), ) ) defer func() { @@ -86,10 +86,10 @@ func (stmt *stmt) Close() (finalErr error) { return nil } -func (stmt *stmt) Exec([]driver.Value) (driver.Result, error) { +func (stmt *Stmt) Exec([]driver.Value) (driver.Result, error) { return nil, errDeprecated } -func (stmt *stmt) Query([]driver.Value) (driver.Rows, error) { +func (stmt *Stmt) Query([]driver.Value) (driver.Rows, error) { return nil, errDeprecated } diff --git a/internal/xsql/tx.go b/internal/xsql/tx.go index 9652da89d..35a395e78 100644 --- a/internal/xsql/tx.go +++ b/internal/xsql/tx.go @@ -6,28 +6,28 @@ import ( "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/conn" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/iface" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy/badconn" "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) -type txWrapper struct { - conn *connWrapper - tx conn.Tx +type Tx struct { + conn *Conn + tx iface.Tx ctx context.Context //nolint:containedctx } -func (tx *txWrapper) ID() string { +func (tx *Tx) ID() string { return tx.tx.ID() } var ( - _ driver.Tx = &txWrapper{} - _ driver.ExecerContext = &txWrapper{} - _ driver.QueryerContext = &txWrapper{} + _ driver.Tx = &Tx{} + _ driver.ExecerContext = &Tx{} + _ driver.QueryerContext = &Tx{} ) -func (tx *txWrapper) Commit() (finalErr error) { +func (tx *Tx) Commit() (finalErr error) { defer func() { tx.conn.currentTx = nil }() @@ -35,7 +35,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/xsql.(*txWrapper).Commit"), + stack.FunctionID("", stack.Package("database/sql")), tx, ) ) @@ -50,7 +50,7 @@ func (tx *txWrapper) Commit() (finalErr error) { return nil } -func (tx *txWrapper) Rollback() (finalErr error) { +func (tx *Tx) Rollback() (finalErr error) { defer func() { tx.conn.currentTx = nil }() @@ -58,7 +58,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/xsql.(*txWrapper).Rollback"), + stack.FunctionID("", stack.Package("database/sql")), tx, ) ) @@ -74,11 +74,11 @@ func (tx *txWrapper) Rollback() (finalErr error) { return err } -func (tx *txWrapper) QueryContext(ctx context.Context, sql string, args []driver.NamedValue) ( +func (tx *Tx) QueryContext(ctx context.Context, sql 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/xsql.(*txWrapper).QueryContext"), + stack.FunctionID("", stack.Package("database/sql")), tx.ctx, tx, sql, ) defer func() { @@ -107,11 +107,11 @@ func (tx *txWrapper) QueryContext(ctx context.Context, sql string, args []driver return rows, nil } -func (tx *txWrapper) ExecContext(ctx context.Context, sql string, args []driver.NamedValue) ( +func (tx *Tx) ExecContext(ctx context.Context, sql 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/xsql.(*txWrapper).ExecContext"), + stack.FunctionID("", stack.Package("database/sql")), tx.ctx, tx, sql, ) defer func() { @@ -131,9 +131,9 @@ func (tx *txWrapper) ExecContext(ctx context.Context, sql string, args []driver. return result, nil } -func (tx *txWrapper) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, finalErr error) { +func (tx *Tx) 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/xsql.(*txWrapper).PrepareContext"), + stack.FunctionID("", stack.Package("database/sql")), tx.ctx, tx, sql, ) defer func() { @@ -143,7 +143,7 @@ func (tx *txWrapper) PrepareContext(ctx context.Context, sql string) (_ driver.S return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn)) } - return &stmt{ + return &Stmt{ conn: tx.conn, processor: tx.tx, ctx: ctx, diff --git a/internal/xsql/unwrap.go b/internal/xsql/unwrap.go index 1f483b090..7f0247a2b 100644 --- a/internal/xsql/unwrap.go +++ b/internal/xsql/unwrap.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy/badconn" ) func Unwrap[T *sql.DB | *sql.Conn](v T) (connector *Connector, _ error) { @@ -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/retry/errors.go b/retry/errors.go index 22ea2a465..90617ba75 100644 --- a/retry/errors.go +++ b/retry/errors.go @@ -2,7 +2,7 @@ package retry import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy/badconn" ) func unwrapErrBadConn(err error) error { diff --git a/retry/sql_test.go b/retry/sql_test.go index 9c76b40ff..4f42d06dd 100644 --- a/retry/sql_test.go +++ b/retry/sql_test.go @@ -13,7 +13,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/backoff" "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/conn/table/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy/badconn" ) type mockConnector struct { diff --git a/spans/helpers.go b/spans/helpers.go index eb96713a1..6e7d88922 100644 --- a/spans/helpers.go +++ b/spans/helpers.go @@ -61,7 +61,7 @@ func logToParentSpan( cfg Adapter, ctx context.Context, //nolint:revive msg string, - fields ...KeyValue, //nolint:unparam + fields ...KeyValue, ) { parent := cfg.SpanFromContext(ctx) parent.Log(msg, fields...) @@ -71,7 +71,7 @@ func logToParentSpanError( cfg Adapter, ctx context.Context, //nolint:revive err error, - fields ...KeyValue, //nolint:unparam + fields ...KeyValue, ) { parent := cfg.SpanFromContext(ctx) logError(parent, err, fields...) diff --git a/spans/sql.go b/spans/sql.go index 5135c42a1..1c885c5af 100644 --- a/spans/sql.go +++ b/spans/sql.go @@ -2,6 +2,7 @@ package spans import ( "context" + "time" "github.com/ydb-platform/ydb-go-sdk/v3/internal/kv" "github.com/ydb-platform/ydb-go-sdk/v3/trace" @@ -24,7 +25,7 @@ func isStmtCall(ctx context.Context) bool { // databaseSQL makes trace.DatabaseSQL with logging events from details // //nolint:funlen -func databaseSQL(adapter Adapter) (t trace.DatabaseSQL) { +func databaseSQL(adapter Adapter) trace.DatabaseSQL { childSpanWithReplaceCtx := func( ctx *context.Context, operationName string, @@ -32,285 +33,431 @@ func databaseSQL(adapter Adapter) (t trace.DatabaseSQL) { ) (s Span) { return childSpanWithReplaceCtx(adapter, ctx, operationName, fields...) } - t.OnConnectorConnect = func( - info trace.DatabaseSQLConnectorConnectStartInfo, - ) func( - trace.DatabaseSQLConnectorConnectDoneInfo, - ) { - if adapter.Details()&trace.DatabaseSQLConnectorEvents != 0 { - start := childSpanWithReplaceCtx(info.Context, - info.Call.String(), - ) - - return func(info trace.DatabaseSQLConnectorConnectDoneInfo) { - finish( - start, - info.Error, + + return trace.DatabaseSQL{ + OnConnectorConnect: func( + info trace.DatabaseSQLConnectorConnectStartInfo, + ) func( + trace.DatabaseSQLConnectorConnectDoneInfo, + ) { + if adapter.Details()&trace.DatabaseSQLConnectorEvents != 0 { + start := childSpanWithReplaceCtx(info.Context, + info.Call.String(), ) + + return func(info trace.DatabaseSQLConnectorConnectDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnConnPing = func(info trace.DatabaseSQLConnPingStartInfo) func(trace.DatabaseSQLConnPingDoneInfo) { - if adapter.Details()&trace.DatabaseSQLConnEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - ) - - return func(info trace.DatabaseSQLConnPingDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnConnPing: func(info trace.DatabaseSQLConnPingStartInfo) func(trace.DatabaseSQLConnPingDoneInfo) { + if adapter.Details()&trace.DatabaseSQLConnEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), ) + + return func(info trace.DatabaseSQLConnPingDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnConnPrepare = func(info trace.DatabaseSQLConnPrepareStartInfo) func(trace.DatabaseSQLConnPrepareDoneInfo) { - if adapter.Details()&trace.DatabaseSQLConnEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("query", info.Query), - ) - - return func(info trace.DatabaseSQLConnPrepareDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnConnPrepare: func(info trace.DatabaseSQLConnPrepareStartInfo) func(trace.DatabaseSQLConnPrepareDoneInfo) { + if adapter.Details()&trace.DatabaseSQLConnEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + kv.String("query", info.Query), ) + + return func(info trace.DatabaseSQLConnPrepareDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnConnExec = func(info trace.DatabaseSQLConnExecStartInfo) func(trace.DatabaseSQLConnExecDoneInfo) { - if adapter.Details()&trace.DatabaseSQLConnEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("query", info.Query), - kv.String("query_mode", info.Mode), - kv.Bool("idempotent", info.Idempotent), - ) - - return func(info trace.DatabaseSQLConnExecDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnConnExec: func(info trace.DatabaseSQLConnExecStartInfo) func(trace.DatabaseSQLConnExecDoneInfo) { + if adapter.Details()&trace.DatabaseSQLConnEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + kv.String("query", info.Query), + kv.String("query_mode", info.Mode), + kv.Bool("idempotent", info.Idempotent), ) + + return func(info trace.DatabaseSQLConnExecDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnConnQuery = func(info trace.DatabaseSQLConnQueryStartInfo) func(trace.DatabaseSQLConnQueryDoneInfo) { - if adapter.Details()&trace.DatabaseSQLConnEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("query", info.Query), - kv.String("query_mode", info.Mode), - kv.Bool("idempotent", info.Idempotent), - ) - - return func(info trace.DatabaseSQLConnQueryDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnConnQuery: func(info trace.DatabaseSQLConnQueryStartInfo) func(trace.DatabaseSQLConnQueryDoneInfo) { + if adapter.Details()&trace.DatabaseSQLConnEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + kv.String("query", info.Query), + kv.String("query_mode", info.Mode), + kv.Bool("idempotent", info.Idempotent), ) + + return func(info trace.DatabaseSQLConnQueryDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnConnIsTableExists = func(info trace.DatabaseSQLConnIsTableExistsStartInfo) func( - trace.DatabaseSQLConnIsTableExistsDoneInfo, - ) { - if adapter.Details()&trace.DatabaseSQLConnEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("table_name", info.TableName), - ) - - return func(info trace.DatabaseSQLConnIsTableExistsDoneInfo) { - finish( - start, - info.Error, - kv.Bool("exists", info.Exists), + return nil + }, + OnConnIsTableExists: func(info trace.DatabaseSQLConnIsTableExistsStartInfo) func( + trace.DatabaseSQLConnIsTableExistsDoneInfo, + ) { + if adapter.Details()&trace.DatabaseSQLConnEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + kv.String("table_name", info.TableName), ) + + return func(info trace.DatabaseSQLConnIsTableExistsDoneInfo) { + finish( + start, + info.Error, + kv.Bool("exists", info.Exists), + ) + } } - } - return nil - } - t.OnConnBegin = func(info trace.DatabaseSQLConnBeginStartInfo) func(trace.DatabaseSQLConnBeginDoneInfo) { - if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - ) - - return func(info trace.DatabaseSQLConnBeginDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnConnBegin: func(info trace.DatabaseSQLConnBeginStartInfo) func(trace.DatabaseSQLConnBeginDoneInfo) { + if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + ) + + return func(info trace.DatabaseSQLConnBeginDoneInfo) { + finish( + start, + info.Error, + kv.String("transaction_id", safeID(info.Tx)), + ) + } + } + + return nil + }, + OnConnBeginTx: func(info trace.DatabaseSQLConnBeginTxStartInfo) func(trace.DatabaseSQLConnBeginTxDoneInfo) { + if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + ) + + return func(info trace.DatabaseSQLConnBeginTxDoneInfo) { + finish( + start, + info.Error, + kv.String("transaction_id", safeID(info.Tx)), + ) + } + } + + return nil + }, + OnTxRollback: func(info trace.DatabaseSQLTxRollbackStartInfo) func(trace.DatabaseSQLTxRollbackDoneInfo) { + if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), kv.String("transaction_id", safeID(info.Tx)), ) + + return func(info trace.DatabaseSQLTxRollbackDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnTxRollback = func(info trace.DatabaseSQLTxRollbackStartInfo) func(trace.DatabaseSQLTxRollbackDoneInfo) { - if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("transaction_id", safeID(info.Tx)), - ) - - return func(info trace.DatabaseSQLTxRollbackDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnTxCommit: func(info trace.DatabaseSQLTxCommitStartInfo) func(trace.DatabaseSQLTxCommitDoneInfo) { + if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + kv.String("transaction_id", safeID(info.Tx)), ) + + return func(info trace.DatabaseSQLTxCommitDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnTxCommit = func(info trace.DatabaseSQLTxCommitStartInfo) func(trace.DatabaseSQLTxCommitDoneInfo) { - if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("transaction_id", safeID(info.Tx)), - ) - - return func(info trace.DatabaseSQLTxCommitDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnTxExec: func(info trace.DatabaseSQLTxExecStartInfo) func(trace.DatabaseSQLTxExecDoneInfo) { + if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + kv.String("query", info.Query), + kv.String("transaction_id", safeID(info.Tx)), ) + + if !isStmtCall(*info.Context) { + start.Link(adapter.SpanFromContext(info.TxContext)) + } + + return func(info trace.DatabaseSQLTxExecDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnTxExec = func(info trace.DatabaseSQLTxExecStartInfo) func(trace.DatabaseSQLTxExecDoneInfo) { - if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("query", info.Query), - kv.String("transaction_id", safeID(info.Tx)), - ) - - if !isStmtCall(*info.Context) { - start.Link(adapter.SpanFromContext(info.TxContext)) + return nil + }, + OnTxQuery: func(info trace.DatabaseSQLTxQueryStartInfo) func(trace.DatabaseSQLTxQueryDoneInfo) { + if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + kv.String("query", info.Query), + kv.String("transaction_id", safeID(info.Tx)), + ) + + if !isStmtCall(*info.Context) { + start.Link(adapter.SpanFromContext(info.TxContext)) + } + + return func(info trace.DatabaseSQLTxQueryDoneInfo) { + finish( + start, + info.Error, + ) + } } - return func(info trace.DatabaseSQLTxExecDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnTxPrepare: func(info trace.DatabaseSQLTxPrepareStartInfo) func(trace.DatabaseSQLTxPrepareDoneInfo) { + if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + kv.String("query", info.Query), + kv.String("transaction_id", safeID(info.Tx)), ) + + return func(info trace.DatabaseSQLTxPrepareDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnTxQuery = func(info trace.DatabaseSQLTxQueryStartInfo) func(trace.DatabaseSQLTxQueryDoneInfo) { - if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("query", info.Query), - kv.String("transaction_id", safeID(info.Tx)), - ) - - if !isStmtCall(*info.Context) { - start.Link(adapter.SpanFromContext(info.TxContext)) + return nil + }, + OnStmtExec: func(info trace.DatabaseSQLStmtExecStartInfo) func(trace.DatabaseSQLStmtExecDoneInfo) { + if adapter.Details()&trace.DatabaseSQLStmtEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + kv.String("query", info.Query), + ) + + start.Link(adapter.SpanFromContext(info.StmtContext)) + + *info.Context = markStmtCall(*info.Context) + + return func(info trace.DatabaseSQLStmtExecDoneInfo) { + finish( + start, + info.Error, + ) + } } - return func(info trace.DatabaseSQLTxQueryDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnStmtQuery: func(info trace.DatabaseSQLStmtQueryStartInfo) func(trace.DatabaseSQLStmtQueryDoneInfo) { + if adapter.Details()&trace.DatabaseSQLStmtEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + kv.String("query", info.Query), ) + + start.Link(adapter.SpanFromContext(info.StmtContext)) + + *info.Context = markStmtCall(*info.Context) + + return func(info trace.DatabaseSQLStmtQueryDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnTxPrepare = func(info trace.DatabaseSQLTxPrepareStartInfo) func(trace.DatabaseSQLTxPrepareDoneInfo) { - if adapter.Details()&trace.DatabaseSQLTxEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("query", info.Query), - kv.String("transaction_id", safeID(info.Tx)), - ) - - return func(info trace.DatabaseSQLTxPrepareDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnConnClose: func(info trace.DatabaseSQLConnCloseStartInfo) func(trace.DatabaseSQLConnCloseDoneInfo) { + if adapter.Details()&trace.DatabaseSQLStmtEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), ) + + *info.Context = markStmtCall(*info.Context) + + return func(info trace.DatabaseSQLConnCloseDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } - t.OnStmtExec = func(info trace.DatabaseSQLStmtExecStartInfo) func(trace.DatabaseSQLStmtExecDoneInfo) { - if adapter.Details()&trace.DatabaseSQLStmtEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("query", info.Query), - ) - - start.Link(adapter.SpanFromContext(info.StmtContext)) - - *info.Context = markStmtCall(*info.Context) - - return func(info trace.DatabaseSQLStmtExecDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnConnCheckNamedValue: func(info trace.DatabaseSQLConnCheckNamedValueStartInfo) func( + trace.DatabaseSQLConnCheckNamedValueDoneInfo, + ) { + if adapter.Details()&trace.DatabaseSQLStmtEvents != 0 { + var ( + start = time.Now() + ctx = *info.Context + call = info.Call + value = info.Value ) + + return func(info trace.DatabaseSQLConnCheckNamedValueDoneInfo) { + if info.Error != nil { + logToParentSpanError(adapter, ctx, info.Error, + kv.Any("value", value), + kv.Latency(start), + ) + } else { + logToParentSpan(adapter, ctx, call.String(), + kv.Any("value", value), + kv.Latency(start), + ) + } + } } - } - return nil - } - t.OnStmtQuery = func(info trace.DatabaseSQLStmtQueryStartInfo) func(trace.DatabaseSQLStmtQueryDoneInfo) { - if adapter.Details()&trace.DatabaseSQLStmtEvents != 0 { - start := childSpanWithReplaceCtx( - info.Context, - info.Call.String(), - kv.String("query", info.Query), - ) - - start.Link(adapter.SpanFromContext(info.StmtContext)) - - *info.Context = markStmtCall(*info.Context) - - return func(info trace.DatabaseSQLStmtQueryDoneInfo) { - finish( - start, - info.Error, + return nil + }, + OnConnIsColumnExists: func(info trace.DatabaseSQLConnIsColumnExistsStartInfo) func( + trace.DatabaseSQLConnIsColumnExistsDoneInfo, + ) { + if adapter.Details()&trace.DatabaseSQLStmtEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), ) + + return func(info trace.DatabaseSQLConnIsColumnExistsDoneInfo) { + finish( + start, + info.Error, + ) + } } - } - return nil - } + return nil + }, + OnConnGetIndexColumns: func(info trace.DatabaseSQLConnGetIndexColumnsStartInfo) func( + trace.DatabaseSQLConnGetIndexColumnsDoneInfo, + ) { + if adapter.Details()&trace.DatabaseSQLStmtEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + ) + + return func(info trace.DatabaseSQLConnGetIndexColumnsDoneInfo) { + finish( + start, + info.Error, + ) + } + } + + return nil + }, + OnStmtClose: func(info trace.DatabaseSQLStmtCloseStartInfo) func(trace.DatabaseSQLStmtCloseDoneInfo) { + if adapter.Details()&trace.DatabaseSQLStmtEvents != 0 { + start := childSpanWithReplaceCtx( + info.StmtContext, + info.Call.String(), + ) + + start.Link(adapter.SpanFromContext(*info.StmtContext)) - return t + *info.StmtContext = markStmtCall(*info.StmtContext) + + return func(info trace.DatabaseSQLStmtCloseDoneInfo) { + finish( + start, + info.Error, + ) + } + } + + return nil + }, + OnDoTx: func(info trace.DatabaseSQLDoTxStartInfo) func(trace.DatabaseSQLDoTxIntermediateInfo) func( + trace.DatabaseSQLDoTxDoneInfo, + ) { + if adapter.Details()&trace.DatabaseSQLStmtEvents != 0 { + start := childSpanWithReplaceCtx( + info.Context, + info.Call.String(), + ) + + return func(info trace.DatabaseSQLDoTxIntermediateInfo) func(trace.DatabaseSQLDoTxDoneInfo) { + return func(info trace.DatabaseSQLDoTxDoneInfo) { + finish( + start, + info.Error, + ) + } + } + } + + return nil + }, + } } diff --git a/sql.go b/sql.go index ecf0d3af9..51f256b01 100644 --- a/sql.go +++ b/sql.go @@ -9,8 +9,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/bind" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql" - connOverQueryServiceClient "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/query" - connOverTableServiceClient "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/conn/table" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/propose" "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" @@ -82,7 +82,7 @@ func (d *sqlDriver) detach(c *xsql.Connector) { type QueryMode int const ( - _ = QueryMode(iota) + unknownQueryMode = QueryMode(iota) DataQueryMode ExplainQueryMode ScanQueryMode @@ -99,20 +99,20 @@ func WithQueryMode(ctx context.Context, mode QueryMode) context.Context { case ExplainQueryMode: return xsql.WithExplain(ctx) case DataQueryMode: - return connOverTableServiceClient.WithQueryMode(ctx, connOverTableServiceClient.DataQueryMode) + return legacy.WithQueryMode(ctx, legacy.DataQueryMode) case ScanQueryMode: - return connOverTableServiceClient.WithQueryMode(ctx, connOverTableServiceClient.ScanQueryMode) + return legacy.WithQueryMode(ctx, legacy.ScanQueryMode) case SchemeQueryMode: - return connOverTableServiceClient.WithQueryMode(ctx, connOverTableServiceClient.SchemeQueryMode) + return legacy.WithQueryMode(ctx, legacy.SchemeQueryMode) case ScriptingQueryMode: - return connOverTableServiceClient.WithQueryMode(ctx, connOverTableServiceClient.ScriptingQueryMode) + return legacy.WithQueryMode(ctx, legacy.ScriptingQueryMode) default: return ctx } } func WithTxControl(ctx context.Context, txc *table.TransactionControl) context.Context { - return connOverTableServiceClient.WithTxControl(ctx, txc) + return legacy.WithTxControl(ctx, txc) } type ConnectorOption = xsql.Option @@ -122,31 +122,31 @@ type QueryBindConnectorOption interface { bind.Bind } -func modeToMode(mode QueryMode) connOverTableServiceClient.QueryMode { +func modeToMode(mode QueryMode) legacy.QueryMode { switch mode { case ScanQueryMode: - return connOverTableServiceClient.ScanQueryMode + return legacy.ScanQueryMode case SchemeQueryMode: - return connOverTableServiceClient.SchemeQueryMode + return legacy.SchemeQueryMode case ScriptingQueryMode: - return connOverTableServiceClient.ScriptingQueryMode + return legacy.ScriptingQueryMode default: - return connOverTableServiceClient.DataQueryMode + return legacy.DataQueryMode } } func WithDefaultQueryMode(mode QueryMode) ConnectorOption { return xsql.WithTableOptions( - connOverTableServiceClient.WithDefaultQueryMode(modeToMode(mode)), + legacy.WithDefaultQueryMode(modeToMode(mode)), ) } -// OverQueryService is an experimental flag for create database/sql driver over query service client +// WithQueryService is an experimental flag for create database/sql driver over query service client // // By default database/sql driver works over table service client -// Default will be changed to `OverQueryService` after March 2025 -func OverQueryService() ConnectorOption { - return xsql.OverQueryService() +// Default will be changed to `WithQueryService` after March 2025 +func WithQueryService(b bool) ConnectorOption { + return xsql.WithQueryService(b) } func WithFakeTx(modes ...QueryMode) ConnectorOption { @@ -156,31 +156,31 @@ func WithFakeTx(modes ...QueryMode) ConnectorOption { switch mode { case DataQueryMode: opts = append(opts, - xsql.WithTableOptions(connOverTableServiceClient.WithFakeTxModes( - connOverTableServiceClient.DataQueryMode, + xsql.WithTableOptions(legacy.WithFakeTxModes( + legacy.DataQueryMode, )), ) case ScanQueryMode: opts = append(opts, - xsql.WithTableOptions(connOverTableServiceClient.WithFakeTxModes( - connOverTableServiceClient.ScanQueryMode, + xsql.WithTableOptions(legacy.WithFakeTxModes( + legacy.ScanQueryMode, )), ) case SchemeQueryMode: opts = append(opts, - xsql.WithTableOptions(connOverTableServiceClient.WithFakeTxModes( - connOverTableServiceClient.SchemeQueryMode, + xsql.WithTableOptions(legacy.WithFakeTxModes( + legacy.SchemeQueryMode, )), ) case ScriptingQueryMode: opts = append(opts, - xsql.WithTableOptions(connOverTableServiceClient.WithFakeTxModes( - connOverTableServiceClient.DataQueryMode, + xsql.WithTableOptions(legacy.WithFakeTxModes( + legacy.DataQueryMode, )), ) case QueryExecuteQueryMode: opts = append(opts, - xsql.WithQueryOptions(connOverQueryServiceClient.WithFakeTx()), + xsql.WithQueryOptions(propose.WithFakeTx()), ) default: } @@ -206,15 +206,15 @@ func WithNumericArgs() QueryBindConnectorOption { } func WithDefaultTxControl(txControl *table.TransactionControl) ConnectorOption { - return xsql.WithTableOptions(connOverTableServiceClient.WithDefaultTxControl(txControl)) + return xsql.WithTableOptions(legacy.WithDefaultTxControl(txControl)) } func WithDefaultDataQueryOptions(opts ...options.ExecuteDataQueryOption) ConnectorOption { - return xsql.WithTableOptions(connOverTableServiceClient.WithDataOpts(opts...)) + return xsql.WithTableOptions(legacy.WithDataOpts(opts...)) } func WithDefaultScanQueryOptions(opts ...options.ExecuteScanQueryOption) ConnectorOption { - return xsql.WithTableOptions(connOverTableServiceClient.WithScanOpts(opts...)) + return xsql.WithTableOptions(legacy.WithScanOpts(opts...)) } func WithDatabaseSQLTrace( diff --git a/tests/integration/database_sql_regression_test.go b/tests/integration/database_sql_regression_test.go index 3cd0dc646..cb221643f 100644 --- a/tests/integration/database_sql_regression_test.go +++ b/tests/integration/database_sql_regression_test.go @@ -20,7 +20,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3" "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/conn/table/badconn" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy/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" @@ -236,7 +236,7 @@ func TestUUIDSerializationDatabaseSQLIssue1501(t *testing.T) { err := row.Scan(&res) switch driverEngine(db) { - case xsql.TABLE_SERVICE: + case xsql.LEGACY: require.Error(t, err) case xsql.QUERY_SERVICE: require.NoError(t, err) @@ -263,7 +263,7 @@ func TestUUIDSerializationDatabaseSQLIssue1501(t *testing.T) { err := row.Scan(&res) switch driverEngine(db) { - case xsql.TABLE_SERVICE: + case xsql.LEGACY: require.NoError(t, err) resUUID := uuid.UUID(res.AsBytesArray()) require.Equal(t, expectedResultWithBug, resUUID.String()) @@ -352,7 +352,7 @@ func TestUUIDSerializationDatabaseSQLIssue1501(t *testing.T) { var resBytes types.UUIDBytesWithIssue1501Type err := row.Scan(&resBytes) switch driverEngine(db) { - case xsql.TABLE_SERVICE: + case xsql.LEGACY: require.NoError(t, err) resUUID := uuid.UUID(resBytes.AsBytesArray()) require.Equal(t, id, resUUID) @@ -419,7 +419,7 @@ func TestUUIDSerializationDatabaseSQLIssue1501(t *testing.T) { err := row.Scan(&resFromDB) switch driverEngine(db) { - case xsql.TABLE_SERVICE: + case xsql.LEGACY: require.NoError(t, err) resUUID := resFromDB.PublicRevertReorderForIssue1501() resString := strings.ToUpper(resUUID.String()) diff --git a/tests/integration/database_sql_with_tx_control_test.go b/tests/integration/database_sql_with_tx_control_test.go index 07d9b7473..eab208c43 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/xsql/conn/table" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsql/legacy" "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" @@ -37,7 +37,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { var hookCalled bool require.NoError(t, retry.Do( ydb.WithTxControl( - tableSql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { + legacy.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { hookCalled = true require.Equal(t, table.SerializableReadWriteTxControl().Desc(), txControl.Desc()) }), @@ -55,7 +55,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { var hookCalled bool require.NoError(t, retry.Do( ydb.WithTxControl( - tableSql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { + legacy.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { hookCalled = true require.Equal(t, table.SerializableReadWriteTxControl().Desc(), txControl.Desc()) }), @@ -73,7 +73,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { var hookCalled bool require.NoError(t, retry.Do( ydb.WithTxControl( - tableSql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { + legacy.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { hookCalled = true require.Equal(t, table.SnapshotReadOnlyTxControl().Desc(), txControl.Desc()) }), @@ -91,7 +91,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { var hookCalled bool require.NoError(t, retry.Do( ydb.WithTxControl( - tableSql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { + legacy.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { hookCalled = true require.Equal(t, table.StaleReadOnlyTxControl().Desc(), txControl.Desc()) }), @@ -109,7 +109,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { var hookCalled bool require.NoError(t, retry.Do( ydb.WithTxControl( - tableSql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { + legacy.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { hookCalled = true require.Equal(t, table.OnlineReadOnlyTxControl().Desc(), txControl.Desc()) }), @@ -127,7 +127,7 @@ func TestDatabaseSqlWithTxControl(t *testing.T) { var hookCalled bool require.NoError(t, retry.Do( ydb.WithTxControl( - tableSql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { + legacy.WithTxControlHook(ctx, func(txControl *table.TransactionControl) { hookCalled = true require.Equal(t, table.OnlineReadOnlyTxControl(table.WithInconsistentReads()).Desc(), txControl.Desc()) }), diff --git a/tests/integration/table_truncated_err_test.go b/tests/integration/table_truncated_err_test.go index 93d7986d6..be1e57c4b 100644 --- a/tests/integration/table_truncated_err_test.go +++ b/tests/integration/table_truncated_err_test.go @@ -135,7 +135,7 @@ func TestIssue798TruncatedError(t *testing.T) { return rows.Err() }, retry.WithIdempotent(true)) switch driverEngine(db) { - case xsql.TABLE_SERVICE: + case xsql.LEGACY: scope.Require.ErrorIs(err, result.ErrTruncated) case xsql.QUERY_SERVICE: scope.Require.NoError(err) diff --git a/trace/sql.go b/trace/sql.go index 8a9d2b2a6..ae0a681e5 100644 --- a/trace/sql.go +++ b/trace/sql.go @@ -4,6 +4,7 @@ package trace import ( "context" + "database/sql/driver" "time" ) @@ -24,11 +25,24 @@ type ( // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals OnConnBegin func(DatabaseSQLConnBeginStartInfo) func(DatabaseSQLConnBeginDoneInfo) // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + OnConnBeginTx func(DatabaseSQLConnBeginTxStartInfo) func(DatabaseSQLConnBeginTxDoneInfo) + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + OnConnCheckNamedValue func(DatabaseSQLConnCheckNamedValueStartInfo) func( + DatabaseSQLConnCheckNamedValueDoneInfo, + ) + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals OnConnQuery func(DatabaseSQLConnQueryStartInfo) func(DatabaseSQLConnQueryDoneInfo) // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals OnConnExec func(DatabaseSQLConnExecStartInfo) func(DatabaseSQLConnExecDoneInfo) // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals OnConnIsTableExists func(DatabaseSQLConnIsTableExistsStartInfo) func(DatabaseSQLConnIsTableExistsDoneInfo) + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + OnConnIsColumnExists func(info DatabaseSQLConnIsColumnExistsStartInfo) func( + DatabaseSQLConnIsColumnExistsDoneInfo, + ) + OnConnGetIndexColumns func(info DatabaseSQLConnGetIndexColumnsStartInfo) func( + DatabaseSQLConnGetIndexColumnsDoneInfo, + ) // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals OnTxQuery func(DatabaseSQLTxQueryStartInfo) func(DatabaseSQLTxQueryDoneInfo) @@ -137,6 +151,34 @@ type ( Error error } // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + DatabaseSQLConnBeginTxStartInfo struct { + // Context make available context in trace callback function. + // Pointer to context provide replacement of context in trace callback function. + // Warning: concurrent access to pointer on client side must be excluded. + // Safe replacement of context are provided only inside callback function + Context *context.Context + Call call + } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + DatabaseSQLConnBeginTxDoneInfo struct { + Tx txInfo + Error error + } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + DatabaseSQLConnCheckNamedValueStartInfo struct { + // Context make available context in trace callback function. + // Pointer to context provide replacement of context in trace callback function. + // Warning: concurrent access to pointer on client side must be excluded. + // Safe replacement of context are provided only inside callback function + Context *context.Context + Call call + Value *driver.NamedValue + } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + DatabaseSQLConnCheckNamedValueDoneInfo struct { + Error error + } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals DatabaseSQLConnQueryStartInfo struct { // Context make available context in trace callback function. // Pointer to context provide replacement of context in trace callback function. @@ -186,6 +228,38 @@ type ( Error error } // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + DatabaseSQLConnIsColumnExistsStartInfo struct { + // Context make available context in trace callback function. + // Pointer to context provide replacement of context in trace callback function. + // Warning: concurrent access to pointer on client side must be excluded. + // Safe replacement of context are provided only inside callback function + Context *context.Context + Call call + TableName string + ColumnName string + } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + DatabaseSQLConnIsColumnExistsDoneInfo struct { + Exists bool + Error error + } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + DatabaseSQLConnGetIndexColumnsStartInfo struct { + // Context make available context in trace callback function. + // Pointer to context provide replacement of context in trace callback function. + // Warning: concurrent access to pointer on client side must be excluded. + // Safe replacement of context are provided only inside callback function + Context *context.Context + Call call + TableName string + IndexName string + } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals + DatabaseSQLConnGetIndexColumnsDoneInfo struct { + Columns []string + Error error + } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals DatabaseSQLTxQueryStartInfo struct { // Context make available context in trace callback function. // Pointer to context provide replacement of context in trace callback function. diff --git a/trace/sql_gtrace.go b/trace/sql_gtrace.go index 618984641..b17249c80 100644 --- a/trace/sql_gtrace.go +++ b/trace/sql_gtrace.go @@ -4,6 +4,7 @@ package trace import ( "context" + "database/sql/driver" "time" ) @@ -212,6 +213,76 @@ func (t *DatabaseSQL) Compose(x *DatabaseSQL, opts ...DatabaseSQLComposeOption) } } } + { + h1 := t.OnConnBeginTx + h2 := x.OnConnBeginTx + ret.OnConnBeginTx = func(d DatabaseSQLConnBeginTxStartInfo) func(DatabaseSQLConnBeginTxDoneInfo) { + if options.panicCallback != nil { + defer func() { + if e := recover(); e != nil { + options.panicCallback(e) + } + }() + } + var r, r1 func(DatabaseSQLConnBeginTxDoneInfo) + if h1 != nil { + r = h1(d) + } + if h2 != nil { + r1 = h2(d) + } + return func(d DatabaseSQLConnBeginTxDoneInfo) { + if options.panicCallback != nil { + defer func() { + if e := recover(); e != nil { + options.panicCallback(e) + } + }() + } + if r != nil { + r(d) + } + if r1 != nil { + r1(d) + } + } + } + } + { + h1 := t.OnConnCheckNamedValue + h2 := x.OnConnCheckNamedValue + ret.OnConnCheckNamedValue = func(d DatabaseSQLConnCheckNamedValueStartInfo) func(DatabaseSQLConnCheckNamedValueDoneInfo) { + if options.panicCallback != nil { + defer func() { + if e := recover(); e != nil { + options.panicCallback(e) + } + }() + } + var r, r1 func(DatabaseSQLConnCheckNamedValueDoneInfo) + if h1 != nil { + r = h1(d) + } + if h2 != nil { + r1 = h2(d) + } + return func(d DatabaseSQLConnCheckNamedValueDoneInfo) { + if options.panicCallback != nil { + defer func() { + if e := recover(); e != nil { + options.panicCallback(e) + } + }() + } + if r != nil { + r(d) + } + if r1 != nil { + r1(d) + } + } + } + } { h1 := t.OnConnQuery h2 := x.OnConnQuery @@ -317,6 +388,76 @@ func (t *DatabaseSQL) Compose(x *DatabaseSQL, opts ...DatabaseSQLComposeOption) } } } + { + h1 := t.OnConnIsColumnExists + h2 := x.OnConnIsColumnExists + ret.OnConnIsColumnExists = func(info DatabaseSQLConnIsColumnExistsStartInfo) func(DatabaseSQLConnIsColumnExistsDoneInfo) { + if options.panicCallback != nil { + defer func() { + if e := recover(); e != nil { + options.panicCallback(e) + } + }() + } + var r, r1 func(DatabaseSQLConnIsColumnExistsDoneInfo) + if h1 != nil { + r = h1(info) + } + if h2 != nil { + r1 = h2(info) + } + return func(doneInfo DatabaseSQLConnIsColumnExistsDoneInfo) { + if options.panicCallback != nil { + defer func() { + if e := recover(); e != nil { + options.panicCallback(e) + } + }() + } + if r != nil { + r(doneInfo) + } + if r1 != nil { + r1(doneInfo) + } + } + } + } + { + h1 := t.OnConnGetIndexColumns + h2 := x.OnConnGetIndexColumns + ret.OnConnGetIndexColumns = func(info DatabaseSQLConnGetIndexColumnsStartInfo) func(DatabaseSQLConnGetIndexColumnsDoneInfo) { + if options.panicCallback != nil { + defer func() { + if e := recover(); e != nil { + options.panicCallback(e) + } + }() + } + var r, r1 func(DatabaseSQLConnGetIndexColumnsDoneInfo) + if h1 != nil { + r = h1(info) + } + if h2 != nil { + r1 = h2(info) + } + return func(doneInfo DatabaseSQLConnGetIndexColumnsDoneInfo) { + if options.panicCallback != nil { + defer func() { + if e := recover(); e != nil { + options.panicCallback(e) + } + }() + } + if r != nil { + r(doneInfo) + } + if r1 != nil { + r1(doneInfo) + } + } + } + } { h1 := t.OnTxQuery h2 := x.OnTxQuery @@ -725,6 +866,36 @@ func (t *DatabaseSQL) onConnBegin(d DatabaseSQLConnBeginStartInfo) func(Database } return res } +func (t *DatabaseSQL) onConnBeginTx(d DatabaseSQLConnBeginTxStartInfo) func(DatabaseSQLConnBeginTxDoneInfo) { + fn := t.OnConnBeginTx + if fn == nil { + return func(DatabaseSQLConnBeginTxDoneInfo) { + return + } + } + res := fn(d) + if res == nil { + return func(DatabaseSQLConnBeginTxDoneInfo) { + return + } + } + return res +} +func (t *DatabaseSQL) onConnCheckNamedValue(d DatabaseSQLConnCheckNamedValueStartInfo) func(DatabaseSQLConnCheckNamedValueDoneInfo) { + fn := t.OnConnCheckNamedValue + if fn == nil { + return func(DatabaseSQLConnCheckNamedValueDoneInfo) { + return + } + } + res := fn(d) + if res == nil { + return func(DatabaseSQLConnCheckNamedValueDoneInfo) { + return + } + } + return res +} func (t *DatabaseSQL) onConnQuery(d DatabaseSQLConnQueryStartInfo) func(DatabaseSQLConnQueryDoneInfo) { fn := t.OnConnQuery if fn == nil { @@ -770,6 +941,36 @@ func (t *DatabaseSQL) onConnIsTableExists(d DatabaseSQLConnIsTableExistsStartInf } return res } +func (t *DatabaseSQL) onConnIsColumnExists(info DatabaseSQLConnIsColumnExistsStartInfo) func(doneInfo DatabaseSQLConnIsColumnExistsDoneInfo) { + fn := t.OnConnIsColumnExists + if fn == nil { + return func(DatabaseSQLConnIsColumnExistsDoneInfo) { + return + } + } + res := fn(info) + if res == nil { + return func(DatabaseSQLConnIsColumnExistsDoneInfo) { + return + } + } + return res +} +func (t *DatabaseSQL) onConnGetIndexColumns(info DatabaseSQLConnGetIndexColumnsStartInfo) func(doneInfo DatabaseSQLConnGetIndexColumnsDoneInfo) { + fn := t.OnConnGetIndexColumns + if fn == nil { + return func(DatabaseSQLConnGetIndexColumnsDoneInfo) { + return + } + } + res := fn(info) + if res == nil { + return func(DatabaseSQLConnGetIndexColumnsDoneInfo) { + return + } + } + return res +} func (t *DatabaseSQL) onTxQuery(d DatabaseSQLTxQueryStartInfo) func(DatabaseSQLTxQueryDoneInfo) { fn := t.OnTxQuery if fn == nil { @@ -917,6 +1118,7 @@ func (t *DatabaseSQL) onDoTx(d DatabaseSQLDoTxStartInfo) func(DatabaseSQLDoTxInt return res } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnectorConnect(t *DatabaseSQL, c *context.Context, call call) func(_ error, session sessionInfo) { var p DatabaseSQLConnectorConnectStartInfo @@ -930,6 +1132,7 @@ func DatabaseSQLOnConnectorConnect(t *DatabaseSQL, c *context.Context, call call res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnPing(t *DatabaseSQL, c *context.Context, call call) func(error) { var p DatabaseSQLConnPingStartInfo @@ -942,6 +1145,7 @@ func DatabaseSQLOnConnPing(t *DatabaseSQL, c *context.Context, call call) func(e res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnPrepare(t *DatabaseSQL, c *context.Context, call call, query string) func(error) { var p DatabaseSQLConnPrepareStartInfo @@ -955,6 +1159,7 @@ func DatabaseSQLOnConnPrepare(t *DatabaseSQL, c *context.Context, call call, que res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnClose(t *DatabaseSQL, c *context.Context, call call) func(error) { var p DatabaseSQLConnCloseStartInfo @@ -967,6 +1172,7 @@ func DatabaseSQLOnConnClose(t *DatabaseSQL, c *context.Context, call call) func( res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnBegin(t *DatabaseSQL, c *context.Context, call call) func(tx txInfo, _ error) { var p DatabaseSQLConnBeginStartInfo @@ -980,6 +1186,35 @@ func DatabaseSQLOnConnBegin(t *DatabaseSQL, c *context.Context, call call) func( res(p) } } + +// Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals +func DatabaseSQLOnConnBeginTx(t *DatabaseSQL, c *context.Context, call call) func(tx txInfo, _ error) { + var p DatabaseSQLConnBeginTxStartInfo + p.Context = c + p.Call = call + res := t.onConnBeginTx(p) + return func(tx txInfo, e error) { + var p DatabaseSQLConnBeginTxDoneInfo + p.Tx = tx + p.Error = e + res(p) + } +} + +// Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals +func DatabaseSQLOnConnCheckNamedValue(t *DatabaseSQL, c *context.Context, call call, value *driver.NamedValue) func(error) { + var p DatabaseSQLConnCheckNamedValueStartInfo + p.Context = c + p.Call = call + p.Value = value + res := t.onConnCheckNamedValue(p) + return func(e error) { + var p DatabaseSQLConnCheckNamedValueDoneInfo + p.Error = e + res(p) + } +} + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnQuery(t *DatabaseSQL, c *context.Context, call call, query string, mode string, idempotent bool, idleTime time.Duration) func(error) { var p DatabaseSQLConnQueryStartInfo @@ -996,6 +1231,7 @@ func DatabaseSQLOnConnQuery(t *DatabaseSQL, c *context.Context, call call, query res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnExec(t *DatabaseSQL, c *context.Context, call call, query string, mode string, idempotent bool, idleTime time.Duration) func(error) { var p DatabaseSQLConnExecStartInfo @@ -1012,6 +1248,7 @@ func DatabaseSQLOnConnExec(t *DatabaseSQL, c *context.Context, call call, query res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnIsTableExists(t *DatabaseSQL, c *context.Context, call call, tableName string) func(exists bool, _ error) { var p DatabaseSQLConnIsTableExistsStartInfo @@ -1026,6 +1263,39 @@ func DatabaseSQLOnConnIsTableExists(t *DatabaseSQL, c *context.Context, call cal res(p) } } + +// Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals +func DatabaseSQLOnConnIsColumnExists(t *DatabaseSQL, c *context.Context, call call, tableName string, columnName string) func(exists bool, _ error) { + var p DatabaseSQLConnIsColumnExistsStartInfo + p.Context = c + p.Call = call + p.TableName = tableName + p.ColumnName = columnName + res := t.onConnIsColumnExists(p) + return func(exists bool, e error) { + var p DatabaseSQLConnIsColumnExistsDoneInfo + p.Exists = exists + p.Error = e + res(p) + } +} + +// Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals +func DatabaseSQLOnConnGetIndexColumns(t *DatabaseSQL, c *context.Context, call call, tableName string, indexName string) func(columns []string, _ error) { + var p DatabaseSQLConnGetIndexColumnsStartInfo + p.Context = c + p.Call = call + p.TableName = tableName + p.IndexName = indexName + res := t.onConnGetIndexColumns(p) + return func(columns []string, e error) { + var p DatabaseSQLConnGetIndexColumnsDoneInfo + p.Columns = columns + p.Error = e + res(p) + } +} + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnTxQuery(t *DatabaseSQL, c *context.Context, call call, txContext context.Context, tx txInfo, query string) func(error) { var p DatabaseSQLTxQueryStartInfo @@ -1041,6 +1311,7 @@ func DatabaseSQLOnTxQuery(t *DatabaseSQL, c *context.Context, call call, txConte res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnTxExec(t *DatabaseSQL, c *context.Context, call call, txContext context.Context, tx txInfo, query string) func(error) { var p DatabaseSQLTxExecStartInfo @@ -1056,6 +1327,7 @@ func DatabaseSQLOnTxExec(t *DatabaseSQL, c *context.Context, call call, txContex res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnTxPrepare(t *DatabaseSQL, c *context.Context, call call, txContext context.Context, tx txInfo, query string) func(error) { var p DatabaseSQLTxPrepareStartInfo @@ -1071,6 +1343,7 @@ func DatabaseSQLOnTxPrepare(t *DatabaseSQL, c *context.Context, call call, txCon res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnTxCommit(t *DatabaseSQL, c *context.Context, call call, tx txInfo) func(error) { var p DatabaseSQLTxCommitStartInfo @@ -1084,6 +1357,7 @@ func DatabaseSQLOnTxCommit(t *DatabaseSQL, c *context.Context, call call, tx txI res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnTxRollback(t *DatabaseSQL, c *context.Context, call call, tx txInfo) func(error) { var p DatabaseSQLTxRollbackStartInfo @@ -1097,6 +1371,7 @@ func DatabaseSQLOnTxRollback(t *DatabaseSQL, c *context.Context, call call, tx t res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnStmtQuery(t *DatabaseSQL, c *context.Context, call call, stmtContext context.Context, query string) func(error) { var p DatabaseSQLStmtQueryStartInfo @@ -1111,6 +1386,7 @@ func DatabaseSQLOnStmtQuery(t *DatabaseSQL, c *context.Context, call call, stmtC res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnStmtExec(t *DatabaseSQL, c *context.Context, call call, stmtContext context.Context, query string) func(error) { var p DatabaseSQLStmtExecStartInfo @@ -1125,6 +1401,7 @@ func DatabaseSQLOnStmtExec(t *DatabaseSQL, c *context.Context, call call, stmtCo res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnStmtClose(t *DatabaseSQL, stmtContext *context.Context, call call) func(error) { var p DatabaseSQLStmtCloseStartInfo @@ -1137,6 +1414,7 @@ func DatabaseSQLOnStmtClose(t *DatabaseSQL, stmtContext *context.Context, call c res(p) } } + // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnDoTx(t *DatabaseSQL, c *context.Context, call call, iD string, idempotent bool) func(error) func(attempts int, _ error) { var p DatabaseSQLDoTxStartInfo From 9599936cfea3d2c25d83f3ed327510643957c2f0 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Thu, 12 Dec 2024 23:11:07 +0300 Subject: [PATCH 59/62] fix linter issue --- tests/integration/database_sql_regression_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration/database_sql_regression_test.go b/tests/integration/database_sql_regression_test.go index cb221643f..c8b3b06e9 100644 --- a/tests/integration/database_sql_regression_test.go +++ b/tests/integration/database_sql_regression_test.go @@ -427,7 +427,6 @@ func TestUUIDSerializationDatabaseSQLIssue1501(t *testing.T) { case xsql.QUERY_SERVICE: require.Error(t, err) } - }) t.Run("good-send-receive", func(t *testing.T) { var ( From 0ed4ce682adfd54c293e577e8f4515399a148bd9 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Thu, 12 Dec 2024 23:16:07 +0300 Subject: [PATCH 60/62] fixed fake tx for scripting mode --- internal/xsql/legacy/tx.go | 10 ++-------- sql.go | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/internal/xsql/legacy/tx.go b/internal/xsql/legacy/tx.go index b5da7d142..7aba57197 100644 --- a/internal/xsql/legacy/tx.go +++ b/internal/xsql/legacy/tx.go @@ -39,14 +39,8 @@ func (tx *transaction) Exec(ctx context.Context, sql string, params *params.Para 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( - xerrors.WithStackTrace( - xerrors.Retryable( - fmt.Errorf("wrong query mode: %s", m.String()), - xerrors.InvalidObject(), - xerrors.WithName("WRONG_QUERY_MODE"), - ), - ), + return nil, xerrors.WithStackTrace( + fmt.Errorf("%s: %w", m.String(), ErrWrongQueryMode), ) } res, err := tx.tx.Execute(ctx, diff --git a/sql.go b/sql.go index 51f256b01..a752dcc09 100644 --- a/sql.go +++ b/sql.go @@ -175,7 +175,7 @@ func WithFakeTx(modes ...QueryMode) ConnectorOption { case ScriptingQueryMode: opts = append(opts, xsql.WithTableOptions(legacy.WithFakeTxModes( - legacy.DataQueryMode, + legacy.ScriptingQueryMode, )), ) case QueryExecuteQueryMode: From 9d2c715580108ca00f075ff87755e02723cdae4b Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Thu, 12 Dec 2024 23:17:36 +0300 Subject: [PATCH 61/62] fixed matrix ydb versions for examples workflow --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index a2f847efa..f3b3d8b18 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - ydb-version: [ 23.3, 24.1 ] + ydb-version: [ 24.1, 24.2, 24.3 ] application: [ native/table, native/query, database_sql, gorm, xorm ] services: ydb: From 8f69ba5ad834092dd742cc38e3fc06b3b623c3d2 Mon Sep 17 00:00:00 2001 From: Aleksey Myasnikov Date: Thu, 12 Dec 2024 23:20:57 +0300 Subject: [PATCH 62/62] fixed go generated code --- trace/sql_gtrace.go | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/trace/sql_gtrace.go b/trace/sql_gtrace.go index b17249c80..6784fa727 100644 --- a/trace/sql_gtrace.go +++ b/trace/sql_gtrace.go @@ -406,7 +406,7 @@ func (t *DatabaseSQL) Compose(x *DatabaseSQL, opts ...DatabaseSQLComposeOption) if h2 != nil { r1 = h2(info) } - return func(doneInfo DatabaseSQLConnIsColumnExistsDoneInfo) { + return func(d DatabaseSQLConnIsColumnExistsDoneInfo) { if options.panicCallback != nil { defer func() { if e := recover(); e != nil { @@ -415,10 +415,10 @@ func (t *DatabaseSQL) Compose(x *DatabaseSQL, opts ...DatabaseSQLComposeOption) }() } if r != nil { - r(doneInfo) + r(d) } if r1 != nil { - r1(doneInfo) + r1(d) } } } @@ -441,7 +441,7 @@ func (t *DatabaseSQL) Compose(x *DatabaseSQL, opts ...DatabaseSQLComposeOption) if h2 != nil { r1 = h2(info) } - return func(doneInfo DatabaseSQLConnGetIndexColumnsDoneInfo) { + return func(d DatabaseSQLConnGetIndexColumnsDoneInfo) { if options.panicCallback != nil { defer func() { if e := recover(); e != nil { @@ -450,10 +450,10 @@ func (t *DatabaseSQL) Compose(x *DatabaseSQL, opts ...DatabaseSQLComposeOption) }() } if r != nil { - r(doneInfo) + r(d) } if r1 != nil { - r1(doneInfo) + r1(d) } } } @@ -941,7 +941,7 @@ func (t *DatabaseSQL) onConnIsTableExists(d DatabaseSQLConnIsTableExistsStartInf } return res } -func (t *DatabaseSQL) onConnIsColumnExists(info DatabaseSQLConnIsColumnExistsStartInfo) func(doneInfo DatabaseSQLConnIsColumnExistsDoneInfo) { +func (t *DatabaseSQL) onConnIsColumnExists(info DatabaseSQLConnIsColumnExistsStartInfo) func(DatabaseSQLConnIsColumnExistsDoneInfo) { fn := t.OnConnIsColumnExists if fn == nil { return func(DatabaseSQLConnIsColumnExistsDoneInfo) { @@ -956,7 +956,7 @@ func (t *DatabaseSQL) onConnIsColumnExists(info DatabaseSQLConnIsColumnExistsSta } return res } -func (t *DatabaseSQL) onConnGetIndexColumns(info DatabaseSQLConnGetIndexColumnsStartInfo) func(doneInfo DatabaseSQLConnGetIndexColumnsDoneInfo) { +func (t *DatabaseSQL) onConnGetIndexColumns(info DatabaseSQLConnGetIndexColumnsStartInfo) func(DatabaseSQLConnGetIndexColumnsDoneInfo) { fn := t.OnConnGetIndexColumns if fn == nil { return func(DatabaseSQLConnGetIndexColumnsDoneInfo) { @@ -1118,7 +1118,6 @@ func (t *DatabaseSQL) onDoTx(d DatabaseSQLDoTxStartInfo) func(DatabaseSQLDoTxInt return res } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnectorConnect(t *DatabaseSQL, c *context.Context, call call) func(_ error, session sessionInfo) { var p DatabaseSQLConnectorConnectStartInfo @@ -1132,7 +1131,6 @@ func DatabaseSQLOnConnectorConnect(t *DatabaseSQL, c *context.Context, call call res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnPing(t *DatabaseSQL, c *context.Context, call call) func(error) { var p DatabaseSQLConnPingStartInfo @@ -1145,7 +1143,6 @@ func DatabaseSQLOnConnPing(t *DatabaseSQL, c *context.Context, call call) func(e res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnPrepare(t *DatabaseSQL, c *context.Context, call call, query string) func(error) { var p DatabaseSQLConnPrepareStartInfo @@ -1159,7 +1156,6 @@ func DatabaseSQLOnConnPrepare(t *DatabaseSQL, c *context.Context, call call, que res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnClose(t *DatabaseSQL, c *context.Context, call call) func(error) { var p DatabaseSQLConnCloseStartInfo @@ -1172,7 +1168,6 @@ func DatabaseSQLOnConnClose(t *DatabaseSQL, c *context.Context, call call) func( res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnBegin(t *DatabaseSQL, c *context.Context, call call) func(tx txInfo, _ error) { var p DatabaseSQLConnBeginStartInfo @@ -1186,7 +1181,6 @@ func DatabaseSQLOnConnBegin(t *DatabaseSQL, c *context.Context, call call) func( res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnBeginTx(t *DatabaseSQL, c *context.Context, call call) func(tx txInfo, _ error) { var p DatabaseSQLConnBeginTxStartInfo @@ -1200,7 +1194,6 @@ func DatabaseSQLOnConnBeginTx(t *DatabaseSQL, c *context.Context, call call) fun res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnCheckNamedValue(t *DatabaseSQL, c *context.Context, call call, value *driver.NamedValue) func(error) { var p DatabaseSQLConnCheckNamedValueStartInfo @@ -1214,7 +1207,6 @@ func DatabaseSQLOnConnCheckNamedValue(t *DatabaseSQL, c *context.Context, call c res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnQuery(t *DatabaseSQL, c *context.Context, call call, query string, mode string, idempotent bool, idleTime time.Duration) func(error) { var p DatabaseSQLConnQueryStartInfo @@ -1231,7 +1223,6 @@ func DatabaseSQLOnConnQuery(t *DatabaseSQL, c *context.Context, call call, query res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnExec(t *DatabaseSQL, c *context.Context, call call, query string, mode string, idempotent bool, idleTime time.Duration) func(error) { var p DatabaseSQLConnExecStartInfo @@ -1248,7 +1239,6 @@ func DatabaseSQLOnConnExec(t *DatabaseSQL, c *context.Context, call call, query res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnIsTableExists(t *DatabaseSQL, c *context.Context, call call, tableName string) func(exists bool, _ error) { var p DatabaseSQLConnIsTableExistsStartInfo @@ -1263,7 +1253,6 @@ func DatabaseSQLOnConnIsTableExists(t *DatabaseSQL, c *context.Context, call cal res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnIsColumnExists(t *DatabaseSQL, c *context.Context, call call, tableName string, columnName string) func(exists bool, _ error) { var p DatabaseSQLConnIsColumnExistsStartInfo @@ -1279,7 +1268,6 @@ func DatabaseSQLOnConnIsColumnExists(t *DatabaseSQL, c *context.Context, call ca res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnConnGetIndexColumns(t *DatabaseSQL, c *context.Context, call call, tableName string, indexName string) func(columns []string, _ error) { var p DatabaseSQLConnGetIndexColumnsStartInfo @@ -1295,7 +1283,6 @@ func DatabaseSQLOnConnGetIndexColumns(t *DatabaseSQL, c *context.Context, call c res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnTxQuery(t *DatabaseSQL, c *context.Context, call call, txContext context.Context, tx txInfo, query string) func(error) { var p DatabaseSQLTxQueryStartInfo @@ -1311,7 +1298,6 @@ func DatabaseSQLOnTxQuery(t *DatabaseSQL, c *context.Context, call call, txConte res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnTxExec(t *DatabaseSQL, c *context.Context, call call, txContext context.Context, tx txInfo, query string) func(error) { var p DatabaseSQLTxExecStartInfo @@ -1327,7 +1313,6 @@ func DatabaseSQLOnTxExec(t *DatabaseSQL, c *context.Context, call call, txContex res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnTxPrepare(t *DatabaseSQL, c *context.Context, call call, txContext context.Context, tx txInfo, query string) func(error) { var p DatabaseSQLTxPrepareStartInfo @@ -1343,7 +1328,6 @@ func DatabaseSQLOnTxPrepare(t *DatabaseSQL, c *context.Context, call call, txCon res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnTxCommit(t *DatabaseSQL, c *context.Context, call call, tx txInfo) func(error) { var p DatabaseSQLTxCommitStartInfo @@ -1357,7 +1341,6 @@ func DatabaseSQLOnTxCommit(t *DatabaseSQL, c *context.Context, call call, tx txI res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnTxRollback(t *DatabaseSQL, c *context.Context, call call, tx txInfo) func(error) { var p DatabaseSQLTxRollbackStartInfo @@ -1371,7 +1354,6 @@ func DatabaseSQLOnTxRollback(t *DatabaseSQL, c *context.Context, call call, tx t res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnStmtQuery(t *DatabaseSQL, c *context.Context, call call, stmtContext context.Context, query string) func(error) { var p DatabaseSQLStmtQueryStartInfo @@ -1386,7 +1368,6 @@ func DatabaseSQLOnStmtQuery(t *DatabaseSQL, c *context.Context, call call, stmtC res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnStmtExec(t *DatabaseSQL, c *context.Context, call call, stmtContext context.Context, query string) func(error) { var p DatabaseSQLStmtExecStartInfo @@ -1401,7 +1382,6 @@ func DatabaseSQLOnStmtExec(t *DatabaseSQL, c *context.Context, call call, stmtCo res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnStmtClose(t *DatabaseSQL, stmtContext *context.Context, call call) func(error) { var p DatabaseSQLStmtCloseStartInfo @@ -1414,7 +1394,6 @@ func DatabaseSQLOnStmtClose(t *DatabaseSQL, stmtContext *context.Context, call c res(p) } } - // Internals: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#internals func DatabaseSQLOnDoTx(t *DatabaseSQL, c *context.Context, call call, iD string, idempotent bool) func(error) func(attempts int, _ error) { var p DatabaseSQLDoTxStartInfo