mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
Fixes after review of guilhem of block record patch
Short overview: Changed a lot of variable, functions, defines and struct elements to use more readable names More comments (mostly function and structure slot comments) Other things: Changed 'USE_WHOLE_KEY' to a big number to not interfer with long keys Ensure that tail block are at least of size 'MIN_TAIL_SIZE' Allow longer keys and key parts than before (don't limit Maria interface by HA_MAX_KEY_LENGTH) Use ma_chsize() to write initial bitmap page Added checking if using file with wrong block_size Added issing types to type_names[] (for maria_chk -d) Added maria_max_key_length() include/maria.h: Changed maria_portable_size_char_ptr to portable_size_char_ptr and moved it to my_handler.h Removed not used variable maria_delay_rec_write. More comments include/my_handler.h: Added portable_sizeof_char_ptr include/myisam.h: Changed mi_portable_size_char_ptr to portable_size_char_ptr and moved it to my_handler.h mysql-test/r/maria.result: Fix results when we now have a longer key length mysql-test/t/maria.test: More tests mysys/my_pread.c: Code cleanup sql/net_serv.cc: Changed warning to note (as in main 5.1 tree) to avoid not critical failing tests sql/sql_select.cc: Use portable_sizeof_char_ptr storage/maria/ha_maria.cc: Added max_supported_key_length(), as this is not a trival function anymore storage/maria/ha_maria.h: Moved max_supported_key_length(), as this is not a trival function anymore storage/maria/ma_bitmap.c: Lots of new comments Added maria_bitmap_marker[] to mark 2 last bytes of each bitmap (for corruption detection) Trivial code changes (based on review comments) storage/maria/ma_blockrec.c: More code comments Renamed _block_row() functions to _block_record() Trivial code changes, based on review comments Moved Code from maria_close() to _ma_end_block_record() Some function renames to make things more understandable DIR_ENTRY_OFFSET -> DIR_COUNT_OFFSET keybuff_used -> keyread_buff_used ma_recordpos_to_offset -> ma_recordpos_to_dir_entry Changed some 'rec' named variables to 'column'. Ensure that tail block are at least of size 'MIN_TAIL_SIZE' storage/maria/ma_blockrec.h: More comments DIRCOUNT_SIZE -> DIR_COUNT_SIZE Added define for maira_bitmap_marker[] ma_recordpos_to_offset -> ma_recordpos_to_dir_entry xxx_block_row() -> xxx_block_record() Made _ma_read_bitmap_page() static storage/maria/ma_check.c: More comments ma_recordpos_to_offset() -> ma_recordpos_to_dir_entry() DIR_ENTRY_OFFSET -> DIR_COUNT_OFFSET rec variables -> column variables recdef -> columndef storage/maria/ma_checksum.c: rec -> column Avoid an 'if' in _ma_checksum() for the common case storage/maria/ma_close.c: Moved resetting of info->dfile to ma_end_once_block_record() storage/maria/ma_create.c: Some variable changes to make things more readable: recinfo -> columndef rec -> column rec_end -> end_column record_type -> datafile_type ma_recinfo_write() -> ma_columndef_write() Fixed wrong setting of 'data_file_length'; Now max_rows should be calculated correctly New check if too long key. Use ma_chsize() to write bitmap page. storage/maria/ma_delete.c: keybuff_used -> keyread_buff_used storage/maria/ma_dynrec.c: rec -> columndef rec_length -> column_length maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr Better comment for _ma_read_rnd_dynamic_record() storage/maria/ma_ft_eval.c: maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/maria/ma_ft_test1.c: maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/maria/ma_ft_update.c: keybuff_used -> keyread_buff_used storage/maria/ma_info.c: More comments storage/maria/ma_open.c: Added checking if using file with wrong block_size New checking of max_key_length rec -> columndef _ma_recinfo_write -> _ma_columndef_write Don't change block_size (as this is checked in ma_create()) More comments storage/maria/ma_packrec.c: Trivial code changes rec -> columndef maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/maria/ma_page.c: keybuff_used -> keyread_buff_used storage/maria/ma_rkey.c: Removed not needded empty line storage/maria/ma_rrnd.c: Removed not used variable storage/maria/ma_rt_index.c: keybuff_used -> keyread_buff_used storage/maria/ma_search.c: keybuff_used -> keyread_buff_used Trivial code changes storage/maria/ma_sp_test.c: maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/maria/ma_test1.c: maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/maria/ma_test2.c: maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/maria/ma_update.c: Updated comment storage/maria/ma_write.c: keybuff_used -> keyread_buff_used storage/maria/maria_chk.c: Added missing types to type_names[] Removed not used variable rec -> columndef Replaced some numbers with define flags storage/maria/maria_def.h: More comments Added 'MARIA_INDEX_MIN_OVERHEAD_SIZE' rec -> columndef keybuff_used -> keyread_buff_used _ma_recinfo_write -> _ma_culumndef_write _ma_recinfo_read -> _ma_columndef_read Changed 'USE_WHOLE_KEY' to a big number to not interfer with long keys Added maria_max_key_length() storage/maria/maria_pack.c: Updated message strings rec -> columndef maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr More comments storage/myisam/ft_eval.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/myisam/ft_test1.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/myisam/mi_checksum.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/myisam/mi_create.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/myisam/mi_dynrec.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/myisam/mi_open.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/myisam/mi_packrec.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/myisam/mi_rkey.c: Unlock mutex also in case of error storage/myisam/mi_test1.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/myisam/mi_test2.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/myisam/myisampack.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr storage/myisam/sp_test.c: mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr support-files/magic: Fixed typo
This commit is contained in:
parent
1bf0ed7754
commit
eb7d9500a9
51 changed files with 997 additions and 555 deletions
|
@ -54,8 +54,6 @@ extern "C" {
|
|||
#define MARIA_KEY_BLOCK_LENGTH 8192 /* default key block length */
|
||||
#define MARIA_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */
|
||||
#define MARIA_MAX_KEY_BLOCK_LENGTH 32768
|
||||
#define maria_portable_sizeof_char_ptr 8
|
||||
#define MARIA_MAX_KEY_LENGTH 1000 /* Max length in bytes */
|
||||
|
||||
/*
|
||||
In the following macros '_keyno_' is 0 .. keys-1.
|
||||
|
@ -150,6 +148,7 @@ typedef struct st_maria_create_info
|
|||
ulonglong auto_increment;
|
||||
ulonglong data_file_length;
|
||||
ulonglong key_file_length;
|
||||
/* Size of null bitmap at start of row */
|
||||
uint null_bytes;
|
||||
uint old_options;
|
||||
enum data_file_type org_data_file_type;
|
||||
|
@ -226,11 +225,13 @@ typedef struct st_maria_columndef /* column information */
|
|||
uint64 offset; /* Offset to position in row */
|
||||
enum en_fieldtype type;
|
||||
uint16 length; /* length of field */
|
||||
/* Intern variable (size of total storage area for the row) */
|
||||
uint16 fill_length;
|
||||
uint16 null_pos; /* Position for null marker */
|
||||
uint16 empty_pos; /* Position for empty marker */
|
||||
uint8 null_bit; /* If column may be NULL */
|
||||
uint8 empty_bit; /* If column may be empty */
|
||||
/* Intern. Set if column should be zero packed (part of empty_bits) */
|
||||
uint8 empty_bit;
|
||||
|
||||
#ifndef NOT_PACKED_DATABASES
|
||||
void(*unpack)(struct st_maria_columndef *rec,
|
||||
|
@ -246,7 +247,7 @@ typedef struct st_maria_columndef /* column information */
|
|||
extern ulong maria_block_size;
|
||||
extern ulong maria_concurrent_insert;
|
||||
extern my_bool maria_flush, maria_single_user;
|
||||
extern my_bool maria_delay_key_write, maria_delay_rec_write;
|
||||
extern my_bool maria_delay_key_write;
|
||||
extern my_off_t maria_max_temp_length;
|
||||
extern ulong maria_bulk_insert_tree_size, maria_data_pointer_size;
|
||||
extern KEY_CACHE maria_key_cache_var, *maria_key_cache;
|
||||
|
|
|
@ -111,4 +111,11 @@ extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
|||
|
||||
extern HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a);
|
||||
|
||||
/*
|
||||
Inside an in-memory data record, memory pointers to pieces of the
|
||||
record (like BLOBs) are stored in their native byte order and in
|
||||
this amount of bytes.
|
||||
*/
|
||||
#define portable_sizeof_char_ptr 8
|
||||
|
||||
#endif /* _my_handler_h */
|
||||
|
|
|
@ -55,8 +55,6 @@ extern "C" {
|
|||
#define MI_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */
|
||||
#define MI_MAX_KEY_BLOCK_LENGTH 16384
|
||||
|
||||
#define mi_portable_sizeof_char_ptr 8
|
||||
|
||||
/*
|
||||
In the following macros '_keyno_' is 0 .. keys-1.
|
||||
If there can be more keys than bits in the key_map, the highest bit
|
||||
|
|
|
@ -325,10 +325,14 @@ Table Op Msg_type Msg_text
|
|||
test.t1 check status OK
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255), KEY t1 (a, b, c, d, e));
|
||||
ERROR 42000: Specified key was too long; max key length is 1000 bytes
|
||||
ERROR 42000: Specified key was too long; max key length is 1112 bytes
|
||||
CREATE TABLE t1 (a varchar(32000), unique key(a));
|
||||
ERROR 42000: Specified key was too long; max key length is 1112 bytes
|
||||
CREATE TABLE t1 (a varchar(1), b varchar(1), key (a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b));
|
||||
ERROR 42000: Too many key parts specified; max 16 parts allowed
|
||||
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255));
|
||||
ALTER TABLE t1 ADD INDEX t1 (a, b, c, d, e);
|
||||
ERROR 42000: Specified key was too long; max key length is 1000 bytes
|
||||
ERROR 42000: Specified key was too long; max key length is 1112 bytes
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a));
|
||||
INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,1,4);
|
||||
|
@ -1476,7 +1480,7 @@ a b
|
|||
drop table t1;
|
||||
create table t1 (v varchar(65530), key(v));
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 1000 bytes
|
||||
Warning 1071 Specified key was too long; max key length is 1112 bytes
|
||||
drop table if exists t1;
|
||||
create table t1 (v varchar(65536));
|
||||
Warnings:
|
||||
|
@ -1607,34 +1611,34 @@ t1 CREATE TABLE `t1` (
|
|||
drop table t1;
|
||||
create table t1 (a varchar(2048), key `a` (a));
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 1000 bytes
|
||||
Warning 1071 Specified key was too long; max key length is 1112 bytes
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(2048) DEFAULT NULL,
|
||||
KEY `a` (`a`(1000))
|
||||
KEY `a` (`a`(1112))
|
||||
) ENGINE=MARIA DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
create table t1 (a varchar(2048), key `a` (a) key_block_size=1024);
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 1000 bytes
|
||||
Warning 1071 Specified key was too long; max key length is 1112 bytes
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(2048) DEFAULT NULL,
|
||||
KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=8192
|
||||
KEY `a` (`a`(1112)) KEY_BLOCK_SIZE=8192
|
||||
) ENGINE=MARIA DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=1024;
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 1000 bytes
|
||||
Warning 1071 Specified key was too long; max key length is 1112 bytes
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
`b` varchar(2048) DEFAULT NULL,
|
||||
KEY `a` (`a`) KEY_BLOCK_SIZE=8192,
|
||||
KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192
|
||||
KEY `b` (`b`(1112)) KEY_BLOCK_SIZE=8192
|
||||
) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=1024
|
||||
alter table t1 key_block_size=2048;
|
||||
show create table t1;
|
||||
|
@ -1643,7 +1647,7 @@ t1 CREATE TABLE `t1` (
|
|||
`a` int(11) NOT NULL,
|
||||
`b` varchar(2048) DEFAULT NULL,
|
||||
KEY `a` (`a`) KEY_BLOCK_SIZE=8192,
|
||||
KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192
|
||||
KEY `b` (`b`(1112)) KEY_BLOCK_SIZE=8192
|
||||
) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2048
|
||||
alter table t1 add c int, add key (c);
|
||||
show create table t1;
|
||||
|
@ -1653,7 +1657,7 @@ t1 CREATE TABLE `t1` (
|
|||
`b` varchar(2048) DEFAULT NULL,
|
||||
`c` int(11) DEFAULT NULL,
|
||||
KEY `a` (`a`) KEY_BLOCK_SIZE=8192,
|
||||
KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192,
|
||||
KEY `b` (`b`(1112)) KEY_BLOCK_SIZE=8192,
|
||||
KEY `c` (`c`) KEY_BLOCK_SIZE=8192
|
||||
) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2048
|
||||
alter table t1 key_block_size=0;
|
||||
|
@ -1666,33 +1670,33 @@ t1 CREATE TABLE `t1` (
|
|||
`c` int(11) DEFAULT NULL,
|
||||
`d` int(11) DEFAULT NULL,
|
||||
KEY `a` (`a`) KEY_BLOCK_SIZE=8192,
|
||||
KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192,
|
||||
KEY `b` (`b`(1112)) KEY_BLOCK_SIZE=8192,
|
||||
KEY `c` (`c`) KEY_BLOCK_SIZE=8192,
|
||||
KEY `d` (`d`)
|
||||
) ENGINE=MARIA DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=8192;
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 1000 bytes
|
||||
Warning 1071 Specified key was too long; max key length is 1112 bytes
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
`b` varchar(2048) DEFAULT NULL,
|
||||
KEY `a` (`a`),
|
||||
KEY `b` (`b`(1000))
|
||||
KEY `b` (`b`(1112))
|
||||
) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8192
|
||||
drop table t1;
|
||||
create table t1 (a int not null, b varchar(2048), key (a) key_block_size=1024, key(b)) key_block_size=8192;
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 1000 bytes
|
||||
Warning 1071 Specified key was too long; max key length is 1112 bytes
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
`b` varchar(2048) DEFAULT NULL,
|
||||
KEY `a` (`a`),
|
||||
KEY `b` (`b`(1000))
|
||||
KEY `b` (`b`(1112))
|
||||
) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8192
|
||||
drop table t1;
|
||||
create table t1 (a int not null, b int, key (a) key_block_size=1024, key(b) key_block_size=8192) key_block_size=16384;
|
||||
|
@ -1715,12 +1719,12 @@ t1 CREATE TABLE `t1` (
|
|||
drop table t1;
|
||||
create table t1 (a varchar(2048), key `a` (a) key_block_size=1000000000000000000);
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 1000 bytes
|
||||
Warning 1071 Specified key was too long; max key length is 1112 bytes
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(2048) DEFAULT NULL,
|
||||
KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=8192
|
||||
KEY `a` (`a`(1112)) KEY_BLOCK_SIZE=8192
|
||||
) ENGINE=MARIA DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
create table t1 (a int not null, key `a` (a) key_block_size=1025);
|
||||
|
|
|
@ -345,6 +345,10 @@ drop table t1;
|
|||
|
||||
--error 1071
|
||||
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255), KEY t1 (a, b, c, d, e));
|
||||
--error 1071
|
||||
CREATE TABLE t1 (a varchar(32000), unique key(a));
|
||||
--error 1070
|
||||
CREATE TABLE t1 (a varchar(1), b varchar(1), key (a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b));
|
||||
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255));
|
||||
--error 1071
|
||||
ALTER TABLE t1 ADD INDEX t1 (a, b, c, d, e);
|
||||
|
|
|
@ -87,10 +87,8 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
|
|||
my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
|
||||
my_filename(Filedes),my_errno);
|
||||
else if (MyFlags & (MY_NABP | MY_FNABP))
|
||||
{
|
||||
my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
|
||||
my_filename(Filedes),my_errno);
|
||||
}
|
||||
}
|
||||
if ((int) readbytes == -1 || (MyFlags & (MY_FNABP | MY_NABP)))
|
||||
DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
|
||||
|
|
|
@ -298,8 +298,8 @@ void net_clear(NET *net, my_bool clear_buffer)
|
|||
{
|
||||
DBUG_PRINT("info",("skipped %d bytes from file: %s",
|
||||
count, vio_description(net->vio)));
|
||||
#if defined(EXTRA_DEBUG) && (MYSQL_VERSION_ID < 51000)
|
||||
fprintf(stderr,"Error: net_clear() skipped %d bytes from file: %s\n",
|
||||
#if defined(EXTRA_DEBUG) && (MYSQL_VERSION_ID < 50100)
|
||||
fprintf(stderr,"Note: net_clear() skipped %d bytes from file: %s\n",
|
||||
count, vio_description(net->vio));
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -9301,7 +9301,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
|||
table->s= share;
|
||||
init_tmp_table_share(share, "", 0, tmpname, tmpname);
|
||||
share->blob_field= blob_field;
|
||||
share->blob_ptr_size= mi_portable_sizeof_char_ptr;
|
||||
share->blob_ptr_size= portable_sizeof_char_ptr;
|
||||
share->db_low_byte_first=1; // True for HEAP and MyISAM
|
||||
share->table_charset= param->table_charset;
|
||||
share->primary_key= MAX_KEY; // Indicate no primary key
|
||||
|
@ -9856,7 +9856,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list)
|
|||
table->s= share;
|
||||
share->blob_field= blob_field;
|
||||
share->fields= field_count;
|
||||
share->blob_ptr_size= mi_portable_sizeof_char_ptr;
|
||||
share->blob_ptr_size= portable_sizeof_char_ptr;
|
||||
setup_tmp_table_column_bitmaps(table, bitmaps);
|
||||
|
||||
/* Create all fields and calculate the total length of record */
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "maria_def.h"
|
||||
#include "ma_rt_index.h"
|
||||
#include "ma_blockrec.h"
|
||||
|
||||
ulong maria_recover_options= HA_RECOVER_NONE;
|
||||
|
||||
|
@ -108,7 +109,6 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Convert TABLE object to Maria key and column definition
|
||||
|
||||
|
@ -512,6 +512,26 @@ double ha_maria::scan_time()
|
|||
return handler::scan_time();
|
||||
}
|
||||
|
||||
/*
|
||||
We need to be able to store at least two keys on an index page as the
|
||||
splitting algorithms depends on this. (With only one key on a page
|
||||
we also can't use any compression, which may make the index file much
|
||||
larger)
|
||||
We use HA_MAX_KEY_BUFF as this is a stack restriction imposed by the
|
||||
handler interface.
|
||||
|
||||
We also need to reserve place for a record pointer (8) and 3 bytes
|
||||
per key segment to store the length of the segment + possible null bytes.
|
||||
These extra bytes are required here so that maria_create() will surely
|
||||
accept any keys created which the returned key data storage length.
|
||||
*/
|
||||
|
||||
uint ha_maria::max_supported_key_length() const
|
||||
{
|
||||
uint tmp= (maria_max_key_length() - 8 - HA_MAX_KEY_SEG*3);
|
||||
return min(HA_MAX_KEY_BUFF, tmp);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_REPLICATION
|
||||
int ha_maria::net_read_dump(NET * net)
|
||||
|
|
|
@ -59,10 +59,9 @@ public:
|
|||
}
|
||||
uint max_supported_keys() const
|
||||
{ return MARIA_MAX_KEY; }
|
||||
uint max_supported_key_length() const
|
||||
{ return HA_MAX_KEY_LENGTH; }
|
||||
uint max_supported_key_length() const;
|
||||
uint max_supported_key_part_length() const
|
||||
{ return HA_MAX_KEY_LENGTH; }
|
||||
{ return max_supported_key_length(); }
|
||||
enum row_type get_row_type() const;
|
||||
uint checksum() const;
|
||||
virtual double scan_time();
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
2 bits are used to indicate:
|
||||
|
||||
0 Empty
|
||||
1 50-75 % full (at least room for 2 records)
|
||||
1 0-75 % full (at least room for 2 records)
|
||||
2 75-100 % full (at least room for one record)
|
||||
3 100 % full (no more room for records)
|
||||
|
||||
|
@ -89,9 +89,9 @@
|
|||
Bitmaps are read on demand in response to insert/delete/update operations.
|
||||
The following bitmap pointers will be cached and stored on disk on close:
|
||||
- Current insert_bitmap; When inserting new data we will first try to
|
||||
fill this one.
|
||||
fill this one.
|
||||
- First bitmap which is not completely full. This is updated when we
|
||||
free data with an update or delete.
|
||||
free data with an update or delete.
|
||||
|
||||
While flushing out bitmaps, we will cache the status of the bitmap in memory
|
||||
to avoid having to read a bitmap for insert of new data that will not
|
||||
|
@ -106,7 +106,6 @@
|
|||
put on disk even if they are not in the page cache).
|
||||
- When explicitely requested (for example on backup or after recvoery,
|
||||
to simplify things)
|
||||
|
||||
*/
|
||||
|
||||
#include "maria_def.h"
|
||||
|
@ -118,6 +117,15 @@
|
|||
#define FULL_HEAD_PAGE 4
|
||||
#define FULL_TAIL_PAGE 7
|
||||
|
||||
uchar maria_bitmap_marker[2]= {(uchar) 'b',(uchar) 'm'};
|
||||
|
||||
static my_bool _ma_read_bitmap_page(MARIA_SHARE *share,
|
||||
MARIA_FILE_BITMAP *bitmap,
|
||||
ulonglong page);
|
||||
|
||||
|
||||
/* Write bitmap page to key cache */
|
||||
|
||||
static inline my_bool write_changed_bitmap(MARIA_SHARE *share,
|
||||
MARIA_FILE_BITMAP *bitmap)
|
||||
{
|
||||
|
@ -128,7 +136,19 @@ static inline my_bool write_changed_bitmap(MARIA_SHARE *share,
|
|||
}
|
||||
|
||||
/*
|
||||
Initialize bitmap. This is called the first time a file is opened
|
||||
Initialize bitmap variables in share
|
||||
|
||||
SYNOPSIS
|
||||
_ma_bitmap_init()
|
||||
share Share handler
|
||||
file data file handler
|
||||
|
||||
NOTES
|
||||
This is called the first time a file is opened.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
|
||||
my_bool _ma_bitmap_init(MARIA_SHARE *share, File file)
|
||||
|
@ -175,20 +195,21 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file)
|
|||
Start by reading first page (assume table scan)
|
||||
Later code is simpler if it can assume we always have an active bitmap.
|
||||
*/
|
||||
if (_ma_read_bitmap_page(share, bitmap, (ulonglong) 0))
|
||||
return(1);
|
||||
return 0;
|
||||
return _ma_read_bitmap_page(share, bitmap, (ulonglong) 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Free data allocated by _ma_bitmap_init
|
||||
|
||||
SYNOPSIS
|
||||
_ma_bitmap_end()
|
||||
share Share handler
|
||||
*/
|
||||
|
||||
my_bool _ma_bitmap_end(MARIA_SHARE *share)
|
||||
{
|
||||
my_bool res= 0;
|
||||
_ma_flush_bitmap(share);
|
||||
my_bool res= _ma_flush_bitmap(share);
|
||||
pthread_mutex_destroy(&share->bitmap.bitmap_lock);
|
||||
my_free((byte*) share->bitmap.map, MYF(MY_ALLOW_ZERO_PTR));
|
||||
share->bitmap.map= 0;
|
||||
|
@ -198,6 +219,20 @@ my_bool _ma_bitmap_end(MARIA_SHARE *share)
|
|||
|
||||
/*
|
||||
Flush bitmap to disk
|
||||
|
||||
SYNOPSIS
|
||||
_ma_flush_bitmap()
|
||||
share Share handler
|
||||
|
||||
NOTES
|
||||
In the future, _ma_flush_bitmap() will be called to flush changes don't
|
||||
by this thread (ie, checking the changed flag is ok). The reason we
|
||||
check it again in the mutex is that if someone else did a flush at the
|
||||
same time, we don't have to do the write.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
|
||||
my_bool _ma_flush_bitmap(MARIA_SHARE *share)
|
||||
|
@ -217,12 +252,24 @@ my_bool _ma_flush_bitmap(MARIA_SHARE *share)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Intialize bitmap in memory to a zero bitmap
|
||||
|
||||
SYNOPSIS
|
||||
_ma_bitmap_delete_all()
|
||||
share Share handler
|
||||
|
||||
NOTES
|
||||
This is called on ma_delete_all (truncate data file).
|
||||
*/
|
||||
|
||||
void _ma_bitmap_delete_all(MARIA_SHARE *share)
|
||||
{
|
||||
MARIA_FILE_BITMAP *bitmap= &share->bitmap;
|
||||
if (bitmap->map) /* Not in create */
|
||||
{
|
||||
bzero(bitmap->map, share->block_size);
|
||||
memcpy(bitmap->map + share->block_size - 2, maria_bitmap_marker, 2);
|
||||
bitmap->changed= 0;
|
||||
bitmap->page= 0;
|
||||
bitmap->used_size= bitmap->total_size;
|
||||
|
@ -256,7 +303,15 @@ static uint size_to_head_pattern(MARIA_FILE_BITMAP *bitmap, uint size)
|
|||
|
||||
|
||||
/*
|
||||
Return bitmap pattern for block where there is size bytes free
|
||||
Return bitmap pattern for head block where there is size bytes free
|
||||
|
||||
SYNOPSIS
|
||||
_ma_free_size_to_head_pattern()
|
||||
bitmap Bitmap
|
||||
size Requested size
|
||||
|
||||
RETURN
|
||||
0-4 (Possible bitmap patterns for head block)
|
||||
*/
|
||||
|
||||
uint _ma_free_size_to_head_pattern(MARIA_FILE_BITMAP *bitmap, uint size)
|
||||
|
@ -294,6 +349,18 @@ static uint size_to_tail_pattern(MARIA_FILE_BITMAP *bitmap, uint size)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Return bitmap pattern for tail block where there is size bytes free
|
||||
|
||||
SYNOPSIS
|
||||
free_size_to_tail_pattern()
|
||||
bitmap Bitmap
|
||||
size Requested size
|
||||
|
||||
RETURN
|
||||
0, 5, 6, 7 For a description of the bitmap sizes, see the header
|
||||
*/
|
||||
|
||||
static uint free_size_to_tail_pattern(MARIA_FILE_BITMAP *bitmap, uint size)
|
||||
{
|
||||
if (size >= bitmap->sizes[0])
|
||||
|
@ -310,7 +377,7 @@ static uint free_size_to_tail_pattern(MARIA_FILE_BITMAP *bitmap, uint size)
|
|||
Return size guranteed to be available on a page
|
||||
|
||||
SYNOPSIS
|
||||
pattern_to_head_size
|
||||
pattern_to_head_size()
|
||||
bitmap Bitmap
|
||||
pattern Pattern (0-7)
|
||||
|
||||
|
@ -327,6 +394,15 @@ static inline uint pattern_to_size(MARIA_FILE_BITMAP *bitmap, uint pattern)
|
|||
|
||||
/*
|
||||
Print bitmap for debugging
|
||||
|
||||
SYNOPSIS
|
||||
_ma_print_bitmap()
|
||||
bitmap Bitmap to print
|
||||
|
||||
IMPLEMENTATION
|
||||
Prints all changed bits since last call to _ma_print_bitmap().
|
||||
This is done by having a copy of the last bitmap in
|
||||
bitmap->map+bitmap->block_size.
|
||||
*/
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
|
@ -342,18 +418,24 @@ static void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap)
|
|||
uchar *pos, *end, *org_pos;
|
||||
ulong page;
|
||||
|
||||
end= bitmap->map+ bitmap->used_size;
|
||||
end= bitmap->map + bitmap->used_size;
|
||||
DBUG_LOCK_FILE;
|
||||
fprintf(DBUG_FILE,"\nBitmap page changes at page %lu\n",
|
||||
(ulong) bitmap->page);
|
||||
|
||||
page= (ulong) bitmap->page+1;
|
||||
for (pos= bitmap->map, org_pos= bitmap->map+bitmap->block_size ; pos < end ;
|
||||
for (pos= bitmap->map, org_pos= bitmap->map + bitmap->block_size ;
|
||||
pos < end ;
|
||||
pos+= 6, org_pos+= 6)
|
||||
{
|
||||
ulonglong bits= uint6korr(pos); /* 6 bytes = 6*8/3= 16 patterns */
|
||||
ulonglong org_bits= uint6korr(org_pos);
|
||||
uint i;
|
||||
|
||||
/*
|
||||
Test if there is any changes in the next 16 bitmaps (to not have to
|
||||
loop through all bits if we know they are the same)
|
||||
*/
|
||||
if (bits != org_bits)
|
||||
{
|
||||
for (i= 0; i < 16 ; i++, bits>>= 3, org_bits>>= 3)
|
||||
|
@ -367,7 +449,7 @@ static void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap)
|
|||
}
|
||||
fputc('\n', DBUG_FILE);
|
||||
DBUG_UNLOCK_FILE;
|
||||
memcpy(bitmap->map+ bitmap->block_size, bitmap->map, bitmap->block_size);
|
||||
memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size);
|
||||
}
|
||||
|
||||
#endif /* DBUG_OFF */
|
||||
|
@ -394,8 +476,9 @@ static void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap)
|
|||
1 error (Error writing old bitmap or reading bitmap page)
|
||||
*/
|
||||
|
||||
my_bool _ma_read_bitmap_page(MARIA_SHARE *share, MARIA_FILE_BITMAP *bitmap,
|
||||
ulonglong page)
|
||||
static my_bool _ma_read_bitmap_page(MARIA_SHARE *share,
|
||||
MARIA_FILE_BITMAP *bitmap,
|
||||
ulonglong page)
|
||||
{
|
||||
my_off_t position= page * bitmap->block_size;
|
||||
my_bool res;
|
||||
|
@ -407,6 +490,7 @@ my_bool _ma_read_bitmap_page(MARIA_SHARE *share, MARIA_FILE_BITMAP *bitmap,
|
|||
{
|
||||
share->state.state.data_file_length= position + bitmap->block_size;
|
||||
bzero(bitmap->map, bitmap->block_size);
|
||||
memcpy(bitmap->map + share->block_size - 2, maria_bitmap_marker, 2);
|
||||
bitmap->used_size= 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
@ -417,7 +501,7 @@ my_bool _ma_read_bitmap_page(MARIA_SHARE *share, MARIA_FILE_BITMAP *bitmap,
|
|||
bitmap->block_size, bitmap->block_size, 0) == 0;
|
||||
#ifndef DBUG_OFF
|
||||
if (!res)
|
||||
memcpy(bitmap->map+ bitmap->block_size, bitmap->map, bitmap->block_size);
|
||||
memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size);
|
||||
#endif
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
@ -465,6 +549,10 @@ static my_bool _ma_change_bitmap_page(MARIA_HA *info,
|
|||
move_to_next_bitmap()
|
||||
bitmap Bitmap handle
|
||||
|
||||
NOTES
|
||||
The found bitmap may be full, so calling function may need to call this
|
||||
repeatedly until it finds enough space.
|
||||
|
||||
TODO
|
||||
Add cache of bitmaps to not read something that is not usable
|
||||
|
||||
|
@ -505,7 +593,12 @@ static my_bool move_to_next_bitmap(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap)
|
|||
best_data Pointer to best 6 byte aligned area in bitmap->map
|
||||
best_pos Which bit in *best_data the area starts
|
||||
0 = first bit pattern, 1 second bit pattern etc
|
||||
best_bits The original value of the bits at best_pos
|
||||
fill_pattern Bitmap pattern to store in best_data[best_pos]
|
||||
|
||||
NOTES
|
||||
We mark all pages to be 'TAIL's, which means that
|
||||
block->page_count is really a row position inside the page.
|
||||
*/
|
||||
|
||||
static void fill_block(MARIA_FILE_BITMAP *bitmap,
|
||||
|
@ -523,7 +616,7 @@ static void fill_block(MARIA_FILE_BITMAP *bitmap,
|
|||
block->empty_space= pattern_to_size(bitmap, best_bits);
|
||||
block->sub_blocks= 1;
|
||||
block->org_bitmap_value= best_bits;
|
||||
block->used= BLOCKUSED_TAIL;
|
||||
block->used= BLOCKUSED_TAIL; /* See _ma_bitmap_release_unused() */
|
||||
|
||||
/*
|
||||
Mark place used by reading/writing 2 bytes at a time to handle
|
||||
|
@ -533,6 +626,8 @@ static void fill_block(MARIA_FILE_BITMAP *bitmap,
|
|||
data= best_data+ best_pos / 8;
|
||||
offset= best_pos & 7;
|
||||
tmp= uint2korr(data);
|
||||
|
||||
/* we turn off the 3 bits and replace them with fill_pattern */
|
||||
tmp= (tmp & ~(7 << offset)) | (fill_pattern << offset);
|
||||
int2store(data, tmp);
|
||||
bitmap->changed= 1;
|
||||
|
@ -546,9 +641,14 @@ static void fill_block(MARIA_FILE_BITMAP *bitmap,
|
|||
SYNOPSIS
|
||||
allocate_head()
|
||||
bitmap bitmap
|
||||
size Size of block we need to find
|
||||
size Size of data region we need to store
|
||||
block Store found information here
|
||||
|
||||
IMPLEMENTATION
|
||||
Find the best-fit page to put a region of 'size'
|
||||
This is defined as the first page of the set of pages
|
||||
with the smallest free space that can hold 'size'.
|
||||
|
||||
RETURN
|
||||
0 ok (block is updated)
|
||||
1 error (no space in bitmap; block is not touched)
|
||||
|
@ -586,9 +686,10 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
|
|||
uint pattern= bits & 7;
|
||||
if (pattern <= min_bits)
|
||||
{
|
||||
/* There is enough space here */
|
||||
if (pattern == min_bits)
|
||||
{
|
||||
/* Found perfect match */
|
||||
/* There is exactly enough space here, return this page */
|
||||
best_bits= min_bits;
|
||||
best_data= data;
|
||||
best_pos= i;
|
||||
|
@ -596,6 +697,11 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
|
|||
}
|
||||
if ((int) pattern > (int) best_bits)
|
||||
{
|
||||
/*
|
||||
There is more than enough space here and it's better than what
|
||||
we have found so far. Remember it, as we will choose it if we
|
||||
don't find anything in this bitmap page.
|
||||
*/
|
||||
best_bits= pattern;
|
||||
best_data= data;
|
||||
best_pos= i;
|
||||
|
@ -603,10 +709,10 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!best_data)
|
||||
if (!best_data) /* Found no place */
|
||||
{
|
||||
if (bitmap->used_size == bitmap->total_size)
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(1); /* No space in bitmap */
|
||||
/* Allocate data at end of bitmap */
|
||||
bitmap->used_size+= 6;
|
||||
best_data= data;
|
||||
|
@ -655,7 +761,12 @@ static my_bool allocate_tail(MARIA_FILE_BITMAP *bitmap, uint size,
|
|||
/*
|
||||
Skip common patterns
|
||||
We can skip empty pages (if we already found a match) or
|
||||
the following patterns: 1-4 or 7
|
||||
the following patterns: 1-4 (head pages, not suitable for tail) or
|
||||
7 (full tail page). See 'Dynamic size records' comment at start of file.
|
||||
|
||||
At the moment we only skip full tail pages (ie, all bits are
|
||||
set) as this is easy to detect with one simple test and is a
|
||||
quite common case if we have blobs.
|
||||
*/
|
||||
|
||||
if ((!bits && best_data) || bits == LL(0xffffffffffff))
|
||||
|
@ -888,6 +999,13 @@ static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap,
|
|||
/*
|
||||
Find right bitmap and position for head block
|
||||
|
||||
SYNOPSIS
|
||||
find_head()
|
||||
info Maria handler
|
||||
length Size of data region we need store
|
||||
position Position in bitmap_blocks where to store the
|
||||
information for the head block.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
|
@ -897,7 +1015,10 @@ static my_bool find_head(MARIA_HA *info, uint length, uint position)
|
|||
{
|
||||
MARIA_FILE_BITMAP *bitmap= &info->s->bitmap;
|
||||
MARIA_BITMAP_BLOCK *block;
|
||||
/* There is always place for head blocks in bitmap_blocks */
|
||||
/*
|
||||
There is always place for the head block in bitmap_blocks as these are
|
||||
preallocated at _ma_init_block_record().
|
||||
*/
|
||||
block= dynamic_element(&info->bitmap_blocks, position, MARIA_BITMAP_BLOCK *);
|
||||
|
||||
while (allocate_head(bitmap, length, block))
|
||||
|
@ -910,6 +1031,13 @@ static my_bool find_head(MARIA_HA *info, uint length, uint position)
|
|||
/*
|
||||
Find right bitmap and position for tail
|
||||
|
||||
SYNOPSIS
|
||||
find_tail()
|
||||
info Maria handler
|
||||
length Size of data region we need store
|
||||
position Position in bitmap_blocks where to store the
|
||||
information for the head block.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
|
@ -936,8 +1064,15 @@ static my_bool find_tail(MARIA_HA *info, uint length, uint position)
|
|||
/*
|
||||
Find right bitmap and position for full blocks in one extent
|
||||
|
||||
SYNOPSIS
|
||||
find_mid()
|
||||
info Maria handler.
|
||||
pages How many pages to allocate.
|
||||
position Position in bitmap_blocks where to store the
|
||||
information for the head block.
|
||||
NOTES
|
||||
This is used to allocate the main extent after the 'head' block
|
||||
(Ie, the middle part of the head-middle-tail entry)
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
|
@ -962,6 +1097,11 @@ static my_bool find_mid(MARIA_HA *info, ulong pages, uint position)
|
|||
/*
|
||||
Find right bitmap and position for putting a blob
|
||||
|
||||
SYNOPSIS
|
||||
find_blob()
|
||||
info Maria handler.
|
||||
length Length of the blob
|
||||
|
||||
NOTES
|
||||
The extents are stored last in info->bitmap_blocks
|
||||
|
||||
|
@ -1023,6 +1163,19 @@ static my_bool find_blob(MARIA_HA *info, ulong length)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Find pages to put ALL blobs
|
||||
|
||||
SYNOPSIS
|
||||
allocate_blobs()
|
||||
info Maria handler
|
||||
row Information of what is in the row (from calc_record_size())
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
|
||||
static my_bool allocate_blobs(MARIA_HA *info, MARIA_ROW *row)
|
||||
{
|
||||
ulong *length, *end;
|
||||
|
@ -1045,6 +1198,23 @@ static my_bool allocate_blobs(MARIA_HA *info, MARIA_ROW *row)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Store in the bitmap the new size for a head page
|
||||
|
||||
SYNOPSIS
|
||||
use_head()
|
||||
info Maria handler
|
||||
page Page number to update
|
||||
(Note that caller guarantees this is in the active
|
||||
bitmap)
|
||||
size How much free space is left on the page
|
||||
block_position In which info->bitmap_block we have the
|
||||
information about the head block.
|
||||
|
||||
NOTES
|
||||
This is used on update where we are updating an existing head page
|
||||
*/
|
||||
|
||||
static void use_head(MARIA_HA *info, ulonglong page, uint size,
|
||||
uint block_position)
|
||||
{
|
||||
|
@ -1078,7 +1248,18 @@ static void use_head(MARIA_HA *info, ulonglong page, uint size,
|
|||
|
||||
|
||||
/*
|
||||
Find out where to split the row;
|
||||
Find out where to split the row (ie, what goes in head, middle, tail etc)
|
||||
|
||||
SYNOPSIS
|
||||
find_where_to_split_row()
|
||||
share Maria share
|
||||
row Information of what is in the row (from calc_record_size())
|
||||
extents_length Number of bytes needed to store all extents
|
||||
split_size Free size on the page (The head length must be less
|
||||
than this)
|
||||
|
||||
RETURN
|
||||
row_length for the head block.
|
||||
*/
|
||||
|
||||
static uint find_where_to_split_row(MARIA_SHARE *share, MARIA_ROW *row,
|
||||
|
@ -1108,6 +1289,21 @@ static uint find_where_to_split_row(MARIA_SHARE *share, MARIA_ROW *row,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Find where to write the middle parts of the row and the tail
|
||||
|
||||
SYNOPSIS
|
||||
write_rest_of_head()
|
||||
info Maria handler
|
||||
position Position in bitmap_blocks. Is 0 for rows that needs
|
||||
full blocks (ie, has a head, middle part and optional tail)
|
||||
rest_length How much left of the head block to write.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
|
||||
static my_bool write_rest_of_head(MARIA_HA *info, uint position,
|
||||
ulong rest_length)
|
||||
{
|
||||
|
@ -1349,6 +1545,23 @@ abort:
|
|||
Clear and reset bits
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
Set fill pattern for a page
|
||||
|
||||
set_page_bits()
|
||||
info Maria handler
|
||||
bitmap Bitmap handler
|
||||
page Adress to page
|
||||
fill_pattern Pattern (not size) for page
|
||||
|
||||
NOTES
|
||||
Page may not be part of active bitmap
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
|
||||
static my_bool set_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap,
|
||||
ulonglong page, uint fill_pattern)
|
||||
{
|
||||
|
@ -1390,11 +1603,10 @@ static my_bool set_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap,
|
|||
Get bitmap pattern for a given page
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
get_page_bits()
|
||||
info Maria handler
|
||||
bitmap Bitmap handler
|
||||
page Page number
|
||||
get_page_bits()
|
||||
info Maria handler
|
||||
bitmap Bitmap handler
|
||||
page Page number
|
||||
|
||||
RETURN
|
||||
0-7 Bitmap pattern
|
||||
|
@ -1432,7 +1644,7 @@ static uint get_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap,
|
|||
Mark all pages in a region as free
|
||||
|
||||
SYNOPSIS
|
||||
reset_full_page_bits()
|
||||
_ma_reset_full_page_bits()
|
||||
info Maria handler
|
||||
bitmap Bitmap handler
|
||||
page Start page
|
||||
|
@ -1579,6 +1791,11 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks)
|
|||
}
|
||||
else
|
||||
bits= block->org_bitmap_value;
|
||||
|
||||
/*
|
||||
The page has all bits set; The following test is an optimization
|
||||
to not set the bits to the same value as before.
|
||||
*/
|
||||
if (bits != FULL_TAIL_PAGE &&
|
||||
set_page_bits(info, bitmap, block->page, bits))
|
||||
goto err;
|
||||
|
@ -1638,8 +1855,22 @@ my_bool _ma_bitmap_free_full_pages(MARIA_HA *info, const byte *extents,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Mark in the bitmap how much free space there is on a page
|
||||
|
||||
my_bool _ma_bitmap_set(MARIA_HA *info, ulonglong pos, my_bool head,
|
||||
SYNOPSIS
|
||||
_ma_bitmap_set()
|
||||
info Mari handler
|
||||
page Adress to page
|
||||
head 1 if page is a head page, 0 if tail page
|
||||
empty_space How much empty space there is on page
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
|
||||
my_bool _ma_bitmap_set(MARIA_HA *info, ulonglong page, my_bool head,
|
||||
uint empty_space)
|
||||
{
|
||||
MARIA_FILE_BITMAP *bitmap= &info->s->bitmap;
|
||||
|
@ -1651,7 +1882,7 @@ my_bool _ma_bitmap_set(MARIA_HA *info, ulonglong pos, my_bool head,
|
|||
bits= (head ?
|
||||
_ma_free_size_to_head_pattern(bitmap, empty_space) :
|
||||
free_size_to_tail_pattern(bitmap, empty_space));
|
||||
res= set_page_bits(info, bitmap, pos, bits);
|
||||
res= set_page_bits(info, bitmap, page, bits);
|
||||
pthread_mutex_unlock(&info->s->bitmap.bitmap_lock);
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
@ -1663,6 +1894,15 @@ my_bool _ma_bitmap_set(MARIA_HA *info, ulonglong pos, my_bool head,
|
|||
NOTES
|
||||
Used in maria_chk
|
||||
|
||||
SYNOPSIS
|
||||
_ma_check_bitmap_data()
|
||||
info Maria handler
|
||||
page_type What kind of page this is
|
||||
page Adress to page
|
||||
empty_space Empty space on page
|
||||
bitmap_pattern Store here the pattern that was in the bitmap for the
|
||||
page. This is always updated.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
|
@ -1694,7 +1934,15 @@ my_bool _ma_check_bitmap_data(MARIA_HA *info,
|
|||
|
||||
|
||||
/*
|
||||
Check that bitmap pattern is correct for a page
|
||||
Check if the page type matches the one that we have in the bitmap
|
||||
|
||||
SYNOPSIS
|
||||
_ma_check_if_right_bitmap_type()
|
||||
info Maria handler
|
||||
page_type What kind of page this is
|
||||
page Adress to page
|
||||
bitmap_pattern Store here the pattern that was in the bitmap for the
|
||||
page. This is always updated.
|
||||
|
||||
NOTES
|
||||
Used in maria_chk
|
||||
|
|
|
@ -16,16 +16,19 @@
|
|||
/*
|
||||
Storage of records in block
|
||||
|
||||
Maria will have a LSN at start of each page (including the bitmap page)
|
||||
Maria will for each row have the additional information:
|
||||
Some clarifactions about the abbrev used:
|
||||
|
||||
TRANSID Transaction ID that last updated row (6 bytes)
|
||||
VER_PTR Version pointer that points on the UNDO entry that
|
||||
contains last version of the row versions (7 bytes)
|
||||
NULL fields -> Fields that may have contain a NULL value.
|
||||
Not null fields -> Fields that may not contain a NULL value.
|
||||
Critical fields -> Fields that can't be null and can't be dropped without
|
||||
causing a table reorganization.
|
||||
|
||||
|
||||
Maria will have a LSN at start of each page (excluding the bitmap pages)
|
||||
|
||||
The different page types that are in a data file are:
|
||||
|
||||
Bitmap pages Map of free pages in the next extent (8129 page size
|
||||
Bitmap pages Map of free pages in the next extent (8192 page size
|
||||
gives us 256M of mapped pages / bitmap)
|
||||
Head page Start of rows are stored on this page.
|
||||
A rowid always points to a head page
|
||||
|
@ -43,9 +46,9 @@
|
|||
Structure of data and tail page:
|
||||
|
||||
The page has a row directory at end of page to allow us to do deletes
|
||||
without having to reorganize the page. It also allows us to store some
|
||||
extra bytes after each row to allow them to grow without having to move
|
||||
around other rows
|
||||
without having to reorganize the page. It also allows us to later store
|
||||
some more bytes after each row to allow them to grow without having to move
|
||||
around other rows.
|
||||
|
||||
Page header:
|
||||
|
||||
|
@ -59,7 +62,7 @@
|
|||
|
||||
Row data
|
||||
|
||||
Row directory of NO entires, that consist of the following for each row
|
||||
Row directory of NO entries, that consist of the following for each row
|
||||
(in reverse order; ie, first record is stored last):
|
||||
|
||||
Position 2 bytes Position of row on page
|
||||
|
@ -69,7 +72,8 @@
|
|||
upmost bit of the length could be used for some states of the row (in
|
||||
other words, we should try to keep these reserved)
|
||||
|
||||
eof flag 1 byte Reserved for full page read testing
|
||||
eof flag 1 byte Reserved for full page read testing. (Ie, did the
|
||||
previous write get the whole block on disk.
|
||||
|
||||
----------------
|
||||
|
||||
|
@ -105,19 +109,27 @@
|
|||
Total length of length array 1-3 byte Only used if we have
|
||||
char/varchar/blob fields.
|
||||
Row checksum 1 byte Only if table created with checksums
|
||||
Null_bits .. One bit for each NULL field
|
||||
Empty_bits .. One bit for each NOT NULL field. This bit is
|
||||
0 if the value is 0 or empty string.
|
||||
Null_bits .. One bit for each NULL field (a field that may
|
||||
have the value NULL)
|
||||
Empty_bits .. One bit for each field that may be 'empty'.
|
||||
(Both for null and not null fields).
|
||||
This bit is 1 if the value for the field is
|
||||
0 or empty string.
|
||||
|
||||
field_offsets 2 byte/offset
|
||||
For each 32 field, there is one offset that
|
||||
points to where the field information starts
|
||||
in the block. This is to provide fast access
|
||||
to later field in the row when we only need
|
||||
to return a small set of fields.
|
||||
For each 32'th field, there is one offset
|
||||
that points to where the field information
|
||||
starts in the block. This is to provide
|
||||
fast access to later field in the row
|
||||
when we only need to return a small
|
||||
set of fields.
|
||||
TODO: Implement this.
|
||||
|
||||
Things marked above as 'optional' will only be present if the corresponding
|
||||
bit is set in 'Flag' field.
|
||||
Things marked above as 'optional' will only be present if the
|
||||
corresponding bit is set in 'Flag' field. Flag gives us a way to
|
||||
get more space on a page when doing page compaction as we don't need
|
||||
to store TRANSID that have committed before the smallest running
|
||||
transaction we have in memory.
|
||||
|
||||
Data in the following order:
|
||||
(Field order is precalculated when table is created)
|
||||
|
@ -176,11 +188,6 @@
|
|||
Nulls_extended_exists 3
|
||||
Row is split 7 This means that 'Number_of_row_extents' exists
|
||||
|
||||
|
||||
This would be a way to get more space on a page when doing page
|
||||
compaction as we don't need to store TRANSID that have committed
|
||||
before the smallest running transaction we have in memory.
|
||||
|
||||
Nulls_extended is the number of new DEFAULT NULL fields in the row
|
||||
compared to the number of DEFAULT NULL fields when the first version
|
||||
of the table was created. If Nulls_extended doesn't exist in the row,
|
||||
|
@ -198,8 +205,10 @@
|
|||
fields. When storing a row, we will mark a dropped field either with a
|
||||
null in the null bit map or in the empty_bits and not store any data
|
||||
for it.
|
||||
TODO: Add code for handling dropped fields.
|
||||
|
||||
One ROW_EXTENT is coded as:
|
||||
|
||||
A ROW EXTENT is range of pages. One ROW_EXTENT is coded as:
|
||||
|
||||
START_PAGE 5 bytes
|
||||
PAGE_COUNT 2 bytes. High bit is used to indicate tail page/
|
||||
|
@ -248,14 +257,36 @@
|
|||
#include "maria_def.h"
|
||||
#include "ma_blockrec.h"
|
||||
|
||||
/*
|
||||
Struct for having a cursor over a set of extent.
|
||||
This is used to loop over all extents for a row when reading
|
||||
the row data. It's also used to store the tail positions for
|
||||
a read row to be used by a later update/delete command.
|
||||
*/
|
||||
|
||||
typedef struct st_maria_extent_cursor
|
||||
{
|
||||
/*
|
||||
Pointer to packed byte array of extents for the row.
|
||||
Format is described above in the header
|
||||
*/
|
||||
byte *extent;
|
||||
byte *data_start; /* For error checking */
|
||||
/* Where data starts on page; Only for debugging */
|
||||
byte *data_start;
|
||||
/* Position to all tails in the row. Updated when reading a row */
|
||||
MARIA_RECORD_POS *tail_positions;
|
||||
/* Current page */
|
||||
my_off_t page;
|
||||
uint extent_count, page_count;
|
||||
uint tail; /* <> 0 if current extent is a tail page */
|
||||
/* How many pages in the page region */
|
||||
uint page_count;
|
||||
/* Total number of extents (ie, entries in the 'extent' slot) */
|
||||
uint extent_count;
|
||||
/* <> 0 if current extent is a tail page; Set while using cursor */
|
||||
uint tail;
|
||||
/*
|
||||
<> 1 if we are working on the first extent (ie, the one that is store in
|
||||
the row header, not an extent that is stored as part of the row data).
|
||||
*/
|
||||
my_bool first_extent;
|
||||
} MARIA_EXTENT_CURSOR;
|
||||
|
||||
|
@ -327,38 +358,47 @@ void _ma_init_block_record_data(void)
|
|||
}
|
||||
|
||||
|
||||
my_bool _ma_once_init_block_row(MARIA_SHARE *share, File data_file)
|
||||
my_bool _ma_once_init_block_record(MARIA_SHARE *share, File data_file)
|
||||
{
|
||||
|
||||
share->base.max_data_file_length=
|
||||
(((ulonglong) 1 << ((share->base.rec_reflength-1)*8))-1) *
|
||||
share->block_size;
|
||||
#if SIZEOF_OFF_T == 4
|
||||
set_if_smaller(max_data_file_length, INT_MAX32);
|
||||
set_if_smaller(share->base.max_data_file_length, INT_MAX32);
|
||||
#endif
|
||||
return _ma_bitmap_init(share, data_file);
|
||||
}
|
||||
|
||||
|
||||
my_bool _ma_once_end_block_row(MARIA_SHARE *share)
|
||||
my_bool _ma_once_end_block_record(MARIA_SHARE *share)
|
||||
{
|
||||
int res= _ma_bitmap_end(share);
|
||||
if (flush_key_blocks(share->key_cache, share->bitmap.file,
|
||||
share->temporary ? FLUSH_IGNORE_CHANGED :
|
||||
FLUSH_RELEASE))
|
||||
res= 1;
|
||||
if (share->bitmap.file >= 0 && my_close(share->bitmap.file, MYF(MY_WME)))
|
||||
res= 1;
|
||||
if (share->bitmap.file >= 0)
|
||||
{
|
||||
if (flush_key_blocks(share->key_cache, share->bitmap.file,
|
||||
share->temporary ? FLUSH_IGNORE_CHANGED :
|
||||
FLUSH_RELEASE))
|
||||
res= 1;
|
||||
if (my_close(share->bitmap.file, MYF(MY_WME)))
|
||||
res= 1;
|
||||
/*
|
||||
Trivial assignment to guard against multiple invocations
|
||||
(May happen if file are closed but we want to keep the maria object
|
||||
around a bit longer)
|
||||
*/
|
||||
share->bitmap.file= -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Init info->cur_row structure */
|
||||
|
||||
my_bool _ma_init_block_row(MARIA_HA *info)
|
||||
my_bool _ma_init_block_record(MARIA_HA *info)
|
||||
{
|
||||
MARIA_ROW *row= &info->cur_row, *new_row= &info->new_row;
|
||||
DBUG_ENTER("_ma_init_block_row");
|
||||
DBUG_ENTER("_ma_init_block_record");
|
||||
|
||||
if (!my_multi_malloc(MY_WME,
|
||||
&row->empty_bits_buffer, info->s->base.pack_bytes,
|
||||
|
@ -398,12 +438,18 @@ my_bool _ma_init_block_row(MARIA_HA *info)
|
|||
}
|
||||
|
||||
|
||||
void _ma_end_block_row(MARIA_HA *info)
|
||||
void _ma_end_block_record(MARIA_HA *info)
|
||||
{
|
||||
DBUG_ENTER("_ma_end_block_row");
|
||||
DBUG_ENTER("_ma_end_block_record");
|
||||
my_free((gptr) info->cur_row.empty_bits_buffer, MYF(MY_ALLOW_ZERO_PTR));
|
||||
delete_dynamic(&info->bitmap_blocks);
|
||||
my_free((gptr) info->cur_row.extents, MYF(MY_ALLOW_ZERO_PTR));
|
||||
/*
|
||||
The data file is closed, when needed, in ma_once_end_block_record().
|
||||
The following protects us from doing an extra, not allowed, close
|
||||
in maria_close()
|
||||
*/
|
||||
info->dfile= -1;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -412,7 +458,19 @@ void _ma_end_block_row(MARIA_HA *info)
|
|||
Helper functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint empty_pos_after_row(byte *dir)
|
||||
/*
|
||||
Return the next used byte on the page after a directory entry.
|
||||
|
||||
SYNOPSIS
|
||||
start_of_next_entry()
|
||||
dir Directory entry to be used
|
||||
|
||||
RETURN
|
||||
# Position in page where next entry starts.
|
||||
Everything between the '*dir' and this are free to be used.
|
||||
*/
|
||||
|
||||
static inline uint start_of_next_entry(byte *dir)
|
||||
{
|
||||
byte *prev;
|
||||
/*
|
||||
|
@ -427,6 +485,18 @@ static inline uint empty_pos_after_row(byte *dir)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Check that a region is all zero
|
||||
|
||||
SYNOPSIS
|
||||
check_if_zero()
|
||||
pos Start of memory to check
|
||||
length length of memory region
|
||||
|
||||
NOTES
|
||||
Used mainly to detect rows with wrong extent information
|
||||
*/
|
||||
|
||||
static my_bool check_if_zero(byte *pos, uint length)
|
||||
{
|
||||
byte *end;
|
||||
|
@ -438,7 +508,7 @@ static my_bool check_if_zero(byte *pos, uint length)
|
|||
|
||||
|
||||
/*
|
||||
Find free postion in directory
|
||||
Find free position in directory
|
||||
|
||||
SYNOPSIS
|
||||
find_free_position()
|
||||
|
@ -450,7 +520,7 @@ static my_bool check_if_zero(byte *pos, uint length)
|
|||
all empty space, including the found block.
|
||||
|
||||
NOTES
|
||||
If there is a free directory entry (entry with postion == 0),
|
||||
If there is a free directory entry (entry with position == 0),
|
||||
then use it and change it to be the size of the empty block
|
||||
after the previous entry. This guarantees that all row entries
|
||||
are stored on disk in inverse directory order, which makes life easier for
|
||||
|
@ -473,7 +543,7 @@ static my_bool check_if_zero(byte *pos, uint length)
|
|||
static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr,
|
||||
uint *res_length, uint *empty_space)
|
||||
{
|
||||
uint max_entry= (uint) ((uchar*) buff)[DIR_ENTRY_OFFSET];
|
||||
uint max_entry= (uint) ((uchar*) buff)[DIR_COUNT_OFFSET];
|
||||
uint entry, length, first_pos;
|
||||
byte *dir, *end;
|
||||
DBUG_ENTER("find_free_position");
|
||||
|
@ -482,22 +552,23 @@ static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr,
|
|||
dir= (buff + block_size - DIR_ENTRY_SIZE * max_entry - PAGE_SUFFIX_SIZE);
|
||||
end= buff + block_size - PAGE_SUFFIX_SIZE - DIR_ENTRY_SIZE;
|
||||
|
||||
first_pos= PAGE_HEADER_SIZE;
|
||||
*empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET);
|
||||
|
||||
/* Search after first empty position */
|
||||
first_pos= PAGE_HEADER_SIZE;
|
||||
for (entry= 0 ; dir <= end ; end-= DIR_ENTRY_SIZE, entry++)
|
||||
{
|
||||
if (end[0] == 0 && end[1] == 0) /* Found not used entry */
|
||||
uint tmp= uint2korr(end);
|
||||
if (!tmp) /* Found not used entry */
|
||||
{
|
||||
length= empty_pos_after_row(end) - first_pos;
|
||||
length= start_of_next_entry(end) - first_pos;
|
||||
int2store(end, first_pos); /* Update dir entry */
|
||||
int2store(end + 2, length);
|
||||
*res_rownr= entry;
|
||||
*res_length= length;
|
||||
DBUG_RETURN(end);
|
||||
}
|
||||
first_pos= uint2korr(end) + uint2korr(end + 2);
|
||||
first_pos= tmp + uint2korr(end + 2);
|
||||
}
|
||||
/* No empty places in dir; create a new one */
|
||||
dir= end;
|
||||
|
@ -513,7 +584,7 @@ static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr,
|
|||
uint2korr(end + DIR_ENTRY_SIZE+ 2));
|
||||
*empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET);
|
||||
}
|
||||
buff[DIR_ENTRY_OFFSET]= (byte) (uchar) max_entry+1;
|
||||
buff[DIR_COUNT_OFFSET]= (byte) (uchar) max_entry+1;
|
||||
length= (uint) (dir - buff - first_pos);
|
||||
DBUG_ASSERT(length <= *empty_space - DIR_ENTRY_SIZE);
|
||||
int2store(dir, first_pos);
|
||||
|
@ -551,7 +622,7 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
|
|||
{
|
||||
MARIA_SHARE *share= info->s;
|
||||
byte *field_length_data;
|
||||
MARIA_COLUMNDEF *rec, *end_field;
|
||||
MARIA_COLUMNDEF *column, *end_column;
|
||||
uint *null_field_lengths= row->null_field_lengths;
|
||||
ulong *blob_lengths= row->blob_lengths;
|
||||
|
||||
|
@ -562,56 +633,56 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
|
|||
bzero(row->empty_bits_buffer, share->base.pack_bytes);
|
||||
row->empty_bits= row->empty_bits_buffer;
|
||||
field_length_data= row->field_lengths;
|
||||
for (rec= share->rec + share->base.fixed_not_null_fields,
|
||||
end_field= share->rec + share->base.fields;
|
||||
rec < end_field; rec++, null_field_lengths++)
|
||||
for (column= share->columndef + share->base.fixed_not_null_fields,
|
||||
end_column= share->columndef + share->base.fields;
|
||||
column < end_column; column++, null_field_lengths++)
|
||||
{
|
||||
if ((record[rec->null_pos] & rec->null_bit))
|
||||
if ((record[column->null_pos] & column->null_bit))
|
||||
{
|
||||
if (rec->type != FIELD_BLOB)
|
||||
if (column->type != FIELD_BLOB)
|
||||
*null_field_lengths= 0;
|
||||
else
|
||||
*blob_lengths++= 0;
|
||||
continue;
|
||||
}
|
||||
switch ((enum en_fieldtype) rec->type) {
|
||||
switch ((enum en_fieldtype) column->type) {
|
||||
case FIELD_CHECK:
|
||||
case FIELD_NORMAL: /* Fixed length field */
|
||||
case FIELD_ZERO:
|
||||
DBUG_ASSERT(rec->empty_bit == 0);
|
||||
DBUG_ASSERT(column->empty_bit == 0);
|
||||
/* fall through */
|
||||
case FIELD_SKIP_PRESPACE: /* Not packed */
|
||||
row->normal_length+= rec->length;
|
||||
*null_field_lengths= rec->length;
|
||||
row->normal_length+= column->length;
|
||||
*null_field_lengths= column->length;
|
||||
break;
|
||||
case FIELD_SKIP_ZERO: /* Fixed length field */
|
||||
if (memcmp(record+ rec->offset, maria_zero_string,
|
||||
rec->length) == 0)
|
||||
if (memcmp(record+ column->offset, maria_zero_string,
|
||||
column->length) == 0)
|
||||
{
|
||||
row->empty_bits[rec->empty_pos] |= rec->empty_bit;
|
||||
row->empty_bits[column->empty_pos] |= column->empty_bit;
|
||||
*null_field_lengths= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
row->normal_length+= rec->length;
|
||||
*null_field_lengths= rec->length;
|
||||
row->normal_length+= column->length;
|
||||
*null_field_lengths= column->length;
|
||||
}
|
||||
break;
|
||||
case FIELD_SKIP_ENDSPACE: /* CHAR */
|
||||
{
|
||||
const char *pos, *end;
|
||||
for (pos= record + rec->offset, end= pos + rec->length;
|
||||
for (pos= record + column->offset, end= pos + column->length;
|
||||
end > pos && end[-1] == ' '; end--)
|
||||
;
|
||||
if (pos == end) /* If empty string */
|
||||
{
|
||||
row->empty_bits[rec->empty_pos]|= rec->empty_bit;
|
||||
row->empty_bits[column->empty_pos]|= column->empty_bit;
|
||||
*null_field_lengths= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint length= (end - pos);
|
||||
if (rec->length <= 255)
|
||||
if (column->length <= 255)
|
||||
*field_length_data++= (byte) (uchar) length;
|
||||
else
|
||||
{
|
||||
|
@ -626,11 +697,11 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
|
|||
case FIELD_VARCHAR:
|
||||
{
|
||||
uint length, field_length_data_length;
|
||||
const byte *field_pos= record + rec->offset;
|
||||
const byte *field_pos= record + column->offset;
|
||||
/* 256 is correct as this includes the length byte */
|
||||
|
||||
field_length_data[0]= field_pos[0];
|
||||
if (rec->length <= 256)
|
||||
if (column->length <= 256)
|
||||
{
|
||||
length= (uint) (uchar) *field_pos;
|
||||
field_length_data_length= 1;
|
||||
|
@ -644,7 +715,7 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
|
|||
*null_field_lengths= length;
|
||||
if (!length)
|
||||
{
|
||||
row->empty_bits[rec->empty_pos]|= rec->empty_bit;
|
||||
row->empty_bits[column->empty_pos]|= column->empty_bit;
|
||||
break;
|
||||
}
|
||||
row->varchar_length+= length;
|
||||
|
@ -654,13 +725,13 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
|
|||
}
|
||||
case FIELD_BLOB:
|
||||
{
|
||||
const byte *field_pos= record + rec->offset;
|
||||
uint size_length= rec->length - maria_portable_sizeof_char_ptr;
|
||||
const byte *field_pos= record + column->offset;
|
||||
uint size_length= column->length - portable_sizeof_char_ptr;
|
||||
ulong blob_length= _ma_calc_blob_length(size_length, field_pos);
|
||||
|
||||
*blob_lengths++= blob_length;
|
||||
if (!blob_length)
|
||||
row->empty_bits[rec->empty_pos]|= rec->empty_bit;
|
||||
row->empty_bits[column->empty_pos]|= column->empty_bit;
|
||||
else
|
||||
{
|
||||
row->blob_length+= blob_length;
|
||||
|
@ -709,7 +780,7 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
|
|||
static void compact_page(byte *buff, uint block_size, uint rownr,
|
||||
my_bool extend_block)
|
||||
{
|
||||
uint max_entry= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET];
|
||||
uint max_entry= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET];
|
||||
uint page_pos, next_free_pos, start_of_found_block, diff, end_of_found_block;
|
||||
byte *dir, *end;
|
||||
DBUG_ENTER("compact_page");
|
||||
|
@ -875,7 +946,7 @@ static my_bool get_head_or_tail_page(MARIA_HA *info,
|
|||
bzero(buff+ PAGE_HEADER_SIZE, block_size - PAGE_HEADER_SIZE);
|
||||
|
||||
buff[PAGE_TYPE_OFFSET]= (byte) page_type;
|
||||
buff[DIR_ENTRY_OFFSET]= 1;
|
||||
buff[DIR_COUNT_OFFSET]= 1;
|
||||
res->buff= buff;
|
||||
res->empty_space= res->length= (block_size - PAGE_OVERHEAD_SIZE);
|
||||
res->data= (buff + PAGE_HEADER_SIZE);
|
||||
|
@ -956,12 +1027,18 @@ static my_bool write_tail(MARIA_HA *info,
|
|||
DBUG_PRINT("enter", ("page: %lu length: %u",
|
||||
(ulong) block->page, length));
|
||||
|
||||
info->keybuff_used= 1;
|
||||
info->keyread_buff_used= 1;
|
||||
if (get_head_or_tail_page(info, block, info->keyread_buff, length,
|
||||
TAIL_PAGE, &row_pos))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
memcpy(row_pos.data, row_part, length);
|
||||
/*
|
||||
Don't allocate smaller block than MIN_TAIL_SIZE (we want to give rows
|
||||
some place to grow in the future)
|
||||
*/
|
||||
if (length < MIN_TAIL_SIZE)
|
||||
length= MIN_TAIL_SIZE;
|
||||
int2store(row_pos.dir + 2, length);
|
||||
empty_space= row_pos.empty_space - length;
|
||||
int2store(row_pos.buff + EMPTY_SPACE_OFFSET, empty_space);
|
||||
|
@ -969,10 +1046,10 @@ static my_bool write_tail(MARIA_HA *info,
|
|||
/*
|
||||
If there is less directory entries free than number of possible tails
|
||||
we can write for a row, we mark the page full to ensure that we don't
|
||||
during _ma_bitmap_find_place() allocate more entires on the tail page
|
||||
during _ma_bitmap_find_place() allocate more entries on the tail page
|
||||
than it can hold
|
||||
*/
|
||||
block->empty_space= ((uint) ((uchar*) row_pos.buff)[DIR_ENTRY_OFFSET] <=
|
||||
block->empty_space= ((uint) ((uchar*) row_pos.buff)[DIR_COUNT_OFFSET] <=
|
||||
MAX_ROWS_PER_PAGE - 1 - info->s->base.blobs ?
|
||||
empty_space : 0);
|
||||
block->used= BLOCKUSED_USED | BLOCKUSED_TAIL;
|
||||
|
@ -1015,7 +1092,7 @@ static my_bool write_full_pages(MARIA_HA *info,
|
|||
(ulong) length, (ulong) block->page,
|
||||
(ulong) block->page_count));
|
||||
|
||||
info->keybuff_used= 1;
|
||||
info->keyread_buff_used= 1;
|
||||
page= block->page;
|
||||
page_count= block->page_count;
|
||||
|
||||
|
@ -1134,7 +1211,7 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
|
|||
byte *page_buff;
|
||||
MARIA_BITMAP_BLOCK *block, *head_block;
|
||||
MARIA_SHARE *share;
|
||||
MARIA_COLUMNDEF *rec, *end_field;
|
||||
MARIA_COLUMNDEF *column, *end_column;
|
||||
uint block_size, flag;
|
||||
ulong *blob_lengths;
|
||||
my_off_t position;
|
||||
|
@ -1219,16 +1296,17 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
|
|||
}
|
||||
|
||||
/* Copy fields that has fixed lengths (primary key etc) */
|
||||
for (rec= share->rec, end_field= rec + share->base.fixed_not_null_fields;
|
||||
rec < end_field; rec++)
|
||||
for (column= share->columndef,
|
||||
end_column= column + share->base.fixed_not_null_fields;
|
||||
column < end_column; column++)
|
||||
{
|
||||
if (!tmp_data_used && tmp_data + rec->length > end_of_data)
|
||||
if (!tmp_data_used && tmp_data + column->length > end_of_data)
|
||||
{
|
||||
tmp_data_used= tmp_data;
|
||||
tmp_data= info->rec_buff;
|
||||
}
|
||||
memcpy(tmp_data, record + rec->offset, rec->length);
|
||||
tmp_data+= rec->length;
|
||||
memcpy(tmp_data, record + column->offset, column->length);
|
||||
tmp_data+= column->length;
|
||||
}
|
||||
|
||||
/* Copy length of data for variable length fields */
|
||||
|
@ -1242,26 +1320,26 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
|
|||
tmp_data+= row->field_lengths_length;
|
||||
|
||||
/* Copy variable length fields and fields with null/zero */
|
||||
for (end_field= share->rec + share->base.fields - share->base.blobs;
|
||||
rec < end_field ;
|
||||
rec++)
|
||||
for (end_column= share->columndef + share->base.fields - share->base.blobs;
|
||||
column < end_column ;
|
||||
column++)
|
||||
{
|
||||
const byte *field_pos;
|
||||
ulong length;
|
||||
if ((record[rec->null_pos] & rec->null_bit) ||
|
||||
(row->empty_bits[rec->empty_pos] & rec->empty_bit))
|
||||
if ((record[column->null_pos] & column->null_bit) ||
|
||||
(row->empty_bits[column->empty_pos] & column->empty_bit))
|
||||
continue;
|
||||
|
||||
field_pos= record + rec->offset;
|
||||
switch ((enum en_fieldtype) rec->type) {
|
||||
field_pos= record + column->offset;
|
||||
switch ((enum en_fieldtype) column->type) {
|
||||
case FIELD_NORMAL: /* Fixed length field */
|
||||
case FIELD_SKIP_PRESPACE:
|
||||
case FIELD_SKIP_ZERO: /* Fixed length field */
|
||||
length= rec->length;
|
||||
length= column->length;
|
||||
break;
|
||||
case FIELD_SKIP_ENDSPACE: /* CHAR */
|
||||
/* Char that is space filled */
|
||||
if (rec->length <= 255)
|
||||
if (column->length <= 255)
|
||||
length= (uint) (uchar) *field_length_data++;
|
||||
else
|
||||
{
|
||||
|
@ -1270,7 +1348,7 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
|
|||
}
|
||||
break;
|
||||
case FIELD_VARCHAR:
|
||||
if (rec->length <= 256)
|
||||
if (column->length <= 256)
|
||||
{
|
||||
length= (uint) (uchar) *field_length_data++;
|
||||
field_pos++; /* Skip length byte */
|
||||
|
@ -1298,21 +1376,21 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
|
|||
|
||||
block= head_block + head_block->sub_blocks; /* Point to first blob data */
|
||||
|
||||
end_field= rec + share->base.blobs;
|
||||
end_column= column + share->base.blobs;
|
||||
blob_lengths= row->blob_lengths;
|
||||
if (!tmp_data_used)
|
||||
{
|
||||
/* Still room on page; Copy as many blobs we can into this page */
|
||||
data= tmp_data;
|
||||
for (; rec < end_field && *blob_lengths < (ulong) (end_of_data - data);
|
||||
rec++, blob_lengths++)
|
||||
for (; column < end_column && *blob_lengths < (ulong) (end_of_data - data);
|
||||
column++, blob_lengths++)
|
||||
{
|
||||
byte *tmp_pos;
|
||||
uint length;
|
||||
if (!*blob_lengths) /* Null or "" */
|
||||
continue;
|
||||
length= rec->length - maria_portable_sizeof_char_ptr;
|
||||
memcpy_fixed((byte*) &tmp_pos, record + rec->offset + length,
|
||||
length= column->length - portable_sizeof_char_ptr;
|
||||
memcpy_fixed((byte*) &tmp_pos, record + column->offset + length,
|
||||
sizeof(char*));
|
||||
memcpy(data, tmp_pos, *blob_lengths);
|
||||
data+= *blob_lengths;
|
||||
|
@ -1342,7 +1420,7 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
|
|||
int2store(page_buff + EMPTY_SPACE_OFFSET, row_pos->empty_space);
|
||||
/* Mark in bitmaps how the current page was actually used */
|
||||
head_block->empty_space= row_pos->empty_space;
|
||||
if (page_buff[DIR_ENTRY_OFFSET] == (char) MAX_ROWS_PER_PAGE)
|
||||
if (page_buff[DIR_COUNT_OFFSET] == (char) MAX_ROWS_PER_PAGE)
|
||||
head_block->empty_space= 0; /* Page is full */
|
||||
head_block->used= BLOCKUSED_USED;
|
||||
}
|
||||
|
@ -1362,14 +1440,14 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
|
|||
|
||||
if (row_extents_in_use)
|
||||
{
|
||||
if (rec != end_field) /* If blob fields */
|
||||
if (column != end_column) /* If blob fields */
|
||||
{
|
||||
MARIA_COLUMNDEF *save_rec= rec;
|
||||
MARIA_COLUMNDEF *save_column= column;
|
||||
MARIA_BITMAP_BLOCK *save_block= block;
|
||||
MARIA_BITMAP_BLOCK *end_block;
|
||||
ulong *save_blob_lengths= blob_lengths;
|
||||
|
||||
for (; rec < end_field; rec++, blob_lengths++)
|
||||
for (; column < end_column; column++, blob_lengths++)
|
||||
{
|
||||
byte *blob_pos;
|
||||
if (!*blob_lengths) /* Null or "" */
|
||||
|
@ -1377,8 +1455,8 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
|
|||
if (block[block->sub_blocks - 1].used & BLOCKUSED_TAIL)
|
||||
{
|
||||
uint length;
|
||||
length= rec->length - maria_portable_sizeof_char_ptr;
|
||||
memcpy_fixed((byte *) &blob_pos, record + rec->offset + length,
|
||||
length= column->length - portable_sizeof_char_ptr;
|
||||
memcpy_fixed((byte *) &blob_pos, record + column->offset + length,
|
||||
sizeof(char*));
|
||||
length= *blob_lengths % FULL_PAGE_SIZE(block_size); /* tail size */
|
||||
if (write_tail(info, block + block->sub_blocks-1,
|
||||
|
@ -1395,7 +1473,7 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
|
|||
block->used|= BLOCKUSED_USED;
|
||||
}
|
||||
}
|
||||
rec= save_rec;
|
||||
column= save_column;
|
||||
block= save_block;
|
||||
blob_lengths= save_blob_lengths;
|
||||
}
|
||||
|
@ -1593,15 +1671,15 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
|
|||
}
|
||||
|
||||
/* Write rest of blobs (data, but no tails as they are already written) */
|
||||
for (; rec < end_field; rec++, blob_lengths++)
|
||||
for (; column < end_column; column++, blob_lengths++)
|
||||
{
|
||||
byte *blob_pos;
|
||||
uint length;
|
||||
ulong blob_length;
|
||||
if (!*blob_lengths) /* Null or "" */
|
||||
continue;
|
||||
length= rec->length - maria_portable_sizeof_char_ptr;
|
||||
memcpy_fixed((byte*) &blob_pos, record + rec->offset + length,
|
||||
length= column->length - portable_sizeof_char_ptr;
|
||||
memcpy_fixed((byte*) &blob_pos, record + column->offset + length,
|
||||
sizeof(char*));
|
||||
/* remove tail part */
|
||||
blob_length= *blob_lengths;
|
||||
|
@ -1705,7 +1783,7 @@ my_bool _ma_write_abort_block_record(MARIA_HA *info)
|
|||
|
||||
if (delete_head_or_tail(info,
|
||||
ma_recordpos_to_page(info->cur_row.lastpos),
|
||||
ma_recordpos_to_offset(info->cur_row.lastpos), 1))
|
||||
ma_recordpos_to_dir_entry(info->cur_row.lastpos), 1))
|
||||
res= 1;
|
||||
for (block= blocks->block + 1, end= block + blocks->count - 1; block < end;
|
||||
block++)
|
||||
|
@ -1764,7 +1842,7 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos,
|
|||
info->buff, block_size, block_size, 0)))
|
||||
DBUG_RETURN(1);
|
||||
org_empty_size= uint2korr(buff + EMPTY_SPACE_OFFSET);
|
||||
rownr= ma_recordpos_to_offset(record_pos);
|
||||
rownr= ma_recordpos_to_dir_entry(record_pos);
|
||||
dir= (buff + block_size - DIR_ENTRY_SIZE * rownr -
|
||||
DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE);
|
||||
|
||||
|
@ -1785,8 +1863,8 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos,
|
|||
if (new_row->total_length > length)
|
||||
{
|
||||
/* See if there is empty space after */
|
||||
if (rownr != (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET] - 1)
|
||||
empty= empty_pos_after_row(dir) - (offset + length);
|
||||
if (rownr != (uint) ((uchar *) buff)[DIR_COUNT_OFFSET] - 1)
|
||||
empty= start_of_next_entry(dir) - (offset + length);
|
||||
if (new_row->total_length > length + empty)
|
||||
{
|
||||
compact_page(buff, info->s->block_size, rownr, 1);
|
||||
|
@ -1876,14 +1954,14 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
|
|||
my_off_t position;
|
||||
DBUG_ENTER("delete_head_or_tail");
|
||||
|
||||
info->keybuff_used= 1;
|
||||
info->keyread_buff_used= 1;
|
||||
if (!(buff= key_cache_read(share->key_cache,
|
||||
info->dfile, page * block_size, 0,
|
||||
info->keyread_buff,
|
||||
block_size, block_size, 0)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
number_of_records= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET];
|
||||
number_of_records= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET];
|
||||
#ifdef SANITY_CHECKS
|
||||
if (record_number >= number_of_records ||
|
||||
record_number > ((block_size - LSN_SIZE - PAGE_TYPE_SIZE - 1 -
|
||||
|
@ -1911,7 +1989,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
|
|||
dir+= DIR_ENTRY_SIZE;
|
||||
empty_space+= DIR_ENTRY_SIZE;
|
||||
} while (dir < end && dir[0] == 0 && dir[1] == 0);
|
||||
buff[DIR_ENTRY_OFFSET]= (byte) (uchar) number_of_records;
|
||||
buff[DIR_COUNT_OFFSET]= (byte) (uchar) number_of_records;
|
||||
}
|
||||
empty_space+= length;
|
||||
if (number_of_records != 0)
|
||||
|
@ -1957,7 +2035,7 @@ static my_bool delete_tails(MARIA_HA *info, MARIA_RECORD_POS *tails)
|
|||
{
|
||||
if (delete_head_or_tail(info,
|
||||
ma_recordpos_to_page(*tails),
|
||||
ma_recordpos_to_offset(*tails), 0))
|
||||
ma_recordpos_to_dir_entry(*tails), 0))
|
||||
res= 1;
|
||||
}
|
||||
DBUG_RETURN(res);
|
||||
|
@ -1978,7 +2056,7 @@ my_bool _ma_delete_block_record(MARIA_HA *info)
|
|||
DBUG_ENTER("_ma_delete_block_record");
|
||||
if (delete_head_or_tail(info,
|
||||
ma_recordpos_to_page(info->cur_row.lastpos),
|
||||
ma_recordpos_to_offset(info->cur_row.lastpos),
|
||||
ma_recordpos_to_dir_entry(info->cur_row.lastpos),
|
||||
1) ||
|
||||
delete_tails(info, info->cur_row.tail_positions))
|
||||
DBUG_RETURN(1);
|
||||
|
@ -2011,7 +2089,7 @@ my_bool _ma_delete_block_record(MARIA_HA *info)
|
|||
static byte *get_record_position(byte *buff, uint block_size,
|
||||
uint record_number, byte **end_of_data)
|
||||
{
|
||||
uint number_of_records= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET];
|
||||
uint number_of_records= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET];
|
||||
byte *dir;
|
||||
byte *data;
|
||||
uint offset, length;
|
||||
|
@ -2254,7 +2332,7 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
|
|||
uint flag, null_bytes, cur_null_bytes, row_extents, field_lengths;
|
||||
my_bool found_blob= 0;
|
||||
MARIA_EXTENT_CURSOR extent;
|
||||
MARIA_COLUMNDEF *rec, *end_field;
|
||||
MARIA_COLUMNDEF *column, *end_column;
|
||||
DBUG_ENTER("_ma_read_block_record2");
|
||||
|
||||
LINT_INIT(field_lengths);
|
||||
|
@ -2347,15 +2425,16 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
|
|||
Data now points to start of fixed length field data that can't be null
|
||||
or 'empty'. Note that these fields can't be split over blocks
|
||||
*/
|
||||
for (rec= share->rec, end_field= rec + share->base.fixed_not_null_fields;
|
||||
rec < end_field; rec++)
|
||||
for (column= share->columndef,
|
||||
end_column= column + share->base.fixed_not_null_fields;
|
||||
column < end_column; column++)
|
||||
{
|
||||
uint rec_length= rec->length;
|
||||
uint column_length= column->length;
|
||||
if (data >= end_of_data &&
|
||||
!(data= read_next_extent(info, &extent, &end_of_data)))
|
||||
goto err;
|
||||
memcpy(record + rec->offset, data, rec_length);
|
||||
data+= rec_length;
|
||||
memcpy(record + column->offset, data, column_length);
|
||||
data+= column_length;
|
||||
}
|
||||
|
||||
/* Read array of field lengths. This may be stored in several extents */
|
||||
|
@ -2368,18 +2447,19 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
|
|||
}
|
||||
|
||||
/* Read variable length data. Each of these may be split over many extents */
|
||||
for (end_field= share->rec + share->base.fields; rec < end_field; rec++)
|
||||
for (end_column= share->columndef + share->base.fields;
|
||||
column < end_column; column++)
|
||||
{
|
||||
enum en_fieldtype type= (enum en_fieldtype) rec->type;
|
||||
byte *field_pos= record + rec->offset;
|
||||
enum en_fieldtype type= (enum en_fieldtype) column->type;
|
||||
byte *field_pos= record + column->offset;
|
||||
/* First check if field is present in record */
|
||||
if ((record[rec->null_pos] & rec->null_bit) ||
|
||||
(info->cur_row.empty_bits[rec->empty_pos] & rec->empty_bit))
|
||||
if ((record[column->null_pos] & column->null_bit) ||
|
||||
(info->cur_row.empty_bits[column->empty_pos] & column->empty_bit))
|
||||
{
|
||||
if (type == FIELD_SKIP_ENDSPACE)
|
||||
bfill(record + rec->offset, rec->length, ' ');
|
||||
bfill(record + column->offset, column->length, ' ');
|
||||
else
|
||||
bzero(record + rec->offset, rec->fill_length);
|
||||
bzero(record + column->offset, column->fill_length);
|
||||
continue;
|
||||
}
|
||||
switch (type) {
|
||||
|
@ -2389,14 +2469,14 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
|
|||
if (data >= end_of_data &&
|
||||
!(data= read_next_extent(info, &extent, &end_of_data)))
|
||||
goto err;
|
||||
memcpy(field_pos, data, rec->length);
|
||||
data+= rec->length;
|
||||
memcpy(field_pos, data, column->length);
|
||||
data+= column->length;
|
||||
break;
|
||||
case FIELD_SKIP_ENDSPACE: /* CHAR */
|
||||
{
|
||||
/* Char that is space filled */
|
||||
uint length;
|
||||
if (rec->length <= 255)
|
||||
if (column->length <= 255)
|
||||
length= (uint) (uchar) *field_length_data++;
|
||||
else
|
||||
{
|
||||
|
@ -2404,19 +2484,19 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
|
|||
field_length_data+= 2;
|
||||
}
|
||||
#ifdef SANITY_CHECKS
|
||||
if (length > rec->length)
|
||||
if (length > column->length)
|
||||
goto err;
|
||||
#endif
|
||||
if (read_long_data(info, field_pos, length, &extent, &data,
|
||||
&end_of_data))
|
||||
DBUG_RETURN(my_errno);
|
||||
bfill(field_pos + length, rec->length - length, ' ');
|
||||
bfill(field_pos + length, column->length - length, ' ');
|
||||
break;
|
||||
}
|
||||
case FIELD_VARCHAR:
|
||||
{
|
||||
ulong length;
|
||||
if (rec->length <= 256)
|
||||
if (column->length <= 256)
|
||||
{
|
||||
length= (uint) (uchar) (*field_pos++= *field_length_data++);
|
||||
}
|
||||
|
@ -2435,7 +2515,7 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
|
|||
}
|
||||
case FIELD_BLOB:
|
||||
{
|
||||
uint size_length= rec->length - maria_portable_sizeof_char_ptr;
|
||||
uint size_length= column->length - portable_sizeof_char_ptr;
|
||||
ulong blob_length= _ma_calc_blob_length(size_length, field_length_data);
|
||||
|
||||
if (!found_blob)
|
||||
|
@ -2443,17 +2523,17 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
|
|||
/* Calculate total length for all blobs */
|
||||
ulong blob_lengths= 0;
|
||||
byte *length_data= field_length_data;
|
||||
MARIA_COLUMNDEF *blob_field= rec;
|
||||
MARIA_COLUMNDEF *blob_field= column;
|
||||
|
||||
found_blob= 1;
|
||||
for (; blob_field < end_field; blob_field++)
|
||||
for (; blob_field < end_column; blob_field++)
|
||||
{
|
||||
uint size_length;
|
||||
if ((record[blob_field->null_pos] & blob_field->null_bit) ||
|
||||
(info->cur_row.empty_bits[blob_field->empty_pos] &
|
||||
blob_field->empty_bit))
|
||||
continue;
|
||||
size_length= blob_field->length - maria_portable_sizeof_char_ptr;
|
||||
size_length= blob_field->length - portable_sizeof_char_ptr;
|
||||
blob_lengths+= _ma_calc_blob_length(size_length, length_data);
|
||||
length_data+= size_length;
|
||||
}
|
||||
|
@ -2547,7 +2627,7 @@ int _ma_read_block_record(MARIA_HA *info, byte *record,
|
|||
|
||||
info->cur_row.lastpos= record_pos;
|
||||
page= ma_recordpos_to_page(record_pos) * block_size;
|
||||
offset= ma_recordpos_to_offset(record_pos);
|
||||
offset= ma_recordpos_to_dir_entry(record_pos);
|
||||
|
||||
if (!(buff= key_cache_read(info->s->key_cache,
|
||||
info->dfile, page, 0, info->buff,
|
||||
|
@ -2754,7 +2834,7 @@ restart_bitmap_scan:
|
|||
if (((info->scan.page_buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) !=
|
||||
HEAD_PAGE) ||
|
||||
(info->scan.number_of_rows=
|
||||
(uint) (uchar) info->scan.page_buff[DIR_ENTRY_OFFSET]) == 0)
|
||||
(uint) (uchar) info->scan.page_buff[DIR_COUNT_OFFSET]) == 0)
|
||||
{
|
||||
DBUG_PRINT("error", ("Wrong page header"));
|
||||
DBUG_RETURN((my_errno= HA_ERR_WRONG_IN_RECORD));
|
||||
|
@ -2818,7 +2898,7 @@ my_bool _ma_compare_block_record(MARIA_HA *info __attribute__ ((unused)),
|
|||
|
||||
static void _ma_print_directory(byte *buff, uint block_size)
|
||||
{
|
||||
uint max_entry= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET], row= 0;
|
||||
uint max_entry= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET], row= 0;
|
||||
uint end_of_prev_row= PAGE_HEADER_SIZE;
|
||||
byte *dir, *end;
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
*/
|
||||
|
||||
#define LSN_SIZE 7
|
||||
#define DIRCOUNT_SIZE 1 /* Stores number of rows on page */
|
||||
#define DIR_COUNT_SIZE 1 /* Stores number of rows on page */
|
||||
#define EMPTY_SPACE_SIZE 2 /* Stores empty space on page */
|
||||
#define PAGE_TYPE_SIZE 1
|
||||
#define PAGE_SUFFIX_SIZE 0 /* Bytes for page suffix */
|
||||
#define PAGE_HEADER_SIZE (LSN_SIZE + DIRCOUNT_SIZE + EMPTY_SPACE_SIZE +\
|
||||
#define PAGE_HEADER_SIZE (LSN_SIZE + DIR_COUNT_SIZE + EMPTY_SPACE_SIZE +\
|
||||
PAGE_TYPE_SIZE)
|
||||
#define PAGE_OVERHEAD_SIZE (PAGE_HEADER_SIZE + DIR_ENTRY_SIZE + \
|
||||
PAGE_SUFFIX_SIZE)
|
||||
|
@ -34,14 +34,18 @@
|
|||
#define ROW_EXTENT_COUNT_SIZE 2
|
||||
#define ROW_EXTENT_SIZE (ROW_EXTENT_PAGE_SIZE + ROW_EXTENT_COUNT_SIZE)
|
||||
#define TAIL_BIT 0x8000 /* Bit in page_count to signify tail */
|
||||
/* Number of extents reserved MARIA_BITMAP_BLOCKS to store head part */
|
||||
#define ELEMENTS_RESERVED_FOR_MAIN_PART 4
|
||||
/* Fields before 'row->null_field_lengths' used by find_where_to_split_row */
|
||||
#define EXTRA_LENGTH_FIELDS 3
|
||||
|
||||
/* Size for the different parts in the row header (and head page) */
|
||||
|
||||
#define FLAG_SIZE 1
|
||||
#define TRANSID_SIZE 6
|
||||
#define VERPTR_SIZE 7
|
||||
#define DIR_ENTRY_SIZE 4
|
||||
#define FIELD_OFFSET_SIZE 2
|
||||
#define FIELD_OFFSET_SIZE 2 /* size of pointers to field starts */
|
||||
|
||||
/* Minimum header size needed for a new row */
|
||||
#define BASE_ROW_HEADER_SIZE FLAG_SIZE
|
||||
|
@ -51,8 +55,8 @@
|
|||
enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_TYPE };
|
||||
|
||||
#define PAGE_TYPE_OFFSET LSN_SIZE
|
||||
#define DIR_ENTRY_OFFSET LSN_SIZE+PAGE_TYPE_SIZE
|
||||
#define EMPTY_SPACE_OFFSET (DIR_ENTRY_OFFSET + DIRCOUNT_SIZE)
|
||||
#define DIR_COUNT_OFFSET LSN_SIZE+PAGE_TYPE_SIZE
|
||||
#define EMPTY_SPACE_OFFSET (DIR_COUNT_OFFSET + DIR_COUNT_SIZE)
|
||||
|
||||
#define PAGE_CAN_BE_COMPACTED 128 /* Bit in PAGE_TYPE */
|
||||
|
||||
|
@ -64,10 +68,15 @@ enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_
|
|||
#define ROW_FLAG_EXTENTS 128
|
||||
#define ROW_FLAG_ALL (1+2+4+8+128)
|
||||
|
||||
/* Variables that affects how data pages are utilized */
|
||||
/******** Variables that affects how data pages are utilized ********/
|
||||
|
||||
/* Minium size of tail segment */
|
||||
#define MIN_TAIL_SIZE 32
|
||||
|
||||
/* Fixed part of Max possible header size; See table in ma_blockrec.c */
|
||||
/*
|
||||
Fixed length part of Max possible header size; See row data structure
|
||||
table in ma_blockrec.c.
|
||||
*/
|
||||
#define MAX_FIXED_HEADER_SIZE (FLAG_SIZE + 3 + ROW_EXTENT_SIZE + 3)
|
||||
#define TRANS_MAX_FIXED_HEADER_SIZE (MAX_FIXED_HEADER_SIZE + \
|
||||
TRANSID_SIZE + VERPTR_SIZE + \
|
||||
|
@ -77,21 +86,30 @@ enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_
|
|||
#define MAX_ROWS_PER_PAGE 255
|
||||
|
||||
/* Bits for MARIA_BITMAP_BLOCKS->used */
|
||||
/* We stored data on disk in the block */
|
||||
#define BLOCKUSED_USED 1
|
||||
/* Bitmap on disk is block->org_bitmap_value ; Happens only on update */
|
||||
#define BLOCKUSED_USE_ORG_BITMAP 2
|
||||
/* We stored tail data on disk for the block */
|
||||
#define BLOCKUSED_TAIL 4
|
||||
|
||||
/* defines that affects allocation (density) of data */
|
||||
/******* defines that affects allocation (density) of data *******/
|
||||
|
||||
/* If we fill up a block to 75 %, don't create a new tail page for it */
|
||||
/*
|
||||
If the tail part (from the main block or a blob) uses more than 75 % of
|
||||
the size of page, store the tail on a full page instead of a shared
|
||||
tail page.
|
||||
*/
|
||||
#define MAX_TAIL_SIZE(block_size) ((block_size) *3 / 4)
|
||||
|
||||
extern uchar maria_bitmap_marker[2];
|
||||
|
||||
/* Functions to convert MARIA_RECORD_POS to/from page:offset */
|
||||
|
||||
static inline MARIA_RECORD_POS ma_recordpos(ulonglong page, uint offset)
|
||||
static inline MARIA_RECORD_POS ma_recordpos(ulonglong page, uint dir_entry)
|
||||
{
|
||||
DBUG_ASSERT(offset <= 255);
|
||||
return (MARIA_RECORD_POS) ((page << 8) | offset);
|
||||
DBUG_ASSERT(dir_entry <= 255);
|
||||
return (MARIA_RECORD_POS) ((page << 8) | dir_entry);
|
||||
}
|
||||
|
||||
static inline my_off_t ma_recordpos_to_page(MARIA_RECORD_POS record_pos)
|
||||
|
@ -99,17 +117,17 @@ 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_offset(MARIA_RECORD_POS record_pos)
|
||||
static inline my_off_t ma_recordpos_to_dir_entry(MARIA_RECORD_POS record_pos)
|
||||
{
|
||||
return record_pos & 255;
|
||||
}
|
||||
|
||||
/* ma_blockrec.c */
|
||||
void _ma_init_block_record_data(void);
|
||||
my_bool _ma_once_init_block_row(MARIA_SHARE *share, File dfile);
|
||||
my_bool _ma_once_end_block_row(MARIA_SHARE *share);
|
||||
my_bool _ma_init_block_row(MARIA_HA *info);
|
||||
void _ma_end_block_row(MARIA_HA *info);
|
||||
my_bool _ma_once_init_block_record(MARIA_SHARE *share, File dfile);
|
||||
my_bool _ma_once_end_block_record(MARIA_SHARE *share);
|
||||
my_bool _ma_init_block_record(MARIA_HA *info);
|
||||
void _ma_end_block_record(MARIA_HA *info);
|
||||
|
||||
my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS pos,
|
||||
const byte *record);
|
||||
|
@ -136,8 +154,6 @@ my_bool _ma_compare_block_record(register MARIA_HA *info,
|
|||
my_bool _ma_bitmap_init(MARIA_SHARE *share, File file);
|
||||
my_bool _ma_bitmap_end(MARIA_SHARE *share);
|
||||
my_bool _ma_flush_bitmap(MARIA_SHARE *share);
|
||||
my_bool _ma_read_bitmap_page(MARIA_SHARE *share, MARIA_FILE_BITMAP *bitmap,
|
||||
ulonglong page);
|
||||
my_bool _ma_bitmap_find_place(MARIA_HA *info, MARIA_ROW *row,
|
||||
MARIA_BITMAP_BLOCKS *result_blocks);
|
||||
my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks);
|
||||
|
|
|
@ -941,7 +941,7 @@ static void record_pos_to_txt(MARIA_HA *info, my_off_t recpos,
|
|||
else
|
||||
{
|
||||
my_off_t page= ma_recordpos_to_page(recpos);
|
||||
uint row= ma_recordpos_to_offset(recpos);
|
||||
uint row= ma_recordpos_to_dir_entry(recpos);
|
||||
char *end= longlong10_to_str(page, buff, 10);
|
||||
*(end++)= ':';
|
||||
longlong10_to_str(row, end, 10);
|
||||
|
@ -1370,6 +1370,9 @@ end:
|
|||
|
||||
/*
|
||||
Check if layout on a page is ok
|
||||
|
||||
NOTES
|
||||
This is for rows-in-block format.
|
||||
*/
|
||||
|
||||
static int check_page_layout(HA_CHECK *param, MARIA_HA *info,
|
||||
|
@ -1442,6 +1445,8 @@ static int check_page_layout(HA_CHECK *param, MARIA_HA *info,
|
|||
Check all rows on head page
|
||||
|
||||
NOTES
|
||||
This is for rows-in-block format.
|
||||
|
||||
Before this, we have already called check_page_layout(), so
|
||||
we know the block is logicaly correct (even if the rows may not be that)
|
||||
|
||||
|
@ -1548,6 +1553,9 @@ static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, byte *record,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Check if rows-in-block data file is consistent
|
||||
*/
|
||||
|
||||
static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
||||
byte *record)
|
||||
|
@ -1638,7 +1646,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
|||
DBUG_ASSERT(0);
|
||||
break;
|
||||
case HEAD_PAGE:
|
||||
row_count= ((uchar*) page_buff)[DIR_ENTRY_OFFSET];
|
||||
row_count= ((uchar*) page_buff)[DIR_COUNT_OFFSET];
|
||||
empty_space= uint2korr(page_buff + EMPTY_SPACE_OFFSET);
|
||||
param->used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE +
|
||||
row_count * DIR_ENTRY_SIZE);
|
||||
|
@ -1647,7 +1655,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
|||
full_dir= row_count == MAX_ROWS_PER_PAGE;
|
||||
break;
|
||||
case TAIL_PAGE:
|
||||
row_count= ((uchar*) page_buff)[DIR_ENTRY_OFFSET];
|
||||
row_count= ((uchar*) page_buff)[DIR_COUNT_OFFSET];
|
||||
empty_space= uint2korr(page_buff + EMPTY_SPACE_OFFSET);
|
||||
param->used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE +
|
||||
row_count * DIR_ENTRY_SIZE);
|
||||
|
@ -1712,7 +1720,7 @@ err:
|
|||
}
|
||||
|
||||
|
||||
/* Check that record-link is ok */
|
||||
/* Check that record-link is ok */
|
||||
|
||||
int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend)
|
||||
{
|
||||
|
@ -4581,7 +4589,7 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
|
|||
MARIA_SHARE share;
|
||||
MARIA_KEYDEF *keyinfo,*key,*key_end;
|
||||
HA_KEYSEG *keysegs,*keyseg;
|
||||
MARIA_COLUMNDEF *recdef,*rec,*end;
|
||||
MARIA_COLUMNDEF *columndef,*column,*end;
|
||||
MARIA_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
|
||||
MARIA_STATUS_INFO status_info;
|
||||
uint unpack,key_parts;
|
||||
|
@ -4610,7 +4618,7 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
|
|||
my_afree((gptr) keyinfo);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (!(recdef=(MARIA_COLUMNDEF*)
|
||||
if (!(columndef=(MARIA_COLUMNDEF*)
|
||||
my_alloca(sizeof(MARIA_COLUMNDEF)*(share.base.fields+1))))
|
||||
{
|
||||
my_afree((gptr) keyinfo);
|
||||
|
@ -4620,22 +4628,24 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
|
|||
if (!(uniquedef=(MARIA_UNIQUEDEF*)
|
||||
my_alloca(sizeof(MARIA_UNIQUEDEF)*(share.state.header.uniques+1))))
|
||||
{
|
||||
my_afree((gptr) recdef);
|
||||
my_afree((gptr) columndef);
|
||||
my_afree((gptr) keyinfo);
|
||||
my_afree((gptr) keysegs);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/* Copy the column definitions */
|
||||
memcpy((byte*) recdef,(byte*) share.rec,
|
||||
memcpy((byte*) columndef,(byte*) share.columndef,
|
||||
(size_t) (sizeof(MARIA_COLUMNDEF)*(share.base.fields+1)));
|
||||
for (rec=recdef,end=recdef+share.base.fields; rec != end ; rec++)
|
||||
for (column=columndef, end= columndef+share.base.fields;
|
||||
column != end ;
|
||||
column++)
|
||||
{
|
||||
if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
|
||||
rec->type != FIELD_BLOB &&
|
||||
rec->type != FIELD_VARCHAR &&
|
||||
rec->type != FIELD_CHECK)
|
||||
rec->type=(int) FIELD_NORMAL;
|
||||
column->type != FIELD_BLOB &&
|
||||
column->type != FIELD_VARCHAR &&
|
||||
column->type != FIELD_CHECK)
|
||||
column->type=(int) FIELD_NORMAL;
|
||||
}
|
||||
|
||||
/* Change the new key to point at the saved key segments */
|
||||
|
@ -4710,7 +4720,7 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
|
|||
*/
|
||||
if (maria_create(filename, share.data_file_type,
|
||||
share.base.keys - share.state.header.uniques,
|
||||
keyinfo, share.base.fields, recdef,
|
||||
keyinfo, share.base.fields, columndef,
|
||||
share.state.header.uniques, uniquedef,
|
||||
&create_info,
|
||||
HA_DONT_TOUCH_DATA))
|
||||
|
@ -4751,7 +4761,7 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
|
|||
end:
|
||||
my_afree((gptr) uniquedef);
|
||||
my_afree((gptr) keyinfo);
|
||||
my_afree((gptr) recdef);
|
||||
my_afree((gptr) columndef);
|
||||
my_afree((gptr) keysegs);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
|
|
@ -20,29 +20,32 @@
|
|||
ha_checksum _ma_checksum(MARIA_HA *info, const byte *record)
|
||||
{
|
||||
ha_checksum crc=0;
|
||||
MARIA_COLUMNDEF *rec= info->s->rec, *rec_end= rec+ info->s->base.fields;
|
||||
MARIA_COLUMNDEF *column= info->s->columndef;
|
||||
MARIA_COLUMNDEF *column_end= column+ info->s->base.fields;
|
||||
|
||||
if (info->s->base.null_bytes)
|
||||
crc= my_checksum(crc, record, info->s->base.null_bytes);
|
||||
|
||||
for ( ; rec != rec_end ; rec++)
|
||||
for ( ; column != column_end ; column++)
|
||||
{
|
||||
const byte *pos= record + rec->offset;
|
||||
const byte *pos= record + column->offset;
|
||||
ulong length;
|
||||
|
||||
switch (rec->type) {
|
||||
switch (column->type) {
|
||||
case FIELD_BLOB:
|
||||
{
|
||||
length= _ma_calc_blob_length(rec->length-
|
||||
maria_portable_sizeof_char_ptr,
|
||||
pos);
|
||||
memcpy((char*) &pos, pos+rec->length- maria_portable_sizeof_char_ptr,
|
||||
sizeof(char*));
|
||||
break;
|
||||
uint blob_size_length= column->length- portable_sizeof_char_ptr;
|
||||
length= _ma_calc_blob_length(blob_size_length, pos);
|
||||
if (length)
|
||||
{
|
||||
memcpy((char*) &pos, pos + blob_size_length, sizeof(char*));
|
||||
crc= my_checksum(crc, pos, length);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case FIELD_VARCHAR:
|
||||
{
|
||||
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length-1);
|
||||
uint pack_length= HA_VARCHAR_PACKLENGTH(column->length-1);
|
||||
if (pack_length == 1)
|
||||
length= (ulong) *(uchar*) pos;
|
||||
else
|
||||
|
@ -51,10 +54,10 @@ ha_checksum _ma_checksum(MARIA_HA *info, const byte *record)
|
|||
break;
|
||||
}
|
||||
default:
|
||||
length= rec->length;
|
||||
length= column->length;
|
||||
break;
|
||||
}
|
||||
crc= my_checksum(crc, pos ? pos : "", length);
|
||||
crc= my_checksum(crc, pos, length);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
|
|
@ -69,10 +69,8 @@ int maria_close(register MARIA_HA *info)
|
|||
pthread_mutex_unlock(&share->intern_lock);
|
||||
|
||||
my_free(info->rec_buff, MYF(MY_ALLOW_ZERO_PTR));
|
||||
(share->end)(info);
|
||||
(*share->end)(info);
|
||||
|
||||
if (info->s->data_file_type == BLOCK_RECORD)
|
||||
info->dfile= -1; /* Closed in ma_end_once_block_row */
|
||||
if (flag)
|
||||
{
|
||||
if (share->kfile >= 0)
|
||||
|
|
|
@ -35,9 +35,9 @@ static int compare_columns(MARIA_COLUMNDEF **a, MARIA_COLUMNDEF **b);
|
|||
Old options is used when recreating database, from maria_chk
|
||||
*/
|
||||
|
||||
int maria_create(const char *name, enum data_file_type record_type,
|
||||
int maria_create(const char *name, enum data_file_type datafile_type,
|
||||
uint keys,MARIA_KEYDEF *keydefs,
|
||||
uint columns, MARIA_COLUMNDEF *recinfo,
|
||||
uint columns, MARIA_COLUMNDEF *columndef,
|
||||
uint uniques, MARIA_UNIQUEDEF *uniquedefs,
|
||||
MARIA_CREATE_INFO *ci,uint flags)
|
||||
{
|
||||
|
@ -55,12 +55,12 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
ulong pack_reclength;
|
||||
ulonglong tot_length,max_rows, tmp;
|
||||
enum en_fieldtype type;
|
||||
enum data_file_type org_record_type= record_type;
|
||||
enum data_file_type org_datafile_type= datafile_type;
|
||||
MARIA_SHARE share;
|
||||
MARIA_KEYDEF *keydef,tmp_keydef;
|
||||
MARIA_UNIQUEDEF *uniquedef;
|
||||
HA_KEYSEG *keyseg,tmp_keyseg;
|
||||
MARIA_COLUMNDEF *rec, *rec_end;
|
||||
MARIA_COLUMNDEF *column, *end_column;
|
||||
ulong *rec_per_key_part;
|
||||
my_off_t key_root[HA_MAX_POSSIBLE_KEY];
|
||||
MARIA_CREATE_INFO tmp_create_info;
|
||||
|
@ -70,6 +70,7 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u",
|
||||
keys, columns, uniques, flags));
|
||||
|
||||
DBUG_ASSERT(maria_block_size && maria_block_size % IO_SIZE == 0);
|
||||
LINT_INIT(dfile);
|
||||
LINT_INIT(file);
|
||||
|
||||
|
@ -89,7 +90,7 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
|
||||
if (flags & HA_DONT_TOUCH_DATA)
|
||||
{
|
||||
org_record_type= ci->org_data_file_type;
|
||||
org_datafile_type= ci->org_data_file_type;
|
||||
if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
|
||||
options=ci->old_options &
|
||||
(HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
|
||||
|
@ -117,83 +118,85 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
pack_reclength= max_field_lengths= 0;
|
||||
reclength= min_pack_length= ci->null_bytes;
|
||||
|
||||
for (rec= recinfo, rec_end= rec + columns ; rec != rec_end ; rec++)
|
||||
for (column= columndef, end_column= column + columns ;
|
||||
column != end_column ;
|
||||
column++)
|
||||
{
|
||||
/* Fill in not used struct parts */
|
||||
rec->offset= reclength;
|
||||
rec->empty_pos= 0;
|
||||
rec->empty_bit= 0;
|
||||
rec->fill_length= rec->length;
|
||||
column->offset= reclength;
|
||||
column->empty_pos= 0;
|
||||
column->empty_bit= 0;
|
||||
column->fill_length= column->length;
|
||||
|
||||
reclength+= rec->length;
|
||||
type= rec->type;
|
||||
if (type == FIELD_SKIP_PRESPACE && record_type == BLOCK_RECORD)
|
||||
reclength+= column->length;
|
||||
type= column->type;
|
||||
if (type == FIELD_SKIP_PRESPACE && datafile_type == BLOCK_RECORD)
|
||||
type= FIELD_NORMAL; /* SKIP_PRESPACE not supported */
|
||||
|
||||
if (type != FIELD_NORMAL && type != FIELD_CHECK)
|
||||
{
|
||||
rec->empty_pos= packed/8;
|
||||
rec->empty_bit= (1 << (packed & 7));
|
||||
column->empty_pos= packed/8;
|
||||
column->empty_bit= (1 << (packed & 7));
|
||||
if (type == FIELD_BLOB)
|
||||
{
|
||||
packed++;
|
||||
share.base.blobs++;
|
||||
if (pack_reclength != INT_MAX32)
|
||||
{
|
||||
if (rec->length == 4+maria_portable_sizeof_char_ptr)
|
||||
if (column->length == 4+portable_sizeof_char_ptr)
|
||||
pack_reclength= INT_MAX32;
|
||||
else
|
||||
{
|
||||
/* Add max possible blob length */
|
||||
pack_reclength+= (1 << ((rec->length-
|
||||
maria_portable_sizeof_char_ptr)*8));
|
||||
pack_reclength+= (1 << ((column->length-
|
||||
portable_sizeof_char_ptr)*8));
|
||||
}
|
||||
}
|
||||
max_field_lengths+= (rec->length - maria_portable_sizeof_char_ptr);
|
||||
max_field_lengths+= (column->length - portable_sizeof_char_ptr);
|
||||
}
|
||||
else if (type == FIELD_SKIP_PRESPACE ||
|
||||
type == FIELD_SKIP_ENDSPACE)
|
||||
{
|
||||
max_field_lengths+= rec->length > 255 ? 2 : 1;
|
||||
if (record_type != BLOCK_RECORD)
|
||||
max_field_lengths+= column->length > 255 ? 2 : 1;
|
||||
if (datafile_type != BLOCK_RECORD)
|
||||
min_pack_length++;
|
||||
packed++;
|
||||
}
|
||||
else if (type == FIELD_VARCHAR)
|
||||
{
|
||||
varchar_length+= rec->length-1; /* Used for min_pack_length */
|
||||
varchar_length+= column->length-1; /* Used for min_pack_length */
|
||||
pack_reclength++;
|
||||
if (record_type != BLOCK_RECORD)
|
||||
if (datafile_type != BLOCK_RECORD)
|
||||
min_pack_length++;
|
||||
max_field_lengths++;
|
||||
packed++;
|
||||
rec->fill_length= 1;
|
||||
column->fill_length= 1;
|
||||
/* We must test for 257 as length includes pack-length */
|
||||
if (test(rec->length >= 257))
|
||||
if (test(column->length >= 257))
|
||||
{
|
||||
long_varchar_count++;
|
||||
max_field_lengths++;
|
||||
rec->fill_length= 2;
|
||||
column->fill_length= 2;
|
||||
}
|
||||
}
|
||||
else if (type == FIELD_SKIP_ZERO)
|
||||
packed++;
|
||||
else
|
||||
{
|
||||
if (record_type != BLOCK_RECORD || !rec->null_bit)
|
||||
min_pack_length+= rec->length;
|
||||
rec->empty_pos= 0;
|
||||
rec->empty_bit= 0;
|
||||
if (datafile_type != BLOCK_RECORD || !column->null_bit)
|
||||
min_pack_length+= column->length;
|
||||
column->empty_pos= 0;
|
||||
column->empty_bit= 0;
|
||||
}
|
||||
}
|
||||
else /* FIELD_NORMAL */
|
||||
{
|
||||
if (record_type != BLOCK_RECORD || !rec->null_bit)
|
||||
min_pack_length+= rec->length;
|
||||
if (!rec->null_bit)
|
||||
if (datafile_type != BLOCK_RECORD || !column->null_bit)
|
||||
min_pack_length+= column->length;
|
||||
if (!column->null_bit)
|
||||
{
|
||||
share.base.fixed_not_null_fields++;
|
||||
share.base.fixed_not_null_fields_length+= rec->length;
|
||||
share.base.fixed_not_null_fields_length+= column->length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -203,14 +206,14 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
Not optimal packing, try to remove a 1 byte length zero-field as
|
||||
this will get same record length, but smaller pack overhead
|
||||
*/
|
||||
while (rec != recinfo)
|
||||
while (column != columndef)
|
||||
{
|
||||
rec--;
|
||||
if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1)
|
||||
column--;
|
||||
if (column->type == (int) FIELD_SKIP_ZERO && column->length == 1)
|
||||
{
|
||||
rec->type=(int) FIELD_NORMAL;
|
||||
rec->empty_pos= 0;
|
||||
rec->empty_bit= 0;
|
||||
column->type=(int) FIELD_NORMAL;
|
||||
column->empty_pos= 0;
|
||||
column->empty_bit= 0;
|
||||
packed--;
|
||||
min_pack_length++;
|
||||
break;
|
||||
|
@ -226,12 +229,12 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
if (pack_reclength != INT_MAX32)
|
||||
pack_reclength+= max_field_lengths + long_varchar_count;
|
||||
|
||||
if (packed && record_type == STATIC_RECORD)
|
||||
record_type= BLOCK_RECORD;
|
||||
if (record_type == DYNAMIC_RECORD)
|
||||
if (packed && datafile_type == STATIC_RECORD)
|
||||
datafile_type= BLOCK_RECORD;
|
||||
if (datafile_type == DYNAMIC_RECORD)
|
||||
options|= HA_OPTION_PACK_RECORD; /* Must use packed records */
|
||||
|
||||
if (record_type == STATIC_RECORD)
|
||||
if (datafile_type == STATIC_RECORD)
|
||||
{
|
||||
/* We can't use checksum with static length rows */
|
||||
flags&= ~HA_CREATE_CHECKSUM;
|
||||
|
@ -275,24 +278,24 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
}
|
||||
else if (!ci->max_rows)
|
||||
{
|
||||
if (record_type == BLOCK_RECORD)
|
||||
if (datafile_type == BLOCK_RECORD)
|
||||
{
|
||||
uint rows_per_page= ((maria_block_size - PAGE_OVERHEAD_SIZE) /
|
||||
(min_pack_length + extra_header_size +
|
||||
DIR_ENTRY_SIZE));
|
||||
ulonglong data_file_length= ci->data_file_length;
|
||||
if (data_file_length)
|
||||
if (!data_file_length)
|
||||
data_file_length= ((((ulonglong) 1 << ((BLOCK_RECORD_POINTER_SIZE-1) *
|
||||
8)) -1));
|
||||
if (rows_per_page > 0)
|
||||
{
|
||||
set_if_smaller(rows_per_page, MAX_ROWS_PER_PAGE);
|
||||
ci->max_rows= ci->data_file_length / maria_block_size * rows_per_page;
|
||||
ci->max_rows= data_file_length / maria_block_size * rows_per_page;
|
||||
}
|
||||
else
|
||||
ci->max_rows= ci->data_file_length / (min_pack_length +
|
||||
extra_header_size +
|
||||
DIR_ENTRY_SIZE);
|
||||
ci->max_rows= data_file_length / (min_pack_length +
|
||||
extra_header_size +
|
||||
DIR_ENTRY_SIZE);
|
||||
}
|
||||
else
|
||||
ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
|
||||
|
@ -301,7 +304,7 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
3 : 0)));
|
||||
}
|
||||
max_rows= (ulonglong) ci->max_rows;
|
||||
if (record_type == BLOCK_RECORD)
|
||||
if (datafile_type == BLOCK_RECORD)
|
||||
{
|
||||
/* The + 1 is for record position withing page */
|
||||
pointer= maria_get_pointer_length((ci->data_file_length /
|
||||
|
@ -314,7 +317,7 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (record_type != STATIC_RECORD)
|
||||
if (datafile_type != STATIC_RECORD)
|
||||
pointer= maria_get_pointer_length(ci->data_file_length,
|
||||
maria_data_pointer_size);
|
||||
else
|
||||
|
@ -324,7 +327,7 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
}
|
||||
|
||||
real_reclength=reclength;
|
||||
if (record_type == STATIC_RECORD)
|
||||
if (datafile_type == STATIC_RECORD)
|
||||
{
|
||||
if (reclength <= pointer)
|
||||
reclength=pointer+1; /* reserve place for delete link */
|
||||
|
@ -533,7 +536,12 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
key_segs)
|
||||
share.state.rec_per_key_part[key_segs-1]=1L;
|
||||
length+=key_length;
|
||||
if (length >= HA_MAX_KEY_BUFF)
|
||||
/*
|
||||
A key can't be longer than than half a index block (as we have
|
||||
to be able to put at least 2 keys on an index block for the key
|
||||
algorithms to work).
|
||||
*/
|
||||
if (length > maria_max_key_length())
|
||||
{
|
||||
my_errno=HA_WRONG_CREATE_OPTION;
|
||||
goto err_no_lock;
|
||||
|
@ -592,8 +600,8 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
mi_int2store(share.state.header.state_info_length,MARIA_STATE_INFO_SIZE);
|
||||
mi_int2store(share.state.header.base_info_length,MARIA_BASE_INFO_SIZE);
|
||||
mi_int2store(share.state.header.base_pos,base_pos);
|
||||
share.state.header.data_file_type= record_type;
|
||||
share.state.header.org_data_file_type= org_record_type;
|
||||
share.state.header.data_file_type= datafile_type;
|
||||
share.state.header.org_data_file_type= org_datafile_type;
|
||||
share.state.header.language= (ci->language ?
|
||||
ci->language : default_charset_info->number);
|
||||
|
||||
|
@ -653,7 +661,7 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
share.base.max_data_file_length= (my_off_t) ci->data_file_length;
|
||||
}
|
||||
|
||||
if (record_type == BLOCK_RECORD)
|
||||
if (datafile_type == BLOCK_RECORD)
|
||||
share.base.min_block_length= share.base.min_row_length;
|
||||
else
|
||||
{
|
||||
|
@ -869,21 +877,23 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
}
|
||||
}
|
||||
DBUG_PRINT("info", ("write field definitions"));
|
||||
if (record_type == BLOCK_RECORD)
|
||||
if (datafile_type == BLOCK_RECORD)
|
||||
{
|
||||
/* Store columns in a more efficent order */
|
||||
MARIA_COLUMNDEF **col_order, **pos;
|
||||
if (!(col_order= (MARIA_COLUMNDEF**) my_malloc(share.base.fields *
|
||||
sizeof(MARIA_COLUMNDEF*),
|
||||
MYF(MY_WME))))
|
||||
sizeof(MARIA_COLUMNDEF*),
|
||||
MYF(MY_WME))))
|
||||
goto err;
|
||||
for (rec= recinfo, pos= col_order ; rec != rec_end ; rec++, pos++)
|
||||
*pos= rec;
|
||||
for (column= columndef, pos= col_order ;
|
||||
column != end_column ;
|
||||
column++, pos++)
|
||||
*pos= column;
|
||||
qsort(col_order, share.base.fields, sizeof(*col_order),
|
||||
(qsort_cmp) compare_columns);
|
||||
for (i=0 ; i < share.base.fields ; i++)
|
||||
{
|
||||
if (_ma_recinfo_write(file, col_order[i]))
|
||||
if (_ma_columndef_write(file, col_order[i]))
|
||||
{
|
||||
my_free((gptr) col_order, MYF(0));
|
||||
goto err;
|
||||
|
@ -894,7 +904,7 @@ int maria_create(const char *name, enum data_file_type record_type,
|
|||
else
|
||||
{
|
||||
for (i=0 ; i < share.base.fields ; i++)
|
||||
if (_ma_recinfo_write(file, &recinfo[i]))
|
||||
if (_ma_columndef_write(file, &columndef[i]))
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -1026,9 +1036,9 @@ static int compare_columns(MARIA_COLUMNDEF **a_ptr, MARIA_COLUMNDEF **b_ptr)
|
|||
MARIA_COLUMNDEF *a= *a_ptr, *b= *b_ptr;
|
||||
enum en_fieldtype a_type, b_type;
|
||||
|
||||
a_type= (a->type == FIELD_NORMAL || a->type == FIELD_CHECK ?
|
||||
a_type= ((a->type == FIELD_NORMAL || a->type == FIELD_CHECK) ?
|
||||
FIELD_NORMAL : a->type);
|
||||
b_type= (b->type == FIELD_NORMAL || b->type == FIELD_CHECK ?
|
||||
b_type= ((b->type == FIELD_NORMAL || b->type == FIELD_CHECK) ?
|
||||
FIELD_NORMAL : b->type);
|
||||
|
||||
if (a_type == FIELD_NORMAL && !a->null_bit)
|
||||
|
@ -1059,15 +1069,8 @@ int _ma_initialize_data_file(File dfile, MARIA_SHARE *share)
|
|||
{
|
||||
if (share->data_file_type == BLOCK_RECORD)
|
||||
{
|
||||
/* Write one bitmap page */
|
||||
byte buff[IO_SIZE];
|
||||
uint i;
|
||||
bzero((char*) buff, sizeof(buff));
|
||||
if (my_seek(dfile, 0, SEEK_SET, 0))
|
||||
if (my_chsize(dfile, maria_block_size, 0, MYF(MY_WME)))
|
||||
return 1;
|
||||
for (i= 0 ; i < maria_block_size ; i+= IO_SIZE)
|
||||
if (my_write(dfile, buff, sizeof(buff), MYF(MY_NABP)))
|
||||
return 1;
|
||||
share->state.state.data_file_length= maria_block_size;
|
||||
_ma_bitmap_delete_all(share);
|
||||
}
|
||||
|
|
|
@ -525,7 +525,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
|
|||
DBUG_DUMP("leaf_buff",leaf_buff,maria_getint(leaf_buff));
|
||||
|
||||
buff=info->buff;
|
||||
info->keybuff_used=1;
|
||||
info->keyread_buff_used=1;
|
||||
next_keypos=keypos;
|
||||
nod_flag=_ma_test_if_nod(leaf_buff);
|
||||
p_length=nod_flag+2;
|
||||
|
|
|
@ -883,7 +883,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
|
|||
uint length,new_length,flag,bit,i;
|
||||
char *pos,*end,*startpos,*packpos;
|
||||
enum en_fieldtype type;
|
||||
reg3 MARIA_COLUMNDEF *rec;
|
||||
reg3 MARIA_COLUMNDEF *column;
|
||||
MARIA_BLOB *blob;
|
||||
DBUG_ENTER("_ma_rec_pack");
|
||||
|
||||
|
@ -892,7 +892,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
|
|||
startpos= packpos=to;
|
||||
to+= info->s->base.pack_bytes;
|
||||
blob= info->blobs;
|
||||
rec= info->s->rec;
|
||||
column= info->s->columndef;
|
||||
if (info->s->base.null_bytes)
|
||||
{
|
||||
memcpy(to, from, info->s->base.null_bytes);
|
||||
|
@ -900,10 +900,10 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
|
|||
to+= info->s->base.null_bytes;
|
||||
}
|
||||
|
||||
for (i=info->s->base.fields ; i-- > 0; from+= length,rec++)
|
||||
for (i=info->s->base.fields ; i-- > 0; from+= length, column++)
|
||||
{
|
||||
length=(uint) rec->length;
|
||||
if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL)
|
||||
length=(uint) column->length;
|
||||
if ((type = (enum en_fieldtype) column->type) != FIELD_NORMAL)
|
||||
{
|
||||
if (type == FIELD_BLOB)
|
||||
{
|
||||
|
@ -912,7 +912,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
|
|||
else
|
||||
{
|
||||
char *temp_pos;
|
||||
size_t tmp_length=length-maria_portable_sizeof_char_ptr;
|
||||
size_t tmp_length=length-portable_sizeof_char_ptr;
|
||||
memcpy((byte*) to,from,tmp_length);
|
||||
memcpy_fixed(&temp_pos,from+tmp_length,sizeof(char*));
|
||||
memcpy(to+tmp_length,temp_pos,(size_t) blob->length);
|
||||
|
@ -944,10 +944,10 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
|
|||
pos++;
|
||||
}
|
||||
new_length=(uint) (end-pos);
|
||||
if (new_length +1 + test(rec->length > 255 && new_length > 127)
|
||||
if (new_length +1 + test(column->length > 255 && new_length > 127)
|
||||
< length)
|
||||
{
|
||||
if (rec->length > 255 && new_length > 127)
|
||||
if (column->length > 255 && new_length > 127)
|
||||
{
|
||||
to[0]=(char) ((new_length & 127)+128);
|
||||
to[1]=(char) (new_length >> 7);
|
||||
|
@ -965,7 +965,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
|
|||
}
|
||||
else if (type == FIELD_VARCHAR)
|
||||
{
|
||||
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
|
||||
uint pack_length= HA_VARCHAR_PACKLENGTH(column->length -1);
|
||||
uint tmp_length;
|
||||
if (pack_length == 1)
|
||||
{
|
||||
|
@ -1018,28 +1018,28 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff,
|
|||
uint length,new_length,flag,bit,i;
|
||||
char *pos,*end,*packpos,*to;
|
||||
enum en_fieldtype type;
|
||||
reg3 MARIA_COLUMNDEF *rec;
|
||||
reg3 MARIA_COLUMNDEF *column;
|
||||
DBUG_ENTER("_ma_rec_check");
|
||||
|
||||
packpos=rec_buff; to= rec_buff+info->s->base.pack_bytes;
|
||||
rec=info->s->rec;
|
||||
column= info->s->columndef;
|
||||
flag= *packpos; bit=1;
|
||||
record+= info->s->base.null_bytes;
|
||||
to+= info->s->base.null_bytes;
|
||||
|
||||
for (i=info->s->base.fields ; i-- > 0; record+= length, rec++)
|
||||
for (i=info->s->base.fields ; i-- > 0; record+= length, column++)
|
||||
{
|
||||
length=(uint) rec->length;
|
||||
if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL)
|
||||
length=(uint) column->length;
|
||||
if ((type = (enum en_fieldtype) column->type) != FIELD_NORMAL)
|
||||
{
|
||||
if (type == FIELD_BLOB)
|
||||
{
|
||||
uint blob_length=
|
||||
_ma_calc_blob_length(length-maria_portable_sizeof_char_ptr,record);
|
||||
_ma_calc_blob_length(length-portable_sizeof_char_ptr,record);
|
||||
if (!blob_length && !(flag & bit))
|
||||
goto err;
|
||||
if (blob_length)
|
||||
to+=length - maria_portable_sizeof_char_ptr+ blob_length;
|
||||
to+=length - portable_sizeof_char_ptr+ blob_length;
|
||||
}
|
||||
else if (type == FIELD_SKIP_ZERO)
|
||||
{
|
||||
|
@ -1066,12 +1066,12 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff,
|
|||
pos++;
|
||||
}
|
||||
new_length=(uint) (end-pos);
|
||||
if (new_length +1 + test(rec->length > 255 && new_length > 127)
|
||||
if (new_length +1 + test(column->length > 255 && new_length > 127)
|
||||
< length)
|
||||
{
|
||||
if (!(flag & bit))
|
||||
goto err;
|
||||
if (rec->length > 255 && new_length > 127)
|
||||
if (column->length > 255 && new_length > 127)
|
||||
{
|
||||
if (to[0] != (char) ((new_length & 127)+128) ||
|
||||
to[1] != (char) (new_length >> 7))
|
||||
|
@ -1087,7 +1087,7 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff,
|
|||
}
|
||||
else if (type == FIELD_VARCHAR)
|
||||
{
|
||||
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
|
||||
uint pack_length= HA_VARCHAR_PACKLENGTH(column->length -1);
|
||||
uint tmp_length;
|
||||
if (pack_length == 1)
|
||||
{
|
||||
|
@ -1139,10 +1139,10 @@ err:
|
|||
ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
|
||||
ulong found_length)
|
||||
{
|
||||
uint flag,bit,length,rec_length,min_pack_length;
|
||||
uint flag,bit,length,min_pack_length, column_length;
|
||||
enum en_fieldtype type;
|
||||
byte *from_end,*to_end,*packpos;
|
||||
reg3 MARIA_COLUMNDEF *rec,*end_field;
|
||||
reg3 MARIA_COLUMNDEF *column, *end_column;
|
||||
DBUG_ENTER("_ma_rec_unpack");
|
||||
|
||||
to_end=to + info->s->base.reclength;
|
||||
|
@ -1161,27 +1161,27 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
|
|||
min_pack_length-= length;
|
||||
}
|
||||
|
||||
for (rec=info->s->rec , end_field=rec+info->s->base.fields ;
|
||||
rec < end_field ; to+= rec_length, rec++)
|
||||
for (column= info->s->columndef, end_column= column + info->s->base.fields;
|
||||
column < end_column ; to+= column_length, column++)
|
||||
{
|
||||
rec_length=rec->length;
|
||||
if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL &&
|
||||
column_length= column->length;
|
||||
if ((type = (enum en_fieldtype) column->type) != FIELD_NORMAL &&
|
||||
(type != FIELD_CHECK))
|
||||
{
|
||||
if (type == FIELD_VARCHAR)
|
||||
{
|
||||
uint pack_length= HA_VARCHAR_PACKLENGTH(rec_length-1);
|
||||
uint pack_length= HA_VARCHAR_PACKLENGTH(column_length-1);
|
||||
if (pack_length == 1)
|
||||
{
|
||||
length= (uint) *(uchar*) from;
|
||||
if (length > rec_length-1)
|
||||
if (length > column_length-1)
|
||||
goto err;
|
||||
*to= *from++;
|
||||
}
|
||||
else
|
||||
{
|
||||
get_key_length(length, from);
|
||||
if (length > rec_length-2)
|
||||
if (length > column_length-2)
|
||||
goto err;
|
||||
int2store(to,length);
|
||||
}
|
||||
|
@ -1195,11 +1195,11 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
|
|||
if (flag & bit)
|
||||
{
|
||||
if (type == FIELD_BLOB || type == FIELD_SKIP_ZERO)
|
||||
bzero((byte*) to,rec_length);
|
||||
bzero((byte*) to,column_length);
|
||||
else if (type == FIELD_SKIP_ENDSPACE ||
|
||||
type == FIELD_SKIP_PRESPACE)
|
||||
{
|
||||
if (rec->length > 255 && *from & 128)
|
||||
if (column->length > 255 && *from & 128)
|
||||
{
|
||||
if (from + 1 >= from_end)
|
||||
goto err;
|
||||
|
@ -1212,25 +1212,25 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
|
|||
length= (uchar) *from++;
|
||||
}
|
||||
min_pack_length--;
|
||||
if (length >= rec_length ||
|
||||
if (length >= column_length ||
|
||||
min_pack_length + length > (uint) (from_end - from))
|
||||
goto err;
|
||||
if (type == FIELD_SKIP_ENDSPACE)
|
||||
{
|
||||
memcpy(to,(byte*) from,(size_t) length);
|
||||
bfill((byte*) to+length,rec_length-length,' ');
|
||||
bfill((byte*) to+length,column_length-length,' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
bfill((byte*) to,rec_length-length,' ');
|
||||
memcpy(to+rec_length-length,(byte*) from,(size_t) length);
|
||||
bfill((byte*) to,column_length-length,' ');
|
||||
memcpy(to+column_length-length,(byte*) from,(size_t) length);
|
||||
}
|
||||
from+=length;
|
||||
}
|
||||
}
|
||||
else if (type == FIELD_BLOB)
|
||||
{
|
||||
uint size_length=rec_length- maria_portable_sizeof_char_ptr;
|
||||
uint size_length=column_length- portable_sizeof_char_ptr;
|
||||
ulong blob_length= _ma_calc_blob_length(size_length,from);
|
||||
ulong from_left= (ulong) (from_end - from);
|
||||
if (from_left < size_length ||
|
||||
|
@ -1246,9 +1246,9 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
|
|||
{
|
||||
if (type == FIELD_SKIP_ENDSPACE || type == FIELD_SKIP_PRESPACE)
|
||||
min_pack_length--;
|
||||
if (min_pack_length + rec_length > (uint) (from_end - from))
|
||||
if (min_pack_length + column_length > (uint) (from_end - from))
|
||||
goto err;
|
||||
memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length;
|
||||
memcpy(to,(byte*) from,(size_t) column_length); from+=column_length;
|
||||
}
|
||||
if ((bit= bit << 1) >= 256)
|
||||
{
|
||||
|
@ -1259,9 +1259,9 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
|
|||
{
|
||||
if (min_pack_length > (uint) (from_end - from))
|
||||
goto err;
|
||||
min_pack_length-=rec_length;
|
||||
memcpy(to, (byte*) from, (size_t) rec_length);
|
||||
from+=rec_length;
|
||||
min_pack_length-=column_length;
|
||||
memcpy(to, (byte*) from, (size_t) column_length);
|
||||
from+=column_length;
|
||||
}
|
||||
}
|
||||
if (info->s->calc_checksum)
|
||||
|
@ -1620,7 +1620,7 @@ err:
|
|||
|
||||
|
||||
/*
|
||||
Read record from datafile.
|
||||
Read next record from datafile during table scan.
|
||||
|
||||
SYNOPSIS
|
||||
_ma_read_rnd_dynamic_record()
|
||||
|
@ -1631,22 +1631,17 @@ err:
|
|||
record is found.
|
||||
|
||||
NOTE
|
||||
This is identical to _ma_read_dynamic_record(), except the following
|
||||
cases:
|
||||
|
||||
If a write buffer is active, it needs to be flushed if its contents
|
||||
intersects with the record to read. We always check if the position
|
||||
of the first byte of the write buffer is lower than the position
|
||||
past the last byte to read. In theory this is also true if the write
|
||||
buffer is completely below the read segment. That is, if there is no
|
||||
intersection. But this case is unusual. We flush anyway. Only if the
|
||||
first byte in the write buffer is above the last byte to read, we do
|
||||
not flush.
|
||||
- If there is no active row at 'filepos', continue scanning for
|
||||
an active row. (This is becasue the previous
|
||||
_ma_read_rnd_dynamic_record() call stored the next block position
|
||||
in filepos, but this position may not be a start block for a row
|
||||
- We may have READ_CACHING enabled, in which case we use the cache
|
||||
to read rows.
|
||||
|
||||
A dynamic record may need several reads. So this check must be done
|
||||
before every read. Reading a dynamic record starts with reading the
|
||||
block header. If the record does not fit into the free space of the
|
||||
header, the block may be longer than the header. In this case a
|
||||
second read is necessary. These one or two reads repeat for every
|
||||
part of the record.
|
||||
For other comments, check _ma_read_dynamic_record()
|
||||
|
||||
RETURN
|
||||
0 OK
|
||||
|
|
|
@ -49,7 +49,7 @@ int main(int argc, char *argv[])
|
|||
recinfo[0].type=FIELD_SKIP_ENDSPACE;
|
||||
recinfo[0].length=docid_length;
|
||||
recinfo[1].type=FIELD_BLOB;
|
||||
recinfo[1].length= 4+maria_portable_sizeof_char_ptr;
|
||||
recinfo[1].length= 4+portable_sizeof_char_ptr;
|
||||
|
||||
/* Define a key over the first column */
|
||||
keyinfo[0].seg=keyseg;
|
||||
|
|
|
@ -76,12 +76,12 @@ static int run_test(const char *filename)
|
|||
|
||||
/* First define 2 columns */
|
||||
recinfo[0].type=extra_field;
|
||||
recinfo[0].length= (extra_field == FIELD_BLOB ? 4 + maria_portable_sizeof_char_ptr :
|
||||
recinfo[0].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr :
|
||||
extra_length);
|
||||
if (extra_field == FIELD_VARCHAR)
|
||||
recinfo[0].length+= HA_VARCHAR_PACKLENGTH(extra_length);
|
||||
recinfo[1].type=key_field;
|
||||
recinfo[1].length= (key_field == FIELD_BLOB ? 4+maria_portable_sizeof_char_ptr :
|
||||
recinfo[1].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr :
|
||||
key_length);
|
||||
if (key_field == FIELD_VARCHAR)
|
||||
recinfo[1].length+= HA_VARCHAR_PACKLENGTH(key_length);
|
||||
|
|
|
@ -329,7 +329,7 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, byte *key)
|
|||
/* creating pageful of keys */
|
||||
maria_putint(info->buff,length+2,0);
|
||||
memcpy(info->buff+2, key_ptr, length);
|
||||
info->keybuff_used=info->page_changed=1; /* info->buff is used */
|
||||
info->keyread_buff_used=info->page_changed=1; /* info->buff is used */
|
||||
if ((root= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR ||
|
||||
_ma_write_keypage(info,keyinfo,root,DFLT_INIT_HITS,info->buff))
|
||||
DBUG_RETURN(-1);
|
||||
|
|
|
@ -126,10 +126,14 @@ void _ma_report_error(int errcode, const char *file_name)
|
|||
|
||||
if ((length= strlen(file_name)) > 64)
|
||||
{
|
||||
/* we first remove the directory */
|
||||
uint dir_length= dirname_length(file_name);
|
||||
file_name+= dir_length;
|
||||
if ((length-= dir_length) > 64)
|
||||
{
|
||||
/* still too long, chop start of table name */
|
||||
file_name+= length - 64;
|
||||
}
|
||||
}
|
||||
my_error(errcode, MYF(ME_NOREFRESH), file_name);
|
||||
DBUG_VOID_RETURN;
|
||||
|
|
|
@ -232,13 +232,21 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||
}
|
||||
|
||||
key_parts+=fulltext_keys*FT_SEGS;
|
||||
if (share->base.max_key_length > HA_MAX_KEY_BUFF || keys > MARIA_MAX_KEY ||
|
||||
key_parts >= MARIA_MAX_KEY * HA_MAX_KEY_SEG)
|
||||
if (share->base.max_key_length > maria_max_key_length() ||
|
||||
keys > MARIA_MAX_KEY || key_parts >= MARIA_MAX_KEY * HA_MAX_KEY_SEG)
|
||||
{
|
||||
DBUG_PRINT("error",("Wrong key info: Max_key_length: %d keys: %d key_parts: %d", share->base.max_key_length, keys, key_parts));
|
||||
my_errno=HA_ERR_UNSUPPORTED;
|
||||
goto err;
|
||||
}
|
||||
if (share->base.block_size != maria_block_size)
|
||||
{
|
||||
DBUG_PRINT("error", ("Wrong block size %u; Expected %u",
|
||||
(uint) share->base.block_size,
|
||||
(uint) maria_block_size));
|
||||
my_errno=HA_ERR_UNSUPPORTED;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Correct max_file_length based on length of sizeof(off_t) */
|
||||
max_data_file_length=
|
||||
|
@ -268,7 +276,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||
&share->keyparts,
|
||||
(key_parts+unique_key_parts+keys+uniques) *
|
||||
sizeof(HA_KEYSEG),
|
||||
&share->rec,
|
||||
&share->columndef,
|
||||
(share->base.fields+1)*sizeof(MARIA_COLUMNDEF),
|
||||
&share->blobs,sizeof(MARIA_BLOB)*share->base.blobs,
|
||||
&share->unique_file_name,strlen(name_buff)+1,
|
||||
|
@ -304,7 +312,6 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||
end_pos);
|
||||
if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE)
|
||||
have_rtree=1;
|
||||
set_if_smaller(share->block_size,share->keyinfo[i].block_length);
|
||||
share->keyinfo[i].seg=pos;
|
||||
for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
|
||||
{
|
||||
|
@ -418,7 +425,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||
if (share->base.transactional)
|
||||
share->base_length+= TRANS_ROW_EXTRA_HEADER_SIZE;
|
||||
share->base.default_rec_buff_size= max(share->base.pack_reclength,
|
||||
share->base.max_key_length);
|
||||
share->base.max_key_length);
|
||||
if (share->data_file_type == DYNAMIC_RECORD)
|
||||
{
|
||||
share->base.extra_rec_buff_size=
|
||||
|
@ -430,18 +437,18 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||
end_pos);
|
||||
for (i= j= 0 ; i < share->base.fields ; i++)
|
||||
{
|
||||
disk_pos=_ma_recinfo_read(disk_pos,&share->rec[i]);
|
||||
share->rec[i].pack_type=0;
|
||||
share->rec[i].huff_tree=0;
|
||||
if (share->rec[i].type == (int) FIELD_BLOB)
|
||||
disk_pos=_ma_columndef_read(disk_pos,&share->columndef[i]);
|
||||
share->columndef[i].pack_type=0;
|
||||
share->columndef[i].huff_tree=0;
|
||||
if (share->columndef[i].type == (int) FIELD_BLOB)
|
||||
{
|
||||
share->blobs[j].pack_length=
|
||||
share->rec[i].length-maria_portable_sizeof_char_ptr;;
|
||||
share->blobs[j].offset= share->rec[i].offset;
|
||||
share->columndef[i].length-portable_sizeof_char_ptr;;
|
||||
share->blobs[j].offset= share->columndef[i].offset;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
share->rec[i].type=(int) FIELD_LAST; /* End marker */
|
||||
share->columndef[i].type=(int) FIELD_LAST; /* End marker */
|
||||
#ifdef ASKMONTY
|
||||
/*
|
||||
This code was added to mi_open.c in this cset:
|
||||
|
@ -718,8 +725,8 @@ void _ma_setup_functions(register MARIA_SHARE *share)
|
|||
share->once_end= maria_once_end_dummy;
|
||||
share->init= maria_scan_init_dummy;
|
||||
share->end= maria_scan_end_dummy;
|
||||
share->scan_init= maria_scan_init_dummy;
|
||||
share->scan_end= maria_scan_end_dummy;
|
||||
share->scan_init= maria_scan_init_dummy;/* Compat. dummy function */
|
||||
share->scan_end= maria_scan_end_dummy;/* Compat. dummy function */
|
||||
share->write_record_init= _ma_write_init_default;
|
||||
share->write_record_abort= _ma_write_abort_default;
|
||||
|
||||
|
@ -729,7 +736,10 @@ void _ma_setup_functions(register MARIA_SHARE *share)
|
|||
share->scan= _ma_read_rnd_pack_record;
|
||||
share->once_init= _ma_once_init_pack_row;
|
||||
share->once_end= _ma_once_end_pack_row;
|
||||
/* Calculate checksum according how the original row was stored */
|
||||
/*
|
||||
Calculate checksum according to data in the original, not compressed,
|
||||
row.
|
||||
*/
|
||||
if (share->state.header.org_data_file_type == STATIC_RECORD)
|
||||
share->calc_checksum= _ma_static_checksum;
|
||||
else
|
||||
|
@ -767,10 +777,10 @@ void _ma_setup_functions(register MARIA_SHARE *share)
|
|||
share->calc_checksum= share->calc_write_checksum= _ma_static_checksum;
|
||||
break;
|
||||
case BLOCK_RECORD:
|
||||
share->once_init= _ma_once_init_block_row;
|
||||
share->once_end= _ma_once_end_block_row;
|
||||
share->init= _ma_init_block_row;
|
||||
share->end= _ma_end_block_row;
|
||||
share->once_init= _ma_once_init_block_record;
|
||||
share->once_end= _ma_once_end_block_record;
|
||||
share->init= _ma_init_block_record;
|
||||
share->end= _ma_end_block_record;
|
||||
share->write_record_init= _ma_write_init_block_record;
|
||||
share->write_record_abort= _ma_write_abort_block_record;
|
||||
share->scan_init= _ma_scan_init_block_record;
|
||||
|
@ -783,6 +793,10 @@ void _ma_setup_functions(register MARIA_SHARE *share)
|
|||
share->write_record= _ma_write_block_record;
|
||||
share->compare_unique= _ma_cmp_block_unique;
|
||||
share->calc_checksum= _ma_checksum;
|
||||
/*
|
||||
write_block_record() will calculate the checksum; Tell maria_write()
|
||||
that it doesn't have to do this.
|
||||
*/
|
||||
share->calc_write_checksum= 0;
|
||||
break;
|
||||
}
|
||||
|
@ -1187,32 +1201,32 @@ char *_ma_uniquedef_read(char *ptr, MARIA_UNIQUEDEF *def)
|
|||
** MARIA_COLUMNDEF
|
||||
***************************************************************************/
|
||||
|
||||
uint _ma_recinfo_write(File file, MARIA_COLUMNDEF *recinfo)
|
||||
uint _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef)
|
||||
{
|
||||
uchar buff[MARIA_COLUMNDEF_SIZE];
|
||||
uchar *ptr=buff;
|
||||
|
||||
mi_int6store(ptr,recinfo->offset); ptr+= 6;
|
||||
mi_int2store(ptr,recinfo->type); ptr+= 2;
|
||||
mi_int2store(ptr,recinfo->length); ptr+= 2;
|
||||
mi_int2store(ptr,recinfo->fill_length); ptr+= 2;
|
||||
mi_int2store(ptr,recinfo->null_pos); ptr+= 2;
|
||||
mi_int2store(ptr,recinfo->empty_pos); ptr+= 2;
|
||||
(*ptr++)= recinfo->null_bit;
|
||||
(*ptr++)= recinfo->empty_bit;
|
||||
mi_int6store(ptr,columndef->offset); ptr+= 6;
|
||||
mi_int2store(ptr,columndef->type); ptr+= 2;
|
||||
mi_int2store(ptr,columndef->length); ptr+= 2;
|
||||
mi_int2store(ptr,columndef->fill_length); ptr+= 2;
|
||||
mi_int2store(ptr,columndef->null_pos); ptr+= 2;
|
||||
mi_int2store(ptr,columndef->empty_pos); ptr+= 2;
|
||||
(*ptr++)= columndef->null_bit;
|
||||
(*ptr++)= columndef->empty_bit;
|
||||
return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
|
||||
}
|
||||
|
||||
char *_ma_recinfo_read(char *ptr, MARIA_COLUMNDEF *recinfo)
|
||||
char *_ma_columndef_read(char *ptr, MARIA_COLUMNDEF *columndef)
|
||||
{
|
||||
recinfo->offset= mi_uint6korr(ptr); ptr+= 6;
|
||||
recinfo->type= mi_sint2korr(ptr); ptr+= 2;
|
||||
recinfo->length= mi_uint2korr(ptr); ptr+= 2;
|
||||
recinfo->fill_length= mi_uint2korr(ptr); ptr+= 2;
|
||||
recinfo->null_pos= mi_uint2korr(ptr); ptr+= 2;
|
||||
recinfo->empty_pos= mi_uint2korr(ptr); ptr+= 2;
|
||||
recinfo->null_bit= (uint8) *ptr++;
|
||||
recinfo->empty_bit= (uint8) *ptr++;
|
||||
columndef->offset= mi_uint6korr(ptr); ptr+= 6;
|
||||
columndef->type= mi_sint2korr(ptr); ptr+= 2;
|
||||
columndef->length= mi_uint2korr(ptr); ptr+= 2;
|
||||
columndef->fill_length= mi_uint2korr(ptr); ptr+= 2;
|
||||
columndef->null_pos= mi_uint2korr(ptr); ptr+= 2;
|
||||
columndef->empty_pos= mi_uint2korr(ptr); ptr+= 2;
|
||||
columndef->null_bit= (uint8) *ptr++;
|
||||
columndef->empty_bit= (uint8) *ptr++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,15 +142,14 @@ static maria_bit_type mask[]=
|
|||
my_bool _ma_once_init_pack_row(MARIA_SHARE *share, File dfile)
|
||||
{
|
||||
share->options|= HA_OPTION_READ_ONLY_DATA;
|
||||
if (_ma_read_pack_info(share, dfile,
|
||||
(pbool)
|
||||
test(!(share->options &
|
||||
(HA_OPTION_PACK_RECORD |
|
||||
HA_OPTION_TEMP_COMPRESS_RECORD)))))
|
||||
return 1;
|
||||
return 0;
|
||||
return (_ma_read_pack_info(share, dfile,
|
||||
(pbool)
|
||||
test(!(share->options &
|
||||
(HA_OPTION_PACK_RECORD |
|
||||
HA_OPTION_TEMP_COMPRESS_RECORD)))));
|
||||
}
|
||||
|
||||
|
||||
my_bool _ma_once_end_pack_row(MARIA_SHARE *share)
|
||||
{
|
||||
if (share->decode_trees)
|
||||
|
@ -262,15 +261,16 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
|
|||
/* Read new info for each field */
|
||||
for (i=0 ; i < share->base.fields ; i++)
|
||||
{
|
||||
share->rec[i].base_type=(enum en_fieldtype) get_bits(&bit_buff,5);
|
||||
share->rec[i].pack_type=(uint) get_bits(&bit_buff,6);
|
||||
share->rec[i].space_length_bits=get_bits(&bit_buff,5);
|
||||
share->rec[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff,
|
||||
share->columndef[i].base_type=(enum en_fieldtype) get_bits(&bit_buff,5);
|
||||
share->columndef[i].pack_type=(uint) get_bits(&bit_buff,6);
|
||||
share->columndef[i].space_length_bits=get_bits(&bit_buff,5);
|
||||
share->columndef[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff,
|
||||
huff_tree_bits);
|
||||
share->rec[i].unpack= get_unpack_function(share->rec+i);
|
||||
share->columndef[i].unpack= get_unpack_function(share->columndef + i);
|
||||
DBUG_PRINT("info", ("col: %2u type: %2u pack: %u slbits: %2u",
|
||||
i, share->rec[i].base_type, share->rec[i].pack_type,
|
||||
share->rec[i].space_length_bits));
|
||||
i, share->columndef[i].base_type,
|
||||
share->columndef[i].pack_type,
|
||||
share->columndef[i].space_length_bits));
|
||||
}
|
||||
skip_to_next_byte(&bit_buff);
|
||||
/*
|
||||
|
@ -776,7 +776,7 @@ int _ma_pack_rec_unpack(register MARIA_HA *info, MARIA_BIT_BUFF *bit_buff,
|
|||
reclength-= info->s->base.null_bytes;
|
||||
}
|
||||
init_bit_buffer(bit_buff, (uchar*) from, reclength);
|
||||
for (current_field=share->rec, end=current_field+share->base.fields ;
|
||||
for (current_field=share->columndef, end=current_field+share->base.fields ;
|
||||
current_field < end ;
|
||||
current_field++,to=end_field)
|
||||
{
|
||||
|
@ -1080,7 +1080,7 @@ static void uf_blob(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff,
|
|||
else
|
||||
{
|
||||
ulong length=get_bits(bit_buff,rec->space_length_bits);
|
||||
uint pack_length=(uint) (end-to)-maria_portable_sizeof_char_ptr;
|
||||
uint pack_length=(uint) (end-to)-portable_sizeof_char_ptr;
|
||||
if (bit_buff->blob_pos+length > bit_buff->blob_end)
|
||||
{
|
||||
bit_buff->error=1;
|
||||
|
|
|
@ -32,7 +32,7 @@ byte *_ma_fetch_keypage(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
|
|||
info->s->block_size, info->s->block_size,
|
||||
return_buffer);
|
||||
if (tmp == info->buff)
|
||||
info->keybuff_used=1;
|
||||
info->keyread_buff_used=1;
|
||||
else if (!tmp)
|
||||
{
|
||||
DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno));
|
||||
|
|
|
@ -150,7 +150,6 @@ int maria_rkey(MARIA_HA *info, byte *buf, int inx, const byte *key,
|
|||
else
|
||||
info->last_rkey_length= pack_key_length;
|
||||
|
||||
|
||||
/* Check if we don't want to have record back, only error message */
|
||||
if (!buf)
|
||||
{
|
||||
|
|
|
@ -36,7 +36,6 @@ int maria_rrnd(MARIA_HA *info, byte *buf, MARIA_RECORD_POS filepos)
|
|||
#ifdef NOT_USED
|
||||
if (filepos == HA_OFFSET_ERROR)
|
||||
{
|
||||
skip_deleted_blocks=1;
|
||||
if (info->cur_row.lastpos == HA_OFFSET_ERROR) /* First read ? */
|
||||
filepos= info->s->pack.header_length; /* Read first record */
|
||||
else
|
||||
|
|
|
@ -127,11 +127,11 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
|
|||
info->int_keypos = info->buff;
|
||||
info->int_maxpos = info->buff + (last - after_key);
|
||||
memcpy(info->buff, after_key, last - after_key);
|
||||
info->keybuff_used = 0;
|
||||
info->keyread_buff_used = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->keybuff_used = 1;
|
||||
info->keyread_buff_used = 1;
|
||||
}
|
||||
|
||||
res = 0;
|
||||
|
@ -192,7 +192,7 @@ int maria_rtree_find_first(MARIA_HA *info, uint keynr, byte *key,
|
|||
info->last_rkey_length = key_length;
|
||||
|
||||
info->maria_rtree_recursion_depth = -1;
|
||||
info->keybuff_used = 1;
|
||||
info->keyread_buff_used = 1;
|
||||
|
||||
nod_cmp_flag= ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ?
|
||||
MBR_WITHIN : MBR_INTERSECT);
|
||||
|
@ -227,7 +227,7 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag)
|
|||
info->lastkey_length,
|
||||
search_flag);
|
||||
|
||||
if (!info->keybuff_used)
|
||||
if (!info->keyread_buff_used)
|
||||
{
|
||||
byte *key= info->int_keypos;
|
||||
|
||||
|
@ -245,7 +245,7 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag)
|
|||
if (after_key < info->int_maxpos)
|
||||
info->int_keypos= after_key;
|
||||
else
|
||||
info->keybuff_used= 1;
|
||||
info->keyread_buff_used= 1;
|
||||
return 0;
|
||||
}
|
||||
key+= keyinfo->keylength;
|
||||
|
@ -342,11 +342,11 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint key_l
|
|||
info->int_keypos = (byte*) saved_key;
|
||||
memcpy(info->buff, page_buf, keyinfo->block_length);
|
||||
info->int_maxpos = rt_PAGE_END(info->buff);
|
||||
info->keybuff_used = 0;
|
||||
info->keyread_buff_used = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->keybuff_used = 1;
|
||||
info->keyread_buff_used = 1;
|
||||
}
|
||||
|
||||
res = 0;
|
||||
|
@ -389,7 +389,7 @@ int maria_rtree_get_first(MARIA_HA *info, uint keynr, uint key_length)
|
|||
}
|
||||
|
||||
info->maria_rtree_recursion_depth = -1;
|
||||
info->keybuff_used = 1;
|
||||
info->keyread_buff_used = 1;
|
||||
|
||||
return maria_rtree_get_req(info, &keyinfo[keynr], key_length, root, 0);
|
||||
}
|
||||
|
@ -409,7 +409,7 @@ int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length)
|
|||
my_off_t root;
|
||||
MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr;
|
||||
|
||||
if (!info->keybuff_used)
|
||||
if (!info->keyread_buff_used)
|
||||
{
|
||||
uint k_len = keyinfo->keylength - info->s->base.rec_reflength;
|
||||
/* rt_PAGE_NEXT_KEY(info->int_keypos) */
|
||||
|
@ -425,7 +425,7 @@ int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length)
|
|||
*(int*)info->int_keypos = key - info->buff;
|
||||
if (after_key >= info->int_maxpos)
|
||||
{
|
||||
info->keybuff_used = 1;
|
||||
info->keyread_buff_used = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -638,7 +638,7 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, byte *key,
|
|||
{
|
||||
if ((old_root = _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
|
||||
return -1;
|
||||
info->keybuff_used = 1;
|
||||
info->keyread_buff_used = 1;
|
||||
maria_putint(info->buff, 2, 0);
|
||||
res = maria_rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL);
|
||||
if (_ma_write_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, info->buff))
|
||||
|
|
|
@ -157,7 +157,7 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
|
|||
info->int_keytree_version=keyinfo->version;
|
||||
info->last_search_keypage=info->last_keypage;
|
||||
info->page_changed=0;
|
||||
info->keybuff_used= (info->keyread_buff != buff); /* If we have to reread */
|
||||
info->keyread_buff_used= (info->keyread_buff != buff); /* If we have to reread */
|
||||
|
||||
DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos));
|
||||
DBUG_RETURN(0);
|
||||
|
@ -618,7 +618,7 @@ void _ma_kpointer(register MARIA_HA *info, register byte *buff, my_off_t pos)
|
|||
case 4: mi_int4store(buff,pos); break;
|
||||
case 3: mi_int3store(buff,pos); break;
|
||||
case 2: mi_int2store(buff,(uint) pos); break;
|
||||
case 1: buff[0]= (char) (uchar) pos; break;
|
||||
case 1: buff[0]= (byte) pos; break;
|
||||
default: abort(); /* impossible */
|
||||
}
|
||||
} /* _ma_kpointer */
|
||||
|
@ -1219,10 +1219,10 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
|
|||
uint nod_flag;
|
||||
byte lastkey[HA_MAX_KEY_BUFF];
|
||||
DBUG_ENTER("_ma_search_next");
|
||||
DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu page_changed %d keybuff_used: %d",
|
||||
DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu page_changed %d keyread_buff_used: %d",
|
||||
nextflag, (ulong) info->cur_row.lastpos,
|
||||
(ulong) info->int_keypos,
|
||||
info->page_changed, info->keybuff_used));
|
||||
info->page_changed, info->keyread_buff_used));
|
||||
DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,key_length););
|
||||
|
||||
/* Force full read if we are at last key or if we are not on a leaf
|
||||
|
@ -1235,16 +1235,16 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
|
|||
if (((nextflag & SEARCH_BIGGER) && info->int_keypos >= info->int_maxpos) ||
|
||||
info->page_changed ||
|
||||
(info->int_keytree_version != keyinfo->version &&
|
||||
(info->int_nod_flag || info->keybuff_used)))
|
||||
(info->int_nod_flag || info->keyread_buff_used)))
|
||||
DBUG_RETURN(_ma_search(info,keyinfo,key, USE_WHOLE_KEY,
|
||||
nextflag | SEARCH_SAVE_BUFF, pos));
|
||||
|
||||
if (info->keybuff_used)
|
||||
if (info->keyread_buff_used)
|
||||
{
|
||||
if (!_ma_fetch_keypage(info,keyinfo,info->last_search_keypage,
|
||||
DFLT_INIT_HITS,info->keyread_buff,0))
|
||||
DBUG_RETURN(-1);
|
||||
info->keybuff_used=0;
|
||||
info->keyread_buff_used=0;
|
||||
}
|
||||
|
||||
/* Last used buffer is in info->keyread_buff */
|
||||
|
@ -1328,7 +1328,7 @@ int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
|
|||
info->int_nod_flag=nod_flag;
|
||||
info->int_keytree_version=keyinfo->version;
|
||||
info->last_search_keypage=info->last_keypage;
|
||||
info->page_changed=info->keybuff_used=0;
|
||||
info->page_changed=info->keyread_buff_used=0;
|
||||
info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length);
|
||||
|
||||
DBUG_PRINT("exit",("found key at %lu", (ulong) info->cur_row.lastpos));
|
||||
|
@ -1373,7 +1373,7 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
|
|||
info->int_nod_flag=nod_flag;
|
||||
info->int_keytree_version=keyinfo->version;
|
||||
info->last_search_keypage=info->last_keypage;
|
||||
info->page_changed=info->keybuff_used=0;
|
||||
info->page_changed=info->keyread_buff_used=0;
|
||||
|
||||
DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos));
|
||||
DBUG_RETURN(0);
|
||||
|
|
|
@ -80,7 +80,7 @@ int run_test(const char *filename)
|
|||
/* Define spatial column */
|
||||
|
||||
recinfo[1].type=FIELD_BLOB;
|
||||
recinfo[1].length=4 + maria_portable_sizeof_char_ptr;
|
||||
recinfo[1].length=4 + portable_sizeof_char_ptr;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -73,12 +73,12 @@ static int run_test(const char *filename)
|
|||
/* First define 2 columns */
|
||||
create_info.null_bytes= 1;
|
||||
recinfo[0].type= key_field;
|
||||
recinfo[0].length= (key_field == FIELD_BLOB ? 4+maria_portable_sizeof_char_ptr :
|
||||
recinfo[0].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr :
|
||||
key_length);
|
||||
if (key_field == FIELD_VARCHAR)
|
||||
recinfo[0].length+= HA_VARCHAR_PACKLENGTH(key_length);
|
||||
recinfo[1].type=extra_field;
|
||||
recinfo[1].length= (extra_field == FIELD_BLOB ? 4 + maria_portable_sizeof_char_ptr : 24);
|
||||
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);
|
||||
if (opt_unique)
|
||||
|
|
|
@ -191,7 +191,7 @@ int main(int argc, char *argv[])
|
|||
if (use_blob)
|
||||
{
|
||||
recinfo[6].type=FIELD_BLOB;
|
||||
recinfo[6].length=4+maria_portable_sizeof_char_ptr;
|
||||
recinfo[6].length=4+portable_sizeof_char_ptr;
|
||||
recinfo[6].null_bit=0;
|
||||
recinfo[6].null_pos=0;
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec)
|
|||
info->state->checksum+= (info->cur_row.checksum - old_checksum);
|
||||
|
||||
/*
|
||||
We can't yet have HA_STATE_ACTIVE here, as block_record dosn't support
|
||||
We can't yet have HA_STATE_AKTIV here, as block_record dosn't support
|
||||
it
|
||||
*/
|
||||
info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | key_changed);
|
||||
|
|
|
@ -356,7 +356,7 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *key,
|
|||
(byte*) 0, (byte*) 0, key,&s_temp);
|
||||
maria_putint(info->buff,t_length+2+nod_flag,nod_flag);
|
||||
(*keyinfo->store_key)(keyinfo,info->buff+2+nod_flag,&s_temp);
|
||||
info->keybuff_used=info->page_changed=1; /* info->buff is used */
|
||||
info->keyread_buff_used=info->page_changed=1; /* info->buff is used */
|
||||
if ((*root= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR ||
|
||||
_ma_write_keypage(info,keyinfo,*root,DFLT_INIT_HITS,info->buff))
|
||||
DBUG_RETURN(-1);
|
||||
|
@ -634,7 +634,7 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
|
|||
|
||||
if (info->s->keyinfo+info->lastinx == keyinfo)
|
||||
info->page_changed=1; /* Info->buff is used */
|
||||
info->keybuff_used=1;
|
||||
info->keyread_buff_used=1;
|
||||
nod_flag=_ma_test_if_nod(buff);
|
||||
key_ref_length=2+nod_flag;
|
||||
if (insert_last_key)
|
||||
|
|
|
@ -50,8 +50,8 @@ static const char *type_names[]=
|
|||
"impossible","char","binary", "short", "long", "float",
|
||||
"double","number","unsigned short",
|
||||
"unsigned long","longlong","ulonglong","int24",
|
||||
"uint24","int8","varchar", "varbin","?",
|
||||
"?"
|
||||
"uint24","int8","varchar", "varbin", "varchar2", "varbin2", "bit",
|
||||
"?","?"
|
||||
};
|
||||
|
||||
static const char *prefix_packed_txt="packed ",
|
||||
|
@ -1224,7 +1224,7 @@ end2:
|
|||
|
||||
static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name)
|
||||
{
|
||||
uint key,keyseg_nr,field,start;
|
||||
uint key,keyseg_nr,field;
|
||||
reg3 MARIA_KEYDEF *keyinfo;
|
||||
reg2 HA_KEYSEG *keyseg;
|
||||
reg4 const char *text;
|
||||
|
@ -1430,43 +1430,42 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name)
|
|||
for (field=0 ; field < share->base.fields ; field++)
|
||||
{
|
||||
if (share->options & HA_OPTION_COMPRESS_RECORD)
|
||||
type=share->rec[field].base_type;
|
||||
type=share->columndef[field].base_type;
|
||||
else
|
||||
type=(enum en_fieldtype) share->rec[field].type;
|
||||
type=(enum en_fieldtype) share->columndef[field].type;
|
||||
end=strmov(buff,field_pack[type]);
|
||||
if (share->options & HA_OPTION_COMPRESS_RECORD)
|
||||
{
|
||||
if (share->rec[field].pack_type & PACK_TYPE_SELECTED)
|
||||
if (share->columndef[field].pack_type & PACK_TYPE_SELECTED)
|
||||
end=strmov(end,", not_always");
|
||||
if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS)
|
||||
if (share->columndef[field].pack_type & PACK_TYPE_SPACE_FIELDS)
|
||||
end=strmov(end,", no empty");
|
||||
if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL)
|
||||
if (share->columndef[field].pack_type & PACK_TYPE_ZERO_FILL)
|
||||
{
|
||||
sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits);
|
||||
sprintf(end,", zerofill(%d)",share->columndef[field].space_length_bits);
|
||||
end=strend(end);
|
||||
}
|
||||
}
|
||||
if (buff[0] == ',')
|
||||
strmov(buff,buff+2);
|
||||
int10_to_str((long) share->rec[field].length,length,10);
|
||||
int10_to_str((long) share->columndef[field].length,length,10);
|
||||
null_bit[0]=null_pos[0]=0;
|
||||
if (share->rec[field].null_bit)
|
||||
if (share->columndef[field].null_bit)
|
||||
{
|
||||
sprintf(null_bit,"%d",share->rec[field].null_bit);
|
||||
sprintf(null_pos,"%d",share->rec[field].null_pos+1);
|
||||
sprintf(null_bit,"%d",share->columndef[field].null_bit);
|
||||
sprintf(null_pos,"%d",share->columndef[field].null_pos+1);
|
||||
}
|
||||
printf("%-6d%-6u%-7s%-8s%-8s%-35s",field+1,
|
||||
(uint) share->rec[field].offset+1,
|
||||
(uint) share->columndef[field].offset+1,
|
||||
length, null_pos, null_bit, buff);
|
||||
if (share->options & HA_OPTION_COMPRESS_RECORD)
|
||||
{
|
||||
if (share->rec[field].huff_tree)
|
||||
if (share->columndef[field].huff_tree)
|
||||
printf("%3d %2d",
|
||||
(uint) (share->rec[field].huff_tree-share->decode_trees)+1,
|
||||
share->rec[field].huff_tree->quick_table_bits);
|
||||
(uint) (share->columndef[field].huff_tree-share->decode_trees)+1,
|
||||
share->columndef[field].huff_tree->quick_table_bits);
|
||||
}
|
||||
VOID(putchar('\n'));
|
||||
start+=share->rec[field].length;
|
||||
}
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
|
@ -1556,8 +1555,9 @@ static int maria_sort_records(HA_CHECK *param,
|
|||
fn_format(param->temp_filename,name,"", MARIA_NAME_DEXT,2+4+32);
|
||||
new_file= my_create(fn_format(param->temp_filename,
|
||||
param->temp_filename,"",
|
||||
DATA_TMP_EXT,2+4),
|
||||
0,param->tmpfile_createflag,
|
||||
DATA_TMP_EXT,
|
||||
MY_REPLACE_EXT | MY_UNPACK_FILENAME),
|
||||
0, param->tmpfile_createflag,
|
||||
MYF(0));
|
||||
if (new_file < 0)
|
||||
{
|
||||
|
|
|
@ -60,7 +60,8 @@ typedef struct st_maria_state_info
|
|||
uchar language; /* Language for indexes */
|
||||
uchar fulltext_keys;
|
||||
uchar data_file_type;
|
||||
uchar org_data_file_type; /* Used by mariapack to store dft */
|
||||
/* Used by mariapack to store the original data_file_type */
|
||||
uchar org_data_file_type;
|
||||
} header;
|
||||
|
||||
MARIA_STATUS_INFO state;
|
||||
|
@ -75,7 +76,7 @@ typedef struct st_maria_state_info
|
|||
ulong *rec_per_key_part;
|
||||
ha_checksum checksum; /* Table checksum */
|
||||
my_off_t *key_root; /* Start of key trees */
|
||||
my_off_t key_del; /* delete links for trees */
|
||||
my_off_t key_del; /* delete links for index pages */
|
||||
my_off_t rec_per_key_rows; /* Rows when calculating rec_per_key */
|
||||
|
||||
ulong sec_index_changed; /* Updated when new sec_index */
|
||||
|
@ -107,6 +108,13 @@ typedef struct st_maria_state_info
|
|||
#define MARIA_COLUMNDEF_SIZE (6+2+2+2+2+2+1+1)
|
||||
#define MARIA_BASE_INFO_SIZE (5*8 + 6*4 + 11*2 + 6 + 5*2 + 1 + 16)
|
||||
#define MARIA_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */
|
||||
/* Internal management bytes needed to store 2 keys on an index page */
|
||||
#define MARIA_INDEX_MIN_OVERHEAD_SIZE (4 + (TRANSID_SIZE+1) * 2)
|
||||
|
||||
/*
|
||||
Basic information of the Maria table. This is stored on disk
|
||||
and not changed (unless we do DLL changes).
|
||||
*/
|
||||
|
||||
typedef struct st_ma_base_info
|
||||
{
|
||||
|
@ -127,7 +135,9 @@ typedef struct st_ma_base_info
|
|||
uint max_field_lengths;
|
||||
uint pack_fields; /* packed fields in table */
|
||||
uint varlength_fields; /* char/varchar/blobs */
|
||||
uint rec_reflength; /* = 2-8 */
|
||||
/* Number of bytes in the index used to refer to a row (2-8) */
|
||||
uint rec_reflength;
|
||||
/* Number of bytes in the index used to refer to another index page (2-8) */
|
||||
uint key_reflength; /* = 2-8 */
|
||||
uint keys; /* same as in state.header */
|
||||
uint auto_key; /* Which key-1 is a auto key */
|
||||
|
@ -144,14 +154,17 @@ typedef struct st_ma_base_info
|
|||
uint extra_alloc_bytes;
|
||||
uint extra_alloc_procent;
|
||||
uint is_nulls_extended; /* 1 if new null bytes */
|
||||
uint min_row_length;
|
||||
uint min_row_length; /* Min possible length of a row */
|
||||
uint default_row_flag; /* 0 or ROW_FLAG_NULLS_EXTENDED */
|
||||
uint block_size;
|
||||
/* Size of initial record buffer */
|
||||
uint default_rec_buff_size;
|
||||
/* Extra number of bytes the row format require in the record buffer */
|
||||
uint extra_rec_buff_size;
|
||||
|
||||
/* The following are from the header */
|
||||
uint key_parts, all_key_parts;
|
||||
/* If false, we disable logging, versioning etc */
|
||||
my_bool transactional;
|
||||
} MARIA_BASE_INFO;
|
||||
|
||||
|
@ -177,8 +190,8 @@ typedef struct st_maria_file_bitmap
|
|||
{
|
||||
uchar *map;
|
||||
ulonglong page; /* Page number for current bitmap */
|
||||
uint used_size; /* Size of bitmap that is not 0 */
|
||||
File file;
|
||||
uint used_size; /* Size of bitmap head that is not 0 */
|
||||
File file; /* Datafile, where bitmap is stored */
|
||||
|
||||
my_bool changed;
|
||||
|
||||
|
@ -204,8 +217,7 @@ typedef struct st_maria_share
|
|||
MARIA_KEYDEF *keyinfo; /* Key definitions */
|
||||
MARIA_UNIQUEDEF *uniqueinfo; /* unique definitions */
|
||||
HA_KEYSEG *keyparts; /* key part info */
|
||||
MARIA_COLUMNDEF *rec; /* Pointer to field information
|
||||
*/
|
||||
MARIA_COLUMNDEF *columndef; /* Pointer to column information */
|
||||
MARIA_PACK pack; /* Data about packed records */
|
||||
MARIA_BLOB *blobs; /* Pointer to blobs */
|
||||
char *unique_file_name; /* realpath() of index file */
|
||||
|
@ -216,25 +228,43 @@ typedef struct st_maria_share
|
|||
KEY_CACHE *key_cache; /* ref to the current key cache */
|
||||
MARIA_DECODE_TREE *decode_trees;
|
||||
uint16 *decode_tables;
|
||||
/* Called the first time the table instance is opened */
|
||||
my_bool (*once_init)(struct st_maria_share *, File);
|
||||
/* Called when the last instance of the table is closed */
|
||||
my_bool (*once_end)(struct st_maria_share *);
|
||||
/* Is called for every open of the table */
|
||||
my_bool (*init)(struct st_maria_info *);
|
||||
/* Is called for every close of the table */
|
||||
void (*end)(struct st_maria_info *);
|
||||
/* Called when we want to read a record from a specific position */
|
||||
int (*read_record)(struct st_maria_info *, byte *, MARIA_RECORD_POS);
|
||||
/* Initialize a scan */
|
||||
my_bool (*scan_init)(struct st_maria_info *);
|
||||
/* Read next record while scanning */
|
||||
int (*scan)(struct st_maria_info *, byte *, MARIA_RECORD_POS, my_bool);
|
||||
/* End scan */
|
||||
void (*scan_end)(struct st_maria_info *);
|
||||
/* Pre-write of row (some handlers may do the actual write here) */
|
||||
MARIA_RECORD_POS (*write_record_init)(struct st_maria_info *, const byte *);
|
||||
/* Write record (or accept write_record_init) */
|
||||
my_bool (*write_record)(struct st_maria_info *, const byte *);
|
||||
/* Called when write failed */
|
||||
my_bool (*write_record_abort)(struct st_maria_info *);
|
||||
my_bool (*update_record)(struct st_maria_info *, MARIA_RECORD_POS,
|
||||
const byte *);
|
||||
my_bool (*delete_record)(struct st_maria_info *);
|
||||
my_bool (*compare_record)(struct st_maria_info *, const byte *);
|
||||
ha_checksum(*calc_checksum) (struct st_maria_info *, const byte *);
|
||||
/* calculate checksum for a row */
|
||||
ha_checksum(*calc_checksum)(struct st_maria_info *, const byte *);
|
||||
/*
|
||||
Calculate checksum for a row during write. May be 0 if we calculate
|
||||
the checksum in write_record_init()
|
||||
*/
|
||||
ha_checksum(*calc_write_checksum) (struct st_maria_info *, const byte *);
|
||||
my_bool (*compare_unique) (struct st_maria_info *, MARIA_UNIQUEDEF *,
|
||||
const byte *record, MARIA_RECORD_POS pos);
|
||||
/* Compare a row in memory with a row on disk */
|
||||
my_bool (*compare_unique)(struct st_maria_info *, MARIA_UNIQUEDEF *,
|
||||
const byte *record, MARIA_RECORD_POS pos);
|
||||
/* Mapings to read/write the data file */
|
||||
uint (*file_read)(MARIA_HA *, byte *, uint, my_off_t, myf);
|
||||
uint (*file_write)(MARIA_HA *, byte *, uint, my_off_t, myf);
|
||||
invalidator_by_filename invalidator; /* query cache invalidator */
|
||||
|
@ -255,6 +285,7 @@ typedef struct st_maria_share
|
|||
uint reopen; /* How many times reopened */
|
||||
uint w_locks, r_locks, tot_locks; /* Number of read/write locks */
|
||||
uint block_size; /* block_size of keyfile & data file*/
|
||||
/* Fixed length part of a packed row in BLOCK_RECORD format */
|
||||
uint base_length;
|
||||
myf write_flag;
|
||||
enum data_file_type data_file_type;
|
||||
|
@ -342,7 +373,8 @@ struct st_maria_info
|
|||
{
|
||||
MARIA_SHARE *s; /* Shared between open:s */
|
||||
MARIA_STATUS_INFO *state, save_state;
|
||||
MARIA_ROW cur_row, new_row;
|
||||
MARIA_ROW cur_row; /* The active row that we just read */
|
||||
MARIA_ROW new_row; /* Storage for a row during update */
|
||||
MARIA_BLOCK_SCAN scan;
|
||||
MARIA_BLOB *blobs; /* Pointer to blobs */
|
||||
MARIA_BIT_BUFF bit_buff;
|
||||
|
@ -404,8 +436,8 @@ struct st_maria_info
|
|||
my_bool quick_mode;
|
||||
/* If info->keyread_buff can't be used for rnext */
|
||||
my_bool page_changed;
|
||||
/* If info->keyread_buff has to be reread for rnext */
|
||||
my_bool keybuff_used;
|
||||
/* If info->keyread_buff has to be re-read for rnext */
|
||||
my_bool keyread_buff_used;
|
||||
my_bool once_flags; /* For MARIA_MRG */
|
||||
#ifdef __WIN__
|
||||
my_bool owned_by_merge; /* This Maria table is part of a merge union */
|
||||
|
@ -419,7 +451,7 @@ struct st_maria_info
|
|||
|
||||
/* Some defines used by maria-functions */
|
||||
|
||||
#define USE_WHOLE_KEY HA_MAX_KEY_BUFF*2 /* Use whole key in _search() */
|
||||
#define USE_WHOLE_KEY 65535 /* Use whole key in _search() */
|
||||
#define F_EXTRA_LCK -1
|
||||
|
||||
/* bits in opt_flag */
|
||||
|
@ -489,6 +521,7 @@ struct st_maria_info
|
|||
{ length=mi_uint2korr((key)+1)+3; } \
|
||||
}
|
||||
|
||||
#define maria_max_key_length() ((maria_block_size - MARIA_INDEX_MIN_OVERHEAD_SIZE)/2)
|
||||
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
|
||||
|
||||
#define MARIA_MIN_BLOCK_LENGTH 20 /* Because of delete-link */
|
||||
|
@ -720,7 +753,11 @@ extern int _ma_ft_update(MARIA_HA *info, uint keynr, byte *keybuf,
|
|||
const byte *oldrec, const byte *newrec,
|
||||
my_off_t pos);
|
||||
|
||||
/* Parameter to _ma_get_block_info */
|
||||
/*
|
||||
Parameter to _ma_get_block_info
|
||||
The dynamic row header is read into this struct. For an explanation of
|
||||
the fields, look at the function _ma_get_block_info().
|
||||
*/
|
||||
|
||||
typedef struct st_maria_block_info
|
||||
{
|
||||
|
@ -736,6 +773,7 @@ typedef struct st_maria_block_info
|
|||
uint offset;
|
||||
} MARIA_BLOCK_INFO;
|
||||
|
||||
|
||||
/* bits in return from _ma_get_block_info */
|
||||
|
||||
#define BLOCK_FIRST 1
|
||||
|
@ -800,8 +838,8 @@ uint _ma_keydef_write(File file, MARIA_KEYDEF *keydef);
|
|||
char *_ma_keydef_read(char *ptr, MARIA_KEYDEF *keydef);
|
||||
uint _ma_uniquedef_write(File file, MARIA_UNIQUEDEF *keydef);
|
||||
char *_ma_uniquedef_read(char *ptr, MARIA_UNIQUEDEF *keydef);
|
||||
uint _ma_recinfo_write(File file, MARIA_COLUMNDEF *recinfo);
|
||||
char *_ma_recinfo_read(char *ptr, MARIA_COLUMNDEF *recinfo);
|
||||
uint _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef);
|
||||
char *_ma_columndef_read(char *ptr, MARIA_COLUMNDEF *columndef);
|
||||
ulong _ma_calc_total_blob_length(MARIA_HA *info, const byte *record);
|
||||
ha_checksum _ma_checksum(MARIA_HA *info, const byte *buf);
|
||||
ha_checksum _ma_static_checksum(MARIA_HA *info, const byte *buf);
|
||||
|
|
|
@ -307,9 +307,10 @@ static void usage(void)
|
|||
puts("and you are welcome to modify and redistribute it under the GPL license\n");
|
||||
|
||||
puts("Pack a MARIA-table to take much less space.");
|
||||
puts("Keys are not updated, you must run maria_chk -rq on the datafile");
|
||||
puts("Keys are not updated, you must run maria_chk -rq on the index (.MAI) file");
|
||||
puts("afterwards to update the keys.");
|
||||
puts("You should give the .MYI file as the filename argument.");
|
||||
puts("You should give the .MAI file as the filename argument.");
|
||||
puts("To unpack a packed table, run maria_chk -u on the table");
|
||||
|
||||
VOID(printf("\nUsage: %s [OPTIONS] filename...\n", my_progname));
|
||||
my_print_help(my_long_options);
|
||||
|
@ -462,9 +463,9 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count)
|
|||
if (mrg->file[j]->s->base.reclength != mrg->file[j+1]->s->base.reclength ||
|
||||
mrg->file[j]->s->base.fields != mrg->file[j+1]->s->base.fields)
|
||||
goto diff_file;
|
||||
m1=mrg->file[j]->s->rec;
|
||||
m1=mrg->file[j]->s->columndef;
|
||||
end=m1+mrg->file[j]->s->base.fields;
|
||||
m2=mrg->file[j+1]->s->rec;
|
||||
m2=mrg->file[j+1]->s->columndef;
|
||||
for ( ; m1 != end ; m1++,m2++)
|
||||
{
|
||||
if (m1->type != m2->type || m1->length != m2->length)
|
||||
|
@ -773,8 +774,8 @@ static HUFF_COUNTS *init_huff_count(MARIA_HA *info,my_off_t records)
|
|||
for (i=0 ; i < info->s->base.fields ; i++)
|
||||
{
|
||||
enum en_fieldtype type;
|
||||
count[i].field_length=info->s->rec[i].length;
|
||||
type= count[i].field_type= (enum en_fieldtype) info->s->rec[i].type;
|
||||
count[i].field_length=info->s->columndef[i].length;
|
||||
type= count[i].field_type= (enum en_fieldtype) info->s->columndef[i].type;
|
||||
if (type == FIELD_INTERVALL ||
|
||||
type == FIELD_CONSTANT ||
|
||||
type == FIELD_ZERO)
|
||||
|
@ -1003,7 +1004,7 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
|
|||
/* Calculate pos, end_pos, and max_length for variable length fields. */
|
||||
if (count->field_type == FIELD_BLOB)
|
||||
{
|
||||
uint field_length=count->field_length -maria_portable_sizeof_char_ptr;
|
||||
uint field_length=count->field_length -portable_sizeof_char_ptr;
|
||||
ulong blob_length= _ma_calc_blob_length(field_length, start_pos);
|
||||
memcpy_fixed((char*) &pos, start_pos+field_length,sizeof(char*));
|
||||
end_pos=pos+blob_length;
|
||||
|
@ -2656,7 +2657,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
|
|||
case FIELD_BLOB:
|
||||
{
|
||||
ulong blob_length= _ma_calc_blob_length(field_length-
|
||||
maria_portable_sizeof_char_ptr,
|
||||
portable_sizeof_char_ptr,
|
||||
start_pos);
|
||||
/* Empty blobs are encoded with a single 1 bit. */
|
||||
if (!blob_length)
|
||||
|
@ -2673,7 +2674,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
|
|||
DBUG_PRINT("fields", ("FIELD_BLOB %lu bytes, bits: %2u",
|
||||
blob_length, count->length_bits));
|
||||
write_bits(blob_length,count->length_bits);
|
||||
memcpy_fixed(&blob,end_pos-maria_portable_sizeof_char_ptr,
|
||||
memcpy_fixed(&blob,end_pos-portable_sizeof_char_ptr,
|
||||
sizeof(char*));
|
||||
blob_end=blob+blob_length;
|
||||
/* Encode the blob bytes. */
|
||||
|
@ -2952,6 +2953,7 @@ static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg,
|
|||
|
||||
options|= HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA;
|
||||
mi_int2store(share->state.header.options,options);
|
||||
/* Save the original file type of we have to undo the packing later */
|
||||
share->state.header.org_data_file_type= share->state.header.data_file_type;
|
||||
share->state.header.data_file_type= COMPRESSED_RECORD;
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ int main(int argc, char *argv[])
|
|||
recinfo[0].type=FIELD_SKIP_ENDSPACE;
|
||||
recinfo[0].length=docid_length;
|
||||
recinfo[1].type=FIELD_BLOB;
|
||||
recinfo[1].length= 4+mi_portable_sizeof_char_ptr;
|
||||
recinfo[1].length= 4+portable_sizeof_char_ptr;
|
||||
|
||||
/* Define a key over the first column */
|
||||
keyinfo[0].seg=keyseg;
|
||||
|
|
|
@ -75,12 +75,12 @@ static int run_test(const char *filename)
|
|||
|
||||
/* First define 2 columns */
|
||||
recinfo[0].type=extra_field;
|
||||
recinfo[0].length= (extra_field == FIELD_BLOB ? 4 + mi_portable_sizeof_char_ptr :
|
||||
recinfo[0].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr :
|
||||
extra_length);
|
||||
if (extra_field == FIELD_VARCHAR)
|
||||
recinfo[0].length+= HA_VARCHAR_PACKLENGTH(extra_length);
|
||||
recinfo[1].type=key_field;
|
||||
recinfo[1].length= (key_field == FIELD_BLOB ? 4+mi_portable_sizeof_char_ptr :
|
||||
recinfo[1].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr :
|
||||
key_length);
|
||||
if (key_field == FIELD_VARCHAR)
|
||||
recinfo[1].length+= HA_VARCHAR_PACKLENGTH(key_length);
|
||||
|
|
|
@ -31,9 +31,9 @@ ha_checksum mi_checksum(MI_INFO *info, const byte *buf)
|
|||
case FIELD_BLOB:
|
||||
{
|
||||
length=_mi_calc_blob_length(rec->length-
|
||||
mi_portable_sizeof_char_ptr,
|
||||
portable_sizeof_char_ptr,
|
||||
buf);
|
||||
memcpy((char*) &pos, buf+rec->length- mi_portable_sizeof_char_ptr,
|
||||
memcpy((char*) &pos, buf+rec->length- portable_sizeof_char_ptr,
|
||||
sizeof(char*));
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -117,10 +117,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
|
|||
share.base.blobs++;
|
||||
if (pack_reclength != INT_MAX32)
|
||||
{
|
||||
if (rec->length == 4+mi_portable_sizeof_char_ptr)
|
||||
if (rec->length == 4+portable_sizeof_char_ptr)
|
||||
pack_reclength= INT_MAX32;
|
||||
else
|
||||
pack_reclength+=(1 << ((rec->length-mi_portable_sizeof_char_ptr)*8)); /* Max blob length */
|
||||
pack_reclength+=(1 << ((rec->length-portable_sizeof_char_ptr)*8)); /* Max blob length */
|
||||
}
|
||||
}
|
||||
else if (type == FIELD_SKIP_PRESPACE ||
|
||||
|
|
|
@ -900,7 +900,7 @@ uint _mi_rec_pack(MI_INFO *info, register byte *to, register const byte *from)
|
|||
else
|
||||
{
|
||||
char *temp_pos;
|
||||
size_t tmp_length=length-mi_portable_sizeof_char_ptr;
|
||||
size_t tmp_length=length-portable_sizeof_char_ptr;
|
||||
memcpy((byte*) to,from,tmp_length);
|
||||
memcpy_fixed(&temp_pos,from+tmp_length,sizeof(char*));
|
||||
memcpy(to+tmp_length,temp_pos,(size_t) blob->length);
|
||||
|
@ -1021,11 +1021,11 @@ my_bool _mi_rec_check(MI_INFO *info,const char *record, byte *rec_buff,
|
|||
if (type == FIELD_BLOB)
|
||||
{
|
||||
uint blob_length=
|
||||
_mi_calc_blob_length(length-mi_portable_sizeof_char_ptr,record);
|
||||
_mi_calc_blob_length(length-portable_sizeof_char_ptr,record);
|
||||
if (!blob_length && !(flag & bit))
|
||||
goto err;
|
||||
if (blob_length)
|
||||
to+=length - mi_portable_sizeof_char_ptr+ blob_length;
|
||||
to+=length - portable_sizeof_char_ptr+ blob_length;
|
||||
}
|
||||
else if (type == FIELD_SKIP_ZERO)
|
||||
{
|
||||
|
@ -1208,7 +1208,7 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
|
|||
}
|
||||
else if (type == FIELD_BLOB)
|
||||
{
|
||||
uint size_length=rec_length- mi_portable_sizeof_char_ptr;
|
||||
uint size_length=rec_length- portable_sizeof_char_ptr;
|
||||
ulong blob_length=_mi_calc_blob_length(size_length,from);
|
||||
ulong from_left= (ulong) (from_end - from);
|
||||
if (from_left < size_length ||
|
||||
|
|
|
@ -453,7 +453,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
|||
if (share->rec[i].type == (int) FIELD_BLOB)
|
||||
{
|
||||
share->blobs[j].pack_length=
|
||||
share->rec[i].length-mi_portable_sizeof_char_ptr;;
|
||||
share->rec[i].length-portable_sizeof_char_ptr;;
|
||||
share->blobs[j].offset=offset;
|
||||
j++;
|
||||
}
|
||||
|
|
|
@ -1036,7 +1036,7 @@ static void uf_blob(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
|
|||
else
|
||||
{
|
||||
ulong length=get_bits(bit_buff,rec->space_length_bits);
|
||||
uint pack_length=(uint) (end-to)-mi_portable_sizeof_char_ptr;
|
||||
uint pack_length=(uint) (end-to)-portable_sizeof_char_ptr;
|
||||
if (bit_buff->blob_pos+length > bit_buff->blob_end)
|
||||
{
|
||||
bit_buff->error=1;
|
||||
|
|
|
@ -83,6 +83,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
|||
{
|
||||
mi_print_error(info->s, HA_ERR_CRASHED);
|
||||
my_errno=HA_ERR_CRASHED;
|
||||
if (share->concurrent_insert)
|
||||
rw_unlock(&share->key_root_lock[inx]);
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -71,12 +71,12 @@ static int run_test(const char *filename)
|
|||
/* First define 2 columns */
|
||||
recinfo[0].type=FIELD_NORMAL; recinfo[0].length=1; /* For NULL bits */
|
||||
recinfo[1].type=key_field;
|
||||
recinfo[1].length= (key_field == FIELD_BLOB ? 4+mi_portable_sizeof_char_ptr :
|
||||
recinfo[1].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr :
|
||||
key_length);
|
||||
if (key_field == FIELD_VARCHAR)
|
||||
recinfo[1].length+= HA_VARCHAR_PACKLENGTH(key_length);;
|
||||
recinfo[2].type=extra_field;
|
||||
recinfo[2].length= (extra_field == FIELD_BLOB ? 4 + mi_portable_sizeof_char_ptr : 24);
|
||||
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);
|
||||
if (opt_unique)
|
||||
|
|
|
@ -188,7 +188,7 @@ int main(int argc, char *argv[])
|
|||
if (use_blob)
|
||||
{
|
||||
recinfo[6].type=FIELD_BLOB;
|
||||
recinfo[6].length=4+mi_portable_sizeof_char_ptr;
|
||||
recinfo[6].length=4+portable_sizeof_char_ptr;
|
||||
recinfo[6].null_bit=0;
|
||||
recinfo[6].null_pos=0;
|
||||
}
|
||||
|
|
|
@ -305,7 +305,7 @@ static void usage(void)
|
|||
puts("and you are welcome to modify and redistribute it under the GPL license\n");
|
||||
|
||||
puts("Pack a MyISAM-table to take much less space.");
|
||||
puts("Keys are not updated, you must run myisamchk -rq on the datafile");
|
||||
puts("Keys are not updated, you must run myisamchk -rq on the index (.MYI) file");
|
||||
puts("afterwards to update the keys.");
|
||||
puts("You should give the .MYI file as the filename argument.");
|
||||
|
||||
|
@ -1008,7 +1008,7 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
|
|||
/* Calculate pos, end_pos, and max_length for variable length fields. */
|
||||
if (count->field_type == FIELD_BLOB)
|
||||
{
|
||||
uint field_length=count->field_length -mi_portable_sizeof_char_ptr;
|
||||
uint field_length=count->field_length -portable_sizeof_char_ptr;
|
||||
ulong blob_length= _mi_calc_blob_length(field_length, start_pos);
|
||||
memcpy_fixed((char*) &pos, start_pos+field_length,sizeof(char*));
|
||||
end_pos=pos+blob_length;
|
||||
|
@ -2650,7 +2650,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
|
|||
case FIELD_BLOB:
|
||||
{
|
||||
ulong blob_length=_mi_calc_blob_length(field_length-
|
||||
mi_portable_sizeof_char_ptr,
|
||||
portable_sizeof_char_ptr,
|
||||
start_pos);
|
||||
/* Empty blobs are encoded with a single 1 bit. */
|
||||
if (!blob_length)
|
||||
|
@ -2667,7 +2667,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
|
|||
DBUG_PRINT("fields", ("FIELD_BLOB %lu bytes, bits: %2u",
|
||||
blob_length, count->length_bits));
|
||||
write_bits(blob_length,count->length_bits);
|
||||
memcpy_fixed(&blob,end_pos-mi_portable_sizeof_char_ptr,
|
||||
memcpy_fixed(&blob,end_pos-portable_sizeof_char_ptr,
|
||||
sizeof(char*));
|
||||
blob_end=blob+blob_length;
|
||||
/* Encode the blob bytes. */
|
||||
|
|
|
@ -79,7 +79,7 @@ int run_test(const char *filename)
|
|||
/* Define spatial column */
|
||||
|
||||
recinfo[1].type=FIELD_BLOB;
|
||||
recinfo[1].length=4 + mi_portable_sizeof_char_ptr;
|
||||
recinfo[1].length=4 + portable_sizeof_char_ptr;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
#
|
||||
0 beshort 0xfe01 MySQL table definition file
|
||||
>2 byte x Version %d
|
||||
0 belong&0xffffff00 0xfefe0700 MySQL MISAM index file
|
||||
0 belong&0xffffff00 0xfefe0700 MySQL MyISAM index file
|
||||
>3 byte x Version %d
|
||||
0 belong&0xffffff00 0xfefe0800 MySQL MISAM compressed data file
|
||||
0 belong&0xffffff00 0xfefe0800 MySQL MyISAM compressed data file
|
||||
>3 byte x Version %d
|
||||
0 belong&0xffffff00 0xfefe0900 MySQL Maria index file
|
||||
>3 byte x Version %d
|
||||
|
|
Loading…
Reference in a new issue