summaryrefslogtreecommitdiff
path: root/innobase/include
diff options
context:
space:
mode:
authorunknown <marko@hundin.mysql.fi>2004-12-02 19:45:07 +0200
committerunknown <marko@hundin.mysql.fi>2004-12-02 19:45:07 +0200
commit0afb38a179687b95a38401a70e6da6abdb1eafc5 (patch)
treec3c716219a8f464ef096a6dd06835d4bfb627c8a /innobase/include
parentac398c4257b43b59e998ef473f44ad6f8746f717 (diff)
downloadmariadb-git-0afb38a179687b95a38401a70e6da6abdb1eafc5.tar.gz
Many files:
Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/btr/btr0btr.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/btr/btr0cur.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/btr/btr0pcur.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/btr/btr0sea.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/data/data0data.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/data/data0type.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/dict/dict0boot.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/dict/dict0crea.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/dict/dict0dict.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/dict/dict0load.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/dict/dict0mem.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/fil/fil0fil.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/fsp/fsp0fsp.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/ibuf/ibuf0ibuf.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/btr0btr.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/btr0btr.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/btr0cur.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/btr0cur.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/btr0pcur.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/btr0sea.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/data0type.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/dict0dict.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/dict0dict.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/dict0mem.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/lock0lock.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/lock0lock.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/mtr0log.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/mtr0mtr.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/page0cur.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/page0cur.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/page0page.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/page0page.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/rem0cmp.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/rem0cmp.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/rem0rec.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/rem0rec.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/row0row.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/row0row.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/row0upd.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/row0upd.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/row0vers.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/row0vers.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/srv0srv.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/trx0rec.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/ut0byte.h: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/include/ut0byte.ic: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/lock/lock0lock.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/log/log0recv.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/mtr/mtr0log.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/page/page0cur.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/page/page0page.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/pars/pars0pars.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/rem/rem0cmp.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/rem/rem0rec.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/row/row0ins.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/row/row0mysql.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/row/row0purge.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/row/row0row.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/row/row0sel.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/row/row0umod.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/row/row0undo.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/row/row0upd.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/row/row0vers.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/srv/srv0srv.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/trx/trx0rec.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. innobase/trx/trx0undo.c: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC. sql/ha_innodb.cc: Implement more compact InnoDB record format. Old format is available as CREATE TABLE ... ROW_FORMAT=DYNAMIC.
Diffstat (limited to 'innobase/include')
-rw-r--r--innobase/include/btr0btr.h22
-rw-r--r--innobase/include/btr0btr.ic9
-rw-r--r--innobase/include/btr0cur.h60
-rw-r--r--innobase/include/btr0cur.ic4
-rw-r--r--innobase/include/btr0pcur.h1
-rw-r--r--innobase/include/btr0sea.h13
-rw-r--r--innobase/include/data0type.ic54
-rw-r--r--innobase/include/dict0dict.h13
-rw-r--r--innobase/include/dict0dict.ic13
-rw-r--r--innobase/include/dict0mem.h12
-rw-r--r--innobase/include/lock0lock.h14
-rw-r--r--innobase/include/lock0lock.ic5
-rw-r--r--innobase/include/mtr0log.h33
-rw-r--r--innobase/include/mtr0mtr.h26
-rw-r--r--innobase/include/page0cur.h57
-rw-r--r--innobase/include/page0cur.ic19
-rw-r--r--innobase/include/page0page.h211
-rw-r--r--innobase/include/page0page.ic133
-rw-r--r--innobase/include/rem0cmp.h32
-rw-r--r--innobase/include/rem0cmp.ic6
-rw-r--r--innobase/include/rem0rec.h435
-rw-r--r--innobase/include/rem0rec.ic898
-rw-r--r--innobase/include/row0row.h30
-rw-r--r--innobase/include/row0row.ic49
-rw-r--r--innobase/include/row0upd.h17
-rw-r--r--innobase/include/row0upd.ic6
-rw-r--r--innobase/include/row0vers.h3
-rw-r--r--innobase/include/row0vers.ic70
-rw-r--r--innobase/include/srv0srv.h4
-rw-r--r--innobase/include/trx0rec.h1
-rw-r--r--innobase/include/ut0byte.h15
-rw-r--r--innobase/include/ut0byte.ic21
32 files changed, 1546 insertions, 740 deletions
diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h
index 8606fcd2a5c..0b19e64d4e0 100644
--- a/innobase/include/btr0btr.h
+++ b/innobase/include/btr0btr.h
@@ -155,7 +155,8 @@ ulint
btr_node_ptr_get_child_page_no(
/*===========================*/
/* out: child node address */
- rec_t* rec); /* in: node pointer record */
+ rec_t* rec, /* in: node pointer record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/****************************************************************
Creates the root node for a new index tree. */
@@ -167,6 +168,7 @@ btr_create(
ulint type, /* in: type of the index */
ulint space, /* in: space where created */
dulint index_id,/* in: index id */
+ ibool comp, /* in: TRUE=compact page format */
mtr_t* mtr); /* in: mini-transaction handle */
/****************************************************************
Frees a B-tree except the root page, which MUST be freed after this
@@ -210,8 +212,9 @@ Reorganizes an index page. */
void
btr_page_reorganize(
/*================*/
- page_t* page, /* in: page to be reorganized */
- mtr_t* mtr); /* in: mtr */
+ page_t* page, /* in: page to be reorganized */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Decides if the page should be split at the convergence point of
inserts converging to left. */
@@ -273,6 +276,7 @@ void
btr_set_min_rec_mark(
/*=================*/
rec_t* rec, /* in: record */
+ ibool comp, /* in: TRUE=compact page format */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes on the upper level the node pointer to a page. */
@@ -332,6 +336,7 @@ btr_parse_set_min_rec_mark(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
+ ibool comp, /* in: TRUE=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
@@ -340,11 +345,12 @@ Parses a redo log record of reorganizing a page. */
byte*
btr_parse_page_reorganize(
/*======================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/******************************************************************
Gets the number of pages in a B-tree. */
diff --git a/innobase/include/btr0btr.ic b/innobase/include/btr0btr.ic
index b0aa0756307..1d1f97d3668 100644
--- a/innobase/include/btr0btr.ic
+++ b/innobase/include/btr0btr.ic
@@ -183,17 +183,18 @@ ulint
btr_node_ptr_get_child_page_no(
/*===========================*/
/* out: child node address */
- rec_t* rec) /* in: node pointer record */
+ rec_t* rec, /* in: node pointer record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint n_fields;
byte* field;
ulint len;
ulint page_no;
- n_fields = rec_get_n_fields(rec);
+ ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
/* The child address is in the last field */
- field = rec_get_nth_field(rec, n_fields - 1, &len);
+ field = rec_get_nth_field(rec, offsets,
+ rec_offs_n_fields(offsets) - 1, &len);
ut_ad(len == 4);
diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h
index f1334656d53..0a8d8ceaeb7 100644
--- a/innobase/include/btr0cur.h
+++ b/innobase/include/btr0cur.h
@@ -34,7 +34,7 @@ page_cur_t*
btr_cur_get_page_cur(
/*=================*/
/* out: pointer to page cursor component */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the record pointer of a tree cursor. */
UNIV_INLINE
@@ -42,14 +42,14 @@ rec_t*
btr_cur_get_rec(
/*============*/
/* out: pointer to record */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Invalidates a tree cursor by setting record pointer to NULL. */
UNIV_INLINE
void
btr_cur_invalidate(
/*===============*/
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the page of a tree cursor. */
UNIV_INLINE
@@ -57,7 +57,7 @@ page_t*
btr_cur_get_page(
/*=============*/
/* out: pointer to page */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the tree of a cursor. */
UNIV_INLINE
@@ -65,7 +65,7 @@ dict_tree_t*
btr_cur_get_tree(
/*=============*/
/* out: tree */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Positions a tree cursor at a given record. */
UNIV_INLINE
@@ -283,8 +283,9 @@ only used by the insert buffer insert merge mechanism. */
void
btr_cur_del_unmark_for_ibuf(
/*========================*/
- rec_t* rec, /* in: record to delete unmark */
- mtr_t* mtr); /* in: mtr */
+ rec_t* rec, /* in: record to delete unmark */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Tries to compress a page of the tree on the leaf level. It is assumed
that mtr holds an x-latch on the tree and on the cursor page. To avoid
@@ -361,10 +362,11 @@ Parses a redo log record of updating a record in-place. */
byte*
btr_cur_parse_update_in_place(
/*==========================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page); /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ page_t* page, /* in: page or NULL */
+ dict_index_t* index); /* in: index corresponding to page */
/********************************************************************
Parses the redo log record for delete marking or unmarking of a clustered
index record. */
@@ -372,10 +374,11 @@ index record. */
byte*
btr_cur_parse_del_mark_set_clust_rec(
/*=================================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page); /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: index corresponding to page */
+ page_t* page); /* in: page or NULL */
/********************************************************************
Parses the redo log record for delete marking or unmarking of a secondary
index record. */
@@ -383,10 +386,11 @@ index record. */
byte*
btr_cur_parse_del_mark_set_sec_rec(
/*===============================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page); /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: index corresponding to page */
+ page_t* page); /* in: page or NULL */
/***********************************************************************
Estimates the number of rows in a given index range. */
@@ -417,9 +421,10 @@ to free the field. */
void
btr_cur_mark_extern_inherited_fields(
/*=================================*/
- rec_t* rec, /* in: record in a clustered index */
- upd_t* update, /* in: update vector */
- mtr_t* mtr); /* in: mtr */
+ rec_t* rec, /* in: record in a clustered index */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update, /* in: update vector */
+ mtr_t* mtr); /* in: mtr */
/***********************************************************************
The complement of the previous function: in an update entry may inherit
some externally stored fields from a record. We must mark them as inherited
@@ -456,6 +461,7 @@ btr_store_big_rec_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree
MUST be X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */
mtr_t* local_mtr); /* in: mtr containing the latch to
@@ -496,6 +502,7 @@ btr_rec_free_externally_stored_fields(
dict_index_t* index, /* in: index of the data, the index
tree MUST be X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
inherited fields */
@@ -510,6 +517,7 @@ btr_rec_copy_externally_stored_field(
/*=================================*/
/* out: the field copied to heap */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint no, /* in: field number */
ulint* len, /* out: length of the field */
mem_heap_t* heap); /* in: mem heap */
@@ -540,10 +548,10 @@ ulint
btr_push_update_extern_fields(
/*==========================*/
/* out: number of values stored in ext_vect */
- ulint* ext_vect, /* in: array of ulints, must be preallocated
- to have place for all fields in rec */
- rec_t* rec, /* in: record */
- upd_t* update); /* in: update vector */
+ ulint* ext_vect,/* in: array of ulints, must be preallocated
+ to have space for all fields in rec */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update);/* in: update vector or NULL */
/*######################################################################*/
diff --git a/innobase/include/btr0cur.ic b/innobase/include/btr0cur.ic
index a3a04b60c45..dcad3e9e14d 100644
--- a/innobase/include/btr0cur.ic
+++ b/innobase/include/btr0cur.ic
@@ -134,17 +134,15 @@ btr_cur_can_delete_without_compress(
/* out: TRUE if can be deleted without
recommended compression */
btr_cur_t* cursor, /* in: btr cursor */
+ ulint rec_size,/* in: rec_get_size(btr_cur_get_rec(cursor))*/
mtr_t* mtr) /* in: mtr */
{
- ulint rec_size;
page_t* page;
ut_ad(mtr_memo_contains(mtr, buf_block_align(
btr_cur_get_page(cursor)),
MTR_MEMO_PAGE_X_FIX));
- rec_size = rec_get_size(btr_cur_get_rec(cursor));
-
page = btr_cur_get_page(cursor);
if ((page_get_data_size(page) - rec_size < BTR_CUR_PAGE_COMPRESS_LIMIT)
diff --git a/innobase/include/btr0pcur.h b/innobase/include/btr0pcur.h
index 81f19af4d40..6384222be51 100644
--- a/innobase/include/btr0pcur.h
+++ b/innobase/include/btr0pcur.h
@@ -462,6 +462,7 @@ struct btr_pcur_struct{
contains an initial segment of the
latest record cursor was positioned
either on, before, or after */
+ ulint old_n_fields; /* number of fields in old_rec */
ulint rel_pos; /* BTR_PCUR_ON, BTR_PCUR_BEFORE, or
BTR_PCUR_AFTER, depending on whether
cursor was on, before, or after the
diff --git a/innobase/include/btr0sea.h b/innobase/include/btr0sea.h
index ce4140ecf92..73cd95d1464 100644
--- a/innobase/include/btr0sea.h
+++ b/innobase/include/btr0sea.h
@@ -77,8 +77,10 @@ parameters as page (this often happens when a page is split). */
void
btr_search_move_or_delete_hash_entries(
/*===================================*/
- page_t* new_page, /* in: records are copied to this page */
- page_t* page); /* in: index page */
+ page_t* new_page, /* in: records are copied
+ to this page */
+ page_t* page, /* in: index page */
+ dict_index_t* index); /* in: record descriptor */
/************************************************************************
Drops a page hash index. */
@@ -128,9 +130,10 @@ btr_search_update_hash_on_delete(
Validates the search system. */
ibool
-btr_search_validate(void);
-/*=====================*/
-
+btr_search_validate(
+/*================*/
+ /* out: TRUE if ok */
+ dict_index_t* index); /* in: record descriptor */
/* Search info directions */
#define BTR_SEA_NO_DIRECTION 1
diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic
index 946b646ffbf..5d6fcf581e5 100644
--- a/innobase/include/data0type.ic
+++ b/innobase/include/data0type.ic
@@ -149,8 +149,10 @@ dtype_new_store_for_order_and_null_size(
bytes where we store the info */
dtype_t* type) /* in: type struct */
{
- ut_ad(6 == DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
-
+#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
+#endif
+
buf[0] = (byte)(type->mtype & 0xFFUL);
if (type->prtype & DATA_BINARY_TYPE) {
@@ -166,10 +168,12 @@ dtype_new_store_for_order_and_null_size(
mach_write_to_2(buf + 2, type->len & 0xFFFFUL);
+ ut_ad(dtype_get_charset_coll(type->prtype) < 256);
mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype));
- /* Note that the second last byte is left unused, because the
- charset-collation code is always < 256 */
+ if (type->prtype & DATA_NOT_NULL) {
+ buf[4] |= 128;
+ }
}
/**************************************************************************
@@ -211,20 +215,26 @@ dtype_new_read_for_order_and_null_size(
{
ulint charset_coll;
- ut_ad(6 == DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
+#endif
type->mtype = buf[0] & 63;
type->prtype = buf[1];
if (buf[0] & 128) {
- type->prtype = type->prtype | DATA_BINARY_TYPE;
+ type->prtype |= DATA_BINARY_TYPE;
+ }
+
+ if (buf[4] & 128) {
+ type->prtype |= DATA_NOT_NULL;
}
type->len = mach_read_from_2(buf + 2);
mach_read_from_2(buf + 4);
- charset_coll = mach_read_from_2(buf + 4);
+ charset_coll = mach_read_from_2(buf + 4) & 0x7fff;
if (dtype_is_string_type(type->mtype)) {
ut_a(charset_coll < 256);
@@ -257,6 +267,26 @@ dtype_get_fixed_size(
mtype = dtype_get_mtype(type);
switch (mtype) {
+ case DATA_SYS:
+#ifdef UNIV_DEBUG
+ switch (type->prtype & DATA_MYSQL_TYPE_MASK) {
+ default:
+ ut_ad(0);
+ return(0);
+ case DATA_ROW_ID:
+ ut_ad(type->len == DATA_ROW_ID_LEN);
+ break;
+ case DATA_TRX_ID:
+ ut_ad(type->len == DATA_TRX_ID_LEN);
+ break;
+ case DATA_ROLL_PTR:
+ ut_ad(type->len == DATA_ROLL_PTR_LEN);
+ break;
+ case DATA_MIX_ID:
+ ut_ad(type->len == DATA_MIX_ID_LEN);
+ break;
+ }
+#endif /* UNIV_DEBUG */
case DATA_CHAR:
case DATA_FIXBINARY:
case DATA_INT:
@@ -264,16 +294,6 @@ dtype_get_fixed_size(
case DATA_DOUBLE:
case DATA_MYSQL:
return(dtype_get_len(type));
-
- case DATA_SYS: if (type->prtype == DATA_ROW_ID) {
- return(DATA_ROW_ID_LEN);
- } else if (type->prtype == DATA_TRX_ID) {
- return(DATA_TRX_ID_LEN);
- } else if (type->prtype == DATA_ROLL_PTR) {
- return(DATA_ROLL_PTR_LEN);
- } else {
- return(0);
- }
case DATA_VARCHAR:
case DATA_BINARY:
case DATA_DECIMAL:
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index ca632691450..a2399a81ca9 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -639,6 +639,16 @@ dict_index_get_sys_col_pos(
dict_index_t* index, /* in: index */
ulint type); /* in: DATA_ROW_ID, ... */
/***********************************************************************
+Adds a column to index. */
+
+void
+dict_index_add_col(
+/*===============*/
+ dict_index_t* index, /* in: index */
+ dict_col_t* col, /* in: column */
+ ulint order, /* in: order criterion */
+ ulint prefix_len); /* in: column prefix length */
+/***********************************************************************
Copies types of fields contained in index to tuple. */
void
@@ -657,6 +667,7 @@ dict_index_rec_get_sys_col(
/*=======================*/
/* out: system column value */
dict_index_t* index, /* in: clustered index describing the record */
+ const ulint* offsets,/* in: offsets returned by rec_get_offsets() */
ulint type, /* in: column type: DATA_ROLL_PTR, ... */
rec_t* rec); /* in: record */
/*************************************************************************
@@ -770,6 +781,7 @@ dict_tree_copy_rec_order_prefix(
/* out: pointer to the prefix record */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to copy prefix */
+ ulint* n_fields,/* out: number of fields copied */
byte** buf, /* in/out: memory buffer for the copied prefix,
or NULL */
ulint* buf_size);/* in/out: buffer size */
@@ -782,6 +794,7 @@ dict_tree_build_data_tuple(
/* out, own: data tuple */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to build data tuple */
+ ulint n_fields,/* in: number of data fields */
mem_heap_t* heap); /* in: memory heap where tuple created */
/*************************************************************************
Gets the space id of the root of the index tree. */
diff --git a/innobase/include/dict0dict.ic b/innobase/include/dict0dict.ic
index 85e4aaf1a05..7f754e316b3 100644
--- a/innobase/include/dict0dict.ic
+++ b/innobase/include/dict0dict.ic
@@ -168,7 +168,7 @@ dict_table_get_sys_col(
col = dict_table_get_nth_col(table, table->n_cols
- DATA_N_SYS_COLS + sys);
ut_ad(col->type.mtype == DATA_SYS);
- ut_ad(col->type.prtype == sys);
+ ut_ad(col->type.prtype == (sys | DATA_NOT_NULL));
return(col);
}
@@ -322,6 +322,7 @@ dict_index_rec_get_sys_col(
/*=======================*/
/* out: system column value */
dict_index_t* index, /* in: clustered index describing the record */
+ const ulint* offsets,/* in: offsets returned by rec_get_offsets() */
ulint type, /* in: column type: DATA_ROLL_PTR, ... */
rec_t* rec) /* in: record */
{
@@ -331,12 +332,13 @@ dict_index_rec_get_sys_col(
ut_ad(index);
ut_ad(index->type & DICT_CLUSTERED);
-
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
pos = dict_index_get_sys_col_pos(index, type);
ut_ad(pos != ULINT_UNDEFINED);
- field = rec_get_nth_field(rec, pos, &len);
+ field = rec_get_nth_field(rec, offsets, pos, &len);
if (type == DATA_ROLL_PTR) {
ut_ad(len == 7);
@@ -677,7 +679,10 @@ dict_is_mixed_table_rec(
byte* mix_id_field;
ulint len;
- mix_id_field = rec_get_nth_field(rec, table->mix_len, &len);
+ ut_ad(!table->comp);
+
+ mix_id_field = rec_get_nth_field_old(rec,
+ table->mix_len, &len);
if ((len != table->mix_id_len)
|| (0 != ut_memcmp(table->mix_id_buf, mix_id_field, len))) {
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index 1e496a25477..670b3445a55 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -54,7 +54,8 @@ dict_mem_table_create(
of the table is placed; this parameter
is ignored if the table is made
a member of a cluster */
- ulint n_cols); /* in: number of columns */
+ ulint n_cols, /* in: number of columns */
+ ibool comp); /* in: TRUE=compact page format */
/**************************************************************************
Creates a cluster memory object. */
@@ -171,6 +172,13 @@ struct dict_field_struct{
DICT_MAX_COL_PREFIX_LEN; NOTE that
in the UTF-8 charset, MySQL sets this
to 3 * the prefix len in UTF-8 chars */
+ ulint fixed_len; /* 0 or the fixed length of the
+ column if smaller than
+ DICT_MAX_COL_PREFIX_LEN */
+ ulint fixed_offs; /* offset to the field, or
+ ULINT_UNDEFINED if it is not fixed
+ within the record (due to preceding
+ variable-length fields) */
};
/* Data structure for an index tree */
@@ -225,6 +233,7 @@ struct dict_index_struct{
ulint n_def; /* number of fields defined so far */
ulint n_fields;/* number of fields in the index */
dict_field_t* fields; /* array of field descriptions */
+ ulint n_nullable;/* number of nullable fields */
UT_LIST_NODE_T(dict_index_t)
indexes;/* list of indexes of the table */
dict_tree_t* tree; /* index tree struct */
@@ -320,6 +329,7 @@ struct dict_table_struct{
ibool tablespace_discarded;/* this flag is set TRUE when the
user calls DISCARD TABLESPACE on this table,
and reset to FALSE in IMPORT TABLESPACE */
+ ibool comp; /* flag: TRUE=compact page format */
hash_node_t name_hash; /* hash chain node */
hash_node_t id_hash; /* hash chain node */
ulint n_def; /* number of columns defined so far */
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index db8dd24973d..d642fe46fef 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -47,7 +47,8 @@ lock_sec_rec_some_has_impl_off_kernel(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index); /* in: secondary index */
+ dict_index_t* index, /* in: secondary index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Checks if some transaction has an implicit x-lock on a record in a clustered
index. */
@@ -58,7 +59,8 @@ lock_clust_rec_some_has_impl(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*****************************************************************
Resets the lock bits for a single record. Releases transactions
waiting for lock requests here. */
@@ -275,6 +277,7 @@ lock_clust_rec_modify_check_and_lock(
does nothing */
rec_t* rec, /* in: record which should be modified */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr); /* in: query thread */
/*************************************************************************
Checks if locks of other transactions prevent an immediate modify
@@ -308,6 +311,7 @@ lock_sec_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: secondary index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@@ -333,6 +337,7 @@ lock_clust_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@@ -350,6 +355,7 @@ lock_clust_rec_cons_read_sees(
rec_t* rec, /* in: user record which should be read or
passed over by a read cursor */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
read_view_t* view); /* in: consistent read view */
/*************************************************************************
Checks that a non-clustered index record is seen in a consistent read. */
@@ -499,6 +505,7 @@ lock_check_trx_id_sanity(
dulint trx_id, /* in: trx id */
rec_t* rec, /* in: user record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
ibool has_kernel_mutex);/* in: TRUE if the caller owns the
kernel mutex */
/*************************************************************************
@@ -509,7 +516,8 @@ lock_rec_queue_validate(
/*====================*/
/* out: TRUE if ok */
rec_t* rec, /* in: record to look at */
- dict_index_t* index); /* in: index, or NULL if not known */
+ dict_index_t* index, /* in: index, or NULL if not known */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Prints info of a table lock. */
diff --git a/innobase/include/lock0lock.ic b/innobase/include/lock0lock.ic
index fabc9256401..c7a71bb45d8 100644
--- a/innobase/include/lock0lock.ic
+++ b/innobase/include/lock0lock.ic
@@ -60,7 +60,8 @@ lock_clust_rec_some_has_impl(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
dulint trx_id;
@@ -70,7 +71,7 @@ lock_clust_rec_some_has_impl(
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(page_rec_is_user_rec(rec));
- trx_id = row_get_rec_trx_id(rec, index);
+ trx_id = row_get_rec_trx_id(rec, index, offsets);
if (trx_is_active(trx_id)) {
/* The modifying or inserting transaction is active */
diff --git a/innobase/include/mtr0log.h b/innobase/include/mtr0log.h
index 9c9c6f696e8..c0636ea1e1e 100644
--- a/innobase/include/mtr0log.h
+++ b/innobase/include/mtr0log.h
@@ -11,6 +11,7 @@ Created 12/7/1995 Heikki Tuuri
#include "univ.i"
#include "mtr0mtr.h"
+#include "dict0types.h"
/************************************************************
Writes 1 - 4 bytes to a file page buffered in the buffer pool.
@@ -173,6 +174,38 @@ mlog_parse_string(
byte* page); /* in: page where to apply the log record, or NULL */
+/************************************************************
+Opens a buffer for mlog, writes the initial log record and,
+if needed, the field lengths of an index. Reserves space
+for further log entries. The log entry must be closed with
+mtr_close(). */
+
+byte*
+mlog_open_and_write_index(
+/*======================*/
+ /* out: buffer, NULL if log mode
+ MTR_LOG_NONE */
+ mtr_t* mtr, /* in: mtr */
+ byte* rec, /* in: index record or page */
+ dict_index_t* index, /* in: record descriptor */
+ byte type, /* in: log item type */
+ ulint size); /* in: requested buffer size in bytes
+ (if 0, calls mlog_close() and returns NULL) */
+
+/************************************************************
+Parses a log record written by mlog_open_and_write_index. */
+
+byte*
+mlog_parse_index(
+/*=============*/
+ /* out: parsed record end,
+ NULL if not a complete record */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ /* out: new value of log_ptr */
+ ibool comp, /* in: TRUE=compact record format */
+ dict_index_t** index); /* out, own: dummy index */
+
/* Insert, update, and maybe other functions may use this value to define an
extra mlog buffer size for variable size data */
#define MLOG_BUF_MARGIN 256
diff --git a/innobase/include/mtr0mtr.h b/innobase/include/mtr0mtr.h
index e8c68a91dad..071279d5259 100644
--- a/innobase/include/mtr0mtr.h
+++ b/innobase/include/mtr0mtr.h
@@ -102,7 +102,31 @@ flag value must give the length also! */
file rename */
#define MLOG_FILE_DELETE ((byte)35) /* log record about an .ibd
file deletion */
-#define MLOG_BIGGEST_TYPE ((byte)35) /* biggest value (used in
+#define MLOG_COMP_REC_MIN_MARK ((byte)36) /* mark a compact index record
+ as the predefined minimum
+ record */
+#define MLOG_COMP_PAGE_CREATE ((byte)37) /* create a compact
+ index page */
+#define MLOG_COMP_REC_INSERT ((byte)38) /* compact record insert */
+#define MLOG_COMP_REC_CLUST_DELETE_MARK ((byte)39)
+ /* mark compact clustered index
+ record deleted */
+#define MLOG_COMP_REC_SEC_DELETE_MARK ((byte)40)/* mark compact secondary index
+ record deleted */
+#define MLOG_COMP_REC_UPDATE_IN_PLACE ((byte)41)/* update of a compact record,
+ preserves record field sizes */
+#define MLOG_COMP_REC_DELETE ((byte)42) /* delete a compact record
+ from a page */
+#define MLOG_COMP_LIST_END_DELETE ((byte)43) /* delete compact record list
+ end on index page */
+#define MLOG_COMP_LIST_START_DELETE ((byte)44) /* delete compact record list
+ start on index page */
+#define MLOG_COMP_LIST_END_COPY_CREATED ((byte)45)
+ /* copy compact record list end
+ to a new created index page */
+#define MLOG_COMP_PAGE_REORGANIZE ((byte)46) /* reorganize an index page */
+
+#define MLOG_BIGGEST_TYPE ((byte)46) /* biggest value (used in
asserts) */
/*******************************************************************
diff --git a/innobase/include/page0cur.h b/innobase/include/page0cur.h
index c85669ed4df..a693931968e 100644
--- a/innobase/include/page0cur.h
+++ b/innobase/include/page0cur.h
@@ -128,7 +128,8 @@ page_cur_tuple_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple */
+ dtuple_t* tuple, /* in: pointer to a data tuple */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
/***************************************************************
Inserts a record next to page cursor. Returns pointer to inserted record if
@@ -142,6 +143,7 @@ page_cur_rec_insert(
otherwise */
page_cur_t* cursor, /* in: a page cursor */
rec_t* rec, /* in: record to insert */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
/***************************************************************
Inserts a record next to page cursor. Returns pointer to inserted record if
@@ -155,9 +157,9 @@ page_cur_insert_rec_low(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
- ulint data_size,/* in: data size of tuple */
- rec_t* rec, /* in: pointer to a physical record or NULL */
+ dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
+ dict_index_t* index, /* in: record descriptor */
+ rec_t* rec, /* in: pointer to a physical record or NULL */
mtr_t* mtr); /* in: mini-transaction handle */
/*****************************************************************
Copies records from page to a newly created page, from a given record onward,
@@ -166,10 +168,11 @@ including that record. Infimum and supremum records are not copied. */
void
page_copy_rec_list_end_to_created_page(
/*===================================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: first record to copy */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: first record to copy */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/***************************************************************
Deletes a record at the page cursor. The cursor is moved to the
next record after the deleted one. */
@@ -178,6 +181,7 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /* in: a page cursor */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
/********************************************************************
Searches the right position for a page cursor. */
@@ -187,6 +191,7 @@ page_cur_search(
/*============*/
/* out: number of matched fields on the left */
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -198,6 +203,7 @@ void
page_cur_search_with_match(
/*=======================*/
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -229,34 +235,37 @@ Parses a log record of a record insert on a page. */
byte*
page_cur_parse_insert_rec(
/*======================*/
- /* out: end of log record or NULL */
- ibool is_short,/* in: TRUE if short inserts */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ ibool is_short,/* in: TRUE if short inserts */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/**************************************************************
Parses a log record of copying a record list end to a new created page. */
byte*
page_parse_copy_rec_list_to_created_page(
/*=====================================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
Parses log record of a record delete on a page. */
byte*
page_cur_parse_delete_rec(
/*======================*/
- /* out: pointer to record end or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: pointer to record end or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/* Index page cursor */
diff --git a/innobase/include/page0cur.ic b/innobase/include/page0cur.ic
index 39f8ab11513..03010fbd766 100644
--- a/innobase/include/page0cur.ic
+++ b/innobase/include/page0cur.ic
@@ -143,7 +143,7 @@ UNIV_INLINE
void
page_cur_move_to_prev(
/*==================*/
- page_cur_t* cur) /* in: cursor; must not before first */
+ page_cur_t* cur) /* in: page cursor, not before first */
{
ut_ad(!page_cur_is_before_first(cur));
@@ -158,6 +158,7 @@ page_cur_search(
/*============*/
/* out: number of matched fields on the left */
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -170,7 +171,7 @@ page_cur_search(
ut_ad(dtuple_check_typed(tuple));
- page_cur_search_with_match(page, tuple, mode,
+ page_cur_search_with_match(page, index, tuple, mode,
&up_matched_fields,
&up_matched_bytes,
&low_matched_fields,
@@ -190,16 +191,11 @@ page_cur_tuple_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple */
+ dtuple_t* tuple, /* in: pointer to a data tuple */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
- ulint data_size;
-
- ut_ad(dtuple_check_typed(tuple));
-
- data_size = dtuple_get_data_size(tuple);
-
- return(page_cur_insert_rec_low(cursor, tuple, data_size, NULL, mtr));
+ return(page_cur_insert_rec_low(cursor, tuple, index, NULL, mtr));
}
/***************************************************************
@@ -214,8 +210,9 @@ page_cur_rec_insert(
otherwise */
page_cur_t* cursor, /* in: a page cursor */
rec_t* rec, /* in: record to insert */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
- return(page_cur_insert_rec_low(cursor, NULL, 0, rec, mtr));
+ return(page_cur_insert_rec_low(cursor, NULL, index, rec, mtr));
}
diff --git a/innobase/include/page0page.h b/innobase/include/page0page.h
index 969313614e3..d3ef8214eb6 100644
--- a/innobase/include/page0page.h
+++ b/innobase/include/page0page.h
@@ -37,7 +37,8 @@ typedef byte page_header_t;
/*-----------------------------*/
#define PAGE_N_DIR_SLOTS 0 /* number of slots in page directory */
#define PAGE_HEAP_TOP 2 /* pointer to record heap top */
-#define PAGE_N_HEAP 4 /* number of records in the heap */
+#define PAGE_N_HEAP 4 /* number of records in the heap,
+ bit 15=flag: new-style compact page format */
#define PAGE_FREE 6 /* pointer to start of page free record list */
#define PAGE_GARBAGE 8 /* number of bytes in deleted records */
#define PAGE_LAST_INSERT 10 /* pointer to the last inserted record, or
@@ -79,15 +80,24 @@ typedef byte page_header_t;
#define PAGE_DATA (PAGE_HEADER + 36 + 2 * FSEG_HEADER_SIZE)
/* start of data on the page */
-#define PAGE_INFIMUM (PAGE_DATA + 1 + REC_N_EXTRA_BYTES)
- /* offset of the page infimum record on the
- page */
-#define PAGE_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_EXTRA_BYTES + 8)
- /* offset of the page supremum record on the
- page */
-#define PAGE_SUPREMUM_END (PAGE_SUPREMUM + 9)
+#define PAGE_OLD_INFIMUM (PAGE_DATA + 1 + REC_N_OLD_EXTRA_BYTES)
+ /* offset of the page infimum record on an
+ old-style page */
+#define PAGE_OLD_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_OLD_EXTRA_BYTES + 8)
+ /* offset of the page supremum record on an
+ old-style page */
+#define PAGE_OLD_SUPREMUM_END (PAGE_OLD_SUPREMUM + 9)
/* offset of the page supremum record end on
- the page */
+ an old-style page */
+#define PAGE_NEW_INFIMUM (PAGE_DATA + REC_N_NEW_EXTRA_BYTES)
+ /* offset of the page infimum record on a
+ new-style compact page */
+#define PAGE_NEW_SUPREMUM (PAGE_DATA + 2 * REC_N_NEW_EXTRA_BYTES + 8)
+ /* offset of the page supremum record on a
+ new-style compact page */
+#define PAGE_NEW_SUPREMUM_END (PAGE_NEW_SUPREMUM + 8)
+ /* offset of the page supremum record end on
+ a new-style compact page */
/*-----------------------------*/
/* Directions of cursor movement */
@@ -233,6 +243,7 @@ page_cmp_dtuple_rec_with_match(
be page infimum or supremum, in which case
matched-parameter values below are not
affected */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns
contains the value for current comparison */
@@ -259,6 +270,22 @@ page_rec_get_n_recs_before(
/* out: number of records */
rec_t* rec); /* in: the physical record */
/*****************************************************************
+Gets the number of records in the heap. */
+UNIV_INLINE
+ulint
+page_dir_get_n_heap(
+/*================*/
+ /* out: number of user records */
+ page_t* page); /* in: index page */
+/*****************************************************************
+Sets the number of records in the heap. */
+UNIV_INLINE
+void
+page_dir_set_n_heap(
+/*================*/
+ page_t* page, /* in: index page */
+ ulint n_heap);/* in: number of records */
+/*****************************************************************
Gets the number of dir slots in directory. */
UNIV_INLINE
ulint
@@ -267,6 +294,15 @@ page_dir_get_n_slots(
/* out: number of slots */
page_t* page); /* in: index page */
/*****************************************************************
+Sets the number of dir slots in directory. */
+UNIV_INLINE
+void
+page_dir_set_n_slots(
+/*=================*/
+ /* out: number of slots */
+ page_t* page, /* in: index page */
+ ulint n_slots);/* in: number of slots */
+/*****************************************************************
Gets pointer to nth directory slot. */
UNIV_INLINE
page_dir_slot_t*
@@ -333,7 +369,16 @@ ulint
page_dir_find_owner_slot(
/*=====================*/
/* out: the directory slot number */
- rec_t* rec); /* in: the physical record */
+ rec_t* rec); /* in: the physical record */
+/****************************************************************
+Determine whether the page is in new-style compact format. */
+UNIV_INLINE
+ibool
+page_is_comp(
+/*=========*/
+ /* out: TRUE if the page is in compact format
+ FALSE if it is in old-style format */
+ page_t* page); /* in: index page */
/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
@@ -359,9 +404,10 @@ UNIV_INLINE
rec_t*
page_rec_get_prev(
/*==============*/
- /* out: pointer to previous record */
- rec_t* rec); /* in: pointer to record, must not be page
- infimum */
+ /* out: pointer to previous record */
+ rec_t* rec); /* in: pointer to record,
+ must not be page infimum */
+
/****************************************************************
TRUE if the record is a user record on the page. */
UNIV_INLINE
@@ -446,9 +492,11 @@ page_get_max_insert_size_after_reorganize(
Calculates free space if a page is emptied. */
UNIV_INLINE
ulint
-page_get_free_space_of_empty(void);
-/*==============================*/
- /* out: free space */
+page_get_free_space_of_empty(
+/*=========================*/
+ /* out: free space */
+ ibool comp) /* in: TRUE=compact page format */
+ __attribute__((const));
/****************************************************************
Returns the sum of the sizes of the records in the record list
excluding the infimum and supremum records. */
@@ -464,20 +512,23 @@ Allocates a block of memory from an index page. */
byte*
page_mem_alloc(
/*===========*/
- /* out: pointer to start of allocated
- buffer, or NULL if allocation fails */
- page_t* page, /* in: index page */
- ulint need, /* in: number of bytes needed */
- ulint* heap_no);/* out: this contains the heap number
- of the allocated record if allocation succeeds */
+ /* out: pointer to start of allocated
+ buffer, or NULL if allocation fails */
+ page_t* page, /* in: index page */
+ ulint need, /* in: number of bytes needed */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* heap_no);/* out: this contains the heap number
+ of the allocated record
+ if allocation succeeds */
/****************************************************************
Puts a record to free list. */
UNIV_INLINE
void
page_mem_free(
/*==========*/
- page_t* page, /* in: index page */
- rec_t* rec); /* in: pointer to the (origin of) record */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: pointer to the (origin of) record */
+ dict_index_t* index); /* in: record descriptor */
/**************************************************************
The index page creation function. */
@@ -487,7 +538,8 @@ page_create(
/* out: pointer to the page */
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
- mtr_t* mtr); /* in: mini-transaction handle */
+ mtr_t* mtr, /* in: mini-transaction handle */
+ ibool comp); /* in: TRUE=compact page format */
/*****************************************************************
Differs from page_copy_rec_list_end, because this function does not
touch the lock table and max trx id on page. */
@@ -495,10 +547,11 @@ touch the lock table and max trx id on page. */
void
page_copy_rec_list_end_no_locks(
/*============================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Copies records from page to new_page, from the given record onward,
including that record. Infimum and supremum records are not copied.
@@ -507,10 +560,11 @@ The records are copied to the start of the record list on new_page. */
void
page_copy_rec_list_end(
/*===================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Copies records from page to new_page, up to the given record, NOT
including that record. Infimum and supremum records are not copied.
@@ -519,10 +573,11 @@ The records are copied to the end of the record list on new_page. */
void
page_copy_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes records from a page from a given record onward, including that record.
The infimum and supremum records are not deleted. */
@@ -530,14 +585,15 @@ The infimum and supremum records are not deleted. */
void
page_delete_rec_list_end(
/*=====================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- ulint n_recs, /* in: number of records to delete, or ULINT_UNDEFINED
- if not known */
- ulint size, /* in: the sum of the sizes of the records in the end
- of the chain to delete, or ULINT_UNDEFINED if not
- known */
- mtr_t* mtr); /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_recs, /* in: number of records to delete,
+ or ULINT_UNDEFINED if not known */
+ ulint size, /* in: the sum of the sizes of the
+ records in the end of the chain to
+ delete, or ULINT_UNDEFINED if not known */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes records from page, up to the given record, NOT including
that record. Infimum and supremum records are not deleted. */
@@ -545,9 +601,10 @@ that record. Infimum and supremum records are not deleted. */
void
page_delete_rec_list_start(
/*=======================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Moves record list end to another page. Moved records include
split_rec. */
@@ -555,10 +612,11 @@ split_rec. */
void
page_move_rec_list_end(
/*===================*/
- page_t* new_page, /* in: index page where to move */
- page_t* page, /* in: index page */
- rec_t* split_rec, /* in: first record to move */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page where to move */
+ page_t* page, /* in: index page */
+ rec_t* split_rec, /* in: first record to move */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Moves record list start to another page. Moved records do not include
split_rec. */
@@ -566,10 +624,11 @@ split_rec. */
void
page_move_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page where to move */
- page_t* page, /* in: index page */
- rec_t* split_rec, /* in: first record not to move */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page where to move */
+ page_t* page, /* in: index page */
+ rec_t* split_rec, /* in: first record not to move */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/********************************************************************
Splits a directory slot which owns too many records. */
@@ -595,13 +654,16 @@ Parses a log record of a record list end or start deletion. */
byte*
page_parse_delete_rec_list(
/*=======================*/
- /* out: end of log record or NULL */
- byte type, /* in: MLOG_LIST_END_DELETE or
- MLOG_LIST_START_DELETE */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte type, /* in: MLOG_LIST_END_DELETE,
+ MLOG_LIST_START_DELETE,
+ MLOG_COMP_LIST_END_DELETE or
+ MLOG_COMP_LIST_START_DELETE */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
Parses a redo log record of creating a page. */
@@ -611,6 +673,7 @@ page_parse_create(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
+ ibool comp, /* in: TRUE=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/****************************************************************
@@ -620,7 +683,8 @@ the index page context. */
void
page_rec_print(
/*===========*/
- rec_t* rec);
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: record descriptor */
/*******************************************************************
This is used to print the contents of the directory for
debugging purposes. */
@@ -637,8 +701,9 @@ debugging purposes. */
void
page_print_list(
/*============*/
- page_t* page, /* in: index page */
- ulint pr_n); /* in: print n first and n last entries */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: dictionary index of the page */
+ ulint pr_n); /* in: print n first and n last entries */
/*******************************************************************
Prints the info in a page header. */
@@ -653,9 +718,12 @@ debugging purposes. */
void
page_print(
/*======*/
- page_t* page, /* in: index page */
- ulint dn, /* in: print dn first and last entries in directory */
- ulint rn); /* in: print rn first and last records on page */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: dictionary index of the page */
+ ulint dn, /* in: print dn first and last entries
+ in directory */
+ ulint rn); /* in: print rn first and last records
+ in directory */
/*******************************************************************
The following is used to validate a record on a page. This function
differs from rec_validate as it can also check the n_owned field and
@@ -664,8 +732,9 @@ the heap_no field. */
ibool
page_rec_validate(
/*==============*/
- /* out: TRUE if ok */
- rec_t* rec); /* in: record on the page */
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Checks that the first directory slot points to the infimum record and
the last to the supremum. This function is intended to track if the
diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic
index 3d2bf3b090e..1d5ea337031 100644
--- a/innobase/include/page0page.ic
+++ b/innobase/include/page0page.ic
@@ -73,7 +73,8 @@ page_header_set_field(
{
ut_ad(page);
ut_ad(field <= PAGE_N_RECS);
- ut_ad(val < UNIV_PAGE_SIZE);
+ ut_ad(field == PAGE_N_HEAP || val < UNIV_PAGE_SIZE);
+ ut_ad(field != PAGE_N_HEAP || (val & 0x7fff) < UNIV_PAGE_SIZE);
mach_write_to_2(page + PAGE_HEADER + field, val);
}
@@ -162,7 +163,11 @@ page_get_infimum_rec(
{
ut_ad(page);
- return(page + PAGE_INFIMUM);
+ if (page_is_comp(page)) {
+ return(page + PAGE_NEW_INFIMUM);
+ } else {
+ return(page + PAGE_OLD_INFIMUM);
+ }
}
/****************************************************************
@@ -176,7 +181,11 @@ page_get_supremum_rec(
{
ut_ad(page);
- return(page + PAGE_SUPREMUM);
+ if (page_is_comp(page)) {
+ return(page + PAGE_NEW_SUPREMUM);
+ } else {
+ return(page + PAGE_OLD_SUPREMUM);
+ }
}
/****************************************************************
@@ -309,6 +318,7 @@ page_cmp_dtuple_rec_with_match(
be page infimum or supremum, in which case
matched-parameter values below are not
affected */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns
contains the value for current comparison */
@@ -320,6 +330,7 @@ page_cmp_dtuple_rec_with_match(
page_t* page;
ut_ad(dtuple_check_typed(dtuple));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
page = buf_frame_align(rec);
@@ -328,7 +339,7 @@ page_cmp_dtuple_rec_with_match(
} else if (rec == page_get_supremum_rec(page)) {
return(-1);
} else {
- return(cmp_dtuple_rec_with_match(dtuple, rec,
+ return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
matched_fields,
matched_bytes));
}
@@ -358,6 +369,45 @@ page_dir_get_n_slots(
{
return(page_header_get_field(page, PAGE_N_DIR_SLOTS));
}
+/*****************************************************************
+Sets the number of dir slots in directory. */
+UNIV_INLINE
+void
+page_dir_set_n_slots(
+/*=================*/
+ /* out: number of slots */
+ page_t* page, /* in: index page */
+ ulint n_slots)/* in: number of slots */
+{
+ page_header_set_field(page, PAGE_N_DIR_SLOTS, n_slots);
+}
+
+/*****************************************************************
+Gets the number of records in the heap. */
+UNIV_INLINE
+ulint
+page_dir_get_n_heap(
+/*================*/
+ /* out: number of user records */
+ page_t* page) /* in: index page */
+{
+ return(page_header_get_field(page, PAGE_N_HEAP) & 0x7fff);
+}
+
+/*****************************************************************
+Sets the number of records in the heap. */
+UNIV_INLINE
+void
+page_dir_set_n_heap(
+/*================*/
+ page_t* page, /* in: index page */
+ ulint n_heap) /* in: number of records */
+{
+ ut_ad(n_heap < 0x8000);
+
+ page_header_set_field(page, PAGE_N_HEAP, n_heap | (0x8000 &
+ page_header_get_field(page, PAGE_N_HEAP)));
+}
/*****************************************************************
Gets pointer to nth directory slot. */
@@ -369,7 +419,7 @@ page_dir_get_nth_slot(
page_t* page, /* in: index page */
ulint n) /* in: position */
{
- ut_ad(page_header_get_field(page, PAGE_N_DIR_SLOTS) > n);
+ ut_ad(page_dir_get_n_slots(page) > n);
return(page + UNIV_PAGE_SIZE - PAGE_DIR
- (n + 1) * PAGE_DIR_SLOT_SIZE);
@@ -431,7 +481,8 @@ page_dir_slot_get_n_owned(
/* out: number of records */
page_dir_slot_t* slot) /* in: page directory slot */
{
- return(rec_get_n_owned(page_dir_slot_get_rec(slot)));
+ return(rec_get_n_owned(page_dir_slot_get_rec(slot),
+ page_is_comp(buf_frame_align(slot))));
}
/*******************************************************************
@@ -444,7 +495,8 @@ page_dir_slot_set_n_owned(
ulint n) /* in: number of records owned
by the slot */
{
- rec_set_n_owned(page_dir_slot_get_rec(slot), n);
+ rec_set_n_owned(page_dir_slot_get_rec(slot),
+ page_is_comp(buf_frame_align(slot)), n);
}
/****************************************************************
@@ -462,6 +514,19 @@ page_dir_calc_reserved_space(
}
/****************************************************************
+Determine whether the page is in new-style compact format. */
+UNIV_INLINE
+ibool
+page_is_comp(
+/*=========*/
+ /* out: TRUE if the page is in compact format
+ FALSE if it is in old-style format */
+ page_t* page) /* in: index page */
+{
+ return(!!(page_header_get_field(page, PAGE_N_HEAP) & 0x8000));
+}
+
+/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
rec_t*
@@ -477,7 +542,7 @@ page_rec_get_next(
page = buf_frame_align(rec);
- offs = rec_get_next_offs(rec);
+ offs = rec_get_next_offs(rec, page_is_comp(page));
if (offs >= UNIV_PAGE_SIZE) {
fprintf(stderr,
@@ -513,6 +578,7 @@ page_rec_set_next(
infimum */
{
page_t* page;
+ ulint offs;
ut_ad(page_rec_check(rec));
ut_a((next == NULL)
@@ -523,11 +589,13 @@ page_rec_set_next(
ut_ad(rec != page_get_supremum_rec(page));
ut_ad(next != page_get_infimum_rec(page));
- if (next == NULL) {
- rec_set_next_offs(rec, 0);
+ if (next) {
+ offs = (ulint) (next - page);
} else {
- rec_set_next_offs(rec, (ulint)(next - page));
+ offs = 0;
}
+
+ rec_set_next_offs(rec, page_is_comp(page), offs);
}
/****************************************************************
@@ -545,6 +613,7 @@ page_rec_get_prev(
rec_t* rec2;
rec_t* prev_rec = NULL;
page_t* page;
+ ibool comp;
ut_ad(page_rec_check(rec));
@@ -559,6 +628,7 @@ page_rec_get_prev(
slot = page_dir_get_nth_slot(page, slot_no - 1);
rec2 = page_dir_slot_get_rec(slot);
+ comp = page_is_comp(page);
while (rec != rec2) {
prev_rec = rec2;
@@ -579,9 +649,12 @@ page_rec_find_owner_rec(
/* out: the owner record */
rec_t* rec) /* in: the physical record */
{
+ ibool comp;
+
ut_ad(page_rec_check(rec));
+ comp = page_is_comp(buf_frame_align(rec));
- while (rec_get_n_owned(rec) == 0) {
+ while (rec_get_n_owned(rec, comp) == 0) {
rec = page_rec_get_next(rec);
}
@@ -601,7 +674,9 @@ page_get_data_size(
ulint ret;
ret = (ulint)(page_header_get_field(page, PAGE_HEAP_TOP)
- - PAGE_SUPREMUM_END
+ - (page_is_comp(page)
+ ? PAGE_NEW_SUPREMUM_END
+ : PAGE_OLD_SUPREMUM_END)
- page_header_get_field(page, PAGE_GARBAGE));
ut_ad(ret < UNIV_PAGE_SIZE);
@@ -613,12 +688,13 @@ page_get_data_size(
Calculates free space if a page is emptied. */
UNIV_INLINE
ulint
-page_get_free_space_of_empty(void)
-/*==============================*/
+page_get_free_space_of_empty(
+/*=========================*/
/* out: free space */
+ ibool comp) /* in: TRUE=compact page layout */
{
return((ulint)(UNIV_PAGE_SIZE
- - PAGE_SUPREMUM_END
+ - (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END)
- PAGE_DIR
- 2 * PAGE_DIR_SLOT_SIZE));
}
@@ -640,13 +716,16 @@ page_get_max_insert_size(
{
ulint occupied;
ulint free_space;
+ ibool comp;
+
+ comp = page_is_comp(page);
occupied = page_header_get_field(page, PAGE_HEAP_TOP)
- - PAGE_SUPREMUM_END
+ - (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END)
+ page_dir_calc_reserved_space(
- n_recs + (page_header_get_field(page, PAGE_N_HEAP) - 2));
+ n_recs + page_dir_get_n_heap(page) - 2);
- free_space = page_get_free_space_of_empty();
+ free_space = page_get_free_space_of_empty(comp);
/* Above the 'n_recs +' part reserves directory space for the new
inserted records; the '- 2' excludes page infimum and supremum
@@ -673,11 +752,14 @@ page_get_max_insert_size_after_reorganize(
{
ulint occupied;
ulint free_space;
+ ibool comp;
+
+ comp = page_is_comp(page);
occupied = page_get_data_size(page)
+ page_dir_calc_reserved_space(n_recs + page_get_n_recs(page));
- free_space = page_get_free_space_of_empty();
+ free_space = page_get_free_space_of_empty(comp);
if (occupied > free_space) {
@@ -693,11 +775,12 @@ UNIV_INLINE
void
page_mem_free(
/*==========*/
- page_t* page, /* in: index page */
- rec_t* rec) /* in: pointer to the (origin of) record */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: pointer to the (origin of) record */
+ dict_index_t* index) /* in: record descriptor */
{
- rec_t* free;
- ulint garbage;
+ rec_t* free;
+ ulint garbage;
free = page_header_get_ptr(page, PAGE_FREE);
@@ -707,7 +790,7 @@ page_mem_free(
garbage = page_header_get_field(page, PAGE_GARBAGE);
page_header_set_field(page, PAGE_GARBAGE,
- garbage + rec_get_size(rec));
+ garbage + rec_get_size(rec, index));
}
#ifdef UNIV_MATERIALIZE
diff --git a/innobase/include/rem0cmp.h b/innobase/include/rem0cmp.h
index 712e263350e..77a5a42c2d5 100644
--- a/innobase/include/rem0cmp.h
+++ b/innobase/include/rem0cmp.h
@@ -90,6 +90,7 @@ cmp_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns,
contains the value for current comparison */
@@ -107,7 +108,8 @@ cmp_dtuple_rec(
less than rec, respectively; see the comments
for cmp_dtuple_rec_with_match */
dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/******************************************************************
Checks if a dtuple is a prefix of a record. The last field in dtuple
is allowed to be a prefix of the corresponding field in the record. */
@@ -116,23 +118,9 @@ ibool
cmp_dtuple_is_prefix_of_rec(
/*========================*/
/* out: TRUE if prefix */
- dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec); /* in: physical record */
-/******************************************************************
-Compares a prefix of a data tuple to a prefix of a physical record for
-equality. If there are less fields in rec than parameter n_fields, FALSE
-is returned. NOTE that n_fields_cmp of dtuple does not affect this
-comparison. */
-
-ibool
-cmp_dtuple_rec_prefix_equal(
-/*========================*/
- /* out: TRUE if equal */
dtuple_t* dtuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
- ulint n_fields); /* in: number of fields which should be
- compared; must not exceed the number of
- fields in dtuple */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*****************************************************************
This function is used to compare two physical records. Only the common
first fields are compared, and if an externally stored field is
@@ -146,7 +134,13 @@ cmp_rec_rec_with_match(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
dict_index_t* index, /* in: data dictionary index */
+ ulint n, /* in: number of fields to compare,
+ or ULINT_UNDEFINED if both records
+ contain all fields, and all fields
+ should be compared */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when the function returns,
contains the value the for current
@@ -167,6 +161,12 @@ cmp_rec_rec(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
+ ulint n, /* in: number of fields to compare,
+ or ULINT_UNDEFINED if both records
+ contain all fields, and all fields
+ should be compared */
dict_index_t* index); /* in: data dictionary index */
diff --git a/innobase/include/rem0cmp.ic b/innobase/include/rem0cmp.ic
index 75cb3ef04e8..d4c30f25f03 100644
--- a/innobase/include/rem0cmp.ic
+++ b/innobase/include/rem0cmp.ic
@@ -57,10 +57,14 @@ cmp_rec_rec(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
+ ulint n, /* in: number of fields to compare */
dict_index_t* index) /* in: data dictionary index */
{
ulint match_f = 0;
ulint match_b = 0;
- return(cmp_rec_rec_with_match(rec1, rec2, index, &match_f, &match_b));
+ return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index, n,
+ &match_f, &match_b));
}
diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h
index 86bf263170f..d450df82311 100644
--- a/innobase/include/rem0rec.h
+++ b/innobase/include/rem0rec.h
@@ -23,9 +23,18 @@ Created 5/30/1994 Heikki Tuuri
info bits of a record */
#define REC_INFO_MIN_REC_FLAG 0x10UL
-/* Number of extra bytes in a record, in addition to the data and the
-offsets */
-#define REC_N_EXTRA_BYTES 6
+/* Number of extra bytes in an old-style record,
+in addition to the data and the offsets */
+#define REC_N_OLD_EXTRA_BYTES 6
+/* Number of extra bytes in a new-style record,
+in addition to the data and the offsets */
+#define REC_N_NEW_EXTRA_BYTES 5
+
+/* Record status values */
+#define REC_STATUS_ORDINARY 0
+#define REC_STATUS_NODE_PTR 1
+#define REC_STATUS_INFIMUM 2
+#define REC_STATUS_SUPREMUM 3
/**********************************************************
The following function is used to get the offset of the
@@ -36,7 +45,8 @@ rec_get_next_offs(
/*==============*/
/* out: the page offset of the next
chained record */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the next record offset field
of the record. */
@@ -45,14 +55,15 @@ void
rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint next); /* in: offset of the next record */
/**********************************************************
The following function is used to get the number of fields
-in the record. */
+in an old-style record. */
UNIV_INLINE
ulint
-rec_get_n_fields(
-/*=============*/
+rec_get_n_fields_old(
+/*=================*/
/* out: number of data fields */
rec_t* rec); /* in: physical record */
/**********************************************************
@@ -63,7 +74,8 @@ ulint
rec_get_n_owned(
/*============*/
/* out: number of owned records */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the number of owned
records. */
@@ -72,6 +84,7 @@ void
rec_set_n_owned(
/*============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint n_owned); /* in: the number of owned */
/**********************************************************
The following function is used to retrieve the info bits of
@@ -81,7 +94,8 @@ ulint
rec_get_info_bits(
/*==============*/
/* out: info bits */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the info bits of a record. */
UNIV_INLINE
@@ -89,15 +103,26 @@ void
rec_set_info_bits(
/*==============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint bits); /* in: info bits */
/**********************************************************
-Gets the value of the deleted falg in info bits. */
+The following function retrieves the status bits of a new-style record. */
UNIV_INLINE
-ibool
-rec_info_bits_get_deleted_flag(
-/*===========================*/
- /* out: TRUE if deleted flag set */
- ulint info_bits); /* in: info bits from a record */
+ulint
+rec_get_status(
+/*===========*/
+ /* out: status bits */
+ rec_t* rec); /* in: physical record */
+
+/**********************************************************
+The following function is used to set the status bits of a new-style record. */
+UNIV_INLINE
+void
+rec_set_status(
+/*===========*/
+ rec_t* rec, /* in: physical record */
+ ulint bits); /* in: info bits */
+
/**********************************************************
The following function tells if record is delete marked. */
UNIV_INLINE
@@ -105,7 +130,8 @@ ibool
rec_get_deleted_flag(
/*=================*/
/* out: TRUE if delete marked */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the deleted bit. */
UNIV_INLINE
@@ -113,8 +139,25 @@ void
rec_set_deleted_flag(
/*=================*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ibool flag); /* in: TRUE if delete marked */
/**********************************************************
+The following function tells if a new-style record is a node pointer. */
+UNIV_INLINE
+ibool
+rec_get_node_ptr_flag(
+/*=================*/
+ /* out: TRUE if node pointer */
+ rec_t* rec); /* in: physical record */
+/**********************************************************
+The following function is used to flag a record as a node pointer. */
+UNIV_INLINE
+void
+rec_set_node_ptr_flag(
+/*=================*/
+ rec_t* rec, /* in: physical record */
+ ibool flag); /* in: TRUE if the record is a node pointer */
+/**********************************************************
The following function is used to get the order number
of the record in the heap of the index page. */
UNIV_INLINE
@@ -122,7 +165,8 @@ ulint
rec_get_heap_no(
/*=============*/
/* out: heap order number */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the heap number
field in the record. */
@@ -131,6 +175,7 @@ void
rec_set_heap_no(
/*=============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint heap_no);/* in: the heap number */
/**********************************************************
The following function is used to test whether the data offsets
@@ -141,31 +186,84 @@ rec_get_1byte_offs_flag(
/*====================*/
/* out: TRUE if 1-byte form */
rec_t* rec); /* in: physical record */
+/**********************************************************
+The following function determines the offsets to each field
+in the record. The offsets are returned in an array of
+ulint, with [0] being the number of fields (n), [1] being the
+extra size (if REC_OFFS_COMPACT is set, the record is in the new
+format), and [2]..[n+1] being the offsets past the end of
+fields 0..n, or to the beginning of fields 1..n+1. When the
+high-order bit of the offset at [n+1] is set (REC_OFFS_SQL_NULL),
+the field n is NULL. When the second high-order bit of the offset
+at [n+1] is set (REC_OFFS_EXTERNAL), the field n is being stored
+externally. */
+
+ulint*
+rec_get_offsets(
+/*============*/
+ /* out: the offsets */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_fields,/* in: maximum number of initialized fields
+ (ULINT_UNDEFINED if all fields) */
+ mem_heap_t* heap); /* in: memory heap */
+/**********************************************************
+The following function determines the offsets to each field
+in the record. It differs from rec_get_offsets() by trying to
+reuse a previously returned array. */
+
+ulint*
+rec_reget_offsets(
+/*==============*/
+ /* out: the new offsets */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* offsets,/* in: array of offsets
+ from rec_get_offsets()
+ or rec_reget_offsets(), or NULL */
+ ulint n_fields,/* in: maximum number of initialized fields
+ (ULINT_UNDEFINED if all fields) */
+ mem_heap_t* heap); /* in: memory heap */
+
+/****************************************************************
+Validates offsets returned by rec_get_offsets() or rec_reget_offsets(). */
+UNIV_INLINE
+ibool
+rec_offs_validate(
+/*==============*/
+ /* out: TRUE if valid */
+ rec_t* rec, /* in: record or NULL */
+ dict_index_t* index, /* in: record descriptor or NULL */
+ const ulint* offsets);/* in: array returned by rec_get_offsets()
+ or rec_reget_offsets() */
+/****************************************************************
+Updates debug data in offsets, in order to avoid bogus
+rec_offs_validate() failures. */
+UNIV_INLINE
+void
+rec_offs_make_valid(
+/*================*/
+ const rec_t* rec, /* in: record */
+ const dict_index_t* index,/* in: record descriptor */
+ ulint* offsets);/* in: array returned by rec_get_offsets()
+ or rec_reget_offsets() */
+
/****************************************************************
The following function is used to get a pointer to the nth
-data field in the record. */
+data field in an old-style record. */
byte*
-rec_get_nth_field(
-/*==============*/
+rec_get_nth_field_old(
+/*==================*/
/* out: pointer to the field */
rec_t* rec, /* in: record */
ulint n, /* in: index of the field */
ulint* len); /* out: length of the field; UNIV_SQL_NULL
if SQL null */
/****************************************************************
-Return field length or UNIV_SQL_NULL. */
-UNIV_INLINE
-ulint
-rec_get_nth_field_len(
-/*==================*/
- /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
- rec_t* rec, /* in: record */
- ulint n); /* in: index of the field */
-/****************************************************************
-Gets the physical size of a field. Also an SQL null may have a field of
-size > 0, if the data type is of a fixed size. */
+Gets the physical size of an old-style field.
+Also an SQL null may have a field of size > 0,
+if the data type is of a fixed size. */
UNIV_INLINE
ulint
rec_get_nth_field_size(
@@ -173,131 +271,194 @@ rec_get_nth_field_size(
/* out: field size in bytes */
rec_t* rec, /* in: record */
ulint n); /* in: index of the field */
-/***************************************************************
-Gets the value of the ith field extern storage bit. If it is TRUE
-it means that the field is stored on another page. */
+/****************************************************************
+The following function is used to get a pointer to the nth
+data field in an old-style record. */
+UNIV_INLINE
+byte*
+rec_get_nth_field(
+/*==============*/
+ /* out: pointer to the field */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index of the field */
+ ulint* len); /* out: length of the field; UNIV_SQL_NULL
+ if SQL null */
+/**********************************************************
+Determine if the offsets are for a record in the new
+compact format. */
UNIV_INLINE
ibool
-rec_get_nth_field_extern_bit(
-/*=========================*/
- /* in: TRUE or FALSE */
- rec_t* rec, /* in: record */
- ulint i); /* in: ith field */
+rec_offs_comp(
+/*==========*/
+ /* out: TRUE if compact format */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**********************************************************
+Returns TRUE if the nth field of rec is SQL NULL. */
+UNIV_INLINE
+ibool
+rec_offs_nth_null(
+/*==============*/
+ /* out: TRUE if SQL NULL */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n); /* in: nth field */
+/**********************************************************
+Returns TRUE if the extern bit is set in nth field of rec. */
+UNIV_INLINE
+ibool
+rec_offs_nth_extern(
+/*================*/
+ /* out: TRUE if externally stored */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n); /* in: nth field */
+/**********************************************************
+Gets the physical size of a field. */
+UNIV_INLINE
+ulint
+rec_offs_nth_size(
+/*==============*/
+ /* out: length of field */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n); /* in: nth field */
+
/**********************************************************
Returns TRUE if the extern bit is set in any of the fields
of rec. */
UNIV_INLINE
ibool
-rec_contains_externally_stored_field(
-/*=================================*/
- /* out: TRUE if a field is stored externally */
- rec_t* rec); /* in: record */
+rec_offs_any_extern(
+/*================*/
+ /* out: TRUE if a field is stored externally */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/***************************************************************
Sets the value of the ith field extern storage bit. */
-
+UNIV_INLINE
void
rec_set_nth_field_extern_bit(
/*=========================*/
- rec_t* rec, /* in: record */
- ulint i, /* in: ith field */
- ibool val, /* in: value to set */
- mtr_t* mtr); /* in: mtr holding an X-latch to the page where
- rec is, or NULL; in the NULL case we do not
- write to log about the change */
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint i, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
/***************************************************************
Sets TRUE the extern storage bits of fields mentioned in an array. */
void
rec_set_field_extern_bits(
/*======================*/
- rec_t* rec, /* in: record */
- ulint* vec, /* in: array of field numbers */
- ulint n_fields, /* in: number of fields numbers */
- mtr_t* mtr); /* in: mtr holding an X-latch to the page
- where rec is, or NULL; in the NULL case we
- do not write to log about the change */
-/****************************************************************
-The following function is used to get a copy of the nth
-data field in the record to a buffer. */
-UNIV_INLINE
-void
-rec_copy_nth_field(
-/*===============*/
- void* buf, /* in: pointer to the buffer */
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- ulint* len); /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ const ulint* vec, /* in: array of field numbers */
+ ulint n_fields,/* in: number of fields numbers */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
/***************************************************************
-This is used to modify the value of an already existing field in
-a physical record. The previous value must have exactly the same
-size as the new value. If len is UNIV_SQL_NULL then the field is
-treated as SQL null. */
+This is used to modify the value of an already existing field in a record.
+The previous value must have exactly the same size as the new value. If len
+is UNIV_SQL_NULL then the field is treated as an SQL null for old-style
+records. For new-style records, len must not be UNIV_SQL_NULL. */
UNIV_INLINE
void
rec_set_nth_field(
/*==============*/
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- void* data, /* in: pointer to the data if not SQL null */
- ulint len); /* in: length of the data or UNIV_SQL_NULL.
- If not SQL null, must have the same length as the
- previous value. If SQL null, previous value must be
- SQL null. */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index number of the field */
+ const void* data, /* in: pointer to the data if not SQL null */
+ ulint len); /* in: length of the data or UNIV_SQL_NULL.
+ If not SQL null, must have the same
+ length as the previous value.
+ If SQL null, previous value must be
+ SQL null. */
/**************************************************************
-The following function returns the data size of a physical
+The following function returns the data size of an old-style physical
record, that is the sum of field lengths. SQL null fields
are counted as length 0 fields. The value returned by the function
is the distance from record origin to record end in bytes. */
UNIV_INLINE
ulint
-rec_get_data_size(
-/*==============*/
- /* out: size */
+rec_get_data_size_old(
+/*==================*/
+ /* out: size */
rec_t* rec); /* in: physical record */
/**************************************************************
+The following function returns the number of fields in a record. */
+UNIV_INLINE
+ulint
+rec_offs_n_fields(
+/*===============*/
+ /* out: number of fields */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
+The following function returns the data size of a physical
+record, that is the sum of field lengths. SQL null fields
+are counted as length 0 fields. The value returned by the function
+is the distance from record origin to record end in bytes. */
+UNIV_INLINE
+ulint
+rec_offs_data_size(
+/*===============*/
+ /* out: size */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
Returns the total size of record minus data size of record.
The value returned by the function is the distance from record
start to record origin in bytes. */
UNIV_INLINE
ulint
-rec_get_extra_size(
-/*===============*/
- /* out: size */
- rec_t* rec); /* in: physical record */
-/**************************************************************
+rec_offs_extra_size(
+/*================*/
+ /* out: size */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
Returns the total size of a physical record. */
UNIV_INLINE
ulint
+rec_offs_size(
+/*==========*/
+ /* out: size */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
+Returns the total size of a physical record. */
+
+ulint
rec_get_size(
/*=========*/
- /* out: size */
- rec_t* rec); /* in: physical record */
+ /* out: size */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index); /* in: record descriptor */
/**************************************************************
Returns a pointer to the start of the record. */
UNIV_INLINE
byte*
rec_get_start(
/*==========*/
- /* out: pointer to start */
- rec_t* rec); /* in: pointer to record */
+ /* out: pointer to start */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**************************************************************
Returns a pointer to the end of the record. */
UNIV_INLINE
byte*
rec_get_end(
/*========*/
- /* out: pointer to end */
- rec_t* rec); /* in: pointer to record */
+ /* out: pointer to end */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Copies a physical record to a buffer. */
UNIV_INLINE
rec_t*
rec_copy(
/*=====*/
- /* out: pointer to the origin of the copied record */
- void* buf, /* in: buffer */
- rec_t* rec); /* in: physical record */
+ /* out: pointer to the origin of the copy */
+ void* buf, /* in: buffer */
+ const rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/******************************************************************
Copies the first n fields of a physical record to a new physical record in
a buffer. */
@@ -305,49 +466,43 @@ a buffer. */
rec_t*
rec_copy_prefix_to_buf(
/*===================*/
- /* out, own: copied record */
- rec_t* rec, /* in: physical record */
- ulint n_fields, /* in: number of fields to copy */
- byte** buf, /* in/out: memory buffer for the copied prefix,
- or NULL */
- ulint* buf_size); /* in/out: buffer size */
+ /* out, own: copied record */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_fields, /* in: number of fields to copy */
+ byte** buf, /* in/out: memory buffer
+ for the copied prefix, or NULL */
+ ulint* buf_size); /* in/out: buffer size */
/****************************************************************
Folds a prefix of a physical record to a ulint. */
UNIV_INLINE
ulint
rec_fold(
/*=====*/
- /* out: the folded value */
- rec_t* rec, /* in: the physical record */
- ulint n_fields, /* in: number of complete fields to fold */
- ulint n_bytes, /* in: number of bytes to fold in an
- incomplete last field */
- dulint tree_id); /* in: index tree id */
+ /* out: the folded value */
+ rec_t* rec, /* in: the physical record */
+ const ulint* offsets, /* in: array returned by
+ rec_get_offsets() */
+ ulint n_fields, /* in: number of complete
+ fields to fold */
+ ulint n_bytes, /* in: number of bytes to fold
+ in an incomplete last field */
+ dulint tree_id); /* in: index tree id */
/*************************************************************
Builds a physical record out of a data tuple and stores it beginning from
address destination. */
-UNIV_INLINE
+
rec_t*
rec_convert_dtuple_to_rec(
/*======================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple); /* in: data tuple */
-/*************************************************************
-Builds a physical record out of a data tuple and stores it beginning from
-address destination. */
-
-rec_t*
-rec_convert_dtuple_to_rec_low(
-/*==========================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple, /* in: data tuple */
- ulint data_size); /* in: data size of dtuple */
+ /* out: pointer to the origin
+ of physical record */
+ byte* buf, /* in: start address of the
+ physical record */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple);/* in: data tuple */
/**************************************************************
-Returns the extra size of a physical record if we know its
+Returns the extra size of an old-style physical record if we know its
data size and number of fields. */
UNIV_INLINE
ulint
@@ -355,7 +510,8 @@ rec_get_converted_extra_size(
/*=========================*/
/* out: extra size */
ulint data_size, /* in: data size */
- ulint n_fields); /* in: number of fields */
+ ulint n_fields) /* in: number of fields */
+ __attribute__((const));
/**************************************************************
The following function returns the size of a data tuple when converted to
a physical record. */
@@ -364,6 +520,7 @@ ulint
rec_get_converted_size(
/*===================*/
/* out: size */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* dtuple);/* in: data tuple */
/******************************************************************
Copies the first n fields of a physical record to a data tuple.
@@ -374,6 +531,7 @@ rec_copy_prefix_to_dtuple(
/*======================*/
dtuple_t* tuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
ulint n_fields, /* in: number of fields to copy */
mem_heap_t* heap); /* in: memory heap */
/*******************************************************************
@@ -382,16 +540,27 @@ Validates the consistency of a physical record. */
ibool
rec_validate(
/*=========*/
- /* out: TRUE if ok */
- rec_t* rec); /* in: physical record */
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/*******************************************************************
+Prints an old-style physical record. */
+
+void
+rec_print_old(
+/*==========*/
+ FILE* file, /* in: file where to print */
+ rec_t* rec); /* in: physical record */
+
/*******************************************************************
Prints a physical record. */
void
rec_print(
/*======*/
- FILE* file, /* in: file where to print */
- rec_t* rec); /* in: physical record */
+ FILE* file, /* in: file where to print */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
#define REC_INFO_BITS 6 /* This is single byte bit-field */
diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic
index c36bf8f6d6e..a8acb4e304a 100644
--- a/innobase/include/rem0rec.ic
+++ b/innobase/include/rem0rec.ic
@@ -8,9 +8,19 @@ Created 5/30/1994 Heikki Tuuri
#include "mach0data.h"
#include "ut0byte.h"
+#include "dict0dict.h"
-/* Offsets of the bit-fields in the record. NOTE! In the table the most
-significant bytes and bits are written below less significant.
+/* Compact flag ORed to the extra size returned by rec_get_offsets() */
+#define REC_OFFS_COMPACT ((ulint) 1 << 31)
+/* SQL NULL flag in offsets returned by rec_get_offsets() */
+#define REC_OFFS_SQL_NULL ((ulint) 1 << 31)
+/* External flag in offsets returned by rec_get_offsets() */
+#define REC_OFFS_EXTERNAL ((ulint) 1 << 30)
+/* Mask for offsets returned by rec_get_offsets() */
+#define REC_OFFS_MASK (REC_OFFS_EXTERNAL - 1)
+
+/* Offsets of the bit-fields in an old-style record. NOTE! In the table the
+most significant bytes and bits are written below less significant.
(1) byte offset (2) bit usage within byte
downward from
@@ -25,6 +35,25 @@ significant bytes and bits are written below less significant.
4 bits info bits
*/
+/* Offsets of the bit-fields in a new-style record. NOTE! In the table the
+most significant bytes and bits are written below less significant.
+
+ (1) byte offset (2) bit usage within byte
+ downward from
+ origin -> 1 8 bits pointer to next record (relative)
+ 2 8 bits pointer to next record (relative)
+ 3 3 bits status:
+ 000=conventional record
+ 001=node pointer record (inside B-tree)
+ 010=infimum record
+ 011=supremum record
+ 1xx=reserved
+ 5 bits heap number
+ 4 8 bits heap number
+ 5 4 bits n_owned
+ 4 bits info bits
+*/
+
/* We list the byte offsets from the origin of the record, the mask,
and the shift needed to obtain each bit-field of the record. */
@@ -32,22 +61,30 @@ and the shift needed to obtain each bit-field of the record. */
#define REC_NEXT_MASK 0xFFFFUL
#define REC_NEXT_SHIFT 0
-#define REC_SHORT 3 /* This is single byte bit-field */
-#define REC_SHORT_MASK 0x1UL
-#define REC_SHORT_SHIFT 0
+#define REC_OLD_SHORT 3 /* This is single byte bit-field */
+#define REC_OLD_SHORT_MASK 0x1UL
+#define REC_OLD_SHORT_SHIFT 0
+
+#define REC_OLD_N_FIELDS 4
+#define REC_OLD_N_FIELDS_MASK 0x7FEUL
+#define REC_OLD_N_FIELDS_SHIFT 1
-#define REC_N_FIELDS 4
-#define REC_N_FIELDS_MASK 0x7FEUL
-#define REC_N_FIELDS_SHIFT 1
+#define REC_NEW_STATUS 3 /* This is single byte bit-field */
+#define REC_NEW_STATUS_MASK 0x7UL
+#define REC_NEW_STATUS_SHIFT 0
-#define REC_HEAP_NO 5
+#define REC_OLD_HEAP_NO 5
+#define REC_NEW_HEAP_NO 4
#define REC_HEAP_NO_MASK 0xFFF8UL
#define REC_HEAP_NO_SHIFT 3
-#define REC_N_OWNED 6 /* This is single byte bit-field */
+#define REC_OLD_N_OWNED 6 /* This is single byte bit-field */
+#define REC_NEW_N_OWNED 5 /* This is single byte bit-field */
#define REC_N_OWNED_MASK 0xFUL
#define REC_N_OWNED_SHIFT 0
+#define REC_OLD_INFO_BITS 6 /* This is single byte bit-field */
+#define REC_NEW_INFO_BITS 5 /* This is single byte bit-field */
#define REC_INFO_BITS_MASK 0xF0UL
#define REC_INFO_BITS_SHIFT 0
@@ -65,26 +102,24 @@ a field stored to another page: */
#define REC_2BYTE_EXTERN_MASK 0x4000UL
-/****************************************************************
-Return field length or UNIV_SQL_NULL. */
-UNIV_INLINE
-ulint
-rec_get_nth_field_len(
-/*==================*/
- /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
- rec_t* rec, /* in: record */
- ulint n) /* in: index of the field */
-{
- ulint len;
-
- rec_get_nth_field(rec, n, &len);
-
- return(len);
-}
+#if REC_OLD_SHORT_MASK << (8 * (REC_OLD_SHORT - 3)) \
+ ^ REC_OLD_N_FIELDS_MASK << (8 * (REC_OLD_N_FIELDS - 4)) \
+ ^ REC_HEAP_NO_MASK << (8 * (REC_OLD_HEAP_NO - 4)) \
+ ^ REC_N_OWNED_MASK << (8 * (REC_OLD_N_OWNED - 3)) \
+ ^ REC_INFO_BITS_MASK << (8 * (REC_OLD_INFO_BITS - 3)) \
+ ^ 0xFFFFFFFFUL
+# error "sum of old-style masks != 0xFFFFFFFFUL"
+#endif
+#if REC_NEW_STATUS_MASK << (8 * (REC_NEW_STATUS - 3)) \
+ ^ REC_HEAP_NO_MASK << (8 * (REC_NEW_HEAP_NO - 4)) \
+ ^ REC_N_OWNED_MASK << (8 * (REC_NEW_N_OWNED - 3)) \
+ ^ REC_INFO_BITS_MASK << (8 * (REC_NEW_INFO_BITS - 3)) \
+ ^ 0xFFFFFFUL
+# error "sum of new-style masks != 0xFFFFFFUL"
+#endif
/***************************************************************
-Sets the value of the ith field SQL null bit. */
+Sets the value of the ith field SQL null bit of an old-style record. */
void
rec_set_nth_field_null_bit(
@@ -93,8 +128,8 @@ rec_set_nth_field_null_bit(
ulint i, /* in: ith field */
ibool val); /* in: value to set */
/***************************************************************
-Sets a record field to SQL null. The physical size of the field is not
-changed. */
+Sets an old-style record field to SQL null.
+The physical size of the field is not changed. */
void
rec_set_nth_field_sql_null(
@@ -102,6 +137,32 @@ rec_set_nth_field_sql_null(
rec_t* rec, /* in: record */
ulint n); /* in: index of the field */
+/***************************************************************
+Sets the value of the ith field extern storage bit of an old-style record. */
+
+void
+rec_set_nth_field_extern_bit_old(
+/*=============================*/
+ rec_t* rec, /* in: old-style record */
+ ulint i, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page where
+ rec is, or NULL; in the NULL case we do not
+ write to log about the change */
+/***************************************************************
+Sets the value of the ith field extern storage bit of a new-style record. */
+
+void
+rec_set_nth_field_extern_bit_new(
+/*=============================*/
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint ith, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
+
/**********************************************************
Gets a bit field from within 1 byte. */
UNIV_INLINE
@@ -131,7 +192,7 @@ rec_set_bit_field_1(
ulint shift) /* in: shift right applied after masking */
{
ut_ad(rec);
- ut_ad(offs <= REC_N_EXTRA_BYTES);
+ ut_ad(offs <= REC_N_OLD_EXTRA_BYTES);
ut_ad(mask);
ut_ad(mask <= 0xFFUL);
ut_ad(((mask >> shift) << shift) == mask);
@@ -171,30 +232,14 @@ rec_set_bit_field_2(
ulint shift) /* in: shift right applied after masking */
{
ut_ad(rec);
- ut_ad(offs <= REC_N_EXTRA_BYTES);
+ ut_ad(offs <= REC_N_OLD_EXTRA_BYTES);
ut_ad(mask > 0xFFUL);
ut_ad(mask <= 0xFFFFUL);
ut_ad((mask >> shift) & 1);
ut_ad(0 == ((mask >> shift) & ((mask >> shift) + 1)));
ut_ad(((mask >> shift) << shift) == mask);
ut_ad(((val << shift) & mask) == (val << shift));
-#ifdef UNIV_DEBUG
- {
- ulint m;
-
- /* The following assertion checks that the masks of currently
- defined bit-fields in bytes 3-6 do not overlap. */
- m = (ulint)((REC_SHORT_MASK << (8 * (REC_SHORT - 3)))
- + (REC_N_FIELDS_MASK << (8 * (REC_N_FIELDS - 4)))
- + (REC_HEAP_NO_MASK << (8 * (REC_HEAP_NO - 4)))
- + (REC_N_OWNED_MASK << (8 * (REC_N_OWNED - 3)))
- + (REC_INFO_BITS_MASK << (8 * (REC_INFO_BITS - 3))));
- if (m != ut_dbg_zero + 0xFFFFFFFFUL) {
- fprintf(stderr, "Sum of masks %lx\n", m);
- ut_error;
- }
- }
-#endif
+
mach_write_to_2(rec - offs,
(mach_read_from_2(rec - offs) & ~mask)
| (val << shift));
@@ -208,17 +253,26 @@ ulint
rec_get_next_offs(
/*==============*/
/* out: the page offset of the next chained record */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp) /* in: TRUE=compact page format */
{
- ulint ret;
-
- ut_ad(rec);
-
- ret = rec_get_bit_field_2(rec, REC_NEXT, REC_NEXT_MASK,
- REC_NEXT_SHIFT);
- ut_ad(ret < UNIV_PAGE_SIZE);
-
- return(ret);
+ if (comp) {
+ lint ret = (int16_t) rec_get_bit_field_2(rec, REC_NEXT,
+ REC_NEXT_MASK, REC_NEXT_SHIFT);
+#if UNIV_PAGE_SIZE <= 32768
+ /* with 64 KiB page size, the pointer will "wrap around",
+ and the following assertions are invalid */
+ ut_ad(ret + ut_align_offset(rec, UNIV_PAGE_SIZE) <
+ UNIV_PAGE_SIZE);
+#endif
+ return(ret ? ut_align_offset(rec + ret, UNIV_PAGE_SIZE) : 0);
+ }
+ else {
+ ulint ret = rec_get_bit_field_2(rec, REC_NEXT,
+ REC_NEXT_MASK, REC_NEXT_SHIFT);
+ ut_ad(ret < UNIV_PAGE_SIZE);
+ return(ret);
+ }
}
/**********************************************************
@@ -229,21 +283,32 @@ void
rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint next) /* in: offset of the next record */
{
ut_ad(rec);
ut_ad(UNIV_PAGE_SIZE > next);
- rec_set_bit_field_2(rec, next, REC_NEXT, REC_NEXT_MASK,
- REC_NEXT_SHIFT);
+ if (comp) {
+ rec_set_bit_field_2(rec, next
+ ? (next - ut_align_offset(rec, UNIV_PAGE_SIZE))
+#ifdef UNIV_DEBUG /* avoid an assertion failure */
+ & (REC_NEXT_MASK >> REC_NEXT_SHIFT)
+#endif
+ : 0, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT);
+ } else {
+ rec_set_bit_field_2(rec, next,
+ REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT);
+ }
}
/**********************************************************
-The following function is used to get the number of fields in the record. */
+The following function is used to get the number of fields
+in an old-style record. */
UNIV_INLINE
ulint
-rec_get_n_fields(
-/*=============*/
+rec_get_n_fields_old(
+/*=================*/
/* out: number of data fields */
rec_t* rec) /* in: physical record */
{
@@ -251,8 +316,8 @@ rec_get_n_fields(
ut_ad(rec);
- ret = rec_get_bit_field_2(rec, REC_N_FIELDS, REC_N_FIELDS_MASK,
- REC_N_FIELDS_SHIFT);
+ ret = rec_get_bit_field_2(rec, REC_OLD_N_FIELDS,
+ REC_OLD_N_FIELDS_MASK, REC_OLD_N_FIELDS_SHIFT);
ut_ad(ret <= REC_MAX_N_FIELDS);
ut_ad(ret > 0);
@@ -260,12 +325,12 @@ rec_get_n_fields(
}
/**********************************************************
-The following function is used to set the number of fields field in the
-record. */
+The following function is used to set the number of fields
+in an old-style record. */
UNIV_INLINE
void
-rec_set_n_fields(
-/*=============*/
+rec_set_n_fields_old(
+/*=================*/
rec_t* rec, /* in: physical record */
ulint n_fields) /* in: the number of fields */
{
@@ -273,8 +338,38 @@ rec_set_n_fields(
ut_ad(n_fields <= REC_MAX_N_FIELDS);
ut_ad(n_fields > 0);
- rec_set_bit_field_2(rec, n_fields, REC_N_FIELDS, REC_N_FIELDS_MASK,
- REC_N_FIELDS_SHIFT);
+ rec_set_bit_field_2(rec, n_fields, REC_OLD_N_FIELDS,
+ REC_OLD_N_FIELDS_MASK, REC_OLD_N_FIELDS_SHIFT);
+}
+
+/**********************************************************
+The following function is used to get the number of fields
+in a record. */
+UNIV_INLINE
+ulint
+rec_get_n_fields(
+/*=============*/
+ /* out: number of data fields */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index) /* in: record descriptor */
+{
+ ut_ad(rec);
+ ut_ad(index);
+ if (!index->table->comp) {
+ return(rec_get_n_fields_old(rec));
+ }
+ switch (rec_get_status(rec)) {
+ case REC_STATUS_ORDINARY:
+ return(dict_index_get_n_fields(index));
+ case REC_STATUS_NODE_PTR:
+ return(dict_index_get_n_unique_in_tree(index) + 1);
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ return(1);
+ default:
+ ut_error;
+ return(ULINT_UNDEFINED);
+ }
}
/**********************************************************
@@ -285,14 +380,16 @@ ulint
rec_get_n_owned(
/*============*/
/* out: number of owned records */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp) /* in: TRUE=compact page format */
{
ulint ret;
ut_ad(rec);
- ret = rec_get_bit_field_1(rec, REC_N_OWNED, REC_N_OWNED_MASK,
- REC_N_OWNED_SHIFT);
+ ret = rec_get_bit_field_1(rec,
+ comp ? REC_NEW_N_OWNED : REC_OLD_N_OWNED,
+ REC_N_OWNED_MASK, REC_N_OWNED_SHIFT);
ut_ad(ret <= REC_MAX_N_OWNED);
return(ret);
@@ -305,13 +402,15 @@ void
rec_set_n_owned(
/*============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint n_owned) /* in: the number of owned */
{
ut_ad(rec);
ut_ad(n_owned <= REC_MAX_N_OWNED);
- rec_set_bit_field_1(rec, n_owned, REC_N_OWNED, REC_N_OWNED_MASK,
- REC_N_OWNED_SHIFT);
+ rec_set_bit_field_1(rec, n_owned,
+ comp ? REC_NEW_N_OWNED : REC_OLD_N_OWNED,
+ REC_N_OWNED_MASK, REC_N_OWNED_SHIFT);
}
/**********************************************************
@@ -321,14 +420,16 @@ ulint
rec_get_info_bits(
/*==============*/
/* out: info bits */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp) /* in: TRUE=compact page format */
{
ulint ret;
ut_ad(rec);
- ret = rec_get_bit_field_1(rec, REC_INFO_BITS, REC_INFO_BITS_MASK,
- REC_INFO_BITS_SHIFT);
+ ret = rec_get_bit_field_1(rec,
+ comp ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS,
+ REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
ut_ad((ret & ~REC_INFO_BITS_MASK) == 0);
return(ret);
@@ -341,30 +442,51 @@ void
rec_set_info_bits(
/*==============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint bits) /* in: info bits */
{
ut_ad(rec);
ut_ad((bits & ~REC_INFO_BITS_MASK) == 0);
- rec_set_bit_field_1(rec, bits, REC_INFO_BITS, REC_INFO_BITS_MASK,
- REC_INFO_BITS_SHIFT);
+ rec_set_bit_field_1(rec, bits,
+ comp ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS,
+ REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
}
/**********************************************************
-Gets the value of the deleted flag in info bits. */
+The following function retrieves the status bits of a new-style record. */
UNIV_INLINE
-ibool
-rec_info_bits_get_deleted_flag(
-/*===========================*/
- /* out: TRUE if deleted flag set */
- ulint info_bits) /* in: info bits from a record */
+ulint
+rec_get_status(
+/*===========*/
+ /* out: status bits */
+ rec_t* rec) /* in: physical record */
{
- if (info_bits & REC_INFO_DELETED_FLAG) {
+ ulint ret;
- return(TRUE);
- }
+ ut_ad(rec);
- return(FALSE);
+ ret = rec_get_bit_field_1(rec, REC_NEW_STATUS,
+ REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT);
+ ut_ad((ret & ~REC_NEW_STATUS_MASK) == 0);
+
+ return(ret);
+}
+
+/**********************************************************
+The following function is used to set the status bits of a new-style record. */
+UNIV_INLINE
+void
+rec_set_status(
+/*===========*/
+ rec_t* rec, /* in: physical record */
+ ulint bits) /* in: info bits */
+{
+ ut_ad(rec);
+ ut_ad((bits & ~REC_NEW_STATUS_MASK) == 0);
+
+ rec_set_bit_field_1(rec, bits, REC_NEW_STATUS,
+ REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT);
}
/**********************************************************
@@ -374,9 +496,10 @@ ibool
rec_get_deleted_flag(
/*=================*/
/* out: TRUE if delete marked */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp) /* in: TRUE=compact page format */
{
- if (REC_INFO_DELETED_FLAG & rec_get_info_bits(rec)) {
+ if (REC_INFO_DELETED_FLAG & rec_get_info_bits(rec, comp)) {
return(TRUE);
}
@@ -391,6 +514,7 @@ void
rec_set_deleted_flag(
/*=================*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ibool flag) /* in: TRUE if delete marked */
{
ulint old_val;
@@ -399,7 +523,7 @@ rec_set_deleted_flag(
ut_ad(TRUE == 1);
ut_ad(flag <= TRUE);
- old_val = rec_get_info_bits(rec);
+ old_val = rec_get_info_bits(rec, comp);
if (flag) {
new_val = REC_INFO_DELETED_FLAG | old_val;
@@ -407,7 +531,39 @@ rec_set_deleted_flag(
new_val = ~REC_INFO_DELETED_FLAG & old_val;
}
- rec_set_info_bits(rec, new_val);
+ rec_set_info_bits(rec, comp, new_val);
+}
+
+/**********************************************************
+The following function tells if a new-style record is a node pointer. */
+UNIV_INLINE
+ibool
+rec_get_node_ptr_flag(
+/*=================*/
+ /* out: TRUE if node pointer */
+ rec_t* rec) /* in: physical record */
+{
+ return(REC_STATUS_NODE_PTR == rec_get_status(rec));
+}
+
+/**********************************************************
+The following function is used to flag a record as a node pointer. */
+UNIV_INLINE
+void
+rec_set_node_ptr_flag(
+/*=================*/
+ rec_t* rec, /* in: physical record */
+ ibool flag) /* in: TRUE if the record is a node pointer */
+{
+ ulint status;
+ ut_ad(flag <= TRUE);
+ ut_ad(REC_STATUS_NODE_PTR >= rec_get_status(rec));
+ if (flag) {
+ status = REC_STATUS_NODE_PTR;
+ } else {
+ status = REC_STATUS_ORDINARY;
+ }
+ rec_set_status(rec, status);
}
/**********************************************************
@@ -418,14 +574,16 @@ ulint
rec_get_heap_no(
/*=============*/
/* out: heap order number */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp) /* in: TRUE=compact page format */
{
ulint ret;
ut_ad(rec);
- ret = rec_get_bit_field_2(rec, REC_HEAP_NO, REC_HEAP_NO_MASK,
- REC_HEAP_NO_SHIFT);
+ ret = rec_get_bit_field_2(rec,
+ comp ? REC_NEW_HEAP_NO : REC_OLD_HEAP_NO,
+ REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT);
ut_ad(ret <= REC_MAX_HEAP_NO);
return(ret);
@@ -438,12 +596,14 @@ void
rec_set_heap_no(
/*=============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint heap_no)/* in: the heap number */
{
ut_ad(heap_no <= REC_MAX_HEAP_NO);
- rec_set_bit_field_2(rec, heap_no, REC_HEAP_NO, REC_HEAP_NO_MASK,
- REC_HEAP_NO_SHIFT);
+ rec_set_bit_field_2(rec, heap_no,
+ comp ? REC_NEW_HEAP_NO : REC_OLD_HEAP_NO,
+ REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT);
}
/**********************************************************
@@ -456,10 +616,12 @@ rec_get_1byte_offs_flag(
/* out: TRUE if 1-byte form */
rec_t* rec) /* in: physical record */
{
- ut_ad(TRUE == 1);
+#if TRUE != 1
+#error "TRUE != 1"
+#endif
- return(rec_get_bit_field_1(rec, REC_SHORT, REC_SHORT_MASK,
- REC_SHORT_SHIFT));
+ return(rec_get_bit_field_1(rec, REC_OLD_SHORT, REC_OLD_SHORT_MASK,
+ REC_OLD_SHORT_SHIFT));
}
/**********************************************************
@@ -471,11 +633,13 @@ rec_set_1byte_offs_flag(
rec_t* rec, /* in: physical record */
ibool flag) /* in: TRUE if 1byte form */
{
- ut_ad(TRUE == 1);
+#if TRUE != 1
+#error "TRUE != 1"
+#endif
ut_ad(flag <= TRUE);
- rec_set_bit_field_1(rec, flag, REC_SHORT, REC_SHORT_MASK,
- REC_SHORT_SHIFT);
+ rec_set_bit_field_1(rec, flag, REC_OLD_SHORT, REC_OLD_SHORT_MASK,
+ REC_OLD_SHORT_SHIFT);
}
/**********************************************************
@@ -492,9 +656,9 @@ rec_1_get_field_end_info(
ulint n) /* in: field index */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- return(mach_read_from_1(rec - (REC_N_EXTRA_BYTES + n + 1)));
+ return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1)));
}
/**********************************************************
@@ -511,68 +675,233 @@ rec_2_get_field_end_info(
ulint n) /* in: field index */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- return(mach_read_from_2(rec - (REC_N_EXTRA_BYTES + 2 * n + 2)));
+ return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2)));
}
-/***************************************************************
-Gets the value of the ith field extern storage bit. If it is TRUE
-it means that the field is stored on another page. */
+#ifdef UNIV_DEBUG
+# define REC_OFFS_HEADER_SIZE 3
+#else /* UNIV_DEBUG */
+# define REC_OFFS_HEADER_SIZE 1
+#endif /* UNIV_DEBUG */
+
+/* Get the base address of offsets. The extra_size is stored at
+this position, and following positions hold the end offsets of
+the fields. */
+#define rec_offs_base(offsets) (offsets + REC_OFFS_HEADER_SIZE)
+
+/****************************************************************
+Validates offsets returned by rec_get_offsets() or rec_reget_offsets(). */
UNIV_INLINE
ibool
-rec_get_nth_field_extern_bit(
-/*=========================*/
- /* in: TRUE or FALSE */
- rec_t* rec, /* in: record */
- ulint i) /* in: ith field */
+rec_offs_validate(
+/*==============*/
+ /* out: TRUE if valid */
+ rec_t* rec, /* in: record or NULL */
+ dict_index_t* index, /* in: record descriptor or NULL */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint i = rec_offs_n_fields(offsets);
+ ulint last = ULINT_MAX;
+ ibool comp = (*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0;
+ ut_a(offsets);
+ if (rec) {
+ ut_ad((ulint) rec == offsets[1]);
+ if (!comp) {
+ ut_a(rec_get_n_fields_old(rec) >= i);
+ }
+ }
+ if (index) {
+ ut_ad((ulint) index == offsets[2]);
+ ulint max_n_fields = ut_max(
+ dict_index_get_n_fields(index),
+ dict_index_get_n_unique_in_tree(index) + 1);
+ if (comp && rec) {
+ switch (rec_get_status(rec)) {
+ case REC_STATUS_ORDINARY:
+ break;
+ case REC_STATUS_NODE_PTR:
+ max_n_fields =
+ dict_index_get_n_unique_in_tree(index) + 1;
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ max_n_fields = 1;
+ break;
+ default:
+ ut_error;
+ }
+ }
+ ut_a(i <= max_n_fields);
+ }
+ while (i--) {
+ ulint curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK;
+ ut_a(curr <= last);
+ last = curr;
+ }
+ return(TRUE);
+}
+/****************************************************************
+Updates debug data in offsets, in order to avoid bogus
+rec_offs_validate() failures. */
+UNIV_INLINE
+void
+rec_offs_make_valid(
+/*================*/
+ const rec_t* rec __attribute__((unused)),
+ /* in: record */
+ const dict_index_t* index __attribute__((unused)),
+ /* in: record descriptor */
+ ulint* offsets __attribute__((unused)))
+ /* in: array returned by rec_get_offsets()
+ or rec_reget_offsets() */
{
- ulint info;
+#ifdef UNIV_DEBUG
+ offsets[1] = (ulint) rec;
+ offsets[2] = (ulint) index;
+#endif /* UNIV_DEBUG */
+}
- if (rec_get_1byte_offs_flag(rec)) {
+/****************************************************************
+The following function is used to get a pointer to the nth
+data field in an old-style record. */
+UNIV_INLINE
+byte*
+rec_get_nth_field(
+/*==============*/
+ /* out: pointer to the field */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index of the field */
+ ulint* len) /* out: length of the field; UNIV_SQL_NULL
+ if SQL null */
+{
+ byte* field;
+ ulint length;
+ ut_ad(rec);
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ ut_ad(len);
- return(FALSE);
+ if (n == 0) {
+ field = rec;
+ } else {
+ field = rec + (rec_offs_base(offsets)[n] & REC_OFFS_MASK);
}
- info = rec_2_get_field_end_info(rec, i);
+ length = rec_offs_base(offsets)[1 + n];
- if (info & REC_2BYTE_EXTERN_MASK) {
- return(TRUE);
+ if (length & REC_OFFS_SQL_NULL) {
+ field = NULL;
+ length = UNIV_SQL_NULL;
+ } else {
+ length &= REC_OFFS_MASK;
+ length -= field - rec;
}
- return(FALSE);
+ *len = length;
+ return(field);
}
/**********************************************************
-Returns TRUE if the extern bit is set in any of the fields
-of rec. */
+Determine if the offsets are for a record in the new
+compact format. */
UNIV_INLINE
ibool
-rec_contains_externally_stored_field(
-/*=================================*/
- /* out: TRUE if a field is stored externally */
- rec_t* rec) /* in: record */
+rec_offs_comp(
+/*==========*/
+ /* out: TRUE if compact format */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint n;
- ulint i;
-
- if (rec_get_1byte_offs_flag(rec)) {
-
- return(FALSE);
- }
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ return((*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0);
+}
- n = rec_get_n_fields(rec);
+/**********************************************************
+Returns TRUE if the nth field of rec is SQL NULL. */
+UNIV_INLINE
+ibool
+rec_offs_nth_null(
+/*==============*/
+ /* out: TRUE if SQL NULL */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n) /* in: nth field */
+{
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ return((rec_offs_base(offsets)[1 + n] & REC_OFFS_SQL_NULL) != 0);
+}
+/**********************************************************
+Returns TRUE if the extern bit is set in nth field of rec. */
+UNIV_INLINE
+ibool
+rec_offs_nth_extern(
+/*================*/
+ /* out: TRUE if externally stored */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n) /* in: nth field */
+{
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ return((rec_offs_base(offsets)[1 + n] & REC_OFFS_EXTERNAL) != 0);
+}
- for (i = 0; i < n; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+/**********************************************************
+Gets the physical size of a field. */
+UNIV_INLINE
+ulint
+rec_offs_nth_size(
+/*==============*/
+ /* out: length of field */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n) /* in: nth field */
+{
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ return(rec_offs_base(offsets)[1 + n] & REC_OFFS_MASK);
+}
+/**********************************************************
+Returns TRUE if the extern bit is set in any of the fields
+of an old-style record. */
+UNIV_INLINE
+ibool
+rec_offs_any_extern(
+/*================*/
+ /* out: TRUE if a field is stored externally */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint i;
+ for (i = rec_offs_n_fields(offsets); i--; ) {
+ if (rec_offs_nth_extern(offsets, i)) {
return(TRUE);
}
}
-
return(FALSE);
}
+/***************************************************************
+Sets the value of the ith field extern storage bit. */
+UNIV_INLINE
+void
+rec_set_nth_field_extern_bit(
+/*=========================*/
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint i, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr) /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
+{
+ if (index->table->comp) {
+ rec_set_nth_field_extern_bit_new(rec, index, i, val, mtr);
+ } else {
+ rec_set_nth_field_extern_bit_old(rec, i, val, mtr);
+ }
+}
+
/**********************************************************
Returns the offset of n - 1th field end if the record is stored in the 1-byte
offsets form. If the field is SQL null, the flag is ORed in the returned
@@ -589,9 +918,9 @@ rec_1_get_prev_field_end_info(
ulint n) /* in: field index */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
- return(mach_read_from_1(rec - (REC_N_EXTRA_BYTES + n)));
+ return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n)));
}
/**********************************************************
@@ -608,9 +937,9 @@ rec_2_get_prev_field_end_info(
ulint n) /* in: field index */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
- return(mach_read_from_2(rec - (REC_N_EXTRA_BYTES + 2 * n)));
+ return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n)));
}
/**********************************************************
@@ -625,9 +954,9 @@ rec_1_set_field_end_info(
ulint info) /* in: value to set */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- mach_write_to_1(rec - (REC_N_EXTRA_BYTES + n + 1), info);
+ mach_write_to_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1), info);
}
/**********************************************************
@@ -642,9 +971,9 @@ rec_2_set_field_end_info(
ulint info) /* in: value to set */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- mach_write_to_2(rec - (REC_N_EXTRA_BYTES + 2 * n + 2), info);
+ mach_write_to_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2), info);
}
/**********************************************************
@@ -659,7 +988,7 @@ rec_1_get_field_start_offs(
ulint n) /* in: field index */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
if (n == 0) {
@@ -682,7 +1011,7 @@ rec_2_get_field_start_offs(
ulint n) /* in: field index */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
if (n == 0) {
@@ -707,7 +1036,7 @@ rec_get_field_start_offs(
ulint n) /* in: field index */
{
ut_ad(rec);
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
if (n == 0) {
@@ -723,8 +1052,9 @@ rec_get_field_start_offs(
}
/****************************************************************
-Gets the physical size of a field. Also an SQL null may have a field of
-size > 0, if the data type is of a fixed size. */
+Gets the physical size of an old-style field.
+Also an SQL null may have a field of size > 0,
+if the data type is of a fixed size. */
UNIV_INLINE
ulint
rec_get_nth_field_size(
@@ -744,133 +1074,132 @@ rec_get_nth_field_size(
return(next_os - os);
}
-/****************************************************************
-The following function is used to get a copy of the nth data field in a
-record to a buffer. */
-UNIV_INLINE
-void
-rec_copy_nth_field(
-/*===============*/
- void* buf, /* in: pointer to the buffer */
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- ulint* len) /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
-{
- byte* ptr;
-
- ut_ad(buf && rec && len);
-
- ptr = rec_get_nth_field(rec, n, len);
-
- if (*len == UNIV_SQL_NULL) {
-
- return;
- }
-
- ut_memcpy(buf, ptr, *len);
-}
-
/***************************************************************
This is used to modify the value of an already existing field in a record.
The previous value must have exactly the same size as the new value. If len
-is UNIV_SQL_NULL then the field is treated as an SQL null. */
+is UNIV_SQL_NULL then the field is treated as an SQL null for old-style
+records. For new-style records, len must not be UNIV_SQL_NULL. */
UNIV_INLINE
void
rec_set_nth_field(
/*==============*/
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- void* data, /* in: pointer to the data if not SQL null */
- ulint len) /* in: length of the data or UNIV_SQL_NULL */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index number of the field */
+ const void* data, /* in: pointer to the data
+ if not SQL null */
+ ulint len) /* in: length of the data or UNIV_SQL_NULL.
+ If not SQL null, must have the same
+ length as the previous value.
+ If SQL null, previous value must be
+ SQL null. */
{
byte* data2;
ulint len2;
- ut_ad((len == UNIV_SQL_NULL)
- || (rec_get_nth_field_size(rec, n) == len));
-
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+
if (len == UNIV_SQL_NULL) {
+ ut_ad(!rec_offs_comp(offsets));
rec_set_nth_field_sql_null(rec, n);
return;
}
- data2 = rec_get_nth_field(rec, n, &len2);
+ data2 = rec_get_nth_field(rec, offsets, n, &len2);
+ ut_ad(len2 == len);
ut_memcpy(data2, data, len);
if (len2 == UNIV_SQL_NULL) {
-
+ ut_ad(!rec_offs_comp(offsets));
rec_set_nth_field_null_bit(rec, n, FALSE);
}
}
/**************************************************************
-The following function returns the data size of a physical
+The following function returns the data size of an old-style physical
record, that is the sum of field lengths. SQL null fields
are counted as length 0 fields. The value returned by the function
is the distance from record origin to record end in bytes. */
UNIV_INLINE
ulint
-rec_get_data_size(
-/*==============*/
- /* out: size */
+rec_get_data_size_old(
+/*==================*/
+ /* out: size */
rec_t* rec) /* in: physical record */
{
ut_ad(rec);
- return(rec_get_field_start_offs(rec, rec_get_n_fields(rec)));
+ return(rec_get_field_start_offs(rec, rec_get_n_fields_old(rec)));
}
/**************************************************************
-Returns the total size of record minus data size of record. The value
-returned by the function is the distance from record start to record origin
-in bytes. */
+The following function returns the number of fields in a record. */
UNIV_INLINE
ulint
-rec_get_extra_size(
+rec_offs_n_fields(
/*===============*/
- /* out: size */
- rec_t* rec) /* in: physical record */
+ /* out: number of fields */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n_fields;
-
- ut_ad(rec);
-
- n_fields = rec_get_n_fields(rec);
+ ut_ad(offsets);
+ n_fields = offsets[0];
+ ut_ad(n_fields > 0);
+ ut_ad(n_fields <= REC_MAX_N_FIELDS);
+ return(n_fields);
+}
- if (rec_get_1byte_offs_flag(rec)) {
+/**************************************************************
+The following function returns the data size of a physical
+record, that is the sum of field lengths. SQL null fields
+are counted as length 0 fields. The value returned by the function
+is the distance from record origin to record end in bytes. */
+UNIV_INLINE
+ulint
+rec_offs_data_size(
+/*===============*/
+ /* out: size */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint size;
- return(REC_N_EXTRA_BYTES + n_fields);
- }
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ size = rec_offs_base(offsets)[rec_offs_n_fields(offsets)]
+ & REC_OFFS_MASK;
+ ut_ad(size < UNIV_PAGE_SIZE);
+ return(size);
+}
- return(REC_N_EXTRA_BYTES + 2 * n_fields);
+/**************************************************************
+Returns the total size of record minus data size of record. The value
+returned by the function is the distance from record start to record origin
+in bytes. */
+UNIV_INLINE
+ulint
+rec_offs_extra_size(
+/*================*/
+ /* out: size */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint size;
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ size = *rec_offs_base(offsets) & ~REC_OFFS_COMPACT;
+ ut_ad(size < UNIV_PAGE_SIZE);
+ return(size);
}
-/**************************************************************
+/**************************************************************
Returns the total size of a physical record. */
UNIV_INLINE
ulint
-rec_get_size(
-/*=========*/
- /* out: size */
- rec_t* rec) /* in: physical record */
+rec_offs_size(
+/*==========*/
+ /* out: size */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint n_fields;
-
- ut_ad(rec);
-
- n_fields = rec_get_n_fields(rec);
-
- if (rec_get_1byte_offs_flag(rec)) {
-
- return(REC_N_EXTRA_BYTES + n_fields
- + rec_1_get_field_start_offs(rec, n_fields));
- }
-
- return(REC_N_EXTRA_BYTES + 2 * n_fields
- + rec_2_get_field_start_offs(rec, n_fields));
+ return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets));
}
/**************************************************************
@@ -879,10 +1208,11 @@ UNIV_INLINE
byte*
rec_get_end(
/*========*/
- /* out: pointer to end */
- rec_t* rec) /* in: pointer to record */
+ /* out: pointer to end */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- return(rec + rec_get_data_size(rec));
+ return(rec + rec_offs_data_size(offsets));
}
/**************************************************************
@@ -891,10 +1221,11 @@ UNIV_INLINE
byte*
rec_get_start(
/*==========*/
- /* out: pointer to start */
- rec_t* rec) /* in: pointer to record */
+ /* out: pointer to start */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- return(rec - rec_get_extra_size(rec));
+ return(rec - rec_offs_extra_size(offsets));
}
/*******************************************************************
@@ -903,18 +1234,20 @@ UNIV_INLINE
rec_t*
rec_copy(
/*=====*/
- /* out: pointer to the origin of the copied record */
- void* buf, /* in: buffer */
- rec_t* rec) /* in: physical record */
+ /* out: pointer to the origin of the copy */
+ void* buf, /* in: buffer */
+ const rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint extra_len;
ulint data_len;
ut_ad(rec && buf);
- ut_ad(rec_validate(rec));
+ ut_ad(rec_offs_validate((rec_t*) rec, NULL, offsets));
+ ut_ad(rec_validate((rec_t*) rec, offsets));
- extra_len = rec_get_extra_size(rec);
- data_len = rec_get_data_size(rec);
+ extra_len = rec_offs_extra_size(offsets);
+ data_len = rec_offs_data_size(offsets);
ut_memcpy(buf, rec - extra_len, extra_len + data_len);
@@ -922,8 +1255,8 @@ rec_copy(
}
/**************************************************************
-Returns the extra size of a physical record if we know its data size and
-the number of fields. */
+Returns the extra size of an old-style physical record if we know its
+data size and number of fields. */
UNIV_INLINE
ulint
rec_get_converted_extra_size(
@@ -934,28 +1267,51 @@ rec_get_converted_extra_size(
{
if (data_size <= REC_1BYTE_OFFS_LIMIT) {
- return(REC_N_EXTRA_BYTES + n_fields);
+ return(REC_N_OLD_EXTRA_BYTES + n_fields);
}
- return(REC_N_EXTRA_BYTES + 2 * n_fields);
+ return(REC_N_OLD_EXTRA_BYTES + 2 * n_fields);
}
/**************************************************************
The following function returns the size of a data tuple when converted to
+a new-style physical record. */
+
+ulint
+rec_get_converted_size_new(
+/*=======================*/
+ /* out: size */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple);/* in: data tuple */
+/**************************************************************
+The following function returns the size of a data tuple when converted to
a physical record. */
UNIV_INLINE
ulint
rec_get_converted_size(
/*===================*/
/* out: size */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* dtuple) /* in: data tuple */
{
ulint data_size;
ulint extra_size;
-
+
+ ut_ad(index);
ut_ad(dtuple);
ut_ad(dtuple_check_typed(dtuple));
+ ut_ad(index->type & DICT_UNIVERSAL
+ || dtuple_get_n_fields(dtuple) ==
+ (((dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK)
+ == REC_STATUS_NODE_PTR)
+ ? dict_index_get_n_unique_in_tree(index) + 1
+ : dict_index_get_n_fields(index)));
+
+ if (index->table->comp) {
+ return(rec_get_converted_size_new(index, dtuple));
+ }
+
data_size = dtuple_get_data_size(dtuple);
extra_size = rec_get_converted_extra_size(
@@ -971,12 +1327,15 @@ UNIV_INLINE
ulint
rec_fold(
/*=====*/
- /* out: the folded value */
- rec_t* rec, /* in: the physical record */
- ulint n_fields, /* in: number of complete fields to fold */
- ulint n_bytes, /* in: number of bytes to fold in an
- incomplete last field */
- dulint tree_id) /* in: index tree id */
+ /* out: the folded value */
+ rec_t* rec, /* in: the physical record */
+ const ulint* offsets, /* in: array returned by
+ rec_get_offsets() */
+ ulint n_fields, /* in: number of complete
+ fields to fold */
+ ulint n_bytes, /* in: number of bytes to fold
+ in an incomplete last field */
+ dulint tree_id) /* in: index tree id */
{
ulint i;
byte* data;
@@ -984,12 +1343,13 @@ rec_fold(
ulint fold;
ulint n_fields_rec;
- ut_ad(rec_validate(rec));
- ut_ad(n_fields <= rec_get_n_fields(rec));
- ut_ad((n_fields < rec_get_n_fields(rec)) || (n_bytes == 0));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(rec_validate((rec_t*) rec, offsets));
ut_ad(n_fields + n_bytes > 0);
-
- n_fields_rec = rec_get_n_fields(rec);
+
+ n_fields_rec = rec_offs_n_fields(offsets);
+ ut_ad(n_fields <= n_fields_rec);
+ ut_ad(n_fields < n_fields_rec || n_bytes == 0);
if (n_fields > n_fields_rec) {
n_fields = n_fields_rec;
@@ -1002,7 +1362,7 @@ rec_fold(
fold = ut_fold_dulint(tree_id);
for (i = 0; i < n_fields; i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
if (len != UNIV_SQL_NULL) {
fold = ut_fold_ulint_pair(fold,
@@ -1011,7 +1371,7 @@ rec_fold(
}
if (n_bytes > 0) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
if (len != UNIV_SQL_NULL) {
if (len > n_bytes) {
@@ -1025,19 +1385,3 @@ rec_fold(
return(fold);
}
-
-/*************************************************************
-Builds a physical record out of a data tuple and stores it beginning from
-the address destination. */
-UNIV_INLINE
-rec_t*
-rec_convert_dtuple_to_rec(
-/*======================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple) /* in: data tuple */
-{
- return(rec_convert_dtuple_to_rec_low(destination, dtuple,
- dtuple_get_data_size(dtuple)));
-}
diff --git a/innobase/include/row0row.h b/innobase/include/row0row.h
index 951e211fb37..782973d8f5d 100644
--- a/innobase/include/row0row.h
+++ b/innobase/include/row0row.h
@@ -27,7 +27,8 @@ row_get_rec_trx_id(
/*===============*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Reads the roll pointer field from a clustered index record. */
UNIV_INLINE
@@ -36,7 +37,8 @@ row_get_rec_roll_ptr(
/*=================*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Writes the trx id field to a clustered index record. */
UNIV_INLINE
@@ -45,7 +47,8 @@ row_set_rec_trx_id(
/*===============*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
- dulint trx_id); /* in: value of the field */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
+ dulint trx_id);/* in: value of the field */
/*************************************************************************
Sets the roll pointer field in a clustered index record. */
UNIV_INLINE
@@ -54,6 +57,7 @@ row_set_rec_roll_ptr(
/*=================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint roll_ptr);/* in: value of the field */
/*********************************************************************
When an insert to a table is performed, this function builds the entry which
@@ -90,6 +94,9 @@ row_build(
the buffer page of this record must be
at least s-latched and the latch held
as long as the row dtuple is used! */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index)
+ or NULL, in which case this function
+ will invoke rec_get_offsets() */
mem_heap_t* heap); /* in: memory heap from which the memory
needed is allocated */
/***********************************************************************
@@ -175,14 +182,15 @@ UNIV_INLINE
void
row_build_row_ref_fast(
/*===================*/
- dtuple_t* ref, /* in: typed data tuple where the reference
- is built */
- ulint* map, /* in: array of field numbers in rec telling
- how ref should be built from the fields of
- rec */
- rec_t* rec); /* in: record in the index; must be preserved
- while ref is used, as we do not copy field
- values to heap */
+ dtuple_t* ref, /* in: typed data tuple where the
+ reference is built */
+ const ulint* map, /* in: array of field numbers in rec
+ telling how ref should be built from
+ the fields of rec */
+ rec_t* rec, /* in: record in the index; must be
+ preserved while ref is used, as we do
+ not copy field values to heap */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Searches the clustered index record for a row, if we have the row
reference. */
diff --git a/innobase/include/row0row.ic b/innobase/include/row0row.ic
index 8e5121f5a96..85410beacf0 100644
--- a/innobase/include/row0row.ic
+++ b/innobase/include/row0row.ic
@@ -20,7 +20,8 @@ row_get_rec_sys_field(
/* out: value of the field */
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Sets the trx id or roll ptr field in a clustered index record: this function
is slower than the specialized inline functions. */
@@ -32,6 +33,7 @@ row_set_rec_sys_field(
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint val); /* in: value to set */
/*************************************************************************
@@ -42,18 +44,21 @@ row_get_rec_trx_id(
/*===============*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
return(trx_read_trx_id(rec + offset));
} else {
- return(row_get_rec_sys_field(DATA_TRX_ID, rec, index));
+ return(row_get_rec_sys_field(DATA_TRX_ID,
+ rec, index, offsets));
}
}
@@ -65,18 +70,21 @@ row_get_rec_roll_ptr(
/*=================*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN));
} else {
- return(row_get_rec_sys_field(DATA_ROLL_PTR, rec, index));
+ return(row_get_rec_sys_field(DATA_ROLL_PTR,
+ rec, index, offsets));
}
}
@@ -88,18 +96,21 @@ row_set_rec_trx_id(
/*===============*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint trx_id) /* in: value of the field */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
trx_write_trx_id(rec + offset, trx_id);
} else {
- row_set_rec_sys_field(DATA_TRX_ID, rec, index, trx_id);
+ row_set_rec_sys_field(DATA_TRX_ID,
+ rec, index, offsets, trx_id);
}
}
@@ -111,18 +122,21 @@ row_set_rec_roll_ptr(
/*=================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint roll_ptr)/* in: value of the field */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr);
} else {
- row_set_rec_sys_field(DATA_ROLL_PTR, rec, index, roll_ptr);
+ row_set_rec_sys_field(DATA_ROLL_PTR,
+ rec, index, offsets, roll_ptr);
}
}
@@ -133,14 +147,15 @@ UNIV_INLINE
void
row_build_row_ref_fast(
/*===================*/
- dtuple_t* ref, /* in: typed data tuple where the reference
- is built */
- ulint* map, /* in: array of field numbers in rec telling
- how ref should be built from the fields of
- rec */
- rec_t* rec) /* in: record in the index; must be preserved
- while ref is used, as we do not copy field
- values to heap */
+ dtuple_t* ref, /* in: typed data tuple where the
+ reference is built */
+ const ulint* map, /* in: array of field numbers in rec
+ telling how ref should be built from
+ the fields of rec */
+ rec_t* rec, /* in: record in the index; must be
+ preserved while ref is used, as we do
+ not copy field values to heap */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
dfield_t* dfield;
byte* field;
@@ -149,6 +164,7 @@ row_build_row_ref_fast(
ulint field_no;
ulint i;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
ref_len = dtuple_get_n_fields(ref);
for (i = 0; i < ref_len; i++) {
@@ -158,7 +174,8 @@ row_build_row_ref_fast(
if (field_no != ULINT_UNDEFINED) {
- field = rec_get_nth_field(rec, field_no, &len);
+ field = rec_get_nth_field(rec, offsets,
+ field_no, &len);
dfield_set_data(dfield, field, len);
}
}
diff --git a/innobase/include/row0upd.h b/innobase/include/row0upd.h
index 28210364833..673e0511153 100644
--- a/innobase/include/row0upd.h
+++ b/innobase/include/row0upd.h
@@ -80,6 +80,7 @@ row_upd_rec_sys_fields(
/*===================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
trx_t* trx, /* in: transaction */
dulint roll_ptr);/* in: roll ptr of the undo log record */
/*************************************************************************
@@ -124,8 +125,8 @@ row_upd_changes_field_size_or_external(
/* out: TRUE if the update changes the size of
some field in index or the field is external
in rec or update */
- rec_t* rec, /* in: record in index */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update);/* in: update vector */
/***************************************************************
Replaces the new column values stored in the update vector to the record
@@ -135,8 +136,9 @@ a clustered index */
void
row_upd_rec_in_place(
/*=================*/
- rec_t* rec, /* in/out: record where replaced */
- upd_t* update);/* in: update vector */
+ rec_t* rec, /* in/out: record where replaced */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update);/* in: update vector */
/*******************************************************************
Builds an update vector from those fields which in a secondary index entry
differ from a record that has the equal ordering fields. NOTE: we compare
@@ -274,10 +276,11 @@ recovery. */
void
row_upd_rec_sys_fields_in_recovery(
/*===============================*/
- rec_t* rec, /* in: record */
- ulint pos, /* in: TRX_ID position in rec */
- dulint trx_id, /* in: transaction id */
- dulint roll_ptr);/* in: roll ptr of the undo log record */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint pos, /* in: TRX_ID position in rec */
+ dulint trx_id, /* in: transaction id */
+ dulint roll_ptr);/* in: roll ptr of the undo log record */
/*************************************************************************
Parses the log data written by row_upd_index_write_log. */
diff --git a/innobase/include/row0upd.ic b/innobase/include/row0upd.ic
index a124228a0de..e2d81a39cfa 100644
--- a/innobase/include/row0upd.ic
+++ b/innobase/include/row0upd.ic
@@ -106,15 +106,17 @@ row_upd_rec_sys_fields(
/*===================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
trx_t* trx, /* in: transaction */
dulint roll_ptr)/* in: roll ptr of the undo log record */
{
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
#ifdef UNIV_SYNC_DEBUG
ut_ad(!buf_block_align(rec)->is_hashed
|| rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- row_set_rec_trx_id(rec, index, trx->id);
- row_set_rec_roll_ptr(rec, index, roll_ptr);
+ row_set_rec_trx_id(rec, index, offsets, trx->id);
+ row_set_rec_roll_ptr(rec, index, offsets, roll_ptr);
}
diff --git a/innobase/include/row0vers.h b/innobase/include/row0vers.h
index 30cf82144e9..0dd40fda65f 100644
--- a/innobase/include/row0vers.h
+++ b/innobase/include/row0vers.h
@@ -30,7 +30,8 @@ row_vers_impl_x_locked_off_kernel(
transaction; NOTE that the kernel mutex is
temporarily released! */
rec_t* rec, /* in: record in a secondary index */
- dict_index_t* index); /* in: the secondary index */
+ dict_index_t* index, /* in: the secondary index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*********************************************************************
Finds out if we must preserve a delete marked earlier version of a clustered
index record, because it is >= the purge view. */
diff --git a/innobase/include/row0vers.ic b/innobase/include/row0vers.ic
index 5ece47c35d1..ab1e264635b 100644
--- a/innobase/include/row0vers.ic
+++ b/innobase/include/row0vers.ic
@@ -11,73 +11,3 @@ Created 2/6/1997 Heikki Tuuri
#include "read0read.h"
#include "page0page.h"
#include "log0recv.h"
-
-/*************************************************************************
-Fetches the trx id of a clustered index record or version. */
-UNIV_INLINE
-dulint
-row_vers_get_trx_id(
-/*================*/
- /* out: trx id or ut_dulint_zero if the
- clustered index record not found */
- rec_t* rec, /* in: clustered index record, or an old
- version of it */
- dict_table_t* table) /* in: table */
-{
- return(row_get_rec_trx_id(rec, dict_table_get_first_index(table)));
-}
-
-/*************************************************************************
-Checks if a consistent read can be performed immediately on the index
-record, or if an older version is needed. */
-UNIV_INLINE
-ibool
-row_vers_clust_rec_sees_older(
-/*==========================*/
- /* out: FALSE if can read immediately */
- rec_t* rec, /* in: record which should be read or passed
- over by a read cursor */
- dict_index_t* index, /* in: clustered index */
- read_view_t* view) /* in: read view */
-{
- ut_ad(index->type & DICT_CLUSTERED);
-
- if (read_view_sees_trx_id(view, row_get_rec_trx_id(rec, index))) {
-
- return(FALSE);
- }
-
- return(TRUE);
-}
-
-/*************************************************************************
-Checks if a secondary index record can be read immediately by a consistent
-read, or if an older version may be needed. To be sure, we will have to
-look in the clustered index. */
-UNIV_INLINE
-ibool
-row_vers_sec_rec_may_see_older(
-/*===========================*/
- /* out: FALSE if can be read immediately */
- rec_t* rec, /* in: record which should be read or passed */
- dict_index_t* index __attribute__((unused)),/* in: secondary index */
- read_view_t* view) /* in: read view */
-{
- page_t* page;
-
- ut_ad(!(index->type & DICT_CLUSTERED));
-
- page = buf_frame_align(rec);
-
- if ((ut_dulint_cmp(page_get_max_trx_id(page), view->up_limit_id) >= 0)
- || recv_recovery_is_on()) {
-
- /* It may be that the record was inserted or modified by a
- transaction the view should not see: we have to look in the
- clustered index */
-
- return(TRUE);
- }
-
- return(FALSE);
-}
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index b9963d93265..d4cc7d8222f 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -538,6 +538,10 @@ struct srv_sys_struct{
srv_table_t* threads; /* server thread table */
UT_LIST_BASE_NODE_T(que_thr_t)
tasks; /* task queue */
+ dict_index_t* dummy_ind1; /* dummy index for old-style
+ supremum and infimum records */
+ dict_index_t* dummy_ind2; /* dummy index for new-style
+ supremum and infimum records */
};
extern ulint srv_n_threads_active[];
diff --git a/innobase/include/trx0rec.h b/innobase/include/trx0rec.h
index 9d7f41cd94e..4387ce1a61e 100644
--- a/innobase/include/trx0rec.h
+++ b/innobase/include/trx0rec.h
@@ -246,6 +246,7 @@ trx_undo_prev_version_build(
index_rec page and purge_view */
rec_t* rec, /* in: version of a clustered index record */
dict_index_t* index, /* in: clustered index */
+ ulint* offsets,/* in: rec_get_offsets(rec, index) */
mem_heap_t* heap, /* in: memory heap from which the memory
needed is allocated */
rec_t** old_vers);/* out, own: previous version, or NULL if
diff --git a/innobase/include/ut0byte.h b/innobase/include/ut0byte.h
index a62c2e2e318..22d488abeaf 100644
--- a/innobase/include/ut0byte.h
+++ b/innobase/include/ut0byte.h
@@ -208,7 +208,20 @@ ut_align_down(
/*==========*/
/* out: aligned pointer */
void* ptr, /* in: pointer */
- ulint align_no); /* in: align by this number */
+ ulint align_no) /* in: align by this number */
+ __attribute__((const));
+/*************************************************************
+The following function computes the offset of a pointer from the nearest
+aligned address. */
+UNIV_INLINE
+ulint
+ut_align_offset(
+/*==========*/
+ /* out: distance from aligned
+ pointer */
+ const void* ptr, /* in: pointer */
+ ulint align_no) /* in: align by this number */
+ __attribute__((const));
/*********************************************************************
Gets the nth bit of a ulint. */
UNIV_INLINE
diff --git a/innobase/include/ut0byte.ic b/innobase/include/ut0byte.ic
index 5a70dcf12a8..e141de3aa3f 100644
--- a/innobase/include/ut0byte.ic
+++ b/innobase/include/ut0byte.ic
@@ -335,6 +335,27 @@ ut_align_down(
return((void*)((((ulint)ptr)) & ~(align_no - 1)));
}
+/*************************************************************
+The following function computes the offset of a pointer from the nearest
+aligned address. */
+UNIV_INLINE
+ulint
+ut_align_offset(
+/*============*/
+ /* out: distance from
+ aligned pointer */
+ const void* ptr, /* in: pointer */
+ ulint align_no) /* in: align by this number */
+{
+ ut_ad(align_no > 0);
+ ut_ad(((align_no - 1) & align_no) == 0);
+ ut_ad(ptr);
+
+ ut_ad(sizeof(void*) == sizeof(ulint));
+
+ return(((ulint)ptr) & (align_no - 1));
+}
+
/*********************************************************************
Gets the nth bit of a ulint. */
UNIV_INLINE