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

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. /* Functions to handle keys and fields in forms */
  14. #include "mysql_priv.h"
  15. /*
  16. ** Search after with key field is. If no key starts with field test
  17. ** if field is part of some key.
  18. **
  19. ** returns number of key. keylength is set to length of key before
  20. ** (not including) field
  21. ** Used when calculating key for NEXT_NUMBER
  22. */
  23. int find_ref_key(TABLE *table,Field *field, uint *key_length)
  24. {
  25.   reg2 int i;
  26.   reg3 KEY *key_info;
  27.   uint fieldpos;
  28.   fieldpos=    field->offset();
  29. /* Test if some key starts as fieldpos */
  30.   for (i=0, key_info=table->key_info ; i < (int) table->keys ; i++, key_info++)
  31.   {
  32.     if (key_info->key_part[0].offset == fieldpos)
  33.     { /* Found key. Calc keylength */
  34.       *key_length=0;
  35.       return(i); /* Use this key */
  36.     }
  37.   }
  38. /* Test if some key contains fieldpos */
  39.   for (i=0, key_info=table->key_info ; i < (int) table->keys ; i++, key_info++)
  40.   {
  41.     uint j;
  42.     KEY_PART_INFO *key_part;
  43.     *key_length=0;
  44.     for (j=0, key_part=key_info->key_part ;
  45.  j < key_info->key_parts ;
  46.  j++, key_part++)
  47.     {
  48.       if (key_part->offset == fieldpos)
  49. return(i); /* Use this key */
  50.       *key_length+=key_part->store_length;
  51.     }
  52.   }
  53.   return(-1); /* No key is ok */
  54. }
  55. /* Copy a key from record to some buffer */
  56. /* if length == 0 then copy whole key */
  57. void key_copy(byte *key,TABLE *table,uint idx,uint key_length)
  58. {
  59.   uint length;
  60.   KEY *key_info=table->key_info+idx;
  61.   KEY_PART_INFO *key_part;
  62.   if (key_length == 0)
  63.     key_length=key_info->key_length;
  64.   for (key_part=key_info->key_part;
  65.        (int) key_length > 0 ;
  66.        key_part++)
  67.   {
  68.     if (key_part->null_bit)
  69.     {
  70.       *key++= test(table->record[0][key_part->null_offset] &
  71.    key_part->null_bit);
  72.       key_length--;
  73.     }
  74.     if (key_part->key_part_flag & HA_BLOB_PART)
  75.     {
  76.       char *pos;
  77.       ulong blob_length=((Field_blob*) key_part->field)->get_length();
  78.       key_length-=2;
  79.       ((Field_blob*) key_part->field)->get_ptr(&pos);
  80.       length=min(key_length,key_part->length);
  81.       set_if_smaller(blob_length,length);
  82.       int2store(key,(uint) blob_length);
  83.       key+=2; // Skip length info
  84.       memcpy(key,pos,blob_length);
  85.     }
  86.     else
  87.     {
  88.       length=min(key_length,key_part->length);
  89.       memcpy(key,table->record[0]+key_part->offset,(size_t) length);
  90.     }
  91.     key+=length;
  92.     key_length-=length;
  93.   }
  94. } /* key_copy */
  95. /* restore a key from some buffer to record */
  96. void key_restore(TABLE *table,byte *key,uint idx,uint key_length)
  97. {
  98.   uint length;
  99.   KEY *key_info=table->key_info+idx;
  100.   KEY_PART_INFO *key_part;
  101.   if (key_length == 0)
  102.   {
  103.     if (idx == (uint) -1)
  104.       return;
  105.     key_length=key_info->key_length;
  106.   }
  107.   for (key_part=key_info->key_part;
  108.        (int) key_length > 0 ;
  109.        key_part++)
  110.   {
  111.     if (key_part->null_bit)
  112.     {
  113.       if (*key++)
  114. table->record[0][key_part->null_offset]|= key_part->null_bit;
  115.       else
  116. table->record[0][key_part->null_offset]&= ~key_part->null_bit;
  117.       key_length--;
  118.     }
  119.     if (key_part->key_part_flag & HA_BLOB_PART)
  120.     {
  121.       uint blob_length=uint2korr(key);
  122.       key+=2;
  123.       key_length-=2;
  124.       ((Field_blob*) key_part->field)->set_ptr((ulong) blob_length,
  125.        (char*) key);
  126.       length=key_part->length;
  127.     }
  128.     else
  129.     {
  130.       length=min(key_length,key_part->length);
  131.       memcpy(table->record[0]+key_part->offset,key,(size_t) length);
  132.     }
  133.     key+=length;
  134.     key_length-=length;
  135.   }
  136. } /* key_restore */
  137. /*
  138.   Compare if a key has changed
  139.   SYNOPSIS
  140.     key_cmp_if_same()
  141.     table TABLE
  142.     key key to compare to row
  143.     idx Index used
  144.     key_length Length of key
  145.   NOTES
  146.     In theory we could just call field->cmp() for all field types,
  147.     but as we are only interested if a key has changed (not if the key is
  148.     larger or smaller than the previous value) we can do things a bit
  149.     faster by using memcmp() instead.
  150.   RETURN
  151.     0 If key is equal
  152.     1 Key has changed
  153. */
  154. bool key_cmp_if_same(TABLE *table,const byte *key,uint idx,uint key_length)
  155. {
  156.   uint length;
  157.   KEY_PART_INFO *key_part;
  158.   for (key_part=table->key_info[idx].key_part;
  159.        (int) key_length > 0;
  160.        key_part++, key+=length, key_length-=length)
  161.   {
  162.     if (key_part->null_bit)
  163.     {
  164.       key_length--;
  165.       if (*key != test(table->record[0][key_part->null_offset] & 
  166.        key_part->null_bit))
  167. return 1;
  168.       if (*key)
  169.       {
  170. length=key_part->store_length;
  171. continue;
  172.       }
  173.       key++;
  174.     }
  175.     if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
  176.     {
  177.       if (key_part->field->key_cmp(key, key_part->length+ HA_KEY_BLOB_LENGTH))
  178. return 1;
  179.       length=key_part->length+HA_KEY_BLOB_LENGTH;
  180.     }
  181.     else
  182.     {
  183.       length=min(key_length,key_part->length);
  184.       if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
  185.   FIELDFLAG_PACK)))
  186.       {
  187.         CHARSET_INFO *cs= key_part->field->charset();
  188.         uint char_length= key_part->length / cs->mbmaxlen;
  189.         const byte *pos= table->record[0] + key_part->offset;
  190.         if (length > char_length)
  191.         {
  192.           char_length= my_charpos(cs, pos, pos + length, char_length);
  193.           set_if_smaller(char_length, length);
  194.         }
  195. if (cs->coll->strnncollsp(cs,
  196.                                   (const uchar*) key, length,
  197.                                   (const uchar*) pos, char_length))
  198.   return 1;
  199.       }
  200.       else if (memcmp(key,table->record[0]+key_part->offset,length))
  201. return 1;
  202.     }
  203.   }
  204.   return 0;
  205. }
  206. /* unpack key-fields from record to some buffer */
  207. /* This is used to get a good error message */
  208. void key_unpack(String *to,TABLE *table,uint idx)
  209. {
  210.   KEY_PART_INFO *key_part,*key_part_end;
  211.   Field *field;
  212.   String tmp;
  213.   DBUG_ENTER("key_unpack");
  214.   to->length(0);
  215.   for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
  216.  table->key_info[idx].key_parts ;
  217.        key_part < key_part_end;
  218.        key_part++)
  219.   {
  220.     if (to->length())
  221.       to->append('-');
  222.     if (key_part->null_bit)
  223.     {
  224.       if (table->record[0][key_part->null_offset] & key_part->null_bit)
  225.       {
  226. to->append("NULL", 4);
  227. continue;
  228.       }
  229.     }
  230.     if ((field=key_part->field))
  231.     {
  232.       field->val_str(&tmp);
  233.       if (key_part->length < field->pack_length())
  234. tmp.length(min(tmp.length(),key_part->length));
  235.       to->append(tmp);
  236.     }
  237.     else
  238.       to->append("???", 3);
  239.   }
  240.   DBUG_VOID_RETURN;
  241. }
  242. /*
  243.   Return 1 if any field in a list is part of key or the key uses a field
  244.   that is automaticly updated (like a timestamp)
  245. */
  246. bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
  247. {
  248.   List_iterator_fast<Item> f(fields);
  249.   KEY_PART_INFO *key_part,*key_part_end;
  250.   for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
  251.  table->key_info[idx].key_parts ;
  252.        key_part < key_part_end;
  253.        key_part++)
  254.   {
  255.     Item_field *field;
  256.     if (key_part->field == table->timestamp_field)
  257.       return 1; // Can't be used for update
  258.     f.rewind();
  259.     while ((field=(Item_field*) f++))
  260.     {
  261.       if (key_part->field->eq(field->field))
  262. return 1;
  263.     }
  264.   }
  265.   /*
  266.     If table handler has primary key as part of the index, check that primary
  267.     key is not updated
  268.   */
  269.   if (idx != table->primary_key && table->primary_key < MAX_KEY &&
  270.       (table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
  271.     return check_if_key_used(table, table->primary_key, fields);
  272.   return 0;
  273. }
  274. /*
  275.   Compare key in row to a given key
  276.   SYNOPSIS
  277.     key_cmp()
  278.     key_part Key part handler
  279.     key Key to compare to value in table->record[0]
  280.     key_length length of 'key'
  281.   RETURN
  282.     The return value is SIGN(key_in_row - range_key):
  283.     0 Key is equal to range or 'range' == 0 (no range)
  284.    -1 Key is less than range
  285.     1 Key is larger than range
  286. */
  287. int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length)
  288. {
  289.   uint store_length;
  290.   for (const byte *end=key + key_length;
  291.        key < end;
  292.        key+= store_length, key_part++)
  293.   {
  294.     int cmp;
  295.     store_length= key_part->store_length;
  296.     if (key_part->null_bit)
  297.     {
  298.       /* This key part allows null values; NULL is lower than everything */
  299.       register bool field_is_null= key_part->field->is_null();
  300.       if (*key)                                 // If range key is null
  301.       {
  302. /* the range is expecting a null value */
  303. if (!field_is_null)
  304.   return 1;                             // Found key is > range
  305.         /* null -- exact match, go to next key part */
  306. continue;
  307.       }
  308.       else if (field_is_null)
  309. return -1;                              // NULL is less than any value
  310.       key++; // Skip null byte
  311.       store_length--;
  312.     }
  313.     if ((cmp=key_part->field->key_cmp((byte*) key, key_part->length)) < 0)
  314.       return -1;
  315.     if (cmp > 0)
  316.       return 1;
  317.   }
  318.   return 0;                                     // Keys are equal
  319. }