/* Put the insert key to node list */
source_cur = static_cast<const byte*>(dfield_get_data(
dtuple_get_nth_field(tuple, 0)));
cur->coords = reserve_coords(buf_pos, SPDIMS);
len = rec_get_converted_size(cursor->index(), tuple, 0);
rec = (byte*) mem_heap_alloc(heap, len);
rec = rec_convert_dtuple_to_rec(rec, cursor->index(), tuple, 0);
cur->key = rec;
cur->key_len = static_cast<uint16_t>(len);
memcpy(cur->coords, source_cur, DATA_MBR_LEN);
return split_node_array;
}
/**********************************************************************//**
Builds a Rtree node pointer out of a physical record and a page number.
Note: For Rtree, we just keep the mbr and page no field in non-leaf level
page. It's different with Btree, Btree still keeps PK fields so far.
@return own: node pointer */
dtuple_t*
rtr_index_build_node_ptr( /*=====================*/ const dict_index_t* index, /*!< in: index */ const rtr_mbr_t* mbr, /*!< in: mbr of lower page */ const rec_t* rec, /*!< in: record for which to build node
pointer */
ulint page_no,/*!< in: page number to put in node
pointer */
mem_heap_t* heap) /*!< in: memory heap where pointer
created */
{
dtuple_t* tuple;
dfield_t* field;
byte* buf;
ulint info_bits;
/* We need to remember the child page no of cursor2, since page could be
reorganized or insert a new rec before it. */ if (cursor2) {
ut_ad(cursor2->index() == index);
rec_t* del_rec = btr_cur_get_rec(cursor2);
offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2),
index, NULL, 0,
ULINT_UNDEFINED, &heap);
del_page_no = btr_node_ptr_get_child_page_no(del_rec, offsets2);
cur2_pos = page_rec_get_n_recs_before(btr_cur_get_rec(cursor2));
}
if (rec_info & REC_INFO_MIN_REC_FLAG) { /* When the rec is minimal rec in this level, we do
in-place update for avoiding it move to other place. */
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
if (UNIV_LIKELY_NULL(page_zip)) { /* Check if there's enough space for in-place
update the zip page. */ if (!btr_cur_update_alloc_zip(
page_zip,
btr_cur_get_page_cur(cursor),
offsets,
rec_offs_size(offsets), false, mtr)) {
/* If there's not enought space for inplaceupdatezippage,wedodelete
insert. */
ins_suc = false;
/* Since btr_cur_update_alloc_zip could reorganizethepage,weneedtoreposition
cursor2. */ if (cursor2) {
cursor2->page_cur.rec =
page_rec_get_nth(page,
cur2_pos);
}
goto update_mbr;
}
/* Record could be repositioned */
rec = btr_cur_get_rec(cursor);
#ifdef UNIV_DEBUG /* Make sure it is still the first record */
rec_info = rec_get_info_bits(
rec, rec_offs_comp(offsets));
ut_ad(rec_info & REC_INFO_MIN_REC_FLAG); #endif/* UNIV_DEBUG */
memcpy(rec, node_ptr->fields[0].data, DATA_MBR_LEN);
page_zip_write_rec(block, rec, index, offsets, 0, mtr);
} else {
mtr->memcpy<mtr_t::MAYBE_NOP>(*block, rec,
node_ptr->fields[0].data,
DATA_MBR_LEN);
}
page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
offsets2, mtr);
}
} elseif (page_get_n_recs(page) == 1) { /* When there's only one rec in the page, we do insert/delete to
avoid page merge. */
} else {
update_mbr: /* When there're not only 1 rec in the page, we do delete/insert
to avoid page split. */
rec_t* insert_rec;
rec_offs* insert_offsets = NULL;
rec_t* next_rec;
/* Delete the rec which cursor point to. */
next_rec = page_rec_get_next(rec);
page_cur_delete_rec(&cursor->page_cur, offsets, mtr); if (!ins_suc) {
ut_ad(rec_info & REC_INFO_MIN_REC_FLAG);
btr_set_min_rec_mark(next_rec, *block, mtr);
}
/* If there's more than 1 rec left in the page, delete
the rec which cursor2 point to. Otherwise, delete it later.*/ if (cursor2 && page_get_n_recs(page) > 1) {
ulint cur2_rec_info;
rec_t* cur2_rec;
/* If the cursor2 position is on a wrong rec, we
need to reposition it. */
cur2_pno = btr_node_ptr_get_child_page_no(cur2_rec, offsets2); if ((del_page_no != cur2_pno)
|| (cur2_rec == insert_rec)) {
cur2_rec = page_get_infimum_rec(page);
while ((cur2_rec
= page_rec_get_next(cur2_rec))) { if (page_rec_is_supremum(cur2_rec)) { break;
}
/* Get the level of the split pages */
level = btr_page_get_level(buf_block_get_frame(block));
ut_ad(level == btr_page_get_level(buf_block_get_frame(new_block)));
page_no = block->page.id().page_no();
new_page_no = new_block->page.id().page_no();
/* Set new mbr for the old page on the upper level. */ /* Look up the index for the node pointer to page */
offsets = rtr_page_get_father_block(nullptr, heap, sea_cur, &cursor,
thr, mtr);
/* Recreate a memory heap as input parameter for btr_cur_pessimistic_insert(),becausetheheapmaybe
emptied in btr_cur_pessimistic_insert(). */
mem_heap_t* new_heap = mem_heap_create(1024);
/* Insert the recs in group 2 to new page. */ for (cur_split_node = node_array;
cur_split_node < end_split_node; ++cur_split_node) { if (cur_split_node->n_node != first_rec_group) {
lock_rec_store_on_page_infimum(
block, cur_split_node->key);
/* Update PAGE_MAX_TRX_ID on the uncompressed page. Modificationswillberedologgedandcopiedtothecompressed pageinpage_zip_compress()orpage_zip_reorganize()below. Multipletransactionscannotsimultaneouslyoperateonthe sametemp-tableinparallel. max_trx_idisignoredfortemptablesbecauseitnotrequired
for MVCC. */ if (n_core && !index->table->is_temporary()) {
page_update_max_trx_id(new_block, NULL,
page_get_max_trx_id(page),
mtr);
}
if (new_page_zip) {
mtr_set_log_mode(mtr, log_mode);
if (!page_zip_compress(new_block, index,
page_zip_level, mtr)) { if (dberr_t err =
page_zip_reorganize(new_block, index,
page_zip_level, mtr)) { if (err == DB_FAIL) {
ut_a(page_zip_decompress(new_page_zip,
new_page, FALSE));
} return err;
}
}
}
/* Update the lock table */
lock_rtr_move_rec_list(new_block, block, rec_move, moved);
/* Delete recs in second group from the old page. */ for (cur_split_node = node_array;
cur_split_node < end_split_node; ++cur_split_node) { if (cur_split_node->n_node != first_rec_group) {
page_cur_position(cur_split_node->key,
block, &page_cursor);
offsets = rec_get_offsets(
page_cur_get_rec(&page_cursor), index,
offsets, n_core, ULINT_UNDEFINED,
&heap);
page_cur_delete_rec(&page_cursor, offsets, mtr);
}
}
return DB_SUCCESS;
}
/*************************************************************//**
Splits an R-tree index page to halves and inserts the tuple. It is assumed
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
released within this function! NOTE that the operation of this
function must always succeed, we cannot reverse it: therefore enough
free disk space (2 pages) must be guaranteed to be available before this function is called.
@return inserted record */
rec_t*
rtr_page_split_and_insert( /*======================*/
ulint flags, /*!< in: undo logging and locking flags */
btr_cur_t* cursor, /*!< in/out: cursor at which to insert; when the functionreturns,thecursorispositioned
on the predecessor of the inserted record */
rec_offs** offsets,/*!< out: offsets on inserted record */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ const dtuple_t* tuple, /*!< in: tuple to insert */
ulint n_ext, /*!< in: number of externally stored columns */
mtr_t* mtr, /*!< in: mtr */
dberr_t* err, /*!< out: error code */
que_thr_t* thr) /*!< in: query thread */
{
buf_block_t* block;
page_t* page;
page_t* new_page;
buf_block_t* new_block;
page_zip_des_t* page_zip;
page_zip_des_t* new_page_zip;
page_cur_t* page_cursor;
rec_t* rec = 0;
ulint n_recs;
ulint total_data;
ulint insert_size;
rtr_split_node_t* rtr_split_node_array;
rtr_split_node_t* cur_split_node;
rtr_split_node_t* end_split_node; double* buf_pos;
node_seq_t current_ssn;
node_seq_t next_ssn;
buf_block_t* root_block;
rtr_mbr_t mbr;
rtr_mbr_t new_mbr;
lock_prdt_t prdt;
lock_prdt_t new_prdt;
rec_t* first_rec = NULL; int first_rec_group = 1;
IF_DBUG(bool iterated = false,);
/* Allocate a new page to the index */ const uint16_t page_level = btr_page_get_level(page);
new_block = btr_page_alloc(cursor->index(), page_id.page_no() + 1,
FSP_UP, page_level, mtr, mtr, err); if (UNIV_UNLIKELY(!new_block)) { return nullptr;
}
new_page_zip = buf_block_get_page_zip(new_block); if (page_level && UNIV_LIKELY_NULL(new_page_zip)) { /* ROW_FORMAT=COMPRESSED non-leaf pages are not expected
to contain FIL_NULL in FIL_PAGE_PREV at this stage. */
memset_aligned<4>(new_block->page.frame + FIL_PAGE_PREV, 0, 4);
}
btr_page_create(new_block, new_page_zip, cursor->index(),
page_level, mtr);
/* Set new ssn to the new page and page. */
page_set_ssn_id(new_block, new_page_zip, current_ssn, mtr);
next_ssn = rtr_get_new_ssn_id(cursor->index());
page_set_ssn_id(block, page_zip, next_ssn, mtr);
/* Keep recs in first group to the old page, move recs in second
groups to the new page. */ if (0 #ifdef UNIV_ZIP_COPY
|| page_zip #endif
|| (*err = rtr_split_page_move_rec_list(rtr_split_node_array,
first_rec_group,
new_block, block,
first_rec, cursor->index(),
*heap, mtr))) { if (*err != DB_FAIL) { return nullptr;
}
*err = DB_SUCCESS;
ulint n = 0;
rec_t* rec;
ulint moved = 0;
ulint max_to_move = 0;
rtr_rec_move_t* rec_move = NULL;
ulint pos;
/* For some reason, compressing new_page failed, eventhoughitshouldcontainfewerrecordsthan theoriginalpage.Copythepagebyteforbyte andthendeletetherecordsfrombothpages
as appropriate. Deleting will always succeed. */
ut_a(new_page_zip);
/* Delete recs in first group from the new page. */ for (cur_split_node = rtr_split_node_array;
cur_split_node < end_split_node - 1; ++cur_split_node) { if (cur_split_node->n_node == first_rec_group) {
ulint pos;
/* It's possible that the new record is too big to be inserted into thepage,andit'llneedthesecondroundsplitinthiscase.
We test this scenario here*/
DBUG_EXECUTE_IF("rtr_page_need_second_split", if (!iterated) {
rec = NULL; goto after_insert; }
);
/* If insert did not fit, try page reorganization. Forcompressedpages,page_cur_tuple_insert()willhave
attempted this already. */ if (rec == NULL) { if (!is_page_cur_get_page_zip(page_cursor)
&& !btr_page_reorganize(page_cursor, mtr)) {
rec = page_cur_tuple_insert(page_cursor, tuple,
offsets,
heap, n_ext, mtr);
} /* If insert fail, we will try to split the block again. */
}
#ifdef UNIV_DEBUG
after_insert: #endif /* Calculate the mbr on the upper half-page, and the mbr on
original page. */
rtr_page_cal_mbr(cursor->index(), block, &mbr, *heap);
rtr_page_cal_mbr(cursor->index(), new_block, &new_mbr, *heap);
prdt.data = &mbr;
new_prdt.data = &new_mbr;
/* Check any predicate locks need to be moved/copied to the
new page */
lock_prdt_update_split(new_block, &prdt, &new_prdt, page_id);
/* If the new res insert fail, we need to do another split
again. */ if (!rec) { /* We need to clean the parent path here and search father nodelater,otherwise,it'spossiblethatfindawrong
parent. */
rtr_clean_rtr_info(cursor->rtr_info, true);
cursor->rtr_info = NULL;
IF_DBUG(iterated=true,);
/*************************************************************//**
Makes tree one level higher by splitting the root, and inserts the tuple.
NOTE that the operation of this function must always succeed,
we cannot reverse it: therefore enough free disk space must be
guaranteed to be available before this function is called.
@return inserted record */
rec_t*
rtr_root_raise_and_insert( /*======================*/
ulint flags, /*!< in: undo logging and locking flags */
btr_cur_t* cursor, /*!< in: cursor at which to insert: must be ontherootpage;whenthefunctionreturns, thecursorispositionedonthepredecessor
of the inserted record */
rec_offs** offsets,/*!< out: offsets on inserted record */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ const dtuple_t* tuple, /*!< in: tuple to insert */
ulint n_ext, /*!< in: number of externally stored columns */
mtr_t* mtr, /*!< in: mtr */
dberr_t* err, /*!< out: error code */
que_thr_t* thr) /*!< in: query thread */
{
dict_index_t* index;
rec_t* rec;
dtuple_t* node_ptr;
ulint level;
rec_t* node_ptr_rec;
page_cur_t* page_cursor;
page_zip_des_t* root_page_zip;
page_zip_des_t* new_page_zip;
buf_block_t* root;
buf_block_t* new_block;
/* Allocate a new page to the tree. Root splitting is done by first movingtherootrecordstothenewpage,emptyingtheroot,putting
a node pointer to the new page, and then splitting the new page. */
/* Copy the page byte for byte. */
page_zip_copy_recs(new_block, root_page_zip,
root->page.frame, index, mtr);
/* Update the lock table and possible hash index. */ if (index->has_locking()) {
lock_move_rec_list_end(
new_block, root,
page_get_infimum_rec(root->page.frame));
}
/* Move any existing predicate locks */
lock_prdt_rec_move(new_block, root_id);
}
constexpr uint16_t max_trx_id = PAGE_HEADER + PAGE_MAX_TRX_ID; if (!index->is_primary()) { /* In secondary indexes, PAGE_MAX_TRX_IDcanberesetontherootpage,because thefieldonlymattersonleafpages,andtherootno longerisaleafpage.(OlderversionsofInnoDBdid
set PAGE_MAX_TRX_ID on all secondary index pages.) */
byte* p = my_assume_aligned<8>(
PAGE_HEADER + PAGE_MAX_TRX_ID + root->page.frame); if (mach_read_from_8(p)) {
mtr->memset(root, max_trx_id, 8, 0); if (UNIV_LIKELY_NULL(root->page.zip.data)) {
memset_aligned<8>(max_trx_id
+ root->page.zip.data, 0, 8);
}
}
} else { /* PAGE_ROOT_AUTO_INC is only present in the clustered index rootpage;onotherclusteredindexpages,wewanttoreserve
the field PAGE_MAX_TRX_ID for future use. */
byte* p = my_assume_aligned<8>(
PAGE_HEADER + PAGE_MAX_TRX_ID + new_block->page.frame); if (mach_read_from_8(p)) {
mtr->memset(new_block, max_trx_id, 8, 0); if (UNIV_LIKELY_NULL(new_block->page.zip.data)) {
memset_aligned<8>(max_trx_id
+ new_block->page.zip.data, 0, 8);
}
}
}
/* If this is a pessimistic insert which is actually done to performapessimisticupdatethenwehavestoredthelock informationoftherecordtobeinsertedontheinfimumofthe
root page: we cannot discard the lock structs on the root page */
if (index->has_locking()) {
lock_update_root_raise(*new_block, root_id);
}
/* Create a memory heap where the node pointer is stored */ if (!*heap) {
*heap = mem_heap_create(1000);
}
const uint32_t new_page_no = new_block->page.id().page_no();
rec = page_rec_get_next(page_get_infimum_rec(new_block->page.frame));
ut_ad(rec); /* We just created the page. */
/* Build the node pointer (= node key and page address) for the
child */
rtr_mbr_t new_mbr;
rtr_page_cal_mbr(index, new_block, &new_mbr, *heap);
node_ptr = rtr_index_build_node_ptr(index, &new_mbr, rec, new_page_no,
*heap); /* The node pointer must be marked as the predefined minimum record, asthereisnoloweralphabeticallimittorecordsintheleftmost
node of a level: */
dtuple_set_info_bits(node_ptr,
dtuple_get_info_bits(node_ptr)
| REC_INFO_MIN_REC_FLAG);
/* Rebuild the root page to get free space */
btr_page_empty(root, root_page_zip, index, level + 1, mtr);
ut_ad(!page_has_siblings(root->page.frame));
/* Split the child and insert tuple */ return rtr_page_split_and_insert(flags, cursor, offsets, heap,
tuple, n_ext, mtr, err, thr);
}
/****************************************************************//**
Following the right link to find the proper block for insert.
@return the proper block.*/
dberr_t
rtr_ins_enlarge_mbr( /*================*/
btr_cur_t* btr_cur, /*!< in: btr cursor */
mtr_t* mtr) /*!< in: mtr */
{
dberr_t err = DB_SUCCESS;
rtr_mbr_t new_mbr;
buf_block_t* block;
mem_heap_t* heap;
page_cur_t* page_cursor;
rec_offs* offsets;
node_visit_t* node_visit;
btr_cur_t cursor;
page_t* page;
ut_ad(btr_cur->index()->is_spatial());
/* If no rtr_info or rtree is one level tree, return. */ if (!btr_cur->rtr_info || btr_cur->tree_height == 1) { return(err);
}
/* Check path info is not empty. */
ut_ad(!btr_cur->rtr_info->parent_path->empty());
ut_ad(btr_cur->rtr_info->thr || !btr_cur->index()->is_committed()
|| btr_cur->index()->table->name.is_temporary());
/* Create a memory heap. */
heap = mem_heap_create(1024);
/* Leaf level page is stored in cursor */
page_cursor = btr_cur_get_page_cur(btr_cur);
block = page_cur_get_block(page_cursor);
for (ulint i = 1; i < btr_cur->tree_height; i++) {
node_visit = rtr_get_parent_node(btr_cur, i, true);
ut_ad(node_visit != NULL);
/* If there's no mbr enlarge, return.*/ if (node_visit->mbr_inc == 0) {
block = btr_pcur_get_block(node_visit->cursor); continue;
}
/* Calculate the mbr of the child page. */
rtr_page_cal_mbr(page_cursor->index, block, &new_mbr, heap);
/* Get father block. */
cursor.page_cur.index = page_cursor->index;
cursor.page_cur.block = block;
offsets = rtr_page_get_father_block(
nullptr, heap, btr_cur, &cursor,
btr_cur->rtr_info->thr, mtr);
page = buf_block_get_frame(block);
/* Update the mbr field of the rec. */
rtr_update_mbr_field(&cursor, offsets, NULL, page,
&new_mbr, NULL, mtr);
block = btr_cur_get_block(&cursor);
}
mem_heap_free(heap);
return(err);
}
/*************************************************************//**
Copy recs from a page to new_block of rtree.
@return error code */
dberr_t
rtr_page_copy_rec_list_end_no_locks( /*================================*/
buf_block_t* new_block, /*!< in: index page to copy to */
buf_block_t* block, /*!< in: index page of rec */
rec_t* rec, /*!< in: record on page */
dict_index_t* index, /*!< in: record descriptor */
mem_heap_t* heap, /*!< in/out: heap memory */
rtr_rec_move_t* rec_move, /*!< in: recording records moved */
ulint max_move, /*!< in: num of rec to move */
ulint* num_moved, /*!< out: num of rec to move */
mtr_t* mtr) /*!< in: mtr */
{
page_t* new_page = buf_block_get_frame(new_block);
page_cur_t page_cur;
page_cur_t cur1;
rec_t* cur_rec;
rec_offs offsets_1[REC_OFFS_NORMAL_SIZE];
rec_offs* offsets1 = offsets_1;
rec_offs offsets_2[REC_OFFS_NORMAL_SIZE];
rec_offs* offsets2 = offsets_2;
ulint moved = 0; const ulint n_core = page_is_leaf(new_page)
? index->n_core_fields : 0;
/* Copy records from the original page to the new page */ while (!page_cur_is_after_last(&cur1)) {
rec_t* cur1_rec = page_cur_get_rec(&cur1);
rec_t* ins_rec;
if (page_rec_is_infimum(cur_rec)) {
cur_rec = page_rec_get_next(cur_rec); if (UNIV_UNLIKELY(!cur_rec)) { return DB_CORRUPTION;
}
}
offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core,
ULINT_UNDEFINED, &heap); while (!page_rec_is_supremum(cur_rec)) {
ulint cur_matched_fields = 0; int cmp;
offsets2 = rec_get_offsets(cur_rec, index, offsets2,
n_core,
ULINT_UNDEFINED, &heap);
cmp = cmp_rec_rec(cur1_rec, cur_rec,
offsets1, offsets2, index, false,
&cur_matched_fields); if (cmp < 0) { goto move_to_prev;
} elseif (cmp > 0) { /* Skip small recs. */
cur_rec = page_cur_move_to_next(&page_cur);
} elseif (n_core) { if (rec_get_deleted_flag(cur1_rec,
dict_table_is_comp(index->table))) { goto next;
} else { /* We have two identical leaf records, skipcopyingtheundeletedone,and
unmark deleted on the current page */
btr_rec_set_deleted<false>(
new_block, cur_rec, mtr); goto next;
}
}
}
/* If position is on suprenum rec, need to move to
previous rec. */ if (page_rec_is_supremum(cur_rec)) {
move_to_prev:
cur_rec = page_cur_move_to_prev(&page_cur);
} else {
cur_rec = page_cur_get_rec(&page_cur);
}
if (UNIV_UNLIKELY(!cur_rec)) { return DB_CORRUPTION;
}
while (!page_rec_is_supremum(cur_rec)) {
ulint cur_matched_fields = 0;
offsets2 = rec_get_offsets(cur_rec, index, offsets2,
n_core,
ULINT_UNDEFINED, &heap); int cmp = cmp_rec_rec(cur1_rec, cur_rec,
offsets1, offsets2, index, false,
&cur_matched_fields); if (cmp < 0) { goto move_to_prev;
} elseif (cmp > 0) { /* Skip small recs. */
cur_rec = page_cur_move_to_next(&page_cur);
} elseif (n_core) { if (rec_get_deleted_flag(
cur1_rec,
dict_table_is_comp(index->table))) { goto next;
} else { /* We have two identical leaf records, skipcopyingtheundeletedone,and
unmark deleted on the current page */
btr_rec_set_deleted<false>(
new_block, cur_rec, mtr); goto next;
}
}
}
/* If position is on suprenum rec, need to move to
previous rec. */ if (page_rec_is_supremum(cur_rec)) {
move_to_prev:
cur_rec = page_cur_move_to_prev(&page_cur);
} else {
cur_rec = page_cur_get_rec(&page_cur);
}
if (UNIV_UNLIKELY(!cur_rec)) { return DB_CORRUPTION;
}
if (!compressed) {
btr_cur_compress_if_useful(cursor, FALSE, mtr);
}
}
/**************************************************************//**
Check whether a Rtree page is child of a parent page
@returntrueif there is child/parent relationship */ bool
rtr_check_same_block( /*================*/
dict_index_t* index, /*!< in: index tree */
btr_cur_t* cursor, /*!< in/out: position at the parent entry
pointing to the child if successful */
buf_block_t* parentb,/*!< in: parent page to check */
mem_heap_t* heap) /*!< in: memory heap */
/*************************************************************//**
Calculates MBR_AREA(a+b) - MBR_AREA(a)
Note: when 'a'and'b' objects are far from each other,
the area increase can be really big, so this function
can return'inf' as a result. Return the area increased. */ staticdouble
rtree_area_increase( const uchar* a, /*!< in: original mbr. */ const uchar* b, /*!< in: new mbr. */ double* ab_area) /*!< out: increased area. */
{ double a_area = 1.0; double loc_ab_area = 1.0; double amin, amax, bmin, bmax; double data_round = 1.0;
/* Value of amax or bmin can be so large that small difference areignored.Forexample:3.2884281489988079e+284-100= 3.2884281489988079e+284.Thisresultssomeareadifference
are not detected */ if (loc_ab_area == a_area) { if (bmin < amin || bmax > amax) {
data_round *= ((double)std::max(amax, bmax)
- amax
+ (amin - (double)std::min(
amin, bmin)));
} else {
data_round *= area;
}
}
}
if (amin > amax) { return(0);
} else {
area *= (amax - amin);
}
}
return(area);
}
/****************************************************************//**
Calculate the area increased for a new record
@return area increased */ double
rtr_rec_cal_increase( /*=================*/ const dtuple_t* dtuple, /*!< in: data tuple to insert, which
cause area increase */ const rec_t* rec, /*!< in: physical record which differs from dtupleinsomeofthecommonfields,orwhich hasanequalnumberormorefieldsthan
dtuple */ double* area) /*!< out: increased area */
{ const dfield_t* dtuple_field;
/** Estimates the number of rows in a given area. @param[in,out]trxtransaction @param[in]indexindex @param[in]tuplerangetuplecontainingmbr,mayalsobeemptytuple @param[in]modesearchmode
@return estimated number of rows */
ha_rows
rtr_estimate_n_rows_in_range(
trx_t* trx,
dict_index_t* index, const dtuple_t* tuple,
page_cur_mode_t mode)
{
ut_ad(dict_index_is_spatial(index));
switch (mode) { case PAGE_CUR_DISJOINT: case PAGE_CUR_CONTAIN: case PAGE_CUR_INTERSECT: case PAGE_CUR_WITHIN: case PAGE_CUR_MBR_EQUAL: break; default: return(HA_POS_ERROR);
}
if (rec_area == 0) { switch (mode) { case PAGE_CUR_CONTAIN: case PAGE_CUR_INTERSECT:
area += 1; break;
case PAGE_CUR_DISJOINT: break;
case PAGE_CUR_WITHIN: case PAGE_CUR_MBR_EQUAL: if (!rtree_key_cmp(
PAGE_CUR_WITHIN, range_mbr_ptr,
rec)) {
area += 1;
}
break;
default:
ut_error;
}
} else { switch (mode) { case PAGE_CUR_CONTAIN: case PAGE_CUR_INTERSECT:
area += rtree_area_overlapping(
range_mbr_ptr, rec)
/ rec_area; break;
case PAGE_CUR_DISJOINT:
area += 1;
area -= rtree_area_overlapping(
range_mbr_ptr, rec)
/ rec_area; break;
case PAGE_CUR_WITHIN: case PAGE_CUR_MBR_EQUAL: if (!rtree_key_cmp(
PAGE_CUR_WITHIN, range_mbr_ptr,
rec)) {
area += range_area / rec_area;
}
break; default:
ut_error;
}
}
}
mtr.commit();
if (!std::isfinite(area)) { return(HA_POS_ERROR);
}
area /= n_recs; return ha_rows(static_cast<double>(dict_table_get_n_rows(index->table))
* area);
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.32Bemerkung:
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.