~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2009-03-25 21:06:47 UTC
  • mto: This revision was merged to the branch mainline in revision 964.
  • Revision ID: mordred@inaugust.com-20090325210647-7j1tm98gvct3jxsu
Removed legacy_db_type.

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, 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
 
}