~mdcallag/+junk/5.1-map

« back to all changes in this revision

Viewing changes to myisam/mi_search.c

  • Committer: sasha at sashanet
  • Date: 2001-04-12 01:09:00 UTC
  • mfrom: (669.1.1)
  • Revision ID: sp1r-sasha@mysql.sashanet.com-20010412010900-14282
Ugly merge of 3.23 changes into 4.0 - fix up needed

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
#define CMP(a,b) (a<b ? -1 : a == b ? 0 : 1)
23
23
 
24
24
static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
25
 
                                uchar *key, uchar *keypos,
26
 
                                uint *return_key_length);
 
25
                                uchar *key, uchar *keypos,
 
26
                                uint *return_key_length);
27
27
 
28
 
        /* Check index */
 
28
        /* Check index */
29
29
 
30
30
int _mi_check_index(MI_INFO *info, int inx)
31
31
{
32
 
  if (inx == -1)                        /* Use last index */
 
32
  if (inx == -1)                        /* Use last index */
33
33
    inx=info->lastinx;
34
34
  if (inx < 0 || ! (((ulonglong) 1 << inx) & info->s->state.key_map))
35
35
  {
36
36
    my_errno=HA_ERR_WRONG_INDEX;
37
37
    return -1;
38
38
  }
39
 
  if (info->lastinx != inx)             /* Index changed */
 
39
  if (info->lastinx != inx)             /* Index changed */
40
40
  {
41
41
    info->lastinx = inx;
42
42
    info->page_changed=1;
43
43
    info->update= ((info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED)) |
44
 
                   HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
 
44
                   HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
45
45
  }
46
46
  if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache))
47
47
    return(-1);
49
49
} /* mi_check_index */
50
50
 
51
51
 
52
 
        /*
53
 
        ** Search after row by a key
54
 
        ** Position to row is stored in info->lastpos
55
 
        ** Return: -1 if not found
56
 
        **          1 if one should continue search on higher level
57
 
        */
 
52
        /*
 
53
        ** Search after row by a key
 
54
        ** Position to row is stored in info->lastpos
 
55
        ** Return: -1 if not found
 
56
        **          1 if one should continue search on higher level
 
57
        */
58
58
 
59
59
int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
60
 
               uchar *key, uint key_len, uint nextflag, register my_off_t pos)
 
60
               uchar *key, uint key_len, uint nextflag, register my_off_t pos)
61
61
{
62
62
  my_bool last_key;
63
63
  int error,flag;
66
66
  uchar lastkey[MI_MAX_KEY_BUFF],*buff;
67
67
  DBUG_ENTER("_mi_search");
68
68
  DBUG_PRINT("enter",("pos: %ld  nextflag: %d  lastpos: %ld",
69
 
                      pos,nextflag,info->lastpos));
 
69
                      pos,nextflag,info->lastpos));
70
70
  DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,key_len););
71
71
 
72
72
  if (pos == HA_OFFSET_ERROR)
73
73
  {
74
 
    my_errno=HA_ERR_KEY_NOT_FOUND;                      /* Didn't find key */
 
74
    my_errno=HA_ERR_KEY_NOT_FOUND;                      /* Didn't find key */
75
75
    info->lastpos= HA_OFFSET_ERROR;
76
76
    if (!(nextflag & (SEARCH_SMALLER | SEARCH_BIGGER | SEARCH_LAST)))
77
 
      DBUG_RETURN(-1);                          /* Not found ; return error */
78
 
    DBUG_RETURN(1);                             /* Search at upper levels */
 
77
      DBUG_RETURN(-1);                          /* Not found ; return error */
 
78
    DBUG_RETURN(1);                             /* Search at upper levels */
79
79
  }
80
80
 
81
81
  if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,info->buff,
82
 
                               test(!(nextflag & SEARCH_SAVE_BUFF)))))
 
82
                               test(!(nextflag & SEARCH_SAVE_BUFF)))))
83
83
    goto err;
84
84
  DBUG_DUMP("page",(byte*) buff,mi_getint(buff));
85
85
 
86
86
  flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
87
 
                              &keypos,lastkey, &last_key);
 
87
                              &keypos,lastkey, &last_key);
88
88
  if (flag == MI_FOUND_WRONG_KEY)
89
89
    DBUG_RETURN(-1);
90
90
  nod_flag=mi_test_if_nod(buff);
93
93
  if (flag)
94
94
  {
95
95
    if ((error=_mi_search(info,keyinfo,key,key_len,nextflag,
96
 
                          _mi_kpos(nod_flag,keypos))) <= 0)
 
96
                          _mi_kpos(nod_flag,keypos))) <= 0)
97
97
      DBUG_RETURN(error);
98
98
 
99
99
    if (flag >0)
100
100
    {
101
101
      if (nextflag & (SEARCH_SMALLER | SEARCH_LAST) &&
102
 
          keypos == buff+2+nod_flag)
103
 
        DBUG_RETURN(1);                                 /* Bigger than key */
 
102
          keypos == buff+2+nod_flag)
 
103
        DBUG_RETURN(1);                                 /* Bigger than key */
104
104
    }
105
105
    else if (nextflag & SEARCH_BIGGER && keypos >= maxpos)
106
 
      DBUG_RETURN(1);                                   /* Smaller than key */
 
106
      DBUG_RETURN(1);                                   /* Smaller than key */
107
107
  }
108
108
  else
109
109
  {
110
110
    if (nextflag & SEARCH_FIND && (!(keyinfo->flag & HA_NOSAME)
111
 
                                   || key_len) && nod_flag)
 
111
                                   || key_len) && nod_flag)
112
112
    {
113
113
      if ((error=_mi_search(info,keyinfo,key,key_len,SEARCH_FIND,
114
 
                            _mi_kpos(nod_flag,keypos))) >= 0 ||
115
 
          my_errno != HA_ERR_KEY_NOT_FOUND)
116
 
        DBUG_RETURN(error);
117
 
      info->last_keypage= HA_OFFSET_ERROR;              /* Buffer not in memory */
 
114
                            _mi_kpos(nod_flag,keypos))) >= 0 ||
 
115
          my_errno != HA_ERR_KEY_NOT_FOUND)
 
116
        DBUG_RETURN(error);
 
117
      info->last_keypage= HA_OFFSET_ERROR;              /* Buffer not in memory */
118
118
    }
119
119
  }
120
120
  if (pos != info->last_keypage)
121
121
  {
122
122
    uchar *old_buff=buff;
123
123
    if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,info->buff,
124
 
                                 test(!(nextflag & SEARCH_SAVE_BUFF)))))
 
124
                                 test(!(nextflag & SEARCH_SAVE_BUFF)))))
125
125
      goto err;
126
126
    keypos=buff+(keypos-old_buff);
127
127
    maxpos=buff+(maxpos-old_buff);
131
131
  {
132
132
    uint not_used;
133
133
    if (_mi_get_prev_key(info,keyinfo, buff, info->lastkey, keypos,
134
 
                         &info->lastkey_length))
 
134
                         &info->lastkey_length))
135
135
      goto err;
136
136
    if ((nextflag & SEARCH_LAST) &&
137
 
        _mi_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND,
138
 
                    &not_used))
 
137
        _mi_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND,
 
138
                    &not_used))
139
139
    {
140
 
      my_errno=HA_ERR_KEY_NOT_FOUND;                    /* Didn't find key */
 
140
      my_errno=HA_ERR_KEY_NOT_FOUND;                    /* Didn't find key */
141
141
      goto err;
142
142
    }
143
143
  }
156
156
  info->int_keytree_version=keyinfo->version;
157
157
  info->last_search_keypage=info->last_keypage;
158
158
  info->page_changed=0;
159
 
  info->buff_used= (info->buff != buff);        /* If we have to reread buff */
 
159
  info->buff_used= (info->buff != buff);        /* If we have to reread buff */
160
160
 
161
161
  DBUG_PRINT("exit",("found key at %ld",info->lastpos));
162
162
  DBUG_RETURN(0);
168
168
} /* _mi_search */
169
169
 
170
170
 
171
 
        /* Search after key in page-block */
172
 
        /* If packed key puts smaller or identical key in buff */
173
 
        /* ret_pos point to where find or bigger key starts */
174
 
        /* ARGSUSED */
 
171
        /* Search after key in page-block */
 
172
        /* If packed key puts smaller or identical key in buff */
 
173
        /* ret_pos point to where find or bigger key starts */
 
174
        /* ARGSUSED */
175
175
 
176
176
int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
177
 
                   uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
178
 
                   uchar *buff __attribute__((unused)), my_bool *last_key)
 
177
                   uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
 
178
                   uchar *buff __attribute__((unused)), my_bool *last_key)
179
179
{
180
180
  reg4 int start,mid,end,save_end;
181
181
  int flag;
193
193
  {
194
194
    mid= (start+end)/2;
195
195
    if ((flag=_mi_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len,
196
 
                          comp_flag,&not_used))
197
 
        >= 0)
 
196
                          comp_flag,&not_used))
 
197
        >= 0)
198
198
      end=mid;
199
199
    else
200
200
      start=mid+1;
201
201
  }
202
202
  if (mid != start)
203
203
    flag=_mi_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len,
204
 
                     comp_flag,&not_used);
 
204
                     comp_flag,&not_used);
205
205
  if (flag < 0)
206
 
    start++;                    /* point at next, bigger key */
 
206
    start++;                    /* point at next, bigger key */
207
207
  *ret_pos=page+(uint) start*totlength;
208
208
  *last_key= end == save_end;
209
209
  DBUG_PRINT("exit",("flag: %d  keypos: %d",flag,start));
211
211
} /* _mi_bin_search */
212
212
 
213
213
 
214
 
        /* Used instead of _mi_bin_search() when key is packed */
215
 
        /* Puts smaller or identical key in buff */
216
 
        /* Key is searched sequentially */
 
214
        /* Used instead of _mi_bin_search() when key is packed */
 
215
        /* Puts smaller or identical key in buff */
 
216
        /* Key is searched sequentially */
217
217
 
218
218
int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
219
 
                   uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
220
 
                   uchar *buff, my_bool *last_key)
 
219
                   uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
 
220
                   uchar *buff, my_bool *last_key)
221
221
{
222
222
  int flag;
223
223
  uint nod_flag,length,not_used;
229
229
  nod_flag=mi_test_if_nod(page);
230
230
  page+=2+nod_flag;
231
231
  *ret_pos=page;
232
 
  t_buff[0]=0;                                  /* Avoid bugs */
 
232
  t_buff[0]=0;                                  /* Avoid bugs */
233
233
  while (page < end)
234
234
  {
235
235
    length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
237
237
    {
238
238
      my_errno=HA_ERR_CRASHED;
239
239
      DBUG_PRINT("error",("Found wrong key:  length: %d  page: %lx  end: %lx",
240
 
                          length,page,end));
 
240
                          length,page,end));
241
241
      DBUG_RETURN(MI_FOUND_WRONG_KEY);
242
242
    }
