From 96555b5f90bcd753a39ce89d197cbcef102fa6c2 Mon Sep 17 00:00:00 2001
From: "jani@rhols221.adsl.netsonic.fi" <>
Date: Tue, 16 Dec 2003 06:09:44 +0200
Subject: [PATCH] Added support for multi statement tests. Use mysqltest
 internal command delimiter to change the default delimiter (;) to something
 else, a string upto 16 characters is allowed. Separate the sub queries with
 ';' and end the whole statement with your own delimiter.

---
 client/mysqltest.c                  | 404 +++++++++++++++-------------
 mysql-test/r/multi_statement.result |  33 +++
 mysql-test/t/multi_statement.test   |  13 +
 3 files changed, 264 insertions(+), 186 deletions(-)
 create mode 100644 mysql-test/r/multi_statement.result
 create mode 100644 mysql-test/t/multi_statement.test

diff --git a/client/mysqltest.c b/client/mysqltest.c
index 9bcef569669..a53e259c726 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -42,7 +42,7 @@
 
 **********************************************************************/
 
-#define MTEST_VERSION "2.0"
+#define MTEST_VERSION "2.1"
 
 #include <my_global.h>
 #include <mysql_embed.h>
@@ -86,7 +86,8 @@
 #define MAX_CON_TRIES	5
 
 #define SLAVE_POLL_INTERVAL 300000 /* 0.3 of a sec */
-
+#define DEFAULT_DELIMITER ";"
+#define MAX_DELIMITER 16
 
 enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
       OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC,
@@ -114,6 +115,8 @@ static FILE** cur_file;
 static FILE** file_stack_end;
 static uint lineno_stack[MAX_INCLUDE_DEPTH];
 static char TMPDIR[FN_REFLEN];
+static char delimiter[MAX_DELIMITER]= DEFAULT_DELIMITER;
+static uint delimiter_length= 1;
 
 static int *cur_block, *block_stack_end;
 static int block_stack[BLOCK_STACK_DEPTH];
@@ -209,7 +212,8 @@ Q_WAIT_FOR_SLAVE_TO_STOP,
 Q_REQUIRE_VERSION,
 Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
 Q_ENABLE_INFO, Q_DISABLE_INFO,
-Q_EXEC,
+Q_EXEC, Q_DELIMITER,
+
 Q_UNKNOWN,			       /* Unknown command.   */
 Q_COMMENT,			       /* Comments, ignored. */
 Q_COMMENT_WITH_COMMAND
@@ -281,6 +285,7 @@ const char *command_names[]=
   "enable_info",
   "disable_info",
   "exec",
+  "delimiter",
   0
 };
 
