~drizzle-trunk/drizzle/development

641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
19
/**************************************************//**
20
@file mtr/mtr0log.c
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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"
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
33
#include "dict0dict.h"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
34
#include "log0recv.h"
35
#include "page0page.h"
36
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
37
#ifndef UNIV_HOTBACKUP
38
# include "dict0boot.h"
39
40
/********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
41
Catenates n bytes to the mtr log. */
42
UNIV_INTERN
43
void
44
mlog_catenate_string(
45
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
46
	mtr_t*		mtr,	/*!< in: mtr */
47
	const byte*	str,	/*!< in: string to write */
48
	ulint		len)	/*!< in: string length */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
62
/********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
/*==========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
70
	const byte*	ptr,	/*!< in: pointer to (inside) a buffer
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
71
				frame holding the file page where
72
				modification is made */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
73
	byte		type,	/*!< in: log item type: MLOG_1BYTE, ... */
74
	mtr_t*		mtr)	/*!< in: mini-transaction handle */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
93
#endif /* !UNIV_HOTBACKUP */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
94
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
98
UNIV_INTERN
99
byte*
100
mlog_parse_initial_log_record(
101
/*==========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
138
UNIV_INTERN
139
byte*
140
mlog_parse_nbytes(
141
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
242
/********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
288
/********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
295
	byte*	ptr,	/*!< in: pointer where to write */
296
	dulint	val,	/*!< in: value to write */
297
	mtr_t*	mtr)	/*!< in: mini-transaction handle */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
324
#ifndef UNIV_HOTBACKUP
325
/********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
345
/********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
/*============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
352
	byte*	ptr,	/*!< in: pointer written to */
353
	ulint	len,	/*!< in: string length */
354
	mtr_t*	mtr)	/*!< in: mini-transaction handle */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
381
#endif /* !UNIV_HOTBACKUP */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
382
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
383
/********************************************************//**
384
Parses a log record written by mlog_write_string.
385
@return	parsed record end, NULL if not a complete record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
386
UNIV_INTERN
387
byte*
388
mlog_parse_string(
389
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
433
#ifndef UNIV_HOTBACKUP
434
/********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
435
Opens a buffer for mlog, writes the initial log record and,
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
436
if needed, the field lengths of an index.
437
@return	buffer, NULL if log mode MTR_LOG_NONE */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
438
UNIV_INTERN
439
byte*
440
mlog_open_and_write_index(
441
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
530
#endif /* !UNIV_HOTBACKUP */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
531
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
532
/********************************************************//**
533
Parses a log record written by mlog_open_and_write_index.
534
@return	parsed record end, NULL if not a complete record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
535
UNIV_INTERN
536
byte*
537
mlog_parse_index(
538
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
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
}