| //go:build sqlite_vtable |
| |
| package sqlite3 |
| |
| import ( |
| "database/sql" |
| "fmt" |
| "sync/atomic" |
| "testing" |
| ) |
| |
| var leakCheckDriverSeq int32 |
| |
| func TestVtabCursorHandleRelease(t *testing.T) { |
| // Use a unique driver name so repeated runs (e.g. -count=2) do not |
| // panic on duplicate registration. |
| driverName := fmt.Sprintf("sqlite3_HandleLeakCheck_%d", atomic.AddInt32(&leakCheckDriverSeq, 1)) |
| sql.Register(driverName, &SQLiteDriver{ |
| ConnectHook: func(conn *SQLiteConn) error { |
| return conn.CreateModule("test", &testModule{t: t, intarray: []int{1, 2, 3}}) |
| }, |
| }) |
| db, err := sql.Open(driverName, ":memory:") |
| if err != nil { |
| t.Fatal(err) |
| } |
| defer db.Close() |
| if _, err := db.Exec("CREATE VIRTUAL TABLE vtab USING test('1', 2, three)"); err != nil { |
| t.Fatal(err) |
| } |
| var before, after int |
| for i := 0; i < 50; i++ { |
| var n int |
| if err := db.QueryRow("SELECT count(*) FROM vtab").Scan(&n); err != nil { |
| t.Fatal(err) |
| } |
| if i == 0 { |
| before = len(loadHandleVals()) |
| } |
| } |
| after = len(loadHandleVals()) |
| if after > before { |
| t.Fatalf("handle map grew from %d to %d over repeated cursor open/close", before, after) |
| } |
| } |