List:Commits« Previous MessageNext Message »
From:mattiasj Date:November 21 2007 5:55pm
Subject:bk commit into 5.1 tree (mattiasj:1.2627) BUG#23603
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of mattiasj. When mattiasj 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-11-21 18:55:33+01:00, mattiasj@stripped +11 -0
  Bug#23603: Partitions: reoganize means delete
  
  Problem was that a user with ALTER priv (and without
  DROP priv) could do a REORGANIZE PARTITION that could
  delete rows.
  
  Added option "WITH NO DELETE" for use with
  REORGANIZE PARTITION for non delete operations
  (do not require DROP priv).
  Requiring DROP priv if "WITH NO DELETE" is NOT used.

  mysql-test/r/partition_grant.result@stripped, 2007-11-21 18:55:29+01:00, mattiasj@stripped +57 -0
    Bug#23603: Partitions: reoganize means delete
    test result

  mysql-test/t/partition_grant.test@stripped, 2007-11-21 18:55:29+01:00, mattiasj@stripped +54 -0
    Bug#23603: Partitions: reorganize means delete
    test case

  sql/ha_partition.cc@stripped, 2007-11-21 18:55:29+01:00, mattiasj@stripped +24 -6
    Bug#23603: Partitions: reorganize means delete
    
    Added parameter in change_partitions and copy_partitions
    to allow alter WITH NO DELETE
    
    If delete would occur when "WITH NO DELETE" is given,
    return error.

  sql/ha_partition.h@stripped, 2007-11-21 18:55:29+01:00, mattiasj@stripped +6 -2
    Bug#23603: Partitions: reorgaize means delete
    
    Added a "no delete in reorganize" parameter to
    change_partitions and copy_partitions

  sql/handler.h@stripped, 2007-11-21 18:55:29+01:00, mattiasj@stripped +3 -1
    Bug#23603: Partitions: reorganize means delete
    
    Added a "no delete in reorganize" parameter in
    change_partitions

  sql/share/errmsg.txt@stripped, 2007-11-21 18:55:30+01:00, mattiasj@stripped +4 -0
    Bug#23603: Partitions: reorgnize means delete
    
    Added an error messege if REORGANIZE PARTITION
    would mean delete (when using the "WITH NO DELETE"
    option)

  sql/sql_lex.cc@stripped, 2007-11-21 18:55:29+01:00, mattiasj@stripped +2 -2
    Bug#23603: Partitions: reorganize means delete
    
    Flags should not be used for equality comparation,
    only by its bits.

  sql/sql_lex.h@stripped, 2007-11-21 18:55:29+01:00, mattiasj@stripped +1 -0
    Bugs#23603: Partitions: reorganize means delete
    
    Added flag for "WITH NO DELETE" part of
    ALTER...REORGANIZE PARTITION [WITH NO DELETE]

  sql/sql_parse.cc@stripped, 2007-11-21 18:55:29+01:00, mattiasj@stripped +10 -0
    Bug#23603: Partitions: reorganize means delete
    
    require DROP privileges for 
    ALTER TABLE ... REORGANIZE PARTITION
    if not including "WITH NO DELETE" part

  sql/sql_partition.cc@stripped, 2007-11-21 18:55:30+01:00, mattiasj@stripped +12 -6
    Bug#23603: Partitions: reorganize means delete
    
    Flags should be compared by bits.
    Added parameters for change_partitions for use of
    WITH NO DELETE in reorg partitions

  sql/sql_yacc.yy@stripped, 2007-11-21 18:55:30+01:00, mattiasj@stripped +10 -2
    Bug#23603: Partitions: reorganize means delete
    
    Added optional "WITH NO DELETE" for use in
    REORGANIZE PARTITION

diff -Nrup a/mysql-test/r/partition_grant.result b/mysql-test/r/partition_grant.result
--- a/mysql-test/r/partition_grant.result	2007-04-04 11:01:44 +02:00
+++ b/mysql-test/r/partition_grant.result	2007-11-21 18:55:29 +01:00
@@ -1,4 +1,61 @@
 drop schema if exists mysqltest_1;
