Skip to content

Commit

Permalink
* Added table.SnapshotReadOnlyTxControl() helper for get transactio…
Browse files Browse the repository at this point in the history
…n control with snapshot read-only
  • Loading branch information
asmyasnikov committed Oct 25, 2023
1 parent 97be827 commit b1f26d4
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Added `interanl/xtest.CurrentFileLine()` helper for table tests
* Added `internal/credentials.IsAccessError(err)` helper for check access errors
* Changed period for re-fresh static credentials token from `1/2` to `1/10` to expiration time
* Added `table.SnapshotReadOnlyTxControl()` helper for get transaction control with snapshot read-only

## v3.53.4
* Downgrade `golang.org/x/net` from `0.17.0` to `0.15.0`
Expand Down
14 changes: 13 additions & 1 deletion internal/xsql/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@ type (
ctxDataQueryOptionsKey struct{}
ctxScanQueryOptionsKey struct{}
ctxModeTypeKey struct{}
ctxTxControlHookKey struct{}

txControlHook func(txControl *table.TransactionControl)
)

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)
Expand All @@ -31,7 +38,12 @@ func WithTxControl(ctx context.Context, txc *table.TransactionControl) context.C
return context.WithValue(ctx, ctxTransactionControlKey{}, txc)
}

func txControl(ctx context.Context, defaultTxControl *table.TransactionControl) *table.TransactionControl {
func txControl(ctx context.Context, defaultTxControl *table.TransactionControl) (txControl *table.TransactionControl) {
defer func() {
if hook, has := ctx.Value(ctxTxControlHookKey{}).(txControlHook); has && hook != nil {
hook(txControl)
}
}()
if txc, ok := ctx.Value(ctxTransactionControlKey{}).(*table.TransactionControl); ok {
return txc
}
Expand Down
9 changes: 8 additions & 1 deletion table/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,15 @@ func StaleReadOnlyTxControl() *TransactionControl {
)
}

// QueryParameters
// SnapshotReadOnlyTxControl returns snapshot read-only transaction control
func SnapshotReadOnlyTxControl() *TransactionControl {
return TxControl(
BeginTx(WithSnapshotReadOnly()),
CommitTx(), // open transactions not supported for StaleReadOnly
)
}

// QueryParameters
type (
queryParams map[string]types.Value
ParameterOption interface {
Expand Down
137 changes: 137 additions & 0 deletions tests/integration/database_sql_with_tx_control_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
//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/internal/xsql"
"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"
)

func TestDatabaseSqlWithTxControl(t *testing.T) {
var (
ctx = xtest.Context(t)
scope = newScope(t)
db = scope.SQLDriverWithFolder(
ydb.WithTablePathPrefix(scope.Folder()),
ydb.WithAutoDeclare(),
)
)

t.Run("default", func(t *testing.T) {
var hookCalled bool
require.NoError(t, retry.Do(
ydb.WithTxControl(
xsql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) {
hookCalled = true
require.Equal(t, table.SerializableReadWriteTxControl().Desc(), txControl.Desc())
}),
table.SerializableReadWriteTxControl(),
),
db, func(ctx context.Context, cc *sql.Conn) error {
_, err := db.QueryContext(ctx, "SELECT 1")
return err
},
))
require.True(t, hookCalled)
})

t.Run("SerializableReadWriteTxControl", func(t *testing.T) {
var hookCalled bool
require.NoError(t, retry.Do(
ydb.WithTxControl(
xsql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) {
hookCalled = true
require.Equal(t, table.SerializableReadWriteTxControl().Desc(), txControl.Desc())
}),
table.SerializableReadWriteTxControl(),
),
db, func(ctx context.Context, cc *sql.Conn) error {
_, err := db.QueryContext(ctx, "SELECT 1")
return err
},
))
require.True(t, hookCalled)
})

t.Run("SnapshotReadOnlyTxControl", func(t *testing.T) {
var hookCalled bool
require.NoError(t, retry.Do(
ydb.WithTxControl(
xsql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) {
hookCalled = true
require.Equal(t, table.SnapshotReadOnlyTxControl().Desc(), txControl.Desc())
}),
table.SnapshotReadOnlyTxControl(),
),
db, func(ctx context.Context, cc *sql.Conn) error {
_, err := db.QueryContext(ctx, "SELECT 1")
return err
},
))
require.True(t, hookCalled)
})

t.Run("StaleReadOnlyTxControl", func(t *testing.T) {
var hookCalled bool
require.NoError(t, retry.Do(
ydb.WithTxControl(
xsql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) {
hookCalled = true
require.Equal(t, table.StaleReadOnlyTxControl().Desc(), txControl.Desc())
}),
table.StaleReadOnlyTxControl(),
),
db, func(ctx context.Context, cc *sql.Conn) error {
_, err := db.QueryContext(ctx, "SELECT 1")
return err
},
))
require.True(t, hookCalled)
})

t.Run("OnlineReadOnlyTxControl{AllowInconsistentReads:false}", func(t *testing.T) {
var hookCalled bool
require.NoError(t, retry.Do(
ydb.WithTxControl(
xsql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) {
hookCalled = true
require.Equal(t, table.OnlineReadOnlyTxControl().Desc(), txControl.Desc())
}),
table.OnlineReadOnlyTxControl(),
),
db, func(ctx context.Context, cc *sql.Conn) error {
_, err := db.QueryContext(ctx, "SELECT 1")
return err
},
))
require.True(t, hookCalled)
})

t.Run("OnlineReadOnlyTxControl{AllowInconsistentReads:true})", func(t *testing.T) {
var hookCalled bool
require.NoError(t, retry.Do(
ydb.WithTxControl(
xsql.WithTxControlHook(ctx, func(txControl *table.TransactionControl) {
hookCalled = true
require.Equal(t, table.OnlineReadOnlyTxControl(table.WithInconsistentReads()).Desc(), txControl.Desc())
}),
table.OnlineReadOnlyTxControl(table.WithInconsistentReads()),
),
db, func(ctx context.Context, cc *sql.Conn) error {
_, err := db.QueryContext(ctx, "SELECT 1")
return err
},
))
require.True(t, hookCalled)
})
}

0 comments on commit b1f26d4

Please sign in to comment.