• unknown's avatar
    Fix for bug#20670 "UPDATE using key and invoking trigger that modifies · e0d2f525
    unknown authored
    this key does not stop" (5.1 version).
    
    UPDATE statement which WHERE clause used key and which invoked trigger
    that modified field in this key worked indefinetely.
    
    This problem occured because in cases when UPDATE statement was
    executed in update-on-the-fly mode (in which row is updated right
    during evaluation of select for WHERE clause) the new version of
    the row became visible to select representing WHERE clause and was
    updated again and again.
    We already solve this problem for UPDATE statements which does not
    invoke triggers by detecting the fact that we are going to update
    field in key used for scanning and performing update in two steps,
    during the first step we gather information about the rows to be
    updated and then doing actual updates. We also do this for
    MULTI-UPDATE and in its case we even detect situation when such
    fields are updated in triggers (actually we simply assume that
    we always update fields used in key if we have before update
    trigger).
    
    The fix simply extends this check which is done with help of
    check_if_key_used()/QUICK_SELECT_I::check_if_keys_used()
    routine/method in such way that it also detects cases when
    field used in key is updated in trigger. We do this by
    changing check_if_key_used() to take field bitmap instead
    field list as argument and passing TABLE::write_set
    to it (we also have to add info about fields used in
    triggers to this bitmap a bit earlier).
    As nice side-effect we have more precise and thus more optimal
    perfomance-wise check for the MULTI-UPDATE.
    Also check_if_key_used() routine and similar method were renamed
    to is_key_used()/is_keys_used() in order to better reflect that
    it is simple boolean predicate.
    Finally, partition_key_modified() routine now also takes field
    bitmap instead of field list as argument.
    
    
    sql/key.cc:
      Now check_if_key_used() takes field bitmap instead of field list as
      argument (bitmaps are also used in its implementation).
      It is no longer responsible for checking if key uses automatically
      updated TIMESTAMP fields, instead callers should properly mark such
      fields in field bitmap.
      Also renamed this function to is_key_used().
    sql/mysql_priv.h:
      Renamed check_if_key_used() to is_key_used(), also now this routine
      takes field bitmap instead of field list as argument.
    sql/opt_range.cc:
      QUICK_SELECT_I::check_if_keys_used() method and check_if_key_used()
      routine were renamed to is_keys_used()/is_key_used(). Also now they
      take bitmap instead of field list as argument.
    sql/opt_range.h:
      QUICK_SELECT_I::check_if_key_used() method was renamed to is_keys_used().
      Now it takes field bitmap instead of field list as argument and no
      longer responsible for checking if key uses automatically updated
      TIMESTAMP fields. Instead callers should properly mark such fields
      in field bitmap.
    sql/sql_partition.cc:
      partition_key_modified() now takes field bitmap instead of list
      as argument.
    sql/sql_partition.h:
      partition_key_modified() now takes field bitmap as argument
      instead of field list.
    sql/sql_update.cc:
      To detect situation in which trigger modifies part of key which is
      going to be used for processing of where clause and thus makes
      processing of this update with update-on-the-fly method unsafe
      we use check_if_key_used() routine and similar method (which were
      renamed to is_key_used()) plus information from TABLE::write_map
      bitmap. Note that we have to call TABLE::mark_columns_needed_for_update()
      method earlier now to fill this bitmap with information about fields
      updated in triggers.
      safe_update_on_fly() routine now uses the same approach and no
      longer needs list of fields as argument.
    e0d2f525
opt_range.h 23 KB