-
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.
Sreeharsha Ramanavarapu authoredIssue: ------ 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