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

     1  // Copyright 2020-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  	"time"
    19  
    20  	"github.com/dolthub/go-mysql-server/sql"
    21  	"github.com/dolthub/go-mysql-server/sql/plan"
    22  	"github.com/dolthub/go-mysql-server/sql/types"
    23  
    24  	"github.com/dolthub/vitess/go/mysql"
    25  )
    26  
    27  var UpdateTests = []WriteQueryTest{
    28  	{
    29  		WriteQuery:          "UPDATE mytable SET s = 'updated';",
    30  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
    31  		SelectQuery:         "SELECT * FROM mytable;",
    32  		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}},
    33  	},
    34  	{
    35  		WriteQuery:          "UPDATE mytable SET S = 'updated';",
    36  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
    37  		SelectQuery:         "SELECT * FROM mytable;",
    38  		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}},
    39  	},
    40  	{
    41  		WriteQuery:          "UPDATE mytable SET s = 'updated' WHERE i > 9999;",
    42  		ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}},
    43  		SelectQuery:         "SELECT * FROM mytable;",
    44  		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}},
    45  	},
    46  	{
    47  		WriteQuery:          "UPDATE mytable SET s = 'updated' WHERE i = 1;",
    48  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
    49  		SelectQuery:         "SELECT * FROM mytable;",
    50  		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "second row"}, {int64(3), "third row"}},
    51  	},
    52  	{
    53  		WriteQuery:          "UPDATE mytable SET s = 'updated' WHERE i <> 9999;",
    54  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
    55  		SelectQuery:         "SELECT * FROM mytable;",
    56  		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}},
    57  	},
    58  	{
    59  		WriteQuery:          "UPDATE floattable SET f32 = f32 + f32, f64 = f32 * f64 WHERE i = 2;",
    60  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
    61  		SelectQuery:         "SELECT * FROM floattable WHERE i = 2;",
    62  		ExpectedSelect:      []sql.Row{{int64(2), float32(3.0), float64(4.5)}},
    63  	},
    64  	{
    65  		WriteQuery:          "UPDATE floattable SET f32 = 5, f32 = 4 WHERE i = 1;",
    66  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
    67  		SelectQuery:         "SELECT f32 FROM floattable WHERE i = 1;",
    68  		ExpectedSelect:      []sql.Row{{float32(4.0)}},
    69  	},
    70  	{
    71  		WriteQuery:          "UPDATE mytable SET s = 'first row' WHERE i = 1;",
    72  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 0)}},
    73  		SelectQuery:         "SELECT * FROM mytable;",
    74  		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}},
    75  	},
    76  	{
    77  		WriteQuery:          "UPDATE niltable SET b = NULL WHERE f IS NULL;",
    78  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 2)}},
    79  		SelectQuery:         "SELECT i,b FROM niltable WHERE f IS NULL;",
    80  		ExpectedSelect:      []sql.Row{{int64(1), nil}, {int64(2), nil}, {int64(3), nil}},
    81  	},
    82  	{
    83  		WriteQuery:          "UPDATE mytable SET s = 'updated' ORDER BY i ASC LIMIT 2;",
    84  		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
    85  		SelectQuery:         "SELECT * FROM mytable;",
    86  		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "third row"}},
    87  	},
    88  	{
    89  		WriteQuery:          "UPDATE mytable SET s = 'updated' ORDER BY i DESC LIMIT 2;",
    90  		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
    91  		SelectQuery:         "SELECT * FROM mytable;",
    92  		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "updated"}, {int64(3), "updated"}},
    93  	},
    94  	{
    95  		WriteQuery:          "UPDATE mytable SET s = 'updated' ORDER BY i LIMIT 1 OFFSET 1;",
    96  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
    97  		SelectQuery:         "SELECT * FROM mytable;",
    98  		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "updated"}, {int64(3), "third row"}},
    99  	},
   100  	{
   101  		WriteQuery:          "UPDATE mytable SET s = 'updated';",
   102  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
   103  		SelectQuery:         "SELECT * FROM mytable;",
   104  		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}},
   105  	},
   106  	{
   107  		WriteQuery:          "UPDATE mytable SET s = _binary 'updated' WHERE i = 3;",
   108  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   109  		SelectQuery:         "SELECT * FROM mytable;",
   110  		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "updated"}},
   111  	},
   112  	{
   113  		WriteQuery:          "UPDATE typestable SET ti = '2020-03-06 00:00:00';",
   114  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   115  		SelectQuery:         "SELECT * FROM typestable;",
   116  		ExpectedSelect: []sql.Row{{
   117  			int64(1),
   118  			int8(2),
   119  			int16(3),
   120  			int32(4),
   121  			int64(5),
   122  			uint8(6),
   123  			uint16(7),
   124  			uint32(8),
   125  			uint64(9),
   126  			float32(10),
   127  			float64(11),
   128  			sql.MustConvert(types.Timestamp.Convert("2020-03-06 00:00:00")),
   129  			sql.MustConvert(types.Date.Convert("2019-12-31")),
   130  			"fourteen",
   131  			0,
   132  			nil,
   133  			nil,
   134  			"", ""}},
   135  	},
   136  	{
   137  		WriteQuery:          "UPDATE typestable SET ti = '2020-03-06 00:00:00', da = '2020-03-06';",
   138  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   139  		SelectQuery:         "SELECT * FROM typestable;",
   140  		ExpectedSelect: []sql.Row{{
   141  			int64(1),
   142  			int8(2),
   143  			int16(3),
   144  			int32(4),
   145  			int64(5),
   146  			uint8(6),
   147  			uint16(7),
   148  			uint32(8),
   149  			uint64(9),
   150  			float32(10),
   151  			float64(11),
   152  			sql.MustConvert(types.Timestamp.Convert("2020-03-06 00:00:00")),
   153  			sql.MustConvert(types.Date.Convert("2020-03-06")),
   154  			"fourteen",
   155  			0,
   156  			nil,
   157  			nil,
   158  			"", ""}},
   159  	},
   160  	{
   161  		SkipServerEngine:    true, // datetime returned is non-zero over the wire
   162  		WriteQuery:          "UPDATE typestable SET da = '0000-00-00', ti = '0000-00-00 00:00:00';",
   163  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   164  		SelectQuery:         "SELECT * FROM typestable;",
   165  		ExpectedSelect: []sql.Row{{
   166  			int64(1),
   167  			int8(2),
   168  			int16(3),
   169  			int32(4),
   170  			int64(5),
   171  			uint8(6),
   172  			uint16(7),
   173  			uint32(8),
   174  			uint64(9),
   175  			float32(10),
   176  			float64(11),
   177  			types.Timestamp.Zero(),
   178  			types.Date.Zero(),
   179  			"fourteen",
   180  			0,
   181  			nil,
   182  			nil,
   183  			"", ""}},
   184  	},
   185  	{
   186  		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET two_pk.c1 = two_pk.c1 + 1`,
   187  		ExpectedWriteResult: []sql.Row{{newUpdateResult(4, 4)}},
   188  		SelectQuery:         "SELECT * FROM two_pk;",
   189  		ExpectedSelect: []sql.Row{
   190  			sql.NewRow(0, 0, 1, 1, 2, 3, 4),
   191  			sql.NewRow(0, 1, 11, 11, 12, 13, 14),
   192  			sql.NewRow(1, 0, 21, 21, 22, 23, 24),
   193  			sql.NewRow(1, 1, 31, 31, 32, 33, 34),
   194  		},
   195  	},
   196  	{
   197  		WriteQuery:          "UPDATE mytable INNER JOIN one_pk ON mytable.i = one_pk.c5 SET mytable.i = mytable.i * 10",
   198  		ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}},
   199  		SelectQuery:         "SELECT * FROM mytable",
   200  		ExpectedSelect: []sql.Row{
   201  			sql.NewRow(int64(1), "first row"),
   202  			sql.NewRow(int64(2), "second row"),
   203  			sql.NewRow(int64(3), "third row"),
   204  		},
   205  	},
   206  	{
   207  		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET two_pk.c1 = two_pk.c1 + 1 WHERE one_pk.c5 < 10`,
   208  		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
   209  		SelectQuery:         "SELECT * FROM two_pk;",
   210  		ExpectedSelect: []sql.Row{
   211  			sql.NewRow(0, 0, 1, 1, 2, 3, 4),
   212  			sql.NewRow(0, 1, 11, 11, 12, 13, 14),
   213  			sql.NewRow(1, 0, 20, 21, 22, 23, 24),
   214  			sql.NewRow(1, 1, 30, 31, 32, 33, 34),
   215  		},
   216  	},
   217  	{
   218  		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 INNER JOIN othertable on othertable.i2 = two_pk.pk2 SET one_pk.c1 = one_pk.c1 + 1`,
   219  		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
   220  		SelectQuery:         "SELECT * FROM one_pk;",
   221  		ExpectedSelect: []sql.Row{
   222  			sql.NewRow(0, 1, 1, 2, 3, 4),
   223  			sql.NewRow(1, 11, 11, 12, 13, 14),
   224  			sql.NewRow(2, 20, 21, 22, 23, 24),
   225  			sql.NewRow(3, 30, 31, 32, 33, 34),
   226  		},
   227  	},
   228  	{
   229  		WriteQuery:          `UPDATE one_pk INNER JOIN (SELECT * FROM two_pk order by pk1, pk2) as t2 on one_pk.pk = t2.pk1 SET one_pk.c1 = t2.c1 + 1 where one_pk.pk < 1`,
   230  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   231  		SelectQuery:         "SELECT * FROM one_pk where pk < 1",
   232  		ExpectedSelect: []sql.Row{
   233  			sql.NewRow(0, 1, 1, 2, 3, 4),
   234  		},
   235  	},
   236  	{
   237  		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1`,
   238  		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
   239  		SelectQuery:         "SELECT * FROM one_pk;",
   240  		ExpectedSelect: []sql.Row{
   241  			sql.NewRow(0, 1, 1, 2, 3, 4),
   242  			sql.NewRow(1, 11, 11, 12, 13, 14),
   243  			sql.NewRow(2, 20, 21, 22, 23, 24),
   244  			sql.NewRow(3, 30, 31, 32, 33, 34),
   245  		},
   246  	},
   247  	{
   248  		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1, one_pk.c2 = one_pk.c2 + 1 ORDER BY one_pk.pk`,
   249  		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
   250  		SelectQuery:         "SELECT * FROM one_pk;",
   251  		ExpectedSelect: []sql.Row{
   252  			sql.NewRow(0, 1, 2, 2, 3, 4),
   253  			sql.NewRow(1, 11, 12, 12, 13, 14),
   254  			sql.NewRow(2, 20, 21, 22, 23, 24),
   255  			sql.NewRow(3, 30, 31, 32, 33, 34),
   256  		},
   257  	},
   258  	{
   259  		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1, two_pk.c1 = two_pk.c2 + 1`,
   260  		ExpectedWriteResult: []sql.Row{{newUpdateResult(8, 6)}}, // TODO: Should be matched = 6
   261  		SelectQuery:         "SELECT * FROM two_pk;",
   262  		ExpectedSelect: []sql.Row{
   263  			sql.NewRow(0, 0, 2, 1, 2, 3, 4),
   264  			sql.NewRow(0, 1, 12, 11, 12, 13, 14),
   265  			sql.NewRow(1, 0, 22, 21, 22, 23, 24),
   266  			sql.NewRow(1, 1, 32, 31, 32, 33, 34),
   267  		},
   268  	},
   269  	{
   270  		WriteQuery:          `update mytable h join mytable on h.i = mytable.i and h.s <> mytable.s set h.i = mytable.i+1;`,
   271  		ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}},
   272  		SelectQuery:         "select * from mytable",
   273  		ExpectedSelect:      []sql.Row{{1, "first row"}, {2, "second row"}, {3, "third row"}},
   274  	},
   275  	{
   276  		WriteQuery:          `UPDATE othertable CROSS JOIN tabletest set othertable.i2 = othertable.i2 * 10`, // cross join
   277  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
   278  		SelectQuery:         "SELECT * FROM othertable order by i2",
   279  		ExpectedSelect: []sql.Row{
   280  			sql.NewRow("third", 10),
   281  			sql.NewRow("second", 20),
   282  			sql.NewRow("first", 30),
   283  		},
   284  	},
   285  	{
   286  		WriteQuery:          `UPDATE tabletest cross join tabletest as t2 set tabletest.i = tabletest.i * 10`, // cross join
   287  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
   288  		SelectQuery:         "SELECT * FROM tabletest order by i",
   289  		ExpectedSelect: []sql.Row{
   290  			sql.NewRow(10, "first row"),
   291  			sql.NewRow(20, "second row"),
   292  			sql.NewRow(30, "third row"),
   293  		},
   294  	},
   295  	{
   296  		WriteQuery:          `UPDATE othertable cross join tabletest set tabletest.i = tabletest.i * 10`, // cross join
   297  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
   298  		SelectQuery:         "SELECT * FROM tabletest order by i",
   299  		ExpectedSelect: []sql.Row{
   300  			sql.NewRow(10, "first row"),
   301  			sql.NewRow(20, "second row"),
   302  			sql.NewRow(30, "third row"),
   303  		},
   304  	},
   305  	{
   306  		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 INNER JOIN two_pk a1 on one_pk.pk = two_pk.pk2 SET two_pk.c1 = two_pk.c1 + 1`, // cross join
   307  		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
   308  		SelectQuery:         "SELECT * FROM two_pk order by pk1 ASC, pk2 ASC;",
   309  		ExpectedSelect: []sql.Row{
   310  			sql.NewRow(0, 0, 1, 1, 2, 3, 4),
   311  			sql.NewRow(0, 1, 10, 11, 12, 13, 14),
   312  			sql.NewRow(1, 0, 20, 21, 22, 23, 24),
   313  			sql.NewRow(1, 1, 31, 31, 32, 33, 34),
   314  		},
   315  	},
   316  	{
   317  		WriteQuery:          `UPDATE othertable INNER JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`, // cross join
   318  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   319  		SelectQuery:         "SELECT * FROM othertable order by i2",
   320  		ExpectedSelect: []sql.Row{
   321  			sql.NewRow("third", 1),
   322  			sql.NewRow("second", 2),
   323  			sql.NewRow("fourth", 3),
   324  		},
   325  	},
   326  	{
   327  		WriteQuery:          `UPDATE tabletest cross join tabletest as t2 set t2.i = t2.i * 10`, // cross join
   328  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
   329  		SelectQuery:         "SELECT * FROM tabletest order by i",
   330  		ExpectedSelect: []sql.Row{
   331  			sql.NewRow(10, "first row"),
   332  			sql.NewRow(20, "second row"),
   333  			sql.NewRow(30, "third row"),
   334  		},
   335  	},
   336  	{
   337  		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`, // left join
   338  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
   339  		SelectQuery:         "SELECT * FROM othertable order by i2",
   340  		ExpectedSelect: []sql.Row{
   341  			sql.NewRow("fourth", 1),
   342  			sql.NewRow("fourth", 2),
   343  			sql.NewRow("fourth", 3),
   344  		},
   345  	},
   346  	{
   347  		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET tabletest.s = 'fourth row', tabletest.i = tabletest.i + 1`, // left join
   348  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   349  		SelectQuery:         "SELECT * FROM tabletest order by i",
   350  		ExpectedSelect: []sql.Row{
   351  			sql.NewRow(1, "first row"),
   352  			sql.NewRow(2, "second row"),
   353  			sql.NewRow(4, "fourth row"),
   354  		},
   355  	},
   356  	{
   357  		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest t3 on othertable.i2=3 and t3.i=3 SET t3.s = 'fourth row', t3.i = t3.i + 1`, // left join
   358  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   359  		SelectQuery:         "SELECT * FROM tabletest order by i",
   360  		ExpectedSelect: []sql.Row{
   361  			sql.NewRow(1, "first row"),
   362  			sql.NewRow(2, "second row"),
   363  			sql.NewRow(4, "fourth row"),
   364  		},
   365  	},
   366  	{
   367  		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 LEFT JOIN one_pk on othertable.i2 = one_pk.pk SET one_pk.c1 = one_pk.c1 + 1`, // left join
   368  		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
   369  		SelectQuery:         "SELECT * FROM one_pk order by pk",
   370  		ExpectedSelect: []sql.Row{
   371  			sql.NewRow(0, 0, 1, 2, 3, 4),
   372  			sql.NewRow(1, 11, 11, 12, 13, 14),
   373  			sql.NewRow(2, 21, 21, 22, 23, 24),
   374  			sql.NewRow(3, 31, 31, 32, 33, 34),
   375  		},
   376  	},
   377  	{
   378  		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 LEFT JOIN one_pk on othertable.i2 = one_pk.pk SET one_pk.c1 = one_pk.c1 + 1 where one_pk.pk > 4`, // left join
   379  		ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}},
   380  		SelectQuery:         "SELECT * FROM one_pk order by pk",
   381  		ExpectedSelect: []sql.Row{
   382  			sql.NewRow(0, 0, 1, 2, 3, 4),
   383  			sql.NewRow(1, 10, 11, 12, 13, 14),
   384  			sql.NewRow(2, 20, 21, 22, 23, 24),
   385  			sql.NewRow(3, 30, 31, 32, 33, 34),
   386  		},
   387  	},
   388  	{
   389  		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 LEFT JOIN one_pk on othertable.i2 = 1 and one_pk.pk = 1 SET one_pk.c1 = one_pk.c1 + 1`, // left join
   390  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   391  		SelectQuery:         "SELECT * FROM one_pk order by pk",
   392  		ExpectedSelect: []sql.Row{
   393  			sql.NewRow(0, 0, 1, 2, 3, 4),
   394  			sql.NewRow(1, 11, 11, 12, 13, 14),
   395  			sql.NewRow(2, 20, 21, 22, 23, 24),
   396  			sql.NewRow(3, 30, 31, 32, 33, 34),
   397  		},
   398  	},
   399  	{
   400  		WriteQuery:          `UPDATE othertable RIGHT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`, // right join
   401  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   402  		SelectQuery:         "SELECT * FROM othertable order by i2",
   403  		ExpectedSelect: []sql.Row{
   404  			sql.NewRow("third", 1),
   405  			sql.NewRow("second", 2),
   406  			sql.NewRow("fourth", 3),
   407  		},
   408  	},
   409  	{
   410  		WriteQuery:          `UPDATE othertable RIGHT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.i2 = othertable.i2 + 1`, // right join
   411  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   412  		SelectQuery:         "SELECT * FROM othertable order by i2",
   413  		ExpectedSelect: []sql.Row{
   414  			sql.NewRow("third", 1),
   415  			sql.NewRow("second", 2),
   416  			sql.NewRow("first", 4),
   417  		},
   418  	},
   419  	{
   420  		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=tabletest.i RIGHT JOIN one_pk on othertable.i2 = 1 and one_pk.pk = 1 SET tabletest.s = 'updated';`, // right join
   421  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   422  		SelectQuery:         "SELECT * FROM tabletest order by i",
   423  		ExpectedSelect: []sql.Row{
   424  			sql.NewRow(1, "updated"),
   425  			sql.NewRow(2, "second row"),
   426  			sql.NewRow(3, "third row"),
   427  		},
   428  	},
   429  	{
   430  		WriteQuery:          "with t (n) as (select (1) from dual) UPDATE mytable set s = concat('updated ', i) where i in (select n from t)",
   431  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   432  		SelectQuery:         "select * from mytable order by i",
   433  		ExpectedSelect: []sql.Row{
   434  			sql.NewRow(1, "updated 1"),
   435  			sql.NewRow(2, "second row"),
   436  			sql.NewRow(3, "third row"),
   437  		},
   438  	},
   439  	{
   440  		WriteQuery:          "with recursive t (n) as (select (1) from dual union all select n + 1 from t where n < 2) UPDATE mytable set s = concat('updated ', i) where i in (select n from t)",
   441  		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
   442  		SelectQuery:         "select * from mytable order by i",
   443  		ExpectedSelect: []sql.Row{
   444  			sql.NewRow(1, "updated 1"),
   445  			sql.NewRow(2, "updated 2"),
   446  			sql.NewRow(3, "third row"),
   447  		},
   448  	},
   449  }
   450  
   451  var SpatialUpdateTests = []WriteQueryTest{
   452  	{
   453  		WriteQuery:          "UPDATE point_table SET p = point(123.456,789);",
   454  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   455  		SelectQuery:         "SELECT * FROM point_table;",
   456  		ExpectedSelect:      []sql.Row{{int64(5), types.Point{X: 123.456, Y: 789}}},
   457  	},
   458  	{
   459  		WriteQuery:          "UPDATE line_table SET l = linestring(point(1.2,3.4),point(5.6,7.8));",
   460  		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
   461  		SelectQuery:         "SELECT * FROM line_table;",
   462  		ExpectedSelect:      []sql.Row{{int64(0), types.LineString{Points: []types.Point{{X: 1.2, Y: 3.4}, {X: 5.6, Y: 7.8}}}}, {int64(1), types.LineString{Points: []types.Point{{X: 1.2, Y: 3.4}, {X: 5.6, Y: 7.8}}}}},
   463  	},
   464  	{
   465  		WriteQuery:          "UPDATE polygon_table SET p = polygon(linestring(point(1,1),point(1,-1),point(-1,-1),point(-1,1),point(1,1)));",
   466  		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
   467  		SelectQuery:         "SELECT * FROM polygon_table;",
   468  		ExpectedSelect: []sql.Row{
   469  			{int64(0), types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: -1}, {X: -1, Y: -1}, {X: -1, Y: 1}, {X: 1, Y: 1}}}}}},
   470  			{int64(1), types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: -1}, {X: -1, Y: -1}, {X: -1, Y: 1}, {X: 1, Y: 1}}}}}},
   471  		},
   472  	},
   473  }
   474  
   475  // These tests return the correct select query answer but the wrong write result.
   476  var SkippedUpdateTests = []WriteQueryTest{
   477  	{
   478  		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1, two_pk.c1 = two_pk.c2 + 1`,
   479  		ExpectedWriteResult: []sql.Row{{newUpdateResult(8, 6)}}, // TODO: Should be matched = 6
   480  		SelectQuery:         "SELECT * FROM two_pk;",
   481  		ExpectedSelect: []sql.Row{
   482  			sql.NewRow(0, 0, 2, 1, 2, 3, 4),
   483  			sql.NewRow(0, 1, 12, 11, 12, 13, 14),
   484  			sql.NewRow(1, 0, 22, 21, 22, 23, 24),
   485  			sql.NewRow(1, 1, 32, 31, 32, 33, 34),
   486  		},
   487  	},
   488  	{
   489  		WriteQuery:          `UPDATE othertable INNER JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`,
   490  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
   491  		SelectQuery:         "SELECT * FROM othertable;",
   492  		ExpectedSelect: []sql.Row{
   493  			sql.NewRow("third", 1),
   494  			sql.NewRow("second", 2),
   495  			sql.NewRow("fourth", 3),
   496  		},
   497  	},
   498  }
   499  
   500  func newUpdateResult(matched, updated int) types.OkResult {
   501  	return types.OkResult{
   502  		RowsAffected: uint64(updated),
   503  		Info:         plan.UpdateInfo{matched, updated, 0},
   504  	}
   505  }
   506  
   507  var GenericUpdateErrorTests = []GenericErrorQueryTest{
   508  	{
   509  		Name:  "invalid table",
   510  		Query: "UPDATE doesnotexist SET i = 0;",
   511  	},
   512  	{
   513  		Name:  "missing binding",
   514  		Query: "UPDATE mytable SET i = ?;",
   515  	},
   516  	{
   517  		Name:  "wrong number of columns",
   518  		Query: `UPDATE mytable SET i = ("one", "two");`,
   519  	},
   520  	{
   521  		Name:  "type mismatch: string -> int",
   522  		Query: `UPDATE mytable SET i = "one"`,
   523  	},
   524  	{
   525  		Name:  "type mismatch: string -> float",
   526  		Query: `UPDATE floattable SET f64 = "one"`,
   527  	},
   528  	{
   529  		Name:  "type mismatch: string -> uint",
   530  		Query: `UPDATE typestable SET f64 = "one"`,
   531  	},
   532  	{
   533  		Name:  "invalid column set",
   534  		Query: "UPDATE mytable SET z = 0;",
   535  	},
   536  	{
   537  		Name:  "invalid column set value",
   538  		Query: "UPDATE mytable SET i = z;",
   539  	},
   540  	{
   541  		Name:  "invalid column where",
   542  		Query: "UPDATE mytable SET s = 'hi' WHERE z = 1;",
   543  	},
   544  	{
   545  		Name:  "invalid column order by",
   546  		Query: "UPDATE mytable SET s = 'hi' ORDER BY z;",
   547  	},
   548  	{
   549  		Name:  "negative limit",
   550  		Query: "UPDATE mytable SET s = 'hi' LIMIT -1;",
   551  	},
   552  	{
   553  		Name:  "negative offset",
   554  		Query: "UPDATE mytable SET s = 'hi' LIMIT 1 OFFSET -1;",
   555  	},
   556  	{
   557  		Name:  "set null on non-nullable",
   558  		Query: "UPDATE mytable SET s = NULL;",
   559  	},
   560  	{
   561  		Name:  "targets join",
   562  		Query: "UPDATE mytable one, mytable two SET s = NULL;",
   563  	},
   564  	{
   565  		Name:  "targets subquery alias",
   566  		Query: "UPDATE (SELECT * FROM mytable) mytable SET s = NULL;",
   567  	},
   568  }
   569  
   570  var UpdateIgnoreTests = []WriteQueryTest{
   571  	{
   572  		WriteQuery:          "UPDATE IGNORE mytable SET i = 2 where i = 1",
   573  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 0)}},
   574  		SelectQuery:         "SELECT * FROM mytable order by i",
   575  		ExpectedSelect: []sql.Row{
   576  			sql.NewRow(1, "first row"),
   577  			sql.NewRow(2, "second row"),
   578  			sql.NewRow(3, "third row"),
   579  		},
   580  	},
   581  	{
   582  		WriteQuery:          "UPDATE IGNORE mytable SET i = i+1 where i = 1",
   583  		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 0)}},
   584  		SelectQuery:         "SELECT * FROM mytable order by i",
   585  		ExpectedSelect: []sql.Row{
   586  			sql.NewRow(1, "first row"),
   587  			sql.NewRow(2, "second row"),
   588  			sql.NewRow(3, "third row"),
   589  		},
   590  	},
   591  }
   592  
   593  var UpdateIgnoreScripts = []ScriptTest{
   594  	{
   595  		Name: "UPDATE IGNORE with primary keys and indexes",
   596  		SetUpScript: []string{
   597  			"CREATE TABLE pkTable(pk int, val int, primary key(pk, val))",
   598  			"CREATE TABLE idxTable(pk int primary key, val int UNIQUE)",
   599  			"INSERT INTO pkTable VALUES (1, 1), (2, 2), (3, 3)",
   600  			"INSERT INTO idxTable VALUES (1, 1), (2, 2), (3, 3)",
   601  		},
   602  		Assertions: []ScriptTestAssertion{
   603  			{
   604  				Query:           "UPDATE IGNORE pkTable set pk = pk + 1, val = val + 1",
   605  				Expected:        []sql.Row{{newUpdateResult(3, 1)}},
   606  				ExpectedWarning: mysql.ERDupEntry,
   607  			},
   608  			{
   609  				Query:    "SELECT * FROM pkTable order by pk",
   610  				Expected: []sql.Row{{1, 1}, {2, 2}, {4, 4}},
   611  			},
   612  			{
   613  				Query:           "UPDATE IGNORE idxTable set val = val + 1",
   614  				Expected:        []sql.Row{{newUpdateResult(3, 1)}},
   615  				ExpectedWarning: mysql.ERDupEntry,
   616  			},
   617  			{
   618  				Query:    "SELECT * FROM idxTable order by pk",
   619  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 4}},
   620  			},
   621  			{
   622  				Query:    "UPDATE IGNORE pkTable set val = val + 1 where pk = 2",
   623  				Expected: []sql.Row{{newUpdateResult(1, 1)}},
   624  			},
   625  			{
   626  				Query:    "SELECT * FROM pkTable order by pk",
   627  				Expected: []sql.Row{{1, 1}, {2, 3}, {4, 4}},
   628  			},
   629  			{
   630  				Query:           "UPDATE IGNORE pkTable SET pk = NULL",
   631  				Expected:        []sql.Row{{newUpdateResult(3, 3)}},
   632  				ExpectedWarning: mysql.ERBadNullError,
   633  			},
   634  			{
   635  				Query:    "SELECT * FROM pkTable order by pk",
   636  				Expected: []sql.Row{{0, 1}, {0, 3}, {0, 4}},
   637  			},
   638  			{
   639  				Query:    "UPDATE IGNORE pkTable SET val = NULL",
   640  				Expected: []sql.Row{{newUpdateResult(3, 1)}},
   641  			},
   642  			{
   643  				Query:    "SELECT * FROM pkTable order by pk",
   644  				Expected: []sql.Row{{0, 0}, {0, 3}, {0, 4}},
   645  			},
   646  			{
   647  				Query:           "UPDATE IGNORE idxTable set pk = pk + 1, val = val + 1", // two bad updates
   648  				Expected:        []sql.Row{{newUpdateResult(3, 1)}},
   649  				ExpectedWarning: mysql.ERDupEntry,
   650  			},
   651  			{
   652  				Query:    "SELECT * FROM idxTable order by pk",
   653  				Expected: []sql.Row{{1, 1}, {2, 2}, {4, 5}},
   654  			},
   655  		},
   656  	},
   657  	{
   658  		Name: "UPDATE IGNORE with type conversions",
   659  		SetUpScript: []string{
   660  			"CREATE TABLE t1 (pk int primary key, v1 int, v2 int)",
   661  			"INSERT INTO t1 VALUES (1, 1, 1)",
   662  		},
   663  		Assertions: []ScriptTestAssertion{
   664  			{
   665  				Query:           "UPDATE IGNORE t1 SET v1 = 'dsddads'",
   666  				Expected:        []sql.Row{{newUpdateResult(1, 1)}},
   667  				ExpectedWarning: mysql.ERTruncatedWrongValueForField,
   668  			},
   669  			{
   670  				Query:    "SELECT * FROM t1",
   671  				Expected: []sql.Row{{1, 0, 1}},
   672  			},
   673  			{
   674  				Query:           "UPDATE IGNORE t1 SET pk = 'dasda', v2 = 'dsddads'",
   675  				Expected:        []sql.Row{{newUpdateResult(1, 1)}},
   676  				ExpectedWarning: mysql.ERTruncatedWrongValueForField,
   677  			},
   678  			{
   679  				Query:    "SELECT * FROM t1",
   680  				Expected: []sql.Row{{0, 0, 0}},
   681  			},
   682  		},
   683  	},
   684  	{
   685  		Name: "UPDATE IGNORE with foreign keys",
   686  		SetUpScript: []string{
   687  			"CREATE TABLE colors ( id INT NOT NULL, color VARCHAR(32) NOT NULL, PRIMARY KEY (id), INDEX color_index(color));",
   688  			"CREATE TABLE objects (id INT NOT NULL, name VARCHAR(64) NOT NULL,color VARCHAR(32), PRIMARY KEY(id),FOREIGN KEY (color) REFERENCES colors(color))",
   689  			"INSERT INTO colors (id,color) VALUES (1,'red'),(2,'green'),(3,'blue'),(4,'purple')",
   690  			"INSERT INTO objects (id,name,color) VALUES (1,'truck','red'),(2,'ball','green'),(3,'shoe','blue')",
   691  		},
   692  		Assertions: []ScriptTestAssertion{
   693  			{
   694  				Query:           "UPDATE IGNORE objects SET color = 'orange' where id = 2",
   695  				Expected:        []sql.Row{{newUpdateResult(1, 0)}},
   696  				ExpectedWarning: mysql.ErNoReferencedRow2,
   697  			},
   698  			{
   699  				Query:    "SELECT * FROM objects ORDER BY id",
   700  				Expected: []sql.Row{{1, "truck", "red"}, {2, "ball", "green"}, {3, "shoe", "blue"}},
   701  			},
   702  		},
   703  	},
   704  	{
   705  		Name: "UPDATE IGNORE with check constraints",
   706  		SetUpScript: []string{
   707  			"CREATE TABLE checksTable(pk int primary key)",
   708  			"ALTER TABLE checksTable ADD CONSTRAINT mycx CHECK (pk < 5)",
   709  			"INSERT INTO checksTable VALUES (1),(2),(3),(4)",
   710  		},
   711  		Assertions: []ScriptTestAssertion{
   712  			{
   713  				Query:           "UPDATE IGNORE checksTable SET pk = pk + 1 where pk = 4",
   714  				Expected:        []sql.Row{{newUpdateResult(1, 0)}},
   715  				ExpectedWarning: mysql.ERUnknownError,
   716  			},
   717  			{
   718  				Query:    "SELECT * from checksTable ORDER BY pk",
   719  				Expected: []sql.Row{{1}, {2}, {3}, {4}},
   720  			},
   721  		},
   722  	},
   723  }
   724  
   725  var UpdateErrorTests = []QueryErrorTest{
   726  	{
   727  		Query:       `UPDATE keyless INNER JOIN one_pk on keyless.c0 = one_pk.pk SET keyless.c0 = keyless.c0 + 1`,
   728  		ExpectedErr: sql.ErrUnsupportedFeature,
   729  	},
   730  	{
   731  		Query:       `UPDATE people set height_inches = null where height_inches < 100`,
   732  		ExpectedErr: sql.ErrInsertIntoNonNullableProvidedNull,
   733  	},
   734  	{
   735  		Query:       `UPDATE people SET height_inches = IF(SUM(height_inches) % 2 = 0, 42, height_inches)`,
   736  		ExpectedErr: sql.ErrAggregationUnsupported,
   737  	},
   738  	{
   739  		Query:       `UPDATE people SET height_inches = IF(SUM(*) % 2 = 0, 42, height_inches)`,
   740  		ExpectedErr: sql.ErrStarUnsupported,
   741  	},
   742  	{
   743  		Query:       `UPDATE people SET height_inches = IF(ROW_NUMBER() OVER() % 2 = 0, 42, height_inches)`,
   744  		ExpectedErr: sql.ErrWindowUnsupported,
   745  	},
   746  }
   747  
   748  var UpdateErrorScripts = []ScriptTest{
   749  	{
   750  		Name: "try updating string that is too long",
   751  		SetUpScript: []string{
   752  			"create table bad (s varchar(9))",
   753  			"insert into bad values ('good')",
   754  		},
   755  		Query:       "update bad set s = '1234567890'",
   756  		ExpectedErr: types.ErrLengthBeyondLimit,
   757  	},
   758  }
   759  
   760  var ZeroTime = time.Date(0000, time.January, 1, 0, 0, 0, 0, time.UTC)
   761  var Jan1Noon = time.Date(2000, time.January, 1, 12, 0, 0, 0, time.UTC)
   762  var Dec15_1_30 = time.Date(2023, time.December, 15, 1, 30, 0, 0, time.UTC)
   763  var Oct2Midnight = time.Date(2020, time.October, 2, 0, 0, 0, 0, time.UTC)
   764  var OnUpdateExprScripts = []ScriptTest{
   765  	{
   766  		Name: "error cases",
   767  		SetUpScript: []string{
   768  			"create table t (i int, ts timestamp);",
   769  		},
   770  		Assertions: []ScriptTestAssertion{
   771  			{
   772  				Query:          "create table tt (i int, j int on update (5))",
   773  				ExpectedErrStr: "syntax error at position 42 near 'update'",
   774  			},
   775  			{
   776  				Query:       "create table tt (i int, j int on update current_timestamp)",
   777  				ExpectedErr: sql.ErrInvalidOnUpdate,
   778  			},
   779  			{
   780  				Query:       "create table tt (i int, d date on update current_timestamp)",
   781  				ExpectedErr: sql.ErrInvalidOnUpdate,
   782  			},
   783  			{
   784  				Query:       "create table tt (i int, ts timestamp on update now(1))",
   785  				ExpectedErr: sql.ErrInvalidOnUpdate,
   786  			},
   787  			{
   788  				Query:       "create table tt (i int, ts timestamp on update current_timestamp(1))",
   789  				ExpectedErr: sql.ErrInvalidOnUpdate,
   790  			},
   791  			{
   792  				Query:       "create table tt (i int, ts timestamp on update current_timestamp(100))",
   793  				ExpectedErr: sql.ErrInvalidOnUpdate,
   794  			},
   795  			{
   796  				Query:       "create table tt (i int, ts timestamp on update localtime(1))",
   797  				ExpectedErr: sql.ErrInvalidOnUpdate,
   798  			},
   799  			{
   800  				Query:       "create table tt (i int, ts timestamp on update localtimestamp(1))",
   801  				ExpectedErr: sql.ErrInvalidOnUpdate,
   802  			},
   803  			{
   804  				Query:          "alter table t modify column ts timestamp on update (5)",
   805  				ExpectedErrStr: "syntax error at position 53 near 'update'",
   806  			},
   807  			{
   808  				Query:       "alter table t modify column t int on update current_timestamp",
   809  				ExpectedErr: sql.ErrInvalidOnUpdate,
   810  			},
   811  			{
   812  				Query:       "alter table t modify column t date on update current_timestamp",
   813  				ExpectedErr: sql.ErrInvalidOnUpdate,
   814  			},
   815  			{
   816  				Query:          "select current_timestamp(i) from t",
   817  				ExpectedErrStr: "syntax error at position 27 near 'i'",
   818  			},
   819  		},
   820  	},
   821  	{
   822  		Name: "basic case",
   823  		SetUpScript: []string{
   824  			"create table t (i int, ts timestamp default 0 on update current_timestamp);",
   825  			"insert into t(i) values (1), (2), (3);",
   826  		},
   827  		Assertions: []ScriptTestAssertion{
   828  			{
   829  				Query: "show create table t",
   830  				Expected: []sql.Row{
   831  					{"t", "CREATE TABLE `t` (\n" +
   832  						"  `i` int,\n" +
   833  						"  `ts` timestamp DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP\n" +
   834  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
   835  				},
   836  			},
   837  			{
   838  				SkipResultCheckOnServerEngine: true,
   839  				Query:                         "select * from t order by i;",
   840  				Expected: []sql.Row{
   841  					{1, ZeroTime},
   842  					{2, ZeroTime},
   843  					{3, ZeroTime},
   844  				},
   845  			},
   846  			{
   847  				Query: "update t set i = 10 where i = 1;",
   848  				Expected: []sql.Row{
   849  					{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}},
   850  				},
   851  			},
   852  			{
   853  				SkipResultCheckOnServerEngine: true,
   854  				Query:                         "select * from t order by i;",
   855  				Expected: []sql.Row{
   856  					{2, ZeroTime},
   857  					{3, ZeroTime},
   858  					{10, Dec15_1_30},
   859  				},
   860  			},
   861  			{
   862  				Query: "update t set i = 100",
   863  				Expected: []sql.Row{
   864  					{types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}},
   865  				},
   866  			},
   867  			{
   868  				Query: "select * from t order by i;",
   869  				Expected: []sql.Row{
   870  					{100, Dec15_1_30},
   871  					{100, Dec15_1_30},
   872  					{100, Dec15_1_30},
   873  				},
   874  			},
   875  			{
   876  				// updating timestamp itself blocks on update
   877  				Query: "update t set ts = timestamp('2020-10-2')",
   878  				Expected: []sql.Row{
   879  					{types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}},
   880  				},
   881  			},
   882  			{
   883  				Query: "select * from t;",
   884  				Expected: []sql.Row{
   885  					{100, Oct2Midnight},
   886  					{100, Oct2Midnight},
   887  					{100, Oct2Midnight},
   888  				},
   889  			},
   890  		},
   891  	},
   892  	{
   893  		Name: "default time is current time",
   894  		SetUpScript: []string{
   895  			"create table t (i int, ts timestamp default current_timestamp on update current_timestamp);",
   896  			"insert into t(i) values (1), (2), (3);",
   897  		},
   898  		Assertions: []ScriptTestAssertion{
   899  			{
   900  				Query: "show create table t",
   901  				Expected: []sql.Row{
   902  					{"t", "CREATE TABLE `t` (\n" +
   903  						"  `i` int,\n" +
   904  						"  `ts` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP\n" +
   905  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
   906  				},
   907  			},
   908  			{
   909  				Query: "select * from t order by i;",
   910  				Expected: []sql.Row{
   911  					{1, Jan1Noon},
   912  					{2, Jan1Noon},
   913  					{3, Jan1Noon},
   914  				},
   915  			},
   916  			{
   917  				Query: "update t set i = 10 where i = 1;",
   918  				Expected: []sql.Row{
   919  					{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}},
   920  				},
   921  			},
   922  			{
   923  				Query: "select * from t order by i;",
   924  				Expected: []sql.Row{
   925  					{2, Jan1Noon},
   926  					{3, Jan1Noon},
   927  					{10, Dec15_1_30},
   928  				},
   929  			},
   930  			{
   931  				Query: "update t set i = 100",
   932  				Expected: []sql.Row{
   933  					{types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}},
   934  				},
   935  			},
   936  			{
   937  				Query: "select * from t order by i;",
   938  				Expected: []sql.Row{
   939  					{100, Dec15_1_30},
   940  					{100, Dec15_1_30},
   941  					{100, Dec15_1_30},
   942  				},
   943  			},
   944  			{
   945  				// updating timestamp itself blocks on update
   946  				Query: "update t set ts = timestamp('2020-10-2')",
   947  				Expected: []sql.Row{
   948  					{types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}},
   949  				},
   950  			},
   951  			{
   952  				Query: "select * from t;",
   953  				Expected: []sql.Row{
   954  					{100, Oct2Midnight},
   955  					{100, Oct2Midnight},
   956  					{100, Oct2Midnight},
   957  				},
   958  			},
   959  		},
   960  	},
   961  	{
   962  		Name: "alter table",
   963  		SetUpScript: []string{
   964  			"create table t (i int, ts timestamp);",
   965  			"insert into t(i) values (1), (2), (3);",
   966  		},
   967  		Assertions: []ScriptTestAssertion{
   968  			{
   969  				Query: "show create table t",
   970  				Expected: []sql.Row{
   971  					{"t", "CREATE TABLE `t` (\n" +
   972  						"  `i` int,\n" +
   973  						"  `ts` timestamp\n" +
   974  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
   975  				},
   976  			},
   977  			{
   978  				Query: "alter table t modify column ts timestamp default 0 on update current_timestamp;",
   979  				Expected: []sql.Row{
   980  					{types.NewOkResult(0)},
   981  				},
   982  			},
   983  			{
   984  				Query: "show create table t",
   985  				Expected: []sql.Row{
   986  					{"t", "CREATE TABLE `t` (\n" +
   987  						"  `i` int,\n" +
   988  						"  `ts` timestamp DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP\n" +
   989  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
   990  				},
   991  			},
   992  			{
   993  				Query: "select * from t order by i;",
   994  				Expected: []sql.Row{
   995  					{1, nil},
   996  					{2, nil},
   997  					{3, nil},
   998  				},
   999  			},
  1000  			{
  1001  				Query: "update t set i = 10 where i = 1;",
  1002  				Expected: []sql.Row{
  1003  					{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}},
  1004  				},
  1005  			},
  1006  			{
  1007  				Query: "select * from t order by i;",
  1008  				Expected: []sql.Row{
  1009  					{2, nil},
  1010  					{3, nil},
  1011  					{10, Dec15_1_30},
  1012  				},
  1013  			},
  1014  			{
  1015  				Query: "update t set i = 100",
  1016  				Expected: []sql.Row{
  1017  					{types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}},
  1018  				},
  1019  			},
  1020  			{
  1021  				Query: "select * from t order by i;",
  1022  				Expected: []sql.Row{
  1023  					{100, Dec15_1_30},
  1024  					{100, Dec15_1_30},
  1025  					{100, Dec15_1_30},
  1026  				},
  1027  			},
  1028  			{
  1029  				Query: "update t set ts = timestamp('2020-10-2')",
  1030  				Expected: []sql.Row{
  1031  					{types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}},
  1032  				},
  1033  			},
  1034  			{
  1035  				Query: "select * from t;",
  1036  				Expected: []sql.Row{
  1037  					{100, Oct2Midnight},
  1038  					{100, Oct2Midnight},
  1039  					{100, Oct2Midnight},
  1040  				},
  1041  			},
  1042  		},
  1043  	},
  1044  	{
  1045  		Name: "multiple columns case",
  1046  		SetUpScript: []string{
  1047  			"create table t (i int primary key, ts timestamp default 0 on update current_timestamp, dt datetime default 0 on update current_timestamp);",
  1048  			"insert into t(i) values (1), (2), (3);",
  1049  		},
  1050  		Assertions: []ScriptTestAssertion{
  1051  			{
  1052  				Query: "show create table t",
  1053  				Expected: []sql.Row{
  1054  					{"t", "CREATE TABLE `t` (\n" +
  1055  						"  `i` int NOT NULL,\n" +
  1056  						"  `ts` timestamp DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP,\n" +
  1057  						"  `dt` datetime DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP,\n" +
  1058  						"  PRIMARY KEY (`i`)\n" +
  1059  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1060  				},
  1061  			},
  1062  			{
  1063  				SkipResultCheckOnServerEngine: true,
  1064  				Query:                         "select * from t order by i;",
  1065  				Expected: []sql.Row{
  1066  					{1, ZeroTime, ZeroTime},
  1067  					{2, ZeroTime, ZeroTime},
  1068  					{3, ZeroTime, ZeroTime},
  1069  				},
  1070  			},
  1071  			{
  1072  				Query: "update t set i = 10 where i = 1;",
  1073  				Expected: []sql.Row{
  1074  					{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}},
  1075  				},
  1076  			},
  1077  			{
  1078  				SkipResultCheckOnServerEngine: true,
  1079  				Query:                         "select * from t order by i;",
  1080  				Expected: []sql.Row{
  1081  					{2, ZeroTime, ZeroTime},
  1082  					{3, ZeroTime, ZeroTime},
  1083  					{10, Dec15_1_30, Dec15_1_30},
  1084  				},
  1085  			},
  1086  			{
  1087  				Query: "update t set ts = timestamp('2020-10-2') where i = 2",
  1088  				Expected: []sql.Row{
  1089  					{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}},
  1090  				},
  1091  			},
  1092  			{
  1093  				SkipResultCheckOnServerEngine: true,
  1094  				Query:                         "select * from t order by i;",
  1095  				Expected: []sql.Row{
  1096  					{2, Oct2Midnight, Dec15_1_30},
  1097  					{3, ZeroTime, ZeroTime},
  1098  					{10, Dec15_1_30, Dec15_1_30},
  1099  				},
  1100  			},
  1101  		},
  1102  	},
  1103  	{
  1104  		// before update triggers that update the timestamp column block the on update
  1105  		Name: "before update trigger",
  1106  		SetUpScript: []string{
  1107  			"create table t (i int primary key, ts timestamp default 0 on update current_timestamp, dt datetime default 0 on update current_timestamp);",
  1108  			"create trigger trig before update on t for each row set new.ts = timestamp('2020-10-2');",
  1109  			"insert into t(i) values (1), (2), (3);",
  1110  		},
  1111  		Assertions: []ScriptTestAssertion{
  1112  			{
  1113  				Query: "update t set i = 10 where i = 1;",
  1114  				Expected: []sql.Row{
  1115  					{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}},
  1116  				},
  1117  			},
  1118  			{
  1119  				SkipResultCheckOnServerEngine: true,
  1120  				Query:                         "select * from t order by i;",
  1121  				Expected: []sql.Row{
  1122  					{2, ZeroTime, ZeroTime},
  1123  					{3, ZeroTime, ZeroTime},
  1124  					{10, Oct2Midnight, Dec15_1_30},
  1125  				},
  1126  			},
  1127  		},
  1128  	},
  1129  	{
  1130  		// update triggers that update other tables do not block on update
  1131  		Name: "after update trigger",
  1132  		SetUpScript: []string{
  1133  			"create table a (i int primary key);",
  1134  			"create table b (i int, ts timestamp default 0 on update current_timestamp, dt datetime default 0 on update current_timestamp);",
  1135  			"create trigger trig after update on a for each row update b set i = i + 1;",
  1136  			"insert into a values (0);",
  1137  			"insert into b(i) values (0);",
  1138  		},
  1139  		Assertions: []ScriptTestAssertion{
  1140  			{
  1141  				SkipResultCheckOnServerEngine: true,
  1142  				Query:                         "select * from b order by i;",
  1143  				Expected: []sql.Row{
  1144  					{0, ZeroTime, ZeroTime},
  1145  				},
  1146  			},
  1147  			{
  1148  				Query: "update a set i = 10;",
  1149  				Expected: []sql.Row{
  1150  					{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}},
  1151  				},
  1152  			},
  1153  			{
  1154  				Query: "select * from b order by i;",
  1155  				Expected: []sql.Row{
  1156  					{1, Dec15_1_30, Dec15_1_30},
  1157  				},
  1158  			},
  1159  		},
  1160  	},
  1161  	{
  1162  		Name: "insert triggers",
  1163  		SetUpScript: []string{
  1164  			"create table t (i int primary key);",
  1165  			"create table a (i int, ts timestamp default 0 on update current_timestamp, dt datetime default 0 on update current_timestamp);",
  1166  			"create table b (i int, ts timestamp default 0 on update current_timestamp, dt datetime default 0 on update current_timestamp);",
  1167  			"create trigger trigA after insert on t for each row update a set i = i + 1;",
  1168  			"create trigger trigB before insert on t for each row update b set i = i + 1;",
  1169  			"insert into a(i) values (0);",
  1170  			"insert into b(i) values (0);",
  1171  		},
  1172  		Assertions: []ScriptTestAssertion{
  1173  			{
  1174  				Query: "insert into t values (1);",
  1175  				Expected: []sql.Row{
  1176  					{types.OkResult{RowsAffected: 1}},
  1177  				},
  1178  			},
  1179  			{
  1180  				Query: "select * from a order by i;",
  1181  				Expected: []sql.Row{
  1182  					{1, Dec15_1_30, Dec15_1_30},
  1183  				},
  1184  			},
  1185  			{
  1186  				Query: "select * from b order by i;",
  1187  				Expected: []sql.Row{
  1188  					{1, Dec15_1_30, Dec15_1_30},
  1189  				},
  1190  			},
  1191  		},
  1192  	},
  1193  	{
  1194  		// Foreign Key Cascade Update does NOT trigger on update on child table
  1195  		Name: "foreign key tests",
  1196  		SetUpScript: []string{
  1197  			"create table parent (i int primary key);",
  1198  			"create table child (i int primary key, ts timestamp default 0 on update current_timestamp, foreign key (i) references parent(i) on update cascade);",
  1199  			"insert into parent values (1);",
  1200  			"insert into child(i) values (1);",
  1201  		},
  1202  		Assertions: []ScriptTestAssertion{
  1203  			{
  1204  				Query: "update parent set i = 10;",
  1205  				Expected: []sql.Row{
  1206  					{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}},
  1207  				},
  1208  			},
  1209  			{
  1210  				SkipResultCheckOnServerEngine: true,
  1211  				Query:                         "select * from child;",
  1212  				Expected: []sql.Row{
  1213  					{10, ZeroTime},
  1214  				},
  1215  			},
  1216  		},
  1217  	},
  1218  	{
  1219  		Name: "stored procedure tests",
  1220  		SetUpScript: []string{
  1221  			"create table t (i int, ts timestamp default 0 on update current_timestamp);",
  1222  			"insert into t(i) values (0);",
  1223  			"create procedure p() update t set i = i + 1;",
  1224  		},
  1225  		Assertions: []ScriptTestAssertion{
  1226  			{
  1227  				// call depends on stored procedure stmt for whether to use 'query' or 'exec' from go sql driver.
  1228  				SkipResultCheckOnServerEngine: true,
  1229  				Query:                         "call p();",
  1230  				Expected: []sql.Row{
  1231  					{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}},
  1232  				},
  1233  			},
  1234  			{
  1235  				Query: "select * from t;",
  1236  				Expected: []sql.Row{
  1237  					{1, Dec15_1_30},
  1238  				},
  1239  			},
  1240  		},
  1241  	},
  1242  	{
  1243  		Name: "now() synonyms",
  1244  		SetUpScript: []string{
  1245  			"create table t (i int, ts timestamp);",
  1246  		},
  1247  		Assertions: []ScriptTestAssertion{
  1248  			{
  1249  				Query: "create table t1 (i int, ts timestamp on update now())",
  1250  				Expected: []sql.Row{
  1251  					{types.NewOkResult(0)},
  1252  				},
  1253  			},
  1254  			{
  1255  				Query: "show create table t1;",
  1256  				Expected: []sql.Row{
  1257  					{"t1", "CREATE TABLE `t1` (\n" +
  1258  						"  `i` int,\n" +
  1259  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1260  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1261  				},
  1262  			},
  1263  			{
  1264  				Query: "create table t2 (i int, ts timestamp on update now(0))",
  1265  				Expected: []sql.Row{
  1266  					{types.NewOkResult(0)},
  1267  				},
  1268  			},
  1269  			{
  1270  				Query: "show create table t2;",
  1271  				Expected: []sql.Row{
  1272  					{"t2", "CREATE TABLE `t2` (\n" +
  1273  						"  `i` int,\n" +
  1274  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1275  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1276  				},
  1277  			},
  1278  			{
  1279  				Query: "create table t3 (i int, ts timestamp on update localtime)",
  1280  				Expected: []sql.Row{
  1281  					{types.NewOkResult(0)},
  1282  				},
  1283  			},
  1284  			{
  1285  				Query: "show create table t3;",
  1286  				Expected: []sql.Row{
  1287  					{"t3", "CREATE TABLE `t3` (\n" +
  1288  						"  `i` int,\n" +
  1289  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1290  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1291  				},
  1292  			},
  1293  			{
  1294  				Query: "create table t4 (i int, ts timestamp on update localtime())",
  1295  				Expected: []sql.Row{
  1296  					{types.NewOkResult(0)},
  1297  				},
  1298  			},
  1299  			{
  1300  				Query: "show create table t4;",
  1301  				Expected: []sql.Row{
  1302  					{"t4", "CREATE TABLE `t4` (\n" +
  1303  						"  `i` int,\n" +
  1304  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1305  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1306  				},
  1307  			},
  1308  			{
  1309  				Query: "create table t5 (i int, ts timestamp on update localtime(0))",
  1310  				Expected: []sql.Row{
  1311  					{types.NewOkResult(0)},
  1312  				},
  1313  			},
  1314  			{
  1315  				Query: "show create table t5;",
  1316  				Expected: []sql.Row{
  1317  					{"t5", "CREATE TABLE `t5` (\n" +
  1318  						"  `i` int,\n" +
  1319  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1320  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1321  				},
  1322  			},
  1323  			{
  1324  				Query: "create table t6 (i int, ts timestamp on update localtimestamp)",
  1325  				Expected: []sql.Row{
  1326  					{types.NewOkResult(0)},
  1327  				},
  1328  			},
  1329  			{
  1330  				Query: "show create table t6;",
  1331  				Expected: []sql.Row{
  1332  					{"t6", "CREATE TABLE `t6` (\n" +
  1333  						"  `i` int,\n" +
  1334  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1335  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1336  				},
  1337  			},
  1338  			{
  1339  				Query: "create table t7 (i int, ts timestamp on update localtimestamp())",
  1340  				Expected: []sql.Row{
  1341  					{types.NewOkResult(0)},
  1342  				},
  1343  			},
  1344  			{
  1345  				Query: "show create table t7;",
  1346  				Expected: []sql.Row{
  1347  					{"t7", "CREATE TABLE `t7` (\n" +
  1348  						"  `i` int,\n" +
  1349  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1350  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1351  				},
  1352  			},
  1353  			{
  1354  				Query: "create table t8 (i int, ts timestamp on update localtimestamp(0))",
  1355  				Expected: []sql.Row{
  1356  					{types.NewOkResult(0)},
  1357  				},
  1358  			},
  1359  			{
  1360  				Query: "show create table t8;",
  1361  				Expected: []sql.Row{
  1362  					{"t8", "CREATE TABLE `t8` (\n" +
  1363  						"  `i` int,\n" +
  1364  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1365  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1366  				},
  1367  			},
  1368  			{
  1369  				Query: "alter table t modify column ts timestamp on update now()",
  1370  				Expected: []sql.Row{
  1371  					{types.NewOkResult(0)},
  1372  				},
  1373  			},
  1374  			{
  1375  				Query: "show create table t;",
  1376  				Expected: []sql.Row{
  1377  					{"t", "CREATE TABLE `t` (\n" +
  1378  						"  `i` int,\n" +
  1379  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1380  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1381  				},
  1382  			},
  1383  			{
  1384  				Query: "alter table t modify column ts timestamp on update now(0)",
  1385  				Expected: []sql.Row{
  1386  					{types.NewOkResult(0)},
  1387  				},
  1388  			},
  1389  			{
  1390  				Query: "show create table t;",
  1391  				Expected: []sql.Row{
  1392  					{"t", "CREATE TABLE `t` (\n" +
  1393  						"  `i` int,\n" +
  1394  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1395  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1396  				},
  1397  			},
  1398  			{
  1399  				Query: "alter table t modify column ts timestamp on update localtime",
  1400  				Expected: []sql.Row{
  1401  					{types.NewOkResult(0)},
  1402  				},
  1403  			},
  1404  			{
  1405  				Query: "show create table t;",
  1406  				Expected: []sql.Row{
  1407  					{"t", "CREATE TABLE `t` (\n" +
  1408  						"  `i` int,\n" +
  1409  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1410  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1411  				},
  1412  			},
  1413  			{
  1414  				Query: "alter table t modify column ts timestamp on update localtime()",
  1415  				Expected: []sql.Row{
  1416  					{types.NewOkResult(0)},
  1417  				},
  1418  			},
  1419  			{
  1420  				Query: "show create table t;",
  1421  				Expected: []sql.Row{
  1422  					{"t", "CREATE TABLE `t` (\n" +
  1423  						"  `i` int,\n" +
  1424  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1425  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1426  				},
  1427  			},
  1428  			{
  1429  				Query: "alter table t modify column ts timestamp on update localtime(0)",
  1430  				Expected: []sql.Row{
  1431  					{types.NewOkResult(0)},
  1432  				},
  1433  			},
  1434  			{
  1435  				Query: "show create table t;",
  1436  				Expected: []sql.Row{
  1437  					{"t", "CREATE TABLE `t` (\n" +
  1438  						"  `i` int,\n" +
  1439  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1440  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1441  				},
  1442  			},
  1443  			{
  1444  				Query: "alter table t modify column ts timestamp on update localtimestamp",
  1445  				Expected: []sql.Row{
  1446  					{types.NewOkResult(0)},
  1447  				},
  1448  			},
  1449  			{
  1450  				Query: "show create table t;",
  1451  				Expected: []sql.Row{
  1452  					{"t", "CREATE TABLE `t` (\n" +
  1453  						"  `i` int,\n" +
  1454  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1455  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1456  				},
  1457  			},
  1458  			{
  1459  				Query: "alter table t modify column ts timestamp on update localtimestamp()",
  1460  				Expected: []sql.Row{
  1461  					{types.NewOkResult(0)},
  1462  				},
  1463  			},
  1464  			{
  1465  				Query: "show create table t;",
  1466  				Expected: []sql.Row{
  1467  					{"t", "CREATE TABLE `t` (\n" +
  1468  						"  `i` int,\n" +
  1469  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1470  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1471  				},
  1472  			},
  1473  			{
  1474  				Query: "alter table t modify column ts timestamp on update localtimestamp(0)",
  1475  				Expected: []sql.Row{
  1476  					{types.NewOkResult(0)},
  1477  				},
  1478  			},
  1479  			{
  1480  				Query: "show create table t;",
  1481  				Expected: []sql.Row{
  1482  					{"t", "CREATE TABLE `t` (\n" +
  1483  						"  `i` int,\n" +
  1484  						"  `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" +
  1485  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
  1486  				},
  1487  			},
  1488  		},
  1489  	},
  1490  }