243
243
    if ((flag=_mi_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag,
244
 
                          &not_used)) >= 0)
 
244
                          &not_used)) >= 0)
245
245
      break;
246
246
#ifdef EXTRA_DEBUG
247
247
    DBUG_PRINT("loop",("page: %lx  key: '%s'  flag: %d",page,t_buff,flag));
250
250
    *ret_pos=page;
251
251
  }
252
252
  if (flag == 0)
253
 
    memcpy(buff,t_buff,length);                 /* Result is first key */
 
253
    memcpy(buff,t_buff,length);                 /* Result is first key */
254
254
  *last_key= page == end;
255
255
  DBUG_PRINT("exit",("flag: %d  ret_pos: %lx",flag,*ret_pos));
256
256
  DBUG_RETURN(flag);
257
257
} /* _mi_seq_search */
258
258
 
259
 
 
260
 
        /* Get pos to a key_block */
 
259
int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
 
260
                      uchar *key, uint key_len, uint nextflag, uchar **ret_pos,
 
261
                      uchar *buff, my_bool *last_key)
 
262
{
 
263
  /* my_flag is raw comparison result to be changed according to
 
264
     SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
 
265
     flag is the value returned by _mi_key_cmp and as treated as final */
 
266
  int flag=0, my_flag=-1;
 
267
  uint nod_flag, length, len, matched, cmplen, kseg_len, key_len_left;
 
268
  uint prefix_len,suffix_len;
 
269
  int key_len_skip, seg_len_pack;
 
270
  uchar *end, *kseg, *vseg;
 
271
  uchar *sort_order=keyinfo->seg->charset->sort_order;
 
272
  uchar tt_buff[MI_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
 
273
  uchar *saved_from, *saved_to, *saved_vseg;
 
274
  uint   saved_length=0, saved_prefix_len=0;
 
275
  DBUG_ENTER("_mi_prefix_search");
 
276
 
 
277
  t_buff[0]=0;                                  /* Avoid bugs */
 
278
  if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
 
279
    key_len=USE_WHOLE_KEY;
 
280
  end= page+mi_getint(page);
 
281
  nod_flag=mi_test_if_nod(page);
 
282
  page+=2+nod_flag;
 
283
  *ret_pos=page;
 
284
  kseg=key;
 
285
  {
 
286
    uint lenght_pack;
 
287
    get_key_pack_length(kseg_len,lenght_pack,kseg);
 
288
    key_len_skip=lenght_pack+kseg_len;
 
289
    key_len_left=key_len-key_len_skip;
 
290
    cmplen=(key_len_left>=0) ? kseg_len : key_len-lenght_pack;
 
291
  }
 
292
 
 
293
/*
 
294
  Keys are compressed the following way:
 
295
 
 
296
  If the max length of first key segment <= 127 characters the prefix is
 
297
  1 byte else it's 2 byte
 
298
 
 
299
  prefix         The high bit is set if this is a prefix for the prev key
 
300
  length         Packed length if the previous was a prefix byte
 
301
  [length]       Length character of data
 
302
  next-key-seg   Next key segments
 
303
*/
 
304
 
 
305
  matched=0;  /* how many char's from prefix were alredy matched */
 
306
  len=0;      /* length of previous key unpacked */
 
307
 
 
308
  while (page < end)
 
309
  {
 
310
    uint packed= *page & 128;
 
311
    
 
312
    vseg=page;
 
313
    if (keyinfo->seg->length >= 127)
 
314
    {
 
315
      suffix_len=mi_uint2korr(vseg) & 32767;
 
316
      vseg+=2;
 
317
    }
 
318
    else
 
319
      suffix_len= *vseg++ & 127;
 
320
 
 
321
    if (packed)
 
322
    {
 
323
      if (suffix_len == 0)                      /* Same key */
 
324
        prefix_len=len;
 
325
      else
 
326
      {
 
327
        prefix_len=suffix_len;       
 
328
        get_key_length(suffix_len,vseg);
 
329
      }
 
330
    }
 
331
    else
 
332
      prefix_len=0;
 
333
 
 
334
    len=prefix_len+suffix_len;
 
335
    seg_len_pack=get_pack_length(len);
 
336
    t_buff=tt_buff+3-seg_len_pack;
 
337
    store_key_length(t_buff,len);
 
338
 
 
339
    if (prefix_len > saved_prefix_len)
 
340
      memcpy(t_buff+seg_len_pack+saved_prefix_len,saved_vseg,
 
341
             prefix_len-saved_prefix_len);
 
342
    saved_vseg=vseg;
 
343
    saved_prefix_len=prefix_len;
 
344
 
 
345
    {
 
346
      uchar *from=vseg+suffix_len;
 
347
      MI_KEYSEG *keyseg;
 
348
      uint l;
 
349
 
 
350
      for (keyseg=keyinfo->seg+1 ; keyseg->type ; keyseg++ )
 
351
      {
 
352
        
 
353
        if (keyseg->flag & HA_NULL_PART)
 
354
        {
 
355
          if (!(*from++))
 
356
            continue;
 
357
        }
 
358
        if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
 
359
        {
 
360
          get_key_length(l,from);
 
361
        }
 
362
        else
 
363
          l=keyseg->length;
 
364
 
 
365
        from+=l;
 
366
      }
 
367
      from+=keyseg->length;
 
368
      page=from+nod_flag;
 
369
      length=from-vseg;
 
370
    }
 
371
 
 
372
    if (page > end)
 
373
    {
 
374
      my_errno=HA_ERR_CRASHED;
 
375
      DBUG_PRINT("error",("Found wrong key:  length: %d  page: %lx  end: %lx",
 
376
                          length,page,end));
 
377
      DBUG_RETURN(MI_FOUND_WRONG_KEY);
 
378
    }
 
379
 
 
380
    if (matched >= prefix_len)
 
381
    {
 
382
      /* We have to compare. But we can still skip part of the key */
 
383
      uint  left;
 
384
      uchar *k=kseg+prefix_len;
 
385
 
 
386
      left=(len>cmplen) ? cmplen-prefix_len : suffix_len;
 
387
 
 
388
      matched=prefix_len+left;
 
389
 
 
390
      for(my_flag=0;left;left--)
 
391
        if ((my_flag= (int) sort_order[*vseg++] - (int) sort_order[*k++]))
 
392
          break;
 
393
 
 
394
      if (my_flag>0)      /* mismatch */
 
395
        break;
 
396
      else if (my_flag==0) /* match */
 
397
      { /*
 
398
        **  len cmplen seg_left_len more_segs
 
399
        **     <                               matched=len; continue search
 
400
        **     >      =                        prefix ? found : (matched=len; continue search)
 
401
        **     >      <                 -      ok, found
 
402
        **     =      <                 -      ok, found
 
403
        **     =      =                 -      ok, found
 
404
        **     =      =                 +      next seg
 
405
        */
 
406
        if (len < cmplen)
 
407
        {
 
408
          my_flag=-1;
 
409
        }
 
410
        else if (len > cmplen)
 
411
        {
 
412
          if(my_flag = !(nextflag & SEARCH_PREFIX) && key_len_left>0)
 
413
            break;
 
414
          goto fix_flag;
 
415
        }
 
416
        else if (key_len_left>0)
 
417
        {
 
418
          uint not_used;
 
419
          if ((flag = _mi_key_cmp(keyinfo->seg+1,vseg,
 
420
                                  k,key_len_left,nextflag,&not_used)) >= 0)
 
421
            break;
 
422
        }
 
423
        else
 
424
        {
 
425
          /* at this line flag==-1 if the following lines were already
 
426
             visited and 0 otherwise,  i.e. flag <=0 here always !!! */
 
427
  fix_flag:
 
428
          if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST))
 
429
            flag=(nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
 
430
          if (flag>=0) break;
 
431
        }
 
432
      }
 
433
      matched-=left;
 
434
    }
 
435
    /* else (matched < prefix_len) ---> do nothing. */
 
436
 
 
437
    memcpy(buff,t_buff,saved_length=seg_len_pack+prefix_len);
 
438
    saved_to=buff+saved_length;
 
439
    saved_from=saved_vseg;
 
440
    saved_length=length;
 
441
    *ret_pos=page;
 
442
  }
 
443
  if (my_flag)
 
444
    flag=(keyinfo->seg->flag & HA_REVERSE_SORT) ? -my_flag : my_flag;
 
445
  if (flag == 0)
 
446
  {
 
447
    memcpy(buff,t_buff,saved_length=seg_len_pack+prefix_len);
 
448
    saved_to=buff+saved_length;
 
449
    saved_from=saved_vseg;
 
450
    saved_length=length;
 
451
  }
 
452
  if (saved_length)
 
453
    memcpy(saved_to,saved_from,saved_length);
 
454
 
 
455
  *last_key= page == end;
 
456
 
 
457
  DBUG_PRINT("exit",("flag: %d  ret_pos: %lx",flag,*ret_pos));
 
458
  DBUG_RETURN(flag);
 
459
} /* _mi_prefix_search */
 
460
 
 
461
 
 
462
        /* Get pos to a key_block */
261
463
 
262
464
my_off_t _mi_kpos(uint nod_flag, uchar *after_key)
263
465
{
286
488
    return (my_off_t) (mi_uint2korr(after_key)*MI_KEY_BLOCK_LENGTH);
287
489
  case 1:
288
490
    return (uint) (*after_key)*MI_KEY_BLOCK_LENGTH;
289
 
  case 0:                                       /* At leaf page */
290
 
  default:                                      /* Impossible */
 
491
  case 0:                                       /* At leaf page */
 
492
  default:                                      /* Impossible */
291
493
    return(HA_OFFSET_ERROR);
292
494
  }
293
495
} /* _kpos */
294
496
 
295
497
 
296
 
        /* Save pos to a key_block */
 
498
        /* Save pos to a key_block */
297
499
 
298
500
void _mi_kpointer(register MI_INFO *info, register uchar *buff, my_off_t pos)
299
501
{
315
517
  case 3: mi_int3store(buff,pos); break;
316
518
  case 2: mi_int2store(buff,(uint) pos); break;
317
519
  case 1: buff[0]= (uchar) pos; break;
318
 
  default: abort();                             /* impossible */
 
520
  default: abort();                             /* impossible */
319
521
  }
320
522
} /* _mi_kpointer */
321
523
 
322
524
 
323
 
        /* Calc pos to a data-record from a key */
 
525
        /* Calc pos to a data-record from a key */
324
526
 
325
527
 
326
528
my_off_t _mi_dpos(MI_INFO *info, uint nod_flag, uchar *after_key)
335
537
  case 5:  pos= (my_off_t) mi_uint5korr(after_key);  break;
336
538
#else
337
539
  case 8:  pos= (my_off_t) mi_uint4korr(after_key+4);   break;
338
 
  case 7:  pos= (my_off_t) mi_uint4korr(after_key+3);   break;
339
 
  case 6:  pos= (my_off_t) mi_uint4korr(after_key+2);   break;
