| 1 | /* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 2 | |
| 3 | This program is free software; you can redistribute it and/or modify |
| 4 | it under the terms of the GNU General Public License as published by |
| 5 | the Free Software Foundation; version 2 of the License. |
| 6 | |
| 7 | This program is distributed in the hope that it will be useful, |
| 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | GNU General Public License for more details. |
| 11 | |
| 12 | You should have received a copy of the GNU General Public License |
| 13 | along with this program; if not, write to the Free Software |
| 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
| 15 | |
| 16 | #include "mariadb.h" |
| 17 | #include "sql_priv.h" |
| 18 | #include "rpl_rli.h" |
| 19 | #include "rpl_record_old.h" |
| 20 | #include "log_event.h" // Log_event_type |
| 21 | |
| 22 | size_t |
| 23 | pack_row_old(TABLE *table, MY_BITMAP const* cols, |
| 24 | uchar *row_data, const uchar *record) |
| 25 | { |
| 26 | Field **p_field= table->field, *field; |
| 27 | int n_null_bytes= table->s->null_bytes; |
| 28 | uchar *ptr; |
| 29 | uint i; |
| 30 | my_ptrdiff_t const rec_offset= record - table->record[0]; |
| 31 | my_ptrdiff_t const def_offset= table->s->default_values - table->record[0]; |
| 32 | memcpy(row_data, record, n_null_bytes); |
| 33 | ptr= row_data+n_null_bytes; |
| 34 | |
| 35 | for (i= 0 ; (field= *p_field) ; i++, p_field++) |
| 36 | { |
| 37 | if (bitmap_is_set(cols,i)) |
| 38 | { |
| 39 | my_ptrdiff_t const offset= |
| 40 | field->is_null(rec_offset) ? def_offset : rec_offset; |
| 41 | field->move_field_offset(offset); |
| 42 | ptr= field->pack(ptr, field->ptr); |
| 43 | field->move_field_offset(-offset); |
| 44 | } |
| 45 | } |
| 46 | return (static_cast<size_t>(ptr - row_data)); |
| 47 | } |
| 48 | |
| 49 | |
| 50 | /* |
| 51 | Unpack a row into a record. |
| 52 | |
| 53 | SYNOPSIS |
| 54 | unpack_row() |
| 55 | rli Relay log info |
| 56 | table Table to unpack into |
| 57 | colcnt Number of columns to read from record |
| 58 | record Record where the data should be unpacked |
| 59 | row Packed row data |
| 60 | cols Pointer to columns data to fill in |
| 61 | row_end Pointer to variable that will hold the value of the |
| 62 | one-after-end position for the row |
| 63 | master_reclength |
| 64 | Pointer to variable that will be set to the length of the |
| 65 | record on the master side |
| 66 | rw_set Pointer to bitmap that holds either the read_set or the |
| 67 | write_set of the table |
| 68 | |
| 69 | DESCRIPTION |
| 70 | |
| 71 | The row is assumed to only consist of the fields for which the |
| 72 | bitset represented by 'arr' and 'bits'; the other parts of the |
| 73 | record are left alone. |
| 74 | |
| 75 | At most 'colcnt' columns are read: if the table is larger than |
| 76 | that, the remaining fields are not filled in. |
| 77 | |
| 78 | RETURN VALUE |
| 79 | |
| 80 | Error code, or zero if no error. The following error codes can |
| 81 | be returned: |
| 82 | |
| 83 | ER_NO_DEFAULT_FOR_FIELD |
| 84 | Returned if one of the fields existing on the slave but not on |
| 85 | the master does not have a default value (and isn't nullable) |
| 86 | ER_SLAVE_CORRUPT_EVENT |
| 87 | Wrong data for field found. |
| 88 | */ |
| 89 | #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) |
| 90 | int |
| 91 | unpack_row_old(rpl_group_info *rgi, |
| 92 | TABLE *table, uint const colcnt, uchar *record, |
| 93 | uchar const *row, const uchar *row_buffer_end, |
| 94 | MY_BITMAP const *cols, |
| 95 | uchar const **row_end, ulong *master_reclength, |
| 96 | MY_BITMAP* const rw_set, Log_event_type const event_type) |
| 97 | { |
| 98 | DBUG_ASSERT(record && row); |
| 99 | my_ptrdiff_t const offset= record - (uchar*) table->record[0]; |
| 100 | size_t master_null_bytes= table->s->null_bytes; |
| 101 | |
| 102 | if (colcnt != table->s->fields) |
| 103 | { |
| 104 | Field **fptr= &table->field[colcnt-1]; |
| 105 | do |
| 106 | master_null_bytes= (*fptr)->last_null_byte(); |
| 107 | while (master_null_bytes == Field::LAST_NULL_BYTE_UNDEF && |
| 108 | fptr-- > table->field); |
| 109 | |
| 110 | /* |
| 111 | If master_null_bytes is LAST_NULL_BYTE_UNDEF (0) at this time, |
| 112 | there were no nullable fields nor BIT fields at all in the |
| 113 | columns that are common to the master and the slave. In that |
| 114 | case, there is only one null byte holding the X bit. |
| 115 | |
| 116 | OBSERVE! There might still be nullable columns following the |
| 117 | common columns, so table->s->null_bytes might be greater than 1. |
| 118 | */ |
| 119 | if (master_null_bytes == Field::LAST_NULL_BYTE_UNDEF) |
| 120 | master_null_bytes= 1; |
| 121 | } |
| 122 | |
| 123 | DBUG_ASSERT(master_null_bytes <= table->s->null_bytes); |
| 124 | memcpy(record, row, master_null_bytes); // [1] |
| 125 | int error= 0; |
| 126 | |
| 127 | bitmap_set_all(rw_set); |
| 128 | |
| 129 | Field **const begin_ptr = table->field; |
| 130 | Field **field_ptr; |
| 131 | uchar const *ptr= row + master_null_bytes; |
| 132 | Field **const end_ptr= begin_ptr + colcnt; |
| 133 | for (field_ptr= begin_ptr ; field_ptr < end_ptr ; ++field_ptr) |
| 134 | { |
| 135 | Field *const f= *field_ptr; |
| 136 | |
| 137 | if (bitmap_is_set(cols, (uint)(field_ptr - begin_ptr))) |
| 138 | { |
| 139 | f->move_field_offset(offset); |
| 140 | ptr= f->unpack(f->ptr, ptr, row_buffer_end, 0); |
| 141 | f->move_field_offset(-offset); |
| 142 | if (!ptr) |
| 143 | { |
| 144 | rgi->rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT, NULL, |
| 145 | "Could not read field `%s` of table `%s`.`%s`" , |
| 146 | f->field_name.str, table->s->db.str, |
| 147 | table->s->table_name.str); |
| 148 | return(ER_SLAVE_CORRUPT_EVENT); |
| 149 | } |
| 150 | } |
| 151 | else |
| 152 | bitmap_clear_bit(rw_set, (uint)(field_ptr - begin_ptr)); |
| 153 | } |
| 154 | |
| 155 | *row_end = ptr; |
| 156 | if (master_reclength) |
| 157 | { |
| 158 | if (*field_ptr) |
| 159 | *master_reclength = (ulong)((*field_ptr)->ptr - table->record[0]); |
| 160 | else |
| 161 | *master_reclength = table->s->reclength; |
| 162 | } |
| 163 | |
| 164 | /* |
| 165 | Set properties for remaining columns, if there are any. We let the |
| 166 | corresponding bit in the write_set be set, to write the value if |
| 167 | it was not there already. We iterate over all remaining columns, |
| 168 | even if there were an error, to get as many error messages as |
| 169 | possible. We are still able to return a pointer to the next row, |
| 170 | so redo that. |
| 171 | |
| 172 | This generation of error messages is only relevant when inserting |
| 173 | new rows. |
| 174 | */ |
| 175 | for ( ; *field_ptr ; ++field_ptr) |
| 176 | { |
| 177 | uint32 const mask= NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG; |
| 178 | |
| 179 | DBUG_PRINT("debug" , ("flags = 0x%x, mask = 0x%x, flags & mask = 0x%x" , |
| 180 | (*field_ptr)->flags, mask, |
| 181 | (*field_ptr)->flags & mask)); |
| 182 | |
| 183 | if (event_type == WRITE_ROWS_EVENT && |
| 184 | ((*field_ptr)->flags & mask) == mask) |
| 185 | { |
| 186 | rgi->rli->report(ERROR_LEVEL, ER_NO_DEFAULT_FOR_FIELD, NULL, |
| 187 | "Field `%s` of table `%s`.`%s` " |
| 188 | "has no default value and cannot be NULL" , |
| 189 | (*field_ptr)->field_name.str, table->s->db.str, |
| 190 | table->s->table_name.str); |
| 191 | error = ER_NO_DEFAULT_FOR_FIELD; |
| 192 | } |
| 193 | else |
| 194 | (*field_ptr)->set_default(); |
| 195 | } |
| 196 | |
| 197 | return error; |
| 198 | } |
| 199 | #endif |
| 200 | |