driver_test.go 29 KB

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