~drizzle-trunk/drizzle/development

641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1
/*****************************************************************************
2
3
Copyright (c) 1994, 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 include/rem0rec.ic
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
21
Record manager
22
23
Created 5/30/1994 Heikki Tuuri
24
*************************************************************************/
25
26
#include "mach0data.h"
27
#include "ut0byte.h"
28
#include "dict0dict.h"
29
30
/* Compact flag ORed to the extra size returned by rec_get_offsets() */
31
#define REC_OFFS_COMPACT	((ulint) 1 << 31)
32
/* SQL NULL flag in offsets returned by rec_get_offsets() */
33
#define REC_OFFS_SQL_NULL	((ulint) 1 << 31)
34
/* External flag in offsets returned by rec_get_offsets() */
35
#define REC_OFFS_EXTERNAL	((ulint) 1 << 30)
36
/* Mask for offsets returned by rec_get_offsets() */
37
#define REC_OFFS_MASK		(REC_OFFS_EXTERNAL - 1)
38
39
/* Offsets of the bit-fields in an old-style record. NOTE! In the table the
40
most significant bytes and bits are written below less significant.
41
42
	(1) byte offset		(2) bit usage within byte
43
	downward from
44
	origin ->	1	8 bits pointer to next record
45
			2	8 bits pointer to next record
46
			3	1 bit short flag
47
				7 bits number of fields
48
			4	3 bits number of fields
49
				5 bits heap number
50
			5	8 bits heap number
51
			6	4 bits n_owned
52
				4 bits info bits
53
*/
54
55
/* Offsets of the bit-fields in a new-style record. NOTE! In the table the
56
most significant bytes and bits are written below less significant.
57
58
	(1) byte offset		(2) bit usage within byte
59
	downward from
60
	origin ->	1	8 bits relative offset of next record
61
			2	8 bits relative offset of next record
62
				  the relative offset is an unsigned 16-bit
63
				  integer:
64
				  (offset_of_next_record
65
				   - offset_of_this_record) mod 64Ki,
66
				  where mod is the modulo as a non-negative
67
				  number;
68
				  we can calculate the the offset of the next
69
				  record with the formula:
70
				  relative_offset + offset_of_this_record
71
				  mod UNIV_PAGE_SIZE
72
			3	3 bits status:
73
					000=conventional record
74
					001=node pointer record (inside B-tree)
75
					010=infimum record
76
					011=supremum record
77
					1xx=reserved
78
				5 bits heap number
79
			4	8 bits heap number
80
			5	4 bits n_owned
81
				4 bits info bits
82
*/
83
84
/* We list the byte offsets from the origin of the record, the mask,
85
and the shift needed to obtain each bit-field of the record. */
86
87
#define REC_NEXT		2
88
#define REC_NEXT_MASK		0xFFFFUL
89
#define REC_NEXT_SHIFT		0
90
91
#define REC_OLD_SHORT		3	/* This is single byte bit-field */
92
#define REC_OLD_SHORT_MASK	0x1UL
93
#define REC_OLD_SHORT_SHIFT	0
94
95
#define REC_OLD_N_FIELDS	4
96
#define REC_OLD_N_FIELDS_MASK	0x7FEUL
97
#define REC_OLD_N_FIELDS_SHIFT	1
98
99
#define REC_NEW_STATUS		3	/* This is single byte bit-field */
100
#define REC_NEW_STATUS_MASK	0x7UL
101
#define REC_NEW_STATUS_SHIFT	0
102
103
#define REC_OLD_HEAP_NO		5
104
#define REC_HEAP_NO_MASK	0xFFF8UL
105
#if 0 /* defined in rem0rec.h for use of page0zip.c */
106
#define REC_NEW_HEAP_NO		4
107
#define	REC_HEAP_NO_SHIFT	3
108
#endif
109
110
#define REC_OLD_N_OWNED		6	/* This is single byte bit-field */
111
#define REC_NEW_N_OWNED		5	/* This is single byte bit-field */
112
#define	REC_N_OWNED_MASK	0xFUL
113
#define REC_N_OWNED_SHIFT	0
114
115
#define REC_OLD_INFO_BITS	6	/* This is single byte bit-field */
116
#define REC_NEW_INFO_BITS	5	/* This is single byte bit-field */
117
#define	REC_INFO_BITS_MASK	0xF0UL
118
#define REC_INFO_BITS_SHIFT	0
119
120
/* The following masks are used to filter the SQL null bit from
121
one-byte and two-byte offsets */
122
123
#define REC_1BYTE_SQL_NULL_MASK	0x80UL
124
#define REC_2BYTE_SQL_NULL_MASK	0x8000UL
125
126
/* In a 2-byte offset the second most significant bit denotes
127
a field stored to another page: */
128
129
#define REC_2BYTE_EXTERN_MASK	0x4000UL
130
131
#if REC_OLD_SHORT_MASK << (8 * (REC_OLD_SHORT - 3)) \
132
		^ REC_OLD_N_FIELDS_MASK << (8 * (REC_OLD_N_FIELDS - 4)) \
133
		^ REC_HEAP_NO_MASK << (8 * (REC_OLD_HEAP_NO - 4)) \
134
		^ REC_N_OWNED_MASK << (8 * (REC_OLD_N_OWNED - 3)) \
135
		^ REC_INFO_BITS_MASK << (8 * (REC_OLD_INFO_BITS - 3)) \
136
		^ 0xFFFFFFFFUL
137
# error "sum of old-style masks != 0xFFFFFFFFUL"
138
#endif
139
#if REC_NEW_STATUS_MASK << (8 * (REC_NEW_STATUS - 3)) \
140
		^ REC_HEAP_NO_MASK << (8 * (REC_NEW_HEAP_NO - 4)) \
141
		^ REC_N_OWNED_MASK << (8 * (REC_NEW_N_OWNED - 3)) \
142
		^ REC_INFO_BITS_MASK << (8 * (REC_NEW_INFO_BITS - 3)) \
143
		^ 0xFFFFFFUL
144
# error "sum of new-style masks != 0xFFFFFFUL"
145
#endif
146
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
147
/***********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
148
Sets the value of the ith field SQL null bit of an old-style record. */
149
UNIV_INTERN
150
void
151
rec_set_nth_field_null_bit(
152
/*=======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
153
	rec_t*	rec,	/*!< in: record */
154
	ulint	i,	/*!< in: ith field */
155
	ibool	val);	/*!< in: value to set */
156
/***********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
157
Sets an old-style record field to SQL null.
158
The physical size of the field is not changed. */
159
UNIV_INTERN
160
void
161
rec_set_nth_field_sql_null(
162
/*=======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
163
	rec_t*	rec,	/*!< in: record */
164
	ulint	n);	/*!< in: index of the field */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
165
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
166
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
167
Gets a bit field from within 1 byte. */
168
UNIV_INLINE
169
ulint
170
rec_get_bit_field_1(
171
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
172
	const rec_t*	rec,	/*!< in: pointer to record origin */
173
	ulint		offs,	/*!< in: offset from the origin down */
174
	ulint		mask,	/*!< in: mask used to filter bits */
175
	ulint		shift)	/*!< in: shift right applied after masking */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
