~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 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
17
/**
18
  @file
19
20
  @brief
21
  Functions for easy reading of records, possible through a cache
22
*/
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
23
#include <drizzled/server_includes.h>
550 by Monty Taylor
Moved error.h into just the files that need it.
24
#include <drizzled/error.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
25
#include <drizzled/table.h>
26
#include <drizzled/session.h>
1 by brian
clean slate
27
28
static int rr_quick(READ_RECORD *info);
29
int rr_sequential(READ_RECORD *info);
30
static int rr_from_tempfile(READ_RECORD *info);
31
static int rr_unpack_from_tempfile(READ_RECORD *info);
32
static int rr_unpack_from_buffer(READ_RECORD *info);
33
static int rr_from_pointers(READ_RECORD *info);
34
static int rr_from_cache(READ_RECORD *info);
520.1.22 by Brian Aker
Second pass of thd cleanup
35
static int init_rr_cache(Session *session, READ_RECORD *info);
481 by Brian Aker
Remove all of uchar.
36
static int rr_cmp(unsigned char *a,unsigned char *b);
1 by brian
clean slate
37
static int rr_index_first(READ_RECORD *info);
38
static int rr_index(READ_RECORD *info);
39
40
41
/**
42
  Initialize READ_RECORD structure to perform full index scan (in forward
43
  direction) using read_record.read_record() interface.
44
45
    This function has been added at late stage and is used only by
46
    UPDATE/DELETE. Other statements perform index scans using
47
    join_read_first/next functions.
48
49
  @param info         READ_RECORD structure to initialize.
520.1.22 by Brian Aker
Second pass of thd cleanup
50
  @param session          Thread handle
1 by brian
clean slate
51
  @param table        Table to be accessed
52
  @param print_error  If true, call table->file->print_error() if an error
53
                      occurs (except for end-of-records error)
54
  @param idx          index to scan
55
*/
56
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
57
void init_read_record_idx(READ_RECORD *info, Session *, Table *table,
482 by Brian Aker
Remove uint.
58
                          bool print_error, uint32_t idx)
1 by brian
clean slate
59
{
60
  empty_record(table);
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
61
  memset(info, 0, sizeof(*info));
1 by brian
clean slate
62
  info->table= table;
63
  info->file=  table->file;
64
  info->record= table->record[0];
65
  info->print_error= print_error;
66
67
  table->status=0;			/* And it's always found */
68
  if (!table->file->inited)
69
    table->file->ha_index_init(idx, 1);
70
  /* read_record will be changed to rr_index in rr_index_first */
71
  info->read_record= rr_index_first;
72
}
73
74
75
/*
76
  init_read_record is used to scan by using a number of different methods.
77
  Which method to use is set-up in this call so that later calls to
78
  the info->read_record will call the appropriate method using a function
79
  pointer.
80
81
  There are five methods that relate completely to the sort function
82
  filesort. The result of a filesort is retrieved using read_record
83
  calls. The other two methods are used for normal table access.
84
85
  The filesort will produce references to the records sorted, these
86
  references can be stored in memory or in a temporary file.
87
88
  The temporary file is normally used when the references doesn't fit into
89
  a properly sized memory buffer. For most small queries the references
90
  are stored in the memory buffer.
91
92
  The temporary file is also used when performing an update where a key is
93
  modified.
94
95
  Methods used when ref's are in memory (using rr_from_pointers):
96
    rr_unpack_from_buffer:
97
    ----------------------
98
      This method is used when table->sort.addon_field is allocated.
99
      This is allocated for most SELECT queries not involving any BLOB's.
100
      In this case the records are fetched from a memory buffer.
101
    rr_from_pointers:
102
    -----------------
103
      Used when the above is not true, UPDATE, DELETE and so forth and
104
      SELECT's involving BLOB's. It is also used when the addon_field
105
      buffer is not allocated due to that its size was bigger than the
106
      session variable max_length_for_sort_data.
107
      In this case the record data is fetched from the handler using the
108
      saved reference using the rnd_pos handler call.
109
110
  Methods used when ref's are in a temporary file (using rr_from_tempfile)
111
    rr_unpack_from_tempfile:
112
    ------------------------
113
      Same as rr_unpack_from_buffer except that references are fetched from
114
      temporary file. Should obviously not really happen other than in
115
      strange configurations.
116
117
    rr_from_tempfile:
118
    -----------------
119
      Same as rr_from_pointers except that references are fetched from
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
120
      temporary file instead of from
1 by brian
clean slate
121
    rr_from_cache:
122
    --------------
123
      This is a special variant of rr_from_tempfile that can be used for
124
      handlers that is not using the HA_FAST_KEY_READ table flag. Instead
125
      of reading the references one by one from the temporary file it reads
126
      a set of them, sorts them and reads all of them into a buffer which
127
      is then used for a number of subsequent calls to rr_from_cache.
128
      It is only used for SELECT queries and a number of other conditions
129
      on table size.
130
131
  All other accesses use either index access methods (rr_quick) or a full
132
  table scan (rr_sequential).
133
  rr_quick:
134
  ---------
135
    rr_quick uses one of the QUICK_SELECT classes in opt_range.cc to
136
    perform an index scan. There are loads of functionality hidden
137
    in these quick classes. It handles all index scans of various kinds.
138
  rr_sequential:
139
  --------------
140
    This is the most basic access method of a table using rnd_init,
141
    rnd_next and rnd_end. No indexes are used.
142
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
143
void init_read_record(READ_RECORD *info,Session *session, Table *table,
1 by brian
clean slate
144
		      SQL_SELECT *select,
145
		      int use_record_cache, bool print_error)
146
{
147
  IO_CACHE *tempfile;
148
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
149
  memset(info, 0, sizeof(*info));
520.1.22 by Brian Aker
Second pass of thd cleanup
150
  info->session=session;
1 by brian
clean slate
151
  info->table=table;
152
  info->file= table->file;
153
  info->forms= &info->table;		/* Only one table */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
