gitlab.com/jakobvarmose/sqlite@v1.0.0/all_test.go (about) 1 // Copyright 2017 The Sqlite Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sqlite // import "modernc.org/sqlite" 6 7 import ( 8 "bytes" 9 "database/sql" 10 "flag" 11 "fmt" 12 "io/ioutil" 13 "os" 14 "path" 15 "path/filepath" 16 "runtime" 17 "strings" 18 "testing" 19 "time" 20 ) 21 22 func caller(s string, va ...interface{}) { 23 if s == "" { 24 s = strings.Repeat("%v ", len(va)) 25 } 26 _, fn, fl, _ := runtime.Caller(2) 27 fmt.Fprintf(os.Stderr, "# caller: %s:%d: ", path.Base(fn), fl) 28 fmt.Fprintf(os.Stderr, s, va...) 29 fmt.Fprintln(os.Stderr) 30 _, fn, fl, _ = runtime.Caller(1) 31 fmt.Fprintf(os.Stderr, "# \tcallee: %s:%d: ", path.Base(fn), fl) 32 fmt.Fprintln(os.Stderr) 33 os.Stderr.Sync() 34 } 35 36 func dbg(s string, va ...interface{}) { 37 if s == "" { 38 s = strings.Repeat("%v ", len(va)) 39 } 40 _, fn, fl, _ := runtime.Caller(1) 41 fmt.Fprintf(os.Stderr, "# dbg %s:%d: ", path.Base(fn), fl) 42 fmt.Fprintf(os.Stderr, s, va...) 43 fmt.Fprintln(os.Stderr) 44 os.Stderr.Sync() 45 } 46 47 func TODO(...interface{}) string { //TODOOK 48 _, fn, fl, _ := runtime.Caller(1) 49 return fmt.Sprintf("# TODO: %s:%d:\n", path.Base(fn), fl) //TODOOK 50 } 51 52 func use(...interface{}) {} 53 54 func init() { 55 use(caller, dbg, TODO) //TODOOK 56 } 57 58 // ============================================================================ 59 60 var ( 61 memTrace = flag.Bool("memory.trace", false, "") 62 recsPerSec = flag.Bool("recs_per_sec_as_mbps", false, "Show records per second as MB/s.") 63 ) 64 65 func tempDB(t testing.TB) (string, *sql.DB) { 66 dir, err := ioutil.TempDir("", "sqlite-test-") 67 if err != nil { 68 t.Fatal(err) 69 } 70 71 db, err := sql.Open(driverName, filepath.Join(dir, "tmp.db")) 72 if err != nil { 73 os.RemoveAll(dir) 74 t.Fatal(err) 75 } 76 77 return dir, db 78 } 79 80 func TestScalar(t *testing.T) { 81 dir, db := tempDB(t) 82 83 defer func() { 84 db.Close() 85 os.RemoveAll(dir) 86 }() 87 88 t1 := time.Date(2017, 4, 20, 1, 2, 3, 56789, time.UTC) 89 t2 := time.Date(2018, 5, 21, 2, 3, 4, 98765, time.UTC) 90 r, err := db.Exec(` 91 create table t(i int, f double, b bool, s text, t time); 92 insert into t values(12, 3.14, ?, "foo", ?), (34, 2.78, ?, "bar", ?); 93 `, 94 true, t1, 95 false, t2, 96 ) 97 if err != nil { 98 t.Fatal(err) 99 } 100 101 n, err := r.RowsAffected() 102 if err != nil { 103 t.Fatal(err) 104 } 105 106 if g, e := n, int64(2); g != e { 107 t.Fatal(g, e) 108 } 109 110 rows, err := db.Query("select * from t") 111 if err != nil { 112 t.Fatal(err) 113 } 114 115 type rec struct { 116 i int 117 f float64 118 b bool 119 s string 120 t string 121 } 122 var a []rec 123 for rows.Next() { 124 var r rec 125 if err := rows.Scan(&r.i, &r.f, &r.b, &r.s, &r.t); err != nil { 126 t.Fatal(err) 127 } 128 129 a = append(a, r) 130 } 131 if err := rows.Err(); err != nil { 132 t.Fatal(err) 133 } 134 135 if g, e := len(a), 2; g != e { 136 t.Fatal(g, e) 137 } 138 139 if g, e := a[0], (rec{12, 3.14, true, "foo", t1.String()}); g != e { 140 t.Fatal(g, e) 141 } 142 143 if g, e := a[1], (rec{34, 2.78, false, "bar", t2.String()}); g != e { 144 t.Fatal(g, e) 145 } 146 } 147 148 func TestBlob(t *testing.T) { 149 dir, db := tempDB(t) 150 151 defer func() { 152 db.Close() 153 os.RemoveAll(dir) 154 }() 155 156 b1 := []byte(time.Now().String()) 157 b2 := []byte("\x00foo\x00bar\x00") 158 if _, err := db.Exec(` 159 create table t(b blob); 160 insert into t values(?), (?); 161 `, b1, b2, 162 ); err != nil { 163 t.Fatal(err) 164 } 165 166 rows, err := db.Query("select * from t") 167 if err != nil { 168 t.Fatal(err) 169 } 170 171 type rec struct { 172 b []byte 173 } 174 var a []rec 175 for rows.Next() { 176 var r rec 177 if err := rows.Scan(&r.b); err != nil { 178 t.Fatal(err) 179 } 180 181 a = append(a, r) 182 } 183 if err := rows.Err(); err != nil { 184 t.Fatal(err) 185 } 186 187 if g, e := len(a), 2; g != e { 188 t.Fatal(g, e) 189 } 190 191 if g, e := a[0].b, b1; !bytes.Equal(g, e) { 192 t.Fatal(g, e) 193 } 194 195 if g, e := a[1].b, b2; !bytes.Equal(g, e) { 196 t.Fatal(g, e) 197 } 198 } 199 200 func BenchmarkInsertMemory(b *testing.B) { 201 db, err := sql.Open(driverName, "file::memory:") 202 if err != nil { 203 b.Fatal(err) 204 } 205 206 defer func() { 207 db.Close() 208 }() 209 210 if _, err := db.Exec(` 211 create table t(i int); 212 begin; 213 `); err != nil { 214 b.Fatal(err) 215 } 216 217 s, err := db.Prepare("insert into t values(?)") 218 if err != nil { 219 b.Fatal(err) 220 } 221 222 b.ResetTimer() 223 for i := 0; i < b.N; i++ { 224 if _, err := s.Exec(int64(i)); err != nil { 225 b.Fatal(err) 226 } 227 } 228 b.StopTimer() 229 if *recsPerSec { 230 b.SetBytes(1e6) 231 } 232 if _, err := db.Exec(`commit;`); err != nil { 233 b.Fatal(err) 234 } 235 } 236 237 func BenchmarkNextMemory(b *testing.B) { 238 db, err := sql.Open(driverName, "file::memory:") 239 if err != nil { 240 b.Fatal(err) 241 } 242 243 defer func() { 244 db.Close() 245 }() 246 247 if _, err := db.Exec(` 248 create table t(i int); 249 begin; 250 `); err != nil { 251 b.Fatal(err) 252 } 253 254 s, err := db.Prepare("insert into t values(?)") 255 if err != nil { 256 b.Fatal(err) 257 } 258 259 defer s.Close() 260 261 for i := 0; i < b.N; i++ { 262 if _, err := s.Exec(int64(i)); err != nil { 263 b.Fatal(err) 264 } 265 } 266 if _, err := db.Exec("commit"); err != nil { 267 b.Fatal(err) 268 } 269 270 r, err := db.Query("select * from t") 271 if err != nil { 272 273 } 274 275 defer r.Close() 276 277 b.ResetTimer() 278 for i := 0; i < b.N; i++ { 279 if !r.Next() { 280 b.Fatal(err) 281 } 282 } 283 b.StopTimer() 284 if *recsPerSec { 285 b.SetBytes(1e6) 286 } 287 } 288 289 // https://gitlab.com/cznic/sqlite/issues/11 290 func TestIssue11(t *testing.T) { 291 const N = 6570 292 dir, db := tempDB(t) 293 294 defer func() { 295 db.Close() 296 os.RemoveAll(dir) 297 }() 298 299 if _, err := db.Exec(` 300 CREATE TABLE t1 (t INT); 301 BEGIN; 302 `, 303 ); err != nil { 304 t.Fatal(err) 305 } 306 307 for i := 0; i < N; i++ { 308 if _, err := db.Exec("INSERT INTO t1 (t) VALUES (?)", i); err != nil { 309 t.Fatalf("#%v: %v", i, err) 310 } 311 } 312 if _, err := db.Exec("COMMIT;"); err != nil { 313 t.Fatal(err) 314 } 315 } 316 317 // https://gitlab.com/cznic/sqlite/issues/12 318 func TestMemDB(t *testing.T) { 319 // Verify we can create out-of-the heap memory DB instance. 320 db, err := sql.Open(driverName, "file::memory:") 321 if err != nil { 322 t.Fatal(err) 323 } 324 325 defer func() { 326 db.Close() 327 }() 328 329 v := strings.Repeat("a", 1024) 330 if _, err := db.Exec(` 331 create table t(s string); 332 begin; 333 `); err != nil { 334 t.Fatal(err) 335 } 336 337 s, err := db.Prepare("insert into t values(?)") 338 if err != nil { 339 t.Fatal(err) 340 } 341 342 // Heap used to be fixed at 32MB. 343 for i := 0; i < (64<<20)/len(v); i++ { 344 if _, err := s.Exec(v); err != nil { 345 t.Fatalf("%v * %v= %v: %v", i, len(v), i*len(v), err) 346 } 347 } 348 if _, err := db.Exec(`commit;`); err != nil { 349 t.Fatal(err) 350 } 351 }