~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/records.cc

  • Committer: Brian Aker
  • Date: 2010-05-27 01:25:56 UTC
  • mfrom: (1567.1.4 new-staging)
  • Revision ID: brian@gaz-20100527012556-5zgkirkl7swbigd6
Merge of Brian, Paul. PBXT compile issue, and test framework cleanup. 

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