@@ -1472,7 +1477,8 @@ int safe_connect(MYSQL* con, const char* host, const char* user,
   int i;
   for (i = 0; i < MAX_CON_TRIES; ++i)
   {
-    if (mysql_real_connect(con, host,user, pass, db, port, sock, 0))
+    if (mysql_real_connect(con, host,user, pass, db, port, sock,
+			   CLIENT_MULTI_STATEMENTS))
     {
       con_error = 0;
       break;
@@ -1622,24 +1628,46 @@ int do_while(struct st_query* q)
 }
 
 
+my_bool end_of_query(int c, char* p)
+{
+  uint i= 0, j;
+  int tmp[MAX_DELIMITER]= {0};
+
+  for (i= 0; c == *(delimiter + i) && i < delimiter_length;
+       i++, c= fgetc(*cur_file))
+    tmp[i]= c;
+  tmp[i]= c;
+
+  for (j= i; j > 0 && i != delimiter_length; j--)
+    ungetc(tmp[j], *cur_file);
+  if (i == delimiter_length)
+  {
+    ungetc(tmp[j], *cur_file);
+    *p= 0;
+    return 1;
+  }
+  return 0;
+}
+
+
 int read_line(char* buf, int size)
 {
   int c;
-  char* p = buf, *buf_end = buf + size-1;
-  int no_save = 0;
+  char* p= buf, *buf_end= buf + size - 1;
+  int no_save= 0;
   enum {R_NORMAL, R_Q1, R_ESC_Q_Q1, R_ESC_Q_Q2,
 	R_ESC_SLASH_Q1, R_ESC_SLASH_Q2,
-	R_Q2, R_COMMENT, R_LINE_START} state = R_LINE_START;
+	R_Q2, R_COMMENT, R_LINE_START} state= R_LINE_START;
 
   start_lineno= *lineno;
   for (; p < buf_end ;)
   {
-    no_save = 0;
-    c = fgetc(*cur_file);
+    no_save= 0;
+    c= fgetc(*cur_file);
     if (feof(*cur_file))
     {
       if ((*cur_file) != stdin)
-	my_fclose(*cur_file,MYF(0));
+	my_fclose(*cur_file, MYF(0));
       cur_file--;
       lineno--;
       if (cur_file == file_stack)
@@ -1650,11 +1678,8 @@ int read_line(char* buf, int size)
     switch(state) {
     case R_NORMAL:
       /*  Only accept '{' in the beginning of a line */
-      if (c == ';')
-      {
-	*p = 0;
+      if (end_of_query(c, p))
 	return 0;
-      }
       else if (c == '\'')
 	state = R_Q1;
       else if (c == '"')
@@ -1668,7 +1693,7 @@ int read_line(char* buf, int size)
     case R_COMMENT:
       if (c == '\n')
       {
-	*p=0;
+	*p= 0;
 	(*lineno)++;
 	return 0;
       }
@@ -1678,78 +1703,72 @@ int read_line(char* buf, int size)
       {
 	state = R_COMMENT;
       }
-      else if (my_isspace(charset_info,c))
+      else if (my_isspace(charset_info, c))
       {
 	if (c == '\n')
 	  start_lineno= ++*lineno;		/* Query hasn't started yet */
-	no_save = 1;
+	no_save= 1;
       }
       else if (c == '}')
       {
-	*buf++ = '}';
-	*buf = 0;
+	*buf++= '}';
+	*buf= 0;
 	return 0;
       }
-      else if (c == ';' || c == '{')
+      else if (end_of_query(c, p) || c == '{')
       {
-	*p = 0;
+	*p= 0;
 	return 0;
       }
       else if (c == '\'')
-	state = R_Q1;
+	state= R_Q1;
       else if (c == '"')
-	state = R_Q2;
+	state= R_Q2;
       else
-	state = R_NORMAL;
+	state= R_NORMAL;
       break;
 
     case R_Q1:
       if (c == '\'')
-	state = R_ESC_Q_Q1;
+	state= R_ESC_Q_Q1;
       else if (c == '\\')
-	state = R_ESC_SLASH_Q1;
+	state= R_ESC_SLASH_Q1;
       break;
     case R_ESC_Q_Q1:
-      if (c == ';')
-      {
-	*p = 0;
+      if (end_of_query(c, p))
 	return 0;
-      }
       if (c != '\'')
-	state = R_NORMAL;
+	state= R_NORMAL;
       else
-	state = R_Q1;
+	state= R_Q1;
       break;
     case R_ESC_SLASH_Q1:
-      state = R_Q1;
+      state= R_Q1;
       break;
 
     case R_Q2:
       if (c == '"')
-	state = R_ESC_Q_Q2;
+	state= R_ESC_Q_Q2;
       else if (c == '\\')
-	state = R_ESC_SLASH_Q2;
+	state= R_ESC_SLASH_Q2;
       break;
     case R_ESC_Q_Q2:
-      if (c == ';')
-      {
-	*p = 0;
+      if (end_of_query(c, p))
 	return 0;
-      }
       if (c != '"')
-	state = R_NORMAL;
+	state= R_NORMAL;
       else
-	state = R_Q2;
+	state= R_Q2;
       break;
     case R_ESC_SLASH_Q2:
-      state = R_Q2;
+      state= R_Q2;
       break;
     }
 
     if (!no_save)
-      *p++ = c;
+      *p++= c;
   }
-  *p=0;						/* Always end with \0 */
+  *p= 0;					/* Always end with \0 */
   return feof(*cur_file);
 }
 
@@ -1766,22 +1785,22 @@ int read_query(struct st_query** q_ptr)
     get_dynamic(&q_lines, (gptr) q_ptr, parser.current_line) ;
     return 0;
   }
-  if (!(*q_ptr=q=(struct st_query*) my_malloc(sizeof(*q), MYF(MY_WME))) ||
+  if (!(*q_ptr= q= (struct st_query*) my_malloc(sizeof(*q), MYF(MY_WME))) ||
       insert_dynamic(&q_lines, (gptr) &q))
     die(NullS);
 
-  q->record_file[0] = 0;
-  q->require_file=0;
-  q->first_word_len = 0;
+  q->record_file[0]= 0;
+  q->require_file= 0;
+  q->first_word_len= 0;
   memcpy((gptr) q->expected_errno, (gptr) global_expected_errno,
 	 sizeof(global_expected_errno));
-  q->expected_errors=global_expected_errors;
-  q->abort_on_error = global_expected_errno[0] == 0;
-  bzero((gptr) global_expected_errno,sizeof(global_expected_errno));
+  q->expected_errors= global_expected_errors;
+  q->abort_on_error= global_expected_errno[0] == 0;
+  bzero((gptr) global_expected_errno, sizeof(global_expected_errno));
   global_expected_errors=0;
 
   q->type = Q_UNKNOWN;
-  q->query_buf=q->query=0;
+  q->query_buf= q->query= 0;
   if (read_line(read_query_buf, sizeof(read_query_buf)))
     return 1;
 
@@ -1791,20 +1810,20 @@ int read_query(struct st_query** q_ptr)
   }
   else if (p[0] == '-' && p[1] == '-')
   {
-    q->type = Q_COMMENT_WITH_COMMAND;
-    p+=2;					/* To calculate first word */
+    q->type= Q_COMMENT_WITH_COMMAND;
+    p+= 2;					/* To calculate first word */
   }
   else
   {
     if (*p == '!')
     {
-      q->abort_on_error = 0;
+      q->abort_on_error= 0;
       p++;
       if (*p == '$')
       {
-	expected_errno = 0;
+	expected_errno= 0;
 	p++;
-	for (;my_isdigit(charset_info,*p);p++)
+	for (; my_isdigit(charset_info, *p); p++)
 	  expected_errno = expected_errno * 10 + *p - '0';
 	q->expected_errno[0] = expected_errno;
 	q->expected_errno[1] = 0;
@@ -1812,30 +1831,30 @@ int read_query(struct st_query** q_ptr)
       }
     }
 
-    while (*p && my_isspace(charset_info,*p))
+    while (*p && my_isspace(charset_info, *p))
       p++ ;
     if (*p == '@')
     {
       p++;
       p1 = q->record_file;
-      while (!my_isspace(charset_info,*p) &&
+      while (!my_isspace(charset_info, *p) &&
 	     p1 < q->record_file + sizeof(q->record_file) - 1)
 	*p1++ = *p++;
       *p1 = 0;
     }
   }
-  while (*p && my_isspace(charset_info,*p))
+  while (*p && my_isspace(charset_info, *p))
     p++;
-  if (!(q->query_buf=q->query=my_strdup(p,MYF(MY_WME))))
+  if (!(q->query_buf= q->query= my_strdup(p, MYF(MY_WME))))
     die(NullS);
 
   /* Calculate first word and first argument */
-  for (p=q->query; *p && !my_isspace(charset_info,*p) ; p++) ;
-  q->first_word_len = (uint) (p - q->query);
-  while (*p && my_isspace(charset_info,*p))
+  for (p= q->query; *p && !my_isspace(charset_info, *p) ; p++) ;
+  q->first_word_len= (uint) (p - q->query);
+  while (*p && my_isspace(charset_info, *p))
     p++;
-  q->first_argument=p;
-  q->end = strend(q->query);
+  q->first_argument= p;
+  q->end= strend(q->query);
   parser.read_lines++;
   return 0;
 }
@@ -2129,12 +2148,12 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
 
 int run_query(MYSQL* mysql, struct st_query* q, int flags)
 {
-  MYSQL_RES* res = 0;
-  int i, error = 0;
+  MYSQL_RES* res= 0;
+  int i, error= 0, err= 0, counter= 0;
   DYNAMIC_STRING *ds;
   DYNAMIC_STRING ds_tmp;
   DYNAMIC_STRING eval_query;
-  char* query;
+  char* query, buff[MAX_DELIMITER + 1]= {0};
   int query_len;
   DBUG_ENTER("run_query");
   
@@ -2162,150 +2181,159 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
 
   if ((flags & QUERY_SEND) && mysql_send_query(mysql, query, query_len))
     die("At line %u: unable to send query '%s'(mysql_errno=%d,errno=%d)",
-	start_lineno, query,
-	mysql_errno(mysql), errno);
-  if ((flags & QUERY_SEND) && !disable_query_log)
-  {
-    replace_dynstr_append_mem(ds,query, query_len);
-    dynstr_append_mem(ds,";\n",2);
-  }
-  if (!(flags & QUERY_REAP))
-    DBUG_RETURN(0);
+	start_lineno, query, mysql_errno(mysql), errno);
 
-  if ((*mysql->methods->read_query_result)(mysql) ||
-      (!(last_result = res = mysql_store_result(mysql)) &&
-       mysql_field_count(mysql)))
+  do
   {
-    if (q->require_file)
+    if ((flags & QUERY_SEND) && !disable_query_log && !counter)
     {
-      abort_not_supported_test();
+      replace_dynstr_append_mem(ds,query, query_len);
+      sprintf(buff, "%s\n", delimiter);
+      dynstr_append_mem(ds, buff, strlen(delimiter) + 1);
     }
-    if (q->abort_on_error)
-      die("At line %u: query '%s' failed: %d: %s", start_lineno, query,
-	  mysql_errno(mysql), mysql_error(mysql));
-    else
+    if (!(flags & QUERY_REAP))
+      DBUG_RETURN(0);
+
+    if ((!counter && (*mysql->methods->read_query_result)(mysql)) ||
+	(!(last_result= res= mysql_store_result(mysql)) &&
+	 mysql_field_count(mysql)))
     {
-      for (i=0 ; (uint) i < q->expected_errors ; i++)
+      if (q->require_file)
       {
-	if ((q->expected_errno[i] == mysql_errno(mysql)))
+	abort_not_supported_test();
+      }
+      if (q->abort_on_error)
+	die("At line %u: query '%s' failed: %d: %s", start_lineno, query,
+	    mysql_errno(mysql), mysql_error(mysql));
+      else
+      {
+	for (i=0 ; (uint) i < q->expected_errors ; i++)
 	{
-	  if (i == 0 && q->expected_errors == 1)
+	  if ((q->expected_errno[i] == mysql_errno(mysql)))
 	  {
-	    /* Only log error if there is one possible error */
-	    dynstr_append_mem(ds,"ERROR ",6);
-	    replace_dynstr_append_mem(ds, mysql_sqlstate(mysql),
-				      strlen(mysql_sqlstate(mysql)));
-	    dynstr_append_mem(ds,": ",2);
-	    replace_dynstr_append_mem(ds,mysql_error(mysql),
-				      strlen(mysql_error(mysql)));
-	    dynstr_append_mem(ds,"\n",1);
+	    if (i == 0 && q->expected_errors == 1)
+	    {
+	      /* Only log error if there is one possible error */
+	      dynstr_append_mem(ds,"ERROR ",6);
+	      replace_dynstr_append_mem(ds, mysql_sqlstate(mysql),
+					strlen(mysql_sqlstate(mysql)));
+	      dynstr_append_mem(ds, ": ", 2);
+	      replace_dynstr_append_mem(ds,mysql_error(mysql),
+					strlen(mysql_error(mysql)));
+	      dynstr_append_mem(ds,"\n",1);
+	    }
+	    /* Don't log error if we may not get an error */
+	    else if (q->expected_errno[0] != 0)
+	      dynstr_append(ds,"Got one of the listed errors\n");
+	    goto end;				/* Ok */
 	  }
-	  /* Don't log error if we may not get an error */
-	  else if (q->expected_errno[0] != 0)
-	    dynstr_append(ds,"Got one of the listed errors\n");
-	  goto end;				/* Ok */
 	}
-      }
-      DBUG_PRINT("info",("i: %d  expected_errors: %d", i, q->expected_errors));
-      dynstr_append_mem(ds,"ERROR ",6);
-      replace_dynstr_append_mem(ds, mysql_sqlstate(mysql),
-				strlen(mysql_sqlstate(mysql)));
-      dynstr_append_mem(ds,": ",2);
-      replace_dynstr_append_mem(ds, mysql_error(mysql),
-				strlen(mysql_error(mysql)));
-      dynstr_append_mem(ds,"\n",1);
-      if (i)
-      {
-	verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
-		    q->query, mysql_errno(mysql), q->expected_errno[0]);
-	error= 1;
+	DBUG_PRINT("info",("i: %d  expected_errors: %d", i, q->expected_errors));
+	dynstr_append_mem(ds, "ERROR ",6);
+	replace_dynstr_append_mem(ds, mysql_sqlstate(mysql),
+				  strlen(mysql_sqlstate(mysql)));
+	dynstr_append_mem(ds,": ",2);
+	replace_dynstr_append_mem(ds, mysql_error(mysql),
+				  strlen(mysql_error(mysql)));
+	dynstr_append_mem(ds,"\n",1);
+	if (i)
+	{
+	  verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
+		      q->query, mysql_errno(mysql), q->expected_errno[0]);
+	  error= 1;
+	  goto end;
+	}
+	verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql),
+		    mysql_error(mysql));
+	/*
+	  if we do not abort on error, failure to run the query does
+	  not fail the whole test case
+	*/
 	goto end;
       }
