home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / key.cpp < prev    next >
C/C++ Source or Header  |  2000-10-24  |  7KB  |  274 lines

  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.  
  17.  
  18. /* Functions to handle keys and fields in forms */
  19.  
  20. #include "mysql_priv.h"
  21.  
  22.     /*
  23.     ** Search after with key field is. If no key starts with field test
  24.     ** if field is part of some key.
  25.     **
  26.     ** returns number of key. keylength is set to length of key before
  27.     ** (not including) field
  28.     ** Used when calculating key for NEXT_NUMBER
  29.     */
  30.  
  31. int find_ref_key(TABLE *table,Field *field, uint *key_length)
  32. {
  33.   reg2 int i;
  34.   reg3 KEY *key_info;
  35.   uint fieldpos;
  36.  
  37.   fieldpos=    field->offset();
  38.  
  39.     /* Test if some key starts as fieldpos */
  40.  
  41.   for (i=0, key_info=table->key_info ; i < (int) table->keys ; i++, key_info++)
  42.   {
  43.     if (key_info->key_part[0].offset == fieldpos)
  44.     {                        /* Found key. Calc keylength */
  45.       *key_length=0;
  46.       return(i);            /* Use this key */
  47.     }
  48.   }
  49.     /* Test if some key contains fieldpos */
  50.  
  51.   for (i=0, key_info=table->key_info ; i < (int) table->keys ; i++, key_info++)
  52.   {
  53.     uint j;
  54.     KEY_PART_INFO *key_part;
  55.     *key_length=0;
  56.     for (j=0, key_part=key_info->key_part ;
  57.      j < key_info->key_parts ;
  58.      j++, key_part++)
  59.     {
  60.       if (key_part->offset == fieldpos)
  61.     return(i);            /* Use this key */
  62.       *key_length+=key_part->length;
  63.     }
  64.   }
  65.   return(-1);                    /* No key is ok */
  66. }
  67.  
  68.  
  69.     /* Copy a key from record to some buffer */
  70.     /* if length == 0 then copy hole key */
  71.  
  72. void key_copy(byte *key,TABLE *table,uint idx,uint key_length)
  73. {
  74.   uint length;
  75.   KEY *key_info=table->key_info+idx;
  76.   KEY_PART_INFO *key_part;
  77.  
  78.   if (key_length == 0)
  79.     key_length=key_info->key_length+key_info->extra_length;
  80.   for (key_part=key_info->key_part;
  81.        (int) key_length > 0 ;
  82.        key_part++)
  83.   {
  84.     if (key_part->null_bit)
  85.     {
  86.       *key++= test(table->record[0][key_part->null_offset] &
  87.            key_part->null_bit);
  88.       key_length--;
  89.     }
  90.     if (key_part->key_part_flag & HA_BLOB_PART)
  91.     {
  92.       char *pos;
  93.       ulong blob_length=((Field_blob*) key_part->field)->get_length();
  94.       key_length-=2;
  95.       ((Field_blob*) key_part->field)->get_ptr(&pos);
  96.       length=min(key_length,key_part->length);
  97.       set_if_smaller(blob_length,length);
  98.       int2store(key,(uint) blob_length);
  99.       key+=2;                    // Skipp length info
  100.       memcpy(key,pos,blob_length);
  101.     }
  102.     else
  103.     {
  104.       length=min(key_length,key_part->length);
  105.       memcpy(key,table->record[0]+key_part->offset,(size_t) length);
  106.     }
  107.     key+=length;
  108.     key_length-=length;
  109.   }
  110. } /* key_copy */
  111.  
  112.  
  113.     /* restore a key from some buffer to record */
  114.  
  115. void key_restore(TABLE *table,byte *key,uint idx,uint key_length)
  116. {
  117.   uint length;
  118.   KEY *key_info=table->key_info+idx;
  119.   KEY_PART_INFO *key_part;
  120.  
  121.   if (key_length == 0)
  122.   {
  123.     if (idx == (uint) -1)
  124.       return;
  125.     key_length=key_info->key_length+key_info->extra_length;
  126.   }
  127.   for (key_part=key_info->key_part;
  128.        (int) key_length > 0 ;
  129.        key_part++)
  130.   {
  131.     if (key_part->null_bit)
  132.     {
  133.       if (*key++)
  134.     table->record[0][key_part->null_offset]|= key_part->null_bit;
  135.       else
  136.     table->record[0][key_part->null_offset]&= ~key_part->null_bit;
  137.       key_length--;
  138.     }
  139.     if (key_part->key_part_flag & HA_BLOB_PART)
  140.     {
  141.       uint blob_length=uint2korr(key);
  142.       key+=2;
  143.       key_length-=2;
  144.       ((Field_blob*) key_part->field)->set_ptr((ulong) blob_length,
  145.                            (char*) key);
  146.       length=key_part->length;
  147.     }
  148.     else
  149.     {
  150.       length=min(key_length,key_part->length);
  151.       memcpy(table->record[0]+key_part->offset,key,(size_t) length);
  152.     }
  153.     key+=length;
  154.     key_length-=length;
  155.   }
  156. } /* key_restore */
  157.  
  158.  
  159.     /* Compare if a key has changed */
  160.  
  161. int key_cmp(TABLE *table,const byte *key,uint idx,uint key_length)
  162. {
  163.   uint length;
  164.   KEY_PART_INFO *key_part;
  165.  
  166.   for (key_part=table->key_info[idx].key_part;
  167.        (int) key_length > 0;
  168.        key_part++, key+=length, key_length-=length)
  169.   {
  170.     if (key_part->null_bit)
  171.     {
  172.       key_length--;
  173.       if (*key != test(table->record[0][key_part->null_offset] & 
  174.                key_part->null_bit))
  175.     return 1;
  176.       if (*key)
  177.       {
  178.     length=key_part->store_length;
  179.     continue;
  180.       }
  181.       key++;
  182.     }
  183.     if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
  184.     {
  185.       if (key_part->field->key_cmp(key, key_part->length+2))
  186.     return 1;
  187.       length=key_part->length+2;
  188.     }
  189.     else
  190.     {
  191.       length=min(key_length,key_part->length);
  192.       if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
  193.                   FIELDFLAG_PACK)))
  194.       {
  195.     if (my_sortcmp((char*) key,(char*) table->record[0]+key_part->offset,
  196.                length))
  197.       return 1;
  198.       }
  199.       else if (memcmp(key,table->record[0]+key_part->offset,length))
  200.     return 1;
  201.     }
  202.   }
  203.   return 0;
  204. }
  205.  
  206.     /* unpack key-fields from record to some buffer */
  207.     /* This is used to get a good error message */
  208.  
  209. void key_unpack(String *to,TABLE *table,uint idx)
  210. {
  211.   KEY_PART_INFO *key_part,*key_part_end;
  212.   Field *field;
  213.   String tmp;
  214.   DBUG_ENTER("key_unpack");
  215.  
  216.   to->length(0);
  217.   for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
  218.      table->key_info[idx].key_parts ;
  219.        key_part < key_part_end;
  220.        key_part++)
  221.   {
  222.     if (to->length())
  223.       to->append('-');
  224.     if (key_part->null_bit)
  225.     {
  226.       if (table->record[0][key_part->null_offset] & key_part->null_bit)
  227.       {
  228.     to->append("NULL");
  229.     continue;
  230.       }
  231.     }
  232.     if ((field=key_part->field))
  233.     {
  234.       field->val_str(&tmp,&tmp);
  235.       if (key_part->length < field->pack_length())
  236.     tmp.length(min(tmp.length(),key_part->length));
  237.       to->append(tmp);
  238.     }
  239.     else
  240.       to->append("???");
  241.   }
  242.   DBUG_VOID_RETURN;
  243. }
  244.  
  245.  
  246. /*
  247.   Return 1 if any field in a list is part of key or the key uses a field
  248.   that is automaticly updated (like a timestamp)
  249. */
  250.  
  251. bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
  252. {
  253.   List_iterator<Item> f(fields);
  254.   KEY_PART_INFO *key_part,*key_part_end;
  255.   for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
  256.      table->key_info[idx].key_parts ;
  257.        key_part < key_part_end;
  258.        key_part++)
  259.   {
  260.     Item_field *field;
  261.     
  262.     if (key_part->field == table->timestamp_field)
  263.       return 1;                    // Can't be used for update
  264.  
  265.     f.rewind();
  266.     while ((field=(Item_field*) f++))
  267.     {
  268.       if (key_part->field == field->field)
  269.     return 1;
  270.     }
  271.   }
  272.   return 0;
  273. }
  274.