~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Renamed strings to mystrings, for include/lib naming consistency.

Show diffs side-by-side

added added

removed removed

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