+CREATE DATABASE mysqltest_1;
+USE mysqltest_1;
+CREATE TABLE t1 (a INT)
+PARTITION BY LIST (a)
+(PARTITION p0 VALUES IN (2),
+PARTITION p1 VALUES IN (1));
+INSERT INTO t1 VALUES (1);
+CREATE USER mysqltest_1@localhost;
+GRANT ALTER,SELECT ON mysqltest_1.t1 TO mysqltest_1@localhost;
+USE mysqltest_1;
+# User mysqltest_1 DB mysqltest_1 (only ALTER and SELECT privs)
+ALTER TABLE t1 REORGANIZE PARTITION p1 INTO (
+PARTITION p1 VALUES IN (0)
+);
+ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 't1'
+ALTER TABLE t1 REORGANIZE PARTITION p1 INTO (
+PARTITION p1 VALUES IN (1,3)
+);
+ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 't1'
+SELECT * FROM t1;
+a
+1
+ALTER TABLE t1 REORGANIZE PARTITION WITH NO DELETE p1 INTO (
+PARTITION p1 VALUES IN (1,3)
+);
+SELECT * FROM t1;
+a
+1
+ALTER TABLE t1 REORGANIZE PARTITION WITH NO DELETE p1 INTO (
+PARTITION p1 VALUES IN (4)
+);
+ERROR HY000: Impossible ALTER ... WITH NO DELETE. No partition was specified for some existing values.
+SELECT * FROM t1;
+a
+1
+ALTER TABLE t1 DROP PARTITION p1;
+ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 't1'
+DROP TABLE t1;
+ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 't1'
+# User root DB mysqltest_1 (all privs)
+SELECT * FROM t1;
+a
+1
+ALTER TABLE t1 REORGANIZE PARTITION WITH NO DELETE p1 INTO (PARTITION p1 VALUES IN (5));
+ERROR HY000: Impossible ALTER ... WITH NO DELETE. No partition was specified for some existing values.
+ALTER TABLE t1 REORGANIZE PARTITION WITH NO DELETE p1 INTO (PARTITION p1 VALUES IN (1,5));
+ALTER TABLE t1 REORGANIZE PARTITION p1 INTO (PARTITION p1 VALUES IN (1,6));
+SELECT * FROM t1;
+a
+1
+ALTER TABLE t1 REORGANIZE PARTITION p1 INTO (PARTITION p1 VALUES IN (7));
+SELECT * FROM t1;
+a
+DROP TABLE t1;
+USE test;
+DROP USER mysqltest_1@localhost;
+DROP DATABASE mysqltest_1;
 create schema mysqltest_1;
 use mysqltest_1;
 create table t1 (a int) partition by list (a) (partition p1 values in (1), partition p2 values in (2), partition p3 values in (3));
diff -Nrup a/mysql-test/t/partition_grant.test b/mysql-test/t/partition_grant.test
--- a/mysql-test/t/partition_grant.test	2007-06-26 13:15:03 +02:00
+++ b/mysql-test/t/partition_grant.test	2007-11-21 18:55:29 +01:00
@@ -6,6 +6,60 @@
 drop schema if exists mysqltest_1;
 --enable_warnings
 
