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

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16. /* Functions to handle keys and fields in forms */
  17. #include "mysql_priv.h"
  18. /*
  19. ** Search after with key field is. If no key starts with field test
  20. ** if field is part of some key.
  21. **
  22. ** returns number of key. keylength is set to length of key before
  23. ** (not including) field
  24. ** Used when calculating key for NEXT_NUMBER
  25. */
  26. int find_ref_key(TABLE *table,Field *field, uint *key_length)
  27. {
  28.   reg2 int i;
  29.   reg3 KEY *key_info;
  30.   uint fieldpos;
  31.   fieldpos=    field->offset();
  32. /* Test if some key starts as fieldpos */
  33.   for (i=0, key_info=table->key_info ; i < (int) table->keys ; i++, key_info++)
  34.   {
  35.     if (key_info->key_part[0].offset == fieldpos)
  36.     { /* Found key. Calc keylength */
  37.       *key_length=0;
  38.       return(i); /* Use this key */
  39.     }
  40.   }
  41. /* Test if some key contains fieldpos */
  42.   for (i=0, key_info=table->key_info ; i < (int) table->keys ; i++, key_info++)
  43.   {
  44.     uint j;
  45.     KEY_PART_INFO *key_part;
  46.     *key_length=0;
  47.     for (j=0, key_part=key_info->key_part ;
  48.  j < key_info->key_parts ;
  49.  j++, key_part++)
  50.     {
  51.       if (key_part->offset == fieldpos)
  52. return(i); /* Use this key */
  53.       *key_length+=key_part->length;
  54.     }
  55.   }
  56.   return(-1); /* No key is ok */
  57. }
  58. /* Copy a key from record to some buffer */
  59. /* if length == 0 then copy hole key */
  60. void key_copy(byte *key,TABLE *table,uint idx,uint key_length)
  61. {
  62.   uint length;
  63.   KEY *key_info=table->key_info+idx;
  64.   KEY_PART_INFO *key_part;
  65.   if (key_length == 0)
  66.     key_length=key_info->key_length;
  67.   for (key_part=key_info->key_part;
  68.        (int) key_length > 0 ;
  69.        key_part++)
  70.   {
  71.     if (key_part->null_bit)
  72.     {
  73.       *key++= test(table->record[0][key_part->null_offset] &
  74.    key_part->null_bit);
  75.       key_length--;
  76.     }
  77.     if (key_part->key_part_flag & HA_BLOB_PART)
  78.     {
  79.       char *pos;
  80.       ulong blob_length=((Field_blob*) key_part->field)->get_length();
  81.       key_length-=2;
  82.       ((Field_blob*) key_part->field)->get_ptr(&pos);
  83.       length=min(key_length,key_part->length);
  84.       set_if_smaller(blob_length,length);
  85.       int2store(key,(uint) blob_length);
  86.       key+=2; // Skipp length info
  87.       memcpy(key,pos,blob_length);
  88.     }
  89.     else
  90.     {
  91.       length=min(key_length,key_part->length);
  92.       memcpy(key,table->record[0]+key_part->offset,(size_t) length);
  93.     }
  94.     key+=length;
  95.     key_length-=length;
  96.   }
  97. } /* key_copy */
  98. /* restore a key from some buffer to record */
  99. void key_restore(TABLE *table,byte *key,uint idx,uint key_length)
  100. {
  101.   uint length;
  102.   KEY *key_info=table->key_info+idx;
  103.   KEY_PART_INFO *key_part;
  104.   if (key_length == 0)
  105.   {
  106.     if (idx == (uint) -1)
  107.       return;
  108.     key_length=key_info->key_length;
  109.   }
  110.   for (key_part=key_info->key_part;
  111.        (int) key_length > 0 ;
  112.        key_part++)
  113.   {
  114.     if (key_part->null_bit)
  115.     {
  116.       if (*key++)
  117. table->record[0][key_part->null_offset]|= key_part->null_bit;
  118.       else
  119. table->record[0][key_part->null_offset]&= ~key_part->null_bit;
  120.       key_length--;
  121.     }
  122.     if (key_part->key_part_flag & HA_BLOB_PART)
  123.     {
  124.       uint blob_length=uint2korr(key);
  125.       key+=2;
  126.       key_length-=2;
  127.       ((Field_blob*) key_part->field)->set_ptr((ulong) blob_length,
  128.        (char*) key);
  129.       length=key_part->length;
  130.     }
  131.     else
  132.     {
  133.       length=min(key_length,key_part->length);
  134.       memcpy(table->record[0]+key_part->offset,key,(size_t) length);
  135.     }
  136.     key+=length;
  137.     key_length-=length;
  138.   }
  139. } /* key_restore */
  140. /* Compare if a key has changed */
  141. int key_cmp(TABLE *table,const byte *key,uint idx,uint key_length)
  142. {
  143.   uint length;
  144.   KEY_PART_INFO *key_part;
  145.   for (key_part=table->key_info[idx].key_part;
  146.        (int) key_length > 0;
  147.        key_part++, key+=length, key_length-=length)
  148.   {
  149.     if (key_part->null_bit)
  150.     {
  151.       key_length--;
  152.       if (*key != test(table->record[0][key_part->null_offset] & 
  153.        key_part->null_bit))
  154. return 1;
  155.       if (*key)
  156.       {
  157. length=key_part->store_length;
  158. continue;
  159.       }
  160.       key++;
  161.     }
  162.     if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
  163.     {
  164.       if (key_part->field->key_cmp(key, key_part->length+2))
  165. return 1;
  166.       length=key_part->length+2;
  167.     }
  168.     else
  169.     {
  170.       length=min(key_length,key_part->length);
  171.       if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
  172.   FIELDFLAG_PACK)))
  173.       {
  174. if (my_sortcmp((char*) key,(char*) table->record[0]+key_part->offset,
  175.        length))
  176.   return 1;
  177.       }
  178.       else if (memcmp(key,table->record[0]+key_part->offset,length))
  179. return 1;
  180.     }
  181.   }
  182.   return 0;
  183. }
  184. /* unpack key-fields from record to some buffer */
  185. /* This is used to get a good error message */
  186. void key_unpack(String *to,TABLE *table,uint idx)
  187. {
  188.   KEY_PART_INFO *key_part,*key_part_end;
  189.   Field *field;
  190.   String tmp;
  191.   DBUG_ENTER("key_unpack");
  192.   to->length(0);
  193.   for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
  194.  table->key_info[idx].key_parts ;
  195.        key_part < key_part_end;
  196.        key_part++)
  197.   {
  198.     if (to->length())
  199.       to->append('-');
  200.     if (key_part->null_bit)
  201.     {
  202.       if (table->record[0][key_part->null_offset] & key_part->null_bit)
  203.       {
  204. to->append("NULL");
  205. continue;
  206.       }
  207.     }
  208.     if ((field=key_part->field))
  209.     {
  210.       field->val_str(&tmp,&tmp);
  211.       if (key_part->length < field->pack_length())
  212. tmp.length(min(tmp.length(),key_part->length));
  213.       to->append(tmp);
  214.     }
  215.     else
  216.       to->append("???");
  217.   }
  218.   DBUG_VOID_RETURN;
  219. }
  220. /*
  221.   Return 1 if any field in a list is part of key or the key uses a field
  222.   that is automaticly updated (like a timestamp)
  223. */
  224. bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
  225. {
  226.   List_iterator<Item> f(fields);
  227.   KEY_PART_INFO *key_part,*key_part_end;
  228.   for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
  229.  table->key_info[idx].key_parts ;
  230.        key_part < key_part_end;
  231.        key_part++)
  232.   {
  233.     Item_field *field;
  234.     
  235.     if (key_part->field == table->timestamp_field)
  236.       return 1; // Can't be used for update
  237.     f.rewind();
  238.     while ((field=(Item_field*) f++))
  239.     {
  240.       if (key_part->field == field->field)
  241. return 1;
  242.     }
  243.   }
  244.   return 0;
  245. }