List:Commits« Previous MessageNext Message »
From:msvensson Date:June 1 2007 10:38am
Subject:bk commit into 5.1 tree (msvensson:1.2508)
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@stripped, 2007-06-01 12:38:54+02:00, msvensson@pilot.(none) +3 -0
  Merge pilot.(none):/data/msvensson/mysql/bug28497/my50-bug28497
  into  pilot.(none):/data/msvensson/mysql/bug28497/my51-bug28497
  MERGE: 1.1810.2938.21

  client/mysqltest.c@stripped, 2007-06-01 12:38:51+02:00, msvensson@pilot.(none) +0 -0
    Auto merged
    MERGE: 1.155.9.102

  mysql-test/r/mysqltest.result@stripped, 2007-06-01 12:38:51+02:00, msvensson@pilot.(none) +0 -0
    Auto merged
    MERGE: 1.24.1.24

  mysql-test/t/mysqltest.test@stripped, 2007-06-01 12:38:52+02:00, msvensson@pilot.(none) +0 -0
    Auto merged
    MERGE: 1.24.1.34

# 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:	pilot.(none)
# Root:	/data/msvensson/mysql/bug28497/my51-bug28497/RESYNC

--- 1.60/mysql-test/r/mysqltest.result	2007-05-18 12:58:03 +02:00
+++ 1.61/mysql-test/r/mysqltest.result	2007-06-01 12:38:51 +02:00
@@ -666,4 +666,43 @@ INSERT INTO t1 SELECT f1 - 256 FROM t1;
 INSERT INTO t1 SELECT f1 - 512 FROM t1;
 SELECT * FROM t1;
 DROP TABLE t1;
+CREATE TABLE t1(
+a int, b varchar(255), c datetime
+);
+SHOW COLUMNS FROM t1;
+Field	Type	Null	Key	Default	Extra
+a	int(11)	YES		NULL	
+b	varchar(255)	YES		NULL	
+c	datetime	YES		NULL	
+statement=SHOW COLUMNS FROM t1 row_number=1, column_name="Type", Value=int(11)
+statement="SHOW COLUMNS FROM t1" row_number=1, column_name="Type", Value=int(11)
+statement=SHOW COLUMNS FROM t1 row_number=1, column_name=Default, Value=NULL
+value= ->A B<-
+value= 1
+mysqltest: At line 1: query_get_value - argument list started with '(' must be ended with ')'
+mysqltest: At line 1: Missing required argument 'query' to command 'query_get_value'
+mysqltest: At line 1: Missing required argument 'column name' to command 'query_get_value'
+mysqltest: At line 1: Missing required argument 'row number' to command 'query_get_value'
+value= No such row
+value= No such row
+mysqltest: At line 1: Invalid row number: 'notnumber'
+mysqltest: At line 1: Could not find column 'column_not_exists' in the result of 'SHOW COLUMNS FROM t1'
+mysqltest: At line 1: Query 'SET @A = 1' didn't return a result set
+mysqltest: At line 1: Could not find column '1 AS B' in the result of 'SELECT 1 AS A'
+value= No such row
+mysqltest: At line 1: Error running query 'SHOW COLNS FROM t1': 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'COLNS FROM t1' at line 1
+
+Field Type Null Key Default Extra
+a int(11) YES -><- NULL 
+b varchar(255) YES -><- NULL 
+c datetime YES -><- NULL 
+
+Number of columns with Default NULL: 3
+
+SHOW COLUMNS FROM t1;
+Field	Type	Null	Key	Default	Extra
+a	int(11)	YES		NULL	
+b	varchar(255)	YES		NULL	
+c	datetime	YES		NULL	
+drop table t1;
 End of tests

--- 1.73/mysql-test/t/mysqltest.test	2007-05-18 12:58:03 +02:00
+++ 1.74/mysql-test/t/mysqltest.test	2007-06-01 12:38:52 +02:00
@@ -1876,5 +1876,127 @@ DROP TABLE t1;
 --error 1
 --exec $MYSQL_TEST a b c 2>&1 > /dev/null
 --enable_abort_on_error
