List:Commits« Previous MessageNext Message »
From:konstantin Date:March 12 2006 10:29am
Subject:bk commit into 5.1 tree (konstantin:1.2166)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of kostja. When kostja 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.2166 06/03/12 12:29:04 konstantin@stripped +9 -0
  Merge bk-internal.mysql.com:/home/bk/mysql-5.1-new
  into  mysql.com:/opt/local/work/mysql-5.1-new

  sql/sql_table.cc
    1.310 06/03/12 12:28:54 konstantin@stripped +0 -0
    Auto merged

  sql/sql_select.h
    1.106 06/03/12 12:28:54 konstantin@stripped +0 -0
    Auto merged

  sql/sql_parse.cc
    1.524 06/03/12 12:28:54 konstantin@stripped +0 -0
    Auto merged

  sql/sql_base.cc
    1.312 06/03/12 12:28:53 konstantin@stripped +0 -0
    Auto merged

  sql/field.h
    1.178 06/03/12 12:28:53 konstantin@stripped +0 -0
    Auto merged

  sql/field.cc
    1.303 06/03/12 12:28:53 konstantin@stripped +0 -0
    Auto merged

  mysql-test/t/ps.test
    1.61 06/03/12 12:28:53 konstantin@stripped +0 -0
    Auto merged

  mysql-test/r/ps.result
    1.63 06/03/12 12:28:53 konstantin@stripped +0 -0
    Auto merged

  mysql-test/r/heap.result
    1.49 06/03/12 12:28:52 konstantin@stripped +0 -0
    Auto merged

# 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:	konstantin
# Host:	dragonfly.local
# Root:	/opt/local/work/mysql-5.1-new/RESYNC

--- 1.302/sql/field.cc	2006-02-24 00:28:21 +03:00
+++ 1.303/sql/field.cc	2006-03-12 12:28:53 +03:00
@@ -5266,7 +5266,7 @@
   }
 
   if (nr >= 19000000000000.0 && nr <= 99991231235959.0)
-    nr=floor(nr/1000000.0);			// Timestamp to date
+    nr= (longlong) floor(nr/1000000.0);         // Timestamp to date
 
   if (error)
     set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,

--- 1.177/sql/field.h	2006-02-24 00:28:23 +03:00
+++ 1.178/sql/field.h	2006-03-12 12:28:53 +03:00
@@ -173,8 +173,9 @@
   virtual int cmp(const char *,const char *)=0;
   virtual int cmp_binary(const char *a,const char *b, uint32 max_length=~0L)
   { return memcmp(a,b,pack_length()); }
-  int cmp_offset(uint row_offset) { return cmp(ptr,ptr+row_offset); }
-  int cmp_binary_offset(uint row_offset)
+  virtual int cmp_offset(uint row_offset)
+  { return cmp(ptr,ptr+row_offset); }
+  virtual int cmp_binary_offset(uint row_offset)
   { return cmp_binary(ptr, ptr+row_offset); };
   virtual int key_cmp(const byte *a,const byte *b)
   { return cmp((char*) a,(char*) b); }
@@ -1317,6 +1318,20 @@
 };
 
 
