int rtree_find_first(MI_INFO *info, uint keynr, uchar *key, uint key_length, uint search_flag) { my_off_t root; uint nod_cmp_flag; MI_KEYDEF *keyinfo = info->s->keyinfo + keynr; if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { my_errno= HA_ERR_END_OF_FILE; return -1; } /* Save searched key, include data pointer. The data pointer is required if the search_flag contains MBR_DATA. (minimum bounding rectangle) */ memcpy(info->first_mbr_key, key, keyinfo->keylength); info->last_rkey_length = key_length; info->rtree_recursion_depth = -1; info->buff_used = 1; nod_cmp_flag = ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? MBR_WITHIN : MBR_INTERSECT); return rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0); }
int rtree_find_next(MI_INFO *info, uint keynr, uint search_flag) { my_off_t root; uint nod_cmp_flag; MI_KEYDEF *keyinfo = info->s->keyinfo + keynr; /* At the moment index can only properly handle the MBR_INTERSECT, so we use it for all sorts of queries. TODO: better searsh for CONTAINS/WITHIN. */ search_flag= nod_cmp_flag= MBR_INTERSECT; if (info->update & HA_STATE_DELETED) return rtree_find_first(info, keynr, info->lastkey, info->lastkey_length, search_flag); if (!info->buff_used) { uchar *key= info->int_keypos; while (key < info->int_maxpos) { if (!rtree_key_cmp(keyinfo->seg, info->first_mbr_key, key, info->last_rkey_length, search_flag)) { uchar *after_key = key + keyinfo->keylength; info->lastpos= _mi_dpos(info, 0, after_key); memcpy(info->lastkey, key, info->lastkey_length); if (after_key < info->int_maxpos) info->int_keypos= after_key; else info->buff_used= 1; return 0; } key+= keyinfo->keylength; } } if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { my_errno= HA_ERR_END_OF_FILE; return -1; } /* TODO better search for CONTAINS/WITHIN. nod_cmp_flag= (((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? MBR_WITHIN : MBR_INTERSECT)); */ return rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0); }
int rtree_find_next(MI_INFO *info, uint keynr, uint search_flag) { my_off_t root; uint nod_cmp_flag; MI_KEYDEF *keyinfo = info->s->keyinfo + keynr; if (info->update & HA_STATE_DELETED) return rtree_find_first(info, keynr, info->lastkey, info->lastkey_length, search_flag); if (!info->buff_used) { uchar *key= info->int_keypos; while (key < info->int_maxpos) { if (!rtree_key_cmp(keyinfo->seg, info->first_mbr_key, key, info->last_rkey_length, search_flag)) { uchar *after_key = key + keyinfo->keylength; info->lastpos= _mi_dpos(info, 0, after_key); memcpy(info->lastkey, key, info->lastkey_length); if (after_key < info->int_maxpos) info->int_keypos= after_key; else info->buff_used= 1; return 0; } key+= keyinfo->keylength; } } if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { my_errno= HA_ERR_END_OF_FILE; return -1; } nod_cmp_flag = ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? MBR_WITHIN : MBR_INTERSECT); return rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0); }
int rtree_find_first(MI_INFO *info, uint keynr, uchar *key, uint key_length, uint search_flag) { my_off_t root; uint nod_cmp_flag; MI_KEYDEF *keyinfo = info->s->keyinfo + keynr; /* At the moment index can only properly handle the MBR_INTERSECT, so we use it for all sorts of queries. TODO: better searsh for CONTAINS/WITHIN. */ search_flag= nod_cmp_flag= MBR_INTERSECT; if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { my_errno= HA_ERR_END_OF_FILE; return -1; } /* Save searched key, include data pointer. The data pointer is required if the search_flag contains MBR_DATA. (minimum bounding rectangle) */ memcpy(info->first_mbr_key, key, keyinfo->keylength); info->last_rkey_length = key_length; info->rtree_recursion_depth = -1; info->buff_used = 1; /* TODO better search for CONTAINS/WITHIN. nod_cmp_flag= ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? MBR_WITHIN : MBR_INTERSECT); */ return rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0); }
int rtree_find_first(MI_INFO *info, uint keynr, uchar *key, uint key_length, uint search_flag) { my_off_t root; uint nod_cmp_flag; MI_KEYDEF *keyinfo = info->s->keyinfo + keynr; if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { // This is assumed to happen only when the index is empty. If that // doesn't hold, the code in mi_rkey() that checks the record // count has to be changed. DBUG_ASSERT(info->s->state.state.records == 0); set_my_errno(HA_ERR_END_OF_FILE); return -1; } // All empty indexes should be caught above. Negative record counts // should never occur. DBUG_ASSERT(info->s->state.state.records > 0); /* Save searched key, include data pointer. The data pointer is required if the search_flag contains MBR_DATA. (minimum bounding rectangle) */ memcpy(info->first_mbr_key, key, keyinfo->keylength); info->last_rkey_length = key_length; info->rtree_recursion_depth = -1; info->buff_used = 1; nod_cmp_flag = ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? MBR_WITHIN : MBR_INTERSECT); return rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0); }
static int rtree_find_req(MI_INFO *info, MI_KEYDEF *keyinfo, uint search_flag, uint nod_cmp_flag, my_off_t page, int level) { uchar *k; uchar *last; uint nod_flag; int res; uchar *page_buf; int k_len; uint *saved_key = (uint*) (info->rtree_recursion_state) + level; if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length))) { my_errno = HA_ERR_OUT_OF_MEM; return -1; } if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0)) goto err1; nod_flag = mi_test_if_nod(page_buf); k_len = keyinfo->keylength - info->s->base.rec_reflength; if(info->rtree_recursion_depth >= level) { k = page_buf + *saved_key; } else { k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); } last = rt_PAGE_END(page_buf); for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) { if (nod_flag) { /* this is an internal node in the tree */ if (!(res = rtree_key_cmp(keyinfo->seg, info->first_mbr_key, k, info->last_rkey_length, nod_cmp_flag))) { switch ((res = rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, _mi_kpos(nod_flag, k), level + 1))) { case 0: /* found - exit from recursion */ *saved_key = (uint) (k - page_buf); goto ok; case 1: /* not found - continue searching */ info->rtree_recursion_depth = level; break; default: /* error */ case -1: goto err1; } } } else { /* this is a leaf */ if (!rtree_key_cmp(keyinfo->seg, info->first_mbr_key, k, info->last_rkey_length, search_flag)) { uchar *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); info->lastpos = _mi_dpos(info, 0, after_key); info->lastkey_length = k_len + info->s->base.rec_reflength; memcpy(info->lastkey, k, info->lastkey_length); info->rtree_recursion_depth = level; *saved_key = (uint) (last - page_buf); if (after_key < last) { info->int_keypos = info->buff; info->int_maxpos = info->buff + (last - after_key); memcpy(info->buff, after_key, last - after_key); info->buff_used = 0; } else { info->buff_used = 1; } res = 0; goto ok; } } } info->lastpos = HA_OFFSET_ERROR; my_errno = HA_ERR_KEY_NOT_FOUND; res = 1; ok: my_afree((uchar*)page_buf); return res; err1: my_afree((uchar*)page_buf); info->lastpos = HA_OFFSET_ERROR; return -1; }