~ubuntu-branches/ubuntu/saucy/drizzle/saucy-proposed

« back to all changes in this revision

Viewing changes to plugin/innobase/row/row0row.c

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2011-01-04 09:31:58 UTC
  • mfrom: (1.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20110104093158-smhgvkfdi2y9au3i
Tags: 2011.01.07-0ubuntu1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (C) 1996, 2010, Innobase Oy. 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., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/**************************************************//**
20
 
@file row/row0row.c
21
 
General row routines
22
 
 
23
 
Created 4/20/1996 Heikki Tuuri
24
 
*******************************************************/
25
 
 
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
 
/*********************************************************************//**
51
 
Gets the offset of trx id field, in bytes relative to the origin of
52
 
a clustered index record.
53
 
@return offset of DATA_TRX_ID */
54
 
UNIV_INTERN
55
 
ulint
56
 
row_get_trx_id_offset(
57
 
/*==================*/
58
 
        const rec_t*    rec __attribute__((unused)),
59
 
                                /*!< in: record */
60
 
        dict_index_t*   index,  /*!< in: clustered index */
61
 
        const ulint*    offsets)/*!< in: rec_get_offsets(rec, index) */
62
 
{
63
 
        ulint   pos;
64
 
        ulint   offset;
65
 
        ulint   len;
66
 
 
67
 
        ut_ad(dict_index_is_clust(index));
68
 
        ut_ad(rec_offs_validate(rec, index, offsets));
69
 
 
70
 
        pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
71
 
 
72
 
        offset = rec_get_nth_field_offs(offsets, pos, &len);
73
 
 
74
 
        ut_ad(len == DATA_TRX_ID_LEN);
75
 
 
76
 
        return(offset);
77
 
}
78
 
 
79
 
/*****************************************************************//**
80
 
When an insert or purge to a table is performed, this function builds
81
 
the entry to be inserted into or purged from an index on the table.
82
 
@return index entry which should be inserted or purged, or NULL if the
83
 
externally stored columns in the clustered index record are
84
 
unavailable and ext != NULL */
85
 
UNIV_INTERN
86
 
dtuple_t*
87
 
row_build_index_entry(
88
 
/*==================*/
89
 
        const dtuple_t* row,    /*!< in: row which should be
90
 
                                inserted or purged */
91
 
        row_ext_t*      ext,    /*!< in: externally stored column prefixes,
92
 
                                or NULL */
93
 
        dict_index_t*   index,  /*!< in: index on the table */
94
 
        mem_heap_t*     heap)   /*!< in: memory heap from which the memory for
95
 
                                the index entry is allocated */
96
 
{
97
 
        dtuple_t*       entry;
98
 
        ulint           entry_len;
99
 
        ulint           i;
100
 
 
101
 
        ut_ad(row && index && heap);
102
 
        ut_ad(dtuple_check_typed(row));
103
 
 
104
 
        entry_len = dict_index_get_n_fields(index);
105
 
        entry = dtuple_create(heap, entry_len);
106
 
 
107
 
        if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
108
 
                dtuple_set_n_fields_cmp(entry, entry_len);
109
 
                /* There may only be externally stored columns
110
 
                in a clustered index B-tree of a user table. */
111
 
                ut_a(!ext);
112
 
        } else {
113
 
                dtuple_set_n_fields_cmp(
114
 
                        entry, dict_index_get_n_unique_in_tree(index));
115
 
        }
116
 
 
117
 
        for (i = 0; i < entry_len; i++) {
118
 
                const dict_field_t*     ind_field
119
 
                        = dict_index_get_nth_field(index, i);
120
 
                const dict_col_t*       col
121
 
                        = ind_field->col;
122
 
                ulint                   col_no
123
 
                        = dict_col_get_no(col);
124
 
                dfield_t*               dfield
125
 
                        = dtuple_get_nth_field(entry, i);
126
 
                const dfield_t*         dfield2
127
 
                        = dtuple_get_nth_field(row, col_no);
128
 
                ulint                   len
129
 
                        = dfield_get_len(dfield2);
130
 
 
131
 
                dfield_copy(dfield, dfield2);
132
 
 
133
 
                if (dfield_is_null(dfield) || ind_field->prefix_len == 0) {
134
 
                        continue;
135
 
                }
136
 
 
137
 
                /* If a column prefix index, take only the prefix.
138
 
                Prefix-indexed columns may be externally stored. */
139
 
                ut_ad(col->ord_part);
140
 
 
141
 
                if (UNIV_LIKELY_NULL(ext)) {
142
 
                        /* See if the column is stored externally. */
143
 
                        const byte*     buf = row_ext_lookup(ext, col_no,
144
 
                                                             &len);
145
 
                        if (UNIV_LIKELY_NULL(buf)) {
146
 
                                if (UNIV_UNLIKELY(buf == field_ref_zero)) {
147
 
                                        return(NULL);
148
 
                                }
149
 
                                dfield_set_data(dfield, buf, len);
150
 
                        }
151
 
                } else if (dfield_is_ext(dfield)) {
152
 
                        ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
153
 
                        len -= BTR_EXTERN_FIELD_REF_SIZE;
154
 
                        ut_a(ind_field->prefix_len <= len
155
 
                             || dict_index_is_clust(index));
156
 
                }
157
 
 
158
 
                len = dtype_get_at_most_n_mbchars(
159
 
                        col->prtype, col->mbminmaxlen,
160
 
                        ind_field->prefix_len, len, dfield_get_data(dfield));
161
 
                dfield_set_len(dfield, len);
162
 
        }
163
 
 
164
 
        ut_ad(dtuple_check_typed(entry));
165
 
 
166
 
        return(entry);
167
 
}
168
 
 
169
 
/*******************************************************************//**
170
 
An inverse function to row_build_index_entry. Builds a row from a
171
 
record in a clustered index.
172
 
@return own: row built; see the NOTE below! */
173
 
UNIV_INTERN
174
 
dtuple_t*
175
 
