mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 11:01:52 +01:00
Merge quant.(none):/ext/mysql/bk/mysql-5.1-bug21842-5.1.22
into quant.(none):/ext/mysql/bk/mysql-5.1-bug21842-5.1.22-merge
This commit is contained in:
commit
95bece5d11
13 changed files with 3202 additions and 573 deletions
119
mysql-test/extra/rpl_tests/rpl_ndb_2multi_basic.test
Normal file
119
mysql-test/extra/rpl_tests/rpl_ndb_2multi_basic.test
Normal file
|
@ -0,0 +1,119 @@
|
|||
#######################################
|
||||
# Author: Rafal Somla #
|
||||
# Date: 2006-08-20 #
|
||||
# Purpose: Test replication of basic #
|
||||
# table operations in various setups #
|
||||
# #
|
||||
# Based on rpl_ndb_2multi_eng.test by #
|
||||
# JBM #
|
||||
#######################################
|
||||
|
||||
--echo --- Doing pre test cleanup ---
|
||||
|
||||
connection master;
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
--enable_query_log
|
||||
|
||||
#################################################
|
||||
--echo --- Create Table Section ---
|
||||
|
||||
CREATE TABLE t1 (id MEDIUMINT NOT NULL,
|
||||
b1 INT,
|
||||
vc VARCHAR(255),
|
||||
bc CHAR(255),
|
||||
d DECIMAL(10,4) DEFAULT 0,
|
||||
f FLOAT DEFAULT 0,
|
||||
total BIGINT UNSIGNED,
|
||||
y YEAR,
|
||||
t DATE,
|
||||
PRIMARY KEY(id));
|
||||
|
||||
--echo --- Show table on master ---
|
||||
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--echo --- Show table on slave ---
|
||||
|
||||
sync_slave_with_master;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--source include/rpl_multi_engine2.inc
|
||||
|
||||
#################################################
|
||||
# Okay lets see how it holds up to table changes
|
||||
--echo --- Check that simple Alter statements are replicated correctly --
|
||||
|
||||
ALTER TABLE t1 DROP PRIMARY KEY;
|
||||
# note: table with no PK can't contain blobs if it is to be replicated.
|
||||
ALTER TABLE t1 MODIFY vc char(32);
|
||||
|
||||
--echo --- Show the new improved table on the master ---
|
||||
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--echo --- Make sure that our tables on slave are still same engine ---
|
||||
--echo --- and that the alter statements replicated correctly ---
|
||||
|
||||
sync_slave_with_master;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--source include/rpl_multi_engine2.inc
|
||||
|
||||
#################################################
|
||||
--echo --- Check that replication works when slave has more columns than master
|
||||
connection master;
|
||||
ALTER TABLE t1 ADD PRIMARY KEY(id,total);
|
||||
ALTER TABLE t1 MODIFY vc TEXT;
|
||||
|
||||
INSERT INTO t1 VALUES(3,1,'Testing MySQL databases is a cool ',
|
||||
'Must make it bug free for the customer',
|
||||
654321.4321,15.21,0,1965,"1905-11-14");
|
||||
INSERT INTO t1 VALUES(20,1,'Testing MySQL databases is a cool ',
|
||||
'Must make it bug free for the customer',
|
||||
654321.4321,15.21,0,1965,"1965-11-14");
|
||||
INSERT INTO t1 VALUES(50,1,'Testing MySQL databases is a cool ',
|
||||
'Must make it bug free for the customer',
|
||||
654321.4321,15.21,0,1965,"1985-11-14");
|
||||
|
||||
--echo --- Add columns on slave ---
|
||||
--sync_slave_with_master
|
||||
ALTER TABLE t1 ADD (u int, v char(16) default 'default');
|
||||
UPDATE t1 SET u=7 WHERE id < 50;
|
||||
UPDATE t1 SET v='explicit' WHERE id >10;
|
||||
|
||||
--echo --- Show changed table on slave ---
|
||||
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT *
|
||||
FROM t1
|
||||
ORDER BY id;
|
||||
|
||||
--source include/rpl_multi_engine2.inc
|
||||
TRUNCATE TABLE t1;
|
||||
|
||||
#################################################
|
||||
--echo --- Check that replication works when master has more columns than slave
|
||||
connection master;
|
||||
|
||||
--echo --- Remove columns on slave ---
|
||||
--sync_slave_with_master
|
||||
ALTER TABLE t1 DROP COLUMN v;
|
||||
ALTER TABLE t1 DROP COLUMN u;
|
||||
ALTER TABLE t1 DROP COLUMN t;
|
||||
ALTER TABLE t1 DROP COLUMN y;
|
||||
|
||||
--echo --- Show changed table on slave ---
|
||||
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--source include/rpl_multi_engine2.inc
|
||||
TRUNCATE TABLE t1;
|
||||
|
||||
#################################################
|
||||
--echo --- Do Cleanup --
|
||||
connection master;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
|
||||
sync_slave_with_master;
|
||||
connection master;
|
91
mysql-test/include/rpl_multi_engine2.inc
Normal file
91
mysql-test/include/rpl_multi_engine2.inc
Normal file
|
@ -0,0 +1,91 @@
|
|||
#############################################################
|
||||
# Author: Rafal
|
||||
# Date: 2007-08-20
|
||||
# based on rpl_multi_engine3.inc
|
||||
#############################################################
|
||||
|
||||
connection slave;
|
||||
STOP SLAVE;
|
||||
RESET SLAVE;
|
||||
|
||||
connection master;
|
||||
RESET MASTER;
|
||||
|
||||
connection slave;
|
||||
START SLAVE;
|
||||
|
||||
--echo --- Populate t1 with data ---
|
||||
connection master;
|
||||
--disable_query_log
|
||||
INSERT INTO t1 VALUES(42,1,'Testing MySQL databases is a cool ',
|
||||
'Must make it bug free for the customer',
|
||||
654321.4321,15.21,0,1965,"1905-11-14");
|
||||
INSERT INTO t1 VALUES(2,1,'Testing MySQL databases is a cool ',
|
||||
'Must make it bug free for the customer',
|
||||
654321.4321,15.21,0,1965,"1965-11-14");
|
||||
INSERT INTO t1 VALUES(4,1,'Testing MySQL databases is a cool ',
|
||||
'Must make it bug free for the customer',
|
||||
654321.4321,15.21,0,1965,"1985-11-14");
|
||||
INSERT INTO t1 VALUES(142,1,'Testing MySQL databases is a cool ',
|
||||
'Must make it bug free for the customer',
|
||||
654321.4321,15.21,0,1965,"1995-11-14");
|
||||
INSERT INTO t1 VALUES(412,1,'Testing MySQL databases is a cool ',
|
||||
'Must make it bug free for the customer',
|
||||
654321.4321,15.21,0,1965,"2005-11-14");
|
||||
--enable_query_log
|
||||
|
||||
--echo --- Select from t1 on master ---
|
||||
select *
|
||||
from t1
|
||||
order by id;
|
||||
|
||||
sync_slave_with_master;
|
||||
--echo --- Select from t1 on slave ---
|
||||
select *
|
||||
from t1
|
||||
order by id;
|
||||
|
||||
--echo --- Perform basic operation on master ---
|
||||
--echo --- and ensure replicated correctly ---
|
||||
connection master;
|
||||
|
||||
--echo --- Update t1 on master --
|
||||
UPDATE t1 SET b1 = 0, bc='updated', t="2006-02-22"
|
||||
WHERE id < 100
|
||||
ORDER BY id;
|
||||
|
||||
--echo --- Check the update on master ---
|
||||
SELECT *
|
||||
FROM t1
|
||||
WHERE id < 100
|
||||
ORDER BY id;
|
||||
|
||||
# Must give injector thread a little time to get update
|
||||
# into the binlog other wise we will miss the update.
|
||||
|
||||
sync_slave_with_master;
|
||||
--echo --- Check Update on slave ---
|
||||
SELECT *
|
||||
FROM t1
|
||||
WHERE id < 100
|
||||
ORDER BY id;
|
||||
|
||||
connection master;
|
||||
--echo --- Remove a record from t1 on master ---
|
||||
# Note: there is an error in replication of Delete_row
|
||||
# from NDB to MyISAM (BUG#28538). However, if there is
|
||||
# only one row in Delete_row event then it works fine,
|
||||
# as this test demonstrates.
|
||||
DELETE FROM t1 WHERE id = 412;
|
||||
|
||||
--echo --- Show current count on master for t1 ---
|
||||
SELECT COUNT(*) FROM t1;
|
||||
|
||||
sync_slave_with_master;
|
||||
--echo --- Show current count on slave for t1 ---
|
||||
SELECT COUNT(*) FROM t1;
|
||||
|
||||
connection master;
|
||||
TRUNCATE TABLE t1;
|
||||
sync_slave_with_master;
|
||||
connection master;
|
1189
mysql-test/suite/rpl_ndb/r/rpl_ndb_2other.result
Normal file
1189
mysql-test/suite/rpl_ndb/r/rpl_ndb_2other.result
Normal file
File diff suppressed because it is too large
Load diff
1
mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt
Normal file
1
mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt
Normal file
|
@ -0,0 +1 @@
|
|||
--innodb --log-slave-updates=0
|
35
mysql-test/suite/rpl_ndb/t/rpl_ndb_2other.test
Normal file
35
mysql-test/suite/rpl_ndb/t/rpl_ndb_2other.test
Normal file
|
@ -0,0 +1,35 @@
|
|||
#############################################################
|
||||
# Author: Rafal Somla
|
||||
# Date: 2006-08-20
|
||||
# Purpose: Trying to test ability to replicate from cluster
|
||||
# to other engines (innodb, myisam).
|
||||
##############################################################
|
||||
--source include/have_ndb.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_binlog_format_mixed_or_row.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
# On master use NDB as storage engine.
|
||||
connection master;
|
||||
SET storage_engine=ndb;
|
||||
|
||||
--echo
|
||||
--echo === NDB -> MYISAM ===
|
||||
--echo
|
||||
connection slave;
|
||||
SET storage_engine=myisam;
|
||||
--source extra/rpl_tests/rpl_ndb_2multi_basic.test
|
||||
|
||||
--echo
|
||||
--echo === NDB -> INNODB ===
|
||||
--echo
|
||||
connection slave;
|
||||
SET storage_engine=innodb;
|
||||
--source extra/rpl_tests/rpl_ndb_2multi_basic.test
|
||||
|
||||
--echo
|
||||
--echo === NDB -> NDB ===
|
||||
--echo
|
||||
connection slave;
|
||||
SET storage_engine=ndb;
|
||||
--source extra/rpl_tests/rpl_ndb_2multi_basic.test
|
856
sql/log_event.cc
856
sql/log_event.cc
File diff suppressed because it is too large
Load diff
107
sql/log_event.h
107
sql/log_event.h
|
@ -23,6 +23,10 @@
|
|||
|
||||
#include <my_bitmap.h>
|
||||
#include "rpl_constants.h"
|
||||
#ifndef MYSQL_CLIENT
|
||||
#include "rpl_record.h"
|
||||
#include "rpl_reporting.h"
|
||||
#endif
|
||||
|
||||
#define LOG_READ_EOF -1
|
||||
#define LOG_READ_BOGUS -2
|
||||
|
@ -2180,7 +2184,13 @@ public:
|
|||
NO_FOREIGN_KEY_CHECKS_F = (1U << 1),
|
||||
|
||||
/* Value of the OPTION_RELAXED_UNIQUE_CHECKS flag in thd->options */
|
||||
RELAXED_UNIQUE_CHECKS_F = (1U << 2)
|
||||
RELAXED_UNIQUE_CHECKS_F = (1U << 2),
|
||||
|
||||
/**
|
||||
Indicates that rows in this event are complete, that is contain
|
||||
values for all columns of the table.
|
||||
*/
|
||||
COMPLETE_ROWS_F = (1U << 3)
|
||||
};
|
||||
|
||||
typedef uint16 flag_set;
|
||||
|
@ -2284,7 +2294,26 @@ protected:
|
|||
uchar *m_rows_cur; /* One-after the end of the data */
|
||||
uchar *m_rows_end; /* One-after the end of the allocated space */
|
||||
|
||||
const uchar *m_curr_row; /* Start of the row being processed */
|
||||
const uchar *m_curr_row_end; /* One-after the end of the current row */
|
||||
|
||||
flag_set m_flags; /* Flags for row-level events */
|
||||
uchar *m_key; /* Buffer to keep key value during searches */
|
||||
|
||||
/* helper functions */
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
int find_row(const RELAY_LOG_INFO *const);
|
||||
int write_row(const RELAY_LOG_INFO *const, const bool);
|
||||
|
||||
// Unpack the current row into m_table->record[0]
|
||||
int unpack_current_row(const RELAY_LOG_INFO *const rli)
|
||||
{
|
||||
DBUG_ASSERT(m_table);
|
||||
return ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols,
|
||||
&m_curr_row_end, &m_master_reclength);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
|
@ -2309,7 +2338,8 @@ private:
|
|||
The member function will return 0 if all went OK, or a non-zero
|
||||
error code otherwise.
|
||||
*/
|
||||
virtual int do_before_row_operations(TABLE *table) = 0;
|
||||
virtual
|
||||
int do_before_row_operations(const Slave_reporting_capability *const log) = 0;
|
||||
|
||||
/*
|
||||
Primitive to clean up after a sequence of row executions.
|
||||
|
@ -2319,45 +2349,33 @@ private:
|
|||
After doing a sequence of do_prepare_row() and do_exec_row(),
|
||||
this member function should be called to clean up and release
|
||||
any allocated buffers.
|
||||
|
||||
The error argument, if non-zero, indicates an error which happened during
|
||||
row processing before this function was called. In this case, even if
|
||||
function is successful, it should return the error code given in the argument.
|
||||
*/
|
||||
virtual int do_after_row_operations(TABLE *table, int error) = 0;
|
||||
|
||||
/*
|
||||
Primitive to prepare for handling one row in a row-level event.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
The member function prepares for execution of operations needed for one
|
||||
row in a row-level event by reading up data from the buffer containing
|
||||
the row. No specific interpretation of the data is normally done here,
|
||||
since SQL thread specific data is not available: that data is made
|
||||
available for the do_exec function.
|
||||
|
||||
A pointer to the start of the next row, or NULL if the preparation
|
||||
failed. Currently, preparation cannot fail, but don't rely on this
|
||||
behavior.
|
||||
|
||||
RETURN VALUE
|
||||
Error code, if something went wrong, 0 otherwise.
|
||||
*/
|
||||
virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
|
||||
uchar const *row_start,
|
||||
uchar const **row_end) = 0;
|
||||
virtual
|
||||
int do_after_row_operations(const Slave_reporting_capability *const log,
|
||||
int error) = 0;
|
||||
|
||||
/*
|
||||
Primitive to do the actual execution necessary for a row.
|
||||
|
||||
DESCRIPTION
|
||||
The member function will do the actual execution needed to handle a row.
|
||||
The row is located at m_curr_row. When the function returns,
|
||||
m_curr_row_end should point at the next row (one byte after the end
|
||||
of the current row).
|
||||
|
||||
RETURN VALUE
|
||||
0 if execution succeeded, 1 if execution failed.
|
||||
|
||||
*/
|
||||
virtual int do_exec_row(TABLE *table) = 0;
|
||||
virtual int do_exec_row(const RELAY_LOG_INFO *const rli) = 0;
|
||||
#endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
|
||||
};
|
||||
|
||||
friend class Old_rows_log_event;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
|
@ -2407,14 +2425,9 @@ private:
|
|||
#endif
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
uchar *m_memory;
|
||||
uchar *m_after_image;
|
||||
|
||||
virtual int do_before_row_operations(TABLE *table);
|
||||
virtual int do_after_row_operations(TABLE *table, int error);
|
||||
virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
|
||||
uchar const *row_start, uchar const **row_end);
|
||||
virtual int do_exec_row(TABLE *table);
|
||||
virtual int do_before_row_operations(const Slave_reporting_capability *const);
|
||||
virtual int do_after_row_operations(const Slave_reporting_capability *const,int);
|
||||
virtual int do_exec_row(const RELAY_LOG_INFO *const);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -2486,15 +2499,9 @@ protected:
|
|||
#endif
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
uchar *m_memory;
|
||||
uchar *m_key;
|
||||
uchar *m_after_image;
|
||||
|
||||
virtual int do_before_row_operations(TABLE *table);
|
||||
virtual int do_after_row_operations(TABLE *table, int error);
|
||||
virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
|
||||
uchar const *row_start, uchar const **row_end);
|
||||
virtual int do_exec_row(TABLE *table);
|
||||
virtual int do_before_row_operations(const Slave_reporting_capability *const);
|
||||
virtual int do_after_row_operations(const Slave_reporting_capability *const,int);
|
||||
virtual int do_exec_row(const RELAY_LOG_INFO *const);
|
||||
#endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
|
||||
};
|
||||
|
||||
|
@ -2557,15 +2564,9 @@ protected:
|
|||
#endif
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
uchar *m_memory;
|
||||
uchar *m_key;
|
||||
uchar *m_after_image;
|
||||
|
||||
virtual int do_before_row_operations(TABLE *table);
|
||||
virtual int do_after_row_operations(TABLE *table, int error);
|
||||
virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
|
||||
uchar const *row_start, uchar const **row_end);
|
||||
virtual int do_exec_row(TABLE *table);
|
||||
virtual int do_before_row_operations(const Slave_reporting_capability *const);
|
||||
virtual int do_after_row_operations(const Slave_reporting_capability *const,int);
|
||||
virtual int do_exec_row(const RELAY_LOG_INFO *const);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
1115
sql/log_event_old.cc
1115
sql/log_event_old.cc
File diff suppressed because it is too large
Load diff
|
@ -20,9 +20,90 @@
|
|||
Need to include this file at the proper position of log_event.h
|
||||
*/
|
||||
|
||||
|
||||
class Write_rows_log_event_old : public Write_rows_log_event
|
||||
|
||||
class Old_rows_log_event
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~Old_rows_log_event() {}
|
||||
|
||||
protected:
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
|
||||
int do_apply_event(Rows_log_event*,const RELAY_LOG_INFO*);
|
||||
|
||||
/*
|
||||
Primitive to prepare for a sequence of row executions.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Before doing a sequence of do_prepare_row() and do_exec_row()
|
||||
calls, this member function should be called to prepare for the
|
||||
entire sequence. Typically, this member function will allocate
|
||||
space for any buffers that are needed for the two member
|
||||
functions mentioned above.
|
||||
|
||||
RETURN VALUE
|
||||
|
||||
The member function will return 0 if all went OK, or a non-zero
|
||||
error code otherwise.
|
||||
*/
|
||||
virtual int do_before_row_operations(TABLE *table) = 0;
|
||||
|
||||
/*
|
||||
Primitive to clean up after a sequence of row executions.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
After doing a sequence of do_prepare_row() and do_exec_row(),
|
||||
this member function should be called to clean up and release
|
||||
any allocated buffers.
|
||||
*/
|
||||
virtual int do_after_row_operations(TABLE *table, int error) = 0;
|
||||
|
||||
/*
|
||||
Primitive to prepare for handling one row in a row-level event.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
The member function prepares for execution of operations needed for one
|
||||
row in a row-level event by reading up data from the buffer containing
|
||||
the row. No specific interpretation of the data is normally done here,
|
||||
since SQL thread specific data is not available: that data is made
|
||||
available for the do_exec function.
|
||||
|
||||
A pointer to the start of the next row, or NULL if the preparation
|
||||
failed. Currently, preparation cannot fail, but don't rely on this
|
||||
behavior.
|
||||
|
||||
RETURN VALUE
|
||||
Error code, if something went wrong, 0 otherwise.
|
||||
*/
|
||||
virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
|
||||
uchar const *row_start,
|
||||
uchar const **row_end) = 0;
|
||||
|
||||
/*
|
||||
Primitive to do the actual execution necessary for a row.
|
||||
|
||||
DESCRIPTION
|
||||
The member function will do the actual execution needed to handle a row.
|
||||
|
||||
RETURN VALUE
|
||||
0 if execution succeeded, 1 if execution failed.
|
||||
|
||||
*/
|
||||
virtual int do_exec_row(TABLE *table) = 0;
|
||||
|
||||
#endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
|
||||
};
|
||||
|
||||
|
||||
class Write_rows_log_event_old
|
||||
: public Write_rows_log_event, public Old_rows_log_event
|
||||
{
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
|
@ -49,14 +130,26 @@ private:
|
|||
virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; }
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
// use old definition of do_apply_event()
|
||||
virtual int do_apply_event(const RELAY_LOG_INFO *rli)
|
||||
{ return Old_rows_log_event::do_apply_event(this,rli); }
|
||||
|
||||
// primitives for old version of do_apply_event()
|
||||
virtual int do_before_row_operations(TABLE *table);
|
||||
virtual int do_after_row_operations(TABLE *table, int error);
|
||||
virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
|
||||
uchar const *row_start, uchar const **row_end);
|
||||
virtual int do_exec_row(TABLE *table);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class Update_rows_log_event_old : public Update_rows_log_event
|
||||
class Update_rows_log_event_old
|
||||
: public Update_rows_log_event, public Old_rows_log_event
|
||||
{
|
||||
uchar *m_after_image, *m_memory;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
|
@ -67,14 +160,16 @@ public:
|
|||
#if !defined(MYSQL_CLIENT)
|
||||
Update_rows_log_event_old(THD *thd, TABLE *table, ulong table_id,
|
||||
MY_BITMAP const *cols, bool is_transactional)
|
||||
: Update_rows_log_event(thd, table, table_id, cols, is_transactional)
|
||||
: Update_rows_log_event(thd, table, table_id, cols, is_transactional),
|
||||
m_after_image(NULL), m_memory(NULL)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_REPLICATION)
|
||||
Update_rows_log_event_old(const char *buf, uint event_len,
|
||||
const Format_description_log_event *descr)
|
||||
: Update_rows_log_event(buf, event_len, descr)
|
||||
: Update_rows_log_event(buf, event_len, descr),
|
||||
m_after_image(NULL), m_memory(NULL)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
@ -83,14 +178,25 @@ private:
|
|||
virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; }
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
// use old definition of do_apply_event()
|
||||
virtual int do_apply_event(const RELAY_LOG_INFO *rli)
|
||||
{ return Old_rows_log_event::do_apply_event(this,rli); }
|
||||
|
||||
// primitives for old version of do_apply_event()
|
||||
virtual int do_before_row_operations(TABLE *table);
|
||||
virtual int do_after_row_operations(TABLE *table, int error);
|
||||
virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
|
||||
uchar const *row_start, uchar const **row_end);
|
||||
virtual int do_exec_row(TABLE *table);
|
||||
#endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
|
||||
};
|
||||
|
||||
|
||||
class Delete_rows_log_event_old : public Delete_rows_log_event
|
||||
class Delete_rows_log_event_old
|
||||
: public Delete_rows_log_event, public Old_rows_log_event
|
||||
{
|
||||
uchar *m_after_image, *m_memory;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
|
@ -101,14 +207,16 @@ public:
|
|||
#if !defined(MYSQL_CLIENT)
|
||||
Delete_rows_log_event_old(THD *thd, TABLE *table, ulong table_id,
|
||||
MY_BITMAP const *cols, bool is_transactional)
|
||||
: Delete_rows_log_event(thd, table, table_id, cols, is_transactional)
|
||||
: Delete_rows_log_event(thd, table, table_id, cols, is_transactional),
|
||||
m_after_image(NULL), m_memory(NULL)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_REPLICATION)
|
||||
Delete_rows_log_event_old(const char *buf, uint event_len,
|
||||
const Format_description_log_event *descr)
|
||||
: Delete_rows_log_event(buf, event_len, descr)
|
||||
: Delete_rows_log_event(buf, event_len, descr),
|
||||
m_after_image(NULL), m_memory(NULL)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
@ -117,8 +225,16 @@ private:
|
|||
virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; }
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
// use old definition of do_apply_event()
|
||||
virtual int do_apply_event(const RELAY_LOG_INFO *rli)
|
||||
{ return Old_rows_log_event::do_apply_event(this,rli); }
|
||||
|
||||
// primitives for old version of do_apply_event()
|
||||
virtual int do_before_row_operations(TABLE *table);
|
||||
virtual int do_after_row_operations(TABLE *table, int error);
|
||||
virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
|
||||
uchar const *row_start, uchar const **row_end);
|
||||
virtual int do_exec_row(TABLE *table);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -157,9 +157,8 @@ pack_row(TABLE *table, MY_BITMAP const* cols,
|
|||
the various member functions of Field and subclasses expect to
|
||||
write.
|
||||
|
||||
The row is assumed to only consist of the fields for which the
|
||||
bitset represented by @c arr and @c bits; the other parts of the
|
||||
record are left alone.
|
||||
The row is assumed to only consist of the fields for which the corresponding
|
||||
bit in bitset @c cols is set; the other parts of the record are left alone.
|
||||
|
||||
At most @c colcnt columns are read: if the table is larger than
|
||||
that, the remaining fields are not filled in.
|
||||
|
@ -169,15 +168,12 @@ pack_row(TABLE *table, MY_BITMAP const* cols,
|
|||
@param colcnt Number of columns to read from record
|
||||
@param row_data
|
||||
Packed row data
|
||||
@param cols Pointer to columns data to fill in
|
||||
@param cols Pointer to bitset describing columns to fill in
|
||||
@param row_end Pointer to variable that will hold the value of the
|
||||
one-after-end position for the row
|
||||
@param master_reclength
|
||||
Pointer to variable that will be set to the length of the
|
||||
record on the master side
|
||||
@param rw_set Pointer to bitmap that holds either the read_set or the
|
||||
write_set of the table
|
||||
|
||||
|
||||
@retval 0 No error
|
||||
|
||||
|
@ -191,8 +187,7 @@ int
|
|||
unpack_row(RELAY_LOG_INFO const *rli,
|
||||
TABLE *table, uint const colcnt,
|
||||
uchar const *const row_data, MY_BITMAP const *cols,
|
||||
uchar const **const row_end, ulong *const master_reclength,
|
||||
MY_BITMAP* const rw_set, Log_event_type const event_type)
|
||||
uchar const **const row_end, ulong *const master_reclength)
|
||||
{
|
||||
DBUG_ENTER("unpack_row");
|
||||
DBUG_ASSERT(row_data);
|
||||
|
@ -202,10 +197,6 @@ unpack_row(RELAY_LOG_INFO const *rli,
|
|||
uchar const *null_ptr= row_data;
|
||||
uchar const *pack_ptr= row_data + master_null_byte_count;
|
||||
|
||||
bitmap_clear_all(rw_set);
|
||||
|
||||
empty_record(table);
|
||||
|
||||
Field **const begin_ptr = table->field;
|
||||
Field **field_ptr;
|
||||
Field **const end_ptr= begin_ptr + colcnt;
|
||||
|
@ -265,7 +256,6 @@ unpack_row(RELAY_LOG_INFO const *rli,
|
|||
#endif
|
||||
}
|
||||
|
||||
bitmap_set_bit(rw_set, f->field_index);
|
||||
null_mask <<= 1;
|
||||
}
|
||||
i++;
|
||||
|
@ -307,30 +297,58 @@ unpack_row(RELAY_LOG_INFO const *rli,
|
|||
else
|
||||
*master_reclength = table->s->reclength;
|
||||
}
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
/*
|
||||
Set properties for remaining columns, if there are any. We let the
|
||||
corresponding bit in the write_set be set, to write the value if
|
||||
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 redo that.
|
||||
/**
|
||||
Fills @c table->record[0] with default values.
|
||||
|
||||
This generation of error messages is only relevant when inserting
|
||||
new rows.
|
||||
*/
|
||||
for ( ; *field_ptr ; ++field_ptr)
|
||||
First @c empty_record() is called and then, additionally, fields are
|
||||
initialized explicitly with a call to @c set_default().
|
||||
|
||||
For optimization reasons, the explicit initialization can be skipped for
|
||||
first @c skip fields. This is useful if later we are going to fill these
|
||||
fields from other source (e.g. from a Rows replication event).
|
||||
|
||||
If @c check is true, fields are explicitly initialized only if they have
|
||||
default value or can be NULL. Otherwise error is reported.
|
||||
|
||||
@param log Used to report errors.
|
||||
@param table Table whose record[0] buffer is prepared.
|
||||
@param skip Number of columns for which default value initialization
|
||||
should be skipped.
|
||||
@param check Indicates if errors should be checked when setting default
|
||||
values.
|
||||
|
||||
@returns 0 on success.
|
||||
*/
|
||||
int prepare_record(const Slave_reporting_capability *const log,
|
||||
TABLE *const table,
|
||||
const uint skip, const bool check)
|
||||
{
|
||||
DBUG_ENTER("prepare_record");
|
||||
|
||||
int error= 0;
|
||||
empty_record(table);
|
||||
|
||||
if (skip >= table->s->fields) // nothing to do
|
||||
DBUG_RETURN(0);
|
||||
|
||||
/* Explicit initialization of fields */
|
||||
|
||||
for (Field **field_ptr= table->field+skip ; *field_ptr ; ++field_ptr)
|
||||
{
|
||||
uint32 const mask= NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG;
|
||||
Field *const f= *field_ptr;
|
||||
|
||||
if (event_type == WRITE_ROWS_EVENT &&
|
||||
((*field_ptr)->flags & mask) == mask)
|
||||
if (check && ((f->flags & mask) == mask))
|
||||
{
|
||||
rli->report(ERROR_LEVEL, ER_NO_DEFAULT_FOR_FIELD,
|
||||
DBUG_ASSERT(log);
|
||||
log->report(ERROR_LEVEL, 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,
|
||||
f->field_name, table->s->db.str,
|
||||
table->s->table_name.str);
|
||||
error = ER_NO_DEFAULT_FOR_FIELD;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#ifndef RPL_RECORD_H
|
||||
#define RPL_RECORD_H
|
||||
|
||||
#include <rpl_reporting.h>
|
||||
|
||||
#if !defined(MYSQL_CLIENT)
|
||||
size_t pack_row(TABLE* table, MY_BITMAP const* cols,
|
||||
uchar *row_data, const uchar *data);
|
||||
|
@ -25,9 +27,11 @@ size_t pack_row(TABLE* table, MY_BITMAP const* cols,
|
|||
int unpack_row(RELAY_LOG_INFO const *rli,
|
||||
TABLE *table, uint const colcnt,
|
||||
uchar const *const row_data, MY_BITMAP const *cols,
|
||||
uchar const **const row_end, ulong *const master_reclength,
|
||||
MY_BITMAP* const rw_set,
|
||||
Log_event_type const event_type);
|
||||
uchar const **const row_end, ulong *const master_reclength);
|
||||
|
||||
// Fill table's record[0] with default values.
|
||||
int prepare_record(const Slave_reporting_capability *const, TABLE *const,
|
||||
const uint =0, const bool =FALSE);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
This function returns the field size in raw bytes based on the type
|
||||
and the encoded field data from the master's raw data.
|
||||
*/
|
||||
uint32 table_def::calc_field_size(uint col, uchar *master_data)
|
||||
uint32 table_def::calc_field_size(uint col, uchar *master_data) const
|
||||
{
|
||||
uint32 length;
|
||||
|
||||
|
|
|
@ -218,7 +218,7 @@ public:
|
|||
WL#3915) or needs to advance the pointer for the fields in the raw
|
||||
data from the master to a specific column.
|
||||
*/
|
||||
uint32 calc_field_size(uint col, uchar *master_data);
|
||||
uint32 calc_field_size(uint col, uchar *master_data) const;
|
||||
|
||||
/**
|
||||
Decide if the table definition is compatible with a table.
|
||||
|
@ -258,4 +258,44 @@ struct RPL_TABLE_LIST
|
|||
table_def m_tabledef;
|
||||
};
|
||||
|
||||
|
||||
/* Anonymous namespace for template functions/classes */
|
||||
namespace {
|
||||
|
||||
/*
|
||||
Smart pointer that will automatically call my_afree (a macro) when
|
||||
the pointer goes out of scope. This is used so that I do not have
|
||||
to remember to call my_afree() before each return. There is no
|
||||
overhead associated with this, since all functions are inline.
|
||||
|
||||
I (Matz) would prefer to use the free function as a template
|
||||
parameter, but that is not possible when the "function" is a
|
||||
macro.
|
||||
*/
|
||||
template <class Obj>
|
||||
class auto_afree_ptr
|
||||
{
|
||||
Obj* m_ptr;
|
||||
public:
|
||||
auto_afree_ptr(Obj* ptr) : m_ptr(ptr) { }
|
||||
~auto_afree_ptr() { if (m_ptr) my_afree(m_ptr); }
|
||||
void assign(Obj* ptr) {
|
||||
/* Only to be called if it hasn't been given a value before. */
|
||||
DBUG_ASSERT(m_ptr == NULL);
|
||||
m_ptr= ptr;
|
||||
}
|
||||
Obj* get() { return m_ptr; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#define DBUG_PRINT_BITSET(N,FRM,BS) \
|
||||
do { \
|
||||
char buf[256]; \
|
||||
for (uint i = 0 ; i < (BS)->n_bits ; ++i) \
|
||||
buf[i] = bitmap_is_set((BS), i) ? '1' : '0'; \
|
||||
buf[(BS)->n_bits] = '\0'; \
|
||||
DBUG_PRINT((N), ((FRM), buf)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* RPL_UTILITY_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue