hstore_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package hstore
  2. import (
  3. "database/sql"
  4. _ "github.com/lib/pq"
  5. "os"
  6. "testing"
  7. )
  8. type Fatalistic interface {
  9. Fatal(args ...interface{})
  10. }
  11. func openTestConn(t Fatalistic) *sql.DB {
  12. datname := os.Getenv("PGDATABASE")
  13. sslmode := os.Getenv("PGSSLMODE")
  14. if datname == "" {
  15. os.Setenv("PGDATABASE", "pqgotest")
  16. }
  17. if sslmode == "" {
  18. os.Setenv("PGSSLMODE", "disable")
  19. }
  20. conn, err := sql.Open("postgres", "")
  21. if err != nil {
  22. t.Fatal(err)
  23. }
  24. return conn
  25. }
  26. func TestHstore(t *testing.T) {
  27. db := openTestConn(t)
  28. defer db.Close()
  29. // quitely create hstore if it doesn't exist
  30. _, err := db.Exec("CREATE EXTENSION IF NOT EXISTS hstore")
  31. if err != nil {
  32. t.Skipf("Skipping hstore tests - hstore extension create failed: %s", err.Error())
  33. }
  34. hs := Hstore{}
  35. // test for null-valued hstores
  36. err = db.QueryRow("SELECT NULL::hstore").Scan(&hs)
  37. if err != nil {
  38. t.Fatal(err)
  39. }
  40. if hs.Map != nil {
  41. t.Fatalf("expected null map")
  42. }
  43. err = db.QueryRow("SELECT $1::hstore", hs).Scan(&hs)
  44. if err != nil {
  45. t.Fatalf("re-query null map failed: %s", err.Error())
  46. }
  47. if hs.Map != nil {
  48. t.Fatalf("expected null map")
  49. }
  50. // test for empty hstores
  51. err = db.QueryRow("SELECT ''::hstore").Scan(&hs)
  52. if err != nil {
  53. t.Fatal(err)
  54. }
  55. if hs.Map == nil {
  56. t.Fatalf("expected empty map, got null map")
  57. }
  58. if len(hs.Map) != 0 {
  59. t.Fatalf("expected empty map, got len(map)=%d", len(hs.Map))
  60. }
  61. err = db.QueryRow("SELECT $1::hstore", hs).Scan(&hs)
  62. if err != nil {
  63. t.Fatalf("re-query empty map failed: %s", err.Error())
  64. }
  65. if hs.Map == nil {
  66. t.Fatalf("expected empty map, got null map")
  67. }
  68. if len(hs.Map) != 0 {
  69. t.Fatalf("expected empty map, got len(map)=%d", len(hs.Map))
  70. }
  71. // a few example maps to test out
  72. hsOnePair := Hstore{
  73. Map: map[string]sql.NullString{
  74. "key1": {"value1", true},
  75. },
  76. }
  77. hsThreePairs := Hstore{
  78. Map: map[string]sql.NullString{
  79. "key1": {"value1", true},
  80. "key2": {"value2", true},
  81. "key3": {"value3", true},
  82. },
  83. }
  84. hsSmorgasbord := Hstore{
  85. Map: map[string]sql.NullString{
  86. "nullstring": {"NULL", true},
  87. "actuallynull": {"", false},
  88. "NULL": {"NULL string key", true},
  89. "withbracket": {"value>42", true},
  90. "withequal": {"value=42", true},
  91. `"withquotes1"`: {`this "should" be fine`, true},
  92. `"withquotes"2"`: {`this "should\" also be fine`, true},
  93. "embedded1": {"value1=>x1", true},
  94. "embedded2": {`"value2"=>x2`, true},
  95. "withnewlines": {"\n\nvalue\t=>2", true},
  96. "<<all sorts of crazy>>": {`this, "should,\" also, => be fine`, true},
  97. },
  98. }
  99. // test encoding in query params, then decoding during Scan
  100. testBidirectional := func(h Hstore) {
  101. err = db.QueryRow("SELECT $1::hstore", h).Scan(&hs)
  102. if err != nil {
  103. t.Fatalf("re-query %d-pair map failed: %s", len(h.Map), err.Error())
  104. }
  105. if hs.Map == nil {
  106. t.Fatalf("expected %d-pair map, got null map", len(h.Map))
  107. }
  108. if len(hs.Map) != len(h.Map) {
  109. t.Fatalf("expected %d-pair map, got len(map)=%d", len(h.Map), len(hs.Map))
  110. }
  111. for key, val := range hs.Map {
  112. otherval, found := h.Map[key]
  113. if !found {
  114. t.Fatalf(" key '%v' not found in %d-pair map", key, len(h.Map))
  115. }
  116. if otherval.Valid != val.Valid {
  117. t.Fatalf(" value %v <> %v in %d-pair map", otherval, val, len(h.Map))
  118. }
  119. if otherval.String != val.String {
  120. t.Fatalf(" value '%v' <> '%v' in %d-pair map", otherval.String, val.String, len(h.Map))
  121. }
  122. }
  123. }
  124. testBidirectional(hsOnePair)
  125. testBidirectional(hsThreePairs)
  126. testBidirectional(hsSmorgasbord)
  127. }