rpl_record_old.cc 5.41 KB
Newer Older
1 2 3 4 5

#include "mysql_priv.h"
#include "rpl_record_old.h"

my_size_t
unknown's avatar
unknown committed
6
pack_row_old(TABLE *table, MY_BITMAP const* cols,
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
             byte *row_data, const byte *record)
{
  Field **p_field= table->field, *field;
  int n_null_bytes= table->s->null_bytes;
  byte *ptr;
  uint i;
  my_ptrdiff_t const rec_offset= record - table->record[0];
  my_ptrdiff_t const def_offset= table->s->default_values - table->record[0];
  memcpy(row_data, record, n_null_bytes);
  ptr= row_data+n_null_bytes;

  for (i= 0 ; (field= *p_field) ; i++, p_field++)
  {
    if (bitmap_is_set(cols,i))
    {
      my_ptrdiff_t const offset=
        field->is_null(rec_offset) ? def_offset : rec_offset;
      field->move_field_offset(offset);
      ptr= (byte*)field->pack((char *) ptr, field->ptr);
      field->move_field_offset(-offset);
    }
  }
  return (static_cast<my_size_t>(ptr - row_data));
}


/*
  Unpack a row into a record.

  SYNOPSIS
    unpack_row()
    rli     Relay log info
    table   Table to unpack into
    colcnt  Number of columns to read from record
    record  Record where the data should be unpacked
    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 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)
 */
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
int
unpack_row_old(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, Log_event_type const event_type)
{
  DBUG_ASSERT(record && row);
  my_ptrdiff_t const offset= record - (byte*) table->record[0];
  my_size_t master_null_bytes= table->s->null_bytes;

  if (colcnt != table->s->fields)
  {
    Field **fptr= &table->field[colcnt-1];
    do
      master_null_bytes= (*fptr)->last_null_byte();
    while (master_null_bytes == Field::LAST_NULL_BYTE_UNDEF &&
           fptr-- > table->field);

    /*
      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);
  memcpy(record, row, master_null_bytes);            // [1]
  int error= 0;

  bitmap_set_all(rw_set);

  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)
  {
    Field *const f= *field_ptr;

    if (bitmap_is_set(cols, field_ptr -  begin_ptr))
    {
      f->move_field_offset(offset);
      ptr= f->unpack(f->ptr, ptr);
      f->move_field_offset(-offset);
      /* 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;
  }

  /*
    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;

    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,
                      "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
      (*field_ptr)->set_default();
  }

  return error;
}
#endif