1 /* Copyright (c) 2014, 2021, Oracle and/or its affiliates.
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 "binary_log_funcs.h"
24 
25 #include "byteorder.h"
26 #include "wrapper_functions.h"
27 
28 #include <string.h>
29 #include <climits>
30 #include <stdint.h>
31 #include <cstring>
32 
33 /**
34    Max value for an unsigned integer of 'bits' bits.
35 
36    The somewhat contorted expression is to avoid overflow.
37  */
uint_max(int bits)38 static unsigned int uint_max(int bits) {
39   BAPI_ASSERT(static_cast<unsigned int>(bits) <= sizeof(unsigned int) * CHAR_BIT);
40   return (((1U << (bits - 1)) - 1) << 1) | 1;
41 }
42 
43 
44 /**
45   Calculate binary size of packed numeric time representation.
46 
47   @param   dec   Precision.
48   The same formula is used to find the binary size of the packed numeric time
49   in libbinlogevents/src/value.cpp calc_field_size().
50   If any modification is done here the same needs to be done in the
51   aforementioned method in libbinlogevents also.
52 */
my_time_binary_length(unsigned int dec)53 unsigned int my_time_binary_length(unsigned int dec)
54 {
55   BAPI_ASSERT(dec <= DATETIME_MAX_DECIMALS);
56   return 3 + (dec + 1) / 2;
57 }
58 
59 /**
60   Calculate binary size of packed datetime representation.
61   @param dec  Precision.
62 
63   The same formula is used to find the binary size of the packed numeric time
64   in libbinlogevents/src/value.cpp calc_field_size().
65   If any modification is done here the same needs to be done in the
66   aforementioned method in libbinlogevents also.
67 */
my_datetime_binary_length(unsigned int dec)68 unsigned int my_datetime_binary_length(unsigned int dec)
69 {
70   BAPI_ASSERT(dec <= DATETIME_MAX_DECIMALS);
71   return 5 + (dec + 1) / 2;
72 }
73 
74 /**
75   Calculate on-disk size of a timestamp value.
76 
77   @param  dec  Precision.
78 
79   The same formula is used to find the binary size of the packed numeric time
80   in libbinlogevents/src/value.cpp calc_field_size().
81   If any modification is done here the same needs to be done in the
82   aforementioned method in libbinlogevents also.
83 */
my_timestamp_binary_length(unsigned int dec)84 unsigned int my_timestamp_binary_length(unsigned int dec)
85 {
86   BAPI_ASSERT(dec <= DATETIME_MAX_DECIMALS);
87   return 4 + (dec + 1) / 2;
88 }
89 
90 /**
91    Compute the maximum display length of a field.
92 
93    @param sql_type Type of the field
94    @param metadata The metadata from the master for the field.
95    @return Maximum length of the field in bytes.
96  */
97 unsigned int
max_display_length_for_field(enum_field_types sql_type,unsigned int metadata)98 max_display_length_for_field(enum_field_types sql_type, unsigned int metadata)
99 {
100   BAPI_ASSERT(metadata >> 16 == 0);
101 
102   switch (sql_type) {
103   case MYSQL_TYPE_NEWDECIMAL:
104     return metadata >> 8;
105 
106   case MYSQL_TYPE_FLOAT:
107     return 12;
108 
109   case MYSQL_TYPE_DOUBLE:
110     return 22;
111 
112   case MYSQL_TYPE_SET:
113   case MYSQL_TYPE_ENUM:
114       return metadata & 0x00ff;
115 
116   case MYSQL_TYPE_STRING:
117   {
118     unsigned char type= metadata >> 8;
119     if (type == MYSQL_TYPE_SET || type == MYSQL_TYPE_ENUM)
120       return metadata & 0xff;
121     else
122       return (((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff);
123   }
124 
125   case MYSQL_TYPE_YEAR:
126   case MYSQL_TYPE_TINY:
127     return 4;
128 
129   case MYSQL_TYPE_SHORT:
130     return 6;
131 
132   case MYSQL_TYPE_INT24:
133     return 9;
134 
135   case MYSQL_TYPE_LONG:
136     return 11;
137 
138   case MYSQL_TYPE_LONGLONG:
139     return 20;
140 
141   case MYSQL_TYPE_NULL:
142     return 0;
143 
144   case MYSQL_TYPE_NEWDATE:
145     return 3;
146 
147   case MYSQL_TYPE_DATE:
148   case MYSQL_TYPE_TIME:
149   case MYSQL_TYPE_TIME2:
150     return 3;
151 
152   case MYSQL_TYPE_TIMESTAMP:
153   case MYSQL_TYPE_TIMESTAMP2:
154     return 4;
155 
156   case MYSQL_TYPE_DATETIME:
157   case MYSQL_TYPE_DATETIME2:
158     return 8;
159 
160   case MYSQL_TYPE_BIT:
161     /*
162       Decode the size of the bit field from the master.
163     */
164     BAPI_ASSERT((metadata & 0xff) <= 7);
165     return 8 * (metadata >> 8U) + (metadata & 0x00ff);
166 
167   case MYSQL_TYPE_VAR_STRING:
168   case MYSQL_TYPE_VARCHAR:
169     return metadata;
170 
171     /*
172       The actual length for these types does not really matter since
173       they are used to calc_pack_length, which ignores the given
174       length for these types.
175 
176       Since we want this to be accurate for other uses, we return the
177       maximum size in bytes of these BLOBs.
178     */
179 
180   case MYSQL_TYPE_TINY_BLOB:
181     return uint_max(1 * 8);
182 
183   case MYSQL_TYPE_MEDIUM_BLOB:
184     return uint_max(3 * 8);
185 
186   case MYSQL_TYPE_BLOB:
187     /*
188       For the blob type, Field::real_type() lies and say that all
189       blobs are of type MYSQL_TYPE_BLOB. In that case, we have to look
190       at the length instead to decide what the max display size is.
191      */
192     return uint_max(metadata * 8);
193 
194   case MYSQL_TYPE_LONG_BLOB:
195   case MYSQL_TYPE_GEOMETRY:
196   case MYSQL_TYPE_JSON:
197     return uint_max(4 * 8);
198 
199   default:
200     return UINT_MAX;
201   }
202 }
203 
decimal_binary_size(int precision,int scale)204 int decimal_binary_size(int precision, int scale)
205  {
206    static const int dig2bytes[10]= {0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
207    int intg= precision-scale,
208        intg0= intg/9, frac0= scale/9,
209        intg0x= intg-intg0*9, frac0x= scale-frac0*9;
210 
211    BAPI_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
212    return intg0 * sizeof(uint32_t) + dig2bytes[intg0x]+
213           frac0 * sizeof(uint32_t) + dig2bytes[frac0x];
214  }
215 
216 
217 /**
218  This helper function calculates the size in bytes of a particular field in a
219  row type event as defined by the field_ptr and metadata_ptr arguments.
220  @param col Field type code
221  @param master_data The field data
222  @param metadata The field metadata
223 
224  @return The size in bytes of a particular field
225 */
calc_field_size(unsigned char col,const unsigned char * master_data,unsigned int metadata)226 uint32_t calc_field_size(unsigned char col, const unsigned char *master_data,
227                          unsigned int metadata)
228 {
229   uint32_t length= 0;
230 
231   switch ((col)) {
232   case MYSQL_TYPE_NEWDECIMAL:
233     length= decimal_binary_size(metadata >> 8,
234                                 metadata & 0xff);
235     break;
236   case MYSQL_TYPE_DECIMAL:
237   case MYSQL_TYPE_FLOAT:
238   case MYSQL_TYPE_DOUBLE:
239     length= metadata;
240     break;
241   /*
242     The cases for SET and ENUM are include for completeness, however
243     both are mapped to type MYSQL_TYPE_STRING and their real types
244     are encoded in the field metadata.
245   */
246   case MYSQL_TYPE_SET:
247   case MYSQL_TYPE_ENUM:
248   case MYSQL_TYPE_STRING:
249   {
250     unsigned char type= metadata >> 8U;
251     if ((type == MYSQL_TYPE_SET) || (type == MYSQL_TYPE_ENUM))
252       length= metadata & 0x00ff;
253     else
254     {
255       /*
256         We are reading the actual size from the master_data record
257         because this field has the actual lengh stored in the first
258         one or two bytes.
259       */
260       length= max_display_length_for_field(MYSQL_TYPE_STRING, metadata) > 255 ? 2 : 1;
261 
262       if (length == 1)
263         length+= *master_data;
264       else
265       {
266         uint32_t temp= 0;
267         memcpy(&temp, master_data, 2);
268         length= length + le32toh(temp);
269       }
270     }
271     break;
272   }
273   case MYSQL_TYPE_YEAR:
274   case MYSQL_TYPE_TINY:
275     length= 1;
276     break;
277   case MYSQL_TYPE_SHORT:
278     length= 2;
279     break;
280   case MYSQL_TYPE_INT24:
281     length= 3;
282     break;
283   case MYSQL_TYPE_LONG:
284     length= 4;
285     break;
286   case MYSQL_TYPE_LONGLONG:
287     length= 8;
288     break;
289   case MYSQL_TYPE_NULL:
290     length= 0;
291     break;
292   case MYSQL_TYPE_NEWDATE:
293     length= 3;
294     break;
295   case MYSQL_TYPE_DATE:
296   case MYSQL_TYPE_TIME:
297     length= 3;
298     break;
299   case MYSQL_TYPE_TIME2:
300     /*
301       The original methods in the server to calculate the binary size of the
302       packed numeric time representation is defined in my_time.c, the signature
303       being  unsigned int my_time_binary_length(uint)
304 
305       The length below needs to be updated if the above method is updated in
306       the server
307     */
308     length= my_time_binary_length(metadata);
309     break;
310   case MYSQL_TYPE_TIMESTAMP:
311     length= 4;
312     break;
313   case MYSQL_TYPE_TIMESTAMP2:
314     /*
315       The original methods in the server to calculate the binary size of the
316       packed numeric time representation is defined in time.c, the signature
317       being  unsigned int my_timestamp_binary_length(uint)
318 
319       The length below needs to be updated if the above method is updated in
320       the server
321     */
322     length= my_timestamp_binary_length(metadata);
323     break;
324   case MYSQL_TYPE_DATETIME:
325     length= 8;
326     break;
327   case MYSQL_TYPE_DATETIME2:
328     /*
329       The original methods in the server to calculate the binary size of the
330       packed numeric time representation is defined in time.c, the signature
331       being  unsigned int my_datetime_binary_length(uint)
332 
333       The length below needs to be updated if the above method is updated in
334       the server
335     */
336     length= my_datetime_binary_length(metadata);
337     break;
338   case MYSQL_TYPE_BIT:
339   {
340     /*
341       Decode the size of the bit field from the master.
342         from_len is the length in bytes from the master
343         from_bit_len is the number of extra bits stored in the master record
344       If from_bit_len is not 0, add 1 to the length to account for accurate
345       number of bytes needed.
346     */
347     unsigned int from_len= (metadata >> 8U) & 0x00ff;
348     unsigned int from_bit_len= metadata & 0x00ff;
349     BAPI_ASSERT(from_bit_len <= 7);
350     length= from_len + ((from_bit_len > 0) ? 1 : 0);
351     break;
352   }
353   case MYSQL_TYPE_VARCHAR:
354   {
355     length= metadata > 255 ? 2 : 1;
356     if (length == 1)
357       length+= (uint32_t) *master_data;
358     else
359     {
360       uint32_t temp= 0;
361       memcpy(&temp, master_data, 2);
362       length= length + le32toh(temp);
363     }
364     break;
365   }
366   case MYSQL_TYPE_TINY_BLOB:
367   case MYSQL_TYPE_MEDIUM_BLOB:
368   case MYSQL_TYPE_LONG_BLOB:
369   case MYSQL_TYPE_BLOB:
370   case MYSQL_TYPE_GEOMETRY:
371   case MYSQL_TYPE_JSON:
372   {
373     /*
374       Compute the length of the data. We cannot use get_length() here
375       since it is dependent on the specific table (and also checks the
376       packlength using the internal 'table' pointer) and replication
377       is using a fixed format for storing data in the binlog.
378     */
379     switch (metadata) {
380     case 1:
381       length= *master_data;
382       break;
383     case 2:
384       memcpy(&length, master_data, 2);
385       length= le32toh(length);
386       break;
387     case 3:
388       memcpy(&length, master_data, 3);
389       length= le32toh(length);
390       break;
391     case 4:
392       memcpy(&length, master_data, 4);
393       length= le32toh(length);
394       break;
395     default:
396       BAPI_ASSERT(0);		// Should not come here
397       break;
398     }
399 
400     length+= metadata;
401     break;
402   }
403   default:
404     length= UINT_MAX;
405   }
406   return length;
407 }
408