mirror of
https://github.com/MariaDB/server.git
synced 2025-07-08 17:02:21 +03:00
MDEV-20403 Assertion 0' or Assertion
btr_validate_index(index, 0)' failed in row_upd_sec_index_entry or error code 126: Index is corrupted upon UPDATE with TIMESTAMP..ON UPDATE
Three issues here: * ON UPDATE DEFAULT NOW columns were updated after generated columns were computed - this broke indexed virtual columns * ON UPDATE DEFAULT NOW columns were updated after BEFORE triggers, so triggers didn't see the correct NEW value * in case of a multi-update generated columns were also updated after BEFORE triggers
This commit is contained in:
@ -3093,3 +3093,26 @@ a b
|
|||||||
1999-12-01 11:22:33.000000 1999-12-01 11:22:33.000000
|
1999-12-01 11:22:33.000000 1999-12-01 11:22:33.000000
|
||||||
2001-09-09 04:46:40.000000 2001-09-09 04:46:40.000000
|
2001-09-09 04:46:40.000000 2001-09-09 04:46:40.000000
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
create table t1 (t timestamp, i int, v timestamp as (t) virtual, key(v));
|
||||||
|
insert t1 (t,i) values ('2006-03-01 23:59:59',1);
|
||||||
|
update t1 set i = 2;
|
||||||
|
check table t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (t timestamp, i int);
|
||||||
|
create trigger tr1 before update on t1 for each row set @new:=new.t;
|
||||||
|
insert t1 (t,i) values ('2006-03-01 23:59:59', 1);
|
||||||
|
update t1 set i = 2;
|
||||||
|
select if(@new = t, 'correct', 'wrong') from t1;
|
||||||
|
if(@new = t, 'correct', 'wrong')
|
||||||
|
correct
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (i int, j int as (i));
|
||||||
|
create trigger tr1 before update on t1 for each row set @new:=new.j;
|
||||||
|
insert t1 (i) values (1);
|
||||||
|
update t1, t1 as t2 set t1.i = 2;
|
||||||
|
select if(@new = j, 'correct', 'wrong') from t1;
|
||||||
|
if(@new = j, 'correct', 'wrong')
|
||||||
|
correct
|
||||||
|
drop table t1;
|
||||||
|
@ -19,3 +19,30 @@ let $now=NOW(6);
|
|||||||
let $timestamp=TIMESTAMP(6);
|
let $timestamp=TIMESTAMP(6);
|
||||||
let $datetime=DATETIME(6);
|
let $datetime=DATETIME(6);
|
||||||
source 'include/function_defaults.inc';
|
source 'include/function_defaults.inc';
|
||||||
|
|
||||||
|
#
|
||||||
|
# MDEV-20403 Assertion `0' or Assertion `btr_validate_index(index, 0)' failed in row_upd_sec_index_entry or error code 126: Index is corrupted upon UPDATE with TIMESTAMP..ON UPDATE
|
||||||
|
#
|
||||||
|
|
||||||
|
# ON UPDATE DEFAULT NOW and indexed virtual columns
|
||||||
|
create table t1 (t timestamp, i int, v timestamp as (t) virtual, key(v));
|
||||||
|
insert t1 (t,i) values ('2006-03-01 23:59:59',1);
|
||||||
|
update t1 set i = 2;
|
||||||
|
check table t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
# ON UPDATE DEFAULT NOW and triggers
|
||||||
|
create table t1 (t timestamp, i int);
|
||||||
|
create trigger tr1 before update on t1 for each row set @new:=new.t;
|
||||||
|
insert t1 (t,i) values ('2006-03-01 23:59:59', 1);
|
||||||
|
update t1 set i = 2;
|
||||||
|
select if(@new = t, 'correct', 'wrong') from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
# triggers, virtual columns, multi-update
|
||||||
|
create table t1 (i int, j int as (i));
|
||||||
|
create trigger tr1 before update on t1 for each row set @new:=new.j;
|
||||||
|
insert t1 (i) values (1);
|
||||||
|
update t1, t1 as t2 set t1.i = 2;
|
||||||
|
select if(@new = j, 'correct', 'wrong') from t1;
|
||||||
|
drop table t1;
|
||||||
|
@ -8071,9 +8071,13 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
|
|||||||
rfield->set_explicit_default(value);
|
rfield->set_explicit_default(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!update && table_arg->default_field &&
|
if (update)
|
||||||
table_arg->update_default_fields(ignore_errors))
|
table_arg->evaluate_update_default_function();
|
||||||
goto err;
|
else
|
||||||
|
if (table_arg->default_field &&
|
||||||
|
table_arg->update_default_fields(ignore_errors))
|
||||||
|
goto err;
|
||||||
|
|
||||||
/* Update virtual fields */
|
/* Update virtual fields */
|
||||||
if (table_arg->vfield &&
|
if (table_arg->vfield &&
|
||||||
table_arg->update_virtual_fields(table_arg->file, VCOL_UPDATE_FOR_WRITE))
|
table_arg->update_virtual_fields(table_arg->file, VCOL_UPDATE_FOR_WRITE))
|
||||||
|
@ -66,12 +66,15 @@ bool compare_record(const TABLE *table)
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(records_are_comparable(table));
|
DBUG_ASSERT(records_are_comparable(table));
|
||||||
|
|
||||||
if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) != 0)
|
if (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ ||
|
||||||
|
table->s->has_update_default_function)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Storage engine may not have read all columns of the record. Fields
|
Storage engine may not have read all columns of the record. Fields
|
||||||
(including NULL bits) not in the write_set may not have been read and
|
(including NULL bits) not in the write_set may not have been read and
|
||||||
can therefore not be compared.
|
can therefore not be compared.
|
||||||
|
Or ON UPDATE DEFAULT NOW() could've changed field values, including
|
||||||
|
NULL bits.
|
||||||
*/
|
*/
|
||||||
for (Field **ptr= table->field ; *ptr != NULL; ptr++)
|
for (Field **ptr= table->field ; *ptr != NULL; ptr++)
|
||||||
{
|
{
|
||||||
@ -762,8 +765,6 @@ int mysql_update(THD *thd,
|
|||||||
|
|
||||||
if (!can_compare_record || compare_record(table))
|
if (!can_compare_record || compare_record(table))
|
||||||
{
|
{
|
||||||
if (table->default_field)
|
|
||||||
table->evaluate_update_default_function();
|
|
||||||
if ((res= table_list->view_check_option(thd, ignore)) !=
|
if ((res= table_list->view_check_option(thd, ignore)) !=
|
||||||
VIEW_CHECK_OK)
|
VIEW_CHECK_OK)
|
||||||
{
|
{
|
||||||
@ -2154,9 +2155,6 @@ int multi_update::send_data(List<Item> ¬_used_values)
|
|||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (table->default_field)
|
|
||||||
table->evaluate_update_default_function();
|
|
||||||
|
|
||||||
if ((error= cur_table->view_check_option(thd, ignore)) !=
|
if ((error= cur_table->view_check_option(thd, ignore)) !=
|
||||||
VIEW_CHECK_OK)
|
VIEW_CHECK_OK)
|
||||||
{
|
{
|
||||||
@ -2472,6 +2470,10 @@ int multi_update::do_updates()
|
|||||||
copy_field_ptr->to_field->set_has_explicit_value();
|
copy_field_ptr->to_field->set_has_explicit_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table->evaluate_update_default_function();
|
||||||
|
if (table->vfield &&
|
||||||
|
table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_WRITE))
|
||||||
|
goto err2;
|
||||||
if (table->triggers &&
|
if (table->triggers &&
|
||||||
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
||||||
TRG_ACTION_BEFORE, TRUE))
|
TRG_ACTION_BEFORE, TRUE))
|
||||||
@ -2480,11 +2482,6 @@ int multi_update::do_updates()
|
|||||||
if (!can_compare_record || compare_record(table))
|
if (!can_compare_record || compare_record(table))
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
if (table->default_field)
|
|
||||||
table->evaluate_update_default_function();
|
|
||||||
if (table->vfield &&
|
|
||||||
table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_WRITE))
|
|
||||||
goto err2;
|
|
||||||
if ((error= cur_table->view_check_option(thd, ignore)) !=
|
if ((error= cur_table->view_check_option(thd, ignore)) !=
|
||||||
VIEW_CHECK_OK)
|
VIEW_CHECK_OK)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user