List:Commits« Previous MessageNext Message »
From:msvensson Date:June 14 2006 3:31pm
Subject:bk commit into 5.1 tree (msvensson:1.2271) BUG#20037
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of msvensson. When msvensson does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2271 06/06/14 17:31:20 msvensson@neptunus.(none) +4 -0
  Bug#20037 mysqltest requires cygwin on windows
   - Update after debugging on Linux
   - Changed write_file and perl commands to read until EOF symbol found in file

  mysql-test/t/mysqltest.test
    1.48 06/06/14 17:31:16 msvensson@neptunus.(none) +91 -46
    Use new syntax for "write_file" and "perl" reading to EOF 

  mysql-test/r/mysqltest.result
    1.39 06/06/14 17:31:15 msvensson@neptunus.(none) +2 -2
    Update test result

  client/mysqltest.c
    1.204 06/06/14 17:31:15 msvensson@neptunus.(none) +187 -147
    Update after debugging on Linux

  client/Makefile.am
    1.67 06/06/14 17:31:15 msvensson@neptunus.(none) +2 -1
    Link mysqltest with mysys

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	msvensson
# Host:	neptunus.(none)
# Root:	/home/msvensson/mysql/my51-mysqltest_no_cyg

--- 1.66/client/Makefile.am	2006-03-24 22:50:43 +01:00
+++ 1.67/client/Makefile.am	2006-06-14 17:31:15 +02:00
@@ -47,7 +47,8 @@ mysqladmin_SOURCES =		mysqladmin.cc
 mysql_LDADD =			@readline_link@ @TERMCAP_LIB@ $(LDADD) $(CXXLDFLAGS)
 mysqltest_SOURCES=		mysqltest.c $(top_srcdir)/mysys/my_getsystime.c \
 				$(yassl_dummy_link_fix)
-mysqltest_LDADD =		$(top_builddir)/regex/libregex.a $(LDADD)
+mysqltest_LDADD =		$(top_builddir)/regex/libregex.a $(LDADD) \
+				$(top_builddir)/mysys/libmysys.a 
 mysqlbinlog_SOURCES =		mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c \
 				$(top_srcdir)/mysys/my_new.cc \
 				$(top_srcdir)/mysys/my_bit.c \

--- 1.38/mysql-test/r/mysqltest.result	2006-04-12 09:28:40 +02:00
+++ 1.39/mysql-test/r/mysqltest.result	2006-06-14 17:31:15 +02:00
@@ -462,8 +462,8 @@ a	D
 drop table t1;
 mysqltest: At line 1: Missing required argument 'filename' to command 'remove_file'
 mysqltest: At line 1: Missing required argument 'filename' to command 'write_file'
-mysqltest: At line 1: Couldn't find first " in argument 'text' to 'write_file' command
-mysqltest: At line 1: Couldn't find last " in argument 'text' to 'write_file' command
+mysqltest: At line 1: End of file encountered before 'EOF' delimiter was found
+mysqltest: At line 1: End of file encountered before 'EOF' delimiter was found
 mysqltest: At line 1: Missing required argument 'filename' to command 'file_exists'
 mysqltest: At line 1: Missing required argument 'from_file' to command 'copy_file'
 mysqltest: At line 1: Missing required argument 'to_file' to command 'copy_file'

--- 1.47/mysql-test/t/mysqltest.test	2006-04-12 09:30:48 +02:00
+++ 1.48/mysql-test/t/mysqltest.test	2006-06-14 17:31:16 +02:00
@@ -89,7 +89,10 @@ select otto from (select 1 as otto) as t
 #!S42S22 select otto from (select 1 as otto) as t1;
 #--error S42S22
 #select otto from (select 1 as otto) as t1;
---write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql "error S42S22; select otto from (select 1 as otto) as t1;"
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+error S42S22; select otto from (select 1 as otto) as t1;
+EOF
+
 --error 1
 --exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
 
@@ -362,21 +365,25 @@ select 3 from t1 ;
 # Missing delimiter
 # The comment will be "sucked into" the sleep command since
 # delimiter is missing until after "show status"
