List:Commits« Previous MessageNext Message »
From:monty Date:June 20 2006 10:20am
Subject:bk commit into 5.1 tree (monty:1.2221) BUG#19764
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of monty. When monty 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.2221 06/06/20 13:20:32 monty@stripped +21 -0
  SHOW STATUS does not anymore change local status variables (except com_show_status). Global status variables are still updated.
  SHOW STATUS are not anymore put in slow query log because of no index usage.
  
  Implemntation done by removing orig_sql_command and moving logic of SHOW STATUS to mysql_excute_command()
  This simplifies code and allows us to remove some if statements all over the code.
  
  Upgraded uc_update_queries[] to sql_command_flags and added more bitmaps to better categorize commands.
  This allowed some overall simplifaction when testing sql_command.
  
  Fixes bugs:
  Bug#10210: running SHOW STATUS increments counters it shouldn't
  Bug#19764: SHOW commands end up in the slow log as table scans

  sql/structs.h
    1.62 06/06/20 13:20:28 monty@stripped +1 -1
    Updated comment

  sql/sql_yacc.yy
    1.483 06/06/20 13:20:28 monty@stripped +25 -40
    Remove usage of orig_sql_command.
    One side effect of this is that we need to test for cursors if the current command is a SELECT or a SHOW command.

  sql/sql_show.cc
    1.352 06/06/20 13:20:28 monty@stripped +39 -33
    Remove orig_sql_command
    Only change sql_command during 'open_normal_and_derived_tables()' (for views) and not for the full duration of generating data.
    Changed 'show status' to use thd->initial_status_var to ensure that the current statement is not affecting the to-be-used values.
    Use thd->fill_information_schema_tables() instead of 'thd->fill_derived_tables()' as the later wrongly checks the value of sql_command.

  sql/sql_select.cc
    1.414 06/06/20 13:20:28 monty@stripped +1 -6
    Remove special handling of SHOW STATUS.
    (This is now done in SQLCOM_SHOW_STATUS part in mysql_execute_command())

  sql/sql_prepare.cc
    1.173 06/06/20 13:20:28 monty@stripped +15 -12
    Clean up prepare-check handling of SQLCOM commands by using sql_command_flags[]
    This simplifes code and ensures that code works even if someone forgets to put a new status commands into the switch statement.
    

  sql/sql_parse.cc
    1.562 06/06/20 13:20:28 monty@stripped +174 -110
    Rename uc_update_queries -> sql_command_flags.
    Enhanced 'sql_command_flags' to better classify SQL commands
    uc_update_queries[] != 0 is changed to (sql_command_flags[] & CF_CHANGES_DATA)
    lex->orig_sql_command == SQLCOM_END is changed to (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0)
    
    Simplify incrementing of thd->status_var.com_stat[] as we don't have to do special handling for SHOW commands.
    
    Split SQLCOM_SELECT handling in mysql_execute_command() to a separate function.
    Added special handling of SHOW STATUS commands in mysql_execute_command() and call common SQLCOM_SELECT handling.
    These changes allows us to easily fix that we save and restore status variables during execution of a SHOW STATUS command.
    Don't log SHOW STATUS commands to slow query log.
    
    This fixes Bug#10210 and Bug#19764 without adding additional 'if' code.
    (The new code is faster than the original as we now have fewer if's than before)
    

  sql/sql_lex.h
    1.234 06/06/20 13:20:28 monty@stripped +1 -1
    Remove orig_sql_command

  sql/sql_lex.cc
    1.186 06/06/20 13:20:28 monty@stripped +1 -1
    Remove orig_sql_command

  sql/sql_class.h
    1.299 06/06/20 13:20:28 monty@stripped +14 -2
    New function 'fill_information_schema_tables()'
    (One could not anymore use fill_derived_tables() for this as only_view_structures() is not relevant for information schema tables)
    Added defines for bit flags in sql_command_flags[]

  sql/sql_class.cc
    1.267 06/06/20 13:20:28 monty@stripped +25 -0
    New function add_diff_to_status(), used to update global status variables when using SHOW STATUS

  sql/mysql_priv.h
    1.411 06/06/20 13:20:28 monty@stripped +1 -0
    Added 'sql_command_flags'

  mysql-test/t/status.test
    1.16 06/06/20 13:20:28 monty@stripped +34 -0
    Added more tests for testing of last_query_cost and how SHOW STATUS affects status variables.
    (Bug #10210)

  mysql-test/t/query_cache.test
    1.61 06/06/20 13:20:28 monty@stripped +3 -0
    Remove resuts from previous tests

  mysql-test/t/information_schema.test
    1.83 06/06/20 13:20:28 monty@stripped +2 -0
    Added extra test to cover more code

  mysql-test/t/events_microsec.test
    1.4 06/06/20 13:20:28 monty@stripped +3 -0
    Disable warnings at init

  mysql-test/r/union.result
    1.85 06/06/20 13:20:28 monty@stripped +4 -4
    Fixed results after SHOW STATUS is not logged to slow query log
    (Bug#19764)

  mysql-test/r/temp_table.result
    1.24 06/06/20 13:20:28 monty@stripped +1 -1
    Fixed results after SHOW STATUS doesn't anymore affect status variables

  mysql-test/r/status.result
    1.12 06/06/20 13:20:27 monty@stripped +50 -0
    Added more tests for testing of last_query_cost and how SHOW STATUS affects status variables.
    (Bug#10210)

  mysql-test/r/query_cache.result
    1.75 06/06/20 13:20:27 monty@stripped +1 -0
    Remove resuts from previous tests

  mysql-test/r/information_schema.result
    1.125 06/06/20 13:20:27 monty@stripped +2 -0
    Added extra test to cover more code

  mysql-test/r/grant_cache.result
    1.17 06/06/20 13:20:27 monty@stripped +8 -8
    Fixed results after SHOW STATUS doesn't anymore affect status variables

# 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:	monty
# Host:	narttu.mysql.fi
# Root:	/home/my/mysql-5.1

--- 1.410/sql/mysql_priv.h	2006-06-15 14:38:08 +03:00
+++ 1.411/sql/mysql_priv.h	2006-06-20 13:20:28 +03:00
@@ -1582,6 +1582,7 @@
 extern const char* any_db;
 extern struct my_option my_long_options[];
 extern const LEX_STRING view_type;
+extern uint sql_command_flags[];
 
 /* optional things, have_* variables */
 

--- 1.266/sql/sql_class.cc	2006-06-18 13:20:28 +03:00
+++ 1.267/sql/sql_class.cc	2006-06-20 13:20:28 +03:00
@@ -516,6 +516,31 @@
   /* it doesn't make sense to add last_query_cost values */
 }
 
+/*
+  Add the difference between two status variable arrays to another one.
+
+  SYNOPSIS
+    add_diff_to_status
+    to_var       add to this array
+    from_var     from this array
+    dec_var      minus this array
+  
+  NOTE
+    This function assumes that all variables are long/ulong.
+*/
+
+void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
+                        STATUS_VAR *dec_var)
+{
+  ulong *end= (ulong*) ((byte*) to_var + offsetof(STATUS_VAR,
+						  last_system_status_var) +
+			sizeof(ulong));
+  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
+
+  while (to != end)
+    *(to++)+= *(from++) - *(dec++);
+}
+
 
 void THD::awake(THD::killed_state state_to_set)
 {

--- 1.298/sql/sql_class.h	2006-06-18 13:20:28 +03:00
+++ 1.299/sql/sql_class.h	2006-06-20 13:20:28 +03:00
@@ -343,7 +343,6 @@
 
 #define last_system_status_var com_stmt_close
 
-
 #ifdef MYSQL_SERVER
 
 void free_tmp_table(THD *thd, TABLE *entry);
@@ -833,6 +832,7 @@
   struct  rand_struct rand;		// used for authentication
   struct  system_variables variables;	// Changeable local variables
   struct  system_status_var status_var; // Per thread statistic vars
+  struct  system_status_var *initial_status_var; /* used by show status */
   THR_LOCK_INFO lock_info;              // Locking info of this thread
   THR_LOCK_OWNER main_lock_id;          // To use for conventional queries
   THR_LOCK_OWNER *lock_id;              // If not main_lock_id, points to
@@ -1306,6 +1306,10 @@
   {
     return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure();
   }
+  inline bool fill_information_schema_tables()
+  {
+    return !stmt_arena->is_stmt_prepare();
+  }
   inline gptr trans_alloc(unsigned int size)
   {
     return alloc_root(&transaction.mem_root,size);
@@ -1952,8 +1956,16 @@
   void cleanup();
 };
 
+/* Bits in sql_command_flags */
+
+#define CF_CHANGES_DATA		1
+#define CF_HAS_ROW_COUNT	2
+#define CF_STATUS_COMMAND	4
+#define CF_SHOW_TABLE_COMMAND	8
+
 /* Functions in sql_class.cc */
 
 void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var);
-
+void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
+                        STATUS_VAR *dec_var);
 #endif /* MYSQL_SERVER */

--- 1.185/sql/sql_lex.cc	2006-06-18 13:20:28 +03:00
+++ 1.186/sql/sql_lex.cc	2006-06-20 13:20:28 +03:00
@@ -168,7 +168,7 @@
   lex->select_lex.group_list.empty();
   lex->select_lex.order_list.empty();
   lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
-  lex->sql_command= lex->orig_sql_command= SQLCOM_END;
+  lex->sql_command= SQLCOM_END;
   lex->duplicates= DUP_ERROR;
   lex->ignore= 0;
   lex->sphead= NULL;

--- 1.233/sql/sql_lex.h	2006-06-18 13:20:28 +03:00
+++ 1.234/sql/sql_lex.h	2006-06-20 13:20:28 +03:00
@@ -934,7 +934,7 @@
     the variable can contain 0 or 1 for each nest level.
   */
   nesting_map allow_sum_func;
-  enum_sql_command sql_command, orig_sql_command;
+  enum_sql_command sql_command;
   thr_lock_type lock_option;
   enum SSL_type ssl_type;			/* defined in violite.h */
   enum my_lex_states next_state;

--- 1.561/sql/sql_parse.cc	2006-06-18 13:20:28 +03:00
+++ 1.562/sql/sql_parse.cc	2006-06-20 13:20:28 +03:00
@@ -68,6 +68,7 @@
 static bool check_db_used(THD *thd,TABLE_LIST *tables);
 static bool check_multi_update_lock(THD *thd);
 static void remove_escape(char *name);
+static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
 
 const char *any_db="*any*";	// Special symbol for check_access
 
@@ -626,50 +627,79 @@
   sql_command is actually set to SQLCOM_END sometimes
   so we need the +1 to include it in the array.
 
-  numbers are:
-     0  - read-only query
-  != 0  - query that may change a table
+  See COMMAND_FLAG_xxx for different type of commands
      2  - query that returns meaningful ROW_COUNT() -
           a number of modified rows
 */
 
-char  uc_update_queries[SQLCOM_END+1];
+uint sql_command_flags[SQLCOM_END+1];
 
 void init_update_queries(void)
 {
-  bzero((gptr) &uc_update_queries, sizeof(uc_update_queries));
+  bzero((gptr) &sql_command_flags, sizeof(sql_command_flags));
 
-  uc_update_queries[SQLCOM_CREATE_TABLE]=1;
-  uc_update_queries[SQLCOM_CREATE_INDEX]=1;
-  uc_update_queries[SQLCOM_ALTER_TABLE]=1;
-  uc_update_queries[SQLCOM_UPDATE]=2;
-  uc_update_queries[SQLCOM_UPDATE_MULTI]=2;
-  uc_update_queries[SQLCOM_INSERT]=2;
-  uc_update_queries[SQLCOM_INSERT_SELECT]=2;
-  uc_update_queries[SQLCOM_DELETE]=2;
-  uc_update_queries[SQLCOM_DELETE_MULTI]=2;
-  uc_update_queries[SQLCOM_TRUNCATE]=1;
-  uc_update_queries[SQLCOM_DROP_TABLE]=1;
-  uc_update_queries[SQLCOM_LOAD]=1;
-  uc_update_queries[SQLCOM_CREATE_DB]=1;
-  uc_update_queries[SQLCOM_DROP_DB]=1;
-  uc_update_queries[SQLCOM_REPLACE]=2;
-  uc_update_queries[SQLCOM_REPLACE_SELECT]=2;
-  uc_update_queries[SQLCOM_RENAME_TABLE]=1;
-  uc_update_queries[SQLCOM_BACKUP_TABLE]=1;
-  uc_update_queries[SQLCOM_RESTORE_TABLE]=1;
-  uc_update_queries[SQLCOM_DROP_INDEX]=1;
-  uc_update_queries[SQLCOM_CREATE_VIEW]=1;
-  uc_update_queries[SQLCOM_DROP_VIEW]=1;
-  uc_update_queries[SQLCOM_CREATE_EVENT]=1;
-  uc_update_queries[SQLCOM_ALTER_EVENT]=1;
-  uc_update_queries[SQLCOM_DROP_EVENT]=1;  
+  sql_command_flags[SQLCOM_CREATE_TABLE]=   CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_CREATE_INDEX]=   CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_ALTER_TABLE]=    CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_TRUNCATE]=       CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_DROP_TABLE]=     CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_LOAD]=           CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_CREATE_DB]=      CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_DROP_DB]=        CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_RENAME_TABLE]=   CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_BACKUP_TABLE]=   CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_RESTORE_TABLE]=  CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_DROP_INDEX]=     CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_CREATE_VIEW]=    CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_DROP_VIEW]=      CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_CREATE_EVENT]=   CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_ALTER_EVENT]=    CF_CHANGES_DATA;
+  sql_command_flags[SQLCOM_DROP_EVENT]=     CF_CHANGES_DATA;  
+
+  sql_command_flags[SQLCOM_UPDATE]=	    CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
+  sql_command_flags[SQLCOM_UPDATE_MULTI]=   CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
+  sql_command_flags[SQLCOM_INSERT]=	    CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
+  sql_command_flags[SQLCOM_INSERT_SELECT]=  CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
+  sql_command_flags[SQLCOM_DELETE]=         CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
+  sql_command_flags[SQLCOM_DELETE_MULTI]=   CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
+  sql_command_flags[SQLCOM_REPLACE]=        CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
+  sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
+
+  sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_STATUS]=      CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_DATABASES]=   CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_TRIGGERS]=    CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_EVENTS]=      CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_PLUGINS]=     CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_FIELDS]=      CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_KEYS]=        CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_VARIABLES]=   CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_CHARSETS]=    CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_COLLATIONS]=  CF_STATUS_COMMAND;
+  sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND;
+
+  sql_command_flags[SQLCOM_SHOW_TABLES]=       (CF_STATUS_COMMAND |
+                                                CF_SHOW_TABLE_COMMAND);
+  sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
+                                                CF_SHOW_TABLE_COMMAND);
+
+  /*
+    The following is used to preserver CF_ROW_COUNT during the
+    a CALL or EXECUTE statement, so the value generated by the
+    last called (or executed) statement is preserved.
+    See mysql_execute_command() for how CF_ROW_COUNT is used.
+  */
+  sql_command_flags[SQLCOM_CALL]= 		CF_HAS_ROW_COUNT;
+  sql_command_flags[SQLCOM_EXECUTE]= 		CF_HAS_ROW_COUNT;
 }
 
