github.com/dolthub/go-mysql-server@v0.18.0/enginetest/queries/procedure_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/types"
    22  )
    23  
    24  var ProcedureLogicTests = []ScriptTest{
    25  	{
    26  		// When a loop is executed once before the first evaluation of the loop condition, we expect the stored
    27  		// procedure to return the last result set from that first loop execution.
    28  		Name: "REPEAT with OnceBefore returns first loop evaluation result set",
    29  		SetUpScript: []string{
    30  			`CREATE PROCEDURE p1()
    31  	BEGIN
    32  	SET @counter = 0;
    33  	REPEAT
    34  		SELECT 42 from dual;
    35  		SET @counter = @counter + 1;
    36  	UNTIL @counter >= 0
    37  	END REPEAT;
    38  	END`,
    39  		},
    40  		Assertions: []ScriptTestAssertion{
    41  			{
    42  				Query:    "CALL p1;",
    43  				Expected: []sql.Row{{42}},
    44  			},
    45  		},
    46  	},
    47  	{
    48  		// When a loop condition evals to false, we expect the stored procedure to return the last
    49  		// result set from the previous loop execution.
    50  		Name: "WHILE returns previous loop evaluation result set",
    51  		SetUpScript: []string{
    52  			`CREATE PROCEDURE p1()
    53  	BEGIN
    54  	SET @counter = 0;
    55  	WHILE @counter <= 0 DO
    56  		SET @counter = @counter + 1;
    57  		SELECT CAST(@counter + 41 as SIGNED) from dual;
    58  	END WHILE;
    59  	END`,
    60  		},
    61  		Assertions: []ScriptTestAssertion{
    62  			{
    63  				Query:    "CALL p1;",
    64  				Expected: []sql.Row{{42}},
    65  			},
    66  		},
    67  	},
    68  
    69  	{
    70  		Name: "Simple SELECT",
    71  		SetUpScript: []string{
    72  			"CREATE PROCEDURE testabc(x DOUBLE, y DOUBLE) SELECT x*y",
    73  		},
    74  		Assertions: []ScriptTestAssertion{
    75  			{
    76  				Query: "CALL testabc(2, 3)",
    77  				Expected: []sql.Row{
    78  					{
    79  						6.0,
    80  					},
    81  				},
    82  			},
    83  			{
    84  				Query: "CALL testabc(9, 9.5)",
    85  				Expected: []sql.Row{
    86  					{
    87  						85.5,
    88  					},
    89  				},
    90  			},
    91  		},
    92  	},
    93  	{
    94  		Name: "Multiple SELECTs",
    95  		SetUpScript: []string{
    96  			"CREATE TABLE t1(pk VARCHAR(20) PRIMARY KEY)",
    97  			"INSERT INTO t1 VALUES (3), (4), (50)",
    98  			`CREATE PROCEDURE p1()
    99  BEGIN
   100  	SELECT * FROM t1;
   101  	UPDATE t1 SET pk = CONCAT(pk, '0');
   102  	SELECT * FROM t1;
   103  	INSERT INTO t1 VALUES (1), (2);
   104  	SELECT * FROM t1;
   105  	REPLACE INTO t1 VALUES (1), (30);
   106  	DELETE FROM t1 WHERE pk LIKE '%00';
   107  END;`,
   108  		},
   109  		Assertions: []ScriptTestAssertion{
   110  			{
   111  				Query: "CALL p1()",
   112  				Expected: []sql.Row{
   113  					{"1"},
   114  					{"2"},
   115  					{"30"},
   116  					{"40"},
   117  					{"500"},
   118  				},
   119  			},
   120  			{
   121  				Query: "SELECT * FROM t1 ORDER BY 1",
   122  				Expected: []sql.Row{
   123  					{"1"},
   124  					{"2"},
   125  					{"30"},
   126  					{"40"},
   127  				},
   128  			},
   129  		},
   130  	},
   131  	{
   132  		Name: "IF/ELSE with 1 SELECT at end",
   133  		SetUpScript: []string{
   134  			"SET @outparam = ''",
   135  			`CREATE PROCEDURE p1(OUT s VARCHAR(200), N DOUBLE, m DOUBLE)
   136  BEGIN
   137  	SET s = '';
   138  	IF n = m THEN SET s = 'equals';
   139  	ELSE
   140  		IF n > m THEN SET s = 'greater';
   141  		ELSE SET s = 'less';
   142  		END IF;
   143  		SET s = CONCAT('is ', s, ' than');
   144  	END IF;
   145  	SET s = CONCAT(n, ' ', s, ' ', m, '.');
   146  	SELECT s;
   147  END;`,
   148  			`CREATE PROCEDURE p2(s VARCHAR(200), N DOUBLE, m DOUBLE)
   149  BEGIN
   150  	SET s = '';
   151  	IF n = m THEN SET s = 'equals';
   152  	ELSE
   153  		IF n > m THEN SET s = 'greater';
   154  		ELSE SET s = 'less';
   155  		END IF;
   156  		SET s = CONCAT('is ', s, ' than');
   157  	END IF;
   158  	SET s = CONCAT(n, ' ', s, ' ', m, '.');
   159  	SELECT s;
   160  END;`,
   161  		},
   162  		Assertions: []ScriptTestAssertion{
   163  			{
   164  				Query: "CALL p1(@outparam, 1, 2)",
   165  				Expected: []sql.Row{
   166  					{
   167  						"1 is less than 2.",
   168  					},
   169  				},
   170  			},
   171  			{
   172  				Query: "SELECT @outparam",
   173  				Expected: []sql.Row{
   174  					{
   175  						"1 is less than 2.",
   176  					},
   177  				},
   178  			},
   179  			{
   180  				Query: "CALL p1(@outparam, null, 2)",
   181  				Expected: []sql.Row{
   182  					{
   183  						nil,
   184  					},
   185  				},
   186  			},
   187  			{
   188  				Query: "CALL p1(@outparam, 7, 4)",
   189  				Expected: []sql.Row{
   190  					{
   191  						"7 is greater than 4.",
   192  					},
   193  				},
   194  			},
   195  			{
   196  				Query: "SELECT @outparam",
   197  				Expected: []sql.Row{
   198  					{
   199  						"7 is greater than 4.",
   200  					},
   201  				},
   202  			},
   203  			{
   204  				Query: "CALL p1(@outparam, 5, 5)",
   205  				Expected: []sql.Row{
   206  					{
   207  						"5 equals 5.",
   208  					},
   209  				},
   210  			},
   211  			{
   212  				Query: "SELECT @outparam",
   213  				Expected: []sql.Row{
   214  					{
   215  						"5 equals 5.",
   216  					},
   217  				},
   218  			},
   219  			{
   220  				Query: "CALL p2(@outparam, 9, 3)",
   221  				Expected: []sql.Row{
   222  					{
   223  						"9 is greater than 3.",
   224  					},
   225  				},
   226  			},
   227  			{ // Not affected as p2 has an IN param rather than OUT
   228  				Query: "SELECT @outparam",
   229  				Expected: []sql.Row{
   230  					{
   231  						"5 equals 5.",
   232  					},
   233  				},
   234  			},
   235  		},
   236  	},
   237  	{
   238  		Name: "IF/ELSE with nested SELECT in branches",
   239  		SetUpScript: []string{
   240  			"CREATE TABLE t1(pk BIGINT PRIMARY KEY)",
   241  			`CREATE PROCEDURE p1(x BIGINT)
   242  BEGIN
   243  	DELETE FROM t1;
   244  	IF x < 10 THEN
   245  		IF x = 0 THEN
   246  			SELECT 1000;
   247  		ELSEIF x = 1 THEN
   248  			SELECT 1001;
   249  		ELSE
   250  			INSERT INTO t1 VALUES (3), (4), (5);
   251  		END IF;
   252  	ELSEIF x < 20 THEN
   253  		IF x = 10 THEN
   254  			INSERT INTO t1 VALUES (1), (2), (6), (7);
   255  		ELSEIF x = 11 THEN
   256  			INSERT INTO t1 VALUES (8), (9), (10), (11), (12);
   257  			SELECT * FROM t1;
   258  		ELSE
   259  			SELECT 2002;
   260  			SELECT 2003;
   261  		END IF;
   262  	END IF;
   263  	INSERT INTO t1 VALUES (1), (2);
   264  END;`,
   265  		},
   266  		Assertions: []ScriptTestAssertion{
   267  			{
   268  				Query: "CALL p1(0)",
   269  				Expected: []sql.Row{
   270  					{
   271  						int64(1000),
   272  					},
   273  				},
   274  			},
   275  			{
   276  				Query: "CALL p1(1)",
   277  				Expected: []sql.Row{
   278  					{
   279  						int64(1001),
   280  					},
   281  				},
   282  			},
   283  			{
   284  				SkipResultCheckOnServerEngine: true, // tracking issue: https://github.com/dolthub/dolt/issues/6918
   285  				Query:                         "CALL p1(2)",
   286  				Expected: []sql.Row{
   287  					{
   288  						types.NewOkResult(2),
   289  					},
   290  				},
   291  			},
   292  			{
   293  				Query:       "CALL p1(10)",
   294  				ExpectedErr: sql.ErrPrimaryKeyViolation,
   295  			},
   296  			{
   297  				Query: "CALL p1(11)",
   298  				Expected: []sql.Row{
   299  					{int64(8)},
   300  					{int64(9)},
   301  					{int64(10)},
   302  					{int64(11)},
   303  					{int64(12)},
   304  				},
   305  			},
   306  			{
   307  				Query: "CALL p1(12)",
   308  				Expected: []sql.Row{
   309  					{
   310  						int64(2003),
   311  					},
   312  				},
   313  			},
   314  		},
   315  	},
   316  	{
   317  		Name: "REPEAT loop over user variable",
   318  		SetUpScript: []string{
   319  			`CREATE PROCEDURE p1(p1 INT)
   320  BEGIN
   321  	SET @x = 0;
   322  	REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
   323  END`,
   324  		},
   325  		Assertions: []ScriptTestAssertion{
   326  			// TODO: MySQL won't actually return *any* result set for these stored procedures. We have done work
   327  			//       to filter out all but the last result set generated by the stored procedure, but we still
   328  			//       need to filter out Result Sets that should be completely omitted.
   329  			{
   330  				Query:    "CALL p1(0)",
   331  				Expected: []sql.Row{{}},
   332  			},
   333  			{
   334  				Query:    "CALL p1(1)",
   335  				Expected: []sql.Row{{}},
   336  			},
   337  			{
   338  				Query:    "CALL p1(2)",
   339  				Expected: []sql.Row{{}},
   340  			},
   341  			{
   342  				// https://github.com/dolthub/dolt/issues/6230
   343  				Query:    "CALL p1(200)",
   344  				Expected: []sql.Row{{}},
   345  			},
   346  		},
   347  	},
   348  	{
   349  		Name: "WHILE loop over user variable",
   350  		SetUpScript: []string{
   351  			`CREATE PROCEDURE p1(p1 INT)
   352  BEGIN
   353  	SET @x = 0;
   354  	WHILE @x <= p1 DO
   355  		SET @x = @x + 1;
   356  	END WHILE;
   357  END`,
   358  		},
   359  		Assertions: []ScriptTestAssertion{
   360  			// TODO: MySQL won't actually return *any* result set for these stored procedures. We have done work
   361  			//       to filter out all but the last result set generated by the stored procedure, but we still
   362  			//       need to filter out Result Sets that should be completely omitted.
   363  			{
   364  				Query:    "CALL p1(0)",
   365  				Expected: []sql.Row{{}},
   366  			},
   367  			{
   368  				Query:    "CALL p1(1)",
   369  				Expected: []sql.Row{{}},
   370  			},
   371  			{
   372  				Query:    "CALL p1(2)",
   373  				Expected: []sql.Row{{}},
   374  			},
   375  		},
   376  	},
   377  	{
   378  		Name: "CASE statements",
   379  		SetUpScript: []string{
   380  			`CREATE PROCEDURE p1(IN a BIGINT)
   381  BEGIN
   382  	DECLARE b VARCHAR(200) DEFAULT "";
   383  	tloop: LOOP
   384  		CASE
   385  			WHEN a < 4 THEN
   386  				SET b = CONCAT(b, "a");
   387  				SET a = a + 1;
   388  			WHEN a < 8 THEN
   389  				SET b = CONCAT(b, "b");
   390  				SET a = a + 1;
   391  			ELSE
   392  				LEAVE tloop;
   393  		END CASE;
   394  	END LOOP;
   395  	SELECT b;
   396  END;`,
   397  			`CREATE PROCEDURE p2(IN a BIGINT)
   398  BEGIN
   399  	DECLARE b VARCHAR(200) DEFAULT "";
   400  	tloop: LOOP
   401  		CASE a
   402  			WHEN 1 THEN
   403  				SET b = CONCAT(b, "a");
   404  				SET a = a + 1;
   405  			WHEN 2 THEN
   406  				SET b = CONCAT(b, "b");
   407  				SET a = a + 1;
   408  			WHEN 3 THEN
   409  				SET b = CONCAT(b, "c");
   410  				SET a = a + 1;
   411  			ELSE
   412  				LEAVE tloop;
   413  		END CASE;
   414  	END LOOP;
   415  	SELECT b;
   416  END;`,
   417  			`CREATE PROCEDURE p3(IN a BIGINT)
   418  BEGIN
   419  	DECLARE b VARCHAR(200) DEFAULT "";
   420  	tloop: LOOP
   421  		CASE a
   422  			WHEN 1 THEN
   423  				SET b = CONCAT(b, "a");
   424  				SET a = a + 1;
   425  		END CASE;
   426  	END LOOP;
   427  	SELECT b;
   428  END;`,
   429  			`CREATE PROCEDURE p4(IN a BIGINT)
   430  BEGIN
   431  	DECLARE b VARCHAR(200) DEFAULT "";
   432  	tloop: LOOP
   433  		CASE
   434  			WHEN a = 1 THEN
   435  				SET b = CONCAT(b, "a");
   436  				SET a = a + 1;
   437  		END CASE;
   438  	END LOOP;
   439  	SELECT b;
   440  END;`,
   441  			`CREATE PROCEDURE p5(IN a BIGINT)
   442  BEGIN
   443  	DECLARE b VARCHAR(200) DEFAULT "";
   444  	REPEAT
   445  		CASE
   446  			WHEN a <= 1 THEN
   447  				SET b = CONCAT(b, "a");
   448  				SET a = a + 1;
   449  		END CASE;
   450  	UNTIL a > 1
   451  	END REPEAT;
   452  	SELECT b;
   453  END;`,
   454  		},
   455  		Assertions: []ScriptTestAssertion{
   456  			{
   457  				Query: "CALL p1(0)",
   458  				Expected: []sql.Row{
   459  					{"aaaabbbb"},
   460  				},
   461  			},
   462  			{
   463  				Query: "CALL p1(3)",
   464  				Expected: []sql.Row{
   465  					{"abbbb"},
   466  				},
   467  			},
   468  			{
   469  				Query: "CALL p1(6)",
   470  				Expected: []sql.Row{
   471  					{"bb"},
   472  				},
   473  			},
   474  			{
   475  				Query: "CALL p1(9)",
   476  				Expected: []sql.Row{
   477  					{""},
   478  				},
   479  			},
   480  			{
   481  				Query: "CALL p2(1)",
   482  				Expected: []sql.Row{
   483  					{"abc"},
   484  				},
   485  			},
   486  			{
   487  				Query: "CALL p2(2)",
   488  				Expected: []sql.Row{
   489  					{"bc"},
   490  				},
   491  			},
   492  			{
   493  				Query: "CALL p2(3)",
   494  				Expected: []sql.Row{
   495  					{"c"},
   496  				},
   497  			},
   498  			{
   499  				Query: "CALL p2(4)",
   500  				Expected: []sql.Row{
   501  					{""},
   502  				},
   503  			},
   504  			{
   505  				Query:          "CALL p3(1)",
   506  				ExpectedErrStr: "Case not found for CASE statement (errno 1339) (sqlstate 20000)",
   507  			},
   508  			{
   509  				Query:          "CALL p3(2)",
   510  				ExpectedErrStr: "Case not found for CASE statement (errno 1339) (sqlstate 20000)",
   511  			},
   512  			{
   513  				Query:          "CALL p4(1)",
   514  				ExpectedErrStr: "Case not found for CASE statement (errno 1339) (sqlstate 20000)",
   515  			},
   516  			{
   517  				Query:          "CALL p4(-1)",
   518  				ExpectedErrStr: "Case not found for CASE statement (errno 1339) (sqlstate 20000)",
   519  			},
   520  			{
   521  				Query: "CALL p5(0)",
   522  				Expected: []sql.Row{
   523  					{"aa"},
   524  				},
   525  			},
   526  			{
   527  				Query: "CALL p5(1)",
   528  				Expected: []sql.Row{
   529  					{"a"},
   530  				},
   531  			},
   532  		},
   533  	},
   534  	{
   535  		Name: "SELECT with JOIN and table aliases",
   536  		SetUpScript: []string{
   537  			"CREATE TABLE foo(a BIGINT PRIMARY KEY, b VARCHAR(20))",
   538  			"INSERT INTO foo VALUES (1, 'd'), (2, 'e'), (3, 'f')",
   539  			"CREATE TABLE bar(b VARCHAR(30) PRIMARY KEY, c BIGINT)",
   540  			"INSERT INTO bar VALUES ('x', 3), ('y', 2), ('z', 1)",
   541  			// Direct child is SELECT
   542  			"CREATE PROCEDURE p1() SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1",
   543  			// Direct child is BEGIN/END
   544  			"CREATE PROCEDURE p2() BEGIN SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1; END;",
   545  			// Direct child is IF
   546  			"CREATE PROCEDURE p3() IF 0 = 0 THEN SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1; END IF;",
   547  			// Direct child is BEGIN/END with preceding SELECT
   548  			"CREATE PROCEDURE p4() BEGIN SELECT 7; SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1; END;",
   549  			// Direct child is IF with preceding SELECT
   550  			"CREATE PROCEDURE p5() IF 0 = 0 THEN SELECT 7; SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1; END IF;",
   551  		},
   552  		Assertions: []ScriptTestAssertion{
   553  			{ // Enforces that this is the expected output from the query normally
   554  				Query: "SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1",
   555  				Expected: []sql.Row{
   556  					{int64(1), "z", "d"},
   557  					{int64(2), "y", "e"},
   558  					{int64(3), "x", "f"},
   559  				},
   560  			},
   561  			{
   562  				Query: "CALL p1()",
   563  				Expected: []sql.Row{
   564  					{int64(1), "z", "d"},
   565  					{int64(2), "y", "e"},
   566  					{int64(3), "x", "f"},
   567  				},
   568  			},
   569  			{
   570  				Query: "CALL p2()",
   571  				Expected: []sql.Row{
   572  					{int64(1), "z", "d"},
   573  					{int64(2), "y", "e"},
   574  					{int64(3), "x", "f"},
   575  				},
   576  			},
   577  			{
   578  				SkipResultCheckOnServerEngine: true, // tracking issue: https://github.com/dolthub/dolt/issues/6918
   579  				Query:                         "CALL p3()",
   580  				Expected: []sql.Row{
   581  					{int64(1), "z", "d"},
   582  					{int64(2), "y", "e"},
   583  					{int64(3), "x", "f"},
   584  				},
   585  			},
   586  			{
   587  				Query: "CALL p4()",
   588  				Expected: []sql.Row{
   589  					{int64(1), "z", "d"},
   590  					{int64(2), "y", "e"},
   591  					{int64(3), "x", "f"},
   592  				},
   593  			},
   594  			{
   595  				SkipResultCheckOnServerEngine: true, // tracking issue: https://github.com/dolthub/dolt/issues/6918
   596  				Query:                         "CALL p5()",
   597  				Expected: []sql.Row{
   598  					{int64(1), "z", "d"},
   599  					{int64(2), "y", "e"},
   600  					{int64(3), "x", "f"},
   601  				},
   602  			},
   603  		},
   604  	},
   605  	{
   606  		Name: "Nested CALL in IF/ELSE branch",
   607  		SetUpScript: []string{
   608  			"CREATE TABLE t1(pk BIGINT PRIMARY KEY)",
   609  			"INSERT INTO t1 VALUES (2), (3)",
   610  			"CREATE PROCEDURE p1(INOUT x BIGINT) BEGIN IF X = 1 THEN CALL p2(10); ELSEIF x = 2 THEN CALL p2(100); ELSE CALL p2(X); END IF; END;",
   611  			"CREATE PROCEDURE p2(INOUT y BIGINT) BEGIN SELECT pk * y FROM t1 ORDER BY 1; END;",
   612  		},
   613  		Assertions: []ScriptTestAssertion{
   614  			{
   615  				Query: "CALL p1(1)",
   616  				Expected: []sql.Row{
   617  					{int64(20)},
   618  					{int64(30)},
   619  				},
   620  			},
   621  			{
   622  				Query: "CALL p1(2)",
   623  				Expected: []sql.Row{
   624  					{int64(200)},
   625  					{int64(300)},
   626  				},
   627  			},
   628  			{
   629  				Query: "CALL p1(5)",
   630  				Expected: []sql.Row{
   631  					{int64(10)},
   632  					{int64(15)},
   633  				},
   634  			},
   635  		},
   636  	},
   637  	{
   638  		Name: "INSERT INTO SELECT doesn't override SELECT",
   639  		SetUpScript: []string{
   640  			"CREATE TABLE t1(pk BIGINT PRIMARY KEY)",
   641  			"CREATE TABLE t2(pk BIGINT PRIMARY KEY)",
   642  			"INSERT INTO t1 VALUES (2), (3)",
   643  			"INSERT INTO t2 VALUES (1)",
   644  			`CREATE PROCEDURE p1(x BIGINT)
   645  BEGIN
   646  	DELETE FROM t2 WHERE pk > 1;
   647  	INSERT INTO t2 SELECT pk FROM t1;
   648  	SELECT * FROM t2;
   649  	INSERT INTO t2 SELECT pk + 10 FROM t1;
   650  	IF x = 1 THEN
   651  		SELECT * FROM t2;
   652  	END IF;
   653  END;`,
   654  		},
   655  		Assertions: []ScriptTestAssertion{
   656  			{
   657  				Query: "CALL p1(0)",
   658  				Expected: []sql.Row{
   659  					{int64(1)},
   660  					{int64(2)},
   661  					{int64(3)},
   662  				},
   663  			},
   664  			{
   665  				Query: "CALL p1(1)",
   666  				Expected: []sql.Row{
   667  					{int64(1)},
   668  					{int64(2)},
   669  					{int64(3)},
   670  					{int64(12)},
   671  					{int64(13)},
   672  				},
   673  			},
   674  		},
   675  	},
   676  	{
   677  		Name: "Parameters resolve inside of INSERT",
   678  		SetUpScript: []string{
   679  			`CREATE TABLE items (
   680  	id INT PRIMARY KEY AUTO_INCREMENT,
   681  	item TEXT NOT NULL
   682  );`,
   683  			`CREATE PROCEDURE add_item (IN txt TEXT) MODIFIES SQL DATA
   684  INSERT INTO items (item) VALUES (txt)`,
   685  		},
   686  		Assertions: []ScriptTestAssertion{
   687  			{
   688  				SkipResultCheckOnServerEngine: true, // call depends on stored procedure stmt for whether to use 'query' or 'exec' from go sql driver.
   689  				Query:                         "CALL add_item('A test item');",
   690  				Expected: []sql.Row{
   691  					{types.OkResult{RowsAffected: 1, InsertID: 1}},
   692  				},
   693  			},
   694  			{
   695  				Query: "SELECT * FROM items;",
   696  				Expected: []sql.Row{
   697  					{1, "A test item"},
   698  				},
   699  			},
   700  		},
   701  	},
   702  	{
   703  		Name: "Parameters resolve inside of SELECT UNION",
   704  		SetUpScript: []string{
   705  			"CREATE TABLE t1(pk BIGINT PRIMARY KEY, v1 BIGINT)",
   706  			"INSERT INTO t1 VALUES (1, 2)",
   707  			"SELECT pk, v1 FROM t1 UNION SELECT 1, 2;",
   708  			`CREATE PROCEDURE p1(x BIGINT, y BIGINT)
   709  BEGIN
   710  	SELECT pk+x, v1+y FROM t1 UNION SELECT x, y;
   711  END;`,
   712  			`CREATE PROCEDURE p2(u BIGINT, v BIGINT) SELECT pk+u, v1+v FROM t1 UNION SELECT u, v;`,
   713  		},
   714  		Assertions: []ScriptTestAssertion{
   715  			{
   716  				Query: "CALL p1(3, 4)",
   717  				Expected: []sql.Row{
   718  					{4, 6},
   719  					{3, 4},
   720  				},
   721  			},
   722  			{
   723  				Query: "CALL p2(5, 6)",
   724  				Expected: []sql.Row{
   725  					{6, 8},
   726  					{5, 6},
   727  				},
   728  			},
   729  		},
   730  	},
   731  	{
   732  		Name: "Parameters resolve inside of REPLACE",
   733  		SetUpScript: []string{
   734  			`CREATE TABLE items (
   735  	id INT PRIMARY KEY AUTO_INCREMENT,
   736  	item INT NOT NULL
   737  );`,
   738  			`CREATE PROCEDURE add_item (IN num INT) MODIFIES SQL DATA
   739  BEGIN
   740  	REPLACE INTO items (item) VALUES (5), (num), (num+1);
   741  END`,
   742  		},
   743  		Assertions: []ScriptTestAssertion{
   744  			{
   745  				SkipResultCheckOnServerEngine: true, // call depends on stored procedure stmt for whether to use 'query' or 'exec' from go sql driver.
   746  				Query:                         "CALL add_item(6);",
   747  				Expected: []sql.Row{
   748  					{types.NewOkResult(3)},
   749  				},
   750  			},
   751  			{
   752  				Query: "SELECT * FROM items ORDER BY 1;",
   753  				Expected: []sql.Row{
   754  					{1, 5},
   755  					{2, 6},
   756  					{3, 7},
   757  				},
   758  			},
   759  		},
   760  	},
   761  	{
   762  		Name: "Parameters resolve inside of INSERT INTO SELECT",
   763  		SetUpScript: []string{
   764  			"CREATE TABLE t1(pk BIGINT PRIMARY KEY)",
   765  			"CREATE TABLE t2(pk BIGINT PRIMARY KEY)",
   766  			"INSERT INTO t1 VALUES (1), (2)",
   767  			`CREATE PROCEDURE p1(x BIGINT)
   768  BEGIN
   769  	TRUNCATE t2;
   770  	INSERT INTO t2 SELECT pk+x FROM t1;
   771  	SELECT * FROM t2;
   772  END;`,
   773  		},
   774  		Assertions: []ScriptTestAssertion{
   775  			{
   776  				Query: "CALL p1(0)",
   777  				Expected: []sql.Row{
   778  					{int64(1)},
   779  					{int64(2)},
   780  				},
   781  			},
   782  			{
   783  				Query: "CALL p1(5)",
   784  				Expected: []sql.Row{
   785  					{int64(6)},
   786  					{int64(7)},
   787  				},
   788  			},
   789  		},
   790  	},
   791  	{
   792  		Name: "Subquery on SET user variable captures parameter",
   793  		SetUpScript: []string{
   794  			`CREATE PROCEDURE p1(x VARCHAR(20)) BEGIN SET @randomvar = (SELECT LENGTH(x)); SELECT @randomvar; END;`,
   795  		},
   796  		Assertions: []ScriptTestAssertion{
   797  			{
   798  				SkipResultCheckOnServerEngine: true, // the user var has null type, which returns nil value over the wire.
   799  				Query:                         "CALL p1('hi')",
   800  				Expected: []sql.Row{
   801  					{int64(2)},
   802  				},
   803  			},
   804  			{
   805  				Query: "CALL p1('hello')",
   806  				Expected: []sql.Row{
   807  					{int64(5)},
   808  				},
   809  			},
   810  		},
   811  	},
   812  	{
   813  		Name: "Simple SELECT INTO",
   814  		SetUpScript: []string{
   815  			"CREATE PROCEDURE testabc(IN x DOUBLE, IN y DOUBLE, OUT abc DOUBLE) SELECT x*y INTO abc",
   816  			"CALL testabc(2, 3, @res1)",
   817  			"CALL testabc(9, 9.5, @res2)",
   818  		},
   819  		Assertions: []ScriptTestAssertion{
   820  			{
   821  				Query:    "SELECT @res1",
   822  				Expected: []sql.Row{{float64(6)}},
   823  			},
   824  			{
   825  				Query:    "SELECT @res2",
   826  				Expected: []sql.Row{{float64(85.5)}},
   827  			},
   828  		},
   829  	},
   830  	{
   831  		Name: "Multiple variables in SELECT INTO",
   832  		SetUpScript: []string{
   833  			"CREATE PROCEDURE new_proc(IN x DOUBLE, IN y DOUBLE, OUT abc DOUBLE, OUT def DOUBLE) SELECT x*y, x+y INTO abc, def",
   834  			"CALL new_proc(2, 3, @res1, @res2)",
   835  			"CALL new_proc(9, 9.5, @res3, @res4)",
   836  		},
   837  		Assertions: []ScriptTestAssertion{
   838  			{
   839  				Query:    "SELECT @res1, @res2",
   840  				Expected: []sql.Row{{float64(6), float64(5)}},
   841  			},
   842  			{
   843  				Query:    "SELECT @res3, @res4",
   844  				Expected: []sql.Row{{float64(85.5), float64(18.5)}},
   845  			},
   846  		},
   847  	},
   848  	{
   849  		Name: "SELECT INTO with condition",
   850  		SetUpScript: []string{
   851  			"CREATE TABLE inventory (item_id int primary key, shelf_id int, items varchar(100))",
   852  			"INSERT INTO inventory VALUES (1, 1, 'a'), (2, 1, 'b'), (3, 2, 'c'), (4, 1, 'd'), (5, 4, 'e')",
   853  			"CREATE PROCEDURE in_stock (IN p_id INT, OUT p_count INT) SELECT COUNT(*) FROM inventory WHERE shelf_id = p_id INTO p_count",
   854  			"CALL in_stock(1, @shelf1)",
   855  			"CALL in_stock(2, @shelf2)",
   856  			"CALL in_stock(3, @shelf3)",
   857  		},
   858  		Assertions: []ScriptTestAssertion{
   859  			{
   860  				Query:    "SELECT @shelf1, @shelf2, @shelf3",
   861  				Expected: []sql.Row{{3, 1, 0}},
   862  			},
   863  		},
   864  	},
   865  	{
   866  		Name: "SELECT INTO with group by, order by and limit",
   867  		SetUpScript: []string{
   868  			"CREATE TABLE inventory (item_id int primary key, shelf_id int, item varchar(10))",
   869  			"INSERT INTO inventory VALUES (1, 1, 'a'), (2, 1, 'b'), (3, 2, 'c'), (4, 1, 'd'), (5, 4, 'e')",
   870  			"CREATE PROCEDURE first_shelf (OUT p_count INT) SELECT COUNT(*) FROM inventory GROUP BY shelf_id ORDER BY shelf_id ASC LIMIT 1 INTO p_count",
   871  			"CREATE PROCEDURE last_shelf (OUT p_count INT) SELECT COUNT(*) FROM inventory GROUP BY shelf_id ORDER BY shelf_id DESC LIMIT 1 INTO p_count",
   872  			"CALL first_shelf(@result1)",
   873  			"CALL last_shelf(@result2)",
   874  		},
   875  		Assertions: []ScriptTestAssertion{
   876  			{
   877  				Query:    "SELECT @result1",
   878  				Expected: []sql.Row{{3}},
   879  			},
   880  			{
   881  				Query:    "SELECT @result2",
   882  				Expected: []sql.Row{{1}},
   883  			},
   884  		},
   885  	},
   886  	{
   887  		Name: "multiple SELECT INTO in begin end block",
   888  		SetUpScript: []string{
   889  			"CREATE TABLE inventory (item_id int primary key, shelf_id int, item varchar(10))",
   890  			"INSERT INTO inventory VALUES (1, 1, 'a'), (2, 1, 'b'), (3, 2, 'c'), (4, 1, 'd'), (5, 4, 'e')",
   891  			"CREATE PROCEDURE random_info(OUT p_count1 INT, OUT p_count2 VARCHAR(10)) BEGIN " +
   892  				"SELECT COUNT(*) FROM inventory GROUP BY shelf_id ORDER BY shelf_id ASC LIMIT 1 INTO p_count1;" +
   893  				"SELECT item INTO p_count2 FROM inventory WHERE shelf_id = 1 ORDER BY item DESC LIMIT 1; " +
   894  				"END",
   895  			"CALL random_info(@s1, @s2)",
   896  		},
   897  		Assertions: []ScriptTestAssertion{
   898  			{
   899  				Query:    "SELECT @s1, @s2",
   900  				Expected: []sql.Row{{3, "d"}},
   901  			},
   902  		},
   903  	},
   904  	{
   905  		Name: "multiple statement with single SELECT INTO in begin end block",
   906  		SetUpScript: []string{
   907  			"CREATE TABLE inventory (item_id int primary key, shelf_id int, item varchar(10))",
   908  			"INSERT INTO inventory VALUES (1, 1, 'a'), (2, 1, 'b'), (3, 2, 'c'), (4, 1, 'd'), (5, 4, 'e')",
   909  			`CREATE PROCEDURE count_and_print(IN p_shelf_id INT, OUT p_count INT) BEGIN
   910  SELECT item FROM inventory WHERE shelf_id = p_shelf_id ORDER BY item ASC;
   911  SELECT COUNT(*) INTO p_count FROM inventory WHERE shelf_id = p_shelf_id;
   912  END`,
   913  		},
   914  		Assertions: []ScriptTestAssertion{
   915  			{
   916  				Query:    "CALL count_and_print(1, @total)",
   917  				Expected: []sql.Row{{"a"}, {"b"}, {"d"}},
   918  			},
   919  			{
   920  				Query:    "SELECT @total",
   921  				Expected: []sql.Row{{3}},
   922  			},
   923  		},
   924  	},
   925  	{
   926  		Name: "DECLARE variables, proper nesting support",
   927  		SetUpScript: []string{
   928  			`CREATE PROCEDURE p1(OUT x BIGINT)
   929  BEGIN
   930  	DECLARE a INT;
   931  	DECLARE b MEDIUMINT;
   932  	DECLARE c VARCHAR(20);
   933  	SELECT 1, 2, 'a' INTO a, b, c;
   934  	BEGIN
   935  		DECLARE b MEDIUMINT;
   936  		SET a = 4;
   937  		SET b = 5;
   938  	END;
   939  	SET x = a + b;
   940  	SELECT a, b, c;
   941  END;`,
   942  		},
   943  		Assertions: []ScriptTestAssertion{
   944  			{
   945  				Query: "CALL p1(@x);",
   946  				Expected: []sql.Row{
   947  					{4, 2, "a"},
   948  				},
   949  			},
   950  			{
   951  				Query: "SELECT @x;",
   952  				Expected: []sql.Row{
   953  					{6},
   954  				},
   955  			},
   956  		},
   957  	},
   958  	{
   959  		Name: "DECLARE multiple variables, same statement",
   960  		SetUpScript: []string{
   961  			`CREATE PROCEDURE p1()
   962  BEGIN
   963  	DECLARE a, b, c INT;
   964  	SELECT 2, 3, 4 INTO a, b, c;
   965  	SELECT a + b + c;
   966  END;`,
   967  		},
   968  		Assertions: []ScriptTestAssertion{
   969  			{
   970  				Query: "CALL p1();",
   971  				Expected: []sql.Row{
   972  					{9},
   973  				},
   974  			},
   975  		},
   976  	},
   977  	{
   978  		Name: "DECLARE variable shadows parameter",
   979  		SetUpScript: []string{
   980  			`CREATE PROCEDURE p1(INOUT x INT)
   981  BEGIN
   982  	DECLARE x INT;
   983  	SET x = 5;
   984  END;`,
   985  		},
   986  		Assertions: []ScriptTestAssertion{
   987  			{
   988  				Query:    "SET @x = 2;",
   989  				Expected: []sql.Row{{}},
   990  			},
   991  			{
   992  				Query:    "CALL p1(@x);",
   993  				Expected: []sql.Row{{}},
   994  			},
   995  			{
   996  				Query: "SELECT @x;",
   997  				Expected: []sql.Row{
   998  					{2},
   999  				},
  1000  			},
  1001  		},
  1002  	},
  1003  	{
  1004  		Name: "DECLARE CONDITION",
  1005  		SetUpScript: []string{
  1006  			`CREATE PROCEDURE p1(x INT)
  1007  BEGIN
  1008  	DECLARE specialty CONDITION FOR SQLSTATE '45000';
  1009  	DECLARE specialty2 CONDITION FOR SQLSTATE '02000';
  1010  	IF x = 0 THEN
  1011  		SIGNAL SQLSTATE '01000';
  1012  	ELSEIF x = 1 THEN
  1013  		SIGNAL SQLSTATE '45000'
  1014  			SET MESSAGE_TEXT = 'A custom error occurred 1';
  1015  	ELSEIF x = 2 THEN
  1016  		SIGNAL specialty
  1017  			SET MESSAGE_TEXT = 'A custom error occurred 2', MYSQL_ERRNO = 1002;
  1018  	ELSEIF x = 3 THEN
  1019  		SIGNAL specialty;
  1020  	ELSEIF x = 4 THEN
  1021  		SIGNAL specialty2;
  1022  	ELSE
  1023  		SIGNAL SQLSTATE '01000'
  1024  			SET MESSAGE_TEXT = 'A warning occurred', MYSQL_ERRNO = 1000;
  1025  		SIGNAL SQLSTATE '45000'
  1026  			SET MESSAGE_TEXT = 'An error occurred', MYSQL_ERRNO = 1001;
  1027  	END IF;
  1028  	BEGIN
  1029  		DECLARE specialty3 CONDITION FOR SQLSTATE '45000';
  1030  	END;
  1031  END;`,
  1032  		},
  1033  		Assertions: []ScriptTestAssertion{
  1034  			{
  1035  				Query:          "CALL p1(0)",
  1036  				ExpectedErrStr: "warnings not yet implemented",
  1037  			},
  1038  			{
  1039  				Query:          "CALL p1(1)",
  1040  				ExpectedErrStr: "A custom error occurred 1 (errno 1644) (sqlstate 45000)",
  1041  			},
  1042  			{
  1043  				Query:          "CALL p1(2)",
  1044  				ExpectedErrStr: "A custom error occurred 2 (errno 1002) (sqlstate 45000)",
  1045  			},
  1046  			{
  1047  				Query:          "CALL p1(3)",
  1048  				ExpectedErrStr: "Unhandled user-defined exception condition (errno 1644) (sqlstate 45000)",
  1049  			},
  1050  			{
  1051  				Query:          "CALL p1(4)",
  1052  				ExpectedErrStr: "Unhandled user-defined not found condition (errno 1643) (sqlstate 02000)",
  1053  			},
  1054  		},
  1055  	},
  1056  	{
  1057  		Name: "DECLARE CONDITION nesting priority",
  1058  		SetUpScript: []string{
  1059  			`CREATE PROCEDURE p1(x INT)
  1060  BEGIN
  1061  	DECLARE cond_name CONDITION FOR SQLSTATE '02000';
  1062  	BEGIN
  1063  		DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1064  		IF x = 0 THEN
  1065  			SIGNAL cond_name;
  1066  		END IF;
  1067  	END;
  1068  	SIGNAL cond_name;
  1069  END;`,
  1070  			`CREATE PROCEDURE p2(x INT)
  1071  BEGIN
  1072  	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1073  	BEGIN
  1074  		DECLARE cond_name CONDITION FOR SQLSTATE '02000';
  1075  		IF x = 0 THEN
  1076  			SIGNAL cond_name;
  1077  		END IF;
  1078  	END;
  1079  	SIGNAL cond_name;
  1080  END;`,
  1081  		},
  1082  		Assertions: []ScriptTestAssertion{
  1083  			{
  1084  				Query:          "CALL p1(0)",
  1085  				ExpectedErrStr: "Unhandled user-defined exception condition (errno 1644) (sqlstate 45000)",
  1086  			},
  1087  			{
  1088  				Query:          "CALL p1(1)",
  1089  				ExpectedErrStr: "Unhandled user-defined not found condition (errno 1643) (sqlstate 02000)",
  1090  			},
  1091  			{
  1092  				Query:          "CALL p2(0)",
  1093  				ExpectedErrStr: "Unhandled user-defined not found condition (errno 1643) (sqlstate 02000)",
  1094  			},
  1095  			{
  1096  				Query:          "CALL p2(1)",
  1097  				ExpectedErrStr: "Unhandled user-defined exception condition (errno 1644) (sqlstate 45000)",
  1098  			},
  1099  		},
  1100  	},
  1101  	{
  1102  		Name: "FETCH multiple rows",
  1103  		SetUpScript: []string{
  1104  			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
  1105  			`CREATE PROCEDURE p1()
  1106  BEGIN
  1107  	DECLARE a, b INT;
  1108  	DECLARE cur1 CURSOR FOR SELECT pk FROM t1;
  1109  	DELETE FROM t1;
  1110      INSERT INTO t1 VALUES (1), (2);
  1111      OPEN cur1;
  1112      FETCH cur1 INTO a;
  1113      FETCH cur1 INTO b;
  1114      CLOSE cur1;
  1115      SELECT a, b;
  1116  END;`,
  1117  		},
  1118  		Assertions: []ScriptTestAssertion{
  1119  			{
  1120  				Query: "CALL p1();",
  1121  				Expected: []sql.Row{
  1122  					{1, 2},
  1123  				},
  1124  			},
  1125  		},
  1126  	},
  1127  	{
  1128  		Name: "FETCH with multiple opens and closes",
  1129  		SetUpScript: []string{
  1130  			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
  1131  			`CREATE PROCEDURE p1()
  1132  BEGIN
  1133  	DECLARE a, b INT;
  1134  	DECLARE cur1 CURSOR FOR SELECT pk FROM t1;
  1135  	DELETE FROM t1;
  1136      INSERT INTO t1 VALUES (1);
  1137      OPEN cur1;
  1138      FETCH cur1 INTO a;
  1139      CLOSE cur1;
  1140  	UPDATE t1 SET pk = 2;
  1141      OPEN cur1;
  1142      FETCH cur1 INTO b;
  1143      CLOSE cur1;
  1144      SELECT a, b;
  1145  END;`,
  1146  		},
  1147  		Assertions: []ScriptTestAssertion{
  1148  			{
  1149  				Query: "CALL p1();",
  1150  				Expected: []sql.Row{
  1151  					{1, 2},
  1152  				},
  1153  			},
  1154  		},
  1155  	},
  1156  	{
  1157  		Name: "issue 7458: proc params as limit values",
  1158  		SetUpScript: []string{
  1159  			"create table t (i int primary key);",
  1160  			"insert into t values (0), (1), (2), (3)",
  1161  			"CREATE PROCEDURE limited(the_limit int, the_offset bigint) SELECT * FROM t LIMIT the_limit OFFSET the_offset",
  1162  			"CREATE PROCEDURE limited_uns(the_limit int unsigned, the_offset bigint unsigned) SELECT * FROM t LIMIT the_limit OFFSET the_offset",
  1163  		},
  1164  		Assertions: []ScriptTestAssertion{
  1165  			{
  1166  				Query:    "call limited(1,0)",
  1167  				Expected: []sql.Row{{0}},
  1168  			},
  1169  			{
  1170  				Query:    "call limited(2,0)",
  1171  				Expected: []sql.Row{{0}, {1}},
  1172  			},
  1173  			{
  1174  				Query:    "call limited(2,2)",
  1175  				Expected: []sql.Row{{2}, {3}},
  1176  			},
  1177  			{
  1178  				Query:    "call limited_uns(2,2)",
  1179  				Expected: []sql.Row{{2}, {3}},
  1180  			},
  1181  			{
  1182  				Query:          "CREATE PROCEDURE limited_inv(the_limit CHAR(3), the_offset INT) SELECT * FROM t LIMIT the_limit OFFSET the_offset",
  1183  				ExpectedErrStr: "the variable 'the_limit' has a non-integer based type: char(3) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin",
  1184  			},
  1185  			{
  1186  				Query:          "CREATE PROCEDURE limited_inv(the_limit float, the_offset INT) SELECT * FROM t LIMIT the_limit OFFSET the_offset",
  1187  				ExpectedErrStr: "the variable 'the_limit' has a non-integer based type: float",
  1188  			},
  1189  		},
  1190  	},
  1191  	{
  1192  		Name: "FETCH captures state at OPEN",
  1193  		SetUpScript: []string{
  1194  			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
  1195  			`CREATE PROCEDURE p1()
  1196  BEGIN
  1197  	DECLARE a, b INT;
  1198  	DECLARE cur1 CURSOR FOR SELECT pk FROM t1;
  1199  	DELETE FROM t1;
  1200      INSERT INTO t1 VALUES (1);
  1201      OPEN cur1;
  1202  	UPDATE t1 SET pk = 2;
  1203      FETCH cur1 INTO a;
  1204      CLOSE cur1;
  1205      OPEN cur1;
  1206      FETCH cur1 INTO b;
  1207      CLOSE cur1;
  1208      SELECT a, b;
  1209  END;`,
  1210  		},
  1211  		Assertions: []ScriptTestAssertion{
  1212  			{
  1213  				Query: "CALL p1();",
  1214  				Expected: []sql.Row{
  1215  					{1, 2},
  1216  				},
  1217  			},
  1218  		},
  1219  	},
  1220  	{
  1221  		Name: "FETCH implicitly closes",
  1222  		SetUpScript: []string{
  1223  			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
  1224  			`CREATE PROCEDURE p1()
  1225  BEGIN
  1226  	DECLARE a INT;
  1227  	DECLARE cur1 CURSOR FOR SELECT pk FROM t1;
  1228  	DELETE FROM t1;
  1229      INSERT INTO t1 VALUES (4);
  1230      OPEN cur1;
  1231      FETCH cur1 INTO a;
  1232      SELECT a;
  1233  END;`,
  1234  		},
  1235  		Assertions: []ScriptTestAssertion{
  1236  			{
  1237  				Query: "CALL p1();",
  1238  				Expected: []sql.Row{
  1239  					{4},
  1240  				},
  1241  			},
  1242  		},
  1243  	},
  1244  	{
  1245  		Name: "SQLEXCEPTION declare handler",
  1246  		SetUpScript: []string{
  1247  			`DROP TABLE IF EXISTS t1;`,
  1248  			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
  1249  			`CREATE PROCEDURE eof()
  1250  BEGIN
  1251  	DECLARE a, b INT DEFAULT 1;
  1252      DECLARE cur1 CURSOR FOR SELECT * FROM t1;
  1253      OPEN cur1;
  1254      BEGIN
  1255  		DECLARE EXIT HANDLER FOR SQLEXCEPTION SET a = 7;
  1256  		tloop: LOOP
  1257  			FETCH cur1 INTO b;
  1258              IF a > 1000 THEN
  1259  				LEAVE tloop;
  1260              END IF;
  1261  		END LOOP;
  1262      END;
  1263      CLOSE cur1;
  1264      SELECT a;
  1265  END;`,
  1266  			`CREATE PROCEDURE duplicate_key()
  1267  BEGIN
  1268  	DECLARE a, b INT DEFAULT 1;
  1269      BEGIN
  1270  		DECLARE EXIT HANDLER FOR SQLEXCEPTION SET a = 7;
  1271  		INSERT INTO t1 values (0);
  1272      END;
  1273      SELECT a;
  1274  END;`,
  1275  		},
  1276  		Assertions: []ScriptTestAssertion{
  1277  			{
  1278  				Query:    "CALL eof();",
  1279  				Expected: []sql.Row{},
  1280  			},
  1281  			{
  1282  				Query:    "CALL duplicate_key();",
  1283  				Expected: []sql.Row{{1}},
  1284  			},
  1285  			{
  1286  				Query:    "CALL duplicate_key();",
  1287  				Expected: []sql.Row{{7}},
  1288  			},
  1289  		},
  1290  	},
  1291  	{
  1292  		Name: "DECLARE HANDLERs exit according to the block they were declared in",
  1293  		SetUpScript: []string{
  1294  			`DROP TABLE IF EXISTS t1;`,
  1295  			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
  1296  			`CREATE PROCEDURE outer_declare()
  1297  BEGIN
  1298  	DECLARE a, b INT DEFAULT 1;
  1299      DECLARE cur1 CURSOR FOR SELECT * FROM t1;
  1300  	DECLARE EXIT HANDLER FOR NOT FOUND SET a = 1001;
  1301      OPEN cur1;
  1302      BEGIN
  1303  		tloop: LOOP
  1304  			FETCH cur1 INTO b;
  1305              IF a > 1000 THEN
  1306  				LEAVE tloop;
  1307              END IF;
  1308  		END LOOP;
  1309      END;
  1310      CLOSE cur1;
  1311      SELECT a;
  1312  END;`,
  1313  			`CREATE PROCEDURE inner_declare()
  1314  BEGIN
  1315  	DECLARE a, b INT DEFAULT 1;
  1316      DECLARE cur1 CURSOR FOR SELECT * FROM t1;
  1317  	DECLARE EXIT HANDLER FOR NOT FOUND SET a = a + 1;
  1318      OPEN cur1;
  1319      BEGIN
  1320  		DECLARE EXIT HANDLER FOR NOT FOUND SET a = 1001;
  1321  		tloop: LOOP
  1322  			FETCH cur1 INTO b;
  1323              IF a > 1000 THEN
  1324  				LEAVE tloop;
  1325              END IF;
  1326  		END LOOP;
  1327      END;
  1328      CLOSE cur1;
  1329      SELECT a;
  1330  END;`,
  1331  		},
  1332  		Assertions: []ScriptTestAssertion{
  1333  			{
  1334  				Query:    "CALL outer_declare();",
  1335  				Expected: []sql.Row{},
  1336  			},
  1337  			{
  1338  				Query: "CALL inner_declare();",
  1339  				Expected: []sql.Row{
  1340  					{1001},
  1341  				},
  1342  			},
  1343  		},
  1344  	},
  1345  	{
  1346  		Name: "Labeled BEGIN...END",
  1347  		SetUpScript: []string{
  1348  			`CREATE PROCEDURE p1()
  1349  BEGIN
  1350  	DECLARE a INT DEFAULT 1;
  1351  	tblock: BEGIN
  1352  		LOOP
  1353  			SET a = a + 3;
  1354  			LEAVE tblock;
  1355  		END LOOP;
  1356  	END;
  1357  	SELECT a;
  1358  END;`,
  1359  		},
  1360  		Assertions: []ScriptTestAssertion{
  1361  			{
  1362  				Query: "CALL p1();",
  1363  				Expected: []sql.Row{
  1364  					{4},
  1365  				},
  1366  			},
  1367  			{
  1368  				Query:       `CREATE PROCEDURE p2() BEGIN tblock: BEGIN ITERATE tblock; END; END;`,
  1369  				ExpectedErr: sql.ErrLoopLabelNotFound,
  1370  			},
  1371  		},
  1372  	},
  1373  	{
  1374  		Name: "REPEAT runs loop before first evaluation",
  1375  		SetUpScript: []string{
  1376  			`CREATE PROCEDURE p1()
  1377  BEGIN
  1378  	DECLARE a INT DEFAULT 10;
  1379  	REPEAT
  1380  		SET a = a * 5;
  1381  	UNTIL a > 0
  1382  	END REPEAT;
  1383      SELECT a;
  1384  END;`,
  1385  		},
  1386  		Assertions: []ScriptTestAssertion{
  1387  			{
  1388  				Query: "CALL p1();",
  1389  				Expected: []sql.Row{
  1390  					{50},
  1391  				},
  1392  			},
  1393  		},
  1394  	},
  1395  	{
  1396  		Name: "WHILE runs evaluation before first loop",
  1397  		SetUpScript: []string{
  1398  			`CREATE PROCEDURE p1()
  1399  BEGIN
  1400  	DECLARE a INT DEFAULT 10;
  1401  	WHILE a < 10 DO
  1402  		SET a = a * 10;
  1403  	END WHILE;
  1404      SELECT a;
  1405  END;`,
  1406  		},
  1407  		Assertions: []ScriptTestAssertion{
  1408  			{
  1409  				Query: "CALL p1();",
  1410  				Expected: []sql.Row{
  1411  					{10},
  1412  				},
  1413  			},
  1414  		},
  1415  	},
  1416  	{
  1417  		Name: "ITERATE and LEAVE LOOP",
  1418  		SetUpScript: []string{
  1419  			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
  1420  			`INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9)`,
  1421  			`CREATE PROCEDURE p1()
  1422  BEGIN
  1423  	DECLARE a, b INT DEFAULT 1;
  1424      DECLARE cur1 CURSOR FOR SELECT * FROM t1;
  1425  	DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;
  1426      OPEN cur1;
  1427      BEGIN
  1428  		tloop: LOOP
  1429  			FETCH cur1 INTO b;
  1430  			SET a = (a + b) * 10;
  1431              IF a < 1000 THEN
  1432  				ITERATE tloop;
  1433  			ELSE
  1434  				LEAVE tloop;
  1435              END IF;
  1436  		END LOOP;
  1437      END;
  1438      CLOSE cur1;
  1439      SELECT a;
  1440  END;`,
  1441  		},
  1442  		Assertions: []ScriptTestAssertion{
  1443  			{
  1444  				Query: "CALL p1();",
  1445  				Expected: []sql.Row{
  1446  					{2230},
  1447  				},
  1448  			},
  1449  		},
  1450  	},
  1451  	{
  1452  		Name: "ITERATE and LEAVE REPEAT",
  1453  		SetUpScript: []string{
  1454  			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
  1455  			`INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9)`,
  1456  			`CREATE PROCEDURE p1()
  1457  BEGIN
  1458  	DECLARE a, b INT DEFAULT 1;
  1459      DECLARE cur1 CURSOR FOR SELECT * FROM t1;
  1460  	DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;
  1461      OPEN cur1;
  1462      BEGIN
  1463  		tloop: REPEAT
  1464  			FETCH cur1 INTO b;
  1465  			SET a = (a + b) * 10;
  1466              IF a < 1000 THEN
  1467  				ITERATE tloop;
  1468  			ELSE
  1469  				LEAVE tloop;
  1470              END IF;
  1471  		UNTIL false
  1472  		END REPEAT;
  1473      END;
  1474      CLOSE cur1;
  1475      SELECT a;
  1476  END;`,
  1477  		},
  1478  		Assertions: []ScriptTestAssertion{
  1479  			{
  1480  				Query: "CALL p1();",
  1481  				Expected: []sql.Row{
  1482  					{2230},
  1483  				},
  1484  			},
  1485  		},
  1486  	},
  1487  	{
  1488  		Name: "ITERATE and LEAVE WHILE",
  1489  		SetUpScript: []string{
  1490  			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
  1491  			`INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9)`,
  1492  			`CREATE PROCEDURE p1()
  1493  BEGIN
  1494  	DECLARE a, b INT DEFAULT 1;
  1495      DECLARE cur1 CURSOR FOR SELECT * FROM t1;
  1496  	DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;
  1497      OPEN cur1;
  1498      BEGIN
  1499  		tloop: WHILE true DO
  1500  			FETCH cur1 INTO b;
  1501  			SET a = (a + b) * 10;
  1502              IF a < 1000 THEN
  1503  				ITERATE tloop;
  1504  			ELSE
  1505  				LEAVE tloop;
  1506              END IF;
  1507  		END WHILE;
  1508      END;
  1509      CLOSE cur1;
  1510      SELECT a;
  1511  END;`,
  1512  		},
  1513  		Assertions: []ScriptTestAssertion{
  1514  			{
  1515  				Query: "CALL p1();",
  1516  				Expected: []sql.Row{
  1517  					{2230},
  1518  				},
  1519  			},
  1520  		},
  1521  	},
  1522  	{
  1523  		Name: "Handle setting an uninitialized user variable",
  1524  		SetUpScript: []string{
  1525  			`CREATE PROCEDURE p1(INOUT param VARCHAR(10))
  1526  BEGIN
  1527  	SELECT param;
  1528  	SET param = '5';
  1529  END`,
  1530  		},
  1531  		Assertions: []ScriptTestAssertion{
  1532  			{
  1533  				Query: "CALL p1(@uservar4);",
  1534  				Expected: []sql.Row{
  1535  					{nil},
  1536  				},
  1537  			},
  1538  			{
  1539  				Query: "SELECT @uservar4;",
  1540  				Expected: []sql.Row{
  1541  					{"5"},
  1542  				},
  1543  			},
  1544  		},
  1545  	},
  1546  	{
  1547  		Name: "Dolt Issue #4980",
  1548  		SetUpScript: []string{
  1549  			`CREATE TABLE person_cal_entries (id VARCHAR(36) PRIMARY KEY, cal_entry_id_fk VARCHAR(36), person_id_fk VARCHAR(36));`,
  1550  			`CREATE TABLE personnel (id VARCHAR(36) PRIMARY KEY, event_id VARCHAR(36));`,
  1551  			`CREATE TABLE season_participants (person_id_fk VARCHAR(36), season_id_fk VARCHAR(36));`,
  1552  			`CREATE TABLE cal_entries (id VARCHAR(36) PRIMARY KEY, season_id_fk VARCHAR(36));`,
  1553  			`INSERT INTO personnel VALUES ('6140e23e-7b9b-11ed-a1eb-0242ac120002', 'c546abc4-7b9b-11ed-a1eb-0242ac120002');`,
  1554  			`INSERT INTO season_participants VALUES ('6140e23e-7b9b-11ed-a1eb-0242ac120002', '46d7041e-7b9b-11ed-a1eb-0242ac120002');`,
  1555  			`INSERT INTO cal_entries VALUES ('cb8ba301-6c27-4bf8-b99b-617082d72621', '46d7041e-7b9b-11ed-a1eb-0242ac120002');`,
  1556  			`CREATE PROCEDURE create_cal_entries_for_event(IN event_id VARCHAR(36))
  1557  BEGIN
  1558      INSERT INTO person_cal_entries (id, cal_entry_id_fk, person_id_fk)
  1559      SELECT 'd17cb898-7b9b-11ed-a1eb-0242ac120002' as id, event_id as cal_entry_id_fk, id as person_id_fk
  1560      FROM personnel
  1561      WHERE id IN (
  1562          SELECT person_id_fk
  1563          FROM season_participants
  1564          WHERE season_id_fk = (
  1565              SELECT season_id_fk
  1566              FROM cal_entries
  1567              WHERE id = event_id
  1568          )
  1569      );
  1570  END`,
  1571  		},
  1572  		Assertions: []ScriptTestAssertion{
  1573  			{
  1574  				SkipResultCheckOnServerEngine: true, // call depends on stored procedure stmt for whether to use 'query' or 'exec' from go sql driver.
  1575  				Query:                         "call create_cal_entries_for_event('cb8ba301-6c27-4bf8-b99b-617082d72621');",
  1576  				Expected: []sql.Row{
  1577  					{types.NewOkResult(1)},
  1578  				},
  1579  			},
  1580  			{
  1581  				Query: "SELECT * FROM person_cal_entries;",
  1582  				Expected: []sql.Row{
  1583  					{"d17cb898-7b9b-11ed-a1eb-0242ac120002", "cb8ba301-6c27-4bf8-b99b-617082d72621", "6140e23e-7b9b-11ed-a1eb-0242ac120002"},
  1584  				},
  1585  			},
  1586  		},
  1587  	},
  1588  	{
  1589  		Name: "HANDLERs ignore variables declared after them",
  1590  		SetUpScript: []string{
  1591  			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
  1592  			`CREATE PROCEDURE p1()
  1593  BEGIN
  1594  	DECLARE dvar BIGINT DEFAULT 1;
  1595  	DECLARE cur1 CURSOR FOR SELECT * FROM t1;
  1596      OPEN cur1;
  1597  	BEGIN
  1598  		DECLARE EXIT HANDLER FOR NOT FOUND SET dvar = 10;
  1599  		BEGIN
  1600  			DECLARE dvar BIGINT DEFAULT 2;
  1601  			BEGIN
  1602  				DECLARE dvar BIGINT DEFAULT 3;
  1603  				LOOP
  1604  					FETCH cur1 INTO dvar; # Handler is triggered here, but should only set the first "dvar"
  1605  				END LOOP;
  1606              END;
  1607  		END;
  1608      END;
  1609      SELECT dvar;
  1610  END`,
  1611  		},
  1612  		Assertions: []ScriptTestAssertion{
  1613  			{
  1614  				Query: "CALL p1();",
  1615  				Expected: []sql.Row{
  1616  					{10},
  1617  				},
  1618  			},
  1619  		},
  1620  	},
  1621  	{
  1622  		Name:        "Duplicate parameter names",
  1623  		Query:       "CREATE PROCEDURE p1(abc DATETIME, abc DOUBLE) SELECT abc",
  1624  		ExpectedErr: sql.ErrDeclareVariableDuplicate,
  1625  	},
  1626  	{
  1627  		Name:        "Duplicate parameter names mixed casing",
  1628  		Query:       "CREATE PROCEDURE p1(abc DATETIME, ABC DOUBLE) SELECT abc",
  1629  		ExpectedErr: sql.ErrDeclareVariableDuplicate,
  1630  	},
  1631  	{
  1632  		Name:        "Invalid parameter type",
  1633  		Query:       "CREATE PROCEDURE p1(x FAKETYPE) SELECT x",
  1634  		ExpectedErr: sql.ErrSyntaxError,
  1635  	},
  1636  	{ // This statement is not allowed in stored procedures, and is caught by the vitess parser.
  1637  		Name:        "Invalid USE statement",
  1638  		Query:       `CREATE PROCEDURE p1() USE mydb`,
  1639  		ExpectedErr: sql.ErrSyntaxError,
  1640  	},
  1641  	{ // These statements are not allowed in stored procedures, and are caught by the vitess parser.
  1642  		Name: "Invalid LOCK/UNLOCK statements",
  1643  		SetUpScript: []string{
  1644  			"CREATE TABLE t1(pk BIGINT PRIMARY KEY)",
  1645  		},
  1646  		Assertions: []ScriptTestAssertion{
  1647  			{
  1648  				Query:       "CREATE PROCEDURE p1(x BIGINT) LOCK TABLES t1 READ",
  1649  				ExpectedErr: sql.ErrSyntaxError,
  1650  			},
  1651  			{
  1652  				Query:       "CREATE PROCEDURE p1(x BIGINT) UNLOCK TABLES",
  1653  				ExpectedErr: sql.ErrSyntaxError,
  1654  			},
  1655  		},
  1656  	},
  1657  	{
  1658  		Name: "DECLARE CONDITION wrong positions",
  1659  		Assertions: []ScriptTestAssertion{
  1660  			{
  1661  				Query: `CREATE PROCEDURE p1(x INT)
  1662  BEGIN
  1663  	SELECT x;
  1664  	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1665  END;`,
  1666  				ExpectedErr: sql.ErrDeclareConditionOrderInvalid,
  1667  			},
  1668  			{
  1669  				Query: `CREATE PROCEDURE p1(x INT)
  1670  BEGIN
  1671  	BEGIN
  1672  		SELECT x;
  1673  		DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1674  	END;
  1675  END;`,
  1676  				ExpectedErr: sql.ErrDeclareConditionOrderInvalid,
  1677  			},
  1678  			{
  1679  				Query: `CREATE PROCEDURE p1(x INT)
  1680  BEGIN
  1681  	IF x = 0 THEN
  1682  		DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1683  	END IF;
  1684  END;`,
  1685  				ExpectedErr: sql.ErrDeclareConditionOrderInvalid,
  1686  			},
  1687  			{
  1688  				Query: `CREATE PROCEDURE p1(x INT)
  1689  BEGIN
  1690  	IF x = 0 THEN
  1691  		SELECT x;
  1692  	ELSE
  1693  		DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1694  	END IF;
  1695  END;`,
  1696  				ExpectedErr: sql.ErrDeclareConditionOrderInvalid,
  1697  			},
  1698  		},
  1699  	},
  1700  	{
  1701  		Name: "DECLARE CONDITION duplicate name",
  1702  		Query: `CREATE PROCEDURE p1()
  1703  BEGIN
  1704  	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1705  	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1706  END;`,
  1707  		ExpectedErr: sql.ErrDeclareConditionDuplicate,
  1708  	},
  1709  	{ //TODO: change this test when we implement DECLARE CONDITION for MySQL error codes
  1710  		Name: "SIGNAL references condition name for MySQL error code",
  1711  		Query: `CREATE PROCEDURE p1(x INT)
  1712  BEGIN
  1713  	DECLARE mysql_err_code CONDITION FOR 1000;
  1714  	SIGNAL mysql_err_code;
  1715  END;`,
  1716  		ExpectedErr: sql.ErrUnsupportedSyntax,
  1717  	},
  1718  	{
  1719  		Name: "SIGNAL non-existent condition name",
  1720  		Query: `CREATE PROCEDURE p1(x INT)
  1721  BEGIN
  1722  	DECLARE abcdefg CONDITION FOR SQLSTATE '45000';
  1723  	SIGNAL abcdef;
  1724  END;`,
  1725  		ExpectedErr: sql.ErrDeclareConditionNotFound,
  1726  	},
  1727  	{
  1728  		Name: "Duplicate procedure name",
  1729  		SetUpScript: []string{
  1730  			"CREATE PROCEDURE test_proc(x DOUBLE, y DOUBLE) SELECT x*y",
  1731  		},
  1732  		Query:       "CREATE PROCEDURE test_proc(z VARCHAR(20)) SELECT z",
  1733  		ExpectedErr: sql.ErrStoredProcedureAlreadyExists,
  1734  	},
  1735  	{
  1736  		Name: "Broken procedure shouldn't break other procedures",
  1737  		SetUpScript: []string{
  1738  			"CREATE TABLE t (pk INT PRIMARY KEY, other INT);",
  1739  			"INSERT INTO t VALUES (1, 1), (2, 2), (3, 3);",
  1740  			"CREATE PROCEDURE fragile() select other from t;",
  1741  			"CREATE PROCEDURE stable() select pk from t;",
  1742  		},
  1743  		Assertions: []ScriptTestAssertion{
  1744  			{
  1745  				Query:    "CALL stable();",
  1746  				Expected: []sql.Row{{1}, {2}, {3}},
  1747  			},
  1748  			{
  1749  				Query:    "CALL fragile();",
  1750  				Expected: []sql.Row{{1}, {2}, {3}},
  1751  			},
  1752  			{
  1753  				Query:            "SHOW PROCEDURE STATUS LIKE 'stable'",
  1754  				SkipResultsCheck: true, // ensure that there's no error
  1755  			},
  1756  			{
  1757  				Query:            "SHOW PROCEDURE STATUS LIKE 'fragile'",
  1758  				SkipResultsCheck: true, // ensure that there's no error
  1759  			},
  1760  			{
  1761  				Query:    "alter table t drop other;",
  1762  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1763  			},
  1764  			{
  1765  				Query:    "CALL stable();",
  1766  				Expected: []sql.Row{{1}, {2}, {3}},
  1767  			},
  1768  			{
  1769  				Query:          "CALL fragile();",
  1770  				ExpectedErrStr: "column \"other\" could not be found in any table in scope",
  1771  			},
  1772  			{
  1773  				Query:            "SHOW PROCEDURE STATUS LIKE 'stable'",
  1774  				SkipResultsCheck: true, // ensure that there's no error
  1775  			},
  1776  			{
  1777  				Query:            "SHOW PROCEDURE STATUS LIKE 'fragile'",
  1778  				SkipResultsCheck: true, // ensure that there's no error
  1779  			},
  1780  			{
  1781  				Query:    "ALTER TABLE t ADD COLUMN other INT",
  1782  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1783  			},
  1784  			{
  1785  				Query:    "CALL stable();",
  1786  				Expected: []sql.Row{{1}, {2}, {3}},
  1787  			},
  1788  			{
  1789  				Query:    "CALL fragile();",
  1790  				Expected: []sql.Row{{nil}, {nil}, {nil}},
  1791  			},
  1792  			{
  1793  				Query:    "INSERT INTO t VALUES (4, 4), (5, 5), (6, 6);",
  1794  				Expected: []sql.Row{{types.NewOkResult(3)}},
  1795  			},
  1796  			{
  1797  				Query:    "CALL stable();",
  1798  				Expected: []sql.Row{{1}, {2}, {3}, {4}, {5}, {6}},
  1799  			},
  1800  			{
  1801  				Query:    "CALL fragile();",
  1802  				Expected: []sql.Row{{nil}, {nil}, {nil}, {4}, {5}, {6}},
  1803  			},
  1804  		},
  1805  	},
  1806  	{
  1807  		Name: "DECLARE name duplicate same type",
  1808  		Assertions: []ScriptTestAssertion{
  1809  			{
  1810  				Query: `CREATE PROCEDURE p1()
  1811  BEGIN
  1812  	DECLARE x INT;
  1813  	DECLARE x INT;
  1814  	SELECT 1;
  1815  END;`,
  1816  				ExpectedErr: sql.ErrDeclareVariableDuplicate,
  1817  			},
  1818  		},
  1819  	},
  1820  	{
  1821  		Name: "DECLARE name duplicate different type",
  1822  		Assertions: []ScriptTestAssertion{
  1823  			{
  1824  				Query: `CREATE PROCEDURE p1()
  1825  BEGIN
  1826  	DECLARE x INT;
  1827  	DECLARE x VARCHAR(20);
  1828  	SELECT 1;
  1829  END;`,
  1830  				ExpectedErr: sql.ErrDeclareVariableDuplicate,
  1831  			},
  1832  		},
  1833  	},
  1834  	{
  1835  		Name: "Variable, condition, and cursor in invalid order",
  1836  		Assertions: []ScriptTestAssertion{
  1837  			{
  1838  				Query: `CREATE PROCEDURE p1()
  1839  BEGIN
  1840  	DECLARE var_name INT;
  1841  	DECLARE cur_name CURSOR FOR SELECT 1;
  1842  	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1843  	SELECT 1;
  1844  END;`,
  1845  				ExpectedErr: sql.ErrDeclareConditionOrderInvalid,
  1846  			},
  1847  			{
  1848  				Query: `CREATE PROCEDURE p2()
  1849  BEGIN
  1850  	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1851  	DECLARE cur_name CURSOR FOR SELECT 1;
  1852  	DECLARE var_name INT;
  1853  	SELECT 1;
  1854  END;`,
  1855  				ExpectedErr: sql.ErrDeclareVariableOrderInvalid,
  1856  			},
  1857  			{
  1858  				Query: `CREATE PROCEDURE p3()
  1859  BEGIN
  1860  	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
  1861  	DECLARE var_name INT;
  1862  	SELECT 1;
  1863  	DECLARE cur_name CURSOR FOR SELECT 1;
  1864  END;`,
  1865  				ExpectedErr: sql.ErrDeclareCursorOrderInvalid,
  1866  			},
  1867  		},
  1868  	},
  1869  	{
  1870  		Name: "FETCH non-existent cursor",
  1871  		Assertions: []ScriptTestAssertion{
  1872  			{
  1873  				Query: `CREATE PROCEDURE p1()
  1874  BEGIN
  1875  	DECLARE a INT;
  1876  	FETCH no_cursor INTO a;
  1877  END;`,
  1878  				ExpectedErr: sql.ErrCursorNotFound,
  1879  			},
  1880  		},
  1881  	},
  1882  	{
  1883  		Name: "OPEN non-existent cursor",
  1884  		Assertions: []ScriptTestAssertion{
  1885  			{
  1886  				Query: `CREATE PROCEDURE p1()
  1887  BEGIN
  1888  	OPEN no_cursor;
  1889  END;`,
  1890  				ExpectedErr: sql.ErrCursorNotFound,
  1891  			},
  1892  		},
  1893  	},
  1894  	{
  1895  		Name: "CLOSE non-existent cursor",
  1896  		Assertions: []ScriptTestAssertion{
  1897  			{
  1898  				Query: `CREATE PROCEDURE p1()
  1899  BEGIN
  1900  	CLOSE no_cursor;
  1901  END;`,
  1902  				ExpectedErr: sql.ErrCursorNotFound,
  1903  			},
  1904  		},
  1905  	},
  1906  	{
  1907  		Name: "CLOSE without OPEN",
  1908  		SetUpScript: []string{
  1909  			`CREATE PROCEDURE p1()
  1910  BEGIN
  1911  	DECLARE cur1 CURSOR FOR SELECT 1;
  1912      CLOSE cur1;
  1913  END;`,
  1914  		},
  1915  		Assertions: []ScriptTestAssertion{
  1916  			{
  1917  				Query:       "CALL p1();",
  1918  				ExpectedErr: sql.ErrCursorNotOpen,
  1919  			},
  1920  		},
  1921  	},
  1922  	{
  1923  		Name: "OPEN repeatedly",
  1924  		SetUpScript: []string{
  1925  			`CREATE PROCEDURE p1()
  1926  BEGIN
  1927  	DECLARE cur1 CURSOR FOR SELECT 1;
  1928      OPEN cur1;
  1929      OPEN cur1;
  1930  END;`,
  1931  		},
  1932  		Assertions: []ScriptTestAssertion{
  1933  			{
  1934  				Query:       "CALL p1();",
  1935  				ExpectedErr: sql.ErrCursorAlreadyOpen,
  1936  			},
  1937  		},
  1938  	},
  1939  	{
  1940  		Name: "CLOSE repeatedly",
  1941  		SetUpScript: []string{
  1942  			`CREATE PROCEDURE p1()
  1943  BEGIN
  1944  	DECLARE cur1 CURSOR FOR SELECT 1;
  1945      OPEN cur1;
  1946      CLOSE cur1;
  1947      CLOSE cur1;
  1948  END;`,
  1949  		},
  1950  		Assertions: []ScriptTestAssertion{
  1951  			{
  1952  				Query:       "CALL p1();",
  1953  				ExpectedErr: sql.ErrCursorNotOpen,
  1954  			},
  1955  		},
  1956  	},
  1957  	{
  1958  		Name: "With CTE using variable",
  1959  		SetUpScript: []string{
  1960  			`CREATE PROCEDURE p1()
  1961  BEGIN
  1962  	DECLARE v1 INT DEFAULT 1234;
  1963  	WITH cte as (SELECT v1)
  1964  	SELECT * FROM cte;
  1965  END;`,
  1966  		},
  1967  		Assertions: []ScriptTestAssertion{
  1968  			{
  1969  				Query: "CALL p1();",
  1970  				Expected: []sql.Row{
  1971  					{1234},
  1972  				},
  1973  			},
  1974  		},
  1975  	},
  1976  	{
  1977  		Name: "With CTE using parameter",
  1978  		SetUpScript: []string{
  1979  			`CREATE PROCEDURE p1(v1 int)
  1980  BEGIN
  1981  	WITH cte as (SELECT v1)
  1982  	SELECT * FROM cte;
  1983  END;`,
  1984  		},
  1985  		Assertions: []ScriptTestAssertion{
  1986  			{
  1987  				Query: "CALL p1(1234);",
  1988  				Expected: []sql.Row{
  1989  					{1234},
  1990  				},
  1991  			},
  1992  		},
  1993  	},
  1994  	{
  1995  		Name: "Dolt Issue #4480",
  1996  		SetUpScript: []string{
  1997  			"create table p1 (row_id int primary key, pred int, actual int)",
  1998  			"create table p2 (row_id int primary key, pred int, actual int)",
  1999  			"insert into p1 values (0, 0, 0), (1, 0, 1), (2, 1, 0), (3, 1, 1)",
  2000  			"insert into p2 values (0, 0, 0), (1, 0, 1), (2, 1, 0), (3, 1, 1)",
  2001  			`CREATE PROCEDURE computeSummary(c VARCHAR(200)) 
  2002  BEGIN
  2003  	with t as (
  2004  		select
  2005  			case
  2006  				when p1.pred = p2.actual then 1
  2007  			else 0
  2008  			end as correct,
  2009  			p1.actual
  2010  			from p1
  2011  			join p2
  2012  			on p1.row_id = p2.row_id
  2013  	)
  2014  	select
  2015  		sum(correct)/count(*),
  2016  		count(*) as row_num
  2017  		from t;
  2018  END;`,
  2019  		},
  2020  		Assertions: []ScriptTestAssertion{
  2021  			{
  2022  				Query: "CALL computeSummary('i am not used');",
  2023  				Expected: []sql.Row{
  2024  					{float64(0.5), 4},
  2025  				},
  2026  			},
  2027  		},
  2028  	},
  2029  }
  2030  
  2031  var ProcedureCallTests = []ScriptTest{
  2032  	{
  2033  		Name: "OUT param with SET",
  2034  		SetUpScript: []string{
  2035  			"SET @outparam = 5",
  2036  			"CREATE PROCEDURE testabc(OUT x BIGINT) SET x = 9",
  2037  			"CALL testabc(@outparam)",
  2038  		},
  2039  		Assertions: []ScriptTestAssertion{
  2040  			{
  2041  				Query: "SELECT @outparam",
  2042  				Expected: []sql.Row{
  2043  					{
  2044  						int64(9),
  2045  					},
  2046  				},
  2047  			},
  2048  		},
  2049  	},
  2050  	{
  2051  		Name: "OUT param without SET",
  2052  		SetUpScript: []string{
  2053  			"SET @outparam = 5",
  2054  			"CREATE PROCEDURE testabc(OUT x BIGINT) SELECT x",
  2055  			"CALL testabc(@outparam)",
  2056  		},
  2057  		Assertions: []ScriptTestAssertion{
  2058  			{
  2059  				Query: "SELECT @outparam",
  2060  				Expected: []sql.Row{
  2061  					{
  2062  						nil,
  2063  					},
  2064  				},
  2065  			},
  2066  		},
  2067  	},
  2068  	{
  2069  		Name: "INOUT param with SET",
  2070  		SetUpScript: []string{
  2071  			"SET @outparam = 5",
  2072  			"CREATE PROCEDURE testabc(INOUT x BIGINT) BEGIN SET x = x + 1; SET x = x + 3; END;",
  2073  			"CALL testabc(@outparam)",
  2074  		},
  2075  		Assertions: []ScriptTestAssertion{
  2076  			{
  2077  				Query: "SELECT @outparam",
  2078  				Expected: []sql.Row{
  2079  					{
  2080  						int64(9),
  2081  					},
  2082  				},
  2083  			},
  2084  		},
  2085  	},
  2086  	{
  2087  		Name: "INOUT param without SET",
  2088  		SetUpScript: []string{
  2089  			"SET @outparam = 5",
  2090  			"CREATE PROCEDURE testabc(INOUT x BIGINT) SELECT x",
  2091  			"CALL testabc(@outparam)",
  2092  		},
  2093  		Assertions: []ScriptTestAssertion{
  2094  			{
  2095  				Query: "SELECT @outparam",
  2096  				Expected: []sql.Row{
  2097  					{
  2098  						int64(5),
  2099  					},
  2100  				},
  2101  			},
  2102  		},
  2103  	},
  2104  	{
  2105  		Name: "Nested CALL with INOUT param",
  2106  		SetUpScript: []string{
  2107  			"SET @outparam = 5",
  2108  			"CREATE PROCEDURE p3(INOUT z INT) BEGIN SET z = z * 111; END;",
  2109  			"CREATE PROCEDURE p2(INOUT y DOUBLE) BEGIN SET y = y + 4; CALL p3(y); END;",
  2110  			"CREATE PROCEDURE p1(INOUT x BIGINT) BEGIN SET x = 3; CALL p2(x); END;",
  2111  			"CALL p1(@outparam)",
  2112  		},
  2113  		Assertions: []ScriptTestAssertion{
  2114  			{
  2115  				Query: "SELECT @outparam",
  2116  				Expected: []sql.Row{
  2117  					{
  2118  						int64(777),
  2119  					},
  2120  				},
  2121  			},
  2122  		},
  2123  	},
  2124  	{
  2125  		Name: "OUT param without SET",
  2126  		SetUpScript: []string{
  2127  			"SET @outparam = 5",
  2128  			"CREATE PROCEDURE testabc(OUT x BIGINT) SELECT x",
  2129  			"CALL testabc(@outparam)",
  2130  		},
  2131  		Assertions: []ScriptTestAssertion{
  2132  			{
  2133  				Query: "SELECT @outparam",
  2134  				Expected: []sql.Row{
  2135  					{
  2136  						nil,
  2137  					},
  2138  				},
  2139  			},
  2140  		},
  2141  	},
  2142  	{
  2143  		Name: "Incompatible type for parameter",
  2144  		SetUpScript: []string{
  2145  			"CREATE PROCEDURE p1(x DATETIME) SELECT x",
  2146  		},
  2147  		Assertions: []ScriptTestAssertion{
  2148  			{
  2149  				Query:       "CALL p1('hi')",
  2150  				ExpectedErr: types.ErrConvertingToTime,
  2151  			},
  2152  		},
  2153  	},
  2154  	{
  2155  		Name: "Incorrect parameter count",
  2156  		SetUpScript: []string{
  2157  			"CREATE PROCEDURE p1(x BIGINT, y BIGINT) SELECT x + y",
  2158  		},
  2159  		Assertions: []ScriptTestAssertion{
  2160  			{
  2161  				Query:       "CALL p1(1)",
  2162  				ExpectedErr: sql.ErrCallIncorrectParameterCount,
  2163  			},
  2164  			{
  2165  				Query:       "CALL p1(1, 2, 3)",
  2166  				ExpectedErr: sql.ErrCallIncorrectParameterCount,
  2167  			},
  2168  		},
  2169  	},
  2170  	{
  2171  		Name: "use procedure parameter in filter expressions and multiple statements",
  2172  		SetUpScript: []string{
  2173  			"CREATE TABLE inventory (store_id int, product varchar(5))",
  2174  			"INSERT INTO inventory VALUES (1, 'a'), (1, 'b'), (1, 'c'), (1, 'd'), (2, 'e'), (2, 'f'), (1, 'g'), (1, 'h'), (3, 'i')",
  2175  			"CREATE PROCEDURE proc1 (IN p_store_id INT) SELECT COUNT(*) FROM inventory WHERE store_id = p_store_id;",
  2176  			"CREATE PROCEDURE proc2 (IN p_store_id INT, OUT p_film_count INT) READS SQL DATA BEGIN SELECT COUNT(*) as counted FROM inventory WHERE store_id = p_store_id; SET p_film_count = 44; END ;",
  2177  		},
  2178  		Assertions: []ScriptTestAssertion{
  2179  			{
  2180  				Query: "CALL proc1(1)",
  2181  				Expected: []sql.Row{
  2182  					{
  2183  						int64(6),
  2184  					},
  2185  				},
  2186  			},
  2187  			{
  2188  				Query: "CALL proc1(2)",
  2189  				Expected: []sql.Row{
  2190  					{
  2191  						int64(2),
  2192  					},
  2193  				},
  2194  			}, {
  2195  				Query: "CALL proc1(4)",
  2196  				Expected: []sql.Row{
  2197  					{
  2198  						int64(0),
  2199  					},
  2200  				},
  2201  			}, {
  2202  				Query: "CALL proc2(3, @foo)",
  2203  				Expected: []sql.Row{
  2204  					{
  2205  						int64(1),
  2206  					},
  2207  				},
  2208  			}, {
  2209  				Query: "SELECT @foo",
  2210  				Expected: []sql.Row{
  2211  					{
  2212  						int64(44),
  2213  					},
  2214  				},
  2215  			},
  2216  		},
  2217  	},
  2218  	{
  2219  		Name: "Call procedures by their qualified name",
  2220  		SetUpScript: []string{
  2221  			"CREATE DATABASE otherdb",
  2222  			"CREATE PROCEDURE mydb.p1() SELECT 42",
  2223  			"CREATE PROCEDURE otherdb.p1() SELECT 43",
  2224  		},
  2225  		Assertions: []ScriptTestAssertion{
  2226  			{
  2227  				Query:    "CALL p1()",
  2228  				Expected: []sql.Row{{42}},
  2229  			},
  2230  			{
  2231  				Query:    "CALL mydb.p1()",
  2232  				Expected: []sql.Row{{42}},
  2233  			},
  2234  			{
  2235  				Query:    "CALL otherdb.p1()",
  2236  				Expected: []sql.Row{{43}},
  2237  			},
  2238  			{
  2239  				Query:    "USE otherdb",
  2240  				Expected: []sql.Row{},
  2241  			},
  2242  			{
  2243  				Query:    "CALL p1()",
  2244  				Expected: []sql.Row{{43}},
  2245  			},
  2246  		},
  2247  	},
  2248  
  2249  	{
  2250  		Name: "String literals with escaped chars",
  2251  		SetUpScript: []string{
  2252  			`CREATE PROCEDURE joe(IN str VARCHAR(15)) SELECT CONCAT('joe''s bar:', str);`,
  2253  			`CREATE PROCEDURE jill(IN str VARCHAR(15)) SELECT CONCAT('jill\'s bar:', str);`,
  2254  			`CREATE PROCEDURE stan(IN str VARCHAR(15)) SELECT CONCAT("stan\'s bar:", str);`,
  2255  		},
  2256  		Assertions: []ScriptTestAssertion{
  2257  			{
  2258  				Query:    "CALL joe('open')",
  2259  				Expected: []sql.Row{{"joe's bar:open"}},
  2260  			},
  2261  			{
  2262  				Query:    "CALL jill('closed')",
  2263  				Expected: []sql.Row{{"jill's bar:closed"}},
  2264  			},
  2265  			{
  2266  				Query:    "CALL stan('quarantined')",
  2267  				Expected: []sql.Row{{"stan's bar:quarantined"}},
  2268  			},
  2269  		},
  2270  	},
  2271  }
  2272  
  2273  var ProcedureDropTests = []ScriptTest{
  2274  	{
  2275  		Name: "DROP procedures",
  2276  		SetUpScript: []string{
  2277  			"CREATE PROCEDURE p1() SELECT 5",
  2278  			"CREATE PROCEDURE p2() SELECT 6",
  2279  		},
  2280  		Assertions: []ScriptTestAssertion{
  2281  			{
  2282  				Query: "CALL p1",
  2283  				Expected: []sql.Row{
  2284  					{
  2285  						int64(5),
  2286  					},
  2287  				},
  2288  			},
  2289  			{
  2290  				Query: "CALL p2",
  2291  				Expected: []sql.Row{
  2292  					{
  2293  						int64(6),
  2294  					},
  2295  				},
  2296  			},
  2297  			{
  2298  				Query:    "DROP PROCEDURE p1",
  2299  				Expected: []sql.Row{{types.OkResult{}}},
  2300  			},
  2301  			{
  2302  				Query:       "CALL p1",
  2303  				ExpectedErr: sql.ErrStoredProcedureDoesNotExist,
  2304  			},
  2305  			{
  2306  				Query:    "DROP PROCEDURE IF EXISTS p2",
  2307  				Expected: []sql.Row{{types.OkResult{}}},
  2308  			},
  2309  			{
  2310  				Query:       "CALL p2",
  2311  				ExpectedErr: sql.ErrStoredProcedureDoesNotExist,
  2312  			},
  2313  			{
  2314  				Query:       "DROP PROCEDURE p3",
  2315  				ExpectedErr: sql.ErrStoredProcedureDoesNotExist,
  2316  			},
  2317  			{
  2318  				Query:    "DROP PROCEDURE IF EXISTS p4",
  2319  				Expected: []sql.Row{{types.OkResult{}}},
  2320  			},
  2321  		},
  2322  	},
  2323  }
  2324  
  2325  var ProcedureShowStatus = []ScriptTest{
  2326  	{
  2327  		Name: "SHOW procedures",
  2328  		SetUpScript: []string{
  2329  			"CREATE PROCEDURE p1() COMMENT 'hi' DETERMINISTIC SELECT 6",
  2330  			"CREATE definer=`user` PROCEDURE p2() SQL SECURITY INVOKER SELECT 7",
  2331  			"CREATE PROCEDURE p21() SQL SECURITY DEFINER SELECT 8",
  2332  		},
  2333  		Assertions: []ScriptTestAssertion{
  2334  			{
  2335  				Query: "SHOW PROCEDURE STATUS",
  2336  				Expected: []sql.Row{
  2337  					{
  2338  						"mydb",                // Db
  2339  						"p1",                  // Name
  2340  						"PROCEDURE",           // Type
  2341  						"",                    // Definer
  2342  						time.Unix(0, 0).UTC(), // Modified
  2343  						time.Unix(0, 0).UTC(), // Created
  2344  						"DEFINER",             // Security_type
  2345  						"hi",                  // Comment
  2346  						"utf8mb4",             // character_set_client
  2347  						"utf8mb4_0900_bin",    // collation_connection
  2348  						"utf8mb4_0900_bin",    // Database Collation
  2349  					},
  2350  					{
  2351  						"mydb",                // Db
  2352  						"p2",                  // Name
  2353  						"PROCEDURE",           // Type
  2354  						"user@%",              // Definer
  2355  						time.Unix(0, 0).UTC(), // Modified
  2356  						time.Unix(0, 0).UTC(), // Created
  2357  						"INVOKER",             // Security_type
  2358  						"",                    // Comment
  2359  						"utf8mb4",             // character_set_client
  2360  						"utf8mb4_0900_bin",    // collation_connection
  2361  						"utf8mb4_0900_bin",    // Database Collation
  2362  					},
  2363  					{
  2364  						"mydb",                // Db
  2365  						"p21",                 // Name
  2366  						"PROCEDURE",           // Type
  2367  						"",                    // Definer
  2368  						time.Unix(0, 0).UTC(), // Modified
  2369  						time.Unix(0, 0).UTC(), // Created
  2370  						"DEFINER",             // Security_type
  2371  						"",                    // Comment
  2372  						"utf8mb4",             // character_set_client
  2373  						"utf8mb4_0900_bin",    // collation_connection
  2374  						"utf8mb4_0900_bin",    // Database Collation
  2375  					},
  2376  				},
  2377  			},
  2378  			{
  2379  				Query: "SHOW PROCEDURE STATUS LIKE 'p2%'",
  2380  				Expected: []sql.Row{
  2381  					{
  2382  						"mydb",                // Db
  2383  						"p2",                  // Name
  2384  						"PROCEDURE",           // Type
  2385  						"user@%",              // Definer
  2386  						time.Unix(0, 0).UTC(), // Modified
  2387  						time.Unix(0, 0).UTC(), // Created
  2388  						"INVOKER",             // Security_type
  2389  						"",                    // Comment
  2390  						"utf8mb4",             // character_set_client
  2391  						"utf8mb4_0900_bin",    // collation_connection
  2392  						"utf8mb4_0900_bin",    // Database Collation
  2393  					},
  2394  					{
  2395  						"mydb",                // Db
  2396  						"p21",                 // Name
  2397  						"PROCEDURE",           // Type
  2398  						"",                    // Definer
  2399  						time.Unix(0, 0).UTC(), // Modified
  2400  						time.Unix(0, 0).UTC(), // Created
  2401  						"DEFINER",             // Security_type
  2402  						"",                    // Comment
  2403  						"utf8mb4",             // character_set_client
  2404  						"utf8mb4_0900_bin",    // collation_connection
  2405  						"utf8mb4_0900_bin",    // Database Collation
  2406  					},
  2407  				},
  2408  			},
  2409  			{
  2410  				Query:    "SHOW PROCEDURE STATUS LIKE 'p4'",
  2411  				Expected: []sql.Row{},
  2412  			},
  2413  			{
  2414  				Query: "SHOW PROCEDURE STATUS WHERE Db = 'mydb'",
  2415  				Expected: []sql.Row{
  2416  					{
  2417  						"mydb",                // Db
  2418  						"p1",                  // Name
  2419  						"PROCEDURE",           // Type
  2420  						"",                    // Definer
  2421  						time.Unix(0, 0).UTC(), // Modified
  2422  						time.Unix(0, 0).UTC(), // Created
  2423  						"DEFINER",             // Security_type
  2424  						"hi",                  // Comment
  2425  						"utf8mb4",             // character_set_client
  2426  						"utf8mb4_0900_bin",    // collation_connection
  2427  						"utf8mb4_0900_bin",    // Database Collation
  2428  					},
  2429  					{
  2430  						"mydb",                // Db
  2431  						"p2",                  // Name
  2432  						"PROCEDURE",           // Type
  2433  						"user@%",              // Definer
  2434  						time.Unix(0, 0).UTC(), // Modified
  2435  						time.Unix(0, 0).UTC(), // Created
  2436  						"INVOKER",             // Security_type
  2437  						"",                    // Comment
  2438  						"utf8mb4",             // character_set_client
  2439  						"utf8mb4_0900_bin",    // collation_connection
  2440  						"utf8mb4_0900_bin",    // Database Collation
  2441  					},
  2442  					{
  2443  						"mydb",                // Db
  2444  						"p21",                 // Name
  2445  						"PROCEDURE",           // Type
  2446  						"",                    // Definer
  2447  						time.Unix(0, 0).UTC(), // Modified
  2448  						time.Unix(0, 0).UTC(), // Created
  2449  						"DEFINER",             // Security_type
  2450  						"",                    // Comment
  2451  						"utf8mb4",             // character_set_client
  2452  						"utf8mb4_0900_bin",    // collation_connection
  2453  						"utf8mb4_0900_bin",    // Database Collation
  2454  					},
  2455  				},
  2456  			},
  2457  			{
  2458  				Query: "SHOW PROCEDURE STATUS WHERE Name LIKE '%1'",
  2459  				Expected: []sql.Row{
  2460  					{
  2461  						"mydb",                // Db
  2462  						"p1",                  // Name
  2463  						"PROCEDURE",           // Type
  2464  						"",                    // Definer
  2465  						time.Unix(0, 0).UTC(), // Modified
  2466  						time.Unix(0, 0).UTC(), // Created
  2467  						"DEFINER",             // Security_type
  2468  						"hi",                  // Comment
  2469  						"utf8mb4",             // character_set_client
  2470  						"utf8mb4_0900_bin",    // collation_connection
  2471  						"utf8mb4_0900_bin",    // Database Collation
  2472  					},
  2473  					{
  2474  						"mydb",                // Db
  2475  						"p21",                 // Name
  2476  						"PROCEDURE",           // Type
  2477  						"",                    // Definer
  2478  						time.Unix(0, 0).UTC(), // Modified
  2479  						time.Unix(0, 0).UTC(), // Created
  2480  						"DEFINER",             // Security_type
  2481  						"",                    // Comment
  2482  						"utf8mb4",             // character_set_client
  2483  						"utf8mb4_0900_bin",    // collation_connection
  2484  						"utf8mb4_0900_bin",    // Database Collation
  2485  					},
  2486  				},
  2487  			},
  2488  			{
  2489  				Query: "SHOW PROCEDURE STATUS WHERE Security_type = 'INVOKER'",
  2490  				Expected: []sql.Row{
  2491  					{
  2492  						"mydb",                // Db
  2493  						"p2",                  // Name
  2494  						"PROCEDURE",           // Type
  2495  						"user@%",              // Definer
  2496  						time.Unix(0, 0).UTC(), // Modified
  2497  						time.Unix(0, 0).UTC(), // Created
  2498  						"INVOKER",             // Security_type
  2499  						"",                    // Comment
  2500  						"utf8mb4",             // character_set_client
  2501  						"utf8mb4_0900_bin",    // collation_connection
  2502  						"utf8mb4_0900_bin",    // Database Collation
  2503  					},
  2504  				},
  2505  			},
  2506  			{
  2507  				Query: "SHOW PROCEDURE STATUS",
  2508  				Expected: []sql.Row{
  2509  					{
  2510  						"mydb",                // Db
  2511  						"p1",                  // Name
  2512  						"PROCEDURE",           // Type
  2513  						"",                    // Definer
  2514  						time.Unix(0, 0).UTC(), // Modified
  2515  						time.Unix(0, 0).UTC(), // Created
  2516  						"DEFINER",             // Security_type
  2517  						"hi",                  // Comment
  2518  						"utf8mb4",             // character_set_client
  2519  						"utf8mb4_0900_bin",    // collation_connection
  2520  						"utf8mb4_0900_bin",    // Database Collation
  2521  					},
  2522  					{
  2523  						"mydb",                // Db
  2524  						"p2",                  // Name
  2525  						"PROCEDURE",           // Type
  2526  						"user@%",              // Definer
  2527  						time.Unix(0, 0).UTC(), // Modified
  2528  						time.Unix(0, 0).UTC(), // Created
  2529  						"INVOKER",             // Security_type
  2530  						"",                    // Comment
  2531  						"utf8mb4",             // character_set_client
  2532  						"utf8mb4_0900_bin",    // collation_connection
  2533  						"utf8mb4_0900_bin",    // Database Collation
  2534  					},
  2535  					{
  2536  						"mydb",                // Db
  2537  						"p21",                 // Name
  2538  						"PROCEDURE",           // Type
  2539  						"",                    // Definer
  2540  						time.Unix(0, 0).UTC(), // Modified
  2541  						time.Unix(0, 0).UTC(), // Created
  2542  						"DEFINER",             // Security_type
  2543  						"",                    // Comment
  2544  						"utf8mb4",             // character_set_client
  2545  						"utf8mb4_0900_bin",    // collation_connection
  2546  						"utf8mb4_0900_bin",    // Database Collation
  2547  					},
  2548  				},
  2549  			},
  2550  		},
  2551  	},
  2552  }
  2553  
  2554  var ProcedureShowCreate = []ScriptTest{
  2555  	{
  2556  		Name: "SHOW procedures",
  2557  		SetUpScript: []string{
  2558  			"CREATE PROCEDURE p1() COMMENT 'hi' DETERMINISTIC SELECT 6",
  2559  			"CREATE definer=`user` PROCEDURE p2() SQL SECURITY INVOKER SELECT 7",
  2560  			"CREATE PROCEDURE p21() SQL SECURITY DEFINER SELECT 8",
  2561  		},
  2562  		Assertions: []ScriptTestAssertion{
  2563  			{
  2564  				Query: "SHOW CREATE PROCEDURE p1",
  2565  				Expected: []sql.Row{
  2566  					{
  2567  						"p1", // Procedure
  2568  						"",   // sql_mode
  2569  						"CREATE PROCEDURE p1() COMMENT 'hi' DETERMINISTIC SELECT 6", // Create Procedure
  2570  						"utf8mb4",          // character_set_client
  2571  						"utf8mb4_0900_bin", // collation_connection
  2572  						"utf8mb4_0900_bin", // Database Collation
  2573  					},
  2574  				},
  2575  			},
  2576  			{
  2577  				Query: "SHOW CREATE PROCEDURE p2",
  2578  				Expected: []sql.Row{
  2579  					{
  2580  						"p2", // Procedure
  2581  						"",   // sql_mode
  2582  						"CREATE definer=`user` PROCEDURE p2() SQL SECURITY INVOKER SELECT 7", // Create Procedure
  2583  						"utf8mb4",          // character_set_client
  2584  						"utf8mb4_0900_bin", // collation_connection
  2585  						"utf8mb4_0900_bin", // Database Collation
  2586  					},
  2587  				},
  2588  			},
  2589  			{
  2590  				Query: "SHOW CREATE PROCEDURE p21",
  2591  				Expected: []sql.Row{
  2592  					{
  2593  						"p21", // Procedure
  2594  						"",    // sql_mode
  2595  						"CREATE PROCEDURE p21() SQL SECURITY DEFINER SELECT 8", // Create Procedure
  2596  						"utf8mb4",          // character_set_client
  2597  						"utf8mb4_0900_bin", // collation_connection
  2598  						"utf8mb4_0900_bin", // Database Collation
  2599  					},
  2600  				},
  2601  			},
  2602  		},
  2603  	},
  2604  	{
  2605  		Name:        "SHOW non-existent procedures",
  2606  		SetUpScript: []string{},
  2607  		Assertions: []ScriptTestAssertion{
  2608  			{
  2609  				Query:       "SHOW CREATE PROCEDURE p1",
  2610  				ExpectedErr: sql.ErrStoredProcedureDoesNotExist,
  2611  			},
  2612  		},
  2613  	},
  2614  }
  2615  
  2616  var NoDbProcedureTests = []ScriptTestAssertion{
  2617  	{
  2618  		Query:    "SHOW databases;",
  2619  		Expected: []sql.Row{{"information_schema"}, {"mydb"}, {"mysql"}},
  2620  	},
  2621  	{
  2622  		Query:    "SELECT database();",
  2623  		Expected: []sql.Row{{nil}},
  2624  	},
  2625  	{
  2626  		Query:    "CREATE PROCEDURE mydb.p5() SELECT 42;",
  2627  		Expected: []sql.Row{{types.NewOkResult(0)}},
  2628  	},
  2629  	{
  2630  		Query:            "SHOW CREATE PROCEDURE mydb.p5;",
  2631  		SkipResultsCheck: true,
  2632  	},
  2633  	{
  2634  		Query:       "SHOW CREATE PROCEDURE p5;",
  2635  		ExpectedErr: sql.ErrNoDatabaseSelected,
  2636  	},
  2637  }