_search.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:25k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* S|ker efter positionen f|r en nyckel samt d{rmedh|rande funktioner */
  14. #include "isamdef.h"
  15. #include "m_ctype.h"
  16. #define CMP(a,b) (a<b ? -1 : a == b ? 0 : 1)
  17. /* Check index */
  18. int _nisam_check_index(N_INFO *info, int inx)
  19. {
  20.   if (inx == -1) /* Use last index */
  21.     inx=info->lastinx;
  22.   if (inx >= (int) info->s->state.keys || inx < 0)
  23.   {
  24.     my_errno=HA_ERR_WRONG_INDEX;
  25.     return -1;
  26.   }
  27.   if (info->lastinx != inx) /* Index changed */
  28.   {
  29.     info->lastinx = inx;
  30.     info->lastpos = NI_POS_ERROR;
  31.     info->update= ((info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED)) |
  32.    HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
  33.   }
  34.   if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache))
  35.     return(-1);
  36.   return(inx);
  37. } /* ni_check_index */
  38. /* S|ker reda p} positionen f|r ett record p} basen av en nyckel */
  39. /* Positionen l{ggs i info->lastpos */
  40. /* Returns -1 if not found and 1 if search at upper levels */
  41. int _nisam_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, uint key_len, uint nextflag, register ulong pos)
  42. {
  43.   int error,flag;
  44.   uint nod_flag;
  45.   uchar *keypos,*maxpos;
  46.   uchar lastkey[N_MAX_KEY_BUFF],*buff;
  47.   DBUG_ENTER("_nisam_search");
  48.   DBUG_PRINT("enter",("pos: %ld  nextflag: %d  lastpos: %ld",
  49.       pos,nextflag,info->lastpos));
  50.   if (pos == NI_POS_ERROR)
  51.   {
  52.     my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
  53.     info->lastpos= NI_POS_ERROR;
  54.     if (!(nextflag & (SEARCH_SMALLER | SEARCH_BIGGER | SEARCH_LAST)))
  55.       DBUG_RETURN(-1); /* Not found ; return error */
  56.     DBUG_RETURN(1); /* Search at upper levels */
  57.   }
  58.   if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,
  59.        test(!(nextflag & SEARCH_SAVE_BUFF)))))
  60.     goto err;
  61.   DBUG_DUMP("page",(byte*) buff,getint(buff));
  62.   flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
  63.       &keypos,lastkey);
  64.   nod_flag=test_if_nod(buff);
  65.   maxpos=buff+getint(buff)-1;
  66.   if (flag)
  67.   {
  68.     if ((error=_nisam_search(info,keyinfo,key,key_len,nextflag,
  69.   _nisam_kpos(nod_flag,keypos))) <= 0)
  70.       DBUG_RETURN(error);
  71.     if (flag >0)
  72.     {
  73.       if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) &&
  74.   keypos == buff+2+nod_flag)
  75. DBUG_RETURN(1); /* Bigger than key */
  76.     }
  77.     else if (nextflag & SEARCH_BIGGER && keypos >= maxpos)
  78.       DBUG_RETURN(1); /* Smaller than key */
  79.   }
  80.   else
  81.   {
  82.     if (nextflag & SEARCH_FIND && (!(keyinfo->base.flag & HA_NOSAME)
  83.    || key_len) && nod_flag)
  84.     {
  85.       if ((error=_nisam_search(info,keyinfo,key,key_len,SEARCH_FIND,
  86.     _nisam_kpos(nod_flag,keypos))) >= 0 ||
  87.   my_errno != HA_ERR_KEY_NOT_FOUND)
  88. DBUG_RETURN(error);
  89.       info->int_pos= NI_POS_ERROR; /* Buffer not in memory */
  90.     }
  91.   }
  92.   if (pos != info->int_pos)
  93.   {
  94.     uchar *old_buff=buff;
  95.     if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,
  96.  test(!(nextflag & SEARCH_SAVE_BUFF)))))
  97.       goto err;
  98.     keypos=buff+(keypos-old_buff);
  99.     maxpos=buff+(maxpos-old_buff);
  100.   }
  101.   if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0)
  102.   {
  103.     keypos=_nisam_get_last_key(info,keyinfo,buff,lastkey,keypos);
  104.     if (!(nextflag & SEARCH_SMALLER) &&
  105. _nisam_key_cmp(keyinfo->seg, lastkey, key, key_len, SEARCH_FIND))
  106.     {
  107.       my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
  108.       goto err;
  109.     }
  110.   }
  111.   VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey));
  112.   VOID(_nisam_move_key(keyinfo,info->lastkey,lastkey));
  113.   info->lastpos=_nisam_dpos(info,nod_flag,keypos);
  114.   info->int_keypos=info->buff+ (keypos-buff);
  115.   info->int_maxpos=info->buff+ (maxpos-buff);
  116.   info->page_changed=0;
  117.   info->buff_used= (info->buff != buff);
  118.   info->last_search_keypage=info->int_pos;
  119.   DBUG_PRINT("exit",("found key at %ld",info->lastpos));
  120.   DBUG_RETURN(0);
  121. err:
  122.   DBUG_PRINT("exit",("Error: %d",my_errno));
  123.   info->lastpos= NI_POS_ERROR;
  124.   DBUG_RETURN (-1);
  125. } /* _nisam_search */
  126. /* Search after key in page-block */
  127. /* If packed key puts smaller or identical key in buff */
  128. /* ret_pos point to where find or bigger key starts */
  129. /* ARGSUSED */
  130. int _nisam_bin_search(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page,
  131.    uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
  132.    uchar *buff __attribute__((unused)))
  133. {
  134.   reg4 int start,mid,end;
  135.   int flag;
  136.   uint totlength,nod_flag;
  137.   DBUG_ENTER("_nisam_bin_search");
  138.   LINT_INIT(flag);
  139.   totlength=keyinfo->base.keylength+(nod_flag=test_if_nod(page));
  140.   start=0; mid=1;
  141.   end= (int) ((getint(page)-2-nod_flag)/totlength-1);
  142.   DBUG_PRINT("test",("getint: %d  end: %d",getint(page),end));
  143.   page+=2+nod_flag;
  144.   while (start != end)
  145.   {
  146.     mid= (start+end)/2;
  147.     if ((flag=_nisam_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len,
  148.   comp_flag))
  149. >= 0)
  150.       end=mid;
  151.     else
  152.       start=mid+1;
  153.   }
  154.   if (mid != start)
  155.     flag=_nisam_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len,
  156.      comp_flag);
  157.   if (flag < 0)
  158.     start++; /* point at next, bigger key */
  159.   *ret_pos=page+(uint) start*totlength;
  160.   DBUG_PRINT("exit",("flag: %d  keypos: %d",flag,start));
  161.   DBUG_RETURN(flag);
  162. } /* _nisam_bin_search */
  163. /* Used instead of _nisam_bin_search() when key is packed */
  164. /* Puts smaller or identical key in buff */
  165. /* Key is searched sequentially */
  166. int _nisam_seq_search(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, uchar *buff)
  167. {
  168.   int flag;
  169.   uint nod_flag,length;
  170.   uchar t_buff[N_MAX_KEY_BUFF],*end;
  171.   DBUG_ENTER("_nisam_seq_search");
  172.   LINT_INIT(flag); LINT_INIT(length);
  173.   end= page+getint(page);
  174.   nod_flag=test_if_nod(page);
  175.   page+=2+nod_flag;
  176.   *ret_pos=page;
  177.   while (page < end)
  178.   {
  179.     length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
  180.     if ((flag=_nisam_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag)) >= 0)
  181.       break;
  182. #ifdef EXTRA_DEBUG
  183.     DBUG_PRINT("loop",("page: %lx  key: '%s'  flag: %d",page,t_buff,flag));
  184. #endif
  185.     memcpy(buff,t_buff,length);
  186.     *ret_pos=page;
  187.   }
  188.   if (flag == 0)
  189.     memcpy(buff,t_buff,length); /* Result is first key */
  190.   DBUG_PRINT("exit",("flag: %d  ret_pos: %lx",flag,*ret_pos));
  191.   DBUG_RETURN(flag);
  192. } /* _nisam_seq_search */
  193. /* Get pos to a key_block */
  194. ulong _nisam_kpos(uint nod_flag, uchar *after_key)
  195. {
  196.   after_key-=nod_flag;
  197.   switch (nod_flag) {
  198.   case 3:
  199.     return uint3korr(after_key)*512L;
  200.   case 2:
  201.     return uint2korr(after_key)*512L;
  202.   case 1:
  203.     return (uint) (*after_key)*512L;
  204.   case 0: /* At leaf page */
  205.   default: /* Impossible */
  206.     return(NI_POS_ERROR);
  207.   }
  208. } /* _kpos */
  209. /* Save pos to a key_block */
  210. void _nisam_kpointer(register N_INFO *info, register uchar *buff, ulong pos)
  211. {
  212.   pos/=512L;
  213.   switch (info->s->base.key_reflength) {
  214.   case 3: int3store(buff,pos); break;
  215.   case 2: int2store(buff,(uint) pos); break;
  216.   case 1: buff[0]= (uchar) pos; break;
  217.   default: abort(); /* impossible */
  218.   }
  219. } /* _nisam_kpointer */
  220. /* Calc pos to a data-record */
  221. ulong _nisam_dpos(N_INFO *info, uint nod_flag, uchar *after_key)
  222. {
  223.   ulong pos;
  224.   after_key-=(nod_flag + info->s->rec_reflength);
  225.   switch (info->s->rec_reflength) {
  226.   case 4:
  227.     pos= (ulong) uint4korr(after_key);
  228.     break;
  229.   case 3:
  230.     pos= (ulong) uint3korr(after_key);
  231.     break;
  232.   case 2:
  233.     pos= (ulong) uint2korr(after_key);
  234.     break;
  235.   default:
  236.     pos=0L; /* Shut compiler up */
  237.   }
  238.   return (info->s->base.options &
  239.   (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
  240.     pos*info->s->base.reclength;
  241. }
  242. /* save pos to record */
  243. void _nisam_dpointer(N_INFO *info, uchar *buff, ulong pos)
  244. {
  245.   if (!(info->s->base.options &
  246. (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
  247.     pos/=info->s->base.reclength;
  248.   switch (info->s->rec_reflength) {
  249.   case 4: int4store(buff,pos); break;
  250.   case 3: int3store(buff,pos); break;
  251.   case 2: int2store(buff,(uint) pos); break;
  252.   default: abort(); /* Impossible */
  253.   }
  254. } /* _nisam_dpointer */
  255. /*
  256. ** Compare two keys with is bigger
  257. ** Returns <0, 0, >0 acording to with is bigger
  258. ** Key_length specifies length of key to use.  Number-keys can't
  259. ** be splitted
  260. ** If flag <> SEARCH_FIND compare also position
  261. */
  262. int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar *b, uint key_length, uint nextflag)
  263. {
  264.   reg4 int flag,length_diff;
  265.   int16 s_1,s_2;
  266.   int32 l_1,l_2;
  267.   uint32 u_1,u_2;
  268.   float f_1,f_2;
  269.   double d_1,d_2;
  270.   reg5 uchar *end;
  271.   if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))
  272.       || key_length == 0)
  273.     key_length=N_MAX_KEY_BUFF*2;
  274.   for ( ; (int) key_length >0 ; key_length-= (keyseg++)->base.length)
  275.   {
  276.     end= a+ min(keyseg->base.length,key_length);
  277.     switch ((enum ha_base_keytype) keyseg->base.type) {
  278.     case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
  279.     case HA_KEYTYPE_BINARY:
  280.       if (keyseg->base.flag & HA_SPACE_PACK)
  281.       {
  282. uchar *as, *bs;
  283. int length,b_length;
  284. as=a++; bs=b++;
  285. length= (length_diff= ((int) *as - (b_length= (int) *bs))) < 0 ?
  286.   (int) *as : b_length;
  287. end= a+ min(key_length,(uint) length);
  288.         if (use_strnxfrm(default_charset_info)) {
  289.           if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
  290.           {
  291.             while (a < end)
  292.               if ((flag= (int) *a++ - (int) *b++))
  293.                 return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  294.           }
  295.           else
  296.           {
  297.             if ((flag = my_strnncoll(default_charset_info,
  298.      a, (int) (end-a), b, b_length)))
  299.               return (keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag;
  300.             b+= (uint) (end-a);
  301.             a=end;
  302.           }
  303.         }
  304.         else
  305. {
  306.           while (a < end)
  307.             if ((flag= (int) *a++ - (int) *b++))
  308.               return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  309. }
  310. if (key_length < (uint) keyseg->base.length)
  311. { /* key_part */
  312.   if (length_diff)
  313.   {
  314.     if (length_diff < 0 || (uint) *as <= key_length)
  315.       return ((keyseg->base.flag & HA_REVERSE_SORT) ?
  316.       -length_diff : length_diff);
  317.     for (length= (int) key_length-b_length; length-- > 0 ;)
  318.     {
  319.       if (*a++ != ' ')
  320. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -1 : 1);
  321.     }
  322.   }
  323.   if (nextflag & SEARCH_NO_FIND) /* Find record after key */
  324.     return (nextflag & SEARCH_BIGGER) ? -1 : 1;
  325.   return 0;
  326. }
  327. else
  328. {
  329.   if (length_diff)
  330.     return ((keyseg->base.flag & HA_REVERSE_SORT) ?
  331.     -length_diff : length_diff);
  332. }
  333. a=as+ (uint) *as+1 ; b= bs+ b_length+1; /* to next key */
  334.       }
  335.       else
  336.       {
  337.         if (use_strnxfrm(default_charset_info)) {
  338.           if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
  339.           {
  340.             while (a < end)
  341.               if ((flag= (int) *a++ - (int) *b++))
  342.                 return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  343.           }
  344.           else
  345.           {
  346.             if ((flag = my_strnncoll(default_charset_info,
  347.      a, (int) (end-a), b, (int) (end-a))))
  348.               return (keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag;
  349.             b+= (uint) (end-a);
  350.             a=end;
  351.           }
  352.         }
  353.         else
  354. {
  355.           while (a < end)
  356.             if ((flag= (int) *a++ - (int) *b++))
  357.               return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  358. }
  359.       }
  360.       break;
  361.     case HA_KEYTYPE_INT8:
  362.     {
  363.       int i_1= (int) *((signed char*) a);
  364.       int i_2= (int) *((signed char*) b);
  365.       if ((flag = CMP(i_1,i_2)))
  366. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  367.       a= end;
  368.       b++;
  369.       break;
  370.     }
  371.     case HA_KEYTYPE_SHORT_INT:
  372.       shortget(s_1,a);
  373.       shortget(s_2,b);
  374.       if ((flag = CMP(s_1,s_2)))
  375. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  376.       a=  end;
  377.       b+= 2; /* sizeof(short int); */
  378.       break;
  379.     case HA_KEYTYPE_USHORT_INT:
  380.       {
  381. uint16 us_1,us_2;
  382. ushortget(us_1,a);
  383. ushortget(us_2,b);
  384. if ((flag = CMP(us_1,us_2)))
  385.   return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  386. a=  end;
  387. b+=2; /* sizeof(short int); */
  388. break;
  389.       }
  390.     case HA_KEYTYPE_LONG_INT:
  391.       longget(l_1,a);
  392.       longget(l_2,b);
  393.       if ((flag = CMP(l_1,l_2)))
  394. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  395.       a=  end;
  396.       b+= 4; /* sizeof(long int); */
  397.       break;
  398.     case HA_KEYTYPE_ULONG_INT:
  399.       ulongget(u_1,a);
  400.       ulongget(u_2,b);
  401.       if ((flag = CMP(u_1,u_2)))
  402. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  403.       a=  end;
  404.       b+= 4; /* sizeof(long int); */
  405.       break;
  406.     case HA_KEYTYPE_INT24:
  407.       l_1=sint3korr(a);
  408.       l_2=sint3korr(b);
  409.       if ((flag = CMP(l_1,l_2)))
  410. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  411.       a=  end;
  412.       b+= 3;
  413.       break;
  414.     case HA_KEYTYPE_UINT24:
  415.       l_1=(long) uint3korr(a);
  416.       l_2=(long) uint3korr(b);
  417.       if ((flag = CMP(l_1,l_2)))
  418. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  419.       a=  end;
  420.       b+= 3;
  421.       break;
  422.     case HA_KEYTYPE_FLOAT:
  423.       bmove((byte*) &f_1,(byte*) a,(int) sizeof(float));
  424.       bmove((byte*) &f_2,(byte*) b,(int) sizeof(float));
  425.       if ((flag = CMP(f_1,f_2)))
  426. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  427.       a=  end;
  428.       b+= sizeof(float);
  429.       break;
  430.     case HA_KEYTYPE_DOUBLE:
  431.       doubleget(d_1,a);
  432.       doubleget(d_2,b);
  433.       if ((flag = CMP(d_1,d_2)))
  434. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  435.       a=  end;
  436.       b+= sizeof(double);
  437.       break;
  438.     case HA_KEYTYPE_NUM: /* Numeric key */
  439.     {
  440.       int swap_flag=keyseg->base.flag & HA_REVERSE_SORT;
  441.       if (keyseg->base.flag & HA_SPACE_PACK)
  442.       {
  443. int alength,blength;
  444. if (swap_flag)
  445.   swap_variables(uchar*, a, b);
  446. alength= *a++; blength= *b++;
  447. if ((flag=(int) (keyseg->base.length-key_length)) < 0)
  448.   flag=0;
  449. if (alength != blength+flag)
  450. {
  451.   if ((alength > blength+flag && *a != '-') ||
  452.       (alength < blength+flag && *b == '-'))
  453.     return 1;
  454.   else
  455.     return -1;
  456. }
  457. if (*a == '-' && *b == '-')
  458. {
  459.   swap_flag=1;
  460.   swap_variables(uchar*, a, b);
  461. }
  462. end=a+alength;
  463. while (a < end)
  464.   if (*a++ !=  *b++)
  465.   {
  466.     a--; b--;
  467.     if (my_isdigit(default_charset_info, (char) *a) && 
  468.         my_isdigit(default_charset_info, (char) *b))
  469.       return ((int) *a - (int) *b);
  470.     if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
  471.       return (-1);
  472.     if (*b == '-' || *b++ == ' ' || 
  473.         my_isdigit(default_charset_info,(char) *a))
  474.       return (1);
  475.     if (*a++ == ' ')
  476.       return (-1);
  477.   }
  478.       }
  479.       else
  480.       {
  481. for ( ; a < end && *a == ' ' && *b == ' ' ; a++, b++) ;
  482. if (*a == '-' && *b == '-')
  483.   swap_flag=1;
  484. if (swap_flag)
  485. {
  486.   end=b+(int) (end-a);
  487.   swap_variables(uchar*, a, b);
  488. }
  489. while (a < end)
  490.   if (*a++ != *b++)
  491.   {
  492.     a--; b--;
  493.     if (my_isdigit(default_charset_info,(char) *a) && 
  494.         my_isdigit(default_charset_info,(char) *b))
  495.       return ((int) *a - (int) *b);
  496.     if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
  497.       return (-1);
  498.     if (*b == '-' || *b++ == ' ' || 
  499.         my_isdigit(default_charset_info,(char) *a))
  500.       return (1);
  501.     if (*a++ == ' ')
  502.       return -1;
  503.   }
  504.       }
  505.       if (swap_flag)
  506. swap_variables(uchar*, a, b);
  507.       break;
  508.     }
  509. #ifdef HAVE_LONG_LONG
  510.     case HA_KEYTYPE_LONGLONG:
  511.     {
  512.       longlong ll_a,ll_b;
  513.       longlongget(ll_a,a);
  514.       longlongget(ll_b,b);
  515.       if ((flag = CMP(ll_a,ll_b)))
  516. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  517.       a=  end;
  518.       b+= sizeof(longlong);
  519.       break;
  520.     }
  521.     case HA_KEYTYPE_ULONGLONG:
  522.     {
  523.       ulonglong ll_a,ll_b;
  524.       longlongget(ll_a,a);
  525.       longlongget(ll_b,b);
  526.       if ((flag = CMP(ll_a,ll_b)))
  527. return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
  528.       a=  end;
  529.       b+= sizeof(ulonglong);
  530.       break;
  531.     }
  532. #endif
  533.     case HA_KEYTYPE_END: /* Ready */
  534.     case HA_KEYTYPE_VARTEXT: /* Impossible */
  535.     case HA_KEYTYPE_VARBINARY: /* Impossible */
  536.       goto end;
  537.     }
  538.   }
  539. end:
  540.   if (!(nextflag & SEARCH_FIND))
  541.   {
  542.     if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
  543.       return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
  544.     LINT_INIT(l_1); LINT_INIT(l_2);
  545.     switch (keyseg->base.length) {
  546.     case 4:
  547.       u_1= (ulong) uint4korr(a);
  548.       u_2= (ulong) uint4korr(b);
  549.       break;
  550.     case 3:
  551.       u_1= (ulong) uint3korr(a);
  552.       u_2= (ulong) uint3korr(b);
  553.       break;
  554.     case 2:
  555.       u_1= (ulong) uint2korr(a);
  556.       u_2= (ulong) uint2korr(b);
  557.       break;
  558.     default: abort(); /* Impossible */
  559.     }
  560.     flag = CMP(u_1,u_2);
  561.     if (nextflag & SEARCH_SAME)
  562.       return (flag); /* read same */
  563.     if (nextflag & SEARCH_BIGGER)
  564.       return (flag <= 0 ? -1 : 1); /* read next */
  565.     return (flag < 0 ? -1 : 1); /* read previous */
  566.   }
  567.   return 0;
  568. } /* _nisam_key_cmp */
  569. /* Get key from key-block */
  570. /* page points at previous key; its advanced to point at next key */
  571. /* key should contain previous key */
  572. /* Returns length of found key + pointers */
  573. /* nod_flag is a flag if we are on nod */
  574. uint _nisam_get_key(register N_KEYDEF *keyinfo, uint nod_flag,
  575.  register uchar **page, register uchar *key)
  576. {
  577.   reg1 N_KEYSEG *keyseg;
  578.   uchar *start,*start_key;
  579.   uint length,c_length;
  580.   LINT_INIT(start);
  581.   start_key=key; c_length=0;
  582.   for (keyseg=keyinfo->seg ; keyseg->base.type ;keyseg++)
  583.   {
  584.     if (keyseg->base.flag & (HA_SPACE_PACK | HA_PACK_KEY))
  585.     {
  586.       start=key;
  587.       if (keyseg->base.flag & HA_SPACE_PACK)
  588. key++;
  589.       if ((length= *(*page)++) & 128)
  590.       {
  591. key+= (c_length=(length & 127));
  592. if (c_length == 0) /* Same key */
  593. {
  594.   key+= *start; /* Same diff_key as prev */
  595.   length=0;
  596. }
  597. else
  598. {
  599.   if (keyseg->base.flag & HA_SPACE_PACK)
  600.     length= *(*page)++;
  601.   else
  602.     length=keyseg->base.length-length+128; /* Rest of key */
  603.   /* Prevent core dumps if wrong data formats */
  604.   if (length > keyseg->base.length)
  605.     length=0;
  606. }
  607.       }
  608.     }
  609.     else
  610.       length=keyseg->base.length;
  611.     memcpy((byte*) key,(byte*) *page,(size_t) length); key+=length;
  612.     if (keyseg->base.flag & HA_SPACE_PACK)
  613.       *start= (uchar) ((key-start)-1);
  614.     *page+=length;
  615.   }
  616.   length=keyseg->base.length+nod_flag;
  617.   bmove((byte*) key,(byte*) *page,length);
  618.   *page+=length;
  619.   return((uint) (key-start_key)+keyseg->base.length);
  620. } /* _nisam_get_key */
  621. /* same as _nisam_get_key but used with fixed length keys */
  622. uint _nisam_get_static_key(register N_KEYDEF *keyinfo, uint nod_flag, register uchar **page, register uchar *key)
  623. {
  624.   memcpy((byte*) key,(byte*) *page,
  625.  (size_t) (keyinfo->base.keylength+nod_flag));
  626.   *page+=keyinfo->base.keylength+nod_flag;
  627.   return(keyinfo->base.keylength);
  628. } /* _nisam_get_static_key */
  629. /* Get last key from key-block, starting from keypos */
  630. /* Return pointer to where keystarts */
  631. uchar *_nisam_get_last_key(N_INFO *info, N_KEYDEF *keyinfo, uchar *keypos, uchar *lastkey, uchar *endpos)
  632. {
  633.   uint nod_flag;
  634.   uchar *lastpos;
  635.   nod_flag=test_if_nod(keypos);
  636.   if (! (keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
  637.   {
  638.     lastpos=endpos-keyinfo->base.keylength-nod_flag;
  639.     if (lastpos > keypos)
  640.       bmove((byte*) lastkey,(byte*) lastpos,keyinfo->base.keylength+nod_flag);
  641.   }
  642.   else
  643.   {
  644.     lastpos=0 ; keypos+=2+nod_flag;
  645.     lastkey[0]=0;
  646.     while (keypos < endpos)
  647.     {
  648.       lastpos=keypos;
  649.       VOID(_nisam_get_key(keyinfo,nod_flag,&keypos,lastkey));
  650.     }
  651.   }
  652.   return lastpos;
  653. } /* _nisam_get_last_key */
  654. /* Calculate length of key */
  655. uint _nisam_keylength(N_KEYDEF *keyinfo, register uchar *key)
  656. {
  657.   reg1 N_KEYSEG *keyseg;
  658.   uchar *start;
  659.   if (! (keyinfo->base.flag & HA_SPACE_PACK_USED))
  660.     return (keyinfo->base.keylength);
  661.   start=key;
  662.   for (keyseg=keyinfo->seg ; keyseg->base.type ; keyseg++)
  663.   {
  664.     if (keyseg->base.flag & HA_SPACE_PACK)
  665.       key+= *key+1;
  666.     else
  667.       key+= keyseg->base.length;
  668.   }
  669.   return((uint) (key-start)+keyseg->base.length);
  670. } /* _nisam_keylength */
  671. /* Move a key */
  672. uchar *_nisam_move_key(N_KEYDEF *keyinfo, uchar *to, uchar *from)
  673. {
  674.   reg1 uint length;
  675.   memcpy((byte*) to, (byte*) from,
  676.  (size_t) (length=_nisam_keylength(keyinfo,from)));
  677.   return to+length;
  678. }
  679. /* Find next/previous record with same key */
  680. /* This can't be used when database is touched after last read */
  681. int _nisam_search_next(register N_INFO *info, register N_KEYDEF *keyinfo,
  682.     uchar *key, uint nextflag, ulong pos)
  683. {
  684.   int error;
  685.   uint nod_flag;
  686.   uchar lastkey[N_MAX_KEY_BUFF];
  687.   DBUG_ENTER("_nisam_search_next");
  688.   DBUG_PRINT("enter",("nextflag: %d  lastpos: %d  int_keypos: %lx",
  689.        nextflag,info->lastpos,info->int_keypos));
  690.   DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,key););
  691.   if ((nextflag & SEARCH_BIGGER && info->int_keypos >= info->int_maxpos) ||
  692.       info->int_pos == NI_POS_ERROR || info->page_changed)
  693.     DBUG_RETURN(_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
  694.    pos));
  695.   if (info->buff_used)
  696.   {
  697.     if (!_nisam_fetch_keypage(info,keyinfo,info->last_search_keypage,
  698.       info->buff,0))
  699.     {
  700.       info->lastpos= NI_POS_ERROR;
  701.       DBUG_RETURN(-1);
  702.     }
  703.     info->buff_used=0;
  704.   }
  705.   /* Last used buffer is in info->buff */
  706.   nod_flag=test_if_nod(info->buff);
  707.   VOID(_nisam_move_key(keyinfo,lastkey,key));
  708.   if (nextflag & SEARCH_BIGGER) /* Next key */
  709.   {
  710.     ulong tmp_pos=_nisam_kpos(nod_flag,info->int_keypos);
  711.     if (tmp_pos != NI_POS_ERROR)
  712.     {
  713.       if ((error=_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
  714.     tmp_pos)) <=0)
  715. DBUG_RETURN(error);
  716.     }
  717.     VOID((*keyinfo->get_key)(keyinfo,nod_flag,&info->int_keypos,lastkey));
  718.   }
  719.   else /* Previous key */
  720.   {
  721.     info->int_keypos=_nisam_get_last_key(info,keyinfo,info->buff,lastkey,
  722.       info->int_keypos);
  723.     if (info->int_keypos == info->buff+2)
  724.       DBUG_RETURN(_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
  725.      pos));
  726.     if ((error=_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
  727.   _nisam_kpos(nod_flag,info->int_keypos))) <= 0)
  728.       DBUG_RETURN(error);
  729.   }
  730.   info->int_keypos=_nisam_get_last_key(info,keyinfo,info->buff,lastkey,
  731.     info->int_keypos);
  732.   VOID(_nisam_move_key(keyinfo,info->lastkey,lastkey));
  733.   VOID((*keyinfo->get_key)(keyinfo,nod_flag,&info->int_keypos,info->lastkey));
  734.   info->lastpos=_nisam_dpos(info,nod_flag,info->int_keypos);
  735.   DBUG_PRINT("exit",("found key at %d",info->lastpos));
  736.   DBUG_RETURN(0);
  737. } /* _nisam_search_next */
  738. /* S|ker reda p} positionen f|r f|rsta recordet i ett index */
  739. /* Positionen l{ggs i info->lastpos */
  740. int _nisam_search_first(register N_INFO *info, register N_KEYDEF *keyinfo, register ulong pos)
  741. {
  742.   uint nod_flag;
  743.   uchar *page;
  744.   DBUG_ENTER("_nisam_search_first");
  745.   if (pos == NI_POS_ERROR)
  746.   {
  747.     my_errno=HA_ERR_KEY_NOT_FOUND;
  748.     info->lastpos= NI_POS_ERROR;
  749.     DBUG_RETURN(-1);
  750.   }
  751.   do
  752.   {
  753.     if (!_nisam_fetch_keypage(info,keyinfo,pos,info->buff,0))
  754.     {
  755.       info->lastpos= NI_POS_ERROR;
  756.       DBUG_RETURN(-1);
  757.     }
  758.     nod_flag=test_if_nod(info->buff);
  759.     page=info->buff+2+nod_flag;
  760.   } while ((pos=_nisam_kpos(nod_flag,page)) != NI_POS_ERROR);
  761.   VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,info->lastkey));
  762.   info->int_keypos=page; info->int_maxpos=info->buff+getint(info->buff)-1;
  763.   info->lastpos=_nisam_dpos(info,nod_flag,page);
  764.   info->page_changed=info->buff_used=0;
  765.   info->last_search_keypage=info->int_pos;
  766.   DBUG_PRINT("exit",("found key at %d",info->lastpos));
  767.   DBUG_RETURN(0);
  768. } /* _nisam_search_first */
  769. /* S|ker reda p} positionen f|r sista recordet i ett index */
  770. /* Positionen l{ggs i info->lastpos */
  771. int _nisam_search_last(register N_INFO *info, register N_KEYDEF *keyinfo, register ulong pos)
  772. {
  773.   uint nod_flag;
  774.   uchar *buff,*page;
  775.   DBUG_ENTER("_nisam_search_last");
  776.   if (pos == NI_POS_ERROR)
  777.   {
  778.     my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
  779.     info->lastpos= NI_POS_ERROR;
  780.     DBUG_RETURN(-1);
  781.   }
  782.   buff=info->buff;
  783.   do
  784.   {
  785.     if (!_nisam_fetch_keypage(info,keyinfo,pos,buff,0))
  786.     {
  787.       info->lastpos= NI_POS_ERROR;
  788.       DBUG_RETURN(-1);
  789.     }
  790.     page= buff+getint(buff);
  791.     nod_flag=test_if_nod(buff);
  792.   } while ((pos=_nisam_kpos(nod_flag,page)) != NI_POS_ERROR);
  793.   VOID(_nisam_get_last_key(info,keyinfo,buff,info->lastkey,page));
  794.   info->lastpos=_nisam_dpos(info,nod_flag,page);
  795.   info->int_keypos=info->int_maxpos=page;
  796.   info->page_changed=info->buff_used=0;
  797.   info->last_search_keypage=info->int_pos;
  798.   DBUG_PRINT("exit",("found key at %d",info->lastpos));
  799.   DBUG_RETURN(0);
  800. } /* _nisam_search_last */