16 #include "myisamdef.h" 
   18 #ifdef HAVE_RTREE_KEYS 
   24 #define REINSERT_BUFFER_INC 10 
   28 typedef struct st_page_level
 
   34 typedef struct st_page_list
 
   54 static int rtree_find_req(
MI_INFO *info, 
MI_KEYDEF *keyinfo, uint search_flag,
 
   55                           uint nod_cmp_flag, my_off_t 
page, 
int level)
 
   63   uint *saved_key = (uint*) (info->rtree_recursion_state) + 
level;
 
   65   if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
 
   67     my_errno = HA_ERR_OUT_OF_MEM;
 
   70   if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
 
   72   nod_flag = mi_test_if_nod(page_buf);
 
   74   k_len = keyinfo->keylength - info->s->base.rec_reflength;
 
   76   if(info->rtree_recursion_depth >= level)
 
   78     k = page_buf + *saved_key;
 
   82     k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
 
   84   last = rt_PAGE_END(page_buf);
 
   86   for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag))
 
   91       if (!(res = rtree_key_cmp(keyinfo->seg, info->first_mbr_key, k, 
 
   92                             info->last_rkey_length, nod_cmp_flag)))
 
   94         switch ((res = rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag,
 
   95                                       _mi_kpos(nod_flag, k), level + 1)))
 
   98             *saved_key = (uint) (k - page_buf);
 
  101             info->rtree_recursion_depth = 
level;
 
  112       if (!rtree_key_cmp(keyinfo->seg, info->first_mbr_key, k, 
 
  113                          info->last_rkey_length, search_flag))
 
  115         uchar *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
 
  116         info->lastpos = _mi_dpos(info, 0, after_key);
 
  117         info->lastkey_length = k_len + info->s->base.rec_reflength;
 
  118         memcpy(info->lastkey, k, info->lastkey_length);
 
  119         info->rtree_recursion_depth = 
level;
 
  120         *saved_key = (uint) (last - page_buf);
 
  122         if (after_key < last)
 
  124           info->int_keypos = info->buff;
 
  125           info->int_maxpos = info->buff + (last - after_key);
 
  126           memcpy(info->buff, after_key, last - after_key);
 
  139   info->lastpos = HA_OFFSET_ERROR;
 
  140   my_errno = HA_ERR_KEY_NOT_FOUND;
 
  144   my_afree((uchar*)page_buf);
 
  148   my_afree((uchar*)page_buf);
 
  149   info->lastpos = HA_OFFSET_ERROR;
 
  171 int rtree_find_first(
MI_INFO *info, uint keynr, uchar *key, uint key_length, 
 
  176   MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
 
  178   if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
 
  180     my_errno= HA_ERR_END_OF_FILE;
 
  189   memcpy(info->first_mbr_key, key, keyinfo->keylength);
 
  190   info->last_rkey_length = key_length;
 
  192   info->rtree_recursion_depth = -1;
 
  195   nod_cmp_flag = ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? 
 
  196         MBR_WITHIN : MBR_INTERSECT);
 
  197   return rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0);
 
  216 int rtree_find_next(
MI_INFO *info, uint keynr, uint search_flag)
 
  220   MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
 
  222   if (info->update & HA_STATE_DELETED)
 
  223     return rtree_find_first(info, keynr, info->lastkey, info->lastkey_length,
 
  226   if (!info->buff_used)
 
  228     uchar *key= info->int_keypos;
 
  230     while (key < info->int_maxpos)
 
  232       if (!rtree_key_cmp(keyinfo->seg, info->first_mbr_key, key, 
 
  233                          info->last_rkey_length, search_flag))
 
  235         uchar *after_key = key + keyinfo->keylength;
 
  237         info->lastpos= _mi_dpos(info, 0, after_key);
 
  238         memcpy(info->lastkey, key, info->lastkey_length);
 
  240         if (after_key < info->int_maxpos)
 
  241           info->int_keypos= after_key;
 
  246       key+= keyinfo->keylength;
 
  249   if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
 
  251     my_errno= HA_ERR_END_OF_FILE;
 
  255   nod_cmp_flag = ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? 
 
  256         MBR_WITHIN : MBR_INTERSECT);
 
  257   return rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0);
 
  273 static int rtree_get_req(
MI_INFO *info, 
MI_KEYDEF *keyinfo, uint key_length, 
 
  274                          my_off_t page, 
int level)
 
  282   uint *saved_key = (uint*) (info->rtree_recursion_state) + 