340
 
  case 5:  pos= (my_off_t) mi_uint4korr(after_key+1);   break;
 
540
  case 7:  pos= (my_off_t) mi_uint4korr(after_key+3);   break;
 
541
  case 6:  pos= (my_off_t) mi_uint4korr(after_key+2);   break;
 
542
  case 5:  pos= (my_off_t) mi_uint4korr(after_key+1);   break;
341
543
#endif
342
544
  case 4:  pos= (my_off_t) mi_uint4korr(after_key);  break;
343
545
  case 3:  pos= (my_off_t) mi_uint3korr(after_key);  break;
344
546
  case 2:  pos= (my_off_t) mi_uint2korr(after_key);  break;
345
547
  default:
346
 
    pos=0L;                                     /* Shut compiler up */
 
548
    pos=0L;                                     /* Shut compiler up */
347
549
  }
348
550
  return (info->s->options &
349
 
          (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
350
 
            pos*info->s->base.pack_reclength;
 
551
          (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
 
552
            pos*info->s->base.pack_reclength;
351
553
}
352
554
 
353
555
 
361
563
  case 8:
362
564
    pos= (my_off_t) mi_uint8korr(ptr);
363
565
    if (pos == HA_OFFSET_ERROR)
364
 
      return HA_OFFSET_ERROR;                   /* end of list */
 
566
      return HA_OFFSET_ERROR;                   /* end of list */
365
567
    break;
366
568
  case 7:
367
569
    pos= (my_off_t) mi_uint7korr(ptr);
368
570
    if (pos == (((my_off_t) 1) << 56) -1)
369
 
      return HA_OFFSET_ERROR;                   /* end of list */
 
571
      return HA_OFFSET_ERROR;                   /* end of list */
370
572
    break;
371
573
  case 6:
372
574
    pos= (my_off_t) mi_uint6korr(ptr);
373
575
    if (pos == (((my_off_t) 1) << 48) -1)
374
 
      return HA_OFFSET_ERROR;                   /* end of list */
 
576
      return HA_OFFSET_ERROR;                   /* end of list */
375
577
    break;
376
578
  case 5:
377
579
    pos= (my_off_t) mi_uint5korr(ptr);
378
580
    if (pos == (((my_off_t) 1) << 40) -1)
379
 
      return HA_OFFSET_ERROR;                   /* end of list */
 
581
      return HA_OFFSET_ERROR;                   /* end of list */
380
582
    break;
381
583
#else
382
584
  case 8:
401
603
    if (pos == (my_off_t) (1 << 16) -1)
402
604
      return HA_OFFSET_ERROR;
403
605
    break;
404
 
  default: abort();                             /* Impossible */
 
606
  default: abort();                             /* Impossible */
405
607
  }
406
608
  return ((s->options &
407
 
          (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
408
 
          pos*s->base.pack_reclength);
 
609
          (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
 
610
          pos*s->base.pack_reclength);
409
611
}
410
612
 
411
613
 
412
 
        /* save position to record */
 
614
        /* save position to record */
413
615
 
414
616
void _mi_dpointer(MI_INFO *info, uchar *buff, my_off_t pos)
415
617
{
416
618
  if (!(info->s->options &
417
 
        (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) &&
 
619
        (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) &&
418
620
      pos != HA_OFFSET_ERROR)
419
621
    pos/=info->s->base.pack_reclength;
420
622
 
437
639
  case 4: mi_int4store(buff,pos); break;
438
640
  case 3: mi_int3store(buff,pos); break;
439
641
  case 2: mi_int2store(buff,(uint) pos); break;
440
 
  default: abort();                             /* Impossible */
 
642
  default: abort();                             /* Impossible */
441
643
  }
442
644
} /* _mi_dpointer */
443
645
 
444
646
 
445
647
int _mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
446
 
                     uchar *b, uint b_length, my_bool part_key)
 
648
                     uchar *b, uint b_length, my_bool part_key)
447
649
{
448
650
  uint length= min(a_length,b_length);
449
651
  uchar *end= a+ length;
470
672
 
471
673
 
472
674
static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
473
 
                       my_bool part_key)
 
675
                       my_bool part_key)
474
676
{
475
677
  uint length= min(a_length,b_length);
476
678
  uchar *end= a+ length;
485
687
}
486
688
 
487
689
 
488
 
        /*
489
 
        ** Compare two keys with is bigger
490
 
        ** Returns <0, 0, >0 acording to with is bigger
491
 
        ** Key_length specifies length of key to use.  Number-keys can't
492
 
        ** be splited
493
 
        ** If flag <> SEARCH_FIND compare also position
494
 
        */
 
690
        /*
 
691
        ** Compare two keys with is bigger
 
692
        ** Returns <0, 0, >0 acording to with is bigger
 
693
        ** Key_length specifies length of key to use.  Number-keys can't
 
694
        ** be splited
 
695
        ** If flag <> SEARCH_FIND compare also position
 
696
        */
495
697
 
496
698
#define FCMP(A,B) ((int) (A) - (int) (B))
497
699
 
498
700
int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
499
 
                register uchar *b, uint key_length, uint nextflag,
500
 
                uint *diff_pos)
 
701
                register uchar *b, uint key_length, uint nextflag,
 
702
                uint *diff_pos)
501
703
{
502
704
  int flag;
503
705
  int16 s_1,s_2;
522
724
      key_length--;
523
725
      if (*a != *b)
524
726
      {
525
 
        flag = (int) *a - (int) *b;
526
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
727
        flag = (int) *a - (int) *b;
 
728
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
527
729
      }
528
730
      b++;
529
 
      if (!*a++)                                /* If key was NULL */
 
731
      if (!*a++)                                /* If key was NULL */
530
732
      {
531
 
        if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
532
 
          nextflag=SEARCH_SAME;                 /* Allow duplicate keys */
533
 
        next_key_length=key_length;
534
 
        continue;                               /* To next key part */
 
733
        if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
 
734
          nextflag=SEARCH_SAME;                 /* Allow duplicate keys */
 
735
        next_key_length=key_length;
 
736
        continue;                               /* To next key part */
535
737
      }
536
738
    }
537
739
    end= a+ min(keyseg->length,key_length);
538
740
    next_key_length=key_length-keyseg->length;
539
741
 
540
742
    switch ((enum ha_base_keytype) keyseg->type) {
541
 
    case HA_KEYTYPE_TEXT:                       /* Ascii; Key is converted */
 
743
    case HA_KEYTYPE_TEXT:                       /* Ascii; Key is converted */
542
744
      if (keyseg->flag & HA_SPACE_PACK)
543
745
      {
544
 
        int a_length,b_length,pack_length;
545
 
        get_key_length(a_length,a);
546
 
        get_key_pack_length(b_length,pack_length,b);
547
 
        next_key_length=key_length-b_length-pack_length;
 
746
        int a_length,b_length,pack_length;
 
747
        get_key_length(a_length,a);
 
748
        get_key_pack_length(b_length,pack_length,b);
 
749
        next_key_length=key_length-b_length-pack_length;
548
750
 
549
 
        if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
550
 
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
551
 
                                              next_key_length <= 0))))
552
 
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
553
 
        a+=a_length;
554
 
        b+=b_length;
555
 
        break;
 
751
        if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
 
752
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
753
                                              next_key_length <= 0))))
 
754
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
755
        a+=a_length;
 
756
        b+=b_length;
 
757
        break;
556
758
      }
557
759
      else
558
760
      {
559
 
        uint length=(uint) (end-a);
560
 
        if ((flag=_mi_compare_text(keyseg->charset,a,length,b,length,
561
 
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
562
 
                                              next_key_length <= 0))))
563
 
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
564
 
        a=end;
565
 
        b+=length;
 
761
        uint length=(uint) (end-a);
 
762
        if ((flag=_mi_compare_text(keyseg->charset,a,length,b,length,
 
763
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
764
                                              next_key_length <= 0))))
 
765
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
766
        a=end;
 
767
        b+=length;
566
768
      }
567
769
      break;
568
770
    case HA_KEYTYPE_BINARY:
569
771
      if (keyseg->flag & HA_SPACE_PACK)
570
772
      {
571
 
        int a_length,b_length,pack_length;
572
 
        get_key_length(a_length,a);
573
 
        get_key_pack_length(b_length,pack_length,b);
574
 
        next_key_length=key_length-b_length-pack_length;
 
773
        int a_length,b_length,pack_length;
 
774
        get_key_length(a_length,a);
 
775
        get_key_pack_length(b_length,pack_length,b);
 
776
        next_key_length=key_length-b_length-pack_length;
575
777
 
576
 
        if ((flag=compare_bin(a,a_length,b,b_length,
577
 
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
578
 
                                         next_key_length <= 0))))
579
 
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
580
 
        a+=a_length;
581
 
        b+=b_length;
582
 
        break;
 
778
        if ((flag=compare_bin(a,a_length,b,b_length,
 
779
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
780
                                         next_key_length <= 0))))
 
781
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
782
        a+=a_length;
 
783
        b+=b_length;
 
784
        break;
583
785
      }
584
786
      else
585
787
      {
586
 
        uint length=keyseg->length;
587
 
        if ((flag=compare_bin(a,length,b,length,
588
 
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
589
 
                                         next_key_length <= 0))))
590
 
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
591
 
        a+=length;
592
 
        b+=length;
 
788
        uint length=keyseg->length;
 
789
        if ((flag=compare_bin(a,length,b,length,
 
790
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
791
                                         next_key_length <= 0))))
 
792
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
793
        a+=length;
 
794
        b+=length;
593
795
      }
594
796
      break;
595
797
    case HA_KEYTYPE_VARTEXT:
596
798
      {
597
 
        int a_length,b_length,pack_length;
598
 
        get_key_length(a_length,a);
599
 
        get_key_pack_length(b_length,pack_length,b);
600
 
        next_key_length=key_length-b_length-pack_length;
 
799
        int a_length,b_length,pack_length;
 
800
        get_key_length(a_length,a);
 
801
        get_key_pack_length(b_length,pack_length,b);
 
802
        next_key_length=key_length-b_length-pack_length;
601
803
 
602
 
        if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
603
 
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
604
 
                                              next_key_length <= 0))))
605
 
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
606
 
        a+=a_length;
607
 
        b+=b_length;
608
 
        break;
 
804
        if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
 
805
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
806
                                              next_key_length <= 0))))
 
807
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
808
        a+=a_length;
 
809
        b+=b_length;
 
810
        break;
609
811
      }
610
812
      break;
611
813
    case HA_KEYTYPE_VARBINARY:
612
814
      {
613
 
        int a_length,b_length,pack_length;
614
 
        get_key_length(a_length,a);
615
 
        get_key_pack_length(b_length,pack_length,b);
616
 
        next_key_length=key_length-b_length-pack_length;
 
815
        int a_length,b_length,pack_length;
 
816
        get_key_length(a_length,a);
 
817
        get_key_pack_length(b_length,pack_length,b);
 
818
        next_key_length=key_length-b_length-pack_length;
617
819
 
618
 
        if ((flag=compare_bin(a,a_length,b,b_length,
619
 
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
620
 
                                         next_key_length <= 0))))
