driver_go18_test.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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. "database/sql"
  12. "fmt"
  13. "reflect"
  14. "testing"
  15. )
  16. func TestMultiResultSet(t *testing.T) {
  17. type result struct {
  18. values [][]int
  19. columns []string
  20. }
  21. // checkRows is a helper test function to validate rows containing 3 result
  22. // sets with specific values and columns. The basic query would look like this:
  23. //
  24. // SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4;
  25. // SELECT 0 UNION SELECT 1;
  26. // SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6;
  27. //
  28. // to distinguish test cases the first string argument is put in front of
  29. // every error or fatal message.
  30. checkRows := func(desc string, rows *sql.Rows, dbt *DBTest) {
  31. expected := []result{
  32. {
  33. values: [][]int{{1, 2}, {3, 4}},
  34. columns: []string{"col1", "col2"},
  35. },
  36. {
  37. values: [][]int{{1, 2, 3}, {4, 5, 6}},
  38. columns: []string{"col1", "col2", "col3"},
  39. },
  40. }
  41. var res1 result
  42. for rows.Next() {
  43. var res [2]int
  44. if err := rows.Scan(&res[0], &res[1]); err != nil {
  45. dbt.Fatal(err)
  46. }
  47. res1.values = append(res1.values, res[:])
  48. }
  49. cols, err := rows.Columns()
  50. if err != nil {
  51. dbt.Fatal(desc, err)
  52. }
  53. res1.columns = cols
  54. if !reflect.DeepEqual(expected[0], res1) {
  55. dbt.Error(desc, "want =", expected[0], "got =", res1)
  56. }
  57. if !rows.NextResultSet() {
  58. dbt.Fatal(desc, "expected next result set")
  59. }
  60. // ignoring one result set
  61. if !rows.NextResultSet() {
  62. dbt.Fatal(desc, "expected next result set")
  63. }
  64. var res2 result
  65. cols, err = rows.Columns()
  66. if err != nil {
  67. dbt.Fatal(desc, err)
  68. }
  69. res2.columns = cols
  70. for rows.Next() {
  71. var res [3]int
  72. if err := rows.Scan(&res[0], &res[1], &res[2]); err != nil {
  73. dbt.Fatal(desc, err)
  74. }
  75. res2.values = append(res2.values, res[:])
  76. }
  77. if !reflect.DeepEqual(expected[1], res2) {
  78. dbt.Error(desc, "want =", expected[1], "got =", res2)
  79. }
  80. if rows.NextResultSet() {
  81. dbt.Error(desc, "unexpected next result set")
  82. }
  83. if err := rows.Err(); err != nil {
  84. dbt.Error(desc, err)
  85. }
  86. }
  87. runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) {
  88. rows := dbt.mustQuery(`DO 1;
  89. SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4;
  90. DO 1;
  91. SELECT 0 UNION SELECT 1;
  92. SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6;`)
  93. defer rows.Close()
  94. checkRows("query: ", rows, dbt)
  95. })
  96. runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) {
  97. queries := []string{
  98. `
  99. DROP PROCEDURE IF EXISTS test_mrss;
  100. CREATE PROCEDURE test_mrss()
  101. BEGIN
  102. DO 1;
  103. SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4;
  104. DO 1;
  105. SELECT 0 UNION SELECT 1;
  106. SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6;
  107. END
  108. `,
  109. `
  110. DROP PROCEDURE IF EXISTS test_mrss;
  111. CREATE PROCEDURE test_mrss()
  112. BEGIN
  113. SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4;
  114. SELECT 0 UNION SELECT 1;
  115. SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6;
  116. END
  117. `,
  118. }
  119. defer dbt.mustExec("DROP PROCEDURE IF EXISTS test_mrss")
  120. for i, query := range queries {
  121. dbt.mustExec(query)
  122. stmt, err := dbt.db.Prepare("CALL test_mrss()")
  123. if err != nil {
  124. dbt.Fatalf("%v (i=%d)", err, i)
  125. }
  126. defer stmt.Close()
  127. for j := 0; j < 2; j++ {
  128. rows, err := stmt.Query()
  129. if err != nil {
  130. dbt.Fatalf("%v (i=%d) (j=%d)", err, i, j)
  131. }
  132. checkRows(fmt.Sprintf("prepared stmt query (i=%d) (j=%d): ", i, j), rows, dbt)
  133. }
  134. }
  135. })
  136. }
  137. func TestMultiResultSetNoSelect(t *testing.T) {
  138. runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) {
  139. rows := dbt.mustQuery("DO 1; DO 2;")
  140. defer rows.Close()
  141. if rows.Next() {
  142. dbt.Error("unexpected row")
  143. }
  144. if rows.NextResultSet() {
  145. dbt.Error("unexpected next result set")
  146. }
  147. if err := rows.Err(); err != nil {
  148. dbt.Error("expected nil; got ", err)
  149. }
  150. })
  151. }
  152. // tests if rows are set in a proper state if some results were ignored before
  153. // calling rows.NextResultSet.
  154. func TestSkipResults(t *testing.T) {
  155. runTests(t, dsn, func(dbt *DBTest) {
  156. rows := dbt.mustQuery("SELECT 1, 2")
  157. defer rows.Close()
  158. if !rows.Next() {
  159. dbt.Error("expected row")
  160. }
  161. if rows.NextResultSet() {
  162. dbt.Error("unexpected next result set")
  163. }
  164. if err := rows.Err(); err != nil {
  165. dbt.Error("expected nil; got ", err)
  166. }
  167. })
  168. }