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

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/mtr/mtr0log.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
 
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
 
4
 
 
5
This program is free software; you can redistribute it and/or modify it under
 
6
the terms of the GNU General Public License as published by the Free Software
 
7
Foundation; version 2 of the License.
 
8
 
 
9
This program is distributed in the hope that it will be useful, but WITHOUT
 
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
12
 
 
13
You should have received a copy of the GNU General Public License along with
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
 
16
 
 
17
*****************************************************************************/
 
18
 
 
19
/**************************************************//**
 
20
@file mtr/mtr0log.c
 
21
Mini-transaction log routines
 
22
 
 
23
Created 12/7/1995 Heikki Tuuri
 
24
*******************************************************/
 
25
 
 
26
#include "mtr0log.h"
 
27
 
 
28
#ifdef UNIV_NONINL
 
29
#include "mtr0log.ic"
 
30
#endif
 
31
 
 
32
#include "buf0buf.h"
 
33
#include "dict0dict.h"
 
34
#include "log0recv.h"
 
35
#include "page0page.h"
 
36
 
 
37
#ifndef UNIV_HOTBACKUP
 
38
# include "dict0boot.h"
 
39
 
 
40
/********************************************************//**
 
41
Catenates n bytes to the mtr log. */
 
42
UNIV_INTERN
 
43
void
 
44
mlog_catenate_string(
 
45
/*=================*/
 
46
        mtr_t*          mtr,    /*!< in: mtr */
 
47
        const byte*     str,    /*!< in: string to write */
 
48
        ulint           len)    /*!< in: string length */
 
49
{
 
50
        dyn_array_t*    mlog;
 
51
 
 
52
        if (mtr_get_log_mode(mtr) == MTR_LOG_NONE) {
 
53
 
 
54
                return;
 
55
        }
 
56
 
 
57
        mlog = &(mtr->log);
 
58
 
 
59
        dyn_push_string(mlog, str, len);
 
60
}
 
61
 
 
62
/********************************************************//**
 
63
Writes the initial part of a log record consisting of one-byte item
 
64
type and four-byte space and page numbers. Also pushes info
 
65
to the mtr memo that a buffer page has been modified. */
 
66
UNIV_INTERN
 
67
void
 
68
mlog_write_initial_log_record(
 
69
/*==========================*/
 
70
        const byte*     ptr,    /*!< in: pointer to (inside) a buffer
 
71
                                frame holding the file page where
 
72
                                modification is made */
 
73
        byte            type,   /*!< in: log item type: MLOG_1BYTE, ... */
 
74
        mtr_t*          mtr)    /*!< in: mini-transaction handle */
 
75
{
 
76
        byte*   log_ptr;
 
77
 
 
78
        ut_ad(type <= MLOG_BIGGEST_TYPE);
 
79
        ut_ad(type > MLOG_8BYTES);
 
80
 
 
81
        log_ptr = mlog_open(mtr, 11);
 
82
 
 
83
        /* If no logging is requested, we may return now */
 
84
        if (log_ptr == NULL) {
 
85
 
 
86
                return;
 
87
        }
 
88
 
 
89
        log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr);
 
90
 
 
91
        mlog_close(mtr, log_ptr);
 
92
}
 
93
#endif /* !UNIV_HOTBACKUP */
 
94
 
 
95
/********************************************************//**
 
96
Parses an initial log record written by mlog_write_initial_log_record.
 
97
@return parsed record end, NULL if not a complete record */
 
98
UNIV_INTERN
 
99
byte*
 
100
mlog_parse_initial_log_record(
 
101
/*==========================*/
 
102
        byte*   ptr,    /*!< in: buffer */
 
103
        byte*   end_ptr,/*!< in: buffer end */
 
104
        byte*   type,   /*!< out: log record type: MLOG_1BYTE, ... */
 
105
        ulint*  space,  /*!< out: space id */
 
106
        ulint*  page_no)/*!< out: page number */
 
