Skip to content
/ server Public

Commit 9dd25e9

Browse files
committed
MDEV-38716: Part 2
The last patch was incorrect - it did not consider columns with both DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP and these records would be re-written with new timestamps. The fix is to add the ON UPDATE based default_fields back to the destination table after the actual data copy. Reviewed-by: TODO Signed-off-by: Brandon Nesterenko <[email protected]>
1 parent 8e7131e commit 9dd25e9

File tree

1 file changed

+44
-16
lines changed

1 file changed

+44
-16
lines changed

sql/sql_table.cc

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12720,16 +12720,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
1272012720
goto err;
1272112721
(copy_end++)->set(*ptr,def->field,0);
1272212722
}
12723-
12724-
/*
12725-
Ensure that TIMESTAMP or DATETIME fields with ON UPDATE clauses
12726-
have their default_fields copied, so they are executed after ALTER.
12727-
*/
12728-
if (dfield_ptr && def->field->has_update_default_function())
12729-
{
12730-
*(dfield_ptr++)= *ptr;
12731-
++to->s->default_fields;
12732-
}
1273312723
}
1273412724
else
1273512725
{
@@ -12746,13 +12736,14 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
1274612736
}
1274712737
}
1274812738
}
12739+
12740+
/*
12741+
Mark the end of the default field list. Note that this is a temporary
12742+
state; fields with ON UPDATE defaults will be added back to this list
12743+
after the data copy is complete.
12744+
*/
1274912745
if (dfield_ptr)
12750-
{
12751-
if (dfield_ptr == to->default_field)
12752-
to->default_field= NULL; // No default fields left
12753-
else
12754-
*dfield_ptr= NULL; // Mark end of default field pointers
12755-
}
12746+
*dfield_ptr= NULL;
1275612747

1275712748
if (order)
1275812749
{
@@ -13031,6 +13022,43 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
1303113022
cleanup_done= 1;
1303213023
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1303313024

13025+
/*
13026+
To prevent this data copy from re-writing previously set default values,
13027+
this function previously has overridden to->default_fields to only account
13028+
for new fields added to the table (i.e those which should get new default
13029+
values). Now that the data copy is done, the to->default_field list is
13030+
missing fields that have ON UPDATE clauses (i.e. TIMESTAMP and DATETIME).
13031+
So restore these fields to the default_fields list.
13032+
13033+
Notes:
13034+
* The code is similar to the dfield_ptr modification earlier in the
13035+
function
13036+
* This must be done before online alter execution, as it unpacks row
13037+
data, which requires the table's default_fields to be set up
13038+
* The following DBUG_ASSERT ensures either there are no default
13039+
fields for the table, or the dfield_ptr points to the end of the
13040+
default field list (which is NULL). This ensures that if we are
13041+
adding back default fields, we are not overwriting any existing
13042+
fields.
13043+
*/
13044+
it.rewind();
13045+
DBUG_ASSERT(!dfield_ptr || !(*dfield_ptr));
13046+
for (Field **ptr=to->field ; *ptr ; ptr++)
13047+
{
13048+
def=it++;
13049+
if (def->field && dfield_ptr && def->field->has_update_default_function())
13050+
{
13051+
*(dfield_ptr++)= *ptr;
13052+
}
13053+
}
13054+
if (dfield_ptr)
13055+
{
13056+
if (dfield_ptr == to->default_field)
13057+
to->default_field= NULL; // No default fields left
13058+
else
13059+
*dfield_ptr= NULL; // Mark end of default field pointers
13060+
}
13061+
1303413062
#ifdef HAVE_REPLICATION
1303513063
if (online && error < 0)
1303613064
{

0 commit comments

Comments
 (0)