MySQL 9.7.4
Source Code Documentation
page0page.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 1994, 2026, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is designed to work with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation. The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have either included with
15the program or referenced in the documentation.
16
17This program is distributed in the hope that it will be useful, but WITHOUT
18ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
20for more details.
21
22You should have received a copy of the GNU General Public License along with
23this program; if not, write to the Free Software Foundation, Inc.,
2451 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
26*****************************************************************************/
27
28#include <stddef.h>
29#include <sys/types.h>
30
31/** @file include/page0page.h
32 Index page routines
33
34 Created 2/2/1994 Heikki Tuuri
35 *******************************************************/
36
37#ifndef page0page_h
38#define page0page_h
39
40#include "univ.i"
41
42#include "buf0buf.h"
43#include "data0data.h"
44#include "dict0dict.h"
45#include "fil0fil.h"
46#include "fsp0fsp.h"
47#include "mtr0mtr.h"
48#include "page0types.h"
49#include "rem0rec.h"
50
51/* PAGE DIRECTORY
52 ==============
53*/
54
55typedef byte page_dir_slot_t;
57
58/* Offset of the directory start down from the page end. We call the
59slot with the highest file address directory start, as it points to
60the first record in the list of records. */
61constexpr uint32_t PAGE_DIR = FIL_PAGE_DATA_END;
62
63/* We define a slot in the page directory as two bytes */
64constexpr uint32_t PAGE_DIR_SLOT_SIZE = 2;
65
66/* The offset of the physically lower end of the directory, counted from
67page end, when the page is empty */
69
70/* The maximum and minimum number of records owned by a directory slot. The
71number may drop below the minimum in the first and the last slot in the
72directory. */
73constexpr uint32_t PAGE_DIR_SLOT_MAX_N_OWNED = 8;
74constexpr uint32_t PAGE_DIR_SLOT_MIN_N_OWNED = 4;
75
76/* The infimum and supremum records are omitted from the compressed page.
77On compress, we compare that the records are there, and on uncompress we
78restore the records. */
79/** Extra bytes of an infimum record */
80static const byte infimum_extra[] = {
81 0x01, /* info_bits=0, n_owned=1 */
82 0x00, 0x02 /* heap_no=0, status=2 */
83 /* ?, ? */ /* next=(first user rec, or supremum) */
84};
85/** Data bytes of an infimum record */
86static const byte infimum_data[] = {
87 0x69, 0x6e, 0x66, 0x69, 0x6d, 0x75, 0x6d, 0x00 /* "infimum\0" */
88};
89/** Extra bytes and data bytes of a supremum record */
90static const byte supremum_extra_data[] = {
91 /* 0x0?, */ /* info_bits=0, n_owned=1..8 */
92 0x00,
93 0x0b, /* heap_no=1, status=3 */
94 0x00,
95 0x00, /* next=0 */
96 0x73,
97 0x75,
98 0x70,
99 0x72,
100 0x65,
101 0x6d,
102 0x75,
103 0x6d /* "supremum" */
104};
105
106/** Gets the start of a page.
107@param[in] ptr pointer to page frame
108@return start of the page */
109static inline page_t *page_align(const void *ptr);
110
111/** Gets the offset within a page.
112@param[in] ptr pointer to page frame
113@return offset from the start of the page */
114static inline ulint page_offset(const void *ptr);
115
116/** Returns the max trx id field value. */
117static inline trx_id_t page_get_max_trx_id(const page_t *page); /*!< in: page */
118
119/** Sets the max trx id field value.
120@param[in,out] block Page
121@param[in,out] page_zip Compressed page, or NULL
122@param[in] trx_id Transaction id
123@param[in,out] mtr Mini-transaction, or NULL */
124void page_set_max_trx_id(buf_block_t *block, page_zip_des_t *page_zip,
125 trx_id_t trx_id, mtr_t *mtr);
126
127/** Sets the max trx id field value if trx_id is bigger than the previous
128value.
129@param[in,out] block Page
130@param[in,out] page_zip Compressed page whose uncompressed part will
131 be updated, or NULL
132@param[in] trx_id Transaction id
133@param[in,out] mtr Mini-transaction */
134static inline void page_update_max_trx_id(buf_block_t *block,
135 page_zip_des_t *page_zip,
136 trx_id_t trx_id, mtr_t *mtr);
137
138/** Returns the RTREE SPLIT SEQUENCE NUMBER (FIL_RTREE_SPLIT_SEQ_NUM).
139@param[in] page page
140@return SPLIT SEQUENCE NUMBER */
141static inline node_seq_t page_get_ssn_id(const page_t *page);
142
143/** Sets the RTREE SPLIT SEQUENCE NUMBER field value
144@param[in,out] block Page
145@param[in,out] page_zip Compressed page whose uncompressed part will
146 be updated, or NULL
147@param[in] ssn_id Split sequence id
148@param[in,out] mtr Mini-transaction */
149static inline void page_set_ssn_id(buf_block_t *block, page_zip_des_t *page_zip,
150 node_seq_t ssn_id, mtr_t *mtr);
151
152/** Reads the given header field.
153@param[in] page page
154@param[in] field PAGE_N_DIR_SLOTS, ... */
155static inline uint16_t page_header_get_field(const page_t *page, ulint field);
156
157/** Sets the given header field.
158@param[in,out] page page
159@param[in,out] page_zip compressed page whose uncompressed part will
160 be updated, or NULL
161@param[in] field PAGE_N_DIR_SLOTS, ...
162@param[in] val value */
163static inline void page_header_set_field(page_t *page, page_zip_des_t *page_zip,
164 ulint field, ulint val);
165
166/** Returns the offset stored in the given header field.
167@param[in] page Page.
168@param[in] field PAGE_FREE, ...
169@return offset from the start of the page, or 0 */
170[[nodiscard]] static inline ulint page_header_get_offs(const page_t *page,
171 ulint field);
172
173/** Returns the pointer stored in the given header field, or NULL. */
174static inline byte *page_header_get_ptr(page_t *page, uint32_t field) {
175 if (page_header_get_offs(page, field)) {
176 return page + page_header_get_offs(page, field);
177 }
178 return nullptr;
179}
180
181static inline const byte *page_header_get_ptr(const page_t *page,
182 uint32_t field) {
183 if (page_header_get_offs(page, field)) {
184 return page + page_header_get_offs(page, field);
185 }
186 return nullptr;
187}
188
189/** Sets the pointer stored in the given header field.
190@param[in,out] page page
191@param[in,out] page_zip compressed page whose uncompressed part will
192 be updated, or NULL
193@param[in,out] field PAGE_FREE, ...
194@param[in] ptr pointer or NULL */
195static inline void page_header_set_ptr(page_t *page, page_zip_des_t *page_zip,
196 ulint field, const byte *ptr);
197#ifndef UNIV_HOTBACKUP
198
199/** Resets the last insert info field in the page header. Writes to mlog about
200this operation.
201@param[in] page page
202@param[in,out] page_zip compressed page whose uncompressed part will
203 be updated, or NULL
204@param[in] mtr mtr */
206 page_zip_des_t *page_zip,
207 mtr_t *mtr);
208#endif /* !UNIV_HOTBACKUP */
209
210/** Gets the offset of the first record on the page.
211 @return offset of the first record in record list, relative from page */
213 const page_t *page); /*!< in: page which must have record(s) */
214/** Gets the offset of the last record on the page.
215 @return offset of the last record in record list, relative from page */
217 const page_t *page); /*!< in: page which must have record(s) */
218static inline byte *page_get_infimum_rec(byte *page) {
220}
221static inline const byte *page_get_infimum_rec(const byte *page) {
223}
224static inline byte *page_get_supremum_rec(byte *page) {
226}
227static inline const byte *page_get_supremum_rec(const byte *page) {
229}
230
231/** Returns the nth record of the record list.
232 This is the inverse function of page_rec_get_n_recs_before().
233 @return nth record */
234[[nodiscard]] const rec_t *page_rec_get_nth_const(
235 const page_t *page, /*!< in: page */
236 ulint nth); /*!< in: nth record */
237
238/** Returns the nth record of the record list.
239This is the inverse function of page_rec_get_n_recs_before().
240@param[in] page page
241@param[in] nth nth record
242@return nth record */
243[[nodiscard]] static inline rec_t *page_rec_get_nth(page_t *page, ulint nth);
244
245#ifndef UNIV_HOTBACKUP
246/** Returns the middle record of the records on the page. If there is an
247 even number of records in the list, returns the first record of the
248 upper half-list.
249 @return middle record */
250[[nodiscard]] static inline rec_t *page_get_middle_rec(
251 page_t *page); /*!< in: page */
252#endif /* !UNIV_HOTBACKUP */
253/** Gets the page number.
254 @return page number */
255static inline page_no_t page_get_page_no(const page_t *page); /*!< in: page */
256/** Gets the tablespace identifier.
257 @return space id */
258static inline space_id_t page_get_space_id(const page_t *page); /*!< in: page */
259
260/** Gets the space id and page number identifying the page.
261 @return page number */
262static inline page_id_t page_get_page_id(const page_t *page);
263
264/** Gets the number of user records on page (the infimum and supremum records
265 are not user records).
266 @return number of user records */
267static inline ulint page_get_n_recs(const page_t *page); /*!< in: index page */
268/** Returns the number of records before the given record in chain.
269 The number includes infimum and supremum records.
270 This is the inverse function of page_rec_get_nth().
271 @return number of records */
273 const rec_t *rec); /*!< in: the physical record */
274/** Gets the number of records in the heap.
275 @param[in] page index page
276 @return number of user records */
277static inline uint16_t page_dir_get_n_heap(const page_t *page);
278
279/** Sets the number of records in the heap.
280@param[in,out] page index page
281@param[in,out] page_zip compressed page whose uncompressed part will
282 be updated, or NULL. Note that the size of the
283 dense page directory in the compressed page
284 trailer is n_heap * PAGE_ZIP_DIR_SLOT_SIZE.
285@param[in] n_heap number of records*/
286static inline void page_dir_set_n_heap(page_t *page, page_zip_des_t *page_zip,
287 ulint n_heap);
288
289/** Gets the number of dir slots in directory.
290 @return number of slots */
292 const page_t *page); /*!< in: index page */
293
294/** Sets the number of dir slots in directory.
295@param[in,out] page page
296@param[in,out] page_zip compressed page whose uncompressed part will
297 be updated, or NULL
298@param[in] n_slots number of slots */
299static inline void page_dir_set_n_slots(page_t *page, page_zip_des_t *page_zip,
300 ulint n_slots);
301
302#ifdef UNIV_DEBUG
303/** Gets pointer to nth directory slot.
304@param[in] page index page
305@param[in] n position
306@return pointer to dir slot */
308 ulint n);
309#else /* UNIV_DEBUG */
310#define page_dir_get_nth_slot(page, n) \
311 ((page) + (UNIV_PAGE_SIZE - PAGE_DIR - (n + 1) * PAGE_DIR_SLOT_SIZE))
312#endif /* UNIV_DEBUG */
313
314/** Used to check the consistency of a record on a page.
315 @return true if succeed */
316static inline bool page_rec_check(const rec_t *rec); /*!< in: record */
317/** Gets the record pointed to by a directory slot.
318 @return pointer to record */
319static inline const rec_t *page_dir_slot_get_rec(
320 const page_dir_slot_t *slot); /*!< in: directory slot */
321
322/** This is used to set the record offset in a directory slot.
323@param[in] rec record on the page
324@param[in] slot directory slot */
325static inline void page_dir_slot_set_rec(page_dir_slot_t *slot, rec_t *rec);
326
327/** Gets the number of records owned by a directory slot.
328 @return number of records */
330 const page_dir_slot_t *slot); /*!< in: page directory slot */
331
332/** This is used to set the owned records field of a directory slot.
333@param[in,out] slot directory slot
334@param[in,out] page_zip compressed page, or NULL
335@param[in] n number of records owned by the slot */
337 page_zip_des_t *page_zip, ulint n);
338
339/** Calculates the space reserved for directory slots of a given
340 number of records. The exact value is a fraction number
341 n * PAGE_DIR_SLOT_SIZE / PAGE_DIR_SLOT_MIN_N_OWNED, and it is
342 rounded upwards to an integer. */
344 ulint n_recs); /*!< in: number of records */
345/** Looks for the directory slot which owns the given record.
346 @return the directory slot number */
348 const rec_t *rec); /*!< in: the physical record */
349/** Determine whether the page is in new-style compact format.
350 @return nonzero if the page is in compact format, zero if it is in
351 old-style format */
352static inline bool page_is_comp(const page_t *page); /*!< in: index page */
353/** true if the record is on a page in compact format.
354 @return nonzero if in compact format */
355static inline bool page_rec_is_comp(const rec_t *rec); /*!< in: record */
356/** Returns the heap number of a record.
357 @return heap number */
359 const rec_t *rec); /*!< in: the physical record */
360/** Determine whether the page is a B-tree leaf.
361 @return true if the page is a B-tree leaf (PAGE_LEVEL = 0) */
362[[nodiscard]] static inline bool page_is_leaf(
363 const page_t *page); /*!< in: page */
364/** Determine whether the page is empty.
365 @return true if the page is empty (PAGE_N_RECS = 0) */
366[[nodiscard]] static inline bool page_is_empty(
367 const page_t *page); /*!< in: page */
368/** Determine whether a page is an index root page.
369@param[in] page page frame
370@return true if the page is a root page of an index */
371[[nodiscard]] static inline bool page_is_root(const page_t *page);
372/** Determine whether the page contains garbage.
373 @return true if the page contains garbage (PAGE_GARBAGE is not 0) */
374[[nodiscard]] static inline bool page_has_garbage(
375 const page_t *page); /*!< in: page */
376
377/** Gets the pointer to the next record on the page.
378@param[in] rec pointer to record
379@param[in] comp nonzero=compact page layout
380@return pointer to next record */
381static inline const rec_t *page_rec_get_next_low(const rec_t *rec, ulint comp);
382
383/** Gets the offset of the next record on the page after validating that it is
384safe for page-level record access.
385@param[in] rec pointer to record
386@param[in] comp true iff compact page layout is used
387@return the page offset of the next chained record, or unexpected offset in case
388the encoded next field is invalid. */
389[[nodiscard]] static inline ut::Expected<uint16_t, uint16_t>
390page_rec_try_get_next_offs(const rec_t *rec, bool comp);
391
392/** Gets the pointer to the next record on the page.
393 @return pointer to next record */
395 rec_t *rec); /*!< in: pointer to record */
396/** Gets the pointer to the next record on the page.
397 @return pointer to next record */
398static inline const rec_t *page_rec_get_next_const(
399 const rec_t *rec); /*!< in: pointer to record */
400/** Gets the pointer to the next non delete-marked record on the page.
401 If all subsequent records are delete-marked, then this function
402 will return the supremum record.
403 @return pointer to next non delete-marked record or pointer to supremum */
405 const rec_t *rec); /*!< in: pointer to record */
406
407/** Sets the pointer to the next record on the page.
408@param[in] rec pointer to record, must not be page supremum
409@param[in] next pointer to next record, must not be page infimum */
410static inline void page_rec_set_next(rec_t *rec, const rec_t *next);
411
412/** Gets the pointer to the previous record.
413 @return pointer to previous record */
414static inline const rec_t *page_rec_get_prev_const(
415 const rec_t *rec); /*!< in: pointer to record, must not be page
416 infimum */
417/** Gets the pointer to the previous record.
418 @return pointer to previous record */
419static inline rec_t *page_rec_get_prev(rec_t *rec); /*!< in: pointer to record,
420 must not be page infimum */
421/** true if the record is a user record on the page.
422@param[in] offset record offset on page
423@return true if a user record */
424static inline bool page_rec_is_user_rec_low(ulint offset);
425
426/** true if the record is the supremum record on a page.
427@param[in] offset record offset on page
428@return true if the supremum record */
429static inline bool page_rec_is_supremum_low(ulint offset);
430
431/** true if the record is the infimum record on a page.
432@param[in] offset record offset on page
433@return true if the infimum record */
434static inline bool page_rec_is_infimum_low(ulint offset);
435
436/** true if the record is a user record on the page.
437 @return true if a user record */
438[[nodiscard]] static inline bool page_rec_is_user_rec(
439 const rec_t *rec); /*!< in: record */
440/** true if the record is the supremum record on a page.
441 @return true if the supremum record */
442[[nodiscard]] static inline bool page_rec_is_supremum(
443 const rec_t *rec); /*!< in: record */
444
445/** true if the record is the infimum record on a page.
446 @return true if the infimum record */
447[[nodiscard]] static inline bool page_rec_is_infimum(
448 const rec_t *rec); /*!< in: record */
449
450/** true if the record is the first user record on a page.
451@param[in] rec Record.
452@param[in] page Page.
453@return true if the first user record */
454[[nodiscard]] static inline bool page_rec_is_first(const rec_t *rec,
455 const page_t *page);
456
457/** true if the record is the second user record on a page.
458@param[in] rec Record.
459@param[in] page Page.
460@return true if the second user record */
461[[nodiscard]] static inline bool page_rec_is_second(const rec_t *rec,
462 const page_t *page);
463
464/** true if the record is the last user record on a page.
465@param[in] rec Record.
466@param[in] page Page.
467@return true if the last user record */
468[[nodiscard]] static inline bool page_rec_is_last(const rec_t *rec,
469 const page_t *page);
470
471/** true if distance between the records (measured in number of times we have to
472move to the next record) is at most the specified value
473@param[in] left_rec lefter record
474@param[in] right_rec righter record
475@param[in] val specified value to compare
476@return true if the distance is smaller than the value */
477[[nodiscard]] static inline bool page_rec_distance_is_at_most(
478 const rec_t *left_rec, const rec_t *right_rec, ulint val);
479
480/** true if the record is the second last user record on a page.
481@param[in] rec Record.
482@param[in] page Page.
483@return true if the second last user record */
484[[nodiscard]] static inline bool page_rec_is_second_last(const rec_t *rec,
485 const page_t *page);
486
487/** Looks for the record which owns the given record.
488 @return the owner record */
490 rec_t *rec); /*!< in: the physical record */
491
492/** Returns the maximum combined size of records which can be inserted on top
493of record heap.
494@param[in] page index page
495@param[in] n_recs number of records
496@return maximum combined size for inserted records */
497static inline ulint page_get_max_insert_size(const page_t *page, ulint n_recs);
498
499/** Returns the maximum combined size of records which can be inserted on top
500of record heap if page is first reorganized.
501@param[in] page index page
502@param[in] n_recs number of records
503@return maximum combined size for inserted records */
505 const page_t *page, ulint n_recs);
506
507/** Calculates free space if a page is emptied.
508@param[in] comp nonzero=compact page format
509@return free space */
510static inline ulint page_get_free_space_of_empty(bool comp);
511
512/** Returns the base extra size of a physical record. This is the
513 size of the fixed header, independent of the record size.
514 @return REC_N_NEW_EXTRA_BYTES or REC_N_OLD_EXTRA_BYTES */
516 const rec_t *rec); /*!< in: physical record */
517/** Returns the sum of the sizes of the records in the record list
518 excluding the infimum and supremum records.
519 @return data in bytes */
521 const page_t *page); /*!< in: index page */
522
523/** Allocates a block of memory from the head of the free list of an index
524page.
525@param[in,out] page index page
526@param[in,out] page_zip compressed page with enough space available
527 for inserting the record, or NULL
528@param[in] next_rec pointer to the new head of the free record
529 list
530@param[in] need number of bytes allocated */
531static inline void page_mem_alloc_free(page_t *page, page_zip_des_t *page_zip,
532 rec_t *next_rec, ulint need);
533
534/** Allocates a block of memory from the heap of an index page.
535 @return pointer to start of allocated buffer, or NULL if allocation fails */
537 page_t *page, /*!< in/out: index page */
538 page_zip_des_t *page_zip, /*!< in/out: compressed page with enough
539 space available for inserting the record,
540 or NULL */
541 ulint need, /*!< in: total number of bytes needed */
542 ulint *heap_no); /*!< out: this contains the heap number
543 of the allocated record
544 if allocation succeeds */
545
546/** Puts a record to free list.
547@param[in,out] page index page
548@param[in,out] page_zip compressed page, or NULL
549@param[in] rec pointer to the (origin of) record
550@param[in] index index of rec
551@param[in] offsets array returned by rec_get_offsets() */
552static inline void page_mem_free(page_t *page, page_zip_des_t *page_zip,
553 rec_t *rec, const dict_index_t *index,
554 const ulint *offsets);
555
556/** Create an uncompressed B-tree or R-tree or SDI index page.
557@param[in] block A buffer block where the page is created
558@param[in] mtr Mini-transaction handle
559@param[in] comp nonzero=compact page format
560@param[in] page_type Page type
561@return pointer to the page */
562page_t *page_create(buf_block_t *block, mtr_t *mtr, ulint comp,
563 page_type_t page_type);
564
565/** Create a compressed B-tree index page.
566@param[in,out] block Buffer frame where the page is created
567@param[in] index Index of the page, or NULL when applying
568 TRUNCATE log record during recovery
569@param[in] level The B-tree level of the page
570@param[in] max_trx_id PAGE_MAX_TRX_ID
571@param[in] mtr Mini-transaction handle
572@param[in] page_type Page type to be created. Only FIL_PAGE_INDEX,
573 FIL_PAGE_RTREE, FIL_PAGE_SDI allowed
574@return pointer to the page */
576 trx_id_t max_trx_id, mtr_t *mtr, page_type_t page_type);
577
578/** Empty a previously created B-tree index page.
579@param[in,out] block B-tree block
580@param[in] index The index of the page
581@param[in,out] mtr Mini-transaction */
583
584/** Differs from page_copy_rec_list_end, because this function does not
585 touch the lock table and max trx id on page or compress the page.
586
587 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE
588 if new_block is a compressed leaf page in a secondary index.
589 This has to be done either within the same mini-transaction,
590 or by invoking ibuf_reset_free_bits() before mtr_commit(). */
592 buf_block_t *new_block, /*!< in: index page to copy to */
593 buf_block_t *block, /*!< in: index page of rec */
594 rec_t *rec, /*!< in: record on page */
595 dict_index_t *index, /*!< in: record descriptor */
596 mtr_t *mtr); /*!< in: mtr */
597/** Copies records from page to new_page, from the given record onward,
598 including that record. Infimum and supremum records are not copied.
599 The records are copied to the start of the record list on new_page.
600
601 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE
602 if new_block is a compressed leaf page in a secondary index.
603 This has to be done either within the same mini-transaction,
604 or by invoking ibuf_reset_free_bits() before mtr_commit().
605
606 @return pointer to the original successor of the infimum record on
607 new_page, or NULL on zip overflow (new_block will be decompressed) */
609 buf_block_t *new_block, /*!< in/out: index page to copy to */
610 buf_block_t *block, /*!< in: index page containing rec */
611 rec_t *rec, /*!< in: record on page */
612 dict_index_t *index, /*!< in: record descriptor */
613 mtr_t *mtr); /*!< in: mtr */
614/** Copies records from page to new_page, up to the given record, NOT
615 including that record. Infimum and supremum records are not copied.
616 The records are copied to the end of the record list on new_page.
617
618 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE
619 if new_block is a compressed leaf page in a secondary index.
620 This has to be done either within the same mini-transaction,
621 or by invoking ibuf_reset_free_bits() before mtr_commit().
622
623 @return pointer to the original predecessor of the supremum record on
624 new_page, or NULL on zip overflow (new_block will be decompressed) */
626 buf_block_t *new_block, /*!< in/out: index page to copy to */
627 buf_block_t *block, /*!< in: index page containing rec */
628 rec_t *rec, /*!< in: record on page */
629 dict_index_t *index, /*!< in: record descriptor */
630 mtr_t *mtr); /*!< in: mtr */
631/** Deletes records from a page from a given record onward, including that
632 record. The infimum and supremum records are not deleted. */
634 rec_t *rec, /*!< in: pointer to record on page */
635 buf_block_t *block, /*!< in: buffer block of the page */
636 dict_index_t *index, /*!< in: record descriptor */
637 ulint n_recs, /*!< in: number of records to delete,
638 or ULINT_UNDEFINED if not known */
639 ulint size, /*!< in: the sum of the sizes of the
640 records in the end of the chain to
641 delete, or ULINT_UNDEFINED if not known */
642 mtr_t *mtr); /*!< in: mtr */
643/** Deletes records from page, up to the given record, NOT including
644 that record. Infimum and supremum records are not deleted. */
646 rec_t *rec, /*!< in: record on page */
647 buf_block_t *block, /*!< in: buffer block of the page */
648 dict_index_t *index, /*!< in: record descriptor */
649 mtr_t *mtr); /*!< in: mtr */
650/** Moves record list end to another page. Moved records include
651 split_rec.
652
653 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE
654 if new_block is a compressed leaf page in a secondary index.
655 This has to be done either within the same mini-transaction,
656 or by invoking ibuf_reset_free_bits() before mtr_commit().
657
658 @return true on success; false on compression failure (new_block will
659 be decompressed) */
661 buf_block_t *new_block, /*!< in/out: index page where to move */
662 buf_block_t *block, /*!< in: index page from where to move */
663 rec_t *split_rec, /*!< in: first record to move */
664 dict_index_t *index, /*!< in: record descriptor */
665 mtr_t *mtr); /*!< in: mtr */
666/** Moves record list start to another page. Moved records do not include
667 split_rec.
668
669 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE
670 if new_block is a compressed leaf page in a secondary index.
671 This has to be done either within the same mini-transaction,
672 or by invoking ibuf_reset_free_bits() before mtr_commit().
673
674 @return true on success; false on compression failure */
676 buf_block_t *new_block, /*!< in/out: index page where to move */
677 buf_block_t *block, /*!< in/out: page containing split_rec */
678 rec_t *split_rec, /*!< in: first record not to move */
679 dict_index_t *index, /*!< in: record descriptor */
680 mtr_t *mtr); /*!< in: mtr */
681
682/** Splits a directory slot which owns too many records.
683@param[in,out] page Index page
684@param[in,out] page_zip Compressed page whose uncompressed part will be written,
685or null
686@param[in] slot_no The directory slot */
687void page_dir_split_slot(page_t *page, page_zip_des_t *page_zip, ulint slot_no);
688
689/** Tries to balance the given directory slot with too few records with the
690 upper neighbor, so that there are at least the minimum number of records
691owned by the slot; this may result in the merging of two slots.
692@param[in,out] page Index page
693@param[in,out] page_zip Compressed page, or null
694@param[in] slot_no The directory slot */
696 ulint slot_no);
697
698/** Parses a log record of a record list end or start deletion.
699 @return end of log record or NULL */
701 mlog_id_t type, /*!< in: MLOG_LIST_END_DELETE,
702 MLOG_LIST_START_DELETE,
703 MLOG_COMP_LIST_END_DELETE or
704 MLOG_COMP_LIST_START_DELETE */
705 const byte *ptr, /*!< in: buffer */
706 const byte *end_ptr, /*!< in: buffer end */
707 buf_block_t *block, /*!< in/out: buffer block or NULL */
708 dict_index_t *index, /*!< in: record descriptor */
709 mtr_t *mtr); /*!< in: mtr or NULL */
710
711/** Parses a redo log record of creating a page.
712@param[in,out] block buffer block, or NULL
713@param[in] comp nonzero=compact page format
714@param[in] page_type page type (FIL_PAGE_INDEX, FIL_PAGE_RTREE
715 or FIL_PAGE_SDI) */
716void page_parse_create(buf_block_t *block, ulint comp, page_type_t page_type);
717
718#ifndef UNIV_HOTBACKUP
719/** Prints record contents including the data relevant only in
720 the index page context.
721@param[in] rec Physical record
722@param[in] offsets Record descriptor */
723void page_rec_print(const rec_t *rec, const ulint *offsets);
724#ifdef UNIV_DEBUG
725/** This is used to print the contents of the directory for
726 debugging purposes. */
727void page_dir_print(page_t *page, /*!< in: index page */
728 ulint pr_n); /*!< in: print n first and n last entries */
729/** This is used to print the contents of the page record list for
730 debugging purposes. */
731void page_print_list(
732 buf_block_t *block, /*!< in: index page */
733 dict_index_t *index, /*!< in: dictionary index of the page */
734 ulint pr_n); /*!< in: print n first and n last entries */
735/** Prints the info in a page header. */
736void page_header_print(const page_t *page); /*!< in: index page */
737/** This is used to print the contents of the page for
738 debugging purposes. */
739void page_print(buf_block_t *block, /*!< in: index page */
740 dict_index_t *index, /*!< in: dictionary index of the page */
741 ulint dn, /*!< in: print dn first and last entries
742 in directory */
743 ulint rn); /*!< in: print rn first and last records
744 in directory */
745#endif /* UNIV_DEBUG */
746#endif /* !UNIV_HOTBACKUP */
747/** The following is used to validate a record on a page. This function
748 differs from rec_validate as it can also check the n_owned field and
749 the heap_no field.
750 @return true if ok */
752 const rec_t *rec, /*!< in: physical record */
753 const ulint *offsets); /*!< in: array returned by rec_get_offsets() */
754#ifdef UNIV_DEBUG
755/** Checks that the first directory slot points to the infimum record and
756 the last to the supremum. This function is intended to track if the
757 bug fixed in 4.0.14 has caused corruption to users' databases. */
758void page_check_dir(const page_t *page); /*!< in: index page */
759#endif /* UNIV_DEBUG */
760/** This function checks the consistency of an index page when we do not
761 know the index. This is also resilient so that this should never crash
762 even if the page is total garbage.
763 @return true if ok */
765 const page_t *page); /*!< in: index page in ROW_FORMAT=REDUNDANT */
766/** This function checks the consistency of an index page when we do not
767 know the index. This is also resilient so that this should never crash
768 even if the page is total garbage.
769 @return true if ok */
771 const page_t *page); /*!< in: index page in ROW_FORMAT!=REDUNDANT */
772
773/** This function checks the consistency of an index page.
774@param[in] page index page
775@param[in] index data dictionary index containing the page record type
776definition
777@param[in] check_min_rec check whether min rec flag (REC_INFO_MIN_REC_FLAG)
778is correctly set in the page. The default value is true.
779@return true if ok */
781 bool check_min_rec = true);
782
783/** Looks in the page record list for a record with the given heap number.
784 @return record, NULL if not found */
786 const page_t *page, /*!< in: index page */
787 ulint heap_no); /*!< in: heap number */
788/** Get the last non-delete-marked record on a page.
789@param[in] page index tree leaf page
790@return the last record, not delete-marked
791@retval infimum record if all records are delete-marked */
793
794/** Issue a warning when the checksum that is stored in the page is valid,
795but different than the global setting innodb_checksum_algorithm.
796@param[in] curr_algo current checksum algorithm
797@param[in] page_checksum page valid checksum
798@param[in] page_id page identifier */
800 srv_checksum_algorithm_t page_checksum,
801 const page_id_t &page_id);
802
803/** Check that a page_size is correct for InnoDB.
804If correct, set the associated page_size_shift which is the power of 2
805for this page size.
806@param[in] page_size Page Size to evaluate
807@return an associated page_size_shift if valid, 0 if invalid. */
808inline ulong page_size_validate(ulong page_size);
809
810/** This function checks if the page in which record is present is a
811non-leaf node of a spatial index.
812param[in] rec Btree record
813param[in] index index
814@return true if ok */
816
817page_t *page_create_low(buf_block_t *block, ulint comp, page_type_t page_type);
818
819#include "page0page.ic"
820
821#endif
uint32_t space_id_t
Tablespace identifier.
Definition: api0api.h:49
uint32_t page_no_t
Page number.
Definition: api0api.h:47
The database buffer pool high-level routines.
srv_checksum_algorithm_t
Alternatives for srv_checksum_algorithm, which can be changed by setting innodb_checksum_algorithm.
Definition: buf0types.h:115
Page identifier.
Definition: buf0types.h:207
C++23 std::expected.
Definition: ut0expected.h:69
int page
Definition: ctype-mb.cc:1226
SQL data field and tuple.
Data dictionary system.
The low-level file system.
uint16_t page_type_t
Definition: fil0fil.h:1244
constexpr uint32_t FIL_PAGE_DATA_END
size of the page trailer
Definition: fil0types.h:119
File space management.
uint32_t node_seq_t
Definition: gis0type.h:58
Mini-transaction buffer.
mlog_id_t
Definition: mtr0types.h:63
bool index(const std::string &value, const String &search_for, uint32_t *idx)
Definition: contains.h:76
size_t size(const char *const c)
Definition: base64.h:46
void page_delete_rec_list_end(rec_t *rec, buf_block_t *block, dict_index_t *index, ulint n_recs, ulint size, mtr_t *mtr)
Deletes records from a page from a given record onward, including that record.
Definition: page0page.cc:873
byte page_dir_slot_t
Definition: page0page.h:55
page_t * page_create_zip(buf_block_t *block, dict_index_t *index, ulint level, trx_id_t max_trx_id, mtr_t *mtr, page_type_t page_type)
Create a compressed B-tree index page.
Definition: page0page.cc:390
void page_set_max_trx_id(buf_block_t *block, page_zip_des_t *page_zip, trx_id_t trx_id, mtr_t *mtr)
Sets the max trx id field value.
Definition: page0page.cc:197
static const byte supremum_extra_data[]
Extra bytes and data bytes of a supremum record.
Definition: page0page.h:90
static ulint page_header_get_offs(const page_t *page, ulint field)
Returns the offset stored in the given header field.
constexpr uint32_t PAGE_DIR_SLOT_MAX_N_OWNED
Definition: page0page.h:73
static bool page_rec_is_comp(const rec_t *rec)
true if the record is on a page in compact format.
static void page_header_reset_last_insert(page_t *page, page_zip_des_t *page_zip, mtr_t *mtr)
Resets the last insert info field in the page header.
static rec_t * page_rec_get_prev(rec_t *rec)
Gets the pointer to the previous record.
static const rec_t * page_rec_get_prev_const(const rec_t *rec)
Gets the pointer to the previous record.
static void page_dir_slot_set_rec(page_dir_slot_t *slot, rec_t *rec)
This is used to set the record offset in a directory slot.
static rec_t * page_rec_get_nth(page_t *page, ulint nth)
Returns the nth record of the record list.
static bool page_rec_is_supremum(const rec_t *rec)
true if the record is the supremum record on a page.
static void page_dir_set_n_heap(page_t *page, page_zip_des_t *page_zip, ulint n_heap)
Sets the number of records in the heap.
void page_create_empty(buf_block_t *block, dict_index_t *index, mtr_t *mtr)
Empty a previously created B-tree index page.
Definition: page0page.cc:429
static rec_t * page_rec_get_next(rec_t *rec)
Gets the pointer to the next record on the page.
ulint page_dir_find_owner_slot(const rec_t *rec)
Looks for the directory slot which owns the given record.
Definition: page0page.cc:94
constexpr uint32_t PAGE_DIR_SLOT_SIZE
Definition: page0page.h:64
static void page_dir_set_n_slots(page_t *page, page_zip_des_t *page_zip, ulint n_slots)
Sets the number of dir slots in directory.
static bool page_rec_is_first(const rec_t *rec, const page_t *page)
true if the record is the first user record on a page.
static bool page_is_empty(const page_t *page)
Determine whether the page is empty.
ulint page_rec_get_n_recs_before(const rec_t *rec)
Returns the number of records before the given record in chain.
Definition: page0page.cc:1463
static ulint page_get_free_space_of_empty(bool comp)
Calculates free space if a page is emptied.
void page_check_dir(const page_t *page)
Checks that the first directory slot points to the infimum record and the last to the supremum.
Definition: page0page.cc:1740
page_t * page_create_low(buf_block_t *block, ulint comp, page_type_t page_type)
The index page creation function.
Definition: page0page.cc:309
static void page_update_max_trx_id(buf_block_t *block, page_zip_des_t *page_zip, trx_id_t trx_id, mtr_t *mtr)
Sets the max trx id field value if trx_id is bigger than the previous value.
bool page_validate(const page_t *page, dict_index_t *index, bool check_min_rec=true)
This function checks the consistency of an index page.
Definition: page0page.cc:2137
static bool page_rec_check(const rec_t *rec)
Used to check the consistency of a record on a page.
constexpr uint32_t PAGE_DIR_SLOT_MIN_N_OWNED
Definition: page0page.h:74
static uint16_t page_dir_get_n_heap(const page_t *page)
Gets the number of records in the heap.
void page_dir_balance_slot(page_t *page, page_zip_des_t *page_zip, ulint slot_no)
Tries to balance the given directory slot with too few records with the upper neighbor,...
Definition: page0page.cc:1354
page_dir_slot_t page_dir_t
Definition: page0page.h:56
static const byte infimum_extra[]
Extra bytes of an infimum record.
Definition: page0page.h:80
rec_t * page_copy_rec_list_end(buf_block_t *new_block, buf_block_t *block, rec_t *rec, dict_index_t *index, mtr_t *mtr)
Copies records from page to new_page, from the given record onward, including that record.
Definition: page0page.cc:532
bool page_move_rec_list_end(buf_block_t *new_block, buf_block_t *block, rec_t *split_rec, dict_index_t *index, mtr_t *mtr)
Moves record list end to another page.
Definition: page0page.cc:1151
bool page_is_spatial_non_leaf(const rec_t *rec, dict_index_t *index)
This function checks if the page in which record is present is a non-leaf node of a spatial index.
Definition: page0page.cc:2133
static uint16_t page_header_get_field(const page_t *page, ulint field)
Reads the given header field.
static void page_dir_slot_set_n_owned(page_dir_slot_t *slot, page_zip_des_t *page_zip, ulint n)
This is used to set the owned records field of a directory slot.
void page_parse_create(buf_block_t *block, ulint comp, page_type_t page_type)
Parses a redo log record of creating a page.
Definition: page0page.cc:362
static bool page_rec_is_supremum_low(ulint offset)
true if the record is the supremum record on a page.
static bool page_rec_is_user_rec_low(ulint offset)
true if the record is a user record on the page.
void page_header_print(const page_t *page)
Prints the info in a page header.
Definition: page0page.cc:1649
static bool page_rec_is_infimum_low(ulint offset)
true if the record is the infimum record on a page.
static ulint page_dir_calc_reserved_space(ulint n_recs)
Calculates the space reserved for directory slots of a given number of records.
void page_print(buf_block_t *block, dict_index_t *index, ulint dn, ulint rn)
This is used to print the contents of the page for debugging purposes.
Definition: page0page.cc:1671
bool page_rec_validate(const rec_t *rec, const ulint *offsets)
The following is used to validate a record on a page.
Definition: page0page.cc:1691
const byte * page_parse_delete_rec_list(mlog_id_t type, const byte *ptr, const byte *end_ptr, buf_block_t *block, dict_index_t *index, mtr_t *mtr)
Parses a log record of a record list end or start deletion.
Definition: page0page.cc:828
static rec_t * page_get_middle_rec(page_t *page)
Returns the middle record of the records on the page.
static void page_mem_alloc_free(page_t *page, page_zip_des_t *page_zip, rec_t *next_rec, ulint need)
Allocates a block of memory from the head of the free list of an index page.
static bool page_rec_is_second(const rec_t *rec, const page_t *page)
true if the record is the second user record on a page.
static ulint page_get_max_insert_size(const page_t *page, ulint n_recs)
Returns the maximum combined size of records which can be inserted on top of record heap.
static byte * page_header_get_ptr(page_t *page, uint32_t field)
Returns the pointer stored in the given header field, or NULL.
Definition: page0page.h:174
void page_warn_strict_checksum(srv_checksum_algorithm_t curr_algo, srv_checksum_algorithm_t page_checksum, const page_id_t &page_id)
Issue a warning when the checksum that is stored in the page is valid, but different than the global ...
Definition: page0page.cc:2654
static bool page_rec_is_infimum(const rec_t *rec)
true if the record is the infimum record on a page.
void page_copy_rec_list_end_no_locks(buf_block_t *new_block, buf_block_t *block, rec_t *rec, dict_index_t *index, mtr_t *mtr)
Differs from page_copy_rec_list_end, because this function does not touch the lock table and max trx ...
Definition: page0page.cc:466
static bool page_is_root(const page_t *page)
Determine whether a page is an index root page.
void page_dir_split_slot(page_t *page, page_zip_des_t *page_zip, ulint slot_no)
Splits a directory slot which owns too many records.
Definition: page0page.cc:1296
bool page_simple_validate_new(const page_t *page)
This function checks the consistency of an index page when we do not know the index.
Definition: page0page.cc:1950
static page_no_t page_get_page_no(const page_t *page)
Gets the page number.
static page_dir_slot_t * page_dir_get_nth_slot(const page_t *page, ulint n)
Gets pointer to nth directory slot.
static ulint page_dir_slot_get_n_owned(const page_dir_slot_t *slot)
Gets the number of records owned by a directory slot.
void page_delete_rec_list_start(rec_t *rec, buf_block_t *block, dict_index_t *index, mtr_t *mtr)
Deletes records from page, up to the given record, NOT including that record.
Definition: page0page.cc:1074
static page_id_t page_get_page_id(const page_t *page)
Gets the space id and page number identifying the page.
static const rec_t * page_dir_slot_get_rec(const page_dir_slot_t *slot)
Gets the record pointed to by a directory slot.
static ut::Expected< uint16_t, uint16_t > page_rec_try_get_next_offs(const rec_t *rec, bool comp)
Gets the offset of the next record on the page after validating that it is safe for page-level record...
static void page_rec_set_next(rec_t *rec, const rec_t *next)
Sets the pointer to the next record on the page.
static bool page_rec_is_last(const rec_t *rec, const page_t *page)
true if the record is the last user record on a page.
static bool page_rec_is_second_last(const rec_t *rec, const page_t *page)
true if the record is the second last user record on a page.
static ulint page_get_max_insert_size_after_reorganize(const page_t *page, ulint n_recs)
Returns the maximum combined size of records which can be inserted on top of record heap if page is f...
static ulint page_rec_get_heap_no(const rec_t *rec)
Returns the heap number of a record.
static trx_id_t page_get_max_trx_id(const page_t *page)
Returns the max trx id field value.
static ulint page_offset(const void *ptr)
Gets the offset within a page.
static void page_mem_free(page_t *page, page_zip_des_t *page_zip, rec_t *rec, const dict_index_t *index, const ulint *offsets)
Puts a record to free list.
static ulint page_get_n_recs(const page_t *page)
Gets the number of user records on page (the infimum and supremum records are not user records).
void page_rec_print(const rec_t *rec, const ulint *offsets)
Prints record contents including the data relevant only in the index page context.
Definition: page0page.cc:1522
void page_dir_print(page_t *page, ulint pr_n)
This is used to print the contents of the directory for debugging purposes.
Definition: page0page.cc:1542
static void page_header_set_ptr(page_t *page, page_zip_des_t *page_zip, ulint field, const byte *ptr)
Sets the pointer stored in the given header field.
const rec_t * page_find_rec_with_heap_no(const page_t *page, ulint heap_no)
Looks in the page record list for a record with the given heap number.
Definition: page0page.cc:2541
static ulint page_get_infimum_offset(const page_t *page)
Gets the offset of the first record on the page.
static ulint page_get_data_size(const page_t *page)
Returns the sum of the sizes of the records in the record list excluding the infimum and supremum rec...
bool page_move_rec_list_start(buf_block_t *new_block, buf_block_t *block, rec_t *split_rec, dict_index_t *index, mtr_t *mtr)
Moves record list start to another page.
Definition: page0page.cc:1204
static node_seq_t page_get_ssn_id(const page_t *page)
Returns the RTREE SPLIT SEQUENCE NUMBER (FIL_RTREE_SPLIT_SEQ_NUM).
static const rec_t * page_rec_get_next_low(const rec_t *rec, ulint comp)
Gets the pointer to the next record on the page.
static void page_header_set_field(page_t *page, page_zip_des_t *page_zip, ulint field, ulint val)
Sets the given header field.
rec_t * page_copy_rec_list_start(buf_block_t *new_block, buf_block_t *block, rec_t *rec, dict_index_t *index, mtr_t *mtr)
Copies records from page to new_page, up to the given record, NOT including that record.
Definition: page0page.cc:669
static ulint page_get_supremum_offset(const page_t *page)
Gets the offset of the last record on the page.
const rec_t * page_rec_get_nth_const(const page_t *page, ulint nth)
Returns the nth record of the record list.
Definition: page0page.cc:1416
static const rec_t * page_rec_get_next_non_del_marked(const rec_t *rec)
Gets the pointer to the next non delete-marked record on the page.
static ulint page_rec_get_base_extra_size(const rec_t *rec)
Returns the base extra size of a physical record.
static bool page_is_comp(const page_t *page)
Determine whether the page is in new-style compact format.
static const byte infimum_data[]
Data bytes of an infimum record.
Definition: page0page.h:86
static bool page_has_garbage(const page_t *page)
Determine whether the page contains garbage.
static space_id_t page_get_space_id(const page_t *page)
Gets the tablespace identifier.
const rec_t * page_find_rec_last_not_deleted(const page_t *page)
Get the last non-delete-marked record on a page.
Definition: page0page.cc:2624
static ulint page_dir_get_n_slots(const page_t *page)
Gets the number of dir slots in directory.
void page_print_list(buf_block_t *block, dict_index_t *index, ulint pr_n)
This is used to print the contents of the page record list for debugging purposes.
Definition: page0page.cc:1579
static bool page_rec_is_user_rec(const rec_t *rec)
true if the record is a user record on the page.
static bool page_rec_distance_is_at_most(const rec_t *left_rec, const rec_t *right_rec, ulint val)
true if distance between the records (measured in number of times we have to move to the next record)...
static byte * page_get_infimum_rec(byte *page)
Definition: page0page.h:218
constexpr uint32_t PAGE_DIR
Definition: page0page.h:61
bool page_simple_validate_old(const page_t *page)
This function checks the consistency of an index page when we do not know the index.
Definition: page0page.cc:1769
page_t * page_create(buf_block_t *block, mtr_t *mtr, ulint comp, page_type_t page_type)
Create an uncompressed B-tree or R-tree or SDI index page.
Definition: page0page.cc:374
constexpr uint32_t PAGE_EMPTY_DIR_START
Definition: page0page.h:68
static rec_t * page_rec_find_owner_rec(rec_t *rec)
Looks for the record which owns the given record.
ulong page_size_validate(ulong page_size)
Check that a page_size is correct for InnoDB.
Definition: page0page.ic:968
static page_t * page_align(const void *ptr)
Gets the start of a page.
static bool page_is_leaf(const page_t *page)
Determine whether the page is a B-tree leaf.
static void page_set_ssn_id(buf_block_t *block, page_zip_des_t *page_zip, node_seq_t ssn_id, mtr_t *mtr)
Sets the RTREE SPLIT SEQUENCE NUMBER field value.
static byte * page_get_supremum_rec(byte *page)
Definition: page0page.h:224
byte * page_mem_alloc_heap(page_t *page, page_zip_des_t *page_zip, ulint need, ulint *heap_no)
Allocates a block of memory from the heap of an index page.
Definition: page0page.cc:223
static const rec_t * page_rec_get_next_const(const rec_t *rec)
Gets the pointer to the next record on the page.
Index page routines.
Index page routines.
byte page_t
Type of the index page.
Definition: page0types.h:152
Record manager.
byte rec_t
Definition: rem0types.h:41
required string type
Definition: replication_group_member_actions.proto:34
The buffer control block structure.
Definition: buf0buf.h:1761
Data structure for an index.
Definition: dict0mem.h:1067
Mini-transaction handle and buffer.
Definition: mtr0mtr.h:177
Compressed page descriptor.
Definition: page0types.h:201
ib_id_t trx_id_t
Transaction identifier (DB_TRX_ID, DATA_TRX_ID)
Definition: trx0types.h:138
Version control for database, common definitions, and include files.
unsigned long int ulint
Definition: univ.i:406
int n
Definition: xcom_base.cc:509