107
{
 
108
        if (end_ptr < ptr + 1) {
 
109
 
 
110
                return(NULL);
 
111
        }
 
112
 
 
113
        *type = (byte)((ulint)*ptr & ~MLOG_SINGLE_REC_FLAG);
 
114
        ut_ad(*type <= MLOG_BIGGEST_TYPE);
 
115
 
 
116
        ptr++;
 
117
 
 
118
        if (end_ptr < ptr + 2) {
 
119
 
 
120
                return(NULL);
 
121
        }
 
122
 
 
123
        ptr = mach_parse_compressed(ptr, end_ptr, space);
 
124
 
 
125
        if (ptr == NULL) {
 
126
 
 
127
                return(NULL);
 
128
        }
 
129
 
 
130
        ptr = mach_parse_compressed(ptr, end_ptr, page_no);
 
131
 
 
132
        return(ptr);
 
133
}
 
134
 
 
135
/********************************************************//**
 
136
Parses a log record written by mlog_write_ulint or mlog_write_dulint.
 
137
@return parsed record end, NULL if not a complete record or a corrupt record */
 
138
UNIV_INTERN
 
139
byte*
 
140
mlog_parse_nbytes(
 
141
/*==============*/
 
142
        ulint   type,   /*!< in: log record type: MLOG_1BYTE, ... */
 
143
        byte*   ptr,    /*!< in: buffer */
 
144
        byte*   end_ptr,/*!< in: buffer end */
 
145
        byte*   page,   /*!< in: page where to apply the log record, or NULL */
 
146
        void*   page_zip)/*!< in/out: compressed page, or NULL */
 
147
{
 
148
        ulint   offset;
 
149
        ulint   val;
 
150
        dulint  dval;
 
151
 
 
152
        ut_a(type <= MLOG_8BYTES);
 
153
        ut_a(!page || !page_zip || fil_page_get_type(page) != FIL_PAGE_INDEX);
 
154
 
 
155
        if (end_ptr < ptr + 2) {
 
156
 
 
157
                return(NULL);
 
158
        }
 
159
 
 
160
        offset = mach_read_from_2(ptr);
 
161
        ptr += 2;
 
162
 
 
163
        if (offset >= UNIV_PAGE_SIZE) {
 
164
                recv_sys->found_corrupt_log = TRUE;
 
165
 
 
166
                return(NULL);
 
167
        }
 
168
 
 
169
        if (type == MLOG_8BYTES) {
 
170
                ptr = mach_dulint_parse_compressed(ptr, end_ptr, &dval);
 
171
 
 
172
                if (ptr == NULL) {
 
173
 
 
174
                        return(NULL);
 
175
                }
 
176
 
 
177
                if (page) {
 
178
                        if (UNIV_LIKELY_NULL(page_zip)) {
 
179
                                mach_write_to_8
 
180
                                        (((page_zip_des_t*) page_zip)->data
 
181
                                         + offset, dval);
 
182
                        }
 
183
                        mach_write_to_8(page + offset, dval);
 
184
                }
 
185
 
 
186
                return(ptr);
 
187
        }
 
188
 
 
189
        ptr = mach_parse_compressed(ptr, end_ptr, &val);
 
190
 
 
191
        if (ptr == NULL) {
 
192
 
 
193
                return(NULL);
 
194
        }
 
195
 
 
196
        switch (type) {
 
197
        case MLOG_1BYTE:
 
198
                if (UNIV_UNLIKELY(val > 0xFFUL)) {
 
199
                        goto corrupt;
 
200
                }
 
201
                if (page) {
 
202
                        if (UNIV_LIKELY_NULL(page_zip)) {
 
203
                                mach_write_to_1
 
204
                                        (((page_zip_des_t*) page_zip)->data
 
205
                                         + offset, val);
 
206
                        }
 
207
                        mach_write_to_1(page + offset, val);
 
208
                }
 
209
                break;
 
210
        case MLOG_2BYTES:
 
211
                if (UNIV_UNLIKELY(val > 0xFFFFUL)) {
 
212
                        goto corrupt;
 
213
                }
 
214
                if (page) {
 
215
                        if (UNIV_LIKELY_NULL(page_zip)) {
 
216
                                mach_write_to_2
 
217
                                        (((page_zip_des_t*) page_zip)->data
 
218
                                         + offset, val);
 
219
                        }
 
220
                        mach_write_to_2(page + offset, val);
 
221
                }
 
222
                break;
 
223
        case MLOG_4BYTES:
 
224
                if (page) {
 
225
                        if (UNIV_LIKELY_NULL(page_zip)) {
 
226
                                mach_write_to_4
 
227
                                        (((page_zip_des_t*) page_zip)->data
 
228
                                         + offset, val);
 
229
                        }
 
230
                        mach_write_to_4(page + offset, val);
 
231
                }
 
232
                break;
 
233
        default:
 
234
        corrupt:
 
235
                recv_sys->found_corrupt_log = TRUE;
 
236
                ptr = NULL;
 
237
        }
 
238
 
 
239
        return(ptr);
 
240
}
 