+
 bool is_update_query(enum enum_sql_command command)
 {
   DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
-  return uc_update_queries[command] != 0;
+  return (sql_command_flags[command] & CF_CHANGES_DATA) == 0;
 }
 
 /*
@@ -733,7 +763,8 @@
   if (check_command < (uint) SQLCOM_END)
   {
     /* Check that we have not done too many updates / hour */
-    if (uc->user_resources.updates && uc_update_queries[check_command] &&
+    if (uc->user_resources.updates &&
+        (sql_command_flags[check_command] & CF_CHANGES_DATA) &&
 	uc->updates++ >= uc->user_resources.updates)
     {
       net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
@@ -2290,8 +2321,6 @@
   TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
   table_list->schema_select_lex= sel;
   table_list->schema_table_reformed= 1;
-  statistic_increment(thd->status_var.com_stat[lex->orig_sql_command],
-                      &LOCK_status);
   DBUG_RETURN(0);
 }
 
@@ -2458,7 +2487,7 @@
     */
     if (opt_readonly &&
 	!(thd->security_ctx->master_access & SUPER_ACL) &&
-	uc_update_queries[lex->sql_command] &&
+	(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) &&
 	!((lex->sql_command == SQLCOM_CREATE_TABLE) &&
 	  (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) &&
 	((lex->sql_command != SQLCOM_UPDATE_MULTI) &&
@@ -2470,9 +2499,8 @@
 #ifdef HAVE_REPLICATION
   } /* endif unlikely slave */
 #endif
-  if(lex->orig_sql_command == SQLCOM_END)
-    statistic_increment(thd->status_var.com_stat[lex->sql_command],
-                        &LOCK_status);
+  statistic_increment(thd->status_var.com_stat[lex->sql_command],
+                      &LOCK_status);
 
 #ifdef HAVE_ROW_BASED_REPLICATION
   if (lex->binlog_row_based_if_mixed)
@@ -2480,77 +2508,61 @@
 #endif /*HAVE_ROW_BASED_REPLICATION*/
 
   switch (lex->sql_command) {
-  case SQLCOM_SELECT:
+  case SQLCOM_SHOW_EVENTS:
+    if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
+                           is_schema_db(thd->lex->select_lex.db))))
+      break;
+    /* fall through */
+  case SQLCOM_SHOW_STATUS_PROC:
+  case SQLCOM_SHOW_STATUS_FUNC:
+    res= execute_sqlcom_select(thd, all_tables);
+    break;
+  case SQLCOM_SHOW_STATUS:
   {
-    /* assign global limit variable if limit is not given */
-    {
-      SELECT_LEX *param= lex->unit.global_parameters;
-      if (!param->explicit_limit)
-	param->select_limit=
-          new Item_int((ulonglong)thd->variables.select_limit);
-    }
-
-    select_result *result=lex->result;
+    system_status_var old_status_var= thd->status_var;
+    thd->initial_status_var= &old_status_var;
+    res= execute_sqlcom_select(thd, all_tables);
+    /* Don't log SHOW STATUS commands to slow query log */
+    thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
+                           SERVER_QUERY_NO_GOOD_INDEX_USED);
+    /*
+      restore status variables, as we don't want 'show status' to cause
+      changes
+    */
+    pthread_mutex_lock(&LOCK_status);
+    add_diff_to_status(&global_status_var, &thd->status_var,
+                       &old_status_var);
+    thd->status_var= old_status_var;
+    pthread_mutex_unlock(&LOCK_status);
+    break;
+  }
+  case SQLCOM_SHOW_DATABASES:
+  case SQLCOM_SHOW_TABLES:
+  case SQLCOM_SHOW_TRIGGERS:
+  case SQLCOM_SHOW_TABLE_STATUS:
+  case SQLCOM_SHOW_OPEN_TABLES:
+  case SQLCOM_SHOW_PLUGINS:
+  case SQLCOM_SHOW_FIELDS:
+  case SQLCOM_SHOW_KEYS:
+  case SQLCOM_SHOW_VARIABLES:
+  case SQLCOM_SHOW_CHARSETS:
+  case SQLCOM_SHOW_COLLATIONS:
+  case SQLCOM_SELECT:
+    thd->status_var.last_query_cost= 0.0;
     if (all_tables)
     {
-      if (lex->orig_sql_command != SQLCOM_SHOW_STATUS_PROC &&
-          lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC &&
-          lex->orig_sql_command != SQLCOM_SHOW_EVENTS)
-        res= check_table_access(thd,
-                                lex->exchange ? SELECT_ACL | FILE_ACL :
-                                SELECT_ACL,
-                                all_tables, 0);
-      else if (lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
-        res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
-                       is_schema_db(thd->lex->select_lex.db));
+      res= check_table_access(thd,
+                              lex->exchange ? SELECT_ACL | FILE_ACL :
+                              SELECT_ACL,
+                              all_tables, 0);
     }
     else
       res= check_access(thd,
-			lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
-			any_db, 0, 0, 0, 0);
-    if (res)
-      goto error;
-
-    if (!(res= open_and_lock_tables(thd, all_tables)))
-    {
-      if (lex->describe)
-      {
-        /*
-          We always use select_send for EXPLAIN, even if it's an EXPLAIN
-          for SELECT ... INTO OUTFILE: a user application should be able
-          to prepend EXPLAIN to any query and receive output for it,
-          even if the query itself redirects the output.
-        */
-	if (!(result= new select_send()))
-	  goto error;
-	else
-	  thd->send_explain_fields(result);
-	res= mysql_explain_union(thd, &thd->lex->unit, result);
-	if (lex->describe & DESCRIBE_EXTENDED)
-	{
-	  char buff[1024];
-	  String str(buff,(uint32) sizeof(buff), system_charset_info);
-	  str.length(0);
-	  thd->lex->unit.print(&str);
-	  str.append('\0');
-	  push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
-		       ER_YES, str.ptr());
-	}
-	result->send_eof();
-        delete result;
-      }
-      else
-      {
-	if (!result && !(result= new select_send()))
-          goto error;
-	query_cache_store_query(thd, all_tables);
-	res= handle_select(thd, lex, result, 0);
-        if (result != lex->result)
-          delete result;
-      }
-    }
+                        lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
+                        any_db, 0, 0, 0, 0);
+    if (!res)
+      res= execute_sqlcom_select(thd, all_tables);
     break;