+#
+# Bug #23603: PARTITION ALTER could case delete
+# ALTER TABLE t REORGANIZE PARTITION
+# requires DROP privileges, if "WITH NO DELETE" is not
+# specified. Then it only succeed if it do not delete
+# any rows
+CREATE DATABASE mysqltest_1;
+USE mysqltest_1;
+CREATE TABLE t1 (a INT)
+PARTITION BY LIST (a)
+(PARTITION p0 VALUES IN (2),
+PARTITION p1 VALUES IN (1));
+INSERT INTO t1 VALUES (1);
+CREATE USER mysqltest_1@localhost;
+GRANT ALTER,SELECT ON mysqltest_1.t1 TO mysqltest_1@localhost;
+CONNECT (con1,localhost,mysqltest_1,,);
+USE mysqltest_1;
+-- echo # User mysqltest_1 DB mysqltest_1 (only ALTER and SELECT privs)
+--error ER_TABLEACCESS_DENIED_ERROR
+ALTER TABLE t1 REORGANIZE PARTITION p1 INTO (
+  PARTITION p1 VALUES IN (0)
+);
+--error ER_TABLEACCESS_DENIED_ERROR
+ALTER TABLE t1 REORGANIZE PARTITION p1 INTO (
+  PARTITION p1 VALUES IN (1,3)
+);
+SELECT * FROM t1;
+ALTER TABLE t1 REORGANIZE PARTITION WITH NO DELETE p1 INTO (
+  PARTITION p1 VALUES IN (1,3)
+);
+SELECT * FROM t1;
+--error ER_PARTITION_ALTER_CAUSES_DELETE
+ALTER TABLE t1 REORGANIZE PARTITION WITH NO DELETE p1 INTO (
+  PARTITION p1 VALUES IN (4)
+);
+SELECT * FROM t1;
+--error ER_TABLEACCESS_DENIED_ERROR
+ALTER TABLE t1 DROP PARTITION p1;
+--error ER_TABLEACCESS_DENIED_ERROR
+DROP TABLE t1;
+connection default;
+-- echo # User root DB mysqltest_1 (all privs)
+SELECT * FROM t1;
+--error ER_PARTITION_ALTER_CAUSES_DELETE
+ALTER TABLE t1 REORGANIZE PARTITION WITH NO DELETE p1 INTO (PARTITION p1 VALUES IN (5));
+ALTER TABLE t1 REORGANIZE PARTITION WITH NO DELETE p1 INTO (PARTITION p1 VALUES IN (1,5));
+ALTER TABLE t1 REORGANIZE PARTITION p1 INTO (PARTITION p1 VALUES IN (1,6));
+SELECT * FROM t1;
+ALTER TABLE t1 REORGANIZE PARTITION p1 INTO (PARTITION p1 VALUES IN (7));
+SELECT * FROM t1;
+DROP TABLE t1;
+USE test;
+DROP USER mysqltest_1@localhost;
+DROP DATABASE mysqltest_1;
 
 #
 # Bug #17139: ALTER TABLE ... DROP PARTITION should require DROP privilege
diff -Nrup a/sql/ha_partition.cc b/sql/ha_partition.cc
--- a/sql/ha_partition.cc	2007-11-14 14:28:18 +01:00
+++ b/sql/ha_partition.cc	2007-11-21 18:55:29 +01:00
@@ -1212,6 +1212,7 @@ void ha_partition::cleanup_new_partition
 
   SYNOPSIS
     change_partitions()
+    thd                         THD object for mem_root use
     create_info                 HA_CREATE_INFO object describing all
                                 fields and indexes in table
     path                        Complete path of db and table name
@@ -1219,6 +1220,7 @@ void ha_partition::cleanup_new_partition
                                 records are added
     out: deleted                Output parameter where number of deleted
                                 records are added
+    no_del_in_reorg             Do not allow delete in REORG PARTITION
     pack_frm_data               Reference to packed frm file
     pack_frm_len                Length of packed frm file
 
@@ -1236,10 +1238,12 @@ void ha_partition::cleanup_new_partition
     get zero length and a NULL reference here.
 */
 
