mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 10:14:19 +01:00
Merge romeo.(none):/home/bkroot/mysql-5.1-new-rpl
into romeo.(none):/home/bk/w3259-mysql-5.1-new-rpl mysql-test/r/rpl_row_tabledefs_2myisam.result: Auto merged sql/field.cc: Auto merged sql/field.h: Auto merged mysql-test/t/disabled.def: SCCS merged
This commit is contained in:
commit
21263710af
8 changed files with 437 additions and 57 deletions
|
@ -25,6 +25,8 @@ eval CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=$engine_type;
|
|||
eval CREATE TABLE t4 (a INT) ENGINE=$engine_type;
|
||||
eval CREATE TABLE t5 (a INT, b INT, c INT) ENGINE=$engine_type;
|
||||
eval CREATE TABLE t6 (a INT, b INT, c INT) ENGINE=$engine_type;
|
||||
eval CREATE TABLE t7 (a INT NOT NULL) ENGINE=$engine_type;
|
||||
eval CREATE TABLE t8 (a INT NOT NULL) ENGINE=$engine_type;
|
||||
|
||||
# Table used to detect that slave is running
|
||||
eval CREATE TABLE t9 (a INT) ENGINE=$engine_type;
|
||||
|
@ -53,6 +55,17 @@ ALTER TABLE t5 MODIFY b FLOAT;
|
|||
# ... change the type of the last column of table 't6'
|
||||
ALTER TABLE t6 MODIFY c FLOAT;
|
||||
|
||||
# ... add one byte worth of null bytes to the table on the slave
|
||||
ALTER TABLE t7 ADD e1 INT, ADD e2 INT, ADD e3 INT, ADD e4 INT,
|
||||
ADD e5 INT, ADD e6 INT, ADD e7 INT, ADD e8 INT;
|
||||
|
||||
# ... add 8 columns that are nullable: t8 will not be entirely
|
||||
# nullable and have no null bits (just an X bit)
|
||||
ALTER TABLE t8 ADD e1 INT NOT NULL DEFAULT 0, ADD e2 INT NOT NULL DEFAULT 0,
|
||||
ADD e3 INT NOT NULL DEFAULT 0, ADD e4 INT NOT NULL DEFAULT 0,
|
||||
ADD e5 INT NOT NULL DEFAULT 0, ADD e6 INT NOT NULL DEFAULT 0,
|
||||
ADD e7 INT NOT NULL DEFAULT 0, ADD e8 INT NOT NULL DEFAULT 0;
|
||||
|
||||
# Insert some values for tables on slave side. These should not be
|
||||
# modified when the row from the master is applied.
|
||||
INSERT INTO t1_int VALUES (2, 4, 4711);
|
||||
|
@ -90,7 +103,7 @@ SELECT a,b,x FROM t1_int;
|
|||
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit;
|
||||
SELECT a,b,x FROM t1_char;
|
||||
|
||||
# Each of these should generate an error and stop the slave
|
||||
# Each of these inserts should generate an error and stop the slave
|
||||
|
||||
connection master;
|
||||
INSERT INTO t9 VALUES (2);
|
||||
|
@ -162,9 +175,60 @@ wait_for_slave_to_stop;
|
|||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||
START SLAVE;
|
||||
|
||||
connection master;
|
||||
INSERT INTO t9 VALUES (6);
|
||||
sync_slave_with_master;
|
||||
--replace_result $MASTER_MYPORT MASTER_PORT
|
||||
--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 #
|
||||
--query_vertical SHOW SLAVE STATUS
|
||||
|
||||
# Testing some tables extra field that can be null and cannot be null
|
||||
# (but have default values)
|
||||
|
||||
connection master;
|
||||
INSERT INTO t7 VALUES (1),(2),(3);
|
||||
INSERT INTO t8 VALUES (1),(2),(3);
|
||||
SELECT * FROM t7;
|
||||
SELECT * FROM t8;
|
||||
sync_slave_with_master;
|
||||
SELECT * FROM t7;
|
||||
SELECT * FROM t8;
|
||||
|
||||
# We will now try to update and then delete a row on the master where
|
||||
# the extra field on the slave does not have a default value. This
|
||||
# update should not generate an error even though there is no default
|
||||
# for the extra column.
|
||||
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
TRUNCATE t1_nodef;
|
||||
SET SQL_LOG_BIN=0;
|
||||
INSERT INTO t1_nodef VALUES (1,2);
|
||||
INSERT INTO t1_nodef VALUES (2,4);
|
||||
SET SQL_LOG_BIN=1;
|
||||
--echo **** On Slave ****
|
||||
connection slave;
|
||||
INSERT INTO t1_nodef VALUES (1,2,3);
|
||||
INSERT INTO t1_nodef VALUES (2,4,6);
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
UPDATE t1_nodef SET b=2*b WHERE a=1;
|
||||
SELECT * FROM t1_nodef;
|
||||
--echo **** On Slave ****
|
||||
sync_slave_with_master;
|
||||
SELECT * FROM t1_nodef;
|
||||
--echo **** On Master ****
|
||||
connection master;
|
||||
DELETE FROM t1_nodef WHERE a=2;
|
||||
SELECT * FROM t1_nodef;
|
||||
--echo **** On Slave ****
|
||||
sync_slave_with_master;
|
||||
SELECT * FROM t1_nodef;
|
||||
|
||||
--echo **** Cleanup ****
|
||||
connection master;
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef;
|
||||
DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t9;
|
||||
DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
--enable_warnings
|
||||
sync_slave_with_master;
|
||||
|
|
|
@ -16,6 +16,8 @@ CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE='MyISAM';
|
|||
CREATE TABLE t4 (a INT) ENGINE='MyISAM';
|
||||
CREATE TABLE t5 (a INT, b INT, c INT) ENGINE='MyISAM';
|
||||
CREATE TABLE t6 (a INT, b INT, c INT) ENGINE='MyISAM';
|
||||
CREATE TABLE t7 (a INT NOT NULL) ENGINE='MyISAM';
|
||||
CREATE TABLE t8 (a INT NOT NULL) ENGINE='MyISAM';
|
||||
CREATE TABLE t9 (a INT) ENGINE='MyISAM';
|
||||
ALTER TABLE t1_int ADD x INT DEFAULT 42;
|
||||
ALTER TABLE t1_bit
|
||||
|
@ -28,6 +30,12 @@ ALTER TABLE t2 DROP b;
|
|||
ALTER TABLE t4 MODIFY a FLOAT;
|
||||
ALTER TABLE t5 MODIFY b FLOAT;
|
||||
ALTER TABLE t6 MODIFY c FLOAT;
|
||||
ALTER TABLE t7 ADD e1 INT, ADD e2 INT, ADD e3 INT, ADD e4 INT,
|
||||
ADD e5 INT, ADD e6 INT, ADD e7 INT, ADD e8 INT;
|
||||
ALTER TABLE t8 ADD e1 INT NOT NULL DEFAULT 0, ADD e2 INT NOT NULL DEFAULT 0,
|
||||
ADD e3 INT NOT NULL DEFAULT 0, ADD e4 INT NOT NULL DEFAULT 0,
|
||||
ADD e5 INT NOT NULL DEFAULT 0, ADD e6 INT NOT NULL DEFAULT 0,
|
||||
ADD e7 INT NOT NULL DEFAULT 0, ADD e8 INT NOT NULL DEFAULT 0;
|
||||
INSERT INTO t1_int VALUES (2, 4, 4711);
|
||||
INSERT INTO t1_char VALUES (2, 4, 'Foo is a bar');
|
||||
INSERT INTO t1_bit VALUES (2, 4, b'101', b'11100', b'01');
|
||||
|
@ -282,5 +290,92 @@ Master_SSL_Key
|
|||
Seconds_Behind_Master #
|
||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||
START SLAVE;
|
||||
INSERT INTO t9 VALUES (6);
|
||||
SHOW SLAVE STATUS;
|
||||
Slave_IO_State #
|
||||
Master_Host 127.0.0.1
|
||||
Master_User root
|
||||
Master_Port MASTER_PORT
|
||||
Connect_Retry 1
|
||||
Master_Log_File master-bin.000001
|
||||
Read_Master_Log_Pos #
|
||||
Relay_Log_File #
|
||||
Relay_Log_Pos #
|
||||
Relay_Master_Log_File master-bin.000001
|
||||
Slave_IO_Running Yes
|
||||
Slave_SQL_Running Yes
|
||||
Replicate_Do_DB
|
||||
Replicate_Ignore_DB
|
||||
Replicate_Do_Table
|
||||
Replicate_Ignore_Table
|
||||
Replicate_Wild_Do_Table
|
||||
Replicate_Wild_Ignore_Table
|
||||
Last_Errno 0
|
||||
Last_Error
|
||||
Skip_Counter 0
|
||||
Exec_Master_Log_Pos #
|
||||
Relay_Log_Space #
|
||||
Until_Condition None
|
||||
Until_Log_File
|
||||
Until_Log_Pos 0
|
||||
Master_SSL_Allowed No
|
||||
Master_SSL_CA_File
|
||||
Master_SSL_CA_Path
|
||||
Master_SSL_Cert
|
||||
Master_SSL_Cipher
|
||||
Master_SSL_Key
|
||||
Seconds_Behind_Master #
|
||||
INSERT INTO t7 VALUES (1),(2),(3);
|
||||
INSERT INTO t8 VALUES (1),(2),(3);
|
||||
SELECT * FROM t7;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
SELECT * FROM t8;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
SELECT * FROM t7;
|
||||
a e1 e2 e3 e4 e5 e6 e7 e8
|
||||
1 NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
2 NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
3 NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
SELECT * FROM t8;
|
||||
a e1 e2 e3 e4 e5 e6 e7 e8
|
||||
1 0 0 0 0 0 0 0 0
|
||||
2 0 0 0 0 0 0 0 0
|
||||
3 0 0 0 0 0 0 0 0
|
||||
**** On Master ****
|
||||
TRUNCATE t1_nodef;
|
||||
SET SQL_LOG_BIN=0;
|
||||
INSERT INTO t1_nodef VALUES (1,2);
|
||||
INSERT INTO t1_nodef VALUES (2,4);
|
||||
SET SQL_LOG_BIN=1;
|
||||
**** On Slave ****
|
||||
INSERT INTO t1_nodef VALUES (1,2,3);
|
||||
INSERT INTO t1_nodef VALUES (2,4,6);
|
||||
**** On Master ****
|
||||
UPDATE t1_nodef SET b=2*b WHERE a=1;
|
||||
SELECT * FROM t1_nodef;
|
||||
a b
|
||||
1 4
|
||||
2 4
|
||||
**** On Slave ****
|
||||
SELECT * FROM t1_nodef;
|
||||
a b x
|
||||
1 4 3
|
||||
2 4 6
|
||||
**** On Master ****
|
||||
DELETE FROM t1_nodef WHERE a=2;
|
||||
SELECT * FROM t1_nodef;
|
||||
a b
|
||||
1 4
|
||||
**** On Slave ****
|
||||
SELECT * FROM t1_nodef;
|
||||
a b x
|
||||
1 4 3
|
||||
**** Cleanup ****
|
||||
DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef;
|
||||
DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t9;
|
||||
DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
|
|
|
@ -16,6 +16,8 @@ CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE='InnoDB';
|
|||
CREATE TABLE t4 (a INT) ENGINE='InnoDB';
|
||||
CREATE TABLE t5 (a INT, b INT, c INT) ENGINE='InnoDB';
|
||||
CREATE TABLE t6 (a INT, b INT, c INT) ENGINE='InnoDB';
|
||||
CREATE TABLE t7 (a INT NOT NULL) ENGINE='InnoDB';
|
||||
CREATE TABLE t8 (a INT NOT NULL) ENGINE='InnoDB';
|
||||
CREATE TABLE t9 (a INT) ENGINE='InnoDB';
|
||||
ALTER TABLE t1_int ADD x INT DEFAULT 42;
|
||||
ALTER TABLE t1_bit
|
||||
|
@ -28,6 +30,12 @@ ALTER TABLE t2 DROP b;
|
|||
ALTER TABLE t4 MODIFY a FLOAT;
|
||||
ALTER TABLE t5 MODIFY b FLOAT;
|
||||
ALTER TABLE t6 MODIFY c FLOAT;
|
||||
ALTER TABLE t7 ADD e1 INT, ADD e2 INT, ADD e3 INT, ADD e4 INT,
|
||||
ADD e5 INT, ADD e6 INT, ADD e7 INT, ADD e8 INT;
|
||||
ALTER TABLE t8 ADD e1 INT NOT NULL DEFAULT 0, ADD e2 INT NOT NULL DEFAULT 0,
|
||||
ADD e3 INT NOT NULL DEFAULT 0, ADD e4 INT NOT NULL DEFAULT 0,
|
||||
ADD e5 INT NOT NULL DEFAULT 0, ADD e6 INT NOT NULL DEFAULT 0,
|
||||
ADD e7 INT NOT NULL DEFAULT 0, ADD e8 INT NOT NULL DEFAULT 0;
|
||||
INSERT INTO t1_int VALUES (2, 4, 4711);
|
||||
INSERT INTO t1_char VALUES (2, 4, 'Foo is a bar');
|
||||
INSERT INTO t1_bit VALUES (2, 4, b'101', b'11100', b'01');
|
||||
|
@ -282,5 +290,92 @@ Master_SSL_Key
|
|||
Seconds_Behind_Master #
|
||||
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||
START SLAVE;
|
||||
INSERT INTO t9 VALUES (6);
|
||||
SHOW SLAVE STATUS;
|
||||
Slave_IO_State #
|
||||
Master_Host 127.0.0.1
|
||||
Master_User root
|
||||
Master_Port MASTER_PORT
|
||||
Connect_Retry 1
|
||||
Master_Log_File master-bin.000001
|
||||
Read_Master_Log_Pos #
|
||||
Relay_Log_File #
|
||||
Relay_Log_Pos #
|
||||
Relay_Master_Log_File master-bin.000001
|
||||
Slave_IO_Running Yes
|
||||
Slave_SQL_Running Yes
|
||||
Replicate_Do_DB
|
||||
Replicate_Ignore_DB
|
||||
Replicate_Do_Table
|
||||
Replicate_Ignore_Table
|
||||
Replicate_Wild_Do_Table
|
||||
Replicate_Wild_Ignore_Table
|
||||
Last_Errno 0
|
||||
Last_Error
|
||||
Skip_Counter 0
|
||||
Exec_Master_Log_Pos #
|
||||
Relay_Log_Space #
|
||||
Until_Condition None
|
||||
Until_Log_File
|
||||
Until_Log_Pos 0
|
||||
Master_SSL_Allowed No
|
||||
Master_SSL_CA_File
|
||||
Master_SSL_CA_Path
|
||||
Master_SSL_Cert
|
||||
Master_SSL_Cipher
|
||||
Master_SSL_Key
|
||||
Seconds_Behind_Master #
|
||||
INSERT INTO t7 VALUES (1),(2),(3);
|
||||
INSERT INTO t8 VALUES (1),(2),(3);
|
||||
SELECT * FROM t7;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
SELECT * FROM t8;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
SELECT * FROM t7;
|
||||
a e1 e2 e3 e4 e5 e6 e7 e8
|
||||
1 NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
2 NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
3 NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
SELECT * FROM t8;
|
||||
a e1 e2 e3 e4 e5 e6 e7 e8
|
||||
1 0 0 0 0 0 0 0 0
|
||||
2 0 0 0 0 0 0 0 0
|
||||
3 0 0 0 0 0 0 0 0
|
||||
**** On Master ****
|
||||
TRUNCATE t1_nodef;
|
||||
SET SQL_LOG_BIN=0;
|
||||
INSERT INTO t1_nodef VALUES (1,2);
|
||||
INSERT INTO t1_nodef VALUES (2,4);
|
||||
SET SQL_LOG_BIN=1;
|
||||
**** On Slave ****
|
||||
INSERT INTO t1_nodef VALUES (1,2,3);
|
||||
INSERT INTO t1_nodef VALUES (2,4,6);
|
||||
**** On Master ****
|
||||
UPDATE t1_nodef SET b=2*b WHERE a=1;
|
||||
SELECT * FROM t1_nodef;
|
||||
a b
|
||||
1 4
|
||||
2 4
|
||||
**** On Slave ****
|
||||
SELECT * FROM t1_nodef;
|
||||
a b x
|
||||
1 4 3
|
||||
2 4 6
|
||||
**** On Master ****
|
||||
DELETE FROM t1_nodef WHERE a=2;
|
||||
SELECT * FROM t1_nodef;
|
||||
a b
|
||||
1 4
|
||||
**** On Slave ****
|
||||
SELECT * FROM t1_nodef;
|
||||
a b x
|
||||
1 4 3
|
||||
**** Cleanup ****
|
||||
DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef;
|
||||
DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t9;
|
||||
DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
|
|
10
sql/field.cc
10
sql/field.cc
|
@ -1261,7 +1261,10 @@ my_size_t
|
|||
Field::do_last_null_byte() const
|
||||
{
|
||||
DBUG_ASSERT(null_ptr == NULL || (byte*) null_ptr >= table->record[0]);
|
||||
return null_ptr ? (byte*) null_ptr - table->record[0] + 1 : 0;
|
||||
if (null_ptr)
|
||||
return (byte*) null_ptr - table->record[0] + 1;
|
||||
else
|
||||
return LAST_NULL_BYTE_UNDEF;
|
||||
}
|
||||
|
||||
|
||||
|
@ -8122,7 +8125,10 @@ Field_bit::do_last_null_byte() const
|
|||
else
|
||||
result= bit_ptr;
|
||||
|
||||
return result ? (byte*) result - table->record[0] + 1 : 0;
|
||||
if (result)
|
||||
return (byte*) result - table->record[0] + 1;
|
||||
else
|
||||
return LAST_NULL_BYTE_UNDEF;
|
||||
}
|
||||
|
||||
Field *Field_bit::new_key_field(MEM_ROOT *root,
|
||||
|
|
31
sql/field.h
31
sql/field.h
|
@ -218,10 +218,24 @@ public:
|
|||
inline bool maybe_null(void) { return null_ptr != 0 || table->maybe_null; }
|
||||
inline bool real_maybe_null(void) { return null_ptr != 0; }
|
||||
|
||||
enum {
|
||||
LAST_NULL_BYTE_UNDEF= 0
|
||||
};
|
||||
|
||||
/*
|
||||
Return a pointer to the last byte of the null bytes where the
|
||||
field conceptually is placed. In the case that the field does not
|
||||
use any bits of the null bytes, a null pointer is returned.
|
||||
Find the position of the last null byte for the field.
|
||||
|
||||
SYNOPSIS
|
||||
last_null_byte()
|
||||
|
||||
DESCRIPTION
|
||||
Return a pointer to the last byte of the null bytes where the
|
||||
field conceptually is placed.
|
||||
|
||||
RETURN VALUE
|
||||
The position of the last null byte relative to the beginning of
|
||||
the record. If the field does not use any bits of the null
|
||||
bytes, the value 0 (LAST_NULL_BYTE_UNDEF) is returned.
|
||||
*/
|
||||
my_size_t last_null_byte() const {
|
||||
my_size_t bytes= do_last_null_byte();
|
||||
|
@ -392,6 +406,17 @@ public:
|
|||
friend class Item_func_group_concat;
|
||||
|
||||
private:
|
||||
/*
|
||||
Primitive for implementing last_null_byte().
|
||||
|
||||
SYNOPSIS
|
||||
do_last_null_byte()
|
||||
|
||||
DESCRIPTION
|
||||
Primitive for the implementation of the last_null_byte()
|
||||
function. This represents the inheritance interface and can be
|
||||
overridden by subclasses.
|
||||
*/
|
||||
virtual my_size_t do_last_null_byte() const;
|
||||
};
|
||||
|
||||
|
|
110
sql/log_event.cc
110
sql/log_event.cc
|
@ -5304,7 +5304,7 @@ int Rows_log_event::do_add_row_data(byte *const row_data,
|
|||
row_end Pointer to variable that will hold the value of the
|
||||
one-after-end position for the row
|
||||
master_reclength
|
||||
Pointer to variable that will hold the length of the
|
||||
Pointer to variable that will be set to the length of the
|
||||
record on the master side
|
||||
rw_set Pointer to bitmap that holds either the read_set or the
|
||||
write_set of the table
|
||||
|
@ -5317,13 +5317,22 @@ int Rows_log_event::do_add_row_data(byte *const row_data,
|
|||
|
||||
At most 'colcnt' columns are read: if the table is larger than
|
||||
that, the remaining fields are not filled in.
|
||||
|
||||
RETURN VALUE
|
||||
|
||||
Error code, or zero if no error. The following error codes can
|
||||
be returned:
|
||||
|
||||
ER_NO_DEFAULT_FOR_FIELD
|
||||
Returned if one of the fields existing on the slave but not on
|
||||
the master does not have a default value (and isn't nullable)
|
||||
*/
|
||||
static int
|
||||
unpack_row(RELAY_LOG_INFO *rli,
|
||||
TABLE *table, uint const colcnt, byte *record,
|
||||
char const *row, MY_BITMAP const *cols,
|
||||
char const **row_end, ulong *master_reclength,
|
||||
MY_BITMAP* const rw_set)
|
||||
MY_BITMAP* const rw_set, Log_event_type const event_type)
|
||||
{
|
||||
DBUG_ASSERT(record && row);
|
||||
my_ptrdiff_t const offset= record - (byte*) table->record[0];
|
||||
|
@ -5334,10 +5343,20 @@ unpack_row(RELAY_LOG_INFO *rli,
|
|||
Field **fptr= &table->field[colcnt-1];
|
||||
do
|
||||
master_null_bytes= (*fptr)->last_null_byte();
|
||||
while (master_null_bytes == 0 && fptr-- > table->field);
|
||||
while (master_null_bytes == Field::LAST_NULL_BYTE_UNDEF &&
|
||||
fptr-- > table->field);
|
||||
|
||||
if (master_null_bytes == 0)
|
||||
master_null_bytes= table->s->null_bytes;
|
||||
/*
|
||||
If master_null_bytes is LAST_NULL_BYTE_UNDEF (0) at this time,
|
||||
there were no nullable fields nor BIT fields at all in the
|
||||
columns that are common to the master and the slave. In that
|
||||
case, there is only one null byte holding the X bit.
|
||||
|
||||
OBSERVE! There might still be nullable columns following the
|
||||
common columns, so table->s->null_bytes might be greater than 1.
|
||||
*/
|
||||
if (master_null_bytes == Field::LAST_NULL_BYTE_UNDEF)
|
||||
master_null_bytes= 1;
|
||||
}
|
||||
|
||||
DBUG_ASSERT(master_null_bytes <= table->s->null_bytes);
|
||||
|
@ -5348,31 +5367,29 @@ unpack_row(RELAY_LOG_INFO *rli,
|
|||
|
||||
Field **const begin_ptr = table->field;
|
||||
Field **field_ptr;
|
||||
char const *ptr= row + master_null_bytes;
|
||||
Field **const end_ptr= begin_ptr + colcnt;
|
||||
for (field_ptr= begin_ptr ; field_ptr < end_ptr ; ++field_ptr)
|
||||
{
|
||||
char const *ptr= row + master_null_bytes;
|
||||
Field **const end_ptr= begin_ptr + colcnt;
|
||||
for (field_ptr= begin_ptr ; field_ptr < end_ptr ; ++field_ptr)
|
||||
{
|
||||
Field *const f= *field_ptr;
|
||||
Field *const f= *field_ptr;
|
||||
|
||||
if (bitmap_is_set(cols, field_ptr - begin_ptr))
|
||||
{
|
||||
ptr= f->unpack(f->ptr + offset, ptr);
|
||||
/* Field...::unpack() cannot return 0 */
|
||||
DBUG_ASSERT(ptr != NULL);
|
||||
}
|
||||
else
|
||||
bitmap_clear_bit(rw_set, field_ptr - begin_ptr);
|
||||
}
|
||||
|
||||
*row_end = ptr;
|
||||
if (master_reclength)
|
||||
if (bitmap_is_set(cols, field_ptr - begin_ptr))
|
||||
{
|
||||
if (*field_ptr)
|
||||
*master_reclength = (*field_ptr)->ptr - (char*) table->record[0];
|
||||
else
|
||||
*master_reclength = table->s->reclength;
|
||||
ptr= f->unpack(f->ptr + offset, ptr);
|
||||
/* Field...::unpack() cannot return 0 */
|
||||
DBUG_ASSERT(ptr != NULL);
|
||||
}
|
||||
else
|
||||
bitmap_clear_bit(rw_set, field_ptr - begin_ptr);
|
||||
}
|
||||
|
||||
*row_end = ptr;
|
||||
if (master_reclength)
|
||||
{
|
||||
if (*field_ptr)
|
||||
*master_reclength = (*field_ptr)->ptr - (char*) table->record[0];
|
||||
else
|
||||
*master_reclength = table->s->reclength;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5381,16 +5398,26 @@ unpack_row(RELAY_LOG_INFO *rli,
|
|||
it was not there already. We iterate over all remaining columns,
|
||||
even if there were an error, to get as many error messages as
|
||||
possible. We are still able to return a pointer to the next row,
|
||||
so wedo that.
|
||||
so redo that.
|
||||
|
||||
This generation of error messages is only relevant when inserting
|
||||
new rows.
|
||||
*/
|
||||
for ( ; *field_ptr ; ++field_ptr)
|
||||
{
|
||||
if ((*field_ptr)->flags & (NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG))
|
||||
uint32 const mask= NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG;
|
||||
|
||||
DBUG_PRINT("debug", ("flags = 0x%x, mask = 0x%x, flags & mask = 0x%x",
|
||||
(*field_ptr)->flags, mask,
|
||||
(*field_ptr)->flags & mask));
|
||||
|
||||
if (event_type == WRITE_ROWS_EVENT &&
|
||||
((*field_ptr)->flags & mask) == mask)
|
||||
{
|
||||
slave_print_msg(ERROR_LEVEL, rli, ER_NO_DEFAULT_FOR_FIELD,
|
||||
slave_print_msg(ERROR_LEVEL, rli, ER_NO_DEFAULT_FOR_FIELD,
|
||||
"Field `%s` of table `%s`.`%s` "
|
||||
"has no default value and cannot be NULL",
|
||||
(*field_ptr)->field_name, table->s->db.str,
|
||||
(*field_ptr)->field_name, table->s->db.str,
|
||||
table->s->table_name.str);
|
||||
error = ER_NO_DEFAULT_FOR_FIELD;
|
||||
}
|
||||
|
@ -5562,8 +5589,8 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
|
|||
{
|
||||
char const *row_end= NULL;
|
||||
if ((error= do_prepare_row(thd, rli, table, row_start, &row_end)))
|
||||
break; // We should to the after-row operation even in the
|
||||
// case of error
|
||||
break; // We should perform the after-row operation even in
|
||||
// the case of error
|
||||
|
||||
DBUG_ASSERT(row_end != NULL); // cannot happen
|
||||
DBUG_ASSERT(row_end <= (const char*)m_rows_end);
|
||||
|
@ -6224,7 +6251,7 @@ int Write_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
|
|||
error= unpack_row(rli,
|
||||
table, m_width, table->record[0],
|
||||
row_start, &m_cols, row_end, &m_master_reclength,
|
||||
table->write_set);
|
||||
table->write_set, WRITE_ROWS_EVENT);
|
||||
bitmap_copy(table->read_set, table->write_set);
|
||||
return error;
|
||||
}
|
||||
|
@ -6285,10 +6312,17 @@ copy_extra_record_fields(TABLE *table,
|
|||
my_size_t master_reclength,
|
||||
my_ptrdiff_t master_fields)
|
||||
{
|
||||
DBUG_PRINT("info", ("Copying to %p from field %d at offset %u to field %d at offset %u",
|
||||
table->record[0],
|
||||
DBUG_PRINT("info", ("Copying to %p "
|
||||
"from field %d at offset %u "
|
||||
"to field %d at offset %u",
|
||||
table->record[0],
|
||||
master_fields, master_reclength,
|
||||
table->s->fields, table->s->reclength));
|
||||
/*
|
||||
Copying the extra fields of the slave that does not exist on
|
||||
master into record[0] (which are basically the default values).
|
||||
*/
|
||||
DBUG_ASSERT(master_reclength <= table->s->reclength);
|
||||
if (master_reclength < table->s->reclength)
|
||||
bmove_align(table->record[0] + master_reclength,
|
||||
table->record[1] + master_reclength,
|
||||
|
@ -6771,7 +6805,7 @@ int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
|
|||
error= unpack_row(rli,
|
||||
table, m_width, table->record[0],
|
||||
row_start, &m_cols, row_end, &m_master_reclength,
|
||||
table->read_set);
|
||||
table->read_set, DELETE_ROWS_EVENT);
|
||||
/*
|
||||
If we will access rows using the random access method, m_key will
|
||||
be set to NULL, so we do not need to make a key copy in that case.
|
||||
|
@ -6914,13 +6948,13 @@ int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
|
|||
error= unpack_row(rli,
|
||||
table, m_width, table->record[0],
|
||||
row_start, &m_cols, row_end, &m_master_reclength,
|
||||
table->read_set);
|
||||
table->read_set, UPDATE_ROWS_EVENT);
|
||||
row_start = *row_end;
|
||||
/* m_after_image is the after image for the update */
|
||||
error= unpack_row(rli,
|
||||
table, m_width, m_after_image,
|
||||
row_start, &m_cols, row_end, &m_master_reclength,
|
||||
table->write_set);
|
||||
table->write_set, UPDATE_ROWS_EVENT);
|
||||
|
||||
/*
|
||||
If we will access rows using the random access method, m_key will
|
||||
|
|
|
@ -107,11 +107,6 @@ field_length_from_packed(enum_field_types const field_type,
|
|||
/*
|
||||
Is the definition compatible with a table?
|
||||
|
||||
Compare the definition with a table to see if it is compatible with
|
||||
it. A table definition is compatible with a table if
|
||||
- the columns types of the table definition is a (not necessarily
|
||||
proper) prefix of the column type of the table, or
|
||||
- the other way around
|
||||
*/
|
||||
int
|
||||
table_def::compatible_with(RELAY_LOG_INFO *rli, TABLE *table)
|
||||
|
|
|
@ -32,29 +32,95 @@ field_length_from_packed(enum_field_types const field_type,
|
|||
|
||||
RESPONSIBILITIES
|
||||
|
||||
- Extract table definition data from the table map event
|
||||
- Extract and decode table definition data from the table map event
|
||||
- Check if table definition in table map is compatible with table
|
||||
definition on slave
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Currently, the only field type data available is an array of the
|
||||
type operators that are present in the table map event.
|
||||
|
||||
TODO
|
||||
|
||||
Add type operands to this structure to allow detection of
|
||||
difference between, e.g., BIT(5) and BIT(10).
|
||||
*/
|
||||
|
||||
class table_def
|
||||
{
|
||||
public:
|
||||
/*
|
||||
Convenience declaration of the type of the field type data in a
|
||||
table map event.
|
||||
*/
|
||||
typedef unsigned char field_type;
|
||||
|
||||
table_def(field_type *t, my_size_t s)
|
||||
: m_type(t), m_size(s)
|
||||
/*
|
||||
Constructor.
|
||||
|
||||
SYNOPSIS
|
||||
table_def()
|
||||
types Array of types
|
||||
size Number of elements in array 'types'
|
||||
*/
|
||||
table_def(field_type *types, my_size_t size)
|
||||
: m_type(types), m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
Return the number of fields there is type data for.
|
||||
|
||||
SYNOPSIS
|
||||
size()
|
||||
|
||||
RETURN VALUE
|
||||
The number of fields that there is type data for.
|
||||
*/
|
||||
my_size_t size() const { return m_size; }
|
||||
|
||||
/*
|
||||
Return a representation of the type data for one field.
|
||||
|
||||
SYNOPSIS
|
||||
type()
|
||||
i Field index to return data for
|
||||
|
||||
RETURN VALUE
|
||||
|
||||
Will return a representation of the type data for field
|
||||
'i'. Currently, only the type identifier is returned.
|
||||
*/
|
||||
field_type type(my_ptrdiff_t i) const { return m_type[i]; }
|
||||
|
||||
/*
|
||||
Decide if the table definition is compatible with a table.
|
||||
|
||||
SYNOPSIS
|
||||
compatible_with()
|
||||
rli Pointer to relay log info
|
||||
table Pointer to table to compare with.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Compare the definition with a table to see if it is compatible
|
||||
with it. A table definition is compatible with a table if:
|
||||
|
||||
- the columns types of the table definition is a (not
|
||||
necessarily proper) prefix of the column type of the table, or
|
||||
|
||||
- the other way around
|
||||
|
||||
RETURN VALUE
|
||||
1 if the table definition is not compatible with 'table'
|
||||
0 if the table definition is compatible with 'table'
|
||||
*/
|
||||
int compatible_with(RELAY_LOG_INFO *rli, TABLE *table) const;
|
||||
|
||||
private:
|
||||
my_size_t m_size;
|
||||
field_type *m_type;
|
||||
my_size_t m_size; // Number of elements in the types array
|
||||
field_type *m_type; // Array of type descriptors
|
||||
};
|
||||
|
||||
#endif /* RPL_UTILITY_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue