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/05 17:50:27 UTC

(arrow-go) branch main updated: fix(flightsql): isolate example SQLite databases (#1067)

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