row_build(
176
 
/*======*/
177
 
        ulint                   type,   /*!< in: ROW_COPY_POINTERS or
178
 
                                        ROW_COPY_DATA; the latter
179
 
                                        copies also the data fields to
180
 
                                        heap while the first only
181
 
                                        places pointers to data fields
182
 
                                        on the index page, and thus is
183
 
                                        more efficient */
184
 
        const dict_index_t*     index,  /*!< in: clustered index */
185
 
        const rec_t*            rec,    /*!< in: record in the clustered
186
 
                                        index; NOTE: in the case
187
 
                                        ROW_COPY_POINTERS the data
188
 
                                        fields in the row will point
189
 
                                        directly into this record,
190
 
                                        therefore, the buffer page of
191
 
                                        this record must be at least
192
 
                                        s-latched and the latch held
193
 
                                        as long as the row dtuple is used! */
194
 
        const ulint*            offsets,/*!< in: rec_get_offsets(rec,index)
195
 
                                        or NULL, in which case this function
196
 
                                        will invoke rec_get_offsets() */
197
 
        const dict_table_t*     col_table,
198
 
                                        /*!< in: table, to check which
199
 
                                        externally stored columns
200
 
                                        occur in the ordering columns
201
 
                                        of an index, or NULL if
202
 
                                        index->table should be
203
 
                                        consulted instead */
204
 
        row_ext_t**             ext,    /*!< out, own: cache of
205
 
                                        externally stored column
206
 
                                        prefixes, or NULL */
207
 
        mem_heap_t*             heap)   /*!< in: memory heap from which
208
 
                                        the memory needed is allocated */
209
 
{
210
 
        dtuple_t*               row;
211
 
        const dict_table_t*     table;
212
 
        ulint                   n_fields;
213
 
        ulint                   n_ext_cols;
214
 
        ulint*                  ext_cols        = NULL; /* remove warning */
215
 
        ulint                   len;
216
 
        ulint                   row_len;
217
 
        byte*                   buf;
218
 
        ulint                   i;
219
 
        ulint                   j;
220
 
        mem_heap_t*             tmp_heap        = NULL;
221
 
        ulint                   offsets_[REC_OFFS_NORMAL_SIZE];
222
 
        rec_offs_init(offsets_);
223
 
 
224
 
        ut_ad(index && rec && heap);
225
 
        ut_ad(dict_index_is_clust(index));
226
 
 
227
 
        if (!offsets) {
228
 
                offsets = rec_get_offsets(rec, index, offsets_,
229
 
                                          ULINT_UNDEFINED, &tmp_heap);
230
 
        } else {
231
 
                ut_ad(rec_offs_validate(rec, index, offsets));
232
 
        }
233
 
 
234
 
        if (type != ROW_COPY_POINTERS) {
235
 
                /* Take a copy of rec to heap */
236
 
                buf = mem_heap_alloc(heap, rec_offs_size(offsets));
237
 
                rec = rec_copy(buf, rec, offsets);
238
 
                /* Avoid a debug assertion in rec_offs_validate(). */
239
 
                rec_offs_make_valid(rec, index, (ulint*) offsets);
240
 
        }
241
 
 
242
 
        table = index->table;
243
 
        row_len = dict_table_get_n_cols(table);
244
 
 
245
 
        row = dtuple_create(heap, row_len);
246
 
 
247
 
        dict_table_copy_types(row, table);
248
 
 
249
 
        dtuple_set_info_bits(row, rec_get_info_bits(
250
 
                                     rec, dict_table_is_comp(table)));
251
 
 
252
 
        n_fields = rec_offs_n_fields(offsets);
253
 
        n_ext_cols = rec_offs_n_extern(offsets);
254
 
        if (n_ext_cols) {
255
 
                ext_cols = mem_heap_alloc(heap, n_ext_cols * sizeof *ext_cols);
256
 
        }
257
 
 
258
 
        for (i = j = 0; i < n_fields; i++) {
259
 
                dict_field_t*           ind_field
260
 
                        = dict_index_get_nth_field(index, i);
261
 
                const dict_col_t*       col
262
 
                        = dict_field_get_col(ind_field);
263
 
                ulint                   col_no
264
 
                        = dict_col_get_no(col);
265
 
                dfield_t*               dfield
266
 
                        = dtuple_get_nth_field(row, col_no);
267
 
 
268
 
                if (ind_field->prefix_len == 0) {
269
 
 
270
 
                        const byte*     field = rec_get_nth_field(
271
 
                                rec, offsets, i, &len);
272
 
 
273
 
                        dfield_set_data(dfield, field, len);
274
 
                }
275
 
 
276
 
                if (rec_offs_nth_extern(offsets, i)) {
277
 
                        dfield_set_ext(dfield);
278
 
 
279
 
                        if (UNIV_LIKELY_NULL(col_table)) {
280
 
                                ut_a(col_no
281
 
                                     < dict_table_get_n_cols(col_table));
282
 
                                col = dict_table_get_nth_col(
283
 
                                        col_table, col_no);
284
 
                        }
285
 
 
286
 
                        if (col->ord_part) {
287
 
                                /* We will have to fetch prefixes of
288
 
                                externally stored columns that are
289
 
                                referenced by column prefixes. */
290
 
                                ext_cols[j++] = col_no;
291
 
                        }
292
 
                }
293
 
        }
294
 
 
295
 
        ut_ad(dtuple_check_typed(row));
296
 
 
297
 
        if (!ext) {
298
 
                /* REDUNDANT and COMPACT formats store a local
299
 
                768-byte prefix of each externally stored
300
 
                column. No cache is needed. */
301
 
                ut_ad(dict_table_get_format(index->table)
302
 
                      < DICT_TF_FORMAT_ZIP);
303
 
        } else if (j) {
304
 
                *ext = row_ext_create(j, ext_cols, row,
305
 
                                      dict_table_zip_size(index->table),
306
 
                                      heap);
307
 
        } else {
308
 
                *ext = NULL;
309
 
        }
310
 
 
311
 
        if (tmp_heap) {
312
 
                mem_heap_free(tmp_heap);
313
 
        }
314
 
 
315
 
        return(row);
316
 
}
317
 
 
318
 
/*******************************************************************//**
319
 
Converts an index record to a typed data tuple.
320
 
@return index entry built; does not set info_bits, and the data fields
321
 
in the entry will point directly to rec */
322
 
UNIV_INTERN
323
 
dtuple_t*
324
 
row_rec_to_index_entry_low(
325
 
/*=======================*/
326
 
        const rec_t*            rec,    /*!< in: record in the index */
327
 
        const dict_index_t*     index,  /*!< in: index */
328
 
        const ulint*            offsets,/*!< in: rec_get_offsets(rec, index) */
329
 
        ulint*                  n_ext,  /*!< out: number of externally
330
 
                                        stored columns */
331
 
        mem_heap_t*             heap)   /*!< in: memory heap from which
332
 
                                        the memory needed is allocated */
333
 