-      verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql),
-		  mysql_error(mysql));
-      /*
-	if we do not abort on error, failure to run the query does
-	not fail the whole test case
-      */
-      goto end;
+      /*{
+	verbose_msg("failed in mysql_store_result for query '%s' (%d)", query,
+	mysql_errno(mysql));
+	error = 1;
+	goto end;
+	}*/
     }
-    /*{
-      verbose_msg("failed in mysql_store_result for query '%s' (%d)", query,
-      mysql_errno(mysql));
+
+    if (q->expected_errno[0])
+    {
       error = 1;
+      verbose_msg("query '%s' succeeded - should have failed with errno %d...",
+		  q->query, q->expected_errno[0]);
       goto end;
-      }*/
-  }
-
-  if (q->expected_errno[0])
-  {
-    error = 1;
-    verbose_msg("query '%s' succeeded - should have failed with errno %d...",
-		q->query, q->expected_errno[0]);
-    goto end;
-  }
+    }
 
-  if (!disable_result_log)
-  {
-    if (res)
+    if (!disable_result_log)
     {
-      int num_fields= mysql_num_fields(res);
-      MYSQL_FIELD *fields= mysql_fetch_fields(res);
-      for (i = 0; i < num_fields; i++)
+      if (res)
       {
-	if (i)
-	  dynstr_append_mem(ds, "\t", 1);
-	dynstr_append(ds, fields[i].name);
+	int num_fields= mysql_num_fields(res);
+	MYSQL_FIELD *fields= mysql_fetch_fields(res);
+
+	for (i = 0; i < num_fields; i++)
+	{
+	  if (i)
+	    dynstr_append_mem(ds, "\t", 1);
+	  dynstr_append(ds, fields[i].name);
+	}
+	dynstr_append_mem(ds, "\n", 1);
+	append_result(ds, res);
       }
-      dynstr_append_mem(ds, "\n", 1);
-      append_result(ds, res);
-    }
 
-    /* Add all warnings to the result */
-    if (!disable_warnings && mysql_warning_count(mysql))
-    {
-      MYSQL_RES *warn_res=0;
-      uint count= mysql_warning_count(mysql);
-      if (!mysql_real_query(mysql, "SHOW WARNINGS", 13))
+      /* Add all warnings to the result */
+      if (!disable_warnings && mysql_warning_count(mysql))
       {
-	warn_res=mysql_store_result(mysql);
+	MYSQL_RES *warn_res=0;
+	uint count= mysql_warning_count(mysql);
+	if (!mysql_real_query(mysql, "SHOW WARNINGS", 13))
+	{
+	  warn_res= mysql_store_result(mysql);
+	}
+	if (!warn_res)
+	  verbose_msg("Warning count is %u but didn't get any warnings\n",
+		      count);
+	else
+	{
+	  dynstr_append_mem(ds, "Warnings:\n", 10);
+	  append_result(ds, warn_res);
+	  mysql_free_result(warn_res);
+	}
       }
-      if (!warn_res)
-	verbose_msg("Warning count is %u but didn't get any warnings\n",
-		    count);
-      else
+      if (!disable_info && mysql_info(mysql))
       {
-	dynstr_append_mem(ds, "Warnings:\n", 10);
-	append_result(ds, warn_res);
-	mysql_free_result(warn_res);
+	dynstr_append(ds, "info: ");
+	dynstr_append(ds, mysql_info(mysql));
+	dynstr_append_mem(ds, "\n", 1);
       }
     }
-    if (!disable_info && mysql_info(mysql))
-    {
-      dynstr_append(ds, "info: ");
-      dynstr_append(ds, mysql_info(mysql));
-      dynstr_append_mem(ds, "\n", 1);
-    }
-  }
 