621
 
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
622
 
        a+=a_length;
623
 
        b+=b_length;
624
 
        break;
 
820
        if ((flag=compare_bin(a,a_length,b,b_length,
 
821
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
822
                                         next_key_length <= 0))))
 
823
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
824
        a+=a_length;
 
825
        b+=b_length;
 
826
        break;
625
827
      }
626
828
      break;
627
829
    case HA_KEYTYPE_INT8:
629
831
      int i_1= (int) *((signed char*) a);
630
832
      int i_2= (int) *((signed char*) b);
631
833
      if ((flag = CMP(i_1,i_2)))
632
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
834
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
633
835
      a= end;
634
836
      b++;
635
837
      break;
638
840
      s_1= mi_sint2korr(a);
639
841
      s_2= mi_sint2korr(b);
640
842
      if ((flag = CMP(s_1,s_2)))
641
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
843
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
642
844
      a=  end;
643
845
      b+= 2; /* sizeof(short int); */
644
846
      break;
645
847
    case HA_KEYTYPE_USHORT_INT:
646
848
      {
647
 
        uint16 us_1,us_2;
648
 
        us_1= mi_sint2korr(a);
649
 
        us_2= mi_sint2korr(b);
650
 
        if ((flag = CMP(us_1,us_2)))
651
 
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
652
 
        a=  end;
653
 
        b+=2; /* sizeof(short int); */
654
 
        break;
 
849
        uint16 us_1,us_2;
 
850
        us_1= mi_sint2korr(a);
 
851
        us_2= mi_sint2korr(b);
 
852
        if ((flag = CMP(us_1,us_2)))
 
853
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
854
        a=  end;
 
855
        b+=2; /* sizeof(short int); */
 
856
        break;
655
857
      }
656
858
    case HA_KEYTYPE_LONG_INT:
657
859
      l_1= mi_sint4korr(a);
658
860
      l_2= mi_sint4korr(b);
659
861
      if ((flag = CMP(l_1,l_2)))
660
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
862
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
661
863
      a=  end;
662
864
      b+= 4; /* sizeof(long int); */
663
865
      break;
665
867
      u_1= mi_sint4korr(a);
666
868
      u_2= mi_sint4korr(b);
667
869
      if ((flag = CMP(u_1,u_2)))
668
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
870
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
669
871
      a=  end;
670
872
      b+= 4; /* sizeof(long int); */
671
873
      break;
673
875
      l_1=mi_sint3korr(a);
674
876
      l_2=mi_sint3korr(b);
675
877
      if ((flag = CMP(l_1,l_2)))
676
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
878
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
677
879
      a=  end;
678
880
      b+= 3;
679
881
      break;
681
883
      l_1=mi_uint3korr(a);
682
884
      l_2=mi_uint3korr(b);
683
885
      if ((flag = CMP(l_1,l_2)))
684
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
886
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
685
887
      a=  end;
686
888
      b+= 3;
687
889
      break;
689
891
      mi_float4get(f_1,a);
690
892
      mi_float4get(f_2,b);
691
893
      if ((flag = CMP(f_1,f_2)))
692
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
894
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
693
895
      a=  end;
694
896
      b+= 4; /* sizeof(float); */
695
897
      break;
697
899
      mi_float8get(d_1,a);
698
900
      mi_float8get(d_2,b);
699
901
      if ((flag = CMP(d_1,d_2)))
700
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
902
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
701
903
      a=  end;
702
904
      b+= 8;  /* sizeof(double); */
703
905
      break;
704
 
    case HA_KEYTYPE_NUM:                                /* Numeric key */
 
906
    case HA_KEYTYPE_NUM:                                /* Numeric key */
705
907
    {
706
908
      int swap_flag= 0;
707
909
      int alength,blength;
708
910
      
709
911
      if (keyseg->flag & HA_REVERSE_SORT)
710
912
      {
711
 
        swap(uchar*,a,b);       
712
 
        swap_flag=1;                            /* Remember swap of a & b */
 
913
        swap(uchar*,a,b);       
 
914
        swap_flag=1;                            /* Remember swap of a & b */
713
915
        end= a+ (int) (end-b);
714
916
      }
715
917
      if (keyseg->flag & HA_SPACE_PACK)
716
918
      {
717
 
        alength= *a++; blength= *b++;
718
 
        end=a+alength;
719
 
        next_key_length=key_length-blength-1;
 
919
        alength= *a++; blength= *b++;
 
920
        end=a+alength;
 
921
        next_key_length=key_length-blength-1;
720
922
      }
721
923
      else
722
924
      {
723
 
        alength= (int) (end-a);
724
 
        blength=keyseg->length;
725
 
        /* remove pre space from keys */
726
 
        for ( ; alength && *a == ' ' ; a++, alength--) ;
727
 
        for ( ; blength && *b == ' ' ; b++, blength--) ;
 
925
        alength= (int) (end-a);
 
926
        blength=keyseg->length;
 
927
        /* remove pre space from keys */
 
928
        for ( ; alength && *a == ' ' ; a++, alength--) ;
 
929
        for ( ; blength && *b == ' ' ; b++, blength--) ;
728
930
      }
729
931
 
730
932
      if (*a == '-')
731
933
      {
732
 
        if (*b != '-')
733
 
          return -1;
734
 
        a++; b++;
735
 
        swap(uchar*,a,b);
736
 
        swap(int,alength,blength);
737
 
        swap_flag=1-swap_flag;
738
 
        alength--; blength--;
739
 
        end=a+alength;
 
934
        if (*b != '-')
 
935
          return -1;
 
936
        a++; b++;
 
937
        swap(uchar*,a,b);
 
938
        swap(int,alength,blength);
 
939
        swap_flag=1-swap_flag;
 
940
        alength--; blength--;
 
941
        end=a+alength;
740
942
      }
741
943
      else if (*b == '-')
742
 
        return 1;
 
944
        return 1;
743
945
      while (alength && (*a == '+' || *a == '0'))
744
946
      {
745
 
        a++; alength--;
 
947
        a++; alength--;
746
948
      }
747
949
      while (blength && (*b == '+' || *b == '0'))
748
950
      {
749
 
        b++; blength--;
 
951
        b++; blength--;
750
952
      }
751
953
      if (alength != blength)
752
 
        return (alength < blength) ? -1 : 1;
 
954
        return (alength < blength) ? -1 : 1;
753
955
      while (a < end)
754
 
        if (*a++ !=  *b++)
755
 
          return ((int) a[-1] - (int) b[-1]);
 
956
        if (*a++ !=  *b++)
 
957
          return ((int) a[-1] - (int) b[-1]);
756
958
 
757
 
      if (swap_flag)                            /* Restore pointers */
758
 
        swap(uchar*,a,b);
 
959
      if (swap_flag)                            /* Restore pointers */
 
960
        swap(uchar*,a,b);
759
961
      break;
760
962
    }
761
963
#ifdef HAVE_LONG_LONG
765
967
      ll_a= mi_sint8korr(a);
766
968
      ll_b= mi_sint8korr(b);
767
969
      if ((flag = CMP(ll_a,ll_b)))
768
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
970
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
769
971
      a=  end;
770
972
      b+= 8;
771
973
      break;
776
978
      ll_a= mi_uint8korr(a);
777
979
      ll_b= mi_uint8korr(b);
778
980
      if ((flag = CMP(ll_a,ll_b)))
779
 
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
981
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
780
982
      a=  end;
781
983
      b+= 8;
782
984
      break;
783
985
    }
784
986
#endif
785
 
    case HA_KEYTYPE_END:                        /* Ready */
786
 
      goto end;                                 /* diff_pos is incremented */
 
987
    case HA_KEYTYPE_END:                        /* Ready */
 
988
      goto end;                                 /* diff_pos is incremented */
787
989
    }
788
990
  }
789
991
  (*diff_pos)++;
798
1000
    {
799
1001
      if (*a++ != *b++)
800
1002
      {
801
 
        flag= FCMP(a[-1],b[-1]);
802
 
        break;
 
1003
        flag= FCMP(a[-1],b[-1]);
 
1004
        break;
803
1005
      }
804
1006
    }
805
1007
    if (nextflag & SEARCH_SAME)
806
 
      return (flag);                            /* read same */
 
1008
      return (flag);                            /* read same */
807
1009
    if (nextflag & SEARCH_BIGGER)
808
 
      return (flag <= 0 ? -1 : 1);              /* read next */
809
 
    return (flag < 0 ? -1 : 1);                 /* read previous */
 
1010
      return (flag <= 0 ? -1 : 1);              /* read next */
 
1011
    return (flag < 0 ? -1 : 1);                 /* read previous */
810
1012
  }
811
1013
  return 0;
812
1014
} /* _mi_key_cmp */
813
1015
 
814
1016
 
815
 
        /* Get key from key-block */
816
 
        /* page points at previous key; its advanced to point at next key */
817
 
        /* key should contain previous key */
818
 
        /* Returns length of found key + pointers */
819
 
        /* nod_flag is a flag if we are on nod */
 
1017
        /* Get key from key-block */
 
1018
        /* page points at previous key; its advanced to point at next key */
 
1019
        /* key should contain previous key */
 
1020
        /* Returns length of found key + pointers */
 
1021
        /* nod_flag is a flag if we are on nod */
820
1022
 
821
 
        /* same as _mi_get_key but used with fixed length keys */
 
1023
        /* same as _mi_get_key but used with fixed length keys */
822
1024
 
823
1025
uint _mi_get_static_key(register MI_KEYDEF *keyinfo, uint nod_flag,
824
 
                       register uchar **page, register uchar *key)
 
1026
                       register uchar **page, register uchar *key)
825
1027
{
826
1028
  memcpy((byte*) key,(byte*) *page,
827
 
         (size_t) (keyinfo->keylength+nod_flag));
 
1029
         (size_t) (keyinfo->keylength+nod_flag));
828
1030
  *page+=keyinfo->keylength+nod_flag;
829
1031
  return(keyinfo->keylength);
830
1032
} /* _mi_get_static_key */
833
1035
/* Key with is packed against previous key or key with a NULL column */
834
1036
 
835
1037
uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
836
 
                      register uchar **page_pos, register uchar *key)
 
1038
                      register uchar **page_pos, register uchar *key)
837
1039
{
838
1040
  reg1 MI_KEYSEG *keyseg;
839
1041
  uchar *start_key,*page=*page_pos;
849
1051
      uint packed= *page & 128,tot_length,rest_length;
850
1052
      if (keyseg->length >= 127)
851
1053
      {
852
 
        length=mi_uint2korr(page) & 32767;
853
 
        page+=2;
 
1054
        length=mi_uint2korr(page) & 32767;
 
1055
        page+=2;
854
1056
      }
855
1057
      else
856
 
        length= *page++ & 127;
 
1058
        length= *page++ & 127;
857
1059
 
858
1060
      if (packed)
859
1061
      {
908
1110
          key+=length;
909
1111
        }
910
1112
        memcpy(key,page,rest_length);
911
 
        page+=rest_length;
912
 
        key+=rest_length;
913
 
        continue;
914
1113
      }
