Skip to content

Commit d113759

Browse files
author
Venkatesh Duggirala
committed
Bug#22916743 RBR DOES NOT USE DEFAULT CURRENT_TIMESTAMP FOR
EXTRA COLUMN ON SLAVE Analysis: In prepare_record(), which is called to prepare the basic record, we call restore_record to fill the tuple with all the default values which are maintained in memory at table->s->default_values. But for the special DEFAULT clauses like DEFAULT CURRENT_TIMESTAMP/NOW(), it is not maintained in table->s->default_values. It will be populated only when we explicit ask to do it (i.e., calling set_default()) function. Fix: For the extra fields that are present only on slave and that does not have 'DEFAULT' clause, replication calls 'set_default()' which will fill the record with default values (like for integer types 'zero' even though there is no DEFAULT 0 for the field). This logic is executed only for the field's that does not have default clause. Now the logic is extended to call set_default when there is special default clause (has_insert_default_function()).
1 parent d2cb428 commit d113759

File tree

4 files changed

+47
-10
lines changed

4 files changed

+47
-10
lines changed

mysql-test/extra/rpl_tests/rpl_extra_col_slave.test

+8
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,16 @@ if (`SELECT UPPER(LEFT($engine_type, 3)) != 'NDB'`)
429429
# they are declared without DEFAULT clause.
430430

431431
sync_slave_with_master;
432+
--replace_column 4 CURRENT_TIMESTAMP
432433
select * from t9;
433434

435+
# Bug #22916743 RBR DOES NOT USE DEFAULT CURRENT_TIMESTAMP FOR EXTRA COLUMN
436+
# ON SLAVE
437+
--let $assert_text= The values of column 'd' should have non-zero timetsamp.
438+
--let $assert_cond= [SELECT COUNT(*) AS Val FROM t9 WHERE d = "0000-00-00 00:00:00", Val, 1] = 0
439+
--source include/assert.inc
440+
# End of test for Bug #22916743
441+
434442
# todo: fix Bug #43992 slave sql thread can't tune own sql_mode ...
435443
# and add/restore waiting for stop test
436444

mysql-test/suite/rpl/r/rpl_extra_col_slave_innodb.result

+4-3
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,10 @@ set @b1 = concat(@b1,@b1);
208208
INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
209209
select * from t9;
210210
a b c d e f g h i
211-
1 b1b1b1b1b1b1b1b1 Kyle 0000-00-00 00:00:00 0 NULL NULL
212-
2 b1b1b1b1b1b1b1b1 JOE 0000-00-00 00:00:00 0 NULL NULL
213-
3 b1b1b1b1b1b1b1b1 QA 0000-00-00 00:00:00 0 NULL NULL
211+
1 b1b1b1b1b1b1b1b1 Kyle CURRENT_TIMESTAMP 0 NULL NULL
212+
2 b1b1b1b1b1b1b1b1 JOE CURRENT_TIMESTAMP 0 NULL NULL
213+
3 b1b1b1b1b1b1b1b1 QA CURRENT_TIMESTAMP 0 NULL NULL
214+
include/assert.inc [The values of column 'd' should have non-zero timetsamp.]
214215
DROP TABLE t9;
215216
*** Create t10 on slave ***
216217
STOP SLAVE;

mysql-test/suite/rpl/r/rpl_extra_col_slave_myisam.result

+4-3
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,10 @@ set @b1 = concat(@b1,@b1);
208208
INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
209209
select * from t9;
210210
a b c d e f g h i
211-
1 b1b1b1b1b1b1b1b1 Kyle 0000-00-00 00:00:00 0 NULL NULL
212-
2 b1b1b1b1b1b1b1b1 JOE 0000-00-00 00:00:00 0 NULL NULL
213-
3 b1b1b1b1b1b1b1b1 QA 0000-00-00 00:00:00 0 NULL NULL
211+
1 b1b1b1b1b1b1b1b1 Kyle CURRENT_TIMESTAMP 0 NULL NULL
212+
2 b1b1b1b1b1b1b1b1 JOE CURRENT_TIMESTAMP 0 NULL NULL
213+
3 b1b1b1b1b1b1b1b1 QA CURRENT_TIMESTAMP 0 NULL NULL
214+
include/assert.inc [The values of column 'd' should have non-zero timetsamp.]
214215
DROP TABLE t9;
215216
*** Create t10 on slave ***
216217
STOP SLAVE;

sql/rpl_record.cc

+31-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -487,11 +487,30 @@ int prepare_record(TABLE *const table, const MY_BITMAP *cols, const bool check)
487487
*/
488488

489489
DBUG_PRINT_BITSET("debug", "cols: %s", cols);
490+
/**
491+
Save a reference to the original write set bitmaps.
492+
We will need this to restore the bitmaps at the end.
493+
*/
494+
MY_BITMAP *old_write_set= table->write_set;
495+
/**
496+
Just to be sure that tmp_set is currently not in use as
497+
the read_set already.
498+
*/
499+
DBUG_ASSERT(table->write_set != &table->tmp_set);
500+
/* set the temporary write_set */
501+
table->column_bitmaps_set_no_signal(table->read_set,
502+
&table->tmp_set);
503+
/**
504+
Set table->write_set bits for all the columns as they
505+
will be checked in set_default() function.
506+
*/
507+
bitmap_set_all(table->write_set);
508+
490509
for (Field **field_ptr= table->field; *field_ptr; ++field_ptr)
491510
{
492-
if ((uint) (field_ptr - table->field) >= cols->n_bits ||
493-
!bitmap_is_set(cols, field_ptr - table->field))
494-
{
511+
uint field_index= (uint) (field_ptr - table->field);
512+
if (field_index >= cols->n_bits || !bitmap_is_set(cols, field_index))
513+
{
495514
Field *const f= *field_ptr;
496515
if ((f->flags & NO_DEFAULT_VALUE_FLAG) &&
497516
(f->real_type() != MYSQL_TYPE_ENUM))
@@ -503,9 +522,17 @@ int prepare_record(TABLE *const table, const MY_BITMAP *cols, const bool check)
503522
ER(ER_NO_DEFAULT_FOR_FIELD),
504523
f->field_name);
505524
}
525+
else if (f->has_insert_default_function())
526+
{
527+
f->set_default();
528+
}
506529
}
507530
}
508531

532+
/* set the write_set back to original*/
533+
table->column_bitmaps_set_no_signal(table->read_set,
534+
old_write_set);
535+
509536
DBUG_RETURN(0);
510537
}
511538

0 commit comments

Comments
 (0)