+/*
+  Note:
+    To use Field_bit::cmp_binary() you need to copy the bits stored in
+    the beginning of the record (the NULL bytes) to each memory you
+    want to compare (where the arguments point).
+
+    This is the reason:
+    - Field_bit::cmp_binary() is only implemented in the base class
+      (Field::cmp_binary()).
+    - Field::cmp_binary() currenly use pack_length() to calculate how
+      long the data is.
+    - pack_length() includes size of the bits stored in the NULL bytes
+      of the record.
+*/
 class Field_bit :public Field {
 public:
   uchar *bit_ptr;     // position in record where 'uneven' bits store
@@ -1342,6 +1357,8 @@
   my_decimal *val_decimal(my_decimal *);
   int cmp(const char *a, const char *b)
   { return cmp_binary(a, b); }
+  int cmp_binary_offset(uint row_offset)
+  { return cmp_offset(row_offset); }
   int cmp_max(const char *a, const char *b, uint max_length);
   int key_cmp(const byte *a, const byte *b)
   { return cmp_binary((char *) a, (char *) b); }

--- 1.523/sql/sql_parse.cc	2006-02-24 00:28:24 +03:00
+++ 1.524/sql/sql_parse.cc	2006-03-12 12:28:54 +03:00
@@ -14,6 +14,7 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+#define MYSQL_LEX 1
 #include "mysql_priv.h"
 #include "sql_repl.h"
 #include "rpl_filter.h"
@@ -2111,6 +2112,7 @@
 
 void log_slow_statement(THD *thd)
 {
+  DBUG_ENTER("log_slow_statement");
   time_t start_of_query;
 
   /*
@@ -2142,6 +2144,7 @@
       slow_log_print(thd, thd->query, thd->query_length, start_of_query);
     }
   }
+  DBUG_VOID_RETURN;
 }
 
 
@@ -3715,7 +3718,7 @@
     }
     if (!strip_sp(db) || check_db_name(db))
     {
-      my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
+      my_error(ER_WRONG_DB_NAME, MYF(0), db);
       break;
     }
     /*
@@ -3727,8 +3730,8 @@
     */
 #ifdef HAVE_REPLICATION
     if (thd->slave_thread &&
-	(!rpl_filter->db_ok(lex->name) ||
-	 !rpl_filter->db_ok_with_wild_table(lex->name)))
+	(!rpl_filter->db_ok(db) ||
+	 !rpl_filter->db_ok_with_wild_table(db)))
     {
       my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
       break;
@@ -4279,6 +4282,90 @@
 #endif
 
     /*
+      If the definer is not specified, this means that CREATE-statement missed
+      DEFINER-clause. DEFINER-clause can be missed in two cases:
+      
+        - The user submitted a statement w/o the clause. This is a normal
+          case, we should assign CURRENT_USER as definer.
+
+        - Our slave received an updated from the master, that does not
+          replicate definer for stored rountines. We should also assign
+          CURRENT_USER as definer here, but also we should mark this routine
+          as NON-SUID. This is essential for the sake of backward
+          compatibility.
+          
+          The problem is the slave thread is running under "special" user (@),
+          that actually does not exist. In the older versions we do not fail
+          execution of a stored routine if its definer does not exist and
+          continue the execution under the authorization of the invoker
+          (BUG#13198). And now if we try to switch to slave-current-user (@),
+          we will fail.
+
+          Actually, this leads to the inconsistent state of master and
+          slave (different definers, different SUID behaviour), but it seems,
+          this is the best we can do.
+    */
+
+    if (!lex->definer)
+    {
+      bool res= FALSE;
+      Query_arena original_arena;
+      Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
+
+      if (!(lex->definer= create_default_definer(thd)))
+        res= TRUE;
+
+      if (ps_arena)
+        thd->restore_active_arena(ps_arena, &original_arena);
+
+      if (res)
+      {
+        /* Error has been already reported. */
+        delete lex->sphead;
+        lex->sphead= 0;
+        goto error;
+      }
+
+      if (thd->slave_thread)
+        lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
+    }
+
+    /*
+      If the specified definer differs from the current user, we should check
+      that the current user has SUPER privilege (in order to create a stored
+      routine under another user one must have SUPER privilege).
+    */
+    
+    else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
+        my_strcasecmp(system_charset_info,
+                      lex->definer->host.str,
+                      thd->security_ctx->priv_host))
+    {
+      if (check_global_access(thd, SUPER_ACL))
+      {
+        my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
+        delete lex->sphead;
+        lex->sphead= 0;
+        goto error;
+      }
+    }
+
+    /* Check that the specified definer exists. Emit a warning if not. */
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+    if (!is_acl_user(lex->definer->host.str,
+                     lex->definer->user.str))
+    {
+      push_warning_printf(thd,
+                          MYSQL_ERROR::WARN_LEVEL_NOTE,
+                          ER_NO_SUCH_USER,
+                          ER(ER_NO_SUCH_USER),
+                          lex->definer->user.str,
+                          lex->definer->host.str);
+    }
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
+
+    /*
       We need to copy name and db in order to use them for
       check_routine_access which is called after lex->sphead has
       been deleted.
@@ -4292,7 +4379,7 @@
       /*
         We must cleanup the unit and the lex here because
         sp_grant_privileges calls (indirectly) db_find_routine,
-        which in turn may call yyparse with THD::lex.
+        which in turn may call MYSQLparse with THD::lex.
         TODO: fix db_find_routine to use a temporary lex.
       */
       lex->unit.cleanup();
@@ -4972,7 +5059,9 @@
     break;
   }
   default:
+#ifndef EMBEDDED_LIBRARY
     DBUG_ASSERT(0);                             /* Impossible */
+#endif
     send_ok(thd);
     break;
   }
@@ -4990,6 +5079,7 @@
   */
   if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION)
     reset_one_shot_variables(thd);
