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"
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);
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);
42
42
static int rr_cmp(unsigned char *a,unsigned char *b);
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;
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
int ReadRecord::init_read_record_idx(Session *,
56
table_arg->emptyRecord();
58
cursor= table->cursor;
59
record= table->getInsertRecord();
60
print_error= print_error_arg;
59
62
table->status=0; /* And it's always found */
60
if (!table->cursor->inited)
61
table->cursor->ha_index_init(idx, 1);
63
if (not table->cursor->inited)
65
int error= table->cursor->startIndexScan(idx, 1);
62
69
/* read_record will be changed to rr_index in rr_index_first */
63
info->read_record= rr_index_first;
70
read_record= rr_index_first;
67
void init_read_record(READ_RECORD *info,
70
optimizer::SqlSelect *select,
76
int ReadRecord::init_read_record(Session *session_arg,
78
optimizer::SqlSelect *select_arg,
74
82
internal::IO_CACHE *tempfile;
76
memset(info, 0, sizeof(*info));
77
info->session=session;
79
info->cursor= table->cursor;
80
info->forms= &info->table; /* Only one table */
87
cursor= table->cursor;
88
forms= &table; /* Only one table */
82
90
if (table->sort.addon_field)
84
info->rec_buf= table->sort.addon_buf;
85
info->ref_length= table->sort.addon_length;
92
rec_buf= table->sort.addon_buf;
93
ref_length= table->sort.addon_length;
89
97
table->emptyRecord();
90
info->record= table->record[0];
91
info->ref_length= table->cursor->ref_length;
98
record= table->getInsertRecord();
99
ref_length= table->cursor->ref_length;
94
info->print_error= print_error;
95
info->ignore_not_found_rows= 0;
102
print_error= print_error_arg;
103
ignore_not_found_rows= 0;
96
104
table->status=0; /* And it's always found */
98
106
if (select && my_b_inited(select->file))
99
108
tempfile= select->file;
101
112
tempfile= table->sort.io_cache;
102
115
if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
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;
117
read_record= (table->sort.addon_field ?
118
rr_unpack_from_tempfile : rr_from_tempfile);
121
io_cache->reinit_io_cache(internal::READ_CACHE,0L,0,0);
122
ref_pos=table->cursor->ref;
109
123
if (!table->cursor->inited)
110
table->cursor->ha_rnd_init(0);
125
error= table->cursor->startTableScan(0);
113
131
table->sort.addon_field is checked because if we use addon fields,
119
137
!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) &&
120
138
(table->db_stat & HA_READ_ONLY ||
121
139
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
122
(uint64_t) table->s->reclength* (table->cursor->stats.records+
140
(uint64_t) table->getShare()->getRecordLength() * (table->cursor->stats.records+
123
141
table->cursor->stats.deleted) >
124
142
(uint64_t) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
125
info->io_cache->end_of_file/info->ref_length * table->s->reclength >
143
io_cache->end_of_file/ref_length * table->getShare()->getRecordLength() >
126
144
(internal::my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
127
!table->s->blob_fields &&
128
info->ref_length <= MAX_REFLENGTH)
145
!table->getShare()->blob_fields &&
146
ref_length <= MAX_REFLENGTH)
130
if (! init_rr_cache(session, info))
132
info->read_record=rr_from_cache;
150
read_record= rr_from_cache;
136
154
else if (select && select->quick)
138
info->read_record=rr_quick;
156
read_record= rr_quick;
140
158
else if (table->sort.record_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);
160
error= table->cursor->startTableScan(0);
164
cache_pos=table->sort.record_pointers;
165
cache_end= cache_pos+ table->sort.found_records * ref_length;
166
read_record= (table->sort.addon_field ? rr_unpack_from_buffer : rr_from_pointers);
151
info->read_record= rr_sequential;
152
table->cursor->ha_rnd_init(1);
170
read_record= rr_sequential;
171
error= table->cursor->startTableScan(1);
153
175
/* We can use record cache if we don't update dynamic length tables */
154
176
if (!table->no_cache &&
155
177
(use_record_cache > 0 ||
156
178
(int) table->reginfo.lock_type <= (int) TL_READ_WITH_SHARED_LOCKS ||
157
!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD)))
179
!(table->getShare()->db_options_in_use & HA_OPTION_PACK_RECORD)))
158
181
table->cursor->extra_opt(HA_EXTRA_CACHE, session->variables.read_buff_size);
162
186
} /* init_read_record */
165
void end_read_record(READ_RECORD *info)
189
void ReadRecord::end_read_record()
166
190
{ /* free cache if used */
169
free((char*) info->cache);
193
global_read_rnd_buffer.sub(session->variables.read_rnd_buff_size);
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();
199
table->filesort_free_buffers();
200
(void) cursor->extra(HA_EXTRA_NO_CACHE);
201
if (read_record != rr_quick) // otherwise quick_range does it
202
(void) cursor->ha_index_or_rnd_end();
182
static int rr_handle_error(READ_RECORD *info, int error)
208
static int rr_handle_error(ReadRecord *info, int error)
184
210
if (error == HA_ERR_END_OF_FILE)
381
408
/* cacheing of records from a database */
382
static int init_rr_cache(Session *session, READ_RECORD *info)
409
bool ReadRecord::init_rr_cache()
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;
411
uint32_t local_rec_cache_size;
413
struct_length= 3 + MAX_REFLENGTH;
414
reclength= ALIGN_SIZE(table->getShare()->getRecordLength() + 1);
415
if (reclength < struct_length)
416
reclength= ALIGN_SIZE(struct_length);
418
error_offset= table->getShare()->getRecordLength();
419
cache_records= (session->variables.read_rnd_buff_size /
420
(reclength + struct_length));
421
local_rec_cache_size= cache_records * reclength;
422
rec_cache_size= cache_records * ref_length;
424
if (not global_read_rnd_buffer.add(session->variables.read_rnd_buff_size))
426
my_error(ER_OUT_OF_GLOBAL_READRNDMEMORY, MYF(ME_ERROR+ME_WAITTANG));
397
430
// We have to allocate one more byte to use uint3korr (see comments for it)
398
if (info->cache_records <= 2 ||
399
!(info->cache=(unsigned char*) malloc(rec_cache_size+info->cache_records*
400
info->struct_length+1)))
431
if (cache_records <= 2 ||
432
!(cache=(unsigned char*) malloc(local_rec_cache_size + cache_records * struct_length + 1)))
403
437
// Avoid warnings in qsort
404
memset(info->cache, 0,
405
rec_cache_size+info->cache_records* info->struct_length+1);
438
memset(cache, 0, local_rec_cache_size + cache_records * struct_length + 1);
407
info->read_positions=info->cache+rec_cache_size;
408
info->cache_pos=info->cache_end=info->cache;
440
read_positions= cache + local_rec_cache_size;
441
cache_pos= cache_end= cache;
410
444
} /* init_rr_cache */
412
static int rr_from_cache(READ_RECORD *info)
446
static int rr_from_cache(ReadRecord *info)
416
449
internal::my_off_t rest_of_file;
434
memcpy(info->record,info->cache_pos, (size_t) info->table->s->reclength);
467
memcpy(info->record,info->cache_pos, (size_t) info->table->getShare()->getRecordLength());
436
info->cache_pos+=info->reclength;
469
info->cache_pos+= info->reclength;
437
470
return ((int) error);
439
472
length=info->rec_cache_size;
440
rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
473
rest_of_file= info->io_cache->end_of_file - my_b_tell(info->io_cache);
441
474
if ((internal::my_off_t) length > rest_of_file)
442
476
length= (uint32_t) rest_of_file;
443
if (!length || my_b_read(info->io_cache,info->cache,length))
479
if (!length || my_b_read(info->io_cache, info->getCache(), length))
445
481
return -1; /* End of cursor */
448
484
length/=info->ref_length;
449
position=info->cache;
485
position=info->getCache();
450
486
ref_position=info->read_positions;
451
for (i=0 ; i < length ; i++,position+=info->ref_length)
487
for (uint32_t i= 0 ; i < length ; i++,position+=info->ref_length)
453
489
memcpy(ref_position,position,(size_t) info->ref_length);
454
490
ref_position+=MAX_REFLENGTH;