176
{
177
	ut_ad(rec);
178
179
	return((mach_read_from_1(rec - offs) & mask) >> shift);
180
}
181
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
182
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
183
Sets a bit field within 1 byte. */
184
UNIV_INLINE
185
void
186
rec_set_bit_field_1(
187
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
188
	rec_t*	rec,	/*!< in: pointer to record origin */
189
	ulint	val,	/*!< in: value to set */
190
	ulint	offs,	/*!< in: offset from the origin down */
191
	ulint	mask,	/*!< in: mask used to filter bits */
192
	ulint	shift)	/*!< in: shift right applied after masking */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
193
{
194
	ut_ad(rec);
195
	ut_ad(offs <= REC_N_OLD_EXTRA_BYTES);
196
	ut_ad(mask);
197
	ut_ad(mask <= 0xFFUL);
198
	ut_ad(((mask >> shift) << shift) == mask);
199
	ut_ad(((val << shift) & mask) == (val << shift));
200
201
	mach_write_to_1(rec - offs,
202
			(mach_read_from_1(rec - offs) & ~mask)
203
			| (val << shift));
204
}
205
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
206
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
207
Gets a bit field from within 2 bytes. */
208
UNIV_INLINE
209
ulint
210
rec_get_bit_field_2(
211
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
212
	const rec_t*	rec,	/*!< in: pointer to record origin */
213
	ulint		offs,	/*!< in: offset from the origin down */
214
	ulint		mask,	/*!< in: mask used to filter bits */
215
	ulint		shift)	/*!< in: shift right applied after masking */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
216
{
217
	ut_ad(rec);
218
219
	return((mach_read_from_2(rec - offs) & mask) >> shift);
220
}
221
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
222
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
223
Sets a bit field within 2 bytes. */
224
UNIV_INLINE
225
void
226
rec_set_bit_field_2(
227
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
228
	rec_t*	rec,	/*!< in: pointer to record origin */
229
	ulint	val,	/*!< in: value to set */
230
	ulint	offs,	/*!< in: offset from the origin down */
231
	ulint	mask,	/*!< in: mask used to filter bits */
232
	ulint	shift)	/*!< in: shift right applied after masking */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
233
{
234
	ut_ad(rec);
235
	ut_ad(offs <= REC_N_OLD_EXTRA_BYTES);
236
	ut_ad(mask > 0xFFUL);
237
	ut_ad(mask <= 0xFFFFUL);
238
	ut_ad((mask >> shift) & 1);
239
	ut_ad(0 == ((mask >> shift) & ((mask >> shift) + 1)));
240
	ut_ad(((mask >> shift) << shift) == mask);
241
	ut_ad(((val << shift) & mask) == (val << shift));
242
243
	mach_write_to_2(rec - offs,
244
			(mach_read_from_2(rec - offs) & ~mask)
245
			| (val << shift));
246
}
247
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
248
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
249
The following function is used to get the pointer of the next chained record
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
250
on the same page.
251
@return	pointer to the next chained record, or NULL if none */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
252
UNIV_INLINE
253
const rec_t*
254
rec_get_next_ptr_const(
255
/*===================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
256
	const rec_t*	rec,	/*!< in: physical record */
257
	ulint		comp)	/*!< in: nonzero=compact page format */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
258
{
259
	ulint	field_value;
260
261
	ut_ad(REC_NEXT_MASK == 0xFFFFUL);
262
	ut_ad(REC_NEXT_SHIFT == 0);
263
264
	field_value = mach_read_from_2(rec - REC_NEXT);
265
266
	if (UNIV_UNLIKELY(field_value == 0)) {
267
268
		return(NULL);
269
	}
270
271
	if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
272
#if UNIV_PAGE_SIZE <= 32768
273
		/* Note that for 64 KiB pages, field_value can 'wrap around'
274
		and the debug assertion is not valid */
275
276
		/* In the following assertion, field_value is interpreted
277
		as signed 16-bit integer in 2's complement arithmetics.
278
		If all platforms defined int16_t in the standard headers,
279
		the expression could be written simpler as
280
		(int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE
281
		*/
282
		ut_ad((field_value >= 32768
283
		       ? field_value - 65536
284
		       : field_value)
285
		      + ut_align_offset(rec, UNIV_PAGE_SIZE)
286
		      < UNIV_PAGE_SIZE);
287
#endif
288
		/* There must be at least REC_N_NEW_EXTRA_BYTES + 1
289
		between each record. */
290
		ut_ad((field_value > REC_N_NEW_EXTRA_BYTES
291
		       && field_value < 32768)
292
		      || field_value < (uint16) -REC_N_NEW_EXTRA_BYTES);
293
294
		return((byte*) ut_align_down(rec, UNIV_PAGE_SIZE)
295
		       + ut_align_offset(rec + field_value, UNIV_PAGE_SIZE));
296
	} else {
297
		ut_ad(field_value < UNIV_PAGE_SIZE);
298
299
		return((byte*) ut_align_down(rec, UNIV_PAGE_SIZE)
300
		       + field_value);
301
	}
302
}
303
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
304
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
305
The following function is used to get the pointer of the next chained record
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
306
on the same page.
307
@return	pointer to the next chained record, or NULL if none */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
308
UNIV_INLINE
309
rec_t*
310
rec_get_next_ptr(
311
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
312
	rec_t*	rec,	/*!< in: physical record */
313
	ulint	comp)	/*!< in: nonzero=compact page format */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
314
{
315
	return((rec_t*) rec_get_next_ptr_const(rec, comp));
316
}
317
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
318
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
319
The following function is used to get the offset of the next chained record
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
320
on the same page.
321
@return	the page offset of the next chained record, or 0 if none */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
322
UNIV_INLINE
323
ulint
324
rec_get_next_offs(
325
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
326
	const rec_t*	rec,	/*!< in: physical record */
327
	ulint		comp)	/*!< in: nonzero=compact page format */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
328
{
329
	ulint	field_value;
330
#if REC_NEXT_MASK != 0xFFFFUL
331
# error "REC_NEXT_MASK != 0xFFFFUL"
332
#endif
333
#if REC_NEXT_SHIFT
334
# error "REC_NEXT_SHIFT != 0"
335
#endif
336
337
	field_value = mach_read_from_2(rec - REC_NEXT);
338
339
	if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
340
#if UNIV_PAGE_SIZE <= 32768
341
		/* Note that for 64 KiB pages, field_value can 'wrap around'
342
		and the debug assertion is not valid */
343
344
		/* In the following assertion, field_value is interpreted
345
		as signed 16-bit integer in 2's complement arithmetics.
346
		If all platforms defined int16_t in the standard headers,
347
		the expression could be written simpler as
348
		(int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE
349
		*/
350
		ut_ad((field_value >= 32768
351
		       ? field_value - 65536
352
		       : field_value)
353
		      + ut_align_offset(rec, UNIV_PAGE_SIZE)
354
		      < UNIV_PAGE_SIZE);
355
#endif
356
		if (UNIV_UNLIKELY(field_value == 0)) {
357
358
			return(0);
359
		}
360
361
		/* There must be at least REC_N_NEW_EXTRA_BYTES + 1
362
		between each record. */
363
		ut_ad((field_value > REC_N_NEW_EXTRA_BYTES
364
		       && field_value < 32768)
365
		      || field_value < (uint16) -REC_N_NEW_EXTRA_BYTES);
366
367
		return(ut_align_offset(rec + field_value, UNIV_PAGE_SIZE));
368
	} else {
369
		ut_ad(field_value < UNIV_PAGE_SIZE);
370
371
		return(field_value);
372
	}
