~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_range.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
  Used when optimizing querries.
19
19
 */
20
20
 
21
 
#include "myisam_priv.h"
 
21
#include "myisamdef.h"
 
22
#include "rt_index.h"
22
23
 
23
 
static ha_rows _mi_record_pos(MI_INFO *, const unsigned char *, key_part_map,
 
24
static ha_rows _mi_record_pos(MI_INFO *, const uchar *, key_part_map,
24
25
                              enum ha_rkey_function);
25
 
static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,unsigned char *, uint,uint,my_off_t);
26
 
static uint32_t _mi_keynr(MI_INFO *info,MI_KEYDEF *,unsigned char *, unsigned char *,uint32_t *);
 
26
static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,uchar *, uint,uint,my_off_t);
 
27
static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *,uchar *, uchar *,uint *);
27
28
 
28
29
/*
29
30
  Estimate how many records there is in a given range
42
43
    HA_POS_ERROR  error (or we can't estimate number of rows)
43
44
    number        Estimated number of rows
44
45
*/
45
 
 
 
46
  
46
47
ha_rows mi_records_in_range(MI_INFO *info, int inx,
47
48
                            key_range *min_key, key_range *max_key)
48
49
{
49
50
  ha_rows start_pos,end_pos,res;
 
51
  DBUG_ENTER("mi_records_in_range");
50
52
 
51
53
  if ((inx = _mi_check_index(info,inx)) < 0)
52
 
    return(HA_POS_ERROR);
 
54
    DBUG_RETURN(HA_POS_ERROR);
53
55
 
54
56
  if (fast_mi_readinfo(info))
55
 
    return(HA_POS_ERROR);
 
57
    DBUG_RETURN(HA_POS_ERROR);
56
58
  info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
57
59
  if (info->s->concurrent_insert)
58
 
    pthread_rwlock_rdlock(&info->s->key_root_lock[inx]);
 
60
    rw_rdlock(&info->s->key_root_lock[inx]);
59
61
 
60
62
  switch(info->s->keyinfo[inx].key_alg){
 
63
#ifdef HAVE_RTREE_KEYS
 
64
  case HA_KEY_ALG_RTREE:
 
65
  {
 
66
    uchar * key_buff;
 
67
    uint start_key_len;
 
68
 
 
69
    /*
 
70
      The problem is that the optimizer doesn't support
 
71
      RTree keys properly at the moment.
 
72
      Hope this will be fixed some day.
 
73
      But now NULL in the min_key means that we
 
74
      didn't make the task for the RTree key
 
75
      and expect BTree functionality from it.
 
76
      As it's not able to handle such request
 
77
      we return the error.
 
78
    */
 
79
    if (!min_key)
 
80
    {
 
81
      res= HA_POS_ERROR;
 
82
      break;
 
83
    }
 
84
    key_buff= info->lastkey+info->s->base.max_key_length;
 
85
    start_key_len= _mi_pack_key(info,inx, key_buff,
 
86
                                (uchar*) min_key->key, min_key->keypart_map,
 
87
                                (HA_KEYSEG**) 0);
 
88
    res= rtree_estimate(info, inx, key_buff, start_key_len,
 
89
                        myisam_read_vec[min_key->flag]);
 
90
    res= res ? res : 1;                       /* Don't return 0 */
 
91
    break;
 
92
  }
 
93
#endif
61
94
  case HA_KEY_ALG_BTREE:
62
95
  default:
63
96
    start_pos= (min_key ?  _mi_record_pos(info, min_key->key,
73
106
  }
74
107
 
75
108
  if (info->s->concurrent_insert)
76
 
    pthread_rwlock_unlock(&info->s->key_root_lock[inx]);
 
109
    rw_unlock(&info->s->key_root_lock[inx]);
77
110
  fast_mi_writeinfo(info);
78
111
 
79
 
  return(res);
 
112
  DBUG_PRINT("info",("records: %ld",(ulong) (res)));
 
113
  DBUG_RETURN(res);
80
114
}
81
115
 
82
116
 
83
117
        /* Find relative position (in records) for key in index-tree */
84
118
 
85
 
static ha_rows _mi_record_pos(MI_INFO *info, const unsigned char *key,
 
119
static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key,
86
120
                              key_part_map keypart_map,
87
121
                              enum ha_rkey_function search_flag)
88
122
{
89
 
  uint32_t inx=(uint) info->lastinx, nextflag, key_len;
 
123
  uint inx=(uint) info->lastinx, nextflag, key_len;
90
124
  MI_KEYDEF *keyinfo=info->s->keyinfo+inx;
91
 
  unsigned char *key_buff;
 
125
  uchar *key_buff;
92
126
  double pos;
93
127
 
94
 
  assert(keypart_map);
 
128
  DBUG_ENTER("_mi_record_pos");
 
129
  DBUG_PRINT("enter",("search_flag: %d",search_flag));
 
130
  DBUG_ASSERT(keypart_map);
95
131
 
96
132
  key_buff=info->lastkey+info->s->base.max_key_length;
97
 
  key_len=_mi_pack_key(info,inx,key_buff,(unsigned char*) key, keypart_map,
 
133
  key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key, keypart_map,
98
134
                       (HA_KEYSEG**) 0);
 
135
  DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,
 
136
                                    (uchar*) key_buff,key_len););
99
137
  nextflag=myisam_read_vec[search_flag];
100
138
  if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
101
139
    key_len=USE_WHOLE_KEY;
139
177
                     info->s->state.key_root[inx]);