+--enable_query_log
+
+# ----------------------------------------------------------------------------
+# test for query_get_value
+# ----------------------------------------------------------------------------
+
+CREATE TABLE t1(
+ a int, b varchar(255), c datetime
+);
+SHOW COLUMNS FROM t1;
+
+#------------ Positive tests ------------
+# 1. constant parameters
+#    value is simple string without spaces
+let $value= query_get_value(SHOW COLUMNS FROM t1, Type, 1);
+--echo statement=SHOW COLUMNS FROM t1 row_number=1, column_name="Type", Value=$value
+let $value= query_get_value("SHOW COLUMNS FROM t1", Type, 1);
+--echo statement="SHOW COLUMNS FROM t1" row_number=1, column_name="Type", Value=$value
+#
+# 2. $variables as parameters
+#    value IS NULL
+let $my_show= SHOW COLUMNS FROM t1;
+let $column_name= Default;
+let $row_number= 1;
+let $value= query_get_value($my_show, $column_name, $row_number);
+--echo statement=$my_show row_number=$row_number, column_name=$column_name, Value=$value
+#
+# 3. result set of a SELECT (not recommended, because projection and
+#         selection could be done much better by pure SELECT functionality)
+#    value is string with space in the middle
+let $value= query_get_value(SELECT 'A B' AS "MyColumn", MyColumn, 1);
+--echo value= ->$value<-
+#
+# 4. column name with space
+let $value= query_get_value(SELECT 1 AS "My Column", My Column, 1);
+--echo value= $value
+#
+#------------ Negative tests ------------
+# 5. Incomplete statement including missing parameters
+# 5.1 incomplete statement
+--error 1
+--exec echo "let \$value= query_get_value(SHOW;" | $MYSQL_TEST 2>&1
+# 5.2 missing query
+--error 1
+--exec echo "let \$value= query_get_value;" | $MYSQL_TEST 2>&1
+# 5.3 missing column name
+--error 1
+--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1);" | $MYSQL_TEST 2>&1
+# 5.4 missing row number
+--error 1
+--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1, Field);" | $MYSQL_TEST 2>&1
+#
+# 6. Somehow "wrong" value of parameters
+# 6.1 row parameter
+# 6.1.1 non sense number 0
+let $value= initialized;
+let $value= query_get_value(SHOW COLUMNS FROM t1, Field, 0);
+--echo value= $value
+# 6.1.2 after the last row
+let $value= initialized;
+let $value= query_get_value(SHOW COLUMNS FROM t1, Field, 10);
+--echo value= $value
+# 6.1.3 invalid row number
+--error 1
+--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1, Field, notnumber);" | $MYSQL_TEST 2>&1
+# 6.2 column name parameter, name of not existing column
+--error 1
+--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1, column_not_exists, 1);" | $MYSQL_TEST 2>&1
+# 6.3. statement which never gives a result set
+--error 1
+--exec echo "let \$value= query_get_value(SET @A = 1, Field, 1);" | $MYSQL_TEST 2>&1
+# 6.4. statement contains a ","
+#      Note: There is no need to improve this, because we need query_get_value
+#            for SHOW commands only.
+--error 1
+--exec echo "let \$value= query_get_value(SELECT 1 AS "A", 1 AS "B", 1);" | $MYSQL_TEST 2>&1
+#
+# 7. empty result set
+let $value= initialized;
+let $value= query_get_value(SELECT a FROM t1, a, 1);
+--echo value= $value
+#
+# 9. failing statement
+--error 1
+--exec echo "let \$value= query_get_value(SHOW COLNS FROM t1, Field, 1);" | $MYSQL_TEST 2>&1
+#
+# 10. Artificial example how to process a complete SHOW result set:
+let $show_statement= SHOW COLUMNS FROM t1;
+let $rowno= 1;
+let $run=1;
+let $count= 0;
+--echo
+--echo Field Type Null Key Default Extra
+while ($run)
+{
+   let $Field=   query_get_value($show_statement, Field,   $rowno);
+   if (`SELECT '$Field' = 'No such row'`)
+   {
+      let $run= 0;
+   }
+   if (`SELECT '$Field' <> 'No such row'`)
+   {
+      let $Type=    query_get_value($show_statement, Type,    $rowno);
+      let $Null=    query_get_value($show_statement, Null,    $rowno);
+      if (`SELECT '$Null' = 'YES'`)
+      {
+         inc $count;
+      }
+      let $Key=     query_get_value($show_statement, Key,     $rowno);
+      let $Default= query_get_value($show_statement, Default, $rowno);
+      let $Extra=   query_get_value($show_statement, Extra,   $rowno);
+      --echo $Field $Type $Null ->$Key<- $Default $Extra
+      inc $rowno;
+   }
+}
+--echo
+--echo Number of columns with Default NULL: $count
+--echo
+eval $show_statement;
+
+drop table t1;
 
 --echo End of tests