373
}
374
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
375
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
376
The following function is used to set the next record offset field
377
of an old-style record. */
378
UNIV_INLINE
379
void
380
rec_set_next_offs_old(
381
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
382
	rec_t*	rec,	/*!< in: old-style physical record */
383
	ulint	next)	/*!< in: offset of the next record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
384
{
385
	ut_ad(rec);
386
	ut_ad(UNIV_PAGE_SIZE > next);
387
#if REC_NEXT_MASK != 0xFFFFUL
388
# error "REC_NEXT_MASK != 0xFFFFUL"
389
#endif
390
#if REC_NEXT_SHIFT
391
# error "REC_NEXT_SHIFT != 0"
392
#endif
393
394
	mach_write_to_2(rec - REC_NEXT, next);
395
}
396
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
397
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
398
The following function is used to set the next record offset field
399
of a new-style record. */
400
UNIV_INLINE
401
void
402
rec_set_next_offs_new(
403
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
404
	rec_t*	rec,	/*!< in/out: new-style physical record */
405
	ulint	next)	/*!< in: offset of the next record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
406
{
407
	ulint	field_value;
408
409
	ut_ad(rec);
410
	ut_ad(UNIV_PAGE_SIZE > next);
411
412
	if (UNIV_UNLIKELY(!next)) {
413
		field_value = 0;
414
	} else {
415
		/* The following two statements calculate
416
		next - offset_of_rec mod 64Ki, where mod is the modulo
417
		as a non-negative number */
418
419
		field_value = (ulint)
420
			((lint) next 
421
			 - (lint) ut_align_offset(rec, UNIV_PAGE_SIZE));
422
		field_value &= REC_NEXT_MASK;
423
	}
424
425
	mach_write_to_2(rec - REC_NEXT, field_value);
426
}
427
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
428
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
429
The following function is used to get the number of fields
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
430
in an old-style record.
431
@return	number of data fields */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
432
UNIV_INLINE
433
ulint
434
rec_get_n_fields_old(
435
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
436
	const rec_t*	rec)	/*!< in: physical record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
437
{
438
	ulint	ret;
439
440
	ut_ad(rec);
441
442
	ret = rec_get_bit_field_2(rec, REC_OLD_N_FIELDS,
443
				  REC_OLD_N_FIELDS_MASK,
444
				  REC_OLD_N_FIELDS_SHIFT);
445
	ut_ad(ret <= REC_MAX_N_FIELDS);
446
	ut_ad(ret > 0);
447
448
	return(ret);
449
}
450
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
451
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
452
The following function is used to set the number of fields
453
in an old-style record. */
454
UNIV_INLINE
455
void
456
rec_set_n_fields_old(
457
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
458
	rec_t*	rec,		/*!< in: physical record */
459
	ulint	n_fields)	/*!< in: the number of fields */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
460
{
461
	ut_ad(rec);
462
	ut_ad(n_fields <= REC_MAX_N_FIELDS);
463
	ut_ad(n_fields > 0);
464
465
	rec_set_bit_field_2(rec, n_fields, REC_OLD_N_FIELDS,
466
			    REC_OLD_N_FIELDS_MASK, REC_OLD_N_FIELDS_SHIFT);
467
}
468
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
469
/******************************************************//**
470
The following function retrieves the status bits of a new-style record.
471
@return	status bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
472
UNIV_INLINE
473
ulint
474
rec_get_status(
475
/*===========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
476
	const rec_t*	rec)	/*!< in: physical record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
477
{
478
	ulint	ret;
479
480
	ut_ad(rec);
481
482
	ret = rec_get_bit_field_1(rec, REC_NEW_STATUS,
483
				  REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT);
484
	ut_ad((ret & ~REC_NEW_STATUS_MASK) == 0);
485
486
	return(ret);
487
}
488
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
489
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
490
The following function is used to get the number of fields
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
491
in a record.
492
@return	number of data fields */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
493
UNIV_INLINE
494
ulint
495
rec_get_n_fields(
496
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
497
	const rec_t*		rec,	/*!< in: physical record */
498
	const dict_index_t*	index)	/*!< in: record descriptor */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
499
{
500
	ut_ad(rec);
501
	ut_ad(index);
502
503
	if (!dict_table_is_comp(index->table)) {
504
		return(rec_get_n_fields_old(rec));
505
	}
506
507
	switch (rec_get_status(rec)) {
508
	case REC_STATUS_ORDINARY:
509
		return(dict_index_get_n_fields(index));
510
	case REC_STATUS_NODE_PTR:
511
		return(dict_index_get_n_unique_in_tree(index) + 1);
512
	case REC_STATUS_INFIMUM:
513
	case REC_STATUS_SUPREMUM:
514
		return(1);
515
	default:
516
		ut_error;
517
		return(ULINT_UNDEFINED);
518
	}
519
}
520
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
521
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
522
The following function is used to get the number of records owned by the
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
523
previous directory record.
524
@return	number of owned records */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
525
UNIV_INLINE
526
ulint
527
rec_get_n_owned_old(
528
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
529
	const rec_t*	rec)	/*!< in: old-style physical record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
530
{
531
	return(rec_get_bit_field_1(rec, REC_OLD_N_OWNED,
532
				   REC_N_OWNED_MASK, REC_N_OWNED_SHIFT));
533
}
534
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
535
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
536
The following function is used to set the number of owned records. */
537
UNIV_INLINE
538
void
539
rec_set_n_owned_old(
540
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
541
	rec_t*	rec,		/*!< in: old-style physical record */
542
	ulint	n_owned)	/*!< in: the number of owned */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
543
{
544
	rec_set_bit_field_1(rec, n_owned, REC_OLD_N_OWNED,
545
			    REC_N_OWNED_MASK, REC_N_OWNED_SHIFT);
546
}
547
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
548
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
549
The following function is used to get the number of records owned by the
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
550
previous directory record.
551
@return	number of owned records */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
552
UNIV_INLINE
553
ulint
554
rec_get_n_owned_new(
555
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
556
	const rec_t*	rec)	/*!< in: new-style physical record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
557
{
558
	return(rec_get_bit_field_1(rec, REC_NEW_N_OWNED,
559
				   REC_N_OWNED_MASK, REC_N_OWNED_SHIFT));
560
}
561
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
562
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
563
The following function is used to set the number of owned records. */
564
UNIV_INLINE
565
void
566
rec_set_n_owned_new(
567
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
568
	rec_t*		rec,	/*!< in/out: new-style physical record */
569
	page_zip_des_t*	page_zip,/*!< in/out: compressed page, or NULL */
570
	ulint		n_owned)/*!< in: the number of owned */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
571
{
572
	rec_set_bit_field_1(rec, n_owned, REC_NEW_N_OWNED,
573
			    REC_N_OWNED_MASK, REC_N_OWNED_SHIFT);
574
	if (UNIV_LIKELY_NULL(page_zip)
575
	    && UNIV_LIKELY(rec_get_status(rec)
576
			   != REC_STATUS_SUPREMUM)) {
577
		page_zip_rec_set_owned(page_zip, rec, n_owned);
578
	}
579
}
580
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
581
/******************************************************//**
582
The following function is used to retrieve the info bits of a record.
583
@return	info bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
584
UNIV_INLINE
585
ulint
586
rec_get_info_bits(
587
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
588
	const rec_t*	rec,	/*!< in: physical record */
589
	ulint		comp)	/*!< in: nonzero=compact page format */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
