Skip to content
  • Sreeharsha Ramanavarapu's avatar
    f84ffaf8
    Bug #23573575: GCOLS: INCORRECT BEHAVIOR WITH BLOB IN DML · f84ffaf8
    Sreeharsha Ramanavarapu authored
    Issue:
    ------
    This problem occurs when:
    1) A virtual generated column is of type BLOB and is part
       of a secondary index.
    2) A REPLACE statement tries to update an existing row.
    
    The row in the clustered index has the new value but the
    value of the virtual generated column in the secondary
    index has not been updated.
    
    This can result in incorrect behavior with future DML
    statements.
    
    Root cause:
    -----------
    ha_index_read_map calls update_generated_read_fields.
    Field_blob object is required here to keep track of the
    actual value of column 'c'.
    
                           a   b            c
    table->record[1] ==> --------------------------------
                         | 7 | 7  |   ptr_to_blob_value |
                         --------------------------------
                                            ||
                                            \/
                                          ......................
                                          | <to-be-calculated> |
                                          ......................
    
    
                           a   b            c
    table->record[0] ==> --------------------------------
                         | 7 | 13 |   ptr_to_blob_value |
                         --------------------------------
                                            ||
                                            \/
                                          ........
                                          |  13  |
                                          ........
    
    table->record[0] was calculated in update_generated_write_fields.
    
    update_generated_read_fields tries to re-create the
    existing row to see if the index's value needs
    modification. Here it has to use the same blob object
    referred to above.
    
    At the end of update_generated_read_fields :
                           a   b            c
    table->record[1] ==> --------------------------------
                         | 7 | 7  |   ptr_to_blob_value |
                         --------------------------------
                                            ||
                                            \/
                                          ........
                                          |  7   |
                                          ........
                                            /\
                                            ||
                           a   b            c
    table->record[0] ==> --------------------------------
                         | 7 | 13 |   ptr_to_blob_value |
                         --------------------------------
    
    update_generated_read_fields never calls
    Field_blob::keep_old_value and hence the value is
    over-written with the current row. This allows the server
    to mistake that no change is required for the secondary
    index. This results in a mis-match between the values in
    the clustered index and the ones in the secondary index.
    
    Solution:
    ---------
    Effectively what we need is a producer-consumer type model:
    Whichever function (among update_generated_write_fields and
    update_generated_read_fields) is called first should set
    the m_keep_old_value flag to true.
    
    The succeeding function (again among the two) should consume
    the flag. If the flag isn't consumed, at the end of the
    statement, set it to false. This will avoid issues that
    arise when, for example an INSERT preceeds an UPDATE.
    
    There are other exceptions, like
    update_generated_write_fields being called from
    COPY_INFO::set_function_defaults. This was done as part of
    Bug#21875520, to avoid a much larger re-factoring. The flag
    is set to false in this case.
    f84ffaf8
    Bug #23573575: GCOLS: INCORRECT BEHAVIOR WITH BLOB IN DML
    Sreeharsha Ramanavarapu authored
    Issue:
    ------
    This problem occurs when:
    1) A virtual generated column is of type BLOB and is part
       of a secondary index.
    2) A REPLACE statement tries to update an existing row.
    
    The row in the clustered index has the new value but the
    value of the virtual generated column in the secondary
    index has not been updated.
    
    This can result in incorrect behavior with future DML
    statements.
    
    Root cause:
    -----------
    ha_index_read_map calls update_generated_read_fields.
    Field_blob object is required here to keep track of the
    actual value of column 'c'.
    
                           a   b            c
    table->record[1] ==> --------------------------------
                         | 7 | 7  |   ptr_to_blob_value |
                         --------------------------------
                                            ||
                                            \/
                                          ......................
                                          | <to-be-calculated> |
                                          ......................
    
    
                           a   b            c
    table->record[0] ==> --------------------------------
                         | 7 | 13 |   ptr_to_blob_value |
                         --------------------------------
                                            ||
                                            \/
                                          ........
                                          |  13  |
                                          ........
    
    table->record[0] was calculated in update_generated_write_fields.
    
    update_generated_read_fields tries to re-create the
    existing row to see if the index's value needs
    modification. Here it has to use the same blob object
    referred to above.
    
    At the end of update_generated_read_fields :
                           a   b            c
    table->record[1] ==> --------------------------------
                         | 7 | 7  |   ptr_to_blob_value |
                         --------------------------------
                                            ||
                                            \/
                                          ........
                                          |  7   |
                                          ........
                                            /\
                                            ||
                           a   b            c
    table->record[0] ==> --------------------------------
                         | 7 | 13 |   ptr_to_blob_value |
                         --------------------------------
    
    update_generated_read_fields never calls
    Field_blob::keep_old_value and hence the value is
    over-written with the current row. This allows the server
    to mistake that no change is required for the secondary
    index. This results in a mis-match between the values in
    the clustered index and the ones in the secondary index.
    
    Solution:
    ---------
    Effectively what we need is a producer-consumer type model:
    Whichever function (among update_generated_write_fields and
    update_generated_read_fields) is called first should set
    the m_keep_old_value flag to true.
    
    The succeeding function (again among the two) should consume
    the flag. If the flag isn't consumed, at the end of the
    statement, set it to false. This will avoid issues that
    arise when, for example an INSERT preceeds an UPDATE.
    
    There are other exceptions, like
    update_generated_write_fields being called from
    COPY_INFO::set_function_defaults. This was done as part of
    Bug#21875520, to avoid a much larger re-factoring. The flag
    is set to false in this case.
Loading