~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/hash.c

  • Committer: Monty Taylor
  • Date: 2008-08-04 19:37:18 UTC
  • mto: (261.2.2 codestyle)
  • mto: This revision was merged to the branch mainline in revision 262.
  • Revision ID: monty@inaugust.com-20080804193718-f0rz13uli4429ozb
Changed gettext_noop() to N_()

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
/* The hash functions used for saving keys */
 
1
/* Copyright (C) 2000 MySQL 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; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
/* The hash functions used for saveing keys */
21
17
/* One of key_length or key_length_offset must be given */
22
18
/* Key length of 0 isn't allowed */
23
19
 
24
 
#include <config.h>
25
 
#include CSTDINT_H
26
 
#include <mysys/hash.h>
27
 
 
28
 
const uint32_t NO_RECORD= UINT32_MAX;
29
 
 
30
 
const int LOWFIND= 1;
31
 
const int LOWUSED= 2;
32
 
const int HIGHFIND= 4;
33
 
const int HIGHUSED= 8;
 
20
#include "mysys_priv.h"
 
21
#include <mystrings/m_string.h>
 
22
#include <mystrings/m_ctype.h>
 
23
#include "hash.h"
 
24
 
 
25
#define NO_RECORD       ((uint) -1)
 
26
#define LOWFIND 1
 
27
#define LOWUSED 2
 
28
#define HIGHFIND 4
 
29
#define HIGHUSED 8
34
30
 
35
31
typedef struct st_hash_info {
36
 
  /* index to next key */
37
 
  uint32_t next;
38
 
  /* data for current entry */
39
 
  unsigned char *data;
 
32
  uint next;                                    /* index to next key */
 
33
  uchar *data;                                  /* data for current entry */
40
34
} HASH_LINK;
41
35
 
42
 
static uint32_t hash_mask(uint32_t hashnr, uint32_t buffmax,
43
 
                          uint32_t maxlength);
44
 
static void movelink(HASH_LINK *array, uint32_t pos,
45
 
                     uint32_t next_link, uint32_t newlink);
46
 
static int hashcmp(const HASH *hash, HASH_LINK *pos, const unsigned char *key,
 
36
static uint hash_mask(uint hashnr,uint buffmax,uint maxlength);
 
37
static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink);
 
38
static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key,
47
39
                   size_t length);
48
40
 
49
 
static uint32_t calc_hash(const HASH *hash, const unsigned char *key,
50
 
                          size_t length)
 
41
static uint calc_hash(const HASH *hash, const uchar *key, size_t length)
51
42
{
52
 
  uint32_t nr1=1, nr2=4;
53
 
  hash->charset->coll->hash_sort(hash->charset, key,length, &nr1, &nr2);
 
43
  ulong nr1=1, nr2=4;
 
44
  hash->charset->coll->hash_sort(hash->charset,(uchar*) key,length,&nr1,&nr2);
54
45
  return nr1;
55
46
}
56
47
 
57
48
bool
58
 
_hash_init(HASH *hash,uint32_t growth_size, const CHARSET_INFO * const charset,
59
 
           uint32_t size, size_t key_offset, size_t key_length,
60
 
           hash_get_key get_key,
61
 
           hash_free_key free_element, uint32_t flags)
 
