driver_test.go 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  1. // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
  2. //
  3. // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public
  6. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  7. // You can obtain one at http://mozilla.org/MPL/2.0/.
  8. package mysql
  9. import (
  10. "crypto/tls"
  11. "database/sql"
  12. "fmt"
  13. "io"
  14. "io/ioutil"
  15. "net"
  16. "net/url"
  17. "os"
  18. "strings"
  19. "testing"
  20. "time"
  21. )
  22. var (
  23. dsn string
  24. netAddr string
  25. available bool
  26. )
  27. var (
  28. tDate = time.Date(2012, 6, 14, 0, 0, 0, 0, time.UTC)
  29. sDate = "2012-06-14"
  30. tDateTime = time.Date(2011, 11, 20, 21, 27, 37, 0, time.UTC)
  31. sDateTime = "2011-11-20 21:27:37"
  32. tDate0 = time.Time{}
  33. sDate0 = "0000-00-00"
  34. sDateTime0 = "0000-00-00 00:00:00"
  35. )
  36. // See https://github.com/go-sql-driver/mysql/wiki/Testing
  37. func init() {
  38. env := func(key, defaultValue string) string {
  39. if value := os.Getenv(key); value != "" {
  40. return value
  41. }
  42. return defaultValue
  43. }
  44. user := env("MYSQL_TEST_USER", "root")
  45. pass := env("MYSQL_TEST_PASS", "")
  46. prot := env("MYSQL_TEST_PROT", "tcp")
  47. addr := env("MYSQL_TEST_ADDR", "localhost:3306")
  48. dbname := env("MYSQL_TEST_DBNAME", "gotest")
  49. netAddr = fmt.Sprintf("%s(%s)", prot, addr)
  50. dsn = fmt.Sprintf("%s:%s@%s/%s?timeout=30s&strict=true", user, pass, netAddr, dbname)
  51. c, err := net.Dial(prot, addr)
  52. if err == nil {
  53. available = true
  54. c.Close()
  55. }
  56. }
  57. type DBTest struct {
  58. *testing.T
  59. db *sql.DB
  60. }
  61. func runTests(t *testing.T, dsn string, tests ...func(dbt *DBTest)) {
  62. if !available {
  63. t.Skipf("MySQL-Server not running on %s", netAddr)
  64. }
  65. db, err := sql.Open("mysql", dsn)
  66. if err != nil {
  67. t.Fatalf("Error connecting: %s", err.Error())
  68. }
  69. defer db.Close()
  70. db.Exec("DROP TABLE IF EXISTS test")
  71. dbt := &DBTest{t, db}
  72. for _, test := range tests {
  73. test(dbt)
  74. dbt.db.Exec("DROP TABLE IF EXISTS test")
  75. }
  76. }
  77. func (dbt *DBTest) fail(method, query string, err error) {
  78. if len(query) > 300 {
  79. query = "[query too large to print]"
  80. }
  81. dbt.Fatalf("Error on %s %s: %s", method, query, err.Error())
  82. }
  83. func (dbt *DBTest) mustExec(query string, args ...interface{}) (res sql.Result) {
  84. res, err := dbt.db.Exec(query, args...)
  85. if err != nil {
  86. dbt.fail("Exec", query, err)
  87. }
  88. return res
  89. }
  90. func (dbt *DBTest) mustQuery(query string, args ...interface{}) (rows *sql.Rows) {
  91. rows, err := dbt.db.Query(query, args...)
  92. if err != nil {
  93. dbt.fail("Query", query, err)
  94. }
  95. return rows
  96. }
  97. func TestCharset(t *testing.T) {
  98. if !available {
  99. t.Skipf("MySQL-Server not running on %s", netAddr)
  100. }
  101. mustSetCharset := func(charsetParam, expected string) {
  102. runTests(t, dsn+"&"+charsetParam, func(dbt *DBTest) {
  103. rows := dbt.mustQuery("SELECT @@character_set_connection")
  104. defer rows.Close()
  105. if !rows.Next() {
  106. dbt.Fatalf("Error getting connection charset: %s", rows.Err())
  107. }
  108. var got string
  109. rows.Scan(&got)
  110. if got != expected {
  111. dbt.Fatalf("Expected connection charset %s but got %s", expected, got)
  112. }
  113. })
  114. }
  115. // non utf8 test
  116. mustSetCharset("charset=ascii", "ascii")
  117. // when the first charset is invalid, use the second
  118. mustSetCharset("charset=none,utf8", "utf8")
  119. // when the first charset is valid, use it
  120. mustSetCharset("charset=ascii,utf8", "ascii")
  121. mustSetCharset("charset=utf8,ascii", "utf8")
  122. }
  123. func TestFailingCharset(t *testing.T) {
  124. runTests(t, dsn+"&charset=none", func(dbt *DBTest) {
  125. // run query to really establish connection...
  126. _, err := dbt.db.Exec("SELECT 1")
  127. if err == nil {
  128. dbt.db.Close()
  129. t.Fatalf("Connection must not succeed without a valid charset")
  130. }
  131. })
  132. }
  133. func TestRawBytesResultExceedsBuffer(t *testing.T) {
  134. runTests(t, dsn, func(dbt *DBTest) {
  135. // defaultBufSize from buffer.go
  136. expected := strings.Repeat("abc", defaultBufSize)
  137. rows := dbt.mustQuery("SELECT '" + expected + "'")
  138. defer rows.Close()
  139. if !rows.Next() {
  140. dbt.Error("expected result, got none")
  141. }
  142. var result sql.RawBytes
  143. rows.Scan(&result)
  144. if expected != string(result) {
  145. dbt.Error("result did not match expected value")
  146. }
  147. })
  148. }
  149. func TestTimezoneConversion(t *testing.T) {
  150. zones := []string{"UTC", "US/Central", "US/Pacific", "Local"}
  151. // Regression test for timezone handling
  152. tzTest := func(dbt *DBTest) {
  153. // Create table
  154. dbt.mustExec("CREATE TABLE test (ts TIMESTAMP)")
  155. // Insert local time into database (should be converted)
  156. usCentral, _ := time.LoadLocation("US/Central")
  157. now := time.Now().In(usCentral)
  158. dbt.mustExec("INSERT INTO test VALUE (?)", now)
  159. // Retrieve time from DB
  160. rows := dbt.mustQuery("SELECT ts FROM test")
  161. if !rows.Next() {
  162. dbt.Fatal("Didn't get any rows out")
  163. }
  164. var nowDB time.Time
  165. err := rows.Scan(&nowDB)
  166. if err != nil {
  167. dbt.Fatal("Err", err)
  168. }
  169. // Check that dates match
  170. if now.Unix() != nowDB.Unix() {
  171. dbt.Errorf("Times don't match.\n")
  172. dbt.Errorf(" Now(%v)=%v\n", usCentral, now)
  173. dbt.Errorf(" Now(UTC)=%v\n", nowDB)
  174. }
  175. }
  176. for _, tz := range zones {
  177. runTests(t, dsn+"&parseTime=true&loc="+url.QueryEscape(tz), tzTest)
  178. }
  179. }
  180. func TestCRUD(t *testing.T) {
  181. runTests(t, dsn, func(dbt *DBTest) {
  182. // Create Table
  183. dbt.mustExec("CREATE TABLE test (value BOOL)")
  184. // Test for unexpected data
  185. var out bool
  186. rows := dbt.mustQuery("SELECT * FROM test")
  187. if rows.Next() {
  188. dbt.Error("unexpected data in empty table")
  189. }
  190. // Create Data
  191. res := dbt.mustExec("INSERT INTO test VALUES (1)")
  192. count, err := res.RowsAffected()
  193. if err != nil {
  194. dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  195. }
  196. if count != 1 {
  197. dbt.Fatalf("Expected 1 affected row, got %d", count)
  198. }
  199. id, err := res.LastInsertId()
  200. if err != nil {
  201. dbt.Fatalf("res.LastInsertId() returned error: %s", err.Error())
  202. }
  203. if id != 0 {
  204. dbt.Fatalf("Expected InsertID 0, got %d", id)
  205. }
  206. // Read
  207. rows = dbt.mustQuery("SELECT value FROM test")
  208. if rows.Next() {
  209. rows.Scan(&out)
  210. if true != out {
  211. dbt.Errorf("true != %t", out)
  212. }
  213. if rows.Next() {
  214. dbt.Error("unexpected data")
  215. }
  216. } else {
  217. dbt.Error("no data")
  218. }
  219. // Update
  220. res = dbt.mustExec("UPDATE test SET value = ? WHERE value = ?", false, true)
  221. count, err = res.RowsAffected()
  222. if err != nil {
  223. dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  224. }
  225. if count != 1 {
  226. dbt.Fatalf("Expected 1 affected row, got %d", count)
  227. }
  228. // Check Update
  229. rows = dbt.mustQuery("SELECT value FROM test")
  230. if rows.Next() {
  231. rows.Scan(&out)
  232. if false != out {
  233. dbt.Errorf("false != %t", out)
  234. }
  235. if rows.Next() {
  236. dbt.Error("unexpected data")
  237. }
  238. } else {
  239. dbt.Error("no data")
  240. }
  241. // Delete
  242. res = dbt.mustExec("DELETE FROM test WHERE value = ?", false)
  243. count, err = res.RowsAffected()
  244. if err != nil {
  245. dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  246. }
  247. if count != 1 {
  248. dbt.Fatalf("Expected 1 affected row, got %d", count)
  249. }
  250. // Check for unexpected rows
  251. res = dbt.mustExec("DELETE FROM test")
  252. count, err = res.RowsAffected()
  253. if err != nil {
  254. dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  255. }
  256. if count != 0 {
  257. dbt.Fatalf("Expected 0 affected row, got %d", count)
  258. }
  259. })
  260. }
  261. func TestInt(t *testing.T) {
  262. runTests(t, dsn, func(dbt *DBTest) {
  263. types := [5]string{"TINYINT", "SMALLINT", "MEDIUMINT", "INT", "BIGINT"}
  264. in := int64(42)
  265. var out int64
  266. var rows *sql.Rows
  267. // SIGNED
  268. for _, v := range types {
  269. dbt.mustExec("CREATE TABLE test (value " + v + ")")
  270. dbt.mustExec("INSERT INTO test VALUES (?)", in)
  271. rows = dbt.mustQuery("SELECT value FROM test")
  272. if rows.Next() {
  273. rows.Scan(&out)
  274. if in != out {
  275. dbt.Errorf("%s: %d != %d", v, in, out)
  276. }
  277. } else {
  278. dbt.Errorf("%s: no data", v)
  279. }
  280. dbt.mustExec("DROP TABLE IF EXISTS test")
  281. }
  282. // UNSIGNED ZEROFILL
  283. for _, v := range types {
  284. dbt.mustExec("CREATE TABLE test (value " + v + " ZEROFILL)")
  285. dbt.mustExec("INSERT INTO test VALUES (?)", in)
  286. rows = dbt.mustQuery("SELECT value FROM test")
  287. if rows.Next() {
  288. rows.Scan(&out)
  289. if in != out {
  290. dbt.Errorf("%s ZEROFILL: %d != %d", v, in, out)
  291. }
  292. } else {
  293. dbt.Errorf("%s ZEROFILL: no data", v)
  294. }
  295. dbt.mustExec("DROP TABLE IF EXISTS test")
  296. }
  297. })
  298. }
  299. func TestFloat(t *testing.T) {
  300. runTests(t, dsn, func(dbt *DBTest) {
  301. types := [2]string{"FLOAT", "DOUBLE"}
  302. in := float32(42.23)
  303. var out float32
  304. var rows *sql.Rows
  305. for _, v := range types {
  306. dbt.mustExec("CREATE TABLE test (value " + v + ")")
  307. dbt.mustExec("INSERT INTO test VALUES (?)", in)
  308. rows = dbt.mustQuery("SELECT value FROM test")
  309. if rows.Next() {
  310. rows.Scan(&out)
  311. if in != out {
  312. dbt.Errorf("%s: %g != %g", v, in, out)
  313. }
  314. } else {
  315. dbt.Errorf("%s: no data", v)
  316. }
  317. dbt.mustExec("DROP TABLE IF EXISTS test")
  318. }
  319. })
  320. }
  321. func TestString(t *testing.T) {
  322. runTests(t, dsn, func(dbt *DBTest) {
  323. types := [6]string{"CHAR(255)", "VARCHAR(255)", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT"}
  324. in := "κόσμε üöäßñóùéàâÿœ'îë Árvíztűrő いろはにほへとちりぬるを イロハニホヘト דג סקרן чащах น่าฟังเอย"
  325. var out string
  326. var rows *sql.Rows
  327. for _, v := range types {
  328. dbt.mustExec("CREATE TABLE test (value " + v + ") CHARACTER SET utf8")
  329. dbt.mustExec("INSERT INTO test VALUES (?)", in)
  330. rows = dbt.mustQuery("SELECT value FROM test")
  331. if rows.Next() {
  332. rows.Scan(&out)
  333. if in != out {
  334. dbt.Errorf("%s: %s != %s", v, in, out)
  335. }
  336. } else {
  337. dbt.Errorf("%s: no data", v)
  338. }
  339. dbt.mustExec("DROP TABLE IF EXISTS test")
  340. }
  341. // BLOB
  342. dbt.mustExec("CREATE TABLE test (id int, value BLOB) CHARACTER SET utf8")
  343. id := 2
  344. in = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " +
  345. "sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " +
  346. "sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. " +
  347. "Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. " +
  348. "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " +
  349. "sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " +
  350. "sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. " +
  351. "Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
  352. dbt.mustExec("INSERT INTO test VALUES (?, ?)", id, in)
  353. err := dbt.db.QueryRow("SELECT value FROM test WHERE id = ?", id).Scan(&out)
  354. if err != nil {
  355. dbt.Fatalf("Error on BLOB-Query: %s", err.Error())
  356. } else if out != in {
  357. dbt.Errorf("BLOB: %s != %s", in, out)
  358. }
  359. })
  360. }
  361. func TestDateTime(t *testing.T) {
  362. type testmode struct {
  363. selectSuffix string
  364. args []interface{}
  365. }
  366. type timetest struct {
  367. in interface{}
  368. sOut string
  369. tOut time.Time
  370. tIsZero bool
  371. }
  372. type tester func(dbt *DBTest, rows *sql.Rows,
  373. test *timetest, sqltype, resulttype, mode string)
  374. type setup struct {
  375. vartype string
  376. dsnSuffix string
  377. test tester
  378. }
  379. var (
  380. modes = map[string]*testmode{
  381. "text": &testmode{},
  382. "binary": &testmode{" WHERE 1 = ?", []interface{}{1}},
  383. }
  384. timetests = map[string][]*timetest{
  385. "DATE": {
  386. {sDate, sDate, tDate, false},
  387. {sDate0, sDate0, tDate0, true},
  388. {tDate, sDate, tDate, false},
  389. {tDate0, sDate0, tDate0, true},
  390. },
  391. "DATETIME": {
  392. {sDateTime, sDateTime, tDateTime, false},
  393. {sDateTime0, sDateTime0, tDate0, true},
  394. {tDateTime, sDateTime, tDateTime, false},
  395. {tDate0, sDateTime0, tDate0, true},
  396. },
  397. }
  398. setups = []*setup{
  399. {"string", "&parseTime=false", func(
  400. dbt *DBTest, rows *sql.Rows, test *timetest, sqltype, resulttype, mode string) {
  401. var sOut string
  402. if err := rows.Scan(&sOut); err != nil {
  403. dbt.Errorf("%s (%s %s): %s", sqltype, resulttype, mode, err.Error())
  404. } else if test.sOut != sOut {
  405. dbt.Errorf("%s (%s %s): %s != %s", sqltype, resulttype, mode, test.sOut, sOut)
  406. }
  407. }},
  408. {"time.Time", "&parseTime=true", func(
  409. dbt *DBTest, rows *sql.Rows, test *timetest, sqltype, resulttype, mode string) {
  410. var tOut time.Time
  411. if err := rows.Scan(&tOut); err != nil {
  412. dbt.Errorf("%s (%s %s): %s", sqltype, resulttype, mode, err.Error())
  413. } else if test.tOut != tOut || test.tIsZero != tOut.IsZero() {
  414. dbt.Errorf("%s (%s %s): %s [%t] != %s [%t]", sqltype, resulttype, mode, test.tOut, test.tIsZero, tOut, tOut.IsZero())
  415. }
  416. }},
  417. }
  418. )
  419. var s *setup
  420. testTime := func(dbt *DBTest) {
  421. var rows *sql.Rows
  422. for sqltype, tests := range timetests {
  423. dbt.mustExec("CREATE TABLE test (value " + sqltype + ")")
  424. for _, test := range tests {
  425. for mode, q := range modes {
  426. dbt.mustExec("TRUNCATE test")
  427. dbt.mustExec("INSERT INTO test VALUES (?)", test.in)
  428. rows = dbt.mustQuery("SELECT value FROM test"+q.selectSuffix, q.args...)
  429. if rows.Next() {
  430. s.test(dbt, rows, test, sqltype, s.vartype, mode)
  431. } else {
  432. if err := rows.Err(); err != nil {
  433. dbt.Errorf("%s (%s %s): %s",
  434. sqltype, s.vartype, mode, err.Error())
  435. } else {
  436. dbt.Errorf("%s (%s %s): no data",
  437. sqltype, s.vartype, mode)
  438. }
  439. }
  440. }
  441. }
  442. dbt.mustExec("DROP TABLE IF EXISTS test")
  443. }
  444. }
  445. timeDsn := dsn + "&sql_mode=ALLOW_INVALID_DATES"
  446. for _, v := range setups {
  447. s = v
  448. runTests(t, timeDsn+s.dsnSuffix, testTime)
  449. }
  450. }
  451. // This tests for https://github.com/go-sql-driver/mysql/pull/139
  452. //
  453. // An extra (invisible) nil byte was being added to the beginning of positive
  454. // time strings.
  455. func TestTimeSign(t *testing.T) {
  456. runTests(t, dsn, func(dbt *DBTest) {
  457. var sTimes = []struct {
  458. value string
  459. fieldType string
  460. }{
  461. {"12:34:56", "TIME"},
  462. {"-12:34:56", "TIME"},
  463. // As described in http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
  464. // they *should* work, but only in 5.6+.
  465. // { "12:34:56.789", "TIME(3)" },
  466. // { "-12:34:56.789", "TIME(3)" },
  467. }
  468. for _, sTime := range sTimes {
  469. dbt.db.Exec("DROP TABLE IF EXISTS test")
  470. dbt.mustExec("CREATE TABLE test (id INT, time_field " + sTime.fieldType + ")")
  471. dbt.mustExec("INSERT INTO test (id, time_field) VALUES(1, '" + sTime.value + "')")
  472. rows := dbt.mustQuery("SELECT time_field FROM test WHERE id = ?", 1)
  473. if rows.Next() {
  474. var oTime string
  475. rows.Scan(&oTime)
  476. if oTime != sTime.value {
  477. dbt.Errorf(`time values differ: got %q, expected %q.`, oTime, sTime.value)
  478. }
  479. } else {
  480. dbt.Error("expecting at least one row.")
  481. }
  482. }
  483. })
  484. }
  485. func TestNULL(t *testing.T) {
  486. runTests(t, dsn, func(dbt *DBTest) {
  487. nullStmt, err := dbt.db.Prepare("SELECT NULL")
  488. if err != nil {
  489. dbt.Fatal(err)
  490. }
  491. defer nullStmt.Close()
  492. nonNullStmt, err := dbt.db.Prepare("SELECT 1")
  493. if err != nil {
  494. dbt.Fatal(err)
  495. }
  496. defer nonNullStmt.Close()
  497. // NullBool
  498. var nb sql.NullBool
  499. // Invalid
  500. err = nullStmt.QueryRow().Scan(&nb)
  501. if err != nil {
  502. dbt.Fatal(err)
  503. }
  504. if nb.Valid {
  505. dbt.Error("Valid NullBool which should be invalid")
  506. }
  507. // Valid
  508. err = nonNullStmt.QueryRow().Scan(&nb)
  509. if err != nil {
  510. dbt.Fatal(err)
  511. }
  512. if !nb.Valid {
  513. dbt.Error("Invalid NullBool which should be valid")
  514. } else if nb.Bool != true {
  515. dbt.Errorf("Unexpected NullBool value: %t (should be true)", nb.Bool)
  516. }
  517. // NullFloat64
  518. var nf sql.NullFloat64
  519. // Invalid
  520. err = nullStmt.QueryRow().Scan(&nf)
  521. if err != nil {
  522. dbt.Fatal(err)
  523. }
  524. if nf.Valid {
  525. dbt.Error("Valid NullFloat64 which should be invalid")
  526. }
  527. // Valid
  528. err = nonNullStmt.QueryRow().Scan(&nf)
  529. if err != nil {
  530. dbt.Fatal(err)
  531. }
  532. if !nf.Valid {
  533. dbt.Error("Invalid NullFloat64 which should be valid")
  534. } else if nf.Float64 != float64(1) {
  535. dbt.Errorf("Unexpected NullFloat64 value: %f (should be 1.0)", nf.Float64)
  536. }
  537. // NullInt64
  538. var ni sql.NullInt64
  539. // Invalid
  540. err = nullStmt.QueryRow().Scan(&ni)
  541. if err != nil {
  542. dbt.Fatal(err)
  543. }
  544. if ni.Valid {
  545. dbt.Error("Valid NullInt64 which should be invalid")
  546. }
  547. // Valid
  548. err = nonNullStmt.QueryRow().Scan(&ni)
  549. if err != nil {
  550. dbt.Fatal(err)
  551. }
  552. if !ni.Valid {
  553. dbt.Error("Invalid NullInt64 which should be valid")
  554. } else if ni.Int64 != int64(1) {
  555. dbt.Errorf("Unexpected NullInt64 value: %d (should be 1)", ni.Int64)
  556. }
  557. // NullString
  558. var ns sql.NullString
  559. // Invalid
  560. err = nullStmt.QueryRow().Scan(&ns)
  561. if err != nil {
  562. dbt.Fatal(err)
  563. }
  564. if ns.Valid {
  565. dbt.Error("Valid NullString which should be invalid")
  566. }
  567. // Valid
  568. err = nonNullStmt.QueryRow().Scan(&ns)
  569. if err != nil {
  570. dbt.Fatal(err)
  571. }
  572. if !ns.Valid {
  573. dbt.Error("Invalid NullString which should be valid")
  574. } else if ns.String != `1` {
  575. dbt.Error("Unexpected NullString value:" + ns.String + " (should be `1`)")
  576. }
  577. // Insert NULL
  578. dbt.mustExec("CREATE TABLE test (dummmy1 int, value int, dummy2 int)")
  579. dbt.mustExec("INSERT INTO test VALUES (?, ?, ?)", 1, nil, 2)
  580. var out interface{}
  581. rows := dbt.mustQuery("SELECT * FROM test")
  582. if rows.Next() {
  583. rows.Scan(&out)
  584. if out != nil {
  585. dbt.Errorf("%v != nil", out)
  586. }
  587. } else {
  588. dbt.Error("no data")
  589. }
  590. })
  591. }
  592. func TestLongData(t *testing.T) {
  593. runTests(t, dsn, func(dbt *DBTest) {
  594. var maxAllowedPacketSize int
  595. err := dbt.db.QueryRow("select @@max_allowed_packet").Scan(&maxAllowedPacketSize)
  596. if err != nil {
  597. dbt.Fatal(err)
  598. }
  599. maxAllowedPacketSize--
  600. // don't get too ambitious
  601. if maxAllowedPacketSize > 1<<25 {
  602. maxAllowedPacketSize = 1 << 25
  603. }
  604. dbt.mustExec("CREATE TABLE test (value LONGBLOB)")
  605. in := strings.Repeat(`a`, maxAllowedPacketSize+1)
  606. var out string
  607. var rows *sql.Rows
  608. // Long text data
  609. const nonDataQueryLen = 28 // length query w/o value
  610. inS := in[:maxAllowedPacketSize-nonDataQueryLen]
  611. dbt.mustExec("INSERT INTO test VALUES('" + inS + "')")
  612. rows = dbt.mustQuery("SELECT value FROM test")
  613. if rows.Next() {
  614. rows.Scan(&out)
  615. if inS != out {
  616. dbt.Fatalf("LONGBLOB: length in: %d, length out: %d", len(inS), len(out))
  617. }
  618. if rows.Next() {
  619. dbt.Error("LONGBLOB: unexpexted row")
  620. }
  621. } else {
  622. dbt.Fatalf("LONGBLOB: no data")
  623. }
  624. // Empty table
  625. dbt.mustExec("TRUNCATE TABLE test")
  626. // Long binary data
  627. dbt.mustExec("INSERT INTO test VALUES(?)", in)
  628. rows = dbt.mustQuery("SELECT value FROM test WHERE 1=?", 1)
  629. if rows.Next() {
  630. rows.Scan(&out)
  631. if in != out {
  632. dbt.Fatalf("LONGBLOB: length in: %d, length out: %d", len(in), len(out))
  633. }
  634. if rows.Next() {
  635. dbt.Error("LONGBLOB: unexpexted row")
  636. }
  637. } else {
  638. if err = rows.Err(); err != nil {
  639. dbt.Fatalf("LONGBLOB: no data (err: %s)", err.Error())
  640. } else {
  641. dbt.Fatal("LONGBLOB: no data (err: <nil>)")
  642. }
  643. }
  644. })
  645. }
  646. func TestLoadData(t *testing.T) {
  647. runTests(t, dsn, func(dbt *DBTest) {
  648. verifyLoadDataResult := func() {
  649. rows, err := dbt.db.Query("SELECT * FROM test")
  650. if err != nil {
  651. dbt.Fatal(err.Error())
  652. }
  653. i := 0
  654. values := [4]string{
  655. "a string",
  656. "a string containing a \t",
  657. "a string containing a \n",
  658. "a string containing both \t\n",
  659. }
  660. var id int
  661. var value string
  662. for rows.Next() {
  663. i++
  664. err = rows.Scan(&id, &value)
  665. if err != nil {
  666. dbt.Fatal(err.Error())
  667. }
  668. if i != id {
  669. dbt.Fatalf("%d != %d", i, id)
  670. }
  671. if values[i-1] != value {
  672. dbt.Fatalf("%s != %s", values[i-1], value)
  673. }
  674. }
  675. err = rows.Err()
  676. if err != nil {
  677. dbt.Fatal(err.Error())
  678. }
  679. if i != 4 {
  680. dbt.Fatalf("Rows count mismatch. Got %d, want 4", i)
  681. }
  682. }
  683. file, err := ioutil.TempFile("", "gotest")
  684. defer os.Remove(file.Name())
  685. if err != nil {
  686. dbt.Fatal(err)
  687. }
  688. file.WriteString("1\ta string\n2\ta string containing a \\t\n3\ta string containing a \\n\n4\ta string containing both \\t\\n\n")
  689. file.Close()
  690. dbt.db.Exec("DROP TABLE IF EXISTS test")
  691. dbt.mustExec("CREATE TABLE test (id INT NOT NULL PRIMARY KEY, value TEXT NOT NULL) CHARACTER SET utf8")
  692. // Local File
  693. RegisterLocalFile(file.Name())
  694. dbt.mustExec(fmt.Sprintf("LOAD DATA LOCAL INFILE '%q' INTO TABLE test", file.Name()))
  695. verifyLoadDataResult()
  696. // negative test
  697. _, err = dbt.db.Exec("LOAD DATA LOCAL INFILE 'doesnotexist' INTO TABLE test")
  698. if err == nil {
  699. dbt.Fatal("Load non-existent file didn't fail")
  700. } else if err.Error() != "Local File 'doesnotexist' is not registered. Use the DSN parameter 'allowAllFiles=true' to allow all files" {
  701. dbt.Fatal(err.Error())
  702. }
  703. // Empty table
  704. dbt.mustExec("TRUNCATE TABLE test")
  705. // Reader
  706. RegisterReaderHandler("test", func() io.Reader {
  707. file, err = os.Open(file.Name())
  708. if err != nil {
  709. dbt.Fatal(err)
  710. }
  711. return file
  712. })
  713. dbt.mustExec("LOAD DATA LOCAL INFILE 'Reader::test' INTO TABLE test")
  714. verifyLoadDataResult()
  715. // negative test
  716. _, err = dbt.db.Exec("LOAD DATA LOCAL INFILE 'Reader::doesnotexist' INTO TABLE test")
  717. if err == nil {
  718. dbt.Fatal("Load non-existent Reader didn't fail")
  719. } else if err.Error() != "Reader 'doesnotexist' is not registered" {
  720. dbt.Fatal(err.Error())
  721. }
  722. })
  723. }
  724. func TestFoundRows(t *testing.T) {
  725. runTests(t, dsn, func(dbt *DBTest) {
  726. dbt.mustExec("CREATE TABLE test (id INT NOT NULL ,data INT NOT NULL)")
  727. dbt.mustExec("INSERT INTO test (id, data) VALUES (0, 0),(0, 0),(1, 0),(1, 0),(1, 1)")
  728. res := dbt.mustExec("UPDATE test SET data = 1 WHERE id = 0")
  729. count, err := res.RowsAffected()
  730. if err != nil {
  731. dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  732. }
  733. if count != 2 {
  734. dbt.Fatalf("Expected 2 affected rows, got %d", count)
  735. }
  736. res = dbt.mustExec("UPDATE test SET data = 1 WHERE id = 1")
  737. count, err = res.RowsAffected()
  738. if err != nil {
  739. dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  740. }
  741. if count != 2 {
  742. dbt.Fatalf("Expected 2 affected rows, got %d", count)
  743. }
  744. })
  745. runTests(t, dsn+"&clientFoundRows=true", func(dbt *DBTest) {
  746. dbt.mustExec("CREATE TABLE test (id INT NOT NULL ,data INT NOT NULL)")
  747. dbt.mustExec("INSERT INTO test (id, data) VALUES (0, 0),(0, 0),(1, 0),(1, 0),(1, 1)")
  748. res := dbt.mustExec("UPDATE test SET data = 1 WHERE id = 0")
  749. count, err := res.RowsAffected()
  750. if err != nil {
  751. dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  752. }
  753. if count != 2 {
  754. dbt.Fatalf("Expected 2 matched rows, got %d", count)
  755. }
  756. res = dbt.mustExec("UPDATE test SET data = 1 WHERE id = 1")
  757. count, err = res.RowsAffected()
  758. if err != nil {
  759. dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  760. }
  761. if count != 3 {
  762. dbt.Fatalf("Expected 3 matched rows, got %d", count)
  763. }
  764. })
  765. }
  766. func TestStrict(t *testing.T) {
  767. // ALLOW_INVALID_DATES to get rid of stricter modes - we want to test for warnings, not errors
  768. relaxedDsn := dsn + "&sql_mode=ALLOW_INVALID_DATES"
  769. runTests(t, relaxedDsn, func(dbt *DBTest) {
  770. dbt.mustExec("CREATE TABLE test (a TINYINT NOT NULL, b CHAR(4))")
  771. var queries = [...]struct {
  772. in string
  773. codes []string
  774. }{
  775. {"DROP TABLE IF EXISTS no_such_table", []string{"1051"}},
  776. {"INSERT INTO test VALUES(10,'mysql'),(NULL,'test'),(300,'Open Source')", []string{"1265", "1048", "1264", "1265"}},
  777. }
  778. var err error
  779. var checkWarnings = func(err error, mode string, idx int) {
  780. if err == nil {
  781. dbt.Errorf("Expected STRICT error on query [%s] %s", mode, queries[idx].in)
  782. }
  783. if warnings, ok := err.(MySQLWarnings); ok {
  784. var codes = make([]string, len(warnings))
  785. for i := range warnings {
  786. codes[i] = warnings[i].Code
  787. }
  788. if len(codes) != len(queries[idx].codes) {
  789. dbt.Errorf("Unexpected STRICT error count on query [%s] %s: Wanted %v, Got %v", mode, queries[idx].in, queries[idx].codes, codes)
  790. }
  791. for i := range warnings {
  792. if codes[i] != queries[idx].codes[i] {
  793. dbt.Errorf("Unexpected STRICT error codes on query [%s] %s: Wanted %v, Got %v", mode, queries[idx].in, queries[idx].codes, codes)
  794. return
  795. }
  796. }
  797. } else {
  798. dbt.Errorf("Unexpected error on query [%s] %s: %s", mode, queries[idx].in, err.Error())
  799. }
  800. }
  801. // text protocol
  802. for i := range queries {
  803. _, err = dbt.db.Exec(queries[i].in)
  804. checkWarnings(err, "text", i)
  805. }
  806. var stmt *sql.Stmt
  807. // binary protocol
  808. for i := range queries {
  809. stmt, err = dbt.db.Prepare(queries[i].in)
  810. if err != nil {
  811. dbt.Errorf("Error on preparing query %s: %s", queries[i].in, err.Error())
  812. }
  813. _, err = stmt.Exec()
  814. checkWarnings(err, "binary", i)
  815. err = stmt.Close()
  816. if err != nil {
  817. dbt.Errorf("Error on closing stmt for query %s: %s", queries[i].in, err.Error())
  818. }
  819. }
  820. })
  821. }
  822. func TestTLS(t *testing.T) {
  823. tlsTest := func(dbt *DBTest) {
  824. if err := dbt.db.Ping(); err != nil {
  825. if err == errNoTLS {
  826. dbt.Skip("Server does not support TLS")
  827. } else {
  828. dbt.Fatalf("Error on Ping: %s", err.Error())
  829. }
  830. }
  831. rows := dbt.mustQuery("SHOW STATUS LIKE 'Ssl_cipher'")
  832. var variable, value *sql.RawBytes
  833. for rows.Next() {
  834. if err := rows.Scan(&variable, &value); err != nil {
  835. dbt.Fatal(err.Error())
  836. }
  837. if value == nil {
  838. dbt.Fatal("No Cipher")
  839. }
  840. }
  841. }
  842. runTests(t, dsn+"&tls=skip-verify", tlsTest)
  843. // Verify that registering / using a custom cfg works
  844. RegisterTLSConfig("custom-skip-verify", &tls.Config{
  845. InsecureSkipVerify: true,
  846. })
  847. runTests(t, dsn+"&tls=custom-skip-verify", tlsTest)
  848. }
  849. // Special cases
  850. func TestRowsClose(t *testing.T) {
  851. runTests(t, dsn, func(dbt *DBTest) {
  852. rows, err := dbt.db.Query("SELECT 1")
  853. if err != nil {
  854. dbt.Fatal(err)
  855. }
  856. err = rows.Close()
  857. if err != nil {
  858. dbt.Fatal(err)
  859. }
  860. if rows.Next() {
  861. dbt.Fatal("Unexpected row after rows.Close()")
  862. }
  863. err = rows.Err()
  864. if err != nil {
  865. dbt.Fatal(err)
  866. }
  867. })
  868. }
  869. // dangling statements
  870. // http://code.google.com/p/go/issues/detail?id=3865
  871. func TestCloseStmtBeforeRows(t *testing.T) {
  872. runTests(t, dsn, func(dbt *DBTest) {
  873. stmt, err := dbt.db.Prepare("SELECT 1")
  874. if err != nil {
  875. dbt.Fatal(err)
  876. }
  877. rows, err := stmt.Query()
  878. if err != nil {
  879. stmt.Close()
  880. dbt.Fatal(err)
  881. }
  882. defer rows.Close()
  883. err = stmt.Close()
  884. if err != nil {
  885. dbt.Fatal(err)
  886. }
  887. if !rows.Next() {
  888. dbt.Fatal("Getting row failed")
  889. } else {
  890. err = rows.Err()
  891. if err != nil {
  892. dbt.Fatal(err)
  893. }
  894. var out bool
  895. err = rows.Scan(&out)
  896. if err != nil {
  897. dbt.Fatalf("Error on rows.Scan(): %s", err.Error())
  898. }
  899. if out != true {
  900. dbt.Errorf("true != %t", out)
  901. }
  902. }
  903. })
  904. }
  905. // It is valid to have multiple Rows for the same Stmt
  906. // http://code.google.com/p/go/issues/detail?id=3734
  907. func TestStmtMultiRows(t *testing.T) {
  908. runTests(t, dsn, func(dbt *DBTest) {
  909. stmt, err := dbt.db.Prepare("SELECT 1 UNION SELECT 0")
  910. if err != nil {
  911. dbt.Fatal(err)
  912. }
  913. rows1, err := stmt.Query()
  914. if err != nil {
  915. stmt.Close()
  916. dbt.Fatal(err)
  917. }
  918. defer rows1.Close()
  919. rows2, err := stmt.Query()
  920. if err != nil {
  921. stmt.Close()
  922. dbt.Fatal(err)
  923. }
  924. defer rows2.Close()
  925. var out bool
  926. // 1
  927. if !rows1.Next() {
  928. dbt.Fatal("1st rows1.Next failed")
  929. } else {
  930. err = rows1.Err()
  931. if err != nil {
  932. dbt.Fatal(err)
  933. }
  934. err = rows1.Scan(&out)
  935. if err != nil {
  936. dbt.Fatalf("Error on rows.Scan(): %s", err.Error())
  937. }
  938. if out != true {
  939. dbt.Errorf("true != %t", out)
  940. }
  941. }
  942. if !rows2.Next() {
  943. dbt.Fatal("1st rows2.Next failed")
  944. } else {
  945. err = rows2.Err()
  946. if err != nil {
  947. dbt.Fatal(err)
  948. }
  949. err = rows2.Scan(&out)
  950. if err != nil {
  951. dbt.Fatalf("Error on rows.Scan(): %s", err.Error())
  952. }
  953. if out != true {
  954. dbt.Errorf("true != %t", out)
  955. }
  956. }
  957. // 2
  958. if !rows1.Next() {
  959. dbt.Fatal("2nd rows1.Next failed")
  960. } else {
  961. err = rows1.Err()
  962. if err != nil {
  963. dbt.Fatal(err)
  964. }
  965. err = rows1.Scan(&out)
  966. if err != nil {
  967. dbt.Fatalf("Error on rows.Scan(): %s", err.Error())
  968. }
  969. if out != false {
  970. dbt.Errorf("false != %t", out)
  971. }
  972. if rows1.Next() {
  973. dbt.Fatal("Unexpected row on rows1")
  974. }
  975. err = rows1.Close()
  976. if err != nil {
  977. dbt.Fatal(err)
  978. }
  979. }
  980. if !rows2.Next() {
  981. dbt.Fatal("2nd rows2.Next failed")
  982. } else {
  983. err = rows2.Err()
  984. if err != nil {
  985. dbt.Fatal(err)
  986. }
  987. err = rows2.Scan(&out)
  988. if err != nil {
  989. dbt.Fatalf("Error on rows.Scan(): %s", err.Error())
  990. }
  991. if out != false {
  992. dbt.Errorf("false != %t", out)
  993. }
  994. if rows2.Next() {
  995. dbt.Fatal("Unexpected row on rows2")
  996. }
  997. err = rows2.Close()
  998. if err != nil {
  999. dbt.Fatal(err)
  1000. }
  1001. }
  1002. })
  1003. }
  1004. func TestConcurrent(t *testing.T) {
  1005. if enabled, _ := readBool(os.Getenv("MYSQL_TEST_CONCURRENT")); !enabled {
  1006. t.Skip("MYSQL_TEST_CONCURRENT env var not set")
  1007. }
  1008. runTests(t, dsn, func(dbt *DBTest) {
  1009. var max int
  1010. err := dbt.db.QueryRow("SELECT @@max_connections").Scan(&max)
  1011. if err != nil {
  1012. dbt.Fatalf("%s", err.Error())
  1013. }
  1014. dbt.Logf("Testing up to %d concurrent connections \r\n", max)
  1015. canStop := false
  1016. c := make(chan struct{}, max)
  1017. for i := 0; i < max; i++ {
  1018. go func(id int) {
  1019. tx, err := dbt.db.Begin()
  1020. if err != nil {
  1021. canStop = true
  1022. if err.Error() == "Error 1040: Too many connections" {
  1023. max--
  1024. return
  1025. } else {
  1026. dbt.Fatalf("Error on Con %d: %s", id, err.Error())
  1027. }
  1028. }
  1029. c <- struct{}{}
  1030. for !canStop {
  1031. _, err = tx.Exec("SELECT 1")
  1032. if err != nil {
  1033. canStop = true
  1034. dbt.Fatalf("Error on Con %d: %s", id, err.Error())
  1035. }
  1036. }
  1037. err = tx.Commit()
  1038. if err != nil {
  1039. canStop = true
  1040. dbt.Fatalf("Error on Con %d: %s", id, err.Error())
  1041. }
  1042. }(i)
  1043. }
  1044. for i := 0; i < max; i++ {
  1045. <-c
  1046. }
  1047. canStop = true
  1048. dbt.Logf("Reached %d concurrent connections \r\n", max)
  1049. })
  1050. }