{
334
 
        dtuple_t*       entry;
335
 
        dfield_t*       dfield;
336
 
        ulint           i;
337
 
        const byte*     field;
338
 
        ulint           len;
339
 
        ulint           rec_len;
340
 
 
341
 
        ut_ad(rec && heap && index);
342
 
        /* Because this function may be invoked by row0merge.c
343
 
        on a record whose header is in different format, the check
344
 
        rec_offs_validate(rec, index, offsets) must be avoided here. */
345
 
        ut_ad(n_ext);
346
 
        *n_ext = 0;
347
 
 
348
 
        rec_len = rec_offs_n_fields(offsets);
349
 
 
350
 
        entry = dtuple_create(heap, rec_len);
351
 
 
352
 
        dtuple_set_n_fields_cmp(entry,
353
 
                                dict_index_get_n_unique_in_tree(index));
354
 
        ut_ad(rec_len == dict_index_get_n_fields(index));
355
 
 
356
 
        dict_index_copy_types(entry, index, rec_len);
357
 
 
358
 
        for (i = 0; i < rec_len; i++) {
359
 
 
360
 
                dfield = dtuple_get_nth_field(entry, i);
361
 
                field = rec_get_nth_field(rec, offsets, i, &len);
362
 
 
363
 
                dfield_set_data(dfield, field, len);
364
 
 
365
 
                if (rec_offs_nth_extern(offsets, i)) {
366
 
                        dfield_set_ext(dfield);
367
 
                        (*n_ext)++;
368
 
                }
369
 
        }
370
 
 
371
 
        ut_ad(dtuple_check_typed(entry));
372
 
 
373
 
        return(entry);
374
 
}
375
 
 
376
 
/*******************************************************************//**
377
 
Converts an index record to a typed data tuple. NOTE that externally
378
 
stored (often big) fields are NOT copied to heap.
379
 
@return own: index entry built; see the NOTE below! */
380
 
UNIV_INTERN
381
 
dtuple_t*
382
 
row_rec_to_index_entry(
383
 
/*===================*/
384
 
        ulint                   type,   /*!< in: ROW_COPY_DATA, or
385
 
                                        ROW_COPY_POINTERS: the former
386
 
                                        copies also the data fields to
387
 
                                        heap as the latter only places
388
 
                                        pointers to data fields on the
389
 
                                        index page */
390
 
        const rec_t*            rec,    /*!< in: record in the index;
391
 
                                        NOTE: in the case
392
 
                                        ROW_COPY_POINTERS the data
393
 
                                        fields in the row will point
394
 
                                        directly into this record,
395
 
                                        therefore, the buffer page of
396
 
                                        this record must be at least
397
 
                                        s-latched and the latch held
398
 
                                        as long as the dtuple is used! */
399
 
        const dict_index_t*     index,  /*!< in: index */
400
 
        ulint*                  offsets,/*!< in/out: rec_get_offsets(rec) */
401
 
        ulint*                  n_ext,  /*!< out: number of externally
402
 
                                        stored columns */
403
 
        mem_heap_t*             heap)   /*!< in: memory heap from which
404
 
                                        the memory needed is allocated */
405
 
{
406
 
        dtuple_t*       entry;
407
 
        byte*           buf;
408
 
 
409
 
        ut_ad(rec && heap && index);
410
 
        ut_ad(rec_offs_validate(rec, index, offsets));
411
 
 
412
 
        if (type == ROW_COPY_DATA) {
413
 
                /* Take a copy of rec to heap */
414
 
                buf = mem_heap_alloc(heap, rec_offs_size(offsets));
415
 
                rec = rec_copy(buf, rec, offsets);
416
 
                /* Avoid a debug assertion in rec_offs_validate(). */
417
 
                rec_offs_make_valid(rec, index, offsets);
418
 
        }
419
 
 
420
 
        entry = row_rec_to_index_entry_low(rec, index, offsets, n_ext, heap);
421
 
 
422
 
        dtuple_set_info_bits(entry,
423
 
                             rec_get_info_bits(rec, rec_offs_comp(offsets)));
424
 
 
425
 
        return(entry);
426
 
}
427
 
 
428
 
/*******************************************************************//**
429
 
Builds from a secondary index record a row reference with which we can
430
 
search the clustered index record.
431
 
@return own: row reference built; see the NOTE below! */
432
 
UNIV_INTERN
433
 
dtuple_t*
434
 
row_build_row_ref(
435
 
/*==============*/
436
 
        ulint           type,   /*!< in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
437
 
                                the former copies also the data fields to
438
 
                                heap, whereas the latter only places pointers
439
 
                                to data fields on the index page */
440
 
        dict_index_t*   index,  /*!< in: secondary index */
441
 
        const rec_t*    rec,    /*!< in: record in the index;
442
 
                                NOTE: in the case ROW_COPY_POINTERS
443
 
                                the data fields in the row will point
444
 
                                directly into this record, therefore,
445
 
                                the buffer page of this record must be
446
 
                                at least s-latched and the latch held
447
 
                                as long as the row reference is used! */
448
 
        mem_heap_t*     heap)   /*!< in: memory heap from which the memory
449
 
                                needed is allocated */
450
 
