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