summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <mats@romeo.(none)>2007-04-13 14:55:28 +0200
committerunknown <mats@romeo.(none)>2007-04-13 14:55:28 +0200
commit0d3f926a1c21f3b760a18d5aa0e2587fe2136709 (patch)
treea6298adece79b18afd126eeb524928c260641fc1 /sql
parentdc125bb3a0b42c2d6aaf235631a3f14645c7e772 (diff)
downloadmariadb-git-0d3f926a1c21f3b760a18d5aa0e2587fe2136709.tar.gz
WL#2735: Refactor replication
Factoring out pack_row() and unpack_row() into new files rpl_record.{cc,h}. libmysqld/Makefile.am: Adding file rpl_record.cc sql/CMakeLists.txt: Adding file rpl_record.cc sql/Makefile.am: Adding file rpl_record.cc and rpl_record.h sql/log_event.cc: Moving implementation of unpack_row() into "rpl_record.cc". Adding inclusion of header file "rpl_record.h". sql/log_event_old.cc: Signature of do_prepare_row() changed. sql/log_event_old.h: Adding copyright. sql/rpl_record_old.cc: Signature of do_prepare_row() changed. sql/rpl_record_old.h: Adding copyright. Signature of do_prepare_row() changed. sql/sql_class.cc: Moving implementation THD::pack_row() into "rpl_record.cc" and rewriting it to be a global function. Adding inclusion of header file "rpl_record.h". sql/sql_class.h: Removing pack_row() as THD member function. sql/rpl_record.cc: New BitKeeper file ``sql/rpl_record.cc'' sql/rpl_record.h: New BitKeeper file ``sql/rpl_record.h''
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt3
-rw-r--r--sql/Makefile.am7
-rw-r--r--sql/log_event.cc158
-rw-r--r--sql/log_event_old.cc21
-rw-r--r--sql/log_event_old.h15
-rw-r--r--sql/rpl_record.cc278
-rw-r--r--sql/rpl_record.h33
-rw-r--r--sql/rpl_record_old.cc2
-rw-r--r--sql/rpl_record_old.h17
-rw-r--r--sql/sql_class.cc111
-rw-r--r--sql/sql_class.h3
11 files changed, 367 insertions, 281 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index f0e7bea74c6..6d0d0473151 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -47,7 +47,8 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc
hostname.cc init.cc item.cc item_buff.cc item_cmpfunc.cc
item_create.cc item_func.cc item_geofunc.cc item_row.cc
item_strfunc.cc item_subselect.cc item_sum.cc item_timefunc.cc
- key.cc log.cc lock.cc log_event.cc message.rc
+ key.cc log.cc lock.cc message.rc
+ log_event.cc rpl_record.cc
log_event_old.cc rpl_record_old.cc
message.h mf_iocache.cc my_decimal.cc ../sql-common/my_time.c
mysqld.cc net_serv.cc
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 0656c1a8f9b..037986e3e45 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -57,8 +57,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
log.h sql_show.h rpl_rli.h rpl_mi.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h \
lex.h lex_symbol.h sql_acl.h sql_crypt.h \
- log_event.h sql_repl.h slave.h rpl_filter.h \
- rpl_injector.h \
+ sql_repl.h slave.h rpl_filter.h rpl_injector.h \
+ log_event.h rpl_record.h \
log_event_old.h rpl_record_old.h \
stacktrace.h sql_sort.h sql_cache.h set_var.h \
spatial.h gstream.h client_settings.h tzfile.h \
@@ -87,8 +87,9 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
sql_prepare.cc sql_error.cc sql_locale.cc \
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc sql_test.cc \
- log.cc log_event.cc init.cc derror.cc sql_acl.cc \
+ log.cc init.cc derror.cc sql_acl.cc \
unireg.cc des_key_file.cc \
+ log_event.cc rpl_record.cc \
log_event_old.cc rpl_record_old.cc \
discover.cc time.cc opt_range.cc opt_sum.cc \
records.cc filesort.cc handler.cc \
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d484ef55e5e..b67629a2c08 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -26,6 +26,7 @@
#include "rpl_mi.h"
#include "rpl_filter.h"
#include "rpl_utility.h"
+#include "rpl_record.h"
#include <my_dir.h>
#endif /* MYSQL_CLIENT */
#include <base64.h>
@@ -5811,163 +5812,6 @@ int Rows_log_event::do_add_row_data(byte *const row_data,
#endif
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
-/*
- Unpack a row into table->record[0].
-
- SYNOPSIS
- unpack_row()
- rli Relay log info
- table Table to unpack into
- colcnt Number of columns to read from record
- row Packed row data
- cols Pointer to columns data to fill in
- 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 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
-
- DESCRIPTION
-
- The function will always unpack into the table->record[0]
- record. This is because there are too many dependencies on
- where 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 'arr' and 'bits'; the other parts of the
- record are left alone.
-
- 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 const *rli,
- TABLE *table, uint const colcnt,
- char const *const row_data, MY_BITMAP const *cols,
- char const **const row_end, ulong *const master_reclength,
- MY_BITMAP* const rw_set, Log_event_type const event_type)
-{
- DBUG_ENTER("unpack_row");
- DBUG_ASSERT(row_data);
- my_size_t const master_null_byte_count= (bitmap_bits_set(cols) + 7) / 8;
- int error= 0;
-
- char const *null_ptr= row_data;
- char 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;
-
- DBUG_ASSERT(null_ptr < row_data + master_null_byte_count);
-
- // Mask to mask out the correct bit among the null bits
- unsigned int null_mask= 1U;
- // The "current" null bits
- unsigned int null_bits= *null_ptr++;
- for (field_ptr= begin_ptr ; field_ptr < end_ptr ; ++field_ptr)
- {
- Field *const f= *field_ptr;
-
- /*
- No need to bother about columns that does not exist: they have
- gotten default values when being emptied above.
- */
- if (bitmap_is_set(cols, field_ptr - begin_ptr))
- {
- if ((null_mask & 0xFF) == 0)
- {
- DBUG_ASSERT(null_ptr < row_data + master_null_byte_count);
- null_mask= 1U;
- null_bits= *null_ptr++;
- }
-
- DBUG_ASSERT(null_mask & 0xFF); // One of the 8 LSB should be set
-
- /* Field...::unpack() cannot return 0 */
- DBUG_ASSERT(pack_ptr != NULL);
-
- if ((null_bits & null_mask) && f->maybe_null())
- f->set_null();
- else
- {
- f->set_notnull();
-
- /*
- We only unpack the field if it was non-null
- */
- pack_ptr= f->unpack(f->ptr, pack_ptr);
- }
-
- bitmap_set_bit(rw_set, f->field_index);
- null_mask <<= 1;
- }
- }
-
- /*
- We should now have read all the null bytes, otherwise something is
- really wrong.
- */
- DBUG_ASSERT(null_ptr == row_data + master_null_byte_count);
-
- *row_end = pack_ptr;
- if (master_reclength)
- {
- if (*field_ptr)
- *master_reclength = (*field_ptr)->ptr - (char*) table->record[0];
- else
- *master_reclength = table->s->reclength;
- }
-
- /*
- 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.
-
- This generation of error messages is only relevant when inserting
- new rows.
- */
- for ( ; *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)
- {
- 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,
- table->s->table_name.str);
- error = ER_NO_DEFAULT_FOR_FIELD;
- }
- else
- f->set_default();
- }
-
- DBUG_RETURN(error);
-}
-
int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli)
{
DBUG_ENTER("Rows_log_event::do_apply_event(st_relay_log_info*)");
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index 1172a3e0ad4..500feab0542 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -5,7 +5,8 @@
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
int
-Write_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
+Write_rows_log_event_old::do_prepare_row(THD *thd,
+ RELAY_LOG_INFO const *rli,
TABLE *table,
char const *row_start,
char const **row_end)
@@ -14,7 +15,8 @@ Write_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
DBUG_ASSERT(row_start && row_end);
int error;
- error= unpack_row_old(rli, table, m_width, table->record[0],
+ error= unpack_row_old(const_cast<RELAY_LOG_INFO*>(rli),
+ table, m_width, table->record[0],
row_start, &m_cols, row_end, &m_master_reclength,
table->write_set, PRE_GA_WRITE_ROWS_EVENT);
bitmap_copy(table->read_set, table->write_set);
@@ -23,7 +25,8 @@ Write_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
int
-Delete_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
+Delete_rows_log_event_old::do_prepare_row(THD *thd,
+ RELAY_LOG_INFO const *rli,
TABLE *table,
char const *row_start,
char const **row_end)
@@ -36,7 +39,8 @@ Delete_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
*/
DBUG_ASSERT(table->s->fields >= m_width);
- error= unpack_row_old(rli, table, m_width, table->record[0],
+ error= unpack_row_old(const_cast<RELAY_LOG_INFO*>(rli),
+ table, m_width, table->record[0],
row_start, &m_cols, row_end, &m_master_reclength,
table->read_set, PRE_GA_DELETE_ROWS_EVENT);
/*
@@ -54,7 +58,8 @@ Delete_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
}
-int Update_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
+int Update_rows_log_event_old::do_prepare_row(THD *thd,
+ RELAY_LOG_INFO const *rli,
TABLE *table,
char const *row_start,
char const **row_end)
@@ -68,12 +73,14 @@ int Update_rows_log_event_old::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
DBUG_ASSERT(table->s->fields >= m_width);
/* record[0] is the before image for the update */
- error= unpack_row_old(rli, table, m_width, table->record[0],
+ error= unpack_row_old(const_cast<RELAY_LOG_INFO*>(rli),
+ table, m_width, table->record[0],
row_start, &m_cols, row_end, &m_master_reclength,
table->read_set, PRE_GA_UPDATE_ROWS_EVENT);
row_start = *row_end;
/* m_after_image is the after image for the update */
- error= unpack_row_old(rli, table, m_width, m_after_image,
+ error= unpack_row_old(const_cast<RELAY_LOG_INFO*>(rli),
+ table, m_width, m_after_image,
row_start, &m_cols, row_end, &m_master_reclength,
table->write_set, PRE_GA_UPDATE_ROWS_EVENT);
diff --git a/sql/log_event_old.h b/sql/log_event_old.h
index 18d17719a5a..87b11aea3a3 100644
--- a/sql/log_event_old.h
+++ b/sql/log_event_old.h
@@ -1,3 +1,18 @@
+/* Copyright 2007 MySQL AB. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
#ifndef LOG_EVENT_OLD_H
#define LOG_EVENT_OLD_H
diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc
new file mode 100644
index 00000000000..414572027b6
--- /dev/null
+++ b/sql/rpl_record.cc
@@ -0,0 +1,278 @@
+/* Copyright 2007 MySQL AB. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysql_priv.h"
+#include "rpl_record.h"
+#include "slave.h" // Need to pull in slave_print_msg
+
+/**
+ Pack a record of data for a table into a format suitable for
+ transfer via the binary log.
+
+ The format for a row in transfer with N fields is the following:
+
+ ceil(N/8) null bytes:
+ One null bit for every column *regardless of whether it can be
+ null or not*. This simplifies the decoding. Observe that the
+ number of null bits is equal to the number of set bits in the
+ @c cols bitmap. The number of null bytes is the smallest number
+ of bytes necessary to store the null bits.
+
+ Padding bits are 1.
+
+ N packets:
+ Each field is stored in packed format.
+
+
+ @param table Table describing the format of the record
+
+ @param cols Bitmap with a set bit for each column that should
+ be stored in the row
+
+ @param row_data Pointer to memory where row will be written
+
+ @param record Pointer to record that should be packed. It is
+ assumed that the pointer refers to either @c
+ record[0] or @c record[1], but no such check is
+ made since the code does not rely on that.
+
+ @return The number of bytes written at @c row_data.
+ */
+my_size_t
+pack_row(TABLE *table, MY_BITMAP const* cols,
+ byte *const row_data, const byte *record)
+{
+ Field **p_field= table->field, *field;
+ int const null_byte_count= (bitmap_bits_set(cols) + 7) / 8;
+ byte *pack_ptr = row_data + null_byte_count;
+ byte *null_ptr = row_data;
+ my_ptrdiff_t const rec_offset= record - table->record[0];
+ my_ptrdiff_t const def_offset= table->s->default_values - table->record[0];
+
+ /*
+ We write the null bits and the packed records using one pass
+ through all the fields. The null bytes are written little-endian,
+ i.e., the first fields are in the first byte.
+ */
+ unsigned int null_bits= (1U << 8) - 1;
+ // Mask to mask out the correct but among the null bits
+ unsigned int null_mask= 1U;
+ for ( ; (field= *p_field) ; p_field++)
+ {
+ DBUG_PRINT("debug", ("null_mask=%d; null_ptr=%p; row_data=%p; null_byte_count=%d",
+ null_mask, null_ptr, row_data, null_byte_count));
+ if (bitmap_is_set(cols, p_field - table->field))
+ {
+ my_ptrdiff_t offset;
+ if (field->is_null(rec_offset))
+ {
+ offset= def_offset;
+ null_bits |= null_mask;
+ }
+ else
+ {
+ offset= rec_offset;
+ null_bits &= ~null_mask;
+
+ /*
+ We only store the data of the field if it is non-null
+ */
+ pack_ptr= (byte*)field->pack((char *) pack_ptr, field->ptr + offset);
+ }
+
+ null_mask <<= 1;
+ if ((null_mask & 0xFF) == 0)
+ {
+ DBUG_ASSERT(null_ptr < row_data + null_byte_count);
+ null_mask = 1U;
+ *null_ptr++ = null_bits;
+ null_bits= (1U << 8) - 1;
+ }
+ }
+ }
+
+ /*
+ Write the last (partial) byte, if there is one
+ */
+ if ((null_mask & 0xFF) > 1)
+ {
+ DBUG_ASSERT(null_ptr < row_data + null_byte_count);
+ *null_ptr++ = null_bits;
+ }
+
+ /*
+ The null pointer should now point to the first byte of the
+ packed data. If it doesn't, something is very wrong.
+ */
+ DBUG_ASSERT(null_ptr == row_data + null_byte_count);
+
+ return static_cast<my_size_t>(pack_ptr - row_data);
+}
+
+
+/**
+ Unpack a row into @c table->record[0].
+
+ The function will always unpack into the @c table->record[0]
+ record. This is because there are too many dependencies on where
+ 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.
+
+ At most @c colcnt columns are read: if the table is larger than
+ that, the remaining fields are not filled in.
+
+ @param rli Relay log info
+ @param table Table to unpack into
+ @param colcnt Number of columns to read from record
+ @param row Packed row data
+ @param cols Pointer to columns data 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
+
+ @retval 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)
+
+ */
+#ifdef HAVE_REPLICATION
+int
+unpack_row(RELAY_LOG_INFO const *rli,
+ TABLE *table, uint const colcnt,
+ char const *const row_data, MY_BITMAP const *cols,
+ char const **const row_end, ulong *const master_reclength,
+ MY_BITMAP* const rw_set, Log_event_type const event_type)
+{
+ DBUG_ENTER("unpack_row");
+ DBUG_ASSERT(row_data);
+ my_size_t const master_null_byte_count= (bitmap_bits_set(cols) + 7) / 8;
+ int error= 0;
+
+ char const *null_ptr= row_data;
+ char 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;
+
+ DBUG_ASSERT(null_ptr < row_data + master_null_byte_count);
+
+ // Mask to mask out the correct bit among the null bits
+ unsigned int null_mask= 1U;
+ // The "current" null bits
+ unsigned int null_bits= *null_ptr++;
+ for (field_ptr= begin_ptr ; field_ptr < end_ptr ; ++field_ptr)
+ {
+ Field *const f= *field_ptr;
+
+ /*
+ No need to bother about columns that does not exist: they have
+ gotten default values when being emptied above.
+ */
+ if (bitmap_is_set(cols, field_ptr - begin_ptr))
+ {
+ if ((null_mask & 0xFF) == 0)
+ {
+ DBUG_ASSERT(null_ptr < row_data + master_null_byte_count);
+ null_mask= 1U;
+ null_bits= *null_ptr++;
+ }
+
+ DBUG_ASSERT(null_mask & 0xFF); // One of the 8 LSB should be set
+
+ /* Field...::unpack() cannot return 0 */
+ DBUG_ASSERT(pack_ptr != NULL);
+
+ if ((null_bits & null_mask) && f->maybe_null())
+ f->set_null();
+ else
+ {
+ f->set_notnull();
+
+ /*
+ We only unpack the field if it was non-null
+ */
+ pack_ptr= f->unpack(f->ptr, pack_ptr);
+ }
+
+ bitmap_set_bit(rw_set, f->field_index);
+ null_mask <<= 1;
+ }
+ }
+
+ /*
+ We should now have read all the null bytes, otherwise something is
+ really wrong.
+ */
+ DBUG_ASSERT(null_ptr == row_data + master_null_byte_count);
+
+ *row_end = pack_ptr;
+ if (master_reclength)
+ {
+ if (*field_ptr)
+ *master_reclength = (*field_ptr)->ptr - (char*) table->record[0];
+ else
+ *master_reclength = table->s->reclength;
+ }
+
+ /*
+ 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.
+
+ This generation of error messages is only relevant when inserting
+ new rows.
+ */
+ for ( ; *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)
+ {
+ 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,
+ table->s->table_name.str);
+ error = ER_NO_DEFAULT_FOR_FIELD;
+ }
+ else
+ f->set_default();
+ }
+
+ DBUG_RETURN(error);
+}
+
+#endif // HAVE_REPLICATION
diff --git a/sql/rpl_record.h b/sql/rpl_record.h
new file mode 100644
index 00000000000..7ff1bbc7c8e
--- /dev/null
+++ b/sql/rpl_record.h
@@ -0,0 +1,33 @@
+/* Copyright 2007 MySQL AB. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef RPL_RECORD_H
+#define RPL_RECORD_H
+
+#if !defined(MYSQL_CLIENT)
+my_size_t pack_row(TABLE* table, MY_BITMAP const* cols,
+ byte *row_data, const byte *data);
+#endif
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+int unpack_row(RELAY_LOG_INFO const *rli,
+ TABLE *table, uint const colcnt,
+ char const *const row_data, MY_BITMAP const *cols,
+ char const **const row_end, ulong *const master_reclength,
+ MY_BITMAP* const rw_set,
+ Log_event_type const event_type);
+#endif
+
+#endif
diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc
index ccee1b2211b..73e2f4e7344 100644
--- a/sql/rpl_record_old.cc
+++ b/sql/rpl_record_old.cc
@@ -3,7 +3,7 @@
#include "rpl_record_old.h"
my_size_t
-pack_row_old(THD *thd, TABLE *table, MY_BITMAP const* cols,
+pack_row_old(TABLE *table, MY_BITMAP const* cols,
byte *row_data, const byte *record)
{
Field **p_field= table->field, *field;
diff --git a/sql/rpl_record_old.h b/sql/rpl_record_old.h
index 7249d98c7b1..6ddb01de07c 100644
--- a/sql/rpl_record_old.h
+++ b/sql/rpl_record_old.h
@@ -1,8 +1,23 @@
+/* Copyright 2007 MySQL AB. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
#ifndef RPL_RECORD_OLD_H
#define RPL_RECORD_OLD_H
#ifndef MYSQL_CLIENT
-my_size_t pack_row_old(THD *thd, TABLE *table, MY_BITMAP const* cols,
+my_size_t pack_row_old(TABLE *table, MY_BITMAP const* cols,
byte *row_data, const byte *record);
#ifdef HAVE_REPLICATION
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 6ba9d0bc8f1..8ea6bb4de2a 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -27,6 +27,7 @@
#include "mysql_priv.h"
#include "rpl_rli.h"
+#include "rpl_record.h"
#include <my_bitmap.h>
#include "log_event.h"
#include <m_ctype.h>
@@ -2554,112 +2555,6 @@ my_size_t THD::max_row_length_blob(TABLE *table, const byte *data) const
}
-/*
- Pack a record of data for a table into a format suitable for
- transfer via the binary log.
-
- SYNOPSIS
- THD::pack_row()
- table Table describing the format of the record
- cols Bitmap with a set bit for each column that should be
- stored in the row
- row_data Pointer to memory where row will be written
- record Pointer to record that should be packed. It is assumed
- that the pointer refers to either record[0] or
- record[1], but no such check is made since the code does
- not rely on that.
-
- DESCRIPTION
-
- The format for a row in transfer with N fields is the following:
-
- ceil(N/8) null bytes:
- One null bit for every column *regardless of whether it can be
- null or not*. This simplifies the decoding. Observe that the
- number of null bits is equal to the number of set bits in the
- 'cols' bitmap. The number of null bytes is the smallest number
- of bytes necessary to store the null bits.
-
- Padding bits are 1.
-
- N packets:
- Each field is stored in packed format.
-
-
- RETURN VALUE
-
- The number of bytes written at 'row_data'.
- */
-my_size_t
-THD::pack_row(TABLE *table, MY_BITMAP const* cols,
- byte *const row_data, const byte *record) const
-{
- Field **p_field= table->field, *field;
- int const null_byte_count= (bitmap_bits_set(cols) + 7) / 8;
- byte *pack_ptr = row_data + null_byte_count;
- byte *null_ptr = row_data;
- my_ptrdiff_t const rec_offset= record - table->record[0];
- my_ptrdiff_t const def_offset= table->s->default_values - table->record[0];
-
- /*
- We write the null bits and the packed records using one pass
- through all the fields. The null bytes are written little-endian,
- i.e., the first fields are in the first byte.
- */
- unsigned int null_bits= (1U << 8) - 1;
- // Mask to mask out the correct but among the null bits
- unsigned int null_mask= 1U;
- for ( ; (field= *p_field) ; p_field++)
- {
- DBUG_PRINT("debug", ("null_mask=%d; null_ptr=%p; row_data=%p; null_byte_count=%d",
- null_mask, null_ptr, row_data, null_byte_count));
- if (bitmap_is_set(cols, p_field - table->field))
- {
- my_ptrdiff_t offset;
- if (field->is_null(rec_offset))
- {
- offset= def_offset;
- null_bits |= null_mask;
- }
- else
- {
- offset= rec_offset;
- null_bits &= ~null_mask;
-
- /*
- We only store the data of the field if it is non-null
- */
- pack_ptr= (byte*)field->pack((char *) pack_ptr, field->ptr + offset);
- }
-
- null_mask <<= 1;
- if ((null_mask & 0xFF) == 0)
- {
- DBUG_ASSERT(null_ptr < row_data + null_byte_count);
- null_mask = 1U;
- *null_ptr++ = null_bits;
- null_bits= (1U << 8) - 1;
- }
- }
- }
-
- /*
- Write the last (partial) byte, if there is one
- */
- if ((null_mask & 0xFF) > 1)
- {
- DBUG_ASSERT(null_ptr < row_data + null_byte_count);
- *null_ptr++ = null_bits;
- }
-
- /*
- The null pointer should now point to the first byte of the
- packed data. If it doesn't, something is very wrong.
- */
- DBUG_ASSERT(null_ptr == row_data + null_byte_count);
-
- return static_cast<my_size_t>(pack_ptr - row_data);
-}
namespace {
@@ -2830,9 +2725,9 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
byte *before_row= row_data.slot(0);
byte *after_row= row_data.slot(1);
- my_size_t const before_size= pack_row(table, cols, before_row,
+ my_size_t const before_size= pack_row(table, cols, before_row,
before_record);
- my_size_t const after_size= pack_row(table, cols, after_row,
+ my_size_t const after_size= pack_row(table, cols, after_row,
after_record);
/*
diff --git a/sql/sql_class.h b/sql/sql_class.h
index dc420976572..ad08fc194c9 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1043,9 +1043,6 @@ public:
return (length+max_row_length_blob(table,data));
}
- my_size_t pack_row(TABLE* table, MY_BITMAP const* cols, byte *row_data,
- const byte *data) const;
-
int binlog_flush_pending_rows_event(bool stmt_end);
void binlog_delete_pending_rows_event();