]>
Commit | Line | Data |
---|---|---|
db82db79 AM |
1 | --- a/include/heap.h |
2 | +++ b/include/heap.h | |
3 | @@ -34,7 +34,17 @@ | |
4 | #include "my_compare.h" | |
5 | #include "my_tree.h" | |
6 | ||
7 | - /* defines used by heap-funktions */ | |
8 | +/* Define index limits to be identical to MyISAM ones for compatibility. */ | |
9 | + | |
10 | +#if MAX_INDEXES > HA_MAX_POSSIBLE_KEY | |
11 | +#define HP_MAX_KEY HA_MAX_POSSIBLE_KEY /* Max allowed keys */ | |
12 | +#else | |
13 | +#define HP_MAX_KEY MAX_INDEXES /* Max allowed keys */ | |
14 | +#endif | |
15 | + | |
16 | +#define HP_MAX_KEY_LENGTH 1000 /* Max length in bytes */ | |
17 | + | |
18 | +/* defines used by heap-funktions */ | |
19 | ||
20 | #define HP_MAX_LEVELS 4 /* 128^5 records is enough */ | |
21 | #define HP_PTRS_IN_NOD 128 | |
734d6226 | 22 | @@ -131,22 +141,58 @@ |
db82db79 AM |
23 | uint (*get_key_length)(struct st_hp_keydef *keydef, const uchar *key); |
24 | } HP_KEYDEF; | |
25 | ||
26 | -typedef struct st_heap_share | |
27 | +typedef struct st_heap_columndef /* column information */ | |
28 | +{ | |
29 | + int16 type; /* en_fieldtype */ | |
30 | + uint32 length; /* length of field */ | |
31 | + uint32 offset; /* Offset to position in row */ | |
32 | + uint8 null_bit; /* If column may be 0 */ | |
33 | + uint16 null_pos; /* position for null marker */ | |
34 | + uint8 length_bytes; /* length of the size, 1 o 2 bytes */ | |
35 | +} HP_COLUMNDEF; | |
36 | + | |
37 | +typedef struct st_heap_dataspace /* control data for data space */ | |
38 | { | |
39 | HP_BLOCK block; | |
40 | + /* Total chunks ever allocated in this dataspace */ | |
41 | + uint chunk_count; | |
42 | + uint del_chunk_count; /* Deleted chunks count */ | |
43 | + uchar *del_link; /* Link to last deleted chunk */ | |
44 | + uint chunk_length; /* Total length of one chunk */ | |
45 | + /* Length of payload that will be placed into one chunk */ | |
46 | + uint chunk_dataspace_length; | |
47 | + /* Offset of the status flag relative to the chunk start */ | |
48 | + uint offset_status; | |
49 | + /* Offset of the linking pointer relative to the chunk start */ | |
50 | + uint offset_link; | |
51 | + /* Test whether records have variable size and so "next" pointer */ | |
52 | + uint is_variable_size; | |
53 | + /* Total size allocated within this data space */ | |
54 | + ulonglong total_data_length; | |
55 | +} HP_DATASPACE; | |
56 | + | |
57 | +typedef struct st_heap_share | |
58 | +{ | |
59 | HP_KEYDEF *keydef; | |
60 | + HP_COLUMNDEF *column_defs; | |
61 | + /* Describes "block", which contains actual records */ | |
62 | + HP_DATASPACE recordspace; | |
63 | ulong min_records,max_records; /* Params to open */ | |
64 | - ulonglong data_length,index_length,max_table_size; | |
65 | + ulonglong index_length, max_table_size; | |
66 | uint key_stat_version; /* version to indicate insert/delete */ | |
67 | - uint records; /* records */ | |
68 | - uint blength; /* records rounded up to 2^n */ | |
69 | - uint deleted; /* Deleted records in database */ | |
70 | - uint reclength; /* Length of one record */ | |
71 | + uint records; /* Actual record (row) count */ | |
72 | + uint blength; /* used_chunk_count rounded up to 2^n */ | |
73 | + /* | |
74 | + Length of record's fixed part, which contains keys and always fits into the | |
75 | + first chunk. | |
76 | + */ | |
77 | + uint fixed_data_length; | |
78 | + uint fixed_column_count; /* Number of columns stored in fixed_data_length */ | |
79 | uint changed; | |
80 | uint keys,max_key_length; | |
81 | + uint column_count; | |
82 | uint currently_disabled_keys; /* saved value from "keys" when disabled */ | |
83 | uint open_count; | |
84 | - uchar *del_link; /* Link to next block with del. rec */ | |
85 | char * name; /* Name of "memory-file" */ | |
734d6226 | 86 | time_t create_time; |
db82db79 | 87 | THR_LOCK lock; |
734d6226 | 88 | @@ -156,6 +202,7 @@ |
db82db79 AM |
89 | uint auto_key; |
90 | uint auto_key_type; /* real type of the auto key segment */ | |
91 | ulonglong auto_increment; | |
92 | + uint blobs; /* Number of blobs in table */ | |
93 | } HP_SHARE; | |
94 | ||
95 | struct st_hp_hash_info; | |
734d6226 | 96 | @@ -165,7 +212,7 @@ |
db82db79 AM |
97 | HP_SHARE *s; |
98 | uchar *current_ptr; | |
99 | struct st_hp_hash_info *current_hash_ptr; | |
100 | - ulong current_record,next_block; | |
101 | + ulong current_record; | |
102 | int lastinx,errkey; | |
103 | int mode; /* Mode of file (READONLY..) */ | |
104 | uint opt_flag,update; | |
734d6226 | 105 | @@ -178,6 +225,9 @@ |
db82db79 AM |
106 | my_bool implicit_emptied; |
107 | THR_LOCK_DATA lock; | |
108 | LIST open_list; | |
109 | + uchar *blob_buffer; /* Temporary buffer used to return BLOB values */ | |
110 | + uint blob_size; /* Current blob_buffer size */ | |
111 | + uint blob_offset; /* Current offset in blob_buffer */ | |
112 | } HP_INFO; | |
113 | ||
114 | ||
734d6226 | 115 | @@ -199,6 +249,14 @@ |
db82db79 AM |
116 | open_count to 1. Is only looked at if not internal_table. |
117 | */ | |
118 | my_bool pin_share; | |
119 | + uint columns; | |
120 | + HP_COLUMNDEF *columndef; | |
121 | + uint fixed_key_fieldnr; | |
122 | + uint fixed_data_size; | |
123 | + uint keys_memory_size; | |
124 | + uint max_chunk_size; | |
125 | + uint is_dynamic; | |
126 | + uint blobs; | |
127 | } HP_CREATE_INFO; | |
128 | ||
129 | /* Prototypes for heap-functions */ | |
734d6226 | 130 | @@ -215,9 +273,8 @@ |
db82db79 AM |
131 | extern int heap_scan(register HP_INFO *info, uchar *record); |
132 | extern int heap_delete(HP_INFO *info,const uchar *buff); | |
133 | extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag); | |
134 | -extern int heap_create(const char *name, | |
135 | - HP_CREATE_INFO *create_info, HP_SHARE **share, | |
136 | - my_bool *created_new_share); | |
137 | +extern int heap_create(const char *name, HP_CREATE_INFO *create_info, | |
138 | + HP_SHARE **res, my_bool *created_new_share); | |
139 | extern int heap_delete_table(const char *name); | |
140 | extern void heap_drop_table(HP_INFO *info); | |
141 | extern int heap_extra(HP_INFO *info,enum ha_extra_function function); | |
142 | --- a/mysql-test/r/create.result | |
143 | +++ b/mysql-test/r/create.result | |
144 | @@ -33,10 +33,7 @@ | |
145 | create table t1 (b char(0) not null, index(b)); | |
146 | ERROR 42000: The used storage engine can't index column 'b' | |
147 | create table t1 (a int not null,b text) engine=heap; | |
148 | -ERROR 42000: The used table type doesn't support BLOB/TEXT columns | |
149 | drop table if exists t1; | |
150 | -Warnings: | |
151 | -Note 1051 Unknown table 't1' | |
152 | create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) engine=heap; | |
153 | ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key | |
154 | create table not_existing_database.test (a int); | |
155 | --- a/mysql-test/r/ctype_utf8mb4_heap.result | |
156 | +++ b/mysql-test/r/ctype_utf8mb4_heap.result | |
157 | @@ -1124,6 +1124,8 @@ | |
158 | a varchar(255) NOT NULL default '', | |
159 | KEY a (a) | |
160 | ) ENGINE=heap DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; | |
161 | +Warnings: | |
162 | +Warning 1071 Specified key was too long; max key length is 1000 bytes | |
163 | insert into t1 values (_utf8mb4 0xe880bd); | |
164 | insert into t1 values (_utf8mb4 0x5b); | |
165 | select hex(a) from t1; | |
166 | @@ -1162,6 +1164,8 @@ | |
167 | Warnings: | |
168 | Note 1051 Unknown table 't1' | |
169 | CREATE TABLE t1(a VARCHAR(255), KEY(a)) ENGINE=heap DEFAULT CHARSET=utf8mb4; | |
170 | +Warnings: | |
171 | +Warning 1071 Specified key was too long; max key length is 1000 bytes | |
172 | INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'); | |
173 | INSERT INTO t1 VALUES('uu'); | |
174 | check table t1; | |
175 | --- a/mysql-test/t/create.test | |
176 | +++ b/mysql-test/t/create.test | |
177 | @@ -33,7 +33,7 @@ | |
178 | drop table if exists t1,t2; | |
179 | --error 1167 | |
180 | create table t1 (b char(0) not null, index(b)); | |
181 | ---error 1163 | |
182 | +# BLOB/TEXT fields are now supported by HEAP | |
183 | create table t1 (a int not null,b text) engine=heap; | |
184 | drop table if exists t1; | |
185 | ||
186 | --- a/storage/heap/CMakeLists.txt | |
187 | +++ b/storage/heap/CMakeLists.txt | |
188 | @@ -20,6 +20,7 @@ | |
189 | ha_heap.cc | |
190 | hp_delete.c hp_extra.c hp_hash.c hp_info.c hp_open.c hp_panic.c | |
191 | hp_rename.c hp_rfirst.c hp_rkey.c hp_rlast.c hp_rnext.c hp_rprev.c | |
192 | + hp_dspace.c hp_record.c | |
193 | hp_rrnd.c hp_rsame.c hp_scan.c hp_static.c hp_update.c hp_write.c) | |
194 | ||
195 | MYSQL_ADD_PLUGIN(heap ${HEAP_SOURCES} STORAGE_ENGINE MANDATORY RECOMPILE_FOR_EMBEDDED) | |
196 | --- a/storage/heap/_check.c | |
197 | +++ b/storage/heap/_check.c | |
198 | @@ -43,7 +43,7 @@ | |
199 | { | |
200 | int error; | |
201 | uint key; | |
202 | - ulong records=0, deleted=0, pos, next_block; | |
203 | + ulong records= 0, deleted= 0, chunk_count= 0, pos, next_block; | |
204 | HP_SHARE *share=info->s; | |
205 | HP_INFO save_info= *info; /* Needed because scan_init */ | |
206 | DBUG_ENTER("heap_check_heap"); | |
207 | @@ -64,31 +64,55 @@ | |
208 | { | |
209 | if (pos < next_block) | |
210 | { | |
211 | - info->current_ptr+= share->block.recbuffer; | |
212 | + info->current_ptr+= share->recordspace.block.recbuffer; | |
213 | } | |
214 | else | |
215 | { | |
216 | - next_block+= share->block.records_in_block; | |
217 | - if (next_block >= share->records+share->deleted) | |
218 | + next_block+= share->recordspace.block.records_in_block; | |
219 | + if (next_block >= share->recordspace.chunk_count) | |
220 | { | |
221 | - next_block= share->records+share->deleted; | |
222 | - if (pos >= next_block) | |
223 | - break; /* End of file */ | |
224 | + next_block= share->recordspace.chunk_count; | |
225 | + if (pos >= next_block) | |
226 | + break; /* End of file */ | |
227 | } | |
228 | } | |
229 | hp_find_record(info,pos); | |
230 | ||
231 | - if (!info->current_ptr[share->reclength]) | |
232 | + switch (get_chunk_status(&share->recordspace, info->current_ptr)) { | |
233 | + case CHUNK_STATUS_DELETED: | |
234 | deleted++; | |
235 | - else | |
236 | + chunk_count++; | |
237 | + break; | |
238 | + case CHUNK_STATUS_ACTIVE: | |
239 | records++; | |
240 | + chunk_count++; | |
241 | + break; | |
242 | + case CHUNK_STATUS_LINKED: | |
243 | + chunk_count++; | |
244 | + break; | |
245 | + default: | |
246 | + DBUG_PRINT("error", | |
247 | + ("Unknown record status: Record: 0x%lx Status %lu", | |
248 | + (long) info->current_ptr, | |
249 | + (ulong) get_chunk_status(&share->recordspace, | |
250 | + info->current_ptr))); | |
251 | + error|= 1; | |
252 | + break; | |
253 | + } | |
254 | } | |
255 | ||
256 | - if (records != share->records || deleted != share->deleted) | |
257 | - { | |
258 | - DBUG_PRINT("error",("Found rows: %lu (%lu) deleted %lu (%lu)", | |
259 | - records, (ulong) share->records, | |
260 | - deleted, (ulong) share->deleted)); | |
261 | + /* TODO: verify linked chunks (no orphans, no cycles, no bad links) */ | |
262 | + | |
263 | + if (records != share->records || | |
264 | + chunk_count != share->recordspace.chunk_count || | |
265 | + deleted != share->recordspace.del_chunk_count) | |
266 | + { | |
267 | + DBUG_PRINT("error", | |
268 | + ("Found rows: %lu (%lu) total chunks %lu (%lu) deleted chunks " | |
269 | + "%lu (%lu)", | |
270 | + records, (ulong) share->records, | |
271 | + chunk_count, (ulong) share->recordspace.chunk_count, | |
272 | + deleted, (ulong) share->recordspace.del_chunk_count)); | |
273 | error= 1; | |
274 | } | |
275 | *info= save_info; | |
276 | @@ -177,7 +201,7 @@ | |
277 | do | |
278 | { | |
279 | memcpy(&recpos, key + (*keydef->get_key_length)(keydef,key), sizeof(uchar*)); | |
280 | - key_length= hp_rb_make_key(keydef, info->recbuf, recpos, 0); | |
281 | + key_length= hp_rb_make_key(keydef, info->recbuf, recpos, 0, TRUE); | |
282 | if (ha_key_cmp(keydef->seg, (uchar*) info->recbuf, (uchar*) key, | |
283 | key_length, SEARCH_FIND | SEARCH_SAME, not_used)) | |
284 | { | |
285 | --- a/storage/heap/_rectest.c | |
286 | +++ b/storage/heap/_rectest.c | |
287 | @@ -22,7 +22,9 @@ | |
288 | { | |
289 | DBUG_ENTER("hp_rectest"); | |
290 | ||
291 | - if (memcmp(info->current_ptr,old,(size_t) info->s->reclength)) | |
292 | + if (hp_process_record_data_to_chunkset(info->s, old, | |
293 | + info->current_ptr, | |
294 | + 1)) | |
295 | { | |
296 | DBUG_RETURN((my_errno=HA_ERR_RECORD_CHANGED)); /* Record have changed */ | |
297 | } | |
298 | --- a/storage/heap/ha_heap.cc | |
299 | +++ b/storage/heap/ha_heap.cc | |
300 | @@ -114,6 +114,7 @@ | |
301 | ||
302 | rc= heap_create(name, &create_info, &internal_share, &created_new_share); | |
303 | my_free(create_info.keydef); | |
304 | + my_free(create_info.columndef); | |
305 | if (rc) | |
306 | goto end; | |
307 | ||
308 | @@ -195,6 +196,12 @@ | |
309 | { | |
310 | if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE) | |
311 | btree_keys.set_bit(i); | |
312 | + /* | |
313 | + Reset per-key block size specification so they are not shown | |
314 | + in SHOW CREATE TABLE. | |
315 | + */ | |
316 | + table->key_info[i].block_size= 0; | |
317 | + table->key_info[i].flags&= ~HA_USES_BLOCK_SIZE; | |
318 | } | |
319 | } | |
320 | ||
734d6226 | 321 | @@ -429,6 +436,13 @@ |
db82db79 AM |
322 | return 0; |
323 | } | |
324 | ||
325 | +enum row_type ha_heap::get_row_type() const | |
326 | +{ | |
327 | + if (file->s->recordspace.is_variable_size) | |
328 | + return ROW_TYPE_DYNAMIC; | |
329 | + | |
330 | + return ROW_TYPE_FIXED; | |
331 | +} | |
332 | ||
333 | int ha_heap::extra(enum ha_extra_function operation) | |
334 | { | |
734d6226 | 335 | @@ -646,23 +660,70 @@ |
db82db79 AM |
336 | heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table, |
337 | HP_CREATE_INFO *hp_create_info) | |
338 | { | |
339 | - uint key, parts, mem_per_row= 0, keys= table_arg->s->keys; | |
340 | + uint key, parts, mem_per_row_keys= 0, keys= table_arg->s->keys; | |
341 | uint auto_key= 0, auto_key_type= 0; | |
342 | - ha_rows max_rows; | |
343 | + uint fixed_key_fieldnr = 0, fixed_data_size = 0, next_field_pos = 0; | |
344 | + uint column_idx, column_count= table_arg->s->fields; | |
345 | + HP_COLUMNDEF *columndef; | |
346 | HP_KEYDEF *keydef; | |
347 | HA_KEYSEG *seg; | |
348 | TABLE_SHARE *share= table_arg->s; | |
349 | bool found_real_auto_increment= 0; | |
350 | + uint blobs= 0; | |
351 | ||
352 | bzero(hp_create_info, sizeof(*hp_create_info)); | |
353 | ||
354 | + if (!(columndef= (HP_COLUMNDEF*) my_malloc(column_count * | |
355 | + sizeof(HP_COLUMNDEF), | |
356 | + MYF(MY_WME)))) | |
357 | + return my_errno; | |
358 | + | |
359 | + for (column_idx= 0; column_idx < column_count; column_idx++) | |
360 | + { | |
361 | + Field* field= *(table_arg->field + column_idx); | |
362 | + HP_COLUMNDEF* column= columndef + column_idx; | |
363 | + column->type= (uint16) field->type(); | |
364 | + column->length= field->pack_length(); | |
365 | + column->offset= field->offset(table_arg->record[0]); | |
366 | + | |
367 | + if (field->null_bit) | |
368 | + { | |
369 | + column->null_bit= field->null_bit; | |
370 | + column->null_pos= (uint) (field->null_ptr - | |
371 | + (uchar*) table_arg->record[0]); | |
372 | + } | |
373 | + else | |
374 | + { | |
375 | + column->null_bit= 0; | |
376 | + column->null_pos= 0; | |
377 | + } | |
378 | + | |
379 | + if (field->type() == MYSQL_TYPE_VARCHAR) | |
380 | + { | |
381 | + column->length_bytes= (uint8) (((Field_varstring *) field)->length_bytes); | |
382 | + } | |
383 | + else if (field->type() == MYSQL_TYPE_BLOB) | |
384 | + { | |
385 | + blobs++; | |
386 | + column->length_bytes= (uint8) | |
387 | + (((Field_blob *) field)->pack_length_no_ptr()); | |
388 | + } | |
389 | + else | |
390 | + { | |
391 | + column->length_bytes= 0; | |
392 | + } | |
393 | + } | |
394 | + | |
395 | for (key= parts= 0; key < keys; key++) | |
396 | parts+= table_arg->key_info[key].key_parts; | |
397 | ||
398 | if (!(keydef= (HP_KEYDEF*) my_malloc(keys * sizeof(HP_KEYDEF) + | |
399 | parts * sizeof(HA_KEYSEG), | |
400 | MYF(MY_WME)))) | |
401 | + { | |
402 | + my_free((uchar *) columndef); | |
403 | return my_errno; | |
404 | + } | |
405 | seg= reinterpret_cast<HA_KEYSEG*>(keydef + keys); | |
406 | for (key= 0; key < keys; key++) | |
407 | { | |
734d6226 | 408 | @@ -678,11 +739,11 @@ |
db82db79 AM |
409 | case HA_KEY_ALG_UNDEF: |
410 | case HA_KEY_ALG_HASH: | |
411 | keydef[key].algorithm= HA_KEY_ALG_HASH; | |
412 | - mem_per_row+= sizeof(char*) * 2; // = sizeof(HASH_INFO) | |
413 | + mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO) | |
414 | break; | |
415 | case HA_KEY_ALG_BTREE: | |
416 | keydef[key].algorithm= HA_KEY_ALG_BTREE; | |
417 | - mem_per_row+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*); | |
418 | + mem_per_row_keys+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*); | |
419 | break; | |
420 | default: | |
421 | DBUG_ASSERT(0); // cannot happen | |
734d6226 | 422 | @@ -707,6 +768,16 @@ |
db82db79 AM |
423 | seg->length= (uint) key_part->length; |
424 | seg->flag= key_part->key_part_flag; | |
425 | ||
426 | + next_field_pos= seg->start; | |
427 | + if (field->type() == MYSQL_TYPE_VARCHAR) | |
428 | + { | |
429 | + Field *orig_field= *(table_arg->field + key_part->field->field_index); | |
430 | + next_field_pos+= orig_field->pack_length(); | |
431 | + } | |
432 | + else | |
433 | + { | |
434 | + next_field_pos+= seg->length; | |
435 | + } | |
436 | if (field->flags & (ENUM_FLAG | SET_FLAG)) | |
437 | seg->charset= &my_charset_bin; | |
438 | else | |
734d6226 | 439 | @@ -732,9 +803,75 @@ |
db82db79 AM |
440 | auto_key= key+ 1; |
441 | auto_key_type= field->key_type(); | |
442 | } | |
443 | + | |
444 | + switch (seg->type) { | |
445 | + case HA_KEYTYPE_SHORT_INT: | |
446 | + case HA_KEYTYPE_LONG_INT: | |
447 | + case HA_KEYTYPE_FLOAT: | |
448 | + case HA_KEYTYPE_DOUBLE: | |
449 | + case HA_KEYTYPE_USHORT_INT: | |
450 | + case HA_KEYTYPE_ULONG_INT: | |
451 | + case HA_KEYTYPE_LONGLONG: | |
452 | + case HA_KEYTYPE_ULONGLONG: | |
453 | + case HA_KEYTYPE_INT24: | |
454 | + case HA_KEYTYPE_UINT24: | |
455 | + case HA_KEYTYPE_INT8: | |
456 | + seg->flag|= HA_SWAP_KEY; | |
457 | + break; | |
458 | + case HA_KEYTYPE_VARBINARY1: | |
459 | + /* Case-insensitiveness is handled in coll->hash_sort */ | |
460 | + seg->type= HA_KEYTYPE_VARTEXT1; | |
461 | + /* fall through */ | |
462 | + case HA_KEYTYPE_VARTEXT1: | |
463 | + keydef[key].flag|= HA_VAR_LENGTH_KEY; | |
464 | + /* Save number of bytes used to store length */ | |
465 | + if (seg->flag & HA_BLOB_PART) | |
466 | + seg->bit_start= field->pack_length() - share->blob_ptr_size; | |
467 | + else | |
468 | + seg->bit_start= 1; | |
469 | + break; | |
470 | + case HA_KEYTYPE_VARBINARY2: | |
471 | + /* Case-insensitiveness is handled in coll->hash_sort */ | |
472 | + /* fall_through */ | |
473 | + case HA_KEYTYPE_VARTEXT2: | |
474 | + keydef[key].flag|= HA_VAR_LENGTH_KEY; | |
475 | + /* Save number of bytes used to store length */ | |
476 | + if (seg->flag & HA_BLOB_PART) | |
477 | + seg->bit_start= field->pack_length() - share->blob_ptr_size; | |
478 | + else | |
479 | + seg->bit_start= 2; | |
480 | + /* | |
481 | + Make future comparison simpler by only having to check for | |
482 | + one type | |
483 | + */ | |
484 | + seg->type= HA_KEYTYPE_VARTEXT1; | |
485 | + break; | |
486 | + default: | |
487 | + break; | |
488 | + } | |
489 | + | |
490 | + if (next_field_pos > fixed_data_size) | |
491 | + { | |
492 | + fixed_data_size= next_field_pos; | |
493 | + } | |
494 | + | |
495 | + | |
496 | + if (field->field_index >= fixed_key_fieldnr) | |
497 | + { | |
498 | + /* | |
499 | + Do not use seg->fieldnr as it's not reliable in case of temp tables | |
500 | + */ | |
501 | + fixed_key_fieldnr= field->field_index + 1; | |
502 | + } | |
503 | } | |
504 | } | |
505 | - mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*)); | |
506 | + | |
507 | + if (fixed_data_size < share->null_bytes) | |
508 | + { | |
509 | + /* Make sure to include null fields regardless of the presense of keys */ | |
510 | + fixed_data_size = share->null_bytes; | |
511 | + } | |
512 | + | |
513 | if (table_arg->found_next_number_field) | |
514 | { | |
515 | keydef[share->next_number_index].flag|= HA_AUTO_KEY; | |
734d6226 | 516 | @@ -745,16 +882,19 @@ |
db82db79 AM |
517 | hp_create_info->max_table_size=current_thd->variables.max_heap_table_size; |
518 | hp_create_info->with_auto_increment= found_real_auto_increment; | |
519 | hp_create_info->internal_table= internal_table; | |
520 | - | |
521 | - max_rows= (ha_rows) (hp_create_info->max_table_size / mem_per_row); | |
522 | - if (share->max_rows && share->max_rows < max_rows) | |
523 | - max_rows= share->max_rows; | |
524 | - | |
525 | - hp_create_info->max_records= (ulong) max_rows; | |
526 | + hp_create_info->max_chunk_size= share->key_block_size; | |
527 | + hp_create_info->is_dynamic= (share->row_type == ROW_TYPE_DYNAMIC); | |
528 | + hp_create_info->columns= column_count; | |
529 | + hp_create_info->columndef= columndef; | |
530 | + hp_create_info->fixed_key_fieldnr= fixed_key_fieldnr; | |
531 | + hp_create_info->fixed_data_size= fixed_data_size; | |
532 | + hp_create_info->max_records= (ulong) share->max_rows; | |
533 | hp_create_info->min_records= (ulong) share->min_rows; | |
534 | hp_create_info->keys= share->keys; | |
535 | hp_create_info->reclength= share->reclength; | |
536 | + hp_create_info->keys_memory_size= mem_per_row_keys; | |
537 | hp_create_info->keydef= keydef; | |
538 | + hp_create_info->blobs= blobs; | |
539 | return 0; | |
540 | } | |
541 | ||
734d6226 | 542 | @@ -774,6 +914,7 @@ |
db82db79 AM |
543 | create_info->auto_increment_value - 1 : 0); |
544 | error= heap_create(name, &hp_create_info, &internal_share, &created); | |
545 | my_free(hp_create_info.keydef); | |
546 | + my_free(hp_create_info.columndef); | |
547 | DBUG_ASSERT(file == 0); | |
548 | return (error); | |
549 | } | |
734d6226 | 550 | @@ -784,6 +925,13 @@ |
db82db79 AM |
551 | table->file->info(HA_STATUS_AUTO); |
552 | if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) | |
553 | create_info->auto_increment_value= stats.auto_increment_value; | |
554 | + if (!(create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) | |
555 | + { | |
556 | + if (file->s->recordspace.is_variable_size) | |
557 | + create_info->key_block_size= file->s->recordspace.chunk_length; | |
558 | + else | |
559 | + create_info->key_block_size= 0; | |
560 | + } | |
561 | } | |
562 | ||
563 | void ha_heap::get_auto_increment(ulonglong offset, ulonglong increment, | |
564 | --- a/storage/heap/ha_heap.h | |
565 | +++ b/storage/heap/ha_heap.h | |
566 | @@ -47,12 +47,11 @@ | |
567 | return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ? | |
568 | "BTREE" : "HASH"); | |
569 | } | |
570 | - /* Rows also use a fixed-size format */ | |
571 | - enum row_type get_row_type() const { return ROW_TYPE_FIXED; } | |
572 | + enum row_type get_row_type() const; | |
573 | const char **bas_ext() const; | |
574 | ulonglong table_flags() const | |
575 | { | |
576 | - return (HA_FAST_KEY_READ | HA_NO_BLOBS | HA_NULL_IN_KEY | | |
577 | + return (HA_FAST_KEY_READ | HA_NULL_IN_KEY | | |
578 | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | | |
579 | HA_REC_NOT_IN_SEQ | HA_CAN_INSERT_DELAYED | HA_NO_TRANSACTIONS | | |
580 | HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT); | |
581 | @@ -64,8 +63,9 @@ | |
582 | HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR); | |
583 | } | |
584 | const key_map *keys_to_use_for_scanning() { return &btree_keys; } | |
585 | - uint max_supported_keys() const { return MAX_KEY; } | |
586 | - uint max_supported_key_part_length() const { return MAX_KEY_LENGTH; } | |
587 | + uint max_supported_keys() const { return HP_MAX_KEY; } | |
588 | + uint max_supported_key_length() const { return HP_MAX_KEY_LENGTH; } | |
589 | + uint max_supported_key_part_length() const { return HP_MAX_KEY_LENGTH; } | |
590 | double scan_time() | |
591 | { return (double) (stats.records+stats.deleted) / 20.0+10; } | |
592 | double read_time(uint index, uint ranges, ha_rows rows) | |
593 | --- a/storage/heap/heapdef.h | |
594 | +++ b/storage/heap/heapdef.h | |
595 | @@ -32,6 +32,13 @@ | |
596 | #define HP_MIN_RECORDS_IN_BLOCK 16 | |
597 | #define HP_MAX_RECORDS_IN_BLOCK 8192 | |
598 | ||
599 | +/* this chunk has been deleted and can be reused */ | |
600 | +#define CHUNK_STATUS_DELETED 0 | |
601 | +/* this chunk represents the first part of a live record */ | |
602 | +#define CHUNK_STATUS_ACTIVE 1 | |
603 | +/* this chunk is a continuation from another chunk (part of chunkset) */ | |
604 | +#define CHUNK_STATUS_LINKED 2 | |
605 | + | |
606 | /* Some extern variables */ | |
607 | ||
608 | extern LIST *heap_open_list,*heap_share_list; | |
609 | @@ -42,7 +49,14 @@ | |
610 | #define hp_find_hash(A,B) ((HASH_INFO*) hp_find_block((A),(B))) | |
611 | ||
612 | /* Find pos for record and update it in info->current_ptr */ | |
613 | -#define hp_find_record(info,pos) (info)->current_ptr= hp_find_block(&(info)->s->block,pos) | |
614 | +#define hp_find_record(info,pos) \ | |
615 | + (info)->current_ptr= hp_find_block(&(info)->s->recordspace.block,pos) | |
616 | + | |
617 | +#define get_chunk_status(info,ptr) (ptr[(info)->offset_status]) | |
618 | + | |
619 | +#define get_chunk_count(info,rec_length) \ | |
620 | + ((rec_length + (info)->chunk_dataspace_length - 1) / \ | |
621 | + (info)->chunk_dataspace_length) | |
622 | ||
623 | typedef struct st_hp_hash_info | |
624 | { | |
625 | @@ -90,7 +104,7 @@ | |
626 | const uchar *key); | |
627 | extern void hp_make_key(HP_KEYDEF *keydef,uchar *key,const uchar *rec); | |
628 | extern uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key, | |
629 | - const uchar *rec, uchar *recpos); | |
630 | + const uchar *rec, uchar *recpos, my_bool packed); | |
631 | extern uint hp_rb_key_length(HP_KEYDEF *keydef, const uchar *key); | |
632 | extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const uchar *key); | |
633 | extern uint hp_rb_var_key_length(HP_KEYDEF *keydef, const uchar *key); | |
634 | @@ -100,6 +114,23 @@ | |
635 | extern void hp_clear_keys(HP_SHARE *info); | |
636 | extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, | |
637 | key_part_map keypart_map); | |
638 | +extern uint hp_calc_blob_length(uint length, const uchar *pos); | |
639 | + | |
640 | +/* Chunkset management (alloc/free/encode/decode) functions */ | |
641 | +extern uchar *hp_allocate_chunkset(HP_DATASPACE *info, uint chunk_count); | |
642 | +extern int hp_reallocate_chunkset(HP_DATASPACE *info, uint chunk_count, | |
643 | + uchar *pos); | |
644 | +extern void hp_free_chunks(HP_DATASPACE *info, uchar *pos); | |
645 | +extern void hp_clear_dataspace(HP_DATASPACE *info); | |
646 | + | |
647 | +extern uint hp_get_encoded_data_length(HP_SHARE *info, const uchar *record, | |
648 | + uint *chunk_count); | |
649 | +extern void hp_copy_record_data_to_chunkset(HP_SHARE *info, const uchar *record, | |
650 | + uchar *pos); | |
651 | +extern int hp_extract_record(HP_INFO *info, uchar *record, const uchar *pos); | |
652 | +extern uint hp_process_record_data_to_chunkset(HP_SHARE *info, | |
653 | + const uchar *record, uchar *pos, | |
654 | + uint is_compare); | |
655 | ||
656 | extern mysql_mutex_t THR_LOCK_heap; | |
657 | ||
658 | --- a/storage/heap/hp_clear.c | |
659 | +++ b/storage/heap/hp_clear.c | |
660 | @@ -31,16 +31,11 @@ | |
661 | { | |
662 | DBUG_ENTER("hp_clear"); | |
663 | ||
664 | - if (info->block.levels) | |
665 | - (void) hp_free_level(&info->block,info->block.levels,info->block.root, | |
666 | - (uchar*) 0); | |
667 | - info->block.levels=0; | |
668 | + hp_clear_dataspace(&info->recordspace); | |
669 | hp_clear_keys(info); | |
670 | - info->records= info->deleted= 0; | |
671 | - info->data_length= 0; | |
672 | + info->records= 0; | |
673 | info->blength=1; | |
674 | info->changed=0; | |
675 | - info->del_link=0; | |
676 | DBUG_VOID_RETURN; | |
677 | } | |
678 | ||
679 | @@ -158,7 +153,7 @@ | |
680 | int error= 0; | |
681 | HP_SHARE *share= info->s; | |
682 | ||
683 | - if (share->data_length || share->index_length) | |
684 | + if (share->recordspace.total_data_length || share->index_length) | |
685 | error= HA_ERR_CRASHED; | |
686 | else | |
687 | if (share->currently_disabled_keys) | |
688 | --- a/storage/heap/hp_close.c | |
689 | +++ b/storage/heap/hp_close.c | |
690 | @@ -46,6 +46,10 @@ | |
691 | heap_open_list=list_delete(heap_open_list,&info->open_list); | |
692 | if (!--info->s->open_count && info->s->delete_on_close) | |
693 | hp_free(info->s); /* Table was deleted */ | |
694 | + if (info->blob_buffer) | |
695 | + { | |
696 | + my_free(info->blob_buffer); | |
697 | + } | |
698 | my_free(info); | |
699 | DBUG_RETURN(error); | |
700 | } | |
701 | --- a/storage/heap/hp_create.c | |
702 | +++ b/storage/heap/hp_create.c | |
703 | @@ -14,11 +14,21 @@ | |
704 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ | |
705 | ||
706 | #include "heapdef.h" | |
707 | +#include <mysql_com.h> | |
708 | +#include <mysqld_error.h> | |
709 | ||
710 | static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2); | |
711 | -static void init_block(HP_BLOCK *block,uint reclength,ulong min_records, | |
712 | +static void init_block(HP_BLOCK *block,uint chunk_length, ulong min_records, | |
713 | ulong max_records); | |
714 | ||
715 | +#define FIXED_REC_OVERHEAD (sizeof(uchar)) | |
716 | +#define VARIABLE_REC_OVERHEAD (sizeof(uchar **) + sizeof(uchar)) | |
717 | + | |
718 | +/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */ | |
719 | +#define VARIABLE_MIN_CHUNK_SIZE \ | |
720 | + ((sizeof(uchar **) + VARIABLE_REC_OVERHEAD + sizeof(uchar **) - 1) & \ | |
721 | + ~(sizeof(uchar **) - 1)) | |
722 | + | |
723 | /* Create a heap table */ | |
724 | ||
725 | int heap_create(const char *name, HP_CREATE_INFO *create_info, | |
726 | @@ -32,6 +42,7 @@ | |
727 | uint keys= create_info->keys; | |
728 | ulong min_records= create_info->min_records; | |
729 | ulong max_records= create_info->max_records; | |
730 | + ulong max_rows_for_stated_memory; | |
731 | DBUG_ENTER("heap_create"); | |
732 | ||
733 | if (!create_info->internal_table) | |
734 | @@ -48,15 +59,147 @@ | |
735 | ||
736 | if (!share) | |
737 | { | |
738 | + uint chunk_dataspace_length, chunk_length, is_variable_size; | |
739 | + uint fixed_data_length, fixed_column_count; | |
740 | HP_KEYDEF *keyinfo; | |
741 | DBUG_PRINT("info",("Initializing new table")); | |
742 | - | |
743 | + | |
744 | + if (create_info->max_chunk_size) | |
745 | + { | |
746 | + uint configured_chunk_size= create_info->max_chunk_size; | |
747 | + | |
748 | + /* User requested variable-size records, let's see if they're possible */ | |
749 | + | |
750 | + if (configured_chunk_size < create_info->fixed_data_size) | |
751 | + { | |
752 | + /* | |
753 | + The resulting chunk_size cannot be smaller than fixed data part | |
754 | + at the start of the first chunk which allows faster copying | |
755 | + with a single memcpy(). | |
756 | + */ | |
757 | + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "key_block_size"); | |
758 | + goto err; | |
759 | + } | |
760 | + | |
761 | + if (reclength > configured_chunk_size + VARIABLE_REC_OVERHEAD || | |
762 | + create_info->blobs > 0) | |
763 | + { | |
764 | + /* | |
765 | + Allow variable size only if we're saving some space, i.e. | |
766 | + if a fixed-size record would take more space than variable-size | |
767 | + one plus the variable-size overhead. | |
768 | + There has to be at least one field after indexed fields. | |
769 | + Note that NULL bits are already included in key_part_size. | |
770 | + */ | |
771 | + is_variable_size= 1; | |
772 | + chunk_dataspace_length= configured_chunk_size; | |
773 | + } | |
774 | + else | |
775 | + { | |
776 | + /* max_chunk_size is near the full reclength, let's use fixed size */ | |
777 | + is_variable_size= 0; | |
778 | + chunk_dataspace_length= reclength; | |
779 | + } | |
780 | + } | |
781 | + else if ((create_info->is_dynamic && reclength > | |
782 | + 256 + VARIABLE_REC_OVERHEAD) | |
783 | + || create_info->blobs > 0) | |
784 | + { | |
785 | + /* | |
786 | + User asked for dynamic records - use 256 as the chunk size, if that | |
787 | + will may save some memory. Otherwise revert to fixed size format. | |
788 | + */ | |
789 | + if ((create_info->fixed_data_size + VARIABLE_REC_OVERHEAD) > 256) | |
790 | + chunk_dataspace_length= create_info->fixed_data_size; | |
791 | + else | |
792 | + chunk_dataspace_length= 256 - VARIABLE_REC_OVERHEAD; | |
793 | + | |
794 | + is_variable_size= 1; | |
795 | + } | |
796 | + else | |
797 | + { | |
798 | + /* | |
799 | + If max_chunk_size is not specified, put the whole record in one chunk | |
800 | + */ | |
801 | + is_variable_size= 0; | |
802 | + chunk_dataspace_length= reclength; | |
803 | + } | |
804 | + | |
805 | + if (is_variable_size) | |
806 | + { | |
807 | + /* Check whether we have any variable size records past key data */ | |
808 | + uint has_variable_fields= 0; | |
809 | + | |
810 | + fixed_data_length= create_info->fixed_data_size; | |
811 | + fixed_column_count= create_info->fixed_key_fieldnr; | |
812 | + | |
813 | + for (i= create_info->fixed_key_fieldnr; i < create_info->columns; i++) | |
814 | + { | |
815 | + HP_COLUMNDEF *column= create_info->columndef + i; | |
816 | + if ((column->type == MYSQL_TYPE_VARCHAR && | |
817 | + (column->length - column->length_bytes) >= 32) || | |
818 | + column->type == MYSQL_TYPE_BLOB) | |
819 | + { | |
820 | + /* | |
821 | + The field has to be either blob or >= 5.0.3 true VARCHAR | |
822 | + and have substantial length. | |
823 | + TODO: do we want to calculate minimum length? | |
824 | + */ | |
825 | + has_variable_fields= 1; | |
826 | + break; | |
827 | + } | |
828 | + | |
829 | + if (has_variable_fields) | |
830 | + { | |
831 | + break; | |
832 | + } | |
833 | + | |
834 | + if ((column->offset + column->length) <= chunk_dataspace_length) | |
835 | + { | |
836 | + /* Still no variable-size columns, add one fixed-length */ | |
837 | + fixed_column_count= i + 1; | |
838 | + fixed_data_length= column->offset + column->length; | |
839 | + } | |
840 | + } | |
841 | + | |
842 | + if (!has_variable_fields && create_info->blobs == 0) | |
843 | + { | |
844 | + /* | |
845 | + There is no need to use variable-size records without variable-size | |
846 | + columns. | |
847 | + Reset sizes if it's not variable size anymore. | |
848 | + */ | |
849 | + is_variable_size= 0; | |
850 | + chunk_dataspace_length= reclength; | |
851 | + fixed_data_length= reclength; | |
852 | + fixed_column_count= create_info->columns; | |
853 | + } | |
854 | + } | |
855 | + else | |
856 | + { | |
857 | + fixed_data_length= reclength; | |
858 | + fixed_column_count= create_info->columns; | |
859 | + } | |
860 | + | |
861 | /* | |
862 | - We have to store sometimes uchar* del_link in records, | |
863 | - so the record length should be at least sizeof(uchar*) | |
864 | + We store uchar* del_link inside the data area of deleted records, | |
865 | + so the data length should be at least sizeof(uchar*) | |
866 | */ | |
867 | - set_if_bigger(reclength, sizeof (uchar*)); | |
868 | - | |
869 | + set_if_bigger(chunk_dataspace_length, sizeof (uchar **)); | |
870 | + | |
871 | + if (is_variable_size) | |
872 | + { | |
873 | + chunk_length= chunk_dataspace_length + VARIABLE_REC_OVERHEAD; | |
874 | + } | |
875 | + else | |
876 | + { | |
877 | + chunk_length= chunk_dataspace_length + FIXED_REC_OVERHEAD; | |
878 | + } | |
879 | + | |
880 | + /* Align chunk length to the next pointer */ | |
881 | + chunk_length= (uint) (chunk_length + sizeof(uchar **) - 1) & | |
882 | + ~(sizeof(uchar **) - 1); | |
883 | + | |
884 | for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++) | |
885 | { | |
886 | bzero((char*) &keyinfo->block,sizeof(keyinfo->block)); | |
887 | @@ -73,42 +216,11 @@ | |
888 | keyinfo->rb_tree.size_of_element++; | |
889 | } | |
890 | switch (keyinfo->seg[j].type) { | |
891 | - case HA_KEYTYPE_SHORT_INT: | |
892 | - case HA_KEYTYPE_LONG_INT: | |
893 | - case HA_KEYTYPE_FLOAT: | |
894 | - case HA_KEYTYPE_DOUBLE: | |
895 | - case HA_KEYTYPE_USHORT_INT: | |
896 | - case HA_KEYTYPE_ULONG_INT: | |
897 | - case HA_KEYTYPE_LONGLONG: | |
898 | - case HA_KEYTYPE_ULONGLONG: | |
899 | - case HA_KEYTYPE_INT24: | |
900 | - case HA_KEYTYPE_UINT24: | |
901 | - case HA_KEYTYPE_INT8: | |
902 | - keyinfo->seg[j].flag|= HA_SWAP_KEY; | |
903 | - break; | |
904 | case HA_KEYTYPE_VARBINARY1: | |
905 | - /* Case-insensitiveness is handled in coll->hash_sort */ | |
906 | - keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1; | |
907 | - /* fall_through */ | |
908 | case HA_KEYTYPE_VARTEXT1: | |
909 | - keyinfo->flag|= HA_VAR_LENGTH_KEY; | |
910 | - length+= 2; | |
911 | - /* Save number of bytes used to store length */ | |
912 | - keyinfo->seg[j].bit_start= 1; | |
913 | - break; | |
914 | case HA_KEYTYPE_VARBINARY2: | |
915 | - /* Case-insensitiveness is handled in coll->hash_sort */ | |
916 | - /* fall_through */ | |
917 | case HA_KEYTYPE_VARTEXT2: | |
918 | - keyinfo->flag|= HA_VAR_LENGTH_KEY; | |
919 | length+= 2; | |
920 | - /* Save number of bytes used to store length */ | |
921 | - keyinfo->seg[j].bit_start= 2; | |
922 | - /* | |
923 | - Make future comparison simpler by only having to check for | |
924 | - one type | |
925 | - */ | |
926 | - keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1; | |
927 | break; | |
928 | default: | |
929 | break; | |
930 | @@ -133,13 +245,34 @@ | |
931 | } | |
932 | if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+ | |
933 | keys*sizeof(HP_KEYDEF)+ | |
934 | + (create_info->columns * | |
935 | + sizeof(HP_COLUMNDEF)) + | |
936 | key_segs*sizeof(HA_KEYSEG), | |
937 | MYF(MY_ZEROFILL)))) | |
938 | goto err; | |
939 | - share->keydef= (HP_KEYDEF*) (share + 1); | |
940 | + | |
941 | + /* | |
942 | + Max_records is used for estimating block sizes and for enforcement. | |
943 | + Calculate the very maximum number of rows (if everything was one chunk) | |
944 | + and then take either that value or configured max_records (pick smallest | |
945 | + one). | |
946 | + */ | |
947 | + max_rows_for_stated_memory= (ha_rows) (create_info->max_table_size / | |
948 | + (create_info->keys_memory_size + | |
949 | + chunk_length)); | |
950 | + max_records = ((max_records && max_records < max_rows_for_stated_memory) ? | |
951 | + max_records : max_rows_for_stated_memory); | |
952 | + | |
953 | + share->column_defs= (HP_COLUMNDEF*) (share + 1); | |
954 | + memcpy(share->column_defs, create_info->columndef, | |
955 | + (size_t) (sizeof(create_info->columndef[0]) * | |
956 | + create_info->columns)); | |
957 | + | |
958 | + share->keydef= (HP_KEYDEF*) (share->column_defs + create_info->columns); | |
959 | share->key_stat_version= 1; | |
960 | keyseg= (HA_KEYSEG*) (share->keydef + keys); | |
961 | - init_block(&share->block, reclength + 1, min_records, max_records); | |
962 | + init_block(&share->recordspace.block, chunk_length, min_records, | |
963 | + max_records); | |
964 | /* Fix keys */ | |
965 | memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys)); | |
966 | for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++) | |
734d6226 | 967 | @@ -177,16 +310,36 @@ |
db82db79 AM |
968 | share->min_records= min_records; |
969 | share->max_records= max_records; | |
970 | share->max_table_size= create_info->max_table_size; | |
971 | - share->data_length= share->index_length= 0; | |
972 | - share->reclength= reclength; | |
973 | + share->index_length= 0; | |
974 | share->blength= 1; | |
975 | share->keys= keys; | |
976 | share->max_key_length= max_length; | |
977 | + share->column_count= create_info->columns; | |
978 | share->changed= 0; | |
979 | share->auto_key= create_info->auto_key; | |
980 | share->auto_key_type= create_info->auto_key_type; | |
981 | share->auto_increment= create_info->auto_increment; | |
734d6226 | 982 | share->create_time= (long) time((time_t*) 0); |
db82db79 AM |
983 | + |
984 | + share->fixed_data_length= fixed_data_length; | |
985 | + share->fixed_column_count= fixed_column_count; | |
986 | + share->blobs= create_info->blobs; | |
987 | + | |
988 | + share->recordspace.chunk_length= chunk_length; | |
989 | + share->recordspace.chunk_dataspace_length= chunk_dataspace_length; | |
990 | + share->recordspace.is_variable_size= is_variable_size; | |
991 | + share->recordspace.total_data_length= 0; | |
992 | + | |
993 | + if (is_variable_size) { | |
994 | + share->recordspace.offset_link= chunk_dataspace_length; | |
995 | + share->recordspace.offset_status= share->recordspace.offset_link + | |
996 | + sizeof(uchar **); | |
997 | + } else { | |
998 | + /* Make it likely to fail if anyone uses this offset */ | |
999 | + share->recordspace.offset_link= 1 << 22; | |
1000 | + share->recordspace.offset_status= chunk_dataspace_length; | |
1001 | + } | |
1002 | + | |
1003 | /* Must be allocated separately for rename to work */ | |
1004 | if (!(share->name= my_strdup(name,MYF(0)))) | |
1005 | { | |
734d6226 | 1006 | @@ -228,7 +381,7 @@ |
db82db79 AM |
1007 | param->search_flag, not_used); |
1008 | } | |
1009 | ||
1010 | -static void init_block(HP_BLOCK *block, uint reclength, ulong min_records, | |
1011 | +static void init_block(HP_BLOCK *block, uint chunk_length, ulong min_records, | |
1012 | ulong max_records) | |
1013 | { | |
1014 | uint i,recbuffer,records_in_block; | |
734d6226 | 1015 | @@ -236,7 +389,12 @@ |
db82db79 AM |
1016 | max_records= max(min_records,max_records); |
1017 | if (!max_records) | |
1018 | max_records= 1000; /* As good as quess as anything */ | |
1019 | - recbuffer= (uint) (reclength + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1); | |
1020 | + /* | |
1021 | + We want to start each chunk at 8 bytes boundary, round recbuffer to the | |
1022 | + next 8. | |
1023 | + */ | |
1024 | + recbuffer= (uint) (chunk_length + sizeof(uchar**) - 1) & | |
1025 | + ~(sizeof(uchar**) - 1); | |
1026 | records_in_block= max_records / 10; | |
1027 | if (records_in_block < 10 && max_records) | |
1028 | records_in_block= 10; | |
1029 | --- a/storage/heap/hp_delete.c | |
1030 | +++ b/storage/heap/hp_delete.c | |
13ceb006 | 1031 | @@ -22,6 +22,7 @@ |
db82db79 AM |
1032 | uchar *pos; |
1033 | HP_SHARE *share=info->s; | |
1034 | HP_KEYDEF *keydef, *end, *p_lastinx; | |
db82db79 AM |
1035 | + |
1036 | DBUG_ENTER("heap_delete"); | |
1037 | DBUG_PRINT("enter",("info: 0x%lx record: 0x%lx", (long) info, (long) record)); | |
1038 | ||
13ceb006 | 1039 | @@ -43,10 +44,7 @@ |
db82db79 AM |
1040 | } |
1041 | ||
1042 | info->update=HA_STATE_DELETED; | |
1043 | - *((uchar**) pos)=share->del_link; | |
1044 | - share->del_link=pos; | |
1045 | - pos[share->reclength]=0; /* Record deleted */ | |
1046 | - share->deleted++; | |
1047 | + hp_free_chunks(&share->recordspace, pos); | |
1048 | info->current_hash_ptr=0; | |
1049 | #if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG) | |
1050 | DBUG_EXECUTE("check_heap",heap_check_heap(info, 0);); | |
13ceb006 | 1051 | @@ -75,7 +73,8 @@ |
db82db79 AM |
1052 | info->last_pos= NULL; /* For heap_rnext/heap_rprev */ |
1053 | ||
1054 | custom_arg.keyseg= keyinfo->seg; | |
1055 | - custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos); | |
1056 | + custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos, | |
1057 | + FALSE); | |
1058 | custom_arg.search_flag= SEARCH_SAME; | |
1059 | old_allocated= keyinfo->rb_tree.allocated; | |
1060 | res= tree_delete(&keyinfo->rb_tree, info->recbuf, custom_arg.key_length, | |
13ceb006 | 1061 | @@ -112,6 +111,7 @@ |
db82db79 AM |
1062 | blength=share->blength; |
1063 | if (share->records+1 == blength) | |
1064 | blength+= blength; | |
1065 | + | |
1066 | lastpos=hp_find_hash(&keyinfo->block,share->records); | |
1067 | last_ptr=0; | |
1068 | ||
1069 | --- /dev/null | |
1070 | +++ b/storage/heap/hp_dspace.c | |
1071 | @@ -0,0 +1,440 @@ | |
1072 | +/* Copyright (C) 2000-2002 MySQL AB | |
1073 | + Copyright (C) 2008 eBay, Inc | |
1074 | + | |
1075 | + This program is free software; you can redistribute it and/or modify | |
1076 | + it under the terms of the GNU General Public License as published by | |
1077 | + the Free Software Foundation; version 2 of the License. | |
1078 | + | |
1079 | + This program is distributed in the hope that it will be useful, | |
1080 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1081 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1082 | + GNU General Public License for more details. | |
1083 | + | |
1084 | + You should have received a copy of the GNU General Public License | |
1085 | + along with this program; if not, write to the Free Software | |
1086 | + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | |
1087 | + | |
1088 | +/* | |
1089 | + Implements various base dataspace-related functions - allocate, free, clear | |
1090 | +*/ | |
1091 | + | |
1092 | +#include "heapdef.h" | |
1093 | + | |
1094 | + | |
1095 | +/* | |
1096 | + MySQL Heap tables keep data in arrays of fixed-size chunks. | |
1097 | + These chunks are organized into two groups of HP_BLOCK structures: | |
1098 | + - group1 contains indexes, with one HP_BLOCK per key | |
1099 | + (part of HP_KEYDEF) | |
1100 | + - group2 contains record data, with single HP_BLOCK | |
1101 | + for all records, referenced by HP_SHARE.recordspace.block | |
1102 | + | |
1103 | + While columns used in index are usually small, other columns | |
1104 | + in the table may need to accomodate larger data. Typically, | |
1105 | + larger data is placed into VARCHAR or BLOB columns. With actual | |
1106 | + sizes varying, Heap Engine has to support variable-sized records | |
1107 | + in memory. Heap Engine implements the concept of dataspace | |
1108 | + (HP_DATASPACE), which incorporates HP_BLOCK for the record data, | |
1109 | + and adds more information for managing variable-sized records. | |
1110 | + | |
1111 | + Variable-size records are stored in multiple "chunks", | |
1112 | + which means that a single record of data (database "row") can | |
1113 | + consist of multiple chunks organized into one "set". HP_BLOCK | |
1114 | + contains chunks. In variable-size format, one record | |
1115 | + is represented as one or many chunks, depending on the actual | |
1116 | + data, while in fixed-size mode, one record is always represented | |
1117 | + as one chunk. The index structures would always point to the first | |
1118 | + chunk in the chunkset. | |
1119 | + | |
1120 | + At the time of table creation, Heap Engine attempts to find out if | |
1121 | + variable-size records are desired. A user can request | |
1122 | + variable-size records by providing either row_type=dynamic or | |
1123 | + key_block_size=NNN table create option. Heap Engine will check | |
1124 | + whether key_block_size provides enough space in the first chunk | |
1125 | + to keep all null bits and columns that are used in indexes. | |
1126 | + If key_block_size is too small, table creation will be aborted | |
1127 | + with an error. Heap Engine will revert to fixed-size allocation | |
1128 | + mode if key_block_size provides no memory benefits (if the | |
1129 | + fixed-size record would always be shorter then the first chunk | |
1130 | + in the chunkset with the specified key_block_size). | |
1131 | + | |
1132 | + In order to improve index search performance, Heap Engine needs | |
1133 | + to keep all null flags and all columns used as keys inside | |
1134 | + the first chunk of a chunkset. In particular, this means that | |
1135 | + all columns used as keys should be defined first in the table | |
1136 | + creation SQL. The length of data used by null bits and key columns | |
1137 | + is stored as fixed_data_length inside HP_SHARE. fixed_data_length | |
1138 | + will extend past last key column if more fixed-length fields can | |
1139 | + fit into the first chunk. | |
1140 | + | |
1141 | + Variable-size records are necessary only in the presence of | |
1142 | + variable-size columns. Heap Engine will be looking for BLOB | |
1143 | + columns or VARCHAR columns, which declare length of 32 or more. If | |
1144 | + no such columns are found, table will be switched to fixed-size | |
1145 | + format. You should always try to put such columns at the end of | |
1146 | + the table definition. | |
1147 | + | |
1148 | + Whenever data is being inserted or updated in the table | |
1149 | + Heap Engine will calculate how many chunks are necessary. | |
1150 | + For insert operations, Heap Engine allocates new chunkset in | |
1151 | + the recordspace. For update operations it will modify length of | |
1152 | + the existing chunkset, unlinking unnecessary chunks at the end, | |
1153 | + or allocating and adding more if larger length is necessary. | |
1154 | + | |
1155 | + When writing data to chunks or copying data back to record, | |
1156 | + fixed-size columns are copied in their full format. VARCHARs and | |
1157 | + BLOBs are copied based on their actual length. Any NULL values | |
1158 | + after fixed_data_length are skipped. | |
1159 | + | |
1160 | + The allocation and contents of the actual chunks varies between | |
1161 | + fixed and variable-size modes. Total chunk length is always | |
1162 | + aligned to the next sizeof(uchar*). Here is the format of | |
1163 | + fixed-size chunk: | |
1164 | + uchar[] - sizeof=chunk_dataspace_length, but at least | |
1165 | + sizeof(uchar*) bytes. Keeps actual data or pointer | |
1166 | + to the next deleted chunk. | |
1167 | + chunk_dataspace_length equals to full record length | |
1168 | + uchar - status field (1 means "in use", 0 means "deleted") | |
1169 | + | |
1170 | + Variable-size chunk uses different format: | |
1171 | + uchar[] - sizeof=chunk_dataspace_length, but at least | |
1172 | + sizeof(uchar*) bytes. Keeps actual data or pointer | |
1173 | + to the next deleted chunk. | |
1174 | + chunk_dataspace_length is set according to table | |
1175 | + setup (key_block_size) | |
1176 | + uchar* - pointer to the next chunk in this chunkset, | |
1177 | + or NULL for the last chunk | |
1178 | + uchar - status field (1 means "first", 0 means "deleted", | |
1179 | + 2 means "linked") | |
1180 | + | |
1181 | + When allocating a new chunkset of N chunks, Heap Engine will try | |
1182 | + to allocate chunks one-by-one, linking them as they become | |
1183 | + allocated. Allocation of a single chunk will attempt to reuse | |
1184 | + a deleted (freed) chunk. If no free chunks are available, | |
1185 | + it will attempt to allocate a new area inside HP_BLOCK. | |
1186 | + Freeing chunks will place them at the front of free list | |
1187 | + referenced by del_link in HP_DATASPACE. The newly freed chunk | |
1188 | + will contain reference to the previously freed chunk in its first | |
1189 | + sizeof(uchar*) of the payload space. | |
1190 | + | |
1191 | + Here is open issues: | |
1192 | + - It is not very nice to require people to keep key columns | |
1193 | + at the beginning of the table creation SQL. There are three | |
1194 | + proposed resolutions: | |
1195 | + a. Leave it as is. It's a reasonable limitation | |
1196 | + b. Add new HA_KEEP_KEY_COLUMNS_TO_FRONT flag to handler.h and | |
1197 | + make table.cpp align columns when it creates the table | |
1198 | + c. Make HeapEngine reorder columns in the chunk data, so that | |
1199 | + key columns go first. Add parallel HA_KEYSEG structures | |
1200 | + to distinguish positions in record vs. positions in | |
1201 | + the first chunk. Copy all data field-by-field rather than | |
1202 | + using single memcpy unless DBA kept key columns to | |
1203 | + the beginning. | |
1204 | + - heap_check_heap needs verify linked chunks, looking for | |
1205 | + issues such as orphans, cycles, and bad links. However, | |
1206 | + Heap Engine today does not do similar things even for | |
1207 | + free list. | |
1208 | + - In a more sophisticated implementation, some space can | |
1209 | + be saved even with all fixed-size columns if many of them | |
1210 | + have NULL value, as long as these columns are not used | |
1211 | + in indexes | |
1212 | + - In variable-size format status should be moved to lower | |
1213 | + bits of the "next" pointer. Pointer is always aligned | |
1214 | + to sizeof(byte*), which is at least 4, leaving 2 lower | |
1215 | + bits free. This will save 8 bytes per chunk | |
1216 | + on 64-bit platform. | |
1217 | + - As we do not want to modify FRM format or to add new SQL | |
1218 | + keywords, KEY_BLOCK_SIZE option of "CREATE TABLE" is reused | |
1219 | + to specify block size for Heap Engine tables. | |
1220 | + - since all key columns must fit in the first chunk, having keys | |
1221 | + on BLOB columns is currently impossible. This limitation is | |
1222 | + relatively easiy to remove in future. | |
1223 | +*/ | |
1224 | + | |
1225 | +static uchar *hp_allocate_one_chunk(HP_DATASPACE *info); | |
1226 | + | |
1227 | + | |
1228 | +/** | |
1229 | + Clear a dataspace | |
1230 | + | |
1231 | + Frees memory and zeros-out any relevant counters in the dataspace | |
1232 | + | |
1233 | + @param info the dataspace to clear | |
1234 | +*/ | |
1235 | + | |
1236 | +void hp_clear_dataspace(HP_DATASPACE *info) | |
1237 | +{ | |
1238 | + if (info->block.levels) | |
1239 | + { | |
1240 | + hp_free_level(&info->block,info->block.levels,info->block.root, | |
1241 | + (uchar *) 0); | |
1242 | + } | |
1243 | + info->block.levels= 0; | |
1244 | + info->del_chunk_count= info->chunk_count= 0; | |
1245 | + info->del_link= 0; | |
1246 | + info->total_data_length= 0; | |
1247 | +} | |
1248 | + | |
1249 | + | |
1250 | +/** | |
1251 | + Allocate or reallocate a chunkset in the dataspace | |
1252 | + | |
1253 | + Attempts to allocate a new chunkset or change the size of an existing chunkset | |
1254 | + | |
1255 | + @param info the hosting dataspace | |
1256 | + @param chunk_count the number of chunks that we expect as the result | |
1257 | + @param existing_set non-null value asks function to resize existing | |
1258 | + chunkset, return value would point to this set | |
1259 | + | |
1260 | + @return Pointer to the first chunk in the new or updated chunkset, or NULL | |
1261 | + if unsuccessful | |
1262 | +*/ | |
1263 | + | |
1264 | +static uchar *hp_allocate_variable_chunkset(HP_DATASPACE *info, | |
1265 | + uint chunk_count, | |
1266 | + uchar *existing_set) | |
1267 | +{ | |
1268 | + int alloc_count= chunk_count, i; | |
1269 | + uchar *first_chunk= 0, *curr_chunk= 0, *prev_chunk= 0; | |
1270 | + uchar *last_existing_chunk= 0; | |
1271 | + | |
1272 | + DBUG_ASSERT(alloc_count); | |
1273 | + | |
1274 | + if (existing_set) | |
1275 | + { | |
1276 | + first_chunk= existing_set; | |
1277 | + | |
1278 | + curr_chunk= existing_set; | |
1279 | + while (curr_chunk && alloc_count) | |
1280 | + { | |
1281 | + prev_chunk= curr_chunk; | |
1282 | + curr_chunk= *((uchar **) (curr_chunk + info->offset_link)); | |
1283 | + alloc_count--; | |
1284 | + } | |
1285 | + | |
1286 | + if (!alloc_count) | |
1287 | + { | |
1288 | + if (curr_chunk) | |
1289 | + { | |
1290 | + /* | |
1291 | + We came through all chunks and there is more left, let's truncate the | |
1292 | + list. | |
1293 | + */ | |
1294 | + *((uchar **) (prev_chunk + info->offset_link))= NULL; | |
1295 | + hp_free_chunks(info, curr_chunk); | |
1296 | + } | |
1297 | + | |
1298 | + return first_chunk; | |
1299 | + } | |
1300 | + | |
1301 | + last_existing_chunk= prev_chunk; | |
1302 | + } | |
1303 | + | |
1304 | + /* | |
1305 | + We can reach this point only if we're allocating new chunkset or more chunks | |
1306 | + in existing set. | |
1307 | + */ | |
1308 | + | |
1309 | + for (i= 0; i < alloc_count; i++) | |
1310 | + { | |
1311 | + curr_chunk= hp_allocate_one_chunk(info); | |
1312 | + if (!curr_chunk) | |
1313 | + { | |
1314 | + /* no space in the current block */ | |
1315 | + | |
1316 | + if (last_existing_chunk) | |
1317 | + { | |
1318 | + /* Truncate whatever was added at the end of the existing chunkset */ | |
1319 | + prev_chunk= last_existing_chunk; | |
1320 | + curr_chunk= *((uchar **)(prev_chunk + info->offset_link)); | |
1321 | + *((uchar **)(prev_chunk + info->offset_link))= NULL; | |
1322 | + hp_free_chunks(info, curr_chunk); | |
1323 | + } | |
1324 | + else if (first_chunk) | |
1325 | + { | |
1326 | + /* free any chunks previously allocated */ | |
1327 | + hp_free_chunks(info, first_chunk); | |
1328 | + } | |
1329 | + | |
1330 | + return NULL; | |
1331 | + } | |
1332 | + | |
1333 | + /* mark as if this chunk is last in the chunkset */ | |
1334 | + *((uchar **) (curr_chunk + info->offset_link))= 0; | |
1335 | + | |
1336 | + if (prev_chunk) | |
1337 | + { | |
1338 | + /* tie them into a linked list */ | |
1339 | + *((uchar **) (prev_chunk + info->offset_link))= curr_chunk; | |
1340 | + /* Record linked from active */ | |
1341 | + curr_chunk[info->offset_status]= CHUNK_STATUS_LINKED; | |
1342 | + } | |
1343 | + else | |
1344 | + { | |
1345 | + /* Record active */ | |
1346 | + curr_chunk[info->offset_status]= CHUNK_STATUS_ACTIVE; | |
1347 | + } | |
1348 | + | |
1349 | + if (!first_chunk) | |
1350 | + { | |
1351 | + first_chunk= curr_chunk; | |
1352 | + } | |
1353 | + | |
1354 | + prev_chunk= curr_chunk; | |
1355 | +} | |
1356 | + | |
1357 | + return first_chunk; | |
1358 | +} | |
1359 | + | |
1360 | + | |
1361 | +/** | |
1362 | + Allocate a new chunkset in the dataspace | |
1363 | + | |
1364 | + Attempts to allocate a new chunkset | |
1365 | + | |
1366 | + @param info the hosting dataspace | |
1367 | + @param chunk_count the number of chunks that we expect as the result | |
1368 | + | |
1369 | + @return Pointer to the first chunk in the new or updated chunkset, or NULL if | |
1370 | + unsuccessful | |
1371 | +*/ | |
1372 | + | |
1373 | +uchar *hp_allocate_chunkset(HP_DATASPACE *info, uint chunk_count) | |
1374 | +{ | |
1375 | + uchar *result; | |
1376 | + | |
1377 | + DBUG_ENTER("hp_allocate_chunks"); | |
1378 | + | |
1379 | + if (info->is_variable_size) | |
1380 | + { | |
1381 | + result = hp_allocate_variable_chunkset(info, chunk_count, NULL); | |
1382 | + } | |
1383 | + else | |
1384 | + { | |
1385 | + result= hp_allocate_one_chunk(info); | |
1386 | + if (result) | |
1387 | + { | |
1388 | + result[info->offset_status]= CHUNK_STATUS_ACTIVE; | |
1389 | + } | |
1390 | + | |
1391 | + DBUG_RETURN(result); | |
1392 | + } | |
1393 | + | |
1394 | + DBUG_RETURN(result); | |
1395 | +} | |
1396 | + | |
1397 | + | |
1398 | +/** | |
1399 | + Reallocate an existing chunkset in the dataspace | |
1400 | + | |
1401 | + Attempts to change the size of an existing chunkset | |
1402 | + | |
1403 | + @param info the hosting dataspace | |
1404 | + @param chunk_count the number of chunks that we expect as the result | |
1405 | + @param pos pointer to the existing chunkset | |
1406 | + | |
1407 | + @return Error code or zero if successful | |
1408 | +*/ | |
1409 | + | |
1410 | +int hp_reallocate_chunkset(HP_DATASPACE *info, uint chunk_count, uchar *pos) | |
1411 | +{ | |
1412 | + DBUG_ENTER("hp_reallocate_chunks"); | |
1413 | + | |
1414 | + if (!info->is_variable_size) | |
1415 | + { | |
1416 | + /* Update should never change chunk_count in fixed-size mode */ | |
1417 | + my_errno= HA_ERR_WRONG_COMMAND; | |
1418 | + return my_errno; | |
1419 | + } | |
1420 | + | |
1421 | + /* Reallocate never moves the first chunk */ | |
1422 | + if (!hp_allocate_variable_chunkset(info, chunk_count, pos)) | |
1423 | + DBUG_RETURN(my_errno); | |
1424 | + | |
1425 | + DBUG_RETURN(0); | |
1426 | +} | |
1427 | + | |
1428 | + | |
1429 | +/** | |
1430 | + Allocate a single chunk in the dataspace | |
1431 | + | |
1432 | + Attempts to allocate a new chunk or reuse one from deleted list | |
1433 | + | |
1434 | + @param info the hosting dataspace | |
1435 | + | |
1436 | + @return Pointer to the chunk, or NULL if unsuccessful | |
1437 | +*/ | |
1438 | + | |
1439 | +static uchar *hp_allocate_one_chunk(HP_DATASPACE *info) | |
1440 | +{ | |
1441 | + uchar *curr_chunk; | |
1442 | + size_t length; | |
1443 | + ulong block_pos; | |
1444 | + | |
1445 | + if (info->del_link) | |
1446 | + { | |
1447 | + curr_chunk= info->del_link; | |
1448 | + info->del_link= *((uchar **) curr_chunk); | |
1449 | + info->del_chunk_count--; | |
1450 | + | |
1451 | + DBUG_PRINT("hp_allocate_one_chunk", | |
1452 | + ("Used old position: 0x%lx",(long) curr_chunk)); | |
1453 | + return curr_chunk; | |
1454 | + } | |
1455 | + | |
1456 | + block_pos= (info->chunk_count % info->block.records_in_block); | |
1457 | + if (!block_pos) | |
1458 | + { | |
1459 | + if (hp_get_new_block(&info->block, &length)) | |
1460 | + { | |
1461 | + /* no space in the current block */ | |
1462 | + return NULL; | |
1463 | + } | |
1464 | + | |
1465 | + info->total_data_length+= length; | |
1466 | + } | |
1467 | + | |
1468 | + info->chunk_count++; | |
1469 | + curr_chunk= ((uchar *) info->block.level_info[0].last_blocks + | |
1470 | + block_pos * info->block.recbuffer); | |
1471 | + | |
1472 | + DBUG_PRINT("hp_allocate_one_chunk", | |
1473 | + ("Used new position: 0x%lx", (long) curr_chunk)); | |
1474 | + | |
1475 | + return curr_chunk; | |
1476 | +} | |
1477 | + | |
1478 | + | |
1479 | +/** | |
1480 | + Free a list of chunks | |
1481 | + | |
1482 | + Reclaims all chunks linked by the pointer, | |
1483 | + which could be the whole chunkset or a part of an existing chunkset | |
1484 | + | |
1485 | + @param info the hosting dataspace | |
1486 | + @param pos pointer to the head of the chunkset | |
1487 | +*/ | |
1488 | + | |
1489 | +void hp_free_chunks(HP_DATASPACE *info, uchar *pos) | |
1490 | +{ | |
1491 | + uchar *curr_chunk= pos; | |
1492 | + | |
1493 | + while (curr_chunk) | |
1494 | + { | |
1495 | + info->del_chunk_count++; | |
1496 | + *((uchar **) curr_chunk)= info->del_link; | |
1497 | + info->del_link= curr_chunk; | |
1498 | + | |
1499 | + curr_chunk[info->offset_status]= CHUNK_STATUS_DELETED; | |
1500 | + | |
1501 | + DBUG_PRINT("hp_free_chunks",("Freed position: 0x%lx", (long) curr_chunk)); | |
1502 | + | |
1503 | + if (!info->is_variable_size) | |
1504 | + { | |
1505 | + break; | |
1506 | + } | |
1507 | + | |
1508 | + /* Delete next chunk in this chunkset */ | |
1509 | + curr_chunk= *((uchar **)(curr_chunk + info->offset_link)); | |
1510 | + } | |
1511 | +} | |
1512 | --- a/storage/heap/hp_extra.c | |
1513 | +++ b/storage/heap/hp_extra.c | |
1514 | @@ -56,7 +56,6 @@ | |
1515 | info->current_record= (ulong) ~0L; | |
1516 | info->current_hash_ptr=0; | |
1517 | info->update=0; | |
1518 | - info->next_block=0; | |
1519 | return 0; | |
1520 | } | |
1521 | ||
1522 | --- a/storage/heap/hp_hash.c | |
1523 | +++ b/storage/heap/hp_hash.c | |
1524 | @@ -336,16 +336,26 @@ | |
1525 | { | |
1526 | CHARSET_INFO *cs= seg->charset; | |
1527 | uint pack_length= seg->bit_start; | |
1528 | - uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos)); | |
1529 | + uint length= hp_calc_blob_length(pack_length, pos); | |
1530 | + | |
1531 | + if (seg->flag & HA_BLOB_PART) | |
1532 | + { | |
1533 | + memcpy(&pos, pos + pack_length, sizeof(char *)); | |
1534 | + } | |
1535 | + else | |
1536 | + { | |
1537 | + pos+= pack_length; | |
1538 | + } | |
1539 | + | |
1540 | if (cs->mbmaxlen > 1) | |
1541 | { | |
1542 | uint char_length; | |
1543 | - char_length= my_charpos(cs, pos + pack_length, | |
1544 | - pos + pack_length + length, | |
1545 | + char_length= my_charpos(cs, pos, | |
1546 | + pos + length, | |
1547 | seg->length/cs->mbmaxlen); | |
1548 | set_if_smaller(length, char_length); | |
1549 | } | |
1550 | - cs->coll->hash_sort(cs, pos+pack_length, length, &nr, &nr2); | |
1551 | + cs->coll->hash_sort(cs, pos, length, &nr, &nr2); | |
1552 | } | |
1553 | else | |
1554 | { | |
1555 | @@ -545,18 +555,18 @@ | |
1556 | uint char_length1, char_length2; | |
1557 | uint pack_length= seg->bit_start; | |
1558 | CHARSET_INFO *cs= seg->charset; | |
1559 | - if (pack_length == 1) | |
1560 | - { | |
1561 | - char_length1= (uint) *(uchar*) pos1++; | |
1562 | - char_length2= (uint) *(uchar*) pos2++; | |
1563 | - } | |
1564 | - else | |
1565 | + | |
1566 | + char_length1= hp_calc_blob_length(pack_length, pos1); | |
1567 | + char_length2= hp_calc_blob_length(pack_length, pos2); | |
1568 | + pos1+= pack_length; | |
1569 | + pos2+= pack_length; | |
1570 | + | |
1571 | + if (seg->flag & HA_BLOB_PART) | |
1572 | { | |
1573 | - char_length1= uint2korr(pos1); | |
1574 | - char_length2= uint2korr(pos2); | |
1575 | - pos1+= 2; | |
1576 | - pos2+= 2; | |
1577 | + memcpy(&pos1, pos1, sizeof(char *)); | |
1578 | + memcpy(&pos2, pos2, sizeof(char *)); | |
1579 | } | |
1580 | + | |
1581 | if (cs->mbmaxlen > 1) | |
1582 | { | |
1583 | uint safe_length1= char_length1; | |
1584 | @@ -668,6 +678,34 @@ | |
1585 | } | |
1586 | ||
1587 | ||
1588 | +/** | |
1589 | + Returns a BLOB length stored in the specified number of bytes at the | |
1590 | + specified location. | |
1591 | + | |
1592 | + @param length the number of bytes used to store length | |
1593 | + @param pos pointer to length bytes | |
1594 | + | |
1595 | + @return Length of BLOB data. | |
1596 | +*/ | |
1597 | + | |
1598 | +uint hp_calc_blob_length(uint bytes, const uchar *pos) | |
1599 | +{ | |
1600 | + switch (bytes) { | |
1601 | + case 1: | |
1602 | + return (uint) *pos; | |
1603 | + case 2: | |
1604 | + return uint2korr(pos); | |
1605 | + case 3: | |
1606 | + return uint3korr(pos); | |
1607 | + case 4: | |
1608 | + return uint4korr(pos); | |
1609 | + default: | |
1610 | + break; | |
1611 | + } | |
1612 | + | |
1613 | + return 0; /* Impossible */ | |
1614 | +} | |
1615 | + | |
1616 | /* Copy a key from a record to a keybuffer */ | |
1617 | ||
1618 | void hp_make_key(HP_KEYDEF *keydef, uchar *key, const uchar *rec) | |
1619 | @@ -678,18 +716,37 @@ | |
1620 | { | |
1621 | CHARSET_INFO *cs= seg->charset; | |
1622 | uint char_length= seg->length; | |
1623 | - uchar *pos= (uchar*) rec + seg->start; | |
1624 | + const uchar *pos= rec + seg->start; | |
1625 | if (seg->null_bit) | |
1626 | *key++= test(rec[seg->null_pos] & seg->null_bit); | |
1627 | - if (cs->mbmaxlen > 1) | |
1628 | + | |
1629 | + if (seg->flag & HA_BLOB_PART) | |
1630 | { | |
1631 | - char_length= my_charpos(cs, pos, pos + seg->length, | |
1632 | - char_length / cs->mbmaxlen); | |
1633 | - set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */ | |
1634 | + uint tmp_length= hp_calc_blob_length(seg->bit_start, pos); | |
1635 | + uint length= min(seg->length, tmp_length); | |
1636 | + | |
1637 | + memcpy(&pos, rec + seg->bit_start, sizeof(char *)); | |
1638 | + if (cs->mbmaxlen > 1) | |
1639 | + { | |
1640 | + char_length= my_charpos(cs, pos, pos + seg->length, | |
1641 | + char_length / cs->mbmaxlen); | |
1642 | + set_if_smaller(char_length, length); /* QQ: ok to remove? */ | |
1643 | + } | |
1644 | + store_key_length_inc(key, char_length); | |
1645 | } | |
1646 | - if (seg->type == HA_KEYTYPE_VARTEXT1) | |
1647 | - char_length+= seg->bit_start; /* Copy also length */ | |
1648 | - memcpy(key,rec+seg->start,(size_t) char_length); | |
1649 | + else | |
1650 | + { | |
1651 | + if (cs->mbmaxlen > 1) | |
1652 | + { | |
1653 | + char_length= my_charpos(cs, pos, pos + seg->length, | |
1654 | + char_length / cs->mbmaxlen); | |
1655 | + set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */ | |
1656 | + } | |
1657 | + if (seg->type == HA_KEYTYPE_VARTEXT1) | |
1658 | + char_length+= seg->bit_start; /* Copy also length */ | |
1659 | + } | |
1660 | + | |
1661 | + memcpy(key, pos, (size_t) char_length); | |
1662 | key+= char_length; | |
1663 | } | |
1664 | } | |
1665 | @@ -702,8 +759,8 @@ | |
1666 | } while(0) | |
1667 | ||
1668 | ||
1669 | -uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key, | |
1670 | - const uchar *rec, uchar *recpos) | |
1671 | +uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key, | |
1672 | + const uchar *rec, uchar *recpos, my_bool packed) | |
1673 | { | |
1674 | uchar *start_key= key; | |
1675 | HA_KEYSEG *seg, *endseg; | |
1676 | @@ -772,6 +829,29 @@ | |
1677 | key+= char_length; | |
1678 | continue; | |
1679 | } | |
1680 | + else if (seg->flag & HA_BLOB_PART) | |
1681 | + { | |
1682 | + uchar *pos= (uchar*) rec + seg->start; | |
1683 | + uint tmp_length= hp_calc_blob_length(seg->bit_start, pos); | |
1684 | + uint length= min(seg->length, tmp_length); | |
1685 | + CHARSET_INFO *cs= seg->charset; | |
1686 | + char_length= seg->length / cs->mbmaxlen; | |
1687 | + | |
1688 | + /* check_one_rb_key() calls hp_rb_make_key() for already packed records */ | |
1689 | + if (!packed) | |
1690 | + { | |
1691 | + memcpy(&pos, pos + seg->bit_start, sizeof(char *)); | |
1692 | + } | |
1693 | + else | |
1694 | + { | |
1695 | + pos+= seg->bit_start; | |
1696 | + } | |
1697 | + FIX_LENGTH(cs, pos, length, char_length); | |
1698 | + store_key_length_inc(key, char_length); | |
1699 | + memcpy(key, pos, (size_t) char_length); | |
1700 | + key+= char_length; | |
1701 | + continue; | |
1702 | + } | |
1703 | ||
1704 | char_length= seg->length; | |
1705 | if (seg->charset->mbmaxlen > 1) | |
1706 | --- a/storage/heap/hp_info.c | |
1707 | +++ b/storage/heap/hp_info.c | |
1708 | @@ -47,9 +47,22 @@ | |
1709 | { | |
1710 | DBUG_ENTER("heap_info"); | |
1711 | x->records = info->s->records; | |
1712 | - x->deleted = info->s->deleted; | |
1713 | - x->reclength = info->s->reclength; | |
1714 | - x->data_length = info->s->data_length; | |
1715 | + x->deleted = info->s->recordspace.del_chunk_count; | |
1716 | + | |
1717 | + if (info->s->recordspace.is_variable_size) | |
1718 | + { | |
1719 | + if (info->s->records) | |
1720 | + x->reclength = (uint) (info->s->recordspace.total_data_length / | |
1721 | + (ulonglong) info->s->records); | |
1722 | + else | |
1723 | + x->reclength = info->s->recordspace.chunk_length; | |
1724 | + } | |
1725 | + else | |
1726 | + { | |
1727 | + x->reclength = info->s->recordspace.chunk_dataspace_length; | |
1728 | + } | |
1729 | + | |
1730 | + x->data_length = info->s->recordspace.total_data_length; | |
1731 | x->index_length = info->s->index_length; | |
1732 | x->max_records = info->s->max_records; | |
1733 | x->errkey = info->errkey; | |
1734 | --- a/storage/heap/hp_open.c | |
1735 | +++ b/storage/heap/hp_open.c | |
1736 | @@ -47,9 +47,9 @@ | |
1737 | #ifndef DBUG_OFF | |
1738 | info->opt_flag= READ_CHECK_USED; /* Check when changing */ | |
1739 | #endif | |
1740 | - DBUG_PRINT("exit",("heap: 0x%lx reclength: %d records_in_block: %d", | |
1741 | - (long) info, share->reclength, | |
1742 | - share->block.records_in_block)); | |
1743 | + DBUG_PRINT("exit",("heap: 0x%lx chunk_length: %d records_in_block: %d", | |
1744 | + (long) info, share->recordspace.chunk_length, | |
1745 | + share->recordspace.block.records_in_block)); | |
1746 | DBUG_RETURN(info); | |
1747 | } | |
1748 | ||
1749 | --- /dev/null | |
1750 | +++ b/storage/heap/hp_record.c | |
1751 | @@ -0,0 +1,498 @@ | |
1752 | +/* Copyright (C) 2000-2002 MySQL AB | |
1753 | + Copyright (C) 2008 eBay, Inc | |
1754 | + | |
1755 | + This program is free software; you can redistribute it and/or modify | |
1756 | + it under the terms of the GNU General Public License as published by | |
1757 | + the Free Software Foundation; version 2 of the License. | |
1758 | + | |
1759 | + This program is distributed in the hope that it will be useful, | |
1760 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1761 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1762 | + GNU General Public License for more details. | |
1763 | + | |
1764 | + You should have received a copy of the GNU General Public License | |
1765 | + along with this program; if not, write to the Free Software | |
1766 | + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | |
1767 | + | |
1768 | +/* | |
1769 | + Implements various base record-related functions, such as encode and decode | |
1770 | + into chunks. | |
1771 | +*/ | |
1772 | + | |
1773 | +#include "heapdef.h" | |
1774 | +#include <mysql_com.h> | |
1775 | + | |
1776 | +/** | |
1777 | + Calculate size of the record for the purpose of storing in chunks | |
1778 | + | |
1779 | + Walk through the fields of the record and calculates the exact space | |
1780 | + needed in chunks as well the the total chunk count | |
1781 | + | |
1782 | + @param info the hosting table | |
1783 | + @param record the record in standard unpacked format | |
1784 | + @param[out] chunk_count the number of chunks needed for this record | |
1785 | + | |
1786 | + @return The size of the required storage in bytes | |
1787 | +*/ | |
1788 | + | |
1789 | +uint hp_get_encoded_data_length(HP_SHARE *info, const uchar *record, | |
1790 | + uint *chunk_count) | |
1791 | +{ | |
1792 | + uint i, dst_offset; | |
1793 | + | |
1794 | + dst_offset= info->fixed_data_length; | |
1795 | + | |
1796 | + if (!info->recordspace.is_variable_size) | |
1797 | + { | |
1798 | + /* Nothing more to copy */ | |
1799 | + *chunk_count= 1; | |
1800 | + return dst_offset; | |
1801 | + } | |
1802 | + | |
1803 | + for (i= info->fixed_column_count; i < info->column_count; i++) | |
1804 | + { | |
1805 | + uint src_offset, length; | |
1806 | + | |
1807 | + HP_COLUMNDEF *column= info->column_defs + i; | |
1808 | + | |
1809 | + if (column->null_bit) | |
1810 | + { | |
1811 | + if (record[column->null_pos] & column->null_bit) | |
1812 | + { | |
1813 | + /* Skip all NULL values */ | |
1814 | + continue; | |
1815 | + } | |
1816 | + } | |
1817 | + | |
1818 | + src_offset= column->offset; | |
1819 | + if (column->type == MYSQL_TYPE_VARCHAR) | |
1820 | + { | |
1821 | + uint pack_length; | |
1822 | + | |
1823 | + /* >= 5.0.3 true VARCHAR */ | |
1824 | + | |
1825 | + pack_length= column->length_bytes; | |
1826 | + length= pack_length + (pack_length == 1 ? | |
1827 | + (uint) *(uchar *) (record + src_offset) : | |
1828 | + uint2korr(record + src_offset)); | |
1829 | + } | |
1830 | + else if (column->type == MYSQL_TYPE_BLOB) | |
1831 | + { | |
1832 | + uint pack_length= column->length_bytes; | |
1833 | + | |
1834 | + length= pack_length + hp_calc_blob_length(pack_length, | |
1835 | + record + src_offset); | |
1836 | + } | |
1837 | + else | |
1838 | + { | |
1839 | + length= column->length; | |
1840 | + } | |
1841 | + | |
1842 | + dst_offset+= length; | |
1843 | + } | |
1844 | + | |
1845 | + *chunk_count= get_chunk_count(&info->recordspace, dst_offset); | |
1846 | + | |
1847 | + return dst_offset; | |
1848 | +} | |
1849 | + | |
1850 | + | |
1851 | +#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG) | |
1852 | +static void dump_chunk(HP_SHARE *info, const uchar *curr_chunk) | |
1853 | +{ | |
1854 | + uint i; | |
1855 | + fprintf(stdout, "Chunk dump at 0x%lx: ", (long) curr_chunk); | |
1856 | + for (i= 0; i < info->recordspace.chunk_dataspace_length; i++) | |
1857 | + { | |
1858 | + uint b= *((uchar *)(curr_chunk + i)); | |
1859 | + if (b < 0x10) | |
1860 | + { | |
1861 | + fprintf(stdout, "0"); | |
1862 | + } | |
1863 | + fprintf(stdout, "%lx ", (long) b); | |
1864 | + } | |
1865 | + fprintf(stdout, ". Next = 0x%lx, Status = %d\n", | |
1866 | + (long) (*((uchar **) (curr_chunk + info->recordspace.offset_link))), | |
1867 | + (uint) (*((uchar *) (curr_chunk + info->recordspace.offset_status)))); | |
1868 | +} | |
1869 | +#endif | |
1870 | + | |
1871 | +/** | |
1872 | + Stores data from packed field into the preallocated chunkset, | |
1873 | + or performs data comparison | |
1874 | + | |
1875 | + @param info the hosting table | |
1876 | + @param data the field data in packed format | |
1877 | + @param length the field data length | |
1878 | + @param pos_ptr the target chunkset | |
1879 | + @param off_ptr the pointer to the offset within the current chunkset | |
1880 | + @param is_compare flag indicating whether we should compare data or store | |
1881 | + it | |
1882 | + | |
1883 | + @return Status of comparison | |
1884 | + @retval non-zero if comparison found data differences | |
1885 | + @retval zero otherwise | |
1886 | +*/ | |
1887 | + | |
1888 | +static inline uint | |
1889 | +hp_process_field_data_to_chunkset(HP_SHARE *info, const uchar *data, | |
1890 | + uint length, uchar **pos_ptr, uint *off_ptr, | |
1891 | + uint is_compare) | |
1892 | +{ | |
1893 | + uint to_copy; | |
1894 | + uchar *curr_chunk= *pos_ptr; | |
1895 | + uint dst_offset= *off_ptr; | |
1896 | + uint rc= 1; | |
1897 | + | |
1898 | + while (length > 0) | |
1899 | + { | |
1900 | + | |
1901 | + to_copy= info->recordspace.chunk_dataspace_length - dst_offset; | |
1902 | + if (to_copy == 0) | |
1903 | + { | |
1904 | + /* Jump to the next chunk */ | |
1905 | +#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG) | |
1906 | + dump_chunk(info, curr_chunk); | |
1907 | +#endif | |
1908 | + curr_chunk= *((uchar **) (curr_chunk + info->recordspace.offset_link)); | |
1909 | + dst_offset= 0; | |
1910 | + continue; | |
1911 | + } | |
1912 | + | |
1913 | + to_copy= min(length, to_copy); | |
1914 | + | |
1915 | + if (is_compare) | |
1916 | + { | |
1917 | + if (memcmp(curr_chunk + dst_offset, data, (size_t) to_copy)) | |
1918 | + { | |
1919 | + goto end; | |
1920 | + } | |
1921 | + } | |
1922 | + else | |
1923 | + { | |
1924 | + memcpy(curr_chunk + dst_offset, data, (size_t) to_copy); | |
1925 | + } | |
1926 | + | |
1927 | + data+= to_copy; | |
1928 | + dst_offset+= to_copy; | |
1929 | + length-= to_copy; | |
1930 | + } | |
1931 | + | |
1932 | + rc= 0; | |
1933 | + | |
1934 | +end: | |
1935 | + *pos_ptr= curr_chunk; | |
1936 | + *off_ptr= dst_offset; | |
1937 | + | |
1938 | + return rc; | |
1939 | +} | |
1940 | + | |
1941 | +/** | |
1942 | + Encodes or compares record | |
1943 | + | |
1944 | + Copies data from original unpacked record into the preallocated chunkset, | |
1945 | + or performs data comparison | |
1946 | + | |
1947 | + @param info the hosting table | |
1948 | + @param record the record in standard unpacked format | |
1949 | + @param pos the target chunkset | |
1950 | + @param is_compare flag indicating whether we should compare data or store | |
1951 | + it | |
1952 | + | |
1953 | + @return Status of comparison | |
1954 | + @retval non-zero if comparison fond data differences | |
1955 | + @retval zero otherwise | |
1956 | +*/ | |
1957 | + | |
1958 | +uint hp_process_record_data_to_chunkset(HP_SHARE *info, const uchar *record, | |
1959 | + uchar *pos, uint is_compare) | |
1960 | +{ | |
1961 | + uint i, dst_offset; | |
1962 | + uchar *curr_chunk= pos; | |
1963 | + | |
1964 | + if (is_compare) | |
1965 | + { | |
1966 | + if (memcmp(curr_chunk, record, (size_t) info->fixed_data_length)) | |
1967 | + { | |
1968 | + return 1; | |
1969 | + } | |
1970 | + } | |
1971 | + else | |
1972 | + { | |
1973 | + memcpy(curr_chunk, record, (size_t) info->fixed_data_length); | |
1974 | + } | |
1975 | + | |
1976 | + if (!info->recordspace.is_variable_size) | |
1977 | + { | |
1978 | + /* Nothing more to copy */ | |
1979 | + return 0; | |
1980 | + } | |
1981 | + | |
1982 | + dst_offset= info->fixed_data_length; | |
1983 | + | |
1984 | + for (i= info->fixed_column_count; i < info->column_count; i++) | |
1985 | + { | |
1986 | + uint length; | |
1987 | + const uchar *data; | |
1988 | + | |
1989 | + HP_COLUMNDEF *column= info->column_defs + i; | |
1990 | + | |
1991 | + if (column->null_bit) | |
1992 | + { | |
1993 | + if (record[column->null_pos] & column->null_bit) | |
1994 | + { | |
1995 | + /* Skip all NULL values */ | |
1996 | + continue; | |
1997 | + } | |
1998 | + } | |
1999 | + | |
2000 | + data= record + column->offset; | |
2001 | + if (column->type == MYSQL_TYPE_VARCHAR) | |
2002 | + { | |
2003 | + uint pack_length; | |
2004 | + | |
2005 | + /* >= 5.0.3 true VARCHAR */ | |
2006 | + | |
2007 | + /* Make sure to copy length indicator and actuals string bytes */ | |
2008 | + pack_length= column->length_bytes; | |
2009 | + length= pack_length + (pack_length == 1 ? (uint) *data : uint2korr(data)); | |
2010 | + } | |
2011 | + else if (column->type == MYSQL_TYPE_BLOB) | |
2012 | + { | |
2013 | + uint pack_length; | |
2014 | + | |
2015 | + pack_length= column->length_bytes; | |
2016 | + /* Just want to store the length, so not interested in the return code */ | |
2017 | + (void) hp_process_field_data_to_chunkset(info, data, pack_length, | |
2018 | + &curr_chunk, &dst_offset, 0); | |
2019 | + length= hp_calc_blob_length(pack_length, data); | |
2020 | + memcpy(&data, data + pack_length, sizeof(char *)); | |
2021 | + } | |
2022 | + else | |
2023 | + { | |
2024 | + length= column->length; | |
2025 | + } | |
2026 | + | |
2027 | + if (hp_process_field_data_to_chunkset(info, data, length, &curr_chunk, | |
2028 | + &dst_offset, is_compare)) | |
2029 | + { | |
2030 | + return 1; | |
2031 | + } | |
2032 | + } | |
2033 | + | |
2034 | +#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG) | |
2035 | + dump_chunk(info, curr_chunk); | |
2036 | +#endif | |
2037 | + | |
2038 | + return 0; | |
2039 | +} | |
2040 | + | |
2041 | + | |
2042 | +/** | |
2043 | + Stores record in the heap table chunks | |
2044 | + | |
2045 | + Copies data from original unpacked record into the preallocated chunkset | |
2046 | + | |
2047 | + @param info the hosting table | |
2048 | + @param record the record in standard unpacked format | |
2049 | + @param pos the target chunkset | |
2050 | +*/ | |
2051 | + | |
2052 | +void hp_copy_record_data_to_chunkset(HP_SHARE *info, const uchar *record, | |
2053 | + uchar *pos) | |
2054 | +{ | |
2055 | + DBUG_ENTER("hp_copy_record_data_to_chunks"); | |
2056 | + | |
2057 | + hp_process_record_data_to_chunkset(info, record, pos, 0); | |
2058 | + | |
2059 | + DBUG_VOID_RETURN; | |
2060 | +} | |
2061 | + | |
2062 | + | |
2063 | +/* | |
2064 | + Macro to switch curr_chunk to the next chunk in the chunkset and reset | |
2065 | + src_offset. | |
2066 | +*/ | |
2067 | +#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG) | |
2068 | +#define SWITCH_TO_NEXT_CHUNK_FOR_READ(share, curr_chunk, src_offset) \ | |
2069 | + { \ | |
2070 | + curr_chunk= *((uchar**) (curr_chunk + share->recordspace.offset_link)); \ | |
2071 | + src_offset= 0; \ | |
2072 | + dump_chunk(share, curr_chunk); \ | |
2073 | + } | |
2074 | +#else | |
2075 | +#define SWITCH_TO_NEXT_CHUNK_FOR_READ(share, curr_chunk, src_offset) \ | |
2076 | + { \ | |
2077 | + curr_chunk= *((uchar**) (curr_chunk + share->recordspace.offset_link)); \ | |
2078 | + src_offset= 0; \ | |
2079 | + } | |
2080 | +#endif | |
2081 | + | |
2082 | +/** | |
2083 | + Copies record data from storage to unpacked record format | |
2084 | + | |
2085 | + Copies data from chunkset into its original unpacked record | |
2086 | + | |
2087 | + @param info the hosting table | |
2088 | + @param[out] record the target record in standard unpacked format | |
2089 | + @param pos the source chunkset | |
2090 | + | |
2091 | + @return Status of conversion | |
2092 | + @retval 0 success | |
2093 | + @retval 1 out of memory | |
2094 | +*/ | |
2095 | + | |
2096 | +int hp_extract_record(HP_INFO *info, uchar *record, const uchar *pos) | |
2097 | +{ | |
2098 | + uint i, src_offset; | |
2099 | + const uchar *curr_chunk= pos; | |
2100 | + HP_SHARE *share= info->s; | |
2101 | + uint *rec_offsets= NULL; | |
2102 | + uint *buf_offsets= NULL; | |
2103 | + uint nblobs= 0; | |
2104 | + uint init_offset= share->blobs * sizeof(uint) * 2; | |
2105 | + | |
2106 | + DBUG_ENTER("hp_extract_record"); | |
2107 | + | |
2108 | +#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG) | |
2109 | + if (share->recordspace.is_variable_size) | |
2110 | + { | |
2111 | + dump_chunk(share, curr_chunk); | |
2112 | + } | |
2113 | +#endif | |
2114 | + | |
2115 | + memcpy(record, curr_chunk, (size_t) share->fixed_data_length); | |
2116 | + | |
2117 | + if (!share->recordspace.is_variable_size) | |
2118 | + { | |
2119 | + /* Nothing more to copy */ | |
2120 | + DBUG_RETURN(0); | |
2121 | + } | |
2122 | + | |
2123 | + /* Reserve space for rec_offsets and buf_offsets.*/ | |
2124 | + info->blob_offset= init_offset; | |
2125 | + src_offset= share->fixed_data_length; | |
2126 | + | |
2127 | + for (i= share->fixed_column_count; i < share->column_count; i++) | |
2128 | + { | |
2129 | + uint length, is_null= 0; | |
2130 | + uchar *to; | |
2131 | + | |
2132 | + HP_COLUMNDEF *column= share->column_defs + i; | |
2133 | + | |
2134 | + if (column->null_bit) | |
2135 | + { | |
2136 | + if (record[column->null_pos] & column->null_bit) | |
2137 | + { | |
2138 | + is_null= 1; | |
2139 | + } | |
2140 | + } | |
2141 | + | |
2142 | + if (is_null) | |
2143 | + { | |
2144 | + /* TODO: is memset really needed? */ | |
2145 | + memset(record + column->offset, 0, column->length); | |
2146 | + continue; | |
2147 | + } | |
2148 | + | |
2149 | + to= record + column->offset; | |
2150 | + if (column->type == MYSQL_TYPE_VARCHAR || column->type == MYSQL_TYPE_BLOB) | |
2151 | + { | |
2152 | + uint pack_length, i; | |
2153 | + uchar *tmp= to; | |
2154 | + | |
2155 | + pack_length= column->length_bytes; | |
2156 | + | |
2157 | + for (i= 0; i < pack_length; i++) | |
2158 | + { | |
2159 | + if (src_offset == share->recordspace.chunk_dataspace_length) | |
2160 | + { | |
2161 | + SWITCH_TO_NEXT_CHUNK_FOR_READ(share, curr_chunk, src_offset); | |
2162 | + } | |
2163 | + *to++= curr_chunk[src_offset++]; | |
2164 | + } | |
2165 | + /* | |
2166 | + We copy byte-by-byte and then use hp_calc_blob_length to combine bytes | |
2167 | + in the right order. | |
2168 | + */ | |
2169 | + length= hp_calc_blob_length(pack_length, tmp); | |
2170 | + | |
2171 | + if (column->type == MYSQL_TYPE_BLOB && length == 0) | |
2172 | + { | |
2173 | + /* | |
2174 | + Store a zero pointer for zero-length BLOBs because the server | |
2175 | + relies on that (see Field_blob::val_*(). | |
2176 | + */ | |
2177 | + *(uchar **) to= 0; | |
2178 | + } | |
2179 | + else if (column->type == MYSQL_TYPE_BLOB && length > 0) | |
2180 | + { | |
2181 | + uint newsize= info->blob_offset + length; | |
2182 | + | |
2183 | + DBUG_ASSERT(share->blobs > 0); | |
2184 | + /* | |
2185 | + Make sure we have enough space in blob_buffer and store the pointer | |
2186 | + to this blob in record. | |
2187 | + */ | |
2188 | + if (info->blob_size < newsize) | |
2189 | + { | |
2190 | + uchar *ptr; | |
2191 | + ptr= my_realloc(info->blob_buffer, newsize, MYF(MY_ALLOW_ZERO_PTR)); | |
2192 | + if (ptr == NULL) | |
2193 | + { | |
2194 | + DBUG_RETURN(1); | |
2195 | + } | |
2196 | + | |
2197 | + if (info->blob_buffer == NULL) | |
2198 | + { | |
2199 | + memset(ptr, 0, init_offset); | |
2200 | + } | |
2201 | + info->blob_buffer= ptr; | |
2202 | + info->blob_size= newsize; | |
2203 | + } | |
2204 | + | |
2205 | + rec_offsets= (uint *) info->blob_buffer; | |
2206 | + buf_offsets= rec_offsets + share->blobs; | |
2207 | + | |
2208 | + rec_offsets[nblobs]= (uint) (to - record); | |
2209 | + buf_offsets[nblobs]= info->blob_offset; | |
2210 | + nblobs++; | |
2211 | + | |
2212 | + /* Change 'to' so blob data is copied into blob_buffer */ | |
2213 | + to= info->blob_buffer + info->blob_offset; | |
2214 | + info->blob_offset= newsize; | |
2215 | + } | |
2216 | + } | |
2217 | + else | |
2218 | + { | |
2219 | + length= column->length; | |
2220 | + } | |
2221 | + | |
2222 | + while (length > 0) | |
2223 | + { | |
2224 | + uint to_copy; | |
2225 | + | |
2226 | + to_copy= share->recordspace.chunk_dataspace_length - src_offset; | |
2227 | + if (to_copy == 0) | |
2228 | + { | |
2229 | + SWITCH_TO_NEXT_CHUNK_FOR_READ(share, curr_chunk, src_offset); | |
2230 | + to_copy= share->recordspace.chunk_dataspace_length; | |
2231 | + } | |
2232 | + | |
2233 | + to_copy= min(length, to_copy); | |
2234 | + | |
2235 | + memcpy(to, curr_chunk + src_offset, (size_t) to_copy); | |
2236 | + src_offset+= to_copy; | |
2237 | + to+= to_copy; | |
2238 | + length-= to_copy; | |
2239 | + } | |
2240 | + } | |
2241 | + | |
2242 | + /* Store pointers to blob data in record */ | |
2243 | + for (i= 0; i < nblobs; i++) | |
2244 | + { | |
2245 | + *(uchar **) (record + rec_offsets[i]) = info->blob_buffer + buf_offsets[i]; | |
2246 | + } | |
2247 | + | |
2248 | + DBUG_RETURN(0); | |
2249 | +} | |
2250 | --- a/storage/heap/hp_rfirst.c | |
2251 | +++ b/storage/heap/hp_rfirst.c | |
2252 | @@ -34,7 +34,10 @@ | |
2253 | memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos), | |
2254 | sizeof(uchar*)); | |
2255 | info->current_ptr = pos; | |
2256 | - memcpy(record, pos, (size_t)share->reclength); | |
2257 | + if (hp_extract_record(info, record, pos)) | |
2258 | + { | |
2259 | + DBUG_RETURN(my_errno); | |
2260 | + } | |
2261 | /* | |
2262 | If we're performing index_first on a table that was taken from | |
2263 | table cache, info->lastkey_len is initialized to previous query. | |
2264 | --- a/storage/heap/hp_rkey.c | |
2265 | +++ b/storage/heap/hp_rkey.c | |
2266 | @@ -67,7 +67,10 @@ | |
2267 | if (!(keyinfo->flag & HA_NOSAME)) | |
2268 | memcpy(info->lastkey, key, (size_t) keyinfo->length); | |
2269 | } | |
2270 | - memcpy(record, pos, (size_t) share->reclength); | |
2271 | + if (hp_extract_record(info, record, pos)) | |
2272 | + { | |
2273 | + DBUG_RETURN(my_errno); | |
2274 | + } | |
2275 | info->update= HA_STATE_AKTIV; | |
2276 | DBUG_RETURN(0); | |
2277 | } | |
2278 | --- a/storage/heap/hp_rlast.c | |
2279 | +++ b/storage/heap/hp_rlast.c | |
2280 | @@ -35,7 +35,10 @@ | |
2281 | memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos), | |
2282 | sizeof(uchar*)); | |
2283 | info->current_ptr = pos; | |
2284 | - memcpy(record, pos, (size_t)share->reclength); | |
2285 | + if (hp_extract_record(info, record, pos)) | |
2286 | + { | |
2287 | + DBUG_RETURN(my_errno); | |
2288 | + } | |
2289 | info->update = HA_STATE_AKTIV; | |
2290 | } | |
2291 | else | |
2292 | --- a/storage/heap/hp_rnext.c | |
2293 | +++ b/storage/heap/hp_rnext.c | |
2294 | @@ -109,7 +109,10 @@ | |
2295 | my_errno=HA_ERR_END_OF_FILE; | |
2296 | DBUG_RETURN(my_errno); | |
2297 | } | |
2298 | - memcpy(record,pos,(size_t) share->reclength); | |
2299 | + if (hp_extract_record(info, record, pos)) | |
2300 | + { | |
2301 | + DBUG_RETURN(my_errno); | |
2302 | + } | |
2303 | info->update=HA_STATE_AKTIV | HA_STATE_NEXT_FOUND; | |
2304 | DBUG_RETURN(0); | |
2305 | } | |
2306 | --- a/storage/heap/hp_rprev.c | |
2307 | +++ b/storage/heap/hp_rprev.c | |
2308 | @@ -77,7 +77,10 @@ | |
2309 | my_errno=HA_ERR_END_OF_FILE; | |
2310 | DBUG_RETURN(my_errno); | |
2311 | } | |
2312 | - memcpy(record,pos,(size_t) share->reclength); | |
2313 | + if (hp_extract_record(info, record, pos)) | |
2314 | + { | |
2315 | + DBUG_RETURN(my_errno); | |
2316 | + } | |
2317 | info->update=HA_STATE_AKTIV | HA_STATE_PREV_FOUND; | |
2318 | DBUG_RETURN(0); | |
2319 | } | |
2320 | --- a/storage/heap/hp_rrnd.c | |
2321 | +++ b/storage/heap/hp_rrnd.c | |
2322 | @@ -36,13 +36,18 @@ | |
2323 | info->update= 0; | |
2324 | DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); | |
2325 | } | |
2326 | - if (!info->current_ptr[share->reclength]) | |
2327 | + if (get_chunk_status(&share->recordspace, info->current_ptr) != | |
2328 | + CHUNK_STATUS_ACTIVE) | |
2329 | { | |
2330 | + /* treat deleted and linked chunks as deleted */ | |
2331 | info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND; | |
2332 | DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED); | |
2333 | } | |
2334 | info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV; | |
2335 | - memcpy(record,info->current_ptr,(size_t) share->reclength); | |
2336 | + if (hp_extract_record(info, record, info->current_ptr)) | |
2337 | + { | |
2338 | + DBUG_RETURN(my_errno); | |
2339 | + } | |
2340 | DBUG_PRINT("exit", ("found record at 0x%lx", (long) info->current_ptr)); | |
2341 | info->current_hash_ptr=0; /* Can't use rnext */ | |
2342 | DBUG_RETURN(0); | |
2343 | @@ -70,17 +75,17 @@ | |
2344 | { | |
2345 | pos= ++info->current_record; | |
2346 | if (pos % share->block.records_in_block && /* Quick next record */ | |
2347 | - pos < share->records+share->deleted && | |
2348 | - (info->update & HA_STATE_PREV_FOUND)) | |
2349 | + pos < share->used_chunk_count + share->deleted_chunk_count && | |
2350 | + (info->update & HA_STATE_PREV_FOUND)) | |
2351 | { | |
2352 | - info->current_ptr+=share->block.recbuffer; | |
2353 | + info->current_ptr+= share->block.recbufferlen; | |
2354 | goto end; | |
2355 | } | |
2356 | } | |
2357 | else | |
2358 | info->current_record=pos; | |
2359 | ||
2360 | - if (pos >= share->records+share->deleted) | |
2361 | + if (pos >= share->used_chunk_count + share->deleted_chunk_count) | |
2362 | { | |
2363 | info->update= 0; | |
2364 | DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); | |
2365 | @@ -90,13 +95,17 @@ | |
2366 | hp_find_record(info, pos); | |
2367 | ||
2368 | end: | |
2369 | - if (!info->current_ptr[share->reclength]) | |
2370 | + if (GET_CHUNK_STATUS(info, info->current_ptr) != CHUNK_STATUS_ACTIVE) | |
2371 | { | |
2372 | + /* treat deleted and linked chunks as deleted */ | |
2373 | info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND; | |
2374 | DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED); | |
2375 | } | |
2376 | info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV; | |
2377 | - memcpy(record,info->current_ptr,(size_t) share->reclength); | |
2378 | + if (hp_extract_record(info, record, info->current_ptr)) | |
2379 | + { | |
2380 | + DBUG_RETURN(my_errno); | |
2381 | + } | |
2382 | DBUG_PRINT("exit",("found record at 0x%lx",info->current_ptr)); | |
2383 | info->current_hash_ptr=0; /* Can't use rnext */ | |
2384 | DBUG_RETURN(0); | |
2385 | --- a/storage/heap/hp_rsame.c | |
2386 | +++ b/storage/heap/hp_rsame.c | |
2387 | @@ -31,7 +31,8 @@ | |
2388 | DBUG_ENTER("heap_rsame"); | |
2389 | ||
2390 | test_active(info); | |
2391 | - if (info->current_ptr[share->reclength]) | |
2392 | + if (get_chunk_status(&share->recordspace, info->current_ptr) == | |
2393 | + CHUNK_STATUS_ACTIVE) | |
2394 | { | |
2395 | if (inx < -1 || inx >= (int) share->keys) | |
2396 | { | |
2397 | @@ -47,9 +48,15 @@ | |
2398 | DBUG_RETURN(my_errno); | |
2399 | } | |
2400 | } | |
2401 | - memcpy(record,info->current_ptr,(size_t) share->reclength); | |
2402 | + if (hp_extract_record(info, record, info->current_ptr)) | |
2403 | + { | |
2404 | + DBUG_RETURN(my_errno); | |
2405 | + } | |
2406 | DBUG_RETURN(0); | |
2407 | } | |
2408 | + | |
2409 | + /* treat deleted and linked chunks as deleted */ | |
2410 | + | |
2411 | info->update=0; | |
2412 | ||
2413 | DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED); | |
2414 | --- a/storage/heap/hp_scan.c | |
2415 | +++ b/storage/heap/hp_scan.c | |
2416 | @@ -30,7 +30,6 @@ | |
2417 | info->lastinx= -1; | |
2418 | info->current_record= (ulong) ~0L; /* No current record */ | |
2419 | info->update=0; | |
2420 | - info->next_block=0; | |
2421 | DBUG_RETURN(0); | |
2422 | } | |
2423 | ||
2424 | @@ -41,32 +40,26 @@ | |
2425 | DBUG_ENTER("heap_scan"); | |
2426 | ||
2427 | pos= ++info->current_record; | |
2428 | - if (pos < info->next_block) | |
2429 | + if (pos >= share->recordspace.chunk_count) | |
2430 | { | |
2431 | - info->current_ptr+=share->block.recbuffer; | |
2432 | + info->update= 0; | |
2433 | + DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); | |
2434 | } | |
2435 | - else | |
2436 | - { | |
2437 | - info->next_block+=share->block.records_in_block; | |
2438 | - if (info->next_block >= share->records+share->deleted) | |
2439 | - { | |
2440 | - info->next_block= share->records+share->deleted; | |
2441 | - if (pos >= info->next_block) | |
2442 | - { | |
2443 | - info->update= 0; | |
2444 | - DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); | |
2445 | - } | |
2446 | - } | |
2447 | - hp_find_record(info, pos); | |
2448 | - } | |
2449 | - if (!info->current_ptr[share->reclength]) | |
2450 | + | |
2451 | + hp_find_record(info, pos); | |
2452 | + | |
2453 | + if (get_chunk_status(&share->recordspace, info->current_ptr) != | |
2454 | + CHUNK_STATUS_ACTIVE) | |
2455 | { | |
2456 | - DBUG_PRINT("warning",("Found deleted record")); | |
2457 | + DBUG_PRINT("warning",("Found deleted record or secondary chunk")); | |
2458 | info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND; | |
2459 | DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED); | |
2460 | } | |
2461 | info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV; | |
2462 | - memcpy(record,info->current_ptr,(size_t) share->reclength); | |
2463 | + if (hp_extract_record(info, record, info->current_ptr)) | |
2464 | + { | |
2465 | + DBUG_RETURN(my_errno); | |
2466 | + } | |
2467 | info->current_hash_ptr=0; /* Can't use read_next */ | |
2468 | DBUG_RETURN(0); | |
2469 | } /* heap_scan */ | |
2470 | --- a/storage/heap/hp_test1.c | |
2471 | +++ b/storage/heap/hp_test1.c | |
2472 | @@ -22,6 +22,7 @@ | |
2473 | #include <my_global.h> | |
2474 | #include <my_sys.h> | |
2475 | #include <m_string.h> | |
2476 | +#include <mysql_com.h> | |
2477 | #include "heap.h" | |
2478 | ||
2479 | static int get_options(int argc, char *argv[]); | |
2480 | @@ -35,6 +36,7 @@ | |
2481 | uchar record[128],key[32]; | |
2482 | const char *filename; | |
2483 | HP_KEYDEF keyinfo[10]; | |
2484 | + HP_COLUMNDEF columndef[2]; | |
2485 | HA_KEYSEG keyseg[4]; | |
2486 | HP_CREATE_INFO hp_create_info; | |
2487 | HP_SHARE *tmp_share; | |
2488 | @@ -51,6 +53,10 @@ | |
2489 | hp_create_info.reclength= 30; | |
2490 | hp_create_info.max_records= (ulong) flag*100000L; | |
2491 | hp_create_info.min_records= 10UL; | |
2492 | + hp_create_info.columns= 2; | |
2493 | + hp_create_info.columndef= columndef; | |
2494 | + hp_create_info.fixed_key_fieldnr= 30; | |
2495 | + hp_create_info.fixed_data_size= sizeof(char*) * 2; | |
2496 | ||
2497 | keyinfo[0].keysegs=1; | |
2498 | keyinfo[0].seg=keyseg; | |
2499 | @@ -62,11 +68,20 @@ | |
2500 | keyinfo[0].seg[0].null_bit= 0; | |
2501 | keyinfo[0].flag = HA_NOSAME; | |
2502 | ||
2503 | + memset(columndef, 0, 2 * sizeof(HP_COLUMNDEF)); | |
2504 | + columndef[0].type= MYSQL_TYPE_STRING; | |
2505 | + columndef[0].offset= 1; | |
2506 | + columndef[0].length= 6; | |
2507 | + columndef[1].type= MYSQL_TYPE_STRING; | |
2508 | + columndef[1].offset= 7; | |
2509 | + columndef[1].length= 23; | |
2510 | + | |
2511 | deleted=0; | |
2512 | bzero((uchar*) flags,sizeof(flags)); | |
2513 | ||
2514 | printf("- Creating heap-file\n"); | |
2515 | - if (heap_create(filename, &hp_create_info, &tmp_share, &unused) || | |
2516 | + if (heap_create(filename, &hp_create_info, | |
2517 | + &tmp_share, &unused) || | |
2518 | !(file= heap_open(filename, 2))) | |
2519 | goto err; | |
2520 | printf("- Writing records:s\n"); | |
2521 | --- a/storage/heap/hp_test2.c | |
2522 | +++ b/storage/heap/hp_test2.c | |
2523 | @@ -18,6 +18,7 @@ | |
2524 | ||
2525 | #include "heapdef.h" /* Because of hp_find_block */ | |
2526 | #include <signal.h> | |
2527 | +#include <mysql_com.h> | |
2528 | ||
2529 | #define MAX_RECORDS 100000 | |
2530 | #define MAX_KEYS 4 | |
13ceb006 | 2531 | @@ -53,6 +54,7 @@ |
db82db79 AM |
2532 | HP_SHARE *tmp_share; |
2533 | HP_KEYDEF keyinfo[MAX_KEYS]; | |
2534 | HA_KEYSEG keyseg[MAX_KEYS*5]; | |
2535 | + HP_COLUMNDEF columndef[4]; | |
2536 | HEAP_PTR UNINIT_VAR(position); | |
2537 | HP_CREATE_INFO hp_create_info; | |
2538 | CHARSET_INFO *cs= &my_charset_latin1; | |
13ceb006 | 2539 | @@ -65,12 +67,16 @@ |
db82db79 AM |
2540 | get_options(argc,argv); |
2541 | ||
2542 | bzero(&hp_create_info, sizeof(hp_create_info)); | |
2543 | - hp_create_info.max_table_size= 1024L*1024L; | |
2544 | + hp_create_info.max_table_size= 1024L*1024L*1024L; | |
2545 | hp_create_info.keys= keys; | |
2546 | hp_create_info.keydef= keyinfo; | |
2547 | hp_create_info.reclength= reclength; | |
2548 | hp_create_info.max_records= (ulong) flag*100000L; | |
2549 | hp_create_info.min_records= (ulong) recant/2; | |
2550 | + hp_create_info.columns= 4; | |
2551 | + hp_create_info.columndef= columndef; | |
2552 | + hp_create_info.fixed_key_fieldnr= 4; | |
2553 | + hp_create_info.fixed_data_size= 39; | |
2554 | ||
2555 | write_count=update=opt_delete=0; | |
2556 | key_check=0; | |
13ceb006 | 2557 | @@ -118,11 +124,28 @@ |
db82db79 AM |
2558 | keyinfo[3].seg[0].null_pos=38; |
2559 | keyinfo[3].seg[0].charset=cs; | |
2560 | ||
2561 | + memset(columndef, 0, 4 * sizeof(HP_COLUMNDEF)); | |
2562 | + columndef[0].type= MYSQL_TYPE_STRING; | |
2563 | + columndef[0].offset= 0; | |
2564 | + columndef[0].length= 6; | |
2565 | + columndef[1].type= MYSQL_TYPE_STRING; | |
2566 | + columndef[1].offset= 7; | |
2567 | + columndef[1].length= 6; | |
2568 | + columndef[2].type= MYSQL_TYPE_STRING; | |
2569 | + columndef[2].offset= 12; | |
2570 | + columndef[2].length= 8; | |
2571 | + columndef[3].type= MYSQL_TYPE_TINY; | |
2572 | + columndef[3].offset= 37; | |
2573 | + columndef[3].length= 1; | |
2574 | + columndef[3].null_bit= 1; | |
2575 | + columndef[3].null_pos= 38; | |
db82db79 AM |
2576 | + |
2577 | bzero((char*) key1,sizeof(key1)); | |
2578 | bzero((char*) key3,sizeof(key3)); | |
2579 | ||
2580 | printf("- Creating heap-file\n"); | |
2581 | - if (heap_create(filename, &hp_create_info, &tmp_share, &unused) || | |
2582 | + if (heap_create(filename, &hp_create_info, | |
2583 | + &tmp_share, &unused) || | |
2584 | !(file= heap_open(filename, 2))) | |
2585 | goto err; | |
2586 | signal(SIGINT,endprog); | |
2587 | --- a/storage/heap/hp_write.c | |
2588 | +++ b/storage/heap/hp_write.c | |
2589 | @@ -26,7 +26,6 @@ | |
2590 | #define HIGHFIND 4 | |
2591 | #define HIGHUSED 8 | |
2592 | ||
2593 | -static uchar *next_free_record_pos(HP_SHARE *info); | |
2594 | static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block, | |
2595 | ulong records); | |
2596 | ||
2597 | @@ -35,6 +34,8 @@ | |
2598 | HP_KEYDEF *keydef, *end; | |
2599 | uchar *pos; | |
2600 | HP_SHARE *share=info->s; | |
13ceb006 | 2601 | + uint chunk_count; |
db82db79 AM |
2602 | + |
2603 | DBUG_ENTER("heap_write"); | |
2604 | #ifndef DBUG_OFF | |
2605 | if (info->mode & O_RDONLY) | |
2606 | @@ -42,7 +43,18 @@ | |
2607 | DBUG_RETURN(my_errno=EACCES); | |
2608 | } | |
2609 | #endif | |
2610 | - if (!(pos=next_free_record_pos(share))) | |
2611 | + | |
2612 | + if ((share->records >= share->max_records && share->max_records) || | |
2613 | + (share->recordspace.total_data_length + share->index_length >= | |
2614 | + share->max_table_size)) | |
2615 | + { | |
2616 | + my_errno= HA_ERR_RECORD_FILE_FULL; | |
2617 | + DBUG_RETURN(my_errno); | |
2618 | + } | |
2619 | + | |
13ceb006 | 2620 | + hp_get_encoded_data_length(share, record, &chunk_count); |
db82db79 AM |
2621 | + |
2622 | + if (!(pos= hp_allocate_chunkset(&share->recordspace, chunk_count))) | |
2623 | DBUG_RETURN(my_errno); | |
2624 | share->changed=1; | |
2625 | ||
2626 | @@ -53,8 +65,8 @@ | |
2627 | goto err; | |
2628 | } | |
2629 | ||
2630 | - memcpy(pos,record,(size_t) share->reclength); | |
2631 | - pos[share->reclength]=1; /* Mark record as not deleted */ | |
2632 | + hp_copy_record_data_to_chunkset(share, record, pos); | |
2633 | + | |
2634 | if (++share->records == share->blength) | |
2635 | share->blength+= share->blength; | |
2636 | info->current_ptr=pos; | |
2637 | @@ -88,10 +100,7 @@ | |
2638 | keydef--; | |
2639 | } | |
2640 | ||
2641 | - share->deleted++; | |
2642 | - *((uchar**) pos)=share->del_link; | |
2643 | - share->del_link=pos; | |
2644 | - pos[share->reclength]=0; /* Record deleted */ | |
2645 | + hp_free_chunks(&share->recordspace, pos); | |
2646 | ||
2647 | DBUG_RETURN(my_errno); | |
2648 | } /* heap_write */ | |
2649 | @@ -107,7 +116,8 @@ | |
2650 | uint old_allocated; | |
2651 | ||
2652 | custom_arg.keyseg= keyinfo->seg; | |
2653 | - custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos); | |
2654 | + custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos, | |
2655 | + FALSE); | |
2656 | if (keyinfo->flag & HA_NOSAME) | |
2657 | { | |
2658 | custom_arg.search_flag= SEARCH_FIND | SEARCH_UPDATE; | |
2659 | @@ -129,42 +139,6 @@ | |
2660 | return 0; | |
2661 | } | |
2662 | ||
2663 | - /* Find where to place new record */ | |
2664 | - | |
2665 | -static uchar *next_free_record_pos(HP_SHARE *info) | |
2666 | -{ | |
2667 | - int block_pos; | |
2668 | - uchar *pos; | |
2669 | - size_t length; | |
2670 | - DBUG_ENTER("next_free_record_pos"); | |
2671 | - | |
2672 | - if (info->del_link) | |
2673 | - { | |
2674 | - pos=info->del_link; | |
2675 | - info->del_link= *((uchar**) pos); | |
2676 | - info->deleted--; | |
2677 | - DBUG_PRINT("exit",("Used old position: 0x%lx",(long) pos)); | |
2678 | - DBUG_RETURN(pos); | |
2679 | - } | |
2680 | - if (!(block_pos=(info->records % info->block.records_in_block))) | |
2681 | - { | |
2682 | - if ((info->records > info->max_records && info->max_records) || | |
2683 | - (info->data_length + info->index_length >= info->max_table_size)) | |
2684 | - { | |
2685 | - my_errno=HA_ERR_RECORD_FILE_FULL; | |
2686 | - DBUG_RETURN(NULL); | |
2687 | - } | |
2688 | - if (hp_get_new_block(&info->block,&length)) | |
2689 | - DBUG_RETURN(NULL); | |
2690 | - info->data_length+=length; | |
2691 | - } | |
2692 | - DBUG_PRINT("exit",("Used new position: 0x%lx", | |
2693 | - (long) ((uchar*) info->block.level_info[0].last_blocks+ | |
2694 | - block_pos * info->block.recbuffer))); | |
2695 | - DBUG_RETURN((uchar*) info->block.level_info[0].last_blocks+ | |
2696 | - block_pos*info->block.recbuffer); | |
2697 | -} | |
2698 | - | |
2699 | ||
2700 | /* | |
2701 | Write a hash-key to the hash-index | |
2702 | --- a/storage/heap/hp_update.c | |
2703 | +++ b/storage/heap/hp_update.c | |
13ceb006 | 2704 | @@ -17,43 +17,65 @@ |
db82db79 AM |
2705 | |
2706 | #include "heapdef.h" | |
2707 | ||
2708 | -int heap_update(HP_INFO *info, const uchar *old, const uchar *heap_new) | |
2709 | +int heap_update(HP_INFO *info, const uchar *old_record, const uchar *new_record) | |
2710 | { | |
2711 | HP_KEYDEF *keydef, *end, *p_lastinx; | |
2712 | uchar *pos; | |
2713 | my_bool auto_key_changed= 0; | |
2714 | HP_SHARE *share= info->s; | |
db82db79 AM |
2715 | + uint old_chunk_count, new_chunk_count; |
2716 | + | |
2717 | DBUG_ENTER("heap_update"); | |
2718 | ||
2719 | test_active(info); | |
2720 | pos=info->current_ptr; | |
2721 | ||
2722 | - if (info->opt_flag & READ_CHECK_USED && hp_rectest(info,old)) | |
2723 | + if (info->opt_flag & READ_CHECK_USED && hp_rectest(info, old_record)) | |
2724 | DBUG_RETURN(my_errno); /* Record changed */ | |
2725 | + | |
13ceb006 AM |
2726 | + hp_get_encoded_data_length(share, old_record, &old_chunk_count); |
2727 | + hp_get_encoded_data_length(share, new_record, &new_chunk_count); | |
db82db79 AM |
2728 | + |
2729 | + if (new_chunk_count > old_chunk_count) | |
2730 | + { | |
2731 | + /* extend the old chunkset size as necessary, but do not shrink yet */ | |
2732 | + if (hp_reallocate_chunkset(&share->recordspace, new_chunk_count, pos)) | |
2733 | + { | |
2734 | + DBUG_RETURN(my_errno); /* Out of memory or table space */ | |
2735 | + } | |
2736 | + } | |
2737 | + | |
2738 | if (--(share->records) < share->blength >> 1) share->blength>>= 1; | |
2739 | share->changed=1; | |
2740 | ||
2741 | p_lastinx= share->keydef + info->lastinx; | |
2742 | for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++) | |
2743 | { | |
2744 | - if (hp_rec_key_cmp(keydef, old, heap_new, 0)) | |
2745 | + if (hp_rec_key_cmp(keydef, old_record, new_record, 0)) | |
2746 | { | |
2747 | - if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) || | |
2748 | - (*keydef->write_key)(info, keydef, heap_new, pos)) | |
2749 | + if ((*keydef->delete_key)(info, keydef, old_record, pos, | |
2750 | + keydef == p_lastinx) || | |
2751 | + (*keydef->write_key)(info, keydef, new_record, pos)) | |
2752 | goto err; | |
2753 | if (share->auto_key == (uint) (keydef - share->keydef + 1)) | |
2754 | auto_key_changed= 1; | |
2755 | } | |
2756 | } | |
2757 | ||
2758 | - memcpy(pos,heap_new,(size_t) share->reclength); | |
2759 | + hp_copy_record_data_to_chunkset(share, new_record, pos); | |
2760 | if (++(share->records) == share->blength) share->blength+= share->blength; | |
2761 | ||
2762 | + if (new_chunk_count < old_chunk_count) | |
2763 | + { | |
2764 | + /* Shrink the chunkset to its new size */ | |
2765 | + hp_reallocate_chunkset(&share->recordspace, new_chunk_count, pos); | |
2766 | + } | |
2767 | + | |
2768 | #if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG) | |
2769 | DBUG_EXECUTE("check_heap",heap_check_heap(info, 0);); | |
2770 | #endif | |
2771 | if (auto_key_changed) | |
2772 | - heap_update_auto_increment(info, heap_new); | |
2773 | + heap_update_auto_increment(info, new_record); | |
2774 | DBUG_RETURN(0); | |
2775 | ||
2776 | err: | |
13ceb006 | 2777 | @@ -63,7 +85,7 @@ |
db82db79 AM |
2778 | if (keydef->algorithm == HA_KEY_ALG_BTREE) |
2779 | { | |
2780 | /* we don't need to delete non-inserted key from rb-tree */ | |
2781 | - if ((*keydef->write_key)(info, keydef, old, pos)) | |
2782 | + if ((*keydef->write_key)(info, keydef, old_record, pos)) | |
2783 | { | |
2784 | if (++(share->records) == share->blength) | |
2785 | share->blength+= share->blength; | |
13ceb006 | 2786 | @@ -73,10 +95,10 @@ |
db82db79 AM |
2787 | } |
2788 | while (keydef >= share->keydef) | |
2789 | { | |
2790 | - if (hp_rec_key_cmp(keydef, old, heap_new, 0)) | |
2791 | + if (hp_rec_key_cmp(keydef, old_record, new_record, 0)) | |
2792 | { | |
2793 | - if ((*keydef->delete_key)(info, keydef, heap_new, pos, 0) || | |
2794 | - (*keydef->write_key)(info, keydef, old, pos)) | |
2795 | + if ((*keydef->delete_key)(info, keydef, new_record, pos, 0) || | |
2796 | + (*keydef->write_key)(info, keydef, old_record, pos)) | |
2797 | break; | |
2798 | } | |
2799 | keydef--; | |
13ceb006 | 2800 | @@ -84,5 +106,12 @@ |
db82db79 AM |
2801 | } |
2802 | if (++(share->records) == share->blength) | |
2803 | share->blength+= share->blength; | |
2804 | + | |
2805 | + if (new_chunk_count > old_chunk_count) | |
2806 | + { | |
2807 | + /* Shrink the chunkset to its original size */ | |
2808 | + hp_reallocate_chunkset(&share->recordspace, old_chunk_count, pos); | |
2809 | + } | |
2810 | + | |
2811 | DBUG_RETURN(my_errno); | |
2812 | } /* heap_update */ | |
48b678b4 AM |
2813 | --- /dev/null |
2814 | +++ b/mysql-test/r/percona_heap_blob.result | |
0ccdf405 | 2815 | @@ -0,0 +1,956 @@ |
48b678b4 AM |
2816 | +SET @old_default_storage_engine=@@default_storage_engine; |
2817 | +SET default_storage_engine=MEMORY; | |
2818 | +drop table if exists t1,t2,t3,t4,t5,t6,t7; | |
2819 | +CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000)); | |
2820 | +show columns from t1; | |
2821 | +Field Type Null Key Default Extra | |
2822 | +a blob YES NULL | |
2823 | +b text YES NULL | |
2824 | +c tinyblob YES NULL | |
2825 | +d mediumtext YES NULL | |
2826 | +e longtext YES NULL | |
2827 | +CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000)); | |
2828 | +Warnings: | |
2829 | +Note 1246 Converting column 'b' from VARBINARY to BLOB | |
2830 | +Note 1246 Converting column 'c' from VARCHAR to TEXT | |
2831 | +CREATE TABLE t4 (c varchar(65530) character set utf8 not null); | |
2832 | +Warnings: | |
2833 | +Note 1246 Converting column 'c' from VARCHAR to TEXT | |
2834 | +show columns from t2; | |
2835 | +Field Type Null Key Default Extra | |
2836 | +a char(255) YES NULL | |
2837 | +b mediumblob YES NULL | |
2838 | +c longtext YES NULL | |
2839 | +create table t3 (a long, b long byte); | |
2840 | +show create TABLE t3; | |
2841 | +Table Create Table | |
2842 | +t3 CREATE TABLE `t3` ( | |
2843 | + `a` mediumtext, | |
2844 | + `b` mediumblob | |
2845 | +) ENGINE=MEMORY DEFAULT CHARSET=latin1 | |
2846 | +show create TABLE t4; | |
2847 | +Table Create Table | |
2848 | +t4 CREATE TABLE `t4` ( | |
2849 | + `c` mediumtext CHARACTER SET utf8 NOT NULL | |
2850 | +) ENGINE=MEMORY DEFAULT CHARSET=latin1 | |
2851 | +drop table t1,t2,t3,t4; | |
2852 | +CREATE TABLE t1 (a char(257) default "hello"); | |
2853 | +ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead | |
2854 | +CREATE TABLE t2 (a char(256)); | |
2855 | +ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead | |
2856 | +CREATE TABLE t1 (a varchar(70000) default "hello"); | |
2857 | +ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB or TEXT instead | |
2858 | +CREATE TABLE t2 (a blob default "hello"); | |
2859 | +ERROR 42000: BLOB/TEXT column 'a' can't have a default value | |
2860 | +drop table if exists t1,t2; | |
2861 | +create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr)); | |
2862 | +insert into t1 values (null,"a","A"); | |
2863 | +insert into t1 values (null,"bbb","BBB"); | |
2864 | +insert into t1 values (null,"ccc","CCC"); | |
2865 | +select last_insert_id(); | |
2866 | +last_insert_id() | |
2867 | +3 | |
2868 | +select * from t1,t1 as t2; | |
2869 | +nr b str nr b str | |
2870 | +1 a A 1 a A | |
2871 | +2 bbb BBB 1 a A | |
2872 | +3 ccc CCC 1 a A | |
2873 | +1 a A 2 bbb BBB | |
2874 | +2 bbb BBB 2 bbb BBB | |
2875 | +3 ccc CCC 2 bbb BBB | |
2876 | +1 a A 3 ccc CCC | |
2877 | +2 bbb BBB 3 ccc CCC | |
2878 | +3 ccc CCC 3 ccc CCC | |
2879 | +drop table t1; | |
2880 | +create table t1 (a text); | |
2881 | +insert into t1 values ('where'); | |
2882 | +update t1 set a='Where'; | |
2883 | +select * from t1; | |
2884 | +a | |
2885 | +Where | |
2886 | +drop table t1; | |
0ccdf405 | 2887 | +create table t1 (t text,c char(10),b blob, d varbinary(10)) collate latin1_general_cs; |
48b678b4 AM |
2888 | +insert into t1 values (NULL,NULL,NULL,NULL); |
2889 | +insert into t1 values ("","","",""); | |
2890 | +insert into t1 values ("hello","hello","hello","hello"); | |
2891 | +insert into t1 values ("HELLO","HELLO","HELLO","HELLO"); | |
2892 | +insert into t1 values ("HELLO MY","HELLO MY","HELLO MY","HELLO MY"); | |
2893 | +insert into t1 values ("a","a","a","a"); | |
2894 | +insert into t1 values (1,1,1,1); | |
2895 | +insert into t1 values (NULL,NULL,NULL,NULL); | |
2896 | +update t1 set c="",b=null where c="1"; | |
2897 | +lock tables t1 READ; | |
2898 | +show full fields from t1; | |
2899 | +Field Type Collation Null Key Default Extra Privileges Comment | |
0ccdf405 AM |
2900 | +t text latin1_general_cs YES NULL # |
2901 | +c char(10) latin1_general_cs YES NULL # | |
48b678b4 AM |
2902 | +b blob NULL YES NULL # |
2903 | +d varbinary(10) NULL YES NULL # | |
2904 | +lock tables t1 WRITE; | |
2905 | +show full fields from t1; | |
2906 | +Field Type Collation Null Key Default Extra Privileges Comment | |
0ccdf405 AM |
2907 | +t text latin1_general_cs YES NULL # |
2908 | +c char(10) latin1_general_cs YES NULL # | |
48b678b4 AM |
2909 | +b blob NULL YES NULL # |
2910 | +d varbinary(10) NULL YES NULL # | |
2911 | +unlock tables; | |
2912 | +select t from t1 where t like "hello"; | |
2913 | +t | |
2914 | +hello | |
48b678b4 AM |
2915 | +select c from t1 where c like "hello"; |
2916 | +c | |
2917 | +hello | |
48b678b4 AM |
2918 | +select b from t1 where b like "hello"; |
2919 | +b | |
2920 | +hello | |
2921 | +select d from t1 where d like "hello"; | |
2922 | +d | |
2923 | +hello | |
2924 | +select c from t1 having c like "hello"; | |
2925 | +c | |
2926 | +hello | |
48b678b4 AM |
2927 | +select d from t1 having d like "hello"; |
2928 | +d | |
2929 | +hello | |
2930 | +select t from t1 where t like "%HELLO%"; | |
2931 | +t | |
48b678b4 AM |
2932 | +HELLO |
2933 | +HELLO MY | |
2934 | +select c from t1 where c like "%HELLO%"; | |
2935 | +c | |
48b678b4 AM |
2936 | +HELLO |
2937 | +HELLO MY | |
2938 | +select b from t1 where b like "%HELLO%"; | |
2939 | +b | |
2940 | +HELLO | |
2941 | +HELLO MY | |
2942 | +select d from t1 where d like "%HELLO%"; | |
2943 | +d | |
2944 | +HELLO | |
2945 | +HELLO MY | |
2946 | +select c from t1 having c like "%HELLO%"; | |
2947 | +c | |
48b678b4 AM |
2948 | +HELLO |
2949 | +HELLO MY | |
2950 | +select d from t1 having d like "%HELLO%"; | |
2951 | +d | |
2952 | +HELLO | |
2953 | +HELLO MY | |
2954 | +select d from t1 having d like "%HE%LLO%"; | |
2955 | +d | |
2956 | +HELLO | |
2957 | +HELLO MY | |
2958 | +select t from t1 order by t; | |
2959 | +t | |
2960 | +NULL | |
2961 | +NULL | |
2962 | + | |
2963 | +1 | |
2964 | +a | |
48b678b4 AM |
2965 | +HELLO |
2966 | +HELLO MY | |
0ccdf405 | 2967 | +hello |
48b678b4 AM |
2968 | +select c from t1 order by c; |
2969 | +c | |
2970 | +NULL | |
2971 | +NULL | |
2972 | + | |
2973 | + | |
2974 | +a | |
48b678b4 AM |
2975 | +HELLO |
2976 | +HELLO MY | |
0ccdf405 | 2977 | +hello |
48b678b4 AM |
2978 | +select b from t1 order by b; |
2979 | +b | |
2980 | +NULL | |
2981 | +NULL | |
2982 | +NULL | |
2983 | + | |
2984 | +HELLO | |
2985 | +HELLO MY | |
2986 | +a | |
2987 | +hello | |
2988 | +select d from t1 order by d; | |
2989 | +d | |
2990 | +NULL | |
2991 | +NULL | |
2992 | + | |
2993 | +1 | |
2994 | +HELLO | |
2995 | +HELLO MY | |
2996 | +a | |
2997 | +hello | |
2998 | +select distinct t from t1; | |
2999 | +t | |
3000 | +NULL | |
3001 | + | |
3002 | +hello | |
0ccdf405 | 3003 | +HELLO |
48b678b4 AM |
3004 | +HELLO MY |
3005 | +a | |
3006 | +1 | |
3007 | +select distinct b from t1; | |
3008 | +b | |
3009 | +NULL | |
3010 | + | |
3011 | +hello | |
3012 | +HELLO | |
3013 | +HELLO MY | |
3014 | +a | |
3015 | +select distinct t from t1 order by t; | |
3016 | +t | |
3017 | +NULL | |
3018 | + | |
3019 | +1 | |
3020 | +a | |
0ccdf405 | 3021 | +HELLO |
48b678b4 | 3022 | +HELLO MY |
0ccdf405 | 3023 | +hello |
48b678b4 AM |
3024 | +select distinct b from t1 order by b; |
3025 | +b | |
3026 | +NULL | |
3027 | + | |
3028 | +HELLO | |
3029 | +HELLO MY | |
3030 | +a | |
3031 | +hello | |
3032 | +select t from t1 group by t; | |
3033 | +t | |
3034 | +NULL | |
3035 | + | |
3036 | +1 | |
3037 | +a | |
0ccdf405 | 3038 | +HELLO |
48b678b4 | 3039 | +HELLO MY |
0ccdf405 | 3040 | +hello |
48b678b4 AM |
3041 | +select b from t1 group by b; |
3042 | +b | |
3043 | +NULL | |
3044 | + | |
3045 | +HELLO | |
3046 | +HELLO MY | |
3047 | +a | |
3048 | +hello | |
3049 | +set option sql_big_tables=1; | |
3050 | +select distinct t from t1; | |
3051 | +t | |
3052 | +NULL | |
3053 | + | |
3054 | +hello | |
0ccdf405 | 3055 | +HELLO |
48b678b4 AM |
3056 | +HELLO MY |
3057 | +a | |
3058 | +1 | |
3059 | +select distinct b from t1; | |
3060 | +b | |
3061 | +NULL | |
3062 | + | |
3063 | +hello | |
3064 | +HELLO | |
3065 | +HELLO MY | |
3066 | +a | |
3067 | +select distinct t from t1 order by t; | |
3068 | +t | |
3069 | +NULL | |
3070 | + | |
3071 | +1 | |
3072 | +a | |
0ccdf405 | 3073 | +HELLO |
48b678b4 | 3074 | +HELLO MY |
0ccdf405 | 3075 | +hello |
48b678b4 AM |
3076 | +select distinct b from t1 order by b; |
3077 | +b | |
3078 | +NULL | |
3079 | + | |
3080 | +HELLO | |
3081 | +HELLO MY | |
3082 | +a | |
3083 | +hello | |
3084 | +select distinct c from t1; | |
3085 | +c | |
3086 | +NULL | |
3087 | + | |
3088 | +hello | |
0ccdf405 | 3089 | +HELLO |
48b678b4 AM |
3090 | +HELLO MY |
3091 | +a | |
3092 | +select distinct d from t1; | |
3093 | +d | |
3094 | +NULL | |
3095 | + | |
3096 | +hello | |
3097 | +HELLO | |
3098 | +HELLO MY | |
3099 | +a | |
3100 | +1 | |
3101 | +select distinct c from t1 order by c; | |
3102 | +c | |
3103 | +NULL | |
3104 | + | |
3105 | +a | |
0ccdf405 | 3106 | +HELLO |
48b678b4 | 3107 | +HELLO MY |
0ccdf405 | 3108 | +hello |
48b678b4 AM |
3109 | +select distinct d from t1 order by d; |
3110 | +d | |
3111 | +NULL | |
3112 | + | |
3113 | +1 | |
3114 | +HELLO | |
3115 | +HELLO MY | |
3116 | +a | |
3117 | +hello | |
3118 | +select c from t1 group by c; | |
3119 | +c | |
3120 | +NULL | |
3121 | + | |
3122 | +a | |
0ccdf405 | 3123 | +HELLO |
48b678b4 | 3124 | +HELLO MY |
0ccdf405 | 3125 | +hello |
48b678b4 AM |
3126 | +select d from t1 group by d; |
3127 | +d | |
3128 | +NULL | |
3129 | + | |
3130 | +1 | |
3131 | +HELLO | |
3132 | +HELLO MY | |
3133 | +a | |
3134 | +hello | |
3135 | +set option sql_big_tables=0; | |
3136 | +select distinct * from t1; | |
3137 | +t c b d | |
3138 | +NULL NULL NULL NULL | |
3139 | + | |
3140 | +hello hello hello hello | |
3141 | +HELLO HELLO HELLO HELLO | |
3142 | +HELLO MY HELLO MY HELLO MY HELLO MY | |
3143 | +a a a a | |
3144 | +1 NULL 1 | |
3145 | +select t,count(*) from t1 group by t; | |
3146 | +t count(*) | |
3147 | +NULL 2 | |
3148 | + 1 | |
3149 | +1 1 | |
3150 | +a 1 | |
0ccdf405 | 3151 | +HELLO 1 |
48b678b4 | 3152 | +HELLO MY 1 |
0ccdf405 | 3153 | +hello 1 |
48b678b4 AM |
3154 | +select b,count(*) from t1 group by b; |
3155 | +b count(*) | |
3156 | +NULL 3 | |
3157 | + 1 | |
3158 | +HELLO 1 | |
3159 | +HELLO MY 1 | |
3160 | +a 1 | |
3161 | +hello 1 | |
3162 | +select c,count(*) from t1 group by c; | |
3163 | +c count(*) | |
3164 | +NULL 2 | |
3165 | + 2 | |
3166 | +a 1 | |
0ccdf405 | 3167 | +HELLO 1 |
48b678b4 | 3168 | +HELLO MY 1 |
0ccdf405 | 3169 | +hello 1 |
48b678b4 AM |
3170 | +select d,count(*) from t1 group by d; |
3171 | +d count(*) | |
3172 | +NULL 2 | |
3173 | + 1 | |
3174 | +1 1 | |
3175 | +HELLO 1 | |
3176 | +HELLO MY 1 | |
3177 | +a 1 | |
3178 | +hello 1 | |
3179 | +drop table t1; | |
3180 | +CREATE TABLE t1 ( | |
3181 | +t1_id bigint(21) NOT NULL auto_increment, | |
3182 | +_field_72 varchar(128) DEFAULT '' NOT NULL, | |
3183 | +_field_95 varchar(32), | |
3184 | +_field_115 tinyint(4) DEFAULT '0' NOT NULL, | |
3185 | +_field_122 tinyint(4) DEFAULT '0' NOT NULL, | |
3186 | +_field_126 tinyint(4), | |
3187 | +_field_134 tinyint(4), | |
3188 | +PRIMARY KEY (t1_id), | |
3189 | +UNIQUE _field_72 (_field_72), | |
3190 | +KEY _field_115 (_field_115), | |
3191 | +KEY _field_122 (_field_122) | |
3192 | +); | |
3193 | +INSERT INTO t1 VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',0,1,NULL,NULL); | |
3194 | +INSERT INTO t1 VALUES (2,'hroberts','7415275a8c95952901e42b13a6b78566',0,1,NULL,NULL); | |
3195 | +INSERT INTO t1 VALUES (3,'guest','d41d8cd98f00b204e9800998ecf8427e',1,0,NULL,NULL); | |
3196 | +CREATE TABLE t2 ( | |
3197 | +seq_0_id bigint(21) DEFAULT '0' NOT NULL, | |
3198 | +seq_1_id bigint(21) DEFAULT '0' NOT NULL, | |
3199 | +PRIMARY KEY (seq_0_id,seq_1_id) | |
3200 | +); | |
3201 | +INSERT INTO t2 VALUES (1,1); | |
3202 | +INSERT INTO t2 VALUES (2,1); | |
3203 | +INSERT INTO t2 VALUES (2,2); | |
3204 | +CREATE TABLE t3 ( | |
3205 | +t3_id bigint(21) NOT NULL auto_increment, | |
3206 | +_field_131 varchar(128), | |
3207 | +_field_133 tinyint(4) DEFAULT '0' NOT NULL, | |
3208 | +_field_135 datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, | |
3209 | +_field_137 tinyint(4), | |
3210 | +_field_139 datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, | |
3211 | +_field_140 blob, | |
3212 | +_field_142 tinyint(4) DEFAULT '0' NOT NULL, | |
3213 | +_field_145 tinyint(4) DEFAULT '0' NOT NULL, | |
3214 | +_field_148 tinyint(4) DEFAULT '0' NOT NULL, | |
3215 | +PRIMARY KEY (t3_id), | |
3216 | +KEY _field_133 (_field_133), | |
3217 | +KEY _field_135 (_field_135), | |
3218 | +KEY _field_139 (_field_139), | |
3219 | +KEY _field_142 (_field_142), | |
3220 | +KEY _field_145 (_field_145), | |
3221 | +KEY _field_148 (_field_148) | |
3222 | +); | |
3223 | +INSERT INTO t3 VALUES (1,'test job 1',0,'0000-00-00 00:00:00',0,'1999-02-25 22:43:32','test\r\njob\r\n1',0,0,0); | |
3224 | +INSERT INTO t3 VALUES (2,'test job 2',0,'0000-00-00 00:00:00',0,'1999-02-26 21:08:04','',0,0,0); | |
3225 | +CREATE TABLE t4 ( | |
3226 | +seq_0_id bigint(21) DEFAULT '0' NOT NULL, | |
3227 | +seq_1_id bigint(21) DEFAULT '0' NOT NULL, | |
3228 | +PRIMARY KEY (seq_0_id,seq_1_id) | |
3229 | +); | |
3230 | +INSERT INTO t4 VALUES (1,1); | |
3231 | +INSERT INTO t4 VALUES (2,1); | |
3232 | +CREATE TABLE t5 ( | |
3233 | +t5_id bigint(21) NOT NULL auto_increment, | |
3234 | +_field_149 tinyint(4), | |
3235 | +_field_156 varchar(128) DEFAULT '' NOT NULL, | |
3236 | +_field_157 varchar(128) DEFAULT '' NOT NULL, | |
3237 | +_field_158 varchar(128) DEFAULT '' NOT NULL, | |
3238 | +_field_159 varchar(128) DEFAULT '' NOT NULL, | |
3239 | +_field_160 varchar(128) DEFAULT '' NOT NULL, | |
3240 | +_field_161 varchar(128) DEFAULT '' NOT NULL, | |
3241 | +PRIMARY KEY (t5_id), | |
3242 | +KEY _field_156 (_field_156), | |
3243 | +KEY _field_157 (_field_157), | |
3244 | +KEY _field_158 (_field_158), | |
3245 | +KEY _field_159 (_field_159), | |
3246 | +KEY _field_160 (_field_160), | |
3247 | +KEY _field_161 (_field_161) | |
3248 | +); | |
3249 | +INSERT INTO t5 VALUES (1,0,'tomato','','','','',''); | |
3250 | +INSERT INTO t5 VALUES (2,0,'cilantro','','','','',''); | |
3251 | +CREATE TABLE t6 ( | |
3252 | +seq_0_id bigint(21) DEFAULT '0' NOT NULL, | |
3253 | +seq_1_id bigint(21) DEFAULT '0' NOT NULL, | |
3254 | +PRIMARY KEY (seq_0_id,seq_1_id) | |
3255 | +); | |
3256 | +INSERT INTO t6 VALUES (1,1); | |
3257 | +INSERT INTO t6 VALUES (1,2); | |
3258 | +INSERT INTO t6 VALUES (2,2); | |
3259 | +CREATE TABLE t7 ( | |
3260 | +t7_id bigint(21) NOT NULL auto_increment, | |
3261 | +_field_143 tinyint(4), | |
3262 | +_field_165 varchar(32), | |
3263 | +_field_166 smallint(6) DEFAULT '0' NOT NULL, | |
3264 | +PRIMARY KEY (t7_id), | |
3265 | +KEY _field_166 (_field_166) | |
3266 | +); | |
3267 | +INSERT INTO t7 VALUES (1,0,'High',1); | |
3268 | +INSERT INTO t7 VALUES (2,0,'Medium',2); | |
3269 | +INSERT INTO t7 VALUES (3,0,'Low',3); | |
3270 | +select replace(t3._field_140, "\r","^M"),t3_id,min(t3._field_131), min(t3._field_135), min(t3._field_139), min(t3._field_137), min(link_alias_142._field_165), min(link_alias_133._field_72), min(t3._field_145), min(link_alias_148._field_156), replace(min(t3._field_140), "\r","^M"),t3.t3_id from t3 left join t4 on t4.seq_0_id = t3.t3_id left join t7 link_alias_142 on t4.seq_1_id = link_alias_142.t7_id left join t6 on t6.seq_0_id = t3.t3_id left join t1 link_alias_133 on t6.seq_1_id = link_alias_133.t1_id left join t2 on t2.seq_0_id = t3.t3_id left join t5 link_alias_148 on t2.seq_1_id = link_alias_148.t5_id where t3.t3_id in (1) group by t3.t3_id order by link_alias_142._field_166, _field_139, link_alias_133._field_72, _field_135, link_alias_148._field_156; | |
3271 | +replace(t3._field_140, "\r","^M") t3_id min(t3._field_131) min(t3._field_135) min(t3._field_139) min(t3._field_137) min(link_alias_142._field_165) min(link_alias_133._field_72) min(t3._field_145) min(link_alias_148._field_156) replace(min(t3._field_140), "\r","^M") t3_id | |
3272 | +test^M | |
3273 | +job^M | |
3274 | +1 1 test job 1 0000-00-00 00:00:00 1999-02-25 22:43:32 0 High admin 0 tomato test^M | |
3275 | +job^M | |
3276 | +1 1 | |
3277 | +drop table t1,t2,t3,t4,t5,t6,t7; | |
3278 | +create table t1 (a blob); | |
3279 | +insert into t1 values ("empty"),(""); | |
3280 | +select a,reverse(a) from t1; | |
3281 | +a reverse(a) | |
3282 | +empty ytpme | |
3283 | + | |
3284 | +drop table t1; | |
3285 | +create table t1 (id integer auto_increment unique,imagem LONGBLOB not null default ''); | |
3286 | +Warnings: | |
3287 | +Warning 1101 BLOB/TEXT column 'imagem' can't have a default value | |
3288 | +insert into t1 (id) values (1); | |
3289 | +select | |
3290 | +charset(load_file('../../std_data/words.dat')), | |
3291 | +collation(load_file('../../std_data/words.dat')), | |
3292 | +coercibility(load_file('../../std_data/words.dat')); | |
3293 | +charset(load_file('../../std_data/words.dat')) collation(load_file('../../std_data/words.dat')) coercibility(load_file('../../std_data/words.dat')) | |
3294 | +binary binary 4 | |
3295 | +explain extended select | |
3296 | +charset(load_file('MYSQLTEST_VARDIR/std_data/words.dat')), | |
3297 | +collation(load_file('MYSQLTEST_VARDIR/std_data/words.dat')), | |
3298 | +coercibility(load_file('MYSQLTEST_VARDIR/std_data/words.dat')); | |
3299 | +id select_type table type possible_keys key key_len ref rows filtered Extra | |
3300 | +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used | |
3301 | +Warnings: | |
3302 | +Note 1003 select charset(load_file('MYSQLTEST_VARDIR/std_data/words.dat')) AS `charset(load_file('MYSQLTEST_VARDIR/std_data/words.dat'))`,collation(load_file('MYSQLTEST_VARDIR/std_data/words.dat')) AS `collation(load_file('MYSQLTEST_VARDIR/std_data/words.dat'))`,coercibility(load_file('MYSQLTEST_VARDIR/std_data/words.dat')) AS `coercibility(load_file('MYSQLTEST_VARDIR/std_data/words.dat'))` | |
3303 | +update t1 set imagem=load_file('MYSQLTEST_VARDIR/std_data/words.dat') where id=1; | |
3304 | +select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1; | |
3305 | +if(imagem is null, "ERROR", "OK") length(imagem) | |
3306 | +OK 581 | |
3307 | +drop table t1; | |
3308 | +create table t1 select load_file('MYSQLTEST_VARDIR/std_data/words.dat') l; | |
3309 | +show full fields from t1; | |
3310 | +Field Type Collation Null Key Default Extra Privileges Comment | |
3311 | +l longblob NULL YES NULL # | |
3312 | +drop table t1; | |
3313 | +create table t1 (id integer primary key auto_increment, txt text not null); | |
3314 | +insert into t1 (txt) values ('Chevy '); | |
3315 | +select * from t1 where txt='Chevy'; | |
3316 | +id txt | |
3317 | +1 Chevy | |
3318 | +select * from t1 where txt='Chevy '; | |
3319 | +id txt | |
3320 | +1 Chevy | |
3321 | +select * from t1 where txt='Chevy ' or txt='Chevy'; | |
3322 | +id txt | |
3323 | +1 Chevy | |
3324 | +select * from t1 where txt='Chevy' or txt='Chevy '; | |
3325 | +id txt | |
3326 | +1 Chevy | |
3327 | +select * from t1 where id='1' or id='2'; | |
3328 | +id txt | |
3329 | +1 Chevy | |
3330 | +insert into t1 (txt) values('Ford'); | |
3331 | +select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford'; | |
3332 | +id txt | |
3333 | +1 Chevy | |
3334 | +2 Ford | |
3335 | +select * from t1 where txt='Chevy' or txt='Chevy '; | |
3336 | +id txt | |
3337 | +1 Chevy | |
3338 | +select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy'; | |
3339 | +id txt | |
3340 | +1 Chevy | |
3341 | +select * from t1 where txt in ('Chevy ','Chevy'); | |
3342 | +id txt | |
3343 | +1 Chevy | |
3344 | +select * from t1 where txt in ('Chevy'); | |
3345 | +id txt | |
3346 | +1 Chevy | |
3347 | +select * from t1 where txt between 'Chevy' and 'Chevy'; | |
3348 | +id txt | |
3349 | +1 Chevy | |
3350 | +select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy '; | |
3351 | +id txt | |
3352 | +1 Chevy | |
3353 | +select * from t1 where txt between 'Chevy' and 'Chevy '; | |
3354 | +id txt | |
3355 | +1 Chevy | |
3356 | +select * from t1 where txt < 'Chevy '; | |
3357 | +id txt | |
3358 | +select * from t1 where txt <= 'Chevy'; | |
3359 | +id txt | |
3360 | +1 Chevy | |
3361 | +select * from t1 where txt > 'Chevy'; | |
3362 | +id txt | |
3363 | +2 Ford | |
3364 | +select * from t1 where txt >= 'Chevy'; | |
3365 | +id txt | |
3366 | +1 Chevy | |
3367 | +2 Ford | |
3368 | +drop table t1; | |
3369 | +create table t1 (id integer primary key auto_increment, txt text); | |
3370 | +insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL); | |
3371 | +select * from t1 where txt='Chevy' or txt is NULL; | |
3372 | +id txt | |
3373 | +1 Chevy | |
3374 | +2 Chevy | |
3375 | +3 NULL | |
3376 | +explain select * from t1 where txt='Chevy' or txt is NULL; | |
3377 | +id select_type table type possible_keys key key_len ref rows Extra | |
3378 | +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where | |
3379 | +select * from t1 where txt='Chevy '; | |
3380 | +id txt | |
3381 | +1 Chevy | |
3382 | +2 Chevy | |
3383 | +select * from t1 where txt='Chevy ' or txt='Chevy'; | |
3384 | +id txt | |
3385 | +1 Chevy | |
3386 | +2 Chevy | |
3387 | +select * from t1 where txt='Chevy' or txt='Chevy '; | |
3388 | +id txt | |
3389 | +1 Chevy | |
3390 | +2 Chevy | |
3391 | +select * from t1 where id='1' or id='2'; | |
3392 | +id txt | |
3393 | +1 Chevy | |
3394 | +2 Chevy | |
3395 | +insert into t1 (txt) values('Ford'); | |
3396 | +select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford'; | |
3397 | +id txt | |
3398 | +1 Chevy | |
3399 | +2 Chevy | |
3400 | +4 Ford | |
3401 | +select * from t1 where txt='Chevy' or txt='Chevy '; | |
3402 | +id txt | |
3403 | +1 Chevy | |
3404 | +2 Chevy | |
3405 | +select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy'; | |
3406 | +id txt | |
3407 | +1 Chevy | |
3408 | +2 Chevy | |
3409 | +select * from t1 where txt in ('Chevy ','Chevy'); | |
3410 | +id txt | |
3411 | +1 Chevy | |
3412 | +2 Chevy | |
3413 | +select * from t1 where txt in ('Chevy'); | |
3414 | +id txt | |
3415 | +1 Chevy | |
3416 | +2 Chevy | |
3417 | +select * from t1 where txt between 'Chevy' and 'Chevy'; | |
3418 | +id txt | |
3419 | +1 Chevy | |
3420 | +2 Chevy | |
3421 | +select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy '; | |
3422 | +id txt | |
3423 | +1 Chevy | |
3424 | +2 Chevy | |
3425 | +select * from t1 where txt between 'Chevy' and 'Chevy '; | |
3426 | +id txt | |
3427 | +1 Chevy | |
3428 | +2 Chevy | |
3429 | +select * from t1 where txt < 'Chevy '; | |
3430 | +id txt | |
3431 | +select * from t1 where txt < 'Chevy ' or txt is NULL; | |
3432 | +id txt | |
3433 | +3 NULL | |
3434 | +select * from t1 where txt <= 'Chevy'; | |
3435 | +id txt | |
3436 | +1 Chevy | |
3437 | +2 Chevy | |
3438 | +select * from t1 where txt > 'Chevy'; | |
3439 | +id txt | |
3440 | +4 Ford | |
3441 | +select * from t1 where txt >= 'Chevy'; | |
3442 | +id txt | |
3443 | +1 Chevy | |
3444 | +2 Chevy | |
3445 | +4 Ford | |
3446 | +alter table t1 modify column txt blob; | |
3447 | +explain select * from t1 where txt='Chevy' or txt is NULL; | |
3448 | +id select_type table type possible_keys key key_len ref rows Extra | |
3449 | +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where | |
3450 | +select * from t1 where txt='Chevy' or txt is NULL; | |
3451 | +id txt | |
3452 | +1 Chevy | |
3453 | +3 NULL | |
3454 | +explain select * from t1 where txt='Chevy' or txt is NULL order by txt; | |
3455 | +id select_type table type possible_keys key key_len ref rows Extra | |
3456 | +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; Using filesort | |
3457 | +select * from t1 where txt='Chevy' or txt is NULL order by txt; | |
3458 | +id txt | |
3459 | +3 NULL | |
3460 | +1 Chevy | |
3461 | +drop table t1; | |
3462 | +CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, d varchar(1) NOT NULL DEFAULT ' ', PRIMARY KEY (i)); | |
3463 | +INSERT t1 (i, c) VALUES (1,''),(2,''),(3,'asdfh'),(4,''); | |
3464 | +select max(i) from t1 where c = ''; | |
3465 | +max(i) | |
3466 | +4 | |
3467 | +drop table t1; | |
3468 | +CREATE table t1 (a blob); | |
3469 | +insert into t1 values ('b'),('a\0'),('a'),('a '),('aa'),(NULL); | |
3470 | +select hex(a) from t1 order by a; | |
3471 | +hex(a) | |
3472 | +NULL | |
3473 | +61 | |
3474 | +6100 | |
3475 | +6120 | |
3476 | +6161 | |
3477 | +62 | |
3478 | +select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0'); | |
3479 | +b | |
3480 | +NULL | |
3481 | +6100 | |
3482 | +610000 | |
3483 | +612000 | |
3484 | +616100 | |
3485 | +6200 | |
3486 | +alter table t1 modify a varbinary(5); | |
3487 | +select hex(a) from t1 order by a; | |
3488 | +hex(a) | |
3489 | +NULL | |
3490 | +61 | |
3491 | +6100 | |
3492 | +6120 | |
3493 | +6161 | |
3494 | +62 | |
3495 | +select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0'); | |
3496 | +b | |
3497 | +NULL | |
3498 | +6100 | |
3499 | +610000 | |
3500 | +612000 | |
3501 | +616100 | |
3502 | +6200 | |
3503 | +alter table t1 modify a char(5); | |
3504 | +select hex(a) from t1 order by a; | |
3505 | +hex(a) | |
3506 | +NULL | |
3507 | +6100 | |
3508 | +61 | |
3509 | +61 | |
3510 | +6161 | |
3511 | +62 | |
3512 | +select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0'); | |
3513 | +b | |
3514 | +NULL | |
3515 | +610000 | |
3516 | +6100 | |
3517 | +6100 | |
3518 | +616100 | |
3519 | +6200 | |
3520 | +alter table t1 modify a binary(5); | |
3521 | +select hex(a) from t1 order by a; | |
3522 | +hex(a) | |
3523 | +NULL | |
3524 | +6100000000 | |
3525 | +6100000000 | |
3526 | +6100000000 | |
3527 | +6161000000 | |
3528 | +6200000000 | |
3529 | +select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0'); | |
3530 | +b | |
3531 | +NULL | |
3532 | +610000000000 | |
3533 | +610000000000 | |
3534 | +610000000000 | |
3535 | +616100000000 | |
3536 | +620000000000 | |
3537 | +drop table t1; | |
3538 | +create table t1 (a text default ''); | |
3539 | +Warnings: | |
3540 | +Warning 1101 BLOB/TEXT column 'a' can't have a default value | |
3541 | +show create table t1; | |
3542 | +Table Create Table | |
3543 | +t1 CREATE TABLE `t1` ( | |
3544 | + `a` text | |
3545 | +) ENGINE=MEMORY DEFAULT CHARSET=latin1 | |
3546 | +insert into t1 values (default); | |
3547 | +select * from t1; | |
3548 | +a | |
3549 | +NULL | |
3550 | +drop table t1; | |
3551 | +set @@sql_mode='TRADITIONAL'; | |
3552 | +create table t1 (a text default ''); | |
3553 | +ERROR 42000: BLOB/TEXT column 'a' can't have a default value | |
3554 | +set @@sql_mode=''; | |
3555 | +CREATE TABLE t (c TEXT CHARSET ASCII); | |
3556 | +INSERT INTO t (c) VALUES (REPEAT('1',65537)); | |
3557 | +Warnings: | |
3558 | +Warning 1265 Data truncated for column 'c' at row 1 | |
3559 | +INSERT INTO t (c) VALUES (REPEAT('2',65536)); | |
3560 | +Warnings: | |
3561 | +Warning 1265 Data truncated for column 'c' at row 1 | |
3562 | +INSERT INTO t (c) VALUES (REPEAT('3',65535)); | |
3563 | +SELECT LENGTH(c), CHAR_LENGTH(c) FROM t; | |
3564 | +LENGTH(c) CHAR_LENGTH(c) | |
3565 | +65535 65535 | |
3566 | +65535 65535 | |
3567 | +65535 65535 | |
3568 | +DROP TABLE t; | |
3569 | +drop table if exists b15776; | |
3570 | +create table b15776 (data blob(2147483647)); | |
3571 | +drop table b15776; | |
3572 | +create table b15776 (data blob(-1)); | |
3573 | +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1))' at line 1 | |
3574 | +create table b15776 (data blob(2147483648)); | |
3575 | +drop table b15776; | |
3576 | +create table b15776 (data blob(4294967294)); | |
3577 | +drop table b15776; | |
3578 | +create table b15776 (data blob(4294967295)); | |
3579 | +drop table b15776; | |
3580 | +create table b15776 (data blob(4294967296)); | |
3581 | +ERROR 42000: Display width out of range for column 'data' (max = 4294967295) | |
3582 | +CREATE TABLE b15776 (a blob(2147483647), b blob(2147483648), c blob(4294967295), a1 text(2147483647), b1 text(2147483648), c1 text(4294967295) ); | |
3583 | +show columns from b15776; | |
3584 | +Field Type Null Key Default Extra | |
3585 | +a longblob YES NULL | |
3586 | +b longblob YES NULL | |
3587 | +c longblob YES NULL | |
3588 | +a1 longtext YES NULL | |
3589 | +b1 longtext YES NULL | |
3590 | +c1 longtext YES NULL | |
3591 | +drop table b15776; | |
3592 | +CREATE TABLE b15776 (a blob(4294967296)); | |
3593 | +ERROR 42000: Display width out of range for column 'a' (max = 4294967295) | |
3594 | +CREATE TABLE b15776 (a text(4294967296)); | |
3595 | +ERROR 42000: Display width out of range for column 'a' (max = 4294967295) | |
3596 | +CREATE TABLE b15776 (a blob(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
3597 | +ERROR 42000: Display width out of range for column 'a' (max = 4294967295) | |
3598 | +CREATE TABLE b15776 (a text(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
3599 | +ERROR 42000: Display width out of range for column 'a' (max = 4294967295) | |
3600 | +CREATE TABLE b15776 (a int(0)); | |
3601 | +INSERT INTO b15776 values (NULL), (1), (42), (654); | |
3602 | +SELECT * from b15776 ORDER BY a; | |
3603 | +a | |
3604 | +NULL | |
3605 | +1 | |
3606 | +42 | |
3607 | +654 | |
3608 | +DROP TABLE b15776; | |
3609 | +CREATE TABLE b15776 (a int(-1)); | |
3610 | +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1))' at line 1 | |
3611 | +CREATE TABLE b15776 (a int(255)); | |
3612 | +DROP TABLE b15776; | |
3613 | +CREATE TABLE b15776 (a int(256)); | |
3614 | +ERROR 42000: Display width out of range for column 'a' (max = 255) | |
3615 | +CREATE TABLE b15776 (data blob(-1)); | |
3616 | +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1))' at line 1 | |
3617 | +CREATE TABLE b15776 (a char(2147483647)); | |
3618 | +ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead | |
3619 | +CREATE TABLE b15776 (a char(2147483648)); | |
3620 | +ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead | |
3621 | +CREATE TABLE b15776 (a char(4294967295)); | |
3622 | +ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead | |
3623 | +CREATE TABLE b15776 (a char(4294967296)); | |
3624 | +ERROR 42000: Display width out of range for column 'a' (max = 4294967295) | |
3625 | +CREATE TABLE b15776 (a year(4294967295)); | |
3626 | +INSERT INTO b15776 VALUES (42); | |
3627 | +SELECT * FROM b15776; | |
3628 | +a | |
3629 | +2042 | |
3630 | +DROP TABLE b15776; | |
3631 | +CREATE TABLE b15776 (a year(4294967296)); | |
3632 | +ERROR 42000: Display width out of range for column 'a' (max = 4294967295) | |
3633 | +CREATE TABLE b15776 (a year(0)); | |
3634 | +DROP TABLE b15776; | |
3635 | +CREATE TABLE b15776 (a year(-2)); | |
3636 | +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-2))' at line 1 | |
3637 | +CREATE TABLE b15776 (a int(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
3638 | +ERROR 42000: Display width out of range for column 'a' (max = 4294967295) | |
3639 | +CREATE TABLE b15776 (a char(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
3640 | +ERROR 42000: Display width out of range for column 'a' (max = 4294967295) | |
3641 | +CREATE TABLE b15776 (a year(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
3642 | +ERROR 42000: Display width out of range for column 'a' (max = 4294967295) | |
3643 | +CREATE TABLE b15776 select cast(null as char(4294967295)); | |
3644 | +show columns from b15776; | |
3645 | +Field Type Null Key Default Extra | |
3646 | +cast(null as char(4294967295)) char(0) YES NULL | |
3647 | +drop table b15776; | |
3648 | +CREATE TABLE b15776 select cast(null as nchar(4294967295)); | |
3649 | +show columns from b15776; | |
3650 | +Field Type Null Key Default Extra | |
3651 | +cast(null as nchar(4294967295)) char(0) YES NULL | |
3652 | +drop table b15776; | |
3653 | +CREATE TABLE b15776 select cast(null as binary(4294967295)); | |
3654 | +show columns from b15776; | |
3655 | +Field Type Null Key Default Extra | |
3656 | +cast(null as binary(4294967295)) binary(0) YES NULL | |
3657 | +drop table b15776; | |
3658 | +explain select cast(1 as char(4294967295)); | |
3659 | +id select_type table type possible_keys key key_len ref rows Extra | |
3660 | +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used | |
3661 | +explain select cast(1 as nchar(4294967295)); | |
3662 | +id select_type table type possible_keys key key_len ref rows Extra | |
3663 | +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used | |
3664 | +explain select cast(1 as binary(4294967295)); | |
3665 | +id select_type table type possible_keys key key_len ref rows Extra | |
3666 | +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used | |
3667 | +explain select cast(1 as char(4294967296)); | |
3668 | +ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295) | |
3669 | +explain select cast(1 as nchar(4294967296)); | |
3670 | +ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295) | |
3671 | +explain select cast(1 as binary(4294967296)); | |
3672 | +ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295) | |
3673 | +explain select cast(1 as decimal(-1)); | |
3674 | +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1))' at line 1 | |
3675 | +explain select cast(1 as decimal(64, 30)); | |
3676 | +id select_type table type possible_keys key key_len ref rows Extra | |
3677 | +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used | |
3678 | +explain select cast(1 as decimal(64, 999999999999999999999999999999)); | |
3679 | +Got one of the listed errors | |
3680 | +explain select cast(1 as decimal(4294967296)); | |
3681 | +Got one of the listed errors | |
3682 | +explain select cast(1 as decimal(999999999999999999999999999999999999)); | |
3683 | +Got one of the listed errors | |
3684 | +explain select convert(1, char(4294967295)); | |
3685 | +id select_type table type possible_keys key key_len ref rows Extra | |
3686 | +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used | |
3687 | +explain select convert(1, char(4294967296)); | |
3688 | +ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295) | |
3689 | +explain select convert(1, char(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
3690 | +ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295) | |
3691 | +explain select convert(1, nchar(4294967295)); | |
3692 | +id select_type table type possible_keys key key_len ref rows Extra | |
3693 | +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used | |
3694 | +explain select convert(1, nchar(4294967296)); | |
3695 | +ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295) | |
3696 | +explain select convert(1, nchar(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
3697 | +ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295) | |
3698 | +explain select convert(1, binary(4294967295)); | |
3699 | +id select_type table type possible_keys key key_len ref rows Extra | |
3700 | +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used | |
3701 | +explain select convert(1, binary(4294967296)); | |
3702 | +ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295) | |
3703 | +explain select convert(1, binary(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
3704 | +ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295) | |
3705 | +End of 5.0 tests | |
3706 | +CREATE TABLE t1(id INT NOT NULL); | |
3707 | +CREATE TABLE t2(id INT NOT NULL, c TEXT NOT NULL); | |
3708 | +INSERT INTO t1 VALUES (1); | |
3709 | +INSERT INTO t2 VALUES (1, ''); | |
3710 | +UPDATE t2 SET c = REPEAT('1', 70000); | |
3711 | +Warnings: | |
3712 | +Warning 1265 Data truncated for column 'c' at row 1 | |
3713 | +SELECT LENGTH(c) FROM t2; | |
3714 | +LENGTH(c) | |
3715 | +65535 | |
3716 | +UPDATE t1 LEFT JOIN t2 USING(id) SET t2.c = REPEAT('1', 70000) WHERE t1.id = 1; | |
3717 | +Warnings: | |
3718 | +Warning 1265 Data truncated for column 'c' at row 1 | |
3719 | +SELECT LENGTH(c) FROM t2; | |
3720 | +LENGTH(c) | |
3721 | +65535 | |
3722 | +DROP TABLE t1, t2; | |
3723 | +# Bug #52160: crash and inconsistent results when grouping | |
3724 | +# by a function and column | |
3725 | +CREATE FUNCTION f1() RETURNS TINYBLOB RETURN 1; | |
3726 | +CREATE TABLE t1(a CHAR(1)); | |
3727 | +INSERT INTO t1 VALUES ('0'), ('0'); | |
3728 | +SELECT COUNT(*) FROM t1 GROUP BY f1(), a; | |
3729 | +COUNT(*) | |
3730 | +2 | |
3731 | +DROP FUNCTION f1; | |
3732 | +DROP TABLE t1; | |
48b678b4 AM |
3733 | +SET @old_max_heap_table_size = @@global.max_heap_table_size; |
3734 | +SET @old_max_allowed_packet = @@global.max_allowed_packet; | |
3735 | +SET GLOBAL max_heap_table_size = 18 * 1024 * 1024; | |
3736 | +SET GLOBAL max_allowed_packet = 24 * 1024 * 1024; | |
3737 | +drop table if exists t1; | |
1bfc1981 | 3738 | +CREATE TABLE t1 (data LONGBLOB); |
48b678b4 AM |
3739 | +INSERT INTO t1 (data) VALUES (NULL); |
3740 | +UPDATE t1 set data=repeat('a',18*1024*1024); | |
3741 | +select length(data) from t1; | |
3742 | +length(data) | |
3743 | +18874368 | |
3744 | +delete from t1 where left(data,1)='a'; | |
3745 | +truncate table t1; | |
3746 | +INSERT INTO t1 (data) VALUES (repeat('a',1*1024*1024)); | |
3747 | +INSERT INTO t1 (data) VALUES (repeat('b',16*1024*1024-1024)); | |
3748 | +delete from t1 where left(data,1)='b'; | |
3749 | +UPDATE t1 set data=repeat('c',17*1024*1024); | |
3750 | +delete from t1 where left(data,1)='c'; | |
3751 | +INSERT INTO t1 set data=repeat('a',18*1024*1024); | |
3752 | +select length(data) from t1; | |
3753 | +length(data) | |
3754 | +18874368 | |
3755 | +alter table t1 modify data blob; | |
3756 | +select length(data) from t1; | |
3757 | +length(data) | |
3758 | +0 | |
3759 | +drop table t1; | |
1bfc1981 | 3760 | +CREATE TABLE t1 (data BLOB); |
48b678b4 AM |
3761 | +INSERT INTO t1 (data) VALUES (NULL); |
3762 | +UPDATE t1 set data=repeat('a',18*1024*1024); | |
3763 | +Warnings: | |
3764 | +Warning 1265 Data truncated for column 'data' at row 1 | |
3765 | +select length(data) from t1; | |
3766 | +length(data) | |
3767 | +65535 | |
3768 | +drop table t1; | |
3769 | +SET GLOBAL max_allowed_packet = @old_max_allowed_packet; | |
3770 | +SET GLOBAL max_heap_table_size = @old_max_heap_table_size; | |
1bfc1981 | 3771 | +SET default_storage_engine=@old_default_storage_engine; |
48b678b4 AM |
3772 | --- /dev/null |
3773 | +++ b/mysql-test/r/percona_heap_bug783366.result | |
3774 | @@ -0,0 +1,14 @@ | |
3775 | +drop table if exists t1; | |
3776 | +CREATE TABLE t1 ( | |
3777 | +f1 VARCHAR ( 128 ) , | |
3778 | +f2 VARCHAR ( 32 ), | |
3779 | +PRIMARY KEY ( f2 ( 2 ) , f1 ) | |
3780 | +) | |
3781 | +ENGINE=HEAP KEY_BLOCK_SIZE = 512; | |
3782 | +INSERT IGNORE INTO t1 VALUES ( 'te' , 'm') , ( NULL , 'think' ); | |
3783 | +Warnings: | |
3784 | +Warning 1048 Column 'f1' cannot be null | |
3785 | +INSERT IGNORE INTO t1 VALUES ( 'te' , 'm') , ( NULL , 'think' ); | |
3786 | +Warnings: | |
3787 | +Warning 1048 Column 'f1' cannot be null | |
3788 | +DROP TABLE t1; | |
3789 | --- /dev/null | |
3790 | +++ b/mysql-test/r/percona_heap_bug783451.result | |
3791 | @@ -0,0 +1,132 @@ | |
3792 | +DROP TABLE IF EXISTS local_1_1; | |
3793 | +CREATE TABLE IF NOT EXISTS local_1_1 ( f1 VARCHAR ( 32 ) NOT NULL , f2 VARCHAR ( 128 ) NOT NULL DEFAULT 'cboepfaobilcchabvglgjdbynog' , f3 VARCHAR ( 32 ) NOT NULL , f4 VARBINARY ( 32 ) NOT NULL , f5 VARBINARY ( 1024 ) DEFAULT 'ycboepfao' , KEY ( f1 /* ( 2 ) */ , f2 /* ( 2 ) */ ) ) ENGINE=HEAP KEY_BLOCK_SIZE = 512; | |
3794 | +INSERT IGNORE INTO local_1_1 VALUES ( REPEAT( 'ervydbimvmbqmsowdbsa' , 1 ) , 'v' , NULL , NULL , REPEAT( 'mervydbimvmbqms' , 5 ) ) , ( 'p' , 6 , 'n' , REPEAT( 'imervydbimvmbqmsowdbs' , 4 ) , 'do' ) , ( NULL , NULL , REPEAT( 'himervydbimvmbqmsowdbsaybudvwaamvhempuublmia' , 6 ) , REPEAT('X', POW(2, 20) * 2) , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT('X', POW(2, 20) * 2) , REPEAT( 'Y' , 763 ) , NULL , REPEAT('X', POW(2, 20) * 2) , NULL ) , ( REPEAT('X', POW(2, 20) * 2) , 'time' , 'how' , 2 , REPEAT( 'Y' , 107 ) ) , ( REPEAT( 'hyshimervydbimvmbqmsowdbsaybud' , 5 ) , 2 , 8 , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( 'come' , NULL , 'i' , NULL , REPEAT('X', POW(2, 20) * 2) ); | |
3795 | +Warnings: | |
3796 | +Warning 1048 Column 'f3' cannot be null | |
3797 | +Warning 1048 Column 'f4' cannot be null | |
3798 | +Warning 1265 Data truncated for column 'f4' at row 2 | |
3799 | +Warning 1048 Column 'f1' cannot be null | |
3800 | +Warning 1048 Column 'f2' cannot be null | |
3801 | +Warning 1265 Data truncated for column 'f3' at row 3 | |
3802 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3803 | +Warning 1048 Column 'f4' cannot be null | |
3804 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3805 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3806 | +Warning 1048 Column 'f1' cannot be null | |
3807 | +Warning 1265 Data truncated for column 'f2' at row 4 | |
3808 | +Warning 1048 Column 'f3' cannot be null | |
3809 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3810 | +Warning 1048 Column 'f4' cannot be null | |
3811 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3812 | +Warning 1048 Column 'f1' cannot be null | |
3813 | +Warning 1265 Data truncated for column 'f1' at row 6 | |
3814 | +Warning 1048 Column 'f4' cannot be null | |
3815 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3816 | +Warning 1048 Column 'f2' cannot be null | |
3817 | +Warning 1048 Column 'f4' cannot be null | |
3818 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3819 | +INSERT IGNORE INTO local_1_1 VALUES ( 'ok' , NULL , REPEAT( 'Y' , 651 ) , 2 , 5 ) , ( REPEAT( 'zylcdzkfrqpihyshimervydbimvmbqmsowdbsaybu' , 3 ) , REPEAT( 'Y' , 282 ) , REPEAT( 'X' , 0 ) , REPEAT( 'Y' , 369 ) , 'g' ) , ( 'think' , REPEAT('X', POW(2, 20) * 2), NULL , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT( 'Y' , 468 ) , REPEAT( 'dfvbrzylcd' , 6 ) , REPEAT( 'Y' , 264 ) , NULL , 'c' ) , ( NULL , NULL , REPEAT( 'srdfvbrzylcdzkfrqpihyshimervydbimvmbqms' , 0 ) , REPEAT( 'Y' , 244 ) , 7 ) , ( REPEAT( 'Y' , 0 ) , 'how' , 'going' , 'q' , NULL ); | |
3820 | +Warnings: | |
3821 | +Warning 1048 Column 'f2' cannot be null | |
3822 | +Warning 1265 Data truncated for column 'f3' at row 1 | |
3823 | +Warning 1265 Data truncated for column 'f1' at row 2 | |
3824 | +Warning 1265 Data truncated for column 'f2' at row 2 | |
3825 | +Warning 1265 Data truncated for column 'f4' at row 2 | |
3826 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3827 | +Warning 1048 Column 'f2' cannot be null | |
3828 | +Warning 1048 Column 'f3' cannot be null | |
3829 | +Warning 1048 Column 'f4' cannot be null | |
3830 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3831 | +Warning 1265 Data truncated for column 'f1' at row 4 | |
3832 | +Warning 1265 Data truncated for column 'f3' at row 4 | |
3833 | +Warning 1048 Column 'f4' cannot be null | |
3834 | +Warning 1048 Column 'f1' cannot be null | |
3835 | +Warning 1048 Column 'f2' cannot be null | |
3836 | +Warning 1265 Data truncated for column 'f4' at row 5 | |
3837 | +INSERT IGNORE INTO local_1_1 VALUES ( REPEAT('X', POW(2, 20) * 2) , NULL , NULL , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT('X', POW(2, 20) * 2) , NULL , REPEAT('X', POW(2, 20) * 2) , 'this' , 'e' ) , ( NULL , 'think' , NULL , 'were' , NULL ) , ( 9 , 'l' , 'c' , 3 , REPEAT( 'geysrdfvbrzylcdzkfrqpihyshimervydbi' , 5 ) ) , ( NULL , NULL , NULL , 'h' , 'w' ); | |
3838 | +Warnings: | |
3839 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3840 | +Warning 1048 Column 'f1' cannot be null | |
3841 | +Warning 1048 Column 'f2' cannot be null | |
3842 | +Warning 1048 Column 'f3' cannot be null | |
3843 | +Warning 1048 Column 'f4' cannot be null | |
3844 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3845 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3846 | +Warning 1048 Column 'f1' cannot be null | |
3847 | +Warning 1048 Column 'f2' cannot be null | |
3848 | +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated | |
3849 | +Warning 1048 Column 'f3' cannot be null | |
3850 | +Warning 1048 Column 'f1' cannot be null | |
3851 | +Warning 1048 Column 'f3' cannot be null | |
3852 | +Warning 1048 Column 'f1' cannot be null | |
3853 | +Warning 1048 Column 'f2' cannot be null | |
3854 | +Warning 1048 Column 'f3' cannot be null | |
3855 | +INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1; | |
3856 | +INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1; | |
3857 | +UPDATE local_1_1 SET f5 = REPEAT ('X', 215566); | |
3858 | +Warnings: | |
3859 | +Warning 1265 Data truncated for column 'f5' at row 1 | |
3860 | +Warning 1265 Data truncated for column 'f5' at row 2 | |
3861 | +Warning 1265 Data truncated for column 'f5' at row 3 | |
3862 | +Warning 1265 Data truncated for column 'f5' at row 4 | |
3863 | +Warning 1265 Data truncated for column 'f5' at row 5 | |
3864 | +Warning 1265 Data truncated for column 'f5' at row 6 | |
3865 | +Warning 1265 Data truncated for column 'f5' at row 7 | |
3866 | +Warning 1265 Data truncated for column 'f5' at row 8 | |
3867 | +Warning 1265 Data truncated for column 'f5' at row 9 | |
3868 | +Warning 1265 Data truncated for column 'f5' at row 10 | |
3869 | +Warning 1265 Data truncated for column 'f5' at row 11 | |
3870 | +Warning 1265 Data truncated for column 'f5' at row 12 | |
3871 | +Warning 1265 Data truncated for column 'f5' at row 13 | |
3872 | +Warning 1265 Data truncated for column 'f5' at row 14 | |
3873 | +Warning 1265 Data truncated for column 'f5' at row 15 | |
3874 | +Warning 1265 Data truncated for column 'f5' at row 16 | |
3875 | +Warning 1265 Data truncated for column 'f5' at row 17 | |
3876 | +Warning 1265 Data truncated for column 'f5' at row 18 | |
3877 | +Warning 1265 Data truncated for column 'f5' at row 19 | |
3878 | +Warning 1265 Data truncated for column 'f5' at row 20 | |
3879 | +Warning 1265 Data truncated for column 'f5' at row 21 | |
3880 | +Warning 1265 Data truncated for column 'f5' at row 22 | |
3881 | +Warning 1265 Data truncated for column 'f5' at row 23 | |
3882 | +Warning 1265 Data truncated for column 'f5' at row 24 | |
3883 | +Warning 1265 Data truncated for column 'f5' at row 25 | |
3884 | +Warning 1265 Data truncated for column 'f5' at row 26 | |
3885 | +Warning 1265 Data truncated for column 'f5' at row 27 | |
3886 | +Warning 1265 Data truncated for column 'f5' at row 28 | |
3887 | +Warning 1265 Data truncated for column 'f5' at row 29 | |
3888 | +Warning 1265 Data truncated for column 'f5' at row 30 | |
3889 | +Warning 1265 Data truncated for column 'f5' at row 31 | |
3890 | +Warning 1265 Data truncated for column 'f5' at row 32 | |
3891 | +Warning 1265 Data truncated for column 'f5' at row 33 | |
3892 | +Warning 1265 Data truncated for column 'f5' at row 34 | |
3893 | +Warning 1265 Data truncated for column 'f5' at row 35 | |
3894 | +Warning 1265 Data truncated for column 'f5' at row 36 | |
3895 | +Warning 1265 Data truncated for column 'f5' at row 37 | |
3896 | +Warning 1265 Data truncated for column 'f5' at row 38 | |
3897 | +Warning 1265 Data truncated for column 'f5' at row 39 | |
3898 | +Warning 1265 Data truncated for column 'f5' at row 40 | |
3899 | +Warning 1265 Data truncated for column 'f5' at row 41 | |
3900 | +Warning 1265 Data truncated for column 'f5' at row 42 | |
3901 | +Warning 1265 Data truncated for column 'f5' at row 43 | |
3902 | +Warning 1265 Data truncated for column 'f5' at row 44 | |
3903 | +Warning 1265 Data truncated for column 'f5' at row 45 | |
3904 | +Warning 1265 Data truncated for column 'f5' at row 46 | |
3905 | +Warning 1265 Data truncated for column 'f5' at row 47 | |
3906 | +Warning 1265 Data truncated for column 'f5' at row 48 | |
3907 | +Warning 1265 Data truncated for column 'f5' at row 49 | |
3908 | +Warning 1265 Data truncated for column 'f5' at row 50 | |
3909 | +Warning 1265 Data truncated for column 'f5' at row 51 | |
3910 | +Warning 1265 Data truncated for column 'f5' at row 52 | |
3911 | +Warning 1265 Data truncated for column 'f5' at row 53 | |
3912 | +Warning 1265 Data truncated for column 'f5' at row 54 | |
3913 | +Warning 1265 Data truncated for column 'f5' at row 55 | |
3914 | +Warning 1265 Data truncated for column 'f5' at row 56 | |
3915 | +Warning 1265 Data truncated for column 'f5' at row 57 | |
3916 | +Warning 1265 Data truncated for column 'f5' at row 58 | |
3917 | +Warning 1265 Data truncated for column 'f5' at row 59 | |
3918 | +Warning 1265 Data truncated for column 'f5' at row 60 | |
3919 | +Warning 1265 Data truncated for column 'f5' at row 61 | |
3920 | +Warning 1265 Data truncated for column 'f5' at row 62 | |
3921 | +Warning 1265 Data truncated for column 'f5' at row 63 | |
3922 | +Warning 1265 Data truncated for column 'f5' at row 64 | |
3923 | +DROP TABLE local_1_1; | |
3924 | --- /dev/null | |
3925 | +++ b/mysql-test/r/percona_heap_bug784464.result | |
3926 | @@ -0,0 +1,58 @@ | |
3927 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
3928 | +PRIMARY KEY (f1)) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3929 | +SHOW TABLE STATUS LIKE 't1'; | |
3930 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 3931 | +t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC |
48b678b4 AM |
3932 | +DROP TABLE t1; |
3933 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
3934 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=33 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3935 | +ERROR 42000: Incorrect usage/placement of 'key_block_size' | |
3936 | +SHOW TABLE STATUS LIKE 't1'; | |
3937 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
3938 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
3939 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=34 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3940 | +SHOW TABLE STATUS LIKE 't1'; | |
3941 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 3942 | +t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=34 |
48b678b4 AM |
3943 | +DROP TABLE t1; |
3944 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
3945 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=123 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3946 | +SHOW TABLE STATUS LIKE 't1'; | |
3947 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 3948 | +t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=123 |
48b678b4 AM |
3949 | +DROP TABLE t1; |
3950 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
3951 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=1000 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3952 | +SHOW TABLE STATUS LIKE 't1'; | |
3953 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 3954 | +t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=1000 |
48b678b4 AM |
3955 | +DROP TABLE t1; |
3956 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
3957 | +PRIMARY KEY (f1)) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3958 | +SHOW TABLE STATUS LIKE 't1'; | |
3959 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 3960 | +t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC |
48b678b4 AM |
3961 | +DROP TABLE t1; |
3962 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
3963 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=33 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3964 | +ERROR 42000: Incorrect usage/placement of 'key_block_size' | |
3965 | +SHOW TABLE STATUS LIKE 't1'; | |
3966 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
3967 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
3968 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=34 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3969 | +SHOW TABLE STATUS LIKE 't1'; | |
3970 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 3971 | +t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=34 |
48b678b4 AM |
3972 | +DROP TABLE t1; |
3973 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
3974 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=121 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3975 | +SHOW TABLE STATUS LIKE 't1'; | |
3976 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 3977 | +t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=121 |
48b678b4 AM |
3978 | +DROP TABLE t1; |
3979 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
3980 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=1000 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3981 | +SHOW TABLE STATUS LIKE 't1'; | |
3982 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 3983 | +t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=1000 |
48b678b4 AM |
3984 | +DROP TABLE t1; |
3985 | --- /dev/null | |
3986 | +++ b/mysql-test/r/percona_heap_bug784464_32bit.result | |
3987 | @@ -0,0 +1,12 @@ | |
3988 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
3989 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=124 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3990 | +SHOW TABLE STATUS LIKE 't1'; | |
3991 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 3992 | +t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=124 |
48b678b4 AM |
3993 | +DROP TABLE t1; |
3994 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
3995 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=122 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
3996 | +SHOW TABLE STATUS LIKE 't1'; | |
3997 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 3998 | +t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=122 |
48b678b4 AM |
3999 | +DROP TABLE t1; |
4000 | --- /dev/null | |
4001 | +++ b/mysql-test/r/percona_heap_bug784464_64bit.result | |
4002 | @@ -0,0 +1,12 @@ | |
4003 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
4004 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=124 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
4005 | +SHOW TABLE STATUS LIKE 't1'; | |
4006 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 4007 | +t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=124 |
48b678b4 AM |
4008 | +DROP TABLE t1; |
4009 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
4010 | +PRIMARY KEY (f1)) KEY_BLOCK_SIZE=122 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
4011 | +SHOW TABLE STATUS LIKE 't1'; | |
4012 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 4013 | +t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=122 |
48b678b4 AM |
4014 | +DROP TABLE t1; |
4015 | --- /dev/null | |
4016 | +++ b/mysql-test/r/percona_heap_bug784468.result | |
4017 | @@ -0,0 +1,15 @@ | |
4018 | +CREATE TABLE t1 ( f1 VARCHAR(30)) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
4019 | +SHOW TABLE STATUS LIKE 't1'; | |
4020 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 4021 | +t1 MEMORY 10 Fixed 0 32 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC |
48b678b4 AM |
4022 | +DROP TABLE t1; |
4023 | +CREATE TABLE t1 ( f1 VARCHAR(31)) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
4024 | +SHOW TABLE STATUS LIKE 't1'; | |
4025 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 4026 | +t1 MEMORY 10 Fixed 0 33 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC |
48b678b4 AM |
4027 | +DROP TABLE t1; |
4028 | +CREATE TABLE t1 ( f1 VARCHAR(32)) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
4029 | +SHOW TABLE STATUS LIKE 't1'; | |
4030 | +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment | |
734d6226 | 4031 | +t1 MEMORY 10 Fixed 0 34 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC |
48b678b4 AM |
4032 | +DROP TABLE t1; |
4033 | --- /dev/null | |
4034 | +++ b/mysql-test/r/percona_heap_bug788544.result | |
4035 | @@ -0,0 +1,9 @@ | |
4036 | +CREATE TABLE t1 (f2 VARCHAR (32), f4 LONGBLOB, f5 TEXT) ENGINE=HEAP; | |
4037 | +INSERT INTO t1 VALUES ('a', NULL, NULL), | |
4038 | +('b' , REPEAT('a' , 593338), REPEAT('a', 800)); | |
4039 | +UPDATE t1 SET f2 = 'c' WHERE f4 = 'd'; | |
4040 | +SELECT LENGTH(f2), LENGTH(f4), LENGTH(f5) FROM t1; | |
4041 | +LENGTH(f2) LENGTH(f4) LENGTH(f5) | |
4042 | +1 NULL NULL | |
4043 | +1 593338 800 | |
4044 | +DROP TABLE t1; | |
4045 | --- /dev/null | |
4046 | +++ b/mysql-test/r/percona_heap_bug788576.result | |
4047 | @@ -0,0 +1,19 @@ | |
4048 | +CREATE TABLE t1 (f1 VARCHAR (32), f2 VARCHAR (128), f3 VARBINARY (128), | |
4049 | +f4 VARBINARY (512), f5 VARBINARY (1024), | |
4050 | +KEY (f2(1))) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
4051 | +INSERT IGNORE INTO t1 VALUES (2, NULL, 6, REPEAT('glugcgqk', 5), 'look'), | |
4052 | +(REPEAT( 'kglugcgqkin', 6), 'if', 'was', NULL, NULL), | |
4053 | +(NULL, NULL, NULL, NULL, 7); | |
4054 | +Warnings: | |
4055 | +Warning 1265 Data truncated for column 'f1' at row 2 | |
4056 | +SELECT * FROM t1; | |
4057 | +f1 f2 f3 f4 f5 | |
4058 | +2 NULL 6 glugcgqkglugcgqkglugcgqkglugcgqkglugcgqk look | |
4059 | +kglugcgqkinkglugcgqkinkglugcgqki if was NULL NULL | |
4060 | +NULL NULL NULL NULL 7 | |
4061 | +DELETE FROM t1 WHERE f5 <=> NULL; | |
4062 | +SELECT * FROM t1; | |
4063 | +f1 f2 f3 f4 f5 | |
4064 | +2 NULL 6 glugcgqkglugcgqkglugcgqkglugcgqkglugcgqk look | |
4065 | +NULL NULL NULL NULL 7 | |
4066 | +DROP TABLE t1; | |
4067 | --- /dev/null | |
4068 | +++ b/mysql-test/r/percona_heap_bug788722.result | |
4069 | @@ -0,0 +1,18 @@ | |
4070 | +CREATE TABLE IF NOT EXISTS local_1_1 (f1 VARCHAR (32) NOT NULL, | |
4071 | +f2 VARCHAR (128) NOT NULL, | |
4072 | +f3 BLOB NOT NULL, | |
4073 | +f4 TEXT, | |
4074 | +f5 BLOB (1024), | |
4075 | +PRIMARY KEY (f1), | |
4076 | +KEY (f1 , f2) | |
4077 | +) ENGINE=HEAP ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE = 2048; | |
4078 | +INSERT IGNORE INTO local_1_1 VALUES | |
4079 | +(REPEAT('egqeqfxwaejpqixuvvtentruyqadxiybjdfqjspfbyjdjczrrwjnagkzsoagatqookhsgtrvvbxacppljfzaseidqggxvuirm' , 5), NULL, NULL, NULL, REPEAT('hegqeqfxwaejpqixuvvtentruyqadxiy', 1)), | |
4080 | +('you', NULL, 0, REPEAT("X", 2048) , 0); | |
4081 | +Warnings: | |
4082 | +Warning 1265 Data truncated for column 'f1' at row 1 | |
4083 | +Warning 1048 Column 'f2' cannot be null | |
4084 | +Warning 1048 Column 'f3' cannot be null | |
4085 | +Warning 1048 Column 'f2' cannot be null | |
4086 | +INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1; | |
4087 | +DROP TABLE local_1_1; | |
4088 | --- /dev/null | |
4089 | +++ b/mysql-test/r/percona_heap_bug789131.result | |
4090 | @@ -0,0 +1,7 @@ | |
4091 | +CREATE TABLE t1 (f1 VARCHAR (128), f2 VARCHAR (128), f3 VARBINARY (512), | |
4092 | +f4 TEXT (65525), f5 VARCHAR (128), KEY (f1(1))) ENGINE=HEAP; | |
4093 | +INSERT IGNORE INTO t1 VALUES | |
4094 | +( 'o' , "" , NULL , "" , 0 ) , | |
4095 | +(NULL, "" , "" , "" , 'f' ) ; | |
4096 | +INSERT IGNORE INTO t1 SELECT * FROM t1; | |
4097 | +DROP TABLE t1; | |
4098 | --- /dev/null | |
4099 | +++ b/mysql-test/r/percona_heap_var.result | |
4100 | @@ -0,0 +1,194 @@ | |
4101 | +drop table if exists t1; | |
4102 | +set @@session.max_heap_table_size=16*1024*1024; | |
4103 | +create table t1 (a int not null, b varchar(400), c int, primary key (a), key (c)) engine=heap comment="testing heaps" key_block_size=128; | |
4104 | +ERROR 42000: Incorrect usage/placement of 'key_block_size' | |
4105 | +create table t1 (a int not null, b int, c varchar(400), primary key (a), key (b)) engine=heap comment="testing heaps" key_block_size=4; | |
4106 | +ERROR 42000: Incorrect usage/placement of 'key_block_size' | |
4107 | +create table t1 (a int not null, b int, c varchar(400), d varchar(400), primary key (a), key (b)) engine=heap comment="testing heaps" key_block_size=24; | |
4108 | +show table status like "t1"; | |
4109 | +Name t1 | |
4110 | +Engine MEMORY | |
4111 | +Version 10 | |
4112 | +Row_format Dynamic | |
4113 | +Rows 0 | |
4114 | +Avg_row_length X | |
4115 | +Data_length X | |
4116 | +Max_data_length X | |
4117 | +Index_length X | |
4118 | +Data_free X | |
4119 | +Auto_increment X | |
4120 | +Create_time X | |
4121 | +Update_time X | |
4122 | +Check_time X | |
4123 | +Collation latin1_swedish_ci | |
4124 | +Checksum NULL | |
4125 | +Create_options KEY_BLOCK_SIZE=24 | |
4126 | +Comment testing heaps | |
4127 | +insert into t1 values (1,1,'012',NULL), (2,2,'0123456789',NULL), (3,3,'012345678901234567890123456789',NULL), (4,4,NULL,'0123456789012345678901234567890123456789012345678901234567890123456789'); | |
4128 | +select * from t1; | |
4129 | +a b c d | |
4130 | +1 1 012 NULL | |
4131 | +2 2 0123456789 NULL | |
4132 | +3 3 012345678901234567890123456789 NULL | |
4133 | +4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789 | |
4134 | +delete from t1 where a = 3; | |
4135 | +select * from t1; | |
4136 | +a b c d | |
4137 | +1 1 012 NULL | |
4138 | +2 2 0123456789 NULL | |
4139 | +4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789 | |
4140 | +insert into t1 values (5,5,NULL,'0123'), (6,6,NULL,'0123'); | |
4141 | +select * from t1; | |
4142 | +a b c d | |
4143 | +1 1 012 NULL | |
4144 | +2 2 0123456789 NULL | |
4145 | +6 6 NULL 0123 | |
4146 | +5 5 NULL 0123 | |
4147 | +4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789 | |
4148 | +update t1 set c = '012345678901234567890123456789' where a = 2; | |
4149 | +select * from t1; | |
4150 | +a b c d | |
4151 | +1 1 012 NULL | |
4152 | +2 2 012345678901234567890123456789 NULL | |
4153 | +6 6 NULL 0123 | |
4154 | +5 5 NULL 0123 | |
4155 | +4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789 | |
4156 | +update t1 set c = '0123456789' where a = 2; | |
4157 | +select * from t1; | |
4158 | +a b c d | |
4159 | +1 1 012 NULL | |
4160 | +2 2 0123456789 NULL | |
4161 | +6 6 NULL 0123 | |
4162 | +5 5 NULL 0123 | |
4163 | +4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789 | |
4164 | +insert into t1 values (7,7,'0123',NULL), (8,8,'0123',NULL); | |
4165 | +select * from t1; | |
4166 | +a b c d | |
4167 | +1 1 012 NULL | |
4168 | +2 2 0123456789 NULL | |
4169 | +6 6 NULL 0123 | |
4170 | +5 5 NULL 0123 | |
4171 | +4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789 | |
4172 | +7 7 0123 NULL | |
4173 | +8 8 0123 NULL | |
4174 | +show table status like "t1"; | |
4175 | +Name t1 | |
4176 | +Engine MEMORY | |
4177 | +Version 10 | |
4178 | +Row_format Dynamic | |
4179 | +Rows 7 | |
4180 | +Avg_row_length X | |
4181 | +Data_length X | |
4182 | +Max_data_length X | |
4183 | +Index_length X | |
4184 | +Data_free X | |
4185 | +Auto_increment X | |
4186 | +Create_time X | |
4187 | +Update_time X | |
4188 | +Check_time X | |
4189 | +Collation latin1_swedish_ci | |
4190 | +Checksum NULL | |
4191 | +Create_options KEY_BLOCK_SIZE=24 | |
4192 | +Comment testing heaps | |
4193 | +alter table t1 key_block_size = 0; | |
4194 | +show table status like "t1"; | |
4195 | +Name t1 | |
4196 | +Engine MEMORY | |
4197 | +Version 10 | |
4198 | +Row_format Dynamic | |
4199 | +Rows 7 | |
4200 | +Avg_row_length X | |
4201 | +Data_length X | |
4202 | +Max_data_length X | |
4203 | +Index_length X | |
4204 | +Data_free X | |
4205 | +Auto_increment X | |
4206 | +Create_time X | |
4207 | +Update_time X | |
4208 | +Check_time X | |
4209 | +Collation latin1_swedish_ci | |
4210 | +Checksum NULL | |
4211 | +Create_options | |
4212 | +Comment testing heaps | |
4213 | +alter table t1 row_format = dynamic; | |
4214 | +show table status like "t1"; | |
4215 | +Name t1 | |
4216 | +Engine MEMORY | |
4217 | +Version 10 | |
4218 | +Row_format Dynamic | |
4219 | +Rows 7 | |
4220 | +Avg_row_length X | |
4221 | +Data_length X | |
4222 | +Max_data_length X | |
4223 | +Index_length X | |
4224 | +Data_free X | |
4225 | +Auto_increment X | |
4226 | +Create_time X | |
4227 | +Update_time X | |
4228 | +Check_time X | |
4229 | +Collation latin1_swedish_ci | |
4230 | +Checksum NULL | |
4231 | +Create_options row_format=DYNAMIC KEY_BLOCK_SIZE=X | |
4232 | +Comment testing heaps | |
4233 | +alter table t1 key_block_size = 128, max_rows = 10001; | |
4234 | +show table status like "t1"; | |
4235 | +Name t1 | |
4236 | +Engine MEMORY | |
4237 | +Version 10 | |
4238 | +Row_format Dynamic | |
4239 | +Rows 7 | |
4240 | +Avg_row_length X | |
4241 | +Data_length X | |
4242 | +Max_data_length X | |
4243 | +Index_length X | |
4244 | +Data_free X | |
4245 | +Auto_increment X | |
4246 | +Create_time X | |
4247 | +Update_time X | |
4248 | +Check_time X | |
4249 | +Collation latin1_swedish_ci | |
4250 | +Checksum NULL | |
4251 | +Create_options max_rows=10001 row_format=DYNAMIC KEY_BLOCK_SIZE=128 | |
4252 | +Comment testing heaps | |
4253 | +select * from t1; | |
4254 | +a b c d | |
4255 | +1 1 012 NULL | |
4256 | +2 2 0123456789 NULL | |
4257 | +6 6 NULL 0123 | |
4258 | +5 5 NULL 0123 | |
4259 | +4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789 | |
4260 | +7 7 0123 NULL | |
4261 | +8 8 0123 NULL | |
4262 | +delete from t1; | |
4263 | +select * from t1; | |
4264 | +a b c d | |
4265 | +call mtr.add_suppression("The table 't1' is full"); | |
4266 | +select count(*) from t1; | |
4267 | +count(*) | |
4268 | +10001 | |
4269 | +insert into t1 values (100000,100000,NULL,'0123'), (100000,100000,NULL,'0123'); | |
4270 | +ERROR HY000: The table 't1' is full | |
4271 | +show table status like "t1"; | |
4272 | +Name t1 | |
4273 | +Engine MEMORY | |
4274 | +Version 10 | |
4275 | +Row_format Dynamic | |
4276 | +Rows 10001 | |
4277 | +Avg_row_length X | |
4278 | +Data_length X | |
4279 | +Max_data_length X | |
4280 | +Index_length X | |
4281 | +Data_free X | |
4282 | +Auto_increment X | |
4283 | +Create_time X | |
4284 | +Update_time X | |
4285 | +Check_time X | |
4286 | +Collation latin1_swedish_ci | |
4287 | +Checksum NULL | |
4288 | +Create_options max_rows=10001 row_format=DYNAMIC KEY_BLOCK_SIZE=128 | |
4289 | +Comment testing heaps | |
4290 | +select count(*) from t1; | |
4291 | +count(*) | |
4292 | +10001 | |
4293 | +set @@session.max_heap_table_size=default; | |
4294 | +drop table t1; | |
4295 | --- /dev/null | |
4296 | +++ b/mysql-test/t/percona_heap_blob.test | |
4297 | @@ -0,0 +1,642 @@ | |
4298 | +######################################################################## | |
4299 | +# Test blobs with the HEAP/MEMORY storage engine | |
4300 | +######################################################################## | |
4301 | + | |
4302 | +######################################################################## | |
4303 | +# Modified tests from type_blob.test | |
4304 | +######################################################################## | |
4305 | + | |
4306 | +SET @old_default_storage_engine=@@default_storage_engine; | |
4307 | +SET default_storage_engine=MEMORY; | |
4308 | + | |
4309 | +# | |
4310 | +# Basic cleanup | |
4311 | +# | |
4312 | +--disable_warnings | |
4313 | +drop table if exists t1,t2,t3,t4,t5,t6,t7; | |
4314 | +--enable_warnings | |
4315 | + | |
4316 | + | |
4317 | +# | |
4318 | +# Check syntax for creating BLOB/TEXT | |
4319 | +# | |
4320 | + | |
4321 | +CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000)); | |
4322 | +show columns from t1; | |
4323 | +# PS doesn't give errors on prepare yet | |
4324 | +CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000)); | |
4325 | +CREATE TABLE t4 (c varchar(65530) character set utf8 not null); | |
4326 | +show columns from t2; | |
4327 | +create table t3 (a long, b long byte); | |
4328 | +show create TABLE t3; | |
4329 | +show create TABLE t4; | |
4330 | +drop table t1,t2,t3,t4; | |
4331 | + | |
4332 | +# | |
4333 | +# Check errors with blob | |
4334 | +# | |
4335 | + | |
4336 | +--error 1074 | |
4337 | +CREATE TABLE t1 (a char(257) default "hello"); | |
4338 | +--error 1074 | |
4339 | +CREATE TABLE t2 (a char(256)); | |
4340 | +--error 1074 | |
4341 | +CREATE TABLE t1 (a varchar(70000) default "hello"); | |
4342 | +--error 1101 | |
4343 | +CREATE TABLE t2 (a blob default "hello"); | |
4344 | + | |
4345 | +# Safety to be able to continue with other tests if above fails | |
4346 | +--disable_warnings | |
4347 | +drop table if exists t1,t2; | |
4348 | +--enable_warnings | |
4349 | + | |
4350 | +# | |
4351 | +# test of full join with blob | |
4352 | +# | |
4353 | + | |
4354 | +create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr)); | |
4355 | +insert into t1 values (null,"a","A"); | |
4356 | +insert into t1 values (null,"bbb","BBB"); | |
4357 | +insert into t1 values (null,"ccc","CCC"); | |
4358 | +select last_insert_id(); | |
4359 | +select * from t1,t1 as t2; | |
4360 | + | |
4361 | +drop table t1; | |
4362 | + | |
4363 | +# | |
4364 | +# Test of changing TEXT column | |
4365 | +# | |
4366 | + | |
4367 | +create table t1 (a text); | |
4368 | +insert into t1 values ('where'); | |
4369 | +update t1 set a='Where'; | |
4370 | +select * from t1; | |
4371 | +drop table t1; | |
4372 | + | |
4373 | +# | |
4374 | +# test of blob, text, char and varbinary | |
4375 | +# | |
0ccdf405 | 4376 | +create table t1 (t text,c char(10),b blob, d varbinary(10)) collate latin1_general_cs; |
48b678b4 AM |
4377 | +insert into t1 values (NULL,NULL,NULL,NULL); |
4378 | +insert into t1 values ("","","",""); | |
4379 | +insert into t1 values ("hello","hello","hello","hello"); | |
4380 | +insert into t1 values ("HELLO","HELLO","HELLO","HELLO"); | |
4381 | +insert into t1 values ("HELLO MY","HELLO MY","HELLO MY","HELLO MY"); | |
4382 | +insert into t1 values ("a","a","a","a"); | |
4383 | +insert into t1 values (1,1,1,1); | |
4384 | +insert into t1 values (NULL,NULL,NULL,NULL); | |
4385 | +update t1 set c="",b=null where c="1"; | |
4386 | + | |
4387 | +lock tables t1 READ; | |
4388 | +# We mask out the Privileges column because it differs for embedded server | |
4389 | +--replace_column 8 # | |
4390 | +show full fields from t1; | |
4391 | +lock tables t1 WRITE; | |
4392 | +--replace_column 8 # | |
4393 | +show full fields from t1; | |
4394 | +unlock tables; | |
4395 | + | |
4396 | +select t from t1 where t like "hello"; | |
4397 | +select c from t1 where c like "hello"; | |
4398 | +select b from t1 where b like "hello"; | |
4399 | +select d from t1 where d like "hello"; | |
4400 | +select c from t1 having c like "hello"; | |
4401 | +select d from t1 having d like "hello"; | |
4402 | +select t from t1 where t like "%HELLO%"; | |
4403 | +select c from t1 where c like "%HELLO%"; | |
4404 | +select b from t1 where b like "%HELLO%"; | |
4405 | +select d from t1 where d like "%HELLO%"; | |
4406 | +select c from t1 having c like "%HELLO%"; | |
4407 | +select d from t1 having d like "%HELLO%"; | |
4408 | +select d from t1 having d like "%HE%LLO%"; | |
4409 | +select t from t1 order by t; | |
4410 | +select c from t1 order by c; | |
4411 | +select b from t1 order by b; | |
4412 | +select d from t1 order by d; | |
4413 | +select distinct t from t1; | |
4414 | +select distinct b from t1; | |
4415 | +select distinct t from t1 order by t; | |
4416 | +select distinct b from t1 order by b; | |
4417 | +select t from t1 group by t; | |
4418 | +select b from t1 group by b; | |
4419 | +set option sql_big_tables=1; | |
4420 | +select distinct t from t1; | |
4421 | +select distinct b from t1; | |
4422 | +select distinct t from t1 order by t; | |
4423 | +select distinct b from t1 order by b; | |
4424 | +select distinct c from t1; | |
4425 | +select distinct d from t1; | |
4426 | +select distinct c from t1 order by c; | |
4427 | +select distinct d from t1 order by d; | |
4428 | +select c from t1 group by c; | |
4429 | +select d from t1 group by d; | |
4430 | +set option sql_big_tables=0; | |
4431 | +select distinct * from t1; | |
4432 | +select t,count(*) from t1 group by t; | |
4433 | +select b,count(*) from t1 group by b; | |
4434 | +select c,count(*) from t1 group by c; | |
4435 | +select d,count(*) from t1 group by d; | |
4436 | +drop table t1; | |
4437 | + | |
4438 | + | |
4439 | +# | |
4440 | +# Test of join with blobs and min | |
4441 | +# | |
4442 | + | |
4443 | +CREATE TABLE t1 ( | |
4444 | + t1_id bigint(21) NOT NULL auto_increment, | |
4445 | + _field_72 varchar(128) DEFAULT '' NOT NULL, | |
4446 | + _field_95 varchar(32), | |
4447 | + _field_115 tinyint(4) DEFAULT '0' NOT NULL, | |
4448 | + _field_122 tinyint(4) DEFAULT '0' NOT NULL, | |
4449 | + _field_126 tinyint(4), | |
4450 | + _field_134 tinyint(4), | |
4451 | + PRIMARY KEY (t1_id), | |
4452 | + UNIQUE _field_72 (_field_72), | |
4453 | + KEY _field_115 (_field_115), | |
4454 | + KEY _field_122 (_field_122) | |
4455 | +); | |
4456 | + | |
4457 | + | |
4458 | +INSERT INTO t1 VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',0,1,NULL,NULL); | |
4459 | +INSERT INTO t1 VALUES (2,'hroberts','7415275a8c95952901e42b13a6b78566',0,1,NULL,NULL); | |
4460 | +INSERT INTO t1 VALUES (3,'guest','d41d8cd98f00b204e9800998ecf8427e',1,0,NULL,NULL); | |
4461 | + | |
4462 | + | |
4463 | +CREATE TABLE t2 ( | |
4464 | + seq_0_id bigint(21) DEFAULT '0' NOT NULL, | |
4465 | + seq_1_id bigint(21) DEFAULT '0' NOT NULL, | |
4466 | + PRIMARY KEY (seq_0_id,seq_1_id) | |
4467 | +); | |
4468 | + | |
4469 | + | |
4470 | +INSERT INTO t2 VALUES (1,1); | |
4471 | +INSERT INTO t2 VALUES (2,1); | |
4472 | +INSERT INTO t2 VALUES (2,2); | |
4473 | + | |
4474 | +CREATE TABLE t3 ( | |
4475 | + t3_id bigint(21) NOT NULL auto_increment, | |
4476 | + _field_131 varchar(128), | |
4477 | + _field_133 tinyint(4) DEFAULT '0' NOT NULL, | |
4478 | + _field_135 datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, | |
4479 | + _field_137 tinyint(4), | |
4480 | + _field_139 datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, | |
4481 | + _field_140 blob, | |
4482 | + _field_142 tinyint(4) DEFAULT '0' NOT NULL, | |
4483 | + _field_145 tinyint(4) DEFAULT '0' NOT NULL, | |
4484 | + _field_148 tinyint(4) DEFAULT '0' NOT NULL, | |
4485 | + PRIMARY KEY (t3_id), | |
4486 | + KEY _field_133 (_field_133), | |
4487 | + KEY _field_135 (_field_135), | |
4488 | + KEY _field_139 (_field_139), | |
4489 | + KEY _field_142 (_field_142), | |
4490 | + KEY _field_145 (_field_145), | |
4491 | + KEY _field_148 (_field_148) | |
4492 | +); | |
4493 | + | |
4494 | + | |
4495 | +INSERT INTO t3 VALUES (1,'test job 1',0,'0000-00-00 00:00:00',0,'1999-02-25 22:43:32','test\r\njob\r\n1',0,0,0); | |
4496 | +INSERT INTO t3 VALUES (2,'test job 2',0,'0000-00-00 00:00:00',0,'1999-02-26 21:08:04','',0,0,0); | |
4497 | + | |
4498 | + | |
4499 | +CREATE TABLE t4 ( | |
4500 | + seq_0_id bigint(21) DEFAULT '0' NOT NULL, | |
4501 | + seq_1_id bigint(21) DEFAULT '0' NOT NULL, | |
4502 | + PRIMARY KEY (seq_0_id,seq_1_id) | |
4503 | +); | |
4504 | + | |
4505 | + | |
4506 | +INSERT INTO t4 VALUES (1,1); | |
4507 | +INSERT INTO t4 VALUES (2,1); | |
4508 | + | |
4509 | +CREATE TABLE t5 ( | |
4510 | + t5_id bigint(21) NOT NULL auto_increment, | |
4511 | + _field_149 tinyint(4), | |
4512 | + _field_156 varchar(128) DEFAULT '' NOT NULL, | |
4513 | + _field_157 varchar(128) DEFAULT '' NOT NULL, | |
4514 | + _field_158 varchar(128) DEFAULT '' NOT NULL, | |
4515 | + _field_159 varchar(128) DEFAULT '' NOT NULL, | |
4516 | + _field_160 varchar(128) DEFAULT '' NOT NULL, | |
4517 | + _field_161 varchar(128) DEFAULT '' NOT NULL, | |
4518 | + PRIMARY KEY (t5_id), | |
4519 | + KEY _field_156 (_field_156), | |
4520 | + KEY _field_157 (_field_157), | |
4521 | + KEY _field_158 (_field_158), | |
4522 | + KEY _field_159 (_field_159), | |
4523 | + KEY _field_160 (_field_160), | |
4524 | + KEY _field_161 (_field_161) | |
4525 | +); | |
4526 | + | |
4527 | + | |
4528 | +INSERT INTO t5 VALUES (1,0,'tomato','','','','',''); | |
4529 | +INSERT INTO t5 VALUES (2,0,'cilantro','','','','',''); | |
4530 | + | |
4531 | +CREATE TABLE t6 ( | |
4532 | + seq_0_id bigint(21) DEFAULT '0' NOT NULL, | |
4533 | + seq_1_id bigint(21) DEFAULT '0' NOT NULL, | |
4534 | + PRIMARY KEY (seq_0_id,seq_1_id) | |
4535 | +); | |
4536 | + | |
4537 | +INSERT INTO t6 VALUES (1,1); | |
4538 | +INSERT INTO t6 VALUES (1,2); | |
4539 | +INSERT INTO t6 VALUES (2,2); | |
4540 | + | |
4541 | +CREATE TABLE t7 ( | |
4542 | + t7_id bigint(21) NOT NULL auto_increment, | |
4543 | + _field_143 tinyint(4), | |
4544 | + _field_165 varchar(32), | |
4545 | + _field_166 smallint(6) DEFAULT '0' NOT NULL, | |
4546 | + PRIMARY KEY (t7_id), | |
4547 | + KEY _field_166 (_field_166) | |
4548 | +); | |
4549 | + | |
4550 | + | |
4551 | +INSERT INTO t7 VALUES (1,0,'High',1); | |
4552 | +INSERT INTO t7 VALUES (2,0,'Medium',2); | |
4553 | +INSERT INTO t7 VALUES (3,0,'Low',3); | |
4554 | + | |
4555 | +select replace(t3._field_140, "\r","^M"),t3_id,min(t3._field_131), min(t3._field_135), min(t3._field_139), min(t3._field_137), min(link_alias_142._field_165), min(link_alias_133._field_72), min(t3._field_145), min(link_alias_148._field_156), replace(min(t3._field_140), "\r","^M"),t3.t3_id from t3 left join t4 on t4.seq_0_id = t3.t3_id left join t7 link_alias_142 on t4.seq_1_id = link_alias_142.t7_id left join t6 on t6.seq_0_id = t3.t3_id left join t1 link_alias_133 on t6.seq_1_id = link_alias_133.t1_id left join t2 on t2.seq_0_id = t3.t3_id left join t5 link_alias_148 on t2.seq_1_id = link_alias_148.t5_id where t3.t3_id in (1) group by t3.t3_id order by link_alias_142._field_166, _field_139, link_alias_133._field_72, _field_135, link_alias_148._field_156; | |
4556 | + | |
4557 | +drop table t1,t2,t3,t4,t5,t6,t7; | |
4558 | + | |
4559 | +# | |
4560 | +# Test of reverse with empty blob | |
4561 | +# | |
4562 | + | |
4563 | +create table t1 (a blob); | |
4564 | +insert into t1 values ("empty"),(""); | |
4565 | +select a,reverse(a) from t1; | |
4566 | +drop table t1; | |
4567 | + | |
4568 | +# | |
4569 | +# Bug when blob is updated | |
4570 | +# | |
4571 | + | |
4572 | +create table t1 (id integer auto_increment unique,imagem LONGBLOB not null default ''); | |
4573 | +insert into t1 (id) values (1); | |
4574 | +# We have to clean up the path in the results for safe comparison | |
4575 | +eval select | |
4576 | + charset(load_file('../../std_data/words.dat')), | |
4577 | + collation(load_file('../../std_data/words.dat')), | |
4578 | + coercibility(load_file('../../std_data/words.dat')); | |
4579 | +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR | |
4580 | +eval explain extended select | |
4581 | + charset(load_file('$MYSQLTEST_VARDIR/std_data/words.dat')), | |
4582 | + collation(load_file('$MYSQLTEST_VARDIR/std_data/words.dat')), | |
4583 | + coercibility(load_file('$MYSQLTEST_VARDIR/std_data/words.dat')); | |
4584 | +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR | |
4585 | +eval update t1 set imagem=load_file('$MYSQLTEST_VARDIR/std_data/words.dat') where id=1; | |
4586 | +select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1; | |
4587 | +drop table t1; | |
4588 | +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR | |
4589 | +eval create table t1 select load_file('$MYSQLTEST_VARDIR/std_data/words.dat') l; | |
4590 | +# We mask out the Privileges column because it differs for embedded server | |
4591 | +--replace_column 8 # | |
4592 | +show full fields from t1; | |
4593 | +drop table t1; | |
4594 | + | |
4595 | +# | |
4596 | +# Test blob's with end space (Bug #1651) | |
4597 | +# This is a bit changed since we now have true varchar | |
4598 | +# | |
4599 | + | |
4600 | +create table t1 (id integer primary key auto_increment, txt text not null); | |
4601 | +insert into t1 (txt) values ('Chevy '); | |
4602 | +select * from t1 where txt='Chevy'; | |
4603 | +select * from t1 where txt='Chevy '; | |
4604 | +select * from t1 where txt='Chevy ' or txt='Chevy'; | |
4605 | +select * from t1 where txt='Chevy' or txt='Chevy '; | |
4606 | +select * from t1 where id='1' or id='2'; | |
4607 | +insert into t1 (txt) values('Ford'); | |
4608 | +select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford'; | |
4609 | +select * from t1 where txt='Chevy' or txt='Chevy '; | |
4610 | +select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy'; | |
4611 | +select * from t1 where txt in ('Chevy ','Chevy'); | |
4612 | +select * from t1 where txt in ('Chevy'); | |
4613 | +select * from t1 where txt between 'Chevy' and 'Chevy'; | |
4614 | +select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy '; | |
4615 | +select * from t1 where txt between 'Chevy' and 'Chevy '; | |
4616 | +select * from t1 where txt < 'Chevy '; | |
4617 | +select * from t1 where txt <= 'Chevy'; | |
4618 | +select * from t1 where txt > 'Chevy'; | |
4619 | +select * from t1 where txt >= 'Chevy'; | |
4620 | +drop table t1; | |
4621 | + | |
4622 | +create table t1 (id integer primary key auto_increment, txt text); | |
4623 | +insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL); | |
4624 | +select * from t1 where txt='Chevy' or txt is NULL; | |
4625 | +explain select * from t1 where txt='Chevy' or txt is NULL; | |
4626 | +select * from t1 where txt='Chevy '; | |
4627 | +select * from t1 where txt='Chevy ' or txt='Chevy'; | |
4628 | +select * from t1 where txt='Chevy' or txt='Chevy '; | |
4629 | +select * from t1 where id='1' or id='2'; | |
4630 | +insert into t1 (txt) values('Ford'); | |
4631 | +select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford'; | |
4632 | +select * from t1 where txt='Chevy' or txt='Chevy '; | |
4633 | +select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy'; | |
4634 | +select * from t1 where txt in ('Chevy ','Chevy'); | |
4635 | +select * from t1 where txt in ('Chevy'); | |
4636 | +select * from t1 where txt between 'Chevy' and 'Chevy'; | |
4637 | +select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy '; | |
4638 | +select * from t1 where txt between 'Chevy' and 'Chevy '; | |
4639 | +select * from t1 where txt < 'Chevy '; | |
4640 | +select * from t1 where txt < 'Chevy ' or txt is NULL; | |
4641 | +select * from t1 where txt <= 'Chevy'; | |
4642 | +select * from t1 where txt > 'Chevy'; | |
4643 | +select * from t1 where txt >= 'Chevy'; | |
4644 | +alter table t1 modify column txt blob; | |
4645 | +explain select * from t1 where txt='Chevy' or txt is NULL; | |
4646 | +select * from t1 where txt='Chevy' or txt is NULL; | |
4647 | +explain select * from t1 where txt='Chevy' or txt is NULL order by txt; | |
4648 | +select * from t1 where txt='Chevy' or txt is NULL order by txt; | |
4649 | +drop table t1; | |
4650 | + | |
4651 | +CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, d varchar(1) NOT NULL DEFAULT ' ', PRIMARY KEY (i)); | |
4652 | +INSERT t1 (i, c) VALUES (1,''),(2,''),(3,'asdfh'),(4,''); | |
4653 | +select max(i) from t1 where c = ''; | |
4654 | +drop table t1; | |
4655 | + | |
4656 | +# End of 4.1 tests | |
4657 | + | |
4658 | +# | |
4659 | +# Test that blob's and varbinary are sorted according to length | |
4660 | +# | |
4661 | + | |
4662 | +CREATE table t1 (a blob); | |
4663 | +insert into t1 values ('b'),('a\0'),('a'),('a '),('aa'),(NULL); | |
4664 | +select hex(a) from t1 order by a; | |
4665 | +select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0'); | |
4666 | +alter table t1 modify a varbinary(5); | |
4667 | +select hex(a) from t1 order by a; | |
4668 | +select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0'); | |
4669 | +alter table t1 modify a char(5); | |
4670 | +select hex(a) from t1 order by a; | |
4671 | +select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0'); | |
4672 | +alter table t1 modify a binary(5); | |
4673 | +select hex(a) from t1 order by a; | |
4674 | +select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0'); | |
4675 | +drop table t1; | |
4676 | + | |
4677 | +# | |
4678 | +# Bug #19489: Inconsistent support for DEFAULT in TEXT columns | |
4679 | +# | |
4680 | +create table t1 (a text default ''); | |
4681 | +show create table t1; | |
4682 | +insert into t1 values (default); | |
4683 | +select * from t1; | |
4684 | +drop table t1; | |
4685 | +set @@sql_mode='TRADITIONAL'; | |
4686 | +--error ER_BLOB_CANT_HAVE_DEFAULT | |
4687 | +create table t1 (a text default ''); | |
4688 | +set @@sql_mode=''; | |
4689 | + | |
4690 | +# | |
4691 | +# Bug #32282: TEXT silently truncates when value is exactly 65536 bytes | |
4692 | +# | |
4693 | + | |
4694 | +CREATE TABLE t (c TEXT CHARSET ASCII); | |
4695 | +INSERT INTO t (c) VALUES (REPEAT('1',65537)); | |
4696 | +INSERT INTO t (c) VALUES (REPEAT('2',65536)); | |
4697 | +INSERT INTO t (c) VALUES (REPEAT('3',65535)); | |
4698 | +SELECT LENGTH(c), CHAR_LENGTH(c) FROM t; | |
4699 | +DROP TABLE t; | |
4700 | +# Bug#15776: 32-bit signed int used for length of blob | |
4701 | +# """LONGBLOB: A BLOB column with a maximum length of 4,294,967,295 or 4GB.""" | |
4702 | +# | |
4703 | +# Conditions should be in this order: | |
4704 | +# A size is not in the allowed bounds. | |
4705 | +# If the type is char-ish AND size is within the max blob size: | |
4706 | +# raise ER_TOO_BIG_FIELDLENGTH (suggest using BLOB) | |
4707 | +# If size is too small: | |
4708 | +# raise ER_PARSE_ERROR | |
4709 | +# raise ER_TOO_BIG_DISPLAYWIDTH | |
4710 | + | |
4711 | +# BLOB and TEXT types | |
4712 | +--disable_warnings | |
4713 | +drop table if exists b15776; | |
4714 | +--enable_warnings | |
4715 | +create table b15776 (data blob(2147483647)); | |
4716 | +drop table b15776; | |
4717 | +--error ER_PARSE_ERROR | |
4718 | +create table b15776 (data blob(-1)); | |
4719 | +create table b15776 (data blob(2147483648)); | |
4720 | +drop table b15776; | |
4721 | +create table b15776 (data blob(4294967294)); | |
4722 | +drop table b15776; | |
4723 | +create table b15776 (data blob(4294967295)); | |
4724 | +drop table b15776; | |
4725 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4726 | +create table b15776 (data blob(4294967296)); | |
4727 | + | |
4728 | +CREATE TABLE b15776 (a blob(2147483647), b blob(2147483648), c blob(4294967295), a1 text(2147483647), b1 text(2147483648), c1 text(4294967295) ); | |
4729 | +show columns from b15776; | |
4730 | +drop table b15776; | |
4731 | + | |
4732 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4733 | +CREATE TABLE b15776 (a blob(4294967296)); | |
4734 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4735 | +CREATE TABLE b15776 (a text(4294967296)); | |
4736 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4737 | +CREATE TABLE b15776 (a blob(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
4738 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4739 | +CREATE TABLE b15776 (a text(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
4740 | + | |
4741 | +# Int types | |
4742 | +# "Another extension is supported by MySQL for optionally specifying the | |
4743 | +# display width of integer data types in parentheses following the base keyword | |
4744 | +# for the type (for example, INT(4)). This optional display width is used to | |
4745 | +# display integer values having a width less than the width specified for the | |
4746 | +# column by left-padding them with spaces." § Numeric Types | |
4747 | +CREATE TABLE b15776 (a int(0)); # 0 is special case, means default size | |
4748 | +INSERT INTO b15776 values (NULL), (1), (42), (654); | |
4749 | +SELECT * from b15776 ORDER BY a; | |
4750 | +DROP TABLE b15776; | |
4751 | +--error ER_PARSE_ERROR | |
4752 | +CREATE TABLE b15776 (a int(-1)); | |
4753 | +CREATE TABLE b15776 (a int(255)); | |
4754 | +DROP TABLE b15776; | |
4755 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4756 | +CREATE TABLE b15776 (a int(256)); | |
4757 | +--error ER_PARSE_ERROR | |
4758 | +CREATE TABLE b15776 (data blob(-1)); | |
4759 | + | |
4760 | +# Char types | |
4761 | +# Recommend BLOB | |
4762 | +--error ER_TOO_BIG_FIELDLENGTH | |
4763 | +CREATE TABLE b15776 (a char(2147483647)); | |
4764 | +--error ER_TOO_BIG_FIELDLENGTH | |
4765 | +CREATE TABLE b15776 (a char(2147483648)); | |
4766 | +--error ER_TOO_BIG_FIELDLENGTH | |
4767 | +CREATE TABLE b15776 (a char(4294967295)); | |
4768 | +# Even BLOB won't hold | |
4769 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4770 | +CREATE TABLE b15776 (a char(4294967296)); | |
4771 | + | |
4772 | + | |
4773 | +# Other numeric-ish types | |
4774 | +## For year, widths not "2" or "4" are silently rewritten to "4". But | |
4775 | +## When we complain about it, we say that the max is 255. We may be | |
4776 | +## talking about different things. It's confusing. | |
4777 | +CREATE TABLE b15776 (a year(4294967295)); | |
4778 | +INSERT INTO b15776 VALUES (42); | |
4779 | +SELECT * FROM b15776; | |
4780 | +DROP TABLE b15776; | |
4781 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4782 | +CREATE TABLE b15776 (a year(4294967296)); | |
4783 | +CREATE TABLE b15776 (a year(0)); # 0 is special case, means default size | |
4784 | +DROP TABLE b15776; | |
4785 | +--error ER_PARSE_ERROR | |
4786 | +CREATE TABLE b15776 (a year(-2)); | |
4787 | + | |
4788 | + | |
4789 | +# We've already tested the case, but this should visually show that | |
4790 | +# widths that are too large to be interpreted cause DISPLAYWIDTH errors. | |
4791 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4792 | +CREATE TABLE b15776 (a int(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
4793 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4794 | +CREATE TABLE b15776 (a char(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
4795 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4796 | +CREATE TABLE b15776 (a year(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
4797 | + | |
4798 | +## Do not select, too much memory needed. | |
4799 | +CREATE TABLE b15776 select cast(null as char(4294967295)); | |
4800 | +show columns from b15776; | |
4801 | +drop table b15776; | |
4802 | +CREATE TABLE b15776 select cast(null as nchar(4294967295)); | |
4803 | +show columns from b15776; | |
4804 | +drop table b15776; | |
4805 | +CREATE TABLE b15776 select cast(null as binary(4294967295)); | |
4806 | +show columns from b15776; | |
4807 | +drop table b15776; | |
4808 | + | |
4809 | +explain select cast(1 as char(4294967295)); | |
4810 | +explain select cast(1 as nchar(4294967295)); | |
4811 | +explain select cast(1 as binary(4294967295)); | |
4812 | + | |
4813 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4814 | +explain select cast(1 as char(4294967296)); | |
4815 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4816 | +explain select cast(1 as nchar(4294967296)); | |
4817 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4818 | +explain select cast(1 as binary(4294967296)); | |
4819 | + | |
4820 | +--error ER_PARSE_ERROR | |
4821 | +explain select cast(1 as decimal(-1)); | |
4822 | +explain select cast(1 as decimal(64, 30)); | |
4823 | +# It's not as important which errors are raised for these, since the | |
4824 | +# limit is nowhere near 2**32. We may fix these eventually to take | |
4825 | +# 4294967295 and still reject it because it's greater than 64 or 30, | |
4826 | +# but that's not a high priority and the parser needn't worry about | |
4827 | +# such a weird case. | |
4828 | +--error ER_TOO_BIG_SCALE,ER_PARSE_ERROR | |
4829 | +explain select cast(1 as decimal(64, 999999999999999999999999999999)); | |
4830 | +--error ER_TOO_BIG_PRECISION,ER_PARSE_ERROR | |
4831 | +explain select cast(1 as decimal(4294967296)); | |
4832 | +--error ER_TOO_BIG_PRECISION,ER_PARSE_ERROR | |
4833 | +explain select cast(1 as decimal(999999999999999999999999999999999999)); | |
4834 | + | |
4835 | +explain select convert(1, char(4294967295)); | |
4836 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4837 | +explain select convert(1, char(4294967296)); | |
4838 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4839 | +explain select convert(1, char(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
4840 | +explain select convert(1, nchar(4294967295)); | |
4841 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4842 | +explain select convert(1, nchar(4294967296)); | |
4843 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4844 | +explain select convert(1, nchar(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
4845 | +explain select convert(1, binary(4294967295)); | |
4846 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4847 | +explain select convert(1, binary(4294967296)); | |
4848 | +--error ER_TOO_BIG_DISPLAYWIDTH | |
4849 | +explain select convert(1, binary(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); | |
4850 | + | |
4851 | +--echo End of 5.0 tests | |
4852 | + | |
4853 | +# | |
4854 | +# Bug #33969: Updating a text field via a left join | |
4855 | +# | |
4856 | + | |
4857 | +CREATE TABLE t1(id INT NOT NULL); | |
4858 | +CREATE TABLE t2(id INT NOT NULL, c TEXT NOT NULL); | |
4859 | + | |
4860 | +INSERT INTO t1 VALUES (1); | |
4861 | +INSERT INTO t2 VALUES (1, ''); | |
4862 | + | |
4863 | +UPDATE t2 SET c = REPEAT('1', 70000); | |
4864 | +SELECT LENGTH(c) FROM t2; | |
4865 | + | |
4866 | +UPDATE t1 LEFT JOIN t2 USING(id) SET t2.c = REPEAT('1', 70000) WHERE t1.id = 1; | |
4867 | +SELECT LENGTH(c) FROM t2; | |
4868 | + | |
4869 | +DROP TABLE t1, t2; | |
4870 | + | |
4871 | +--echo # Bug #52160: crash and inconsistent results when grouping | |
4872 | +--echo # by a function and column | |
4873 | + | |
4874 | +CREATE FUNCTION f1() RETURNS TINYBLOB RETURN 1; | |
4875 | + | |
4876 | +CREATE TABLE t1(a CHAR(1)); | |
4877 | +INSERT INTO t1 VALUES ('0'), ('0'); | |
4878 | + | |
4879 | +SELECT COUNT(*) FROM t1 GROUP BY f1(), a; | |
4880 | + | |
4881 | +DROP FUNCTION f1; | |
4882 | +DROP TABLE t1; | |
4883 | + | |
4884 | + | |
4885 | + | |
48b678b4 AM |
4886 | + |
4887 | + | |
4888 | +######################################################################## | |
4889 | +# Modified test from myisam-blob.test | |
4890 | +######################################################################## | |
4891 | + | |
4892 | +SET @old_max_heap_table_size = @@global.max_heap_table_size; | |
4893 | +SET @old_max_allowed_packet = @@global.max_allowed_packet; | |
4894 | +SET GLOBAL max_heap_table_size = 18 * 1024 * 1024; | |
4895 | +SET GLOBAL max_allowed_packet = 24 * 1024 * 1024; | |
4896 | + | |
4897 | +connect(con1, localhost, root,,); | |
4898 | +connection con1; | |
4899 | + | |
4900 | +--disable_warnings | |
4901 | +drop table if exists t1; | |
4902 | +--enable_warnings | |
4903 | + | |
4904 | +# Bug #2159 (Problem with update of blob to > 16M) | |
4905 | + | |
1bfc1981 | 4906 | +CREATE TABLE t1 (data LONGBLOB); |
48b678b4 AM |
4907 | +INSERT INTO t1 (data) VALUES (NULL); |
4908 | +UPDATE t1 set data=repeat('a',18*1024*1024); | |
4909 | +select length(data) from t1; | |
4910 | +delete from t1 where left(data,1)='a'; | |
4911 | +truncate table t1; | |
4912 | +INSERT INTO t1 (data) VALUES (repeat('a',1*1024*1024)); | |
4913 | +INSERT INTO t1 (data) VALUES (repeat('b',16*1024*1024-1024)); | |
4914 | +delete from t1 where left(data,1)='b'; | |
4915 | + | |
4916 | +# now we have two blocks in the table, first is a 1M record and second is | |
4917 | +# a 16M delete block. | |
4918 | + | |
4919 | +UPDATE t1 set data=repeat('c',17*1024*1024); | |
4920 | +delete from t1 where left(data,1)='c'; | |
4921 | + | |
4922 | +INSERT INTO t1 set data=repeat('a',18*1024*1024); | |
4923 | +select length(data) from t1; | |
4924 | +alter table t1 modify data blob; | |
4925 | +select length(data) from t1; | |
4926 | +drop table t1; | |
4927 | + | |
1bfc1981 | 4928 | +CREATE TABLE t1 (data BLOB); |
48b678b4 AM |
4929 | +INSERT INTO t1 (data) VALUES (NULL); |
4930 | +UPDATE t1 set data=repeat('a',18*1024*1024); | |
4931 | +select length(data) from t1; | |
4932 | +drop table t1; | |
4933 | + | |
4934 | +disconnect con1; | |
4935 | +connection default; | |
4936 | + | |
4937 | +SET GLOBAL max_allowed_packet = @old_max_allowed_packet; | |
4938 | +SET GLOBAL max_heap_table_size = @old_max_heap_table_size; | |
1bfc1981 | 4939 | +SET default_storage_engine=@old_default_storage_engine; |
48b678b4 AM |
4940 | --- /dev/null |
4941 | +++ b/mysql-test/t/percona_heap_bug783366.test | |
4942 | @@ -0,0 +1,19 @@ | |
4943 | +# | |
4944 | +# Test for bug lp:783366 | |
4945 | +# | |
4946 | + | |
4947 | +--disable_warnings | |
4948 | +drop table if exists t1; | |
4949 | +--enable_warnings | |
4950 | + | |
4951 | +CREATE TABLE t1 ( | |
4952 | + f1 VARCHAR ( 128 ) , | |
4953 | + f2 VARCHAR ( 32 ), | |
4954 | + PRIMARY KEY ( f2 ( 2 ) , f1 ) | |
4955 | +) | |
4956 | +ENGINE=HEAP KEY_BLOCK_SIZE = 512; | |
4957 | +INSERT IGNORE INTO t1 VALUES ( 'te' , 'm') , ( NULL , 'think' ); | |
4958 | +INSERT IGNORE INTO t1 VALUES ( 'te' , 'm') , ( NULL , 'think' ); | |
4959 | + | |
4960 | +DROP TABLE t1; | |
4961 | + | |
4962 | --- /dev/null | |
4963 | +++ b/mysql-test/t/percona_heap_bug783451.test | |
4964 | @@ -0,0 +1,16 @@ | |
4965 | +# Testcase for the bug https://bugs.launchpad.net/percona-projects-qa/+bug/783451 | |
4966 | +# With dynamic row format in HEAP and the UPDATE statement that significantly | |
4967 | +# increases the data size, the table scan in-progress desyncs its table position state. | |
4968 | +# Run with Valgrind if it does not crash for you. | |
4969 | +--disable_warnings | |
4970 | +DROP TABLE IF EXISTS local_1_1; | |
4971 | +--enable_warnings | |
4972 | +CREATE TABLE IF NOT EXISTS local_1_1 ( f1 VARCHAR ( 32 ) NOT NULL , f2 VARCHAR ( 128 ) NOT NULL DEFAULT 'cboepfaobilcchabvglgjdbynog' , f3 VARCHAR ( 32 ) NOT NULL , f4 VARBINARY ( 32 ) NOT NULL , f5 VARBINARY ( 1024 ) DEFAULT 'ycboepfao' , KEY ( f1 /* ( 2 ) */ , f2 /* ( 2 ) */ ) ) ENGINE=HEAP KEY_BLOCK_SIZE = 512; | |
4973 | +INSERT IGNORE INTO local_1_1 VALUES ( REPEAT( 'ervydbimvmbqmsowdbsa' , 1 ) , 'v' , NULL , NULL , REPEAT( 'mervydbimvmbqms' , 5 ) ) , ( 'p' , 6 , 'n' , REPEAT( 'imervydbimvmbqmsowdbs' , 4 ) , 'do' ) , ( NULL , NULL , REPEAT( 'himervydbimvmbqmsowdbsaybudvwaamvhempuublmia' , 6 ) , REPEAT('X', POW(2, 20) * 2) , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT('X', POW(2, 20) * 2) , REPEAT( 'Y' , 763 ) , NULL , REPEAT('X', POW(2, 20) * 2) , NULL ) , ( REPEAT('X', POW(2, 20) * 2) , 'time' , 'how' , 2 , REPEAT( 'Y' , 107 ) ) , ( REPEAT( 'hyshimervydbimvmbqmsowdbsaybud' , 5 ) , 2 , 8 , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( 'come' , NULL , 'i' , NULL , REPEAT('X', POW(2, 20) * 2) ); | |
4974 | +INSERT IGNORE INTO local_1_1 VALUES ( 'ok' , NULL , REPEAT( 'Y' , 651 ) , 2 , 5 ) , ( REPEAT( 'zylcdzkfrqpihyshimervydbimvmbqmsowdbsaybu' , 3 ) , REPEAT( 'Y' , 282 ) , REPEAT( 'X' , 0 ) , REPEAT( 'Y' , 369 ) , 'g' ) , ( 'think' , REPEAT('X', POW(2, 20) * 2), NULL , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT( 'Y' , 468 ) , REPEAT( 'dfvbrzylcd' , 6 ) , REPEAT( 'Y' , 264 ) , NULL , 'c' ) , ( NULL , NULL , REPEAT( 'srdfvbrzylcdzkfrqpihyshimervydbimvmbqms' , 0 ) , REPEAT( 'Y' , 244 ) , 7 ) , ( REPEAT( 'Y' , 0 ) , 'how' , 'going' , 'q' , NULL ); | |
4975 | +INSERT IGNORE INTO local_1_1 VALUES ( REPEAT('X', POW(2, 20) * 2) , NULL , NULL , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT('X', POW(2, 20) * 2) , NULL , REPEAT('X', POW(2, 20) * 2) , 'this' , 'e' ) , ( NULL , 'think' , NULL , 'were' , NULL ) , ( 9 , 'l' , 'c' , 3 , REPEAT( 'geysrdfvbrzylcdzkfrqpihyshimervydbi' , 5 ) ) , ( NULL , NULL , NULL , 'h' , 'w' ); | |
4976 | +--enable_warnings | |
4977 | +INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1; | |
4978 | +INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1; | |
4979 | +UPDATE local_1_1 SET f5 = REPEAT ('X', 215566); | |
4980 | +DROP TABLE local_1_1; | |
4981 | --- /dev/null | |
4982 | +++ b/mysql-test/t/percona_heap_bug784464.test | |
734d6226 | 4983 | @@ -0,0 +1,66 @@ |
48b678b4 AM |
4984 | +# |
4985 | +# Bug #784464: Silent conversion from Dynamic to Fixed row_format for certain | |
4986 | +# values of key_block_size. | |
4987 | +# Also see percona_heap_bug784464_32bit and percona_heap_bug784464_64bit tests. | |
4988 | +# | |
4989 | + | |
4990 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
4991 | + PRIMARY KEY (f1)) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 4992 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
4993 | +SHOW TABLE STATUS LIKE 't1'; |
4994 | +DROP TABLE t1; | |
4995 | + | |
4996 | +--error ER_CANT_USE_OPTION_HERE | |
4997 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
4998 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=33 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 4999 | +--replace_column 12 X 13 X |
48b678b4 AM |
5000 | +SHOW TABLE STATUS LIKE 't1'; |
5001 | + | |
5002 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
5003 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=34 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5004 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5005 | +SHOW TABLE STATUS LIKE 't1'; |
5006 | +DROP TABLE t1; | |
5007 | + | |
5008 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
5009 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=123 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5010 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5011 | +SHOW TABLE STATUS LIKE 't1'; |
5012 | +DROP TABLE t1; | |
5013 | + | |
5014 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
5015 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=1000 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5016 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5017 | +SHOW TABLE STATUS LIKE 't1'; |
5018 | +DROP TABLE t1; | |
5019 | + | |
5020 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
5021 | + PRIMARY KEY (f1)) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5022 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5023 | +SHOW TABLE STATUS LIKE 't1'; |
5024 | +DROP TABLE t1; | |
5025 | + | |
5026 | +--error ER_CANT_USE_OPTION_HERE | |
5027 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
5028 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=33 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5029 | +--replace_column 12 X 13 X |
48b678b4 AM |
5030 | +SHOW TABLE STATUS LIKE 't1'; |
5031 | + | |
5032 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
5033 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=34 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5034 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5035 | +SHOW TABLE STATUS LIKE 't1'; |
5036 | +DROP TABLE t1; | |
5037 | + | |
5038 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
5039 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=121 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5040 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5041 | +SHOW TABLE STATUS LIKE 't1'; |
5042 | +DROP TABLE t1; | |
5043 | + | |
5044 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
5045 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=1000 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5046 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5047 | +SHOW TABLE STATUS LIKE 't1'; |
5048 | +DROP TABLE t1; | |
5049 | + | |
5050 | --- /dev/null | |
5051 | +++ b/mysql-test/t/percona_heap_bug784464_32bit.test | |
5052 | @@ -0,0 +1,15 @@ | |
5053 | +# 32-bit platform specific parts of tests for LP bug #784464 | |
5054 | + | |
5055 | +--source include/have_32bit.inc | |
5056 | + | |
5057 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
5058 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=124 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5059 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5060 | +SHOW TABLE STATUS LIKE 't1'; |
5061 | +DROP TABLE t1; | |
5062 | + | |
5063 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
5064 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=122 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5065 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5066 | +SHOW TABLE STATUS LIKE 't1'; |
5067 | +DROP TABLE t1; | |
5068 | --- /dev/null | |
5069 | +++ b/mysql-test/t/percona_heap_bug784464_64bit.test | |
5070 | @@ -0,0 +1,15 @@ | |
5071 | +# 64-bit platform specific parts of tests for LP bug #784464 | |
5072 | + | |
5073 | +--source include/have_64bit.inc | |
5074 | + | |
5075 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32), | |
5076 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=124 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5077 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5078 | +SHOW TABLE STATUS LIKE 't1'; |
5079 | +DROP TABLE t1; | |
5080 | + | |
5081 | +CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96), | |
5082 | + PRIMARY KEY (f1)) KEY_BLOCK_SIZE=122 ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5083 | +--replace_column 6 X 8 X 12 X 13 X |
48b678b4 AM |
5084 | +SHOW TABLE STATUS LIKE 't1'; |
5085 | +DROP TABLE t1; | |
5086 | --- /dev/null | |
5087 | +++ b/mysql-test/t/percona_heap_bug784468.test | |
5088 | @@ -0,0 +1,19 @@ | |
5089 | +# | |
5090 | +# Bug #784468: Tables with VARCHAR(<31) are created as row_format = Fixed | |
5091 | +# | |
5092 | + | |
5093 | +CREATE TABLE t1 ( f1 VARCHAR(30)) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5094 | +--replace_column 8 X 12 X 13 X |
48b678b4 AM |
5095 | +SHOW TABLE STATUS LIKE 't1'; |
5096 | +DROP TABLE t1; | |
5097 | + | |
5098 | +CREATE TABLE t1 ( f1 VARCHAR(31)) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5099 | +--replace_column 8 X 12 X 13 X |
48b678b4 AM |
5100 | +SHOW TABLE STATUS LIKE 't1'; |
5101 | +DROP TABLE t1; | |
5102 | + | |
5103 | +CREATE TABLE t1 ( f1 VARCHAR(32)) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
734d6226 | 5104 | +--replace_column 8 X 12 X 13 X |
48b678b4 AM |
5105 | +SHOW TABLE STATUS LIKE 't1'; |
5106 | +DROP TABLE t1; | |
5107 | + | |
5108 | --- /dev/null | |
5109 | +++ b/mysql-test/t/percona_heap_bug788544.test | |
5110 | @@ -0,0 +1,15 @@ | |
5111 | +# | |
5112 | +# Bug #788544: Valgrind warnings/crash in mysql-55-eb-blobs in | |
5113 | +# hp_extract_record / hp_process_field_data_to_chunkset | |
5114 | +# | |
5115 | + | |
5116 | +CREATE TABLE t1 (f2 VARCHAR (32), f4 LONGBLOB, f5 TEXT) ENGINE=HEAP; | |
5117 | + | |
5118 | +INSERT INTO t1 VALUES ('a', NULL, NULL), | |
5119 | + ('b' , REPEAT('a' , 593338), REPEAT('a', 800)); | |
5120 | + | |
5121 | +UPDATE t1 SET f2 = 'c' WHERE f4 = 'd'; | |
5122 | + | |
5123 | +SELECT LENGTH(f2), LENGTH(f4), LENGTH(f5) FROM t1; | |
5124 | + | |
5125 | +DROP TABLE t1; | |
5126 | --- /dev/null | |
5127 | +++ b/mysql-test/t/percona_heap_bug788576.test | |
5128 | @@ -0,0 +1,19 @@ | |
5129 | +# | |
5130 | +# Bug #788576: Second crash in hp_movelink with mysql-55-eb | |
5131 | +# | |
5132 | + | |
5133 | +CREATE TABLE t1 (f1 VARCHAR (32), f2 VARCHAR (128), f3 VARBINARY (128), | |
5134 | + f4 VARBINARY (512), f5 VARBINARY (1024), | |
5135 | + KEY (f2(1))) ENGINE=HEAP ROW_FORMAT=DYNAMIC; | |
5136 | + | |
5137 | +INSERT IGNORE INTO t1 VALUES (2, NULL, 6, REPEAT('glugcgqk', 5), 'look'), | |
5138 | + (REPEAT( 'kglugcgqkin', 6), 'if', 'was', NULL, NULL), | |
5139 | + (NULL, NULL, NULL, NULL, 7); | |
5140 | + | |
5141 | +SELECT * FROM t1; | |
5142 | + | |
5143 | +DELETE FROM t1 WHERE f5 <=> NULL; | |
5144 | + | |
5145 | +SELECT * FROM t1; | |
5146 | + | |
5147 | +DROP TABLE t1; | |
5148 | --- /dev/null | |
5149 | +++ b/mysql-test/t/percona_heap_bug788722.test | |
5150 | @@ -0,0 +1,20 @@ | |
5151 | +# | |
5152 | +# Bug #788722: Second valgrind warning around hp_extract_record in mysql-55-eb-blobs | |
5153 | +# | |
5154 | + | |
5155 | +CREATE TABLE IF NOT EXISTS local_1_1 (f1 VARCHAR (32) NOT NULL, | |
5156 | + f2 VARCHAR (128) NOT NULL, | |
5157 | + f3 BLOB NOT NULL, | |
5158 | + f4 TEXT, | |
5159 | + f5 BLOB (1024), | |
5160 | + PRIMARY KEY (f1), | |
5161 | + KEY (f1 , f2) | |
5162 | +) ENGINE=HEAP ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE = 2048; | |
5163 | + | |
5164 | +INSERT IGNORE INTO local_1_1 VALUES | |
5165 | + (REPEAT('egqeqfxwaejpqixuvvtentruyqadxiybjdfqjspfbyjdjczrrwjnagkzsoagatqookhsgtrvvbxacppljfzaseidqggxvuirm' , 5), NULL, NULL, NULL, REPEAT('hegqeqfxwaejpqixuvvtentruyqadxiy', 1)), | |
5166 | + ('you', NULL, 0, REPEAT("X", 2048) , 0); | |
5167 | + | |
5168 | +INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1; | |
5169 | + | |
5170 | +DROP TABLE local_1_1; | |
5171 | --- /dev/null | |
5172 | +++ b/mysql-test/t/percona_heap_bug789131.test | |
5173 | @@ -0,0 +1,14 @@ | |
5174 | +# | |
5175 | +# Bug #789131: Valgrind warning in MyISAM in mysql-55-eb-blobs | |
5176 | +# | |
5177 | + | |
5178 | +CREATE TABLE t1 (f1 VARCHAR (128), f2 VARCHAR (128), f3 VARBINARY (512), | |
5179 | + f4 TEXT (65525), f5 VARCHAR (128), KEY (f1(1))) ENGINE=HEAP; | |
5180 | + | |
5181 | +INSERT IGNORE INTO t1 VALUES | |
5182 | + ( 'o' , "" , NULL , "" , 0 ) , | |
5183 | + (NULL, "" , "" , "" , 'f' ) ; | |
5184 | + | |
5185 | +INSERT IGNORE INTO t1 SELECT * FROM t1; | |
5186 | + | |
5187 | +DROP TABLE t1; | |
5188 | \ No newline at end of file | |
5189 | --- /dev/null | |
5190 | +++ b/mysql-test/t/percona_heap_var.test | |
5191 | @@ -0,0 +1,85 @@ | |
5192 | +# | |
5193 | +# Test heap tables with variable-sized records. | |
5194 | +# | |
5195 | + | |
5196 | +--disable_warnings | |
5197 | +drop table if exists t1; | |
5198 | +--enable_warnings | |
5199 | + | |
5200 | +set @@session.max_heap_table_size=16*1024*1024; | |
5201 | + | |
5202 | +--error 1234 | |
5203 | +create table t1 (a int not null, b varchar(400), c int, primary key (a), key (c)) engine=heap comment="testing heaps" key_block_size=128; | |
5204 | + | |
5205 | +--error 1234 | |
5206 | +create table t1 (a int not null, b int, c varchar(400), primary key (a), key (b)) engine=heap comment="testing heaps" key_block_size=4; | |
5207 | + | |
5208 | +create table t1 (a int not null, b int, c varchar(400), d varchar(400), primary key (a), key (b)) engine=heap comment="testing heaps" key_block_size=24; | |
5209 | + | |
5210 | +--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X | |
5211 | +--query_vertical show table status like "t1" | |
5212 | + | |
5213 | +insert into t1 values (1,1,'012',NULL), (2,2,'0123456789',NULL), (3,3,'012345678901234567890123456789',NULL), (4,4,NULL,'0123456789012345678901234567890123456789012345678901234567890123456789'); | |
5214 | +select * from t1; | |
5215 | + | |
5216 | +delete from t1 where a = 3; | |
5217 | +select * from t1; | |
5218 | + | |
5219 | +insert into t1 values (5,5,NULL,'0123'), (6,6,NULL,'0123'); | |
5220 | +select * from t1; | |
5221 | + | |
5222 | +update t1 set c = '012345678901234567890123456789' where a = 2; | |
5223 | +select * from t1; | |
5224 | + | |
5225 | +update t1 set c = '0123456789' where a = 2; | |
5226 | +select * from t1; | |
5227 | + | |
5228 | +insert into t1 values (7,7,'0123',NULL), (8,8,'0123',NULL); | |
5229 | +select * from t1; | |
5230 | + | |
5231 | +--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X | |
5232 | +--query_vertical show table status like "t1" | |
5233 | +alter table t1 key_block_size = 0; | |
5234 | +--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X | |
5235 | +--query_vertical show table status like "t1" | |
5236 | +alter table t1 row_format = dynamic; | |
5237 | +--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X | |
5238 | +--replace_regex /KEY_BLOCK_SIZE=[[:digit:]]+/KEY_BLOCK_SIZE=X/ | |
5239 | +--query_vertical show table status like "t1" | |
5240 | +alter table t1 key_block_size = 128, max_rows = 10001; | |
5241 | +--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X | |
5242 | +--query_vertical show table status like "t1" | |
5243 | + | |
5244 | +select * from t1; | |
5245 | + | |
5246 | +delete from t1; | |
5247 | +select * from t1; | |
5248 | + | |
5249 | +let $1=10001; | |
5250 | + | |
5251 | +call mtr.add_suppression("The table 't1' is full"); | |
5252 | + | |
5253 | +disable_query_log; | |
5254 | + | |
5255 | +while ($1) | |
5256 | +{ | |
5257 | + | |
5258 | + eval insert into t1 values ($1,$1,$1,$1); | |
5259 | + | |
5260 | + dec $1; | |
5261 | + | |
5262 | +} | |
5263 | +enable_query_log; | |
5264 | + | |
5265 | +select count(*) from t1; | |
5266 | + | |
5267 | +--error 1114 | |
5268 | +insert into t1 values (100000,100000,NULL,'0123'), (100000,100000,NULL,'0123'); | |
5269 | + | |
5270 | +--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X | |
5271 | +--query_vertical show table status like "t1" | |
5272 | +select count(*) from t1; | |
5273 | + | |
5274 | +set @@session.max_heap_table_size=default; | |
5275 | + | |
5276 | +drop table t1; |