-  }
   case SQLCOM_PREPARE:
   {
     mysql_sql_stmt_prepare(thd);
@@ -4826,6 +4838,7 @@
       }
       break;
     }
+#ifdef NOT_USED
   case SQLCOM_SHOW_STATUS_PROC:
     {
       res= sp_show_status_procedure(thd, (lex->wild ?
@@ -4838,6 +4851,7 @@
 					 lex->wild->ptr() : NullS));
       break;
     }
+#endif
 #ifndef DBUG_OFF
   case SQLCOM_SHOW_PROC_CODE:
   case SQLCOM_SHOW_FUNC_CODE:
@@ -5162,13 +5176,10 @@
   /*
     The return value for ROW_COUNT() is "implementation dependent" if the
     statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC
-    wants.
-
-    We do not change the value for a CALL or EXECUTE statement, so the value
-    generated by the last called (or executed) statement is preserved.
-   */
-  if (lex->sql_command != SQLCOM_CALL && lex->sql_command != SQLCOM_EXECUTE &&
-      uc_update_queries[lex->sql_command]<2)
+    wants. We also keep the last value in case of SQLCOM_CALL or
+    SQLCOM_EXECUTE.
+  */
+  if (!(sql_command_flags[lex->sql_command] & CF_HAS_ROW_COUNT))
     thd->row_count_func= -1;
   DBUG_RETURN(res || thd->net.report_error);
 
