github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/go-sql-driver/mysql/driver_test.go (about)

     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  
     9  package mysql
    10  
    11  import (
    12  	"bytes"
    13  	"crypto/tls"
    14  	"database/sql"
    15  	"database/sql/driver"
    16  	"fmt"
    17  	"io"
    18  	"io/ioutil"
    19  	"log"
    20  	"net"
    21  	"net/url"
    22  	"os"
    23  	"strings"
    24  	"sync"
    25  	"sync/atomic"
    26  	"testing"
    27  	"time"
    28  )
    29  
    30  var (
    31  	user      string
    32  	pass      string
    33  	prot      string
    34  	addr      string
    35  	dbname    string
    36  	dsn       string
    37  	netAddr   string
    38  	available bool
    39  )
    40  
    41  var (
    42  	tDate      = time.Date(2012, 6, 14, 0, 0, 0, 0, time.UTC)
    43  	sDate      = "2012-06-14"
    44  	tDateTime  = time.Date(2011, 11, 20, 21, 27, 37, 0, time.UTC)
    45  	sDateTime  = "2011-11-20 21:27:37"
    46  	tDate0     = time.Time{}
    47  	sDate0     = "0000-00-00"
    48  	sDateTime0 = "0000-00-00 00:00:00"
    49  )
    50  
    51  // See https://yougam/libraries/go-sql-driver/mysql/wiki/Testing
    52  func init() {
    53  	// get environment variables
    54  	env := func(key, defaultValue string) string {
    55  		if value := os.Getenv(key); value != "" {
    56  			return value
    57  		}
    58  		return defaultValue
    59  	}
    60  	user = env("MYSQL_TEST_USER", "root")
    61  	pass = env("MYSQL_TEST_PASS", "")
    62  	prot = env("MYSQL_TEST_PROT", "tcp")
    63  	addr = env("MYSQL_TEST_ADDR", "localhost:3306")
    64  	dbname = env("MYSQL_TEST_DBNAME", "gotest")
    65  	netAddr = fmt.Sprintf("%s(%s)", prot, addr)
    66  	dsn = fmt.Sprintf("%s:%s@%s/%s?timeout=30s&strict=true", user, pass, netAddr, dbname)
    67  	c, err := net.Dial(prot, addr)
    68  	if err == nil {
    69  		available = true
    70  		c.Close()
    71  	}
    72  }
    73  
    74  type DBTest struct {
    75  	*testing.T
    76  	db *sql.DB
    77  }
    78  
    79  func runTestsWithMultiStatement(t *testing.T, dsn string, tests ...func(dbt *DBTest)) {
    80  	if !available {
    81  		t.Skipf("MySQL server not running on %s", netAddr)
    82  	}
    83  
    84  	dsn += "&multiStatements=true"
    85  	var db *sql.DB
    86  	if _, err := ParseDSN(dsn); err != errInvalidDSNUnsafeCollation {
    87  		db, err = sql.Open("mysql", dsn)
    88  		if err != nil {
    89  			t.Fatalf("error connecting: %s", err.Error())
    90  		}
    91  		defer db.Close()
    92  	}
    93  
    94  	dbt := &DBTest{t, db}
    95  	for _, test := range tests {
    96  		test(dbt)
    97  		dbt.db.Exec("DROP TABLE IF EXISTS test")
    98  	}
    99  }
   100  
   101  func runTests(t *testing.T, dsn string, tests ...func(dbt *DBTest)) {
   102  	if !available {
   103  		t.Skipf("MySQL server not running on %s", netAddr)
   104  	}
   105  
   106  	db, err := sql.Open("mysql", dsn)
   107  	if err != nil {
   108  		t.Fatalf("error connecting: %s", err.Error())
   109  	}
   110  	defer db.Close()
   111  
   112  	db.Exec("DROP TABLE IF EXISTS test")
   113  
   114  	dsn2 := dsn + "&interpolateParams=true"
   115  	var db2 *sql.DB
   116  	if _, err := ParseDSN(dsn2); err != errInvalidDSNUnsafeCollation {
   117  		db2, err = sql.Open("mysql", dsn2)
   118  		if err != nil {
   119  			t.Fatalf("error connecting: %s", err.Error())
   120  		}
   121  		defer db2.Close()
   122  	}
   123  
   124  	dsn3 := dsn + "&multiStatements=true"
   125  	var db3 *sql.DB
   126  	if _, err := ParseDSN(dsn3); err != errInvalidDSNUnsafeCollation {
   127  		db3, err = sql.Open("mysql", dsn3)
   128  		if err != nil {
   129  			t.Fatalf("error connecting: %s", err.Error())
   130  		}
   131  		defer db3.Close()
   132  	}
   133  
   134  	dbt := &DBTest{t, db}
   135  	dbt2 := &DBTest{t, db2}
   136  	dbt3 := &DBTest{t, db3}
   137  	for _, test := range tests {
   138  		test(dbt)
   139  		dbt.db.Exec("DROP TABLE IF EXISTS test")
   140  		if db2 != nil {
   141  			test(dbt2)
   142  			dbt2.db.Exec("DROP TABLE IF EXISTS test")
   143  		}
   144  		if db3 != nil {
   145  			test(dbt3)
   146  			dbt3.db.Exec("DROP TABLE IF EXISTS test")
   147  		}
   148  	}
   149  }
   150  
   151  func (dbt *DBTest) fail(method, query string, err error) {
   152  	if len(query) > 300 {
   153  		query = "[query too large to print]"
   154  	}
   155  	dbt.Fatalf("error on %s %s: %s", method, query, err.Error())
   156  }
   157  
   158  func (dbt *DBTest) mustExec(query string, args ...interface{}) (res sql.Result) {
   159  	res, err := dbt.db.Exec(query, args...)
   160  	if err != nil {
   161  		dbt.fail("exec", query, err)
   162  	}
   163  	return res
   164  }
   165  
   166  func (dbt *DBTest) mustQuery(query string, args ...interface{}) (rows *sql.Rows) {
   167  	rows, err := dbt.db.Query(query, args...)
   168  	if err != nil {
   169  		dbt.fail("query", query, err)
   170  	}
   171  	return rows
   172  }
   173  
   174  func TestEmptyQuery(t *testing.T) {
   175  	runTests(t, dsn, func(dbt *DBTest) {
   176  		// just a comment, no query
   177  		rows := dbt.mustQuery("--")
   178  		// will hang before #255
   179  		if rows.Next() {
   180  			dbt.Errorf("next on rows must be false")
   181  		}
   182  	})
   183  }
   184  
   185  func TestCRUD(t *testing.T) {
   186  	runTests(t, dsn, func(dbt *DBTest) {
   187  		// Create Table
   188  		dbt.mustExec("CREATE TABLE test (value BOOL)")
   189  
   190  		// Test for unexpected data
   191  		var out bool
   192  		rows := dbt.mustQuery("SELECT * FROM test")
   193  		if rows.Next() {
   194  			dbt.Error("unexpected data in empty table")
   195  		}
   196  
   197  		// Create Data
   198  		res := dbt.mustExec("INSERT INTO test VALUES (1)")
   199  		count, err := res.RowsAffected()
   200  		if err != nil {
   201  			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
   202  		}
   203  		if count != 1 {
   204  			dbt.Fatalf("expected 1 affected row, got %d", count)
   205  		}
   206  
   207  		id, err := res.LastInsertId()
   208  		if err != nil {
   209  			dbt.Fatalf("res.LastInsertId() returned error: %s", err.Error())
   210  		}
   211  		if id != 0 {
   212  			dbt.Fatalf("expected InsertId 0, got %d", id)
   213  		}
   214  
   215  		// Read
   216  		rows = dbt.mustQuery("SELECT value FROM test")
   217  		if rows.Next() {
   218  			rows.Scan(&out)
   219  			if true != out {
   220  				dbt.Errorf("true != %t", out)
   221  			}
   222  
   223  			if rows.Next() {
   224  				dbt.Error("unexpected data")
   225  			}
   226  		} else {
   227  			dbt.Error("no data")
   228  		}
   229  
   230  		// Update
   231  		res = dbt.mustExec("UPDATE test SET value = ? WHERE value = ?", false, true)
   232  		count, err = res.RowsAffected()
   233  		if err != nil {
   234  			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
   235  		}
   236  		if count != 1 {
   237  			dbt.Fatalf("expected 1 affected row, got %d", count)
   238  		}
   239  
   240  		// Check Update
   241  		rows = dbt.mustQuery("SELECT value FROM test")
   242  		if rows.Next() {
   243  			rows.Scan(&out)
   244  			if false != out {
   245  				dbt.Errorf("false != %t", out)
   246  			}
   247  
   248  			if rows.Next() {
   249  				dbt.Error("unexpected data")
   250  			}
   251  		} else {
   252  			dbt.Error("no data")
   253  		}
   254  
   255  		// Delete
   256  		res = dbt.mustExec("DELETE FROM test WHERE value = ?", false)
   257  		count, err = res.RowsAffected()
   258  		if err != nil {
   259  			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
   260  		}
   261  		if count != 1 {
   262  			dbt.Fatalf("expected 1 affected row, got %d", count)
   263  		}
   264  
   265  		// Check for unexpected rows
   266  		res = dbt.mustExec("DELETE FROM test")
   267  		count, err = res.RowsAffected()
   268  		if err != nil {
   269  			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
   270  		}
   271  		if count != 0 {
   272  			dbt.Fatalf("expected 0 affected row, got %d", count)
   273  		}
   274  	})
   275  }
   276  
   277  func TestMultiQuery(t *testing.T) {
   278  	runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) {
   279  		// Create Table
   280  		dbt.mustExec("CREATE TABLE `test` (`id` int(11) NOT NULL, `value` int(11) NOT NULL) ")
   281  
   282  		// Create Data
   283  		res := dbt.mustExec("INSERT INTO test VALUES (1, 1)")
   284  		count, err := res.RowsAffected()
   285  		if err != nil {
   286  			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
   287  		}
   288  		if count != 1 {
   289  			dbt.Fatalf("expected 1 affected row, got %d", count)
   290  		}
   291  
   292  		// Update
   293  		res = dbt.mustExec("UPDATE test SET value = 3 WHERE id = 1; UPDATE test SET value = 4 WHERE id = 1; UPDATE test SET value = 5 WHERE id = 1;")
   294  		count, err = res.RowsAffected()
   295  		if err != nil {
   296  			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
   297  		}
   298  		if count != 1 {
   299  			dbt.Fatalf("expected 1 affected row, got %d", count)
   300  		}
   301  
   302  		// Read
   303  		var out int
   304  		rows := dbt.mustQuery("SELECT value FROM test WHERE id=1;")
   305  		if rows.Next() {
   306  			rows.Scan(&out)
   307  			if 5 != out {
   308  				dbt.Errorf("5 != %d", out)
   309  			}
   310  
   311  			if rows.Next() {
   312  				dbt.Error("unexpected data")
   313  			}
   314  		} else {
   315  			dbt.Error("no data")
   316  		}
   317  
   318  	})
   319  }
   320  
   321  func TestInt(t *testing.T) {
   322  	runTests(t, dsn, func(dbt *DBTest) {
   323  		types := [5]string{"TINYINT", "SMALLINT", "MEDIUMINT", "INT", "BIGINT"}
   324  		in := int64(42)
   325  		var out int64
   326  		var rows *sql.Rows
   327  
   328  		// SIGNED
   329  		for _, v := range types {
   330  			dbt.mustExec("CREATE TABLE test (value " + v + ")")
   331  
   332  			dbt.mustExec("INSERT INTO test VALUES (?)", in)
   333  
   334  			rows = dbt.mustQuery("SELECT value FROM test")
   335  			if rows.Next() {
   336  				rows.Scan(&out)
   337  				if in != out {
   338  					dbt.Errorf("%s: %d != %d", v, in, out)
   339  				}
   340  			} else {
   341  				dbt.Errorf("%s: no data", v)
   342  			}
   343  
   344  			dbt.mustExec("DROP TABLE IF EXISTS test")
   345  		}
   346  
   347  		// UNSIGNED ZEROFILL
   348  		for _, v := range types {
   349  			dbt.mustExec("CREATE TABLE test (value " + v + " ZEROFILL)")
   350  
   351  			dbt.mustExec("INSERT INTO test VALUES (?)", in)
   352  
   353  			rows = dbt.mustQuery("SELECT value FROM test")
   354  			if rows.Next() {
   355  				rows.Scan(&out)
   356  				if in != out {
   357  					dbt.Errorf("%s ZEROFILL: %d != %d", v, in, out)
   358  				}
   359  			} else {
   360  				dbt.Errorf("%s ZEROFILL: no data", v)
   361  			}
   362  
   363  			dbt.mustExec("DROP TABLE IF EXISTS test")
   364  		}
   365  	})
   366  }
   367  
   368  func TestFloat(t *testing.T) {
   369  	runTests(t, dsn, func(dbt *DBTest) {
   370  		types := [2]string{"FLOAT", "DOUBLE"}
   371  		in := float32(42.23)
   372  		var out float32
   373  		var rows *sql.Rows
   374  		for _, v := range types {
   375  			dbt.mustExec("CREATE TABLE test (value " + v + ")")
   376  			dbt.mustExec("INSERT INTO test VALUES (?)", in)
   377  			rows = dbt.mustQuery("SELECT value FROM test")
   378  			if rows.Next() {
   379  				rows.Scan(&out)
   380  				if in != out {
   381  					dbt.Errorf("%s: %g != %g", v, in, out)
   382  				}
   383  			} else {
   384  				dbt.Errorf("%s: no data", v)
   385  			}
   386  			dbt.mustExec("DROP TABLE IF EXISTS test")
   387  		}
   388  	})
   389  }
   390  
   391  func TestString(t *testing.T) {
   392  	runTests(t, dsn, func(dbt *DBTest) {
   393  		types := [6]string{"CHAR(255)", "VARCHAR(255)", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT"}
   394  		in := "κόσμε üöäßñóùéàâÿœ'îë Árvíztűrő いろはにほへとちりぬるを イロハニホヘト דג סקרן чащах  น่าฟังเอย"
   395  		var out string
   396  		var rows *sql.Rows
   397  
   398  		for _, v := range types {
   399  			dbt.mustExec("CREATE TABLE test (value " + v + ") CHARACTER SET utf8")
   400  
   401  			dbt.mustExec("INSERT INTO test VALUES (?)", in)
   402  
   403  			rows = dbt.mustQuery("SELECT value FROM test")
   404  			if rows.Next() {
   405  				rows.Scan(&out)
   406  				if in != out {
   407  					dbt.Errorf("%s: %s != %s", v, in, out)
   408  				}
   409  			} else {
   410  				dbt.Errorf("%s: no data", v)
   411  			}
   412  
   413  			dbt.mustExec("DROP TABLE IF EXISTS test")
   414  		}
   415  
   416  		// BLOB
   417  		dbt.mustExec("CREATE TABLE test (id int, value BLOB) CHARACTER SET utf8")
   418  
   419  		id := 2
   420  		in = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " +
   421  			"sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " +
   422  			"sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. " +
   423  			"Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. " +
   424  			"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " +
   425  			"sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " +
   426  			"sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. " +
   427  			"Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
   428  		dbt.mustExec("INSERT INTO test VALUES (?, ?)", id, in)
   429  
   430  		err := dbt.db.QueryRow("SELECT value FROM test WHERE id = ?", id).Scan(&out)
   431  		if err != nil {
   432  			dbt.Fatalf("Error on BLOB-Query: %s", err.Error())
   433  		} else if out != in {
   434  			dbt.Errorf("BLOB: %s != %s", in, out)
   435  		}
   436  	})
   437  }
   438  
   439  type timeTests struct {
   440  	dbtype  string
   441  	tlayout string
   442  	tests   []timeTest
   443  }
   444  
   445  type timeTest struct {
   446  	s string // leading "!": do not use t as value in queries
   447  	t time.Time
   448  }
   449  
   450  type timeMode byte
   451  
   452  func (t timeMode) String() string {
   453  	switch t {
   454  	case binaryString:
   455  		return "binary:string"
   456  	case binaryTime:
   457  		return "binary:time.Time"
   458  	case textString:
   459  		return "text:string"
   460  	}
   461  	panic("unsupported timeMode")
   462  }
   463  
   464  func (t timeMode) Binary() bool {
   465  	switch t {
   466  	case binaryString, binaryTime:
   467  		return true
   468  	}
   469  	return false
   470  }
   471  
   472  const (
   473  	binaryString timeMode = iota
   474  	binaryTime
   475  	textString
   476  )
   477  
   478  func (t timeTest) genQuery(dbtype string, mode timeMode) string {
   479  	var inner string
   480  	if mode.Binary() {
   481  		inner = "?"
   482  	} else {
   483  		inner = `"%s"`
   484  	}
   485  	return `SELECT cast(` + inner + ` as ` + dbtype + `)`
   486  }
   487  
   488  func (t timeTest) run(dbt *DBTest, dbtype, tlayout string, mode timeMode) {
   489  	var rows *sql.Rows
   490  	query := t.genQuery(dbtype, mode)
   491  	switch mode {
   492  	case binaryString:
   493  		rows = dbt.mustQuery(query, t.s)
   494  	case binaryTime:
   495  		rows = dbt.mustQuery(query, t.t)
   496  	case textString:
   497  		query = fmt.Sprintf(query, t.s)
   498  		rows = dbt.mustQuery(query)
   499  	default:
   500  		panic("unsupported mode")
   501  	}
   502  	defer rows.Close()
   503  	var err error
   504  	if !rows.Next() {
   505  		err = rows.Err()
   506  		if err == nil {
   507  			err = fmt.Errorf("no data")
   508  		}
   509  		dbt.Errorf("%s [%s]: %s", dbtype, mode, err)
   510  		return
   511  	}
   512  	var dst interface{}
   513  	err = rows.Scan(&dst)
   514  	if err != nil {
   515  		dbt.Errorf("%s [%s]: %s", dbtype, mode, err)
   516  		return
   517  	}
   518  	switch val := dst.(type) {
   519  	case []uint8:
   520  		str := string(val)
   521  		if str == t.s {
   522  			return
   523  		}
   524  		if mode.Binary() && dbtype == "DATETIME" && len(str) == 26 && str[:19] == t.s {
   525  			// a fix mainly for TravisCI:
   526  			// accept full microsecond resolution in result for DATETIME columns
   527  			// where the binary protocol was used
   528  			return
   529  		}
   530  		dbt.Errorf("%s [%s] to string: expected %q, got %q",
   531  			dbtype, mode,
   532  			t.s, str,
   533  		)
   534  	case time.Time:
   535  		if val == t.t {
   536  			return
   537  		}
   538  		dbt.Errorf("%s [%s] to string: expected %q, got %q",
   539  			dbtype, mode,
   540  			t.s, val.Format(tlayout),
   541  		)
   542  	default:
   543  		fmt.Printf("%#v\n", []interface{}{dbtype, tlayout, mode, t.s, t.t})
   544  		dbt.Errorf("%s [%s]: unhandled type %T (is '%v')",
   545  			dbtype, mode,
   546  			val, val,
   547  		)
   548  	}
   549  }
   550  
   551  func TestDateTime(t *testing.T) {
   552  	afterTime := func(t time.Time, d string) time.Time {
   553  		dur, err := time.ParseDuration(d)
   554  		if err != nil {
   555  			panic(err)
   556  		}
   557  		return t.Add(dur)
   558  	}
   559  	// NOTE: MySQL rounds DATETIME(x) up - but that's not included in the tests
   560  	format := "2006-01-02 15:04:05.999999"
   561  	t0 := time.Time{}
   562  	tstr0 := "0000-00-00 00:00:00.000000"
   563  	testcases := []timeTests{
   564  		{"DATE", format[:10], []timeTest{
   565  			{t: time.Date(2011, 11, 20, 0, 0, 0, 0, time.UTC)},
   566  			{t: t0, s: tstr0[:10]},
   567  		}},
   568  		{"DATETIME", format[:19], []timeTest{
   569  			{t: time.Date(2011, 11, 20, 21, 27, 37, 0, time.UTC)},
   570  			{t: t0, s: tstr0[:19]},
   571  		}},
   572  		{"DATETIME(0)", format[:21], []timeTest{
   573  			{t: time.Date(2011, 11, 20, 21, 27, 37, 0, time.UTC)},
   574  			{t: t0, s: tstr0[:19]},
   575  		}},
   576  		{"DATETIME(1)", format[:21], []timeTest{
   577  			{t: time.Date(2011, 11, 20, 21, 27, 37, 100000000, time.UTC)},
   578  			{t: t0, s: tstr0[:21]},
   579  		}},
   580  		{"DATETIME(6)", format, []timeTest{
   581  			{t: time.Date(2011, 11, 20, 21, 27, 37, 123456000, time.UTC)},
   582  			{t: t0, s: tstr0},
   583  		}},
   584  		{"TIME", format[11:19], []timeTest{
   585  			{t: afterTime(t0, "12345s")},
   586  			{s: "!-12:34:56"},
   587  			{s: "!-838:59:59"},
   588  			{s: "!838:59:59"},
   589  			{t: t0, s: tstr0[11:19]},
   590  		}},
   591  		{"TIME(0)", format[11:19], []timeTest{
   592  			{t: afterTime(t0, "12345s")},
   593  			{s: "!-12:34:56"},
   594  			{s: "!-838:59:59"},
   595  			{s: "!838:59:59"},
   596  			{t: t0, s: tstr0[11:19]},
   597  		}},
   598  		{"TIME(1)", format[11:21], []timeTest{
   599  			{t: afterTime(t0, "12345600ms")},
   600  			{s: "!-12:34:56.7"},
   601  			{s: "!-838:59:58.9"},
   602  			{s: "!838:59:58.9"},
   603  			{t: t0, s: tstr0[11:21]},
   604  		}},
   605  		{"TIME(6)", format[11:], []timeTest{
   606  			{t: afterTime(t0, "1234567890123000ns")},
   607  			{s: "!-12:34:56.789012"},
   608  			{s: "!-838:59:58.999999"},
   609  			{s: "!838:59:58.999999"},
   610  			{t: t0, s: tstr0[11:]},
   611  		}},
   612  	}
   613  	dsns := []string{
   614  		dsn + "&parseTime=true",
   615  		dsn + "&parseTime=false",
   616  	}
   617  	for _, testdsn := range dsns {
   618  		runTests(t, testdsn, func(dbt *DBTest) {
   619  			microsecsSupported := false
   620  			zeroDateSupported := false
   621  			var rows *sql.Rows
   622  			var err error
   623  			rows, err = dbt.db.Query(`SELECT cast("00:00:00.1" as TIME(1)) = "00:00:00.1"`)
   624  			if err == nil {
   625  				rows.Scan(&microsecsSupported)
   626  				rows.Close()
   627  			}
   628  			rows, err = dbt.db.Query(`SELECT cast("0000-00-00" as DATE) = "0000-00-00"`)
   629  			if err == nil {
   630  				rows.Scan(&zeroDateSupported)
   631  				rows.Close()
   632  			}
   633  			for _, setups := range testcases {
   634  				if t := setups.dbtype; !microsecsSupported && t[len(t)-1:] == ")" {
   635  					// skip fractional second tests if unsupported by server
   636  					continue
   637  				}
   638  				for _, setup := range setups.tests {
   639  					allowBinTime := true
   640  					if setup.s == "" {
   641  						// fill time string whereever Go can reliable produce it
   642  						setup.s = setup.t.Format(setups.tlayout)
   643  					} else if setup.s[0] == '!' {
   644  						// skip tests using setup.t as source in queries
   645  						allowBinTime = false
   646  						// fix setup.s - remove the "!"
   647  						setup.s = setup.s[1:]
   648  					}
   649  					if !zeroDateSupported && setup.s == tstr0[:len(setup.s)] {
   650  						// skip disallowed 0000-00-00 date
   651  						continue
   652  					}
   653  					setup.run(dbt, setups.dbtype, setups.tlayout, textString)
   654  					setup.run(dbt, setups.dbtype, setups.tlayout, binaryString)
   655  					if allowBinTime {
   656  						setup.run(dbt, setups.dbtype, setups.tlayout, binaryTime)
   657  					}
   658  				}
   659  			}
   660  		})
   661  	}
   662  }
   663  
   664  func TestTimestampMicros(t *testing.T) {
   665  	format := "2006-01-02 15:04:05.999999"
   666  	f0 := format[:19]
   667  	f1 := format[:21]
   668  	f6 := format[:26]
   669  	runTests(t, dsn, func(dbt *DBTest) {
   670  		// check if microseconds are supported.
   671  		// Do not use timestamp(x) for that check - before 5.5.6, x would mean display width
   672  		// and not precision.
   673  		// Se last paragraph at http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
   674  		microsecsSupported := false
   675  		if rows, err := dbt.db.Query(`SELECT cast("00:00:00.1" as TIME(1)) = "00:00:00.1"`); err == nil {
   676  			rows.Scan(&microsecsSupported)
   677  			rows.Close()
   678  		}
   679  		if !microsecsSupported {
   680  			// skip test
   681  			return
   682  		}
   683  		_, err := dbt.db.Exec(`
   684  			CREATE TABLE test (
   685  				value0 TIMESTAMP NOT NULL DEFAULT '` + f0 + `',
   686  				value1 TIMESTAMP(1) NOT NULL DEFAULT '` + f1 + `',
   687  				value6 TIMESTAMP(6) NOT NULL DEFAULT '` + f6 + `'
   688  			)`,
   689  		)
   690  		if err != nil {
   691  			dbt.Error(err)
   692  		}
   693  		defer dbt.mustExec("DROP TABLE IF EXISTS test")
   694  		dbt.mustExec("INSERT INTO test SET value0=?, value1=?, value6=?", f0, f1, f6)
   695  		var res0, res1, res6 string
   696  		rows := dbt.mustQuery("SELECT * FROM test")
   697  		if !rows.Next() {
   698  			dbt.Errorf("test contained no selectable values")
   699  		}
   700  		err = rows.Scan(&res0, &res1, &res6)
   701  		if err != nil {
   702  			dbt.Error(err)
   703  		}
   704  		if res0 != f0 {
   705  			dbt.Errorf("expected %q, got %q", f0, res0)
   706  		}
   707  		if res1 != f1 {
   708  			dbt.Errorf("expected %q, got %q", f1, res1)
   709  		}
   710  		if res6 != f6 {
   711  			dbt.Errorf("expected %q, got %q", f6, res6)
   712  		}
   713  	})
   714  }
   715  
   716  func TestNULL(t *testing.T) {
   717  	runTests(t, dsn, func(dbt *DBTest) {
   718  		nullStmt, err := dbt.db.Prepare("SELECT NULL")
   719  		if err != nil {
   720  			dbt.Fatal(err)
   721  		}
   722  		defer nullStmt.Close()
   723  
   724  		nonNullStmt, err := dbt.db.Prepare("SELECT 1")
   725  		if err != nil {
   726  			dbt.Fatal(err)
   727  		}
   728  		defer nonNullStmt.Close()
   729  
   730  		// NullBool
   731  		var nb sql.NullBool
   732  		// Invalid
   733  		if err = nullStmt.QueryRow().Scan(&nb); err != nil {
   734  			dbt.Fatal(err)
   735  		}
   736  		if nb.Valid {
   737  			dbt.Error("valid NullBool which should be invalid")
   738  		}
   739  		// Valid
   740  		if err = nonNullStmt.QueryRow().Scan(&nb); err != nil {
   741  			dbt.Fatal(err)
   742  		}
   743  		if !nb.Valid {
   744  			dbt.Error("invalid NullBool which should be valid")
   745  		} else if nb.Bool != true {
   746  			dbt.Errorf("Unexpected NullBool value: %t (should be true)", nb.Bool)
   747  		}
   748  
   749  		// NullFloat64
   750  		var nf sql.NullFloat64
   751  		// Invalid
   752  		if err = nullStmt.QueryRow().Scan(&nf); err != nil {
   753  			dbt.Fatal(err)
   754  		}
   755  		if nf.Valid {
   756  			dbt.Error("valid NullFloat64 which should be invalid")
   757  		}
   758  		// Valid
   759  		if err = nonNullStmt.QueryRow().Scan(&nf); err != nil {
   760  			dbt.Fatal(err)
   761  		}
   762  		if !nf.Valid {
   763  			dbt.Error("invalid NullFloat64 which should be valid")
   764  		} else if nf.Float64 != float64(1) {
   765  			dbt.Errorf("unexpected NullFloat64 value: %f (should be 1.0)", nf.Float64)
   766  		}
   767  
   768  		// NullInt64
   769  		var ni sql.NullInt64
   770  		// Invalid
   771  		if err = nullStmt.QueryRow().Scan(&ni); err != nil {
   772  			dbt.Fatal(err)
   773  		}
   774  		if ni.Valid {
   775  			dbt.Error("valid NullInt64 which should be invalid")
   776  		}
   777  		// Valid
   778  		if err = nonNullStmt.QueryRow().Scan(&ni); err != nil {
   779  			dbt.Fatal(err)
   780  		}
   781  		if !ni.Valid {
   782  			dbt.Error("invalid NullInt64 which should be valid")
   783  		} else if ni.Int64 != int64(1) {
   784  			dbt.Errorf("unexpected NullInt64 value: %d (should be 1)", ni.Int64)
   785  		}
   786  
   787  		// NullString
   788  		var ns sql.NullString
   789  		// Invalid
   790  		if err = nullStmt.QueryRow().Scan(&ns); err != nil {
   791  			dbt.Fatal(err)
   792  		}
   793  		if ns.Valid {
   794  			dbt.Error("valid NullString which should be invalid")
   795  		}
   796  		// Valid
   797  		if err = nonNullStmt.QueryRow().Scan(&ns); err != nil {
   798  			dbt.Fatal(err)
   799  		}
   800  		if !ns.Valid {
   801  			dbt.Error("invalid NullString which should be valid")
   802  		} else if ns.String != `1` {
   803  			dbt.Error("unexpected NullString value:" + ns.String + " (should be `1`)")
   804  		}
   805  
   806  		// nil-bytes
   807  		var b []byte
   808  		// Read nil
   809  		if err = nullStmt.QueryRow().Scan(&b); err != nil {
   810  			dbt.Fatal(err)
   811  		}
   812  		if b != nil {
   813  			dbt.Error("non-nil []byte wich should be nil")
   814  		}
   815  		// Read non-nil
   816  		if err = nonNullStmt.QueryRow().Scan(&b); err != nil {
   817  			dbt.Fatal(err)
   818  		}
   819  		if b == nil {
   820  			dbt.Error("nil []byte wich should be non-nil")
   821  		}
   822  		// Insert nil
   823  		b = nil
   824  		success := false
   825  		if err = dbt.db.QueryRow("SELECT ? IS NULL", b).Scan(&success); err != nil {
   826  			dbt.Fatal(err)
   827  		}
   828  		if !success {
   829  			dbt.Error("inserting []byte(nil) as NULL failed")
   830  		}
   831  		// Check input==output with input==nil
   832  		b = nil
   833  		if err = dbt.db.QueryRow("SELECT ?", b).Scan(&b); err != nil {
   834  			dbt.Fatal(err)
   835  		}
   836  		if b != nil {
   837  			dbt.Error("non-nil echo from nil input")
   838  		}
   839  		// Check input==output with input!=nil
   840  		b = []byte("")
   841  		if err = dbt.db.QueryRow("SELECT ?", b).Scan(&b); err != nil {
   842  			dbt.Fatal(err)
   843  		}
   844  		if b == nil {
   845  			dbt.Error("nil echo from non-nil input")
   846  		}
   847  
   848  		// Insert NULL
   849  		dbt.mustExec("CREATE TABLE test (dummmy1 int, value int, dummy2 int)")
   850  
   851  		dbt.mustExec("INSERT INTO test VALUES (?, ?, ?)", 1, nil, 2)
   852  
   853  		var out interface{}
   854  		rows := dbt.mustQuery("SELECT * FROM test")
   855  		if rows.Next() {
   856  			rows.Scan(&out)
   857  			if out != nil {
   858  				dbt.Errorf("%v != nil", out)
   859  			}
   860  		} else {
   861  			dbt.Error("no data")
   862  		}
   863  	})
   864  }
   865  
   866  func TestUint64(t *testing.T) {
   867  	const (
   868  		u0    = uint64(0)
   869  		uall  = ^u0
   870  		uhigh = uall >> 1
   871  		utop  = ^uhigh
   872  		s0    = int64(0)
   873  		sall  = ^s0
   874  		shigh = int64(uhigh)
   875  		stop  = ^shigh
   876  	)
   877  	runTests(t, dsn, func(dbt *DBTest) {
   878  		stmt, err := dbt.db.Prepare(`SELECT ?, ?, ? ,?, ?, ?, ?, ?`)
   879  		if err != nil {
   880  			dbt.Fatal(err)
   881  		}
   882  		defer stmt.Close()
   883  		row := stmt.QueryRow(
   884  			u0, uhigh, utop, uall,
   885  			s0, shigh, stop, sall,
   886  		)
   887  
   888  		var ua, ub, uc, ud uint64
   889  		var sa, sb, sc, sd int64
   890  
   891  		err = row.Scan(&ua, &ub, &uc, &ud, &sa, &sb, &sc, &sd)
   892  		if err != nil {
   893  			dbt.Fatal(err)
   894  		}
   895  		switch {
   896  		case ua != u0,
   897  			ub != uhigh,
   898  			uc != utop,
   899  			ud != uall,
   900  			sa != s0,
   901  			sb != shigh,
   902  			sc != stop,
   903  			sd != sall:
   904  			dbt.Fatal("unexpected result value")
   905  		}
   906  	})
   907  }
   908  
   909  func TestLongData(t *testing.T) {
   910  	runTests(t, dsn, func(dbt *DBTest) {
   911  		var maxAllowedPacketSize int
   912  		err := dbt.db.QueryRow("select @@max_allowed_packet").Scan(&maxAllowedPacketSize)
   913  		if err != nil {
   914  			dbt.Fatal(err)
   915  		}
   916  		maxAllowedPacketSize--
   917  
   918  		// don't get too ambitious
   919  		if maxAllowedPacketSize > 1<<25 {
   920  			maxAllowedPacketSize = 1 << 25
   921  		}
   922  
   923  		dbt.mustExec("CREATE TABLE test (value LONGBLOB)")
   924  
   925  		in := strings.Repeat(`a`, maxAllowedPacketSize+1)
   926  		var out string
   927  		var rows *sql.Rows
   928  
   929  		// Long text data
   930  		const nonDataQueryLen = 28 // length query w/o value
   931  		inS := in[:maxAllowedPacketSize-nonDataQueryLen]
   932  		dbt.mustExec("INSERT INTO test VALUES('" + inS + "')")
   933  		rows = dbt.mustQuery("SELECT value FROM test")
   934  		if rows.Next() {
   935  			rows.Scan(&out)
   936  			if inS != out {
   937  				dbt.Fatalf("LONGBLOB: length in: %d, length out: %d", len(inS), len(out))
   938  			}
   939  			if rows.Next() {
   940  				dbt.Error("LONGBLOB: unexpexted row")
   941  			}
   942  		} else {
   943  			dbt.Fatalf("LONGBLOB: no data")
   944  		}
   945  
   946  		// Empty table
   947  		dbt.mustExec("TRUNCATE TABLE test")
   948  
   949  		// Long binary data
   950  		dbt.mustExec("INSERT INTO test VALUES(?)", in)
   951  		rows = dbt.mustQuery("SELECT value FROM test WHERE 1=?", 1)
   952  		if rows.Next() {
   953  			rows.Scan(&out)
   954  			if in != out {
   955  				dbt.Fatalf("LONGBLOB: length in: %d, length out: %d", len(in), len(out))
   956  			}
   957  			if rows.Next() {
   958  				dbt.Error("LONGBLOB: unexpexted row")
   959  			}
   960  		} else {
   961  			if err = rows.Err(); err != nil {
   962  				dbt.Fatalf("LONGBLOB: no data (err: %s)", err.Error())
   963  			} else {
   964  				dbt.Fatal("LONGBLOB: no data (err: <nil>)")
   965  			}
   966  		}
   967  	})
   968  }
   969  
   970  func TestLoadData(t *testing.T) {
   971  	runTests(t, dsn, func(dbt *DBTest) {
   972  		verifyLoadDataResult := func() {
   973  			rows, err := dbt.db.Query("SELECT * FROM test")
   974  			if err != nil {
   975  				dbt.Fatal(err.Error())
   976  			}
   977  
   978  			i := 0
   979  			values := [4]string{
   980  				"a string",
   981  				"a string containing a \t",
   982  				"a string containing a \n",
   983  				"a string containing both \t\n",
   984  			}
   985  
   986  			var id int
   987  			var value string
   988  
   989  			for rows.Next() {
   990  				i++
   991  				err = rows.Scan(&id, &value)
   992  				if err != nil {
   993  					dbt.Fatal(err.Error())
   994  				}
   995  				if i != id {
   996  					dbt.Fatalf("%d != %d", i, id)
   997  				}
   998  				if values[i-1] != value {
   999  					dbt.Fatalf("%q != %q", values[i-1], value)
  1000  				}
  1001  			}
  1002  			err = rows.Err()
  1003  			if err != nil {
  1004  				dbt.Fatal(err.Error())
  1005  			}
  1006  
  1007  			if i != 4 {
  1008  				dbt.Fatalf("rows count mismatch. Got %d, want 4", i)
  1009  			}
  1010  		}
  1011  		file, err := ioutil.TempFile("", "gotest")
  1012  		defer os.Remove(file.Name())
  1013  		if err != nil {
  1014  			dbt.Fatal(err)
  1015  		}
  1016  		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")
  1017  		file.Close()
  1018  
  1019  		dbt.db.Exec("DROP TABLE IF EXISTS test")
  1020  		dbt.mustExec("CREATE TABLE test (id INT NOT NULL PRIMARY KEY, value TEXT NOT NULL) CHARACTER SET utf8")
  1021  
  1022  		// Local File
  1023  		RegisterLocalFile(file.Name())
  1024  		dbt.mustExec(fmt.Sprintf("LOAD DATA LOCAL INFILE %q INTO TABLE test", file.Name()))
  1025  		verifyLoadDataResult()
  1026  		// negative test
  1027  		_, err = dbt.db.Exec("LOAD DATA LOCAL INFILE 'doesnotexist' INTO TABLE test")
  1028  		if err == nil {
  1029  			dbt.Fatal("load non-existent file didn't fail")
  1030  		} else if err.Error() != "local file 'doesnotexist' is not registered" {
  1031  			dbt.Fatal(err.Error())
  1032  		}
  1033  
  1034  		// Empty table
  1035  		dbt.mustExec("TRUNCATE TABLE test")
  1036  
  1037  		// Reader
  1038  		RegisterReaderHandler("test", func() io.Reader {
  1039  			file, err = os.Open(file.Name())
  1040  			if err != nil {
  1041  				dbt.Fatal(err)
  1042  			}
  1043  			return file
  1044  		})
  1045  		dbt.mustExec("LOAD DATA LOCAL INFILE 'Reader::test' INTO TABLE test")
  1046  		verifyLoadDataResult()
  1047  		// negative test
  1048  		_, err = dbt.db.Exec("LOAD DATA LOCAL INFILE 'Reader::doesnotexist' INTO TABLE test")
  1049  		if err == nil {
  1050  			dbt.Fatal("load non-existent Reader didn't fail")
  1051  		} else if err.Error() != "Reader 'doesnotexist' is not registered" {
  1052  			dbt.Fatal(err.Error())
  1053  		}
  1054  	})
  1055  }
  1056  
  1057  func TestFoundRows(t *testing.T) {
  1058  	runTests(t, dsn, func(dbt *DBTest) {
  1059  		dbt.mustExec("CREATE TABLE test (id INT NOT NULL ,data INT NOT NULL)")
  1060  		dbt.mustExec("INSERT INTO test (id, data) VALUES (0, 0),(0, 0),(1, 0),(1, 0),(1, 1)")
  1061  
  1062  		res := dbt.mustExec("UPDATE test SET data = 1 WHERE id = 0")
  1063  		count, err := res.RowsAffected()
  1064  		if err != nil {
  1065  			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  1066  		}
  1067  		if count != 2 {
  1068  			dbt.Fatalf("Expected 2 affected rows, got %d", count)
  1069  		}
  1070  		res = dbt.mustExec("UPDATE test SET data = 1 WHERE id = 1")
  1071  		count, err = res.RowsAffected()
  1072  		if err != nil {
  1073  			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  1074  		}
  1075  		if count != 2 {
  1076  			dbt.Fatalf("Expected 2 affected rows, got %d", count)
  1077  		}
  1078  	})
  1079  	runTests(t, dsn+"&clientFoundRows=true", func(dbt *DBTest) {
  1080  		dbt.mustExec("CREATE TABLE test (id INT NOT NULL ,data INT NOT NULL)")
  1081  		dbt.mustExec("INSERT INTO test (id, data) VALUES (0, 0),(0, 0),(1, 0),(1, 0),(1, 1)")
  1082  
  1083  		res := dbt.mustExec("UPDATE test SET data = 1 WHERE id = 0")
  1084  		count, err := res.RowsAffected()
  1085  		if err != nil {
  1086  			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  1087  		}
  1088  		if count != 2 {
  1089  			dbt.Fatalf("Expected 2 matched rows, got %d", count)
  1090  		}
  1091  		res = dbt.mustExec("UPDATE test SET data = 1 WHERE id = 1")
  1092  		count, err = res.RowsAffected()
  1093  		if err != nil {
  1094  			dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error())
  1095  		}
  1096  		if count != 3 {
  1097  			dbt.Fatalf("Expected 3 matched rows, got %d", count)
  1098  		}
  1099  	})
  1100  }
  1101  
  1102  func TestStrict(t *testing.T) {
  1103  	// ALLOW_INVALID_DATES to get rid of stricter modes - we want to test for warnings, not errors
  1104  	relaxedDsn := dsn + "&sql_mode='ALLOW_INVALID_DATES,NO_AUTO_CREATE_USER'"
  1105  	// make sure the MySQL version is recent enough with a separate connection
  1106  	// before running the test
  1107  	conn, err := MySQLDriver{}.Open(relaxedDsn)
  1108  	if conn != nil {
  1109  		conn.Close()
  1110  	}
  1111  	if me, ok := err.(*MySQLError); ok && me.Number == 1231 {
  1112  		// Error 1231: Variable 'sql_mode' can't be set to the value of 'ALLOW_INVALID_DATES'
  1113  		// => skip test, MySQL server version is too old
  1114  		return
  1115  	}
  1116  	runTests(t, relaxedDsn, func(dbt *DBTest) {
  1117  		dbt.mustExec("CREATE TABLE test (a TINYINT NOT NULL, b CHAR(4))")
  1118  
  1119  		var queries = [...]struct {
  1120  			in    string
  1121  			codes []string
  1122  		}{
  1123  			{"DROP TABLE IF EXISTS no_such_table", []string{"1051"}},
  1124  			{"INSERT INTO test VALUES(10,'mysql'),(NULL,'test'),(300,'Open Source')", []string{"1265", "1048", "1264", "1265"}},
  1125  		}
  1126  		var err error
  1127  
  1128  		var checkWarnings = func(err error, mode string, idx int) {
  1129  			if err == nil {
  1130  				dbt.Errorf("expected STRICT error on query [%s] %s", mode, queries[idx].in)
  1131  			}
  1132  
  1133  			if warnings, ok := err.(MySQLWarnings); ok {
  1134  				var codes = make([]string, len(warnings))
  1135  				for i := range warnings {
  1136  					codes[i] = warnings[i].Code
  1137  				}
  1138  				if len(codes) != len(queries[idx].codes) {
  1139  					dbt.Errorf("unexpected STRICT error count on query [%s] %s: Wanted %v, Got %v", mode, queries[idx].in, queries[idx].codes, codes)
  1140  				}
  1141  
  1142  				for i := range warnings {
  1143  					if codes[i] != queries[idx].codes[i] {
  1144  						dbt.Errorf("unexpected STRICT error codes on query [%s] %s: Wanted %v, Got %v", mode, queries[idx].in, queries[idx].codes, codes)
  1145  						return
  1146  					}
  1147  				}
  1148  
  1149  			} else {
  1150  				dbt.Errorf("unexpected error on query [%s] %s: %s", mode, queries[idx].in, err.Error())
  1151  			}
  1152  		}
  1153  
  1154  		// text protocol
  1155  		for i := range queries {
  1156  			_, err = dbt.db.Exec(queries[i].in)
  1157  			checkWarnings(err, "text", i)
  1158  		}
  1159  
  1160  		var stmt *sql.Stmt
  1161  
  1162  		// binary protocol
  1163  		for i := range queries {
  1164  			stmt, err = dbt.db.Prepare(queries[i].in)
  1165  			if err != nil {
  1166  				dbt.Errorf("error on preparing query %s: %s", queries[i].in, err.Error())
  1167  			}
  1168  
  1169  			_, err = stmt.Exec()
  1170  			checkWarnings(err, "binary", i)
  1171  
  1172  			err = stmt.Close()
  1173  			if err != nil {
  1174  				dbt.Errorf("error on closing stmt for query %s: %s", queries[i].in, err.Error())
  1175  			}
  1176  		}
  1177  	})
  1178  }
  1179  
  1180  func TestTLS(t *testing.T) {
  1181  	tlsTest := func(dbt *DBTest) {
  1182  		if err := dbt.db.Ping(); err != nil {
  1183  			if err == ErrNoTLS {
  1184  				dbt.Skip("server does not support TLS")
  1185  			} else {
  1186  				dbt.Fatalf("error on Ping: %s", err.Error())
  1187  			}
  1188  		}
  1189  
  1190  		rows := dbt.mustQuery("SHOW STATUS LIKE 'Ssl_cipher'")
  1191  
  1192  		var variable, value *sql.RawBytes
  1193  		for rows.Next() {
  1194  			if err := rows.Scan(&variable, &value); err != nil {
  1195  				dbt.Fatal(err.Error())
  1196  			}
  1197  
  1198  			if value == nil {
  1199  				dbt.Fatal("no Cipher")
  1200  			}
  1201  		}
  1202  	}
  1203  
  1204  	runTests(t, dsn+"&tls=skip-verify", tlsTest)
  1205  
  1206  	// Verify that registering / using a custom cfg works
  1207  	RegisterTLSConfig("custom-skip-verify", &tls.Config{
  1208  		InsecureSkipVerify: true,
  1209  	})
  1210  	runTests(t, dsn+"&tls=custom-skip-verify", tlsTest)
  1211  }
  1212  
  1213  func TestReuseClosedConnection(t *testing.T) {
  1214  	// this test does not use sql.database, it uses the driver directly
  1215  	if !available {
  1216  		t.Skipf("MySQL server not running on %s", netAddr)
  1217  	}
  1218  
  1219  	md := &MySQLDriver{}
  1220  	conn, err := md.Open(dsn)
  1221  	if err != nil {
  1222  		t.Fatalf("error connecting: %s", err.Error())
  1223  	}
  1224  	stmt, err := conn.Prepare("DO 1")
  1225  	if err != nil {
  1226  		t.Fatalf("error preparing statement: %s", err.Error())
  1227  	}
  1228  	_, err = stmt.Exec(nil)
  1229  	if err != nil {
  1230  		t.Fatalf("error executing statement: %s", err.Error())
  1231  	}
  1232  	err = conn.Close()
  1233  	if err != nil {
  1234  		t.Fatalf("error closing connection: %s", err.Error())
  1235  	}
  1236  
  1237  	defer func() {
  1238  		if err := recover(); err != nil {
  1239  			t.Errorf("panic after reusing a closed connection: %v", err)
  1240  		}
  1241  	}()
  1242  	_, err = stmt.Exec(nil)
  1243  	if err != nil && err != driver.ErrBadConn {
  1244  		t.Errorf("unexpected error '%s', expected '%s'",
  1245  			err.Error(), driver.ErrBadConn.Error())
  1246  	}
  1247  }
  1248  
  1249  func TestCharset(t *testing.T) {
  1250  	if !available {
  1251  		t.Skipf("MySQL server not running on %s", netAddr)
  1252  	}
  1253  
  1254  	mustSetCharset := func(charsetParam, expected string) {
  1255  		runTests(t, dsn+"&"+charsetParam, func(dbt *DBTest) {
  1256  			rows := dbt.mustQuery("SELECT @@character_set_connection")
  1257  			defer rows.Close()
  1258  
  1259  			if !rows.Next() {
  1260  				dbt.Fatalf("error getting connection charset: %s", rows.Err())
  1261  			}
  1262  
  1263  			var got string
  1264  			rows.Scan(&got)
  1265  
  1266  			if got != expected {
  1267  				dbt.Fatalf("expected connection charset %s but got %s", expected, got)
  1268  			}
  1269  		})
  1270  	}
  1271  
  1272  	// non utf8 test
  1273  	mustSetCharset("charset=ascii", "ascii")
  1274  
  1275  	// when the first charset is invalid, use the second
  1276  	mustSetCharset("charset=none,utf8", "utf8")
  1277  
  1278  	// when the first charset is valid, use it
  1279  	mustSetCharset("charset=ascii,utf8", "ascii")
  1280  	mustSetCharset("charset=utf8,ascii", "utf8")
  1281  }
  1282  
  1283  func TestFailingCharset(t *testing.T) {
  1284  	runTests(t, dsn+"&charset=none", func(dbt *DBTest) {
  1285  		// run query to really establish connection...
  1286  		_, err := dbt.db.Exec("SELECT 1")
  1287  		if err == nil {
  1288  			dbt.db.Close()
  1289  			t.Fatalf("connection must not succeed without a valid charset")
  1290  		}
  1291  	})
  1292  }
  1293  
  1294  func TestCollation(t *testing.T) {
  1295  	if !available {
  1296  		t.Skipf("MySQL server not running on %s", netAddr)
  1297  	}
  1298  
  1299  	defaultCollation := "utf8_general_ci"
  1300  	testCollations := []string{
  1301  		"",               // do not set
  1302  		defaultCollation, // driver default
  1303  		"latin1_general_ci",
  1304  		"binary",
  1305  		"utf8_unicode_ci",
  1306  		"cp1257_bin",
  1307  	}
  1308  
  1309  	for _, collation := range testCollations {
  1310  		var expected, tdsn string
  1311  		if collation != "" {
  1312  			tdsn = dsn + "&collation=" + collation
  1313  			expected = collation
  1314  		} else {
  1315  			tdsn = dsn
  1316  			expected = defaultCollation
  1317  		}
  1318  
  1319  		runTests(t, tdsn, func(dbt *DBTest) {
  1320  			var got string
  1321  			if err := dbt.db.QueryRow("SELECT @@collation_connection").Scan(&got); err != nil {
  1322  				dbt.Fatal(err)
  1323  			}
  1324  
  1325  			if got != expected {
  1326  				dbt.Fatalf("expected connection collation %s but got %s", expected, got)
  1327  			}
  1328  		})
  1329  	}
  1330  }
  1331  
  1332  func TestColumnsWithAlias(t *testing.T) {
  1333  	runTests(t, dsn+"&columnsWithAlias=true", func(dbt *DBTest) {
  1334  		rows := dbt.mustQuery("SELECT 1 AS A")
  1335  		defer rows.Close()
  1336  		cols, _ := rows.Columns()
  1337  		if len(cols) != 1 {
  1338  			t.Fatalf("expected 1 column, got %d", len(cols))
  1339  		}
  1340  		if cols[0] != "A" {
  1341  			t.Fatalf("expected column name \"A\", got \"%s\"", cols[0])
  1342  		}
  1343  		rows.Close()
  1344  
  1345  		rows = dbt.mustQuery("SELECT * FROM (SELECT 1 AS one) AS A")
  1346  		cols, _ = rows.Columns()
  1347  		if len(cols) != 1 {
  1348  			t.Fatalf("expected 1 column, got %d", len(cols))
  1349  		}
  1350  		if cols[0] != "A.one" {
  1351  			t.Fatalf("expected column name \"A.one\", got \"%s\"", cols[0])
  1352  		}
  1353  	})
  1354  }
  1355  
  1356  func TestRawBytesResultExceedsBuffer(t *testing.T) {
  1357  	runTests(t, dsn, func(dbt *DBTest) {
  1358  		// defaultBufSize from buffer.go
  1359  		expected := strings.Repeat("abc", defaultBufSize)
  1360  
  1361  		rows := dbt.mustQuery("SELECT '" + expected + "'")
  1362  		defer rows.Close()
  1363  		if !rows.Next() {
  1364  			dbt.Error("expected result, got none")
  1365  		}
  1366  		var result sql.RawBytes
  1367  		rows.Scan(&result)
  1368  		if expected != string(result) {
  1369  			dbt.Error("result did not match expected value")
  1370  		}
  1371  	})
  1372  }
  1373  
  1374  func TestTimezoneConversion(t *testing.T) {
  1375  	zones := []string{"UTC", "US/Central", "US/Pacific", "Local"}
  1376  
  1377  	// Regression test for timezone handling
  1378  	tzTest := func(dbt *DBTest) {
  1379  
  1380  		// Create table
  1381  		dbt.mustExec("CREATE TABLE test (ts TIMESTAMP)")
  1382  
  1383  		// Insert local time into database (should be converted)
  1384  		usCentral, _ := time.LoadLocation("US/Central")
  1385  		reftime := time.Date(2014, 05, 30, 18, 03, 17, 0, time.UTC).In(usCentral)
  1386  		dbt.mustExec("INSERT INTO test VALUE (?)", reftime)
  1387  
  1388  		// Retrieve time from DB
  1389  		rows := dbt.mustQuery("SELECT ts FROM test")
  1390  		if !rows.Next() {
  1391  			dbt.Fatal("did not get any rows out")
  1392  		}
  1393  
  1394  		var dbTime time.Time
  1395  		err := rows.Scan(&dbTime)
  1396  		if err != nil {
  1397  			dbt.Fatal("Err", err)
  1398  		}
  1399  
  1400  		// Check that dates match
  1401  		if reftime.Unix() != dbTime.Unix() {
  1402  			dbt.Errorf("times do not match.\n")
  1403  			dbt.Errorf(" Now(%v)=%v\n", usCentral, reftime)
  1404  			dbt.Errorf(" Now(UTC)=%v\n", dbTime)
  1405  		}
  1406  	}
  1407  
  1408  	for _, tz := range zones {
  1409  		runTests(t, dsn+"&parseTime=true&loc="+url.QueryEscape(tz), tzTest)
  1410  	}
  1411  }
  1412  
  1413  // Special cases
  1414  
  1415  func TestRowsClose(t *testing.T) {
  1416  	runTests(t, dsn, func(dbt *DBTest) {
  1417  		rows, err := dbt.db.Query("SELECT 1")
  1418  		if err != nil {
  1419  			dbt.Fatal(err)
  1420  		}
  1421  
  1422  		err = rows.Close()
  1423  		if err != nil {
  1424  			dbt.Fatal(err)
  1425  		}
  1426  
  1427  		if rows.Next() {
  1428  			dbt.Fatal("unexpected row after rows.Close()")
  1429  		}
  1430  
  1431  		err = rows.Err()
  1432  		if err != nil {
  1433  			dbt.Fatal(err)
  1434  		}
  1435  	})
  1436  }
  1437  
  1438  // dangling statements
  1439  // http://code.google.com/p/go/issues/detail?id=3865
  1440  func TestCloseStmtBeforeRows(t *testing.T) {
  1441  	runTests(t, dsn, func(dbt *DBTest) {
  1442  		stmt, err := dbt.db.Prepare("SELECT 1")
  1443  		if err != nil {
  1444  			dbt.Fatal(err)
  1445  		}
  1446  
  1447  		rows, err := stmt.Query()
  1448  		if err != nil {
  1449  			stmt.Close()
  1450  			dbt.Fatal(err)
  1451  		}
  1452  		defer rows.Close()
  1453  
  1454  		err = stmt.Close()
  1455  		if err != nil {
  1456  			dbt.Fatal(err)
  1457  		}
  1458  
  1459  		if !rows.Next() {
  1460  			dbt.Fatal("getting row failed")
  1461  		} else {
  1462  			err = rows.Err()
  1463  			if err != nil {
  1464  				dbt.Fatal(err)
  1465  			}
  1466  
  1467  			var out bool
  1468  			err = rows.Scan(&out)
  1469  			if err != nil {
  1470  				dbt.Fatalf("error on rows.Scan(): %s", err.Error())
  1471  			}
  1472  			if out != true {
  1473  				dbt.Errorf("true != %t", out)
  1474  			}
  1475  		}
  1476  	})
  1477  }
  1478  
  1479  // It is valid to have multiple Rows for the same Stmt
  1480  // http://code.google.com/p/go/issues/detail?id=3734
  1481  func TestStmtMultiRows(t *testing.T) {
  1482  	runTests(t, dsn, func(dbt *DBTest) {
  1483  		stmt, err := dbt.db.Prepare("SELECT 1 UNION SELECT 0")
  1484  		if err != nil {
  1485  			dbt.Fatal(err)
  1486  		}
  1487  
  1488  		rows1, err := stmt.Query()
  1489  		if err != nil {
  1490  			stmt.Close()
  1491  			dbt.Fatal(err)
  1492  		}
  1493  		defer rows1.Close()
  1494  
  1495  		rows2, err := stmt.Query()
  1496  		if err != nil {
  1497  			stmt.Close()
  1498  			dbt.Fatal(err)
  1499  		}
  1500  		defer rows2.Close()
  1501  
  1502  		var out bool
  1503  
  1504  		// 1
  1505  		if !rows1.Next() {
  1506  			dbt.Fatal("first rows1.Next failed")
  1507  		} else {
  1508  			err = rows1.Err()
  1509  			if err != nil {
  1510  				dbt.Fatal(err)
  1511  			}
  1512  
  1513  			err = rows1.Scan(&out)
  1514  			if err != nil {
  1515  				dbt.Fatalf("error on rows.Scan(): %s", err.Error())
  1516  			}
  1517  			if out != true {
  1518  				dbt.Errorf("true != %t", out)
  1519  			}
  1520  		}
  1521  
  1522  		if !rows2.Next() {
  1523  			dbt.Fatal("first rows2.Next failed")
  1524  		} else {
  1525  			err = rows2.Err()
  1526  			if err != nil {
  1527  				dbt.Fatal(err)
  1528  			}
  1529  
  1530  			err = rows2.Scan(&out)
  1531  			if err != nil {
  1532  				dbt.Fatalf("error on rows.Scan(): %s", err.Error())
  1533  			}
  1534  			if out != true {
  1535  				dbt.Errorf("true != %t", out)
  1536  			}
  1537  		}
  1538  
  1539  		// 2
  1540  		if !rows1.Next() {
  1541  			dbt.Fatal("second rows1.Next failed")
  1542  		} else {
  1543  			err = rows1.Err()
  1544  			if err != nil {
  1545  				dbt.Fatal(err)
  1546  			}
  1547  
  1548  			err = rows1.Scan(&out)
  1549  			if err != nil {
  1550  				dbt.Fatalf("error on rows.Scan(): %s", err.Error())
  1551  			}
  1552  			if out != false {
  1553  				dbt.Errorf("false != %t", out)
  1554  			}
  1555  
  1556  			if rows1.Next() {
  1557  				dbt.Fatal("unexpected row on rows1")
  1558  			}
  1559  			err = rows1.Close()
  1560  			if err != nil {
  1561  				dbt.Fatal(err)
  1562  			}
  1563  		}
  1564  
  1565  		if !rows2.Next() {
  1566  			dbt.Fatal("second rows2.Next failed")
  1567  		} else {
  1568  			err = rows2.Err()
  1569  			if err != nil {
  1570  				dbt.Fatal(err)
  1571  			}
  1572  
  1573  			err = rows2.Scan(&out)
  1574  			if err != nil {
  1575  				dbt.Fatalf("error on rows.Scan(): %s", err.Error())
  1576  			}
  1577  			if out != false {
  1578  				dbt.Errorf("false != %t", out)
  1579  			}
  1580  
  1581  			if rows2.Next() {
  1582  				dbt.Fatal("unexpected row on rows2")
  1583  			}
  1584  			err = rows2.Close()
  1585  			if err != nil {
  1586  				dbt.Fatal(err)
  1587  			}
  1588  		}
  1589  	})
  1590  }
  1591  
  1592  // Regression test for
  1593  // * more than 32 NULL parameters (issue 209)
  1594  // * more parameters than fit into the buffer (issue 201)
  1595  func TestPreparedManyCols(t *testing.T) {
  1596  	const numParams = defaultBufSize
  1597  	runTests(t, dsn, func(dbt *DBTest) {
  1598  		query := "SELECT ?" + strings.Repeat(",?", numParams-1)
  1599  		stmt, err := dbt.db.Prepare(query)
  1600  		if err != nil {
  1601  			dbt.Fatal(err)
  1602  		}
  1603  		defer stmt.Close()
  1604  		// create more parameters than fit into the buffer
  1605  		// which will take nil-values
  1606  		params := make([]interface{}, numParams)
  1607  		rows, err := stmt.Query(params...)
  1608  		if err != nil {
  1609  			stmt.Close()
  1610  			dbt.Fatal(err)
  1611  		}
  1612  		defer rows.Close()
  1613  	})
  1614  }
  1615  
  1616  func TestConcurrent(t *testing.T) {
  1617  	if enabled, _ := readBool(os.Getenv("MYSQL_TEST_CONCURRENT")); !enabled {
  1618  		t.Skip("MYSQL_TEST_CONCURRENT env var not set")
  1619  	}
  1620  
  1621  	runTests(t, dsn, func(dbt *DBTest) {
  1622  		var max int
  1623  		err := dbt.db.QueryRow("SELECT @@max_connections").Scan(&max)
  1624  		if err != nil {
  1625  			dbt.Fatalf("%s", err.Error())
  1626  		}
  1627  		dbt.Logf("testing up to %d concurrent connections \r\n", max)
  1628  
  1629  		var remaining, succeeded int32 = int32(max), 0
  1630  
  1631  		var wg sync.WaitGroup
  1632  		wg.Add(max)
  1633  
  1634  		var fatalError string
  1635  		var once sync.Once
  1636  		fatalf := func(s string, vals ...interface{}) {
  1637  			once.Do(func() {
  1638  				fatalError = fmt.Sprintf(s, vals...)
  1639  			})
  1640  		}
  1641  
  1642  		for i := 0; i < max; i++ {
  1643  			go func(id int) {
  1644  				defer wg.Done()
  1645  
  1646  				tx, err := dbt.db.Begin()
  1647  				atomic.AddInt32(&remaining, -1)
  1648  
  1649  				if err != nil {
  1650  					if err.Error() != "Error 1040: Too many connections" {
  1651  						fatalf("error on conn %d: %s", id, err.Error())
  1652  					}
  1653  					return
  1654  				}
  1655  
  1656  				// keep the connection busy until all connections are open
  1657  				for remaining > 0 {
  1658  					if _, err = tx.Exec("DO 1"); err != nil {
  1659  						fatalf("error on conn %d: %s", id, err.Error())
  1660  						return
  1661  					}
  1662  				}
  1663  
  1664  				if err = tx.Commit(); err != nil {
  1665  					fatalf("error on conn %d: %s", id, err.Error())
  1666  					return
  1667  				}
  1668  
  1669  				// everything went fine with this connection
  1670  				atomic.AddInt32(&succeeded, 1)
  1671  			}(i)
  1672  		}
  1673  
  1674  		// wait until all conections are open
  1675  		wg.Wait()
  1676  
  1677  		if fatalError != "" {
  1678  			dbt.Fatal(fatalError)
  1679  		}
  1680  
  1681  		dbt.Logf("reached %d concurrent connections\r\n", succeeded)
  1682  	})
  1683  }
  1684  
  1685  // Tests custom dial functions
  1686  func TestCustomDial(t *testing.T) {
  1687  	if !available {
  1688  		t.Skipf("MySQL server not running on %s", netAddr)
  1689  	}
  1690  
  1691  	// our custom dial function which justs wraps net.Dial here
  1692  	RegisterDial("mydial", func(addr string) (net.Conn, error) {
  1693  		return net.Dial(prot, addr)
  1694  	})
  1695  
  1696  	db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@mydial(%s)/%s?timeout=30s&strict=true", user, pass, addr, dbname))
  1697  	if err != nil {
  1698  		t.Fatalf("error connecting: %s", err.Error())
  1699  	}
  1700  	defer db.Close()
  1701  
  1702  	if _, err = db.Exec("DO 1"); err != nil {
  1703  		t.Fatalf("connection failed: %s", err.Error())
  1704  	}
  1705  }
  1706  
  1707  func TestSQLInjection(t *testing.T) {
  1708  	createTest := func(arg string) func(dbt *DBTest) {
  1709  		return func(dbt *DBTest) {
  1710  			dbt.mustExec("CREATE TABLE test (v INTEGER)")
  1711  			dbt.mustExec("INSERT INTO test VALUES (?)", 1)
  1712  
  1713  			var v int
  1714  			// NULL can't be equal to anything, the idea here is to inject query so it returns row
  1715  			// This test verifies that escapeQuotes and escapeBackslash are working properly
  1716  			err := dbt.db.QueryRow("SELECT v FROM test WHERE NULL = ?", arg).Scan(&v)
  1717  			if err == sql.ErrNoRows {
  1718  				return // success, sql injection failed
  1719  			} else if err == nil {
  1720  				dbt.Errorf("sql injection successful with arg: %s", arg)
  1721  			} else {
  1722  				dbt.Errorf("error running query with arg: %s; err: %s", arg, err.Error())
  1723  			}
  1724  		}
  1725  	}
  1726  
  1727  	dsns := []string{
  1728  		dsn,
  1729  		dsn + "&sql_mode='NO_BACKSLASH_ESCAPES,NO_AUTO_CREATE_USER'",
  1730  	}
  1731  	for _, testdsn := range dsns {
  1732  		runTests(t, testdsn, createTest("1 OR 1=1"))
  1733  		runTests(t, testdsn, createTest("' OR '1'='1"))
  1734  	}
  1735  }
  1736  
  1737  // Test if inserted data is correctly retrieved after being escaped
  1738  func TestInsertRetrieveEscapedData(t *testing.T) {
  1739  	testData := func(dbt *DBTest) {
  1740  		dbt.mustExec("CREATE TABLE test (v VARCHAR(255))")
  1741  
  1742  		// All sequences that are escaped by escapeQuotes and escapeBackslash
  1743  		v := "foo \x00\n\r\x1a\"'\\"
  1744  		dbt.mustExec("INSERT INTO test VALUES (?)", v)
  1745  
  1746  		var out string
  1747  		err := dbt.db.QueryRow("SELECT v FROM test").Scan(&out)
  1748  		if err != nil {
  1749  			dbt.Fatalf("%s", err.Error())
  1750  		}
  1751  
  1752  		if out != v {
  1753  			dbt.Errorf("%q != %q", out, v)
  1754  		}
  1755  	}
  1756  
  1757  	dsns := []string{
  1758  		dsn,
  1759  		dsn + "&sql_mode='NO_BACKSLASH_ESCAPES,NO_AUTO_CREATE_USER'",
  1760  	}
  1761  	for _, testdsn := range dsns {
  1762  		runTests(t, testdsn, testData)
  1763  	}
  1764  }
  1765  
  1766  func TestUnixSocketAuthFail(t *testing.T) {
  1767  	runTests(t, dsn, func(dbt *DBTest) {
  1768  		// Save the current logger so we can restore it.
  1769  		oldLogger := errLog
  1770  
  1771  		// Set a new logger so we can capture its output.
  1772  		buffer := bytes.NewBuffer(make([]byte, 0, 64))
  1773  		newLogger := log.New(buffer, "prefix: ", 0)
  1774  		SetLogger(newLogger)
  1775  
  1776  		// Restore the logger.
  1777  		defer SetLogger(oldLogger)
  1778  
  1779  		// Make a new DSN that uses the MySQL socket file and a bad password, which
  1780  		// we can make by simply appending any character to the real password.
  1781  		badPass := pass + "x"
  1782  		socket := ""
  1783  		if prot == "unix" {
  1784  			socket = addr
  1785  		} else {
  1786  			// Get socket file from MySQL.
  1787  			err := dbt.db.QueryRow("SELECT @@socket").Scan(&socket)
  1788  			if err != nil {
  1789  				t.Fatalf("error on SELECT @@socket: %s", err.Error())
  1790  			}
  1791  		}
  1792  		t.Logf("socket: %s", socket)
  1793  		badDSN := fmt.Sprintf("%s:%s@unix(%s)/%s?timeout=30s&strict=true", user, badPass, socket, dbname)
  1794  		db, err := sql.Open("mysql", badDSN)
  1795  		if err != nil {
  1796  			t.Fatalf("error connecting: %s", err.Error())
  1797  		}
  1798  		defer db.Close()
  1799  
  1800  		// Connect to MySQL for real. This will cause an auth failure.
  1801  		err = db.Ping()
  1802  		if err == nil {
  1803  			t.Error("expected Ping() to return an error")
  1804  		}
  1805  
  1806  		// The driver should not log anything.
  1807  		if actual := buffer.String(); actual != "" {
  1808  			t.Errorf("expected no output, got %q", actual)
  1809  		}
  1810  	})
  1811  }