~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/records.cc

  • Committer: Monty Taylor
  • Date: 2008-11-16 06:29:53 UTC
  • mto: (584.1.9 devel)
  • mto: This revision was merged to the branch mainline in revision 589.
  • Revision ID: monty@inaugust.com-20081116062953-ivdltjmfe009b5fr
Moved stuff into item/

Show diffs side-by-side

added added

removed removed

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