@@ -5178,6 +5189,59 @@
 }
 
 
+static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
+{
+  LEX	*lex= thd->lex;
+  select_result *result=lex->result;
+  bool res;
+  /* assign global limit variable if limit is not given */
+  {
+    SELECT_LEX *param= lex->unit.global_parameters;
+    if (!param->explicit_limit)
+      param->select_limit=
+        new Item_int((ulonglong) thd->variables.select_limit);
+  }
+  if (!(res= open_and_lock_tables(thd, all_tables)))
+  {
+    if (lex->describe)
+    {
+      /*
+        We always use select_send for EXPLAIN, even if it's an EXPLAIN
+        for SELECT ... INTO OUTFILE: a user application should be able
+        to prepend EXPLAIN to any query and receive output for it,
+        even if the query itself redirects the output.
+      */
+      if (!(result= new select_send()))
+        return 1;
+      thd->send_explain_fields(result);
+      res= mysql_explain_union(thd, &thd->lex->unit, result);
+      if (lex->describe & DESCRIBE_EXTENDED)
+      {
+        char buff[1024];
+        String str(buff,(uint32) sizeof(buff), system_charset_info);
+        str.length(0);
+        thd->lex->unit.print(&str);
+        str.append('\0');
+        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+                     ER_YES, str.ptr());
+      }
+      result->send_eof();
+      delete result;
+    }
+    else
+    {
+      if (!result && !(result= new select_send()))
+        return 1;
+      query_cache_store_query(thd, all_tables);
+      res= handle_select(thd, lex, result, 0);
+      if (result != lex->result)
+        delete result;
+    }
+  }
+  return res;
+}
+
+
 /*
   Check grants for commands which work only with one table and all other
   tables belonging to subselects or implicitly opened tables.
@@ -6283,7 +6347,7 @@
     ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->table_name);
     if (!schema_table ||
         (schema_table->hidden && 
-         lex->orig_sql_command == SQLCOM_END))  // not a 'show' command
+         (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0))
     {
       my_error(ER_UNKNOWN_TABLE, MYF(0),
                ptr->table_name, information_schema_name.str);

--- 1.413/sql/sql_select.cc	2006-06-18 13:20:28 +03:00
+++ 1.414/sql/sql_select.cc	2006-06-20 13:20:28 +03:00
@@ -551,9 +551,6 @@
     DBUG_RETURN(0);
   optimized= 1;
 
-  if (thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS)
-    thd->status_var.last_query_cost= 0.0;
-
   row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
 	      unit->select_limit_cnt);
   /* select_limit is used to decide if we are likely to scan the whole table */
@@ -3875,10 +3872,8 @@
 
   /* 
     Store the cost of this query into a user variable
-    Don't update last_query_cost for 'show status' command
   */
-  if (join->thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS)
-    join->thd->status_var.last_query_cost= join->best_read;
+  join->thd->status_var.last_query_cost= join->best_read;
   DBUG_VOID_RETURN;
 }
 