241
 
 
242
/********************************************************//**
 
243
Writes 1 - 4 bytes to a file page buffered in the buffer pool.
 
244
Writes the corresponding log record to the mini-transaction log. */
 
245
UNIV_INTERN
 
246
void
 
247
mlog_write_ulint(
 
248
/*=============*/
 
249
        byte*   ptr,    /*!< in: pointer where to write */
 
250
        ulint   val,    /*!< in: value to write */
 
251
        byte    type,   /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
 
252
        mtr_t*  mtr)    /*!< in: mini-transaction handle */
 
253
{
 
254
        byte*   log_ptr;
 
255
 
 
256
        switch (type) {
 
257
        case MLOG_1BYTE:
 
258
                mach_write_to_1(ptr, val);
 
259
                break;
 
260
        case MLOG_2BYTES:
 
261
                mach_write_to_2(ptr, val);
 
262
                break;
 
263
        case MLOG_4BYTES:
 
264
                mach_write_to_4(ptr, val);
 
265
                break;
 
266
        default:
 
267
                ut_error;
 
268
        }
 
269
 
 
270
        log_ptr = mlog_open(mtr, 11 + 2 + 5);
 
271
 
 
272
        /* If no logging is requested, we may return now */
 
273
        if (log_ptr == NULL) {
 
274
 
 
275
                return;
 
276
        }
 
277
 
 
278
        log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr);
 
279
 
 
280
        mach_write_to_2(log_ptr, page_offset(ptr));
 
281
        log_ptr += 2;
 
282
 
 
283
        log_ptr += mach_write_compressed(log_ptr, val);
 
284
 
 
285
        mlog_close(mtr, log_ptr);
 
286
}
 
287
 
 
288
/********************************************************//**
 
289
Writes 8 bytes to a file page buffered in the buffer pool.
 
290
Writes the corresponding log record to the mini-transaction log. */
 
291
UNIV_INTERN
 
292
void
 
293
mlog_write_dulint(
 
294
/*==============*/
 
295
        byte*   ptr,    /*!< in: pointer where to write */
 
296
        dulint  val,    /*!< in: value to write */
 
297
        mtr_t*  mtr)    /*!< in: mini-transaction handle */
 
298
{
 
299
        byte*   log_ptr;
 
300
 
 
301
        ut_ad(ptr && mtr);
 
302
 
 
303
        mach_write_to_8(ptr, val);
 
304
 
 
305
        log_ptr = mlog_open(mtr, 11 + 2 + 9);
 
306
 
 
307
        /* If no logging is requested, we may return now */
 
308
        if (log_ptr == NULL) {
 
309
 
 
310
                return;
 
311
        }
 
312
 
 
313
        log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_8BYTES,
 
314
                                                     log_ptr, mtr);
 
315
 
 
316
        mach_write_to_2(log_ptr, page_offset(ptr));
 
317
        log_ptr += 2;
 
318
 
 
319
        log_ptr += mach_dulint_write_compressed(log_ptr, val);
 
320
 
 
321
        mlog_close(mtr, log_ptr);
 
322
}
 
323
 
 
324
#ifndef UNIV_HOTBACKUP
 
325
/********************************************************//**
 
326
Writes a string to a file page buffered in the buffer pool. Writes the
 
327
corresponding log record to the mini-transaction log. */
 
328
UNIV_INTERN
 
329
void
 
