github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/sqlite3/sqlite3_test.go (about) 1 package sqlite3 2 3 import ( 4 "./sqltest" 5 "crypto/rand" 6 "database/sql" 7 "encoding/hex" 8 "os" 9 "path/filepath" 10 "testing" 11 "time" 12 ) 13 14 func TempFilename() string { 15 randBytes := make([]byte, 16) 16 rand.Read(randBytes) 17 return filepath.Join(os.TempDir(), "foo"+hex.EncodeToString(randBytes)+".db") 18 } 19 20 func TestOpen(t *testing.T) { 21 tempFilename := TempFilename() 22 db, err := sql.Open("sqlite3", tempFilename) 23 if err != nil { 24 t.Fatal("Failed to open database:", err) 25 } 26 defer os.Remove(tempFilename) 27 defer db.Close() 28 29 _, err = db.Exec("drop table foo") 30 _, err = db.Exec("create table foo (id integer)") 31 if err != nil { 32 t.Fatal("Failed to create table:", err) 33 } 34 35 if stat, err := os.Stat(tempFilename); err != nil || stat.IsDir() { 36 t.Error("Failed to create ./foo.db") 37 } 38 } 39 40 func TestClose(t *testing.T) { 41 tempFilename := TempFilename() 42 db, err := sql.Open("sqlite3", tempFilename) 43 if err != nil { 44 t.Fatal("Failed to open database:", err) 45 } 46 defer os.Remove(tempFilename) 47 48 _, err = db.Exec("drop table foo") 49 _, err = db.Exec("create table foo (id integer)") 50 if err != nil { 51 t.Fatal("Failed to create table:", err) 52 } 53 54 stmt, err := db.Prepare("select id from foo where id = ?") 55 if err != nil { 56 t.Fatal("Failed to select records:", err) 57 } 58 59 db.Close() 60 _, err = stmt.Exec(1) 61 if err == nil { 62 t.Fatal("Failed to operate closed statement") 63 } 64 } 65 66 func TestInsert(t *testing.T) { 67 tempFilename := TempFilename() 68 db, err := sql.Open("sqlite3", tempFilename) 69 if err != nil { 70 t.Fatal("Failed to open database:", err) 71 } 72 defer os.Remove(tempFilename) 73 defer db.Close() 74 75 _, err = db.Exec("drop table foo") 76 _, err = db.Exec("create table foo (id integer)") 77 if err != nil { 78 t.Fatal("Failed to create table:", err) 79 } 80 81 res, err := db.Exec("insert into foo(id) values(123)") 82 if err != nil { 83 t.Fatal("Failed to insert record:", err) 84 } 85 affected, _ := res.RowsAffected() 86 if affected != 1 { 87 t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) 88 } 89 90 rows, err := db.Query("select id from foo") 91 if err != nil { 92 t.Fatal("Failed to select records:", err) 93 } 94 defer rows.Close() 95 96 rows.Next() 97 98 var result int 99 rows.Scan(&result) 100 if result != 123 { 101 t.Errorf("Fetched %q; expected %q", 123, result) 102 } 103 } 104 105 func TestUpdate(t *testing.T) { 106 tempFilename := TempFilename() 107 db, err := sql.Open("sqlite3", tempFilename) 108 if err != nil { 109 t.Fatal("Failed to open database:", err) 110 } 111 defer os.Remove(tempFilename) 112 defer db.Close() 113 114 _, err = db.Exec("drop table foo") 115 _, err = db.Exec("create table foo (id integer)") 116 if err != nil { 117 t.Fatal("Failed to create table:", err) 118 } 119 120 res, err := db.Exec("insert into foo(id) values(123)") 121 if err != nil { 122 t.Fatal("Failed to insert record:", err) 123 } 124 expected, err := res.LastInsertId() 125 if err != nil { 126 t.Fatal("Failed to get LastInsertId:", err) 127 } 128 affected, _ := res.RowsAffected() 129 if err != nil { 130 t.Fatal("Failed to get RowsAffected:", err) 131 } 132 if affected != 1 { 133 t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) 134 } 135 136 res, err = db.Exec("update foo set id = 234") 137 if err != nil { 138 t.Fatal("Failed to update record:", err) 139 } 140 lastId, err := res.LastInsertId() 141 if err != nil { 142 t.Fatal("Failed to get LastInsertId:", err) 143 } 144 if expected != lastId { 145 t.Errorf("Expected %q for last Id, but %q:", expected, lastId) 146 } 147 affected, _ = res.RowsAffected() 148 if err != nil { 149 t.Fatal("Failed to get RowsAffected:", err) 150 } 151 if affected != 1 { 152 t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) 153 } 154 155 rows, err := db.Query("select id from foo") 156 if err != nil { 157 t.Fatal("Failed to select records:", err) 158 } 159 defer rows.Close() 160 161 rows.Next() 162 163 var result int 164 rows.Scan(&result) 165 if result != 234 { 166 t.Errorf("Fetched %q; expected %q", 234, result) 167 } 168 } 169 170 func TestDelete(t *testing.T) { 171 tempFilename := TempFilename() 172 db, err := sql.Open("sqlite3", tempFilename) 173 if err != nil { 174 t.Fatal("Failed to open database:", err) 175 } 176 defer os.Remove(tempFilename) 177 defer db.Close() 178 179 _, err = db.Exec("drop table foo") 180 _, err = db.Exec("create table foo (id integer)") 181 if err != nil { 182 t.Fatal("Failed to create table:", err) 183 } 184 185 res, err := db.Exec("insert into foo(id) values(123)") 186 if err != nil { 187 t.Fatal("Failed to insert record:", err) 188 } 189 expected, err := res.LastInsertId() 190 if err != nil { 191 t.Fatal("Failed to get LastInsertId:", err) 192 } 193 affected, err := res.RowsAffected() 194 if err != nil { 195 t.Fatal("Failed to get RowsAffected:", err) 196 } 197 if affected != 1 { 198 t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected) 199 } 200 201 res, err = db.Exec("delete from foo where id = 123") 202 if err != nil { 203 t.Fatal("Failed to delete record:", err) 204 } 205 lastId, err := res.LastInsertId() 206 if err != nil { 207 t.Fatal("Failed to get LastInsertId:", err) 208 } 209 if expected != lastId { 210 t.Errorf("Expected %q for last Id, but %q:", expected, lastId) 211 } 212 affected, err = res.RowsAffected() 213 if err != nil { 214 t.Fatal("Failed to get RowsAffected:", err) 215 } 216 if affected != 1 { 217 t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected) 218 } 219 220 rows, err := db.Query("select id from foo") 221 if err != nil { 222 t.Fatal("Failed to select records:", err) 223 } 224 defer rows.Close() 225 226 if rows.Next() { 227 t.Error("Fetched row but expected not rows") 228 } 229 } 230 231 func TestBooleanRoundtrip(t *testing.T) { 232 tempFilename := TempFilename() 233 db, err := sql.Open("sqlite3", tempFilename) 234 if err != nil { 235 t.Fatal("Failed to open database:", err) 236 } 237 defer os.Remove(tempFilename) 238 defer db.Close() 239 240 _, err = db.Exec("DROP TABLE foo") 241 _, err = db.Exec("CREATE TABLE foo(id INTEGER, value BOOL)") 242 if err != nil { 243 t.Fatal("Failed to create table:", err) 244 } 245 246 _, err = db.Exec("INSERT INTO foo(id, value) VALUES(1, ?)", true) 247 if err != nil { 248 t.Fatal("Failed to insert true value:", err) 249 } 250 251 _, err = db.Exec("INSERT INTO foo(id, value) VALUES(2, ?)", false) 252 if err != nil { 253 t.Fatal("Failed to insert false value:", err) 254 } 255 256 rows, err := db.Query("SELECT id, value FROM foo") 257 if err != nil { 258 t.Fatal("Unable to query foo table:", err) 259 } 260 defer rows.Close() 261 262 for rows.Next() { 263 var id int 264 var value bool 265 266 if err := rows.Scan(&id, &value); err != nil { 267 t.Error("Unable to scan results:", err) 268 continue 269 } 270 271 if id == 1 && !value { 272 t.Error("Value for id 1 should be true, not false") 273 274 } else if id == 2 && value { 275 t.Error("Value for id 2 should be false, not true") 276 } 277 } 278 } 279 280 func TestTimestamp(t *testing.T) { 281 tempFilename := TempFilename() 282 db, err := sql.Open("sqlite3", tempFilename) 283 if err != nil { 284 t.Fatal("Failed to open database:", err) 285 } 286 defer os.Remove(tempFilename) 287 defer db.Close() 288 289 _, err = db.Exec("DROP TABLE foo") 290 _, err = db.Exec("CREATE TABLE foo(id INTEGER, ts timeSTAMP, dt DATETIME)") 291 if err != nil { 292 t.Fatal("Failed to create table:", err) 293 } 294 295 timestamp1 := time.Date(2012, time.April, 6, 22, 50, 0, 0, time.UTC) 296 timestamp2 := time.Date(2006, time.January, 2, 15, 4, 5, 123456789, time.UTC) 297 timestamp3 := time.Date(2012, time.November, 4, 0, 0, 0, 0, time.UTC) 298 tests := []struct { 299 value interface{} 300 expected time.Time 301 }{ 302 {"nonsense", time.Time{}}, 303 {"0000-00-00 00:00:00", time.Time{}}, 304 {timestamp1, timestamp1}, 305 {timestamp1.Unix(), timestamp1}, 306 {timestamp1.In(time.FixedZone("TEST", -7*3600)), timestamp1}, 307 {timestamp1.Format("2006-01-02 15:04:05.000"), timestamp1}, 308 {timestamp1.Format("2006-01-02T15:04:05.000"), timestamp1}, 309 {timestamp1.Format("2006-01-02 15:04:05"), timestamp1}, 310 {timestamp1.Format("2006-01-02T15:04:05"), timestamp1}, 311 {timestamp2, timestamp2}, 312 {"2006-01-02 15:04:05.123456789", timestamp2}, 313 {"2006-01-02T15:04:05.123456789", timestamp2}, 314 {"2012-11-04", timestamp3}, 315 {"2012-11-04 00:00", timestamp3}, 316 {"2012-11-04 00:00:00", timestamp3}, 317 {"2012-11-04 00:00:00.000", timestamp3}, 318 {"2012-11-04T00:00", timestamp3}, 319 {"2012-11-04T00:00:00", timestamp3}, 320 {"2012-11-04T00:00:00.000", timestamp3}, 321 } 322 for i := range tests { 323 _, err = db.Exec("INSERT INTO foo(id, ts, dt) VALUES(?, ?, ?)", i, tests[i].value, tests[i].value) 324 if err != nil { 325 t.Fatal("Failed to insert timestamp:", err) 326 } 327 } 328 329 rows, err := db.Query("SELECT id, ts, dt FROM foo ORDER BY id ASC") 330 if err != nil { 331 t.Fatal("Unable to query foo table:", err) 332 } 333 defer rows.Close() 334 335 seen := 0 336 for rows.Next() { 337 var id int 338 var ts, dt time.Time 339 340 if err := rows.Scan(&id, &ts, &dt); err != nil { 341 t.Error("Unable to scan results:", err) 342 continue 343 } 344 if id < 0 || id >= len(tests) { 345 t.Error("Bad row id: ", id) 346 continue 347 } 348 seen++ 349 if !tests[id].expected.Equal(ts) { 350 t.Errorf("Timestamp value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) 351 } 352 if !tests[id].expected.Equal(dt) { 353 t.Errorf("Datetime value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) 354 } 355 } 356 357 if seen != len(tests) { 358 t.Errorf("Expected to see %d rows", len(tests)) 359 } 360 } 361 362 func TestBoolean(t *testing.T) { 363 tempFilename := TempFilename() 364 db, err := sql.Open("sqlite3", tempFilename) 365 if err != nil { 366 t.Fatal("Failed to open database:", err) 367 } 368 369 defer os.Remove(tempFilename) 370 defer db.Close() 371 372 _, err = db.Exec("CREATE TABLE foo(id INTEGER, fbool BOOLEAN)") 373 if err != nil { 374 t.Fatal("Failed to create table:", err) 375 } 376 377 bool1 := true 378 _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(1, ?)", bool1) 379 if err != nil { 380 t.Fatal("Failed to insert boolean:", err) 381 } 382 383 bool2 := false 384 _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(2, ?)", bool2) 385 if err != nil { 386 t.Fatal("Failed to insert boolean:", err) 387 } 388 389 bool3 := "nonsense" 390 _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(3, ?)", bool3) 391 if err != nil { 392 t.Fatal("Failed to insert nonsense:", err) 393 } 394 395 rows, err := db.Query("SELECT id, fbool FROM foo where fbool = ?", bool1) 396 if err != nil { 397 t.Fatal("Unable to query foo table:", err) 398 } 399 counter := 0 400 401 var id int 402 var fbool bool 403 404 for rows.Next() { 405 if err := rows.Scan(&id, &fbool); err != nil { 406 t.Fatal("Unable to scan results:", err) 407 } 408 counter++ 409 } 410 411 if counter != 1 { 412 t.Fatalf("Expected 1 row but %v", counter) 413 } 414 415 if id != 1 && fbool != true { 416 t.Fatalf("Value for id 1 should be %v, not %v", bool1, fbool) 417 } 418 419 rows, err = db.Query("SELECT id, fbool FROM foo where fbool = ?", bool2) 420 if err != nil { 421 t.Fatal("Unable to query foo table:", err) 422 } 423 424 counter = 0 425 426 for rows.Next() { 427 if err := rows.Scan(&id, &fbool); err != nil { 428 t.Fatal("Unable to scan results:", err) 429 } 430 counter++ 431 } 432 433 if counter != 1 { 434 t.Fatalf("Expected 1 row but %v", counter) 435 } 436 437 if id != 2 && fbool != false { 438 t.Fatalf("Value for id 2 should be %v, not %v", bool2, fbool) 439 } 440 441 // make sure "nonsense" triggered an error 442 rows, err = db.Query("SELECT id, fbool FROM foo where id=?;", 3) 443 if err != nil { 444 t.Fatal("Unable to query foo table:", err) 445 } 446 447 rows.Next() 448 err = rows.Scan(&id, &fbool) 449 if err == nil { 450 t.Error("Expected error from \"nonsense\" bool") 451 } 452 } 453 454 func TestFloat32(t *testing.T) { 455 tempFilename := TempFilename() 456 db, err := sql.Open("sqlite3", tempFilename) 457 if err != nil { 458 t.Fatal("Failed to open database:", err) 459 } 460 461 defer os.Remove(tempFilename) 462 defer db.Close() 463 464 _, err = db.Exec("CREATE TABLE foo(id INTEGER)") 465 if err != nil { 466 t.Fatal("Failed to create table:", err) 467 } 468 469 _, err = db.Exec("INSERT INTO foo(id) VALUES(null)") 470 if err != nil { 471 t.Fatal("Failed to insert null:", err) 472 } 473 474 rows, err := db.Query("SELECT id FROM foo") 475 if err != nil { 476 t.Fatal("Unable to query foo table:", err) 477 } 478 479 if !rows.Next() { 480 t.Fatal("Unable to query results:", err) 481 } 482 483 var id interface{} 484 if err := rows.Scan(&id); err != nil { 485 t.Fatal("Unable to scan results:", err) 486 } 487 if id != nil { 488 t.Error("Expected nil but not") 489 } 490 } 491 492 func TestNull(t *testing.T) { 493 tempFilename := TempFilename() 494 db, err := sql.Open("sqlite3", tempFilename) 495 if err != nil { 496 t.Fatal("Failed to open database:", err) 497 } 498 499 defer os.Remove(tempFilename) 500 defer db.Close() 501 502 rows, err := db.Query("SELECT 3.141592") 503 if err != nil { 504 t.Fatal("Unable to query foo table:", err) 505 } 506 507 if !rows.Next() { 508 t.Fatal("Unable to query results:", err) 509 } 510 511 var v interface{} 512 if err := rows.Scan(&v); err != nil { 513 t.Fatal("Unable to scan results:", err) 514 } 515 f, ok := v.(float64) 516 if !ok { 517 t.Error("Expected float but not") 518 } 519 if f != 3.141592 { 520 t.Error("Expected 3.141592 but not") 521 } 522 } 523 524 func TestTransaction(t *testing.T) { 525 tempFilename := TempFilename() 526 db, err := sql.Open("sqlite3", tempFilename) 527 if err != nil { 528 t.Fatal("Failed to open database:", err) 529 } 530 531 defer os.Remove(tempFilename) 532 defer db.Close() 533 534 _, err = db.Exec("CREATE TABLE foo(id INTEGER)") 535 if err != nil { 536 t.Fatal("Failed to create table:", err) 537 } 538 539 tx, err := db.Begin() 540 if err != nil { 541 t.Fatal("Failed to begin transaction:", err) 542 } 543 544 _, err = tx.Exec("INSERT INTO foo(id) VALUES(1)") 545 if err != nil { 546 t.Fatal("Failed to insert null:", err) 547 } 548 549 rows, err := tx.Query("SELECT id from foo") 550 if err != nil { 551 t.Fatal("Unable to query foo table:", err) 552 } 553 554 err = tx.Rollback() 555 if err != nil { 556 t.Fatal("Failed to rollback transaction:", err) 557 } 558 559 if rows.Next() { 560 t.Fatal("Unable to query results:", err) 561 } 562 563 tx, err = db.Begin() 564 if err != nil { 565 t.Fatal("Failed to begin transaction:", err) 566 } 567 568 _, err = tx.Exec("INSERT INTO foo(id) VALUES(1)") 569 if err != nil { 570 t.Fatal("Failed to insert null:", err) 571 } 572 573 err = tx.Commit() 574 if err != nil { 575 t.Fatal("Failed to commit transaction:", err) 576 } 577 578 rows, err = tx.Query("SELECT id from foo") 579 if err == nil { 580 t.Fatal("Expected failure to query") 581 } 582 } 583 584 func TestWAL(t *testing.T) { 585 tempFilename := TempFilename() 586 db, err := sql.Open("sqlite3", tempFilename) 587 if err != nil { 588 t.Fatal("Failed to open database:", err) 589 } 590 591 defer os.Remove(tempFilename) 592 defer db.Close() 593 if _, err = db.Exec("PRAGMA journal_mode=WAL;"); err != nil { 594 t.Fatal("Failed to Exec PRAGMA journal_mode:", err) 595 } 596 if _, err = db.Exec("PRAGMA locking_mode=EXCLUSIVE;"); err != nil { 597 t.Fatal("Failed to Exec PRAGMA locking_mode:", err) 598 } 599 if _, err = db.Exec("CREATE TABLE test (id SERIAL, user TEXT NOT NULL, name TEXT NOT NULL);"); err != nil { 600 t.Fatal("Failed to Exec CREATE TABLE:", err) 601 } 602 if _, err = db.Exec("INSERT INTO test (user, name) VALUES ('user','name');"); err != nil { 603 t.Fatal("Failed to Exec INSERT:", err) 604 } 605 606 trans, err := db.Begin() 607 if err != nil { 608 t.Fatal("Failed to Begin:", err) 609 } 610 s, err := trans.Prepare("INSERT INTO test (user, name) VALUES (?, ?);") 611 if err != nil { 612 t.Fatal("Failed to Prepare:", err) 613 } 614 615 var count int 616 if err = trans.QueryRow("SELECT count(user) FROM test;").Scan(&count); err != nil { 617 t.Fatal("Failed to QueryRow:", err) 618 } 619 if _, err = s.Exec("bbbb", "aaaa"); err != nil { 620 t.Fatal("Failed to Exec prepared statement:", err) 621 } 622 if err = s.Close(); err != nil { 623 t.Fatal("Failed to Close prepared statement:", err) 624 } 625 if err = trans.Commit(); err != nil { 626 t.Fatal("Failed to Commit:", err) 627 } 628 } 629 630 func TestSuite(t *testing.T) { 631 db, err := sql.Open("sqlite3", ":memory:") 632 if err != nil { 633 t.Fatal(err) 634 } 635 defer db.Close() 636 637 sqltest.RunTests(t, db, sqltest.SQLITE) 638 } 639 640 // TODO: Execer & Queryer currently disabled 641 // https://github.com/mattn/go-sqlite3/issues/82 642 //func TestExecer(t *testing.T) { 643 // tempFilename := TempFilename() 644 // db, err := sql.Open("sqlite3", tempFilename) 645 // if err != nil { 646 // t.Fatal("Failed to open database:", err) 647 // } 648 // defer os.Remove(tempFilename) 649 // defer db.Close() 650 // 651 // _, err = db.Exec(` 652 // create table foo (id integer); 653 // insert into foo(id) values(?); 654 // insert into foo(id) values(?); 655 // insert into foo(id) values(?); 656 // `, 1, 2, 3) 657 // if err != nil { 658 // t.Error("Failed to call db.Exec:", err) 659 // } 660 // if err != nil { 661 // t.Error("Failed to call res.RowsAffected:", err) 662 // } 663 //} 664 // 665 //func TestQueryer(t *testing.T) { 666 // tempFilename := TempFilename() 667 // db, err := sql.Open("sqlite3", tempFilename) 668 // if err != nil { 669 // t.Fatal("Failed to open database:", err) 670 // } 671 // defer os.Remove(tempFilename) 672 // defer db.Close() 673 // 674 // _, err = db.Exec(` 675 // create table foo (id integer); 676 // `) 677 // if err != nil { 678 // t.Error("Failed to call db.Query:", err) 679 // } 680 // 681 // rows, err := db.Query(` 682 // insert into foo(id) values(?); 683 // insert into foo(id) values(?); 684 // insert into foo(id) values(?); 685 // select id from foo order by id; 686 // `, 3, 2, 1) 687 // if err != nil { 688 // t.Error("Failed to call db.Query:", err) 689 // } 690 // defer rows.Close() 691 // n := 1 692 // if rows != nil { 693 // for rows.Next() { 694 // var id int 695 // err = rows.Scan(&id) 696 // if err != nil { 697 // t.Error("Failed to db.Query:", err) 698 // } 699 // if id != n { 700 // t.Error("Failed to db.Query: not matched results") 701 // } 702 // } 703 // } 704 //}