level;
 
  284   if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
 
  286   if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
 
  288   nod_flag = mi_test_if_nod(page_buf);
 
  290   k_len = keyinfo->keylength - info->s->base.rec_reflength;
 
  292   if(info->rtree_recursion_depth >= level)
 
  294     k = page_buf + *saved_key;
 
  299       k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
 
  304     k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
 
  306   last = rt_PAGE_END(page_buf);
 
  308   for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag))
 
  313       switch ((res = rtree_get_req(info, keyinfo, key_length, 
 
  314                                   _mi_kpos(nod_flag, k), level + 1)))
 
  317           *saved_key = (uint) (k - page_buf);
 
  320           info->rtree_recursion_depth = 
level;
 
  330       uchar *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
 
  331       info->lastpos = _mi_dpos(info, 0, after_key);
 
  332       info->lastkey_length = k_len + info->s->base.rec_reflength;
 
  333       memcpy(info->lastkey, k, info->lastkey_length);
 
  335       info->rtree_recursion_depth = 
level;
 
  336       *saved_key = (uint) (k - page_buf);
 
  338       if (after_key < last)
 
  340         info->int_keypos = (uchar*)saved_key;
 
  341         memcpy(info->buff, page_buf, keyinfo->block_length);
 
  342         info->int_maxpos = rt_PAGE_END(info->buff);
 
  354   info->lastpos = HA_OFFSET_ERROR;
 
  355   my_errno = HA_ERR_KEY_NOT_FOUND;
 
  359   my_afree((uchar*)page_buf);
 
  363   my_afree((uchar*)page_buf);
 
  364   info->lastpos = HA_OFFSET_ERROR;
 
  378 int rtree_get_first(
MI_INFO *info, uint keynr, uint key_length)
 
  381   MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
 
  383   if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
 
  385     my_errno= HA_ERR_END_OF_FILE;
 
  389   info->rtree_recursion_depth = -1;
 
  392   return rtree_get_req(info, keyinfo, key_length, root, 0);
 
  405 int rtree_get_next(
MI_INFO *info, uint keynr, uint key_length)
 
  407   my_off_t root= info->s->state.key_root[keynr];
 
  408   MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
 
  410   if (root == HA_OFFSET_ERROR)
 
  412     my_errno= HA_ERR_END_OF_FILE;
 
  416   if (!info->buff_used && !info->page_changed)
 
  418     uint k_len = keyinfo->keylength - info->s->base.rec_reflength;
 
  420     uchar *key = info->buff + *(
int*)info->int_keypos + k_len + 
 
  421                  info->s->base.rec_reflength;
 
  423     uchar *after_key = key + k_len + info->s->base.rec_reflength; 
 
  425     info->lastpos = _mi_dpos(info, 0, after_key);
 
  426     info->lastkey_length = k_len + info->s->base.rec_reflength;
 
  427     memcpy(info->lastkey, key, k_len + info->s->base.rec_reflength);
 
  429     *(uint*)info->int_keypos = (uint) (key - info->buff);
 
  430     if (after_key >= info->int_maxpos)
 
  438   return rtree_get_req(info, keyinfo, key_length, root, 0);
 
  446 #ifdef PICK_BY_PERIMETER 
  448                              uint key_length, uchar *page_buf, uint nod_flag)
 
  451   double best_incr = DBL_MAX;
 
  453   double best_perimeter;
 
  455   uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
 
  456   uchar *last = rt_PAGE_END(page_buf);
 
  458   LINT_INIT(best_perimeter);
 
  461   for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
 
  463     if ((increase = rtree_perimeter_increase(keyinfo->seg, k, key, key_length,
 
  466     if ((increase < best_incr)||
 
  467         (increase == best_incr && perimeter < best_perimeter))
 
  470       best_perimeter= perimeter;
 
  471       best_incr = increase;
 
  481                              uint key_length, uchar *page_buf, uint nod_flag)
 
  484   double UNINIT_VAR(best_incr);
 
  486   double UNINIT_VAR(best_area);
 
  487   uchar *best_key= NULL;
 
  488   uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
 
  489   uchar *last = rt_PAGE_END(page_buf);
 
  491   for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
 
  494     if ((increase = rtree_area_increase(keyinfo->seg, k, key, key_length, 
 
  498     if (!best_key || increase < best_incr ||
 
  499         ((increase == best_incr) && (area < best_area)))
 
  503       best_incr = increase;
 
  521                             uint key_length, my_off_t page, my_off_t *new_page, 
 
  522                             int ins_level, 
int level)
 
  528   DBUG_ENTER(
"rtree_insert_req");
 
  530   if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length + 
 
  533     my_errno = HA_ERR_OUT_OF_MEM;
 
  536   if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
 
  538   nod_flag = mi_test_if_nod(page_buf);
 
  539   DBUG_PRINT(
"rtree", (
"page: %lu  level: %d  ins_level: %d  nod_flag: %u",
 
  540                        (ulong) page, level, ins_level, nod_flag));
 
  542   if ((ins_level == -1 && nod_flag) ||       
 
  543       (ins_level > -1 && ins_level > level)) 
 
  545     if ((k = rtree_pick_key(info, keyinfo, key, key_length, page_buf, 
 
  548     switch ((res = rtree_insert_req(info, keyinfo, key, key_length, 
 
  549                      _mi_kpos(nod_flag, k), new_page, ins_level, level + 1)))
 
  553         rtree_combine_rect(keyinfo->seg, k, key, k, key_length);
 
  554         if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
 
  560         uchar *new_key = page_buf + keyinfo->block_length + nod_flag;
 
  562         if (rtree_set_key_mbr(info, keyinfo, k, key_length, 
 
  563                             _mi_kpos(nod_flag, k)))
 
  566         _mi_kpointer(info, new_key - nod_flag, *new_page);
 
  567         if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, *new_page))
 
  569         res = rtree_add_key(info, keyinfo, new_key, key_length, 
 
  571         if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
 
  584     res = rtree_add_key(info, keyinfo, key, key_length, page_buf, new_page);
 
  585     if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
 
  591   my_afree((uchar*)page_buf);
 
  595   my_afree((uchar*)page_buf);
 
  609 static int rtree_insert_level(
MI_INFO *info, uint keynr, uchar *key, 
 
  610                              uint key_length, 
int ins_level)
 
  613   MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
 
  616   DBUG_ENTER(
"rtree_insert_level");
 
  618   if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
 
  620     if ((old_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
 
  623     mi_putint(info->buff, 2, 0);
 
  624     res = rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL);
 
  625     if (_mi_write_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, info->buff))
 
  627     info->s->state.key_root[keynr] = old_root;
 
  631   switch ((res = rtree_insert_req(info, keyinfo, key, key_length, 
 
  632                                   old_root, &new_page, ins_level, 0)))
 
  640       uchar *new_root_buf= info->buff + info->s->base.max_key_block_length;
 
  643       uint nod_flag = info->s->base.key_reflength;
 
  645       DBUG_PRINT(
"rtree", (
"root was split, grow a new root"));
 
  647       mi_putint(new_root_buf, 2, nod_flag);
 
  648       if ((new_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) ==
 
  652       new_key = new_root_buf + keyinfo->block_length + nod_flag;
 
  654       _mi_kpointer(info, new_key - nod_flag, old_root);
 
  655       if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, old_root))
 
  657       if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL) 
 
  660       _mi_kpointer(info, new_key - nod_flag, new_page);
 
  661       if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, new_page))
 
  663       if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL) 
 
  666       if (_mi_write_keypage(info, keyinfo, new_root,
 
  667                             DFLT_INIT_HITS, new_root_buf))
 
  669       info->s->state.key_root[keynr] = new_root;
 
  670       DBUG_PRINT(
"rtree", (
"new root page: %lu  level: %d  nod_flag: %u",
 
  671                            (ulong) new_root, 0, mi_test_if_nod(new_root_buf)));
 
  695 int rtree_insert(
MI_INFO *info, uint keynr, uchar *key, uint key_length)
 
  697   DBUG_ENTER(
"rtree_insert");
 
  698   DBUG_RETURN((!key_length ||
 
  699                (rtree_insert_level(info, keynr, key, key_length, -1) == -1)) ?
 
  712 static int rtree_fill_reinsert_list(stPageList *ReinsertList, my_off_t page, 
 
  715   DBUG_ENTER(
"rtree_fill_reinsert_list");
 
  716   DBUG_PRINT(
"rtree", (
"page: %lu  level: %d", (ulong) page, level));
 
  717   if (ReinsertList->n_pages == ReinsertList->m_pages)
 
  719     ReinsertList->m_pages += REINSERT_BUFFER_INC;
 
  720     if (!(ReinsertList->pages = (stPageLevel*)my_realloc((uchar*)ReinsertList->pages, 
 
  721       ReinsertList->m_pages * 
sizeof(stPageLevel), MYF(MY_ALLOW_ZERO_PTR))))
 
  725   ReinsertList->pages[ReinsertList->n_pages].offs = 
page;
 
  726   ReinsertList->pages[ReinsertList->n_pages].level = 
level;
 
  727   ReinsertList->n_pages++;
 
  746                            uint key_length, my_off_t page, uint *page_size, 
 
  747                            stPageList *ReinsertList, 
int level)
 
  755   DBUG_ENTER(
"rtree_delete_req");
 
  757   if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
 
  759     my_errno = HA_ERR_OUT_OF_MEM;
 
  762   if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
 
  764   nod_flag = mi_test_if_nod(page_buf);
 
  765   DBUG_PRINT(
"rtree", (
"page: %lu  level: %d  nod_flag: %u",
 
  766                        (ulong) page, level, nod_flag));
 
  768   k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
 
  769   last = rt_PAGE_END(page_buf);
 
  771   for (i = 0; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag), ++
i)
 
  776       if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN))
 
  778         switch ((res = rtree_delete_req(info, keyinfo, key, key_length, 
 
  779                   _mi_kpos(nod_flag, k), page_size, ReinsertList, level + 1)))
 
  784             if (*page_size + key_length >= rt_PAGE_MIN_SIZE(keyinfo->block_length)) 
 
  788               if (rtree_set_key_mbr(info, keyinfo, k, key_length, 
 
  789                                   _mi_kpos(nod_flag, k)))
 
  791               if (_mi_write_keypage(info, keyinfo, page,
 
  792                                     DFLT_INIT_HITS, page_buf))
 
  802               DBUG_PRINT(
"rtree", (
"too small. move block to reinsert list"));
 
  803               if (rtree_fill_reinsert_list(ReinsertList, _mi_kpos(nod_flag, k),
 
  814               rtree_delete_key(info, page_buf, k, key_length, nod_flag);
 
  815               if (_mi_write_keypage(info, keyinfo, page,
 
  816                                     DFLT_INIT_HITS, page_buf))
 
  818               *page_size = mi_getint(page_buf);
 
  829             rtree_delete_key(info, page_buf, k, key_length, nod_flag);
 
  830             if (_mi_write_keypage(info, keyinfo, page,
 
  831                                   DFLT_INIT_HITS, page_buf))
 
  833             *page_size = mi_getint(page_buf);
 
  848       if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_EQUAL | MBR_DATA))
 
  850         rtree_delete_key(info, page_buf, k, key_length, nod_flag);
 
  851         *page_size = mi_getint(page_buf);
 
  856           if (_mi_dispose(info, keyinfo, page, DFLT_INIT_HITS))
 
  862           if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
 
  872   my_afree((uchar*)page_buf);
 
  876   my_afree((uchar*)page_buf);
 
  889 int rtree_delete(
MI_INFO *info, uint keynr, uchar *key, uint key_length)
 
  892   stPageList ReinsertList;
 
  894   MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
 
  895   DBUG_ENTER(
"rtree_delete");
 
  897   if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
 
  899     my_errno= HA_ERR_END_OF_FILE;
 
  902   DBUG_PRINT(
"rtree", (
"starting deletion at root page: %lu",
 
  905   ReinsertList.pages = NULL;
 
  906   ReinsertList.n_pages = 0;
 
  907   ReinsertList.m_pages = 0;
 
  909   switch (rtree_delete_req(info, keyinfo, key, key_length, old_root, 
 
  910                                  &page_size, &ReinsertList, 0))
 
  914       info->s->state.key_root[keynr] = HA_OFFSET_ERROR;
 
  921       for (i = 0; i < ReinsertList.n_pages; ++
i)
 
  927         if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
 
  929           my_errno = HA_ERR_OUT_OF_MEM;
 
  932         if (!_mi_fetch_keypage(info, keyinfo, ReinsertList.pages[i].offs, 
 
  933                                DFLT_INIT_HITS, page_buf, 0))
 
  935         nod_flag = mi_test_if_nod(page_buf);
 
  936         DBUG_PRINT(
"rtree", (
"reinserting keys from " 
  937                              "page: %lu  level: %d  nod_flag: %u",
 
  938                              (ulong) ReinsertList.pages[i].offs,
 
  939                              ReinsertList.pages[i].level, nod_flag));
 
  941         k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
 
  942         last = rt_PAGE_END(page_buf);
 
  943         for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
 
  946           if ((res= rtree_insert_level(info, keynr, k, key_length,
 
  947                                        ReinsertList.pages[i].level)) == -1)
 
  949             my_afree((uchar*)page_buf);
 
  955             DBUG_PRINT(
"rtree", (
"root has been split, adjust levels"));
 
  956             for (j= i; j < ReinsertList.n_pages; j++)
 
  958               ReinsertList.pages[j].level++;
 
  959               DBUG_PRINT(
"rtree", (
"keys from page: %lu  now level: %d",
 
  960                                    (ulong) ReinsertList.pages[i].offs,
 
  961                                    ReinsertList.pages[i].level));
 
  965         my_afree((uchar*)page_buf);
 
  966         if (_mi_dispose(info, keyinfo, ReinsertList.pages[i].offs,
 
  970       if (ReinsertList.pages)
 
  971         my_free(ReinsertList.pages);
 
  974       if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
 
  976       if (!_mi_fetch_keypage(info, keyinfo, old_root, DFLT_INIT_HITS,
 
  979       nod_flag = mi_test_if_nod(info->buff);
 
  980       page_size = mi_getint(info->buff);
 
  981       if (nod_flag && (page_size == 2 + key_length + nod_flag))
 
  983         my_off_t new_root = _mi_kpos(nod_flag,
 
  984                                      rt_PAGE_FIRST_KEY(info->buff, nod_flag));
 
  985         if (_mi_dispose(info, keyinfo, old_root, DFLT_INIT_HITS))
 
  987         info->s->state.key_root[keynr] = new_root;
 
  989       info->update= HA_STATE_DELETED;
 
  997       my_errno = HA_ERR_KEY_NOT_FOUND;
 
 1016 ha_rows rtree_estimate(
MI_INFO *info, uint keynr, uchar *key, 
 
 1017                        uint key_length, uint flag)
 
 1019   MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
 
 1030   if (flag & MBR_DISJOINT)
 
 1031     return info->state->records;
 
 1033   if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
 
 1034     return HA_POS_ERROR;
 
 1035   if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
 
 1036     return HA_POS_ERROR;
 
 1037   if (!_mi_fetch_keypage(info, keyinfo, root, DFLT_INIT_HITS, page_buf, 0))
 
 1039   nod_flag = mi_test_if_nod(page_buf);
 
 1041   k_len = keyinfo->keylength - info->s->base.rec_reflength;
 
 1043   k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
 
 1044   last = rt_PAGE_END(page_buf);
 
 1046   for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag), ++
i)
 
 1050       double k_area = rtree_rect_volume(keyinfo->seg, k, key_length);
 
 1055         if (flag & (MBR_CONTAIN | MBR_INTERSECT))
 
 1059         else if (flag & (MBR_WITHIN | MBR_EQUAL))
 
 1061           if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN))
 
 1069         if (flag & (MBR_CONTAIN | MBR_INTERSECT))
 
 1071           area += rtree_overlapping_area(keyinfo->seg, key, k, key_length) / 
 
 1074         else if (flag & (MBR_WITHIN | MBR_EQUAL))
 
 1076           if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN))
 
 1077             area += rtree_rect_volume(keyinfo->seg, key, key_length) /
 
 1086       if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, flag))
 
 1093       res = (ha_rows) (area / i * info->state->records);
 
 1098   my_afree((uchar*)page_buf);
 
 1102   my_afree((uchar*)page_buf);
 
 1103   return HA_POS_ERROR;