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 4c36d2e2 fix(flightsql): isolate example SQLite databases (#1067)
4c36d2e2 is described below

commit 4c36d2e21997801a22901e61c8563ba0a4d44ef1
Author: Minh Vu <[email protected]>
AuthorDate: Wed Aug 5 19:50:22 2026 +0200

    fix(flightsql): isolate example SQLite databases (#1067)
    
    Fixes #916
    
    ## Problem
    
    CreateDB always opened the same named in-memory SQLite database with
    `cache=shared`. Independent server instances created in the same process
    therefore shared tables and data unexpectedly.
    
    ## Change
    
    Generate a unique database name for each CreateDB call while retaining
    `cache=shared`. Connections obtained from the same `sql.DB` still share
    one in-memory database, but separate CreateDB calls are isolated.
    
    ## Coverage
    
    The regression test verifies both sides of the contract:
    
    - two CreateDB calls cannot see each other’s tables
    - two connections from one `sql.DB` see the same data
    
    ## Validation
    
    `go test ./arrow/flight/flightsql/example`
---
 arrow/flight/flightsql/example/sqlite_server.go    |  6 +-
 .../flight/flightsql/example/sqlite_server_test.go | 67 ++++++++++++++++++++++
 2 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/arrow/flight/flightsql/example/sqlite_server.go 
b/arrow/flight/flightsql/example/sqlite_server.go
index 0b818a2e..4a1441c2 100644
--- a/arrow/flight/flightsql/example/sqlite_server.go
+++ b/arrow/flight/flightsql/example/sqlite_server.go
@@ -44,6 +44,7 @@ import (
        "math/rand"
        "strings"
        "sync"
+       "sync/atomic"
 
        "github.com/apache/arrow-go/v18/arrow"
        "github.com/apache/arrow-go/v18/arrow/array"
@@ -59,6 +60,8 @@ import (
        _ "modernc.org/sqlite"
 )
 
+var dbSequence atomic.Uint64
+
 func genRandomString() []byte {
        const length = 16
        max := int('z')
@@ -146,7 +149,8 @@ func prepareQueryForGetKeys(filter string) string {
 }
 
 func CreateDB() (*sql.DB, error) {
-       db, err := sql.Open("sqlite", "file::memory:?cache=shared")
+       dsn := 
fmt.Sprintf("file:arrow-go-flightsql-%d?mode=memory&cache=shared", 
dbSequence.Add(1))
+       db, err := sql.Open("sqlite", dsn)
        if err != nil {
                return nil, err
        }
diff --git a/arrow/flight/flightsql/example/sqlite_server_test.go 
b/arrow/flight/flightsql/example/sqlite_server_test.go
new file mode 100644
index 00000000..f0ded995
--- /dev/null
+++ b/arrow/flight/flightsql/example/sqlite_server_test.go
@@ -0,0 +1,67 @@
+// 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 example
+
+import (
+       "context"
+       "testing"
+)
+
+func TestCreateDBIsolation(t *testing.T) {
+       db1, err := CreateDB()
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer db1.Close()
+
+       db2, err := CreateDB()
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer db2.Close()
+
+       if _, err := db1.Exec("CREATE TABLE sentinel (value INTEGER)"); err != 
nil {
+               t.Fatal(err)
+       }
+       if _, err := db2.Exec("SELECT * FROM sentinel"); err == nil {
+               t.Fatal("separate CreateDB calls unexpectedly shared state")
+       }
+
+       ctx := context.Background()
+       conn1, err := db1.Conn(ctx)
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer conn1.Close()
+       conn2, err := db1.Conn(ctx)
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer conn2.Close()
+
+       if _, err := conn1.ExecContext(ctx, "INSERT INTO sentinel VALUES 
(42)"); err != nil {
+               t.Fatal(err)
+       }
+       var value int
+       if err := conn2.QueryRowContext(ctx, "SELECT value FROM 
sentinel").Scan(&value); err != nil {
+               t.Fatal(err)
+       }
+       if value != 42 {
+               t.Fatalf("unexpected sentinel value: got %d, want 42", value)
+       }
+}

Reply via email to