This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git
The following commit(s) were added to refs/heads/main by this push:
new 986b0274 fix(flightsql): reject unsupported transaction options (#1152)
986b0274 is described below
commit 986b027408e1d973cb78023fc74a2a1bc361c6a9
Author: Minh Vu <[email protected]>
AuthorDate: Wed Aug 12 21:48:23 2026 +0200
fix(flightsql): reject unsupported transaction options (#1152)
## What
- Connection.BeginTx used sql.TxOptions instead of driver.TxOptions.
- Because of that, Connection did not implement driver.ConnBeginTx and
database/sql never called the method.
- Use driver.TxOptions so database/sql forwards the caller context and
transaction options.
- Return ErrNotSupported for non-default isolation levels and read-only
transactions because FlightSQL does not support configuring them.
- Add a compile-time interface check and test the behavior through
sql.DB.BeginTx.
## Test
- go test ./arrow/flight/flightsql/driver -run
TestBeginTxRejectsUnsupportedOptions -count=1
- go test -race ./arrow/flight/flightsql/driver -run
TestBeginTxRejectsUnsupportedOptions -count=1
- go test ./arrow/flight/flightsql/... -count=1
- go test ./arrow/flight/... -count=1
- go vet ./arrow/flight/flightsql/driver
---
arrow/flight/flightsql/driver/driver.go | 25 +++++++++--
arrow/flight/flightsql/driver/transaction_test.go | 51 +++++++++++++++++++++++
2 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/arrow/flight/flightsql/driver/driver.go
b/arrow/flight/flightsql/driver/driver.go
index 0e6a8abb..3d7f8589 100644
--- a/arrow/flight/flightsql/driver/driver.go
+++ b/arrow/flight/flightsql/driver/driver.go
@@ -464,9 +464,11 @@ func (c *Connector) Connect(ctx context.Context)
(driver.Conn, error) {
}
client.Alloc = c.allocator
- return &Connection{
- client: client,
- timeout: c.timeout,
+ return &connBeginTx{
+ Connection: &Connection{
+ client: client,
+ timeout: c.timeout,
+ },
}, nil
}
@@ -484,6 +486,19 @@ type Connection struct {
timeout time.Duration
}
+type connBeginTx struct {
+ *Connection
+}
+
+var _ driver.ConnBeginTx = (*connBeginTx)(nil)
+
+func (c *connBeginTx) BeginTx(ctx context.Context, opts driver.TxOptions)
(driver.Tx, error) {
+ return c.Connection.BeginTx(ctx, sql.TxOptions{
+ Isolation: sql.IsolationLevel(opts.Isolation),
+ ReadOnly: opts.ReadOnly,
+ })
+}
+
// Prepare returns a prepared statement, bound to this connection.
func (c *Connection) Prepare(query string) (driver.Stmt, error) {
return c.PrepareContext(context.Background(), query)
@@ -639,6 +654,10 @@ func (c *Connection) Begin() (driver.Tx, error) {
}
func (c *Connection) BeginTx(ctx context.Context, opts sql.TxOptions)
(driver.Tx, error) {
+ if opts.Isolation != sql.LevelDefault || opts.ReadOnly {
+ return nil, fmt.Errorf("%w: transaction options are not
supported", ErrNotSupported)
+ }
+
tx, err := c.client.BeginTransaction(ctx)
if err != nil {
return nil, err
diff --git a/arrow/flight/flightsql/driver/transaction_test.go
b/arrow/flight/flightsql/driver/transaction_test.go
new file mode 100644
index 00000000..ad23371f
--- /dev/null
+++ b/arrow/flight/flightsql/driver/transaction_test.go
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package driver
+
+import (
+ "context"
+ "database/sql"
+ sqldriver "database/sql/driver"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+type connectionConnector struct{}
+
+func (connectionConnector) Connect(context.Context) (sqldriver.Conn, error) {
+ return &connBeginTx{Connection: &Connection{}}, nil
+}
+
+func (connectionConnector) Driver() sqldriver.Driver {
+ return &Driver{}
+}
+
+func TestBeginTxRejectsUnsupportedOptions(t *testing.T) {
+ db := sql.OpenDB(connectionConnector{})
+ t.Cleanup(func() {
+ require.NoError(t, db.Close())
+ })
+
+ for _, opts := range []sql.TxOptions{
+ {Isolation: sql.LevelSerializable},
+ {ReadOnly: true},
+ } {
+ _, err := db.BeginTx(context.Background(), &opts)
+ require.ErrorIs(t, err, ErrNotSupported)
+ }
+}