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