encode_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. package pq
  2. import (
  3. "bytes"
  4. "database/sql"
  5. "fmt"
  6. "strings"
  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. expectedErrorStrPrefix := `sql: Scan error on column index 0: unsupported`
  270. type testCases []struct {
  271. Query string
  272. Param string
  273. ExpectedErrStrPrefix string
  274. ExpectedVal interface{}
  275. }
  276. tc := testCases{
  277. {"SELECT $1::timestamp", "-infinity", expectedErrorStrPrefix, "-infinity"},
  278. {"SELECT $1::timestamptz", "-infinity", expectedErrorStrPrefix, "-infinity"},
  279. {"SELECT $1::timestamp", "infinity", expectedErrorStrPrefix, "infinity"},
  280. {"SELECT $1::timestamptz", "infinity", expectedErrorStrPrefix, "infinity"},
  281. }
  282. // try to assert []byte to time.Time
  283. for _, q := range tc {
  284. err = db.QueryRow(q.Query, q.Param).Scan(&resultT)
  285. if !strings.HasPrefix(err.Error(), q.ExpectedErrStrPrefix) {
  286. t.Errorf("Scanning -/+infinity, expected error to have prefix %q, got %q", q.ExpectedErrStrPrefix, err)
  287. }
  288. }
  289. // yield []byte
  290. for _, q := range tc {
  291. var resultI interface{}
  292. err = db.QueryRow(q.Query, q.Param).Scan(&resultI)
  293. if err != nil {
  294. t.Errorf("Scanning -/+infinity, expected no error, got %q", err)
  295. }
  296. result, ok := resultI.([]byte)
  297. if !ok {
  298. t.Errorf("Scanning -/+infinity, expected []byte, got %#v", resultI)
  299. }
  300. if string(result) != q.ExpectedVal {
  301. t.Errorf("Scanning -/+infinity, expected %q, got %q", q.ExpectedVal, result)
  302. }
  303. }
  304. y1500 := time.Date(1500, time.January, 1, 0, 0, 0, 0, time.UTC)
  305. y2500 := time.Date(2500, time.January, 1, 0, 0, 0, 0, time.UTC)
  306. EnableInfinityTs(y1500, y2500)
  307. err = db.QueryRow("SELECT $1::timestamp", "infinity").Scan(&resultT)
  308. if err != nil {
  309. t.Errorf("Scanning infinity, expected no error, got %q", err)
  310. }
  311. if !resultT.Equal(y2500) {
  312. t.Errorf("Scanning infinity, expected %q, got %q", y2500, resultT)
  313. }
  314. err = db.QueryRow("SELECT $1::timestamptz", "infinity").Scan(&resultT)
  315. if err != nil {
  316. t.Errorf("Scanning infinity, expected no error, got %q", err)
  317. }
  318. if !resultT.Equal(y2500) {
  319. t.Errorf("Scanning Infinity, expected time %q, got %q", y2500, resultT.String())
  320. }
  321. err = db.QueryRow("SELECT $1::timestamp", "-infinity").Scan(&resultT)
  322. if err != nil {
  323. t.Errorf("Scanning -infinity, expected no error, got %q", err)
  324. }
  325. if !resultT.Equal(y1500) {
  326. t.Errorf("Scanning -infinity, expected time %q, got %q", y1500, resultT.String())
  327. }
  328. err = db.QueryRow("SELECT $1::timestamptz", "-infinity").Scan(&resultT)
  329. if err != nil {
  330. t.Errorf("Scanning -infinity, expected no error, got %q", err)
  331. }
  332. if !resultT.Equal(y1500) {
  333. t.Errorf("Scanning -infinity, expected time %q, got %q", y1500, resultT.String())
  334. }
  335. ym1500 := time.Date(-1500, time.January, 1, 0, 0, 0, 0, time.UTC)
  336. y11500 := time.Date(11500, time.January, 1, 0, 0, 0, 0, time.UTC)
  337. var s string
  338. err = db.QueryRow("SELECT $1::timestamp::text", ym1500).Scan(&s)
  339. if err != nil {
  340. t.Errorf("Encoding -infinity, expected no error, got %q", err)
  341. }
  342. if s != "-infinity" {
  343. t.Errorf("Encoding -infinity, expected %q, got %q", "-infinity", s)
  344. }
  345. err = db.QueryRow("SELECT $1::timestamptz::text", ym1500).Scan(&s)
  346. if err != nil {
  347. t.Errorf("Encoding -infinity, expected no error, got %q", err)
  348. }
  349. if s != "-infinity" {
  350. t.Errorf("Encoding -infinity, expected %q, got %q", "-infinity", s)
  351. }
  352. err = db.QueryRow("SELECT $1::timestamp::text", y11500).Scan(&s)
  353. if err != nil {
  354. t.Errorf("Encoding infinity, expected no error, got %q", err)
  355. }
  356. if s != "infinity" {
  357. t.Errorf("Encoding infinity, expected %q, got %q", "infinity", s)
  358. }
  359. err = db.QueryRow("SELECT $1::timestamptz::text", y11500).Scan(&s)
  360. if err != nil {
  361. t.Errorf("Encoding infinity, expected no error, got %q", err)
  362. }
  363. if s != "infinity" {
  364. t.Errorf("Encoding infinity, expected %q, got %q", "infinity", s)
  365. }
  366. disableInfinityTs()
  367. var panicErrorString string
  368. func() {
  369. defer func() {
  370. panicErrorString, _ = recover().(string)
  371. }()
  372. EnableInfinityTs(y2500, y1500)
  373. }()
  374. if panicErrorString != infinityTsNegativeMustBeSmaller {
  375. t.Errorf("Expected error, %q, got %q", infinityTsNegativeMustBeSmaller, panicErrorString)
  376. }
  377. }
  378. func TestStringWithNul(t *testing.T) {
  379. db := openTestConn(t)
  380. defer db.Close()
  381. hello0world := string("hello\x00world")
  382. _, err := db.Query("SELECT $1::text", &hello0world)
  383. if err == nil {
  384. t.Fatal("Postgres accepts a string with nul in it; " +
  385. "injection attacks may be plausible")
  386. }
  387. }
  388. func TestByteSliceToText(t *testing.T) {
  389. db := openTestConn(t)
  390. defer db.Close()
  391. b := []byte("hello world")
  392. row := db.QueryRow("SELECT $1::text", b)
  393. var result []byte
  394. err := row.Scan(&result)
  395. if err != nil {
  396. t.Fatal(err)
  397. }
  398. if string(result) != string(b) {
  399. t.Fatalf("expected %v but got %v", b, result)
  400. }
  401. }
  402. func TestStringToBytea(t *testing.T) {
  403. db := openTestConn(t)
  404. defer db.Close()
  405. b := "hello world"
  406. row := db.QueryRow("SELECT $1::bytea", b)
  407. var result []byte
  408. err := row.Scan(&result)
  409. if err != nil {
  410. t.Fatal(err)
  411. }
  412. if !bytes.Equal(result, []byte(b)) {
  413. t.Fatalf("expected %v but got %v", b, result)
  414. }
  415. }
  416. func TestTextByteSliceToUUID(t *testing.T) {
  417. db := openTestConn(t)
  418. defer db.Close()
  419. b := []byte("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11")
  420. row := db.QueryRow("SELECT $1::uuid", b)
  421. var result string
  422. err := row.Scan(&result)
  423. if forceBinaryParameters() {
  424. pqErr := err.(*Error)
  425. if pqErr == nil {
  426. t.Errorf("Expected to get error")
  427. } else if pqErr.Code != "22P03" {
  428. t.Fatalf("Expected to get invalid binary encoding error (22P03), got %s", pqErr.Code)
  429. }
  430. } else {
  431. if err != nil {
  432. t.Fatal(err)
  433. }
  434. if result != string(b) {
  435. t.Fatalf("expected %v but got %v", b, result)
  436. }
  437. }
  438. }
  439. func TestBinaryByteSlicetoUUID(t *testing.T) {
  440. db := openTestConn(t)
  441. defer db.Close()
  442. b := []byte{'\xa0', '\xee', '\xbc', '\x99',
  443. '\x9c', '\x0b',
  444. '\x4e', '\xf8',
  445. '\xbb', '\x00', '\x6b',
  446. '\xb9', '\xbd', '\x38', '\x0a', '\x11'}
  447. row := db.QueryRow("SELECT $1::uuid", b)
  448. var result string
  449. err := row.Scan(&result)
  450. if forceBinaryParameters() {
  451. if err != nil {
  452. t.Fatal(err)
  453. }
  454. if result != string("a0eebc99-9c0b-4ef8-bb00-6bb9bd380a11") {
  455. t.Fatalf("expected %v but got %v", b, result)
  456. }
  457. } else {
  458. pqErr := err.(*Error)
  459. if pqErr == nil {
  460. t.Errorf("Expected to get error")
  461. } else if pqErr.Code != "22021" {
  462. t.Fatalf("Expected to get invalid byte sequence for encoding error (22021), got %s", pqErr.Code)
  463. }
  464. }
  465. }
  466. func TestStringToUUID(t *testing.T) {
  467. db := openTestConn(t)
  468. defer db.Close()
  469. s := "a0eebc99-9c0b-4ef8-bb00-6bb9bd380a11"
  470. row := db.QueryRow("SELECT $1::uuid", s)
  471. var result string
  472. err := row.Scan(&result)
  473. if err != nil {
  474. t.Fatal(err)
  475. }
  476. if result != s {
  477. t.Fatalf("expected %v but got %v", s, result)
  478. }
  479. }
  480. func TestTextByteSliceToInt(t *testing.T) {
  481. db := openTestConn(t)
  482. defer db.Close()
  483. expected := 12345678
  484. b := []byte(fmt.Sprintf("%d", expected))
  485. row := db.QueryRow("SELECT $1::int", b)
  486. var result int
  487. err := row.Scan(&result)
  488. if forceBinaryParameters() {
  489. pqErr := err.(*Error)
  490. if pqErr == nil {
  491. t.Errorf("Expected to get error")
  492. } else if pqErr.Code != "22P03" {
  493. t.Fatalf("Expected to get invalid binary encoding error (22P03), got %s", pqErr.Code)
  494. }
  495. } else {
  496. if err != nil {
  497. t.Fatal(err)
  498. }
  499. if result != expected {
  500. t.Fatalf("expected %v but got %v", expected, result)
  501. }
  502. }
  503. }
  504. func TestBinaryByteSliceToInt(t *testing.T) {
  505. db := openTestConn(t)
  506. defer db.Close()
  507. expected := 12345678
  508. b := []byte{'\x00', '\xbc', '\x61', '\x4e'}
  509. row := db.QueryRow("SELECT $1::int", b)
  510. var result int
  511. err := row.Scan(&result)
  512. if forceBinaryParameters() {
  513. if err != nil {
  514. t.Fatal(err)
  515. }
  516. if result != expected {
  517. t.Fatalf("expected %v but got %v", expected, result)
  518. }
  519. } else {
  520. pqErr := err.(*Error)
  521. if pqErr == nil {
  522. t.Errorf("Expected to get error")
  523. } else if pqErr.Code != "22021" {
  524. t.Fatalf("Expected to get invalid byte sequence for encoding error (22021), got %s", pqErr.Code)
  525. }
  526. }
  527. }
  528. func TestTextDecodeIntoString(t *testing.T) {
  529. input := []byte("hello world")
  530. want := string(input)
  531. for _, typ := range []oid.Oid{oid.T_char, oid.T_varchar, oid.T_text} {
  532. got := decode(&parameterStatus{}, input, typ, formatText)
  533. if got != want {
  534. t.Errorf("invalid string decoding output for %T(%+v), got %v but expected %v", typ, typ, got, want)
  535. }
  536. }
  537. }
  538. func TestByteaOutputFormatEncoding(t *testing.T) {
  539. input := []byte("\\x\x00\x01\x02\xFF\xFEabcdefg0123")
  540. want := []byte("\\x5c78000102fffe6162636465666730313233")
  541. got := encode(&parameterStatus{serverVersion: 90000}, input, oid.T_bytea)
  542. if !bytes.Equal(want, got) {
  543. t.Errorf("invalid hex bytea output, got %v but expected %v", got, want)
  544. }
  545. want = []byte("\\\\x\\000\\001\\002\\377\\376abcdefg0123")
  546. got = encode(&parameterStatus{serverVersion: 84000}, input, oid.T_bytea)
  547. if !bytes.Equal(want, got) {
  548. t.Errorf("invalid escape bytea output, got %v but expected %v", got, want)
  549. }
  550. }
  551. func TestByteaOutputFormats(t *testing.T) {
  552. db := openTestConn(t)
  553. defer db.Close()
  554. if getServerVersion(t, db) < 90000 {
  555. // skip
  556. return
  557. }
  558. testByteaOutputFormat := func(f string, usePrepared bool) {
  559. expectedData := []byte("\x5c\x78\x00\xff\x61\x62\x63\x01\x08")
  560. sqlQuery := "SELECT decode('5c7800ff6162630108', 'hex')"
  561. var data []byte
  562. // use a txn to avoid relying on getting the same connection
  563. txn, err := db.Begin()
  564. if err != nil {
  565. t.Fatal(err)
  566. }
  567. defer txn.Rollback()
  568. _, err = txn.Exec("SET LOCAL bytea_output TO " + f)
  569. if err != nil {
  570. t.Fatal(err)
  571. }
  572. var rows *sql.Rows
  573. var stmt *sql.Stmt
  574. if usePrepared {
  575. stmt, err = txn.Prepare(sqlQuery)
  576. if err != nil {
  577. t.Fatal(err)
  578. }
  579. rows, err = stmt.Query()
  580. } else {
  581. // use Query; QueryRow would hide the actual error
  582. rows, err = txn.Query(sqlQuery)
  583. }
  584. if err != nil {
  585. t.Fatal(err)
  586. }
  587. if !rows.Next() {
  588. if rows.Err() != nil {
  589. t.Fatal(rows.Err())
  590. }
  591. t.Fatal("shouldn't happen")
  592. }
  593. err = rows.Scan(&data)
  594. if err != nil {
  595. t.Fatal(err)
  596. }
  597. err = rows.Close()
  598. if err != nil {
  599. t.Fatal(err)
  600. }
  601. if stmt != nil {
  602. err = stmt.Close()
  603. if err != nil {
  604. t.Fatal(err)
  605. }
  606. }
  607. if !bytes.Equal(data, expectedData) {
  608. t.Errorf("unexpected bytea value %v for format %s; expected %v", data, f, expectedData)
  609. }
  610. }
  611. testByteaOutputFormat("hex", false)
  612. testByteaOutputFormat("escape", false)
  613. testByteaOutputFormat("hex", true)
  614. testByteaOutputFormat("escape", true)
  615. }
  616. func TestAppendEncodedText(t *testing.T) {
  617. var buf []byte
  618. buf = appendEncodedText(&parameterStatus{serverVersion: 90000}, buf, int64(10))
  619. buf = append(buf, '\t')
  620. buf = appendEncodedText(&parameterStatus{serverVersion: 90000}, buf, 42.0000000001)
  621. buf = append(buf, '\t')
  622. buf = appendEncodedText(&parameterStatus{serverVersion: 90000}, buf, "hello\tworld")
  623. buf = append(buf, '\t')
  624. buf = appendEncodedText(&parameterStatus{serverVersion: 90000}, buf, []byte{0, 128, 255})
  625. if string(buf) != "10\t42.0000000001\thello\\tworld\t\\\\x0080ff" {
  626. t.Fatal(string(buf))
  627. }
  628. }
  629. func TestAppendEscapedText(t *testing.T) {
  630. if esc := appendEscapedText(nil, "hallo\tescape"); string(esc) != "hallo\\tescape" {
  631. t.Fatal(string(esc))
  632. }
  633. if esc := appendEscapedText(nil, "hallo\\tescape\n"); string(esc) != "hallo\\\\tescape\\n" {
  634. t.Fatal(string(esc))
  635. }
  636. if esc := appendEscapedText(nil, "\n\r\t\f"); string(esc) != "\\n\\r\\t\f" {
  637. t.Fatal(string(esc))
  638. }
  639. }
  640. func TestAppendEscapedTextExistingBuffer(t *testing.T) {
  641. buf := []byte("123\t")
  642. if esc := appendEscapedText(buf, "hallo\tescape"); string(esc) != "123\thallo\\tescape" {
  643. t.Fatal(string(esc))
  644. }
  645. buf = []byte("123\t")
  646. if esc := appendEscapedText(buf, "hallo\\tescape\n"); string(esc) != "123\thallo\\\\tescape\\n" {
  647. t.Fatal(string(esc))
  648. }
  649. buf = []byte("123\t")
  650. if esc := appendEscapedText(buf, "\n\r\t\f"); string(esc) != "123\t\\n\\r\\t\f" {
  651. t.Fatal(string(esc))
  652. }
  653. }
  654. func BenchmarkAppendEscapedText(b *testing.B) {
  655. longString := ""
  656. for i := 0; i < 100; i++ {
  657. longString += "123456789\n"
  658. }
  659. for i := 0; i < b.N; i++ {
  660. appendEscapedText(nil, longString)
  661. }
  662. }
  663. func BenchmarkAppendEscapedTextNoEscape(b *testing.B) {
  664. longString := ""
  665. for i := 0; i < 100; i++ {
  666. longString += "1234567890"
  667. }
  668. for i := 0; i < b.N; i++ {
  669. appendEscapedText(nil, longString)
  670. }
  671. }