590
{
591
	return(rec_get_bit_field_1(
592
		       rec, comp ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS,
593
		       REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT));
594
}
595
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
596
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
597
The following function is used to set the info bits of a record. */
598
UNIV_INLINE
599
void
600
rec_set_info_bits_old(
601
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
602
	rec_t*	rec,	/*!< in: old-style physical record */
603
	ulint	bits)	/*!< in: info bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
604
{
605
	rec_set_bit_field_1(rec, bits, REC_OLD_INFO_BITS,
606
			    REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
607
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
608
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
609
The following function is used to set the info bits of a record. */
610
UNIV_INLINE
611
void
612
rec_set_info_bits_new(
613
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
614
	rec_t*	rec,	/*!< in/out: new-style physical record */
615
	ulint	bits)	/*!< in: info bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
616
{
617
	rec_set_bit_field_1(rec, bits, REC_NEW_INFO_BITS,
618
			    REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
619
}
620
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
621
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
622
The following function is used to set the status bits of a new-style record. */
623
UNIV_INLINE
624
void
625
rec_set_status(
626
/*===========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
627
	rec_t*	rec,	/*!< in/out: physical record */
628
	ulint	bits)	/*!< in: info bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
629
{
630
	rec_set_bit_field_1(rec, bits, REC_NEW_STATUS,
631
			    REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT);
632
}
633
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
634
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
635
The following function is used to retrieve the info and status
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
636
bits of a record.  (Only compact records have status bits.)
637
@return	info bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
638
UNIV_INLINE
639
ulint
640
rec_get_info_and_status_bits(
641
/*=========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
642
	const rec_t*	rec,	/*!< in: physical record */
643
	ulint		comp)	/*!< in: nonzero=compact page format */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
644
{
645
	ulint	bits;
646
#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \
647
& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT)
648
# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap"
649
#endif
650
	if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
651
		bits = rec_get_info_bits(rec, TRUE) | rec_get_status(rec);
652
	} else {
653
		bits = rec_get_info_bits(rec, FALSE);
654
		ut_ad(!(bits & ~(REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT)));
655
	}
656
	return(bits);
657
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
658
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
659
The following function is used to set the info and status
660
bits of a record.  (Only compact records have status bits.) */
661
UNIV_INLINE
662
void
663
rec_set_info_and_status_bits(
664
/*=========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
665
	rec_t*	rec,	/*!< in/out: physical record */
666
	ulint	bits)	/*!< in: info bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
667
{
668
#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \
669
& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT)
670
# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap"
671
#endif
672
	rec_set_status(rec, bits & REC_NEW_STATUS_MASK);
673
	rec_set_info_bits_new(rec, bits & ~REC_NEW_STATUS_MASK);
674
}
675
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
676
/******************************************************//**
677
The following function tells if record is delete marked.
678
@return	nonzero if delete marked */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
679
UNIV_INLINE
680
ulint
681
rec_get_deleted_flag(
682
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
683
	const rec_t*	rec,	/*!< in: physical record */
684
	ulint		comp)	/*!< in: nonzero=compact page format */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
685
{
686
	if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
687
		return(UNIV_UNLIKELY(
688
			       rec_get_bit_field_1(rec, REC_NEW_INFO_BITS,
689
						   REC_INFO_DELETED_FLAG,
690
						   REC_INFO_BITS_SHIFT)));
691
	} else {
692
		return(UNIV_UNLIKELY(
693
			       rec_get_bit_field_1(rec, REC_OLD_INFO_BITS,
694
						   REC_INFO_DELETED_FLAG,
695
						   REC_INFO_BITS_SHIFT)));
696
	}
697
}
698
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
699
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
700
The following function is used to set the deleted bit. */
701
UNIV_INLINE
702
void
703
rec_set_deleted_flag_old(
704
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
705
	rec_t*	rec,	/*!< in: old-style physical record */
706
	ulint	flag)	/*!< in: nonzero if delete marked */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
707
{
708
	ulint	val;
709
710
	val = rec_get_info_bits(rec, FALSE);
711
712
	if (flag) {
713
		val |= REC_INFO_DELETED_FLAG;
714
	} else {
715
		val &= ~REC_INFO_DELETED_FLAG;
716
	}
717
718
	rec_set_info_bits_old(rec, val);
719
}
720
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
721
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
722
The following function is used to set the deleted bit. */
723
UNIV_INLINE
724
void
725
rec_set_deleted_flag_new(
726
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
727
	rec_t*		rec,	/*!< in/out: new-style physical record */
728
	page_zip_des_t*	page_zip,/*!< in/out: compressed page, or NULL */
729
	ulint		flag)	/*!< in: nonzero if delete marked */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
730
{
731
	ulint	val;
732
733
	val = rec_get_info_bits(rec, TRUE);
734
735
	if (flag) {
736
		val |= REC_INFO_DELETED_FLAG;
737
	} else {
738
		val &= ~REC_INFO_DELETED_FLAG;
739
	}
740
741
	rec_set_info_bits_new(rec, val);
742
743
	if (UNIV_LIKELY_NULL(page_zip)) {
744
		page_zip_rec_set_deleted(page_zip, rec, flag);
745
	}
746
}
747
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
748
/******************************************************//**
749
The following function tells if a new-style record is a node pointer.
750
@return	TRUE if node pointer */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
751
UNIV_INLINE
752
ibool
753
rec_get_node_ptr_flag(
754
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
755
	const rec_t*	rec)	/*!< in: physical record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
756
{
757
	return(REC_STATUS_NODE_PTR == rec_get_status(rec));
758
}
759
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
760
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
761
The following function is used to get the order number
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
762
of an old-style record in the heap of the index page.
763
@return	heap order number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
764
UNIV_INLINE
765
ulint
766
rec_get_heap_no_old(
767
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
768
	const rec_t*	rec)	/*!< in: physical record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
769
{
770
	return(rec_get_bit_field_2(rec, REC_OLD_HEAP_NO,
771
				   REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT));
772
}
773
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
774
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
775
The following function is used to set the heap number
776
field in an old-style record. */
777
UNIV_INLINE
778
void
779
rec_set_heap_no_old(
780
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
781
	rec_t*	rec,	/*!< in: physical record */
782
	ulint	heap_no)/*!< in: the heap number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
783
{
784
	rec_set_bit_field_2(rec, heap_no, REC_OLD_HEAP_NO,
785
			    REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT);
786
}
787
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
788
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
789
The following function is used to get the order number
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
790
of a new-style record in the heap of the index page.
791
@return	heap order number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
792
UNIV_INLINE
793
ulint
794
rec_get_heap_no_new(
795
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
796
	const rec_t*	rec)	/*!< in: physical record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
797
{
798
	return(rec_get_bit_field_2(rec, REC_NEW_HEAP_NO,
799
				   REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT));
800
}
801
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
802
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
803
The following function is used to set the heap number
804
field in a new-style record. */
805
UNIV_INLINE
806
void
807
rec_set_heap_no_new(
808
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
809
	rec_t*	rec,	/*!< in/out: physical record */
810
	ulint	heap_no)/*!< in: the heap number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
811
{
812
	rec_set_bit_field_2(rec, heap_no, REC_NEW_HEAP_NO,
813
			    REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT);
814
}
815
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
816
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
817
The following function is used to test whether the data offsets in the record
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
818
are stored in one-byte or two-byte format.
819
@return	TRUE if 1-byte form */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
820
UNIV_INLINE
821
ibool
822
rec_get_1byte_offs_flag(
823
/*====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
824
	const rec_t*	rec)	/*!< in: physical record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
825
{
826
#if TRUE != 1
827
#error "TRUE != 1"
828
#endif
829
830
	return(rec_get_bit_field_1(rec, REC_OLD_SHORT, REC_OLD_SHORT_MASK,
831
				   REC_OLD_SHORT_SHIFT));
832
}
833
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
834
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
835
The following function is used to set the 1-byte offsets flag. */
836
UNIV_INLINE
837
void
838
rec_set_1byte_offs_flag(
839
/*====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
840
	rec_t*	rec,	/*!< in: physical record */
841
	ibool	flag)	/*!< in: TRUE if 1byte form */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
842
{
843
#if TRUE != 1
844
#error "TRUE != 1"
845
#endif
846
	ut_ad(flag <= TRUE);
847
848
	rec_set_bit_field_1(rec, flag, REC_OLD_SHORT, REC_OLD_SHORT_MASK,
849
			    REC_OLD_SHORT_SHIFT);
850
}
851
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
852
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
853
Returns the offset of nth field end if the record is stored in the 1-byte
854
offsets form. If the field is SQL null, the flag is ORed in the returned
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
855
value.
856
@return	offset of the start of the field, SQL null flag ORed */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
857
UNIV_INLINE
858
ulint
859
rec_1_get_field_end_info(
860
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
861
	const rec_t*	rec,	/*!< in: record */
862
	ulint		n)	/*!< in: field index */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
863
{
864
	ut_ad(rec_get_1byte_offs_flag(rec));
865
	ut_ad(n < rec_get_n_fields_old(rec));
866
867
	return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1)));
