~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
General row routines
 
3
 
 
4
(c) 1996 Innobase Oy
 
5
 
 
6
Created 4/20/1996 Heikki Tuuri
 
7
*******************************************************/
 
8
 
 
9
#include "row0row.h"
 
10
 
 
11
#ifdef UNIV_NONINL
 
12
#include "row0row.ic"
 
13
#endif
 
14
 
 
15
#include "dict0dict.h"
 
16
#include "btr0btr.h"
 
17
#include "mach0data.h"
 
18
#include "trx0rseg.h"
 
19
#include "trx0trx.h"
 
20
#include "trx0roll.h"
 
21
#include "trx0undo.h"
 
22
#include "trx0purge.h"
 
23
#include "trx0rec.h"
 
24
#include "que0que.h"
 
25
#include "row0row.h"
 
26
#include "row0upd.h"
 
27
#include "rem0cmp.h"
 
28
#include "read0read.h"
 
29
 
 
30
/*************************************************************************
 
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(
 
36
/*==================*/
 
37
                                /* out: value of the field */
 
38
        ulint           type,   /* in: DATA_TRX_ID or DATA_ROLL_PTR */
 
39
        rec_t*          rec,    /* in: record */
 
40
        dict_index_t*   index,  /* in: clustered index */
 
41
        const ulint*    offsets)/* in: rec_get_offsets(rec, index) */
 
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
{
 
77
        ulint   pos;
 
78
        byte*   field;
 
79
        ulint   len;
 
80
 
 
81
        ut_ad(index->type & DICT_CLUSTERED);
 
82
        ut_ad(rec_offs_validate(rec, index, offsets));
 
83
 
 
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
        }
 
96
}
 
97
 
 
98
/*********************************************************************
 
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
 
 
102
dtuple_t*
 
103
row_build_index_entry(
 
104
/*==================*/
 
105
                                /* out: index entry which should be inserted */
 
106
        dtuple_t*       row,    /* in: row which should be inserted to the
 
107
                                table */
 
108
        dict_index_t*   index,  /* in: index on the table */
 
109
        mem_heap_t*     heap)   /* in: memory heap from which the memory for
 
110
                                the index entry is allocated */
 
111
{
 
112
        dtuple_t*       entry;
 
113
        ulint           entry_len;
 
114
        dict_field_t*   ind_field;
 
115
        dfield_t*       dfield;
 
116
        dfield_t*       dfield2;
 
117
        ulint           i;
 
118
        ulint           storage_len;
 
119
 
 
120
        ut_ad(row && index && heap);
 
121
        ut_ad(dtuple_check_typed(row));
 
122
 
 
123
        entry_len = dict_index_get_n_fields(index);
 
124
        entry = dtuple_create(heap, entry_len);
 
125
 
 
126
        if (index->type & DICT_UNIVERSAL) {
 
127
                dtuple_set_n_fields_cmp(entry, entry_len);
 
128
        } else {
 
129
                dtuple_set_n_fields_cmp(
 
130
                        entry, dict_index_get_n_unique_in_tree(index));
 
131
        }
 
132
 
 
133
        for (i = 0; i < entry_len; i++) {
 
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));
 
141
 
 
142
                dfield_copy(dfield, dfield2);
 
143
 
 
144
                /* If a column prefix index, take only the prefix */
 
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(
 
149
                                col->prtype, col->mbminlen, col->mbmaxlen,
 
150
                                ind_field->prefix_len,
 
151
                                dfield_get_len(dfield2), dfield2->data);
 
152
 
 
153
                        dfield_set_len(dfield, storage_len);
 
154
                }
 
155
        }
 
156
 
 
157
        ut_ad(dtuple_check_typed(entry));
 
158
 
 
159
        return(entry);
 
160
}
 
161
 
 
162
/***********************************************************************
 
163
An inverse function to dict_row_build_index_entry. Builds a row from a
 
164
record in a clustered index. */
 
165
 
 
166
dtuple_t*
 