--- 1.351/sql/sql_show.cc	2006-06-16 13:17:00 +03:00
+++ 1.352/sql/sql_show.cc	2006-06-20 13:20:28 +03:00
@@ -2143,7 +2143,7 @@
 void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values)
 {
   const char *wild= lex->wild ? lex->wild->ptr() : NullS;
-  switch (lex->orig_sql_command) {
+  switch (lex->sql_command) {
   case SQLCOM_SHOW_DATABASES:
     index_field_values->db_value= wild;
     break;
@@ -2332,10 +2332,9 @@
   /*
     This part of code is for SHOW TABLES, SHOW TABLE STATUS commands.
     idx_field_vals->db_value can't be 0 (see get_index_field_values()
-    function). lex->orig_sql_command can be not equal to SQLCOM_END
-    only in case of executing of SHOW commands.
+    function).
   */
-  if (lex->orig_sql_command != SQLCOM_END)
+  if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
   {
     if (!my_strcasecmp(system_charset_info, information_schema_name.str,
                        idx_field_vals->db_value))
@@ -2414,12 +2413,6 @@
   LINT_INIT(end);
   LINT_INIT(len);
 
-  /*
-    Let us set fake sql_command so views won't try to merge
-    themselves into main statement.
-  */
-  lex->sql_command= SQLCOM_SHOW_FIELDS;
-
   lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
 
   /*
@@ -2442,8 +2435,16 @@
       I_S tables will be done.
     */
     thd->temporary_tables= open_tables_state_backup.temporary_tables;
+    /*
+      Let us set fake sql_command so views won't try to merge
+      themselves into main statement. If we don't do this,
+      SELECT * from information_schema.xxxx will cause problems.
+      SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()' 
+    */
+    lex->sql_command= SQLCOM_SHOW_FIELDS;
     res= open_normal_and_derived_tables(thd, show_table_list,
                                         MYSQL_LOCK_IGNORE_FLUSH);
+    lex->sql_command= save_sql_command;
     /*
       get_all_tables() returns 1 on failure and 0 on success thus
       return only these and not the result code of ::process_table()
@@ -2474,13 +2475,13 @@
 
   partial_cond= make_cond_for_info_schema(cond, tables);
   it.rewind(); /* To get access to new elements in basis list */
+
+  /*
+    Below we generate error for non existing database.
+    (to save old behaviour for SHOW TABLES FROM db)
+  */
   while ((orig_base_name= base_name= it++) ||
-	 /*
-	   generate error for non existing database.
-	   (to save old behaviour for SHOW TABLES FROM db)
-	 */
-	 ((lex->orig_sql_command == SQLCOM_SHOW_TABLES ||
-           lex->orig_sql_command == SQLCOM_SHOW_TABLE_STATUS) &&
+         ((sql_command_flags[save_sql_command] & CF_SHOW_TABLE_COMMAND) &&
 	  (base_name= select_lex->db) && !bases.elements))
   {
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -2521,7 +2522,8 @@
         {
           if (schema_table_idx == SCH_TABLE_NAMES)
           {
-            if (lex->verbose || lex->orig_sql_command == SQLCOM_END)
+            if (lex->verbose ||
+                (sql_command_flags[save_sql_command] & CF_STATUS_COMMAND) == 0)
             {
               if (with_i_schema)
               {
@@ -2565,8 +2567,10 @@
             TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first;
             lex->all_selects_list= &sel;
             lex->derived_tables= 0;
+            lex->sql_command= SQLCOM_SHOW_FIELDS;
             res= open_normal_and_derived_tables(thd, show_table_list,
                                                 MYSQL_LOCK_IGNORE_FLUSH);
+            lex->sql_command= save_sql_command;
             /*
               We should use show_table_list->alias instead of 
               show_table_list->table_name because table_name
@@ -2876,7 +2880,7 @@
 
   if (res)
   {
-    if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS)
+    if (lex->sql_command != SQLCOM_SHOW_FIELDS)
     {
       /*
         I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
@@ -2927,7 +2931,7 @@
     col_access= get_column_grant(thd, &tables->grant, 
                                  base_name, file_name,
                                  field->field_name) & COL_ACLS;
-    if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS  && 
+    if (lex->sql_command != SQLCOM_SHOW_FIELDS  &&
         !tables->schema_table && !col_access)
       continue;
     end= tmp;
@@ -2972,7 +2976,7 @@
       table->field[5]->set_notnull();
     }
     else if (field->unireg_check == Field::NEXT_NUMBER ||
-             lex->orig_sql_command != SQLCOM_SHOW_FIELDS ||
+             lex->sql_command != SQLCOM_SHOW_FIELDS ||
              field->maybe_null())
       table->field[5]->set_null();                // Null as default
     else
@@ -3242,16 +3246,18 @@
   get_field(thd->mem_root, proc_table->field[11], &definer);
   if (!full_access)
     full_access= !strcmp(sp_user, definer.ptr());
-  if (!full_access && check_some_routine_access(thd, sp_db.ptr(), sp_name.ptr(),
-                                                proc_table->field[2]->val_int() ==
+  if (!full_access && check_some_routine_access(thd, sp_db.ptr(),
+                                                sp_name.ptr(),
+                                                proc_table->field[2]->
+                                                val_int() ==
                                                 TYPE_ENUM_PROCEDURE))
     return 0;
 
-  if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC &&
+  if (lex->sql_command == SQLCOM_SHOW_STATUS_PROC &&
       proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE ||
-      lex->orig_sql_command == SQLCOM_SHOW_STATUS_FUNC &&
+      lex->sql_command == SQLCOM_SHOW_STATUS_FUNC &&
       proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION ||
-      lex->orig_sql_command == SQLCOM_END)
+      (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0)
   {
     restore_record(table, s->default_values);
     if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0))
@@ -3362,7 +3368,7 @@
   DBUG_ENTER("get_schema_stat_record");
   if (res)
   {
-    if (thd->lex->orig_sql_command != SQLCOM_SHOW_KEYS)
+    if (thd->lex->sql_command != SQLCOM_SHOW_KEYS)
     {
       /*
         I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
@@ -4153,7 +4159,7 @@
     optimized. It's guaranteed in case of SHOW EVENTS that the user
     has access.
   */
-  if (thd->lex->orig_sql_command != SQLCOM_SHOW_EVENTS &&
+  if (thd->lex->sql_command != SQLCOM_SHOW_EVENTS &&
       check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1,
                    is_schema_db(et.dbname.str)))
     DBUG_RETURN(0);
@@ -4383,7 +4389,7 @@
     If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
     be NULL. Let's do an assert anyway.
   */
-  if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
+  if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS)
   {
     DBUG_ASSERT(thd->lex->select_lex.db);
     if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
@@ -4411,7 +4417,7 @@
                   will save use from doing a table scan and comparing
                   every single row's `db` with the schema which we show.
   */
-  if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
+  if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS)
     ret= events_table_index_read_for_db(thd, schema_table, event_table);
   else
     ret= events_table_scan_all(thd, schema_table, event_table);
@@ -4477,7 +4483,7 @@
                          (SHOW_VAR *)all_status_vars.buffer,
                          OPT_GLOBAL,
                          (lex->option_type == OPT_GLOBAL ?
-                          &tmp: &thd->status_var), "",tables->table);
+                          &tmp: thd->initial_status_var), "",tables->table);
   pthread_mutex_unlock(&LOCK_status);
   DBUG_RETURN(res);
 }
@@ -4670,8 +4676,8 @@
     schema_table        pointer to 'schema_tables' element
 
   RETURN
-   -1	errror
-    0	success
+   1	error
+   0	success
 */
 
 int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
@@ -4994,7 +5000,7 @@
       break;
 
     TABLE_LIST *table_list= tab->table->pos_in_table_list;
-    if (table_list->schema_table && thd->fill_derived_tables())
+    if (table_list->schema_table && thd->fill_information_schema_tables())
     {
       bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
                           lex->current_select->master_unit()->item);

--- 1.482/sql/sql_yacc.yy	2006-06-18 13:20:29 +03:00
+++ 1.483/sql/sql_yacc.yy	2006-06-20 13:20:28 +03:00
@@ -2058,16 +2058,19 @@
 	  {
 	    Lex->sphead->reset_lex(YYTHD);
 
-	    /* We use statement here just be able to get a better
-	       error message. Using 'select' works too, but will then
-	       result in a generic "syntax error" if a non-select
-	       statement is given. */
+	    /*
+	      We use statement here just be able to get a better
+	      error message. Using 'select' works too, but will then
+	      result in a generic "syntax error" if a non-select
+	      statement is given.
+	    */
 	  }
 	  statement
 	  {
 	    LEX *lex= Lex;
 
-	    if (lex->sql_command != SQLCOM_SELECT)
+	    if (lex->sql_command != SQLCOM_SELECT &&
+	       !(sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND))
 	    {
 	      my_message(ER_SP_BAD_CURSOR_QUERY, ER(ER_SP_BAD_CURSOR_QUERY),
                          MYF(0));
@@ -8062,16 +8065,14 @@
          DATABASES wild_and_where
          {
            LEX *lex= Lex;
-           lex->sql_command= SQLCOM_SELECT;
-           lex->orig_sql_command= SQLCOM_SHOW_DATABASES;
+           lex->sql_command= SQLCOM_SHOW_DATABASES;
            if (prepare_schema_table(YYTHD, lex, 0, SCH_SCHEMATA))
              YYABORT;
          }
          | opt_full TABLES opt_db wild_and_where
            {
              LEX *lex= Lex;
-             lex->sql_command= SQLCOM_SELECT;
-             lex->orig_sql_command= SQLCOM_SHOW_TABLES;
+             lex->sql_command= SQLCOM_SHOW_TABLES;
              lex->select_lex.db= $3;
              if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_NAMES))
                YYABORT;
@@ -8079,8 +8080,7 @@
          | opt_full TRIGGERS_SYM opt_db wild_and_where
            {
              LEX *lex= Lex;
-             lex->sql_command= SQLCOM_SELECT;
-             lex->orig_sql_command= SQLCOM_SHOW_TRIGGERS;
+             lex->sql_command= SQLCOM_SHOW_TRIGGERS;
              lex->select_lex.db= $3;
              if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS))
                YYABORT;
@@ -8088,8 +8088,7 @@
          | EVENTS_SYM opt_db wild_and_where
            {
              LEX *lex= Lex;
-             lex->sql_command= SQLCOM_SELECT;
-             lex->orig_sql_command= SQLCOM_SHOW_EVENTS;
+             lex->sql_command= SQLCOM_SHOW_EVENTS;
              lex->select_lex.db= $2;
              if (prepare_schema_table(YYTHD, lex, 0, SCH_EVENTS))
                YYABORT;
@@ -8106,8 +8105,7 @@
          | TABLE_SYM STATUS_SYM opt_db wild_and_where
            {
              LEX *lex= Lex;
-             lex->sql_command= SQLCOM_SELECT;
-             lex->orig_sql_command= SQLCOM_SHOW_TABLE_STATUS;
+             lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
              lex->select_lex.db= $3;
              if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLES))
                YYABORT;
@@ -8115,8 +8113,7 @@
         | OPEN_SYM TABLES opt_db wild_and_where
 	  {
 	    LEX *lex= Lex;
-            lex->sql_command= SQLCOM_SELECT;
-            lex->orig_sql_command= SQLCOM_SHOW_OPEN_TABLES;
+            lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
 	    lex->select_lex.db= $3;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES))
               YYABORT;
@@ -8125,16 +8122,14 @@
 	  {
 	    LEX *lex= Lex;
 	    WARN_DEPRECATED(yythd, "5.2", "SHOW PLUGIN", "'SHOW PLUGINS'");
-            lex->sql_command= SQLCOM_SELECT;
-            lex->orig_sql_command= SQLCOM_SHOW_PLUGINS;
+            lex->sql_command= SQLCOM_SHOW_PLUGINS;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS))
               YYABORT;
 	  }
         | PLUGINS_SYM
 	  {
 	    LEX *lex= Lex;
-            lex->sql_command= SQLCOM_SELECT;
-            lex->orig_sql_command= SQLCOM_SHOW_PLUGINS;
+            lex->sql_command= SQLCOM_SHOW_PLUGINS;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS))
               YYABORT;
 	  }