154
1 by brian
clean slate
155
  if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE &&
156
      !table->sort.addon_field)
398.1.10 by Monty Taylor
Actually removed VOID() this time.
157
    table->file->extra(HA_EXTRA_MMAP);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
158
1 by brian
clean slate
159
  if (table->sort.addon_field)
160
  {
161
    info->rec_buf= table->sort.addon_buf;
162
    info->ref_length= table->sort.addon_length;
163
  }
164
  else
165
  {
166
    empty_record(table);
167
    info->record= table->record[0];
168
    info->ref_length= table->file->ref_length;
169
  }
170
  info->select=select;
171
  info->print_error=print_error;
172
  info->ignore_not_found_rows= 0;
173
  table->status=0;			/* And it's always found */
174
175
  if (select && my_b_inited(&select->file))
176
    tempfile= &select->file;
177
  else
178
    tempfile= table->sort.io_cache;
179
  if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
180
  {
181
    info->read_record= (table->sort.addon_field ?
182
                        rr_unpack_from_tempfile : rr_from_tempfile);
183
    info->io_cache=tempfile;
184
    reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
185
    info->ref_pos=table->file->ref;
186
    if (!table->file->inited)
187
      table->file->ha_rnd_init(0);
188
189
    /*
190
      table->sort.addon_field is checked because if we use addon fields,
191
      it doesn't make sense to use cache - we don't read from the table
192
      and table->sort.io_cache is read sequentially
193
    */
194
    if (!table->sort.addon_field &&
520.1.22 by Brian Aker
Second pass of thd cleanup
195
	session->variables.read_rnd_buff_size &&
1 by brian
clean slate
196
	!(table->file->ha_table_flags() & HA_FAST_KEY_READ) &&
197
	(table->db_stat & HA_READ_ONLY ||
198
	 table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
151 by Brian Aker
Ulonglong to uint64_t
199
	(uint64_t) table->s->reclength* (table->file->stats.records+
1 by brian
clean slate
200
                                          table->file->stats.deleted) >
151 by Brian Aker
Ulonglong to uint64_t
201
	(uint64_t) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
1 by brian
clean slate
202
	info->io_cache->end_of_file/info->ref_length * table->s->reclength >
203
	(my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
204
	!table->s->blob_fields &&
205
        info->ref_length <= MAX_REFLENGTH)
206
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
207
      if (! init_rr_cache(session, info))
1 by brian
clean slate
208
      {
209
	info->read_record=rr_from_cache;
210
      }
211
    }
212
  }
213
  else if (select && select->quick)
214
  {
215
    info->read_record=rr_quick;
216
  }
217
  else if (table->sort.record_pointers)
218
  {
219
    table->file->ha_rnd_init(0);
220
    info->cache_pos=table->sort.record_pointers;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
221
    info->cache_end=info->cache_pos+
1 by brian
clean slate
222
                    table->sort.found_records*info->ref_length;
223
    info->read_record= (table->sort.addon_field ?
224
                        rr_unpack_from_buffer : rr_from_pointers);
225
  }
226
  else
227
  {
228
    info->read_record=rr_sequential;
229
    table->file->ha_rnd_init(1);
230
    /* We can use record cache if we don't update dynamic length tables */
231
    if (!table->no_cache &&
232
	(use_record_cache > 0 ||
233
	 (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
234
	 !(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) ||
235
	 (use_record_cache < 0 &&
236
	  !(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE))))
520.1.22 by Brian Aker
Second pass of thd cleanup
237
      table->file->extra_opt(HA_EXTRA_CACHE, session->variables.read_buff_size);
1 by brian
clean slate
238
  }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
239
  /*
1 by brian
clean slate
240
    Do condition pushdown for UPDATE/DELETE.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
241
    TODO: Remove this from here as it causes two condition pushdown calls
1 by brian
clean slate
242
    when we're running a SELECT and the condition cannot be pushed down.
243
  */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
244
  if (session->variables.engine_condition_pushdown &&
245
      select && select->cond &&
1 by brian
clean slate
246
      (select->cond->used_tables() & table->map) &&
247
      !table->file->pushed_cond)
248
    table->file->cond_push(select->cond);
249
51.1.4 by Jay Pipes
Removed all DBUG_XXX content from records.cc. Builds/tests run fine. On to next file...
250
  return;
1 by brian
clean slate
251
} /* init_read_record */
252
253
254
255
void end_read_record(READ_RECORD *info)
256
{                   /* free cache if used */
257
  if (info->cache)
258
  {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
259
    free((char*) info->cache);
1 by brian
clean slate
260
    info->cache=0;
261
  }
262
  if (info->table)
263
  {
264
    filesort_free_buffers(info->table,0);
265
    (void) info->file->extra(HA_EXTRA_NO_CACHE);
266
    if (info->read_record != rr_quick) // otherwise quick_range does it
267
      (void) info->file->ha_index_or_rnd_end();
268
    info->table=0;
269
  }
270
}
271
272
static int rr_handle_error(READ_RECORD *info, int error)
273
{
274
  if (error == HA_ERR_END_OF_FILE)
275
    error= -1;
276
  else
277
  {
278
    if (info->print_error)
279
      info->table->file->print_error(error, MYF(0));
280
    if (error < 0)                            // Fix negative BDB errno
281
      error= 1;
282
  }
283
  return error;
284
}
285
286
287
/** Read a record from head-database. */
288
289
static int rr_quick(READ_RECORD *info)
290
{
291
  int tmp;
292
  while ((tmp= info->select->quick->get_next()))
293
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
294
    if (info->session->killed)
1 by brian
clean slate
295
    {
296
      my_error(ER_SERVER_SHUTDOWN, MYF(0));
297
      return 1;
298
    }
299
    if (tmp != HA_ERR_RECORD_DELETED)
300
    {
301
      tmp= rr_handle_error(info, tmp);
302
      break;
303
    }
304
  }
383.7.1 by Andrey Zhakov
Initial submit of code and tests
305
  update_virtual_fields_marked_for_write(info->table);
1 by brian
clean slate
306
  return tmp;
307
}
308
309
310
/**
311
  Reads first row in an index scan.
312
313
  @param info  	Scan info
314
315
  @retval
316
    0   Ok
317
  @retval
318
    -1   End of records
319
  @retval
320
    1   Error
321
*/
322
323
static int rr_index_first(READ_RECORD *info)
324
{
325
  int tmp= info->file->index_first(info->record);
326
  info->read_record= rr_index;
327
  if (tmp)
328
    tmp= rr_handle_error(info, tmp);
329
  return tmp;
330
}
331
332
333
/**
334
  Reads index sequentially after first row.
335
336
  Read the next index record (in forward direction) and translate return
337
  value.
338
339
  @param info  Scan info
340
341
  @retval
342
    0   Ok
343
  @retval
344
    -1   End of records
345
  @retval
346
    1   Error
347
*/
348
349
static int rr_index(READ_RECORD *info)
350
{
351
  int tmp= info->file->index_next(info->record);
352
  if (tmp)
353
    tmp= rr_handle_error(info, tmp);
354
  return tmp;
355
}
356
357
358
int rr_sequential(READ_RECORD *info)
359
{
360
  int tmp;
361
  while ((tmp=info->file->rnd_next(info->record)))
362
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
363
    if (info->session->killed)
1 by brian
clean slate
364
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
365
      info->session->send_kill_message();
1 by brian
clean slate
366
      return 1;
367
    }
