MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
data0data.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /********************************************************************/
26 #include "data0data.h"
27 
28 #ifdef UNIV_NONINL
29 #include "data0data.ic"
30 #endif
31 
32 #ifndef UNIV_HOTBACKUP
33 #include "rem0rec.h"
34 #include "rem0cmp.h"
35 #include "page0page.h"
36 #include "page0zip.h"
37 #include "dict0dict.h"
38 #include "btr0cur.h"
39 
40 #include <ctype.h>
41 #endif /* !UNIV_HOTBACKUP */
42 
43 #ifdef UNIV_DEBUG
44 
47 UNIV_INTERN byte data_error;
48 
49 # ifndef UNIV_DEBUG_VALGRIND
50 
51 UNIV_INTERN ulint data_dummy;
52 # endif /* !UNIV_DEBUG_VALGRIND */
53 #endif /* UNIV_DEBUG */
54 
55 #ifndef UNIV_HOTBACKUP
56 /************************************************************/
60 UNIV_INTERN
61 int
63 /*============*/
64  const dtuple_t* tuple1,
65  const dtuple_t* tuple2)
66 {
67  ulint n_fields;
68  ulint i;
69 
70  ut_ad(tuple1 && tuple2);
71  ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
72  ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
73  ut_ad(dtuple_check_typed(tuple1));
74  ut_ad(dtuple_check_typed(tuple2));
75 
76  n_fields = dtuple_get_n_fields(tuple1);
77 
78  if (n_fields != dtuple_get_n_fields(tuple2)) {
79 
80  return(n_fields < dtuple_get_n_fields(tuple2) ? -1 : 1);
81  }
82 
83  for (i = 0; i < n_fields; i++) {
84  int cmp;
85  const dfield_t* field1 = dtuple_get_nth_field(tuple1, i);
86  const dfield_t* field2 = dtuple_get_nth_field(tuple2, i);
87 
88  cmp = cmp_dfield_dfield(field1, field2);
89 
90  if (cmp) {
91  return(cmp);
92  }
93  }
94 
95  return(0);
96 }
97 
98 /*********************************************************************/
101 UNIV_INTERN
102 void
104 /*================*/
105  dtuple_t* tuple,
106  ulint n_fields)
107 {
108  ut_ad(tuple);
109 
110  tuple->n_fields = n_fields;
111  tuple->n_fields_cmp = n_fields;
112 }
113 
114 /**********************************************************/
117 static
118 ibool
119 dfield_check_typed_no_assert(
120 /*=========================*/
121  const dfield_t* field)
122 {
123  if (dfield_get_type(field)->mtype > DATA_MYSQL
124  || dfield_get_type(field)->mtype < DATA_VARCHAR) {
125 
126  fprintf(stderr,
127  "InnoDB: Error: data field type %lu, len %lu\n",
128  (ulong) dfield_get_type(field)->mtype,
129  (ulong) dfield_get_len(field));
130  return(FALSE);
131  }
132 
133  return(TRUE);
134 }
135 
136 /**********************************************************/
139 UNIV_INTERN
140 ibool
142 /*=========================*/
143  const dtuple_t* tuple)
144 {
145  const dfield_t* field;
146  ulint i;
147 
148  if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
149  fprintf(stderr,
150  "InnoDB: Error: index entry has %lu fields\n",
151  (ulong) dtuple_get_n_fields(tuple));
152 dump:
153  fputs("InnoDB: Tuple contents: ", stderr);
154  dtuple_print(stderr, tuple);
155  putc('\n', stderr);
156 
157  return(FALSE);
158  }
159 
160  for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
161 
162  field = dtuple_get_nth_field(tuple, i);
163 
164  if (!dfield_check_typed_no_assert(field)) {
165  goto dump;
166  }
167  }
168 
169  return(TRUE);
170 }
171 #endif /* !UNIV_HOTBACKUP */
172 
173 #ifdef UNIV_DEBUG
174 /**********************************************************/
177 UNIV_INTERN
178 ibool
180 /*===============*/
181  const dfield_t* field)
182 {
183  if (dfield_get_type(field)->mtype > DATA_MYSQL
184  || dfield_get_type(field)->mtype < DATA_VARCHAR) {
185 
186  fprintf(stderr,
187  "InnoDB: Error: data field type %lu, len %lu\n",
188  (ulong) dfield_get_type(field)->mtype,
189  (ulong) dfield_get_len(field));
190 
191  ut_error;
192  }
193 
194  return(TRUE);
195 }
196 
197 /**********************************************************/
200 UNIV_INTERN
201 ibool
203 /*===============*/
204  const dtuple_t* tuple)
205 {
206  const dfield_t* field;
207  ulint i;
208 
209  for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
210 
211  field = dtuple_get_nth_field(tuple, i);
212 
213  ut_a(dfield_check_typed(field));
214  }
215 
216  return(TRUE);
217 }
218 
219 /**********************************************************/
223 UNIV_INTERN
224 ibool
225 dtuple_validate(
226 /*============*/
227  const dtuple_t* tuple)
228 {
229  const dfield_t* field;
230  ulint n_fields;
231  ulint len;
232  ulint i;
233 
234  ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
235 
236  n_fields = dtuple_get_n_fields(tuple);
237 
238  /* We dereference all the data of each field to test
239  for memory traps */
240 
241  for (i = 0; i < n_fields; i++) {
242 
243  field = dtuple_get_nth_field(tuple, i);
244  len = dfield_get_len(field);
245 
246  if (!dfield_is_null(field)) {
247 
248  const byte* data;
249 
250  data = static_cast<const byte*>(dfield_get_data(field));
251 #ifndef UNIV_DEBUG_VALGRIND
252  ulint j;
253 
254  for (j = 0; j < len; j++) {
255 
256  data_dummy += *data; /* fool the compiler not
257  to optimize out this
258  code */
259  data++;
260  }
261 #endif /* !UNIV_DEBUG_VALGRIND */
262 
263  UNIV_MEM_ASSERT_RW(data, len);
264  }
265  }
266 
267  ut_a(dtuple_check_typed(tuple));
268 
269  return(TRUE);
270 }
271 #endif /* UNIV_DEBUG */
272 
273 #ifndef UNIV_HOTBACKUP
274 /*************************************************************/
276 UNIV_INTERN
277 void
279 /*=========*/
280  const dfield_t* dfield)
281 {
282  const byte* data;
283  ulint len;
284  ulint i;
285 
286  len = dfield_get_len(dfield);
287  data = static_cast<const byte*>(dfield_get_data(dfield));
288 
289  if (dfield_is_null(dfield)) {
290  fputs("NULL", stderr);
291 
292  return;
293  }
294 
295  switch (dtype_get_mtype(dfield_get_type(dfield))) {
296  case DATA_CHAR:
297  case DATA_VARCHAR:
298  for (i = 0; i < len; i++) {
299  int c = *data++;
300  putc(isprint(c) ? c : ' ', stderr);
301  }
302 
303  if (dfield_is_ext(dfield)) {
304  fputs("(external)", stderr);
305  }
306  break;
307  case DATA_INT:
308  ut_a(len == 4); /* only works for 32-bit integers */
309  fprintf(stderr, "%d", (int) mach_read_from_4(data));
310  break;
311  default:
312  ut_error;
313  }
314 }
315 
316 /*************************************************************/
319 UNIV_INTERN
320 void
322 /*==================*/
323  const dfield_t* dfield)
324 {
325  const byte* data;
326  ulint len;
327  ulint prtype;
328  ulint i;
329  ibool print_also_hex;
330 
331  len = dfield_get_len(dfield);
332  data = static_cast<const byte*>(dfield_get_data(dfield));
333 
334  if (dfield_is_null(dfield)) {
335  fputs("NULL", stderr);
336 
337  return;
338  }
339 
340  prtype = dtype_get_prtype(dfield_get_type(dfield));
341 
342  switch (dtype_get_mtype(dfield_get_type(dfield))) {
343  ib_id_t id;
344  case DATA_INT:
345  switch (len) {
346  ulint val;
347  case 1:
348  val = mach_read_from_1(data);
349 
350  if (!(prtype & DATA_UNSIGNED)) {
351  val &= ~0x80;
352  fprintf(stderr, "%ld", (long) val);
353  } else {
354  fprintf(stderr, "%lu", (ulong) val);
355  }
356  break;
357 
358  case 2:
359  val = mach_read_from_2(data);
360 
361  if (!(prtype & DATA_UNSIGNED)) {
362  val &= ~0x8000;
363  fprintf(stderr, "%ld", (long) val);
364  } else {
365  fprintf(stderr, "%lu", (ulong) val);
366  }
367  break;
368 
369  case 3:
370  val = mach_read_from_3(data);
371 
372  if (!(prtype & DATA_UNSIGNED)) {
373  val &= ~0x800000;
374  fprintf(stderr, "%ld", (long) val);
375  } else {
376  fprintf(stderr, "%lu", (ulong) val);
377  }
378  break;
379 
380  case 4:
381  val = mach_read_from_4(data);
382 
383  if (!(prtype & DATA_UNSIGNED)) {
384  val &= ~0x80000000;
385  fprintf(stderr, "%ld", (long) val);
386  } else {
387  fprintf(stderr, "%lu", (ulong) val);
388  }
389  break;
390 
391  case 6:
392  id = mach_read_from_6(data);
393  fprintf(stderr, "%llu", (ullint) id);
394  break;
395 
396  case 7:
397  id = mach_read_from_7(data);
398  fprintf(stderr, "%llu", (ullint) id);
399  break;
400  case 8:
401  id = mach_read_from_8(data);
402  fprintf(stderr, "%llu", (ullint) id);
403  break;
404  default:
405  goto print_hex;
406  }
407  break;
408 
409  case DATA_SYS:
410  switch (prtype & DATA_SYS_PRTYPE_MASK) {
411  case DATA_TRX_ID:
412  id = mach_read_from_6(data);
413 
414  fprintf(stderr, "trx_id " TRX_ID_FMT, id);
415  break;
416 
417  case DATA_ROLL_PTR:
418  id = mach_read_from_7(data);
419 
420  fprintf(stderr, "roll_ptr " TRX_ID_FMT, id);
421  break;
422 
423  case DATA_ROW_ID:
424  id = mach_read_from_6(data);
425 
426  fprintf(stderr, "row_id " TRX_ID_FMT, id);
427  break;
428 
429  default:
430  id = mach_ull_read_compressed(data);
431 
432  fprintf(stderr, "mix_id " TRX_ID_FMT, id);
433  }
434  break;
435 
436  case DATA_CHAR:
437  case DATA_VARCHAR:
438  print_also_hex = FALSE;
439 
440  for (i = 0; i < len; i++) {
441  int c = *data++;
442 
443  if (!isprint(c)) {
444  print_also_hex = TRUE;
445 
446  fprintf(stderr, "\\x%02x", (unsigned char) c);
447  } else {
448  putc(c, stderr);
449  }
450  }
451 
452  if (dfield_is_ext(dfield)) {
453  fputs("(external)", stderr);
454  }
455 
456  if (!print_also_hex) {
457  break;
458  }
459 
460  data = static_cast<byte*>(dfield_get_data(dfield));
461  /* fall through */
462 
463  case DATA_BINARY:
464  default:
465 print_hex:
466  fputs(" Hex: ",stderr);
467 
468  for (i = 0; i < len; i++) {
469  fprintf(stderr, "%02lx", (ulint) *data++);
470  }
471 
472  if (dfield_is_ext(dfield)) {
473  fputs("(external)", stderr);
474  }
475  }
476 }
477 
478 /*************************************************************/
480 static
481 void
482 dfield_print_raw(
483 /*=============*/
484  FILE* f,
485  const dfield_t* dfield)
486 {
487  ulint len = dfield_get_len(dfield);
488  if (!dfield_is_null(dfield)) {
489  ulint print_len = ut_min(len, 1000);
490  ut_print_buf(f, dfield_get_data(dfield), print_len);
491  if (len != print_len) {
492  fprintf(f, "(total %lu bytes%s)",
493  (ulong) len,
494  dfield_is_ext(dfield) ? ", external" : "");
495  }
496  } else {
497  fputs(" SQL NULL", f);
498  }
499 }
500 
501 /**********************************************************/
503 UNIV_INTERN
504 void
506 /*=========*/
507  FILE* f,
508  const dtuple_t* tuple)
509 {
510  ulint n_fields;
511  ulint i;
512 
513  n_fields = dtuple_get_n_fields(tuple);
514 
515  fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
516 
517  for (i = 0; i < n_fields; i++) {
518  fprintf(f, " %lu:", (ulong) i);
519 
520  dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
521 
522  putc(';', f);
523  putc('\n', f);
524  }
525 
526  ut_ad(dtuple_validate(tuple));
527 }
528 
529 /**************************************************************/
537 UNIV_INTERN
538 big_rec_t*
540 /*===================*/
542  dtuple_t* entry,
543  ulint* n_ext)
545 {
546  mem_heap_t* heap;
547  big_rec_t* vector;
548  dfield_t* dfield;
549  dict_field_t* ifield;
550  ulint size;
551  ulint n_fields;
552  ulint local_len;
553  ulint local_prefix_len;
554 
555  if (!dict_index_is_clust(index)) {
556  return(NULL);
557  }
558 
559  if (dict_table_get_format(index->table) < UNIV_FORMAT_B) {
560  /* up to MySQL 5.1: store a 768-byte prefix locally */
561  local_len = BTR_EXTERN_FIELD_REF_SIZE
563  } else {
564  /* new-format table: do not store any BLOB prefix locally */
565  local_len = BTR_EXTERN_FIELD_REF_SIZE;
566  }
567 
569 
570  size = rec_get_converted_size(index, entry, *n_ext);
571 
572  if (UNIV_UNLIKELY(size > 1000000000)) {
573  fprintf(stderr,
574  "InnoDB: Warning: tuple size very big: %lu\n",
575  (ulong) size);
576  fputs("InnoDB: Tuple contents: ", stderr);
577  dtuple_print(stderr, entry);
578  putc('\n', stderr);
579  }
580 
581  heap = mem_heap_create(size + dtuple_get_n_fields(entry)
582  * sizeof(big_rec_field_t) + 1000);
583 
584  vector = static_cast<big_rec_t*>(
585  mem_heap_alloc(heap, sizeof(big_rec_t)));
586 
587  vector->heap = heap;
588 
589  vector->fields = static_cast<big_rec_field_t*>(
591  heap,
592  dtuple_get_n_fields(entry) * sizeof(big_rec_field_t)));
593 
594  /* Decide which fields to shorten: the algorithm is to look for
595  a variable-length field that yields the biggest savings when
596  stored externally */
597 
598  n_fields = 0;
599 
601  *n_ext),
602  dict_table_is_comp(index->table),
604  dict_table_zip_size(index->table))) {
605  ulint i;
606  ulint longest = 0;
607  ulint longest_i = ULINT_MAX;
608  byte* data;
609  big_rec_field_t* b;
610 
611  for (i = dict_index_get_n_unique_in_tree(index);
612  i < dtuple_get_n_fields(entry); i++) {
613  ulint savings;
614 
615  dfield = dtuple_get_nth_field(entry, i);
616  ifield = dict_index_get_nth_field(index, i);
617 
618  /* Skip fixed-length, NULL, externally stored,
619  or short columns */
620 
621  if (ifield->fixed_len
622  || dfield_is_null(dfield)
623  || dfield_is_ext(dfield)
624  || dfield_get_len(dfield) <= local_len
625  || dfield_get_len(dfield)
626  <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
627  goto skip_field;
628  }
629 
630  savings = dfield_get_len(dfield) - local_len;
631 
632  /* Check that there would be savings */
633  if (longest >= savings) {
634  goto skip_field;
635  }
636 
637  /* In DYNAMIC and COMPRESSED format, store
638  locally any non-BLOB columns whose maximum
639  length does not exceed 256 bytes. This is
640  because there is no room for the "external
641  storage" flag when the maximum length is 255
642  bytes or less. This restriction trivially
643  holds in REDUNDANT and COMPACT format, because
644  there we always store locally columns whose
645  length is up to local_len == 788 bytes.
646  @see rec_init_offsets_comp_ordinary */
647  if (ifield->col->mtype != DATA_BLOB
648  && ifield->col->len < 256) {
649  goto skip_field;
650  }
651 
652  longest_i = i;
653  longest = savings;
654 
655 skip_field:
656  continue;
657  }
658 
659  if (!longest) {
660  /* Cannot shorten more */
661 
662  mem_heap_free(heap);
663 
664  return(NULL);
665  }
666 
667  /* Move data from field longest_i to big rec vector.
668 
669  We store the first bytes locally to the record. Then
670  we can calculate all ordering fields in all indexes
671  from locally stored data. */
672 
673  dfield = dtuple_get_nth_field(entry, longest_i);
674  ifield = dict_index_get_nth_field(index, longest_i);
675  local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
676 
677  b = &vector->fields[n_fields];
678  b->field_no = longest_i;
679  b->len = dfield_get_len(dfield) - local_prefix_len;
680  b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
681 
682  /* Allocate the locally stored part of the column. */
683  data = static_cast<byte*>(mem_heap_alloc(heap, local_len));
684 
685  /* Copy the local prefix. */
686  memcpy(data, dfield_get_data(dfield), local_prefix_len);
687  /* Clear the extern field reference (BLOB pointer). */
688  memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
689 #if 0
690  /* The following would fail the Valgrind checks in
691  page_cur_insert_rec_low() and page_cur_insert_rec_zip().
692  The BLOB pointers in the record will be initialized after
693  the record and the BLOBs have been written. */
694  UNIV_MEM_ALLOC(data + local_prefix_len,
695  BTR_EXTERN_FIELD_REF_SIZE);
696 #endif
697 
698  dfield_set_data(dfield, data, local_len);
699  dfield_set_ext(dfield);
700 
701  n_fields++;
702  (*n_ext)++;
703  ut_ad(n_fields < dtuple_get_n_fields(entry));
704  }
705 
706  vector->n_fields = n_fields;
707  return(vector);
708 }
709 
710 /**************************************************************/
714 UNIV_INTERN
715 void
717 /*========================*/
718  dict_index_t* index __attribute__((unused)),
719  dtuple_t* entry,
720  big_rec_t* vector)
722 {
723  big_rec_field_t* b = vector->fields;
724  const big_rec_field_t* const end = b + vector->n_fields;
725 
726  for (; b < end; b++) {
727  dfield_t* dfield;
728  ulint local_len;
729 
730  dfield = dtuple_get_nth_field(entry, b->field_no);
731  local_len = dfield_get_len(dfield);
732 
733  ut_ad(dfield_is_ext(dfield));
734  ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
735 
736  local_len -= BTR_EXTERN_FIELD_REF_SIZE;
737 
738  /* Only in REDUNDANT and COMPACT format, we store
739  up to DICT_ANTELOPE_MAX_INDEX_COL_LEN (768) bytes
740  locally */
742 
743  dfield_set_data(dfield,
744  (char*) b->data - local_len,
745  b->len + local_len);
746  }
747 
748  mem_heap_free(vector->heap);
749 }
750 #endif /* !UNIV_HOTBACKUP */