From 075e8d25566b6cbbd5dff719994ac6a3546fb61b Mon Sep 17 00:00:00 2001 From: albertlockett Date: Thu, 6 Oct 2022 19:12:10 -0400 Subject: [PATCH] #733 driver implemets the sql/driver/ConnBeginTx interface --- clickhouse_std.go | 16 +++++ tests/issues/733_test.go | 128 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 tests/issues/733_test.go diff --git a/clickhouse_std.go b/clickhouse_std.go index 18d7df8115..b740c6f669 100644 --- a/clickhouse_std.go +++ b/clickhouse_std.go @@ -160,6 +160,22 @@ func (std *stdDriver) Ping(ctx context.Context) error { return std.conn.ping(ctx func (std *stdDriver) Begin() (driver.Tx, error) { return std, nil } +func (std *stdDriver) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { + // Check the transaction level. If the transaction level is non-default + // then return an error here as the BeginTx driver value is not supported. + if int(opts.Isolation) != int(sql.LevelDefault) { + return nil, errors.New("sql: driver does not support non-default isolation level") + } + + // If a read-only transaction is requested return an error as the + // BeginTx driver value is not supported. + if opts.ReadOnly { + return nil, errors.New("sql: driver does not support read-only transactions") + } + + return std.Begin() +} + func (std *stdDriver) Commit() error { if std.commit == nil { return nil diff --git a/tests/issues/733_test.go b/tests/issues/733_test.go new file mode 100644 index 0000000000..28ad0f4ecd --- /dev/null +++ b/tests/issues/733_test.go @@ -0,0 +1,128 @@ +package issues + +import ( + "context" + "crypto/tls" + "database/sql" + "fmt" + "github.com/ClickHouse/clickhouse-go/v2" + clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" + "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func Test733_txWithOptionsDoesntThrowWithNilOptions(t *testing.T) { + env, err := GetIssuesTestEnvironment() + require.NoError(t, err) + useSSL, err := strconv.ParseBool(clickhouse_tests.GetEnv("CLICKHOUSE_USE_SSL", "false")) + require.NoError(t, err) + var tlsConfig *tls.Config + port := env.Port + if useSSL { + tlsConfig = &tls.Config{} + port = env.SslPort + } + options := &clickhouse.Options{ + Addr: []string{fmt.Sprintf("%s:%d", env.Host, port)}, + Auth: clickhouse.Auth{ + Database: "default", + Username: env.Username, + Password: env.Password, + }, + TLS: tlsConfig, + } + conn := clickhouse.OpenDB(options) + ctx := context.Background() + require.NoError(t, conn.Ping()) + tx, err := conn.BeginTx(ctx, nil) + require.NoError(t, err) + require.NoError(t, tx.Commit()) +} + +func Test733_defaultTxDoesntThrow(t *testing.T) { + env, err := GetIssuesTestEnvironment() + require.NoError(t, err) + useSSL, err := strconv.ParseBool(clickhouse_tests.GetEnv("CLICKHOUSE_USE_SSL", "false")) + require.NoError(t, err) + var tlsConfig *tls.Config + port := env.Port + if useSSL { + tlsConfig = &tls.Config{} + port = env.SslPort + } + options := &clickhouse.Options{ + Addr: []string{fmt.Sprintf("%s:%d", env.Host, port)}, + Auth: clickhouse.Auth{ + Database: "default", + Username: env.Username, + Password: env.Password, + }, + TLS: tlsConfig, + } + conn := clickhouse.OpenDB(options) + require.NoError(t, conn.Ping()) + tx, err := conn.Begin() + require.NoError(t, err) + require.NoError(t, tx.Commit()) +} + +func Test733_errorIfInvalidIsolationLevel(t *testing.T) { + env, err := GetIssuesTestEnvironment() + require.NoError(t, err) + useSSL, err := strconv.ParseBool(clickhouse_tests.GetEnv("CLICKHOUSE_USE_SSL", "false")) + require.NoError(t, err) + var tlsConfig *tls.Config + port := env.Port + if useSSL { + tlsConfig = &tls.Config{} + port = env.SslPort + } + options := &clickhouse.Options{ + Addr: []string{fmt.Sprintf("%s:%d", env.Host, port)}, + Auth: clickhouse.Auth{ + Database: "default", + Username: env.Username, + Password: env.Password, + }, + TLS: tlsConfig, + } + conn := clickhouse.OpenDB(options) + ctx := context.Background() + require.NoError(t, conn.Ping()) + tx, err := conn.BeginTx(ctx, &sql.TxOptions{ + Isolation: sql.LevelWriteCommitted, + }) + require.Nil(t, tx) + require.Error(t, err) +} + +func Test733_errorIfReadOnlyTx(t *testing.T) { + env, err := GetIssuesTestEnvironment() + require.NoError(t, err) + useSSL, err := strconv.ParseBool(clickhouse_tests.GetEnv("CLICKHOUSE_USE_SSL", "false")) + require.NoError(t, err) + var tlsConfig *tls.Config + port := env.Port + if useSSL { + tlsConfig = &tls.Config{} + port = env.SslPort + } + options := &clickhouse.Options{ + Addr: []string{fmt.Sprintf("%s:%d", env.Host, port)}, + Auth: clickhouse.Auth{ + Database: "default", + Username: env.Username, + Password: env.Password, + }, + TLS: tlsConfig, + } + conn := clickhouse.OpenDB(options) + ctx := context.Background() + require.NoError(t, conn.Ping()) + tx, err := conn.BeginTx(ctx, &sql.TxOptions{ + ReadOnly: true, + }) + require.Nil(t, tx) + require.Error(t, err) +}