@@ -8147,8 +8142,7 @@
 	| opt_full COLUMNS from_or_in table_ident opt_db wild_and_where
 	  {
  	    LEX *lex= Lex;
-	    lex->sql_command= SQLCOM_SELECT;
-	    lex->orig_sql_command= SQLCOM_SHOW_FIELDS;
+	    lex->sql_command= SQLCOM_SHOW_FIELDS;
 	    if ($5)
 	      $4->change_db($5);
 	    if (prepare_schema_table(YYTHD, lex, $4, SCH_COLUMNS))
@@ -8180,8 +8174,7 @@
         | keys_or_index from_or_in table_ident opt_db where_clause
           {
             LEX *lex= Lex;
-            lex->sql_command= SQLCOM_SELECT;
-            lex->orig_sql_command= SQLCOM_SHOW_KEYS;
+            lex->sql_command= SQLCOM_SHOW_KEYS;
 	    if ($4)
 	      $3->change_db($4);
             if (prepare_schema_table(YYTHD, lex, $3, SCH_STATISTICS))
@@ -8202,7 +8195,6 @@
 	  {
 	    LEX *lex=Lex;
 	    lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES;
-            lex->orig_sql_command= SQLCOM_SHOW_AUTHORS;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_ENGINES))
               YYABORT;
 	  }
@@ -8232,8 +8224,7 @@
         | opt_var_type STATUS_SYM wild_and_where
           {
             LEX *lex= Lex;
-            lex->sql_command= SQLCOM_SELECT;
-            lex->orig_sql_command= SQLCOM_SHOW_STATUS;
+            lex->sql_command= SQLCOM_SHOW_STATUS;
             lex->option_type= $1;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_STATUS))
               YYABORT;
@@ -8267,8 +8258,7 @@
         | opt_var_type  VARIABLES wild_and_where
 	  {
             LEX *lex= Lex;
-            lex->sql_command= SQLCOM_SELECT;
-            lex->orig_sql_command= SQLCOM_SHOW_VARIABLES;
+            lex->sql_command= SQLCOM_SHOW_VARIABLES;
             lex->option_type= $1;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_VARIABLES))
               YYABORT;
@@ -8276,16 +8266,14 @@
         | charset wild_and_where
           {
             LEX *lex= Lex;
-            lex->sql_command= SQLCOM_SELECT;
-            lex->orig_sql_command= SQLCOM_SHOW_CHARSETS;
+            lex->sql_command= SQLCOM_SHOW_CHARSETS;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_CHARSETS))
               YYABORT;
           }
         | COLLATION_SYM wild_and_where
           {
             LEX *lex= Lex;
-            lex->sql_command= SQLCOM_SELECT;
-            lex->orig_sql_command= SQLCOM_SHOW_COLLATIONS;
+            lex->sql_command= SQLCOM_SHOW_COLLATIONS;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_COLLATIONS))
               YYABORT;
           }
