encode_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. package pq
  2. import (
  3. "bytes"
  4. "database/sql"
  5. "fmt"
  6. "regexp"
  7. "testing"
  8. "time"
  9. "github.com/lib/pq/oid"
  10. )
  11. func TestScanTimestamp(t *testing.T) {
  12. var nt NullTime
  13. tn := time.Now()
  14. nt.Scan(tn)
  15. if !nt.Valid {
  16. t.Errorf("Expected Valid=false")
  17. }
  18. if nt.Time != tn {
  19. t.Errorf("Time value mismatch")
  20. }
  21. }
  22. func TestScanNilTimestamp(t *testing.T) {
  23. var nt NullTime
  24. nt.Scan(nil)
  25. if nt.Valid {
  26. t.Errorf("Expected Valid=false")
  27. }
  28. }
  29. var timeTests = []struct {
  30. str string
  31. timeval time.Time
  32. }{
  33. {"22001-02-03", time.Date(22001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
  34. {"2001-02-03", time.Date(2001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
  35. {"0001-12-31 BC", time.Date(0, time.December, 31, 0, 0, 0, 0, time.FixedZone("", 0))},
  36. {"2001-02-03 BC", time.Date(-2000, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
  37. {"2001-02-03 04:05:06", time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))},
  38. {"2001-02-03 04:05:06.000001", time.Date(2001, time.February, 3, 4, 5, 6, 1000, time.FixedZone("", 0))},
  39. {"2001-02-03 04:05:06.00001", time.Date(2001, time.February, 3, 4, 5, 6, 10000, time.FixedZone("", 0))},
  40. {"2001-02-03 04:05:06.0001", time.Date(2001, time.February, 3, 4, 5, 6, 100000, time.FixedZone("", 0))},
  41. {"2001-02-03 04:05:06.001", time.Date(2001, time.February, 3, 4, 5, 6, 1000000, time.FixedZone("", 0))},
  42. {"2001-02-03 04:05:06.01", time.Date(2001, time.February, 3, 4, 5, 6, 10000000, time.FixedZone("", 0))},
  43. {"2001-02-03 04:05:06.1", time.Date(2001, time.February, 3, 4, 5, 6, 100000000, time.FixedZone("", 0))},
  44. {"2001-02-03 04:05:06.12", time.Date(2001, time.February, 3, 4, 5, 6, 120000000, time.FixedZone("", 0))},
  45. {"2001-02-03 04:05:06.123", time.Date(2001, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))},
  46. {"2001-02-03 04:05:06.1234", time.Date(2001, time.February, 3, 4, 5, 6, 123400000, time.FixedZone("", 0))},
  47. {"2001-02-03 04:05:06.12345", time.Date(2001, time.February, 3, 4, 5, 6, 123450000, time.FixedZone("", 0))},
  48. {"2001-02-03 04:05:06.123456", time.Date(2001, time.February, 3, 4, 5, 6, 123456000, time.FixedZone("", 0))},
  49. {"2001-02-03 04:05:06.123-07", time.Date(2001, time.February, 3, 4, 5, 6, 123000000,
  50. time.FixedZone("", -7*60*60))},
  51. {"2001-02-03 04:05:06-07", time.Date(2001, time.February, 3, 4, 5, 6, 0,
  52. time.FixedZone("", -7*60*60))},
  53. {"2001-02-03 04:05:06-07:42", time.Date(2001, time.February, 3, 4, 5, 6, 0,
  54. time.FixedZone("", -(7*60*60+42*60)))},
  55. {"2001-02-03 04:05:06-07:30:09", time.Date(2001, time.February, 3, 4, 5, 6, 0,
  56. time.FixedZone("", -(7*60*60+30*60+9)))},
  57. {"2001-02-03 04:05:06+07", time.Date(2001, time.February, 3, 4, 5, 6, 0,
  58. time.FixedZone("", 7*60*60))},
  59. {"0011-02-03 04:05:06 BC", time.Date(-10, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))},
  60. {"0011-02-03 04:05:06.123 BC", time.Date(-10, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))},
  61. {"0011-02-03 04:05:06.123-07 BC", time.Date(-10, time.February, 3, 4, 5, 6, 123000000,
  62. time.FixedZone("", -7*60*60))},
  63. {"0001-02-03 04:05:06.123", time.Date(1, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))},
  64. {"0001-02-03 04:05:06.123 BC", time.Date(1, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0)).AddDate(-1, 0, 0)},
  65. {"0001-02-03 04:05:06.123 BC", time.Date(0, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))},
  66. {"0002-02-03 04:05:06.123 BC", time.Date(0, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0)).AddDate(-1, 0, 0)},
  67. {"0002-02-03 04:05:06.123 BC", time.Date(-1, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))},
  68. {"12345-02-03 04:05:06.1", time.Date(12345, time.February, 3, 4, 5, 6, 100000000, time.FixedZone("", 0))},
  69. {"123456-02-03 04:05:06.1", time.Date(123456, time.February, 3, 4, 5, 6, 100000000, time.FixedZone("", 0))},
  70. }
  71. // Test that parsing the string results in the expected value.
  72. func TestParseTs(t *testing.T) {
  73. for i, tt := range timeTests {
  74. val, err := ParseTimestamp(nil, tt.str)
  75. if err != nil {
  76. t.Errorf("%d: got error: %v", i, err)
  77. } else if val.String() != tt.timeval.String() {
  78. t.Errorf("%d: expected to parse %q into %q; got %q",
  79. i, tt.str, tt.timeval, val)
  80. }
  81. }
  82. }
  83. var timeErrorTests = []string{
  84. "BC",
  85. " BC",
  86. "2001",
  87. "2001-2-03",
  88. "2001-02-3",
  89. "2001-02-03 ",
  90. "2001-02-03 B",
  91. "2001-02-03 04",
  92. "2001-02-03 04:",
  93. "2001-02-03 04:05",
  94. "2001-02-03 04:05 B",
  95. "2001-02-03 04:05 BC",
  96. "2001-02-03 04:05:",
  97. "2001-02-03 04:05:6",
  98. "2001-02-03 04:05:06 B",
  99. "2001-02-03 04:05:06BC",
  100. "2001-02-03 04:05:06.123 B",
  101. }
  102. // Test that parsing the string results in an error.
  103. func TestParseTsErrors(t *testing.T) {
  104. for i, tt := range timeErrorTests {
  105. _, err := ParseTimestamp(nil, tt)
  106. if err == nil {
  107. t.Errorf("%d: expected an error from parsing: %v", i, tt)
  108. }
  109. }
  110. }
  111. // Now test that sending the value into the database and parsing it back
  112. // returns the same time.Time value.
  113. func TestEncodeAndParseTs(t *testing.T) {
  114. db, err := openTestConnConninfo("timezone='Etc/UTC'")
  115. if err != nil {
  116. t.Fatal(err)
  117. }
  118. defer db.Close()
  119. for i, tt := range timeTests {
  120. var dbstr string
  121. err = db.QueryRow("SELECT ($1::timestamptz)::text", tt.timeval).Scan(&dbstr)
  122. if err != nil {
  123. t.Errorf("%d: could not send value %q to the database: %s", i, tt.timeval, err)
  124. continue
  125. }
  126. val, err := ParseTimestamp(nil, dbstr)
  127. if err != nil {
  128. t.Errorf("%d: could not parse value %q: %s", i, dbstr, err)
  129. continue
  130. }
  131. val = val.In(tt.timeval.Location())
  132. if val.String() != tt.timeval.String() {
  133. t.Errorf("%d: expected to parse %q into %q; got %q", i, dbstr, tt.timeval, val)
  134. }
  135. }
  136. }
  137. var formatTimeTests = []struct {
  138. time time.Time
  139. expected string
  140. }{
  141. {time.Time{}, "0001-01-01 00:00:00Z"},
  142. {time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "2001-02-03 04:05:06.123456789Z"},
  143. {time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "2001-02-03 04:05:06.123456789+02:00"},
  144. {time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "2001-02-03 04:05:06.123456789-06:00"},
  145. {time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "2001-02-03 04:05:06-07:30:09"},
  146. {time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "0001-02-03 04:05:06.123456789Z"},
  147. {time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "0001-02-03 04:05:06.123456789+02:00"},
  148. {time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "0001-02-03 04:05:06.123456789-06:00"},
  149. {time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "0001-02-03 04:05:06.123456789Z BC"},
  150. {time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "0001-02-03 04:05:06.123456789+02:00 BC"},
  151. {time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "0001-02-03 04:05:06.123456789-06:00 BC"},
  152. {time.Date(1, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "0001-02-03 04:05:06-07:30:09"},
  153. {time.Date(0, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "0001-02-03 04:05:06-07:30:09 BC"},
  154. }
  155. func TestFormatTs(t *testing.T) {
  156. for i, tt := range formatTimeTests {
  157. val := string(formatTs(tt.time))
  158. if val != tt.expected {
  159. t.Errorf("%d: incorrect time format %q, want %q", i, val, tt.expected)
  160. }
  161. }
  162. }
  163. func TestFormatTsBackend(t *testing.T) {
  164. db := openTestConn(t)
  165. defer db.Close()
  166. var str string
  167. err := db.QueryRow("SELECT '2001-02-03T04:05:06.007-08:09:10'::time::text").Scan(&str)
  168. if err == nil {
  169. t.Fatalf("PostgreSQL is accepting an ISO timestamp input for time")
  170. }
  171. for i, tt := range formatTimeTests {
  172. for _, typ := range []string{"date", "time", "timetz", "timestamp", "timestamptz"} {
  173. err = db.QueryRow("SELECT $1::"+typ+"::text", tt.time).Scan(&str)
  174. if err != nil {
  175. t.Errorf("%d: incorrect time format for %v on the backend: %v", i, typ, err)
  176. }
  177. }
  178. }
  179. }
  180. func TestTimestampWithTimeZone(t *testing.T) {
  181. db := openTestConn(t)
  182. defer db.Close()
  183. tx, err := db.Begin()
  184. if err != nil {
  185. t.Fatal(err)
  186. }
  187. defer tx.Rollback()
  188. // try several different locations, all included in Go's zoneinfo.zip
  189. for _, locName := range []string{
  190. "UTC",
  191. "America/Chicago",
  192. "America/New_York",
  193. "Australia/Darwin",
  194. "Australia/Perth",
  195. } {
  196. loc, err := time.LoadLocation(locName)
  197. if err != nil {
  198. t.Logf("Could not load time zone %s - skipping", locName)
  199. continue
  200. }
  201. // Postgres timestamps have a resolution of 1 microsecond, so don't
  202. // use the full range of the Nanosecond argument
  203. refTime := time.Date(2012, 11, 6, 10, 23, 42, 123456000, loc)
  204. for _, pgTimeZone := range []string{"US/Eastern", "Australia/Darwin"} {
  205. // Switch Postgres's timezone to test different output timestamp formats
  206. _, err = tx.Exec(fmt.Sprintf("set time zone '%s'", pgTimeZone))
  207. if err != nil {
  208. t.Fatal(err)
  209. }
  210. var gotTime time.Time
  211. row := tx.QueryRow("select $1::timestamp with time zone", refTime)
  212. err = row.Scan(&gotTime)
  213. if err != nil {
  214. t.Fatal(err)
  215. }
  216. if !refTime.Equal(gotTime) {
  217. t.Errorf("timestamps not equal: %s != %s", refTime, gotTime)
  218. }
  219. // check that the time zone is set correctly based on TimeZone
  220. pgLoc, err := time.LoadLocation(pgTimeZone)
  221. if err != nil {
  222. t.Logf("Could not load time zone %s - skipping", pgLoc)
  223. continue
  224. }
  225. translated := refTime.In(pgLoc)
  226. if translated.String() != gotTime.String() {
  227. t.Errorf("timestamps not equal: %s != %s", translated, gotTime)
  228. }
  229. }
  230. }
  231. }
  232. func TestTimestampWithOutTimezone(t *testing.T) {
  233. db := openTestConn(t)
  234. defer db.Close()
  235. test := func(ts, pgts string) {
  236. r, err := db.Query("SELECT $1::timestamp", pgts)
  237. if err != nil {
  238. t.Fatalf("Could not run query: %v", err)
  239. }
  240. if !r.Next() {
  241. t.Fatal("Expected at least one row")
  242. }
  243. var result time.Time
  244. err = r.Scan(&result)
  245. if err != nil {
  246. t.Fatalf("Did not expect error scanning row: %v", err)
  247. }
  248. expected, err := time.Parse(time.RFC3339, ts)
  249. if err != nil {
  250. t.Fatalf("Could not parse test time literal: %v", err)
  251. }
  252. if !result.Equal(expected) {
  253. t.Fatalf("Expected time to match %v: got mismatch %v",
  254. expected, result)
  255. }
  256. if r.Next() {
  257. t.Fatal("Expected only one row")
  258. }
  259. }
  260. test("2000-01-01T00:00:00Z", "2000-01-01T00:00:00")
  261. // Test higher precision time
  262. test("2013-01-04T20:14:58.80033Z", "2013-01-04 20:14:58.80033")
  263. }
  264. func TestInfinityTimestamp(t *testing.T) {
  265. db := openTestConn(t)
  266. defer db.Close()
  267. var err error
  268. var resultT time.Time
  269. expectedErrorStrRegexp := regexp.MustCompile(
  270. `^sql: Scan error on column index 0(, name "timestamp(tz)?"|): unsupported`)
  271. type testCases []struct {
  272. Query string
  273. Param string
  274. ExpectedErrorStrRegexp *regexp.Regexp
  275. ExpectedVal interface{}
  276. }
  277. tc := testCases{
  278. {"SELECT $1::timestamp", "-infinity", expectedErrorStrRegexp, "-infinity"},
  279. {"SELECT $1::timestamptz", "-infinity", expectedErrorStrRegexp, "-infinity"},
  280. {"SELECT $1::timestamp", "infinity", expectedErrorStrRegexp, "infinity"},
  281. {"SELECT $1::timestamptz", "infinity", expectedErrorStrRegexp, "infinity"},
  282. }
  283. // try to assert []byte to time.Time
  284. for _, q := range tc {
  285. err = db.QueryRow(q.Query, q.Param).Scan(&resultT)
  286. if !q.ExpectedErrorStrRegexp.MatchString(err.Error()) {
  287. t.Errorf("Scanning -/+infinity, expected error to match regexp %q, got %q",
  288. q.ExpectedErrorStrRegexp, err)
  289. }
  290. }
  291. // yield []byte
  292. for _, q := range tc {
  293. var resultI interface{}
  294. err = db.QueryRow(q.Query, q.Param).Scan(&resultI)
  295. if err != nil {
  296. t.Errorf("Scanning -/+infinity, expected no error, got %q", err)
  297. }
  298. result, ok := resultI.([]byte)
  299. if !ok {
  300. t.Errorf("Scanning -/+infinity, expected []byte, got %#v", resultI)
  301. }
  302. if string(result) != q.ExpectedVal {
  303. t.Errorf("Scanning -/+infinity, expected %q, got %q", q.ExpectedVal, result)
  304. }
  305. }
  306. y1500 := time.Date(1500, time.January, 1, 0, 0, 0, 0, time.UTC)
  307. y2500 := time.Date(2500, time.January, 1, 0, 0, 0, 0, time.UTC)
  308. EnableInfinityTs(y1500, y2500)
  309. err = db.QueryRow("SELECT $1::timestamp", "infinity").Scan(&resultT)
  310. if err != nil {
  311. t.Errorf("Scanning infinity, expected no error, got %q", err)
  312. }
  313. if !resultT.Equal(y2500) {
  314. t.Errorf("Scanning infinity, expected %q, got %q", y2500, resultT)
  315. }
  316. err = db.QueryRow("SELECT $1::timestamptz", "infinity").Scan(&resultT)
  317. if err != nil {
  318. t.Errorf("Scanning infinity, expected no error, got %q", err)
  319. }
  320. if !resultT.Equal(y2500) {
  321. t.Errorf("Scanning Infinity, expected time %q, got %q", y2500, resultT.String())
  322. }
  323. err = db.QueryRow("SELECT $1::timestamp", "-infinity").Scan(&resultT)
  324. if err != nil {
  325. t.Errorf("Scanning -infinity, expected no error, got %q", err)
  326. }
  327. if !resultT.Equal(y1500) {
  328. t.Errorf("Scanning -infinity, expected time %q, got %q", y1500, resultT.String())
  329. }
  330. err = db.QueryRow("SELECT $1::timestamptz", "-infinity").Scan(&resultT)
  331. if err != nil {
  332. t.Errorf("Scanning -infinity, expected no error, got %q", err)
  333. }
  334. if !resultT.Equal(y1500) {
  335. t.Errorf("Scanning -infinity, expected time %q, got %q", y1500, resultT.String())
  336. }
  337. ym1500 := time.Date(-1500, time.January, 1, 0, 0, 0, 0, time.UTC)
  338. y11500 := time.Date(11500, time.January, 1, 0, 0, 0, 0, time.UTC)
  339. var s string
  340. err = db.QueryRow("SELECT $1::timestamp::text", ym1500).Scan(&s)
  341. if err != nil {
  342. t.Errorf("Encoding -infinity, expected no error, got %q", err)
  343. }
  344. if s != "-infinity" {
  345. t.Errorf("Encoding -infinity, expected %q, got %q", "-infinity", s)
  346. }
  347. err = db.QueryRow("SELECT $1::timestamptz::text", ym1500).Scan(&s)
  348. if err != nil {
  349. t.Errorf("Encoding -infinity, expected no error, got %q", err)
  350. }
  351. if s != "-infinity" {
  352. t.Errorf("Encoding -infinity, expected %q, got %q", "-infinity", s)
  353. }
  354. err = db.QueryRow("SELECT $1::timestamp::text", y11500).Scan(&s)
  355. if err != nil {
  356. t.Errorf("Encoding infinity, expected no error, got %q", err)
  357. }
  358. if s != "infinity" {
  359. t.Errorf("Encoding infinity, expected %q, got %q", "infinity", s)
  360. }
  361. err = db.QueryRow("SELECT $1::timestamptz::text", y11500).Scan(&s)
  362. if err != nil {
  363. t.Errorf("Encoding infinity, expected no error, got %q", err)
  364. }
  365. if s != "infinity" {
  366. t.Errorf("Encoding infinity, expected %q, got %q", "infinity", s)
  367. }
  368. disableInfinityTs()
  369. var panicErrorString string
  370. func() {
  371. defer func() {
  372. panicErrorString, _ = recover().(string)
  373. }()
  374. EnableInfinityTs(y2500, y1500)
  375. }()
  376. if panicErrorString != infinityTsNegativeMustBeSmaller {
  377. t.Errorf("Expected error, %q, got %q", infinityTsNegativeMustBeSmaller, panicErrorString)
  378. }
  379. }
  380. func TestStringWithNul(t *testing.T) {
  381. db := openTestConn(t)
  382. defer db.Close()
  383. hello0world := string("hello\x00world")
  384. _, err := db.Query("SELECT $1::text", &hello0world)
  385. if err == nil {
  386. t.Fatal("Postgres accepts a string with nul in it; " +
  387. "injection attacks may be plausible")
  388. }
  389. }
  390. func TestByteSliceToText(t *testing.T) {
  391. db := openTestConn(t)
  392. defer db.Close()
  393. b := []byte("hello world")
  394. row := db.QueryRow("SELECT $1::text", b)
  395. var result []byte
  396. err := row.Scan(&result)
  397. if err != nil {
  398. t.Fatal(err)
  399. }
  400. if string(result) != string(b) {
  401. t.Fatalf("expected %v but got %v", b, result)
  402. }
  403. }
  404. func TestStringToBytea(t *testing.T) {
  405. db := openTestConn(t)
  406. defer db.Close()
  407. b := "hello world"
  408. row := db.QueryRow("SELECT $1::bytea", b)
  409. var result []byte
  410. err := row.Scan(&result)
  411. if err != nil {
  412. t.Fatal(err)
  413. }
  414. if !bytes.Equal(result, []byte(b)) {
  415. t.Fatalf("expected %v but got %v", b, result)
  416. }
  417. }
  418. func TestTextByteSliceToUUID(t *testing.T) {
  419. db := openTestConn(t)
  420. defer db.Close()
  421. b := []byte("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11")
  422. row := db.QueryRow("SELECT $1::uuid", b)
  423. var result string
  424. err := row.Scan(&result)
  425. if forceBinaryParameters() {
  426. pqErr := err.(*Error)
  427. if pqErr == nil {
  428. t.Errorf("Expected to get error")
  429. } else if pqErr.Code != "22P03" {
  430. t.Fatalf("Expected to get invalid binary encoding error (22P03), got %s", pqErr.Code)
  431. }
  432. } else {
  433. if err != nil {
  434. t.Fatal(err)
  435. }
  436. if result != string(b) {
  437. t.Fatalf("expected %v but got %v", b, result)
  438. }
  439. }
  440. }
  441. func TestBinaryByteSlicetoUUID(t *testing.T) {
  442. db := openTestConn(t)
  443. defer db.Close()
  444. b := []byte{'\xa0', '\xee', '\xbc', '\x99',
  445. '\x9c', '\x0b',
  446. '\x4e', '\xf8',
  447. '\xbb', '\x00', '\x6b',
  448. '\xb9', '\xbd', '\x38', '\x0a', '\x11'}
  449. row := db.QueryRow("SELECT $1::uuid", b)
  450. var result string
  451. err := row.Scan(&result)
  452. if forceBinaryParameters() {
  453. if err != nil {
  454. t.Fatal(err)
  455. }
  456. if result != string("a0eebc99-9c0b-4ef8-bb00-6bb9bd380a11") {
  457. t.Fatalf("expected %v but got %v", b, result)
  458. }
  459. } else {
  460. pqErr := err.(*Error)
  461. if pqErr == nil {
  462. t.Errorf("Expected to get error")
  463. } else if pqErr.Code != "22021" {
  464. t.Fatalf("Expected to get invalid byte sequence for encoding error (22021), got %s", pqErr.Code)
  465. }
  466. }
  467. }
  468. func TestStringToUUID(t *testing.T) {
  469. db := openTestConn(t)
  470. defer db.Close()
  471. s := "a0eebc99-9c0b-4ef8-bb00-6bb9bd380a11"
  472. row := db.QueryRow("SELECT $1::uuid", s)
  473. var result string
  474. err := row.Scan(&result)
  475. if err != nil {
  476. t.Fatal(err)
  477. }
  478. if result != s {
  479. t.Fatalf("expected %v but got %v", s, result)
  480. }
  481. }
  482. func TestTextByteSliceToInt(t *testing.T) {
  483. db := openTestConn(t)
  484. defer db.Close()
  485. expected := 12345678
  486. b := []byte(fmt.Sprintf("%d", expected))
  487. row := db.QueryRow("SELECT $1::int", b)
  488. var result int
  489. err := row.Scan(&result)
  490. if forceBinaryParameters() {
  491. pqErr := err.(*Error)
  492. if pqErr == nil {
  493. t.Errorf("Expected to get error")
  494. } else if pqErr.Code != "22P03" {
  495. t.Fatalf("Expected to get invalid binary encoding error (22P03), got %s", pqErr.Code)
  496. }
  497. } else {
  498. if err != nil {
  499. t.Fatal(err)
  500. }
  501. if result != expected {
  502. t.Fatalf("expected %v but got %v", expected, result)
  503. }
  504. }
  505. }
  506. func TestBinaryByteSliceToInt(t *testing.T) {
  507. db := openTestConn(t)
  508. defer db.Close()
  509. expected := 12345678
  510. b := []byte{'\x00', '\xbc', '\x61', '\x4e'}
  511. row := db.QueryRow("SELECT $1::int", b)
  512. var result int
  513. err := row.Scan(&result)
  514. if forceBinaryParameters() {
  515. if err != nil {
  516. t.Fatal(err)
  517. }
  518. if result != expected {
  519. t.Fatalf("expected %v but got %v", expected, result)
  520. }
  521. } else {
  522. pqErr := err.(*Error)
  523. if pqErr == nil {
  524. t.Errorf("Expected to get error")
  525. } else if pqErr.Code != "22021" {
  526. t.Fatalf("Expected to get invalid byte sequence for encoding error (22021), got %s", pqErr.Code)
  527. }
  528. }
  529. }
  530. func TestTextDecodeIntoString(t *testing.T) {
  531. input := []byte("hello world")
  532. want := string(input)
  533. for _, typ := range []oid.Oid{oid.T_char, oid.T_varchar, oid.T_text} {
  534. got := decode(&parameterStatus{}, input, typ, formatText)
  535. if got != want {
  536. t.Errorf("invalid string decoding output for %T(%+v), got %v but expected %v", typ, typ, got, want)
  537. }
  538. }
  539. }
  540. func TestByteaOutputFormatEncoding(t *testing.T) {
  541. input := []byte("\\x\x00\x01\x02\xFF\xFEabcdefg0123")
  542. want := []byte("\\x5c78000102fffe6162636465666730313233")
  543. got := encode(&parameterStatus{serverVersion: 90000}, input, oid.T_bytea)
  544. if !bytes.Equal(want, got) {
  545. t.Errorf("invalid hex bytea output, got %v but expected %v", got, want)
  546. }
  547. want = []byte("\\\\x\\000\\001\\002\\377\\376abcdefg0123")
  548. got = encode(&parameterStatus{serverVersion: 84000}, input, oid.T_bytea)
  549. if !bytes.Equal(want, got) {
  550. t.Errorf("invalid escape bytea output, got %v but expected %v", got, want)
  551. }
  552. }
  553. func TestByteaOutputFormats(t *testing.T) {
  554. db := openTestConn(t)
  555. defer db.Close()
  556. if getServerVersion(t, db) < 90000 {
  557. // skip
  558. return
  559. }
  560. testByteaOutputFormat := func(f string, usePrepared bool) {
  561. expectedData := []byte("\x5c\x78\x00\xff\x61\x62\x63\x01\x08")
  562. sqlQuery := "SELECT decode('5c7800ff6162630108', 'hex')"
  563. var data []byte
  564. // use a txn to avoid relying on getting the same connection
  565. txn, err := db.Begin()
  566. if err != nil {
  567. t.Fatal(err)
  568. }
  569. defer txn.Rollback()
  570. _, err = txn.Exec("SET LOCAL bytea_output TO " + f)
  571. if err != nil {
  572. t.Fatal(err)
  573. }
  574. var rows *sql.Rows
  575. var stmt *sql.Stmt
  576. if usePrepared {
  577. stmt, err = txn.Prepare(sqlQuery)
  578. if err != nil {
  579. t.Fatal(err)
  580. }
  581. rows, err = stmt.Query()
  582. } else {
  583. // use Query; QueryRow would hide the actual error
  584. rows, err = txn.Query(sqlQuery)
  585. }
  586. if err != nil {
  587. t.Fatal(err)
  588. }
  589. if !rows.Next() {
  590. if rows.Err() != nil {
  591. t.Fatal(rows.Err())
  592. }
  593. t.Fatal("shouldn't happen")
  594. }
  595. err = rows.Scan(&data)
  596. if err != nil {
  597. t.Fatal(err)
  598. }
  599. err = rows.Close()
  600. if err != nil {
  601. t.Fatal(err)
  602. }
  603. if stmt != nil {
  604. err = stmt.Close()
  605. if err != nil {
  606. t.Fatal(err)
  607. }
  608. }
  609. if !bytes.Equal(data, expectedData) {
  610. t.Errorf("unexpected bytea value %v for format %s; expected %v", data, f, expectedData)
  611. }
  612. }
  613. testByteaOutputFormat("hex", false)
  614. testByteaOutputFormat("escape", false)
  615. testByteaOutputFormat("hex", true)
  616. testByteaOutputFormat("escape", true)
  617. }
  618. func TestAppendEncodedText(t *testing.T) {
  619. var buf []byte
  620. buf = appendEncodedText(&parameterStatus{serverVersion: 90000}, buf, int64(10))
  621. buf = append(buf, '\t')
  622. buf = appendEncodedText(&parameterStatus{serverVersion: 90000}, buf, 42.0000000001)
  623. buf = append(buf, '\t')
  624. buf = appendEncodedText(&parameterStatus{serverVersion: 90000}, buf, "hello\tworld")
  625. buf = append(buf, '\t')
  626. buf = appendEncodedText(&parameterStatus{serverVersion: 90000}, buf, []byte{0, 128, 255})
  627. if string(buf) != "10\t42.0000000001\thello\\tworld\t\\\\x0080ff" {
  628. t.Fatal(string(buf))
  629. }
  630. }
  631. func TestAppendEscapedText(t *testing.T) {
  632. if esc := appendEscapedText(nil, "hallo\tescape"); string(esc) != "hallo\\tescape" {
  633. t.Fatal(string(esc))
  634. }
  635. if esc := appendEscapedText(nil, "hallo\\tescape\n"); string(esc) != "hallo\\\\tescape\\n" {
  636. t.Fatal(string(esc))
  637. }
  638. if esc := appendEscapedText(nil, "\n\r\t\f"); string(esc) != "\\n\\r\\t\f" {
  639. t.Fatal(string(esc))
  640. }
  641. }
  642. func TestAppendEscapedTextExistingBuffer(t *testing.T) {
  643. buf := []byte("123\t")
  644. if esc := appendEscapedText(buf, "hallo\tescape"); string(esc) != "123\thallo\\tescape" {
  645. t.Fatal(string(esc))
  646. }
  647. buf = []byte("123\t")
  648. if esc := appendEscapedText(buf, "hallo\\tescape\n"); string(esc) != "123\thallo\\\\tescape\\n" {
  649. t.Fatal(string(esc))
  650. }
  651. buf = []byte("123\t")
  652. if esc := appendEscapedText(buf, "\n\r\t\f"); string(esc) != "123\t\\n\\r\\t\f" {
  653. t.Fatal(string(esc))
  654. }
  655. }
  656. func BenchmarkAppendEscapedText(b *testing.B) {
  657. longString := ""
  658. for i := 0; i < 100; i++ {
  659. longString += "123456789\n"
  660. }
  661. for i := 0; i < b.N; i++ {
  662. appendEscapedText(nil, longString)
  663. }
  664. }
  665. func BenchmarkAppendEscapedTextNoEscape(b *testing.B) {
  666. longString := ""
  667. for i := 0; i < 100; i++ {
  668. longString += "1234567890"
  669. }
  670. for i := 0; i < b.N; i++ {
  671. appendEscapedText(nil, longString)
  672. }
  673. }