~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/mtr/mtr0log.c

  • Committer: Monty Taylor
  • Date: 2010-06-19 16:36:52 UTC
  • mto: This revision was merged to the branch mainline in revision 1628.
  • Revision ID: mordred@inaugust.com-20100619163652-6fej38011wsop52k
Moved password parsing code into get_password.cc.

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., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 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_ull.
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
 
        ib_uint64_t     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_ull_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_ull(
294
 
/*===========*/
295
 
        byte*           ptr,    /*!< in: pointer where to write */
296
 
        ib_uint64_t     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_ull_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
 
}