github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/mattn/go-sqlite3/sqlite3_test.go (about)

     1  // Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
     2  //
     3  // Use of this source code is governed by an MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package sqlite3
     7  
     8  import (
     9  	"database/sql"
    10  	"database/sql/driver"
    11  	"errors"
    12  	"fmt"
    13  	"io/ioutil"
    14  	"net/url"
    15  	"os"
    16  	"reflect"
    17  	"regexp"
    18  	"strings"
    19  	"sync"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/insionng/yougam/libraries/mattn/go-sqlite3/sqlite3_test"
    24  )
    25  
    26  func TempFilename(t *testing.T) string {
    27  	f, err := ioutil.TempFile("", "go-sqlite3-test-")
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  	f.Close()
    32  	return f.Name()
    33  }
    34  
    35  func doTestOpen(t *testing.T, option string) (string, error) {
    36  	var url string
    37  	tempFilename := TempFilename(t)
    38  	defer os.Remove(tempFilename)
    39  	if option != "" {
    40  		url = tempFilename + option
    41  	} else {
    42  		url = tempFilename
    43  	}
    44  	db, err := sql.Open("sqlite3", url)
    45  	if err != nil {
    46  		return "Failed to open database:", err
    47  	}
    48  	defer os.Remove(tempFilename)
    49  	defer db.Close()
    50  
    51  	_, err = db.Exec("drop table foo")
    52  	_, err = db.Exec("create table foo (id integer)")
    53  	if err != nil {
    54  		return "Failed to create table:", err
    55  	}
    56  
    57  	if stat, err := os.Stat(tempFilename); err != nil || stat.IsDir() {
    58  		return "Failed to create ./foo.db", nil
    59  	}
    60  
    61  	return "", nil
    62  }
    63  
    64  func TestOpen(t *testing.T) {
    65  	cases := map[string]bool{
    66  		"":                   true,
    67  		"?_txlock=immediate": true,
    68  		"?_txlock=deferred":  true,
    69  		"?_txlock=exclusive": true,
    70  		"?_txlock=bogus":     false,
    71  	}
    72  	for option, expectedPass := range cases {
    73  		result, err := doTestOpen(t, option)
    74  		if result == "" {
    75  			if !expectedPass {
    76  				errmsg := fmt.Sprintf("_txlock error not caught at dbOpen with option: %s", option)
    77  				t.Fatal(errmsg)
    78  			}
    79  		} else if expectedPass {
    80  			if err == nil {
    81  				t.Fatal(result)
    82  			} else {
    83  				t.Fatal(result, err)
    84  			}
    85  		}
    86  	}
    87  }
    88  
    89  func TestReadonly(t *testing.T) {
    90  	tempFilename := TempFilename(t)
    91  	defer os.Remove(tempFilename)
    92  
    93  	db1, err := sql.Open("sqlite3", "file:"+tempFilename)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  	db1.Exec("CREATE TABLE test (x int, y float)")
    98  
    99  	db2, err := sql.Open("sqlite3", "file:"+tempFilename+"?mode=ro")
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  	_ = db2
   104  	_, err = db2.Exec("INSERT INTO test VALUES (1, 3.14)")
   105  	if err == nil {
   106  		t.Fatal("didn't expect INSERT into read-only database to work")
   107  	}
   108  }
   109  
   110  func TestClose(t *testing.T) {
   111  	tempFilename := TempFilename(t)
   112  	defer os.Remove(tempFilename)
   113  	db, err := sql.Open("sqlite3", tempFilename)
   114  	if err != nil {
   115  		t.Fatal("Failed to open database:", err)
   116  	}
   117  
   118  	_, err = db.Exec("drop table foo")
   119  	_, err = db.Exec("create table foo (id integer)")
   120  	if err != nil {
   121  		t.Fatal("Failed to create table:", err)
   122  	}
   123  
   124  	stmt, err := db.Prepare("select id from foo where id = ?")
   125  	if err != nil {
   126  		t.Fatal("Failed to select records:", err)
   127  	}
   128  
   129  	db.Close()
   130  	_, err = stmt.Exec(1)
   131  	if err == nil {
   132  		t.Fatal("Failed to operate closed statement")
   133  	}
   134  }
   135  
   136  func TestInsert(t *testing.T) {
   137  	tempFilename := TempFilename(t)
   138  	defer os.Remove(tempFilename)
   139  	db, err := sql.Open("sqlite3", tempFilename)
   140  	if err != nil {
   141  		t.Fatal("Failed to open database:", err)
   142  	}
   143  	defer db.Close()
   144  
   145  	_, err = db.Exec("drop table foo")
   146  	_, err = db.Exec("create table foo (id integer)")
   147  	if err != nil {
   148  		t.Fatal("Failed to create table:", err)
   149  	}
   150  
   151  	res, err := db.Exec("insert into foo(id) values(123)")
   152  	if err != nil {
   153  		t.Fatal("Failed to insert record:", err)
   154  	}
   155  	affected, _ := res.RowsAffected()
   156  	if affected != 1 {
   157  		t.Fatalf("Expected %d for affected rows, but %d:", 1, affected)
   158  	}
   159  
   160  	rows, err := db.Query("select id from foo")
   161  	if err != nil {
   162  		t.Fatal("Failed to select records:", err)
   163  	}
   164  	defer rows.Close()
   165  
   166  	rows.Next()
   167  
   168  	var result int
   169  	rows.Scan(&result)
   170  	if result != 123 {
   171  		t.Errorf("Expected %d for fetched result, but %d:", 123, result)
   172  	}
   173  }
   174  
   175  func TestUpdate(t *testing.T) {
   176  	tempFilename := TempFilename(t)
   177  	defer os.Remove(tempFilename)
   178  	db, err := sql.Open("sqlite3", tempFilename)
   179  	if err != nil {
   180  		t.Fatal("Failed to open database:", err)
   181  	}
   182  	defer db.Close()
   183  
   184  	_, err = db.Exec("drop table foo")
   185  	_, err = db.Exec("create table foo (id integer)")
   186  	if err != nil {
   187  		t.Fatal("Failed to create table:", err)
   188  	}
   189  
   190  	res, err := db.Exec("insert into foo(id) values(123)")
   191  	if err != nil {
   192  		t.Fatal("Failed to insert record:", err)
   193  	}
   194  	expected, err := res.LastInsertId()
   195  	if err != nil {
   196  		t.Fatal("Failed to get LastInsertId:", err)
   197  	}
   198  	affected, _ := res.RowsAffected()
   199  	if err != nil {
   200  		t.Fatal("Failed to get RowsAffected:", err)
   201  	}
   202  	if affected != 1 {
   203  		t.Fatalf("Expected %d for affected rows, but %d:", 1, affected)
   204  	}
   205  
   206  	res, err = db.Exec("update foo set id = 234")
   207  	if err != nil {
   208  		t.Fatal("Failed to update record:", err)
   209  	}
   210  	lastId, err := res.LastInsertId()
   211  	if err != nil {
   212  		t.Fatal("Failed to get LastInsertId:", err)
   213  	}
   214  	if expected != lastId {
   215  		t.Errorf("Expected %q for last Id, but %q:", expected, lastId)
   216  	}
   217  	affected, _ = res.RowsAffected()
   218  	if err != nil {
   219  		t.Fatal("Failed to get RowsAffected:", err)
   220  	}
   221  	if affected != 1 {
   222  		t.Fatalf("Expected %d for affected rows, but %d:", 1, affected)
   223  	}
   224  
   225  	rows, err := db.Query("select id from foo")
   226  	if err != nil {
   227  		t.Fatal("Failed to select records:", err)
   228  	}
   229  	defer rows.Close()
   230  
   231  	rows.Next()
   232  
   233  	var result int
   234  	rows.Scan(&result)
   235  	if result != 234 {
   236  		t.Errorf("Expected %d for fetched result, but %d:", 234, result)
   237  	}
   238  }
   239  
   240  func TestDelete(t *testing.T) {
   241  	tempFilename := TempFilename(t)
   242  	defer os.Remove(tempFilename)
   243  	db, err := sql.Open("sqlite3", tempFilename)
   244  	if err != nil {
   245  		t.Fatal("Failed to open database:", err)
   246  	}
   247  	defer db.Close()
   248  
   249  	_, err = db.Exec("drop table foo")
   250  	_, err = db.Exec("create table foo (id integer)")
   251  	if err != nil {
   252  		t.Fatal("Failed to create table:", err)
   253  	}
   254  
   255  	res, err := db.Exec("insert into foo(id) values(123)")
   256  	if err != nil {
   257  		t.Fatal("Failed to insert record:", err)
   258  	}
   259  	expected, err := res.LastInsertId()
   260  	if err != nil {
   261  		t.Fatal("Failed to get LastInsertId:", err)
   262  	}
   263  	affected, err := res.RowsAffected()
   264  	if err != nil {
   265  		t.Fatal("Failed to get RowsAffected:", err)
   266  	}
   267  	if affected != 1 {
   268  		t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected)
   269  	}
   270  
   271  	res, err = db.Exec("delete from foo where id = 123")
   272  	if err != nil {
   273  		t.Fatal("Failed to delete record:", err)
   274  	}
   275  	lastId, err := res.LastInsertId()
   276  	if err != nil {
   277  		t.Fatal("Failed to get LastInsertId:", err)
   278  	}
   279  	if expected != lastId {
   280  		t.Errorf("Expected %q for last Id, but %q:", expected, lastId)
   281  	}
   282  	affected, err = res.RowsAffected()
   283  	if err != nil {
   284  		t.Fatal("Failed to get RowsAffected:", err)
   285  	}
   286  	if affected != 1 {
   287  		t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected)
   288  	}
   289  
   290  	rows, err := db.Query("select id from foo")
   291  	if err != nil {
   292  		t.Fatal("Failed to select records:", err)
   293  	}
   294  	defer rows.Close()
   295  
   296  	if rows.Next() {
   297  		t.Error("Fetched row but expected not rows")
   298  	}
   299  }
   300  
   301  func TestBooleanRoundtrip(t *testing.T) {
   302  	tempFilename := TempFilename(t)
   303  	defer os.Remove(tempFilename)
   304  	db, err := sql.Open("sqlite3", tempFilename)
   305  	if err != nil {
   306  		t.Fatal("Failed to open database:", err)
   307  	}
   308  	defer db.Close()
   309  
   310  	_, err = db.Exec("DROP TABLE foo")
   311  	_, err = db.Exec("CREATE TABLE foo(id INTEGER, value BOOL)")
   312  	if err != nil {
   313  		t.Fatal("Failed to create table:", err)
   314  	}
   315  
   316  	_, err = db.Exec("INSERT INTO foo(id, value) VALUES(1, ?)", true)
   317  	if err != nil {
   318  		t.Fatal("Failed to insert true value:", err)
   319  	}
   320  
   321  	_, err = db.Exec("INSERT INTO foo(id, value) VALUES(2, ?)", false)
   322  	if err != nil {
   323  		t.Fatal("Failed to insert false value:", err)
   324  	}
   325  
   326  	rows, err := db.Query("SELECT id, value FROM foo")
   327  	if err != nil {
   328  		t.Fatal("Unable to query foo table:", err)
   329  	}
   330  	defer rows.Close()
   331  
   332  	for rows.Next() {
   333  		var id int
   334  		var value bool
   335  
   336  		if err := rows.Scan(&id, &value); err != nil {
   337  			t.Error("Unable to scan results:", err)
   338  			continue
   339  		}
   340  
   341  		if id == 1 && !value {
   342  			t.Error("Value for id 1 should be true, not false")
   343  
   344  		} else if id == 2 && value {
   345  			t.Error("Value for id 2 should be false, not true")
   346  		}
   347  	}
   348  }
   349  
   350  func timezone(t time.Time) string { return t.Format("-07:00") }
   351  
   352  func TestTimestamp(t *testing.T) {
   353  	tempFilename := TempFilename(t)
   354  	defer os.Remove(tempFilename)
   355  	db, err := sql.Open("sqlite3", tempFilename)
   356  	if err != nil {
   357  		t.Fatal("Failed to open database:", err)
   358  	}
   359  	defer db.Close()
   360  
   361  	_, err = db.Exec("DROP TABLE foo")
   362  	_, err = db.Exec("CREATE TABLE foo(id INTEGER, ts timeSTAMP, dt DATETIME)")
   363  	if err != nil {
   364  		t.Fatal("Failed to create table:", err)
   365  	}
   366  
   367  	timestamp1 := time.Date(2012, time.April, 6, 22, 50, 0, 0, time.UTC)
   368  	timestamp2 := time.Date(2006, time.January, 2, 15, 4, 5, 123456789, time.UTC)
   369  	timestamp3 := time.Date(2012, time.November, 4, 0, 0, 0, 0, time.UTC)
   370  	tzTest := time.FixedZone("TEST", -9*3600-13*60)
   371  	tests := []struct {
   372  		value    interface{}
   373  		expected time.Time
   374  	}{
   375  		{"nonsense", time.Time{}},
   376  		{"0000-00-00 00:00:00", time.Time{}},
   377  		{timestamp1, timestamp1},
   378  		{timestamp2.Unix(), timestamp2.Truncate(time.Second)},
   379  		{timestamp2.UnixNano() / int64(time.Millisecond), timestamp2.Truncate(time.Millisecond)},
   380  		{timestamp1.In(tzTest), timestamp1.In(tzTest)},
   381  		{timestamp1.Format("2006-01-02 15:04:05.000"), timestamp1},
   382  		{timestamp1.Format("2006-01-02T15:04:05.000"), timestamp1},
   383  		{timestamp1.Format("2006-01-02 15:04:05"), timestamp1},
   384  		{timestamp1.Format("2006-01-02T15:04:05"), timestamp1},
   385  		{timestamp2, timestamp2},
   386  		{"2006-01-02 15:04:05.123456789", timestamp2},
   387  		{"2006-01-02T15:04:05.123456789", timestamp2},
   388  		{"2006-01-02T05:51:05.123456789-09:13", timestamp2.In(tzTest)},
   389  		{"2012-11-04", timestamp3},
   390  		{"2012-11-04 00:00", timestamp3},
   391  		{"2012-11-04 00:00:00", timestamp3},
   392  		{"2012-11-04 00:00:00.000", timestamp3},
   393  		{"2012-11-04T00:00", timestamp3},
   394  		{"2012-11-04T00:00:00", timestamp3},
   395  		{"2012-11-04T00:00:00.000", timestamp3},
   396  		{"2006-01-02T15:04:05.123456789Z", timestamp2},
   397  		{"2012-11-04Z", timestamp3},
   398  		{"2012-11-04 00:00Z", timestamp3},
   399  		{"2012-11-04 00:00:00Z", timestamp3},
   400  		{"2012-11-04 00:00:00.000Z", timestamp3},
   401  		{"2012-11-04T00:00Z", timestamp3},
   402  		{"2012-11-04T00:00:00Z", timestamp3},
   403  		{"2012-11-04T00:00:00.000Z", timestamp3},
   404  	}
   405  	for i := range tests {
   406  		_, err = db.Exec("INSERT INTO foo(id, ts, dt) VALUES(?, ?, ?)", i, tests[i].value, tests[i].value)
   407  		if err != nil {
   408  			t.Fatal("Failed to insert timestamp:", err)
   409  		}
   410  	}
   411  
   412  	rows, err := db.Query("SELECT id, ts, dt FROM foo ORDER BY id ASC")
   413  	if err != nil {
   414  		t.Fatal("Unable to query foo table:", err)
   415  	}
   416  	defer rows.Close()
   417  
   418  	seen := 0
   419  	for rows.Next() {
   420  		var id int
   421  		var ts, dt time.Time
   422  
   423  		if err := rows.Scan(&id, &ts, &dt); err != nil {
   424  			t.Error("Unable to scan results:", err)
   425  			continue
   426  		}
   427  		if id < 0 || id >= len(tests) {
   428  			t.Error("Bad row id: ", id)
   429  			continue
   430  		}
   431  		seen++
   432  		if !tests[id].expected.Equal(ts) {
   433  			t.Errorf("Timestamp value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt)
   434  		}
   435  		if !tests[id].expected.Equal(dt) {
   436  			t.Errorf("Datetime value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt)
   437  		}
   438  		if timezone(tests[id].expected) != timezone(ts) {
   439  			t.Errorf("Timezone for id %v (%v) should be %v, not %v", id, tests[id].value,
   440  				timezone(tests[id].expected), timezone(ts))
   441  		}
   442  		if timezone(tests[id].expected) != timezone(dt) {
   443  			t.Errorf("Timezone for id %v (%v) should be %v, not %v", id, tests[id].value,
   444  				timezone(tests[id].expected), timezone(dt))
   445  		}
   446  	}
   447  
   448  	if seen != len(tests) {
   449  		t.Errorf("Expected to see %d rows", len(tests))
   450  	}
   451  }
   452  
   453  func TestBoolean(t *testing.T) {
   454  	tempFilename := TempFilename(t)
   455  	defer os.Remove(tempFilename)
   456  	db, err := sql.Open("sqlite3", tempFilename)
   457  	if err != nil {
   458  		t.Fatal("Failed to open database:", err)
   459  	}
   460  
   461  	defer db.Close()
   462  
   463  	_, err = db.Exec("CREATE TABLE foo(id INTEGER, fbool BOOLEAN)")
   464  	if err != nil {
   465  		t.Fatal("Failed to create table:", err)
   466  	}
   467  
   468  	bool1 := true
   469  	_, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(1, ?)", bool1)
   470  	if err != nil {
   471  		t.Fatal("Failed to insert boolean:", err)
   472  	}
   473  
   474  	bool2 := false
   475  	_, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(2, ?)", bool2)
   476  	if err != nil {
   477  		t.Fatal("Failed to insert boolean:", err)
   478  	}
   479  
   480  	bool3 := "nonsense"
   481  	_, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(3, ?)", bool3)
   482  	if err != nil {
   483  		t.Fatal("Failed to insert nonsense:", err)
   484  	}
   485  
   486  	rows, err := db.Query("SELECT id, fbool FROM foo where fbool = ?", bool1)
   487  	if err != nil {
   488  		t.Fatal("Unable to query foo table:", err)
   489  	}
   490  	counter := 0
   491  
   492  	var id int
   493  	var fbool bool
   494  
   495  	for rows.Next() {
   496  		if err := rows.Scan(&id, &fbool); err != nil {
   497  			t.Fatal("Unable to scan results:", err)
   498  		}
   499  		counter++
   500  	}
   501  
   502  	if counter != 1 {
   503  		t.Fatalf("Expected 1 row but %v", counter)
   504  	}
   505  
   506  	if id != 1 && fbool != true {
   507  		t.Fatalf("Value for id 1 should be %v, not %v", bool1, fbool)
   508  	}
   509  
   510  	rows, err = db.Query("SELECT id, fbool FROM foo where fbool = ?", bool2)
   511  	if err != nil {
   512  		t.Fatal("Unable to query foo table:", err)
   513  	}
   514  
   515  	counter = 0
   516  
   517  	for rows.Next() {
   518  		if err := rows.Scan(&id, &fbool); err != nil {
   519  			t.Fatal("Unable to scan results:", err)
   520  		}
   521  		counter++
   522  	}
   523  
   524  	if counter != 1 {
   525  		t.Fatalf("Expected 1 row but %v", counter)
   526  	}
   527  
   528  	if id != 2 && fbool != false {
   529  		t.Fatalf("Value for id 2 should be %v, not %v", bool2, fbool)
   530  	}
   531  
   532  	// make sure "nonsense" triggered an error
   533  	rows, err = db.Query("SELECT id, fbool FROM foo where id=?;", 3)
   534  	if err != nil {
   535  		t.Fatal("Unable to query foo table:", err)
   536  	}
   537  
   538  	rows.Next()
   539  	err = rows.Scan(&id, &fbool)
   540  	if err == nil {
   541  		t.Error("Expected error from \"nonsense\" bool")
   542  	}
   543  }
   544  
   545  func TestFloat32(t *testing.T) {
   546  	tempFilename := TempFilename(t)
   547  	defer os.Remove(tempFilename)
   548  	db, err := sql.Open("sqlite3", tempFilename)
   549  	if err != nil {
   550  		t.Fatal("Failed to open database:", err)
   551  	}
   552  	defer db.Close()
   553  
   554  	_, err = db.Exec("CREATE TABLE foo(id INTEGER)")
   555  	if err != nil {
   556  		t.Fatal("Failed to create table:", err)
   557  	}
   558  
   559  	_, err = db.Exec("INSERT INTO foo(id) VALUES(null)")
   560  	if err != nil {
   561  		t.Fatal("Failed to insert null:", err)
   562  	}
   563  
   564  	rows, err := db.Query("SELECT id FROM foo")
   565  	if err != nil {
   566  		t.Fatal("Unable to query foo table:", err)
   567  	}
   568  
   569  	if !rows.Next() {
   570  		t.Fatal("Unable to query results:", err)
   571  	}
   572  
   573  	var id interface{}
   574  	if err := rows.Scan(&id); err != nil {
   575  		t.Fatal("Unable to scan results:", err)
   576  	}
   577  	if id != nil {
   578  		t.Error("Expected nil but not")
   579  	}
   580  }
   581  
   582  func TestNull(t *testing.T) {
   583  	tempFilename := TempFilename(t)
   584  	defer os.Remove(tempFilename)
   585  	db, err := sql.Open("sqlite3", tempFilename)
   586  	if err != nil {
   587  		t.Fatal("Failed to open database:", err)
   588  	}
   589  	defer db.Close()
   590  
   591  	rows, err := db.Query("SELECT 3.141592")
   592  	if err != nil {
   593  		t.Fatal("Unable to query foo table:", err)
   594  	}
   595  
   596  	if !rows.Next() {
   597  		t.Fatal("Unable to query results:", err)
   598  	}
   599  
   600  	var v interface{}
   601  	if err := rows.Scan(&v); err != nil {
   602  		t.Fatal("Unable to scan results:", err)
   603  	}
   604  	f, ok := v.(float64)
   605  	if !ok {
   606  		t.Error("Expected float but not")
   607  	}
   608  	if f != 3.141592 {
   609  		t.Error("Expected 3.141592 but not")
   610  	}
   611  }
   612  
   613  func TestTransaction(t *testing.T) {
   614  	tempFilename := TempFilename(t)
   615  	defer os.Remove(tempFilename)
   616  	db, err := sql.Open("sqlite3", tempFilename)
   617  	if err != nil {
   618  		t.Fatal("Failed to open database:", err)
   619  	}
   620  	defer db.Close()
   621  
   622  	_, err = db.Exec("CREATE TABLE foo(id INTEGER)")
   623  	if err != nil {
   624  		t.Fatal("Failed to create table:", err)
   625  	}
   626  
   627  	tx, err := db.Begin()
   628  	if err != nil {
   629  		t.Fatal("Failed to begin transaction:", err)
   630  	}
   631  
   632  	_, err = tx.Exec("INSERT INTO foo(id) VALUES(1)")
   633  	if err != nil {
   634  		t.Fatal("Failed to insert null:", err)
   635  	}
   636  
   637  	rows, err := tx.Query("SELECT id from foo")
   638  	if err != nil {
   639  		t.Fatal("Unable to query foo table:", err)
   640  	}
   641  
   642  	err = tx.Rollback()
   643  	if err != nil {
   644  		t.Fatal("Failed to rollback transaction:", err)
   645  	}
   646  
   647  	if rows.Next() {
   648  		t.Fatal("Unable to query results:", err)
   649  	}
   650  
   651  	tx, err = db.Begin()
   652  	if err != nil {
   653  		t.Fatal("Failed to begin transaction:", err)
   654  	}
   655  
   656  	_, err = tx.Exec("INSERT INTO foo(id) VALUES(1)")
   657  	if err != nil {
   658  		t.Fatal("Failed to insert null:", err)
   659  	}
   660  
   661  	err = tx.Commit()
   662  	if err != nil {
   663  		t.Fatal("Failed to commit transaction:", err)
   664  	}
   665  
   666  	rows, err = tx.Query("SELECT id from foo")
   667  	if err == nil {
   668  		t.Fatal("Expected failure to query")
   669  	}
   670  }
   671  
   672  func TestWAL(t *testing.T) {
   673  	tempFilename := TempFilename(t)
   674  	defer os.Remove(tempFilename)
   675  	db, err := sql.Open("sqlite3", tempFilename)
   676  	if err != nil {
   677  		t.Fatal("Failed to open database:", err)
   678  	}
   679  	defer db.Close()
   680  
   681  	if _, err = db.Exec("PRAGMA journal_mode=WAL;"); err != nil {
   682  		t.Fatal("Failed to Exec PRAGMA journal_mode:", err)
   683  	}
   684  	if _, err = db.Exec("PRAGMA locking_mode=EXCLUSIVE;"); err != nil {
   685  		t.Fatal("Failed to Exec PRAGMA locking_mode:", err)
   686  	}
   687  	if _, err = db.Exec("CREATE TABLE test (id SERIAL, user TEXT NOT NULL, name TEXT NOT NULL);"); err != nil {
   688  		t.Fatal("Failed to Exec CREATE TABLE:", err)
   689  	}
   690  	if _, err = db.Exec("INSERT INTO test (user, name) VALUES ('user','name');"); err != nil {
   691  		t.Fatal("Failed to Exec INSERT:", err)
   692  	}
   693  
   694  	trans, err := db.Begin()
   695  	if err != nil {
   696  		t.Fatal("Failed to Begin:", err)
   697  	}
   698  	s, err := trans.Prepare("INSERT INTO test (user, name) VALUES (?, ?);")
   699  	if err != nil {
   700  		t.Fatal("Failed to Prepare:", err)
   701  	}
   702  
   703  	var count int
   704  	if err = trans.QueryRow("SELECT count(user) FROM test;").Scan(&count); err != nil {
   705  		t.Fatal("Failed to QueryRow:", err)
   706  	}
   707  	if _, err = s.Exec("bbbb", "aaaa"); err != nil {
   708  		t.Fatal("Failed to Exec prepared statement:", err)
   709  	}
   710  	if err = s.Close(); err != nil {
   711  		t.Fatal("Failed to Close prepared statement:", err)
   712  	}
   713  	if err = trans.Commit(); err != nil {
   714  		t.Fatal("Failed to Commit:", err)
   715  	}
   716  }
   717  
   718  func TestTimezoneConversion(t *testing.T) {
   719  	zones := []string{"UTC", "US/Central", "US/Pacific", "Local"}
   720  	for _, tz := range zones {
   721  		tempFilename := TempFilename(t)
   722  		defer os.Remove(tempFilename)
   723  		db, err := sql.Open("sqlite3", tempFilename+"?_loc="+url.QueryEscape(tz))
   724  		if err != nil {
   725  			t.Fatal("Failed to open database:", err)
   726  		}
   727  		defer db.Close()
   728  
   729  		_, err = db.Exec("DROP TABLE foo")
   730  		_, err = db.Exec("CREATE TABLE foo(id INTEGER, ts TIMESTAMP, dt DATETIME)")
   731  		if err != nil {
   732  			t.Fatal("Failed to create table:", err)
   733  		}
   734  
   735  		loc, err := time.LoadLocation(tz)
   736  		if err != nil {
   737  			t.Fatal("Failed to load location:", err)
   738  		}
   739  
   740  		timestamp1 := time.Date(2012, time.April, 6, 22, 50, 0, 0, time.UTC)
   741  		timestamp2 := time.Date(2006, time.January, 2, 15, 4, 5, 123456789, time.UTC)
   742  		timestamp3 := time.Date(2012, time.November, 4, 0, 0, 0, 0, time.UTC)
   743  		tests := []struct {
   744  			value    interface{}
   745  			expected time.Time
   746  		}{
   747  			{"nonsense", time.Time{}.In(loc)},
   748  			{"0000-00-00 00:00:00", time.Time{}.In(loc)},
   749  			{timestamp1, timestamp1.In(loc)},
   750  			{timestamp1.Unix(), timestamp1.In(loc)},
   751  			{timestamp1.In(time.FixedZone("TEST", -7*3600)), timestamp1.In(loc)},
   752  			{timestamp1.Format("2006-01-02 15:04:05.000"), timestamp1.In(loc)},
   753  			{timestamp1.Format("2006-01-02T15:04:05.000"), timestamp1.In(loc)},
   754  			{timestamp1.Format("2006-01-02 15:04:05"), timestamp1.In(loc)},
   755  			{timestamp1.Format("2006-01-02T15:04:05"), timestamp1.In(loc)},
   756  			{timestamp2, timestamp2.In(loc)},
   757  			{"2006-01-02 15:04:05.123456789", timestamp2.In(loc)},
   758  			{"2006-01-02T15:04:05.123456789", timestamp2.In(loc)},
   759  			{"2012-11-04", timestamp3.In(loc)},
   760  			{"2012-11-04 00:00", timestamp3.In(loc)},
   761  			{"2012-11-04 00:00:00", timestamp3.In(loc)},
   762  			{"2012-11-04 00:00:00.000", timestamp3.In(loc)},
   763  			{"2012-11-04T00:00", timestamp3.In(loc)},
   764  			{"2012-11-04T00:00:00", timestamp3.In(loc)},
   765  			{"2012-11-04T00:00:00.000", timestamp3.In(loc)},
   766  		}
   767  		for i := range tests {
   768  			_, err = db.Exec("INSERT INTO foo(id, ts, dt) VALUES(?, ?, ?)", i, tests[i].value, tests[i].value)
   769  			if err != nil {
   770  				t.Fatal("Failed to insert timestamp:", err)
   771  			}
   772  		}
   773  
   774  		rows, err := db.Query("SELECT id, ts, dt FROM foo ORDER BY id ASC")
   775  		if err != nil {
   776  			t.Fatal("Unable to query foo table:", err)
   777  		}
   778  		defer rows.Close()
   779  
   780  		seen := 0
   781  		for rows.Next() {
   782  			var id int
   783  			var ts, dt time.Time
   784  
   785  			if err := rows.Scan(&id, &ts, &dt); err != nil {
   786  				t.Error("Unable to scan results:", err)
   787  				continue
   788  			}
   789  			if id < 0 || id >= len(tests) {
   790  				t.Error("Bad row id: ", id)
   791  				continue
   792  			}
   793  			seen++
   794  			if !tests[id].expected.Equal(ts) {
   795  				t.Errorf("Timestamp value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, ts)
   796  			}
   797  			if !tests[id].expected.Equal(dt) {
   798  				t.Errorf("Datetime value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt)
   799  			}
   800  			if tests[id].expected.Location().String() != ts.Location().String() {
   801  				t.Errorf("Location for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected.Location().String(), ts.Location().String())
   802  			}
   803  			if tests[id].expected.Location().String() != dt.Location().String() {
   804  				t.Errorf("Location for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected.Location().String(), dt.Location().String())
   805  			}
   806  		}
   807  
   808  		if seen != len(tests) {
   809  			t.Errorf("Expected to see %d rows", len(tests))
   810  		}
   811  	}
   812  }
   813  
   814  func TestSuite(t *testing.T) {
   815  	tempFilename := TempFilename(t)
   816  	defer os.Remove(tempFilename)
   817  	db, err := sql.Open("sqlite3", tempFilename+"?_busy_timeout=99999")
   818  	if err != nil {
   819  		t.Fatal(err)
   820  	}
   821  	defer db.Close()
   822  
   823  	sqlite3_test.RunTests(t, db, sqlite3_test.SQLITE)
   824  }
   825  
   826  // TODO: Execer & Queryer currently disabled
   827  // https://yougam/libraries/mattn/go-sqlite3/issues/82
   828  func TestExecer(t *testing.T) {
   829  	tempFilename := TempFilename(t)
   830  	defer os.Remove(tempFilename)
   831  	db, err := sql.Open("sqlite3", tempFilename)
   832  	if err != nil {
   833  		t.Fatal("Failed to open database:", err)
   834  	}
   835  	defer db.Close()
   836  
   837  	_, err = db.Exec(`
   838         create table foo (id integer); -- one comment
   839         insert into foo(id) values(?);
   840         insert into foo(id) values(?);
   841         insert into foo(id) values(?); -- another comment
   842         `, 1, 2, 3)
   843  	if err != nil {
   844  		t.Error("Failed to call db.Exec:", err)
   845  	}
   846  }
   847  
   848  func TestQueryer(t *testing.T) {
   849  	tempFilename := TempFilename(t)
   850  	defer os.Remove(tempFilename)
   851  	db, err := sql.Open("sqlite3", tempFilename)
   852  	if err != nil {
   853  		t.Fatal("Failed to open database:", err)
   854  	}
   855  	defer db.Close()
   856  
   857  	_, err = db.Exec(`
   858  	create table foo (id integer);
   859  	`)
   860  	if err != nil {
   861  		t.Error("Failed to call db.Query:", err)
   862  	}
   863  
   864  	rows, err := db.Query(`
   865  	insert into foo(id) values(?);
   866  	insert into foo(id) values(?);
   867  	insert into foo(id) values(?);
   868  	select id from foo order by id;
   869  	`, 3, 2, 1)
   870  	if err != nil {
   871  		t.Error("Failed to call db.Query:", err)
   872  	}
   873  	defer rows.Close()
   874  	n := 1
   875  	if rows != nil {
   876  		for rows.Next() {
   877  			var id int
   878  			err = rows.Scan(&id)
   879  			if err != nil {
   880  				t.Error("Failed to db.Query:", err)
   881  			}
   882  			if id != n {
   883  				t.Error("Failed to db.Query: not matched results")
   884  			}
   885  		}
   886  	}
   887  }
   888  
   889  func TestStress(t *testing.T) {
   890  	tempFilename := TempFilename(t)
   891  	defer os.Remove(tempFilename)
   892  	db, err := sql.Open("sqlite3", tempFilename)
   893  	if err != nil {
   894  		t.Fatal("Failed to open database:", err)
   895  	}
   896  	db.Exec("CREATE TABLE foo (id int);")
   897  	db.Exec("INSERT INTO foo VALUES(1);")
   898  	db.Exec("INSERT INTO foo VALUES(2);")
   899  	db.Close()
   900  
   901  	for i := 0; i < 10000; i++ {
   902  		db, err := sql.Open("sqlite3", tempFilename)
   903  		if err != nil {
   904  			t.Fatal("Failed to open database:", err)
   905  		}
   906  
   907  		for j := 0; j < 3; j++ {
   908  			rows, err := db.Query("select * from foo where id=1;")
   909  			if err != nil {
   910  				t.Error("Failed to call db.Query:", err)
   911  			}
   912  			for rows.Next() {
   913  				var i int
   914  				if err := rows.Scan(&i); err != nil {
   915  					t.Errorf("Scan failed: %v\n", err)
   916  				}
   917  			}
   918  			if err := rows.Err(); err != nil {
   919  				t.Errorf("Post-scan failed: %v\n", err)
   920  			}
   921  			rows.Close()
   922  		}
   923  		db.Close()
   924  	}
   925  }
   926  
   927  func TestDateTimeLocal(t *testing.T) {
   928  	zone := "Asia/Tokyo"
   929  	tempFilename := TempFilename(t)
   930  	defer os.Remove(tempFilename)
   931  	db, err := sql.Open("sqlite3", tempFilename+"?_loc="+zone)
   932  	if err != nil {
   933  		t.Fatal("Failed to open database:", err)
   934  	}
   935  	db.Exec("CREATE TABLE foo (dt datetime);")
   936  	db.Exec("INSERT INTO foo VALUES('2015-03-05 15:16:17');")
   937  
   938  	row := db.QueryRow("select * from foo")
   939  	var d time.Time
   940  	err = row.Scan(&d)
   941  	if err != nil {
   942  		t.Fatal("Failed to scan datetime:", err)
   943  	}
   944  	if d.Hour() == 15 || !strings.Contains(d.String(), "JST") {
   945  		t.Fatal("Result should have timezone", d)
   946  	}
   947  	db.Close()
   948  
   949  	db, err = sql.Open("sqlite3", tempFilename)
   950  	if err != nil {
   951  		t.Fatal("Failed to open database:", err)
   952  	}
   953  
   954  	row = db.QueryRow("select * from foo")
   955  	err = row.Scan(&d)
   956  	if err != nil {
   957  		t.Fatal("Failed to scan datetime:", err)
   958  	}
   959  	if d.UTC().Hour() != 15 || !strings.Contains(d.String(), "UTC") {
   960  		t.Fatalf("Result should not have timezone %v %v", zone, d.String())
   961  	}
   962  
   963  	_, err = db.Exec("DELETE FROM foo")
   964  	if err != nil {
   965  		t.Fatal("Failed to delete table:", err)
   966  	}
   967  	dt, err := time.Parse("2006/1/2 15/4/5 -0700 MST", "2015/3/5 15/16/17 +0900 JST")
   968  	if err != nil {
   969  		t.Fatal("Failed to parse datetime:", err)
   970  	}
   971  	db.Exec("INSERT INTO foo VALUES(?);", dt)
   972  
   973  	db.Close()
   974  	db, err = sql.Open("sqlite3", tempFilename+"?_loc="+zone)
   975  	if err != nil {
   976  		t.Fatal("Failed to open database:", err)
   977  	}
   978  
   979  	row = db.QueryRow("select * from foo")
   980  	err = row.Scan(&d)
   981  	if err != nil {
   982  		t.Fatal("Failed to scan datetime:", err)
   983  	}
   984  	if d.Hour() != 15 || !strings.Contains(d.String(), "JST") {
   985  		t.Fatalf("Result should have timezone %v %v", zone, d.String())
   986  	}
   987  }
   988  
   989  func TestVersion(t *testing.T) {
   990  	s, n, id := Version()
   991  	if s == "" || n == 0 || id == "" {
   992  		t.Errorf("Version failed %q, %d, %q\n", s, n, id)
   993  	}
   994  }
   995  
   996  func TestNumberNamedParams(t *testing.T) {
   997  	tempFilename := TempFilename(t)
   998  	defer os.Remove(tempFilename)
   999  	db, err := sql.Open("sqlite3", tempFilename)
  1000  	if err != nil {
  1001  		t.Fatal("Failed to open database:", err)
  1002  	}
  1003  	defer db.Close()
  1004  
  1005  	_, err = db.Exec(`
  1006  	create table foo (id integer, name text, extra text);
  1007  	`)
  1008  	if err != nil {
  1009  		t.Error("Failed to call db.Query:", err)
  1010  	}
  1011  
  1012  	_, err = db.Exec(`insert into foo(id, name, extra) values($1, $2, $2)`, 1, "foo")
  1013  	if err != nil {
  1014  		t.Error("Failed to call db.Exec:", err)
  1015  	}
  1016  
  1017  	row := db.QueryRow(`select id, extra from foo where id = $1 and extra = $2`, 1, "foo")
  1018  	if row == nil {
  1019  		t.Error("Failed to call db.QueryRow")
  1020  	}
  1021  	var id int
  1022  	var extra string
  1023  	err = row.Scan(&id, &extra)
  1024  	if err != nil {
  1025  		t.Error("Failed to db.Scan:", err)
  1026  	}
  1027  	if id != 1 || extra != "foo" {
  1028  		t.Error("Failed to db.QueryRow: not matched results")
  1029  	}
  1030  }
  1031  
  1032  func TestStringContainingZero(t *testing.T) {
  1033  	tempFilename := TempFilename(t)
  1034  	defer os.Remove(tempFilename)
  1035  	db, err := sql.Open("sqlite3", tempFilename)
  1036  	if err != nil {
  1037  		t.Fatal("Failed to open database:", err)
  1038  	}
  1039  	defer db.Close()
  1040  
  1041  	_, err = db.Exec(`
  1042  	create table foo (id integer, name, extra text);
  1043  	`)
  1044  	if err != nil {
  1045  		t.Error("Failed to call db.Query:", err)
  1046  	}
  1047  
  1048  	const text = "foo\x00bar"
  1049  
  1050  	_, err = db.Exec(`insert into foo(id, name, extra) values($1, $2, $2)`, 1, text)
  1051  	if err != nil {
  1052  		t.Error("Failed to call db.Exec:", err)
  1053  	}
  1054  
  1055  	row := db.QueryRow(`select id, extra from foo where id = $1 and extra = $2`, 1, text)
  1056  	if row == nil {
  1057  		t.Error("Failed to call db.QueryRow")
  1058  	}
  1059  
  1060  	var id int
  1061  	var extra string
  1062  	err = row.Scan(&id, &extra)
  1063  	if err != nil {
  1064  		t.Error("Failed to db.Scan:", err)
  1065  	}
  1066  	if id != 1 || extra != text {
  1067  		t.Error("Failed to db.QueryRow: not matched results")
  1068  	}
  1069  }
  1070  
  1071  const CurrentTimeStamp = "2006-01-02 15:04:05"
  1072  
  1073  type TimeStamp struct{ *time.Time }
  1074  
  1075  func (t TimeStamp) Scan(value interface{}) error {
  1076  	var err error
  1077  	switch v := value.(type) {
  1078  	case string:
  1079  		*t.Time, err = time.Parse(CurrentTimeStamp, v)
  1080  	case []byte:
  1081  		*t.Time, err = time.Parse(CurrentTimeStamp, string(v))
  1082  	default:
  1083  		err = errors.New("invalid type for current_timestamp")
  1084  	}
  1085  	return err
  1086  }
  1087  
  1088  func (t TimeStamp) Value() (driver.Value, error) {
  1089  	return t.Time.Format(CurrentTimeStamp), nil
  1090  }
  1091  
  1092  func TestDateTimeNow(t *testing.T) {
  1093  	tempFilename := TempFilename(t)
  1094  	defer os.Remove(tempFilename)
  1095  	db, err := sql.Open("sqlite3", tempFilename)
  1096  	if err != nil {
  1097  		t.Fatal("Failed to open database:", err)
  1098  	}
  1099  	defer db.Close()
  1100  
  1101  	var d time.Time
  1102  	err = db.QueryRow("SELECT datetime('now')").Scan(TimeStamp{&d})
  1103  	if err != nil {
  1104  		t.Fatal("Failed to scan datetime:", err)
  1105  	}
  1106  }
  1107  
  1108  func TestFunctionRegistration(t *testing.T) {
  1109  	addi_8_16_32 := func(a int8, b int16) int32 { return int32(a) + int32(b) }
  1110  	addi_64 := func(a, b int64) int64 { return a + b }
  1111  	addu_8_16_32 := func(a uint8, b uint16) uint32 { return uint32(a) + uint32(b) }
  1112  	addu_64 := func(a, b uint64) uint64 { return a + b }
  1113  	addiu := func(a int, b uint) int64 { return int64(a) + int64(b) }
  1114  	addf_32_64 := func(a float32, b float64) float64 { return float64(a) + b }
  1115  	not := func(a bool) bool { return !a }
  1116  	regex := func(re, s string) (bool, error) {
  1117  		return regexp.MatchString(re, s)
  1118  	}
  1119  	generic := func(a interface{}) int64 {
  1120  		switch a.(type) {
  1121  		case int64:
  1122  			return 1
  1123  		case float64:
  1124  			return 2
  1125  		case []byte:
  1126  			return 3
  1127  		case string:
  1128  			return 4
  1129  		default:
  1130  			panic("unreachable")
  1131  		}
  1132  	}
  1133  	variadic := func(a, b int64, c ...int64) int64 {
  1134  		ret := a + b
  1135  		for _, d := range c {
  1136  			ret += d
  1137  		}
  1138  		return ret
  1139  	}
  1140  	variadicGeneric := func(a ...interface{}) int64 {
  1141  		return int64(len(a))
  1142  	}
  1143  
  1144  	sql.Register("sqlite3_FunctionRegistration", &SQLiteDriver{
  1145  		ConnectHook: func(conn *SQLiteConn) error {
  1146  			if err := conn.RegisterFunc("addi_8_16_32", addi_8_16_32, true); err != nil {
  1147  				return err
  1148  			}
  1149  			if err := conn.RegisterFunc("addi_64", addi_64, true); err != nil {
  1150  				return err
  1151  			}
  1152  			if err := conn.RegisterFunc("addu_8_16_32", addu_8_16_32, true); err != nil {
  1153  				return err
  1154  			}
  1155  			if err := conn.RegisterFunc("addu_64", addu_64, true); err != nil {
  1156  				return err
  1157  			}
  1158  			if err := conn.RegisterFunc("addiu", addiu, true); err != nil {
  1159  				return err
  1160  			}
  1161  			if err := conn.RegisterFunc("addf_32_64", addf_32_64, true); err != nil {
  1162  				return err
  1163  			}
  1164  			if err := conn.RegisterFunc("not", not, true); err != nil {
  1165  				return err
  1166  			}
  1167  			if err := conn.RegisterFunc("regex", regex, true); err != nil {
  1168  				return err
  1169  			}
  1170  			if err := conn.RegisterFunc("generic", generic, true); err != nil {
  1171  				return err
  1172  			}
  1173  			if err := conn.RegisterFunc("variadic", variadic, true); err != nil {
  1174  				return err
  1175  			}
  1176  			if err := conn.RegisterFunc("variadicGeneric", variadicGeneric, true); err != nil {
  1177  				return err
  1178  			}
  1179  			return nil
  1180  		},
  1181  	})
  1182  	db, err := sql.Open("sqlite3_FunctionRegistration", ":memory:")
  1183  	if err != nil {
  1184  		t.Fatal("Failed to open database:", err)
  1185  	}
  1186  	defer db.Close()
  1187  
  1188  	ops := []struct {
  1189  		query    string
  1190  		expected interface{}
  1191  	}{
  1192  		{"SELECT addi_8_16_32(1,2)", int32(3)},
  1193  		{"SELECT addi_64(1,2)", int64(3)},
  1194  		{"SELECT addu_8_16_32(1,2)", uint32(3)},
  1195  		{"SELECT addu_64(1,2)", uint64(3)},
  1196  		{"SELECT addiu(1,2)", int64(3)},
  1197  		{"SELECT addf_32_64(1.5,1.5)", float64(3)},
  1198  		{"SELECT not(1)", false},
  1199  		{"SELECT not(0)", true},
  1200  		{`SELECT regex("^foo.*", "foobar")`, true},
  1201  		{`SELECT regex("^foo.*", "barfoobar")`, false},
  1202  		{"SELECT generic(1)", int64(1)},
  1203  		{"SELECT generic(1.1)", int64(2)},
  1204  		{`SELECT generic(NULL)`, int64(3)},
  1205  		{`SELECT generic("foo")`, int64(4)},
  1206  		{"SELECT variadic(1,2)", int64(3)},
  1207  		{"SELECT variadic(1,2,3,4)", int64(10)},
  1208  		{"SELECT variadic(1,1,1,1,1,1,1,1,1,1)", int64(10)},
  1209  		{`SELECT variadicGeneric(1,"foo",2.3, NULL)`, int64(4)},
  1210  	}
  1211  
  1212  	for _, op := range ops {
  1213  		ret := reflect.New(reflect.TypeOf(op.expected))
  1214  		err = db.QueryRow(op.query).Scan(ret.Interface())
  1215  		if err != nil {
  1216  			t.Errorf("Query %q failed: %s", op.query, err)
  1217  		} else if !reflect.DeepEqual(ret.Elem().Interface(), op.expected) {
  1218  			t.Errorf("Query %q returned wrong value: got %v (%T), want %v (%T)", op.query, ret.Elem().Interface(), ret.Elem().Interface(), op.expected, op.expected)
  1219  		}
  1220  	}
  1221  }
  1222  
  1223  type sumAggregator int64
  1224  
  1225  func (s *sumAggregator) Step(x int64) {
  1226  	*s += sumAggregator(x)
  1227  }
  1228  
  1229  func (s *sumAggregator) Done() int64 {
  1230  	return int64(*s)
  1231  }
  1232  
  1233  func TestAggregatorRegistration(t *testing.T) {
  1234  	customSum := func() *sumAggregator {
  1235  		var ret sumAggregator
  1236  		return &ret
  1237  	}
  1238  
  1239  	sql.Register("sqlite3_AggregatorRegistration", &SQLiteDriver{
  1240  		ConnectHook: func(conn *SQLiteConn) error {
  1241  			if err := conn.RegisterAggregator("customSum", customSum, true); err != nil {
  1242  				return err
  1243  			}
  1244  			return nil
  1245  		},
  1246  	})
  1247  	db, err := sql.Open("sqlite3_AggregatorRegistration", ":memory:")
  1248  	if err != nil {
  1249  		t.Fatal("Failed to open database:", err)
  1250  	}
  1251  	defer db.Close()
  1252  
  1253  	_, err = db.Exec("create table foo (department integer, profits integer)")
  1254  	if err != nil {
  1255  		t.Fatal("Failed to create table:", err)
  1256  	}
  1257  
  1258  	_, err = db.Exec("insert into foo values (1, 10), (1, 20), (2, 42)")
  1259  	if err != nil {
  1260  		t.Fatal("Failed to insert records:", err)
  1261  	}
  1262  
  1263  	tests := []struct {
  1264  		dept, sum int64
  1265  	}{
  1266  		{1, 30},
  1267  		{2, 42},
  1268  	}
  1269  
  1270  	for _, test := range tests {
  1271  		var ret int64
  1272  		err = db.QueryRow("select customSum(profits) from foo where department = $1 group by department", test.dept).Scan(&ret)
  1273  		if err != nil {
  1274  			t.Fatal("Query failed:", err)
  1275  		}
  1276  		if ret != test.sum {
  1277  			t.Fatalf("Custom sum returned wrong value, got %d, want %d", ret, test.sum)
  1278  		}
  1279  	}
  1280  }
  1281  
  1282  func TestDeclTypes(t *testing.T) {
  1283  
  1284  	d := SQLiteDriver{}
  1285  
  1286  	conn, err := d.Open(":memory:")
  1287  	if err != nil {
  1288  		t.Fatal("Failed to begin transaction:", err)
  1289  	}
  1290  	defer conn.Close()
  1291  
  1292  	sqlite3conn := conn.(*SQLiteConn)
  1293  
  1294  	_, err = sqlite3conn.Exec("create table foo (id integer not null primary key, name text)", nil)
  1295  	if err != nil {
  1296  		t.Fatal("Failed to create table:", err)
  1297  	}
  1298  
  1299  	_, err = sqlite3conn.Exec("insert into foo(name) values(\"bar\")", nil)
  1300  	if err != nil {
  1301  		t.Fatal("Failed to insert:", err)
  1302  	}
  1303  
  1304  	rs, err := sqlite3conn.Query("select * from foo", nil)
  1305  	if err != nil {
  1306  		t.Fatal("Failed to select:", err)
  1307  	}
  1308  	defer rs.Close()
  1309  
  1310  	declTypes := rs.(*SQLiteRows).DeclTypes()
  1311  
  1312  	if !reflect.DeepEqual(declTypes, []string{"integer", "text"}) {
  1313  		t.Fatal("Unexpected declTypes:", declTypes)
  1314  	}
  1315  }
  1316  
  1317  var customFunctionOnce sync.Once
  1318  
  1319  func BenchmarkCustomFunctions(b *testing.B) {
  1320  	customFunctionOnce.Do(func() {
  1321  		custom_add := func(a, b int64) int64 {
  1322  			return a + b
  1323  		}
  1324  
  1325  		sql.Register("sqlite3_BenchmarkCustomFunctions", &SQLiteDriver{
  1326  			ConnectHook: func(conn *SQLiteConn) error {
  1327  				// Impure function to force sqlite to reexecute it each time.
  1328  				if err := conn.RegisterFunc("custom_add", custom_add, false); err != nil {
  1329  					return err
  1330  				}
  1331  				return nil
  1332  			},
  1333  		})
  1334  	})
  1335  
  1336  	db, err := sql.Open("sqlite3_BenchmarkCustomFunctions", ":memory:")
  1337  	if err != nil {
  1338  		b.Fatal("Failed to open database:", err)
  1339  	}
  1340  	defer db.Close()
  1341  
  1342  	b.ResetTimer()
  1343  	for i := 0; i < b.N; i++ {
  1344  		var i int64
  1345  		err = db.QueryRow("SELECT custom_add(1,2)").Scan(&i)
  1346  		if err != nil {
  1347  			b.Fatal("Failed to run custom add:", err)
  1348  		}
  1349  	}
  1350  }