330
mlog_write_string(
 
331
/*==============*/
 
332
        byte*           ptr,    /*!< in: pointer where to write */
 
333
        const byte*     str,    /*!< in: string to write */
 
334
        ulint           len,    /*!< in: string length */
 
335
        mtr_t*          mtr)    /*!< in: mini-transaction handle */
 
336
{
 
337
        ut_ad(ptr && mtr);
 
338
        ut_a(len < UNIV_PAGE_SIZE);
 
339
 
 
340
        memcpy(ptr, str, len);
 
341
 
 
342
        mlog_log_string(ptr, len, mtr);
 
343
}
 
344
 
 
345
/********************************************************//**
 
346
Logs a write of a string to a file page buffered in the buffer pool.
 
347
Writes the corresponding log record to the mini-transaction log. */
 
348
UNIV_INTERN
 
349
void
 
350
mlog_log_string(
 
351
/*============*/
 
352
        byte*   ptr,    /*!< in: pointer written to */
 
353
        ulint   len,    /*!< in: string length */
 
354
        mtr_t*  mtr)    /*!< in: mini-transaction handle */
 
355
{
 
356
        byte*   log_ptr;
 
357
 
 
358
        ut_ad(ptr && mtr);
 
359
        ut_ad(len <= UNIV_PAGE_SIZE);
 
360
 
 
361
        log_ptr = mlog_open(mtr, 30);
 
362
 
 
363
        /* If no logging is requested, we may return now */
 
364
        if (log_ptr == NULL) {
 
365
 
 
366
                return;
 
367
        }
 
368
 
 
369
        log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_WRITE_STRING,
 
370
                                                     log_ptr, mtr);
 
371
        mach_write_to_2(log_ptr, page_offset(ptr));
 
372
        log_ptr += 2;
 
373
 
 
374
        mach_write_to_2(log_ptr, len);
 
375
        log_ptr += 2;
 
376
 
 
377
        mlog_close(mtr, log_ptr);
 
378
 
 
379
        mlog_catenate_string(mtr, ptr, len);
 
380
}
 
381
#endif /* !UNIV_HOTBACKUP */
 
382
 
 
383
/********************************************************//**
 
384
Parses a log record written by mlog_write_string.
 
385
@return parsed record end, NULL if not a complete record */
 
386
UNIV_INTERN
 
387
byte*
 
388
mlog_parse_string(
 
389
/*==============*/
 
390
        byte*   ptr,    /*!< in: buffer */
 
391
        byte*   end_ptr,/*!< in: buffer end */
 
392
        byte*   page,   /*!< in: page where to apply the log record, or NULL */
 
393
        void*   page_zip)/*!< in/out: compressed page, or NULL */
 
394
{
 
395
        ulint   offset;
 
396
        ulint   len;
 
397
 
 
398
        ut_a(!page || !page_zip || fil_page_get_type(page) != FIL_PAGE_INDEX);
 
399
 
 
400
        if (end_ptr < ptr + 4) {
 
401
 
 
402
                return(NULL);
 
403
        }
 
404
 
 
405
        offset = mach_read_from_2(ptr);
 
406
        ptr += 2;
 
407
        len = mach_read_from_2(ptr);
 
408
        ptr += 2;
 
409
 
 
410
        if (UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)
 
411
                        || UNIV_UNLIKELY(len + offset) > UNIV_PAGE_SIZE) {
 
412
                recv_sys->found_corrupt_log = TRUE;
 
413
 
 
414
                return(NULL);
 
415
        }
 
416
 
 
417
        if (end_ptr < ptr + len) {
 
418
 
 
419
                return(NULL);
 
420
        }
 
421
 
 
422
        if (page) {
 
423
                if (UNIV_LIKELY_NULL(page_zip)) {
 
424
                        memcpy(((page_zip_des_t*) page_zip)->data
 
425
                                + offset, ptr, len);
 
426
                }
 
427
                memcpy(page + offset, ptr, len);
 
428
        }
 
429
 
 
430
        return(ptr + len);
 
431
}
 
432
 
 
433
#ifndef UNIV_HOTBACKUP
 
434
/********************************************************//**
 
435
Opens a buffer for mlog, writes the initial log record and,
 
436
if needed, the field lengths of an index.
 
437
@return buffer, NULL if log mode MTR_LOG_NONE */
 