-write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql 
-"sleep 4
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+sleep 4
 # A comment
-show status;";
+show status;
+EOF
+
 --error 1
 --exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
 
 #
 # Missing delimiter until eof
 # The comment will be "sucked into" the sleep command since
-# delimiter is missing 
-write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
-"sleep 7
+# delimiter is missing
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+sleep 7
 # Another comment
-";
+
+EOF
+
 --error 1
 --exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
 
@@ -604,13 +611,19 @@ echo $var3_var3;
 --exec echo "source non_existingFile;" | $MYSQL_TEST 2>&1
 
 # Too many source
---write_file $MYSQLTEST_VARDIR/tmp/recursive.sql "source $MYSQLTEST_VARDIR/tmp/recursive.sql;"
+--write_file $MYSQLTEST_VARDIR/tmp/recursive.sql
+source $MYSQLTEST_VARDIR/tmp/recursive.sql;
+EOF
+
 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
 --error 1
 --exec echo "source $MYSQLTEST_VARDIR/tmp/recursive.sql;" | $MYSQL_TEST 2>&1
 
 # Source a file with error
---write_file $MYSQLTEST_VARDIR/tmp/error.sql "garbage ;"
+--write_file $MYSQLTEST_VARDIR/tmp/error.sql
+garbage ;
+EOF
+
 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
 --error 1
 --exec echo "source $MYSQLTEST_VARDIR/tmp/error.sql;" | $MYSQL_TEST 2>&1
@@ -824,22 +837,27 @@ while (!$i)
 --error 1
 --exec echo "{;" | $MYSQL_TEST 2>&1
 
-write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
-"while (0)
-echo hej;";
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+while (0)
+echo hej;
+EOF
+
 --error 1
 --exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
 
-write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
-"while (0)
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+while (0)
 {echo hej;
-";
+EOF
+
 --error 1
 --exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
 
-write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
-"while (0){
-echo hej;";
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+while (0){
+echo hej;
+EOF
+
 --error 1
 --exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
 
@@ -932,42 +950,50 @@ select "a" as col1, "c" as col2;
 --exec echo "connect (con1,localhost,root,,,,,SMTP POP);" | $MYSQL_TEST 2>&1
 
 # Repeat connect/disconnect
-write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
-"let \$i=100;
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+let \$i=100;
 while (\$i)
 {
   connect (test_con1,localhost,root,,);
   disconnect test_con1;
   dec \$i;
-}";
+}
+EOF
+
 --exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql; echo OK;" | $MYSQL_TEST 2>&1
 
 # Repeat connect/disconnect, exceed max number of connections
-write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
-"let \$i=200;
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+let \$i=200;
 while (\$i)
 {
  connect (test_con1,localhost,root,,);
  disconnect test_con1;
  dec \$i;
-}";
+}
+EOF
+
 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
 --error 1
 --exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql;" | $MYSQL_TEST 2>&1
 
 # Select disconnected connection
-write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
-"connect (test_con1,localhost,root,,);
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+connect (test_con1,localhost,root,,);
 disconnect test_con1;
-connection test_con1;";
+connection test_con1;
+EOF
+
 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
 --error 1
 --exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql;" | $MYSQL_TEST 2>&1
 
 # Connection name already used
-write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
-"connect (test_con1,localhost,root,,);
-connect (test_con1,localhost,root,,);";
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+connect (test_con1,localhost,root,,);
+connect (test_con1,localhost,root,,);
+EOF
+
 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
 --error 1
 --exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql;" | $MYSQL_TEST 2>&1
@@ -1064,14 +1090,22 @@ select "this will be executed";
 #
 # Test zero length result file. Should not pass
 #
---write_file $MYSQLTEST_VARDIR/tmp/zero_length_file.result ""
---write_file $MYSQLTEST_VARDIR/tmp/query.sql "echo ok;"
+--write_file $MYSQLTEST_VARDIR/tmp/zero_length_file.result
+EOF
+
+--write_file $MYSQLTEST_VARDIR/tmp/query.sql
+echo ok;
+EOF
+
 --error 1
 --exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/query.sql -R $MYSQLTEST_VARDIR/tmp/zero_length_file.result  2>&1
 #
 # Test that a test file that does not generate any output fails.
 #
