diff --git a/include/my_base.h b/include/my_base.h index 473ed46ff19..2ab1123ce76 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -292,6 +292,7 @@ enum ha_base_keytype { #define HA_OPTION_NO_PACK_KEYS 128 /* Reserved for MySQL */ #define HA_OPTION_CREATE_FROM_ENGINE 256 #define HA_OPTION_RELIES_ON_SQL_LAYER 512 +#define HA_OPTION_NULL_FIELDS 1024 #define HA_OPTION_TEMP_COMPRESS_RECORD ((uint) 16384) /* set by isamchk */ #define HA_OPTION_READ_ONLY_DATA ((uint) 32768) /* Set by isamchk */ diff --git a/mysql-test/r/maria.result b/mysql-test/r/maria.result index 68ae0cb267b..710cb5ec094 100644 --- a/mysql-test/r/maria.result +++ b/mysql-test/r/maria.result @@ -588,14 +588,14 @@ insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, ""); insert t2 select * from t1; checksum table t1, t2, t3 quick; Table Checksum -test.t1 2948697075 +test.t1 3442722830 test.t2 NULL test.t3 NULL Warnings: Error 1146 Table 'test.t3' doesn't exist checksum table t1, t2, t3; Table Checksum -test.t1 2948697075 +test.t1 3442722830 test.t2 2948697075 test.t3 NULL Warnings: diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 158f415317c..22b1d7701e7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7082,6 +7082,10 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, for (uint i= 0; i < t->s->fields; i++ ) { Field *f= t->field[i]; +#ifdef NOT_YET + if (f->is_real_null(0)) + continue; +#endif if ((f->type() == MYSQL_TYPE_BLOB) || (f->type() == MYSQL_TYPE_VARCHAR)) { diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 40fa5364a44..394ff7bc6ae 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -1937,6 +1937,7 @@ static my_bool write_block_record(MARIA_HA *info, /* Update page directory */ uint length= (uint) (data - row_pos->data); DBUG_PRINT("info", ("Used head length on page: %u", length)); + DBUG_ASSERT(data <= end_of_data); if (length < info->s->base.min_row_length) { uint diff_length= info->s->base.min_row_length - length; @@ -2517,7 +2518,9 @@ static my_bool allocate_and_write_block_record(MARIA_HA *info, blocks, blocks->block->org_bitmap_value != 0, &row_pos, undo_lsn)) DBUG_RETURN(1); /* Error reading bitmap */ - DBUG_PRINT("exit", ("Rowid: %lu", (ulong) row->lastpos)); + DBUG_PRINT("exit", ("Rowid: %lu (%lu:%u)", (ulong) row->lastpos, + (ulong) ma_recordpos_to_page(row->lastpos), + ma_recordpos_to_dir_entry(row->lastpos))); DBUG_RETURN(0); } @@ -2790,7 +2793,8 @@ err: my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos, const uchar *orig_rec, const uchar *new_rec) { - return _ma_update_block_record2(info, record_pos, orig_rec, new_rec, 0); + return _ma_update_block_record2(info, record_pos, orig_rec, new_rec, + LSN_ERROR); } @@ -3041,6 +3045,8 @@ my_bool _ma_delete_block_record(MARIA_HA *info, const uchar *record) page= ma_recordpos_to_page(info->cur_row.lastpos); record_number= ma_recordpos_to_dir_entry(info->cur_row.lastpos); + DBUG_PRINT("enter", ("Rowid: %lu (%lu:%u)", (ulong) info->cur_row.lastpos, + (ulong) page, record_number)); if (delete_head_or_tail(info, page, record_number, 1, 0) || delete_tails(info, info->cur_row.tail_positions)) @@ -4309,16 +4315,12 @@ static size_t fill_insert_undo_parts(MARIA_HA *info, const uchar *record, } case FIELD_VARCHAR: { - if (column->length <= 256) - { + if (column->fill_length == 1) column_length= *field_lengths; - field_lengths++; - } else - { column_length= uint2korr(field_lengths); - field_lengths+= 2; - } + field_lengths+= column->fill_length; + column_pos+= column->fill_length; break; } default: @@ -4971,6 +4973,7 @@ my_bool _ma_apply_undo_row_delete(MARIA_HA *info, LSN undo_lsn, uint *null_field_lengths; ulong *blob_lengths; MARIA_COLUMNDEF *column, *end_column; + my_bool res; DBUG_ENTER("_ma_apply_undo_row_delete"); /* @@ -5003,11 +5006,9 @@ my_bool _ma_apply_undo_row_delete(MARIA_HA *info, LSN undo_lsn, row.blob_length= ma_get_length((uchar**) &header); /* We need to build up a record (without blobs) in rec_buff */ - if (_ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, - length - row.blob_length)) + if (!(record= my_malloc(share->base.reclength, MYF(MY_WME)))) DBUG_RETURN(1); - record= info->rec_buff; memcpy(record, null_bits, share->base.null_bytes); /* Copy field information from header to record */ @@ -5073,21 +5074,22 @@ my_bool _ma_apply_undo_row_delete(MARIA_HA *info, LSN undo_lsn, uchar *field_pos= record + column->offset; /* 256 is correct as this includes the length uchar */ - if (column->length <= 256) + if (column->fill_length == 1) { field_pos[0]= *field_length_data; - length= (uint) *field_length_data++; + length= (uint) *field_length_data; } else { field_pos[0]= field_length_data[0]; field_pos[1]= field_length_data[1]; length= uint2korr(field_length_data); - field_length_data+= 2; } + field_length_data+= column->fill_length; + field_pos+= column->fill_length; row.varchar_length+= length; *null_field_lengths= length; - memcpy(record + column->offset, header, length); + memcpy(field_pos, header, length); header+= length; break; } @@ -5122,7 +5124,9 @@ my_bool _ma_apply_undo_row_delete(MARIA_HA *info, LSN undo_lsn, /* Row is now up to date. Time to insert the record */ - DBUG_RETURN(allocate_and_write_block_record(info, record, &row, undo_lsn)); + res= allocate_and_write_block_record(info, record, &row, undo_lsn); + my_free(record, MYF(0)); + DBUG_RETURN(res); } diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index cdaf8b9d124..30dffe1c0c0 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -118,9 +118,9 @@ static inline my_off_t ma_recordpos_to_page(MARIA_RECORD_POS record_pos) return record_pos >> 8; } -static inline my_off_t ma_recordpos_to_dir_entry(MARIA_RECORD_POS record_pos) +static inline uint ma_recordpos_to_dir_entry(MARIA_RECORD_POS record_pos) { - return record_pos & 255; + return (uint) (record_pos & 255); } /* ma_blockrec.c */ diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 93d4e2aa492..354af51fbfd 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -3836,7 +3836,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) if (param->testflag & T_VERBOSE) { char llbuff[22]; - record_pos_to_txt(info, sort_param->filepos, llbuff); + record_pos_to_txt(info, info->cur_row.lastpos, llbuff); _ma_check_print_info(param, "Found record with wrong checksum at %s", llbuff); @@ -3846,7 +3846,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) info->cur_row.checksum= checksum; param->glob_crc+= checksum; } - sort_param->filepos= info->cur_row.lastpos; + sort_param->start_recpos= sort_param->filepos= info->cur_row.lastpos; DBUG_RETURN(0); } if (flag == HA_ERR_END_OF_FILE) diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 7f26a7777c0..b31460d24d2 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -131,6 +131,8 @@ int maria_create(const char *name, enum data_file_type datafile_type, column->empty_pos= 0; column->empty_bit= 0; column->fill_length= column->length; + if (column->null_bit) + options|= HA_OPTION_NULL_FIELDS; reclength+= column->length; type= column->type; @@ -664,14 +666,6 @@ int maria_create(const char *name, enum data_file_type datafile_type, share.base.keystart = share.state.state.key_file_length= MY_ALIGN(info_length, maria_block_size); - if (share.data_file_type == BLOCK_RECORD) - { - /* - we are going to create a first bitmap page, set data_file_length - to reflect this, before the state goes to disk - */ - share.state.state.data_file_length= maria_block_size; - } share.base.max_key_block_length= maria_block_size; share.base.max_key_length=ALIGN_SIZE(max_key_length+4); share.base.records=ci->max_rows; @@ -683,11 +677,18 @@ int maria_create(const char *name, enum data_file_type datafile_type, share.base.pack_bytes= pack_bytes; share.base.fields= columns; share.base.pack_fields= packed; -#ifdef USE_RAID - share.base.raid_type=ci->raid_type; - share.base.raid_chunks=ci->raid_chunks; - share.base.raid_chunksize=ci->raid_chunksize; -#endif + + if (share.data_file_type == BLOCK_RECORD) + { + /* + we are going to create a first bitmap page, set data_file_length + to reflect this, before the state goes to disk + */ + share.state.state.data_file_length= maria_block_size; + /* Add length of packed fields + length */ + share.base.pack_reclength+= share.base.max_field_lengths+3; + + } /* max_data_file_length and max_key_file_length are recalculated on open */ if (tmp_table) diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index f0962404ac4..cd57f6f0b11 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -314,7 +314,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA | HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE | - HA_OPTION_RELIES_ON_SQL_LAYER)) + HA_OPTION_RELIES_ON_SQL_LAYER | HA_OPTION_NULL_FIELDS)) { DBUG_PRINT("error",("wrong options: 0x%lx", share->options)); my_errno=HA_ERR_OLD_FILE; @@ -847,7 +847,8 @@ void _ma_setup_functions(register MARIA_SHARE *share) Calculate checksum according to data in the original, not compressed, row. */ - if (share->state.header.org_data_file_type == STATIC_RECORD) + if (share->state.header.org_data_file_type == STATIC_RECORD && + ! (share->options & HA_OPTION_NULL_FIELDS)) share->calc_checksum= _ma_static_checksum; else share->calc_checksum= _ma_checksum; @@ -881,7 +882,11 @@ void _ma_setup_functions(register MARIA_SHARE *share) share->update_record= _ma_update_static_record; share->write_record= _ma_write_static_record; share->compare_unique= _ma_cmp_static_unique; - share->calc_checksum= share->calc_write_checksum= _ma_static_checksum; + if (share->state.header.org_data_file_type == STATIC_RECORD && + ! (share->options & HA_OPTION_NULL_FIELDS)) + share->calc_checksum= _ma_static_checksum; + else + share->calc_checksum= _ma_checksum; break; case BLOCK_RECORD: share->once_init= _ma_once_init_block_record; diff --git a/storage/maria/ma_test1.c b/storage/maria/ma_test1.c index 45dffd279a0..e7cde8a7e28 100644 --- a/storage/maria/ma_test1.c +++ b/storage/maria/ma_test1.c @@ -119,6 +119,8 @@ static int run_test(const char *filename) recinfo[1].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : 24); if (extra_field == FIELD_VARCHAR) recinfo[1].length+= HA_VARCHAR_PACKLENGTH(recinfo[1].length); + recinfo[1].null_bit= null_fields ? 2 : 0; + if (opt_unique) { recinfo[2].type=FIELD_CHECK; @@ -186,7 +188,7 @@ static int run_test(const char *filename) uniques=0; offset_to_key= test(null_fields); - if (key_field == FIELD_BLOB) + if (key_field == FIELD_BLOB || key_field == FIELD_VARCHAR) offset_to_key+= 2; if (!silent) @@ -338,8 +340,7 @@ static int run_test(const char *filename) { fprintf(stderr, "delete-rows number of rows deleted; Going down hard!\n"); - VOID(maria_close(file)); - exit(0) ; + goto end; } j=i*2; if (!flags[j]) diff --git a/storage/maria/ma_test_recovery.expected b/storage/maria/ma_test_recovery.expected index 3ded68e7f56..55fe04cffdb 100644 --- a/storage/maria/ma_test_recovery.expected +++ b/storage/maria/ma_test_recovery.expected @@ -126,6 +126,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! > 1 2 6 unique number NULL 0 8192 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace --testflag=3 (commit at end) +Terminating after update TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace --testflag=4 --test-undo=1 (additional aborted work) terminating after deletes Dying on request without maria_commit()/maria_close() @@ -137,7 +138,7 @@ applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Checksum: 3536469224 +< Checksum: 3697324514 --- > Checksum: 0 11c11 @@ -204,6 +205,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! > 1 2 6 unique number NULL 0 8192 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace --testflag=3 (commit at end) +Terminating after update TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace --testflag=4 --test-undo=2 (additional aborted work) terminating after deletes Dying on request without maria_commit()/maria_close() @@ -215,7 +217,7 @@ applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Checksum: 3536469224 +< Checksum: 3697324514 --- > Checksum: 0 11c11 @@ -282,6 +284,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! > 1 2 6 unique number NULL 0 8192 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace --testflag=3 (commit at end) +Terminating after update TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace --testflag=4 --test-undo=3 (additional aborted work) terminating after deletes Dying on request without maria_commit()/maria_close() @@ -293,7 +296,7 @@ applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Checksum: 3536469224 +< Checksum: 3697324514 --- > Checksum: 0 11c11 @@ -319,7 +322,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 49152 Keyfile length: 16384 --- -> Datafile length: 57344 Keyfile length: 8192 +> Datafile length: 49152 Keyfile length: 8192 18c18 < 1 2 6 unique varchar BLOB NULL 0 8192 8192 --- @@ -336,7 +339,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 49152 Keyfile length: 16384 --- -> Datafile length: 57344 Keyfile length: 8192 +> Datafile length: 49152 Keyfile length: 8192 18c18 < 1 2 6 unique varchar BLOB NULL 0 8192 8192 --- @@ -353,13 +356,14 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 49152 Keyfile length: 16384 --- -> Datafile length: 57344 Keyfile length: 8192 +> Datafile length: 49152 Keyfile length: 8192 18c18 < 1 2 6 unique varchar BLOB NULL 0 8192 8192 --- > 1 2 6 unique varchar BLOB NULL 0 8192 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace -b --testflag=3 (commit at end) +Terminating after update TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace -b --testflag=4 --test-undo=1 (additional aborted work) terminating after deletes Dying on request without maria_commit()/maria_close() @@ -371,13 +375,13 @@ applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Checksum: 1984748106 +< Checksum: 4024695312 --- > Checksum: 0 11c11 -< Datafile length: 57344 Keyfile length: 16384 +< Datafile length: 49152 Keyfile length: 16384 --- -> Datafile length: 57344 Keyfile length: 8192 +> Datafile length: 49152 Keyfile length: 8192 18c18 < 1 2 6 unique varchar BLOB NULL 0 8192 8192 --- @@ -397,7 +401,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 49152 Keyfile length: 16384 --- -> Datafile length: 57344 Keyfile length: 8192 +> Datafile length: 49152 Keyfile length: 8192 18c18 < 1 2 6 unique varchar BLOB NULL 0 8192 8192 --- @@ -414,7 +418,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 49152 Keyfile length: 16384 --- -> Datafile length: 57344 Keyfile length: 8192 +> Datafile length: 49152 Keyfile length: 8192 18c18 < 1 2 6 unique varchar BLOB NULL 0 8192 8192 --- @@ -431,13 +435,14 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 49152 Keyfile length: 16384 --- -> Datafile length: 57344 Keyfile length: 8192 +> Datafile length: 49152 Keyfile length: 8192 18c18 < 1 2 6 unique varchar BLOB NULL 0 8192 8192 --- > 1 2 6 unique varchar BLOB NULL 0 8192 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace -b --testflag=3 (commit at end) +Terminating after update TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace -b --testflag=4 --test-undo=2 (additional aborted work) terminating after deletes Dying on request without maria_commit()/maria_close() @@ -449,13 +454,13 @@ applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Checksum: 1984748106 +< Checksum: 4024695312 --- > Checksum: 0 11c11 -< Datafile length: 57344 Keyfile length: 16384 +< Datafile length: 49152 Keyfile length: 16384 --- -> Datafile length: 57344 Keyfile length: 8192 +> Datafile length: 49152 Keyfile length: 8192 18c18 < 1 2 6 unique varchar BLOB NULL 0 8192 8192 --- @@ -516,6 +521,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! > 1 2 6 unique varchar BLOB NULL 0 8192 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace -b --testflag=3 (commit at end) +Terminating after update TEST WITH ma_test1 -s -M -T -c -N --debug=d:t:i:o,/tmp/ma_test1.trace -b --testflag=4 --test-undo=3 (additional aborted work) terminating after deletes Dying on request without maria_commit()/maria_close() @@ -527,13 +533,13 @@ applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Checksum: 1984748106 +< Checksum: 4024695312 --- > Checksum: 0 11c11 -< Datafile length: 57344 Keyfile length: 16384 +< Datafile length: 49152 Keyfile length: 16384 --- -> Datafile length: 57344 Keyfile length: 8192 +> Datafile length: 49152 Keyfile length: 8192 18c18 < 1 2 6 unique varchar BLOB NULL 0 8192 8192 --- diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 4f02705c18c..a9a9f44049f 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -252,7 +252,8 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, DBUG_PRINT("loop", ("found: 0x%lx recpos: %d minpos: %d length: %d", (long) found, recpos, minpos, length)); if (recpos != minpos) - { // Reserved space (Null bits?) + { + /* reserve space for null bits */ bzero((char*) recinfo_pos, sizeof(*recinfo_pos)); recinfo_pos->type= (int) FIELD_NORMAL; recinfo_pos++->length= (uint16) (minpos - recpos); diff --git a/storage/myisam/mi_test1.c b/storage/myisam/mi_test1.c index 1ceedf7f86a..4137b33fe42 100644 --- a/storage/myisam/mi_test1.c +++ b/storage/myisam/mi_test1.c @@ -79,6 +79,8 @@ static int run_test(const char *filename) recinfo[2].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : 24); if (extra_field == FIELD_VARCHAR) recinfo[2].length+= HA_VARCHAR_PACKLENGTH(recinfo[2].length); + recinfo[1].null_bit= null_fields ? 2 : 0; + if (opt_unique) { recinfo[3].type=FIELD_CHECK; @@ -258,7 +260,8 @@ static int run_test(const char *filename) continue; create_key(key,j); my_errno=0; - if ((error = mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))) + if ((error = mi_rkey(file,read_record,0,key,HA_WHOLE_KEY, + HA_READ_KEY_EXACT))) { if (verbose || (flags[j] >= 1 || (error && my_errno != HA_ERR_KEY_NOT_FOUND))) @@ -285,7 +288,7 @@ static int run_test(const char *filename) { create_key(key,i); my_errno=0; - error=mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT); + error=mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT); if (verbose || (error == 0 && flags[i] == 0 && unique_key) || (error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))