MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
row0row.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1996, 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 "row0row.h"
27 
28 #ifdef UNIV_NONINL
29 #include "row0row.ic"
30 #endif
31 
32 #include "data0type.h"
33 #include "dict0dict.h"
34 #include "btr0btr.h"
35 #include "ha_prototypes.h"
36 #include "mach0data.h"
37 #include "trx0rseg.h"
38 #include "trx0trx.h"
39 #include "trx0roll.h"
40 #include "trx0undo.h"
41 #include "trx0purge.h"
42 #include "trx0rec.h"
43 #include "que0que.h"
44 #include "row0ext.h"
45 #include "row0upd.h"
46 #include "rem0cmp.h"
47 #include "read0read.h"
48 #include "ut0mem.h"
49 
50 /*****************************************************************/
56 UNIV_INTERN
57 dtuple_t*
59 /*======================*/
60  const dtuple_t* row,
62  const row_ext_t* ext,
65  mem_heap_t* heap)
68 {
69  dtuple_t* entry;
70  ulint entry_len;
71  ulint i;
72 
73  entry_len = dict_index_get_n_fields(index);
74  entry = dtuple_create(heap, entry_len);
75 
76  if (dict_index_is_univ(index)) {
77  dtuple_set_n_fields_cmp(entry, entry_len);
78  /* There may only be externally stored columns
79  in a clustered index B-tree of a user table. */
80  ut_a(!ext);
81  } else {
83  entry, dict_index_get_n_unique_in_tree(index));
84  }
85 
86  for (i = 0; i < entry_len; i++) {
87  const dict_field_t* ind_field
88  = dict_index_get_nth_field(index, i);
89  const dict_col_t* col
90  = ind_field->col;
91  ulint col_no
92  = dict_col_get_no(col);
93  dfield_t* dfield
94  = dtuple_get_nth_field(entry, i);
95  const dfield_t* dfield2
96  = dtuple_get_nth_field(row, col_no);
97  ulint len;
98 
99 #if DATA_MISSING != 0
100 # error "DATA_MISSING != 0"
101 #endif
102  if (UNIV_UNLIKELY(dfield_get_type(dfield2)->mtype
103  == DATA_MISSING)) {
104  /* The field has not been initialized in the row.
105  This should be from trx_undo_rec_get_partial_row(). */
106  return(NULL);
107  }
108 
109  len = dfield_get_len(dfield2);
110 
111  dfield_copy(dfield, dfield2);
112 
113  if (dfield_is_null(dfield)) {
114  continue;
115  }
116 
117  if (ind_field->prefix_len == 0
118  && (!dfield_is_ext(dfield)
119  || dict_index_is_clust(index))) {
120  /* The dfield_copy() above suffices for
121  columns that are stored in-page, or for
122  clustered index record columns that are not
123  part of a column prefix in the PRIMARY KEY. */
124  continue;
125  }
126 
127  /* If the column is stored externally (off-page) in
128  the clustered index, it must be an ordering field in
129  the secondary index. In the Antelope format, only
130  prefix-indexed columns may be stored off-page in the
131  clustered index record. In the Barracuda format, also
132  fully indexed long CHAR or VARCHAR columns may be
133  stored off-page. */
134  ut_ad(col->ord_part);
135 
136  if (ext) {
137  /* See if the column is stored externally. */
138  const byte* buf = row_ext_lookup(ext, col_no,
139  &len);
140  if (UNIV_LIKELY_NULL(buf)) {
141  if (UNIV_UNLIKELY(buf == field_ref_zero)) {
142  return(NULL);
143  }
144  dfield_set_data(dfield, buf, len);
145  }
146 
147  if (ind_field->prefix_len == 0) {
148  /* In the Barracuda format
149  (ROW_FORMAT=DYNAMIC or
150  ROW_FORMAT=COMPRESSED), we can have a
151  secondary index on an entire column
152  that is stored off-page in the
153  clustered index. As this is not a
154  prefix index (prefix_len == 0),
155  include the entire off-page column in
156  the secondary index record. */
157  continue;
158  }
159  } else if (dfield_is_ext(dfield)) {
160  /* This table is either in Antelope format
161  (ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT)
162  or a purge record where the ordered part of
163  the field is not external.
164  In Antelope, the maximum column prefix
165  index length is 767 bytes, and the clustered
166  index record contains a 768-byte prefix of
167  each off-page column. */
170  dfield_set_len(dfield, len);
171  }
172 
173  /* If a column prefix index, take only the prefix. */
174  if (ind_field->prefix_len) {
176  col->prtype, col->mbminmaxlen,
177  ind_field->prefix_len, len,
178  static_cast<char*>(dfield_get_data(dfield)));
179  dfield_set_len(dfield, len);
180  }
181  }
182 
183  return(entry);
184 }
185 
186 /*******************************************************************/
190 UNIV_INTERN
191 dtuple_t*
193 /*======*/
194  ulint type,
201  const dict_index_t* index,
202  const rec_t* rec,
211  const ulint* offsets,
214  const dict_table_t* col_table,
221  const dtuple_t* add_cols,
224  const ulint* col_map,
226  row_ext_t** ext,
229  mem_heap_t* heap)
231 {
232  const byte* copy;
233  dtuple_t* row;
234  ulint n_ext_cols;
235  ulint* ext_cols = NULL; /* remove warning */
236  ulint len;
237  byte* buf;
238  ulint j;
239  mem_heap_t* tmp_heap = NULL;
240  ulint offsets_[REC_OFFS_NORMAL_SIZE];
241  rec_offs_init(offsets_);
242 
243  ut_ad(index && rec && heap);
244  ut_ad(dict_index_is_clust(index));
245  ut_ad(!mutex_own(&trx_sys->mutex));
246  ut_ad(!col_map || col_table);
247 
248  if (!offsets) {
249  offsets = rec_get_offsets(rec, index, offsets_,
250  ULINT_UNDEFINED, &tmp_heap);
251  } else {
252  ut_ad(rec_offs_validate(rec, index, offsets));
253  }
254 
255 #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
256  if (rec_offs_any_null_extern(rec, offsets)) {
257  /* This condition can occur during crash recovery
258  before trx_rollback_active() has completed execution,
259  or when a concurrently executing
260  row_ins_index_entry_low() has committed the B-tree
261  mini-transaction but has not yet managed to restore
262  the cursor position for writing the big_rec. */
264  row_get_rec_roll_ptr(rec, index, offsets)));
265  }
266 #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
267 
268  if (type != ROW_COPY_POINTERS) {
269  /* Take a copy of rec to heap */
270  buf = static_cast<byte*>(
271  mem_heap_alloc(heap, rec_offs_size(offsets)));
272 
273  copy = rec_copy(buf, rec, offsets);
274  } else {
275  copy = rec;
276  }
277 
278  n_ext_cols = rec_offs_n_extern(offsets);
279  if (n_ext_cols) {
280  ext_cols = static_cast<ulint*>(
281  mem_heap_alloc(heap, n_ext_cols * sizeof *ext_cols));
282  }
283 
284  /* Avoid a debug assertion in rec_offs_validate(). */
285  rec_offs_make_valid(copy, index, const_cast<ulint*>(offsets));
286 
287  if (!col_table) {
288  ut_ad(!col_map);
289  ut_ad(!add_cols);
290  col_table = index->table;
291  }
292 
293  if (add_cols) {
294  ut_ad(col_map);
295  row = dtuple_copy(add_cols, heap);
296  /* dict_table_copy_types() would set the fields to NULL */
297  for (ulint i = 0; i < dict_table_get_n_cols(col_table); i++) {
299  dict_table_get_nth_col(col_table, i),
300  dfield_get_type(dtuple_get_nth_field(row, i)));
301  }
302  } else {
303  row = dtuple_create(heap, dict_table_get_n_cols(col_table));
304  dict_table_copy_types(row, col_table);
305  }
306 
308  copy, rec_offs_comp(offsets)));
309 
310  j = 0;
311 
312  for (ulint i = 0; i < rec_offs_n_fields(offsets); i++) {
313  const dict_field_t* ind_field
314  = dict_index_get_nth_field(index, i);
315 
316  if (ind_field->prefix_len) {
317  /* Column prefixes can only occur in key
318  fields, which cannot be stored externally. For
319  a column prefix, there should also be the full
320  field in the clustered index tuple. The row
321  tuple comprises full fields, not prefixes. */
322  ut_ad(!rec_offs_nth_extern(offsets, i));
323  continue;
324  }
325 
326  const dict_col_t* col
327  = dict_field_get_col(ind_field);
328  ulint col_no
329  = dict_col_get_no(col);
330 
331  if (col_map) {
332  col_no = col_map[col_no];
333 
334  if (col_no == ULINT_UNDEFINED) {
335  /* dropped column */
336  continue;
337  }
338  }
339 
340  dfield_t* dfield = dtuple_get_nth_field(row, col_no);
341 
342  const byte* field = rec_get_nth_field(
343  copy, offsets, i, &len);
344 
345  dfield_set_data(dfield, field, len);
346 
347  if (rec_offs_nth_extern(offsets, i)) {
348  dfield_set_ext(dfield);
349 
350  col = dict_table_get_nth_col(col_table, col_no);
351 
352  if (col->ord_part) {
353  /* We will have to fetch prefixes of
354  externally stored columns that are
355  referenced by column prefixes. */
356  ext_cols[j++] = col_no;
357  }
358  }
359  }
360 
361  rec_offs_make_valid(rec, index, const_cast<ulint*>(offsets));
362 
364 
365  if (!ext) {
366  /* REDUNDANT and COMPACT formats store a local
367  768-byte prefix of each externally stored
368  column. No cache is needed.
369 
370  During online table rebuild,
371  row_log_table_apply_delete_low()
372  may use a cache that was set up by
373  row_log_table_delete(). */
374 
375  } else if (j) {
376  *ext = row_ext_create(j, ext_cols, index->table->flags, row,
377  heap);
378  } else {
379  *ext = NULL;
380  }
381 
382  if (tmp_heap) {
383  mem_heap_free(tmp_heap);
384  }
385 
386  return(row);
387 }
388 
389 /*******************************************************************/
393 UNIV_INTERN
394 dtuple_t*
396 /*=======================*/
397  const rec_t* rec,
398  const dict_index_t* index,
399  const ulint* offsets,
400  ulint* n_ext,
402  mem_heap_t* heap)
404 {
405  dtuple_t* entry;
406  dfield_t* dfield;
407  ulint i;
408  const byte* field;
409  ulint len;
410  ulint rec_len;
411 
412  ut_ad(rec && heap && index);
413  /* Because this function may be invoked by row0merge.cc
414  on a record whose header is in different format, the check
415  rec_offs_validate(rec, index, offsets) must be avoided here. */
416  ut_ad(n_ext);
417  *n_ext = 0;
418 
419  rec_len = rec_offs_n_fields(offsets);
420 
421  entry = dtuple_create(heap, rec_len);
422 
425  ut_ad(rec_len == dict_index_get_n_fields(index));
426 
427  dict_index_copy_types(entry, index, rec_len);
428 
429  for (i = 0; i < rec_len; i++) {
430 
431  dfield = dtuple_get_nth_field(entry, i);
432  field = rec_get_nth_field(rec, offsets, i, &len);
433 
434  dfield_set_data(dfield, field, len);
435 
436  if (rec_offs_nth_extern(offsets, i)) {
437  dfield_set_ext(dfield);
438  (*n_ext)++;
439  }
440  }
441 
442  ut_ad(dtuple_check_typed(entry));
443 
444  return(entry);
445 }
446 
447 /*******************************************************************/
451 UNIV_INTERN
452 dtuple_t*
454 /*===================*/
455  const rec_t* rec,
456  const dict_index_t* index,
457  const ulint* offsets,
458  ulint* n_ext,
460  mem_heap_t* heap)
462 {
463  dtuple_t* entry;
464  byte* buf;
465  const rec_t* copy_rec;
466 
467  ut_ad(rec && heap && index);
468  ut_ad(rec_offs_validate(rec, index, offsets));
469 
470  /* Take a copy of rec to heap */
471  buf = static_cast<byte*>(
472  mem_heap_alloc(heap, rec_offs_size(offsets)));
473 
474  copy_rec = rec_copy(buf, rec, offsets);
475 
476  rec_offs_make_valid(copy_rec, index, const_cast<ulint*>(offsets));
478  copy_rec, index, offsets, n_ext, heap);
479  rec_offs_make_valid(rec, index, const_cast<ulint*>(offsets));
480 
481  dtuple_set_info_bits(entry,
482  rec_get_info_bits(rec, rec_offs_comp(offsets)));
483 
484  return(entry);
485 }
486 
487 /*******************************************************************/
491 UNIV_INTERN
492 dtuple_t*
494 /*==============*/
495  ulint type,
500  const rec_t* rec,
507  mem_heap_t* heap)
509 {
511  dict_index_t* clust_index;
512  dfield_t* dfield;
513  dtuple_t* ref;
514  const byte* field;
515  ulint len;
516  ulint ref_len;
517  ulint pos;
518  byte* buf;
519  ulint clust_col_prefix_len;
520  ulint i;
521  mem_heap_t* tmp_heap = NULL;
522  ulint offsets_[REC_OFFS_NORMAL_SIZE];
523  ulint* offsets = offsets_;
524  rec_offs_init(offsets_);
525 
526  ut_ad(index && rec && heap);
527  ut_ad(!dict_index_is_clust(index));
528 
529  offsets = rec_get_offsets(rec, index, offsets,
530  ULINT_UNDEFINED, &tmp_heap);
531  /* Secondary indexes must not contain externally stored columns. */
532  ut_ad(!rec_offs_any_extern(offsets));
533 
534  if (type == ROW_COPY_DATA) {
535  /* Take a copy of rec to heap */
536 
537  buf = static_cast<byte*>(
538  mem_heap_alloc(heap, rec_offs_size(offsets)));
539 
540  rec = rec_copy(buf, rec, offsets);
541  /* Avoid a debug assertion in rec_offs_validate(). */
542  rec_offs_make_valid(rec, index, offsets);
543  }
544 
545  table = index->table;
546 
547  clust_index = dict_table_get_first_index(table);
548 
549  ref_len = dict_index_get_n_unique(clust_index);
550 
551  ref = dtuple_create(heap, ref_len);
552 
553  dict_index_copy_types(ref, clust_index, ref_len);
554 
555  for (i = 0; i < ref_len; i++) {
556  dfield = dtuple_get_nth_field(ref, i);
557 
558  pos = dict_index_get_nth_field_pos(index, clust_index, i);
559 
560  ut_a(pos != ULINT_UNDEFINED);
561 
562  field = rec_get_nth_field(rec, offsets, pos, &len);
563 
564  dfield_set_data(dfield, field, len);
565 
566  /* If the primary key contains a column prefix, then the
567  secondary index may contain a longer prefix of the same
568  column, or the full column, and we must adjust the length
569  accordingly. */
570 
571  clust_col_prefix_len = dict_index_get_nth_field(
572  clust_index, i)->prefix_len;
573 
574  if (clust_col_prefix_len > 0) {
575  if (len != UNIV_SQL_NULL) {
576 
577  const dtype_t* dtype
578  = dfield_get_type(dfield);
579 
580  dfield_set_len(dfield,
582  dtype->prtype,
583  dtype->mbminmaxlen,
584  clust_col_prefix_len,
585  len, (char*) field));
586  }
587  }
588  }
589 
591  if (tmp_heap) {
592  mem_heap_free(tmp_heap);
593  }
594 
595  return(ref);
596 }
597 
598 /*******************************************************************/
601 UNIV_INTERN
602 void
604 /*=======================*/
605  dtuple_t* ref,
607  const rec_t* rec,
615  const dict_index_t* index,
616  ulint* offsets,
618  trx_t* trx)
619 {
620  const dict_index_t* clust_index;
621  dfield_t* dfield;
622  const byte* field;
623  ulint len;
624  ulint ref_len;
625  ulint pos;
626  ulint clust_col_prefix_len;
627  ulint i;
628  mem_heap_t* heap = NULL;
629  ulint offsets_[REC_OFFS_NORMAL_SIZE];
630  rec_offs_init(offsets_);
631 
632  ut_a(ref);
633  ut_a(index);
634  ut_a(rec);
635  ut_ad(!dict_index_is_clust(index));
636 
637  if (UNIV_UNLIKELY(!index->table)) {
638  fputs("InnoDB: table ", stderr);
639 notfound:
640  ut_print_name(stderr, trx, TRUE, index->table_name);
641  fputs(" for index ", stderr);
642  ut_print_name(stderr, trx, FALSE, index->name);
643  fputs(" not found\n", stderr);
644  ut_error;
645  }
646 
647  clust_index = dict_table_get_first_index(index->table);
648 
649  if (UNIV_UNLIKELY(!clust_index)) {
650  fputs("InnoDB: clust index for table ", stderr);
651  goto notfound;
652  }
653 
654  if (!offsets) {
655  offsets = rec_get_offsets(rec, index, offsets_,
656  ULINT_UNDEFINED, &heap);
657  } else {
658  ut_ad(rec_offs_validate(rec, index, offsets));
659  }
660 
661  /* Secondary indexes must not contain externally stored columns. */
662  ut_ad(!rec_offs_any_extern(offsets));
663  ref_len = dict_index_get_n_unique(clust_index);
664 
665  ut_ad(ref_len == dtuple_get_n_fields(ref));
666 
667  dict_index_copy_types(ref, clust_index, ref_len);
668 
669  for (i = 0; i < ref_len; i++) {
670  dfield = dtuple_get_nth_field(ref, i);
671 
672  pos = dict_index_get_nth_field_pos(index, clust_index, i);
673 
674  ut_a(pos != ULINT_UNDEFINED);
675 
676  field = rec_get_nth_field(rec, offsets, pos, &len);
677 
678  dfield_set_data(dfield, field, len);
679 
680  /* If the primary key contains a column prefix, then the
681  secondary index may contain a longer prefix of the same
682  column, or the full column, and we must adjust the length
683  accordingly. */
684 
685  clust_col_prefix_len = dict_index_get_nth_field(
686  clust_index, i)->prefix_len;
687 
688  if (clust_col_prefix_len > 0) {
689  if (len != UNIV_SQL_NULL) {
690 
691  const dtype_t* dtype
692  = dfield_get_type(dfield);
693 
694  dfield_set_len(dfield,
696  dtype->prtype,
697  dtype->mbminmaxlen,
698  clust_col_prefix_len,
699  len, (char*) field));
700  }
701  }
702  }
703 
705  if (UNIV_LIKELY_NULL(heap)) {
706  mem_heap_free(heap);
707  }
708 }
709 
710 /***************************************************************/
713 UNIV_INTERN
714 ibool
716 /*==================*/
717  btr_pcur_t* pcur,
719  ulint mode,
720  const dict_table_t* table,
721  const dtuple_t* ref,
722  mtr_t* mtr)
723 {
724  ulint low_match;
725  rec_t* rec;
727 
729 
730  index = dict_table_get_first_index(table);
731 
733 
734  btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr);
735 
736  low_match = btr_pcur_get_low_match(pcur);
737 
738  rec = btr_pcur_get_rec(pcur);
739 
740  if (page_rec_is_infimum(rec)) {
741 
742  return(FALSE);
743  }
744 
745  if (low_match != dtuple_get_n_fields(ref)) {
746 
747  return(FALSE);
748  }
749 
750  return(TRUE);
751 }
752 
753 /*********************************************************************/
757 UNIV_INTERN
758 rec_t*
760 /*==============*/
761  ulint mode,
762  const rec_t* rec,
764  dict_index_t** clust_index,
765  mtr_t* mtr)
766 {
767  mem_heap_t* heap;
768  dtuple_t* ref;
771  ibool found;
772  rec_t* clust_rec;
773 
774  ut_ad(!dict_index_is_clust(index));
775 
776  table = index->table;
777 
778  heap = mem_heap_create(256);
779 
780  ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec, heap);
781 
782  found = row_search_on_row_ref(&pcur, mode, table, ref, mtr);
783 
784  clust_rec = found ? btr_pcur_get_rec(&pcur) : NULL;
785 
786  mem_heap_free(heap);
787 
788  btr_pcur_close(&pcur);
789 
790  *clust_index = dict_table_get_first_index(table);
791 
792  return(clust_rec);
793 }
794 
795 /***************************************************************/
798 UNIV_INTERN
801 /*===================*/
803  const dtuple_t* entry,
804  ulint mode,
805  btr_pcur_t* pcur,
807  mtr_t* mtr)
808 {
809  ulint n_fields;
810  ulint low_match;
811  rec_t* rec;
812 
813  ut_ad(dtuple_check_typed(entry));
814 
815  btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr);
816 
817  switch (btr_pcur_get_btr_cur(pcur)->flag) {
818  case BTR_CUR_DELETE_REF:
819  ut_a(mode & BTR_DELETE);
820  return(ROW_NOT_DELETED_REF);
821 
823  case BTR_CUR_DELETE_IBUF:
825  return(ROW_BUFFERED);
826 
827  case BTR_CUR_HASH:
828  case BTR_CUR_HASH_FAIL:
829  case BTR_CUR_BINARY:
830  break;
831  }
832 
833  low_match = btr_pcur_get_low_match(pcur);
834 
835  rec = btr_pcur_get_rec(pcur);
836 
837  n_fields = dtuple_get_n_fields(entry);
838 
839  if (page_rec_is_infimum(rec)) {
840 
841  return(ROW_NOT_FOUND);
842  } else if (low_match != n_fields) {
843 
844  return(ROW_NOT_FOUND);
845  }
846 
847  return(ROW_FOUND);
848 }
849 
850 /*******************************************************************/
861 static
862 ulint
863 row_raw_format_int(
864 /*===============*/
865  const char* data,
866  ulint data_len,
868  ulint prtype,
869  char* buf,
870  ulint buf_size,
872  ibool* format_in_hex)
874 {
875  ulint ret;
876 
877  if (data_len <= sizeof(ib_uint64_t)) {
878 
879  ib_uint64_t value;
880  ibool unsigned_type = prtype & DATA_UNSIGNED;
881 
882  value = mach_read_int_type(
883  (const byte*) data, data_len, unsigned_type);
884 
885  ret = ut_snprintf(
886  buf, buf_size,
887  unsigned_type ? UINT64PF : INT64PF, value) + 1;
888  } else {
889 
890  *format_in_hex = TRUE;
891  ret = 0;
892  }
893 
894  return(ut_min(ret, buf_size));
895 }
896 
897 /*******************************************************************/
909 static
910 ulint
911 row_raw_format_str(
912 /*===============*/
913  const char* data,
914  ulint data_len,
916  ulint prtype,
917  char* buf,
918  ulint buf_size,
920  ibool* format_in_hex)
922 {
923  ulint charset_coll;
924 
925  if (buf_size == 0) {
926 
927  return(0);
928  }
929 
930  /* we assume system_charset_info is UTF-8 */
931 
932  charset_coll = dtype_get_charset_coll(prtype);
933 
934  if (UNIV_LIKELY(dtype_is_utf8(prtype))) {
935 
936  return(ut_str_sql_format(data, data_len, buf, buf_size));
937  }
938  /* else */
939 
940  if (charset_coll == DATA_MYSQL_BINARY_CHARSET_COLL) {
941 
942  *format_in_hex = TRUE;
943  return(0);
944  }
945  /* else */
946 
947  return(innobase_raw_format(data, data_len, charset_coll,
948  buf, buf_size));
949 }
950 
951 /*******************************************************************/
959 UNIV_INTERN
960 ulint
962 /*===========*/
963  const char* data,
964  ulint data_len,
966  const dict_field_t* dict_field,
967  char* buf,
968  ulint buf_size)
970 {
971  ulint mtype;
972  ulint prtype;
973  ulint ret;
974  ibool format_in_hex;
975 
976  if (buf_size == 0) {
977 
978  return(0);
979  }
980 
981  if (data_len == UNIV_SQL_NULL) {
982 
983  ret = ut_snprintf((char*) buf, buf_size, "NULL") + 1;
984 
985  return(ut_min(ret, buf_size));
986  }
987 
988  mtype = dict_field->col->mtype;
989  prtype = dict_field->col->prtype;
990 
991  format_in_hex = FALSE;
992 
993  switch (mtype) {
994  case DATA_INT:
995 
996  ret = row_raw_format_int(data, data_len, prtype,
997  buf, buf_size, &format_in_hex);
998  if (format_in_hex) {
999 
1000  goto format_in_hex;
1001  }
1002  break;
1003  case DATA_CHAR:
1004  case DATA_VARCHAR:
1005  case DATA_MYSQL:
1006  case DATA_VARMYSQL:
1007 
1008  ret = row_raw_format_str(data, data_len, prtype,
1009  buf, buf_size, &format_in_hex);
1010  if (format_in_hex) {
1011 
1012  goto format_in_hex;
1013  }
1014 
1015  break;
1016  /* XXX support more data types */
1017  default:
1018  format_in_hex:
1019 
1020  if (UNIV_LIKELY(buf_size > 2)) {
1021 
1022  memcpy(buf, "0x", 2);
1023  buf += 2;
1024  buf_size -= 2;
1025  ret = 2 + ut_raw_to_hex(data, data_len,
1026  buf, buf_size);
1027  } else {
1028 
1029  buf[0] = '\0';
1030  ret = 1;
1031  }
1032  }
1033 
1034  return(ret);
1035 }
1036 
1037 #ifdef UNIV_COMPILE_TEST_FUNCS
1038 
1039 #include "ut0dbg.h"
1040 
1041 void
1042 test_row_raw_format_int()
1043 {
1044  ulint ret;
1045  char buf[128];
1046  ibool format_in_hex;
1047  speedo_t speedo;
1048  ulint i;
1049 
1050 #define CALL_AND_TEST(data, data_len, prtype, buf, buf_size,\
1051  ret_expected, buf_expected, format_in_hex_expected)\
1052  do {\
1053  ibool ok = TRUE;\
1054  ulint i;\
1055  memset(buf, 'x', 10);\
1056  buf[10] = '\0';\
1057  format_in_hex = FALSE;\
1058  fprintf(stderr, "TESTING \"\\x");\
1059  for (i = 0; i < data_len; i++) {\
1060  fprintf(stderr, "%02hhX", data[i]);\
1061  }\
1062  fprintf(stderr, "\", %lu, %lu, %lu\n",\
1063  (ulint) data_len, (ulint) prtype,\
1064  (ulint) buf_size);\
1065  ret = row_raw_format_int(data, data_len, prtype,\
1066  buf, buf_size, &format_in_hex);\
1067  if (ret != ret_expected) {\
1068  fprintf(stderr, "expected ret %lu, got %lu\n",\
1069  (ulint) ret_expected, ret);\
1070  ok = FALSE;\
1071  }\
1072  if (strcmp((char*) buf, buf_expected) != 0) {\
1073  fprintf(stderr, "expected buf \"%s\", got \"%s\"\n",\
1074  buf_expected, buf);\
1075  ok = FALSE;\
1076  }\
1077  if (format_in_hex != format_in_hex_expected) {\
1078  fprintf(stderr, "expected format_in_hex %d, got %d\n",\
1079  (int) format_in_hex_expected,\
1080  (int) format_in_hex);\
1081  ok = FALSE;\
1082  }\
1083  if (ok) {\
1084  fprintf(stderr, "OK: %lu, \"%s\" %d\n\n",\
1085  (ulint) ret, buf, (int) format_in_hex);\
1086  } else {\
1087  return;\
1088  }\
1089  } while (0)
1090 
1091 #if 1
1092  /* min values for signed 1-8 byte integers */
1093 
1094  CALL_AND_TEST("\x00", 1, 0,
1095  buf, sizeof(buf), 5, "-128", 0);
1096 
1097  CALL_AND_TEST("\x00\x00", 2, 0,
1098  buf, sizeof(buf), 7, "-32768", 0);
1099 
1100  CALL_AND_TEST("\x00\x00\x00", 3, 0,
1101  buf, sizeof(buf), 9, "-8388608", 0);
1102 
1103  CALL_AND_TEST("\x00\x00\x00\x00", 4, 0,
1104  buf, sizeof(buf), 12, "-2147483648", 0);
1105 
1106  CALL_AND_TEST("\x00\x00\x00\x00\x00", 5, 0,
1107  buf, sizeof(buf), 14, "-549755813888", 0);
1108 
1109  CALL_AND_TEST("\x00\x00\x00\x00\x00\x00", 6, 0,
1110  buf, sizeof(buf), 17, "-140737488355328", 0);
1111 
1112  CALL_AND_TEST("\x00\x00\x00\x00\x00\x00\x00", 7, 0,
1113  buf, sizeof(buf), 19, "-36028797018963968", 0);
1114 
1115  CALL_AND_TEST("\x00\x00\x00\x00\x00\x00\x00\x00", 8, 0,
1116  buf, sizeof(buf), 21, "-9223372036854775808", 0);
1117 
1118  /* min values for unsigned 1-8 byte integers */
1119 
1120  CALL_AND_TEST("\x00", 1, DATA_UNSIGNED,
1121  buf, sizeof(buf), 2, "0", 0);
1122 
1123  CALL_AND_TEST("\x00\x00", 2, DATA_UNSIGNED,
1124  buf, sizeof(buf), 2, "0", 0);
1125 
1126  CALL_AND_TEST("\x00\x00\x00", 3, DATA_UNSIGNED,
1127  buf, sizeof(buf), 2, "0", 0);
1128 
1129  CALL_AND_TEST("\x00\x00\x00\x00", 4, DATA_UNSIGNED,
1130  buf, sizeof(buf), 2, "0", 0);
1131 
1132  CALL_AND_TEST("\x00\x00\x00\x00\x00", 5, DATA_UNSIGNED,
1133  buf, sizeof(buf), 2, "0", 0);
1134 
1135  CALL_AND_TEST("\x00\x00\x00\x00\x00\x00", 6, DATA_UNSIGNED,
1136  buf, sizeof(buf), 2, "0", 0);
1137 
1138  CALL_AND_TEST("\x00\x00\x00\x00\x00\x00\x00", 7, DATA_UNSIGNED,
1139  buf, sizeof(buf), 2, "0", 0);
1140 
1141  CALL_AND_TEST("\x00\x00\x00\x00\x00\x00\x00\x00", 8, DATA_UNSIGNED,
1142  buf, sizeof(buf), 2, "0", 0);
1143 
1144  /* max values for signed 1-8 byte integers */
1145 
1146  CALL_AND_TEST("\xFF", 1, 0,
1147  buf, sizeof(buf), 4, "127", 0);
1148 
1149  CALL_AND_TEST("\xFF\xFF", 2, 0,
1150  buf, sizeof(buf), 6, "32767", 0);
1151 
1152  CALL_AND_TEST("\xFF\xFF\xFF", 3, 0,
1153  buf, sizeof(buf), 8, "8388607", 0);
1154 
1155  CALL_AND_TEST("\xFF\xFF\xFF\xFF", 4, 0,
1156  buf, sizeof(buf), 11, "2147483647", 0);
1157 
1158  CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF", 5, 0,
1159  buf, sizeof(buf), 13, "549755813887", 0);
1160 
1161  CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF", 6, 0,
1162  buf, sizeof(buf), 16, "140737488355327", 0);
1163 
1164  CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 7, 0,
1165  buf, sizeof(buf), 18, "36028797018963967", 0);
1166 
1167  CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8, 0,
1168  buf, sizeof(buf), 20, "9223372036854775807", 0);
1169 
1170  /* max values for unsigned 1-8 byte integers */
1171 
1172  CALL_AND_TEST("\xFF", 1, DATA_UNSIGNED,
1173  buf, sizeof(buf), 4, "255", 0);
1174 
1175  CALL_AND_TEST("\xFF\xFF", 2, DATA_UNSIGNED,
1176  buf, sizeof(buf), 6, "65535", 0);
1177 
1178  CALL_AND_TEST("\xFF\xFF\xFF", 3, DATA_UNSIGNED,
1179  buf, sizeof(buf), 9, "16777215", 0);
1180 
1181  CALL_AND_TEST("\xFF\xFF\xFF\xFF", 4, DATA_UNSIGNED,
1182  buf, sizeof(buf), 11, "4294967295", 0);
1183 
1184  CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF", 5, DATA_UNSIGNED,
1185  buf, sizeof(buf), 14, "1099511627775", 0);
1186 
1187  CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF", 6, DATA_UNSIGNED,
1188  buf, sizeof(buf), 16, "281474976710655", 0);
1189 
1190  CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 7, DATA_UNSIGNED,
1191  buf, sizeof(buf), 18, "72057594037927935", 0);
1192 
1193  CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8, DATA_UNSIGNED,
1194  buf, sizeof(buf), 21, "18446744073709551615", 0);
1195 
1196  /* some random values */
1197 
1198  CALL_AND_TEST("\x52", 1, 0,
1199  buf, sizeof(buf), 4, "-46", 0);
1200 
1201  CALL_AND_TEST("\x0E", 1, DATA_UNSIGNED,
1202  buf, sizeof(buf), 3, "14", 0);
1203 
1204  CALL_AND_TEST("\x62\xCE", 2, 0,
1205  buf, sizeof(buf), 6, "-7474", 0);
1206 
1207  CALL_AND_TEST("\x29\xD6", 2, DATA_UNSIGNED,
1208  buf, sizeof(buf), 6, "10710", 0);
1209 
1210  CALL_AND_TEST("\x7F\xFF\x90", 3, 0,
1211  buf, sizeof(buf), 5, "-112", 0);
1212 
1213  CALL_AND_TEST("\x00\xA1\x16", 3, DATA_UNSIGNED,
1214  buf, sizeof(buf), 6, "41238", 0);
1215 
1216  CALL_AND_TEST("\x7F\xFF\xFF\xF7", 4, 0,
1217  buf, sizeof(buf), 3, "-9", 0);
1218 
1219  CALL_AND_TEST("\x00\x00\x00\x5C", 4, DATA_UNSIGNED,
1220  buf, sizeof(buf), 3, "92", 0);
1221 
1222  CALL_AND_TEST("\x7F\xFF\xFF\xFF\xFF\xFF\xDC\x63", 8, 0,
1223  buf, sizeof(buf), 6, "-9117", 0);
1224 
1225  CALL_AND_TEST("\x00\x00\x00\x00\x00\x01\x64\x62", 8, DATA_UNSIGNED,
1226  buf, sizeof(buf), 6, "91234", 0);
1227 #endif
1228 
1229  /* speed test */
1230 
1231  speedo_reset(&speedo);
1232 
1233  for (i = 0; i < 1000000; i++) {
1234  row_raw_format_int("\x23", 1,
1235  0, buf, sizeof(buf),
1236  &format_in_hex);
1237  row_raw_format_int("\x23", 1,
1238  DATA_UNSIGNED, buf, sizeof(buf),
1239  &format_in_hex);
1240 
1241  row_raw_format_int("\x00\x00\x00\x00\x00\x01\x64\x62", 8,
1242  0, buf, sizeof(buf),
1243  &format_in_hex);
1244  row_raw_format_int("\x00\x00\x00\x00\x00\x01\x64\x62", 8,
1245  DATA_UNSIGNED, buf, sizeof(buf),
1246  &format_in_hex);
1247  }
1248 
1249  speedo_show(&speedo);
1250 }
1251 
1252 #endif /* UNIV_COMPILE_TEST_FUNCS */