{
451
 
        dict_table_t*   table;
452
 
        dict_index_t*   clust_index;
453
 
        dfield_t*       dfield;
454
 
        dtuple_t*       ref;
455
 
        const byte*     field;
456
 
        ulint           len;
457
 
        ulint           ref_len;
458
 
        ulint           pos;
459
 
        byte*           buf;
460
 
        ulint           clust_col_prefix_len;
461
 
        ulint           i;
462
 
        mem_heap_t*     tmp_heap        = NULL;
463
 
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
464
 
        ulint*          offsets         = offsets_;
465
 
        rec_offs_init(offsets_);
466
 
 
467
 
        ut_ad(index && rec && heap);
468
 
        ut_ad(!dict_index_is_clust(index));
469
 
 
470
 
        offsets = rec_get_offsets(rec, index, offsets,
471
 
                                  ULINT_UNDEFINED, &tmp_heap);
472
 
        /* Secondary indexes must not contain externally stored columns. */
473
 
        ut_ad(!rec_offs_any_extern(offsets));
474
 
 
475
 
        if (type == ROW_COPY_DATA) {
476
 
                /* Take a copy of rec to heap */
477
 
 
478
 
                buf = mem_heap_alloc(heap, rec_offs_size(offsets));
479
 
 
480
 
                rec = rec_copy(buf, rec, offsets);
481
 
                /* Avoid a debug assertion in rec_offs_validate(). */
482
 
                rec_offs_make_valid(rec, index, offsets);
483
 
        }
484
 
 
485
 
        table = index->table;
486
 
 
487
 
        clust_index = dict_table_get_first_index(table);
488
 
 
489
 
        ref_len = dict_index_get_n_unique(clust_index);
490
 
 
491
 
        ref = dtuple_create(heap, ref_len);
492
 
 
493
 
        dict_index_copy_types(ref, clust_index, ref_len);
494
 
 
495
 
        for (i = 0; i < ref_len; i++) {
496
 
                dfield = dtuple_get_nth_field(ref, i);
497
 
 
498
 
                pos = dict_index_get_nth_field_pos(index, clust_index, i);
499
 
 
500
 
                ut_a(pos != ULINT_UNDEFINED);
501
 
 
502
 
                field = rec_get_nth_field(rec, offsets, pos, &len);
503
 
 
504
 
                dfield_set_data(dfield, field, len);
505
 
 
506
 
                /* If the primary key contains a column prefix, then the
507
 
                secondary index may contain a longer prefix of the same
508
 
                column, or the full column, and we must adjust the length
509
 
                accordingly. */
510
 
 
511
 
                clust_col_prefix_len = dict_index_get_nth_field(
512
 
                        clust_index, i)->prefix_len;
513
 
 
514
 
                if (clust_col_prefix_len > 0) {
515
 
                        if (len != UNIV_SQL_NULL) {
516
 
 
517
 
                                const dtype_t*  dtype
518
 
                                        = dfield_get_type(dfield);
519
 
 
520
 
                                dfield_set_len(dfield,
521
 
                                               dtype_get_at_most_n_mbchars(
522
 
                                                       dtype->prtype,
523
 
                                                       dtype->mbminmaxlen,
524
 
                                                       clust_col_prefix_len,
525
 
                                                       len, (char*) field));
526
 
                        }
527
 
                }
528
 
        }
529
 
 
530
 
        ut_ad(dtuple_check_typed(ref));
531
 
        if (tmp_heap) {
532
 
                mem_heap_free(tmp_heap);
533
 
        }
534
 
 
535
 
        return(ref);
536
 
}
537
 
 
538
 
/*******************************************************************//**
539
 
Builds from a secondary index record a row reference with which we can
540
 
search the clustered index record. */
541
 
UNIV_INTERN
542
 
void
543
 
row_build_row_ref_in_tuple(
544
 
/*=======================*/
545
 
        dtuple_t*               ref,    /*!< in/out: row reference built;
546
 
                                        see the NOTE below! */
547
 
        const rec_t*            rec,    /*!< in: record in the index;
548
 
                                        NOTE: the data fields in ref
549
 
                                        will point directly into this
550
 
                                        record, therefore, the buffer
551
 
                                        page of this record must be at
552
 
                                        least s-latched and the latch
553
 
                                        held as long as the row
554
 
                                        reference is used! */
555
 
        const dict_index_t*     index,  /*!< in: secondary index */
556
 
        ulint*                  offsets,/*!< in: rec_get_offsets(rec, index)
557
 
                                        or NULL */
558
 
        trx_t*                  trx)    /*!< in: transaction */
559
 
{
560
 
        const dict_index_t*     clust_index;
561
 
        dfield_t*               dfield;
562
 
        const byte*             field;
563
 
        ulint                   len;
564
 
        ulint                   ref_len;
565
 
        ulint                   pos;
566
 
        ulint                   clust_col_prefix_len;
567
 
        ulint                   i;
568
 
        mem_heap_t*             heap            = NULL;
569
 
        ulint                   offsets_[REC_OFFS_NORMAL_SIZE];
570
 
        rec_offs_init(offsets_);
571
 
 
572
 
        ut_a(ref);
573
 
        ut_a(index);
574
 
        ut_a(rec);
575
 
        ut_ad(!dict_index_is_clust(index));
576
 
 
577
 
        if (UNIV_UNLIKELY(!index->table)) {
578
 
                fputs("InnoDB: table ", stderr);
579
 
notfound:
580
 
                ut_print_name(stderr, trx, TRUE, index->table_name);
581
 
                fputs(" for index ", stderr);
582
 
                ut_print_name(stderr, trx, FALSE, index->name);
583
 
                fputs(" not found\n", stderr);
584
 
                ut_error;
585
 
        }
586
 
 
587
 
        clust_index = dict_table_get_first_index(index->table);
588
 
 
589
 
        if (UNIV_UNLIKELY(!clust_index)) {
590
 
                fputs("InnoDB: clust index for table ", stderr);
591
 
                goto notfound;
592
 
        }
593
 
 
594
 
        if (!offsets) {
595
 
                offsets = rec_get_offsets(rec, index, offsets_,
596
 
                                          ULINT_UNDEFINED, &heap);
597
 
        } else {
598
 
                ut_ad(rec_offs_validate(rec, index, offsets));
599
 
        }
600
 
 
601
 
        /* Secondary indexes must not contain externally stored columns. */
602
 
        ut_ad(!rec_offs_any_extern(offsets));
603
 
        ref_len = dict_index_get_n_unique(clust_index);
604
 
 
605
 
        ut_ad(ref_len == dtuple_get_n_fields(ref));
606
 
 
607
 
        dict_index_copy_types(ref, clust_index, ref_len);
608
 
 
609
 
        for (i = 0; i < ref_len; i++) {
610
 
                dfield = dtuple_get_nth_field(ref, i);
611
 
 
612
 
                pos = dict_index_get_nth_field_pos(index, clust_index, i);
613
 
 
614
 
                ut_a(pos != ULINT_UNDEFINED);
615
 
 
616
 
                field = rec_get_nth_field(rec, offsets, pos, &len);
617
 
 
618
 
                dfield_set_data(dfield, field, len);
619
 
 
620
 
                /* If the primary key contains a column prefix, then the
621
 
                secondary index may contain a longer prefix of the same
622
 
                column, or the full column, and we must adjust the length
623
 
                accordingly. */
624
 
 
625
 
                clust_col_prefix_len = dict_index_get_nth_field(
626
 
                        clust_index, i)->prefix_len;
627
 
 
628
 
                if (clust_col_prefix_len > 0) {
629
 
                        if (len != UNIV_SQL_NULL) {
630
 
 
631
 
                                const dtype_t*  dtype
632
 
                                        = dfield_get_type(dfield);
633
 
 
634
 
                                dfield_set_len(dfield,
635
 
                                               dtype_get_at_most_n_mbchars(
636
 
                                                       dtype->prtype,
637
 
                                                       dtype->mbminmaxlen,
638
 
                                                       clust_col_prefix_len,
639
 
                                                       len, (char*) field));
640
 
                        }
641
 
                }
642
 
        }
643
 
 
644
 
        ut_ad(dtuple_check_typed(ref));
645
 
        if (UNIV_LIKELY_NULL(heap)) {
646
 
                mem_heap_free(heap);
647
 
        }
648
 
}
649
 
 
650
 