438
UNIV_INTERN
 
439
byte*
 
440
mlog_open_and_write_index(
 
441
/*======================*/
 
442
        mtr_t*          mtr,    /*!< in: mtr */
 
443
        const byte*     rec,    /*!< in: index record or page */
 
444
        dict_index_t*   index,  /*!< in: record descriptor */
 
445
        byte            type,   /*!< in: log item type */
 
446
        ulint           size)   /*!< in: requested buffer size in bytes
 
447
                                (if 0, calls mlog_close() and returns NULL) */
 
448
{
 
449
        byte*           log_ptr;
 
450
        const byte*     log_start;
 
451
        const byte*     log_end;
 
452
 
 
453
        ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
 
454
 
 
455
        if (!page_rec_is_comp(rec)) {
 
456
                log_start = log_ptr = mlog_open(mtr, 11 + size);
 
457
                if (!log_ptr) {
 
458
                        return(NULL); /* logging is disabled */
 
459
                }
 
460
                log_ptr = mlog_write_initial_log_record_fast(rec, type,
 
461
                                                             log_ptr, mtr);
 
462
                log_end = log_ptr + 11 + size;
 
463
        } else {
 
464
                ulint   i;
 
465
                ulint   n       = dict_index_get_n_fields(index);
 
466
                /* total size needed */
 
467
                ulint   total   = 11 + size + (n + 2) * 2;
 
468
                ulint   alloc   = total;
 
469
                /* allocate at most DYN_ARRAY_DATA_SIZE at a time */
 
470
                if (alloc > DYN_ARRAY_DATA_SIZE) {
 
471
                        alloc = DYN_ARRAY_DATA_SIZE;
 
472
                }
 
473
                log_start = log_ptr = mlog_open(mtr, alloc);
 
474
                if (!log_ptr) {
 
475
                        return(NULL); /* logging is disabled */
 
476
                }
 
477
                log_end = log_ptr + alloc;
 
478
                log_ptr = mlog_write_initial_log_record_fast(rec, type,
 
479
                                                             log_ptr, mtr);
 
480
                mach_write_to_2(log_ptr, n);
 
481
                log_ptr += 2;
 
482
                mach_write_to_2(log_ptr,
 
483
                                dict_index_get_n_unique_in_tree(index));
 
484
                log_ptr += 2;
 
485
                for (i = 0; i < n; i++) {
 
486
                        dict_field_t*           field;
 
487
                        const dict_col_t*       col;
 
488
                        ulint                   len;
 
489
 
 
490
                        field = dict_index_get_nth_field(index, i);
 
491
                        col = dict_field_get_col(field);
 
492
                        len = field->fixed_len;
 
493
                        ut_ad(len < 0x7fff);
 
494
                        if (len == 0
 
495
                            && (col->len > 255 || col->mtype == DATA_BLOB)) {
 
496
                                /* variable-length field
 
497
                                with maximum length > 255 */
 
498
                                len = 0x7fff;
 
499
                        }
 
500
                        if (col->prtype & DATA_NOT_NULL) {
 
501
                                len |= 0x8000;
 
502
                        }
 
503
                        if (log_ptr + 2 > log_end) {
 
504
                                mlog_close(mtr, log_ptr);
 
505
                                ut_a(total > (ulint) (log_ptr - log_start));
 
506
                                total -= log_ptr - log_start;
 
507
                                alloc = total;
 
508
                                if (alloc > DYN_ARRAY_DATA_SIZE) {
 
509
                                        alloc = DYN_ARRAY_DATA_SIZE;
 
510
                                }
 
511
                                log_start = log_ptr = mlog_open(mtr, alloc);
 
512
                                if (!log_ptr) {
 
513
                                        return(NULL); /* logging is disabled */
 
514
                                }
 
515
                                log_end = log_ptr + alloc;
 
516
                        }
 
517
                        mach_write_to_2(log_ptr, len);
 
518
                        log_ptr += 2;
 
519
                }
 
520
        }
 
521
        if (size == 0) {
 
522
                mlog_close(mtr, log_ptr);
 
523
                log_ptr = NULL;
 
524
        } else if (log_ptr + size > log_end) {
 
525
                mlog_close(mtr, log_ptr);
 
526
                log_ptr = mlog_open(mtr, size);
 
527
        }
 
528
        return(log_ptr);
 
529
}
 