868
}
869
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
870
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
871
Returns the offset of nth field end if the record is stored in the 2-byte
872
offsets form. If the field is SQL null, the flag is ORed in the returned
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
873
value.
874
@return offset of the start of the field, SQL null flag and extern
875
storage flag ORed */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
876
UNIV_INLINE
877
ulint
878
rec_2_get_field_end_info(
879
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
880
	const rec_t*	rec,	/*!< in: record */
881
	ulint		n)	/*!< in: field index */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
882
{
883
	ut_ad(!rec_get_1byte_offs_flag(rec));
884
	ut_ad(n < rec_get_n_fields_old(rec));
885
886
	return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2)));
887
}
888
889
/* Get the base address of offsets.  The extra_size is stored at
890
this position, and following positions hold the end offsets of
891
the fields. */
892
#define rec_offs_base(offsets) (offsets + REC_OFFS_HEADER_SIZE)
893
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
894
/**********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
895
The following function returns the number of allocated elements
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
896
for an array of offsets.
897
@return	number of elements */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
898
UNIV_INLINE
899
ulint
900
rec_offs_get_n_alloc(
901
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
902
	const ulint*	offsets)/*!< in: array for rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
903
{
904
	ulint	n_alloc;
905
	ut_ad(offsets);
906
	n_alloc = offsets[0];
907
	ut_ad(n_alloc > REC_OFFS_HEADER_SIZE);
908
	UNIV_MEM_ASSERT_W(offsets, n_alloc * sizeof *offsets);
909
	return(n_alloc);
910
}
911
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
912
/**********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
913
The following function sets the number of allocated elements
914
for an array of offsets. */
915
UNIV_INLINE
916
void
917
rec_offs_set_n_alloc(
918
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
919
	ulint*	offsets,	/*!< out: array for rec_get_offsets(),
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
920
				must be allocated */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
921
	ulint	n_alloc)	/*!< in: number of elements */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
922
{
923
	ut_ad(offsets);
924
	ut_ad(n_alloc > REC_OFFS_HEADER_SIZE);
925
	UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets);
926
	offsets[0] = n_alloc;