915
1114
      else
916
1115
      {
917
 
        if (keyseg->flag & HA_NULL_PART)
918
 
        {
919
 
          if (!length--)                        /* Null part */
920
 
          {
921
 
            *key++=0;
922
 
            continue;
923
 
          }
924
 
          *key++=1;                             /* Not null */
925
 
        }
 
1116
        if (keyseg->flag & HA_NULL_PART)
 
1117
        {
 
1118
          if (!length--)                        /* Null part */
 
1119
          {
 
1120
            *key++=0;
 
1121
            continue;
 
1122
          }
 
1123
          *key++=1;                             /* Not null */
 
1124
        }
926
1125
      }
927
1126
      if (length > (uint) keyseg->length)
928
1127
      {
929
 
        DBUG_PRINT("error",("Found too long packed key: %d of %d at %lx",
930
 
                            length, keyseg->length, *page_pos));
931
 
        DBUG_DUMP("key",(char*) *page_pos,16);
932
 
        my_errno=HA_ERR_CRASHED;
933
 
        return 0;                               /* Error */
 
1128
        DBUG_PRINT("error",("Found too long packed key: %d of %d at %lx",
 
1129
                            length, keyseg->length, *page_pos));
 
1130
        DBUG_DUMP("key",(char*) *page_pos,16);
 
1131
        my_errno=HA_ERR_CRASHED;
 
1132
        return 0;                               /* Error */
934
1133
      }
935
1134
      store_key_length_inc(key,length);
936
1135
    }
938
1137
    {
939
1138
      if (keyseg->flag & HA_NULL_PART)
940
1139
      {
941
 
        if (!(*key++ = *page++))
942
 
          continue;
 
1140
        if (!(*key++ = *page++))
 
1141
          continue;
943
1142
      }
944
1143
      if (keyseg->flag &
945
 
          (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
 
1144
          (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
946
1145
      {
947
 
        uchar *tmp=page;
948
 
        get_key_length(length,tmp);
949
 
        length+=(uint) (tmp-page);
 
1146
        uchar *tmp=page;
 
1147
        get_key_length(length,tmp);
 
1148
        length+=(uint) (tmp-page);
950
1149
      }
951
1150
      else
952
 
        length=keyseg->length;
 
1151
        length=keyseg->length;
953
1152
    }
954
1153
    memcpy((byte*) key,(byte*) page,(size_t) length);
955
1154
    key+=length;
966
1165
/* key that is packed relatively to previous */
967
1166
 
968
1167
uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
969
 
                             register uchar **page_pos, register uchar *key)
 
1168
                             register uchar **page_pos, register uchar *key)
970
1169
{
971
1170
  reg1 MI_KEYSEG *keyseg;
972
1171
  uchar *start_key,*page=*page_pos,*page_end,*from,*from_end;
981
1180
    if (length > keyinfo->maxlength)
982
1181
    {
983
1182
      DBUG_PRINT("error",("Found too long binary packed key: %d of %d at %lx",
984
 
                          length, keyinfo->maxlength, *page_pos));
 
1183
                          length, keyinfo->maxlength, *page_pos));
985
1184
      DBUG_DUMP("key",(char*) *page_pos,16);
986
1185
      my_errno=HA_ERR_CRASHED;
987
 
      return 0;                                 /* Wrong key */
 
1186
      return 0;                                 /* Wrong key */
988
1187
    }
989
1188
    from=key;  from_end=key+length;
990
1189
  }
991
1190
  else
992
1191
  {
993
 
    from=page; from_end=page_end;               /* Not packed key */
 
1192
    from=page; from_end=page_end;               /* Not packed key */
994
1193
  }
995
1194
 
996
1195
  /*
1004
1203
    {
1005
1204
      if (from == from_end) { from=page;  from_end=page_end; }
1006
1205
      if (!(*key++ = *from++))
1007
 
        continue;                               /* Null part */
 
1206
        continue;                               /* Null part */
1008
1207
    }
1009
1208
    if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
1010
1209
    {
1012
1211
      if (from == from_end) { from=page;  from_end=page_end; }
1013
1212
      if ((length= (*key++ = *from++)) == 255)
1014
1213
      {
1015
 
        if (from == from_end) { from=page;  from_end=page_end; }
1016
 
        length= (uint) ((*key++ = *from++)) << 8;
1017
 
        if (from == from_end) { from=page;  from_end=page_end; }
1018
 
        length+= (uint) ((*key++ = *from++));
 
1214
        if (from == from_end) { from=page;  from_end=page_end; }
 
1215
        length= (uint) ((*key++ = *from++)) << 8;
 
1216
        if (from == from_end) { from=page;  from_end=page_end; }
 
1217
        length+= (uint) ((*key++ = *from++));
1019
1218
      }
1020
1219
    }
1021
1220
    else
1023
1222
 
1024
1223
    if ((tmp=(uint) (from_end-from)) <= length)
1025
1224
    {
1026
 
      key+=tmp;                                 /* Use old key */
 
1225
      key+=tmp;                                 /* Use old key */
1027
1226
      length-=tmp;
1028
1227
      from=page; from_end=page_end;
1029
1228
    }
1034
1233
  length=keyseg->length+nod_flag;
1035
1234
  if ((tmp=(uint) (from_end-from)) <= length)
1036
1235
  {
1037
 
    memcpy(key+tmp,page,length-tmp);            /* Get last part of key */
 
1236
    memcpy(key+tmp,page,length-tmp);            /* Get last part of key */
1038
1237
    *page_pos= page+length-tmp;
1039
1238
  }
1040
1239
  else
1043
1242
    {
1044
1243
      DBUG_PRINT("error",("Error when unpacking key"));
1045
1244
      my_errno=HA_ERR_CRASHED;
1046
 
      return 0;                                 /* Error */
 
1245
      return 0;                                 /* Error */
1047
1246
    }
1048
1247
    memcpy((byte*) key,(byte*) from,(size_t) length);
1049
1248
    *page_pos= from+length;
1052
1251
}
1053
1252
 
1054
1253
 
1055
 
        /* Get key at position without knowledge of previous key */
1056
 
        /* Returns pointer to next key */
 
1254
        /* Get key at position without knowledge of previous key */
 
1255
        /* Returns pointer to next key */
1057
1256
 
1058
1257
uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
1059
 
                   uchar *key, uchar *keypos, uint *return_key_length)
 
1258
                   uchar *key, uchar *keypos, uint *return_key_length)
1060
1259
{
1061
1260
  uint nod_flag;
1062
1261
  DBUG_ENTER("_mi_get_key");
1070
1269
  else
1071
1270
  {
1072
1271
    page+=2+nod_flag;
1073
 
    key[0]=0;                                   /* safety */
 
1272
    key[0]=0;                                   /* safety */
1074
1273
    while (page <= keypos)
1075
1274
    {
1076
1275
      *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
1077
1276
      if (*return_key_length == 0)
1078
1277
      {
1079
 
        my_errno=HA_ERR_CRASHED;
1080
 
        DBUG_RETURN(0);
 
1278
        my_errno=HA_ERR_CRASHED;
 
1279
        DBUG_RETURN(0);
1081
1280
      }
1082
1281
    }
1083
1282
  }
1086
1285
} /* _mi_get_key */
1087
1286
 
1088
1287
 
1089
 
        /* Get key at position without knowledge of previous key */
1090
 
        /* Returns 0 if ok */
 
1288
        /* Get key at position without knowledge of previous key */
 
1289
        /* Returns 0 if ok */
1091
1290
 
1092
1291
static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
1093
 
                                uchar *key, uchar *keypos,
1094
 
                                uint *return_key_length)
 
1292
                                uchar *key, uchar *keypos,
 
1293
                                uint *return_key_length)
1095
1294
{
1096
1295
  uint nod_flag;
1097
1296
  DBUG_ENTER("_mi_get_prev_key");
1101
1300
  {
1102
1301
    *return_key_length=keyinfo->keylength;
1103
1302
    bmove((byte*) key,(byte*) keypos- *return_key_length-nod_flag,
1104
 
          *return_key_length);
 
1303
          *return_key_length);
1105
1304
    DBUG_RETURN(0);
1106
1305
  }
1107
1306
  else
1108
1307
  {
1109
1308
    page+=2+nod_flag;
1110
 
    key[0]=0;                                   /* safety */
 
1309
    key[0]=0;                                   /* safety */
1111
1310
    while (page < keypos)
1112
1311
    {
1113
1312
      *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
1114
1313
      if (*return_key_length == 0)
1115
1314
      {
1116
 
        my_errno=HA_ERR_CRASHED;
1117
 
        DBUG_RETURN(1);
 
1315
        my_errno=HA_ERR_CRASHED;
 
1316
        DBUG_RETURN(1);
1118
1317
      }
1119
1318
    }
1120
1319
  }
1123
1322
 
1124
1323
 
1125
1324
 
1126
 
        /* Get last key from key-page */
1127
 
        /* Return pointer to where key starts */
 
1325
        /* Get last key from key-page */
 
1326
        /* Return pointer to where key starts */
1128
1327
 
1129
1328
uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
1130
 
                        uchar *lastkey, uchar *endpos, uint *return_key_length)
 
1329
                        uchar *lastkey, uchar *endpos, uint *return_key_length)
1131
1330
{
1132
1331
  uint nod_flag;
1133
1332
  uchar *lastpos;
1152
1351
      *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,lastkey);
1153
1352
      if (*return_key_length == 0)
1154
1353
      {
1155
 
        DBUG_PRINT("error",("Couldn't find last key:  page: %lx",page));
1156
 
        my_errno=HA_ERR_CRASHED;
1157
 
        DBUG_RETURN(0);
 
1354
        DBUG_PRINT("error",("Couldn't find last key:  page: %lx",page));
 
1355
        my_errno=HA_ERR_CRASHED;
 
1356
        DBUG_RETURN(0);
1158
1357
      }
1159
1358
    }
1160
1359
  }
1163
1362
} /* _mi_get_last_key */
1164
1363
 
1165
1364
 
1166
 
        /* Calculate length of key */
 
1365
        /* Calculate length of key */
1167
1366
 
1168
1367
uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
1169
1368
{
1178
1377
  {
1179
1378
    if (keyseg->flag & HA_NULL_PART)
1180
1379
      if (!*key++)
1181
 
        continue;
 
1380
        continue;
1182
1381
    if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
1183
1382
    {
1184
1383
      uint length;
1192
1391
} /* _mi_keylength */
1193
1392
 
1194
1393
 
1195
 
        /* Move a key */
 
1394
        /* Move a key */
1196
1395
 
1197
1396
uchar *_mi_move_key(MI_KEYDEF *keyinfo, uchar *to, uchar *from)
1198
1397
{
1199
1398
  reg1 uint length;
1200
1399
  memcpy((byte*) to, (byte*) from,
1201
 
         (size_t) (length=_mi_keylength(keyinfo,from)));
 
1400
         (size_t) (length=_mi_keylength(keyinfo,from)));
1202
1401
  return to+length;
1203
1402
}
1204
1403
 
1205
 
        /* Find next/previous record with same key */
1206
 
        /* This can't be used when database is touched after last read */
 
1404
        /* Find next/previous record with same key */
 
1405
        /* This can't be used when database is touched after last read */
1207
1406
 
1208
1407
int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo,
1209
 
                    uchar *key, uint key_length, uint nextflag, my_off_t pos)
 
