12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
16
#include "heap_priv.h"
38
39
/* Create a heap table */
40
41
int heap_create(const char *name, uint32_t keys, HP_KEYDEF *keydef,
42
uint32_t key_part_size,
43
uint32_t reclength, uint32_t keys_memory_size,
44
uint32_t max_records, uint32_t min_records,
45
HP_CREATE_INFO *create_info, HP_SHARE **res)
42
uint32_t columns, HP_COLUMNDEF *columndef,
43
uint32_t max_key_fieldnr, uint32_t key_part_size,
44
uint32_t reclength, uint32_t keys_memory_size,
45
uint32_t max_records, uint32_t min_records,
46
HP_CREATE_INFO *create_info, HP_SHARE **res)
47
48
uint32_t i, key_segs, max_length, length;
48
49
uint32_t max_rows_for_stated_memory;
49
50
HP_SHARE *share= 0;
52
if (not create_info->internal_table)
53
if (!create_info->internal_table)
54
55
THR_LOCK_heap.lock();
55
56
if ((share= hp_find_named_heap(name)) && share->open_count == 0)
75
76
if (configured_chunk_size < key_part_size)
77
78
/* Eventual chunk_size cannot be smaller than key data,
78
which allows all keys to fit into the first chunk */
79
which allows all keys to fit into the first chunk */
79
80
my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "block_size");
80
81
THR_LOCK_heap.unlock();
81
82
return(ER_CANT_USE_OPTION_HERE);
84
/* max_chunk_size is near the full reclength, let's use fixed size */
85
chunk_dataspace_length= reclength;
85
if ((reclength - configured_chunk_size) >= VARIABLE_MIN_CHUNK_SIZE<<1)
87
/* Allow variable size only if we're saving at least two smallest chunks */
88
/* There has to be at least one field after indexed fields */
89
/* Note that NULL bits are already included in key_part_size */
91
chunk_dataspace_length= configured_chunk_size;
95
/* max_chunk_size is near the full reclength, let's use fixed size */
97
chunk_dataspace_length= reclength;
100
else if (create_info->is_dynamic)
102
/* User asked for dynamic records - use 256 as the chunk size */
103
if ((key_part_size + VARIABLE_REC_OVERHEAD) > 256)
104
chunk_dataspace_length= key_part_size;
106
chunk_dataspace_length= 256 - VARIABLE_REC_OVERHEAD;
89
112
/* if max_chunk_size is not specified, put the whole record in one chunk */
90
114
chunk_dataspace_length= reclength;
117
if (is_variable_size)
119
/* Check whether we have any variable size records past key data */
120
uint32_t has_variable_fields= 0;
122
fixed_data_length= key_part_size;
123
fixed_column_count= max_key_fieldnr;
125
for (i= max_key_fieldnr; i < columns; i++)
127
HP_COLUMNDEF* column= columndef + i;
128
if (column->type == DRIZZLE_TYPE_VARCHAR && column->length >= 32)
130
/* The field has to be >= 5.0.3 true VARCHAR and have substantial length */
131
/* TODO: do we want to calculate minimum length? */
132
has_variable_fields= 1;
136
if (has_variable_fields)
141
if ((column->offset + column->length) <= chunk_dataspace_length)
143
/* Still no variable-size columns, add one fixed-length */
144
fixed_column_count= i + 1;
145
fixed_data_length= column->offset + column->length;
149
if (!has_variable_fields)
151
/* There is no need to use variable-size records without variable-size columns */
152
/* Reset sizes if it's not variable size anymore */
154
chunk_dataspace_length= reclength;
155
fixed_data_length= reclength;
156
fixed_column_count= columns;
94
161
fixed_data_length= reclength;
95
162
fixed_column_count= columns;
113
185
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
115
187
memset(&keyinfo->block, 0, sizeof(keyinfo->block));
188
memset(&keyinfo->rb_tree , 0, sizeof(keyinfo->rb_tree));
116
189
for (uint32_t j= length= 0; j < keyinfo->keysegs; j++)
118
191
length+= keyinfo->seg[j].length;
161
237
keyinfo->length= length;
238
length+= keyinfo->rb_tree.size_of_element +
239
((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(unsigned char*) : 0);
162
240
if (length > max_length)
163
241
max_length= length;
164
242
key_segs+= keyinfo->keysegs;
243
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
245
key_segs++; /* additional HA_KEYTYPE_END segment */
246
if (keyinfo->flag & HA_VAR_LENGTH_KEY)
247
keyinfo->get_key_length= hp_rb_var_key_length;
248
else if (keyinfo->flag & HA_NULL_PART_KEY)
249
keyinfo->get_key_length= hp_rb_null_key_length;
251
keyinfo->get_key_length= hp_rb_key_length;
166
254
share= new HP_SHARE;
192
282
memcpy(keyseg, keydef[i].seg,
193
283
(size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
194
284
keyseg+= keydef[i].keysegs;
286
if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
288
/* additional HA_KEYTYPE_END keyseg */
289
keyseg->type= HA_KEYTYPE_END;
290
keyseg->length= sizeof(unsigned char*);
295
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
296
(qsort_cmp2)keys_compare, true, NULL, NULL);
297
keyinfo->delete_key= hp_rb_delete_key;
298
keyinfo->write_key= hp_rb_write_key;
196
302
init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
304
keyinfo->delete_key= hp_delete_key;
305
keyinfo->write_key= hp_write_key;
198
306
keyinfo->hash_buckets= 0;
200
308
if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
219
327
share->recordspace.chunk_length= chunk_length;
220
328
share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
329
share->recordspace.is_variable_size= is_variable_size;
221
330
share->recordspace.total_data_length= 0;
332
if (is_variable_size) {
333
share->recordspace.offset_link= chunk_dataspace_length;
334
share->recordspace.offset_status= share->recordspace.offset_link + sizeof(unsigned char**);
224
336
share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
225
337
share->recordspace.offset_status= chunk_dataspace_length;
228
340
/* Must be allocated separately for rename to work */
229
341
share->name.append(name);
342
thr_lock_init(&share->lock);
230
343
if (!create_info->internal_table)
232
345
heap_share_list.push_front(share);
253
368
} /* heap_create */
371
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2)
373
uint32_t not_used[2];
374
return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
375
param->search_flag, not_used);
256
378
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
257
379
uint32_t max_records)