~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to sql/rpl_utility.cc

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2006 MySQL AB
 
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 "rpl_utility.h"
 
17
#include "rpl_rli.h"
 
18
 
 
19
/*********************************************************************
 
20
 *                   table_def member definitions                    *
 
21
 *********************************************************************/
 
22
 
 
23
/*
 
24
  This function returns the field size in raw bytes based on the type
 
25
  and the encoded field data from the master's raw data.
 
26
*/
 
27
uint32 table_def::calc_field_size(uint col, uchar *master_data) const
 
28
{
 
29
  uint32 length;
 
30
 
 
31
  switch (type(col)) {
 
32
  case MYSQL_TYPE_NEWDECIMAL:
 
33
    length= my_decimal_get_binary_size(m_field_metadata[col] >> 8, 
 
34
                                       m_field_metadata[col] & 0xff);
 
35
    break;
 
36
  case MYSQL_TYPE_DECIMAL:
 
37
  case MYSQL_TYPE_FLOAT:
 
38
  case MYSQL_TYPE_DOUBLE:
 
39
    length= m_field_metadata[col];
 
40
    break;
 
41
  /*
 
42
    The cases for SET and ENUM are include for completeness, however
 
43
    both are mapped to type MYSQL_TYPE_STRING and their real types
 
44
    are encoded in the field metadata.
 
45
  */
 
46
  case MYSQL_TYPE_SET:
 
47
  case MYSQL_TYPE_ENUM:
 
48
  case MYSQL_TYPE_STRING:
 
49
  {
 
50
    uchar type= m_field_metadata[col] >> 8U;
 
51
    if ((type == MYSQL_TYPE_SET) || (type == MYSQL_TYPE_ENUM))
 
52
      length= m_field_metadata[col] & 0x00ff;
 
53
    else
 
54
    {
 
55
      /*
 
56
        We are reading the actual size from the master_data record
 
57
        because this field has the actual lengh stored in the first
 
58
        byte.
 
59
      */
 
60
      length= (uint) *master_data + 1;
 
61
      DBUG_ASSERT(length != 0);
 
62
    }
 
63
    break;
 
64
  }
 
65
  case MYSQL_TYPE_YEAR:
 
66
  case MYSQL_TYPE_TINY:
 
67
    length= 1;
 
68
    break;
 
69
  case MYSQL_TYPE_SHORT:
 
70
    length= 2;
 
71
    break;
 
72
  case MYSQL_TYPE_INT24:
 
73
    length= 3;
 
74
    break;
 
75
  case MYSQL_TYPE_LONG:
 
76
    length= 4;
 
77
    break;
 
78
#ifdef HAVE_LONG_LONG
 
79
  case MYSQL_TYPE_LONGLONG:
 
80
    length= 8;
 
81
    break;
 
82
#endif
 
83
  case MYSQL_TYPE_NULL:
 
84
    length= 0;
 
85
    break;
 
86
  case MYSQL_TYPE_NEWDATE:
 
87
    length= 3;
 
88
    break;
 
89
  case MYSQL_TYPE_DATE:
 
90
  case MYSQL_TYPE_TIME:
 
91
    length= 3;
 
92
    break;
 
93
  case MYSQL_TYPE_TIMESTAMP:
 
94
    length= 4;
 
95
    break;
 
96
  case MYSQL_TYPE_DATETIME:
 
97
    length= 8;
 
98
    break;
 
99
  case MYSQL_TYPE_BIT:
 
100
  {
 
101
    /*
 
102
      Decode the size of the bit field from the master.
 
103
        from_len is the length in bytes from the master
 
104
        from_bit_len is the number of extra bits stored in the master record
 
105
      If from_bit_len is not 0, add 1 to the length to account for accurate
 
106
      number of bytes needed.
 
107
    */
 
108
    uint from_len= (m_field_metadata[col] >> 8U) & 0x00ff;
 
109
    uint from_bit_len= m_field_metadata[col] & 0x00ff;
 
110
    DBUG_ASSERT(from_bit_len <= 7);
 
111
    length= from_len + ((from_bit_len > 0) ? 1 : 0);
 
112
    break;
 
113
  }
 
114
  case MYSQL_TYPE_VARCHAR:
 
115
  {
 
116
    length= m_field_metadata[col] > 255 ? 2 : 1; // c&p of Field_varstring::data_length()
 
117
    DBUG_ASSERT(uint2korr(master_data) > 0);
 
118
    length+= length == 1 ? (uint32) *master_data : uint2korr(master_data);
 
119
    break;
 
120
  }
 
121
  case MYSQL_TYPE_TINY_BLOB:
 
122
  case MYSQL_TYPE_MEDIUM_BLOB:
 
123
  case MYSQL_TYPE_LONG_BLOB:
 
124
  case MYSQL_TYPE_BLOB:
 
125
  case MYSQL_TYPE_GEOMETRY:
 
126
  {
 
127
#if 1
 
128
    /*
 
129
      BUG#29549: 
 
130
      This is currently broken for NDB, which is using big-endian
 
131
      order when packing length of BLOB. Once they have decided how to
 
132
      fix the issue, we can enable the code below to make sure to
 
133
      always read the length in little-endian order.
 
134
    */
 
135
    Field_blob fb(m_field_metadata[col]);
 
136
    length= fb.get_packed_size(master_data, TRUE);
 
137
#else
 
138
    /*
 
139
      Compute the length of the data. We cannot use get_length() here
 
140
      since it is dependent on the specific table (and also checks the
 
141
      packlength using the internal 'table' pointer) and replication
 
142
      is using a fixed format for storing data in the binlog.
 
143
    */
 
144
    switch (m_field_metadata[col]) {
 
145
    case 1:
 
146
      length= *master_data;
 
147
      break;
 
148
    case 2:
 
149
      length= uint2korr(master_data);
 
150
      break;
 
151
    case 3:
 
152
      length= uint3korr(master_data);
 
153
      break;
 
154
    case 4:
 
155
      length= uint4korr(master_data);
 
156
      break;
 
157
    default:
 
158
      DBUG_ASSERT(0);           // Should not come here
 
159
      break;
 
160
    }
 
161
 
 
162
    length+= m_field_metadata[col];
 
163
#endif
 
164
    break;
 
165
  }
 
166
  default:
 
167
    length= ~(uint32) 0;
 
168
  }
 
169
  return length;
 
170
}
 