-  if (glob_replace)
-    free_replace();
+    if (glob_replace)
+      free_replace();
 
-  if (record)
-  {
-    if (!q->record_file[0] && !result_file)
-      die("At line %u: Missing result file", start_lineno);
-    if (!result_file)
-      str_to_file(q->record_file, ds->str, ds->length);
-  }
-  else if (q->record_file[0])
-  {
-    error = check_result(ds, q->record_file, q->require_file);
-  }
+    if (record)
+    {
+      if (!q->record_file[0] && !result_file)
+	die("At line %u: Missing result file", start_lineno);
+      if (!result_file)
+	str_to_file(q->record_file, ds->str, ds->length);
+    }
+    else if (q->record_file[0])
+    {
+      error = check_result(ds, q->record_file, q->require_file);
+    }
+    if (res)
+      mysql_free_result(res);
+    last_result= 0;
+    counter++;
+  } while (!(err= mysql_next_result(mysql)));
+  if (err >= 1)
+    mysql_error(mysql);
 
 end:
-  if (res)
-    mysql_free_result(res);
   last_result=0;
   if (ds == &ds_tmp)
     dynstr_free(&ds_tmp);
@@ -2425,7 +2453,7 @@ int main(int argc, char **argv)
   my_bool require_file=0, q_send_flag=0;
   char save_file[FN_REFLEN];
   MY_INIT(argv[0]);