530
#endif /* !UNIV_HOTBACKUP */
 
531
 
 
532
/********************************************************//**
 
533
Parses a log record written by mlog_open_and_write_index.
 
534
@return parsed record end, NULL if not a complete record */
 
535
UNIV_INTERN
 
536
byte*
 
537
mlog_parse_index(
 
538
/*=============*/
 
539
        byte*           ptr,    /*!< in: buffer */
 
540
        const byte*     end_ptr,/*!< in: buffer end */
 
541
        ibool           comp,   /*!< in: TRUE=compact record format */
 
542
        dict_index_t**  index)  /*!< out, own: dummy index */
 
543
{
 
544
        ulint           i, n, n_uniq;
 
545
        dict_table_t*   table;
 
546
        dict_index_t*   ind;
 
547
 
 
548
        ut_ad(comp == FALSE || comp == TRUE);
 
549
 
 
550
        if (comp) {
 
551
                if (end_ptr < ptr + 4) {
 
552
                        return(NULL);
 
553
                }
 
554
                n = mach_read_from_2(ptr);
 
555
                ptr += 2;
 
556
                n_uniq = mach_read_from_2(ptr);
 
557
                ptr += 2;
 
558
                ut_ad(n_uniq <= n);
 
559
                if (end_ptr < ptr + n * 2) {
 
560
                        return(NULL);
 
561
                }
 
562
        } else {
 
563
                n = n_uniq = 1;
 
564
        }
 
565
        table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n,
 
566
                                      comp ? DICT_TF_COMPACT : 0);
 
567
        ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY",
 
568
                                    DICT_HDR_SPACE, 0, n);
 
569
        ind->table = table;
 
570
        ind->n_uniq = (unsigned int) n_uniq;
 
571
        if (n_uniq != n) {
 
572
                ut_a(n_uniq + DATA_ROLL_PTR <= n);
 
573
                ind->type = DICT_CLUSTERED;
 
574
        }
 
575
        if (comp) {
 
576
                for (i = 0; i < n; i++) {
 
577
                        ulint   len = mach_read_from_2(ptr);
 
578
                        ptr += 2;
 
579
                        /* The high-order bit of len is the NOT NULL flag;
 
580
                        the rest is 0 or 0x7fff for variable-length fields,
 
581
                        and 1..0x7ffe for fixed-length fields. */
 
582
                        dict_mem_table_add_col(
 
583
                                table, NULL, NULL,
 
584
                                ((len + 1) & 0x7fff) <= 1
 
585
                                ? DATA_BINARY : DATA_FIXBINARY,
 
586
                                len & 0x8000 ? DATA_NOT_NULL : 0,
 
587
                                len & 0x7fff);
 
588
 
 
589
                        dict_index_add_col(ind, table,
 
590
                                           dict_table_get_nth_col(table, i),
 
591
                                           0);
 
592
                }
 
593
                dict_table_add_system_columns(table, table->heap);
 
594
                if (n_uniq != n) {
 
595
                        /* Identify DB_TRX_ID and DB_ROLL_PTR in the index. */
 
596
                        ut_a(DATA_TRX_ID_LEN
 
597
                             == dict_index_get_nth_col(ind, DATA_TRX_ID - 1
 
598
                                                       + n_uniq)->len);
 
599
                        ut_a(DATA_ROLL_PTR_LEN
 
600
                             == dict_index_get_nth_col(ind, DATA_ROLL_PTR - 1
 
601
                                                       + n_uniq)->len);
 
602
                        ind->fields[DATA_TRX_ID - 1 + n_uniq].col
 
603
                                = &table->cols[n + DATA_TRX_ID];
 
604
                        ind->fields[DATA_ROLL_PTR - 1 + n_uniq].col
 
605
                                = &table->cols[n + DATA_ROLL_PTR];
 
606
                }
 
607
        }
 
608
        /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
 
609
        ind->cached = TRUE;
 
610
        *index = ind;
 
611
        return(ptr);
 
612
}