171
 
 
172
/*
 
173
  Is the definition compatible with a table?
 
174
 
 
175
*/
 
176
int
 
177
table_def::compatible_with(Relay_log_info const *rli_arg, TABLE *table)
 
178
  const
 
179
{
 
180
  /*
 
181
    We only check the initial columns for the tables.
 
182
  */
 
183
  uint const cols_to_check= min(table->s->fields, size());
 
184
  int error= 0;
 
185
  Relay_log_info const *rli= const_cast<Relay_log_info*>(rli_arg);
 
186
 
 
187
  TABLE_SHARE const *const tsh= table->s;
 
188
 
 
189
  for (uint col= 0 ; col < cols_to_check ; ++col)
 
190
  {
 
191
    Field *const field= table->field[col];
 
192
    if (field->type() != type(col))
 
193
    {
 
194
      DBUG_ASSERT(col < size() && col < tsh->fields);
 
195
      DBUG_ASSERT(tsh->db.str && tsh->table_name.str);
 
196
      error= 1;
 
197
      char buf[256];
 
198
      my_snprintf(buf, sizeof(buf), "Column %d type mismatch - "
 
199
                  "received type %d, %s.%s has type %d",
 
200
                  col, type(col), tsh->db.str, tsh->table_name.str,
 
201
                  field->type());
 
202
      rli->report(ERROR_LEVEL, ER_BINLOG_ROW_WRONG_TABLE_DEF,
 
203
                  ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf);
 
204
    }
 
205
    /*
 
206
      Check the slave's field size against that of the master.
 
207
    */
 
208
    if (!error &&
 
209
        !field->compatible_field_size(field_metadata(col), rli_arg))
 
210
    {
 
211
      error= 1;
 
212
      char buf[256];
 
213
      my_snprintf(buf, sizeof(buf), "Column %d size mismatch - "
 
214
                  "master has size %d, %s.%s on slave has size %d."
 
215
                  " Master's column size should be <= the slave's "
 
216
                  "column size.", col,
 
217
                  field->pack_length_from_metadata(m_field_metadata[col]),
 
218
                  tsh->db.str, tsh->table_name.str,
 
219
                  field->row_pack_length());
 
220
      rli->report(ERROR_LEVEL, ER_BINLOG_ROW_WRONG_TABLE_DEF,
 
221
                  ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf);
 
222
    }
 
223
  }
 
224
 
 
225
  return error;
 
226
}