167
row_build(
 
168
/*======*/
 
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 */
 
188
{
 
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_;
 
202
 
 
203
        ut_ad(index && rec && heap);
 
204
        ut_ad(index->type & DICT_CLUSTERED);
 
205
 
 
206
        if (!offsets) {
 
207
                offsets = rec_get_offsets(rec, index, offsets_,
 
208
                                          ULINT_UNDEFINED, &tmp_heap);
 
209
        } else {
 
210
                ut_ad(rec_offs_validate(rec, index, offsets));
 
211
        }
 
212
 
 
213
        if (type != ROW_COPY_POINTERS) {
 
214
                /* Take a copy of rec to heap */
 
215
                buf = mem_heap_alloc(heap, rec_offs_size(offsets));
 
216
                rec = rec_copy(buf, rec, offsets);
 
217
                /* Avoid a debug assertion in rec_offs_validate(). */
 
218
                rec_offs_make_valid(rec, index, (ulint*) offsets);
 
219
        }
 
220
 
 
221
        table = index->table;
 
222
        row_len = dict_table_get_n_cols(table);
 
223
 
 
224
        row = dtuple_create(heap, row_len);
 
225
 
 
226
        dtuple_set_info_bits(row, rec_get_info_bits(
 
227
                                     rec, dict_table_is_comp(table)));
 
228
 
 
229
        n_fields = rec_offs_n_fields(offsets);
 
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);
 
235
 
 
236
                if (ind_field->prefix_len == 0) {
 
237
 
 
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);
 
244
 
 
245
                        dfield_set_data(dfield, field, len);
 
246
                }
 
247
        }
 
248
 
 
249
        ut_ad(dtuple_check_typed(row));
 
250
 
 
251
        if (tmp_heap) {
 
252
                mem_heap_free(tmp_heap);
 
253
        }
 
254
 
 
255
        return(row);
 
256
}
 
257
 
 
258
/***********************************************************************
 
259
Converts an index record to a typed data tuple. NOTE that externally
 
260
stored (often big) fields are NOT copied to heap. */
 
261
 
 
262
dtuple_t*
 
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 */
 
281
{
 
282
        dtuple_t*       entry;
 
283
        dfield_t*       dfield;
 
284
        ulint           i;
 
285
        byte*           field;
 
286
        ulint           len;
 
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_;
 
293
 
 
294
        ut_ad(rec && heap && index);
 
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
        }
 
306
 
 
307
        rec_len = rec_offs_n_fields(offsets);
 
308
 
 
309
        entry = dtuple_create(heap, rec_len);
 
310
 
 
311
        dtuple_set_n_fields_cmp(entry,
 
312
                                dict_index_get_n_unique_in_tree(index));
 
313
        ut_ad(rec_len == dict_index_get_n_fields(index));
 
314
 
 
315
        dict_index_copy_types(entry, index, rec_len);
 
316
 
 
317
        dtuple_set_info_bits(entry,
 
318
                             rec_get_info_bits(rec, rec_offs_comp(offsets)));
 
319
 
 
320
        for (i = 0; i < rec_len; i++) {
 
321
 
 
322
                dfield = dtuple_get_nth_field(entry, i);
 
323
                field = rec_get_nth_field(rec, offsets, i, &len);
 
324
 
 
325
                dfield_set_data(dfield, field, len);
 
326
        }
 
327
 
 
328
        ut_ad(dtuple_check_typed(entry));
 
329
        if (tmp_heap) {
 
330
                mem_heap_free(tmp_heap);
 
331
        }
 
332
 
 
333
        return(entry);
 
334
}
 
335
 
 
336
/***********************************************************************
 
337
Builds from a secondary index record a row reference with which we can
 
338
search the clustered index record. */
 
339
 
 
340
dtuple_t*
 
341
row_build_row_ref(
 
342
/*==============*/
 
343
                                /* out, own: row reference built; see the
 
344
                                NOTE below! */
 
345
        ulint           type,   /* in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
 
346
                                the former copies also the data fields to
 
347
                                heap, whereas the latter only places pointers
 
348
                                to data fields on the index page */
 
349
        dict_index_t*   index,  /* in: index */
 
350
        rec_t*          rec,    /* in: record in the index;
 
351
                                NOTE: in the case ROW_COPY_POINTERS
 
352
                                the data fields in the row will point
 
353
                                directly into this record, therefore,
 
354
                                the buffer page of this record must be
 
355
                                at least s-latched and the latch held
 
356
                                as long as the row reference is used! */
 
357
        mem_heap_t*     heap)   /* in: memory heap from which the memory
 
358
                                needed is allocated */
 
