driver_go18_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
  2. //
  3. // Copyright 2017 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. // +build go1.8
  9. package mysql
  10. import (
  11. "context"
  12. "database/sql"
  13. "database/sql/driver"
  14. "fmt"
  15. "reflect"
  16. "testing"
  17. "time"
  18. )
  19. // static interface implementation checks of mysqlConn
  20. var (
  21. _ driver.ConnBeginTx = &mysqlConn{}
  22. _ driver.ConnPrepareContext = &mysqlConn{}
  23. _ driver.ExecerContext = &mysqlConn{}
  24. _ driver.Pinger = &mysqlConn{}
  25. _ driver.QueryerContext = &mysqlConn{}
  26. )
  27. // static interface implementation checks of mysqlStmt
  28. var (
  29. _ driver.StmtExecContext = &mysqlStmt{}
  30. _ driver.StmtQueryContext = &mysqlStmt{}
  31. )
  32. func TestMultiResultSet(t *testing.T) {
  33. type result struct {
  34. values [][]int
  35. columns []string
  36. }
  37. // checkRows is a helper test function to validate rows containing 3 result
  38. // sets with specific values and columns. The basic query would look like this:
  39. //
  40. // SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4;
  41. // SELECT 0 UNION SELECT 1;
  42. // SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6;
  43. //
  44. // to distinguish test cases the first string argument is put in front of
  45. // every error or fatal message.
  46. checkRows := func(desc string, rows *sql.Rows, dbt *DBTest) {
  47. expected := []result{
  48. {
  49. values: [][]int{{1, 2}, {3, 4}},
  50. columns: []string{"col1", "col2"},
  51. },
  52. {
  53. values: [][]int{{1, 2, 3}, {4, 5, 6}},
  54. columns: []string{"col1", "col2", "col3"},
  55. },
  56. }
  57. var res1 result
  58. for rows.Next() {
  59. var res [2]int
  60. if err := rows.Scan(&res[0], &res[1]); err != nil {
  61. dbt.Fatal(err)
  62. }
  63. res1.values = append(res1.values, res[:])
  64. }
  65. cols, err := rows.Columns()
  66. if err != nil {
  67. dbt.Fatal(desc, err)
  68. }
  69. res1.columns = cols
  70. if !reflect.DeepEqual(expected[0], res1) {
  71. dbt.Error(desc, "want =", expected[0], "got =", res1)
  72. }
  73. if !rows.NextResultSet() {
  74. dbt.Fatal(desc, "expected next result set")
  75. }
  76. // ignoring one result set
  77. if !rows.NextResultSet() {
  78. dbt.Fatal(desc, "expected next result set")
  79. }
  80. var res2 result
  81. cols, err = rows.Columns()
  82. if err != nil {
  83. dbt.Fatal(desc, err)
  84. }
  85. res2.columns = cols
  86. for rows.Next() {
  87. var res [3]int
  88. if err := rows.Scan(&res[0], &res[1], &res[2]); err != nil {
  89. dbt.Fatal(desc, err)
  90. }
  91. res2.values = append(res2.values, res[:])
  92. }
  93. if !reflect.DeepEqual(expected[1], res2) {
  94. dbt.Error(desc, "want =", expected[1], "got =", res2)
  95. }
  96. if rows.NextResultSet() {
  97. dbt.Error(desc, "unexpected next result set")
  98. }
  99. if err := rows.Err(); err != nil {
  100. dbt.Error(desc, err)
  101. }
  102. }
  103. runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) {
  104. rows := dbt.mustQuery(`DO 1;
  105. SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4;
  106. DO 1;
  107. SELECT 0 UNION SELECT 1;
  108. SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6;`)
  109. defer rows.Close()
  110. checkRows("query: ", rows, dbt)
  111. })
  112. runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) {
  113. queries := []string{
  114. `
  115. DROP PROCEDURE IF EXISTS test_mrss;
  116. CREATE PROCEDURE test_mrss()
  117. BEGIN
  118. DO 1;
  119. SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4;
  120. DO 1;
  121. SELECT 0 UNION SELECT 1;
  122. SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6;
  123. END
  124. `,
  125. `
  126. DROP PROCEDURE IF EXISTS test_mrss;
  127. CREATE PROCEDURE test_mrss()
  128. BEGIN
  129. SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4;
  130. SELECT 0 UNION SELECT 1;
  131. SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6;
  132. END
  133. `,
  134. }
  135. defer dbt.mustExec("DROP PROCEDURE IF EXISTS test_mrss")
  136. for i, query := range queries {
  137. dbt.mustExec(query)
  138. stmt, err := dbt.db.Prepare("CALL test_mrss()")
  139. if err != nil {
  140. dbt.Fatalf("%v (i=%d)", err, i)
  141. }
  142. defer stmt.Close()
  143. for j := 0; j < 2; j++ {
  144. rows, err := stmt.Query()
  145. if err != nil {
  146. dbt.Fatalf("%v (i=%d) (j=%d)", err, i, j)
  147. }
  148. checkRows(fmt.Sprintf("prepared stmt query (i=%d) (j=%d): ", i, j), rows, dbt)
  149. }
  150. }
  151. })
  152. }
  153. func TestMultiResultSetNoSelect(t *testing.T) {
  154. runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) {
  155. rows := dbt.mustQuery("DO 1; DO 2;")
  156. defer rows.Close()
  157. if rows.Next() {
  158. dbt.Error("unexpected row")
  159. }
  160. if rows.NextResultSet() {
  161. dbt.Error("unexpected next result set")
  162. }
  163. if err := rows.Err(); err != nil {
  164. dbt.Error("expected nil; got ", err)
  165. }
  166. })
  167. }
  168. // tests if rows are set in a proper state if some results were ignored before
  169. // calling rows.NextResultSet.
  170. func TestSkipResults(t *testing.T) {
  171. runTests(t, dsn, func(dbt *DBTest) {
  172. rows := dbt.mustQuery("SELECT 1, 2")
  173. defer rows.Close()
  174. if !rows.Next() {
  175. dbt.Error("expected row")
  176. }
  177. if rows.NextResultSet() {
  178. dbt.Error("unexpected next result set")
  179. }
  180. if err := rows.Err(); err != nil {
  181. dbt.Error("expected nil; got ", err)
  182. }
  183. })
  184. }
  185. func TestPingContext(t *testing.T) {
  186. runTests(t, dsn, func(dbt *DBTest) {
  187. ctx, cancel := context.WithCancel(context.Background())
  188. cancel()
  189. if err := dbt.db.PingContext(ctx); err != context.Canceled {
  190. dbt.Errorf("expected context.Canceled, got %v", err)
  191. }
  192. })
  193. }
  194. func TestContextCancelExec(t *testing.T) {
  195. runTests(t, dsn, func(dbt *DBTest) {
  196. dbt.mustExec("CREATE TABLE test (v INTEGER)")
  197. ctx, cancel := context.WithCancel(context.Background())
  198. // Delay execution for just a bit until db.ExecContext has begun.
  199. defer time.AfterFunc(100*time.Millisecond, cancel).Stop()
  200. // This query will be canceled.
  201. startTime := time.Now()
  202. if _, err := dbt.db.ExecContext(ctx, "INSERT INTO test VALUES (SLEEP(1))"); err != context.Canceled {
  203. dbt.Errorf("expected context.Canceled, got %v", err)
  204. }
  205. if d := time.Since(startTime); d > 500*time.Millisecond {
  206. dbt.Errorf("too long execution time: %s", d)
  207. }
  208. // Wait for the INSERT query has done.
  209. time.Sleep(time.Second)
  210. // Check how many times the query is executed.
  211. var v int
  212. if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil {
  213. dbt.Fatalf("%s", err.Error())
  214. }
  215. if v != 1 { // TODO: need to kill the query, and v should be 0.
  216. dbt.Errorf("expected val to be 1, got %d", v)
  217. }
  218. // Context is already canceled, so error should come before execution.
  219. if _, err := dbt.db.ExecContext(ctx, "INSERT INTO test VALUES (1)"); err == nil {
  220. dbt.Error("expected error")
  221. } else if err.Error() != "context canceled" {
  222. dbt.Fatalf("unexpected error: %s", err)
  223. }
  224. // The second insert query will fail, so the table has no changes.
  225. if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil {
  226. dbt.Fatalf("%s", err.Error())
  227. }
  228. if v != 1 {
  229. dbt.Errorf("expected val to be 1, got %d", v)
  230. }
  231. })
  232. }
  233. func TestContextCancelQuery(t *testing.T) {
  234. runTests(t, dsn, func(dbt *DBTest) {
  235. dbt.mustExec("CREATE TABLE test (v INTEGER)")
  236. ctx, cancel := context.WithCancel(context.Background())
  237. // Delay execution for just a bit until db.ExecContext has begun.
  238. defer time.AfterFunc(100*time.Millisecond, cancel).Stop()
  239. // This query will be canceled.
  240. startTime := time.Now()
  241. if _, err := dbt.db.QueryContext(ctx, "INSERT INTO test VALUES (SLEEP(1))"); err != context.Canceled {
  242. dbt.Errorf("expected context.Canceled, got %v", err)
  243. }
  244. if d := time.Since(startTime); d > 500*time.Millisecond {
  245. dbt.Errorf("too long execution time: %s", d)
  246. }
  247. // Wait for the INSERT query has done.
  248. time.Sleep(time.Second)
  249. // Check how many times the query is executed.
  250. var v int
  251. if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil {
  252. dbt.Fatalf("%s", err.Error())
  253. }
  254. if v != 1 { // TODO: need to kill the query, and v should be 0.
  255. dbt.Errorf("expected val to be 1, got %d", v)
  256. }
  257. // Context is already canceled, so error should come before execution.
  258. if _, err := dbt.db.QueryContext(ctx, "INSERT INTO test VALUES (1)"); err != context.Canceled {
  259. dbt.Errorf("expected context.Canceled, got %v", err)
  260. }
  261. // The second insert query will fail, so the table has no changes.
  262. if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil {
  263. dbt.Fatalf("%s", err.Error())
  264. }
  265. if v != 1 {
  266. dbt.Errorf("expected val to be 1, got %d", v)
  267. }
  268. })
  269. }
  270. func TestContextCancelQueryRow(t *testing.T) {
  271. runTests(t, dsn, func(dbt *DBTest) {
  272. dbt.mustExec("CREATE TABLE test (v INTEGER)")
  273. dbt.mustExec("INSERT INTO test VALUES (1), (2), (3)")
  274. ctx, cancel := context.WithCancel(context.Background())
  275. rows, err := dbt.db.QueryContext(ctx, "SELECT v FROM test")
  276. if err != nil {
  277. dbt.Fatalf("%s", err.Error())
  278. }
  279. // the first row will be succeed.
  280. var v int
  281. if !rows.Next() {
  282. dbt.Fatalf("unexpected end")
  283. }
  284. if err := rows.Scan(&v); err != nil {
  285. dbt.Fatalf("%s", err.Error())
  286. }
  287. cancel()
  288. // make sure the driver recieve cancel request.
  289. time.Sleep(100 * time.Millisecond)
  290. if rows.Next() {
  291. dbt.Errorf("expected end, but not")
  292. }
  293. if err := rows.Err(); err != context.Canceled {
  294. dbt.Errorf("expected context.Canceled, got %v", err)
  295. }
  296. })
  297. }
  298. func TestContextCancelPrepare(t *testing.T) {
  299. runTests(t, dsn, func(dbt *DBTest) {
  300. ctx, cancel := context.WithCancel(context.Background())
  301. cancel()
  302. if _, err := dbt.db.PrepareContext(ctx, "SELECT 1"); err != context.Canceled {
  303. dbt.Errorf("expected context.Canceled, got %v", err)
  304. }
  305. })
  306. }
  307. func TestContextCancelStmtExec(t *testing.T) {
  308. runTests(t, dsn, func(dbt *DBTest) {
  309. dbt.mustExec("CREATE TABLE test (v INTEGER)")
  310. ctx, cancel := context.WithCancel(context.Background())
  311. stmt, err := dbt.db.PrepareContext(ctx, "INSERT INTO test VALUES (SLEEP(1))")
  312. if err != nil {
  313. dbt.Fatalf("unexpected error: %v", err)
  314. }
  315. // Delay execution for just a bit until db.ExecContext has begun.
  316. defer time.AfterFunc(100*time.Millisecond, cancel).Stop()
  317. // This query will be canceled.
  318. startTime := time.Now()
  319. if _, err := stmt.ExecContext(ctx); err != context.Canceled {
  320. dbt.Errorf("expected context.Canceled, got %v", err)
  321. }
  322. if d := time.Since(startTime); d > 500*time.Millisecond {
  323. dbt.Errorf("too long execution time: %s", d)
  324. }
  325. // Wait for the INSERT query has done.
  326. time.Sleep(time.Second)
  327. // Check how many times the query is executed.
  328. var v int
  329. if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil {
  330. dbt.Fatalf("%s", err.Error())
  331. }
  332. if v != 1 { // TODO: need to kill the query, and v should be 0.
  333. dbt.Errorf("expected val to be 1, got %d", v)
  334. }
  335. })
  336. }
  337. func TestContextCancelStmtQuery(t *testing.T) {
  338. runTests(t, dsn, func(dbt *DBTest) {
  339. dbt.mustExec("CREATE TABLE test (v INTEGER)")
  340. ctx, cancel := context.WithCancel(context.Background())
  341. stmt, err := dbt.db.PrepareContext(ctx, "INSERT INTO test VALUES (SLEEP(1))")
  342. if err != nil {
  343. dbt.Fatalf("unexpected error: %v", err)
  344. }
  345. // Delay execution for just a bit until db.ExecContext has begun.
  346. defer time.AfterFunc(100*time.Millisecond, cancel).Stop()
  347. // This query will be canceled.
  348. startTime := time.Now()
  349. if _, err := stmt.QueryContext(ctx); err != context.Canceled {
  350. dbt.Errorf("expected context.Canceled, got %v", err)
  351. }
  352. if d := time.Since(startTime); d > 500*time.Millisecond {
  353. dbt.Errorf("too long execution time: %s", d)
  354. }
  355. // Wait for the INSERT query has done.
  356. time.Sleep(time.Second)
  357. // Check how many times the query is executed.
  358. var v int
  359. if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil {
  360. dbt.Fatalf("%s", err.Error())
  361. }
  362. if v != 1 { // TODO: need to kill the query, and v should be 0.
  363. dbt.Errorf("expected val to be 1, got %d", v)
  364. }
  365. })
  366. }
  367. func TestContextCancelBegin(t *testing.T) {
  368. runTests(t, dsn, func(dbt *DBTest) {
  369. dbt.mustExec("CREATE TABLE test (v INTEGER)")
  370. ctx, cancel := context.WithCancel(context.Background())
  371. tx, err := dbt.db.BeginTx(ctx, nil)
  372. if err != nil {
  373. dbt.Fatal(err)
  374. }
  375. // Delay execution for just a bit until db.ExecContext has begun.
  376. defer time.AfterFunc(100*time.Millisecond, cancel).Stop()
  377. // This query will be canceled.
  378. startTime := time.Now()
  379. if _, err := tx.ExecContext(ctx, "INSERT INTO test VALUES (SLEEP(1))"); err != context.Canceled {
  380. dbt.Errorf("expected context.Canceled, got %v", err)
  381. }
  382. if d := time.Since(startTime); d > 500*time.Millisecond {
  383. dbt.Errorf("too long execution time: %s", d)
  384. }
  385. // Transaction is canceled, so expect an error.
  386. switch err := tx.Commit(); err {
  387. case sql.ErrTxDone:
  388. // because the transaction has already been rollbacked.
  389. // the database/sql package watches ctx
  390. // and rollbacks when ctx is canceled.
  391. case context.Canceled:
  392. // the database/sql package rollbacks on another goroutine,
  393. // so the transaction may not be rollbacked depending on goroutine scheduling.
  394. default:
  395. dbt.Errorf("expected sql.ErrTxDone or context.Canceled, got %v", err)
  396. }
  397. // Context is canceled, so cannot begin a transaction.
  398. if _, err := dbt.db.BeginTx(ctx, nil); err != context.Canceled {
  399. dbt.Errorf("expected context.Canceled, got %v", err)
  400. }
  401. })
  402. }
  403. func TestContextBeginIsolationLevel(t *testing.T) {
  404. runTests(t, dsn, func(dbt *DBTest) {
  405. dbt.mustExec("CREATE TABLE test (v INTEGER)")
  406. ctx, cancel := context.WithCancel(context.Background())
  407. defer cancel()
  408. tx1, err := dbt.db.BeginTx(ctx, &sql.TxOptions{
  409. Isolation: sql.LevelRepeatableRead,
  410. })
  411. if err != nil {
  412. dbt.Fatal(err)
  413. }
  414. tx2, err := dbt.db.BeginTx(ctx, &sql.TxOptions{
  415. Isolation: sql.LevelReadCommitted,
  416. })
  417. if err != nil {
  418. dbt.Fatal(err)
  419. }
  420. _, err = tx1.ExecContext(ctx, "INSERT INTO test VALUES (1)")
  421. if err != nil {
  422. dbt.Fatal(err)
  423. }
  424. var v int
  425. row := tx2.QueryRowContext(ctx, "SELECT COUNT(*) FROM test")
  426. if err := row.Scan(&v); err != nil {
  427. dbt.Fatal(err)
  428. }
  429. // Because writer transaction wasn't commited yet, it should be available
  430. if v != 0 {
  431. dbt.Errorf("expected val to be 0, got %d", v)
  432. }
  433. err = tx1.Commit()
  434. if err != nil {
  435. dbt.Fatal(err)
  436. }
  437. row = tx2.QueryRowContext(ctx, "SELECT COUNT(*) FROM test")
  438. if err := row.Scan(&v); err != nil {
  439. dbt.Fatal(err)
  440. }
  441. // Data written by writer transaction is already commited, it should be selectable
  442. if v != 1 {
  443. dbt.Errorf("expected val to be 1, got %d", v)
  444. }
  445. tx2.Commit()
  446. })
  447. }
  448. func TestContextBeginReadOnly(t *testing.T) {
  449. runTests(t, dsn, func(dbt *DBTest) {
  450. dbt.mustExec("CREATE TABLE test (v INTEGER)")
  451. ctx, cancel := context.WithCancel(context.Background())
  452. defer cancel()
  453. tx, err := dbt.db.BeginTx(ctx, &sql.TxOptions{
  454. ReadOnly: true,
  455. })
  456. if _, ok := err.(*MySQLError); ok {
  457. dbt.Skip("It seems that your MySQL does not support READ ONLY transactions")
  458. return
  459. } else if err != nil {
  460. dbt.Fatal(err)
  461. }
  462. // INSERT queries fail in a READ ONLY transaction.
  463. _, err = tx.ExecContext(ctx, "INSERT INTO test VALUES (1)")
  464. if _, ok := err.(*MySQLError); !ok {
  465. dbt.Errorf("expected MySQLError, got %v", err)
  466. }
  467. // SELECT queries can be executed.
  468. var v int
  469. row := tx.QueryRowContext(ctx, "SELECT COUNT(*) FROM test")
  470. if err := row.Scan(&v); err != nil {
  471. dbt.Fatal(err)
  472. }
  473. if v != 0 {
  474. dbt.Errorf("expected val to be 0, got %d", v)
  475. }
  476. if err := tx.Commit(); err != nil {
  477. dbt.Fatal(err)
  478. }
  479. })
  480. }