+

--- 1.299/client/mysqltest.c	2007-05-18 13:00:59 +02:00
+++ 1.300/client/mysqltest.c	2007-06-01 12:38:51 +02:00
@@ -1127,6 +1127,50 @@ void check_require(DYNAMIC_STRING* ds, c
 }
 
 
+/*
+   Remove surrounding chars from string
+
+   Return 1 if first character is found but not last
+*/
+static int strip_surrounding(char* str, char c1, char c2)
+{
+  char* ptr= str;
+
+  /* Check if the first non space character is c1 */
+  while(*ptr && my_isspace(charset_info, *ptr))
+    ptr++;
+  if (*ptr == c1)
+  {
+    /* Replace it with a space */
+    *ptr= ' ';
+
+    /* Last non space charecter should be c2 */
+    ptr= strend(str)-1;
+    while(*ptr && my_isspace(charset_info, *ptr))
+      ptr--;
+    if (*ptr == c2)
+    {
+      /* Replace it with \0 */
+      *ptr= 0;
+    }
+    else
+    {
+      /* Mismatch detected */
+      return 1;
+    }
+  }
+  return 0;
+}
+
+
+static void strip_parentheses(struct st_command *command)
+{
+  if (strip_surrounding(command->first_argument, '(', ')'))
+      die("%.*s - argument list started with '%c' must be ended with '%c'",
+          command->first_word_len, command->query, '(', ')');
+}
+
+
 static byte *get_var_key(const byte* var, uint* len,
                   my_bool __attribute__((unused)) t)
 {
@@ -1382,12 +1426,11 @@ void var_query_set(VAR *var, const char 
   init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
   do_eval(&ds_query, query, end, FALSE);
 
-  if (mysql_real_query(mysql, ds_query.str, ds_query.length) ||
-      !(res = mysql_store_result(mysql)))
-  {
+  if (mysql_real_query(mysql, ds_query.str, ds_query.length))
     die("Error running query '%s': %d %s", ds_query.str,
 	mysql_errno(mysql), mysql_error(mysql));
-  }
+  if (!(res= mysql_store_result(mysql)))
+    die("Query '%s' didn't return a result set", ds_query.str);
   dynstr_free(&ds_query);
 
   if ((row = mysql_fetch_row(res)) && row[0])
@@ -1441,6 +1484,130 @@ void var_query_set(VAR *var, const char 
 }
 
 
+/*
+  Set variable from the result of a field in a query
+
+  This function is useful when checking for a certain value
+  in the output from a query that can't be restricted to only
+  return some values. A very good example of that is most SHOW
+  commands.
+
+  SYNOPSIS
+  var_set_query_get_value()
+
+  DESCRIPTION
+  let $variable= query_get_value(<query to run>,<column name>,<row no>);
+
+  <query to run> -    The query that should be sent to the server
+  <column name> -     Name of the column that holds the field be compared
+                      against the expected value
+  <row no> -          Number of the row that holds the field to be
+                      compared against the expected value
+
+*/
+
+void var_set_query_get_value(struct st_command *command, VAR *var)
+{
+  ulong row_no;
+  int col_no= -1;
+  MYSQL_RES* res;
+  MYSQL* mysql= &cur_con->mysql;
+  LINT_INIT(res);
+
+  static DYNAMIC_STRING ds_query;
+  static DYNAMIC_STRING ds_col;
+  static DYNAMIC_STRING ds_row;
+  const struct command_arg query_get_value_args[] = {
+    "query", ARG_STRING, TRUE, &ds_query, "Query to run",
+    "column name", ARG_STRING, TRUE, &ds_col, "Name of column",
+    "row number", ARG_STRING, TRUE, &ds_row, "Number for row",
+  };
+
+  DBUG_ENTER("var_set_query_get_value");
+
+  strip_parentheses(command);
+  DBUG_PRINT("info", ("query: %s", command->query));
+  check_command_args(command, command->first_argument, query_get_value_args,
+                     sizeof(query_get_value_args)/sizeof(struct command_arg),
+                     ',');
+
+  DBUG_PRINT("info", ("query: %s", ds_query.str));
+  DBUG_PRINT("info", ("col: %s", ds_col.str));
+
+  /* Convert row number to int */
+  if (!str2int(ds_row.str, 10, (long) 0, (long) INT_MAX, &row_no))
+    die("Invalid row number: '%s'", ds_row.str);
+  DBUG_PRINT("info", ("row: %s, row_no: %ld", ds_row.str, row_no));
+  dynstr_free(&ds_row);
+
+  /* Remove any surrounding "'s from the query - if there is any */
+  if (strip_surrounding(ds_query.str, '"', '"'))
+    die("Mismatched \"'s around query '%s'", ds_query.str);
+
+  /* Run the query */
+  if (mysql_real_query(mysql, ds_query.str, ds_query.length))
+    die("Error running query '%s': %d %s", ds_query.str,
+	mysql_errno(mysql), mysql_error(mysql));
+  if (!(res= mysql_store_result(mysql)))
+    die("Query '%s' didn't return a result set", ds_query.str);
+
+  {
+    /* Find column number from the given column name */
+    uint i;
+    uint num_fields= mysql_num_fields(res);
+    MYSQL_FIELD *fields= mysql_fetch_fields(res);
+
+    for (i= 0; i < num_fields; i++)
+    {
+      if (strcmp(fields[i].name, ds_col.str) == 0 &&
+          strlen(fields[i].name) == ds_col.length)
+      {
+        col_no= i;
+        break;
+      }
+    }
+    if (col_no == -1)
+    {
+      mysql_free_result(res);
+      die("Could not find column '%s' in the result of '%s'",
+          ds_col.str, ds_query.str);
+    }
+    DBUG_PRINT("info", ("Found column %d with name '%s'",
+                        i, fields[i].name));
+  }
+  dynstr_free(&ds_col);
+
+  {
+    /* Get the value */
+    MYSQL_ROW row;
+    ulong rows= 0;
+    const char* value= "No such row";
+
+    while ((row= mysql_fetch_row(res)))
+    {
+      if (++rows == row_no)
+      {
+
+        DBUG_PRINT("info", ("At row %ld, column %d is '%s'",
+                            row_no, col_no, row[col_no]));
+        /* Found the row to get */
+        if (row[col_no])
+          value= row[col_no];
+        else
+          value= "NULL";
+
+        break;
+      }
+    }
+    eval_expr(var, value, 0);
+  }
+  dynstr_free(&ds_query);
+  mysql_free_result(res);
+
+  DBUG_VOID_RETURN;
+}
+
+
 void var_copy(VAR *dest, VAR *src)
 {
   dest->int_val= src->int_val;
@@ -1464,26 +1631,47 @@ void var_copy(VAR *dest, VAR *src)
 
 void eval_expr(VAR *v, const char *p, const char **p_end)
 {
-  static int MIN_VAR_ALLOC= 32; /* MASV why 32? */
-  VAR *vp;
+
+  DBUG_ENTER("eval_expr");
+  DBUG_PRINT("enter", ("p: '%s'", p));
+
   if (*p == '$')
   {
+    VAR *vp;
     if ((vp= var_get(p, p_end, 0, 0)))
-    {
       var_copy(v, vp);
-      return;
-    }
+    DBUG_VOID_RETURN;
   }
-  else if (*p == '`')
+
+  if (*p == '`')
   {
     var_query_set(v, p, p_end);
+    DBUG_VOID_RETURN;
   }
-  else
+
+  {
+    /* Check if this is a "let $var= query_get_value()" */
+    const char* get_value_str= "query_get_value";
+    const size_t len= strlen(get_value_str);
+    if (strncmp(p, get_value_str, len)==0)
+    {
+      struct st_command command;
+      memset(&command, 0, sizeof(command));
+      command.query= (char*)p;
+      command.first_word_len= len;
+      command.first_argument= command.query + len;
+      command.end= (char*)*p_end;
+      var_set_query_get_value(&command, v);
+      DBUG_VOID_RETURN;
+    }
+  }
+
   {
     int new_val_len = (p_end && *p_end) ?
       (int) (*p_end - p) : (int) strlen(p);
     if (new_val_len + 1 >= v->alloced_len)
     {
+      static int MIN_VAR_ALLOC= 32;
       v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
         MIN_VAR_ALLOC : new_val_len + 1;
       if (!(v->str_val =
@@ -1496,9 +1684,10 @@ void eval_expr(VAR *v, const char *p, co
     memcpy(v->str_val, p, new_val_len);
     v->str_val[new_val_len] = 0;
     v->int_val=atoi(p);
+    DBUG_PRINT("info", ("atoi on '%s', returns: %d", p, v->int_val));
     v->int_dirty=0;
   }
-  return;
+  DBUG_VOID_RETURN;
 }
 
 
@@ -3441,7 +3630,6 @@ void do_connect(struct st_command *comma
   int con_port= opt_port;
   char *con_options;
   bool con_ssl= 0, con_compress= 0;
-  char *ptr;
 
   static DYNAMIC_STRING ds_connection_name;
   static DYNAMIC_STRING ds_host;
@@ -3465,20 +3653,7 @@ void do_connect(struct st_command *comma
   DBUG_ENTER("do_connect");
   DBUG_PRINT("enter",("connect: %s", command->first_argument));
 
-  /* Remove parenteses around connect arguments */
-  if ((ptr= strstr(command->first_argument, "(")))
-  {
-    /* Replace it with a space */
-    *ptr= ' ';
-    if ((ptr= strstr(command->first_argument, ")")))
-    {
-      /* Replace it with \0 */
-      *ptr= 0;
-    }
-    else
-      die("connect - argument list started with '(' must be ended with ')'");
-  }
-
+  strip_parentheses(command);
   check_command_args(command, command->first_argument, connect_args,
                      sizeof(connect_args)/sizeof(struct command_arg),
                      ',');
@@ -4176,16 +4351,12 @@ int read_command(struct st_command** com
     DBUG_RETURN(0);
   }
   if (!(*command_ptr= command=
-        (struct st_command*) my_malloc(sizeof(*command), MYF(MY_WME))) ||
+        (struct st_command*) my_malloc(sizeof(*command),
+                                       MYF(MY_WME|MY_ZEROFILL))) ||
       insert_dynamic(&q_lines, (gptr) &command))
     die(NullS);
-
-  command->require_file[0]= 0;
-  command->first_word_len= 0;
-  command->query_len= 0;
-
   command->type= Q_UNKNOWN;
-  command->query_buf= command->query= 0;
+
   read_command_buf[0]= 0;
   if (read_line(read_command_buf, sizeof(read_command_buf)))
   {
Thread
bk commit into 5.1 tree (msvensson:1.2508)msvensson1 Jun