49
_hash_init(HASH *hash,uint growth_size, CHARSET_INFO *charset,
 
50
           ulong size, size_t key_offset, size_t key_length,
 
51
           hash_get_key get_key,
 
52
           void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
62
53
{
63
54
  hash->records=0;
64
55
  if (my_init_dynamic_array_ci(&hash->array, sizeof(HASH_LINK), size,
65
56
                               growth_size))
66
57
  {
67
 
    /* Allow call to hash_free */
68
 
    hash->free=0;
 
58
    hash->free=0;                               /* Allow call to hash_free */
69
59
    return true;
70
60
  }
71
61
  hash->key_offset=key_offset;
83
73
  Call hash->free on all elements in hash.
84
74
 
85
75
  SYNOPSIS
86
 
  hash_free_elements()
87
 
  hash   hash table
 
76
    hash_free_elements()
 
77
    hash   hash table
88
78
 
89
79
  NOTES:
90
 
  Sets records to 0
 
80
    Sets records to 0
91
81
*/
92
82
 
93
83
static inline void hash_free_elements(HASH *hash)
107
97
  Free memory used by hash.
108
98
 
109
99
  SYNOPSIS
110
 
  hash_free()
111
 
  hash   the hash to delete elements of
 
100
    hash_free()
 
101
    hash   the hash to delete elements of
112
102
 
113
103
  NOTES: Hash can't be reused without calling hash_init again.
114
104
*/
126
116
  Delete all elements from the hash (the hash itself is to be reused).
127
117
 
128
118
  SYNOPSIS
129
 
  my_hash_reset()
130
 
  hash   the hash to delete elements of
 
119
    my_hash_reset()
 
120
    hash   the hash to delete elements of
131
121
*/
132
122
 
133
123
void my_hash_reset(HASH *hash)
142
132
/* some helper functions */
143
133
 
144
134
/*
145
 
  This function is char* instead of unsigned char* as HPUX11 compiler can't
 
135
  This function is char* instead of uchar* as HPUX11 compiler can't
146
136
  handle inline functions that are not defined as native types
147
137
*/
148
138
 
149
139
static inline char*
150
 
hash_key(const HASH *hash, const unsigned char *record, size_t *length,
 
140
hash_key(const HASH *hash, const uchar *record, size_t *length,
151
141
         bool first)
152
142
{
153
143
  if (hash->get_key)
156
146
  return (char*) record+hash->key_offset;
157
147
}
158
148
 
159
 
/* Calculate pos according to keys */
 
149
        /* Calculate pos according to keys */
160
150
 
161
 
static uint32_t hash_mask(uint32_t hashnr,uint32_t buffmax,uint32_t maxlength)
 
151
static uint hash_mask(uint hashnr,uint buffmax,uint maxlength)
162
152
{
163
153
  if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
164
154
  return (hashnr & ((buffmax >> 1) -1));
165
155
}
166
156
 
167
 
static uint32_t hash_rec_mask(const HASH *hash, HASH_LINK *pos,
168
 
                              uint32_t buffmax, uint32_t maxlength)
 
157
static uint hash_rec_mask(const HASH *hash, HASH_LINK *pos,
 
158
                          uint buffmax, uint maxlength)
169
159
{
170
160
  size_t length;
171
 
  unsigned char *key= (unsigned char*) hash_key(hash,pos->data,&length,0);
 
161
  uchar *key= (uchar*) hash_key(hash,pos->data,&length,0);
172
162
  return hash_mask(calc_hash(hash,key,length),buffmax,maxlength);
173
163
}
174
164
 
175
165
 
176
166
 
 
167
/* for compilers which can not handle inline */
177
168
static
 
169
#if !defined(__USLC__) && !defined(__sgi)
178
170
inline
179
 
unsigned int rec_hashnr(HASH *hash,const unsigned char *record)
 
171
#endif
 
172
unsigned int rec_hashnr(HASH *hash,const uchar *record)
180
173
{
181
174
  size_t length;
182
 
  unsigned char *key= (unsigned char*) hash_key(hash,record,&length,0);
 
175
  uchar *key= (uchar*) hash_key(hash,record,&length,0);
183
176
  return calc_hash(hash,key,length);
184
177
}
185
178
 
186
179
 
187
 
unsigned char* hash_search(const HASH *hash, const unsigned char *key,
188
 
                           size_t length)
 
180
uchar* hash_search(const HASH *hash, const uchar *key, size_t length)
189
181
{
190
182
  HASH_SEARCH_STATE state;
191
183
  return hash_first(hash, key, length, &state);
195
187
  Search after a record based on a key
196
188
 
197
189
  NOTE
198
 
  Assigns the number of the found record to HASH_SEARCH_STATE state
 
190
   Assigns the number of the found record to HASH_SEARCH_STATE state
199
191
*/
200
192
 
201
 
unsigned char* hash_first(const HASH *hash, const unsigned char *key,
202
 
                          size_t length,
203
 
                          HASH_SEARCH_STATE *current_record)
 
193
uchar* hash_first(const HASH *hash, const uchar *key, size_t length,
 
194
                HASH_SEARCH_STATE *current_record)
204
195
{
205
196
  HASH_LINK *pos;
206
 
  uint32_t flag,idx;
 
197
  uint flag,idx;
207
198
 
208
199
  flag=1;
209
200
  if (hash->records)
210
201
  {
211
202
    idx=hash_mask(calc_hash(hash,key,length ? length : hash->key_length),
212
 
                  hash->blength,hash->records);
 
203
                    hash->blength,hash->records);
213
204
    do
214
205
    {
215
206
      pos= dynamic_element(&hash->array,idx,HASH_LINK*);
216
207
      if (!hashcmp(hash,pos,key,length))
217
208
      {
218
 
        *current_record= idx;
219
 
        return (pos->data);
 
209
        *current_record= idx;
 
210
        return (pos->data);
220
211
      }
221
212
      if (flag)
222
213
      {
223
 
        /* Reset flag */
224
 
        flag=0;
225
 
        if (hash_rec_mask(hash,pos,hash->blength,hash->records) != idx)
226
 
          /* Wrong link */
227
 
          break;
 
214
        flag=0;                                 /* Reset flag */
 
215
        if (hash_rec_mask(hash,pos,hash->blength,hash->records) != idx)
 
216
          break;                                /* Wrong link */
228
217
      }
229
218
    }
230
219
    while ((idx=pos->next) != NO_RECORD);
233
222
  return(0);
234
223
}
235
224
 
236
 
/* Get next record with identical key */
237
 
/* Can only be called if previous calls was hash_search */
 
225
        /* Get next record with identical key */
 
226
        /* Can only be called if previous calls was hash_search */
238
227
 
239
 
unsigned char* hash_next(const HASH *hash, const unsigned char *key,
240
 
                         size_t length,
241
 
                         HASH_SEARCH_STATE *current_record)
 
228
uchar* hash_next(const HASH *hash, const uchar *key, size_t length,
 
229
               HASH_SEARCH_STATE *current_record)
242
230
{
243
231
  HASH_LINK *pos;
244
 
  uint32_t idx;
 
232
  uint idx;
245
233
 
246
234
  if (*current_record != NO_RECORD)
247
235
  {
251
239
      pos=data+idx;
252
240
      if (!hashcmp(hash,pos,key,length))
253
241
      {
254
 
        *current_record= idx;
255
 
        return pos->data;
 
242
        *current_record= idx;
 
243
        return pos->data;
256
244
      }
257
245
    }
258
246
    *current_record= NO_RECORD;
261
249
}
262
250
 
263
251
 
264
 
/* Change link from pos to new_link */
 
252
        /* Change link from pos to new_link */
265
253
 
266
 
static void movelink(HASH_LINK *array, uint32_t find,
267
 
                     uint32_t next_link, uint32_t newlink)
 
254
static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink)
268
255
{
269
256
  HASH_LINK *old_link;
270
257
  do
280
267
  Compare a key in a record to a whole key. Return 0 if identical
281
268
 
282
269
  SYNOPSIS
283
 
  hashcmp()
284
 
  hash   hash table
285
 
  pos    position of hash record to use in comparison
286
 
  key    key for comparison
287
 
  length length of key
 
270
    hashcmp()
 
271
    hash   hash table
 
272
    pos    position of hash record to use in comparison
 
273
    key    key for comparison
 
274
    length length of key
288
275
 
289
276
  NOTES:
290
 
  If length is 0, comparison is done using the length of the
291
 
  record being compared against.
 
277
    If length is 0, comparison is done using the length of the
 
278
    record being compared against.
292
279
 
293
280
  RETURN
294
 
  = 0  key of record == key
295
 
  != 0 key of record != key
296
 
*/
 
281
    = 0  key of record == key
 
282
    != 0 key of record != key
 
283
 */
297
284
 
298
 
static int hashcmp(const HASH *hash, HASH_LINK *pos, const unsigned char *key,
 
285
static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key,
299
286
                   size_t length)
300
287
{
301
288
  size_t rec_keylength;
302
 
  unsigned char *rec_key= (unsigned char*) hash_key(hash, pos->data,
303
 
                                                    &rec_keylength,1);
 
289
  uchar *rec_key= (uchar*) hash_key(hash,pos->data,&rec_keylength,1);
304
290
  return ((length && length != rec_keylength) ||
305
 
          my_strnncoll(hash->charset, rec_key, rec_keylength,
306
 
                       key, rec_keylength));
 
291
          my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength,
 
292
                       (uchar*) key, rec_keylength));
307
293
}
308
294
 
309
295
 
310
 
/* Write a hash-key to the hash-index */
 
296
        /* Write a hash-key to the hash-index */
311
297
 
312
 
bool my_hash_insert(HASH *info,const unsigned char *record)
 
298
bool my_hash_insert(HASH *info,const uchar *record)
313
299
{
314
300
  int flag;
315
301
  size_t idx;
316
 
  uint32_t halfbuff,hash_nr,first_index;
317
 
  unsigned char *ptr_to_rec=NULL,*ptr_to_rec2=NULL;
 
302
  uint halfbuff,hash_nr,first_index;
 
303
  uchar *ptr_to_rec=NULL,*ptr_to_rec2=NULL;
318
304
  HASH_LINK *data,*empty,*gpos=NULL,*gpos2=NULL,*pos;
319
305
 
320
306
  if (HASH_UNIQUE & info->flags)
321
307
  {
322
 
    unsigned char *key= (unsigned char*) hash_key(info, record, &idx, 1);
 
308
    uchar *key= (uchar*) hash_key(info, record, &idx, 1);
323
309
    if (hash_search(info, key, idx))
324
 
      /* Duplicate entry */
325
 
      return(true);
 
310
      return(true);                             /* Duplicate entry */
326
311
  }
327
312
 
328
313
  flag=0;
329
314
  if (!(empty=(HASH_LINK*) alloc_dynamic(&info->array)))
330
 
    /* No more memory */
331
 
    return(true);
 
315
    return(true);                               /* No more memory */
332
316
 
333
317
  data=dynamic_element(&info->array,0,HASH_LINK*);
334
318
  halfbuff= info->blength >> 1;
335
319
 
336
320
  idx=first_index=info->records-halfbuff;
337
 
  /* If some records */
338
 
  if (idx != info->records)
 
321
  if (idx != info->records)                             /* If some records */
339
322
  {
340
323
    do
341
324
    {
342
325
      pos=data+idx;
343
326
      hash_nr=rec_hashnr(info,pos->data);
344
 
      /* First loop; Check if ok */
345
 
      if (flag == 0)
346
 
        if (hash_mask(hash_nr,info->blength,info->records) != first_index)
347
 
          break;
 
327
      if (flag == 0)                            /* First loop; Check if ok */
 
328
        if (hash_mask(hash_nr,info->blength,info->records) != first_index)
 
329
          break;
348
330
      if (!(hash_nr & halfbuff))
349
 
      {
350
 
        /* Key will not move */
351
 
        if (!(flag & LOWFIND))
352
 
        {
353
 
          if (flag & HIGHFIND)
354
 
          {
355
 
            flag=LOWFIND | HIGHFIND;
356
 
            /* key shall be moved to the current empty position */
357
 
            gpos=empty;
358
 
            ptr_to_rec=pos->data;
359
 
            /* This place is now free */
360
 
            empty=pos;
361
 
          }
362
 
          else
363
 
          {
364
 
            /* key isn't changed */
365
 
            flag=LOWFIND | LOWUSED;
366
 
            gpos=pos;
367
 
            ptr_to_rec=pos->data;
368
 
          }
369
 
        }
370
 
        else
371
 
        {
372
 
          if (!(flag & LOWUSED))
373
 
          {
374
 
            /* Change link of previous LOW-key */
375
 
            gpos->data=ptr_to_rec;
376
 
            gpos->next= (uint) (pos-data);
377
 
            flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED);
378
 
          }
379
 
          gpos=pos;
380
 
          ptr_to_rec=pos->data;
381
 
        }
 
331
      {                                         /* Key will not move */
 
332
        if (!(flag & LOWFIND))
 
333
        {
 
334
          if (flag & HIGHFIND)
 
335
          {
 
336
            flag=LOWFIND | HIGHFIND;
 
337
            /* key shall be moved to the current empty position */
 
338
            gpos=empty;
 
339
            ptr_to_rec=pos->data;
 
340
            empty=pos;                          /* This place is now free */
 
341
          }
 
342
          else
 
343
          {
 
344
            flag=LOWFIND | LOWUSED;             /* key isn't changed */
 
345
            gpos=pos;
 
346
            ptr_to_rec=pos->data;
 
347
          }
 
348
        }
 
349
        else
 
350
        {
 
351
          if (!(flag & LOWUSED))
 
352
          {
 
353
            /* Change link of previous LOW-key */
 
354
            gpos->data=ptr_to_rec;
 
355
            gpos->next= (uint) (pos-data);
 
356
            flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED);
 
357
          }
 
358
          gpos=pos;
 
359
          ptr_to_rec=pos->data;
 
360
        }
382
361
      }
383
362
      else
384
 
      {
385
 
        /* key will be moved */
386
 
        if (!(flag & HIGHFIND))
387
 
        {
388
 
          flag= (flag & LOWFIND) | HIGHFIND;
389
 
          /* key shall be moved to the last (empty) position */
390
 
          gpos2 = empty; empty=pos;
391
 
          ptr_to_rec2=pos->data;
392
 
        }
393
 
        else
394
 
        {
395
 
          if (!(flag & HIGHUSED))
396
 
          {
397
 
            /* Change link of previous hash-key and save */
398
 
            gpos2->data=ptr_to_rec2;
399
 
            gpos2->next=(uint) (pos-data);
400
 
            flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED);
401
 
          }
402
 
          gpos2=pos;
403
 
          ptr_to_rec2=pos->data;
404
 
        }
 
363
      {                                         /* key will be moved */
 
364
        if (!(flag & HIGHFIND))
 
365
        {
 
366
          flag= (flag & LOWFIND) | HIGHFIND;
 
367
          /* key shall be moved to the last (empty) position */
 
368
          gpos2 = empty; empty=pos;
 
369
          ptr_to_rec2=pos->data;
 
370
        }
 
371
        else
 
372
        {
 
373
          if (!(flag & HIGHUSED))
 
374
          {
 
375
            /* Change link of previous hash-key and save */
 
376
            gpos2->data=ptr_to_rec2;
 
377
            gpos2->next=(uint) (pos-data);
 
378
            flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED);
 
379
          }
 
380
          gpos2=pos;
 
381
          ptr_to_rec2=pos->data;
 
382
        }
405
383
      }
406
384
    }
407
385
    while ((idx=pos->next) != NO_RECORD);
423
401
  pos=data+idx;
424
402
  if (pos == empty)
425
403
  {
426
 
    pos->data=(unsigned char*) record;
 
404
    pos->data=(uchar*) record;
427
405
    pos->next=NO_RECORD;
428
406
  }
429
407
  else
433
411
    gpos=data+hash_rec_mask(info,pos,info->blength,info->records+1);
434
412
    if (pos == gpos)
435
413
    {
436
 
      pos->data=(unsigned char*) record;
 
414
      pos->data=(uchar*) record;
437
415
      pos->next=(uint) (empty - data);
438
416
    }
439
417
    else
440
418
    {
441
 
      pos->data=(unsigned char*) record;
 
419
      pos->data=(uchar*) record;
442
420
      pos->next=NO_RECORD;
443
421
      movelink(data,(uint) (pos-data),(uint) (gpos-data),(uint) (empty-data));
444
422
    }
450
428
 
451
429
 
452
430
/******************************************************************************
453
 
 ** Remove one record from hash-table. The record with the same record
454
 
 ** ptr is removed.
455
 
 ** if there is a free-function it's called for record if found
456
 
 *****************************************************************************/
 
431
** Remove one record from hash-table. The record with the same record
 
432
** ptr is removed.
 
433
** if there is a free-function it's called for record if found
 
434
******************************************************************************/
457
435
 
458
 
bool hash_delete(HASH *hash,unsigned char *record)
 
436
bool hash_delete(HASH *hash,uchar *record)
459
437
{
460
 
  uint32_t blength,pos2,pos_hashnr,lastpos_hashnr,idx,empty_index;
 
438
  uint blength,pos2,pos_hashnr,lastpos_hashnr,idx,empty_index;
461
439
  HASH_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty;
462
440
  if (!hash->records)
463
441
    return(1);
472
450
  {
473
451
    gpos=pos;
474
452
    if (pos->next == NO_RECORD)
475
 
      /* Key not found */
476
 
      return(1);
477
 
 
 
453
      return(1);                        /* Key not found */
478
454
    pos=data+pos->next;
479
455
  }
480
456
 
484
460
  /* Remove link to record */
485
461
  empty=pos; empty_index=(uint) (empty-data);
486
462
  if (gpos)
487
 
    /* unlink current ptr */
488
 
    gpos->next=pos->next;
 
463
    gpos->next=pos->next;               /* unlink current ptr */
489
464
  else if (pos->next != NO_RECORD)
490
465
  {
491
466
    empty=data+(empty_index=pos->next);
493
468
    pos->next=empty->next;
494
469
  }
495
470
 
496
 
  /* last key at wrong pos or no next link */
497
 
  if (empty == lastpos)
 
471
  if (empty == lastpos)                 /* last key at wrong pos or no next link */
498
472
    goto exit;
499
473
 
500
474
  /* Move the last key (lastpos) */
501
475
  lastpos_hashnr=rec_hashnr(hash,lastpos->data);
502
476
  /* pos is where lastpos should be */
503
477
  pos=data+hash_mask(lastpos_hashnr,hash->blength,hash->records);
504
 
  /* Move to empty position. */
505
 
  if (pos == empty)
 
478
  if (pos == empty)                     /* Move to empty position. */
506
479
  {
507
480
    empty[0]=lastpos[0];
508
481
    goto exit;
535
508
  pos->next=empty_index;
536
509
 
537
510
exit:
538
 
  pop_dynamic(&hash->array);
 
511
  VOID(pop_dynamic(&hash->array));
539
512
  if (hash->free)
540
 
    (*hash->free)((unsigned char*) record);
 
513
    (*hash->free)((uchar*) record);
541
514
  return(0);
542
515
}
543
516
 
544
 
/*
545
 
  Update keys when record has changed.
546
 
  This is much more efficent than using a delete & insert.
547
 
*/
 
517
        /*
 
518
          Update keys when record has changed.
 
519
          This is much more efficent than using a delete & insert.
 
520
          */
548
521
 
549
 
bool hash_update(HASH *hash, unsigned char *record, unsigned char *old_key,
550
 
                 size_t old_key_length)
 
522
bool hash_update(HASH *hash, uchar *record, uchar *old_key,
 
523
                    size_t old_key_length)
551
524
{
552
 
  uint32_t new_index,new_pos_index,blength,records,empty;
 
525
  uint new_index,new_pos_index,blength,records,empty;
553
526
  size_t idx;
554
527
  HASH_LINK org_link,*data,*previous,*pos;
555
 
 
 
528
  
556
529
  if (HASH_UNIQUE & hash->flags)
557
530
  {
558
531
    HASH_SEARCH_STATE state;
559
 
    unsigned char *found,
560
 
      *new_key= (unsigned char*) hash_key(hash, record, &idx, 1);
561
 
 
 
532
    uchar *found, *new_key= (uchar*) hash_key(hash, record, &idx, 1);
562
533
    if ((found= hash_first(hash, new_key, idx, &state)))
563
534
    {
564
 
      do
 
535
      do 
565
536
      {
566
537
        if (found != record)
567
538
          return(1);            /* Duplicate entry */
568
 
      }
 
539
      } 
569
540
      while ((found= hash_next(hash, new_key, idx, &state)));
570
541
    }
571
542
  }
576
547
  /* Search after record with key */
577
548
 
578
549
  idx=hash_mask(calc_hash(hash, old_key,(old_key_length ?
579
 
                                         old_key_length :
580
 
                                         hash->key_length)),
581
 
                blength,records);
 
550
                                              old_key_length :
 
551
                                              hash->key_length)),
 
552
                  blength,records);
582
553
  new_index=hash_mask(rec_hashnr(hash,record),blength,records);
583
554
  if (idx == new_index)
584
555
    return(0);                  /* Nothing to do (No record check) */
647
618
}
648
619
 
649
620
 
650
 
unsigned char *hash_element(HASH *hash,uint32_t idx)
 
621
uchar *hash_element(HASH *hash,ulong idx)
651
622
{
652
623
  if (idx < hash->records)
653
624
    return dynamic_element(&hash->array,idx,HASH_LINK*)->data;
660
631
  isn't changed
661
632
*/
662
633
 
663
 
void hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record,
664
 
                  unsigned char *new_row)
 
634
void hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record, uchar *new_row)
665
635
{
666
636
  if (*current_record != NO_RECORD)            /* Safety */
667
637
    dynamic_element(&hash->array, *current_record, HASH_LINK*)->data= new_row;