From 57aded972938e3bfbb012266dd423117f4ed2d8c Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Thu, 25 Jan 2024 22:58:17 +0900 Subject: [PATCH] remove needless files --- sqlite3_go113_test.go | 120 ---------- sqlite3_go18.go | 54 ----- sqlite3_go18_test.go | 504 ------------------------------------------ 3 files changed, 678 deletions(-) delete mode 100644 sqlite3_go113_test.go delete mode 100644 sqlite3_go18.go delete mode 100644 sqlite3_go18_test.go diff --git a/sqlite3_go113_test.go b/sqlite3_go113_test.go deleted file mode 100644 index f38d6d18..00000000 --- a/sqlite3_go113_test.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (C) 2019 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -//go:build go1.13 && cgo -// +build go1.13,cgo - -package sqlite3 - -import ( - "context" - "database/sql" - "database/sql/driver" - "errors" - "os" - "testing" -) - -func TestBeginTxCancel(t *testing.T) { - srcTempFilename := TempFilename(t) - defer os.Remove(srcTempFilename) - - db, err := sql.Open("sqlite3", srcTempFilename) - if err != nil { - t.Fatal(err) - } - - db.SetMaxOpenConns(10) - db.SetMaxIdleConns(5) - - defer db.Close() - initDatabase(t, db, 100) - - // create several go-routines to expose racy issue - for i := 0; i < 1000; i++ { - func() { - ctx, cancel := context.WithCancel(context.Background()) - conn, err := db.Conn(ctx) - if err != nil { - t.Fatal(err) - } - defer func() { - if err := conn.Close(); err != nil { - t.Error(err) - } - }() - - err = conn.Raw(func(driverConn any) error { - d, ok := driverConn.(driver.ConnBeginTx) - if !ok { - t.Fatal("unexpected: wrong type") - } - // checks that conn.Raw can be used to get *SQLiteConn - if _, ok = driverConn.(*SQLiteConn); !ok { - t.Fatalf("conn.Raw() driverConn type=%T, expected *SQLiteConn", driverConn) - } - - go cancel() // make it cancel concurrently with exec("BEGIN"); - tx, err := d.BeginTx(ctx, driver.TxOptions{}) - switch err { - case nil: - switch err := tx.Rollback(); err { - case nil, sql.ErrTxDone: - default: - return err - } - case context.Canceled: - default: - // must not fail with "cannot start a transaction within a transaction" - return err - } - return nil - }) - if err != nil { - t.Fatal(err) - } - }() - } -} - -func TestStmtReadonly(t *testing.T) { - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec("CREATE TABLE t (count INT)") - if err != nil { - t.Fatal(err) - } - - isRO := func(query string) bool { - c, err := db.Conn(context.Background()) - if err != nil { - return false - } - - var ro bool - c.Raw(func(dc any) error { - stmt, err := dc.(*SQLiteConn).Prepare(query) - if err != nil { - return err - } - if stmt == nil { - return errors.New("stmt is nil") - } - ro = stmt.(*SQLiteStmt).Readonly() - return nil - }) - return ro // On errors ro will remain false. - } - - if !isRO(`select * from t`) { - t.Error("select not seen as read-only") - } - if isRO(`insert into t values (1), (2)`) { - t.Error("insert seen as read-only") - } -} diff --git a/sqlite3_go18.go b/sqlite3_go18.go deleted file mode 100644 index 34cad08e..00000000 --- a/sqlite3_go18.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2019 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -//go:build cgo && go1.8 -// +build cgo,go1.8 - -package sqlite3 - -import ( - "database/sql/driver" - - "context" -) - -// Ping implement Pinger. -func (c *SQLiteConn) Ping(ctx context.Context) error { - if c.db == nil { - // must be ErrBadConn for sql to close the database - return driver.ErrBadConn - } - return nil -} - -// QueryContext implement QueryerContext. -func (c *SQLiteConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { - return c.query(ctx, query, args) -} - -// ExecContext implement ExecerContext. -func (c *SQLiteConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { - return c.exec(ctx, query, args) -} - -// PrepareContext implement ConnPrepareContext. -func (c *SQLiteConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { - return c.prepare(ctx, query) -} - -// BeginTx implement ConnBeginTx. -func (c *SQLiteConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { - return c.begin(ctx) -} - -// QueryContext implement QueryerContext. -func (s *SQLiteStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { - return s.query(ctx, args) -} - -// ExecContext implement ExecerContext. -func (s *SQLiteStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { - return s.exec(ctx, args) -} diff --git a/sqlite3_go18_test.go b/sqlite3_go18_test.go deleted file mode 100644 index eec7479d..00000000 --- a/sqlite3_go18_test.go +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright (C) 2019 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -//go:build go1.8 && cgo -// +build go1.8,cgo - -package sqlite3 - -import ( - "context" - "database/sql" - "fmt" - "io/ioutil" - "math/rand" - "os" - "sync" - "testing" - "time" -) - -func TestNamedParams(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec(` - create table foo (id integer, name text, extra text); - `) - if err != nil { - t.Error("Failed to call db.Query:", err) - } - - _, err = db.Exec(`insert into foo(id, name, extra) values(:id, :name, :name)`, sql.Named("name", "foo"), sql.Named("id", 1)) - if err != nil { - t.Error("Failed to call db.Exec:", err) - } - - row := db.QueryRow(`select id, extra from foo where id = :id and extra = :extra`, sql.Named("id", 1), sql.Named("extra", "foo")) - if row == nil { - t.Error("Failed to call db.QueryRow") - } - var id int - var extra string - err = row.Scan(&id, &extra) - if err != nil { - t.Error("Failed to db.Scan:", err) - } - if id != 1 || extra != "foo" { - t.Error("Failed to db.QueryRow: not matched results") - } -} - -var ( - testTableStatements = []string{ - `DROP TABLE IF EXISTS test_table`, - ` -CREATE TABLE IF NOT EXISTS test_table ( - key1 VARCHAR(64) PRIMARY KEY, - key_id VARCHAR(64) NOT NULL, - key2 VARCHAR(64) NOT NULL, - key3 VARCHAR(64) NOT NULL, - key4 VARCHAR(64) NOT NULL, - key5 VARCHAR(64) NOT NULL, - key6 VARCHAR(64) NOT NULL, - data BLOB NOT NULL -);`, - } - letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" -) - -func randStringBytes(n int) string { - b := make([]byte, n) - for i := range b { - b[i] = letterBytes[rand.Intn(len(letterBytes))] - } - return string(b) -} - -func initDatabase(t *testing.T, db *sql.DB, rowCount int64) { - for _, query := range testTableStatements { - _, err := db.Exec(query) - if err != nil { - t.Fatal(err) - } - } - for i := int64(0); i < rowCount; i++ { - query := `INSERT INTO test_table - (key1, key_id, key2, key3, key4, key5, key6, data) - VALUES - (?, ?, ?, ?, ?, ?, ?, ?);` - args := []interface{}{ - randStringBytes(50), - fmt.Sprint(i), - randStringBytes(50), - randStringBytes(50), - randStringBytes(50), - randStringBytes(50), - randStringBytes(50), - randStringBytes(50), - randStringBytes(2048), - } - _, err := db.Exec(query, args...) - if err != nil { - t.Fatal(err) - } - } -} - -func TestShortTimeout(t *testing.T) { - srcTempFilename := TempFilename(t) - defer os.Remove(srcTempFilename) - - db, err := sql.Open("sqlite3", srcTempFilename) - if err != nil { - t.Fatal(err) - } - defer db.Close() - initDatabase(t, db, 100) - - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Microsecond) - defer cancel() - query := `SELECT key1, key_id, key2, key3, key4, key5, key6, data - FROM test_table - ORDER BY key2 ASC` - _, err = db.QueryContext(ctx, query) - if err != nil && err != context.DeadlineExceeded { - t.Fatal(err) - } - if ctx.Err() != nil && ctx.Err() != context.DeadlineExceeded { - t.Fatal(ctx.Err()) - } -} - -func TestExecContextCancel(t *testing.T) { - srcTempFilename := TempFilename(t) - defer os.Remove(srcTempFilename) - - db, err := sql.Open("sqlite3", srcTempFilename) - if err != nil { - t.Fatal(err) - } - - defer db.Close() - - ts := time.Now() - initDatabase(t, db, 1000) - spent := time.Since(ts) - const minTestTime = 100 * time.Millisecond - if spent < minTestTime { - t.Skipf("test will be too racy (spent=%s < min=%s) as ExecContext below will be too fast.", - spent.String(), minTestTime.String(), - ) - } - - // expected to be extremely slow query - q := ` -INSERT INTO test_table (key1, key_id, key2, key3, key4, key5, key6, data) -SELECT t1.key1 || t2.key1, t1.key_id || t2.key_id, t1.key2 || t2.key2, t1.key3 || t2.key3, t1.key4 || t2.key4, t1.key5 || t2.key5, t1.key6 || t2.key6, t1.data || t2.data -FROM test_table t1 LEFT OUTER JOIN test_table t2` - // expect query above take ~ same time as setup above - // This is racy: the context must be valid so sql/db.ExecContext calls the sqlite3 driver. - // It starts the query, the context expires, then calls sqlite3_interrupt - ctx, cancel := context.WithTimeout(context.Background(), minTestTime/2) - defer cancel() - ts = time.Now() - r, err := db.ExecContext(ctx, q) - // racy check - if r != nil { - n, err := r.RowsAffected() - t.Logf("query should not have succeeded: rows=%d; err=%v; duration=%s", - n, err, time.Since(ts).String()) - } - if err != context.DeadlineExceeded { - t.Fatal(err, ctx.Err()) - } -} - -func TestQueryRowContextCancel(t *testing.T) { - srcTempFilename := TempFilename(t) - defer os.Remove(srcTempFilename) - - db, err := sql.Open("sqlite3", srcTempFilename) - if err != nil { - t.Fatal(err) - } - defer db.Close() - initDatabase(t, db, 100) - - const query = `SELECT key_id FROM test_table ORDER BY key2 ASC` - var keyID string - unexpectedErrors := make(map[string]int) - for i := 0; i < 10000; i++ { - ctx, cancel := context.WithCancel(context.Background()) - row := db.QueryRowContext(ctx, query) - - cancel() - // it is fine to get "nil" as context cancellation can be handled with delay - if err := row.Scan(&keyID); err != nil && err != context.Canceled { - if err.Error() == "sql: Rows are closed" { - // see https://github.com/golang/go/issues/24431 - // fixed in 1.11.1 to properly return context error - continue - } - unexpectedErrors[err.Error()]++ - } - } - for errText, count := range unexpectedErrors { - t.Error(errText, count) - } -} - -func TestQueryRowContextCancelParallel(t *testing.T) { - srcTempFilename := TempFilename(t) - defer os.Remove(srcTempFilename) - - db, err := sql.Open("sqlite3", srcTempFilename) - if err != nil { - t.Fatal(err) - } - db.SetMaxOpenConns(10) - db.SetMaxIdleConns(5) - - defer db.Close() - initDatabase(t, db, 100) - - const query = `SELECT key_id FROM test_table ORDER BY key2 ASC` - wg := sync.WaitGroup{} - defer wg.Wait() - - testCtx, cancel := context.WithCancel(context.Background()) - defer cancel() - - for i := 0; i < 10; i++ { - wg.Add(1) - go func() { - defer wg.Done() - - var keyID string - for { - select { - case <-testCtx.Done(): - return - default: - } - ctx, cancel := context.WithCancel(context.Background()) - row := db.QueryRowContext(ctx, query) - - cancel() - _ = row.Scan(&keyID) // see TestQueryRowContextCancel - } - }() - } - - var keyID string - for i := 0; i < 10000; i++ { - // note that testCtx is not cancelled during query execution - row := db.QueryRowContext(testCtx, query) - - if err := row.Scan(&keyID); err != nil { - t.Fatal(i, err) - } - } -} - -func TestExecCancel(t *testing.T) { - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - t.Fatal(err) - } - defer db.Close() - - if _, err = db.Exec("create table foo (id integer primary key)"); err != nil { - t.Fatal(err) - } - - for n := 0; n < 100; n++ { - ctx, cancel := context.WithCancel(context.Background()) - _, err = db.ExecContext(ctx, "insert into foo (id) values (?)", n) - cancel() - if err != nil { - t.Fatal(err) - } - } -} - -func doTestOpenContext(t *testing.T, option string) (string, error) { - tempFilename := TempFilename(t) - url := tempFilename + option - - defer func() { - err := os.Remove(tempFilename) - if err != nil { - t.Error("temp file remove error:", err) - } - }() - - db, err := sql.Open("sqlite3", url) - if err != nil { - return "Failed to open database:", err - } - - defer func() { - err = db.Close() - if err != nil { - t.Error("db close error:", err) - } - }() - - ctx, cancel := context.WithTimeout(context.Background(), 55*time.Second) - err = db.PingContext(ctx) - cancel() - if err != nil { - return "ping error:", err - } - - ctx, cancel = context.WithTimeout(context.Background(), 55*time.Second) - _, err = db.ExecContext(ctx, "drop table foo") - cancel() - ctx, cancel = context.WithTimeout(context.Background(), 55*time.Second) - _, err = db.ExecContext(ctx, "create table foo (id integer)") - cancel() - if err != nil { - return "Failed to create table:", err - } - - if stat, err := os.Stat(tempFilename); err != nil || stat.IsDir() { - return "Failed to create ./foo.db", nil - } - - return "", nil -} - -func TestOpenContext(t *testing.T) { - cases := map[string]bool{ - "": true, - "?_txlock=immediate": true, - "?_txlock=deferred": true, - "?_txlock=exclusive": true, - "?_txlock=bogus": false, - } - for option, expectedPass := range cases { - result, err := doTestOpenContext(t, option) - if result == "" { - if !expectedPass { - errmsg := fmt.Sprintf("_txlock error not caught at dbOpen with option: %s", option) - t.Fatal(errmsg) - } - } else if expectedPass { - if err == nil { - t.Fatal(result) - } else { - t.Fatal(result, err) - } - } - } -} - -func TestFileCopyTruncate(t *testing.T) { - var err error - tempFilename := TempFilename(t) - - defer func() { - err = os.Remove(tempFilename) - if err != nil { - t.Error("temp file remove error:", err) - } - }() - - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("open error:", err) - } - - defer func() { - err = db.Close() - if err != nil { - t.Error("db close error:", err) - } - }() - - ctx, cancel := context.WithTimeout(context.Background(), 55*time.Second) - err = db.PingContext(ctx) - cancel() - if err != nil { - t.Fatal("ping error:", err) - } - - ctx, cancel = context.WithTimeout(context.Background(), 55*time.Second) - _, err = db.ExecContext(ctx, "drop table foo") - cancel() - ctx, cancel = context.WithTimeout(context.Background(), 55*time.Second) - _, err = db.ExecContext(ctx, "create table foo (id integer)") - cancel() - if err != nil { - t.Fatal("create table error:", err) - } - - // copy db to new file - var data []byte - data, err = ioutil.ReadFile(tempFilename) - if err != nil { - t.Fatal("read file error:", err) - } - - var f *os.File - f, err = os.Create(tempFilename + "-db-copy") - if err != nil { - t.Fatal("create file error:", err) - } - - defer func() { - err = os.Remove(tempFilename + "-db-copy") - if err != nil { - t.Error("temp file moved remove error:", err) - } - }() - - _, err = f.Write(data) - if err != nil { - f.Close() - t.Fatal("write file error:", err) - } - err = f.Close() - if err != nil { - t.Fatal("close file error:", err) - } - - // truncate current db file - f, err = os.OpenFile(tempFilename, os.O_WRONLY|os.O_TRUNC, 0666) - if err != nil { - t.Fatal("open file error:", err) - } - err = f.Close() - if err != nil { - t.Fatal("close file error:", err) - } - - // test db after file truncate - ctx, cancel = context.WithTimeout(context.Background(), 55*time.Second) - err = db.PingContext(ctx) - cancel() - if err != nil { - t.Fatal("ping error:", err) - } - - ctx, cancel = context.WithTimeout(context.Background(), 55*time.Second) - _, err = db.ExecContext(ctx, "drop table foo") - cancel() - if err == nil { - t.Fatal("drop table no error") - } - - ctx, cancel = context.WithTimeout(context.Background(), 55*time.Second) - _, err = db.ExecContext(ctx, "create table foo (id integer)") - cancel() - if err != nil { - t.Fatal("create table error:", err) - } - - err = db.Close() - if err != nil { - t.Error("db close error:", err) - } - - // test copied file - db, err = sql.Open("sqlite3", tempFilename+"-db-copy") - if err != nil { - t.Fatal("open error:", err) - } - - defer func() { - err = db.Close() - if err != nil { - t.Error("db close error:", err) - } - }() - - ctx, cancel = context.WithTimeout(context.Background(), 55*time.Second) - err = db.PingContext(ctx) - cancel() - if err != nil { - t.Fatal("ping error:", err) - } - - ctx, cancel = context.WithTimeout(context.Background(), 55*time.Second) - _, err = db.ExecContext(ctx, "drop table foo") - cancel() - if err != nil { - t.Fatal("drop table error:", err) - } - - ctx, cancel = context.WithTimeout(context.Background(), 55*time.Second) - _, err = db.ExecContext(ctx, "create table foo (id integer)") - cancel() - if err != nil { - t.Fatal("create table error:", err) - } -}