/***************************************************************//**
651
 
Searches the clustered index record for a row, if we have the row reference.
652
 
@return TRUE if found */
653
 
UNIV_INTERN
654
 
ibool
655
 
row_search_on_row_ref(
656
 
/*==================*/
657
 
        btr_pcur_t*             pcur,   /*!< out: persistent cursor, which must
658
 
                                        be closed by the caller */
659
 
        ulint                   mode,   /*!< in: BTR_MODIFY_LEAF, ... */
660
 
        const dict_table_t*     table,  /*!< in: table */
661
 
        const dtuple_t*         ref,    /*!< in: row reference */
662
 
        mtr_t*                  mtr)    /*!< in/out: mtr */
663
 
{
664
 
        ulint           low_match;
665
 
        rec_t*          rec;
666
 
        dict_index_t*   index;
667
 
 
668
 
        ut_ad(dtuple_check_typed(ref));
669
 
 
670
 
        index = dict_table_get_first_index(table);
671
 
 
672
 
        ut_a(dtuple_get_n_fields(ref) == dict_index_get_n_unique(index));
673
 
 
674
 
        btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr);
675
 
 
676
 
        low_match = btr_pcur_get_low_match(pcur);
677
 
 
678
 
        rec = btr_pcur_get_rec(pcur);
679
 
 
680
 
        if (page_rec_is_infimum(rec)) {
681
 
 
682
 
                return(FALSE);
683
 
        }
684
 
 
685
 
        if (low_match != dtuple_get_n_fields(ref)) {
686
 
 
687
 
                return(FALSE);
688
 
        }
689
 
 
690
 
        return(TRUE);
691
 
}
692
 
 
693
 
/*********************************************************************//**
694
 
Fetches the clustered index record for a secondary index record. The latches
695
 
on the secondary index record are preserved.
696
 
@return record or NULL, if no record found */
697
 
UNIV_INTERN
698
 
rec_t*
699
 
row_get_clust_rec(
700
 
/*==============*/
701
 
        ulint           mode,   /*!< in: BTR_MODIFY_LEAF, ... */
702
 
        const rec_t*    rec,    /*!< in: record in a secondary index */
703
 
        dict_index_t*   index,  /*!< in: secondary index */
704
 
        dict_index_t**  clust_index,/*!< out: clustered index */
705
 
        mtr_t*          mtr)    /*!< in: mtr */
706
 
{
707
 
        mem_heap_t*     heap;
708
 
        dtuple_t*       ref;
709
 
        dict_table_t*   table;
710
 
        btr_pcur_t      pcur;
711
 
        ibool           found;
712
 
        rec_t*          clust_rec;
713
 
 
714
 
        ut_ad(!dict_index_is_clust(index));
715
 
 
716
 
        table = index->table;
717
 
 
718
 
        heap = mem_heap_create(256);
719
 
 
720
 
        ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec, heap);
721
 
 
722
 
        found = row_search_on_row_ref(&pcur, mode, table, ref, mtr);
723
 
 
724
 
        clust_rec = found ? btr_pcur_get_rec(&pcur) : NULL;
725
 
 
726
 
        mem_heap_free(heap);
727
 
 
728
 
        btr_pcur_close(&pcur);
729
 
 
730
 
        *clust_index = dict_table_get_first_index(table);
731
 
 
732
 
        return(clust_rec);
733
 
}
734
 
 
735
 
/***************************************************************//**
736
 
Searches an index record.
737
 
@return whether the record was found or buffered */
738
 
UNIV_INTERN
739
 
enum row_search_result
740
 
row_search_index_entry(
741
 
/*===================*/
742
 
        dict_index_t*   index,  /*!< in: index */
743
 
        const dtuple_t* entry,  /*!< in: index entry */
744
 
        ulint           mode,   /*!< in: BTR_MODIFY_LEAF, ... */
745
 
        btr_pcur_t*     pcur,   /*!< in/out: persistent cursor, which must
746
 
                                be closed by the caller */
747
 
        mtr_t*          mtr)    /*!< in: mtr */
748
 
{
749
 
        ulint   n_fields;
750
 
        ulint   low_match;
751
 
        rec_t*  rec;
752
 
 
753
 
        ut_ad(dtuple_check_typed(entry));
754
 
 
755
 
        btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr);
756
 
 
757
 
        switch (btr_pcur_get_btr_cur(pcur)->flag) {
758
 
        case BTR_CUR_DELETE_REF:
759
 
                ut_a(mode & BTR_DELETE);
760
 
                return(ROW_NOT_DELETED_REF);
761
 
 
762
 
        case BTR_CUR_DEL_MARK_IBUF:
763
 
        case BTR_CUR_DELETE_IBUF:
764
 
        case BTR_CUR_INSERT_TO_IBUF:
765
 
                return(ROW_BUFFERED);
766
 
 
767
 
        case BTR_CUR_HASH:
768
 
        case BTR_CUR_HASH_FAIL:
769
 
        case BTR_CUR_BINARY:
770
 
                break;
771
 
        }
772
 
 
773
 
        low_match = btr_pcur_get_low_match(pcur);
774
 
 
775
 
        rec = btr_pcur_get_rec(pcur);
776
 
 
777
 
        n_fields = dtuple_get_n_fields(entry);
778
 
 
779
 
        if (page_rec_is_infimum(rec)) {
780
 
 
781
 
                return(ROW_NOT_FOUND);
782
 
        } else if (low_match != n_fields) {
783
 
 
784
 
                return(ROW_NOT_FOUND);
785
 
        }
786
 
 
787
 
        return(ROW_FOUND);
788
 
}
789
 
 
790
 
#if !defined(BUILD_DRIZZLE)
791
 
# include "my_sys.h"
792
 
#endif
793
 
 
794
 
 
795
 