-int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
+int ha_partition::change_partitions(THD *thd,
+                                    HA_CREATE_INFO *create_info,
                                     const char *path,
                                     ulonglong *copied,
                                     ulonglong *deleted,
+                                    bool no_del_in_reorg,
                                     const uchar *pack_frm_data
                                     __attribute__((unused)),
                                     size_t pack_frm_len
@@ -1256,7 +1260,6 @@ int ha_partition::change_partitions(HA_C
   int error= 1;
   bool first;
   uint temp_partitions= m_part_info->temp_partitions.elements;
-  THD *thd= current_thd;
   DBUG_ENTER("ha_partition::change_partitions");
 
   m_reorged_parts= 0;
@@ -1502,7 +1505,7 @@ int ha_partition::change_partitions(HA_C
     part_elem->part_state= PART_TO_BE_DROPPED;
   }
   m_new_file= new_file_array;
-  DBUG_RETURN(copy_partitions(copied, deleted));
+  DBUG_RETURN(copy_partitions(no_del_in_reorg, copied, deleted));
 }
 
 
@@ -1511,6 +1514,7 @@ int ha_partition::change_partitions(HA_C
 
   SYNOPSIS
     copy_partitions()
+    no_del_in_reorg            Do not allow delete in REORG PARTITION
     out:copied                 Number of records copied
     out:deleted                Number of records deleted
 
@@ -1524,7 +1528,9 @@ int ha_partition::change_partitions(HA_C
     partitions.
 */
 
-int ha_partition::copy_partitions(ulonglong *copied, ulonglong *deleted)
+int ha_partition::copy_partitions(bool no_del_in_reorg,
+                                  ulonglong *copied,
+                                  ulonglong *deleted)
 {
   uint reorg_part= 0;
   int result= 0;
@@ -1562,12 +1568,21 @@ int ha_partition::copy_partitions(ulongl
            table since it doesn't fit into any partition any longer due to
            changed partitioning ranges or list values.
         */
-        deleted++;
+        /*
+          If ALTER TABLE ... REORGANIZE PARTITION WITH NO DELETE ...
+          return error that it is impossible to do without delete
+        */
+	if (no_del_in_reorg)
+        {
+          result= ER_PARTITION_ALTER_CAUSES_DELETE;
+          goto error;
+        }
+        (*deleted)++;
       }
       else
       {
         /* Copy record to new handler */
-        copied++;
+        (*copied)++;
         if ((result= m_new_file[new_part]->write_row(m_rec0)))
           goto error;
       }
@@ -5379,6 +5394,9 @@ void ha_partition::print_error(int error
 
   if (error == HA_ERR_NO_PARTITION_FOUND)
     m_part_info->print_no_partition_found(table);
+  else if (error == ER_PARTITION_ALTER_CAUSES_DELETE)
+    my_error(error, MYF(0));
+
   else
     m_file[m_last_part]->print_error(error, errflag);
   DBUG_VOID_RETURN;
diff -Nrup a/sql/ha_partition.h b/sql/ha_partition.h
--- a/sql/ha_partition.h	2007-09-24 15:30:28 +02:00
+++ b/sql/ha_partition.h	2007-11-21 18:55:29 +01:00
@@ -195,10 +195,12 @@ public:
                                    HA_CREATE_INFO *create_info);
   virtual void update_create_info(HA_CREATE_INFO *create_info);
   virtual char *update_table_comment(const char *comment);
-  virtual int change_partitions(HA_CREATE_INFO *create_info,
+  virtual int change_partitions(THD *thd,
+                                HA_CREATE_INFO *create_info,
                                 const char *path,
                                 ulonglong *copied,
                                 ulonglong *deleted,
+                                bool no_del_in_reorg,
                                 const uchar *pack_frm_data,
                                 size_t pack_frm_len);
   virtual int drop_partitions(const char *path);
@@ -212,7 +214,9 @@ public:
   virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);
 private:
   int prepare_for_delete();
-  int copy_partitions(ulonglong *copied, ulonglong *deleted);
+  int copy_partitions(bool no_del_in_reorg,
+                      ulonglong *copied,
+                      ulonglong *deleted);
   void cleanup_new_partition(uint part_count);
   int prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info,
                             handler *file, const char *part_name,
diff -Nrup a/sql/handler.h b/sql/handler.h
--- a/sql/handler.h	2007-09-07 15:41:46 +02:00
+++ b/sql/handler.h	2007-11-21 18:55:29 +01:00
@@ -1617,10 +1617,12 @@ public:
                                    int action_flag, HA_CREATE_INFO *info)
   { return FALSE; }
 
-  virtual int change_partitions(HA_CREATE_INFO *create_info,
+  virtual int change_partitions(THD *thd,
+                                HA_CREATE_INFO *create_info,
                                 const char *path,
                                 ulonglong *copied,
                                 ulonglong *deleted,
+                                bool no_del_in_reorg,
                                 const uchar *pack_frm_data,
                                 size_t pack_frm_len)
   { return HA_ERR_WRONG_COMMAND; }
diff -Nrup a/sql/share/errmsg.txt b/sql/share/errmsg.txt
--- a/sql/share/errmsg.txt	2007-11-14 14:28:21 +01:00
+++ b/sql/share/errmsg.txt	2007-11-21 18:55:30 +01:00
@@ -6114,3 +6114,7 @@ ER_TRG_CANT_OPEN_TABLE
 
 ER_CANT_CREATE_SROUTINE
   eng "Cannot create stored routine `%-.64s`. Check warnings"
+
+ER_PARTITION_ALTER_CAUSES_DELETE
+  eng "Impossible ALTER ... WITH NO DELETE. No partition was specified for some existing values."
diff -Nrup a/sql/sql_lex.cc b/sql/sql_lex.cc
--- a/sql/sql_lex.cc	2007-11-10 11:58:37 +01:00
+++ b/sql/sql_lex.cc	2007-11-21 18:55:29 +01:00
@@ -2944,7 +2944,7 @@ bool st_select_lex::add_index_hint (THD 
 bool st_lex::is_partition_management() const
 {
   return (sql_command == SQLCOM_ALTER_TABLE &&
-          (alter_info.flags == ALTER_ADD_PARTITION ||
-           alter_info.flags == ALTER_REORGANIZE_PARTITION));
+          (alter_info.flags & ALTER_ADD_PARTITION ||
+           alter_info.flags & ALTER_REORGANIZE_PARTITION));
 }
 
diff -Nrup a/sql/sql_lex.h b/sql/sql_lex.h
--- a/sql/sql_lex.h	2007-11-14 12:25:40 +01:00
+++ b/sql/sql_lex.h	2007-11-21 18:55:29 +01:00
@@ -835,6 +835,7 @@ inline bool st_select_lex_unit::is_union
 #define ALTER_REPAIR_PARTITION   (1L << 24)
 #define ALTER_REMOVE_PARTITIONING (1L << 25)
 #define ALTER_FOREIGN_KEY         (1L << 26)
+#define ALTER_REORG_PART_NO_DELETE (1L << 27) 
 
 enum enum_alter_table_change_level
 {
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc	2007-11-15 20:25:41 +01:00
+++ b/sql/sql_parse.cc	2007-11-21 18:55:29 +01:00
@@ -2495,6 +2495,16 @@ end_with_restore_list:
       */
       if (alter_info.flags & (ALTER_DROP_PARTITION | ALTER_RENAME))
         priv_needed|= DROP_ACL;
+      /*
+        For ALTER TABLE ... REORGANIZE PARTITION ...
+        We also require DROP priv
+        For ALTER TABLE ... REORGANIZE PARTITION WITH NO DELETE ...
+        We do not require DROP priv but returns error in copy_partition
+        if delete would occur.
+      */
+      if (alter_info.flags & ALTER_REORGANIZE_PARTITION
+          && !(alter_info.flags & ALTER_REORG_PART_NO_DELETE))
+        priv_needed|= DROP_ACL;
 
       /* Must be set in the parser */
       DBUG_ASSERT(select_lex->db);
diff -Nrup a/sql/sql_partition.cc b/sql/sql_partition.cc
--- a/sql/sql_partition.cc	2007-11-16 14:07:55 +01:00
+++ b/sql/sql_partition.cc	2007-11-21 18:55:30 +01:00
@@ -4204,7 +4204,7 @@ uint prep_alter_part_table(THD *thd, TAB
       my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
       DBUG_RETURN(TRUE);
     }
-    if (alter_info->flags == ALTER_TABLE_REORG)
+    if (alter_info->flags & ALTER_TABLE_REORG)
     {
       uint new_part_no, curr_part_no;
       if (tab_part_info->part_type != HASH_PARTITION ||
@@ -4734,7 +4734,7 @@ state of p1.
         tab_part_info->is_auto_partitioned= FALSE;
       }
     }
-    else if (alter_info->flags == ALTER_REORGANIZE_PARTITION)
+    else if (alter_info->flags & ALTER_REORGANIZE_PARTITION)
     {
       /*
         Reorganise partitions takes a number of partitions that are next
@@ -4915,8 +4915,8 @@ the generated partition syntax in a corr
     }
     *partition_changed= TRUE;
     thd->work_part_info= tab_part_info;
-    if (alter_info->flags == ALTER_ADD_PARTITION ||
-        alter_info->flags == ALTER_REORGANIZE_PARTITION)
+    if (alter_info->flags & ALTER_ADD_PARTITION ||
+        alter_info->flags & ALTER_REORGANIZE_PARTITION)
     {
       if (tab_part_info->use_default_subpartitions &&
           !alt_part_info->use_default_subpartitions)
@@ -5090,6 +5090,8 @@ the generated partition syntax in a corr
                                records are added
     deleted                    Output parameter where number of deleted
                                records are added
+    alter_info.flags           Flag to copy_partition about ALTER TABLE ...
+                               REORGANIZE PARTITION ... [WITH NO DELETE]
 */
 
 static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
@@ -5100,8 +5102,12 @@ static bool mysql_change_partitions(ALTE
   DBUG_ENTER("mysql_change_partitions");
 
   build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, "", 0);
-  if ((error= file->change_partitions(lpt->create_info, path, &lpt->copied,
-                                      &lpt->deleted, lpt->pack_frm_data,
+  if ((error= file->change_partitions(lpt->thd, lpt->create_info, path,
+                                      &lpt->copied,
+                                      &lpt->deleted,
+                                      lpt->alter_info->flags
+                                      & ALTER_REORG_PART_NO_DELETE,
+                                      lpt->pack_frm_data,
                                       lpt->pack_frm_len)))
   {
     if (error != ER_OUTOFMEMORY)
diff -Nrup a/sql/sql_yacc.yy b/sql/sql_yacc.yy
--- a/sql/sql_yacc.yy	2007-11-16 14:07:55 +01:00
+++ b/sql/sql_yacc.yy	2007-11-21 18:55:30 +01:00
@@ -3858,7 +3858,7 @@ opt_part_values:
             LEX *lex= Lex;
             if (! lex->is_partition_management())
             {
-              if (Lex->part_info->part_type != LIST_PARTITION)
+              if (lex->part_info->part_type != LIST_PARTITION)
               {
                 my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
                          "LIST", "IN");
@@ -5541,7 +5541,7 @@ reorg_parts_rule:
           {
             Lex->alter_info.flags|= ALTER_TABLE_REORG;
           }
-        | alt_part_name_list
+        | opt_with_no_delete alt_part_name_list
           {
             Lex->alter_info.flags|= ALTER_REORGANIZE_PARTITION;
           }
@@ -5549,6 +5549,14 @@ reorg_parts_rule:
           {
             LEX *lex= Lex;
             lex->part_info->no_parts= lex->part_info->partitions.elements;
+          }
+        ;
+
+opt_with_no_delete:
+          /* empty */
+        | WITH NO_SYM DELETE_SYM
+          {
+            Lex->alter_info.flags|= ALTER_REORG_PART_NO_DELETE;
           }
         ;
 
Thread
bk commit into 5.1 tree (mattiasj:1.2627) BUG#23603mattiasj21 Nov