---write_file $MYSQLTEST_VARDIR/tmp/query.sql "let \$i= 1;"
+--write_file $MYSQLTEST_VARDIR/tmp/query.sql
+let \$i= 1;
+EOF
+
 --error 1
 --exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/query.sql  2>&1
 
@@ -1092,15 +1126,16 @@ select "this will be executed";
 
 echo Failing multi statement query;
 
-write_file $MYSQLTEST_VARDIR/tmp/bug11731.sql
-"# PS does not support multi statement
+--write_file $MYSQLTEST_VARDIR/tmp/bug11731.sql
+# PS does not support multi statement
 --disable_ps_protocol
 delimiter ||||;
 create table t1 (a int primary key);
 insert into t1 values (1);
 select 'select-me';
 insertz 'error query'||||
-delimiter ;||||";
+delimiter ;||||
+EOF
 
 --error 1
 --exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/bug11731.sql 2>&1
@@ -1115,8 +1150,8 @@ drop table t1;
 drop table t1;
 
 echo Multi statement using expected error;
-write_file $MYSQLTEST_VARDIR/tmp/bug11731.sql
-"# PS does not support multi statement
+-- write_file $MYSQLTEST_VARDIR/tmp/bug11731.sql
+# PS does not support multi statement
 --disable_ps_protocol
 delimiter ||||;
 --error 1064
@@ -1124,7 +1159,8 @@ create table t1 (a int primary key);
 insert into t1 values (1);
 select 'select-me';
 insertz 'error query'||||
-delimiter ;||||";
+delimiter ;||||
+EOF
 
 # These two should work since the error is expected
 --exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/bug11731.sql  2>&1
@@ -1204,7 +1240,10 @@ drop table t1;
 # ----------------------------------------------------------------------------
 # test for copy_file
 # ----------------------------------------------------------------------------
-write_file $MYSQLTEST_VARDIR/tmp/file1.tmp "file1";
+--write_file $MYSQLTEST_VARDIR/tmp/file1.tmp
+file1
+EOF
+
 copy_file $MYSQLTEST_VARDIR/tmp/file1.tmp $MYSQLTEST_VARDIR/tmp/file2.tmp;
 file_exists $MYSQLTEST_VARDIR/tmp/file2.tmp;
 remove_file $MYSQLTEST_VARDIR/tmp/file1.tmp;
@@ -1218,10 +1257,16 @@ remove_file $MYSQLTEST_VARDIR/tmp/file2.
 # ----------------------------------------------------------------------------
 # test for perl
 # ----------------------------------------------------------------------------
---perl "print "hello\n";"
-perl "print "hello\n";";
-perl "
-  # Print "hello" 
+--perl
+print "hello\n";
+EOF
+
+perl;
+print "hello\n";
+EOF
+
+perl;
+  # Print "hello"
   print "hello\n";
-";
+EOF
 