927
}
928
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
929
/**********************************************************//**
930
The following function returns the number of fields in a record.
931
@return	number of fields */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
932
UNIV_INLINE
933
ulint
934
rec_offs_n_fields(
935
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
936
	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
937
{
938
	ulint	n_fields;
939
	ut_ad(offsets);
940
	n_fields = offsets[1];
941
	ut_ad(n_fields > 0);
942
	ut_ad(n_fields <= REC_MAX_N_FIELDS);
943
	ut_ad(n_fields + REC_OFFS_HEADER_SIZE
944
	      <= rec_offs_get_n_alloc(offsets));
945
	return(n_fields);
946
}
947
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
948
/************************************************************//**
949
Validates offsets returned by rec_get_offsets().
950
@return	TRUE if valid */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
951
UNIV_INLINE
952
ibool
953
rec_offs_validate(
954
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
955
	const rec_t*		rec,	/*!< in: record or NULL */
956
	const dict_index_t*	index,	/*!< in: record descriptor or NULL */
957
	const ulint*		offsets)/*!< in: array returned by
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
958
					rec_get_offsets() */
959
{
960
	ulint	i	= rec_offs_n_fields(offsets);
961
	ulint	last	= ULINT_MAX;
962
	ulint	comp	= *rec_offs_base(offsets) & REC_OFFS_COMPACT;
963
964
	if (rec) {
965
		ut_ad((ulint) rec == offsets[2]);
966
		if (!comp) {
967
			ut_a(rec_get_n_fields_old(rec) >= i);
968
		}
969
	}
970
	if (index) {
971
		ulint max_n_fields;
972
		ut_ad((ulint) index == offsets[3]);
973
		max_n_fields = ut_max(
974
			dict_index_get_n_fields(index),
975
			dict_index_get_n_unique_in_tree(index) + 1);
976
		if (comp && rec) {
977
			switch (rec_get_status(rec)) {
978
			case REC_STATUS_ORDINARY:
979
				break;
980
			case REC_STATUS_NODE_PTR:
981
				max_n_fields = dict_index_get_n_unique_in_tree(
982
					index) + 1;
983
				break;
984
			case REC_STATUS_INFIMUM:
985
			case REC_STATUS_SUPREMUM:
986
				max_n_fields = 1;
987
				break;
988
			default:
989
				ut_error;
990
			}
991
		}
992
		/* index->n_def == 0 for dummy indexes if !comp */
993
		ut_a(!comp || index->n_def);
994
		ut_a(!index->n_def || i <= max_n_fields);
995
	}
996
	while (i--) {
997
		ulint	curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK;
998
		ut_a(curr <= last);
999
		last = curr;
1000
	}
1001
	return(TRUE);
1002
}
1003
#ifdef UNIV_DEBUG
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1004
/************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1005
Updates debug data in offsets, in order to avoid bogus
1006
rec_offs_validate() failures. */
1007
UNIV_INLINE
1008
void
1009
rec_offs_make_valid(
1010
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1011
	const rec_t*		rec,	/*!< in: record */
1012
	const dict_index_t*	index,	/*!< in: record descriptor */
1013
	ulint*			offsets)/*!< in: array returned by
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1014
					rec_get_offsets() */
1015
{
1016
	ut_ad(rec);
1017
	ut_ad(index);
1018
	ut_ad(offsets);
1019
	ut_ad(rec_get_n_fields(rec, index) >= rec_offs_n_fields(offsets));
1020
	offsets[2] = (ulint) rec;
1021
	offsets[3] = (ulint) index;
1022
}
1023
#endif /* UNIV_DEBUG */
1024
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1025
/************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1026
The following function is used to get an offset to the nth
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1027
data field in a record.
1028
@return	offset from the origin of rec */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1029
UNIV_INLINE
1030
ulint
1031
rec_get_nth_field_offs(
1032
/*===================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1033
	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
1034
	ulint		n,	/*!< in: index of the field */
1035
	ulint*		len)	/*!< out: length of the field; UNIV_SQL_NULL
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1036
				if SQL null */
1037
{
1038
	ulint	offs;
1039
	ulint	length;
1040
	ut_ad(n < rec_offs_n_fields(offsets));
1041
	ut_ad(len);
1042
1043
	if (UNIV_UNLIKELY(n == 0)) {
1044
		offs = 0;
1045
	} else {
1046
		offs = rec_offs_base(offsets)[n] & REC_OFFS_MASK;
1047
	}
1048
1049
	length = rec_offs_base(offsets)[1 + n];
1050
1051
	if (length & REC_OFFS_SQL_NULL) {
1052
		length = UNIV_SQL_NULL;
1053
	} else {
1054
		length &= REC_OFFS_MASK;
1055
		length -= offs;
1056
	}
1057
1058
	*len = length;
1059
	return(offs);
1060
}
1061
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1062
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1063
Determine if the offsets are for a record in the new
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1064
compact format.
1065
@return	nonzero if compact format */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1066
UNIV_INLINE
1067
ulint
1068
rec_offs_comp(
1069
/*==========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1070
	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1071
{
1072
	ut_ad(rec_offs_validate(NULL, NULL, offsets));
1073
	return(*rec_offs_base(offsets) & REC_OFFS_COMPACT);
1074
}
1075
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1076
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1077
Determine if the offsets are for a record containing
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1078
externally stored columns.
1079
@return	nonzero if externally stored */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1080
UNIV_INLINE
1081
ulint
1082
rec_offs_any_extern(
1083
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1084
	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1085
{
1086
	ut_ad(rec_offs_validate(NULL, NULL, offsets));
1087
	return(UNIV_UNLIKELY(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL));
1088
}
1089
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1090
/******************************************************//**
1091
Returns nonzero if the extern bit is set in nth field of rec.
1092
@return	nonzero if externally stored */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1093
UNIV_INLINE
1094
ulint
1095
rec_offs_nth_extern(
1096
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1097
	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
1098
	ulint		n)	/*!< in: nth field */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1099
{
1100
	ut_ad(rec_offs_validate(NULL, NULL, offsets));
1101
	ut_ad(n < rec_offs_n_fields(offsets));
1102
	return(UNIV_UNLIKELY(rec_offs_base(offsets)[1 + n]
1103
			     & REC_OFFS_EXTERNAL));
1104
}
1105
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1106
/******************************************************//**
1107
Returns nonzero if the SQL NULL bit is set in nth field of rec.
1108
@return	nonzero if SQL NULL */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1109
UNIV_INLINE
1110
ulint
1111
rec_offs_nth_sql_null(
1112
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1113
	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
1114
	ulint		n)	/*!< in: nth field */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1115
{
1116
	ut_ad(rec_offs_validate(NULL, NULL, offsets));
1117
	ut_ad(n < rec_offs_n_fields(offsets));
1118
	return(UNIV_UNLIKELY(rec_offs_base(offsets)[1 + n]
1119
			     & REC_OFFS_SQL_NULL));
1120
}
1121
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1122
/******************************************************//**
1123
Gets the physical size of a field.
1124
@return	length of field */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1125
UNIV_INLINE
1126
ulint
1127
rec_offs_nth_size(
1128
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1129
	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
1130
	ulint		n)	/*!< in: nth field */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1131
{
1132
	ut_ad(rec_offs_validate(NULL, NULL, offsets));
1133
	ut_ad(n < rec_offs_n_fields(offsets));
1134
	if (!n) {
1135
		return(rec_offs_base(offsets)[1 + n] & REC_OFFS_MASK);
1136
	}
1137
	return((rec_offs_base(offsets)[1 + n] - rec_offs_base(offsets)[n])
1138
	       & REC_OFFS_MASK);
1139
}
1140
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1141
/******************************************************//**
1142
Returns the number of extern bits set in a record.
1143
@return	number of externally stored fields */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1144
UNIV_INLINE
1145
ulint
1146
rec_offs_n_extern(
1147
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1148
	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1149
{
1150
	ulint	n = 0;
1151
1152
	if (rec_offs_any_extern(offsets)) {
1153
		ulint	i;
1154
1155
		for (i = rec_offs_n_fields(offsets); i--; ) {
1156
			if (rec_offs_nth_extern(offsets, i)) {
1157
				n++;
1158
			}
1159
		}
1160
	}
1161
1162
	return(n);
1163
}
1164
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1165
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1166
Returns the offset of n - 1th field end if the record is stored in the 1-byte
1167
offsets form. If the field is SQL null, the flag is ORed in the returned
1168
value. This function and the 2-byte counterpart are defined here because the
1169
C-compiler was not able to sum negative and positive constant offsets, and
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1170
warned of constant arithmetic overflow within the compiler.
1171
@return	offset of the start of the PREVIOUS field, SQL null flag ORed */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1172
UNIV_INLINE
1173
ulint
1174
rec_1_get_prev_field_end_info(
1175
/*==========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1176
	const rec_t*	rec,	/*!< in: record */
1177
	ulint		n)	/*!< in: field index */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1178
{
1179
	ut_ad(rec_get_1byte_offs_flag(rec));
1180
	ut_ad(n <= rec_get_n_fields_old(rec));
1181
1182
	return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n)));
1183
}
1184
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1185
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1186
Returns the offset of n - 1th field end if the record is stored in the 2-byte
1187
offsets form. If the field is SQL null, the flag is ORed in the returned
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1188
value.
1189
@return	offset of the start of the PREVIOUS field, SQL null flag ORed */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1190
UNIV_INLINE
1191
ulint
1192
rec_2_get_prev_field_end_info(
1193
/*==========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1194
	const rec_t*	rec,	/*!< in: record */
1195
	ulint		n)	/*!< in: field index */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1196
{
1197
	ut_ad(!rec_get_1byte_offs_flag(rec));
1198
	ut_ad(n <= rec_get_n_fields_old(rec));
1199
1200
	return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n)));
1201
}
1202
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1203
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1204
Sets the field end info for the nth field if the record is stored in the
1205
1-byte format. */
1206
UNIV_INLINE
1207
void
1208
rec_1_set_field_end_info(
1209
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1210
	rec_t*	rec,	/*!< in: record */
1211
	ulint	n,	/*!< in: field index */
1212
	ulint	info)	/*!< in: value to set */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1213
{
1214
	ut_ad(rec_get_1byte_offs_flag(rec));
1215
	ut_ad(n < rec_get_n_fields_old(rec));
1216
1217
	mach_write_to_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1), info);
1218
}
1219
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1220
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1221
Sets the field end info for the nth field if the record is stored in the
1222
2-byte format. */
1223
UNIV_INLINE
1224
void
1225
rec_2_set_field_end_info(
1226
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1227
	rec_t*	rec,	/*!< in: record */
1228
	ulint	n,	/*!< in: field index */
1229
	ulint	info)	/*!< in: value to set */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1230
{
1231
	ut_ad(!rec_get_1byte_offs_flag(rec));
1232
	ut_ad(n < rec_get_n_fields_old(rec));
1233
1234
	mach_write_to_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2), info);