-  {
+
   DBUG_ENTER("main");
   DBUG_PROCESS(argv[0]);
 
@@ -2520,6 +2548,10 @@ int main(int argc, char **argv)
       case Q_DEC: do_dec(q); break;
       case Q_ECHO: do_echo(q); break;
       case Q_SYSTEM: do_system(q); break;
+      case Q_DELIMITER:
+	strmake(delimiter, q->first_argument, sizeof(delimiter) - 1);
+	delimiter_length= strlen(delimiter);
+	break;
       case Q_LET: do_let(q); break;
       case Q_EVAL_RESULT: eval_result = 1; break;
       case Q_EVAL:
@@ -2646,9 +2678,9 @@ int main(int argc, char **argv)
   free_used_memory();
   exit(error ? 1 : 0);
   return error ? 1 : 0;				/* Keep compiler happy */
-  }
 }
 
+
 /*
   Read arguments for embedded server and put them into
   embedded_server_args_count and embedded_server_args[]
diff --git a/mysql-test/r/multi_statement.result b/mysql-test/r/multi_statement.result
new file mode 100644
index 00000000000..4451b0a355e
--- /dev/null
+++ b/mysql-test/r/multi_statement.result
@@ -0,0 +1,33 @@
+select 1;
+1
+1
+select 2;
+select 3;
+select 4||||
+2
+2
+3
+3
+4
+4
+select 5;
+select 6;
+select 50, 'abc';'abcd'
+5
+5
+6
+6
+50	abc
+50	abc
+select "abcd'";'abcd'
+abcd'
+abcd'
+select "'abcd";'abcd'
+'abcd
+'abcd
+select 5'abcd'
+5
+5
+select 'finish';
+finish
+finish
diff --git a/mysql-test/t/multi_statement.test b/mysql-test/t/multi_statement.test
new file mode 100644
index 00000000000..bd90275c9f5
--- /dev/null
+++ b/mysql-test/t/multi_statement.test
@@ -0,0 +1,13 @@
+select 1;
+delimiter ||||;
+select 2;
+select 3;
+select 4||||
+delimiter 'abcd'||||
+select 5;
+select 6;
+select 50, 'abc';'abcd'
+select "abcd'";'abcd'select "'abcd";'abcd'
+select 5'abcd'
+delimiter ;'abcd'
+select 'finish';
-- 
2.30.9