140
178
  if (pos >= 0.0)
141
179
  {
142
 
    return((uint32_t) (pos*info->state->records+0.5));
 
180
    DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->state->records)));
 
181
    DBUG_RETURN((ulong) (pos*info->state->records+0.5));
143
182
  }
144
 
  return(HA_POS_ERROR);
 
183
  DBUG_RETURN(HA_POS_ERROR);
145
184
}
146
185
 
147
186
 
150
189
 
151
190
static double _mi_search_pos(register MI_INFO *info,
152
191
                             register MI_KEYDEF *keyinfo,
153
 
                             unsigned char *key, uint32_t key_len, uint32_t nextflag,
 
192
                             uchar *key, uint key_len, uint nextflag,
154
193
                             register my_off_t pos)
155
194
{
156
195
  int flag;
157
 
  uint32_t nod_flag, keynr, max_keynr= 0;
158
 
  bool after_key;
159
 
  unsigned char *keypos,*buff;
 
196
  uint nod_flag, keynr, max_keynr= 0;
 
197
  my_bool after_key;
 
198
  uchar *keypos,*buff;
160
199
  double offset;
 
200
  DBUG_ENTER("_mi_search_pos");
161
201
 
162
202
  if (pos == HA_OFFSET_ERROR)
163
 
    return(0.5);
 
203
    DBUG_RETURN(0.5);
164
204
 
165
205
  if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,1)))
166
206
    goto err;
172
212
  if (flag)
173
213
  {
174
214
    if (flag == MI_FOUND_WRONG_KEY)
175
 
      return(-1);                               /* error */
 
215
      DBUG_RETURN(-1);                          /* error */
176
216
    /*
177
217
      Didn't found match. keypos points at next (bigger) key
178
218
      Try to find a smaller, better matching key.
182
222
      offset= 1.0;
183
223
    else if ((offset=_mi_search_pos(info,keyinfo,key,key_len,nextflag,
184
224
                                    _mi_kpos(nod_flag,keypos))) < 0)
185
 
      return(offset);
 
225
      DBUG_RETURN(offset);
186
226
  }
187
227
  else
188
228
  {
201
241
      */
202
242
      if ((offset=_mi_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
203
243
                                 _mi_kpos(nod_flag,keypos))) < 0)
204
 
        return(offset);                 /* Read error */
 
244
        DBUG_RETURN(offset);                    /* Read error */
205
245
    }
206
246
  }
207
 
  return((keynr+offset)/(max_keynr+1));
 
247
  DBUG_PRINT("info",("keynr: %d  offset: %g  max_keynr: %d  nod: %d  flag: %d",
 
248
                     keynr,offset,max_keynr,nod_flag,flag));
 
249
  DBUG_RETURN((keynr+offset)/(max_keynr+1));
208
250
err:
209
 
  return (-1.0);
 
251
  DBUG_PRINT("exit",("Error: %d",my_errno));
 
252
  DBUG_RETURN (-1.0);
210
253
}
211
254
 
212
255
 
213
256
        /* Get keynummer of current key and max number of keys in nod */
214
257
 
215
 
static uint32_t _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *page,
216
 
                      unsigned char *keypos, uint32_t *ret_max_key)
 
258
static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
 
259
                      uchar *keypos, uint *ret_max_key)
217
260
{
218
 
  uint32_t nod_flag,keynr,max_key;
219
 
  unsigned char t_buff[MI_MAX_KEY_BUFF],*end;
 
261
  uint nod_flag,keynr,max_key;
 
262
  uchar t_buff[MI_MAX_KEY_BUFF],*end;
220
263
 
221
264
  end= page+mi_getint(page);
222
265
  nod_flag=mi_test_if_nod(page);