• Monty's avatar
    Fixed bug in extended key handling when there is no primary key · 00704aff
    Monty authored
    Extended keys works by first checking if the engine supports extended
    keys.
    If yes, it extends secondary key with primary key components and mark the
    secondary keys as HA_EXT_NOSAME (unique).
    If we later notice that there where no primary key, the extended key
    information for secondary keys in share->key_info is reset. However the
    key_info->flag HA_EXT_NOSAME was not reset!
    
    This causes some strange things to happen:
    - Tables that have no primary key or secondary index that contained the
      primary key would be wrongly optimized as the secondary key could be
      thought to be unique when it was not and not unique when it was.
    - The problem was not shown in EXPLAIN because of a bug in
      create_ref_for_key() that caused EQ_REF to be displayed by EXPLAIN as REF
      when extended keys where used and the secondary key contained the primary
      key.
    
    This is fixed with:
    - Removed wrong test in make_join_select() which did not detect that key
      where unique when a secondary key contains the primary.
    - Moved initialization of extended keys from create_key_infos() to
      init_from_binary_frm_image() after we know if there is a usable primary
      key or not. One disadvantage with this approach is that
      key_info->key_parts may have not used slots (for keys we thought could
      be extended but could not). Fixed by adding a check for unused key_parts
      to copy_keys_from_share().
    
    Other things:
    - Simplified copying of first key part in create_key_infos().
    - Added a lot of code comments in code that I had to check as part of
      finding the issue.
    - Fixed some indentation.
    - Replaced a couple of looks using references to pointers in C
      context where the reference does not give any benefit.
    - Updated Aria and Maria to not assume the all key_info->rec_per_key
      are in one memory block (this could happen when using dervived
      tables with many keys).
    - Fixed a bug where key_info->rec_per_key where not allocated
    - Optimized TABLE::add_tmp_key() to only call alloc() once.
      (No logic changes)
    
    Test case changes:
    - innodb_mysql.test changed index as an index the optimizer thought
      was unique, was not. (Table had no primary key)
    
    TODO:
    - Move code that checks for partial or too long keys to the primary loop
      earlier that initally decides if we should add extended key fields.
      This is needed to ensure that HA_EXT_NOSAME is not set for partial or
      too long keys. It will also shorten the current code notable.
    00704aff
innodb_mysql.result 90.7 KB