+  thd->reset_current_stmt_binlog_row_based();
 
   /*
     The return value for ROW_COUNT() is "implementation dependent" if the
@@ -5728,7 +5818,7 @@
     sp_cache_flush_obsolete(&thd->sp_proc_cache);
     sp_cache_flush_obsolete(&thd->sp_func_cache);
     
-    if (!yyparse((void *)thd) && ! thd->is_fatal_error)
+    if (!MYSQLparse((void *)thd) && ! thd->is_fatal_error)
     {
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
       if (mqh_used && thd->user_connect &&
@@ -5820,7 +5910,7 @@
   DBUG_ENTER("mysql_test_parse_for_slave");
 
   mysql_init_query(thd, (uchar*) inBuf, length);
-  if (!yyparse((void*) thd) && ! thd->is_fatal_error &&
+  if (!MYSQLparse((void*) thd) && ! thd->is_fatal_error &&
       all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
     error= 1;                  /* Ignore question */
   thd->end_statement();
@@ -5916,10 +6006,7 @@
     */
     char buf[32];
     my_snprintf(buf, sizeof(buf), "TIMESTAMP(%s)", length);
-    push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
-                        ER_WARN_DEPRECATED_SYNTAX,
-                        ER(ER_WARN_DEPRECATED_SYNTAX),
-                        buf, "TIMESTAMP");
+    WARN_DEPRECATED(thd, "5.2", buf, "'TIMESTAMP'");
   }
 
   if (!(new_field= new create_field()) ||
@@ -6149,10 +6236,11 @@
     /*
       table_list.next points to the last inserted TABLE_LIST->next_local'
       element
+      We don't use the offsetof() macro here to avoid warnings from gcc
     */
-    previous_table_ref= (TABLE_LIST*) (table_list.next -
-                                       offsetof(TABLE_LIST, next_local));
-    DBUG_ASSERT(previous_table_ref);
+    previous_table_ref= (TABLE_LIST*) ((char*) table_list.next -
+                                       ((char*) &(ptr->next_local) -
+                                        (char*) ptr));
     /*
       Set next_name_resolution_table of the previous table reference to point
       to the current table reference. In effect the list
@@ -7341,47 +7429,54 @@
 
 /*
   Set the specified definer to the default value, which is the current user in
-  the thread. Also check that the current user satisfies to the definers
-  requirements.
+  the thread.
  
   SYNOPSIS
     get_default_definer()
     thd       [in] thread handler
     definer   [out] definer
- 
-  RETURN
-    error status, that is:
-      - FALSE -- on success;
-      - TRUE -- on error (current user can not be a definer).
 */
  
-bool get_default_definer(THD *thd, LEX_USER *definer)
+void get_default_definer(THD *thd, LEX_USER *definer)
 {
-  /* Check that current user has non-empty host name. */
-
   const Security_context *sctx= thd->security_ctx;
 
-  if (sctx->priv_host[0] == 0)
-  {
-    my_error(ER_MALFORMED_DEFINER, MYF(0));
-    return TRUE;
-  }
-
-  /* Fill in. */
-
   definer->user.str= (char *) sctx->priv_user;
   definer->user.length= strlen(definer->user.str);
 
   definer->host.str= (char *) sctx->priv_host;
   definer->host.length= strlen(definer->host.str);
+}
 
-  return FALSE;
+
+/*
+  Create default definer for the specified THD.
+
+  SYNOPSIS
+    create_default_definer()
+    thd         [in] thread handler
+
+  RETURN
+    On success, return a valid pointer to the created and initialized
+    LEX_USER, which contains definer information.
+    On error, return 0.
+*/
+
+LEX_USER *create_default_definer(THD *thd)
+{
+  LEX_USER *definer;
+
+  if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+    return 0;
+
+  get_default_definer(thd, definer);
+
+  return definer;
 }
 
 
 /*
-  Create definer with the given user and host names. Also check that the user
-  and host names satisfy definers requirements.
+  Create definer with the given user and host names.
 
   SYNOPSIS
     create_definer()
@@ -7391,21 +7486,13 @@
 
   RETURN
     On success, return a valid pointer to the created and initialized
-    LEX_STRING, which contains definer information.
+    LEX_USER, which contains definer information.
     On error, return 0.
 */
 
 LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
 {
   LEX_USER *definer;
-
-  /* Check that specified host name is valid. */
-
-  if (host_name->length == 0)
-  {
-    my_error(ER_MALFORMED_DEFINER, MYF(0));
-    return 0;
-  }
 
   /* Create and initialize. */
 

--- 1.105/sql/sql_select.h	2006-02-24 00:28:24 +03:00
+++ 1.106/sql/sql_select.h	2006-03-12 12:28:54 +03:00
@@ -104,6 +104,7 @@
 Next_select_func setup_end_select_func(JOIN *join);
 
 typedef struct st_join_table {
+  st_join_table() {}                          /* Remove gcc warning */
   TABLE		*table;
   KEYUSE	*keyuse;			/* pointer to first used key */
   SQL_SELECT	*select;
@@ -288,7 +289,6 @@
   {
     init(thd_arg, fields_arg, select_options_arg, result_arg);
   }
-
 
   void init(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
        select_result *result_arg)

--- 1.309/sql/sql_table.cc	2006-02-24 00:28:25 +03:00
+++ 1.310/sql/sql_table.cc	2006-03-12 12:28:54 +03:00
@@ -565,7 +565,7 @@
   String built_query;
   DBUG_ENTER("mysql_rm_table_part2");
 
-  if (binlog_row_based && !dont_log_query)
+  if (thd->current_stmt_binlog_row_based && !dont_log_query)
   {
     built_query.set_charset(system_charset_info);
     if (if_exists)
@@ -612,7 +612,7 @@
       being built.  The string always end in a comma and the comma
       will be chopped off before being written to the binary log.
       */
-    if (binlog_row_based && !dont_log_query)
+    if (thd->current_stmt_binlog_row_based && !dont_log_query)
     {
       ++non_temp_tables_count;
       /*
@@ -722,7 +722,7 @@
     query_cache_invalidate3(thd, tables, 0);
     if (!dont_log_query)
     {
-      if (!binlog_row_based ||
+      if (!thd->current_stmt_binlog_row_based ||
           non_temp_tables_count > 0 && !tmp_table_deleted)
       {
         /*
@@ -734,7 +734,7 @@
          */
         write_bin_log(thd, !error, thd->query, thd->query_length);
       }
-      else if (binlog_row_based &&
+      else if (thd->current_stmt_binlog_row_based &&
                non_temp_tables_count > 0 &&
                tmp_table_deleted)
       {
@@ -1748,7 +1748,9 @@
       }
       if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
       {
-	length=file->max_key_part_length();
+        length= file->max_key_part_length();
+        /* Align key length to multibyte char boundary */
+        length-= length % sql_field->charset->mbmaxlen;
 	if (key->type == Key::MULTIPLE)
 	{
 	  /* not a critical problem */
@@ -2254,8 +2256,8 @@
     Otherwise, the statement shall be binlogged.
    */
   if (!internal_tmp_table &&
-      (!binlog_row_based ||
-       (binlog_row_based &&
+      (!thd->current_stmt_binlog_row_based ||
+       (thd->current_stmt_binlog_row_based &&
         !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
     write_bin_log(thd, TRUE, thd->query, thd->query_length);
   error= FALSE;
@@ -2368,7 +2370,8 @@
 			       List<create_field> *extra_fields,
 			       List<Key> *keys,
 			       List<Item> *items,
-			       MYSQL_LOCK **lock)
+			       MYSQL_LOCK **lock,
+                               TABLEOP_HOOKS *hooks)
 {
   TABLE tmp_table;		// Used during 'create_field()'
   TABLE_SHARE share;
@@ -2447,6 +2450,7 @@
            save us from that ?
   */
   table->reginfo.lock_type=TL_WRITE;
+  hooks->prelock(&table, 1);                    // Call prelock hooks
   if (! ((*lock)= mysql_lock_tables(thd, &table, 1,
                                     MYSQL_LOCK_IGNORE_FLUSH, &not_used)))
   {
@@ -3481,7 +3485,7 @@
   /*
     We have to write the query before we unlock the tables.
   */
-  if (binlog_row_based)
+  if (thd->current_stmt_binlog_row_based)
   {
     /*
        Since temporary tables are not replicated under row-based
@@ -3704,6 +3708,8 @@
   uint changes= 0, tmp;
   List_iterator_fast<create_field> new_field_it(*create_list);
   create_field *new_field;
+  KEY_PART_INFO *key_part;
+  KEY_PART_INFO *end;
   DBUG_ENTER("compare_tables");
 
   /*
@@ -3831,9 +3837,14 @@
     /* Key modified. Add the offset of the key to both buffers. */
     index_drop_buffer[(*index_drop_count)++]= table_key - table->key_info;
     index_add_buffer[(*index_add_count)++]= new_key - key_info_buffer;
-    field= table->field[new_key->key_part->fieldnr];
-    // Mark field to be part of new key 
-    field->add_index= 1;
+    key_part= new_key->key_part;
+    end= key_part + new_key->key_parts;
+    for(; key_part != end; key_part++)
+    {
+      // Mark field to be part of new key 
+      field= table->field[key_part->fieldnr];
+      field->add_index= 1;
+    }
     DBUG_PRINT("info", ("index changed: '%s'", table_key->name));
   }
   /*end of for (; table_key < table_key_end;) */
@@ -3853,9 +3864,14 @@
     {
       /* Key not found. Add the offset of the key to the add buffer. */
       index_add_buffer[(*index_add_count)++]= new_key - key_info_buffer;
-      field= table->field[new_key->key_part->fieldnr];
-      // Mark field to be part of new key 
-      field->add_index= 1;
+      key_part= new_key->key_part;
+      end= key_part + new_key->key_parts;
+      for(; key_part != end; key_part++)
+      {
+        // Mark field to be part of new key 
+        field= table->field[key_part->fieldnr];
+        field->add_index= 1;
+      }
       DBUG_PRINT("info", ("index added: '%s'", new_key->name));
     }
   }
@@ -4035,6 +4051,13 @@
 	close_cached_table(thd, table);
 	if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias))
 	  error= -1;
+        else if (Table_triggers_list::change_table_name(thd, db, table_name,
+                                                        new_db, new_alias))
+        {
+          VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
+                                  table_name));
+          error= -1;
+        }
       }
       VOID(pthread_mutex_unlock(&LOCK_open));
     }
@@ -4867,7 +4890,7 @@
       goto err;
     }
     /* We don't replicate alter table statement on temporary tables */
-    if (!binlog_row_based)
+    if (!thd->current_stmt_binlog_row_based)
       write_bin_log(thd, TRUE, thd->query, thd->query_length);
     goto end_temporary;
   }
@@ -4937,7 +4960,11 @@
     VOID(quick_rm_table(new_db_type,new_db,tmp_name));
   }
   else if (mysql_rename_table(new_db_type,new_db,tmp_name,new_db,
-			      new_alias))
+			      new_alias) ||
+           (new_name != table_name || new_db != db) && // we also do rename
+           Table_triggers_list::change_table_name(thd, db, table_name,
+                                                  new_db, new_alias))
+       
   {						// Try to get everything back
     error=1;
     VOID(quick_rm_table(new_db_type,new_db,new_alias));
@@ -5037,7 +5064,7 @@
                       thd->query, thd->query_length,
                       db, table_name);
 