/*******************************************************************//**
796
 
Formats the raw data in "data" (in InnoDB on-disk format) that is of
797
 
type DATA_INT using "prtype" and writes the result to "buf".
798
 
If the data is in unknown format, then nothing is written to "buf",
799
 
0 is returned and "format_in_hex" is set to TRUE, otherwise
800
 
"format_in_hex" is left untouched.
801
 
Not more than "buf_size" bytes are written to "buf".
802
 
The result is always '\0'-terminated (provided buf_size > 0) and the
803
 
number of bytes that were written to "buf" is returned (including the
804
 
terminating '\0').
805
 
@return number of bytes that were written */
806
 
static
807
 
ulint
808
 
row_raw_format_int(
809
 
/*===============*/
810
 
        const char*     data,           /*!< in: raw data */
811
 
        ulint           data_len,       /*!< in: raw data length
812
 
                                        in bytes */
813
 
        ulint           prtype,         /*!< in: precise type */
814
 
        char*           buf,            /*!< out: output buffer */
815
 
        ulint           buf_size,       /*!< in: output buffer size
816
 
                                        in bytes */
817
 
        ibool*          format_in_hex)  /*!< out: should the data be
818
 
                                        formated in hex */
819
 
{
820
 
        ulint   ret;
821
 
 
822
 
        if (data_len <= sizeof(ullint)) {
823
 
 
824
 
                ullint          value;
825
 
                ibool           unsigned_type = prtype & DATA_UNSIGNED;
826
 
 
827
 
                value = mach_read_int_type((const byte*) data,
828
 
                                           data_len, unsigned_type);
829
 
 
830
 
                if (unsigned_type) {
831
 
 
832
 
                        ret = ut_snprintf(buf, buf_size, "%llu",
833
 
                                          value) + 1;
834
 
                } else {
835
 
 
836
 
                        ret = ut_snprintf(buf, buf_size, "%lld",
837
 
                                          (long long) value) + 1;
838
 
                }
839
 
 
840
 
        } else {
841
 
 
842
 
                *format_in_hex = TRUE;
843
 
                ret = 0;
844
 
        }
845
 
 
846
 
        return(ut_min(ret, buf_size));
847
 
}
848
 
 
849
 
/*******************************************************************//**
850
 
Formats the raw data in "data" (in InnoDB on-disk format) that is of
851
 
type DATA_(CHAR|VARCHAR|MYSQL|VARMYSQL) using "prtype" and writes the
852
 
result to "buf".
853
 
If the data is in binary format, then nothing is written to "buf",
854
 
0 is returned and "format_in_hex" is set to TRUE, otherwise
855
 
"format_in_hex" is left untouched.
856
 
Not more than "buf_size" bytes are written to "buf".
857
 
The result is always '\0'-terminated (provided buf_size > 0) and the
858
 
number of bytes that were written to "buf" is returned (including the
859
 
terminating '\0').
860
 
@return number of bytes that were written */
861
 
static
862
 
ulint
863
 
row_raw_format_str(
864
 
/*===============*/
865
 
        const char*     data,           /*!< in: raw data */
866
 
        ulint           data_len,       /*!< in: raw data length
867
 
                                        in bytes */
868
 
        ulint           prtype,         /*!< in: precise type */
869
 
        char*           buf,            /*!< out: output buffer */
870
 
        ulint           buf_size,       /*!< in: output buffer size
871
 
                                        in bytes */
872
 
        ibool*          format_in_hex)  /*!< out: should the data be
873
 
                                        formated in hex */
874
 
{
875
 
        ulint   charset_coll;
876
 
 
877
 
        if (buf_size == 0) {
878
 
 
879
 
                return(0);
880
 
        }
881
 
 
882
 
        /* we assume system_charset_info is UTF-8 */
883
 
 
884
 
        charset_coll = dtype_get_charset_coll(prtype);
885
 
 
886
 
        if (UNIV_LIKELY(dtype_is_utf8(prtype))) {
887
 
 
888
 
                return(ut_str_sql_format(data, data_len, buf, buf_size));
889
 
        }
890
 
        /* else */
891
 
 
892
 
        if (charset_coll == DATA_MYSQL_BINARY_CHARSET_COLL) {
893
 
 
894
 
                *format_in_hex = TRUE;
895
 
                return(0);
896
 
        }
897
 
        /* else */
898
 
 
899
 
        return(innobase_raw_format(data, data_len, charset_coll,
900
 
                                          buf, buf_size));
901
 
}
902
 
 
903
 
/*******************************************************************//**
904
 
Formats the raw data in "data" (in InnoDB on-disk format) using
905
 
"dict_field" and writes the result to "buf".
906
 
Not more than "buf_size" bytes are written to "buf".
907
 
The result is always NUL-terminated (provided buf_size is positive) and the
908
 
number of bytes that were written to "buf" is returned (including the
909
 
terminating NUL).
910
 
@return number of bytes that were written */
911
 
UNIV_INTERN
912
 
ulint
913
 
row_raw_format(
914
 
/*===========*/
915
 
        const char*             data,           /*!< in: raw data */
916
 
        ulint                   data_len,       /*!< in: raw data length
917
 
                                                in bytes */
918
 
        const dict_field_t*     dict_field,     /*!< in: index field */
919
 
        char*                   buf,            /*!< out: output buffer */
920
 
        ulint                   buf_size)       /*!< in: output buffer size
921
 
                                                in bytes */
922
 
{
923
 
        ulint   mtype;
924
 
        ulint   prtype;
925
 
        ulint   ret= 0;
926
 
        ibool   format_in_hex;
927
 
 
928
 
        if (buf_size == 0) {
929
 
 
930
 
                return(ret);
931
 
        }
932
 
 
933
 
        if (data_len == UNIV_SQL_NULL) {
934
 
 
935
 
                ret = ut_snprintf((char*) buf, buf_size, "NULL") + 1;
936
 
 
937
 
                return(ut_min(ret, buf_size));
938
 
        }
939
 
 
940
 
        mtype = dict_field->col->mtype;
941
 
        prtype = dict_field->col->prtype;
942
 
 
943
 
        format_in_hex = FALSE;
944
 
 
945
 
        switch (mtype) {
946
 
        case DATA_INT:
947
 
 
948
 
                ret = row_raw_format_int(data, data_len, prtype,
949
 
                                         buf, buf_size, &format_in_hex);
950
 
                if (format_in_hex) {
951
 
 
952
 
                        goto format_in_hex;
953
 
                }
954
 
                break;
955
 
        case DATA_CHAR:
956
 
        case DATA_VARCHAR:
957
 
        case DATA_MYSQL:
958
 
        case DATA_VARMYSQL:
959
 
 
960
 
                ret = row_raw_format_str(data, data_len, prtype,
961
 
                                         buf, buf_size, &format_in_hex);
962
 
                if (format_in_hex) {
963
 
 
964
 
                        goto format_in_hex;
965
 
                }
966
 
 
967
 
                break;
968
 
        /* XXX support more data types */
969
 
        default:
970
 
        format_in_hex:
971
 
 
972
 
                if (UNIV_LIKELY(buf_size > 2)) {
973
 
 
974
 
                        memcpy(buf, "0x", 2);
975
 
                        buf += 2;
976
 
                        buf_size -= 2;
977
 
                        ret = 2 + ut_raw_to_hex(data, data_len,
978
 
                                                buf, buf_size);
979
 
                } else {
980
 
 
981
 
                        buf[0] = '\0';
982
 
                        ret = 1;
983
 
                }
984
 
        }
985
 
 
986
 
        return(ret);
987
 
}
988
 
 
989
 
