You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ze...@apache.org on 2026/08/12 19:48:28 UTC

(arrow-go) branch main updated: fix(flightsql): reject unsupported transaction options (#1152)

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 <vu...@gmail.com>
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)
+	}
+}