1235
}
1236
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1237
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1238
Returns the offset of nth field start if the record is stored in the 1-byte
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1239
offsets form.
1240
@return	offset of the start of the field */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1241
UNIV_INLINE
1242
ulint
1243
rec_1_get_field_start_offs(
1244
/*=======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1245
	const rec_t*	rec,	/*!< in: record */
1246
	ulint		n)	/*!< in: field index */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1247
{
1248
	ut_ad(rec_get_1byte_offs_flag(rec));
1249
	ut_ad(n <= rec_get_n_fields_old(rec));
1250
1251
	if (n == 0) {
1252
1253
		return(0);
1254
	}
1255
1256
	return(rec_1_get_prev_field_end_info(rec, n)
1257
	       & ~REC_1BYTE_SQL_NULL_MASK);
1258
}
1259
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1260
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1261
Returns the offset of nth field start if the record is stored in the 2-byte
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1262
offsets form.
1263
@return	offset of the start of the field */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1264
UNIV_INLINE
1265
ulint
1266
rec_2_get_field_start_offs(
1267
/*=======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1268
	const rec_t*	rec,	/*!< in: record */
1269
	ulint		n)	/*!< in: field index */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1270
{
1271
	ut_ad(!rec_get_1byte_offs_flag(rec));
1272
	ut_ad(n <= rec_get_n_fields_old(rec));
1273
1274
	if (n == 0) {
1275
1276
		return(0);
1277
	}
1278
1279
	return(rec_2_get_prev_field_end_info(rec, n)
1280
	       & ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK));
1281
}
1282
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1283
/******************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1284
The following function is used to read the offset of the start of a data field
1285
in the record. The start of an SQL null field is the end offset of the
1286
previous non-null field, or 0, if none exists. If n is the number of the last
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1287
field + 1, then the end offset of the last field is returned.
1288
@return	offset of the start of the field */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1289
UNIV_INLINE
1290
ulint
1291
rec_get_field_start_offs(
1292
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1293
	const rec_t*	rec,	/*!< in: record */
1294
	ulint		n)	/*!< in: field index */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1295
{
1296
	ut_ad(rec);
1297
	ut_ad(n <= rec_get_n_fields_old(rec));
1298
1299
	if (n == 0) {
1300
1301
		return(0);
1302
	}
1303
1304
	if (rec_get_1byte_offs_flag(rec)) {
1305
1306
		return(rec_1_get_field_start_offs(rec, n));
1307
	}
1308
1309
	return(rec_2_get_field_start_offs(rec, n));
1310
}
1311
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1312
/************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1313
Gets the physical size of an old-style field.
1314
Also an SQL null may have a field of size > 0,
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1315
if the data type is of a fixed size.
1316
@return	field size in bytes */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1317
UNIV_INLINE
1318
ulint
1319
rec_get_nth_field_size(
1320
/*===================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1321
	const rec_t*	rec,	/*!< in: record */
1322
	ulint		n)	/*!< in: index of the field */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1323
{
1324
	ulint	os;
1325
	ulint	next_os;
1326
1327
	os = rec_get_field_start_offs(rec, n);
1328
	next_os = rec_get_field_start_offs(rec, n + 1);
1329
1330
	ut_ad(next_os - os < UNIV_PAGE_SIZE);
1331
1332
	return(next_os - os);
1333
}
1334
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1335
/***********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1336
This is used to modify the value of an already existing field in a record.
1337
The previous value must have exactly the same size as the new value. If len
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1338
is UNIV_SQL_NULL then the field is treated as an SQL null.
1339
For records in ROW_FORMAT=COMPACT (new-style records), len must not be
1340
UNIV_SQL_NULL unless the field already is SQL null. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1341
UNIV_INLINE
1342
void
1343
rec_set_nth_field(
1344
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1345
	rec_t*		rec,	/*!< in: record */
1346
	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
1347
	ulint		n,	/*!< in: index number of the field */