368
    /*
369
      rnd_next can return RECORD_DELETED for MyISAM when one thread is
370
      reading and another deleting without locks.
371
    */
372
    if (tmp != HA_ERR_RECORD_DELETED)
373
    {
374
      tmp= rr_handle_error(info, tmp);
375
      break;
376
    }
377
  }
383.7.1 by Andrey Zhakov
Initial submit of code and tests
378
  if (!tmp)
379
    update_virtual_fields_marked_for_write(info->table);
1 by brian
clean slate
380
  return tmp;
381
}
382
383
384
static int rr_from_tempfile(READ_RECORD *info)
385
{
386
  int tmp;
387
  for (;;)
388
  {
389
    if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
390
      return -1;					/* End of file */
391
    if (!(tmp=info->file->rnd_pos(info->record,info->ref_pos)))
392
      break;
393
    /* The following is extremely unlikely to happen */
394
    if (tmp == HA_ERR_RECORD_DELETED ||
395
        (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
396
      continue;
397
    tmp= rr_handle_error(info, tmp);
398
    break;
399
  }
400
  return tmp;
401
} /* rr_from_tempfile */
402
403
404
/**
405
  Read a result set record from a temporary file after sorting.
406
407
  The function first reads the next sorted record from the temporary file.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
408
  into a buffer. If a success it calls a callback function that unpacks
1 by brian
clean slate
409
  the fields values use in the result set from this buffer into their
410
  positions in the regular record buffer.
411
412
  @param info          Reference to the context including record descriptors
413
414
  @retval
415
    0   Record successfully read.
416
  @retval
417
    -1   There is no record to be read anymore.
418
*/
419
420
static int rr_unpack_from_tempfile(READ_RECORD *info)
421
{
422
  if (my_b_read(info->io_cache, info->rec_buf, info->ref_length))
423
    return -1;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
424
  Table *table= info->table;
1 by brian
clean slate
425
  (*table->sort.unpack)(table->sort.addon_field, info->rec_buf);
426
427
  return 0;
428
}
429
430
static int rr_from_pointers(READ_RECORD *info)
431
{
432
  int tmp;
481 by Brian Aker
Remove all of uchar.
433
  unsigned char *cache_pos;
1 by brian
clean slate
434
435
  for (;;)
436
  {
437
    if (info->cache_pos == info->cache_end)
438
      return -1;					/* End of file */
439
    cache_pos= info->cache_pos;
440
    info->cache_pos+= info->ref_length;
441
442
    if (!(tmp=info->file->rnd_pos(info->record,cache_pos)))
443
      break;
444
445
    /* The following is extremely unlikely to happen */
446
    if (tmp == HA_ERR_RECORD_DELETED ||
447
        (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
448
      continue;
449
    tmp= rr_handle_error(info, tmp);
450
    break;
451
  }
452
  return tmp;
453
}
454
455
/**
456
  Read a result set record from a buffer after sorting.
457
458
  The function first reads the next sorted record from the sort buffer.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
459
  If a success it calls a callback function that unpacks
1 by brian
clean slate
460
  the fields values use in the result set from this buffer into their
461
  positions in the regular record buffer.
462
463
  @param info          Reference to the context including record descriptors
464
465
  @retval
466
    0   Record successfully read.
467
  @retval
468
    -1   There is no record to be read anymore.
469
*/
470
471
static int rr_unpack_from_buffer(READ_RECORD *info)
472
{
473
  if (info->cache_pos == info->cache_end)
474
    return -1;                      /* End of buffer */
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
475
  Table *table= info->table;
1 by brian
clean slate
476
  (*table->sort.unpack)(table->sort.addon_field, info->cache_pos);
477
  info->cache_pos+= info->ref_length;
478
479
  return 0;
480
}
481
	/* cacheing of records from a database */
482
520.1.22 by Brian Aker
Second pass of thd cleanup
483
static int init_rr_cache(Session *session, READ_RECORD *info)
1 by brian
clean slate
484
{
482 by Brian Aker
Remove uint.
485
  uint32_t rec_cache_size;
1 by brian
clean slate
486
487
  info->struct_length= 3+MAX_REFLENGTH;
488
  info->reclength= ALIGN_SIZE(info->table->s->reclength+1);
489
  if (info->reclength < info->struct_length)
490
    info->reclength= ALIGN_SIZE(info->struct_length);
491
492
  info->error_offset= info->table->s->reclength;
520.1.22 by Brian Aker
Second pass of thd cleanup
493
  info->cache_records= (session->variables.read_rnd_buff_size /
1 by brian
clean slate
494
                        (info->reclength+info->struct_length));
495
  rec_cache_size= info->cache_records*info->reclength;
496
  info->rec_cache_size= info->cache_records*info->ref_length;
497
498
  // We have to allocate one more byte to use uint3korr (see comments for it)
499
  if (info->cache_records <= 2 ||
641.3.7 by Monty Taylor
More my_malloc removal.
500
      !(info->cache=(unsigned char*) malloc(rec_cache_size+info->cache_records*
501
					    info->struct_length+1)))
51.1.4 by Jay Pipes
Removed all DBUG_XXX content from records.cc. Builds/tests run fine. On to next file...
502
    return(1);
1 by brian
clean slate
503
#ifdef HAVE_purify
504
  // Avoid warnings in qsort
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
505
  memset(info->cache, 0,
506
         rec_cache_size+info->cache_records* info->struct_length+1);
1 by brian
clean slate
507
#endif
508
  info->read_positions=info->cache+rec_cache_size;
509
  info->cache_pos=info->cache_end=info->cache;
51.1.4 by Jay Pipes
Removed all DBUG_XXX content from records.cc. Builds/tests run fine. On to next file...
510
  return(0);
1 by brian
clean slate
511
} /* init_rr_cache */
512
513
514
static int rr_from_cache(READ_RECORD *info)
515
{
482 by Brian Aker
Remove uint.
516
  register uint32_t i;
308 by Brian Aker
ulong conversion
517
  uint32_t length;
1 by brian
clean slate
518
  my_off_t rest_of_file;
206 by Brian Aker
Removed final uint dead types.
519
  int16_t error;
481 by Brian Aker
Remove all of uchar.
520
  unsigned char *position,*ref_position,*record_pos;
308 by Brian Aker
ulong conversion
521
  uint32_t record;
1 by brian
clean slate
522
523
  for (;;)
524
  {
525
    if (info->cache_pos != info->cache_end)
526
    {
527
      if (info->cache_pos[info->error_offset])
528
      {
529
	shortget(error,info->cache_pos);
530
	if (info->print_error)
531
	  info->table->file->print_error(error,MYF(0));
532
      }
533
      else
534
      {
535
	error=0;
536
	memcpy(info->record,info->cache_pos,
537
               (size_t) info->table->s->reclength);
538
      }
539
      info->cache_pos+=info->reclength;
540
      return ((int) error);
541
    }
542
    length=info->rec_cache_size;
543
    rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
544
    if ((my_off_t) length > rest_of_file)
308 by Brian Aker
ulong conversion
545
      length= (uint32_t) rest_of_file;
1 by brian
clean slate
546
    if (!length || my_b_read(info->io_cache,info->cache,length))
547
    {
548
      return -1;			/* End of file */
549
    }
550
551
    length/=info->ref_length;
552
    position=info->cache;
553
    ref_position=info->read_positions;
554
    for (i=0 ; i < length ; i++,position+=info->ref_length)
555
    {
556
      memcpy(ref_position,position,(size_t) info->ref_length);
557
      ref_position+=MAX_REFLENGTH;
558
      int3store(ref_position,(long) i);
559
      ref_position+=3;
560
    }
561
    my_qsort(info->read_positions, length, info->struct_length,
562
             (qsort_cmp) rr_cmp);
563
564
    position=info->read_positions;
565
    for (i=0 ; i < length ; i++)
566
    {
567
      memcpy(info->ref_pos,position,(size_t) info->ref_length);
568
      position+=MAX_REFLENGTH;
569
      record=uint3korr(position);
570
      position+=3;
571
      record_pos=info->cache+record*info->reclength;
206 by Brian Aker
Removed final uint dead types.
572
      if ((error=(int16_t) info->file->rnd_pos(record_pos,info->ref_pos)))
1 by brian
clean slate
573
      {
574
	record_pos[info->error_offset]=1;
575
	shortstore(record_pos,error);
576
      }
577
      else
578
	record_pos[info->error_offset]=0;
579
    }
580
    info->cache_end=(info->cache_pos=info->cache)+length*info->reclength;
581
  }
582
} /* rr_from_cache */
583
584
481 by Brian Aker
Remove all of uchar.
585
static int rr_cmp(unsigned char *a,unsigned char *b)
1 by brian
clean slate
586
{
587
  if (a[0] != b[0])
588
    return (int) a[0] - (int) b[0];
589
  if (a[1] != b[1])
590
    return (int) a[1] - (int) b[1];
591
  if (a[2] != b[2])
592
    return (int) a[2] - (int) b[2];
593
#if MAX_REFLENGTH == 4
594
  return (int) a[3] - (int) b[3];
595
#else
596
  if (a[3] != b[3])
597
    return (int) a[3] - (int) b[3];
598
  if (a[4] != b[4])
599
    return (int) a[4] - (int) b[4];
600
  if (a[5] != b[5])
601
    return (int) a[1] - (int) b[5];
602
  if (a[6] != b[6])
603
    return (int) a[6] - (int) b[6];
604
  return (int) a[7] - (int) b[7];
605
#endif
606
}