359
{
 
360
        dict_table_t*   table;
 
361
        dict_index_t*   clust_index;
 
362
        dfield_t*       dfield;
 
363
        dtuple_t*       ref;
 
364
        byte*           field;
 
365
        ulint           len;
 
366
        ulint           ref_len;
 
367
        ulint           pos;
 
368
        byte*           buf;
 
369
        ulint           clust_col_prefix_len;
 
370
        ulint           i;
 
371
        mem_heap_t*     tmp_heap        = NULL;
 
372
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
 
373
        ulint*          offsets         = offsets_;
 
374
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
375
 
 
376
        ut_ad(index && rec && heap);
 
377
 
 
378
        offsets = rec_get_offsets(rec, index, offsets,
 
379
                                  ULINT_UNDEFINED, &tmp_heap);
 
380
 
 
381
        if (type == ROW_COPY_DATA) {
 
382
                /* Take a copy of rec to heap */
 
383
 
 
384
                buf = mem_heap_alloc(heap, rec_offs_size(offsets));
 
385
 
 
386
                rec = rec_copy(buf, rec, offsets);
 
387
                /* Avoid a debug assertion in rec_offs_validate(). */
 
388
                rec_offs_make_valid(rec, index, offsets);
 
389
        }
 
390
 
 
391
        table = index->table;
 
392
 
 
393
        clust_index = dict_table_get_first_index(table);
 
394
 
 
395
        ref_len = dict_index_get_n_unique(clust_index);
 
396
 
 
397
        ref = dtuple_create(heap, ref_len);
 
398
 
 
399
        dict_index_copy_types(ref, clust_index, ref_len);
 
400
 
 
401
        for (i = 0; i < ref_len; i++) {
 
402
                dfield = dtuple_get_nth_field(ref, i);
 
403
 
 
404
                pos = dict_index_get_nth_field_pos(index, clust_index, i);
 
405
 
 
406
                ut_a(pos != ULINT_UNDEFINED);
 
407
 
 
408
                field = rec_get_nth_field(rec, offsets, pos, &len);
 
409
 
 
410
                dfield_set_data(dfield, field, len);
 
411
 
 
412
                /* If the primary key contains a column prefix, then the
 
413
                secondary index may contain a longer prefix of the same
 
414
                column, or the full column, and we must adjust the length
 
415
                accordingly. */
 
416
 
 
417
                clust_col_prefix_len = dict_index_get_nth_field(
 
418
                        clust_index, i)->prefix_len;
 
419
 
 
420
                if (clust_col_prefix_len > 0) {
 
421
                        if (len != UNIV_SQL_NULL) {
 
422
 
 
423
                                const dtype_t*  dtype
 
424
                                        = dfield_get_type(dfield);
 
425
 
 
426
                                dfield_set_len(dfield,
 
427
                                               dtype_get_at_most_n_mbchars(
 
428
                                                       dtype->prtype,
 
429
                                                       dtype->mbminlen,
 
430
                                                       dtype->mbmaxlen,
 
431
                                                       clust_col_prefix_len,
 
432
                                                       len, (char*) field));
 
433
                        }
 
434
                }
 
435
        }
 
436
 
 
437
        ut_ad(dtuple_check_typed(ref));
 
438
        if (tmp_heap) {
 
439
                mem_heap_free(tmp_heap);
 
440
        }
 
441
 
 
442
        return(ref);
 
443
}
 
444
 
 
445
/***********************************************************************
 
446
Builds from a secondary index record a row reference with which we can
 
447
search the clustered index record. */
 
448
 
 
449
void
 