#ifdef UNIV_COMPILE_TEST_FUNCS
990
 
 
991
 
#include "ut0dbg.h"
992
 
 
993
 
void
994
 
test_row_raw_format_int()
995
 
{
996
 
        ulint   ret;
997
 
        char    buf[128];
998
 
        ibool   format_in_hex;
999
 
 
1000
 
#define CALL_AND_TEST(data, data_len, prtype, buf, buf_size,\
1001
 
                      ret_expected, buf_expected, format_in_hex_expected)\
1002
 
        do {\
1003
 
                ibool   ok = TRUE;\
1004
 
                ulint   i;\
1005
 
                memset(buf, 'x', 10);\
1006
 
                buf[10] = '\0';\
1007
 
                format_in_hex = FALSE;\
1008
 
                fprintf(stderr, "TESTING \"\\x");\
1009
 
                for (i = 0; i < data_len; i++) {\
1010
 
                        fprintf(stderr, "%02hhX", data[i]);\
1011
 
                }\
1012
 
                fprintf(stderr, "\", %lu, %lu, %lu\n",\
1013
 
                        (ulint) data_len, (ulint) prtype,\
1014
 
                        (ulint) buf_size);\
1015
 
                ret = row_raw_format_int(data, data_len, prtype,\
1016
 
                                         buf, buf_size, &format_in_hex);\
1017
 
                if (ret != ret_expected) {\
1018
 
                        fprintf(stderr, "expected ret %lu, got %lu\n",\
1019
 
                                (ulint) ret_expected, ret);\
1020
 
                        ok = FALSE;\
1021
 
                }\
1022
 
                if (strcmp((char*) buf, buf_expected) != 0) {\
1023
 
                        fprintf(stderr, "expected buf \"%s\", got \"%s\"\n",\
1024
 
                                buf_expected, buf);\
1025
 
                        ok = FALSE;\
1026
 
                }\
1027
 
                if (format_in_hex != format_in_hex_expected) {\
1028
 
                        fprintf(stderr, "expected format_in_hex %d, got %d\n",\
1029
 
                                (int) format_in_hex_expected,\
1030
 
                                (int) format_in_hex);\
1031
 
                        ok = FALSE;\
1032
 
                }\
1033
 
                if (ok) {\
1034
 
                        fprintf(stderr, "OK: %lu, \"%s\" %d\n\n",\
1035
 
                                (ulint) ret, buf, (int) format_in_hex);\
1036
 
                } else {\
1037
 
                        return;\
1038
 
                }\
1039
 
        } while (0)
1040
 
 
1041
 
#if 1
1042
 
        /* min values for signed 1-8 byte integers */
1043
 
 
1044
 
        CALL_AND_TEST("\x00", 1, 0,
1045
 
                      buf, sizeof(buf), 5, "-128", 0);
1046
 
 
1047
 
        CALL_AND_TEST("\x00\x00", 2, 0,
1048
 
                      buf, sizeof(buf), 7, "-32768", 0);
1049
 
 
1050
 
        CALL_AND_TEST("\x00\x00\x00", 3, 0,
1051
 
                      buf, sizeof(buf), 9, "-8388608", 0);
1052
 
 
1053
 
        CALL_AND_TEST("\x00\x00\x00\x00", 4, 0,
1054
 
                      buf, sizeof(buf), 12, "-2147483648", 0);
1055
 
 
1056
 
        CALL_AND_TEST("\x00\x00\x00\x00\x00", 5, 0,
1057
 
                      buf, sizeof(buf), 14, "-549755813888", 0);
1058
 
 
1059
 
        CALL_AND_TEST("\x00\x00\x00\x00\x00\x00", 6, 0,
1060
 
                      buf, sizeof(buf), 17, "-140737488355328", 0);
1061
 
 
1062
 
        CALL_AND_TEST("\x00\x00\x00\x00\x00\x00\x00", 7, 0,
1063
 
                      buf, sizeof(buf), 19, "-36028797018963968", 0);
1064
 
 
1065
 
        CALL_AND_TEST("\x00\x00\x00\x00\x00\x00\x00\x00", 8, 0,
1066
 
                      buf, sizeof(buf), 21, "-9223372036854775808", 0);
1067
 
 
1068
 
        /* min values for unsigned 1-8 byte integers */
1069
 
 
1070
 
        CALL_AND_TEST("\x00", 1, DATA_UNSIGNED,
1071
 
                      buf, sizeof(buf), 2, "0", 0);
1072
 
 
1073
 
        CALL_AND_TEST("\x00\x00", 2, DATA_UNSIGNED,
1074
 
                      buf, sizeof(buf), 2, "0", 0);
1075
 
 
1076
 
        CALL_AND_TEST("\x00\x00\x00", 3, DATA_UNSIGNED,
1077
 
                      buf, sizeof(buf), 2, "0", 0);
1078
 
 
1079
 
        CALL_AND_TEST("\x00\x00\x00\x00", 4, DATA_UNSIGNED,
1080
 
                      buf, sizeof(buf), 2, "0", 0);
1081
 
 
1082
 
        CALL_AND_TEST("\x00\x00\x00\x00\x00", 5, DATA_UNSIGNED,
1083
 
                      buf, sizeof(buf), 2, "0", 0);
1084
 
 
1085
 
        CALL_AND_TEST("\x00\x00\x00\x00\x00\x00", 6, DATA_UNSIGNED,
1086
 
                      buf, sizeof(buf), 2, "0", 0);
1087
 
 
1088
 
        CALL_AND_TEST("\x00\x00\x00\x00\x00\x00\x00", 7, DATA_UNSIGNED,
1089
 
                      buf, sizeof(buf), 2, "0", 0);
