github.com/dolthub/go-mysql-server@v0.18.0/enginetest/queries/transaction_queries.go (about)

     1  // Copyright 2021 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package queries
    16  
    17  import (
    18  	"github.com/dolthub/go-mysql-server/sql"
    19  	"github.com/dolthub/go-mysql-server/sql/types"
    20  )
    21  
    22  // TransactionTest is a script to test transaction correctness. It's similar to ScriptTest, but its assertions name
    23  // clients that participate
    24  type TransactionTest struct {
    25  	// Name of the script test
    26  	Name string
    27  	// The sql statements to execute as setup, in order. Results are not checked, but statements must not error.
    28  	// Setup scripts are run as a distinct client separate from the client used in any assertions.
    29  	SetUpScript []string
    30  	// The set of assertions to make after setup, in order
    31  	// The transaction test runner augments the ScriptTest runner by allowing embedding of a client string in a query
    32  	// comment to name the client running the query, like so:
    33  	// /* client a */ select * from myTable
    34  	Assertions []ScriptTestAssertion
    35  }
    36  
    37  var TransactionTests = []TransactionTest{
    38  	{
    39  		Name: "Changes from transactions are available before analyzing statements in other sessions (autocommit off)",
    40  		Assertions: []ScriptTestAssertion{
    41  			{
    42  				Query:    "/* client a */ set @@autocommit = 0;",
    43  				Expected: []sql.Row{{}},
    44  			},
    45  			{
    46  				Query:    "/* client b */ set @@autocommit = 0;",
    47  				Expected: []sql.Row{{}},
    48  			},
    49  			{
    50  				Query:    "/* client a */ select @@autocommit;",
    51  				Expected: []sql.Row{{0}},
    52  			},
    53  			{
    54  				Query:    "/* client b */ select @@autocommit;",
    55  				Expected: []sql.Row{{0}},
    56  			},
    57  			{
    58  				Query:    "/* client a */ start transaction;",
    59  				Expected: []sql.Row{},
    60  			},
    61  			{
    62  				Query:       "/* client a */ select * from t;",
    63  				ExpectedErr: sql.ErrTableNotFound,
    64  			},
    65  			{
    66  				Query:    "/* client a */ create table t(pk int primary key);",
    67  				Expected: []sql.Row{{types.OkResult{}}},
    68  			},
    69  			{
    70  				// Trigger a query error to make sure explicit transaction is still
    71  				// correctly configured in the session despite the error
    72  				Query:       "/* client a */ select * from t2;",
    73  				ExpectedErr: sql.ErrTableNotFound,
    74  			},
    75  			{
    76  				Query:    "/* client a */ commit;",
    77  				Expected: []sql.Row{},
    78  			},
    79  			{
    80  				Query:    "/* client b */ start transaction;",
    81  				Expected: []sql.Row{},
    82  			},
    83  			{
    84  				Query:    "/* client b */ select count(*) from t;",
    85  				Expected: []sql.Row{{0}},
    86  			},
    87  		},
    88  	},
    89  	{
    90  		Name: "autocommit on",
    91  		SetUpScript: []string{
    92  			"create table t (x int primary key, y int)",
    93  			"insert into t values (1, 1)",
    94  		},
    95  		Assertions: []ScriptTestAssertion{
    96  			{
    97  				Query:    "/* client a */ insert into t values (2, 2)",
    98  				Expected: []sql.Row{{types.NewOkResult(1)}},
    99  			},
   100  			{
   101  				Query:    "/* client b */ select * from t order by x",
   102  				Expected: []sql.Row{{1, 1}, {2, 2}},
   103  			},
   104  			{
   105  				Query:    "/* client b */ insert into t values (3, 3)",
   106  				Expected: []sql.Row{{types.NewOkResult(1)}},
   107  			},
   108  			{
   109  				Query:    "/* client a */ select * from t order by x",
   110  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   111  			},
   112  		},
   113  	},
   114  	{
   115  		Name: "autocommit off",
   116  		SetUpScript: []string{
   117  			"create table t (x int primary key, y int)",
   118  			"insert into t values (1, 1)",
   119  		},
   120  		Assertions: []ScriptTestAssertion{
   121  			{
   122  				Query:    "/* client a */ set autocommit = off",
   123  				Expected: []sql.Row{{}},
   124  			},
   125  			{
   126  				Query:    "/* client b */ set autocommit = off",
   127  				Expected: []sql.Row{{}},
   128  			},
   129  			{
   130  				Query:    "/* client b */ select * from t order by x",
   131  				Expected: []sql.Row{{1, 1}},
   132  			},
   133  			{
   134  				Query:    "/* client b */ insert into t values (2, 2)",
   135  				Expected: []sql.Row{{types.NewOkResult(1)}},
   136  			},
   137  			{
   138  				Query: "/* client a */ select * from t order by x",
   139  				Expected: []sql.Row{
   140  					{1, 1},
   141  				},
   142  			},
   143  			{
   144  				Query:    "/* client a */ insert into t values (3,3)",
   145  				Expected: []sql.Row{{types.NewOkResult(1)}},
   146  			},
   147  			{
   148  				Query:    "/* client b */ select * from t order by x",
   149  				Expected: []sql.Row{{1, 1}, {2, 2}},
   150  			},
   151  			{
   152  				Query:    "/* client b */ commit",
   153  				Expected: []sql.Row{},
   154  			},
   155  			{
   156  				Query:    "/* client a */ select * from t order by x",
   157  				Expected: []sql.Row{{1, 1}, {3, 3}},
   158  			},
   159  			{
   160  				Query:    "/* client b */ select * from t order by x",
   161  				Expected: []sql.Row{{1, 1}, {2, 2}},
   162  			},
   163  			{
   164  				Query:    "/* client a */ commit",
   165  				Expected: []sql.Row{},
   166  			},
   167  			{
   168  				Query:    "/* client b */ select * from t order by x",
   169  				Expected: []sql.Row{{1, 1}, {2, 2}},
   170  			},
   171  			{
   172  				Query:    "/* client b */ start transaction",
   173  				Expected: []sql.Row{},
   174  			},
   175  			{
   176  				Query:    "/* client b */ select * from t order by x",
   177  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   178  			},
   179  			{
   180  				Query:    "/* client a */ select * from t order by x",
   181  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   182  			},
   183  		},
   184  	},
   185  	{
   186  		Name: "toggle autocommit",
   187  		SetUpScript: []string{
   188  			"create table t (x int primary key, y int)",
   189  			"insert into t values (1, 1)",
   190  		},
   191  		Assertions: []ScriptTestAssertion{
   192  			{
   193  				Query:    "/* client a */ set autocommit = off",
   194  				Expected: []sql.Row{{}},
   195  			},
   196  			{
   197  				Query:    "/* client b */ set autocommit = off",
   198  				Expected: []sql.Row{{}},
   199  			},
   200  			{
   201  				Query:    "/* client b */ insert into t values (2,2)",
   202  				Expected: []sql.Row{{types.NewOkResult(1)}},
   203  			},
   204  			{
   205  				Query:    "/* client a */ select * from t order by x",
   206  				Expected: []sql.Row{{1, 1}},
   207  			},
   208  			// should commit any pending transaction
   209  			{
   210  				Query:    "/* client b */ set autocommit = on",
   211  				Expected: []sql.Row{{}},
   212  			},
   213  			{
   214  				Query:    "/* client a */ select * from t order by x",
   215  				Expected: []sql.Row{{1, 1}},
   216  			},
   217  			// client a sees the committed transaction from client b when it begins a new transaction
   218  			{
   219  				Query:    "/* client a */ set autocommit = on",
   220  				Expected: []sql.Row{{}},
   221  			},
   222  			{
   223  				Query:    "/* client a */ select * from t order by x",
   224  				Expected: []sql.Row{{1, 1}, {2, 2}},
   225  			},
   226  		},
   227  	},
   228  	{
   229  		Name: "autocommit on with explicit transactions",
   230  		SetUpScript: []string{
   231  			"create table t (x int primary key, y int)",
   232  			"insert into t values (1, 1)",
   233  		},
   234  		Assertions: []ScriptTestAssertion{
   235  			{
   236  				Query:    "/* client a */ start transaction",
   237  				Expected: []sql.Row{},
   238  			},
   239  			{
   240  				// Trigger an analyzer error to make sure transaction state is managed correctly
   241  				Query:       "/* client a */ select * from doesnotexist;",
   242  				ExpectedErr: sql.ErrTableNotFound,
   243  			},
   244  			{
   245  				Query:    "/* client a */ insert into t values (2, 2)",
   246  				Expected: []sql.Row{{types.NewOkResult(1)}},
   247  			},
   248  			{
   249  				Query:    "/* client b */ select * from t order by x",
   250  				Expected: []sql.Row{{1, 1}},
   251  			},
   252  			{
   253  				// Trigger an analyzer error to make sure state for the explicitly started
   254  				// transaction is managed correctly and not cleared
   255  				Query:       "/* client a */ select * from doesnotexist;",
   256  				ExpectedErr: sql.ErrTableNotFound,
   257  			},
   258  			{
   259  				Query:    "/* client a */ commit",
   260  				Expected: []sql.Row{},
   261  			},
   262  			{
   263  				Query:    "/* client b */ select * from t order by x",
   264  				Expected: []sql.Row{{1, 1}, {2, 2}},
   265  			},
   266  			// After commit, autocommit turns back on
   267  			{
   268  				Query:    "/* client a */ insert into t values (3, 3)",
   269  				Expected: []sql.Row{{types.NewOkResult(1)}},
   270  			},
   271  			{
   272  				Query:    "/* client b */ select * from t order by x",
   273  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   274  			},
   275  		},
   276  	},
   277  	{
   278  		Name: "rollback",
   279  		SetUpScript: []string{
   280  			"create table t (x int primary key, y int)",
   281  			"insert into t values (1, 1)",
   282  		},
   283  		Assertions: []ScriptTestAssertion{
   284  			{
   285  				Query:    "/* client a */ set autocommit = off",
   286  				Expected: []sql.Row{{}},
   287  			},
   288  			{
   289  				Query:    "/* client b */ set autocommit = off",
   290  				Expected: []sql.Row{{}},
   291  			},
   292  			{
   293  				Query:    "/* client a */ start transaction",
   294  				Expected: []sql.Row{},
   295  			},
   296  			{
   297  				Query:    "/* client b */ start transaction",
   298  				Expected: []sql.Row{},
   299  			},
   300  			{
   301  				Query:    "/* client a */ insert into t values (2, 2)",
   302  				Expected: []sql.Row{{types.NewOkResult(1)}},
   303  			},
   304  			{
   305  				Query:    "/* client b */ insert into t values (3, 3)",
   306  				Expected: []sql.Row{{types.NewOkResult(1)}},
   307  			},
   308  			{
   309  				Query:    "/* client a */ select * from t order by x",
   310  				Expected: []sql.Row{{1, 1}, {2, 2}},
   311  			},
   312  			{
   313  				Query:    "/* client b */ commit",
   314  				Expected: []sql.Row{},
   315  			},
   316  			{
   317  				Query:    "/* client a */ select * from t order by x",
   318  				Expected: []sql.Row{{1, 1}, {2, 2}},
   319  			},
   320  			{
   321  				Query:    "/* client a */ rollback",
   322  				Expected: []sql.Row{},
   323  			},
   324  			{
   325  				Query:    "/* client a */ select * from t order by x",
   326  				Expected: []sql.Row{{1, 1}, {3, 3}},
   327  			},
   328  			{
   329  				Query:    "/* client a */ insert into t values (2, 2)",
   330  				Expected: []sql.Row{{types.NewOkResult(1)}},
   331  			},
   332  			{
   333  				Query:    "/* client b */ select * from t order by x",
   334  				Expected: []sql.Row{{1, 1}, {3, 3}},
   335  			},
   336  			{
   337  				Query:    "/* client a */ commit",
   338  				Expected: []sql.Row{},
   339  			},
   340  			{
   341  				Query:    "/* client b */ select * from t order by x",
   342  				Expected: []sql.Row{{1, 1}, {3, 3}},
   343  			},
   344  			{
   345  				Query:    "/* client b */ rollback",
   346  				Expected: []sql.Row{},
   347  			},
   348  			{
   349  				Query:    "/* client b */ select * from t order by x",
   350  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   351  			},
   352  		},
   353  	},
   354  	{
   355  		Name: "rollback to savepoint",
   356  		SetUpScript: []string{
   357  			"create table t (x int primary key, y int)",
   358  			"insert into t values (1, 1)",
   359  		},
   360  		Assertions: []ScriptTestAssertion{
   361  			{
   362  				Query:    "/* client a */ set autocommit = off",
   363  				Expected: []sql.Row{{}},
   364  			},
   365  			{
   366  				Query:    "/* client b */ set autocommit = off",
   367  				Expected: []sql.Row{{}},
   368  			},
   369  			{
   370  				Query:    "/* client a */ start transaction",
   371  				Expected: []sql.Row{},
   372  			},
   373  			{
   374  				Query:    "/* client b */ start transaction",
   375  				Expected: []sql.Row{},
   376  			},
   377  			{
   378  				Query:    "/* client a */ insert into t values (2, 2)",
   379  				Expected: []sql.Row{{types.NewOkResult(1)}},
   380  			},
   381  			{
   382  				Query:    "/* client b */ insert into t values (3, 3)",
   383  				Expected: []sql.Row{{types.NewOkResult(1)}},
   384  			},
   385  			{
   386  				Query:    "/* client a */ savepoint spa1",
   387  				Expected: []sql.Row{},
   388  			},
   389  			{
   390  				Query:    "/* client b */ savepoint spb1",
   391  				Expected: []sql.Row{},
   392  			},
   393  			{
   394  				Query:    "/* client a */ insert into t values (4, 4)",
   395  				Expected: []sql.Row{{types.NewOkResult(1)}},
   396  			},
   397  			{
   398  				Query:    "/* client b */ insert into t values (5, 5)",
   399  				Expected: []sql.Row{{types.NewOkResult(1)}},
   400  			},
   401  			{
   402  				Query:    "/* client a */ savepoint spa2",
   403  				Expected: []sql.Row{},
   404  			},
   405  			{
   406  				Query:    "/* client b */ savepoint spb2",
   407  				Expected: []sql.Row{},
   408  			},
   409  			{
   410  				Query:    "/* client a */ insert into t values (6, 6)",
   411  				Expected: []sql.Row{{types.NewOkResult(1)}},
   412  			},
   413  			{
   414  				Query:    "/* client b */ insert into t values (7, 7)",
   415  				Expected: []sql.Row{{types.NewOkResult(1)}},
   416  			},
   417  			{
   418  				Query:    "/* client a */ select * from t order by x",
   419  				Expected: []sql.Row{{1, 1}, {2, 2}, {4, 4}, {6, 6}},
   420  			},
   421  			{
   422  				Query:    "/* client b */ select * from t order by x",
   423  				Expected: []sql.Row{{1, 1}, {3, 3}, {5, 5}, {7, 7}},
   424  			},
   425  			{
   426  				Query:    "/* client a */ rollback to SPA2",
   427  				Expected: []sql.Row{},
   428  			},
   429  			{
   430  				Query:    "/* client b */ rollback to spB2",
   431  				Expected: []sql.Row{},
   432  			},
   433  			{
   434  				Query:    "/* client a */ select * from t order by x",
   435  				Expected: []sql.Row{{1, 1}, {2, 2}, {4, 4}},
   436  			},
   437  			{
   438  				Query:    "/* client b */ select * from t order by x",
   439  				Expected: []sql.Row{{1, 1}, {3, 3}, {5, 5}},
   440  			},
   441  			{
   442  				Query:    "/* client a */ rollback to sPa2",
   443  				Expected: []sql.Row{},
   444  			},
   445  			{
   446  				Query:    "/* client b */ rollback to Spb2",
   447  				Expected: []sql.Row{},
   448  			},
   449  			{
   450  				Query:    "/* client a */ select * from t order by x",
   451  				Expected: []sql.Row{{1, 1}, {2, 2}, {4, 4}},
   452  			},
   453  			{
   454  				Query:    "/* client b */ select * from t order by x",
   455  				Expected: []sql.Row{{1, 1}, {3, 3}, {5, 5}},
   456  			},
   457  			{
   458  				Query:    "/* client a */ rollback to spA1",
   459  				Expected: []sql.Row{},
   460  			},
   461  			{
   462  				Query:    "/* client b */ rollback to SPb1",
   463  				Expected: []sql.Row{},
   464  			},
   465  			{
   466  				Query:    "/* client a */ select * from t order by x",
   467  				Expected: []sql.Row{{1, 1}, {2, 2}},
   468  			},
   469  			{
   470  				Query:    "/* client b */ select * from t order by x",
   471  				Expected: []sql.Row{{1, 1}, {3, 3}},
   472  			},
   473  			{
   474  				Query:       "/* client a */ rollback to spa2",
   475  				ExpectedErr: sql.ErrSavepointDoesNotExist,
   476  			},
   477  			{
   478  				Query:       "/* client b */ rollback to spb2",
   479  				ExpectedErr: sql.ErrSavepointDoesNotExist,
   480  			},
   481  			{
   482  				Query:    "/* client a */ rollback to Spa1",
   483  				Expected: []sql.Row{},
   484  			},
   485  			{
   486  				Query:    "/* client b */ rollback to spB1",
   487  				Expected: []sql.Row{},
   488  			},
   489  			{
   490  				Query:    "/* client a */ select * from t order by x",
   491  				Expected: []sql.Row{{1, 1}, {2, 2}},
   492  			},
   493  			{
   494  				Query:    "/* client b */ select * from t order by x",
   495  				Expected: []sql.Row{{1, 1}, {3, 3}},
   496  			},
   497  			{
   498  				Query:    "/* client a */ rollback",
   499  				Expected: []sql.Row{},
   500  			},
   501  			{
   502  				Query:    "/* client b */ commit",
   503  				Expected: []sql.Row{},
   504  			},
   505  			{
   506  				Query:    "/* client a */ select * from t order by x",
   507  				Expected: []sql.Row{{1, 1}, {3, 3}},
   508  			},
   509  			{
   510  				Query:    "/* client b */ select * from t order by x",
   511  				Expected: []sql.Row{{1, 1}, {3, 3}},
   512  			},
   513  			{
   514  				Query:       "/* client a */ rollback to spa1",
   515  				ExpectedErr: sql.ErrSavepointDoesNotExist,
   516  			},
   517  			{
   518  				Query:       "/* client b */ rollback to spb1",
   519  				ExpectedErr: sql.ErrSavepointDoesNotExist,
   520  			},
   521  		},
   522  	},
   523  	{
   524  		Name: "release savepoint",
   525  		SetUpScript: []string{
   526  			"create table t (x int primary key, y int)",
   527  			"insert into t values (1, 1)",
   528  		},
   529  		Assertions: []ScriptTestAssertion{
   530  			{
   531  				Query:    "/* client a */ set autocommit = off",
   532  				Expected: []sql.Row{{}},
   533  			},
   534  			{
   535  				Query:    "/* client b */ set autocommit = off",
   536  				Expected: []sql.Row{{}},
   537  			},
   538  			{
   539  				Query:    "/* client a */ start transaction",
   540  				Expected: []sql.Row{},
   541  			},
   542  			{
   543  				Query:    "/* client b */ start transaction",
   544  				Expected: []sql.Row{},
   545  			},
   546  			{
   547  				Query:    "/* client a */ insert into t values (2, 2)",
   548  				Expected: []sql.Row{{types.NewOkResult(1)}},
   549  			},
   550  			{
   551  				Query:    "/* client b */ insert into t values (3, 3)",
   552  				Expected: []sql.Row{{types.NewOkResult(1)}},
   553  			},
   554  			{
   555  				Query:    "/* client a */ savepoint spa1",
   556  				Expected: []sql.Row{},
   557  			},
   558  			{
   559  				Query:    "/* client b */ savepoint spb1",
   560  				Expected: []sql.Row{},
   561  			},
   562  			{
   563  				Query:    "/* client a */ release savepoint Spa1",
   564  				Expected: []sql.Row{},
   565  			},
   566  			{
   567  				Query:    "/* client b */ release savepoint sPb1",
   568  				Expected: []sql.Row{},
   569  			},
   570  			{
   571  				Query:       "/* client a */ rollback to spa1",
   572  				ExpectedErr: sql.ErrSavepointDoesNotExist,
   573  			},
   574  			{
   575  				Query:       "/* client b */ rollback to spb1",
   576  				ExpectedErr: sql.ErrSavepointDoesNotExist,
   577  			},
   578  			{
   579  				Query:    "/* client a */ select * from t order by x",
   580  				Expected: []sql.Row{{1, 1}, {2, 2}},
   581  			},
   582  			{
   583  				Query:    "/* client b */ select * from t order by x",
   584  				Expected: []sql.Row{{1, 1}, {3, 3}},
   585  			},
   586  		},
   587  	},
   588  	{
   589  		Name: "overwrite savepoint",
   590  		SetUpScript: []string{
   591  			"create table t (x int primary key, y int)",
   592  			"insert into t values (1, 1)",
   593  		},
   594  		Assertions: []ScriptTestAssertion{
   595  			{
   596  				Query:    "/* client a */ start transaction",
   597  				Expected: []sql.Row{},
   598  			},
   599  			{
   600  				Query:    "/* client a */ insert into t values (2, 2)",
   601  				Expected: []sql.Row{{types.NewOkResult(1)}},
   602  			},
   603  			{
   604  				Query:    "/* client a */ savepoint spa1",
   605  				Expected: []sql.Row{},
   606  			},
   607  			{
   608  				Query:    "/* client a */ insert into t values (3, 3)",
   609  				Expected: []sql.Row{{types.NewOkResult(1)}},
   610  			},
   611  			{
   612  				Query:    "/* client a */ savepoint spa2",
   613  				Expected: []sql.Row{},
   614  			},
   615  			{
   616  				Query:    "/* client a */ insert into t values (4, 4)",
   617  				Expected: []sql.Row{{types.NewOkResult(1)}},
   618  			},
   619  			{
   620  				Query:    "/* client a */ savepoint SPA1",
   621  				Expected: []sql.Row{},
   622  			},
   623  			{
   624  				Query:    "/* client a */ insert into t values (5, 5)",
   625  				Expected: []sql.Row{{types.NewOkResult(1)}},
   626  			},
   627  			{
   628  				Query:    "/* client a */ select * from t order by x",
   629  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}},
   630  			},
   631  			{
   632  				Query:    "/* client a */ rollback to Spa1",
   633  				Expected: []sql.Row{},
   634  			},
   635  			{
   636  				Query:    "/* client a */ select * from t order by x",
   637  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {4, 4}},
   638  			},
   639  			{
   640  				Query:    "/* client a */ rollback to spa2",
   641  				Expected: []sql.Row{},
   642  			},
   643  			{
   644  				Query:    "/* client a */ select * from t order by x",
   645  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   646  			},
   647  			{
   648  				Query:       "/* client a */ rollback to spa1",
   649  				ExpectedErr: sql.ErrSavepointDoesNotExist,
   650  			},
   651  			{
   652  				Query:       "/* client a */ release savepoint spa1",
   653  				ExpectedErr: sql.ErrSavepointDoesNotExist,
   654  			},
   655  		},
   656  	},
   657  	{
   658  		Name: "Test AUTO INCREMENT with no autocommit",
   659  		SetUpScript: []string{
   660  			"CREATE table t (x int PRIMARY KEY AUTO_INCREMENT, y int);",
   661  			"CREATE table t2 (x int PRIMARY KEY AUTO_INCREMENT, y int);",
   662  			"CREATE table t3 (x int PRIMARY KEY AUTO_INCREMENT, y int);",
   663  			"insert into t (y) values (1);",
   664  			"insert into t2 values (10, 10);",
   665  		},
   666  		Assertions: []ScriptTestAssertion{
   667  			{
   668  				Query:    "/* client a */ set autocommit = off",
   669  				Expected: []sql.Row{{}},
   670  			},
   671  			{
   672  				Query:    "/* client b */ set autocommit = off",
   673  				Expected: []sql.Row{{}},
   674  			},
   675  			{
   676  				Query:    "/* client c */ set autocommit = off",
   677  				Expected: []sql.Row{{}},
   678  			},
   679  			// Client a starts by insert into t
   680  			{
   681  				Query:    "/* client a */ insert into t (y) values (2)",
   682  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 2}}},
   683  			},
   684  			{
   685  				Query:    "/* client b */ select * from t order by x",
   686  				Expected: []sql.Row{{1, 1}},
   687  			},
   688  			{
   689  				Query:    "/* client c*/ select * from t order by x",
   690  				Expected: []sql.Row{{1, 1}},
   691  			},
   692  			// Client b inserts into t
   693  			{
   694  				Query:    "/* client b */ insert into t (y) values (3)",
   695  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 3}}},
   696  			},
   697  			{
   698  				Query: "/* client a */ select * from t order by x",
   699  				Expected: []sql.Row{
   700  					{1, 1}, {2, 2},
   701  				},
   702  			},
   703  			{
   704  				Query: "/* client c */ select * from t order by x",
   705  				Expected: []sql.Row{
   706  					{1, 1},
   707  				},
   708  			},
   709  			// Client c inserts into t2
   710  			{
   711  				Query:    "/* client c */ insert into t2 (y) values (11)",
   712  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 11}}},
   713  			},
   714  			{
   715  				Query:    "/* client a */ select * from t2 order by x",
   716  				Expected: []sql.Row{{10, 10}},
   717  			},
   718  			{
   719  				Query:    "/* client b */ select * from t2 order by x",
   720  				Expected: []sql.Row{{10, 10}},
   721  			},
   722  			{
   723  				Query:    "/* client c */ select * from t2 order by x",
   724  				Expected: []sql.Row{{10, 10}, {11, 11}},
   725  			},
   726  			// Client a inserts into t2
   727  			{
   728  				Query:    "/* client a */ insert into t2 (y) values (12)",
   729  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 12}}},
   730  			},
   731  			{
   732  				Query:    "/* client a */ select * from t2 order by x",
   733  				Expected: []sql.Row{{10, 10}, {12, 12}},
   734  			},
   735  			{
   736  				Query:    "/* client b */ select * from t2 order by x",
   737  				Expected: []sql.Row{{10, 10}},
   738  			},
   739  			{
   740  				Query:    "/* client c */ select * from t2 order by x",
   741  				Expected: []sql.Row{{10, 10}, {11, 11}},
   742  			},
   743  			// Client a commits
   744  			{
   745  				Query:    "/* client a */ commit",
   746  				Expected: []sql.Row{},
   747  			},
   748  			{
   749  				Query:    "/* client b */ select * from t order by x",
   750  				Expected: []sql.Row{{1, 1}, {3, 3}},
   751  			},
   752  			{
   753  				Query:    "/* client b */ select * from t2 order by x",
   754  				Expected: []sql.Row{{10, 10}},
   755  			},
   756  			{
   757  				Query:    "/* client c */ select * from t2 order by x",
   758  				Expected: []sql.Row{{10, 10}, {11, 11}},
   759  			},
   760  			{
   761  				Query: "/* client c */ select * from t order by x",
   762  				Expected: []sql.Row{
   763  					{1, 1},
   764  				},
   765  			},
   766  			// Client b commits
   767  			{
   768  				Query:    "/* client b */ commit",
   769  				Expected: []sql.Row{},
   770  			},
   771  			{
   772  				Query:    "/* client a */ select * from t order by x",
   773  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   774  			},
   775  			{
   776  				Query:    "/* client a */ select * from t2 order by x",
   777  				Expected: []sql.Row{{10, 10}, {12, 12}},
   778  			},
   779  			{
   780  				Query:    "/* client c */ select * from t2 order by x",
   781  				Expected: []sql.Row{{10, 10}, {11, 11}},
   782  			},
   783  			{
   784  				Query:    "/* client c */ select * from t order by x",
   785  				Expected: []sql.Row{{1, 1}},
   786  			},
   787  			// Client c commits
   788  			{
   789  				Query:    "/* client c */ commit",
   790  				Expected: []sql.Row{},
   791  			},
   792  			{
   793  				Query:    "/* client a */ select * from t order by x",
   794  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   795  			},
   796  			{
   797  				Query:    "/* client a */ select * from t2 order by x",
   798  				Expected: []sql.Row{{10, 10}, {12, 12}},
   799  			},
   800  			{
   801  				Query:    "/* client b */ select * from t order by x",
   802  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   803  			},
   804  			{
   805  				Query:    "/* client b */ select * from t2 order by x",
   806  				Expected: []sql.Row{{10, 10}, {11, 11}, {12, 12}},
   807  			},
   808  			// Client a starts transactions
   809  			{
   810  				Query:    "/* client a */ start transaction",
   811  				Expected: []sql.Row{},
   812  			},
   813  			{
   814  				Query:    "/* client a */ select * from t order by x",
   815  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   816  			},
   817  			{
   818  				Query:    "/* client b */ select * from t order by x",
   819  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   820  			},
   821  			{
   822  				Query:    "/* client c */ select * from t order by x",
   823  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   824  			},
   825  			{
   826  				Query:    "/* client a */ select * from t2 order by x",
   827  				Expected: []sql.Row{{10, 10}, {11, 11}, {12, 12}},
   828  			},
   829  			{
   830  				Query:    "/* client b */ select * from t2 order by x",
   831  				Expected: []sql.Row{{10, 10}, {11, 11}, {12, 12}},
   832  			},
   833  			{
   834  				Query:    "/* client c */ select * from t2 order by x",
   835  				Expected: []sql.Row{{10, 10}, {11, 11}, {12, 12}},
   836  			},
   837  			// Client a does a skip ahead
   838  			{
   839  				Query:    "/* client a */ insert into t values (10, 10)",
   840  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 10}}},
   841  			},
   842  			{
   843  				Query:    "/* client b */ insert into t (y) values (11)",
   844  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 11}}},
   845  			},
   846  			// Client c skips ahead
   847  			{
   848  				Query:    "/* client c */ insert into t values (50, 50)",
   849  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 50}}},
   850  			},
   851  			{
   852  				Query:    "/* client b */ insert into t (y) values (51)",
   853  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 51}}},
   854  			},
   855  			{
   856  				Query:    "/* client a */ select * from t order by x",
   857  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {10, 10}},
   858  			},
   859  			{
   860  				Query:    "/* client b */ select * from t order by x",
   861  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {11, 11}, {51, 51}},
   862  			},
   863  			{
   864  				Query:    "/* client c */ select * from t order by x",
   865  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {50, 50}},
   866  			},
   867  			{
   868  				Query:    "/* client a */ commit",
   869  				Expected: []sql.Row{},
   870  			},
   871  			{
   872  				Query:    "/* client b */ commit",
   873  				Expected: []sql.Row{},
   874  			},
   875  			{
   876  				Query:    "/* client c */ commit",
   877  				Expected: []sql.Row{},
   878  			},
   879  			{
   880  				Query:    "/* client a */ select * from t order by x",
   881  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {10, 10}, {11, 11}, {50, 50}, {51, 51}},
   882  			},
   883  			{
   884  				Query:    "/* client b */ select * from t order by x",
   885  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {10, 10}, {11, 11}, {50, 50}, {51, 51}},
   886  			},
   887  			{
   888  				Query:    "/* client c */ select * from t order by x",
   889  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {10, 10}, {11, 11}, {50, 50}, {51, 51}},
   890  			},
   891  			// Client a does a simple insert to ensure merging worked
   892  			{
   893  				Query:    "/* client a */ insert into t values (NULL, 52)",
   894  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 52}}},
   895  			},
   896  			{
   897  				Query:    "/* client a */ select * from t order by x",
   898  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {10, 10}, {11, 11}, {50, 50}, {51, 51}, {52, 52}},
   899  			},
   900  		},
   901  	},
   902  	{
   903  		Name: "AUTO_INCREMENT transactions off",
   904  		SetUpScript: []string{
   905  			"CREATE table t2 (x int PRIMARY KEY AUTO_INCREMENT, y int);",
   906  			"insert into t2 (y) values (1);",
   907  		},
   908  		Assertions: []ScriptTestAssertion{
   909  			{
   910  				Query:    "/* client a */ insert into t2 (y) values (2)",
   911  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 2}}},
   912  			},
   913  			{
   914  				Query:    "/* client b */ select * from t2 order by x",
   915  				Expected: []sql.Row{{1, 1}, {2, 2}},
   916  			},
   917  			{
   918  				Query:    "/* client b */ insert into t2 (y) values (3)",
   919  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 3}}},
   920  			},
   921  			{
   922  				Query:    "/* client a */ select * from t2 order by x",
   923  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   924  			},
   925  			{
   926  				Query:    "/* client a */ alter table t2 modify column x int",
   927  				Expected: []sql.Row{{types.OkResult{RowsAffected: 0, InsertID: 0}}},
   928  			},
   929  			{
   930  				Query:       "/* client a */ INSERT INTO t2 values (NULL, 3)",
   931  				ExpectedErr: sql.ErrInsertIntoNonNullableProvidedNull,
   932  			},
   933  			{
   934  				Query:    "/* client a */ DROP TABLE t2",
   935  				Expected: []sql.Row{{types.OkResult{RowsAffected: 0, InsertID: 0}}},
   936  			},
   937  			{
   938  				Query:    "/* client a */ CREATE table t2 (x int PRIMARY KEY AUTO_INCREMENT, y int)",
   939  				Expected: []sql.Row{{types.OkResult{RowsAffected: 0, InsertID: 0}}},
   940  			},
   941  			{
   942  				Query:    "/* client a */ insert into t2 (y) values (4)",
   943  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 1}}},
   944  			},
   945  			{
   946  				Query:    "/* client a */ SELECT * FROM t2",
   947  				Expected: []sql.Row{{1, 4}},
   948  			},
   949  		},
   950  	},
   951  	{
   952  		Name: "READ ONLY Transactions",
   953  		SetUpScript: []string{
   954  			"create table t2 (pk int primary key, val int)",
   955  			"insert into t2 values (0,0)",
   956  			"commit",
   957  		},
   958  		Assertions: []ScriptTestAssertion{
   959  			{
   960  				Query:    "/* client a */ set autocommit = off",
   961  				Expected: []sql.Row{{}},
   962  			},
   963  			{
   964  				Query:    "/* client a */ create temporary table tmp(pk int primary key)",
   965  				Expected: []sql.Row{{types.NewOkResult(0)}},
   966  			},
   967  			{
   968  				Query:    "/* client a */  START TRANSACTION READ ONLY",
   969  				Expected: []sql.Row{},
   970  			},
   971  			{
   972  				Query:    "/* client a */ INSERT INTO tmp VALUES (1)",
   973  				Expected: []sql.Row{{types.NewOkResult(1)}},
   974  			},
   975  			{
   976  				Query:       "/* client a */ insert into t2 values (1, 1)",
   977  				ExpectedErr: sql.ErrReadOnlyTransaction,
   978  			},
   979  			{
   980  				Query:       "/* client a */ insert into t2 values (2, 2)",
   981  				ExpectedErr: sql.ErrReadOnlyTransaction,
   982  			},
   983  			{
   984  				Query:       "/* client a */ delete from t2 where pk = 0",
   985  				ExpectedErr: sql.ErrReadOnlyTransaction,
   986  			},
   987  			{
   988  
   989  				Query:    "/* client a */ alter table t2 add val2 int",
   990  				Expected: []sql.Row{{types.NewOkResult(0)}},
   991  			},
   992  			{
   993  				Query:    "/* client a */ select * from t2",
   994  				Expected: []sql.Row{{0, 0, nil}},
   995  			},
   996  			{
   997  				Query:       "/* client a */ create temporary table tmp2(pk int primary key)",
   998  				ExpectedErr: sql.ErrReadOnlyTransaction,
   999  			},
  1000  			{
  1001  				Query:    "/* client a */ COMMIT",
  1002  				Expected: []sql.Row{},
  1003  			},
  1004  			{
  1005  				Query:    "/* client b */ START TRANSACTION READ ONLY",
  1006  				Expected: []sql.Row{},
  1007  			},
  1008  			{
  1009  				Query:    "/* client b */ SELECT * FROM t2",
  1010  				Expected: []sql.Row{{0, 0, nil}},
  1011  			},
  1012  		},
  1013  	},
  1014  	{
  1015  		Name: "Insert error with auto commit off",
  1016  		SetUpScript: []string{
  1017  			"create table t1 (pk int primary key, val int)",
  1018  			"insert into t1 values (0,0)",
  1019  		},
  1020  		Assertions: []ScriptTestAssertion{
  1021  			{
  1022  				Query:            "/* client a */ set autocommit = off",
  1023  				SkipResultsCheck: true,
  1024  			},
  1025  			{
  1026  				Query:            "/* client b */ set autocommit = off",
  1027  				SkipResultsCheck: true,
  1028  			},
  1029  			{
  1030  				Query:    "/* client a */ insert into t1 values (1, 1)",
  1031  				Expected: []sql.Row{{types.NewOkResult(1)}},
  1032  			},
  1033  			{
  1034  				Query:       "/* client a */ insert into t1 values (1, 2)",
  1035  				ExpectedErr: sql.ErrPrimaryKeyViolation,
  1036  			},
  1037  			{
  1038  				Query:    "/* client a */ insert into t1 values (2, 2)",
  1039  				Expected: []sql.Row{{types.NewOkResult(1)}},
  1040  			},
  1041  			{
  1042  				Query:    "/* client a */ select * from t1 order by pk",
  1043  				Expected: []sql.Row{{0, 0}, {1, 1}, {2, 2}},
  1044  			},
  1045  			{
  1046  				Query:    "/* client b */ select * from t1 order by pk",
  1047  				Expected: []sql.Row{{0, 0}},
  1048  			},
  1049  			{
  1050  				Query:            "/* client a */ commit",
  1051  				SkipResultsCheck: true,
  1052  			},
  1053  			{
  1054  				Query:            "/* client b */ start transaction",
  1055  				SkipResultsCheck: true,
  1056  			},
  1057  			{
  1058  				Query:    "/* client b */ select * from t1 order by pk",
  1059  				Expected: []sql.Row{{0, 0}, {1, 1}, {2, 2}},
  1060  			},
  1061  			{
  1062  				Query:    "/* client a */ select * from t1 order by pk",
  1063  				Expected: []sql.Row{{0, 0}, {1, 1}, {2, 2}},
  1064  			},
  1065  		},
  1066  	},
  1067  }