1408
                    uchar *key, uint key_length, uint nextflag, my_off_t pos)
1210
1409
{
1211
1410
  int error;
1212
1411
  uint nod_flag;
1213
1412
  uchar lastkey[MI_MAX_KEY_BUFF];
1214
1413
  DBUG_ENTER("_mi_search_next");
1215
1414
  DBUG_PRINT("enter",("nextflag: %d  lastpos: %ld  int_keypos: %lx",
1216
 
                       nextflag,(long) info->lastpos,info->int_keypos));
 
1415
                       nextflag,(long) info->lastpos,info->int_keypos));
1217
1416
  DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,key_length););
1218
1417
 
1219
1418
  /* Force full read if we are at last key or if we are not on a leaf
1228
1427
      (info->int_keytree_version != keyinfo->version &&
1229
1428
       (info->int_nod_flag || info->buff_used)))
1230
1429
    DBUG_RETURN(_mi_search(info,keyinfo,key,key_length,
1231
 
                           nextflag | SEARCH_SAVE_BUFF, pos));
 
1430
                           nextflag | SEARCH_SAVE_BUFF, pos));
1232
1431
 
1233
1432
  if (info->buff_used)
1234
1433
  {
1235
1434
    if (!_mi_fetch_keypage(info,keyinfo,info->last_search_keypage,
1236
 
                           info->buff,0))
 
1435
                           info->buff,0))
1237
1436
      DBUG_RETURN(-1);
1238
1437
    info->buff_used=0;
1239
1438
  }
1242
1441
  nod_flag=mi_test_if_nod(info->buff);
1243
1442
  memcpy(lastkey,key,key_length);
1244
1443
 
1245
 
  if (nextflag & SEARCH_BIGGER)                                 /* Next key */
 
1444
  if (nextflag & SEARCH_BIGGER)                                 /* Next key */
1246
1445
  {
1247
1446
    my_off_t tmp_pos=_mi_kpos(nod_flag,info->int_keypos);
1248
1447
    if (tmp_pos != HA_OFFSET_ERROR)
1249
1448
    {
1250
1449
      if ((error=_mi_search(info,keyinfo,key,key_length,
1251
 
                            nextflag | SEARCH_SAVE_BUFF, tmp_pos)) <=0)
1252
 
        DBUG_RETURN(error);
 
1450
                            nextflag | SEARCH_SAVE_BUFF, tmp_pos)) <=0)
 
1451
        DBUG_RETURN(error);
1253
1452
    }
1254
1453
    if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,
1255
 
                                                   &info->int_keypos,lastkey)))
 
1454
                                                   &info->int_keypos,lastkey)))
1256
1455
      DBUG_RETURN(-1);
1257
1456
  }
1258
 
  else                                                  /* Previous key */
 
1457
  else                                                  /* Previous key */
1259
1458
  {
1260
1459
    uint length;
1261
1460
    /* Find start of previous key */
1262
1461
    info->int_keypos=_mi_get_last_key(info,keyinfo,info->buff,lastkey,
1263
 
                                      info->int_keypos, &length);
 
1462
                                      info->int_keypos, &length);
1264
1463
    if (!info->int_keypos)
1265
1464
      DBUG_RETURN(-1);
1266
1465
    if (info->int_keypos == info->buff+2)
1267
1466
      DBUG_RETURN(_mi_search(info,keyinfo,key,key_length,
1268
 
                             nextflag | SEARCH_SAVE_BUFF, pos));
 
1467
                             nextflag | SEARCH_SAVE_BUFF, pos));
1269
1468
    if ((error=_mi_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
1270
 
                          _mi_kpos(nod_flag,info->int_keypos))) <= 0)
 
1469
                          _mi_kpos(nod_flag,info->int_keypos))) <= 0)
1271
1470
      DBUG_RETURN(error);
1272
1471
 
1273
1472
    if (! _mi_get_last_key(info,keyinfo,info->buff,lastkey,
1274
 
                           info->int_keypos,&info->lastkey_length))
 
1473
                           info->int_keypos,&info->lastkey_length))
1275
1474
      DBUG_RETURN(-1);
1276
1475
  }
1277
1476
  memcpy(info->lastkey,lastkey,info->lastkey_length);
1281
1480
} /* _mi_search_next */
1282
1481
 
1283
1482
 
1284
 
        /* Search after position for the first row in an index */
1285
 
        /* This is stored in info->lastpos */
 
1483
        /* Search after position for the first row in an index */
 
1484
        /* This is stored in info->lastpos */
1286
1485
 
1287
1486
int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo,
1288
 
                     register my_off_t pos)
 
1487
                     register my_off_t pos)
1289
1488
{
1290
1489
  uint nod_flag;
1291
1490
  uchar *page;
1310
1509
  } while ((pos=_mi_kpos(nod_flag,page)) != HA_OFFSET_ERROR);
1311
1510
 
1312
1511
  info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
1313
 
                                           info->lastkey);
 
1512
                                           info->lastkey);
1314
1513
  info->int_keypos=page; info->int_maxpos=info->buff+mi_getint(info->buff)-1;
1315
1514
  info->int_nod_flag=nod_flag;
1316
1515
  info->int_keytree_version=keyinfo->version;
1323
1522
} /* _mi_search_first */
1324
1523
 
1325
1524
 
1326
 
        /* Search after position for the last row in an index */
1327
 
        /* This is stored in info->lastpos */
 
1525
        /* Search after position for the last row in an index */
 
1526
        /* This is stored in info->lastpos */
1328
1527
 
1329
1528
int _mi_search_last(register MI_INFO *info, register MI_KEYDEF *keyinfo,
1330
 
                    register my_off_t pos)
 
1529
                    register my_off_t pos)
1331
1530
{
1332
1531
  uint nod_flag;
1333
1532
  uchar *buff,*page;
1335
1534
 
1336
1535
  if (pos == HA_OFFSET_ERROR)
1337
1536
  {
1338
 
    my_errno=HA_ERR_KEY_NOT_FOUND;                      /* Didn't find key */
 
1537
    my_errno=HA_ERR_KEY_NOT_FOUND;                      /* Didn't find key */
1339
1538
    info->lastpos= HA_OFFSET_ERROR;
1340
1539
    DBUG_RETURN(-1);
1341
1540
  }
1353
1552
  } while ((pos=_mi_kpos(nod_flag,page)) != HA_OFFSET_ERROR);
1354
1553
 
1355
1554
  if (!_mi_get_last_key(info,keyinfo,buff,info->lastkey,page,
1356
 
                        &info->lastkey_length))
 
1555
                        &info->lastkey_length))
1357
1556
    DBUG_RETURN(-1);
1358
1557
  info->lastpos=_mi_dpos(info,0,info->lastkey+info->lastkey_length);
1359
1558
  info->int_keypos=info->int_maxpos=page;
1373
1572
** Functions to store and pack a key in a page
1374
1573
**
1375
1574
** mi_calc_xx_key_length takes the following arguments:
1376
 
**  nod_flag    If nod: Length of nod-pointer
1377
 
**  next_key    Position to pos after the new key in buffer
1378
 
**  org_key     Key that was before the next key in buffer
1379
 
**  prev_key    Last key before current key
1380
 
**  key         Key that will be stored
1381
 
**  s_temp      Information how next key will be packed
 
1575
**  nod_flag    If nod: Length of nod-pointer
 
1576
**  next_key    Position to pos after the new key in buffer
 
1577
**  org_key     Key that was before the next key in buffer
 
1578
**  prev_key    Last key before current key
 
1579
**  key         Key that will be stored
 
1580
**  s_temp      Information how next key will be packed
1382
1581
****************************************************************************/
1383
1582
 
1384
1583
/* Static length key */
1385
1584
 
1386
1585
int
1387
1586
_mi_calc_static_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
1388
 
                           uchar *next_pos  __attribute__((unused)),
1389
 
                           uchar *org_key  __attribute__((unused)),
1390
 
                           uchar *prev_key __attribute__((unused)),
1391
 
                           uchar *key, MI_KEY_PARAM *s_temp)
 
1587
                           uchar *next_pos  __attribute__((unused)),
 
1588
                           uchar *org_key  __attribute__((unused)),
 
1589
                           uchar *prev_key __attribute__((unused)),
 
1590
                           uchar *key, MI_KEY_PARAM *s_temp)
1392
1591
{
1393
1592
  s_temp->key=key;
1394
1593
  return (int) (s_temp->totlength=keyinfo->keylength+nod_flag);
1398
1597
 
1399
1598
int
1400
1599
_mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
1401
 
                        uchar *next_pos  __attribute__((unused)),
1402
 
                        uchar *org_key  __attribute__((unused)),
1403
 
                        uchar *prev_key __attribute__((unused)),
1404
 
                        uchar *key, MI_KEY_PARAM *s_temp)
 
1600
                        uchar *next_pos  __attribute__((unused)),
 
1601
                        uchar *org_key  __attribute__((unused)),
 
1602
                        uchar *prev_key __attribute__((unused)),
 
1603
                        uchar *key, MI_KEY_PARAM *s_temp)
1405
1604
{
1406
1605
  s_temp->key=key;
1407
1606
  return (int) (s_temp->totlength=_mi_keylength(keyinfo,key)+nod_flag);
1416
1615
  If the max length of first key segment <= 127 characters the prefix is
1417
1616
  1 byte else it's 2 byte
1418
1617
 
1419
 
  prefix byte    The high bit is set if this is a prefix for the prev key
1420
 
  length         Packed length if the previous was a prefix byte
1421
 
  [length]       Length character of data
1422
 
  next-key-seg   Next key segments
 
1618
  prefix byte    The high bit is set if this is a prefix for the prev key
 
1619
  length         Packed length if the previous was a prefix byte
 
1620
  [length]       Length character of data
 
1621
  next-key-seg   Next key segments
1423
1622
 
1424
1623
  If the first segment can have NULL:
1425
1624
  The length is 0 for NULLS and 1+length for not null columns.
1428
1627
 
1429
1628
int
1430
1629
_mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
1431
 
                             uchar *org_key, uchar *prev_key, uchar *key,
1432
 
                             MI_KEY_PARAM *s_temp)
 
1630
                             uchar *org_key, uchar *prev_key, uchar *key,
 
1631
                             MI_KEY_PARAM *s_temp)
