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)
+       }
+}

Reply via email to