450
row_build_row_ref_in_tuple(
 
451
/*=======================*/
 
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 */
 
462
{
 
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_;
 
475
 
 
476
        ut_a(ref);
 
477
        ut_a(index);
 
478
        ut_a(rec);
 
479
 
 
480
        if (UNIV_UNLIKELY(!index->table)) {
 
481
                fputs("InnoDB: table ", stderr);
 
482
notfound:
 
483
                ut_print_name(stderr, trx, TRUE, index->table_name);
 
484
                fputs(" for index ", stderr);
 
485
                ut_print_name(stderr, trx, FALSE, index->name);
 
486
                fputs(" not found\n", stderr);
 
487
                ut_error;
 
488
        }
 
489
 
 
490
        clust_index = dict_table_get_first_index(index->table);
 
491
 
 
492
        if (!clust_index) {
 
493
                fputs("InnoDB: clust index for table ", stderr);
 
494
                goto notfound;
 
495
        }
 
496
 
 
497
        offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
 
498
 
 
499
        ref_len = dict_index_get_n_unique(clust_index);
 
500
 
 
501
        ut_ad(ref_len == dtuple_get_n_fields(ref));
 
502
 
 
503
        dict_index_copy_types(ref, clust_index, ref_len);
 
504
 
 
505
        for (i = 0; i < ref_len; i++) {
 
506
                dfield = dtuple_get_nth_field(ref, i);
 
507
 
 
508
                pos = dict_index_get_nth_field_pos(index, clust_index, i);
 
509
 
 
510
                ut_a(pos != ULINT_UNDEFINED);
 
511
 
 
512
                field = rec_get_nth_field(rec, offsets, pos, &len);
 
513
 
 
514
                dfield_set_data(dfield, field, len);
 
515
 
 
516
                /* If the primary key contains a column prefix, then the
 
517
                secondary index may contain a longer prefix of the same
 
518
                column, or the full column, and we must adjust the length
 
519
                accordingly. */
 
520
 
 
521
                clust_col_prefix_len = dict_index_get_nth_field(
 
522
                        clust_index, i)->prefix_len;
 
523
 
 
524
                if (clust_col_prefix_len > 0) {
 
525
                        if (len != UNIV_SQL_NULL) {
 
526
 
 
527
                                const dtype_t*  dtype
 
528
                                        = dfield_get_type(dfield);
 
529
 
 
530
                                dfield_set_len(dfield,
 
531
                                               dtype_get_at_most_n_mbchars(
 
532
                                                       dtype->prtype,
 
533
                                                       dtype->mbminlen,
 
534
                                                       dtype->mbmaxlen,
 
535
                                                       clust_col_prefix_len,
 
536
                                                       len, (char*) field));
 
537
                        }
 
538
                }
 
539
        }
 
540
 
 
541
        ut_ad(dtuple_check_typed(ref));
 
542
        if (UNIV_LIKELY_NULL(heap)) {
 
543
                mem_heap_free(heap);
 
544
        }
 
545
}
 
546
 
 
547
/***********************************************************************
 
548
From a row build a row reference with which we can search the clustered
 
549
index record. */
 
550
 
 
551
void
 
552
row_build_row_ref_from_row(
 
553
/*=======================*/
 
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 */
 
561
{
 
562
        dict_index_t*   clust_index;
 
563
        ulint           ref_len;
 
564
        ulint           i;
 
565
 
 
566
        ut_ad(ref && table && row);
 
567
 
 
568
        clust_index = dict_table_get_first_index(table);
 
569
 
 
570
        ref_len = dict_index_get_n_unique(clust_index);
 
571
 
 
572
        ut_ad(ref_len == dtuple_get_n_fields(ref));
 
573
 
 
574
        for (i = 0; i < ref_len; i++) {
 
575
                const dict_col_t*       col;
 
576
                dict_field_t*           field;
 
577
                dfield_t*               dfield;
 
578
                dfield_t*               dfield2;
 
579
 
 
580
                dfield = dtuple_get_nth_field(ref, i);
 
581
 
 
582
                field = dict_index_get_nth_field(clust_index, i);
 
583
 
 
584
                col = dict_field_get_col(field);
 
585
 
 
586
                dfield2 = dtuple_get_nth_field(row, dict_col_get_no(col));
 
587
 
 
588
                dfield_copy(dfield, dfield2);
 
589
 
 
590
                if (field->prefix_len > 0
 
591
                    && dfield->len != UNIV_SQL_NULL) {
 
592
 
 
593
                        dfield->len = dtype_get_at_most_n_mbchars(
 
594
                                col->prtype, col->mbminlen, col->mbmaxlen,
 
595
                                field->prefix_len, dfield->len, dfield->data);
 
596
                }
 
597
        }
 
598
 
 
599
        ut_ad(dtuple_check_typed(ref));
 
600
}
 
601
 
 
602
/*******************************************************************
 
603
Searches the clustered index record for a row, if we have the row reference. */
 
604
 
 
605
ibool
 
606
row_search_on_row_ref(
 
607
/*==================*/
 
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 */
 
615
{
 
616
        ulint           low_match;
 
617
        rec_t*          rec;
 
618
        dict_index_t*   index;
 
619
 
 
620
        ut_ad(dtuple_check_typed(ref));
 
621
 
 
622
        index = dict_table_get_first_index(table);
 
623
 
 
624
        ut_a(dtuple_get_n_fields(ref) == dict_index_get_n_unique(index));
 
625
 
 
626
        btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr);
 
627
 
 
628
        low_match = btr_pcur_get_low_match(pcur);
 
629
 
 
630
        rec = btr_pcur_get_rec(pcur);
 
631
 
 
632
        if (page_rec_is_infimum(rec)) {
 
633
 
 
634
                return(FALSE);
 
635
        }
 
636
 
 
637
        if (low_match != dtuple_get_n_fields(ref)) {
 
638
 
 
639
                return(FALSE);
 
640
        }
 
641
 
 
642
        return(TRUE);
 
643
}
 
644
 
 
645
/*************************************************************************
 
646
Fetches the clustered index record for a secondary index record. The latches
 
647
on the secondary index record are preserved. */
 
648
 
 
649
rec_t*
 
650
row_get_clust_rec(
 
651
/*==============*/
 
652
                                /* out: record or NULL, if no record found */
 
653
        ulint           mode,   /* in: BTR_MODIFY_LEAF, ... */
 
654
        rec_t*          rec,    /* in: record in a secondary index */
 
655
        dict_index_t*   index,  /* in: secondary index */
 
656
        dict_index_t**  clust_index,/* out: clustered index */
 
657
        mtr_t*          mtr)    /* in: mtr */
 
658
{
 
659
        mem_heap_t*     heap;
 
660
        dtuple_t*       ref;
 
661
        dict_table_t*   table;
 
662
        btr_pcur_t      pcur;
 
663
        ibool           found;
 
664
        rec_t*          clust_rec;
 
665
 
 
666
        ut_ad((index->type & DICT_CLUSTERED) == 0);
 
667
 
 
668
        table = index->table;
 
669
 
 
670
        heap = mem_heap_create(256);
 
671
 
 
672
        ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec, heap);
 
673
 
 
674
        found = row_search_on_row_ref(&pcur, mode, table, ref, mtr);
 
675
 
 
676
        clust_rec = found ? btr_pcur_get_rec(&pcur) : NULL;
 
677
 
 
678
        mem_heap_free(heap);
 
679
 
 
680
        btr_pcur_close(&pcur);
 
681
 
 
682
        *clust_index = dict_table_get_first_index(table);
 
683
 
 
684
        return(clust_rec);
 
685
}
 
686
 
 
687
/*******************************************************************
 
688
Searches an index record. */
 
689
 
 
690
ibool
 
691
row_search_index_entry(
 
692
/*===================*/
 
693
                                /* out: TRUE if found */
 
694
        dict_index_t*   index,  /* in: index */
 
695
        dtuple_t*       entry,  /* in: index entry */
 
696
        ulint           mode,   /* in: BTR_MODIFY_LEAF, ... */
 
697
        btr_pcur_t*     pcur,   /* in/out: persistent cursor, which must
 
698
                                be closed by the caller */
 
699
        mtr_t*          mtr)    /* in: mtr */
 
700
{
 
701
        ulint   n_fields;
 
702
        ulint   low_match;
 
703
        rec_t*  rec;
 
704
 
 
705
        ut_ad(dtuple_check_typed(entry));
 
706
 
 
707
        btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr);
 
708
        low_match = btr_pcur_get_low_match(pcur);
 
709
 
 
710
        rec = btr_pcur_get_rec(pcur);
 
711
 
 
712
        n_fields = dtuple_get_n_fields(entry);
 
713
 
 
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
}