1433
1632
{
1434
1633
  reg1 MI_KEYSEG *keyseg;
1435
1634
  int length;
1470
1669
      s_temp->key=key;
1471
1670
      s_temp->ref_length=s_temp->key_length=0;
1472
1671
      s_temp->totlength=key_length-1+diff_flag;
1473
 
      s_temp->next_key_pos=0;                   /* No next key */
 
1672
      s_temp->next_key_pos=0;                   /* No next key */
1474
1673
      return (s_temp->totlength);
1475
1674
    }
1476
1675
    s_temp->store_not_null=1;
1477
 
    key_length--;                               /* We don't store NULL */
 
1676
    key_length--;                               /* We don't store NULL */
1478
1677
    if (prev_key && !*prev_key++)
1479
 
      org_key=prev_key=0;                       /* Can't pack against prev */
 
1678
      org_key=prev_key=0;                       /* Can't pack against prev */
1480
1679
    else if (org_key)
1481
 
      org_key++;                                /* Skipp NULL */
 
1680
      org_key++;                                /* Skipp NULL */
1482
1681
  }
1483
1682
  else
1484
1683
    s_temp->store_not_null=0;
1494
1693
  if (prev_key)
1495
1694
  {
1496
1695
    get_key_length(org_key_length,prev_key);
1497
 
    s_temp->prev_key=prev_key;          /* Pointer at data */
 
1696
    s_temp->prev_key=prev_key;          /* Pointer at data */
1498
1697
    /* Don't use key-pack if length == 0 */
1499
1698
    if (new_key_length && new_key_length == org_key_length)
1500
1699
      same_length=1;
1501
1700
    else if (new_key_length > org_key_length)
1502
1701
      end=key + org_key_length;
1503
1702
 
1504
 
    if (sort_order)                             /* SerG */
 
1703
    if (sort_order)                             /* SerG */
1505
1704
    {
1506
1705
      while (key < end && sort_order[*key] == sort_order[*prev_key])
1507
1706
      {
1512
1711
    {
1513
1712
      while (key < end && *key == *prev_key)
1514
1713
      {
1515
 
        key++; prev_key++;
 
1714
        key++; prev_key++;
1516
1715
      }
1517
1716
    }
1518
1717
  }
1527
1726
    length=(int) key_length-(int) (key_end-start)-length_pack;
1528
1727
    length+= diff_flag;
1529
1728
    if (next_key)
1530
 
    {                                           /* Can't combine with next */
1531
 
      s_temp->n_length= *next_key;              /* Needed by _mi_store_key */
 
1729
    {                                           /* Can't combine with next */
 
1730
      s_temp->n_length= *next_key;              /* Needed by _mi_store_key */
1532
1731
      next_key=0;
1533
1732
    }
1534
1733
  }
1535
1734
  else
1536
1735
  {
1537
1736
    if (start != key)
1538
 
    {                                           /* Starts as prev key */
 
1737
    {                                           /* Starts as prev key */
1539
1738
      ref_length= (uint) (key-start);
1540
1739
      s_temp->ref_length= ref_length + pack_marker;
1541
1740
      length= (int) (key_length - ref_length);
1546
1745
    }
1547
1746
    else
1548
1747
    {
1549
 
      s_temp->key_length+=s_temp->store_not_null;       /* If null */
 
1748
      s_temp->key_length+=s_temp->store_not_null;       /* If null */
1550
1749
      length= key_length - length_pack+ diff_flag;
1551
1750
    }
1552
1751
  }
1553
1752
  s_temp->totlength=(uint) length;
1554
1753
  s_temp->prev_length=0;
1555
1754
  DBUG_PRINT("test",("tot_length: %d  length: %d  uniq_key_length: %d",
1556
 
                     key_length,length,s_temp->key_length));
 
1755
                     key_length,length,s_temp->key_length));
1557
1756
 
1558
 
        /* If something after that hasn't length=0, test if we can combine */
 
1757
        /* If something after that hasn't length=0, test if we can combine */
1559
1758
  if ((s_temp->next_key_pos=next_key))
1560
1759
  {
1561
1760
    uint packed,n_length;
1571
1770
    if (!packed)
1572
1771
      n_length-= s_temp->store_not_null;
1573
1772
 
1574
 
    if (n_length || packed)             /* Don't pack 0 length keys */
 
1773
    if (n_length || packed)             /* Don't pack 0 length keys */
1575
1774
    {
1576
1775
      uint next_length_pack, new_ref_length=s_temp->ref_length;
1577
1776
 
1578
1777
      if (packed)
1579
1778
      {
1580
 
        /* If first key and next key is packed (only on delete) */
1581
 
        if (!prev_key && org_key)
1582
 
        {
1583
 
          get_key_length(org_key_length,org_key);
1584
 
          key=start;
1585
 
          if (sort_order)                       /* SerG */
1586
 
          {
1587
 
            while (key < end && sort_order[*key] == sort_order[*org_key])
1588
 
            {
1589
 
              key++; org_key++;
1590
 
            }
1591
 
          }
1592
 
          else
1593
 
          {
1594
 
            while (key < end && *key == *org_key)
1595
 
            {
1596
 
              key++; org_key++;
1597
 
            }
1598
 
          }
1599
 
          if ((new_ref_length= (uint) (key - start)))
1600
 
            new_ref_length+=pack_marker;
1601
 
        }
1602
 
 
1603
 
        if (!n_length)
1604
 
        {
1605
 
          /*
1606
 
            We put a different key between two identical variable length keys
1607
 
            Extend next key to have same prefix as this key
1608
 
          */
1609
 
          if (new_ref_length)                   /* prefix of previus key */
1610
 
          {                                     /* make next key longer */
1611
 
            s_temp->part_of_prev_key= new_ref_length;
1612
 
            s_temp->prev_length=          org_key_length -
1613
 
              (new_ref_length-pack_marker);
1614
 
            s_temp->n_ref_length= s_temp->n_length= s_temp->prev_length;
1615
 
            n_length=             get_pack_length(s_temp->prev_length);
1616
 
            s_temp->prev_key+=    (new_ref_length - pack_marker);
1617
 
            length+=              s_temp->prev_length + n_length;
1618
 
          }
1619
 
          else
1620
 
          {                                     /* Can't use prev key */
1621
 
            s_temp->part_of_prev_key=0;
1622
 
            s_temp->prev_length= org_key_length;
1623
 
            s_temp->n_ref_length=s_temp->n_length=  org_key_length;
1624
 
            length+=           org_key_length;
1625
 
            /* +get_pack_length(org_key_length); */
1626
 
          }
1627
 
          return (int) length;
1628
 
        }
1629
 
 
1630
 
        ref_length=n_length;
1631
 
        get_key_pack_length(n_length,next_length_pack,next_key);
1632
 
 
1633
 
        /* Test if new keys has fewer characters that match the previous key */
1634
 
        if (!new_ref_length)
1635
 
        {                                       /* Can't use prev key */
1636
 
          s_temp->part_of_prev_key=     0;
1637
 
          s_temp->prev_length=          ref_length;
1638
 
          s_temp->n_ref_length= s_temp->n_length= n_length+ref_length;
1639
 
          /* s_temp->prev_key+=         get_pack_length(org_key_length); */
1640
 
          return (int) length+ref_length-next_length_pack;
1641
 
        }
1642
 
        if (ref_length+pack_marker > new_ref_length)
1643
 
        {
1644
 
          uint new_pack_length=new_ref_length-pack_marker;
1645
 
          /* We must copy characters from the original key to the next key */
1646
 
          s_temp->part_of_prev_key= new_ref_length;
1647
 
          s_temp->prev_length=      ref_length - new_pack_length;
1648
 
          s_temp->n_ref_length=s_temp->n_length=n_length + s_temp->prev_length;
1649
 
          s_temp->prev_key+=        new_pack_length;
1650
 
/*                                  +get_pack_length(org_key_length); */
1651
 
          length= length-get_pack_length(ref_length)+
1652
 
            get_pack_length(new_pack_length);
1653
 
          return (int) length + s_temp->prev_length;
1654
 
        }
 
1779
        /* If first key and next key is packed (only on delete) */
 
1780
        if (!prev_key && org_key)
 
1781
        {
 
1782
          get_key_length(org_key_length,org_key);
 
1783
          key=start;
 
1784
          if (sort_order)                       /* SerG */
 
1785
          {
 
1786
            while (key < end && sort_order[*key] == sort_order[*org_key])
 
1787
            {
 
1788
              key++; org_key++;
 
1789
            }
 
1790
          }
 
1791
          else
 
1792
          {
 
1793
            while (key < end && *key == *org_key)
 
1794
            {
 
1795
              key++; org_key++;
 
1796
            }
 
1797
          }
 
1798
          if ((new_ref_length= (uint) (key - start)))
 
1799
            new_ref_length+=pack_marker;
 
1800
        }
 
1801
 
 
1802
        if (!n_length)
 
1803
        {
 
1804
          /*
 
1805
            We put a different key between two identical variable length keys
 
1806
            Extend next key to have same prefix as this key
 
1807
          */
 
1808
          if (new_ref_length)                   /* prefix of previus key */
 
1809
          {                                     /* make next key longer */
 
1810
            s_temp->part_of_prev_key= new_ref_length;
 
1811
            s_temp->prev_length=          org_key_length -
 
1812
              (new_ref_length-pack_marker);
 
1813
            s_temp->n_ref_length= s_temp->n_length= s_temp->prev_length;
 
1814
            n_length=             get_pack_length(s_temp->prev_length);
 
1815
            s_temp->prev_key+=    (new_ref_length - pack_marker);
 
1816
            length+=              s_temp->prev_length + n_length;
 
1817
          }
 
1818
          else
 
1819
          {                                     /* Can't use prev key */
 
1820
            s_temp->part_of_prev_key=0;
 
1821
            s_temp->prev_length= org_key_length;
 
1822
            s_temp->n_ref_length=s_temp->n_length=  org_key_length;
 
1823
            length+=           org_key_length;
 
1824
            /* +get_pack_length(org_key_length); */
 
1825
          }
 
1826
          return (int) length;
 
1827
        }
 
1828
 
 
1829
        ref_length=n_length;
 
1830
        get_key_pack_length(n_length,next_length_pack,next_key);
 
1831
 
 
1832
        /* Test if new keys has fewer characters that match the previous key */
 
1833
        if (!new_ref_length)
 
1834
        {                                       /* Can't use prev key */
 
1835
          s_temp->part_of_prev_key=     0;
 
1836
          s_temp->prev_length=          ref_length;
 
1837
          s_temp->n_ref_length= s_temp->n_length= n_length+ref_length;
 
1838
          /* s_temp->prev_key+=         get_pack_length(org_key_length); */
 
1839
          return (int) length+ref_length-next_length_pack;
 
1840
        }
 
1841
        if (ref_length+pack_marker > new_ref_length)
 
1842
        {
 
1843
          uint new_pack_length=new_ref_length-pack_marker;
 
1844
          /* We must copy characters from the original key to the next key */
 
1845
          s_temp->part_of_prev_key= new_ref_length;
 
1846
          s_temp->prev_length=      ref_length - new_pack_length;
 
1847
          s_temp->n_ref_length=s_temp->n_length=n_length + s_temp->prev_length;
 
1848
          s_temp->prev_key+=        new_pack_length;
 
1849
/*                                  +get_pack_length(org_key_length); */
 
1850
          length= length-get_pack_length(ref_length)+
 
1851
            get_pack_length(new_pack_length);
 
1852
          return (int) length + s_temp->prev_length;
 
1853
        }
1655
1854
      }
1656
1855
      else
1657
1856
      {
1658
 
        /* Next key wasn't a prefix of previous key */
1659
 
        ref_length=0;
1660
 
        next_length_pack=0;
 
1857
        /* Next key wasn't a prefix of previous key */
 
1858
        ref_length=0;
 
1859
        next_length_pack=0;
1661
1860
     }
1662
1861
      DBUG_PRINT("test",("length: %d  next_key: %lx",length,next_key));
1663
1862
 
1664
1863
      {
1665
 
        uint tmp_length;
1666
 
        key=(start+=ref_length);
1667
 
        if (key+n_length < key_end)             /* Normalize length based */
1668
 
          key_end=key+n_length;
1669
 
        if (sort_order)                         /* SerG */
1670
 
        {
 
1864
        uint tmp_length;
 
1865
        key=(start+=ref_length);
 
1866
        if (key+n_length < key_end)             /* Normalize length based */
 
1867
          key_end=key+n_length;
 
1868
        if (sort_order)                         /* SerG */
 
1869
        {
1671
1870
          while (key < key_end && sort_order[*key] ==
1672
 
                 sort_order[*next_key])
1673
 
          {
1674
 
            key++; next_key++;
1675
 
          }
1676
 
        }
1677
 
        else
1678
 
        {
1679
 
          while (key < key_end && *key == *next_key)
1680
 
          {
1681
 
            key++; next_key++;
1682
 
          }
1683
 
        }
1684
 
        if (!(tmp_length=(uint) (key-start)))
1685
 
        {                                       /* Key can't be re-packed */
1686
 
          s_temp->next_key_pos=0;
1687
 
          return length;
1688
 
        }
1689
 
        ref_length+=tmp_length;
1690
 
        n_length-=tmp_length;
1691
 
        length-=tmp_length+next_length_pack;    /* We gained these chars */
 
1871
                 sort_order[*next_key])
 
1872
          {
 
1873
            key++; next_key++;
 
1874
          }
 
1875
        }
 
1876
        else
 
1877
        {
 
1878
          while (key < key_end && *key == *next_key)
 
1879
          {
 
1880
            key++; next_key++;
 
1881
          }
 
1882
        }
 
1883
        if (!(tmp_length=(uint) (key-start)))
 
1884
        {                                       /* Key can't be re-packed */
 
1885
          s_temp->next_key_pos=0;
 
1886
          return length;
 
1887
        }
 
1888
        ref_length+=tmp_length;
 
1889
        n_length-=tmp_length;
 
1890
        length-=tmp_length+next_length_pack;    /* We gained these chars */
1692
1891
      }
1693
1892
      if (n_length == 0)
1694
1893
      {
1695
 
        s_temp->n_ref_length=pack_marker;       /* Same as prev key */
 
1894
        s_temp->n_ref_length=pack_marker;       /* Same as prev key */
1696
1895
      }
1697
1896
      else
1698
1897
      {
1699
 
        s_temp->n_ref_length=ref_length | pack_marker;
1700
 
        length+= get_pack_length(n_length);
1701
 
        s_temp->n_length=n_length;
 
1898
        s_temp->n_ref_length=ref_length | pack_marker;
 
1899
        length+= get_pack_length(n_length);
 
1900
        s_temp->n_length=n_length;
1702
1901
      }
1703
1902
    }
1704
1903
  }
