27
27
#include "drizzled/optimizer/range.h"
28
28
#include "drizzled/internal/my_sys.h"
29
29
#include "drizzled/internal/iocache.h"
30
#include "drizzled/drizzled.h"
35
static int rr_sequential(ReadRecord *info);
36
static int rr_quick(ReadRecord *info);
37
static int rr_from_tempfile(ReadRecord *info);
38
static int rr_unpack_from_tempfile(ReadRecord *info);
39
static int rr_unpack_from_buffer(ReadRecord *info);
40
static int rr_from_pointers(ReadRecord *info);
41
static int rr_from_cache(ReadRecord *info);
34
int rr_sequential(READ_RECORD *info);
35
static int rr_quick(READ_RECORD *info);
36
static int rr_from_tempfile(READ_RECORD *info);
37
static int rr_unpack_from_tempfile(READ_RECORD *info);
38
static int rr_unpack_from_buffer(READ_RECORD *info);
39
static int rr_from_pointers(READ_RECORD *info);
40
static int rr_from_cache(READ_RECORD *info);
41
static int init_rr_cache(Session *session, READ_RECORD *info);
42
42
static int rr_cmp(unsigned char *a,unsigned char *b);
43
static int rr_index_first(ReadRecord *info);
44
static int rr_index(ReadRecord *info);
46
void ReadRecord::init_reard_record_sequential()
48
read_record= rr_sequential;
51
void ReadRecord::init_read_record_idx(Session *,
56
table_arg->emptyRecord();
58
cursor= table->cursor;
59
record= table->getInsertRecord();
60
print_error= print_error_arg;
43
static int rr_index_first(READ_RECORD *info);
44
static int rr_index(READ_RECORD *info);
46
void init_read_record_idx(READ_RECORD *info,
53
memset(info, 0, sizeof(*info));
55
info->cursor= table->cursor;
56
info->record= table->record[0];
57
info->print_error= print_error;
62
59
table->status=0; /* And it's always found */
63
if (not table->cursor->inited)
64
table->cursor->startIndexScan(idx, 1);
60
if (!table->cursor->inited)
61
table->cursor->ha_index_init(idx, 1);
65
62
/* read_record will be changed to rr_index in rr_index_first */
66
read_record= rr_index_first;
63
info->read_record= rr_index_first;
70
void ReadRecord::init_read_record(Session *session_arg,
72
optimizer::SqlSelect *select_arg,
67
void init_read_record(READ_RECORD *info,
70
optimizer::SqlSelect *select,
76
74
internal::IO_CACHE *tempfile;
80
cursor= table->cursor;
81
forms= &table; /* Only one table */
76
memset(info, 0, sizeof(*info));
77
info->session=session;
79
info->cursor= table->cursor;
80
info->forms= &info->table; /* Only one table */
83
82
if (table->sort.addon_field)
85
rec_buf= table->sort.addon_buf;
86
ref_length= table->sort.addon_length;
84
info->rec_buf= table->sort.addon_buf;
85
info->ref_length= table->sort.addon_length;
90
89
table->emptyRecord();
91
record= table->getInsertRecord();
92
ref_length= table->cursor->ref_length;
90
info->record= table->record[0];
91
info->ref_length= table->cursor->ref_length;
95
print_error= print_error_arg;
96
ignore_not_found_rows= 0;
94
info->print_error= print_error;
95
info->ignore_not_found_rows= 0;
97
96
table->status=0; /* And it's always found */
99
98
if (select && my_b_inited(select->file))
101
99
tempfile= select->file;
105
101
tempfile= table->sort.io_cache;
108
102
if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
110
read_record= (table->sort.addon_field ?
111
rr_unpack_from_tempfile : rr_from_tempfile);
114
io_cache->reinit_io_cache(internal::READ_CACHE,0L,0,0);
115
ref_pos=table->cursor->ref;
104
info->read_record= (table->sort.addon_field ?
105
rr_unpack_from_tempfile : rr_from_tempfile);
106
info->io_cache=tempfile;
107
reinit_io_cache(info->io_cache,internal::READ_CACHE,0L,0,0);
108
info->ref_pos=table->cursor->ref;
116
109
if (!table->cursor->inited)
117
table->cursor->startTableScan(0);
110
table->cursor->ha_rnd_init(0);
120
113
table->sort.addon_field is checked because if we use addon fields,
126
119
!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) &&
127
120
(table->db_stat & HA_READ_ONLY ||
128
121
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
129
(uint64_t) table->getShare()->getRecordLength() * (table->cursor->stats.records+
122
(uint64_t) table->s->reclength* (table->cursor->stats.records+
130
123
table->cursor->stats.deleted) >
131
124
(uint64_t) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
132
io_cache->end_of_file/ref_length * table->getShare()->getRecordLength() >
125
info->io_cache->end_of_file/info->ref_length * table->s->reclength >
133
126
(internal::my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
134
!table->getShare()->blob_fields &&
135
ref_length <= MAX_REFLENGTH)
127
!table->s->blob_fields &&
128
info->ref_length <= MAX_REFLENGTH)
130
if (! init_rr_cache(session, info))
139
read_record= rr_from_cache;
132
info->read_record=rr_from_cache;
143
136
else if (select && select->quick)
145
read_record= rr_quick;
138
info->read_record=rr_quick;
147
140
else if (table->sort.record_pointers)
149
table->cursor->startTableScan(0);
150
cache_pos=table->sort.record_pointers;
151
cache_end= cache_pos+ table->sort.found_records * ref_length;
152
read_record= (table->sort.addon_field ? rr_unpack_from_buffer : rr_from_pointers);
142
table->cursor->ha_rnd_init(0);
143
info->cache_pos=table->sort.record_pointers;
144
info->cache_end=info->cache_pos+
145
table->sort.found_records*info->ref_length;
146
info->read_record= (table->sort.addon_field ?
147
rr_unpack_from_buffer : rr_from_pointers);
156
read_record= rr_sequential;
157
table->cursor->startTableScan(1);
151
info->read_record= rr_sequential;
152
table->cursor->ha_rnd_init(1);
158
153
/* We can use record cache if we don't update dynamic length tables */
159
154
if (!table->no_cache &&
160
155
(use_record_cache > 0 ||
161
156
(int) table->reginfo.lock_type <= (int) TL_READ_WITH_SHARED_LOCKS ||
162
!(table->getShare()->db_options_in_use & HA_OPTION_PACK_RECORD)))
157
!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD)))
164
158
table->cursor->extra_opt(HA_EXTRA_CACHE, session->variables.read_buff_size);
169
162
} /* init_read_record */
172
void ReadRecord::end_read_record()
165
void end_read_record(READ_RECORD *info)
173
166
{ /* free cache if used */
176
global_read_rnd_buffer.sub(session->variables.read_rnd_buff_size);
169
free((char*) info->cache);
182
table->filesort_free_buffers();
183
(void) cursor->extra(HA_EXTRA_NO_CACHE);
184
if (read_record != rr_quick) // otherwise quick_range does it
185
(void) cursor->ha_index_or_rnd_end();
174
info->table->filesort_free_buffers();
175
(void) info->cursor->extra(HA_EXTRA_NO_CACHE);
176
if (info->read_record != rr_quick) // otherwise quick_range does it
177
(void) info->cursor->ha_index_or_rnd_end();
191
static int rr_handle_error(ReadRecord *info, int error)
182
static int rr_handle_error(READ_RECORD *info, int error)
193
184
if (error == HA_ERR_END_OF_FILE)
391
381
/* cacheing of records from a database */
392
bool ReadRecord::init_rr_cache()
382
static int init_rr_cache(Session *session, READ_RECORD *info)
394
uint32_t local_rec_cache_size;
396
struct_length= 3 + MAX_REFLENGTH;
397
reclength= ALIGN_SIZE(table->getShare()->getRecordLength() + 1);
398
if (reclength < struct_length)
399
reclength= ALIGN_SIZE(struct_length);
401
error_offset= table->getShare()->getRecordLength();
402
cache_records= (session->variables.read_rnd_buff_size /
403
(reclength + struct_length));
404
local_rec_cache_size= cache_records * reclength;
405
rec_cache_size= cache_records * ref_length;
407
if (not global_read_rnd_buffer.add(session->variables.read_rnd_buff_size))
409
my_error(ER_OUT_OF_GLOBAL_READRNDMEMORY, MYF(ME_ERROR+ME_WAITTANG));
384
uint32_t rec_cache_size;
386
info->struct_length= 3+MAX_REFLENGTH;
387
info->reclength= ALIGN_SIZE(info->table->s->reclength+1);
388
if (info->reclength < info->struct_length)
389
info->reclength= ALIGN_SIZE(info->struct_length);
391
info->error_offset= info->table->s->reclength;
392
info->cache_records= (session->variables.read_rnd_buff_size /
393
(info->reclength+info->struct_length));
394
rec_cache_size= info->cache_records*info->reclength;
395
info->rec_cache_size= info->cache_records*info->ref_length;
413
397
// We have to allocate one more byte to use uint3korr (see comments for it)
414
if (cache_records <= 2 ||
415
!(cache=(unsigned char*) malloc(local_rec_cache_size + cache_records * struct_length + 1)))
398
if (info->cache_records <= 2 ||
399
!(info->cache=(unsigned char*) malloc(rec_cache_size+info->cache_records*
400
info->struct_length+1)))
420
403
// Avoid warnings in qsort
421
memset(cache, 0, local_rec_cache_size + cache_records * struct_length + 1);
404
memset(info->cache, 0,
405
rec_cache_size+info->cache_records* info->struct_length+1);
423
read_positions= cache + local_rec_cache_size;
424
cache_pos= cache_end= cache;
407
info->read_positions=info->cache+rec_cache_size;
408
info->cache_pos=info->cache_end=info->cache;
427
410
} /* init_rr_cache */
429
static int rr_from_cache(ReadRecord *info)
412
static int rr_from_cache(READ_RECORD *info)
432
416
internal::my_off_t rest_of_file;
450
memcpy(info->record,info->cache_pos, (size_t) info->table->getShare()->getRecordLength());
434
memcpy(info->record,info->cache_pos, (size_t) info->table->s->reclength);
452
info->cache_pos+= info->reclength;
436
info->cache_pos+=info->reclength;
453
437
return ((int) error);
455
439
length=info->rec_cache_size;
456
rest_of_file= info->io_cache->end_of_file - my_b_tell(info->io_cache);
440
rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
457
441
if ((internal::my_off_t) length > rest_of_file)
459
442
length= (uint32_t) rest_of_file;
462
if (!length || my_b_read(info->io_cache, info->getCache(), length))
443
if (!length || my_b_read(info->io_cache,info->cache,length))
464
445
return -1; /* End of cursor */
467
448
length/=info->ref_length;
468
position=info->getCache();
449
position=info->cache;
469
450
ref_position=info->read_positions;
470
for (uint32_t i= 0 ; i < length ; i++,position+=info->ref_length)
451
for (i=0 ; i < length ; i++,position+=info->ref_length)
472
453
memcpy(ref_position,position,(size_t) info->ref_length);
473
454
ref_position+=MAX_REFLENGTH;