-  DBUG_ASSERT(!(mysql_bin_log.is_open() && binlog_row_based &&
+  DBUG_ASSERT(!(mysql_bin_log.is_open() && thd->current_stmt_binlog_row_based &&
                 (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
   write_bin_log(thd, TRUE, thd->query, thd->query_length);
   /*
@@ -5118,7 +5145,7 @@
   if (!(copy= new Copy_field[to->s->fields]))
     DBUG_RETURN(-1);				/* purecov: inspected */
 
-  if (to->file->external_lock(thd, F_WRLCK))
+  if (to->file->ha_external_lock(thd, F_WRLCK))
     DBUG_RETURN(-1);
 
   /* We can abort alter table for any table type */
@@ -5258,7 +5285,7 @@
   free_io_cache(from);
   *copied= found_count;
   *deleted=delete_count;
-  if (to->file->external_lock(thd,F_UNLCK))
+  if (to->file->ha_external_lock(thd,F_UNLCK))
     error=1;
   DBUG_RETURN(error > 0 ? -1 : 0);
 }

--- 1.62/mysql-test/r/ps.result	2006-02-24 00:28:21 +03:00
+++ 1.63/mysql-test/r/ps.result	2006-03-12 12:28:53 +03:00
@@ -859,6 +859,20 @@
 5
 deallocate prepare stmt;
 drop table t1;
+prepare stmt from 'create table t1 (a varchar(10) character set utf8)';
+execute stmt;
+insert into t1 (a) values (repeat('a', 20));
+select length(a) from t1;
+length(a)
+10
+drop table t1;
+execute stmt;
+insert into t1 (a) values (repeat('a', 20));
+select length(a) from t1;
+length(a)
+10
+drop table t1;
+deallocate prepare stmt;
 create table t1 (id int);
 prepare ins_call from "insert into t1 (id) values (1)";
 execute ins_call;
Thread
bk commit into 5.1 tree (konstantin:1.2166)konstantin12 Mar