1710
1909
 
1711
1910
int
1712
1911
_mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
1713
 
                             uchar *org_key, uchar *prev_key, uchar *key,
1714
 
                             MI_KEY_PARAM *s_temp)
 
1912
                             uchar *org_key, uchar *prev_key, uchar *key,
 
1913
                             MI_KEY_PARAM *s_temp)
1715
1914
{
1716
1915
  uint length,key_length,ref_length;
1717
1916
 
1718
1917
  s_temp->totlength=key_length=_mi_keylength(keyinfo,key)+nod_flag;
1719
1918
  s_temp->key=key;
1720
1919
  s_temp->prev_key=org_key;
1721
 
  if (prev_key)                                 /* If not first key in block */
 
1920
  if (prev_key)                                 /* If not first key in block */
1722
1921
  {
1723
1922
    /* pack key against previous key */
1724
1923
    /*
1737
1936
    s_temp->ref_length=ref_length=0;
1738
1937
    length=key_length+1;
1739
1938
  }
1740
 
  if ((s_temp->next_key_pos=next_key))          /* If another key after */
 
1939
  if ((s_temp->next_key_pos=next_key))          /* If another key after */
1741
1940
  {
1742
1941
    /* pack key against next key */
1743
1942
    uint next_length,next_length_pack;
1748
1947
    {
1749
1948
      uchar *end;
1750
1949
      for (key= s_temp->key, end=key+next_length ;
1751
 
           *key == *org_key && key < end;
1752
 
           key++,org_key++) ;
 
1950
           *key == *org_key && key < end;
 
1951
           key++,org_key++) ;
1753
1952
      ref_length= (uint) (key - s_temp->key);
1754
1953
    }
1755
1954
 
1756
1955
    if (next_length > ref_length)
1757
1956
    {
1758
1957
      /* We put a key with different case between two keys with the same prefix
1759
 
         Extend next key to have same prefix as
1760
 
         this key */
 
1958
         Extend next key to have same prefix as
 
1959
         this key */
1761
1960
      s_temp->n_ref_length= ref_length;
1762
1961
      s_temp->prev_length=  next_length-ref_length;
1763
1962
      s_temp->prev_key+=    ref_length;
1764
1963
      return (int) (length+ s_temp->prev_length - next_length_pack +
1765
 
                    get_pack_length(ref_length));
 
1964
                    get_pack_length(ref_length));
1766
1965
    }
1767
1966
    /* Check how many characters are identical to next key */
1768
1967
    key= s_temp->key+next_length;
1770
1969
    if ((ref_length= (uint) (key - s_temp->key)-1) == next_length)
1771
1970
    {
1772
1971
      s_temp->next_key_pos=0;
1773
 
      return length;                            /* can't pack next key */
 
1972
      return length;                            /* can't pack next key */
1774
1973
    }
1775
1974
    s_temp->prev_length=0;
1776
1975
    s_temp->n_ref_length=ref_length;
1777
1976
    return (int) (length-(ref_length - next_length) - next_length_pack +
1778
 
                  get_pack_length(ref_length));
 
1977
                  get_pack_length(ref_length));
1779
1978
  }
1780
1979
  return (int) length;
1781
1980
}
1788
1987
/* store key without compression */
1789
1988
 
1790
1989
void _mi_store_static_key(MI_KEYDEF *keyinfo __attribute__((unused)),
1791
 
                          register uchar *key_pos,
1792
 
                          register MI_KEY_PARAM *s_temp)
 
1990
                          register uchar *key_pos,
 
1991
                          register MI_KEY_PARAM *s_temp)
1793
1992
{
1794
1993
  memcpy((byte*) key_pos,(byte*) s_temp->key,(size_t) s_temp->totlength);
1795
1994
}
1803
2002
 
1804
2003
 
1805
2004
void _mi_store_var_pack_key(MI_KEYDEF *keyinfo  __attribute__((unused)),
1806
 
                            register uchar *key_pos,
1807
 
                            register MI_KEY_PARAM *s_temp)
 
2005
                            register uchar *key_pos,
 
2006
                            register MI_KEY_PARAM *s_temp)
1808
2007
{
1809
2008
  uint length;
1810
2009
  uchar *start;
1825
2024
    store_pack_length(s_temp->pack_marker == 128,key_pos,s_temp->key_length);
1826
2025
  }
1827
2026
  bmove((byte*) key_pos,(byte*) s_temp->key,
1828
 
        (length=s_temp->totlength-(uint) (key_pos-start)));
 
2027
        (length=s_temp->totlength-(uint) (key_pos-start)));
1829
2028
 
1830
 
  if (!s_temp->next_key_pos)                    /* No following key */
 
2029
  if (!s_temp->next_key_pos)                    /* No following key */
1831
2030
    return;
1832
2031
  key_pos+=length;
1833
2032
 
1837
2036
    if (s_temp->part_of_prev_key)
1838
2037
    {
1839
2038
      store_pack_length(s_temp->pack_marker == 128,key_pos,
1840
 
                        s_temp->part_of_prev_key);
 
2039
                        s_temp->part_of_prev_key);
1841
2040
      store_key_length_inc(key_pos,s_temp->n_length);
1842
2041
    }
1843
2042
    else
1844
2043
    {
1845
2044
      s_temp->n_length+= s_temp->store_not_null;
1846
2045
      store_pack_length(s_temp->pack_marker == 128,key_pos,
1847
 
                        s_temp->n_length);
 
2046
                        s_temp->n_length);
1848
2047
    }
1849
2048
    memcpy(key_pos, s_temp->prev_key, s_temp->prev_length);
1850
2049
  }
1852
2051
  {
1853
2052
    store_pack_length(s_temp->pack_marker == 128,key_pos,s_temp->n_ref_length);
1854
2053
    if (s_temp->n_ref_length == s_temp->pack_marker)
1855
 
      return;                                   /* Identical key */
 
2054
      return;                                   /* Identical key */
1856
2055
    store_key_length(key_pos,s_temp->n_length);
1857
2056
  }
1858
2057
  else
1866
2065
/* variable length key with prefix compression */
1867
2066
 
1868
2067
void _mi_store_bin_pack_key(MI_KEYDEF *keyinfo  __attribute__((unused)),
1869
 
                            register uchar *key_pos,
1870
 
                            register MI_KEY_PARAM *s_temp)
 
2068
                            register uchar *key_pos,
 
2069
                            register MI_KEY_PARAM *s_temp)
1871
2070
{
1872
2071
  store_key_length_inc(key_pos,s_temp->ref_length);
1873
2072
  memcpy((char*) key_pos,(char*) s_temp->key+s_temp->ref_length,
1874
 
          (size_t) s_temp->totlength-s_temp->ref_length);
 
2073
          (size_t) s_temp->totlength-s_temp->ref_length);
1875
2074
 
1876
2075
  if (s_temp->next_key_pos)
1877
2076
  {
1878
2077
    key_pos+=(uint) (s_temp->totlength-s_temp->ref_length);
1879
2078
    store_key_length_inc(key_pos,s_temp->n_ref_length);
1880
 
    if (s_temp->prev_length)                    /* If we must extend key */
 
2079
    if (s_temp->prev_length)                    /* If we must extend key */
1881
2080
    {
1882
2081
      memcpy(key_pos,s_temp->prev_key,s_temp->prev_length);
1883
2082
    }