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 }