1090
 
 
1091
 
        CALL_AND_TEST("\x00\x00\x00\x00\x00\x00\x00\x00", 8, DATA_UNSIGNED,
1092
 
                      buf, sizeof(buf), 2, "0", 0);
1093
 
 
1094
 
        /* max values for signed 1-8 byte integers */
1095
 
 
1096
 
        CALL_AND_TEST("\xFF", 1, 0,
1097
 
                      buf, sizeof(buf), 4, "127", 0);
1098
 
 
1099
 
        CALL_AND_TEST("\xFF\xFF", 2, 0,
1100
 
                      buf, sizeof(buf), 6, "32767", 0);
1101
 
 
1102
 
        CALL_AND_TEST("\xFF\xFF\xFF", 3, 0,
1103
 
                      buf, sizeof(buf), 8, "8388607", 0);
1104
 
 
1105
 
        CALL_AND_TEST("\xFF\xFF\xFF\xFF", 4, 0,
1106
 
                      buf, sizeof(buf), 11, "2147483647", 0);
1107
 
 
1108
 
        CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF", 5, 0,
1109
 
                      buf, sizeof(buf), 13, "549755813887", 0);
1110
 
 
1111
 
        CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF", 6, 0,
1112
 
                      buf, sizeof(buf), 16, "140737488355327", 0);
1113
 
 
1114
 
        CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 7, 0,
1115
 
                      buf, sizeof(buf), 18, "36028797018963967", 0);
1116
 
 
1117
 
        CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8, 0,
1118
 
                      buf, sizeof(buf), 20, "9223372036854775807", 0);
1119
 
 
1120
 
        /* max values for unsigned 1-8 byte integers */
1121
 
 
1122
 
        CALL_AND_TEST("\xFF", 1, DATA_UNSIGNED,
1123
 
                      buf, sizeof(buf), 4, "255", 0);
1124
 
 
1125
 
        CALL_AND_TEST("\xFF\xFF", 2, DATA_UNSIGNED,
1126
 
                      buf, sizeof(buf), 6, "65535", 0);
1127
 
 
1128
 
        CALL_AND_TEST("\xFF\xFF\xFF", 3, DATA_UNSIGNED,
1129
 
                      buf, sizeof(buf), 9, "16777215", 0);
1130
 
 
1131
 
        CALL_AND_TEST("\xFF\xFF\xFF\xFF", 4, DATA_UNSIGNED,
1132
 
                      buf, sizeof(buf), 11, "4294967295", 0);
1133
 
 
1134
 
        CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF", 5, DATA_UNSIGNED,
1135
 
                      buf, sizeof(buf), 14, "1099511627775", 0);
1136
 
 
1137
 
        CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF", 6, DATA_UNSIGNED,
1138
 
                      buf, sizeof(buf), 16, "281474976710655", 0);
1139
 
 
1140
 
        CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 7, DATA_UNSIGNED,
1141
 
                      buf, sizeof(buf), 18, "72057594037927935", 0);
1142
 
 
1143
 
        CALL_AND_TEST("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8, DATA_UNSIGNED,
1144
 
                      buf, sizeof(buf), 21, "18446744073709551615", 0);
1145
 
 
1146
 
        /* some random values */
1147
 
 
1148
 
        CALL_AND_TEST("\x52", 1, 0,
1149
 
                      buf, sizeof(buf), 4, "-46", 0);
1150
 
 
1151
 
        CALL_AND_TEST("\x0E", 1, DATA_UNSIGNED,
1152
 
                      buf, sizeof(buf), 3, "14", 0);
1153
 
 
1154
 
        CALL_AND_TEST("\x62\xCE", 2, 0,
1155
 
                      buf, sizeof(buf), 6, "-7474", 0);
1156
 
 
1157
 
        CALL_AND_TEST("\x29\xD6", 2, DATA_UNSIGNED,
1158
 
                      buf, sizeof(buf), 6, "10710", 0);
1159
 
 
1160
 
        CALL_AND_TEST("\x7F\xFF\x90", 3, 0,
1161
 
                      buf, sizeof(buf), 5, "-112", 0);
1162
 
 
1163
 
        CALL_AND_TEST("\x00\xA1\x16", 3, DATA_UNSIGNED,
1164
 
                      buf, sizeof(buf), 6, "41238", 0);
1165
 
 
1166
 
        CALL_AND_TEST("\x7F\xFF\xFF\xF7", 4, 0,
1167
 
                      buf, sizeof(buf), 3, "-9", 0);
1168
 
 
1169
 
        CALL_AND_TEST("\x00\x00\x00\x5C", 4, DATA_UNSIGNED,
1170
 
                      buf, sizeof(buf), 3, "92", 0);
1171
 
 
1172
 
        CALL_AND_TEST("\x7F\xFF\xFF\xFF\xFF\xFF\xDC\x63", 8, 0,
1173
 
                      buf, sizeof(buf), 6, "-9117", 0);
1174
 
 
1175
 
        CALL_AND_TEST("\x00\x00\x00\x00\x00\x01\x64\x62", 8, DATA_UNSIGNED,
1176
 
                      buf, sizeof(buf), 6, "91234", 0);
1177
 
#endif
1178
 
 
1179
 
        /* speed test */
1180
 
 
1181
 
        speedo_t        speedo;
1182
 
        ulint           i;
1183
 
 
1184
 
        speedo_reset(&speedo);
1185
 
 
1186
 
        for (i = 0; i < 1000000; i++) {
1187
 
                row_raw_format_int("\x23", 1,
1188
 
                                   0, buf, sizeof(buf),
1189
 
                                   &format_in_hex);
1190
 
                row_raw_format_int("\x23", 1,
1191
 
                                   DATA_UNSIGNED, buf, sizeof(buf),
1192
 
                                   &format_in_hex);
1193
 
 
1194
 
                row_raw_format_int("\x00\x00\x00\x00\x00\x01\x64\x62", 8,
1195
 
                                   0, buf, sizeof(buf),
1196
 
                                   &format_in_hex);
1197
 
                row_raw_format_int("\x00\x00\x00\x00\x00\x01\x64\x62", 8,
1198
 
                                   DATA_UNSIGNED, buf, sizeof(buf),
1199
 
                                   &format_in_hex);
1200
 
        }
1201
 
 
1202
 
        speedo_show(&speedo);
1203
 
}
1204
 
 
1205
 
#endif /* UNIV_COMPILE_TEST_FUNCS */