github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/lib/pq/conn_test.go (about) 1 package pq 2 3 import ( 4 "database/sql" 5 "database/sql/driver" 6 "fmt" 7 "io" 8 "os" 9 "reflect" 10 "strings" 11 "testing" 12 "time" 13 ) 14 15 type Fatalistic interface { 16 Fatal(args ...interface{}) 17 } 18 19 func forceBinaryParameters() bool { 20 bp := os.Getenv("PQTEST_BINARY_PARAMETERS") 21 if bp == "yes" { 22 return true 23 } else if bp == "" || bp == "no" { 24 return false 25 } else { 26 panic("unexpected value for PQTEST_BINARY_PARAMETERS") 27 } 28 } 29 30 func openTestConnConninfo(conninfo string) (*sql.DB, error) { 31 defaultTo := func(envvar string, value string) { 32 if os.Getenv(envvar) == "" { 33 os.Setenv(envvar, value) 34 } 35 } 36 defaultTo("PGDATABASE", "pqgotest") 37 defaultTo("PGSSLMODE", "disable") 38 defaultTo("PGCONNECT_TIMEOUT", "20") 39 40 if forceBinaryParameters() && 41 !strings.HasPrefix(conninfo, "postgres://") && 42 !strings.HasPrefix(conninfo, "postgresql://") { 43 conninfo = conninfo + " binary_parameters=yes" 44 } 45 46 return sql.Open("postgres", conninfo) 47 } 48 49 func openTestConn(t Fatalistic) *sql.DB { 50 conn, err := openTestConnConninfo("") 51 if err != nil { 52 t.Fatal(err) 53 } 54 55 return conn 56 } 57 58 func getServerVersion(t *testing.T, db *sql.DB) int { 59 var version int 60 err := db.QueryRow("SHOW server_version_num").Scan(&version) 61 if err != nil { 62 t.Fatal(err) 63 } 64 return version 65 } 66 67 func TestReconnect(t *testing.T) { 68 db1 := openTestConn(t) 69 defer db1.Close() 70 tx, err := db1.Begin() 71 if err != nil { 72 t.Fatal(err) 73 } 74 var pid1 int 75 err = tx.QueryRow("SELECT pg_backend_pid()").Scan(&pid1) 76 if err != nil { 77 t.Fatal(err) 78 } 79 db2 := openTestConn(t) 80 defer db2.Close() 81 _, err = db2.Exec("SELECT pg_terminate_backend($1)", pid1) 82 if err != nil { 83 t.Fatal(err) 84 } 85 // The rollback will probably "fail" because we just killed 86 // its connection above 87 _ = tx.Rollback() 88 89 const expected int = 42 90 var result int 91 err = db1.QueryRow(fmt.Sprintf("SELECT %d", expected)).Scan(&result) 92 if err != nil { 93 t.Fatal(err) 94 } 95 if result != expected { 96 t.Errorf("got %v; expected %v", result, expected) 97 } 98 } 99 100 func TestCommitInFailedTransaction(t *testing.T) { 101 db := openTestConn(t) 102 defer db.Close() 103 104 txn, err := db.Begin() 105 if err != nil { 106 t.Fatal(err) 107 } 108 rows, err := txn.Query("SELECT error") 109 if err == nil { 110 rows.Close() 111 t.Fatal("expected failure") 112 } 113 err = txn.Commit() 114 if err != ErrInFailedTransaction { 115 t.Fatalf("expected ErrInFailedTransaction; got %#v", err) 116 } 117 } 118 119 func TestOpenURL(t *testing.T) { 120 testURL := func(url string) { 121 db, err := openTestConnConninfo(url) 122 if err != nil { 123 t.Fatal(err) 124 } 125 defer db.Close() 126 // database/sql might not call our Open at all unless we do something with 127 // the connection 128 txn, err := db.Begin() 129 if err != nil { 130 t.Fatal(err) 131 } 132 txn.Rollback() 133 } 134 testURL("postgres://") 135 testURL("postgresql://") 136 } 137 138 const pgpass_file = "/tmp/pqgotest_pgpass" 139 func TestPgpass(t *testing.T) { 140 testAssert := func(conninfo string, expected string, reason string) { 141 conn, err := openTestConnConninfo(conninfo) 142 if err != nil { 143 t.Fatal(err) 144 } 145 defer conn.Close() 146 147 txn, err := conn.Begin() 148 if err != nil { 149 if expected != "fail" { 150 t.Fatalf(reason, err) 151 } 152 return 153 } 154 rows, err := txn.Query("SELECT USER") 155 if err != nil { 156 txn.Rollback() 157 rows.Close() 158 if expected != "fail" { 159 t.Fatalf(reason, err) 160 } 161 } else { 162 if expected != "ok" { 163 t.Fatalf(reason, err) 164 } 165 } 166 txn.Rollback() 167 } 168 testAssert("", "ok", "missing .pgpass, unexpected error %#v") 169 os.Setenv("PGPASSFILE", pgpass_file) 170 testAssert("host=/tmp", "fail", ", unexpected error %#v") 171 os.Remove(pgpass_file) 172 pgpass, err := os.OpenFile(pgpass_file, os.O_RDWR|os.O_CREATE, 0644) 173 if err != nil { 174 t.Fatalf("Unexpected error writing pgpass file %#v", err) 175 } 176 _, err = pgpass.WriteString(`# comment 177 server:5432:some_db:some_user:pass_A 178 *:5432:some_db:some_user:pass_B 179 localhost:*:*:*:pass_C 180 *:*:*:*:pass_fallback 181 `) 182 if err != nil { 183 t.Fatalf("Unexpected error writing pgpass file %#v", err) 184 } 185 pgpass.Close() 186 187 assertPassword := func(extra values, expected string) { 188 o := &values{"host": "localhost", "sslmode": "disable", "connect_timeout": "20", "user": "majid", "port": "5432", "extra_float_digits": "2", "dbname": "pqgotest", "client_encoding": "UTF8", "datestyle": "ISO, MDY"} 189 for k, v := range extra { 190 (*o)[k] = v 191 } 192 (&conn{}).handlePgpass(*o) 193 if o.Get("password") != expected { 194 t.Fatalf("For %v expected %s got %s", extra, expected, o.Get("password")) 195 } 196 } 197 // wrong permissions for the pgpass file means it should be ignored 198 assertPassword(values{"host": "example.com", "user": "foo"}, "") 199 // fix the permissions and check if it has taken effect 200 os.Chmod(pgpass_file, 0600) 201 assertPassword(values{"host": "server", "dbname": "some_db", "user": "some_user"}, "pass_A") 202 assertPassword(values{"host": "example.com", "user": "foo"}, "pass_fallback") 203 assertPassword(values{"host": "example.com", "dbname": "some_db", "user": "some_user"}, "pass_B") 204 // localhost also matches the default "" and UNIX sockets 205 assertPassword(values{"host": "", "user": "some_user"}, "pass_C") 206 assertPassword(values{"host": "/tmp", "user": "some_user"}, "pass_C") 207 // cleanup 208 os.Remove(pgpass_file) 209 os.Setenv("PGPASSFILE", "") 210 } 211 212 func TestExec(t *testing.T) { 213 db := openTestConn(t) 214 defer db.Close() 215 216 _, err := db.Exec("CREATE TEMP TABLE temp (a int)") 217 if err != nil { 218 t.Fatal(err) 219 } 220 221 r, err := db.Exec("INSERT INTO temp VALUES (1)") 222 if err != nil { 223 t.Fatal(err) 224 } 225 226 if n, _ := r.RowsAffected(); n != 1 { 227 t.Fatalf("expected 1 row affected, not %d", n) 228 } 229 230 r, err = db.Exec("INSERT INTO temp VALUES ($1), ($2), ($3)", 1, 2, 3) 231 if err != nil { 232 t.Fatal(err) 233 } 234 235 if n, _ := r.RowsAffected(); n != 3 { 236 t.Fatalf("expected 3 rows affected, not %d", n) 237 } 238 239 // SELECT doesn't send the number of returned rows in the command tag 240 // before 9.0 241 if getServerVersion(t, db) >= 90000 { 242 r, err = db.Exec("SELECT g FROM generate_series(1, 2) g") 243 if err != nil { 244 t.Fatal(err) 245 } 246 if n, _ := r.RowsAffected(); n != 2 { 247 t.Fatalf("expected 2 rows affected, not %d", n) 248 } 249 250 r, err = db.Exec("SELECT g FROM generate_series(1, $1) g", 3) 251 if err != nil { 252 t.Fatal(err) 253 } 254 if n, _ := r.RowsAffected(); n != 3 { 255 t.Fatalf("expected 3 rows affected, not %d", n) 256 } 257 } 258 } 259 260 func TestStatment(t *testing.T) { 261 db := openTestConn(t) 262 defer db.Close() 263 264 st, err := db.Prepare("SELECT 1") 265 if err != nil { 266 t.Fatal(err) 267 } 268 269 st1, err := db.Prepare("SELECT 2") 270 if err != nil { 271 t.Fatal(err) 272 } 273 274 r, err := st.Query() 275 if err != nil { 276 t.Fatal(err) 277 } 278 defer r.Close() 279 280 if !r.Next() { 281 t.Fatal("expected row") 282 } 283 284 var i int 285 err = r.Scan(&i) 286 if err != nil { 287 t.Fatal(err) 288 } 289 290 if i != 1 { 291 t.Fatalf("expected 1, got %d", i) 292 } 293 294 // st1 295 296 r1, err := st1.Query() 297 if err != nil { 298 t.Fatal(err) 299 } 300 defer r1.Close() 301 302 if !r1.Next() { 303 if r.Err() != nil { 304 t.Fatal(r1.Err()) 305 } 306 t.Fatal("expected row") 307 } 308 309 err = r1.Scan(&i) 310 if err != nil { 311 t.Fatal(err) 312 } 313 314 if i != 2 { 315 t.Fatalf("expected 2, got %d", i) 316 } 317 } 318 319 func TestRowsCloseBeforeDone(t *testing.T) { 320 db := openTestConn(t) 321 defer db.Close() 322 323 r, err := db.Query("SELECT 1") 324 if err != nil { 325 t.Fatal(err) 326 } 327 328 err = r.Close() 329 if err != nil { 330 t.Fatal(err) 331 } 332 333 if r.Next() { 334 t.Fatal("unexpected row") 335 } 336 337 if r.Err() != nil { 338 t.Fatal(r.Err()) 339 } 340 } 341 342 func TestParameterCountMismatch(t *testing.T) { 343 db := openTestConn(t) 344 defer db.Close() 345 346 var notused int 347 err := db.QueryRow("SELECT false", 1).Scan(¬used) 348 if err == nil { 349 t.Fatal("expected err") 350 } 351 // make sure we clean up correctly 352 err = db.QueryRow("SELECT 1").Scan(¬used) 353 if err != nil { 354 t.Fatal(err) 355 } 356 357 err = db.QueryRow("SELECT $1").Scan(¬used) 358 if err == nil { 359 t.Fatal("expected err") 360 } 361 // make sure we clean up correctly 362 err = db.QueryRow("SELECT 1").Scan(¬used) 363 if err != nil { 364 t.Fatal(err) 365 } 366 } 367 368 // Test that EmptyQueryResponses are handled correctly. 369 func TestEmptyQuery(t *testing.T) { 370 db := openTestConn(t) 371 defer db.Close() 372 373 _, err := db.Exec("") 374 if err != nil { 375 t.Fatal(err) 376 } 377 rows, err := db.Query("") 378 if err != nil { 379 t.Fatal(err) 380 } 381 cols, err := rows.Columns() 382 if err != nil { 383 t.Fatal(err) 384 } 385 if len(cols) != 0 { 386 t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) 387 } 388 if rows.Next() { 389 t.Fatal("unexpected row") 390 } 391 if rows.Err() != nil { 392 t.Fatal(rows.Err()) 393 } 394 395 stmt, err := db.Prepare("") 396 if err != nil { 397 t.Fatal(err) 398 } 399 _, err = stmt.Exec() 400 if err != nil { 401 t.Fatal(err) 402 } 403 rows, err = stmt.Query() 404 if err != nil { 405 t.Fatal(err) 406 } 407 cols, err = rows.Columns() 408 if err != nil { 409 t.Fatal(err) 410 } 411 if len(cols) != 0 { 412 t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) 413 } 414 if rows.Next() { 415 t.Fatal("unexpected row") 416 } 417 if rows.Err() != nil { 418 t.Fatal(rows.Err()) 419 } 420 } 421 422 // Test that rows.Columns() is correct even if there are no result rows. 423 func TestEmptyResultSetColumns(t *testing.T) { 424 db := openTestConn(t) 425 defer db.Close() 426 427 rows, err := db.Query("SELECT 1 AS a, text 'bar' AS bar WHERE FALSE") 428 if err != nil { 429 t.Fatal(err) 430 } 431 cols, err := rows.Columns() 432 if err != nil { 433 t.Fatal(err) 434 } 435 if len(cols) != 2 { 436 t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) 437 } 438 if rows.Next() { 439 t.Fatal("unexpected row") 440 } 441 if rows.Err() != nil { 442 t.Fatal(rows.Err()) 443 } 444 if cols[0] != "a" || cols[1] != "bar" { 445 t.Fatalf("unexpected Columns result %v", cols) 446 } 447 448 stmt, err := db.Prepare("SELECT $1::int AS a, text 'bar' AS bar WHERE FALSE") 449 if err != nil { 450 t.Fatal(err) 451 } 452 rows, err = stmt.Query(1) 453 if err != nil { 454 t.Fatal(err) 455 } 456 cols, err = rows.Columns() 457 if err != nil { 458 t.Fatal(err) 459 } 460 if len(cols) != 2 { 461 t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) 462 } 463 if rows.Next() { 464 t.Fatal("unexpected row") 465 } 466 if rows.Err() != nil { 467 t.Fatal(rows.Err()) 468 } 469 if cols[0] != "a" || cols[1] != "bar" { 470 t.Fatalf("unexpected Columns result %v", cols) 471 } 472 473 } 474 475 func TestEncodeDecode(t *testing.T) { 476 db := openTestConn(t) 477 defer db.Close() 478 479 q := ` 480 SELECT 481 E'\\000\\001\\002'::bytea, 482 'foobar'::text, 483 NULL::integer, 484 '2000-1-1 01:02:03.04-7'::timestamptz, 485 0::boolean, 486 123, 487 -321, 488 3.14::float8 489 WHERE 490 E'\\000\\001\\002'::bytea = $1 491 AND 'foobar'::text = $2 492 AND $3::integer is NULL 493 ` 494 // AND '2000-1-1 12:00:00.000000-7'::timestamp = $3 495 496 exp1 := []byte{0, 1, 2} 497 exp2 := "foobar" 498 499 r, err := db.Query(q, exp1, exp2, nil) 500 if err != nil { 501 t.Fatal(err) 502 } 503 defer r.Close() 504 505 if !r.Next() { 506 if r.Err() != nil { 507 t.Fatal(r.Err()) 508 } 509 t.Fatal("expected row") 510 } 511 512 var got1 []byte 513 var got2 string 514 var got3 = sql.NullInt64{Valid: true} 515 var got4 time.Time 516 var got5, got6, got7, got8 interface{} 517 518 err = r.Scan(&got1, &got2, &got3, &got4, &got5, &got6, &got7, &got8) 519 if err != nil { 520 t.Fatal(err) 521 } 522 523 if !reflect.DeepEqual(exp1, got1) { 524 t.Errorf("expected %q byte: %q", exp1, got1) 525 } 526 527 if !reflect.DeepEqual(exp2, got2) { 528 t.Errorf("expected %q byte: %q", exp2, got2) 529 } 530 531 if got3.Valid { 532 t.Fatal("expected invalid") 533 } 534 535 if got4.Year() != 2000 { 536 t.Fatal("wrong year") 537 } 538 539 if got5 != false { 540 t.Fatalf("expected false, got %q", got5) 541 } 542 543 if got6 != int64(123) { 544 t.Fatalf("expected 123, got %d", got6) 545 } 546 547 if got7 != int64(-321) { 548 t.Fatalf("expected -321, got %d", got7) 549 } 550 551 if got8 != float64(3.14) { 552 t.Fatalf("expected 3.14, got %f", got8) 553 } 554 } 555 556 func TestNoData(t *testing.T) { 557 db := openTestConn(t) 558 defer db.Close() 559 560 st, err := db.Prepare("SELECT 1 WHERE true = false") 561 if err != nil { 562 t.Fatal(err) 563 } 564 defer st.Close() 565 566 r, err := st.Query() 567 if err != nil { 568 t.Fatal(err) 569 } 570 defer r.Close() 571 572 if r.Next() { 573 if r.Err() != nil { 574 t.Fatal(r.Err()) 575 } 576 t.Fatal("unexpected row") 577 } 578 579 _, err = db.Query("SELECT * FROM nonexistenttable WHERE age=$1", 20) 580 if err == nil { 581 t.Fatal("Should have raised an error on non existent table") 582 } 583 584 _, err = db.Query("SELECT * FROM nonexistenttable") 585 if err == nil { 586 t.Fatal("Should have raised an error on non existent table") 587 } 588 } 589 590 func TestErrorDuringStartup(t *testing.T) { 591 // Don't use the normal connection setup, this is intended to 592 // blow up in the startup packet from a non-existent user. 593 db, err := openTestConnConninfo("user=thisuserreallydoesntexist") 594 if err != nil { 595 t.Fatal(err) 596 } 597 defer db.Close() 598 599 _, err = db.Begin() 600 if err == nil { 601 t.Fatal("expected error") 602 } 603 604 e, ok := err.(*Error) 605 if !ok { 606 t.Fatalf("expected Error, got %#v", err) 607 } else if e.Code.Name() != "invalid_authorization_specification" && e.Code.Name() != "invalid_password" { 608 t.Fatalf("expected invalid_authorization_specification or invalid_password, got %s (%+v)", e.Code.Name(), err) 609 } 610 } 611 612 func TestBadConn(t *testing.T) { 613 var err error 614 615 cn := conn{} 616 func() { 617 defer cn.errRecover(&err) 618 panic(io.EOF) 619 }() 620 if err != driver.ErrBadConn { 621 t.Fatalf("expected driver.ErrBadConn, got: %#v", err) 622 } 623 if !cn.bad { 624 t.Fatalf("expected cn.bad") 625 } 626 627 cn = conn{} 628 func() { 629 defer cn.errRecover(&err) 630 e := &Error{Severity: Efatal} 631 panic(e) 632 }() 633 if err != driver.ErrBadConn { 634 t.Fatalf("expected driver.ErrBadConn, got: %#v", err) 635 } 636 if !cn.bad { 637 t.Fatalf("expected cn.bad") 638 } 639 } 640 641 func TestErrorOnExec(t *testing.T) { 642 db := openTestConn(t) 643 defer db.Close() 644 645 txn, err := db.Begin() 646 if err != nil { 647 t.Fatal(err) 648 } 649 defer txn.Rollback() 650 651 _, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)") 652 if err != nil { 653 t.Fatal(err) 654 } 655 656 _, err = txn.Exec("INSERT INTO foo VALUES (0), (0)") 657 if err == nil { 658 t.Fatal("Should have raised error") 659 } 660 661 e, ok := err.(*Error) 662 if !ok { 663 t.Fatalf("expected Error, got %#v", err) 664 } else if e.Code.Name() != "unique_violation" { 665 t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err) 666 } 667 } 668 669 func TestErrorOnQuery(t *testing.T) { 670 db := openTestConn(t) 671 defer db.Close() 672 673 txn, err := db.Begin() 674 if err != nil { 675 t.Fatal(err) 676 } 677 defer txn.Rollback() 678 679 _, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)") 680 if err != nil { 681 t.Fatal(err) 682 } 683 684 _, err = txn.Query("INSERT INTO foo VALUES (0), (0)") 685 if err == nil { 686 t.Fatal("Should have raised error") 687 } 688 689 e, ok := err.(*Error) 690 if !ok { 691 t.Fatalf("expected Error, got %#v", err) 692 } else if e.Code.Name() != "unique_violation" { 693 t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err) 694 } 695 } 696 697 func TestErrorOnQueryRowSimpleQuery(t *testing.T) { 698 db := openTestConn(t) 699 defer db.Close() 700 701 txn, err := db.Begin() 702 if err != nil { 703 t.Fatal(err) 704 } 705 defer txn.Rollback() 706 707 _, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)") 708 if err != nil { 709 t.Fatal(err) 710 } 711 712 var v int 713 err = txn.QueryRow("INSERT INTO foo VALUES (0), (0)").Scan(&v) 714 if err == nil { 715 t.Fatal("Should have raised error") 716 } 717 718 e, ok := err.(*Error) 719 if !ok { 720 t.Fatalf("expected Error, got %#v", err) 721 } else if e.Code.Name() != "unique_violation" { 722 t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err) 723 } 724 } 725 726 // Test the QueryRow bug workarounds in stmt.exec() and simpleQuery() 727 func TestQueryRowBugWorkaround(t *testing.T) { 728 db := openTestConn(t) 729 defer db.Close() 730 731 // stmt.exec() 732 _, err := db.Exec("CREATE TEMP TABLE notnulltemp (a varchar(10) not null)") 733 if err != nil { 734 t.Fatal(err) 735 } 736 737 var a string 738 err = db.QueryRow("INSERT INTO notnulltemp(a) values($1) RETURNING a", nil).Scan(&a) 739 if err == sql.ErrNoRows { 740 t.Fatalf("expected constraint violation error; got: %v", err) 741 } 742 pge, ok := err.(*Error) 743 if !ok { 744 t.Fatalf("expected *Error; got: %#v", err) 745 } 746 if pge.Code.Name() != "not_null_violation" { 747 t.Fatalf("expected not_null_violation; got: %s (%+v)", pge.Code.Name(), err) 748 } 749 750 // Test workaround in simpleQuery() 751 tx, err := db.Begin() 752 if err != nil { 753 t.Fatalf("unexpected error %s in Begin", err) 754 } 755 defer tx.Rollback() 756 757 _, err = tx.Exec("SET LOCAL check_function_bodies TO FALSE") 758 if err != nil { 759 t.Fatalf("could not disable check_function_bodies: %s", err) 760 } 761 _, err = tx.Exec(` 762 CREATE OR REPLACE FUNCTION bad_function() 763 RETURNS integer 764 -- hack to prevent the function from being inlined 765 SET check_function_bodies TO TRUE 766 AS $$ 767 SELECT text 'bad' 768 $$ LANGUAGE sql`) 769 if err != nil { 770 t.Fatalf("could not create function: %s", err) 771 } 772 773 err = tx.QueryRow("SELECT * FROM bad_function()").Scan(&a) 774 if err == nil { 775 t.Fatalf("expected error") 776 } 777 pge, ok = err.(*Error) 778 if !ok { 779 t.Fatalf("expected *Error; got: %#v", err) 780 } 781 if pge.Code.Name() != "invalid_function_definition" { 782 t.Fatalf("expected invalid_function_definition; got: %s (%+v)", pge.Code.Name(), err) 783 } 784 785 err = tx.Rollback() 786 if err != nil { 787 t.Fatalf("unexpected error %s in Rollback", err) 788 } 789 790 // Also test that simpleQuery()'s workaround works when the query fails 791 // after a row has been received. 792 rows, err := db.Query(` 793 select 794 (select generate_series(1, ss.i)) 795 from (select gs.i 796 from generate_series(1, 2) gs(i) 797 order by gs.i limit 2) ss`) 798 if err != nil { 799 t.Fatalf("query failed: %s", err) 800 } 801 if !rows.Next() { 802 t.Fatalf("expected at least one result row; got %s", rows.Err()) 803 } 804 var i int 805 err = rows.Scan(&i) 806 if err != nil { 807 t.Fatalf("rows.Scan() failed: %s", err) 808 } 809 if i != 1 { 810 t.Fatalf("unexpected value for i: %d", i) 811 } 812 if rows.Next() { 813 t.Fatalf("unexpected row") 814 } 815 pge, ok = rows.Err().(*Error) 816 if !ok { 817 t.Fatalf("expected *Error; got: %#v", err) 818 } 819 if pge.Code.Name() != "cardinality_violation" { 820 t.Fatalf("expected cardinality_violation; got: %s (%+v)", pge.Code.Name(), rows.Err()) 821 } 822 } 823 824 func TestSimpleQuery(t *testing.T) { 825 db := openTestConn(t) 826 defer db.Close() 827 828 r, err := db.Query("select 1") 829 if err != nil { 830 t.Fatal(err) 831 } 832 defer r.Close() 833 834 if !r.Next() { 835 t.Fatal("expected row") 836 } 837 } 838 839 func TestBindError(t *testing.T) { 840 db := openTestConn(t) 841 defer db.Close() 842 843 _, err := db.Exec("create temp table test (i integer)") 844 if err != nil { 845 t.Fatal(err) 846 } 847 848 _, err = db.Query("select * from test where i=$1", "hhh") 849 if err == nil { 850 t.Fatal("expected an error") 851 } 852 853 // Should not get error here 854 r, err := db.Query("select * from test where i=$1", 1) 855 if err != nil { 856 t.Fatal(err) 857 } 858 defer r.Close() 859 } 860 861 func TestParseErrorInExtendedQuery(t *testing.T) { 862 db := openTestConn(t) 863 defer db.Close() 864 865 rows, err := db.Query("PARSE_ERROR $1", 1) 866 if err == nil { 867 t.Fatal("expected error") 868 } 869 870 rows, err = db.Query("SELECT 1") 871 if err != nil { 872 t.Fatal(err) 873 } 874 rows.Close() 875 } 876 877 // TestReturning tests that an INSERT query using the RETURNING clause returns a row. 878 func TestReturning(t *testing.T) { 879 db := openTestConn(t) 880 defer db.Close() 881 882 _, err := db.Exec("CREATE TEMP TABLE distributors (did integer default 0, dname text)") 883 if err != nil { 884 t.Fatal(err) 885 } 886 887 rows, err := db.Query("INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') " + 888 "RETURNING did;") 889 if err != nil { 890 t.Fatal(err) 891 } 892 if !rows.Next() { 893 t.Fatal("no rows") 894 } 895 var did int 896 err = rows.Scan(&did) 897 if err != nil { 898 t.Fatal(err) 899 } 900 if did != 0 { 901 t.Fatalf("bad value for did: got %d, want %d", did, 0) 902 } 903 904 if rows.Next() { 905 t.Fatal("unexpected next row") 906 } 907 err = rows.Err() 908 if err != nil { 909 t.Fatal(err) 910 } 911 } 912 913 func TestIssue186(t *testing.T) { 914 db := openTestConn(t) 915 defer db.Close() 916 917 // Exec() a query which returns results 918 _, err := db.Exec("VALUES (1), (2), (3)") 919 if err != nil { 920 t.Fatal(err) 921 } 922 923 _, err = db.Exec("VALUES ($1), ($2), ($3)", 1, 2, 3) 924 if err != nil { 925 t.Fatal(err) 926 } 927 928 // Query() a query which doesn't return any results 929 txn, err := db.Begin() 930 if err != nil { 931 t.Fatal(err) 932 } 933 defer txn.Rollback() 934 935 rows, err := txn.Query("CREATE TEMP TABLE foo(f1 int)") 936 if err != nil { 937 t.Fatal(err) 938 } 939 if err = rows.Close(); err != nil { 940 t.Fatal(err) 941 } 942 943 // small trick to get NoData from a parameterized query 944 _, err = txn.Exec("CREATE RULE nodata AS ON INSERT TO foo DO INSTEAD NOTHING") 945 if err != nil { 946 t.Fatal(err) 947 } 948 rows, err = txn.Query("INSERT INTO foo VALUES ($1)", 1) 949 if err != nil { 950 t.Fatal(err) 951 } 952 if err = rows.Close(); err != nil { 953 t.Fatal(err) 954 } 955 } 956 957 func TestIssue196(t *testing.T) { 958 db := openTestConn(t) 959 defer db.Close() 960 961 row := db.QueryRow("SELECT float4 '0.10000122' = $1, float8 '35.03554004971999' = $2", 962 float32(0.10000122), float64(35.03554004971999)) 963 964 var float4match, float8match bool 965 err := row.Scan(&float4match, &float8match) 966 if err != nil { 967 t.Fatal(err) 968 } 969 if !float4match { 970 t.Errorf("Expected float4 fidelity to be maintained; got no match") 971 } 972 if !float8match { 973 t.Errorf("Expected float8 fidelity to be maintained; got no match") 974 } 975 } 976 977 // Test that any CommandComplete messages sent before the query results are 978 // ignored. 979 func TestIssue282(t *testing.T) { 980 db := openTestConn(t) 981 defer db.Close() 982 983 var search_path string 984 err := db.QueryRow(` 985 SET LOCAL search_path TO pg_catalog; 986 SET LOCAL search_path TO pg_catalog; 987 SHOW search_path`).Scan(&search_path) 988 if err != nil { 989 t.Fatal(err) 990 } 991 if search_path != "pg_catalog" { 992 t.Fatalf("unexpected search_path %s", search_path) 993 } 994 } 995 996 func TestReadFloatPrecision(t *testing.T) { 997 db := openTestConn(t) 998 defer db.Close() 999 1000 row := db.QueryRow("SELECT float4 '0.10000122', float8 '35.03554004971999'") 1001 var float4val float32 1002 var float8val float64 1003 err := row.Scan(&float4val, &float8val) 1004 if err != nil { 1005 t.Fatal(err) 1006 } 1007 if float4val != float32(0.10000122) { 1008 t.Errorf("Expected float4 fidelity to be maintained; got no match") 1009 } 1010 if float8val != float64(35.03554004971999) { 1011 t.Errorf("Expected float8 fidelity to be maintained; got no match") 1012 } 1013 } 1014 1015 func TestXactMultiStmt(t *testing.T) { 1016 // minified test case based on bug reports from 1017 // pico303@gmail.com and rangelspam@gmail.com 1018 t.Skip("Skipping failing test") 1019 db := openTestConn(t) 1020 defer db.Close() 1021 1022 tx, err := db.Begin() 1023 if err != nil { 1024 t.Fatal(err) 1025 } 1026 defer tx.Commit() 1027 1028 rows, err := tx.Query("select 1") 1029 if err != nil { 1030 t.Fatal(err) 1031 } 1032 1033 if rows.Next() { 1034 var val int32 1035 if err = rows.Scan(&val); err != nil { 1036 t.Fatal(err) 1037 } 1038 } else { 1039 t.Fatal("Expected at least one row in first query in xact") 1040 } 1041 1042 rows2, err := tx.Query("select 2") 1043 if err != nil { 1044 t.Fatal(err) 1045 } 1046 1047 if rows2.Next() { 1048 var val2 int32 1049 if err := rows2.Scan(&val2); err != nil { 1050 t.Fatal(err) 1051 } 1052 } else { 1053 t.Fatal("Expected at least one row in second query in xact") 1054 } 1055 1056 if err = rows.Err(); err != nil { 1057 t.Fatal(err) 1058 } 1059 1060 if err = rows2.Err(); err != nil { 1061 t.Fatal(err) 1062 } 1063 1064 if err = tx.Commit(); err != nil { 1065 t.Fatal(err) 1066 } 1067 } 1068 1069 var envParseTests = []struct { 1070 Expected map[string]string 1071 Env []string 1072 }{ 1073 { 1074 Env: []string{"PGDATABASE=hello", "PGUSER=goodbye"}, 1075 Expected: map[string]string{"dbname": "hello", "user": "goodbye"}, 1076 }, 1077 { 1078 Env: []string{"PGDATESTYLE=ISO, MDY"}, 1079 Expected: map[string]string{"datestyle": "ISO, MDY"}, 1080 }, 1081 { 1082 Env: []string{"PGCONNECT_TIMEOUT=30"}, 1083 Expected: map[string]string{"connect_timeout": "30"}, 1084 }, 1085 } 1086 1087 func TestParseEnviron(t *testing.T) { 1088 for i, tt := range envParseTests { 1089 results := parseEnviron(tt.Env) 1090 if !reflect.DeepEqual(tt.Expected, results) { 1091 t.Errorf("%d: Expected: %#v Got: %#v", i, tt.Expected, results) 1092 } 1093 } 1094 } 1095 1096 func TestParseComplete(t *testing.T) { 1097 tpc := func(commandTag string, command string, affectedRows int64, shouldFail bool) { 1098 defer func() { 1099 if p := recover(); p != nil { 1100 if !shouldFail { 1101 t.Error(p) 1102 } 1103 } 1104 }() 1105 cn := &conn{} 1106 res, c := cn.parseComplete(commandTag) 1107 if c != command { 1108 t.Errorf("Expected %v, got %v", command, c) 1109 } 1110 n, err := res.RowsAffected() 1111 if err != nil { 1112 t.Fatal(err) 1113 } 1114 if n != affectedRows { 1115 t.Errorf("Expected %d, got %d", affectedRows, n) 1116 } 1117 } 1118 1119 tpc("ALTER TABLE", "ALTER TABLE", 0, false) 1120 tpc("INSERT 0 1", "INSERT", 1, false) 1121 tpc("UPDATE 100", "UPDATE", 100, false) 1122 tpc("SELECT 100", "SELECT", 100, false) 1123 tpc("FETCH 100", "FETCH", 100, false) 1124 // allow COPY (and others) without row count 1125 tpc("COPY", "COPY", 0, false) 1126 // don't fail on command tags we don't recognize 1127 tpc("UNKNOWNCOMMANDTAG", "UNKNOWNCOMMANDTAG", 0, false) 1128 1129 // failure cases 1130 tpc("INSERT 1", "", 0, true) // missing oid 1131 tpc("UPDATE 0 1", "", 0, true) // too many numbers 1132 tpc("SELECT foo", "", 0, true) // invalid row count 1133 } 1134 1135 func TestExecerInterface(t *testing.T) { 1136 // Gin up a straw man private struct just for the type check 1137 cn := &conn{c: nil} 1138 var cni interface{} = cn 1139 1140 _, ok := cni.(driver.Execer) 1141 if !ok { 1142 t.Fatal("Driver doesn't implement Execer") 1143 } 1144 } 1145 1146 func TestNullAfterNonNull(t *testing.T) { 1147 db := openTestConn(t) 1148 defer db.Close() 1149 1150 r, err := db.Query("SELECT 9::integer UNION SELECT NULL::integer") 1151 if err != nil { 1152 t.Fatal(err) 1153 } 1154 1155 var n sql.NullInt64 1156 1157 if !r.Next() { 1158 if r.Err() != nil { 1159 t.Fatal(err) 1160 } 1161 t.Fatal("expected row") 1162 } 1163 1164 if err := r.Scan(&n); err != nil { 1165 t.Fatal(err) 1166 } 1167 1168 if n.Int64 != 9 { 1169 t.Fatalf("expected 2, not %d", n.Int64) 1170 } 1171 1172 if !r.Next() { 1173 if r.Err() != nil { 1174 t.Fatal(err) 1175 } 1176 t.Fatal("expected row") 1177 } 1178 1179 if err := r.Scan(&n); err != nil { 1180 t.Fatal(err) 1181 } 1182 1183 if n.Valid { 1184 t.Fatal("expected n to be invalid") 1185 } 1186 1187 if n.Int64 != 0 { 1188 t.Fatalf("expected n to 2, not %d", n.Int64) 1189 } 1190 } 1191 1192 func Test64BitErrorChecking(t *testing.T) { 1193 defer func() { 1194 if err := recover(); err != nil { 1195 t.Fatal("panic due to 0xFFFFFFFF != -1 " + 1196 "when int is 64 bits") 1197 } 1198 }() 1199 1200 db := openTestConn(t) 1201 defer db.Close() 1202 1203 r, err := db.Query(`SELECT * 1204 FROM (VALUES (0::integer, NULL::text), (1, 'test string')) AS t;`) 1205 1206 if err != nil { 1207 t.Fatal(err) 1208 } 1209 1210 defer r.Close() 1211 1212 for r.Next() { 1213 } 1214 } 1215 1216 func TestCommit(t *testing.T) { 1217 db := openTestConn(t) 1218 defer db.Close() 1219 1220 _, err := db.Exec("CREATE TEMP TABLE temp (a int)") 1221 if err != nil { 1222 t.Fatal(err) 1223 } 1224 sqlInsert := "INSERT INTO temp VALUES (1)" 1225 sqlSelect := "SELECT * FROM temp" 1226 tx, err := db.Begin() 1227 if err != nil { 1228 t.Fatal(err) 1229 } 1230 _, err = tx.Exec(sqlInsert) 1231 if err != nil { 1232 t.Fatal(err) 1233 } 1234 err = tx.Commit() 1235 if err != nil { 1236 t.Fatal(err) 1237 } 1238 var i int 1239 err = db.QueryRow(sqlSelect).Scan(&i) 1240 if err != nil { 1241 t.Fatal(err) 1242 } 1243 if i != 1 { 1244 t.Fatalf("expected 1, got %d", i) 1245 } 1246 } 1247 1248 func TestErrorClass(t *testing.T) { 1249 db := openTestConn(t) 1250 defer db.Close() 1251 1252 _, err := db.Query("SELECT int 'notint'") 1253 if err == nil { 1254 t.Fatal("expected error") 1255 } 1256 pge, ok := err.(*Error) 1257 if !ok { 1258 t.Fatalf("expected *pq.Error, got %#+v", err) 1259 } 1260 if pge.Code.Class() != "22" { 1261 t.Fatalf("expected class 28, got %v", pge.Code.Class()) 1262 } 1263 if pge.Code.Class().Name() != "data_exception" { 1264 t.Fatalf("expected data_exception, got %v", pge.Code.Class().Name()) 1265 } 1266 } 1267 1268 func TestParseOpts(t *testing.T) { 1269 tests := []struct { 1270 in string 1271 expected values 1272 valid bool 1273 }{ 1274 {"dbname=hello user=goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, 1275 {"dbname=hello user=goodbye ", values{"dbname": "hello", "user": "goodbye"}, true}, 1276 {"dbname = hello user=goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, 1277 {"dbname=hello user =goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, 1278 {"dbname=hello user= goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, 1279 {"host=localhost password='correct horse battery staple'", values{"host": "localhost", "password": "correct horse battery staple"}, true}, 1280 {"dbname=データベース password=パスワード", values{"dbname": "データベース", "password": "パスワード"}, true}, 1281 {"dbname=hello user=''", values{"dbname": "hello", "user": ""}, true}, 1282 {"user='' dbname=hello", values{"dbname": "hello", "user": ""}, true}, 1283 // The last option value is an empty string if there's no non-whitespace after its = 1284 {"dbname=hello user= ", values{"dbname": "hello", "user": ""}, true}, 1285 1286 // The parser ignores spaces after = and interprets the next set of non-whitespace characters as the value. 1287 {"user= password=foo", values{"user": "password=foo"}, true}, 1288 1289 // Backslash escapes next char 1290 {`user=a\ \'\\b`, values{"user": `a '\b`}, true}, 1291 {`user='a \'b'`, values{"user": `a 'b`}, true}, 1292 1293 // Incomplete escape 1294 {`user=x\`, values{}, false}, 1295 1296 // No '=' after the key 1297 {"postgre://marko@internet", values{}, false}, 1298 {"dbname user=goodbye", values{}, false}, 1299 {"user=foo blah", values{}, false}, 1300 {"user=foo blah ", values{}, false}, 1301 1302 // Unterminated quoted value 1303 {"dbname=hello user='unterminated", values{}, false}, 1304 } 1305 1306 for _, test := range tests { 1307 o := make(values) 1308 err := parseOpts(test.in, o) 1309 1310 switch { 1311 case err != nil && test.valid: 1312 t.Errorf("%q got unexpected error: %s", test.in, err) 1313 case err == nil && test.valid && !reflect.DeepEqual(test.expected, o): 1314 t.Errorf("%q got: %#v want: %#v", test.in, o, test.expected) 1315 case err == nil && !test.valid: 1316 t.Errorf("%q expected an error", test.in) 1317 } 1318 } 1319 } 1320 1321 func TestRuntimeParameters(t *testing.T) { 1322 type RuntimeTestResult int 1323 const ( 1324 ResultUnknown RuntimeTestResult = iota 1325 ResultSuccess 1326 ResultError // other error 1327 ) 1328 1329 tests := []struct { 1330 conninfo string 1331 param string 1332 expected string 1333 expectedOutcome RuntimeTestResult 1334 }{ 1335 // invalid parameter 1336 {"DOESNOTEXIST=foo", "", "", ResultError}, 1337 // we can only work with a specific value for these two 1338 {"client_encoding=SQL_ASCII", "", "", ResultError}, 1339 {"datestyle='ISO, YDM'", "", "", ResultError}, 1340 // "options" should work exactly as it does in libpq 1341 {"options='-c search_path=pqgotest'", "search_path", "pqgotest", ResultSuccess}, 1342 // pq should override client_encoding in this case 1343 {"options='-c client_encoding=SQL_ASCII'", "client_encoding", "UTF8", ResultSuccess}, 1344 // allow client_encoding to be set explicitly 1345 {"client_encoding=UTF8", "client_encoding", "UTF8", ResultSuccess}, 1346 // test a runtime parameter not supported by libpq 1347 {"work_mem='139kB'", "work_mem", "139kB", ResultSuccess}, 1348 // test fallback_application_name 1349 {"application_name=foo fallback_application_name=bar", "application_name", "foo", ResultSuccess}, 1350 {"application_name='' fallback_application_name=bar", "application_name", "", ResultSuccess}, 1351 {"fallback_application_name=bar", "application_name", "bar", ResultSuccess}, 1352 } 1353 1354 for _, test := range tests { 1355 db, err := openTestConnConninfo(test.conninfo) 1356 if err != nil { 1357 t.Fatal(err) 1358 } 1359 1360 // application_name didn't exist before 9.0 1361 if test.param == "application_name" && getServerVersion(t, db) < 90000 { 1362 db.Close() 1363 continue 1364 } 1365 1366 tryGetParameterValue := func() (value string, outcome RuntimeTestResult) { 1367 defer db.Close() 1368 row := db.QueryRow("SELECT current_setting($1)", test.param) 1369 err = row.Scan(&value) 1370 if err != nil { 1371 return "", ResultError 1372 } 1373 return value, ResultSuccess 1374 } 1375 1376 value, outcome := tryGetParameterValue() 1377 if outcome != test.expectedOutcome && outcome == ResultError { 1378 t.Fatalf("%v: unexpected error: %v", test.conninfo, err) 1379 } 1380 if outcome != test.expectedOutcome { 1381 t.Fatalf("unexpected outcome %v (was expecting %v) for conninfo \"%s\"", 1382 outcome, test.expectedOutcome, test.conninfo) 1383 } 1384 if value != test.expected { 1385 t.Fatalf("bad value for %s: got %s, want %s with conninfo \"%s\"", 1386 test.param, value, test.expected, test.conninfo) 1387 } 1388 } 1389 } 1390 1391 func TestIsUTF8(t *testing.T) { 1392 var cases = []struct { 1393 name string 1394 want bool 1395 }{ 1396 {"unicode", true}, 1397 {"utf-8", true}, 1398 {"utf_8", true}, 1399 {"UTF-8", true}, 1400 {"UTF8", true}, 1401 {"utf8", true}, 1402 {"u n ic_ode", true}, 1403 {"ut_f%8", true}, 1404 {"ubf8", false}, 1405 {"punycode", false}, 1406 } 1407 1408 for _, test := range cases { 1409 if g := isUTF8(test.name); g != test.want { 1410 t.Errorf("isUTF8(%q) = %v want %v", test.name, g, test.want) 1411 } 1412 } 1413 } 1414 1415 func TestQuoteIdentifier(t *testing.T) { 1416 var cases = []struct { 1417 input string 1418 want string 1419 }{ 1420 {`foo`, `"foo"`}, 1421 {`foo bar baz`, `"foo bar baz"`}, 1422 {`foo"bar`, `"foo""bar"`}, 1423 {"foo\x00bar", `"foo"`}, 1424 {"\x00foo", `""`}, 1425 } 1426 1427 for _, test := range cases { 1428 got := QuoteIdentifier(test.input) 1429 if got != test.want { 1430 t.Errorf("QuoteIdentifier(%q) = %v want %v", test.input, got, test.want) 1431 } 1432 } 1433 }