ft_update.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:6k
源码类别:

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. /* Written by Sergei A. Golubchik, who has a shared copyright to this code */
  14. /* functions to work with full-text indices */
  15. #include "ftdefs.h"
  16. /**************************************************************
  17.    This is to make ft-code to ignore keyseg.length at all     *
  18.    and to index the whole VARCHAR/BLOB instead...             */
  19. #undef set_if_smaller
  20. #define set_if_smaller(A,B)                          /* no op */
  21. /**************************************************************/
  22. /* parses a document i.e. calls _mi_ft_parse for every keyseg */
  23. static FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, byte *keybuf,
  24.     const byte *record)
  25. {
  26.   TREE *parsed=NULL;
  27.   MI_KEYSEG *keyseg;
  28.   byte *pos;
  29.   uint i;
  30.   keyseg=info->s->keyinfo[keynr].seg;
  31.   for (i=info->s->keyinfo[keynr].keysegs-FT_SEGS ; i-- ; )
  32.   {
  33.     uint len;
  34.     keyseg--;
  35.     if (keyseg->null_bit && (record[keyseg->null_pos] & keyseg->null_bit))
  36. continue; /* NULL field */
  37.     pos= (byte *)record+keyseg->start;
  38.     if (keyseg->flag & HA_VAR_LENGTH)
  39.     {
  40.       len=uint2korr(pos);
  41.       pos+=2;  /* Skip VARCHAR length */
  42.       set_if_smaller(len,keyseg->length);
  43.     }
  44.     else if (keyseg->flag & HA_BLOB_PART)
  45.     {
  46.       len=_mi_calc_blob_length(keyseg->bit_start,pos);
  47.       memcpy_fixed(&pos,pos+keyseg->bit_start,sizeof(char*));
  48.       set_if_smaller(len,keyseg->length);
  49.     }
  50.     else
  51.       len=keyseg->length;
  52.     if (!(parsed=ft_parse(parsed, pos, len)))
  53.       return NULL;
  54.   }
  55.   /* Handle the case where all columns are NULL */
  56.   if (!parsed && !(parsed=ft_parse(0, (byte*) "", 0)))
  57.     return NULL;
  58.   return ft_linearize(info, keynr, keybuf, parsed);
  59. }
  60. static int _mi_ft_store(MI_INFO *info, uint keynr, byte *keybuf,
  61. FT_WORD *wlist, my_off_t filepos)
  62. {
  63.   uint key_length;
  64.   while(wlist->pos)
  65.   {
  66.     key_length=_ft_make_key(info,keynr,keybuf,wlist,filepos);
  67.     if (_mi_ck_write(info,keynr,(uchar*) keybuf,key_length))
  68.       return 1;
  69.     wlist++;
  70.    }
  71.    return 0;
  72. }
  73. static int _mi_ft_erase(MI_INFO *info, uint keynr, byte *keybuf, FT_WORD *wlist, my_off_t filepos)
  74. {
  75.   uint key_length, err=0;
  76.   while(wlist->pos)
  77.   {
  78.     key_length=_ft_make_key(info,keynr,keybuf,wlist,filepos);
  79.     if (_mi_ck_delete(info,keynr,(uchar*) keybuf,key_length))
  80.       err=1;
  81.     wlist++;
  82.    }
  83.    return err;
  84. }
  85. /* compares an appropriate parts of two WORD_KEY keys directly out of records */
  86. /* returns 1 if they are different */
  87. #define THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT 1
  88. #define GEE_THEY_ARE_ABSOLUTELY_IDENTICAL  0
  89. int _mi_ft_cmp(MI_INFO *info, uint keynr, const byte *rec1, const byte *rec2)
  90. {
  91.   MI_KEYSEG *keyseg;
  92.   byte *pos1, *pos2;
  93.   uint i;
  94.   i=info->s->keyinfo[keynr].keysegs-FT_SEGS;
  95.   keyseg=info->s->keyinfo[keynr].seg;
  96.   while(i--)
  97.   {
  98.     uint len1, len2;
  99.     LINT_INIT(len1); LINT_INIT(len2);
  100.     keyseg--;
  101.     if (keyseg->null_bit)
  102.     {
  103.       if ( (rec1[keyseg->null_pos] ^ rec2[keyseg->null_pos])
  104.    & keyseg->null_bit )
  105. return THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT;
  106.       if (rec1[keyseg->null_pos] & keyseg->null_bit )
  107. continue; /* NULL field */
  108.     }
  109.     pos1= (byte *)rec1+keyseg->start;
  110.     pos2= (byte *)rec2+keyseg->start;
  111.     if (keyseg->flag & HA_VAR_LENGTH)
  112.     {
  113.       len1=uint2korr(pos1);
  114.       pos1+=2;  /* Skip VARCHAR length */
  115.       set_if_smaller(len1,keyseg->length);
  116.       len2=uint2korr(pos2);
  117.       pos2+=2;  /* Skip VARCHAR length */
  118.       set_if_smaller(len2,keyseg->length);
  119.     }
  120.     else if (keyseg->flag & HA_BLOB_PART)
  121.     {
  122.       len1=_mi_calc_blob_length(keyseg->bit_start,pos1);
  123.       memcpy_fixed(&pos1,pos1+keyseg->bit_start,sizeof(char*));
  124.       set_if_smaller(len1,keyseg->length);
  125.       len2=_mi_calc_blob_length(keyseg->bit_start,pos2);
  126.       memcpy_fixed(&pos2,pos2+keyseg->bit_start,sizeof(char*));
  127.       set_if_smaller(len2,keyseg->length);
  128.     }
  129.     if ((len1 != len2) || memcmp(pos1, pos2, len1))
  130.       return THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT;
  131.   }
  132.   return GEE_THEY_ARE_ABSOLUTELY_IDENTICAL;
  133. }
  134. /* adds a document to the collection */
  135. int _mi_ft_add(MI_INFO *info, uint keynr, byte *keybuf, const byte *record,
  136.        my_off_t pos)
  137. {
  138.   int error= -1;
  139.   FT_WORD *wlist;
  140.   if ((wlist=_mi_ft_parserecord(info, keynr, keybuf, record)))
  141.   {
  142.     error=_mi_ft_store(info,keynr,keybuf,wlist,pos);
  143.     my_free((char*) wlist,MYF(0));
  144.   }
  145.   return error;
  146. }
  147. /* removes a document from the collection */
  148. int _mi_ft_del(MI_INFO *info, uint keynr, byte *keybuf, const byte *record,
  149.        my_off_t pos)
  150. {
  151.   int error= -1;
  152.   FT_WORD *wlist;
  153.   if ((wlist=_mi_ft_parserecord(info, keynr, keybuf, record)))
  154.   {
  155.     error=_mi_ft_erase(info,keynr,keybuf,wlist,pos);
  156.     my_free((char*) wlist,MYF(0));
  157.   }
  158.   return error;
  159. }
  160. uint _ft_make_key(MI_INFO *info, uint keynr, byte *keybuf, FT_WORD *wptr,
  161.   my_off_t filepos)
  162. {
  163.   byte buf[HA_FT_MAXLEN+16];
  164. #if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
  165.   float weight=(float) ((filepos==HA_OFFSET_ERROR) ? 0 : wptr->weight);
  166.   mi_float4store(buf,weight);
  167. #else
  168. #error
  169. #endif
  170. #ifdef EVAL_RUN
  171.   *(buf+HA_FT_WLEN)=wptr->cnt;
  172.   int2store(buf+HA_FT_WLEN+1,wptr->len);
  173.   memcpy(buf+HA_FT_WLEN+3,wptr->pos,wptr->len);
  174. #else /* EVAL_RUN */
  175.   int2store(buf+HA_FT_WLEN,wptr->len);
  176.   memcpy(buf+HA_FT_WLEN+2,wptr->pos,wptr->len);
  177. #endif /* EVAL_RUN */
  178.   return _mi_make_key(info,keynr,(uchar*) keybuf,buf,filepos);
  179. }