@@ -8391,8 +8379,7 @@
 	| PROCEDURE STATUS_SYM wild_and_where
 	  {
             LEX *lex= Lex;
-            lex->sql_command= SQLCOM_SELECT;
-            lex->orig_sql_command= SQLCOM_SHOW_STATUS_PROC;
+            lex->sql_command= SQLCOM_SHOW_STATUS_PROC;
 	    if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
 	      YYABORT;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
@@ -8401,8 +8388,7 @@
 	| FUNCTION_SYM STATUS_SYM wild_and_where
 	  {
             LEX *lex= Lex;
-            lex->sql_command= SQLCOM_SELECT;
-            lex->orig_sql_command= SQLCOM_SHOW_STATUS_FUNC;
+            lex->sql_command= SQLCOM_SHOW_STATUS_FUNC;
 	    if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
 	      YYABORT;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
@@ -8497,8 +8483,7 @@
           lex->lock_option= TL_READ;
           mysql_init_select(lex);
           lex->current_select->parsing_place= SELECT_LIST;
-          lex->sql_command= SQLCOM_SELECT;
-          lex->orig_sql_command= SQLCOM_SHOW_FIELDS;
+          lex->sql_command= SQLCOM_SHOW_FIELDS;
           lex->select_lex.db= 0;
           lex->verbose= 0;
           if (prepare_schema_table(YYTHD, lex, $2, SCH_COLUMNS))

--- 1.61/sql/structs.h	2006-06-18 13:20:29 +03:00
+++ 1.62/sql/structs.h	2006-06-20 13:20:28 +03:00
@@ -180,7 +180,7 @@
   uint questions;
   /*
      Maximum number of updating statements per hour (which statements are
-     updating is defined by uc_update_queries array).
+     updating is defined by sql_command_flags array).
   */
   uint updates;
   /* Maximum number of connections established per hour. */

--- 1.84/mysql-test/r/union.result	2006-06-18 13:20:26 +03:00
+++ 1.85/mysql-test/r/union.result	2006-06-20 13:20:28 +03:00
@@ -836,27 +836,27 @@
 26
 show status like 'Slow_queries';
 Variable_name	Value
-Slow_queries	1
+Slow_queries	0
 select count(*) from t1 where b=13;
 count(*)
 10
 show status like 'Slow_queries';
 Variable_name	Value
-Slow_queries	3
+Slow_queries	1
 select count(*) from t1 where b=13 union select count(*) from t1 where a=7;
 count(*)
 10
 26
 show status like 'Slow_queries';
 Variable_name	Value
-Slow_queries	5
+Slow_queries	2
 select count(*) from t1 where a=7 union select count(*) from t1 where b=13;
 count(*)
 26
 10
 show status like 'Slow_queries';
 Variable_name	Value
-Slow_queries	7
+Slow_queries	3
 flush status;
 select a from t1 where b not in (1,2,3) union select a from t1 where b not in (4,5,6);
 a

--- 1.3/mysql-test/t/events_microsec.test	2006-05-22 21:45:57 +03:00
+++ 1.4/mysql-test/t/events_microsec.test	2006-06-20 13:20:28 +03:00
@@ -1,4 +1,7 @@
+--disable_warnings
 create database if not exists events_test;
+--enable_warnings
+
 use events_test;
 
 --error ER_NOT_SUPPORTED_YET

--- 1.124/mysql-test/r/information_schema.result	2006-06-14 11:50:14 +03:00
+++ 1.125/mysql-test/r/information_schema.result	2006-06-20 13:20:27 +03:00
@@ -199,6 +199,8 @@
 where table_schema = 'mysqltest' and table_name = 'v1';
 table_name	column_name	privileges
 v1	c	select
+explain select * from v1;
+ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
 drop view v1, mysqltest.v1;
 drop tables mysqltest.t4, mysqltest.t1, t2, t3, t5;
 drop database mysqltest;

--- 1.82/mysql-test/t/information_schema.test	2006-06-14 08:54:50 +03:00
+++ 1.83/mysql-test/t/information_schema.test	2006-06-20 13:20:28 +03:00
@@ -80,6 +80,8 @@
 connection user4;
 select table_name, column_name, privileges from information_schema.columns
 where table_schema = 'mysqltest' and table_name = 'v1';
+--error 1345
+explain select * from v1;
 connection default;
 
 drop view v1, mysqltest.v1;

--- 1.23/mysql-test/r/temp_table.result	2006-02-22 11:09:52 +02:00
+++ 1.24/mysql-test/r/temp_table.result	2006-06-20 13:20:28 +03:00
@@ -98,7 +98,7 @@
 show status like "created_tmp%tables";
 Variable_name	Value
 Created_tmp_disk_tables	0
-Created_tmp_tables	2
+Created_tmp_tables	1
 drop table t1;
 create temporary table v1 as select 'This is temp. table' A;
 create view v1 as select 'This is view' A;

--- 1.16/mysql-test/r/grant_cache.result	2005-05-18 23:51:22 +03:00
+++ 1.17/mysql-test/r/grant_cache.result	2006-06-20 13:20:27 +03:00
@@ -60,7 +60,7 @@
 Qcache_hits	0
 show status like "Qcache_not_cached";
 Variable_name	Value
-Qcache_not_cached	5
+Qcache_not_cached	0
 select "user1";
 user1
 user1
@@ -72,7 +72,7 @@
 Qcache_hits	0
 show status like "Qcache_not_cached";
 Variable_name	Value
-Qcache_not_cached	9
+Qcache_not_cached	1
 select * from t1;
 a	b	c
 1	1	1
@@ -85,7 +85,7 @@
 Qcache_hits	1
 show status like "Qcache_not_cached";
 Variable_name	Value
-Qcache_not_cached	12
+Qcache_not_cached	1
 select a from t1 ;
 a
 1
@@ -98,7 +98,7 @@
 Qcache_hits	2
 show status like "Qcache_not_cached";
 Variable_name	Value
-Qcache_not_cached	15
+Qcache_not_cached	1
 select c from t1;
 c
 1
@@ -111,7 +111,7 @@
 Qcache_hits	3
 show status like "Qcache_not_cached";
 Variable_name	Value
-Qcache_not_cached	18
+Qcache_not_cached	1
 show grants for current_user();
 Grants for @localhost
 GRANT USAGE ON *.* TO ''@'localhost'
@@ -144,7 +144,7 @@
 Qcache_hits	7
 show status like "Qcache_not_cached";
 Variable_name	Value
-Qcache_not_cached	22
+Qcache_not_cached	2
 select "user3";
 user3
 user3
@@ -168,7 +168,7 @@
 Qcache_hits	7
 show status like "Qcache_not_cached";
 Variable_name	Value
-Qcache_not_cached	30
+Qcache_not_cached	7
 select "user4";
 user4
 user4
@@ -198,7 +198,7 @@
 Qcache_hits	8
 show status like "Qcache_not_cached";
 Variable_name	Value
-Qcache_not_cached	34
+Qcache_not_cached	8
 set names binary;
 delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
 delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3");

--- 1.74/mysql-test/r/query_cache.result	2006-02-26 15:11:52 +02:00
+++ 1.75/mysql-test/r/query_cache.result	2006-06-20 13:20:27 +03:00
@@ -1050,6 +1050,7 @@
 drop table t1;
 create table t1 (a int);
 insert into t1 values (1),(2);
+drop procedure if exists p1;
 CREATE PROCEDURE `p1`()
 begin
 Declare c1 cursor for select a from t1;

--- 1.60/mysql-test/t/query_cache.test	2006-05-02 16:13:52 +03:00
+++ 1.61/mysql-test/t/query_cache.test	2006-06-20 13:20:28 +03:00
@@ -765,6 +765,9 @@
 create table t1 (a int);
 insert into t1 values (1),(2);
 
+--disable_warnings
+drop procedure if exists p1;
+--enable_warnings
 delimiter //;
 CREATE PROCEDURE `p1`()
 begin

--- 1.11/mysql-test/r/status.result	2006-05-23 13:10:00 +03:00
+++ 1.12/mysql-test/r/status.result	2006-06-20 13:20:27 +03:00
@@ -23,6 +23,32 @@
 show status like 'last_query_cost';
 Variable_name	Value
 Last_query_cost	0.000000
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+select * from t1 where a=6;
+a
+6
+6
+6
+6
+6
+show status like 'last_query_cost';
+Variable_name	Value
+Last_query_cost	12.084449
+show status like 'last_query_cost';
+Variable_name	Value
+Last_query_cost	12.084449
+select 1;
+1
+1
+show status like 'last_query_cost';
+Variable_name	Value
+Last_query_cost	0.000000
+drop table t1;
 FLUSH STATUS;
 SHOW STATUS LIKE 'max_used_connections';
 Variable_name	Value
@@ -43,3 +69,27 @@
 Variable_name	Value
 Max_used_connections	5
 SET GLOBAL thread_cache_size=@save_thread_cache_size;
+show status like 'com_show_status';
+Variable_name	Value
+Com_show_status	3
+show status like 'hand%write%';
+Variable_name	Value
+Handler_write	0
+show status like '%tmp%';
+Variable_name	Value
+Created_tmp_disk_tables	0
+Created_tmp_files	0
+Created_tmp_tables	0
+show status like 'hand%write%';
+Variable_name	Value
+Handler_write	0
+show status like '%tmp%';
+Variable_name	Value
+Created_tmp_disk_tables	0
+Created_tmp_files	0
+Created_tmp_tables	0
+show status like 'com_show_status';
+Variable_name	Value
+Com_show_status	8
+rnd_diff	tmp_table_diff
+20	8

--- 1.15/mysql-test/t/status.test	2006-04-12 16:37:51 +03:00
+++ 1.16/mysql-test/t/status.test	2006-06-20 13:20:28 +03:00
@@ -48,6 +48,19 @@
 
 select 1;
 show status like 'last_query_cost';
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+select * from t1 where a=6;
+show status like 'last_query_cost';
+# Ensure value dosn't change by second status call
+show status like 'last_query_cost';
+select 1;
+show status like 'last_query_cost';
+drop table t1;
 
 #
 # Test for Bug #15933 max_used_connections is wrong after FLUSH STATUS
@@ -144,3 +157,24 @@
 disconnect con1;
 
 # End of 5.0 tests
+
+#
+# Ensure that SHOW STATUS only changes global status variables
+#
+
+connect (con1,localhost,root,,);
+let $rnd_next = `show global status like 'handler_read_rnd_next'`;
+let $tmp_table = `show global status like 'Created_tmp_tables'`;
+show status like 'com_show_status';
+show status like 'hand%write%';
+show status like '%tmp%';
+show status like 'hand%write%';
+show status like '%tmp%';
+show status like 'com_show_status';
+let $rnd_next2 = `show global status like 'handler_read_rnd_next'`;
+let $tmp_table2 = `show global status like 'Created_tmp_tables'`;
+--disable_query_log
+eval select substring_index('$rnd_next2',0x9,-1)-substring_index('$rnd_next',0x9,-1) as rnd_diff, substring_index('$tmp_table2',0x9,-1)-substring_index('$tmp_table',0x9,-1) as tmp_table_diff;
+--enable_query_log
+
+# End of 5.1 tests

--- 1.172/sql/sql_prepare.cc	2006-06-04 19:23:56 +03:00
+++ 1.173/sql/sql_prepare.cc	2006-06-20 13:20:28 +03:00
@@ -1727,22 +1727,17 @@
     res= mysql_test_insert_select(stmt, tables);
     break;
 
-  case SQLCOM_SHOW_DATABASES:
+    /*
+      Note that we don't need to have cases in this list if they are
+      marked with CF_STATUS_COMMAND in sql_command_flags
+    */
   case SQLCOM_SHOW_PROCESSLIST:
   case SQLCOM_SHOW_STORAGE_ENGINES:
   case SQLCOM_SHOW_PRIVILEGES:
   case SQLCOM_SHOW_COLUMN_TYPES:
-  case SQLCOM_SHOW_STATUS:
-  case SQLCOM_SHOW_VARIABLES:
   case SQLCOM_SHOW_ENGINE_LOGS:
   case SQLCOM_SHOW_ENGINE_STATUS:
   case SQLCOM_SHOW_ENGINE_MUTEX:
-  case SQLCOM_SHOW_TABLES:
-  case SQLCOM_SHOW_OPEN_TABLES:
-  case SQLCOM_SHOW_CHARSETS:
-  case SQLCOM_SHOW_COLLATIONS:
-  case SQLCOM_SHOW_FIELDS:
-  case SQLCOM_SHOW_KEYS:
   case SQLCOM_SHOW_CREATE_DB:
   case SQLCOM_SHOW_GRANTS:
   case SQLCOM_DROP_TABLE:
@@ -1762,9 +1757,17 @@
     break;
 
   default:
-    /* All other statements are not supported yet. */
-    my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0));
-    goto error;
+    /*
+      Trivial check of all status commands. This is easier than having
+      things in the above case list, as it's less chance for mistakes.
+    */
+    if (!(sql_command_flags[sql_command] & CF_STATUS_COMMAND))
+    {
+      /* All other statements are not supported yet. */
+      my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0));
+      goto error;
+    }
+    break;
   }
   if (res == 0)
     DBUG_RETURN(text_protocol? FALSE : (send_prep_stmt(stmt, 0) ||
Thread
bk commit into 5.1 tree (monty:1.2221) BUG#19764monty20 Jun