--- 1.203/client/mysqltest.c	2006-04-12 09:28:40 +02:00
+++ 1.204/client/mysqltest.c	2006-06-14 17:31:15 +02:00
@@ -490,7 +490,7 @@ typedef struct st_pointer_array {		/* wh
 struct st_replace;
 struct st_replace *init_replace(my_string *from, my_string *to, uint count,
 				my_string word_end_chars);
-void free_replace();
+static void free_replace();
 static void free_replace_regex();
 static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name);
 static void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
@@ -586,13 +586,11 @@ enum arg_type
 };
 
 struct command_arg {
-  char* argname;       /* Name of argument   */
-  enum arg_type type;  /* Type of argument   */
-  my_bool required;    /* Argument required  */
-  union {
-    DYNAMIC_STRING *ds;/* Storage for string argument */
-  };
-  char *description;  /* Description of the argument */
+  const char* argname;       /* Name of argument   */
+  enum arg_type type;        /* Type of argument   */
+  my_bool required;          /* Argument required  */
+  DYNAMIC_STRING *ds;        /* Storage for string argument */
+  const char *description;   /* Description of the argument */
 };
 
 static void check_command_args(struct st_query *command, const char *arguments,
@@ -600,14 +598,14 @@ static void check_command_args(struct st
 {
   int i;
   const char *ptr= arguments;
-  const char *end, *start;
+  const char *start;
 
   DBUG_ENTER("check_command_args");
   DBUG_PRINT("enter", ("num_args: %d", num_args));
   for (i= 0; i < num_args; i++)
   {
     const struct command_arg *arg= &args[i];
- 
+
     switch (arg->type)
     {
     /* A string surrounded by spaces */
@@ -623,24 +621,11 @@ static void check_command_args(struct st
         ptr++;
       break;
 
-    /* Rest of line, surrounded by " */ 
+    /* Rest of line */
     case ARG_REST:
-      /* Find first " */
-      while (*ptr && *ptr != '"')
-        ptr++;
-      if (*ptr != '"')
-        die("Couldn't find first \" in argument '%s' to '%.*s' command",
-            arg->argname, command->first_word_len, command->query);
-      ptr++; /* Step past it */
-      /* Find last " */
-      end= command->end;
-      while (end > ptr && *end != '"')
-        end--;
-      if (*end != '"')
-        die("Couldn't find last \" in argument '%s' to '%.*s' command",
-            arg->argname, command->first_word_len, command->query);
+      start= ptr;
       init_dynamic_string(arg->ds, 0, command->query_len, 256);
-      do_eval(arg->ds, ptr, end);
+      do_eval(arg->ds, start, command->end);
       command->last_argument= command->end;
       break;
 
@@ -651,14 +636,15 @@ static void check_command_args(struct st
 
     /* Check required arg */
     if (arg->ds->length == 0 && arg->required)
-      die("Missing required argument '%s' to command '%.*s'", arg->argname, command->first_word_len, command->query);
+      die("Missing required argument '%s' to command '%.*s'", arg->argname,
+          command->first_word_len, command->query);
 
   }
   DBUG_VOID_RETURN;
 }
 
 
-static void handle_command_error(struct st_query *command, int error)
+static void handle_command_error(struct st_query *command, uint error)
 {
   DBUG_ENTER("handle_command_error");
   DBUG_PRINT("enter", ("error: %d", error));
@@ -1089,6 +1075,12 @@ int open_file(const char *name)
 }
 
 
+static void set_delimiter(const char* delimiter_str)
+{
+  strmake(delimiter, delimiter_str, sizeof(delimiter) - 1);
+  delimiter_length= strlen(delimiter);
+}
+
 /*
   Check for unexpected "junk" after the end of query
   This is normally caused by missing delimiters
@@ -1274,9 +1266,9 @@ static void do_exec(struct st_query *que
     DYNAMIC_STRING ds_text;
     char *text_start, *ptr= cmd+5;
     /*
-      Special handling of "exec echo "<text>" | <command>" for backward compatibility,
-      find <text> and write it to temp file. Then make the command read from
-      that file by using input redirection operator <
+      Special handling of "exec echo "<text>" | <command>" for backward
+      compatibility, find <text> and write it to temp file. Then make the
+      command read from that file by using input redirection operator <
       ex. <command> < tmp_89.sql
     */
     while (*ptr && my_isspace(charset_info, *ptr))
@@ -1297,7 +1289,7 @@ static void do_exec(struct st_query *que
     /* Write to file */
     DBUG_PRINT("info", ("Writing %s to file", ds_text.str));
     /* Format a name for a tmp file that is unique for this process */
-    my_snprintf(tmp_name, sizeof(tmp_name), "%s/tmp/tmp_%d.sql", 
+    my_snprintf(tmp_name, sizeof(tmp_name), "%s/tmp/tmp_%d.sql",
                 getenv("MYSQLTEST_VARDIR"), getpid());
     str_to_file(tmp_name, ds_text.str, ds_text.length);
     dynstr_free(&ds_text);
@@ -1308,10 +1300,10 @@ static void do_exec(struct st_query *que
     if (*ptr != '|')
        die("Couldn't find | in 'exec echo' command");
     ptr++;
-  
+
     /* Make cmd start at first char after | */
     cmd= ptr;
-  
+
     init_dynamic_string(&ds_cmd, 0, query->query_len, 256);
     /* Eval the command, thus replacing all environment variables */
     do_eval(&ds_cmd, cmd, query->end);
@@ -1410,7 +1402,6 @@ int var_query_set(VAR* var, const char *
     uint i;
     ulong *lengths;
     char *end;
-    MYSQL_FIELD *fields= mysql_fetch_fields(res);
 
     init_dynamic_string(&result, "", 16384, 65536);
     lengths= mysql_fetch_lengths(res);
@@ -1418,21 +1409,6 @@ int var_query_set(VAR* var, const char *
     {
       if (row[0])
       {
-#ifdef NOT_YET
-	/* Add to <var_name>_<col_name> */
-	uint j;
-	char var_col_name[MAX_VAR_NAME];
-	uint length= snprintf(var_col_name, MAX_VAR_NAME,
-			      "$%s_%s", var->name, fields[i].name);
-	/* Convert characters not allowed in variable names to '_' */
-	for (j= 1; j < length; j++)
-	{
-	  if (!my_isvar(charset_info,var_col_name[j]))
-	     var_col_name[j]= '_';
-        }
-	var_set(var_col_name,  var_col_name + length,
-		row[i], row[i] + lengths[i]);
-#endif
         /* Add column to tab separated string */
 	dynstr_append_mem(&result, row[i], lengths[i]);
       }
@@ -1570,7 +1546,7 @@ int do_modify_var(struct st_query *query
   Not supported any more
 */
 
-static void do_system(struct st_query *command)
+static void do_system(struct st_query *command __attribute__((unused)))
 {
   DBUG_ENTER("do_system");
   die("system command not supported anymore");
@@ -1629,43 +1605,135 @@ static void do_file_exist(struct st_quer
 
   check_command_args(command, command->first_argument,
       file_exist_args, sizeof(file_exist_args)/sizeof(struct command_arg));
-  
+
   DBUG_PRINT("info", ("Checking for existence of file: %s", ds_filename.str));
-  error= access(ds_filename.str, F_OK) != 0;
+  error= (access(ds_filename.str, F_OK) != 0);
   handle_command_error(command, error);
   dynstr_free(&ds_filename);
   DBUG_VOID_RETURN;
 }
 
+
+/*
+  Read characters from line buffer or file. This is needed to allow
+  my_ungetc() to buffer MAX_DELIMITER characters for a file
+
+  NOTE:
+    This works as long as one doesn't change files (with 'source file_name')
+    when there is things pushed into the buffer.  This should however not
+    happen for any tests in the test suite.
+*/
+
+int my_getc(FILE *file)
+{
+  if (line_buffer_pos == line_buffer)
+    return fgetc(file);
+  return *--line_buffer_pos;
+}
+
+void my_ungetc(int c)
+{
+  *line_buffer_pos++= (char) c;
+}
+
+
+my_bool match_delimiter(int c, const char* delim, uint length)
+{
+  uint i;
+  char tmp[MAX_DELIMITER];
+
+  if (c != *delim)
+    return 0;
+
+  for (i= 1; i < length &&
+	 (c= my_getc(cur_file->file)) == *(delim + i);
+       i++)
+    tmp[i]= c;
+
+  if (i == length)
+    return 1;					/* Found delimiter */
+
+  /* didn't find delimiter, push back things that we read */
+  my_ungetc(c);
+  while (i > 1)
+    my_ungetc(tmp[--i]);
+  return 0;
+}
+
+
+my_bool end_of_query(int c)
+{
+  return match_delimiter(c, delimiter, delimiter_length);
+}
+
+
+static void read_until_EOF(DYNAMIC_STRING* ds)
+{
+  int c;
+  DBUG_ENTER("read_until_EOF");
+  /* Read from file until delimiter EOF is found */
+  while (1)
+  {
+    c= my_getc(cur_file->file);
+
+    if (feof(cur_file->file))
+      die("End of file encountered before 'EOF' delimiter was found");
+
+    if (match_delimiter(c, "EOF", 3))
+    {
+      DBUG_PRINT("exit", ("Found EOF"));
+      break;
+    }
+    dynstr_append_mem(ds, (const char*)&c, 1);
+  }
+  DBUG_PRINT("exit", ("ds: %s", ds->str));
+  DBUG_VOID_RETURN;
+}
+
 /*
   SYNOPSIS
   do_write_file
     command	called command
 
   DESCRIPTION
-    write_file <file_name> "<what to write>"
-    Write <what_to_write> to <file_name>
+    write_file <file_name>;
+    <what to write line 1>
+    <...>
+    < what to write line n>
+    EOF
+
+    --write_file <file_name>;
+    <what to write line 1>
+    <...>
+    < what to write line n>
+    EOF
+
+    Write everything between the "write_file" command and EOF to "file_name"
 
     NOTE! Overwrites existing file
+
 */
 
 static void do_write_file(struct st_query *command)
 {
-  DYNAMIC_STRING ds_filename;
   DYNAMIC_STRING ds_content;
+  DYNAMIC_STRING ds_filename;
   const struct command_arg write_file_args[] = {
     "filename", ARG_STRING, TRUE, &ds_filename, "File to write to",
-    "text", ARG_REST, FALSE, &ds_content, "What to write to the file"
   };
   DBUG_ENTER("do_write_file");
 
-  check_command_args(command, command->first_argument,
-      write_file_args, sizeof(write_file_args)/sizeof(struct command_arg));
-  
+  check_command_args(command,
+                     command->first_argument,
+                     write_file_args,
+                     sizeof(write_file_args)/sizeof(struct command_arg));
+
+  init_dynamic_string(&ds_content, "", 1024, 1024);
+  read_until_EOF(&ds_content);
   DBUG_PRINT("info", ("Writing to file: %s", ds_filename.str));
   str_to_file(ds_filename.str, ds_content.str, ds_content.length);
-  dynstr_free(&ds_filename);
   dynstr_free(&ds_content);
+  dynstr_free(&ds_filename);
   DBUG_VOID_RETURN;
 }
 
@@ -1673,12 +1741,25 @@ static void do_write_file(struct st_quer
 /*
   SYNOPSIS
   do_perl
-    command	called command
+    command	command handle
 
   DESCRIPTION
-    perl "<perlscript>"
-    Execute <perlscript> in perl. Useful for doing more advanced things but still
-    being able to execute it on all platforms.
+    perl;
+    <perlscript line 1>
+    <...>
+    <perlscript line n>
+    EOF
+
+    Execute everything after "perl" until EOF as perl.
+    Useful for doing more advanced things
+    but still being able to execute it on all platforms.
+
+    The function sets delimiter to EOF and remembers that this
+    is a perl command by setting "perl mode". The following lines
+    will then be parsed as any normal query, but when searching
+    for command in get_query_type, this function will be called
+    again since "perl mode" is on and the perl script can be
+    executed.
 */
 
 static void do_perl(struct st_query *command)
@@ -1687,23 +1768,20 @@ static void do_perl(struct st_query *com
   char buf[FN_REFLEN];
   FILE *res_file;
   DYNAMIC_STRING ds_script;
-  const struct command_arg perl_args[] = {
-    "script", ARG_REST, TRUE, &ds_script, "Perlscript to execute"
-  };
   DBUG_ENTER("do_perl");
 
-  check_command_args(command, command->first_argument,
-      perl_args, sizeof(perl_args)/sizeof(struct command_arg));
-  
+  init_dynamic_string(&ds_script, "", 1024, 1024);
+  read_until_EOF(&ds_script);
+
   DBUG_PRINT("info", ("Executing perl: %s", ds_script.str));
 
   /* Format a name for a tmp .pl file that is unique for this process */
-  my_snprintf(buf, sizeof(buf), "%s/tmp/tmp_%d.pl", 
+  my_snprintf(buf, sizeof(buf), "%s/tmp/tmp_%d.pl",
               getenv("MYSQLTEST_VARDIR"), getpid());
   str_to_file(buf, ds_script.str, ds_script.length);
 
   /* Format the perl <filename> command */
-  my_snprintf(buf, sizeof(buf), "perl %s/tmp/tmp_%d.pl", 
+  my_snprintf(buf, sizeof(buf), "perl %s/tmp/tmp_%d.pl",
               getenv("MYSQLTEST_VARDIR"), getpid());
 
   if (!(res_file= popen(buf, "r")) && command->abort_on_error)
@@ -1731,7 +1809,7 @@ static void do_perl(struct st_query *com
 /*
   SYNOPSIS
   do_copy_file
-    command	called command
+    command	command handle
 
   DESCRIPTION
     copy_file <from_file> <to_file>
@@ -1753,9 +1831,10 @@ static void do_copy_file(struct st_query
 
   check_command_args(command, command->first_argument,
       copy_file_args, sizeof(copy_file_args)/sizeof(struct command_arg));
-  
+
   DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
-  error= my_copy(ds_from_file.str, ds_to_file.str, MYF(MY_DONT_OVERWRITE_FILE)) != 0;
+  error= (my_copy(ds_from_file.str, ds_to_file.str,
+                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
   handle_command_error(command, error);
   dynstr_free(&ds_from_file);
   dynstr_free(&ds_to_file);
@@ -2069,7 +2148,7 @@ int do_disable_rpl_parse(struct st_query
 
 
 /*
-  Sleep the number of specifed seconds
+  Sleep the number of specified seconds
 
   SYNOPSIS
    do_sleep()
@@ -3111,9 +3190,7 @@ void do_block(enum block_cmd cmd, struct
 
   while (*p && my_isspace(charset_info, *p))
     p++;
-  if (*p == '{')
-    die("Missing newline between %s and '{'", cmd_name);
-  if (*p)
+  if (*p && *p != '{')
     die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
 
   var_init(&v,0,0,0,0);
@@ -3134,51 +3211,6 @@ void do_block(enum block_cmd cmd, struct
 }
 
 
-/*
-  Read characters from line buffer or file. This is needed to allow
-  my_ungetc() to buffer MAX_DELIMITER characters for a file
-
-  NOTE:
-    This works as long as one doesn't change files (with 'source file_name')
-    when there is things pushed into the buffer.  This should however not
-    happen for any tests in the test suite.
-*/
-
-int my_getc(FILE *file)
-{
-  if (line_buffer_pos == line_buffer)
-    return fgetc(file);
-  return *--line_buffer_pos;
-}
-
-void my_ungetc(int c)
-{
-  *line_buffer_pos++= (char) c;
-}
-
-
-my_bool end_of_query(int c)
-{
-  uint i;
-  char tmp[MAX_DELIMITER];
-
-  if (c != *delimiter)
-    return 0;
-
-  for (i= 1; i < delimiter_length &&
-	 (c= my_getc(cur_file->file)) == *(delimiter + i);
-       i++)
-    tmp[i]= c;
-
-  if (i == delimiter_length)
-    return 1;					/* Found delimiter */
-
-  /* didn't find delimiter, push back things that we read */
-  my_ungetc(c);
-  while (i > 1)
-    my_ungetc(tmp[--i]);
-  return 0;
-}
 
 
 /*
@@ -3199,24 +3231,30 @@ my_bool end_of_query(int c)
     The function should be smart enough not to detect delimiter's
     found inside strings surrounded with '"' and '\'' escaped strings.
 
-    If the first line in a query starts with '#' or '-' this line is treated
-    as a comment. A comment is always terminated when end of line '\n' is
-    reached.
+    It will also return if:
+     - the first char in a line starts with '#' or '-', this line
+       is treated as a comment. A comment is always terminated when
+       end of line '\n' is reached.
+
+     - it finds '{' or '}', this is used for "while" and "if" blocks.
+
+     - if finds the end of the file
 
 */
 
-int read_line(char *buf, int size)
+static int read_line(char *buf, int size)
 {
   int c;
   char quote;
   char *p= buf, *buf_end= buf + size - 1;
   int no_save= 0;
-  enum {R_NORMAL, R_Q, R_Q_IN_Q, R_SLASH_IN_Q,
+  enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
 	R_COMMENT, R_LINE_START} state= R_LINE_START;
   DBUG_ENTER("read_line");
   LINT_INIT(quote);
 
   start_lineno= cur_file->lineno;
+  DBUG_PRINT("info", ("start_lineno: %d", start_lineno));
   for (; p < buf_end ;)
   {
     no_save= 0;
@@ -3260,10 +3298,17 @@ int read_line(char *buf, int size)
 
     switch(state) {
     case R_NORMAL:
-      /*  Only accept '{' in the beginning of a line */
       if (end_of_query(c))
       {
 	*p= 0;
+        DBUG_PRINT("exit", ("Found delimiter '%s'", delimiter));
+	DBUG_RETURN(0);
+      }
+      else if (c == '{' || c == '}')
+      {
+        *p++= c;
+	*p= 0;
+        DBUG_PRINT("exit", ("Found '%c'", c));
 	DBUG_RETURN(0);
       }
       else if (c == '\'' || c == '"' || c == '`')
@@ -3281,6 +3326,7 @@ int read_line(char *buf, int size)
       if (c == '\n')
       {
 	*p= 0;
+        DBUG_PRINT("exit", ("Found newline in comment"));
 	DBUG_RETURN(0);
       }
       break;
@@ -3298,15 +3344,17 @@ int read_line(char *buf, int size)
 	  start_lineno= cur_file->lineno; /* Query hasn't started yet */
 	no_save= 1;
       }
-      else if (c == '}')
+      else if (end_of_query(c))
       {
-	*buf++= '}';
-	*buf= 0;
+	*p= 0;
+        DBUG_PRINT("exit", ("Found delimiter '%s'", delimiter));
 	DBUG_RETURN(0);
       }
-      else if (end_of_query(c) || c == '{')
+      else if (c == '{'  || c == '}')
       {
+        *p++= c;
 	*p= 0;
+        DBUG_PRINT("exit", ("Found '%c'", c));
 	DBUG_RETURN(0);
       }
       else if (c == '\'' || c == '"' || c == '`')
@@ -3319,19 +3367,12 @@ int read_line(char *buf, int size)
       break;
 
     case R_Q:
-      /*if ((c == '\'' || c == '"' || c == '`') && c != quote)
-	state= R_Q_IN_Q;
-      else */if (c == quote)
+      if (c == quote)
 	state= R_NORMAL;
       else if (c == '\\')
 	state= R_SLASH_IN_Q;
       break;
 
-    case R_Q_IN_Q:
-      if (c == quote)
-	state= R_Q;
-      break;
-
     case R_SLASH_IN_Q:
       state= R_Q;
       break;
@@ -3426,8 +3467,9 @@ int read_query(struct st_query** q_ptr)
     check_eol_junk(read_query_buf);
     DBUG_RETURN(1);
   }
-  
+
   DBUG_PRINT("info", ("query: %s", read_query_buf));
+
   if (*p == '#')
   {
     q->type= Q_COMMENT;
@@ -3452,7 +3494,6 @@ int read_query(struct st_query** q_ptr)
     while (*p && my_isspace(charset_info, *p))
       p++ ;
   }
-
 end:
   while (*p && my_isspace(charset_info, *p))
     p++;
@@ -5485,8 +5526,7 @@ int main(int argc, char **argv)
       case Q_COPY_FILE: do_copy_file(q); break;
       case Q_PERL: do_perl(q); break;
       case Q_DELIMITER:
-	strmake(delimiter, q->first_argument, sizeof(delimiter) - 1);
-	delimiter_length= strlen(delimiter);
+        set_delimiter(q->first_argument);
         q->last_argument= q->first_argument+delimiter_length;
 	break;
       case Q_DISPLAY_VERTICAL_RESULTS:
Thread
bk commit into 5.1 tree (msvensson:1.2271) BUG#20037msvensson14 Jun