1348
	const void*	data,	/*!< in: pointer to the data
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1349
				if not SQL null */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1350
	ulint		len)	/*!< in: length of the data or UNIV_SQL_NULL */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1351
{
1352
	byte*	data2;
1353
	ulint	len2;
1354
1355
	ut_ad(rec);
1356
	ut_ad(rec_offs_validate(rec, NULL, offsets));
1357
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1358
	if (UNIV_UNLIKELY(len == UNIV_SQL_NULL)) {
1359
		if (!rec_offs_nth_sql_null(offsets, n)) {
1360
			ut_a(!rec_offs_comp(offsets));
1361
			rec_set_nth_field_sql_null(rec, n);
1362
		}
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1363
1364
		return;
1365
	}
1366
1367
	data2 = rec_get_nth_field(rec, offsets, n, &len2);
1368
	if (len2 == UNIV_SQL_NULL) {
1369
		ut_ad(!rec_offs_comp(offsets));
1370
		rec_set_nth_field_null_bit(rec, n, FALSE);
1371
		ut_ad(len == rec_get_nth_field_size(rec, n));
1372
	} else {
1373
		ut_ad(len2 == len);
1374
	}
1375
1376
	ut_memcpy(data2, data, len);
1377
}
1378
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1379
/**********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1380
The following function returns the data size of an old-style physical
1381
record, that is the sum of field lengths. SQL null fields
1382
are counted as length 0 fields. The value returned by the function
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1383
is the distance from record origin to record end in bytes.
1384
@return	size */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1385
UNIV_INLINE
1386
ulint
1387
rec_get_data_size_old(
1388
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1389
	const rec_t*	rec)	/*!< in: physical record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1390
{
1391
	ut_ad(rec);
1392
1393
	return(rec_get_field_start_offs(rec, rec_get_n_fields_old(rec)));
1394
}
1395
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1396
/**********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1397
The following function sets the number of fields in offsets. */
1398
UNIV_INLINE
1399
void
1400
rec_offs_set_n_fields(
1401
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1402
	ulint*	offsets,	/*!< in/out: array returned by
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1403
				rec_get_offsets() */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1404
	ulint	n_fields)	/*!< in: number of fields */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1405
{
1406
	ut_ad(offsets);
1407
	ut_ad(n_fields > 0);
1408
	ut_ad(n_fields <= REC_MAX_N_FIELDS);
1409
	ut_ad(n_fields + REC_OFFS_HEADER_SIZE
1410
	      <= rec_offs_get_n_alloc(offsets));
1411
	offsets[1] = n_fields;
1412
}
1413
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1414
/**********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1415
The following function returns the data size of a physical
1416
record, that is the sum of field lengths. SQL null fields
1417
are counted as length 0 fields. The value returned by the function
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1418
is the distance from record origin to record end in bytes.
1419
@return	size */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1420
UNIV_INLINE
1421
ulint
1422
rec_offs_data_size(
1423
/*===============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1424
	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1425
{
1426
	ulint	size;
1427
1428
	ut_ad(rec_offs_validate(NULL, NULL, offsets));
1429
	size = rec_offs_base(offsets)[rec_offs_n_fields(offsets)]
1430
		& REC_OFFS_MASK;
1431
	ut_ad(size < UNIV_PAGE_SIZE);
1432
	return(size);
1433
}
1434
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1435
/**********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1436
Returns the total size of record minus data size of record. The value
1437
returned by the function is the distance from record start to record origin
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1438
in bytes.
1439
@return	size */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1440
UNIV_INLINE
1441
ulint
1442
rec_offs_extra_size(
1443
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1444
	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1445
{
1446
	ulint	size;
1447
	ut_ad(rec_offs_validate(NULL, NULL, offsets));
1448
	size = *rec_offs_base(offsets) & ~(REC_OFFS_COMPACT | REC_OFFS_EXTERNAL);
1449
	ut_ad(size < UNIV_PAGE_SIZE);
1450
	return(size);
1451
}
1452
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1453
/**********************************************************//**
1454
Returns the total size of a physical record.
1455
@return	size */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1456
UNIV_INLINE
1457
ulint
1458
rec_offs_size(
1459
/*==========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1460
	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1461
{
1462
	return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets));
1463
}
1464
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1465
/**********************************************************//**
1466
Returns a pointer to the end of the record.
1467
@return	pointer to end */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1468
UNIV_INLINE
1469
byte*
1470
rec_get_end(
1471
/*========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1472
	rec_t*		rec,	/*!< in: pointer to record */
1473
	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1474
{
1475
	ut_ad(rec_offs_validate(rec, NULL, offsets));
1476
	return(rec + rec_offs_data_size(offsets));
1477
}
1478
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1479
/**********************************************************//**
1480
Returns a pointer to the start of the record.
1481
@return	pointer to start */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1482
UNIV_INLINE
1483
byte*
1484
rec_get_start(
1485
/*==========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1486
	rec_t*		rec,	/*!< in: pointer to record */
1487
	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1488
{
1489
	ut_ad(rec_offs_validate(rec, NULL, offsets));
1490
	return(rec - rec_offs_extra_size(offsets));
1491
}
1492
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1493
/***************************************************************//**
1494
Copies a physical record to a buffer.
1495
@return	pointer to the origin of the copy */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1496
UNIV_INLINE
1497
rec_t*
1498
rec_copy(
1499
/*=====*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1500
	void*		buf,	/*!< in: buffer */
1501
	const rec_t*	rec,	/*!< in: physical record */
1502
	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1503
{
1504
	ulint	extra_len;
1505
	ulint	data_len;
1506
1507
	ut_ad(rec && buf);
1508
	ut_ad(rec_offs_validate((rec_t*) rec, NULL, offsets));
1509
	ut_ad(rec_validate(rec, offsets));
1510
1511
	extra_len = rec_offs_extra_size(offsets);
1512
	data_len = rec_offs_data_size(offsets);
1513
1514
	ut_memcpy(buf, rec - extra_len, extra_len + data_len);
1515
1516
	return((byte*)buf + extra_len);
1517
}
1518
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1519
/**********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1520
Returns the extra size of an old-style physical record if we know its
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1521
data size and number of fields.
1522
@return	extra size */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1523
UNIV_INLINE
1524
ulint
1525
rec_get_converted_extra_size(
1526
/*=========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1527
	ulint	data_size,	/*!< in: data size */
1528
	ulint	n_fields,	/*!< in: number of fields */
1529
	ulint	n_ext)		/*!< in: number of externally stored columns */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1530
{
1531
	if (!n_ext && data_size <= REC_1BYTE_OFFS_LIMIT) {
1532
1533
		return(REC_N_OLD_EXTRA_BYTES + n_fields);
1534
	}
1535
1536
	return(REC_N_OLD_EXTRA_BYTES + 2 * n_fields);
1537
}
1538
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1539
/**********************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1540
The following function returns the size of a data tuple when converted to
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1541
a physical record.
1542
@return	size */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1543
UNIV_INLINE
1544
ulint
1545
rec_get_converted_size(
1546
/*===================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1547
	dict_index_t*	index,	/*!< in: record descriptor */
1548
	const dtuple_t*	dtuple,	/*!< in: data tuple */
1549
	ulint		n_ext)	/*!< in: number of externally stored columns */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1550
{
1551
	ulint	data_size;
1552
	ulint	extra_size;
1553
1554
	ut_ad(index);
1555
	ut_ad(dtuple);
1556
	ut_ad(dtuple_check_typed(dtuple));
1557
1558
	ut_ad(index->type & DICT_UNIVERSAL
1559
	      || dtuple_get_n_fields(dtuple)
1560
	      == (((dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK)
1561
		   == REC_STATUS_NODE_PTR)
1562
		  ? dict_index_get_n_unique_in_tree(index) + 1
1563
		  : dict_index_get_n_fields(index)));
1564
1565
	if (dict_table_is_comp(index->table)) {
1566
		return(rec_get_converted_size_comp(index,
1567
						   dtuple_get_info_bits(dtuple)
1568
						   & REC_NEW_STATUS_MASK,
1569
						   dtuple->fields,
1570
						   dtuple->n_fields, NULL));
1571
	}
1572
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1573
	data_size = dtuple_get_data_size(dtuple, 0);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1574
1575
	extra_size = rec_get_converted_extra_size(
1576
		data_size, dtuple_get_n_fields(dtuple), n_ext);
1577
1578
	return(data_size + extra_size);
1579
}
1580
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1581
#ifndef UNIV_HOTBACKUP
1582
/************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1583
Folds a prefix of a physical record to a ulint. Folds only existing fields,
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1584
that is, checks that we do not run out of the record.
1585
@return	the folded value */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1586
UNIV_INLINE
1587
ulint
1588
rec_fold(
1589
/*=====*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1590
	const rec_t*	rec,		/*!< in: the physical record */
1591
	const ulint*	offsets,	/*!< in: array returned by
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1592
					rec_get_offsets() */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1593
	ulint		n_fields,	/*!< in: number of complete
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1594
					fields to fold */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1595
	ulint		n_bytes,	/*!< in: number of bytes to fold
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1596
					in an incomplete last field */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1597
	dulint		tree_id)	/*!< in: index tree id */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1598
{
1599
	ulint		i;
1600
	const byte*	data;
1601
	ulint		len;
1602
	ulint		fold;
1603
	ulint		n_fields_rec;
1604
1605
	ut_ad(rec_offs_validate(rec, NULL, offsets));
1606
	ut_ad(rec_validate(rec, offsets));
1607
	ut_ad(n_fields + n_bytes > 0);
1608
1609
	n_fields_rec = rec_offs_n_fields(offsets);
1610
	ut_ad(n_fields <= n_fields_rec);
1611
	ut_ad(n_fields < n_fields_rec || n_bytes == 0);
1612
1613
	if (n_fields > n_fields_rec) {
1614
		n_fields = n_fields_rec;
1615
	}
1616
1617
	if (n_fields == n_fields_rec) {
1618
		n_bytes = 0;
1619
	}
1620
1621
	fold = ut_fold_dulint(tree_id);
1622
1623
	for (i = 0; i < n_fields; i++) {
1624
		data = rec_get_nth_field(rec, offsets, i, &len);
1625
1626
		if (len != UNIV_SQL_NULL) {
1627
			fold = ut_fold_ulint_pair(fold,
1628
						  ut_fold_binary(data, len));
1629
		}
1630
	}
1631
1632
	if (n_bytes > 0) {
1633
		data = rec_get_nth_field(rec, offsets, i, &len);
1634
1635
		if (len != UNIV_SQL_NULL) {
1636
			if (len > n_bytes) {
1637
				len = n_bytes;
1638
			}
1639
1640
			fold = ut_fold_ulint_pair(fold,
1641
						  ut_fold_binary(data, len));
1642
		}
1643
	}
1644
1645
	return(fold);
1646
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1647
#endif /* !UNIV_HOTBACKUP */