diff --git a/include/maria.h b/include/maria.h index 8baacfc9c13..6e9ae4d8391 100644 --- a/include/maria.h +++ b/include/maria.h @@ -14,7 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This file should be included when using maria_funktions */ +/* This file should be included when using maria functions */ #ifndef _maria_h #define _maria_h @@ -250,7 +250,7 @@ typedef struct st_maria_columndef /* column information */ extern ulong maria_block_size, maria_checkpoint_frequency; extern ulong maria_concurrent_insert; -extern my_bool maria_flush, maria_single_user; +extern my_bool maria_flush, maria_single_user, maria_page_checksums; 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; diff --git a/include/my_base.h b/include/my_base.h index 553dcfe2232..fdf8d248879 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -304,8 +304,10 @@ enum ha_base_keytype { #define HA_OPTION_RELIES_ON_SQL_LAYER 512 #define HA_OPTION_NULL_FIELDS 1024 #define HA_OPTION_PAGE_CHECKSUM 2048 -#define HA_OPTION_TEMP_COMPRESS_RECORD ((uint) 16384) /* set by isamchk */ -#define HA_OPTION_READ_ONLY_DATA ((uint) 32768) /* Set by isamchk */ +#define HA_OPTION_TEMP_COMPRESS_RECORD (1L << 15) /* set by isamchk */ +#define HA_OPTION_READ_ONLY_DATA (1L << 16) /* Set by isamchk */ +#define HA_OPTION_NO_CHECKSUM (1L << 17) +#define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18) /* Bits in flag to create() */ @@ -372,6 +374,7 @@ enum ha_base_keytype { #define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */ #define HA_ERR_FOUND_DUPP_KEY 121 /* Dupplicate key on write */ +#define HA_ERR_INTERNAL_ERROR 122 /* Internal error */ #define HA_ERR_RECORD_CHANGED 123 /* Uppdate with is recoverable */ #define HA_ERR_WRONG_INDEX 124 /* Wrong index given to function */ #define HA_ERR_CRASHED 126 /* Indexfile is crashed */ @@ -433,7 +436,8 @@ enum ha_base_keytype { #define HA_ERR_NEW_FILE 172 /* New file format */ #define HA_ERR_INITIALIZATION 173 /* Error during initialization */ #define HA_ERR_FILE_TOO_SHORT 174 /* File too short */ -#define HA_ERR_LAST 174 /* Copy of last error nr */ +#define HA_ERR_WRONG_CRC 175 /* Wrong CRC on page */ +#define HA_ERR_LAST 175 /* Copy of last error nr */ /* Number of different errors */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/include/my_sys.h b/include/my_sys.h index 439670e34fc..48009a6eb46 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -62,12 +62,14 @@ extern int NEAR my_errno; /* Last error in mysys */ #define MY_HOLD_ORIGINAL_MODES 128 /* my_copy() holds to file modes */ #define MY_REDEL_MAKE_BACKUP 256 #define MY_SEEK_NOT_DONE 32 /* my_lock may have to do a seek */ -#define MY_DONT_WAIT 64 /* my_lock() don't wait if can't lock */ +#define MY_SHORT_WAIT 64 /* my_lock() don't wait if can't lock */ +#define MY_FORCE_LOCK 128 /* use my_lock() even if disable_locking */ +#define MY_NO_WAIT 256 /* my_lock() don't wait at all */ #define MY_ZEROFILL 32 /* my_malloc(), fill array with zero */ #define MY_ALLOW_ZERO_PTR 64 /* my_realloc() ; zero ptr -> malloc */ #define MY_FREE_ON_ERROR 128 /* my_realloc() ; Free old ptr on error */ #define MY_HOLD_ON_ERROR 256 /* my_realloc() ; Return old ptr on error */ -#define MY_DONT_OVERWRITE_FILE 1024 /* my_copy: Don't overwrite file */ +#define MY_DONT_OVERWRITE_FILE 2048 /* my_copy: Don't overwrite file */ #define MY_THREADSAFE 2048 /* my_seek(): lock fd mutex */ #define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */ diff --git a/include/myisam.h b/include/myisam.h index c49c094e757..292a0015964 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -225,7 +225,7 @@ struct st_mi_bit_buff; typedef struct st_columndef /* column information */ { - int16 type; /* en_fieldtype */ + enum en_fieldtype type; uint16 length; /* length of field */ uint32 offset; /* Offset to position in row */ uint8 null_bit; /* If column may be 0 */ diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 945a9af6d2a..566ccfe0778 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -474,12 +474,6 @@ sub mtr_kill_leftovers () { } } } - else - { - mtr_warning("Found non pid file $elem in $rundir") - if -f "$rundir/$elem"; - next; - } } closedir(RUNDIR); diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index bb2d91143f0..b8fc9f6c62d 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3097,6 +3097,7 @@ sub install_db ($$) { mtr_add_arg($args, "--datadir=%s", $data_dir); mtr_add_arg($args, "--loose-skip-innodb"); mtr_add_arg($args, "--loose-skip-ndbcluster"); + mtr_add_arg($args, "--sync-frm=0"); mtr_add_arg($args, "--tmpdir=."); mtr_add_arg($args, "--core-file"); @@ -3852,6 +3853,7 @@ sub mysqld_arguments ($$$$) { mtr_add_arg($args, "%s--datadir=%s", $prefix, $mysqld->{'path_myddir'}); + mtr_add_arg($args, "--sync-frm=0"); # Faster test if ( $mysql_version_id >= 50106 ) { diff --git a/mysql-test/r/binlog_unsafe.result b/mysql-test/r/binlog_unsafe.result index 47284ed8bc3..8467a18aa6b 100644 --- a/mysql-test/r/binlog_unsafe.result +++ b/mysql-test/r/binlog_unsafe.result @@ -11,3 +11,4 @@ Level Warning Code 1592 Message Statement is not safe to log in statement format. DROP TABLE t1,t2,t3; +DROP VIEW v1; diff --git a/mysql-test/r/maria.result b/mysql-test/r/maria.result index 62619feb323..8c462d6206c 100644 --- a/mysql-test/r/maria.result +++ b/mysql-test/r/maria.result @@ -325,7 +325,7 @@ KEY `ip` (`ip`), KEY `poster_login` (`poster_login`), KEY `topic_id` (`topic_id`), FULLTEXT KEY `post_text` (`post_text`) -); +) TRANSACTIONAL=0; INSERT INTO t1 (post_text) VALUES ('ceci est un test'),('ceci est un test'),('ceci est un test'),('ceci est un test'),('ceci est un test'); REPAIR TABLE t1; Table Op Msg_type Msg_text @@ -2052,6 +2052,7 @@ maria_checkpoint_interval 30 maria_log_file_size 4294959104 maria_log_purge_type immediate maria_max_sort_file_size 9223372036853727232 +maria_page_checksum ON maria_pagecache_age_threshold 300 maria_pagecache_buffer_size 8384512 maria_pagecache_division_limit 100 @@ -2068,3 +2069,10 @@ Maria_pagecache_read_requests # Maria_pagecache_reads # Maria_pagecache_write_requests # Maria_pagecache_writes # +create table t1 (s varchar(25), fulltext(s)) TRANSACTIONAL= 1; +ERROR HY000: Maria can't yet handle SPATIAL or FULLTEXT keys in transactional mode. For now use TRANSACTIONAL=0 +drop table if exists t1; +create table t1 ( fid int not null auto_increment primary key, +g geometry not null, spatial key(g)); +ERROR HY000: Maria can't yet handle SPATIAL or FULLTEXT keys in transactional mode. For now use TRANSACTIONAL=0 +drop table if exists t1; diff --git a/mysql-test/r/ps_maria.result b/mysql-test/r/ps_maria.result index f06aac10747..40ed382ec6d 100644 --- a/mysql-test/r/ps_maria.result +++ b/mysql-test/r/ps_maria.result @@ -1166,7 +1166,7 @@ def Extra 253 255 0 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t9 ALL NULL NULL NULL NULL 2 drop table if exists t2 ; -create table t2 (s varchar(25), fulltext(s)) +create table t2 (s varchar(25), fulltext(s)) TRANSACTIONAL= 0 ENGINE = 'MARIA' ; insert into t2 values ('Gravedigger'), ('Greed'),('Hollow Dogs') ; commit ; diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug28430.test b/mysql-test/suite/rpl/t/rpl_innodb_bug28430.test index eb828f07415..a2e6a7a5f98 100644 --- a/mysql-test/suite/rpl/t/rpl_innodb_bug28430.test +++ b/mysql-test/suite/rpl/t/rpl_innodb_bug28430.test @@ -1,3 +1,4 @@ +--source include/big_test.inc --source include/have_innodb.inc --source include/have_partition.inc --source include/have_binlog_format_mixed_or_row.inc diff --git a/mysql-test/t/binlog_unsafe.test b/mysql-test/t/binlog_unsafe.test index f34c22dc5f7..209e16e0cc0 100644 --- a/mysql-test/t/binlog_unsafe.test +++ b/mysql-test/t/binlog_unsafe.test @@ -14,5 +14,4 @@ INSERT INTO t1 SELECT UUID(); query_vertical SHOW WARNINGS; DROP TABLE t1,t2,t3; - - +DROP VIEW v1; diff --git a/mysql-test/t/maria.test b/mysql-test/t/maria.test index 219bae02d5d..dad107ad474 100644 --- a/mysql-test/t/maria.test +++ b/mysql-test/t/maria.test @@ -342,7 +342,7 @@ CREATE TABLE `t1` ( KEY `poster_login` (`poster_login`), KEY `topic_id` (`topic_id`), FULLTEXT KEY `post_text` (`post_text`) -); +) TRANSACTIONAL=0; INSERT INTO t1 (post_text) VALUES ('ceci est un test'),('ceci est un test'),('ceci est un test'),('ceci est un test'),('ceci est un test'); @@ -1306,6 +1306,18 @@ show variables like 'maria%'; --replace_column 2 # show status like 'maria%'; +# +# Show that we can't yet create fulltext or spatial index with Maria +# +--error 138 +create table t1 (s varchar(25), fulltext(s)) TRANSACTIONAL= 1; +drop table if exists t1; + +--error 138 +create table t1 ( fid int not null auto_increment primary key, +g geometry not null, spatial key(g)); +drop table if exists t1; + # End of 5.2 tests --disable_result_log diff --git a/mysql-test/t/ps_maria.test b/mysql-test/t/ps_maria.test index dba1cd01844..5c042b955e7 100644 --- a/mysql-test/t/ps_maria.test +++ b/mysql-test/t/ps_maria.test @@ -24,7 +24,7 @@ let $type= 'MARIA' ; --disable_warnings drop table if exists t2 ; --enable_warnings -eval create table t2 (s varchar(25), fulltext(s)) +eval create table t2 (s varchar(25), fulltext(s)) TRANSACTIONAL= 0 ENGINE = $type ; insert into t2 values ('Gravedigger'), ('Greed'),('Hollow Dogs') ; commit ; diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 44156da6ae3..351851cca76 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -134,7 +134,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) FILE *fd; char type[5]; DBUG_ENTER("my_fdopen"); - DBUG_PRINT("my",("Fd: %d Flags: %d MyFlags: %d", + DBUG_PRINT("my",("fd: %d Flags: %d MyFlags: %d", Filedes, Flags, MyFlags)); make_ftype(type,Flags); diff --git a/mysys/my_handler.c b/mysys/my_handler.c index 2b1c91a43e2..312227891c5 100644 --- a/mysys/my_handler.c +++ b/mysys/my_handler.c @@ -575,7 +575,7 @@ static const char *handler_error_messages[]= { "Didn't find key on read or update", "Duplicate key on write or update", - "Undefined handler error 122", + "Internal (unspecified) error in handler", "Someone has changed the row since it was read (while the table was locked to prevent it)", "Wrong index given to function", "Undefined handler error 125", @@ -627,7 +627,8 @@ static const char *handler_error_messages[]= "It is not possible to log this statement", "The table is of a new format not supported by this version", "Got a fatal error during initialzaction of handler", - "File to short; Expected more data in file" + "File to short; Expected more data in file", + "Read page with wrong checksum" }; diff --git a/mysys/my_lock.c b/mysys/my_lock.c index c0522ee849d..200ee7188c9 100644 --- a/mysys/my_lock.c +++ b/mysys/my_lock.c @@ -49,12 +49,12 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, int nxErrno; #endif DBUG_ENTER("my_lock"); - DBUG_PRINT("my",("Fd: %d Op: %d start: %ld Length: %ld MyFlags: %d", + DBUG_PRINT("my",("fd: %d Op: %d start: %ld Length: %ld MyFlags: %d", fd,locktype,(long) start,(long) length,MyFlags)); #ifdef VMS DBUG_RETURN(0); #else - if (my_disable_locking) + if (my_disable_locking && ! (MyFlags & MY_FORCE_LOCK)) DBUG_RETURN(0); #if defined(__NETWARE__) @@ -131,10 +131,16 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, lock.l_start= (off_t) start; lock.l_len= (off_t) length; - if (MyFlags & MY_DONT_WAIT) + if (MyFlags & (MY_NO_WAIT | MY_SHORT_WAIT)) { if (fcntl(fd,F_SETLK,&lock) != -1) /* Check if we can lock */ - DBUG_RETURN(0); /* Ok, file locked */ + DBUG_RETURN(0); /* Ok, file locked */ + if (MyFlags & MY_NO_WAIT) + { + my_errno= (errno == EACCES) ? EAGAIN : errno ? errno : -1; + DBUG_RETURN(-1); + } + DBUG_PRINT("info",("Was locked, trying with alarm")); ALARM_INIT; while ((value=fcntl(fd,F_SETLKW,&lock)) && ! ALARM_TEST && diff --git a/mysys/my_pread.c b/mysys/my_pread.c index 821d8636d8e..e0218cd1f1f 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -48,7 +48,7 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, size_t readbytes; int error= 0; DBUG_ENTER("my_pread"); - DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d", + DBUG_PRINT("my",("fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d", Filedes, (ulong) offset, (long) Buffer, (uint) Count, MyFlags)); for (;;) @@ -128,7 +128,7 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count, size_t writenbytes, written; uint errors; DBUG_ENTER("my_pwrite"); - DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d", + DBUG_PRINT("my",("fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d", Filedes, (ulong) offset, (long) Buffer, (uint) Count, MyFlags)); errors= 0; diff --git a/mysys/my_read.c b/mysys/my_read.c index ee91620e163..63f1d4fdebd 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -37,7 +37,7 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) { size_t readbytes, save_count; DBUG_ENTER("my_read"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", + DBUG_PRINT("my",("fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", Filedes, (long) Buffer, (ulong) Count, MyFlags)); save_count= Count; diff --git a/mysys/my_seek.c b/mysys/my_seek.c index 2c661baeff7..4e18b510a1e 100644 --- a/mysys/my_seek.c +++ b/mysys/my_seek.c @@ -47,7 +47,7 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, { reg1 os_off_t newpos= -1; DBUG_ENTER("my_seek"); - DBUG_PRINT("my",("Fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d", + DBUG_PRINT("my",("fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d", fd, (ulong) (((ulonglong) pos) >> 32), (ulong) pos, whence, MyFlags)); DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */ @@ -87,7 +87,7 @@ my_off_t my_tell(File fd, myf MyFlags __attribute__((unused))) { os_off_t pos; DBUG_ENTER("my_tell"); - DBUG_PRINT("my",("Fd: %d MyFlags: %d",fd, MyFlags)); + DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); DBUG_ASSERT(fd >= 0); #ifdef HAVE_TELL pos=tell(fd); diff --git a/mysys/my_sync.c b/mysys/my_sync.c index ba6964b00d6..1b8420c034e 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -44,7 +44,7 @@ int my_sync(File fd, myf my_flags) { int res; DBUG_ENTER("my_sync"); - DBUG_PRINT("my",("Fd: %d my_flags: %d", fd, my_flags)); + DBUG_PRINT("my",("fd: %d my_flags: %d", fd, my_flags)); do { diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index c9ce6ab169f..aadb86d39ed 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -289,12 +289,12 @@ my_bool my_thread_init(void) #endif pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST); pthread_cond_init(&tmp->suspend, NULL); - tmp->init= 1; pthread_mutex_lock(&THR_LOCK_threads); tmp->id= ++thread_id; ++THR_thread_count; pthread_mutex_unlock(&THR_LOCK_threads); + tmp->init= 1; #ifndef DBUG_OFF /* Generate unique name for thread */ (void) my_thread_name(); @@ -392,7 +392,7 @@ extern void **my_thread_var_dbug() { struct st_my_thread_var *tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); - return tmp ? &tmp->dbug : 0; + return tmp && tmp->init ? &tmp->dbug : 0; } #endif diff --git a/mysys/my_write.c b/mysys/my_write.c index c67b1d8f3f2..7f8b85c241e 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -25,7 +25,7 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags) size_t writenbytes, written; uint errors; DBUG_ENTER("my_write"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", + DBUG_PRINT("my",("fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", Filedes, (long) Buffer, (ulong) Count, MyFlags)); errors=0; written=0; diff --git a/sql/handler.cc b/sql/handler.cc index bb804768326..5d2646cf36c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -26,7 +26,7 @@ #include "mysql_priv.h" #include "rpl_filter.h" #include -#include +#include "myisam.h" #ifdef WITH_PARTITION_STORAGE_ENGINE #include "ha_partition.h" diff --git a/sql/handler.h b/sql/handler.h index 707334ccecd..93da48d450f 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -237,8 +237,6 @@ #define HA_LEX_CREATE_TMP_TABLE 1 #define HA_LEX_CREATE_IF_NOT_EXISTS 2 #define HA_LEX_CREATE_TABLE_LIKE 4 -#define HA_OPTION_NO_CHECKSUM (1L << 17) -#define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18) #define HA_MAX_REC_LENGTH 65535 /* Table caching type */ @@ -1359,14 +1357,18 @@ public: } virtual int read_first_row(uchar *buf, uint primary_key); /* - The following function is only needed for tables that may be temporary - tables during joins + The following 3 function is only needed for tables that may be + internal temporary tables during joins */ - virtual int restart_rnd_next(uchar *buf, uchar *pos) + virtual int remember_rnd_pos() + { return HA_ERR_WRONG_COMMAND; } + virtual int restart_rnd_next(uchar *buf) { return HA_ERR_WRONG_COMMAND; } virtual int rnd_same(uchar *buf, uint inx) { return HA_ERR_WRONG_COMMAND; } - virtual ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key) + + virtual ha_rows records_in_range(uint inx, key_range *min_key, + key_range *max_key) { return (ha_rows) 10; } virtual void position(const uchar *record)=0; virtual int info(uint)=0; // see my_base.h for full description diff --git a/sql/my_lock.c b/sql/my_lock.c index f66d7282f72..276259b106a 100644 --- a/sql/my_lock.c +++ b/sql/my_lock.c @@ -25,7 +25,15 @@ #include #include - /* Lock a part of a file */ +/** + @breif Lock a part of a file + + @note + This works like mysys/my_lock.c, with the exception that this function + uses the thr_alarm() to break long lock statements. + (mysys can't use thr_alarm() as by default the alarm handling doesn't + exists) +*/ int my_lock(File fd,int locktype,my_off_t start,my_off_t length,myf MyFlags) { @@ -36,29 +44,34 @@ int my_lock(File fd,int locktype,my_off_t start,my_off_t length,myf MyFlags) DBUG_ENTER("my_lock"); DBUG_PRINT("my",("Fd: %d Op: %d start: %ld Length: %ld MyFlags: %d", fd,locktype,(ulong) start,(ulong) length,MyFlags)); - if (my_disable_locking) + if (my_disable_locking && ! (MyFlags & MY_FORCE_LOCK)) DBUG_RETURN(0); /* purecov: inspected */ + m_lock.l_type=(short) locktype; m_lock.l_whence=0L; m_lock.l_start=(long) start; m_lock.l_len=(long) length; - wait_for_alarm=(MyFlags & MY_DONT_WAIT ? MY_HOW_OFTEN_TO_ALARM : - (uint) 12*60*60); if (fcntl(fd,F_SETLK,&m_lock) != -1) /* Check if we can lock */ DBUG_RETURN(0); /* Ok, file locked */ - DBUG_PRINT("info",("Was locked, trying with alarm")); - if (!thr_alarm(&alarmed,wait_for_alarm,&alarm_buff)) + + if (!(MyFlags & MY_NO_WAIT)) { - int value; - while ((value=fcntl(fd,F_SETLKW,&m_lock)) && !thr_got_alarm(&alarmed) && - errno == EINTR) ; - thr_end_alarm(&alarmed); - if (value != -1) - DBUG_RETURN(0); - } - else - { - errno=EINTR; + wait_for_alarm= (MyFlags & MY_SHORT_WAIT ? MY_HOW_OFTEN_TO_ALARM : + (uint) 12*60*60); + DBUG_PRINT("info",("Was locked, trying with alarm")); + if (!thr_alarm(&alarmed,wait_for_alarm,&alarm_buff)) + { + int value; + while ((value=fcntl(fd,F_SETLKW,&m_lock)) && !thr_got_alarm(&alarmed) && + errno == EINTR) ; + thr_end_alarm(&alarmed); + if (value != -1) + DBUG_RETURN(0); + } + else + { + errno=EINTR; + } } if (errno == EINTR || errno == EACCES) my_errno=EAGAIN; /* Easier to check for this */ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7484c2b26b1..d4154c7bcfe 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1945,6 +1945,7 @@ extern TYPELIB log_output_typelib; extern SHOW_COMP_OPTION have_maria_db; extern handlerton *partition_hton; extern handlerton *myisam_hton; +extern handlerton *maria_hton; extern handlerton *heap_hton; extern SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a6a1d0a88db..91cc824b3d8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3284,7 +3284,7 @@ static int init_server_components() my_rnd_init(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2); set_proper_floating_point_mode(); init_thr_lock(); - my_uuid_init(my_rnd(&sql_rand),12345); + my_uuid_init((ulong) (my_rnd(&sql_rand))*12345,12345); #ifdef HAVE_REPLICATION init_slave_list(); #endif diff --git a/sql/sql_class.h b/sql/sql_class.h index fdc76309593..a6a821a9433 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2214,7 +2214,14 @@ public: int prepare2(void) { return 0; } }; + +#ifdef WITH_MARIA_STORAGE_ENGINE +#include +#define ENGINE_COLUMNDEF MARIA_COLUMNDEF +#else #include +#define ENGINE_COLUMNDEF MI_COLUMNDEF +#endif /* Param to create temporary tables when doing SELECT:s @@ -2236,7 +2243,7 @@ public: Copy_field *save_copy_field, *save_copy_field_end; uchar *group_buff; Item **items_to_copy; /* Fields in tmp table */ - MI_COLUMNDEF *recinfo,*start_recinfo; + ENGINE_COLUMNDEF *recinfo, *start_recinfo; KEY *keyinfo; ha_rows end_write_records; uint field_count,sum_func_count,func_count; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 2a86844c8c6..a602ff6ada6 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -633,7 +633,7 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO) *plugin= pi; #endif pi->ref_count++; - DBUG_PRINT("info",("thd: 0x%lx, plugin: \"%s\", ref_count: %d", + DBUG_PRINT("info",("thd: 0x%lx plugin: \"%s\" ref_count: %d", (long) current_thd, pi->name.str, pi->ref_count)); if (lex) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ff15789df97..8b6ff35b06f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -27,11 +27,16 @@ #include "mysql_priv.h" #include "sql_select.h" #include "sql_cursor.h" - #include #include #include #include +#ifdef WITH_MARIA_STORAGE_ENGINE +#include "../storage/maria/ha_maria.h" +#define TMP_ENGINE_HTON maria_hton +#else +#define TMP_ENGINE_HTON myisam_hton +#endif const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref", "MAYBE_REF","ALL","range","index","fulltext", @@ -116,8 +121,14 @@ static COND *optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value); static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item); static bool open_tmp_table(TABLE *table); -static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, +static bool create_internal_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, ulonglong options); +static bool create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, + TMP_TABLE_PARAM *param, + int error, + bool ignore_last_dupp, + handlerton *hton, + const char *proc_info); static int do_select(JOIN *join,List *fields,TABLE *tmp_table, Procedure *proc); @@ -9565,7 +9576,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, KEY *keyinfo; KEY_PART_INFO *key_part_info; Item **copy_func; - MI_COLUMNDEF *recinfo; + ENGINE_COLUMNDEF *recinfo; uint total_uneven_bit_length= 0; bool force_copy_fields= param->force_copy_fields; DBUG_ENTER("create_tmp_table"); @@ -9591,11 +9602,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, /* No need to change table name to lower case as we are only creating - MyISAM or HEAP tables here + MyISAM, Maria or HEAP tables here */ fn_format(path, path, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME); - if (group) { if (!param->quick_group) @@ -9687,7 +9697,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, init_tmp_table_share(thd, share, "", 0, tmpname, tmpname); share->blob_field= blob_field; share->blob_ptr_size= portable_sizeof_char_ptr; - share->db_low_byte_first=1; // True for HEAP and MyISAM + share->db_low_byte_first=1; // True for HEAP, MyISAM and Maria share->table_charset= param->table_charset; share->primary_key= MAX_KEY; // Indicate no primary key share->keys_for_keyread.init(); @@ -9819,6 +9829,12 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, *blob_field++= fieldnr; blob_count++; } + if (new_field->real_type() == MYSQL_TYPE_STRING || + new_field->real_type() == MYSQL_TYPE_VARCHAR) + { + string_count++; + string_total_length+= new_field->pack_length(); + } if (item->marker == 4 && item->maybe_null) { group_null_items++; @@ -9855,7 +9871,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) == OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM)) { - share->db_plugin= ha_lock_engine(0, myisam_hton); + share->db_plugin= ha_lock_engine(0, TMP_ENGINE_HTON); table->file= get_new_handler(share, &table->mem_root, share->db_type()); if (group && @@ -9872,7 +9888,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, if (!table->file) goto err; - if (!using_unique_constraint) reclength+= group_null_items; // null flag is stored separately @@ -10008,13 +10023,16 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, /* Make entry for create table */ recinfo->length=length; if (field->flags & BLOB_FLAG) - recinfo->type= (int) FIELD_BLOB; + recinfo->type= FIELD_BLOB; else if (use_packed_rows && field->real_type() == MYSQL_TYPE_STRING && length >= MIN_STRING_LENGTH_TO_PACK_ROWS) - recinfo->type=FIELD_SKIP_ENDSPACE; + recinfo->type= FIELD_SKIP_ENDSPACE; + else if (field->real_type() == MYSQL_TYPE_VARCHAR) + recinfo->type= FIELD_VARCHAR; else - recinfo->type=FIELD_NORMAL; + recinfo->type= FIELD_NORMAL; + if (!--hidden_field_count) null_count=(null_count+7) & ~7; // move to next byte @@ -10177,9 +10195,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, if (thd->is_fatal_error) // If end of memory goto err; /* purecov: inspected */ share->db_record_offset= 1; - if (share->db_type() == myisam_hton) + if (share->db_type() == TMP_ENGINE_HTON) { - if (create_myisam_tmp_table(table,param,select_options)) + if (create_internal_tmp_table(table,param,select_options)) goto err; } if (open_tmp_table(table)) @@ -10344,15 +10362,149 @@ static bool open_tmp_table(TABLE *table) } -static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, - ulonglong options) +#ifdef WITH_MARIA_STORAGE_ENGINE + +/* Create internal Maria temporary table */ + +static bool create_internal_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, + ulonglong options) +{ + int error; + MARIA_KEYDEF keydef; + MARIA_UNIQUEDEF uniquedef; + KEY *keyinfo=param->keyinfo; + TABLE_SHARE *share= table->s; + MARIA_CREATE_INFO create_info; + DBUG_ENTER("create_internal_tmp_table"); + + if (share->keys) + { // Get keys for ni_create + bool using_unique_constraint=0; + HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&table->mem_root, + sizeof(*seg) * keyinfo->key_parts); + if (!seg) + goto err; + + bzero(seg, sizeof(*seg) * keyinfo->key_parts); + if (keyinfo->key_length >= table->file->max_key_length() || + keyinfo->key_parts > table->file->max_key_parts() || + share->uniques) + { + /* Can't create a key; Make a unique constraint instead of a key */ + share->keys= 0; + share->uniques= 1; + using_unique_constraint=1; + bzero((char*) &uniquedef,sizeof(uniquedef)); + uniquedef.keysegs=keyinfo->key_parts; + uniquedef.seg=seg; + uniquedef.null_are_equal=1; + + /* Create extra column for hash value */ + bzero((uchar*) param->recinfo,sizeof(*param->recinfo)); + param->recinfo->type= FIELD_CHECK; + param->recinfo->length= MARIA_UNIQUE_HASH_LENGTH; + param->recinfo++; + share->reclength+= MARIA_UNIQUE_HASH_LENGTH; + } + else + { + /* Create an unique key */ + bzero((char*) &keydef,sizeof(keydef)); + keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY; + keydef.keysegs= keyinfo->key_parts; + keydef.seg= seg; + } + for (uint i=0; i < keyinfo->key_parts ; i++,seg++) + { + Field *field=keyinfo->key_part[i].field; + seg->flag= 0; + seg->language= field->charset()->number; + seg->length= keyinfo->key_part[i].length; + seg->start= keyinfo->key_part[i].offset; + if (field->flags & BLOB_FLAG) + { + seg->type= + ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ? + HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2); + seg->bit_start= (uint8)(field->pack_length() - share->blob_ptr_size); + seg->flag= HA_BLOB_PART; + seg->length=0; // Whole blob in unique constraint + } + else + { + seg->type= keyinfo->key_part[i].type; + /* Tell handler if it can do suffic space compression */ + if (field->real_type() == MYSQL_TYPE_STRING && + keyinfo->key_part[i].length > 4) + seg->flag|= HA_SPACE_PACK; + } + if (!(field->flags & NOT_NULL_FLAG)) + { + seg->null_bit= field->null_bit; + seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]); + /* + We are using a GROUP BY on something that contains NULL + In this case we have to tell Maria that two NULL should + on INSERT be regarded at the same value + */ + if (!using_unique_constraint) + keydef.flag|= HA_NULL_ARE_EQUAL; + } + } + } + bzero((char*) &create_info,sizeof(create_info)); + + if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) == + OPTION_BIG_TABLES) + create_info.data_file_length= ~(ulonglong) 0; + + if ((error= maria_create(share->table_name.str, + share->reclength < 64 && + !share->blob_fields ? STATIC_RECORD : + BLOCK_RECORD, + share->keys, &keydef, + (uint) (param->recinfo-param->start_recinfo), + param->start_recinfo, + share->uniques, &uniquedef, + &create_info, + HA_CREATE_TMP_TABLE))) + { + table->file->print_error(error,MYF(0)); /* purecov: inspected */ + table->db_stat=0; + goto err; + } + status_var_increment(table->in_use->status_var.created_tmp_disk_tables); + share->db_record_offset= 1; + DBUG_RETURN(0); + err: + DBUG_RETURN(1); +} + + +bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, + TMP_TABLE_PARAM *param, + int error, + bool ignore_last_dupp_key_error) +{ + return create_internal_tmp_table_from_heap2(thd, table, param, error, + ignore_last_dupp_key_error, + maria_hton, + "converting HEAP to Maria"); +} + +#else + +/* Create internal MyISAM temporary table */ + +static bool create_internal_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, + ulonglong options) { int error; MI_KEYDEF keydef; MI_UNIQUEDEF uniquedef; KEY *keyinfo=param->keyinfo; TABLE_SHARE *share= table->s; - DBUG_ENTER("create_myisam_tmp_table"); + DBUG_ENTER("create_internal_tmp_table"); if (share->keys) { // Get keys for ni_create @@ -10455,54 +10607,43 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, } -void -free_tmp_table(THD *thd, TABLE *entry) -{ - MEM_ROOT own_root= entry->mem_root; - const char *save_proc_info; - DBUG_ENTER("free_tmp_table"); - DBUG_PRINT("enter",("table: %s",entry->alias)); - - save_proc_info=thd->proc_info; - thd->proc_info="removing tmp table"; - - if (entry->file) - { - if (entry->db_stat) - entry->file->drop_table(entry->s->table_name.str); - else - entry->file->delete_table(entry->s->table_name.str); - delete entry->file; - } - - /* free blobs */ - for (Field **ptr=entry->field ; *ptr ; ptr++) - (*ptr)->free(); - free_io_cache(entry); - - if (entry->temp_pool_slot != MY_BIT_NONE) - bitmap_lock_clear_bit(&temp_pool, entry->temp_pool_slot); - - plugin_unlock(0, entry->s->db_plugin); - - free_root(&own_root, MYF(0)); /* the table is allocated in its own root */ - thd->proc_info=save_proc_info; - - DBUG_VOID_RETURN; -} - /* -* If a HEAP table gets full, create a MyISAM table and copy all rows to this + If a HEAP table gets full, create a MyISAM table and copy all rows to this */ -bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, - int error, bool ignore_last_dupp_key_error) +bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, + TMP_TABLE_PARAM *param, + int error, + bool ignore_last_dupp_key_error) +{ + return create_internal_tmp_table_from_heap2(thd, table, param, error, + ignore_last_dupp_key_error, + myisam_hton, + "converting HEAP to MyISAM"); +} + +#endif /* WITH_MARIA_STORAGE_ENGINE */ + + +/* + If a HEAP table gets full, create a internal table in MyISAM or Maria + and copy all rows to this +*/ + + +static bool +create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, + TMP_TABLE_PARAM *param, + int error, + bool ignore_last_dupp_key_error, + handlerton *hton, + const char *proc_info) { TABLE new_table; TABLE_SHARE share; const char *save_proc_info; int write_err; - DBUG_ENTER("create_myisam_from_heap"); + DBUG_ENTER("create_internal_tmp_table_from_heap2"); if (table->s->db_type() != heap_hton || error != HA_ERR_RECORD_FILE_FULL) @@ -10513,15 +10654,15 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, new_table= *table; share= *table->s; new_table.s= &share; - new_table.s->db_plugin= ha_lock_engine(thd, myisam_hton); + new_table.s->db_plugin= ha_lock_engine(thd, hton); if (!(new_table.file= get_new_handler(&share, &new_table.mem_root, new_table.s->db_type()))) DBUG_RETURN(1); // End of memory save_proc_info=thd->proc_info; - thd->proc_info="converting HEAP to MyISAM"; + thd->proc_info= proc_info; - if (create_myisam_tmp_table(&new_table, param, + if (create_internal_tmp_table(&new_table, param, thd->lex->select_lex.options | thd->options)) goto err2; if (open_tmp_table(&new_table)) @@ -10602,6 +10743,43 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, } +void +free_tmp_table(THD *thd, TABLE *entry) +{ + MEM_ROOT own_root= entry->mem_root; + const char *save_proc_info; + DBUG_ENTER("free_tmp_table"); + DBUG_PRINT("enter",("table: %s",entry->alias)); + + save_proc_info=thd->proc_info; + thd->proc_info="removing tmp table"; + + if (entry->file) + { + if (entry->db_stat) + entry->file->drop_table(entry->s->table_name.str); + else + entry->file->delete_table(entry->s->table_name.str); + delete entry->file; + } + + /* free blobs */ + for (Field **ptr=entry->field ; *ptr ; ptr++) + (*ptr)->free(); + free_io_cache(entry); + + if (entry->temp_pool_slot != MY_BIT_NONE) + bitmap_lock_clear_bit(&temp_pool, entry->temp_pool_slot); + + plugin_unlock(0, entry->s->db_plugin); + + free_root(&own_root, MYF(0)); /* the table is allocated in its own root */ + thd->proc_info=save_proc_info; + + DBUG_VOID_RETURN; +} + + /* SYNOPSIS setup_end_select_func() @@ -12029,7 +12207,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { if (!table->file->is_fatal_error(error, HA_CHECK_DUP)) goto end; - if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param, + if (create_internal_tmp_table_from_heap(join->thd, table, &join->tmp_table_param, error,1)) DBUG_RETURN(NESTED_LOOP_ERROR); // Not a table_is_full error table->s->uniques=0; // To ensure rows are the same @@ -12113,7 +12291,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), copy_funcs(join->tmp_table_param.items_to_copy); if ((error=table->file->write_row(table->record[0]))) { - if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param, + if (create_internal_tmp_table_from_heap(join->thd, table, &join->tmp_table_param, error, 0)) DBUG_RETURN(NESTED_LOOP_ERROR); // Not a table_is_full error /* Change method to update rows */ @@ -12208,7 +12386,7 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (!join->having || join->having->val_int()) { int error= table->file->write_row(table->record[0]); - if (error && create_myisam_from_heap(join->thd, table, + if (error && create_internal_tmp_table_from_heap(join->thd, table, &join->tmp_table_param, error, 0)) DBUG_RETURN(NESTED_LOOP_ERROR); @@ -13468,13 +13646,14 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field, else if (!found) { found=1; - file->position(record); // Remember position + if ((error= file->remember_rnd_pos())) + goto err; } } if (!found) break; // End of file - /* Restart search on next row */ - error=file->restart_rnd_next(record,file->ref); + /* Restart search on saved row */ + error=file->restart_rnd_next(record); } file->extra(HA_EXTRA_NO_CACHE); @@ -15585,7 +15764,7 @@ int JOIN::rollup_write_data(uint idx, TABLE *table_arg) copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]); if ((write_error= table_arg->file->write_row(table_arg->record[0]))) { - if (create_myisam_from_heap(thd, table_arg, &tmp_table_param, + if (create_internal_tmp_table_from_heap(thd, table_arg, &tmp_table_param, write_error, 0)) return 1; } diff --git a/sql/sql_select.h b/sql/sql_select.h index cb59032315a..743d8a45dc3 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -542,7 +542,7 @@ bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, uint elements, List &fields); void copy_fields(TMP_TABLE_PARAM *param); void copy_funcs(Item **func_ptr); -bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, +bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, int error, bool ignore_last_dupp_error); uint find_shortest_key(TABLE *table, const key_map *usable_keys); Field* create_tmp_field_from_field(THD *thd, Field* org_field, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index f57359231f8..35f56e9ce04 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -167,15 +167,15 @@ static my_bool show_plugins(THD *thd, plugin_ref plugin, switch (plug->license) { case PLUGIN_LICENSE_GPL: - table->field[9]->store(PLUGIN_LICENSE_GPL_STRING, + table->field[9]->store(PLUGIN_LICENSE_GPL_STRING, strlen(PLUGIN_LICENSE_GPL_STRING), cs); break; case PLUGIN_LICENSE_BSD: - table->field[9]->store(PLUGIN_LICENSE_BSD_STRING, + table->field[9]->store(PLUGIN_LICENSE_BSD_STRING, strlen(PLUGIN_LICENSE_BSD_STRING), cs); break; default: - table->field[9]->store(PLUGIN_LICENSE_PROPRIETARY_STRING, + table->field[9]->store(PLUGIN_LICENSE_PROPRIETARY_STRING, strlen(PLUGIN_LICENSE_PROPRIETARY_STRING), cs); break; } @@ -483,7 +483,7 @@ find_files(THD *thd, List *files, const char *db, file=dirp->dir_entry+i; if (dir) { /* Return databases */ - if ((file->name[0] == '.' && + if ((file->name[0] == '.' && ((file->name[1] == '.' && file->name[2] == '\0') || file->name[1] == '\0'))) continue; /* . or .. */ @@ -509,7 +509,7 @@ find_files(THD *thd, List *files, const char *db, file_name_len= filename_to_tablename(file->name, uname, sizeof(uname)); if (wild && wild_compare(uname, wild, 0)) continue; - if (!(file_name= + if (!(file_name= thd->make_lex_string(file_name, uname, file_name_len, TRUE))) { my_dirend(dirp); @@ -548,7 +548,7 @@ find_files(THD *thd, List *files, const char *db, continue; } #endif - if (!(file_name= + if (!(file_name= thd->make_lex_string(file_name, uname, file_name_len, TRUE)) || files->push_back(file_name)) { @@ -586,7 +586,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) /* Clear all messages with 'error' level status and - issue a warning with 'warning' level status in + issue a warning with 'warning' level status in case of invalid view and last error is ER_VIEW_INVALID */ mysql_reset_errors(thd, true); @@ -776,7 +776,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) Field **ptr,*field; for (ptr=table->field ; (field= *ptr); ptr++) { - if (!wild || !wild[0] || + if (!wild || !wild[0] || !wild_case_compare(system_charset_info, field->field_name,wild)) { if (table_list->view) @@ -987,13 +987,13 @@ static bool get_field_default_value(THD *thd, TABLE *table, bool has_default; bool has_now_default; - /* + /* We are using CURRENT_TIMESTAMP instead of NOW because it is more standard */ - has_now_default= table->timestamp_field == field && + has_now_default= table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_UN_FIELD; - + has_default= (field->type() != FIELD_TYPE_BLOB && !(field->flags & NO_DEFAULT_VALUE_FLAG) && field->unireg_check != Field::NEXT_NUMBER && @@ -1048,11 +1048,11 @@ static bool get_field_default_value(THD *thd, TABLE *table, to tailor the format of the statement. Can be NULL, in which case only SQL_MODE is considered when building the statement. - + NOTE Currently always return 0, but might return error code in the future. - + RETURN 0 OK */ @@ -1134,7 +1134,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, field->sql_type(type); packet->append(type.ptr(), type.length(), system_charset_info); - if (field->has_charset() && + if (field->has_charset() && !(thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))) { if (field->charset() != share->table_charset) @@ -1142,8 +1142,8 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN(" CHARACTER SET ")); packet->append(field->charset()->csname); } - /* - For string types dump collation name only if + /* + For string types dump collation name only if collation is not primary for the given charset */ if (!(field->charset()->state & MY_CS_PRIMARY)) @@ -1170,11 +1170,11 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(def_value.ptr(), def_value.length(), system_charset_info); } - if (!limited_mysql_mode && table->timestamp_field == field && + if (!limited_mysql_mode && table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD) packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP")); - if (field->unireg_check == Field::NEXT_NUMBER && + if (field->unireg_check == Field::NEXT_NUMBER && !(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS)) packet->append(STRING_WITH_LEN(" AUTO_INCREMENT")); @@ -1323,7 +1323,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(buff, (uint) (end - buff)); } - + if (share->table_charset && !(thd->variables.sql_mode & MODE_MYSQL323) && !(thd->variables.sql_mode & MODE_MYSQL40)) @@ -1494,7 +1494,7 @@ view_store_options(THD *thd, TABLE_LIST *table, String *buff) /* Append DEFINER clause to the given buffer. - + SYNOPSIS append_definer() thd [in] thread handle @@ -1523,7 +1523,7 @@ static void append_algorithm(TABLE_LIST *table, String *buff) /* Append DEFINER clause to the given buffer. - + SYNOPSIS append_definer() thd [in] thread handle @@ -1683,8 +1683,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port); } else - thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ? - tmp_sctx->host_or_ip : + thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ? + tmp_sctx->host_or_ip : tmp_sctx->host ? tmp_sctx->host : ""); if ((thd_info->db=tmp->db)) // Safe test thd_info->db=thd->strdup(thd_info->db); @@ -1713,7 +1713,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) thd_info->query=0; if (tmp->query) { - /* + /* query_length is always set to 0 when we set query = NULL; see the comment in sql_class.h why this prevents crashes in possible races with query_length @@ -1960,7 +1960,7 @@ void reset_status_vars() /* Note that SHOW_LONG_NOFLUSH variables are not reset */ if (ptr->type == SHOW_LONG) *(ulong*) ptr->value= 0; - } + } } /* @@ -2206,14 +2206,14 @@ void calc_sum_of_all_status(STATUS_VAR *to) I_List_iterator it(threads); THD *tmp; - + /* Get global values as base */ *to= global_status_var; - + /* Add to this status from existing threads */ while ((tmp= it++)) add_to_status(to, &tmp->status_var); - + VOID(pthread_mutex_unlock(&LOCK_thread_count)); DBUG_VOID_RETURN; } @@ -2248,7 +2248,7 @@ bool schema_table_store_record(THD *thd, TABLE *table) int error; if ((error= table->file->ha_write_row(table->record[0]))) { - if (create_myisam_from_heap(thd, table, + if (create_internal_tmp_table_from_heap(thd, table, table->pos_in_table_list->schema_table_param, error, 0)) return 1; @@ -2270,17 +2270,17 @@ int make_table_list(THD *thd, SELECT_LEX *sel, /** - @brief Get lookup value from the part of 'WHERE' condition + @brief Get lookup value from the part of 'WHERE' condition - @details This function gets lookup value from - the part of 'WHERE' condition if it's possible and + @details This function gets lookup value from + the part of 'WHERE' condition if it's possible and fill appropriate lookup_field_vals struct field with this value. @param[in] thd thread handler @param[in] item_func part of WHERE condition @param[in] table I_S table - @param[in, out] lookup_field_vals Struct which holds lookup values + @param[in, out] lookup_field_vals Struct which holds lookup values @return 0 success @@ -2288,7 +2288,7 @@ int make_table_list(THD *thd, SELECT_LEX *sel, */ bool get_lookup_value(THD *thd, Item_func *item_func, - TABLE_LIST *table, + TABLE_LIST *table, LOOKUP_FIELD_VALUES *lookup_field_vals) { ST_SCHEMA_TABLE *schema_table= table->schema_table; @@ -2354,16 +2354,16 @@ bool get_lookup_value(THD *thd, Item_func *item_func, /** - @brief Calculates lookup values from 'WHERE' condition + @brief Calculates lookup values from 'WHERE' condition @details This function calculates lookup value(database name, table name) - from 'WHERE' condition if it's possible and + from 'WHERE' condition if it's possible and fill lookup_field_vals struct fields with these values. @param[in] thd thread handler @param[in] cond WHERE condition @param[in] table I_S table - @param[in, out] lookup_field_vals Struct which holds lookup values + @param[in, out] lookup_field_vals Struct which holds lookup values @return 0 success @@ -2512,7 +2512,7 @@ static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table) @param[in] thd thread handler @param[in] cond WHERE condition @param[in] tables I_S table - @param[in, out] lookup_field_values Struct which holds lookup values + @param[in, out] lookup_field_values Struct which holds lookup values @return 0 success @@ -2574,7 +2574,7 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table) idx_field_vals idx_field_vals->db_name contains db name or wild string with_i_schema returns 1 if we added 'IS' name to list - otherwise returns 0 + otherwise returns 0 RETURN zero success @@ -2598,7 +2598,7 @@ int make_db_list(THD *thd, List *files, LIKE clause (see also get_index_field_values() function) */ if (!lookup_field_vals->db_value.str || - !wild_case_compare(system_charset_info, + !wild_case_compare(system_charset_info, INFORMATION_SCHEMA_NAME.str, lookup_field_vals->db_value.str)) { @@ -2642,7 +2642,7 @@ int make_db_list(THD *thd, List *files, } -struct st_add_schema_table +struct st_add_schema_table { List *files; const char *wild; @@ -2706,7 +2706,7 @@ int schema_tables_add(THD *thd, List *files, const char *wild) else if (wild_compare(tmp_schema_table->table_name, wild, 0)) continue; } - if ((file_name= + if ((file_name= thd->make_lex_string(file_name, tmp_schema_table->table_name, strlen(tmp_schema_table->table_name), TRUE)) && !files->push_back(file_name)) @@ -2762,7 +2762,7 @@ make_table_name_list(THD *thd, List *table_names, LEX *lex, } } else - { + { if (table_names->push_back(&lookup_field_vals->table_value)) return 1; /* @@ -2823,7 +2823,7 @@ make_table_name_list(THD *thd, List *table_names, LEX *lex, @retval 1 error */ -static int +static int fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables, ST_SCHEMA_TABLE *schema_table, Open_tables_state *open_tables_state_backup) @@ -2850,7 +2850,7 @@ fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables, Let us set fake sql_command so views won't try to merge themselves into main statement. If we don't do this, SELECT * from information_schema.xxxx will cause problems. - SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()' + SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()' */ lex->sql_command= SQLCOM_SHOW_FIELDS; res= open_normal_and_derived_tables(thd, show_table_list, @@ -2860,11 +2860,11 @@ fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables, get_all_tables() returns 1 on failure and 0 on success thus return only these and not the result code of ::process_table() - We should use show_table_list->alias instead of + We should use show_table_list->alias instead of show_table_list->table_name because table_name could be changed during opening of I_S tables. It's safe - to use alias because alias contains original table name - in this case(this part of code is used only for + to use alias because alias contains original table name + in this case(this part of code is used only for 'show columns' & 'show statistics' commands). */ table_name= thd->make_lex_string(&tmp_lex_string1, show_table_list->alias, @@ -2874,7 +2874,7 @@ fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables, show_table_list->db_length, FALSE); else db_name= &show_table_list->view_db; - + error= test(schema_table->process_table(thd, show_table_list, table, res, db_name, @@ -2912,7 +2912,7 @@ static int fill_schema_table_names(THD *thd, TABLE *table, { enum legacy_db_type not_used; char path[FN_REFLEN]; - (void) build_table_filename(path, sizeof(path), db_name->str, + (void) build_table_filename(path, sizeof(path), db_name->str, table_name->str, reg_ext, 0); switch (mysql_frm_type(thd, path, ¬_used)) { case FRMTYPE_ERROR: @@ -3000,7 +3000,7 @@ static uint get_table_open_method(TABLE_LIST *tables, */ static int fill_schema_table_from_frm(THD *thd,TABLE *table, - ST_SCHEMA_TABLE *schema_table, + ST_SCHEMA_TABLE *schema_table, LEX_STRING *db_name, LEX_STRING *table_name, enum enum_schema_tables schema_table_idx) @@ -3027,7 +3027,7 @@ static int fill_schema_table_from_frm(THD *thd,TABLE *table, res= 0; goto err; } - + if (share->is_view) { if (schema_table->i_s_requested_object & OPEN_TABLE_ONLY) @@ -3039,7 +3039,7 @@ static int fill_schema_table_from_frm(THD *thd,TABLE *table, else if (schema_table->i_s_requested_object & OPEN_VIEW_FULL) { /* - tell get_all_tables() to fall back to + tell get_all_tables() to fall back to open_normal_and_derived_tables() */ res= 1; @@ -3108,7 +3108,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) List db_names; List_iterator_fast it(db_names); COND *partial_cond= 0; - uint derived_tables= lex->derived_tables; + uint derived_tables= lex->derived_tables; int error= 1; Open_tables_state open_tables_state_backup; bool save_view_prepare_mode= lex->view_prepare_mode; @@ -3129,7 +3129,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) */ thd->reset_n_backup_open_tables_state(&open_tables_state_backup); - /* + /* this branch processes SHOW FIELDS, SHOW INDEXES commands. see sql_parse.cc, prepare_schema_table() function where this values are initialized @@ -3153,7 +3153,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value) { - /* + /* if lookup value is empty string then it's impossible table name or db name */ @@ -3171,7 +3171,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) !lookup_field_vals.wild_db_value) tables->has_db_lookup_value= TRUE; if (lookup_field_vals.table_value.length && - !lookup_field_vals.wild_table_value) + !lookup_field_vals.wild_table_value) tables->has_table_lookup_value= TRUE; if (tables->has_db_lookup_value && tables->has_table_lookup_value) @@ -3195,7 +3195,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) while ((db_name= it++)) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (!check_access(thd,SELECT_ACL, db_name->str, + if (!check_access(thd,SELECT_ACL, db_name->str, &thd->col_access, 0, 1, with_i_schema) || sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0) || @@ -3225,7 +3225,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) { /* If table is I_S.tables and open_table_method is 0 (eg SKIP_OPEN) - we can skip table opening and we don't have lookup value for + we can skip table opening and we don't have lookup value for table name or lookup value is wild string(table name list is already created by make_table_name_list() function). */ @@ -3247,7 +3247,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) } else { - if (!(table_open_method & ~OPEN_FRM_ONLY) && + if (!(table_open_method & ~OPEN_FRM_ONLY) && !with_i_schema) { if (!fill_schema_table_from_frm(thd, table, schema_table, db_name, @@ -3278,7 +3278,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) res= open_normal_and_derived_tables(thd, show_table_list, MYSQL_LOCK_IGNORE_FLUSH); lex->sql_command= save_sql_command; - + if (thd->net.last_errno == ER_NO_SUCH_TABLE) { /* @@ -3293,10 +3293,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) else { /* - We should use show_table_list->alias instead of + We should use show_table_list->alias instead of show_table_list->table_name because table_name could be changed during opening of I_S tables. It's safe - to use alias because alias contains original table name + to use alias because alias contains original table name in this case. */ thd->make_lex_string(&tmp_lex_string, show_table_list->alias, @@ -3506,7 +3506,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE) ptr=strmov(ptr," delay_key_write=1"); if (share->row_type != ROW_TYPE_DEFAULT) - ptr=strxmov(ptr, " row_format=", + ptr=strxmov(ptr, " row_format=", ha_row_type[(uint) share->row_type], NullS); if (share->transactional != HA_CHOICE_UNDEF) @@ -3516,8 +3516,8 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, NullS); } #ifdef WITH_PARTITION_STORAGE_ENGINE - if (show_table->s->db_type() == partition_hton && - show_table->part_info != NULL && + if (show_table->s->db_type() == partition_hton && + show_table->part_info != NULL && show_table->part_info->no_parts > 0) ptr= strmov(ptr, " partitioned"); #endif @@ -3525,7 +3525,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, ptr= strxmov(ptr, " transactional=", ha_choice_values[(uint) share->transactional], NullS); table->field[19]->store(option_buff+1, - (ptr == option_buff ? 0 : + (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1), cs); tmp_buff= (share->table_charset ? @@ -3640,7 +3640,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, /* I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS rather than in SHOW COLUMNS - */ + */ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, thd->net.last_errno, thd->net.last_error); thd->clear_error(); @@ -3678,7 +3678,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, uint col_access; check_access(thd,SELECT_ACL | EXTRA_ACL, db_name->str, &tables->grant.privilege, 0, 0, test(tables->schema_table)); - col_access= get_column_grant(thd, &tables->grant, + col_access= get_column_grant(thd, &tables->grant, db_name->str, table_name->str, field->field_name) & COL_ACLS; if (!tables->schema_table && !col_access) @@ -3701,7 +3701,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, cs); table->field[4]->store((longlong) count, TRUE); field->sql_type(type); - table->field[14]->store(type.ptr(), type.length(), cs); + table->field[14]->store(type.ptr(), type.length(), cs); tmp_buff= strchr(type.ptr(), '('); table->field[7]->store(type.ptr(), (tmp_buff ? tmp_buff - type.ptr() : @@ -3723,7 +3723,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, uint32 octet_max_length= field->max_display_length(); if (is_blob && octet_max_length != (uint32) 4294967295U) octet_max_length /= field->charset()->mbmaxlen; - longlong char_max_len= is_blob ? + longlong char_max_len= is_blob ? (longlong) octet_max_length / field->charset()->mbminlen : (longlong) octet_max_length / field->charset()->mbmaxlen; table->field[8]->store(char_max_len, TRUE); @@ -3756,7 +3756,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, field_length= field->max_display_length(); decimals= -1; // return NULL break; - case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_DOUBLE: field_length= field->field_length; if (decimals == NOT_FIXED_DEC) @@ -3822,7 +3822,7 @@ int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond) for (cs= all_charsets ; cs < all_charsets+255 ; cs++) { CHARSET_INFO *tmp_cs= cs[0]; - if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) && + if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) && (tmp_cs->state & MY_CS_AVAILABLE) && !(tmp_cs->state & MY_CS_HIDDEN) && !(wild && wild[0] && @@ -3910,7 +3910,7 @@ int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond) for (cl= all_charsets; cl < all_charsets+255 ;cl ++) { CHARSET_INFO *tmp_cl= cl[0]; - if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || + if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || !my_charset_same(tmp_cs, tmp_cl)) continue; if (!(wild && wild[0] && @@ -3944,13 +3944,13 @@ int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond) { CHARSET_INFO **cl; CHARSET_INFO *tmp_cs= cs[0]; - if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || + if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || !(tmp_cs->state & MY_CS_PRIMARY)) continue; for (cl= all_charsets; cl < all_charsets+255 ;cl ++) { CHARSET_INFO *tmp_cl= cl[0]; - if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || + if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || !my_charset_same(tmp_cs,tmp_cl)) continue; restore_record(table, s->default_values); @@ -4016,7 +4016,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, table->field[10]->store(STRING_WITH_LEN("SQL"), cs); get_field(thd->mem_root, proc_table->field[6], &tmp_string); table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs); - table->field[12]->store(sp_data_access_name[enum_idx].str, + table->field[12]->store(sp_data_access_name[enum_idx].str, sp_data_access_name[enum_idx].length , cs); get_field(thd->mem_root, proc_table->field[7], &tmp_string); table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs); @@ -4309,10 +4309,10 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, if (schema_table_store_record(thd, table)) DBUG_RETURN(1); if (res && thd->net.last_errno) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, thd->net.last_errno, thd->net.last_error); } - if (res) + if (res) thd->clear_error(); DBUG_RETURN(0); } @@ -4353,7 +4353,7 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, TABLE *show_table= tables->table; KEY *key_info=show_table->key_info; uint primary_key= show_table->s->primary_key; - show_table->file->info(HA_STATUS_VARIABLE | + show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) @@ -4382,7 +4382,7 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, List_iterator_fast it(f_key_list); while ((f_key_info=it++)) { - if (store_constraints(thd, table, db_name, table_name, + if (store_constraints(thd, table, db_name, table_name, f_key_info->forein_id->str, strlen(f_key_info->forein_id->str), "FOREIGN KEY", 11)) @@ -4541,7 +4541,7 @@ static int get_schema_key_column_usage_record(THD *thd, TABLE *show_table= tables->table; KEY *key_info=show_table->key_info; uint primary_key= show_table->s->primary_key; - show_table->file->info(HA_STATUS_VARIABLE | + show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) @@ -4558,8 +4558,8 @@ static int get_schema_key_column_usage_record(THD *thd, restore_record(table, s->default_values); store_key_column_usage(table, db_name, table_name, key_info->name, - strlen(key_info->name), - key_part->field->field_name, + strlen(key_info->name), + key_part->field->field_name, strlen(key_part->field->field_name), (longlong) f_idx); if (schema_table_store_record(thd, table)) @@ -4595,7 +4595,7 @@ static int get_schema_key_column_usage_record(THD *thd, system_charset_info); table->field[9]->set_notnull(); table->field[10]->store(f_key_info->referenced_table->str, - f_key_info->referenced_table->length, + f_key_info->referenced_table->length, system_charset_info); table->field[10]->set_notnull(); table->field[11]->store(r_info->str, r_info->length, @@ -4763,7 +4763,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, tmp_res.append(partition_keywords[PKW_KEY].str, partition_keywords[PKW_KEY].length); else - tmp_res.append(partition_keywords[PKW_HASH].str, + tmp_res.append(partition_keywords[PKW_HASH].str, partition_keywords[PKW_HASH].length); table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs); break; @@ -4798,7 +4798,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, tmp_res.append(partition_keywords[PKW_KEY].str, partition_keywords[PKW_KEY].length); else - tmp_res.append(partition_keywords[PKW_HASH].str, + tmp_res.append(partition_keywords[PKW_HASH].str, partition_keywords[PKW_HASH].length); table->field[8]->store(tmp_res.ptr(), tmp_res.length(), cs); table->field[8]->set_notnull(); @@ -4877,7 +4877,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, /* SUBPARTITION_ORDINAL_POSITION */ table->field[6]->store((longlong) ++subpart_pos, TRUE); table->field[6]->set_notnull(); - + store_schema_partitions_record(thd, table, show_table, subpart_elem, file, part_id); part_id++; @@ -5095,7 +5095,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) else sch_table->field[ISE_ON_COMPLETION]-> store(STRING_WITH_LEN("PRESERVE"), scs); - + number_to_datetime(et.created, &time, 0, ¬_used); DBUG_ASSERT(not_used==0); sch_table->field[ISE_CREATED]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); @@ -5216,7 +5216,7 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) tmp1= &tmp; } else - { + { option_type= OPT_SESSION; tmp1= &thd->status_var; } @@ -5271,7 +5271,7 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables, { List f_key_list; TABLE *show_table= tables->table; - show_table->file->info(HA_STATUS_VARIABLE | + show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); @@ -5285,16 +5285,16 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables, table->field[9]->store(table_name->str, table_name->length, cs); table->field[2]->store(f_key_info->forein_id->str, f_key_info->forein_id->length, cs); - table->field[4]->store(f_key_info->referenced_db->str, + table->field[4]->store(f_key_info->referenced_db->str, f_key_info->referenced_db->length, cs); - table->field[10]->store(f_key_info->referenced_table->str, + table->field[10]->store(f_key_info->referenced_table->str, f_key_info->referenced_table->length, cs); - table->field[5]->store(f_key_info->referenced_key_name->str, + table->field[5]->store(f_key_info->referenced_key_name->str, f_key_info->referenced_key_name->length, cs); table->field[6]->store(STRING_WITH_LEN("NONE"), cs); - table->field[7]->store(f_key_info->update_method->str, + table->field[7]->store(f_key_info->update_method->str, f_key_info->update_method->length, cs); - table->field[8]->store(f_key_info->delete_method->str, + table->field[8]->store(f_key_info->delete_method->str, f_key_info->delete_method->length, cs); if (schema_table_store_record(thd, table)) DBUG_RETURN(1); @@ -5303,7 +5303,7 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables, DBUG_RETURN(0); } -struct schema_table_ref +struct schema_table_ref { const char *table_name; ST_SCHEMA_TABLE *schema_table; @@ -5370,7 +5370,7 @@ ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name) } schema_table_a.table_name= table_name; - if (plugin_foreach(thd, find_schema_table_in_plugin, + if (plugin_foreach(thd, find_schema_table_in_plugin, MYSQL_INFORMATION_SCHEMA_PLUGIN, &schema_table_a)) DBUG_RETURN(schema_table_a.schema_table); @@ -5437,7 +5437,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) break; case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_DOUBLE: - if ((item= new Item_float(fields_info->field_name, 0.0, NOT_FIXED_DEC, + if ((item= new Item_float(fields_info->field_name, 0.0, NOT_FIXED_DEC, fields_info->field_length)) == NULL) DBUG_RETURN(NULL); break; @@ -5490,7 +5490,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) tmp_table_param->schema_table= 1; SELECT_LEX *select_lex= thd->lex->current_select; if (!(table= create_tmp_table(thd, tmp_table_param, - field_list, (ORDER*) 0, 0, 0, + field_list, (ORDER*) 0, 0, 0, (select_lex->options | thd->options | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR, table_list->alias))) @@ -5835,7 +5835,7 @@ bool get_schema_tables_result(JOIN *join, thd->no_warnings_for_error= 1; for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++) - { + { if (!tab->table || !tab->table->pos_in_table_list) break; @@ -5954,17 +5954,17 @@ ST_FIELD_INFO tables_fields_info[]= {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", OPEN_FULL_TABLE}, {"TABLE_ROWS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Rows", OPEN_FULL_TABLE}, - {"AVG_ROW_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, + {"AVG_ROW_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Avg_row_length", OPEN_FULL_TABLE}, - {"DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, + {"DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_length", OPEN_FULL_TABLE}, {"MAX_DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_data_length", OPEN_FULL_TABLE}, - {"INDEX_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, + {"INDEX_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Index_length", OPEN_FULL_TABLE}, {"DATA_FREE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_free", OPEN_FULL_TABLE}, - {"AUTO_INCREMENT", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG, 0, + {"AUTO_INCREMENT", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Auto_increment", OPEN_FULL_TABLE}, {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create_time", OPEN_FULL_TABLE}, {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update_time", OPEN_FULL_TABLE}, @@ -6429,9 +6429,9 @@ ST_FIELD_INFO files_fields_info[]= {"EXTENT_SIZE", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE}, {"INITIAL_SIZE", 21, MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE}, - {"MAXIMUM_SIZE", 21, MYSQL_TYPE_LONGLONG, 0, + {"MAXIMUM_SIZE", 21, MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE}, - {"AUTOEXTEND_SIZE", 21, MYSQL_TYPE_LONGLONG, 0, + {"AUTOEXTEND_SIZE", 21, MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE}, {"CREATION_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE}, {"LAST_UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE}, @@ -6443,20 +6443,20 @@ ST_FIELD_INFO files_fields_info[]= {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", SKIP_OPEN_TABLE}, {"TABLE_ROWS", 21 , MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Rows", SKIP_OPEN_TABLE}, - {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, + {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Avg_row_length", SKIP_OPEN_TABLE}, - {"DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, + {"DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_length", SKIP_OPEN_TABLE}, - {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, + {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_data_length", SKIP_OPEN_TABLE}, - {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, + {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Index_length", SKIP_OPEN_TABLE}, - {"DATA_FREE", 21 , MYSQL_TYPE_LONGLONG, 0, + {"DATA_FREE", 21 , MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_free", SKIP_OPEN_TABLE}, {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create_time", SKIP_OPEN_TABLE}, {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update_time", SKIP_OPEN_TABLE}, {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Check_time", SKIP_OPEN_TABLE}, - {"CHECKSUM", 21 , MYSQL_TYPE_LONGLONG, 0, + {"CHECKSUM", 21 , MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Checksum", SKIP_OPEN_TABLE}, {"STATUS", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}, {"EXTRA", 255, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, @@ -6505,13 +6505,13 @@ ST_FIELD_INFO referential_constraints_fields_info[]= ST_SCHEMA_TABLE schema_tables[]= { - {"CHARACTER_SETS", charsets_fields_info, create_schema_table, + {"CHARACTER_SETS", charsets_fields_info, create_schema_table, fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0}, - {"COLLATIONS", collation_fields_info, create_schema_table, + {"COLLATIONS", collation_fields_info, create_schema_table, fill_schema_collation, make_old_format, 0, -1, -1, 0, 0}, {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info, create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0, 0}, - {"COLUMNS", columns_fields_info, create_schema_table, + {"COLUMNS", columns_fields_info, create_schema_table, get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0, OPTIMIZE_I_S_TABLE|OPEN_VIEW_FULL}, {"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table, @@ -6540,7 +6540,7 @@ ST_SCHEMA_TABLE schema_tables[]= {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info, create_schema_table, get_all_tables, 0, get_referential_constraints_record, 1, 9, 0, OPEN_TABLE_ONLY}, - {"ROUTINES", proc_fields_info, create_schema_table, + {"ROUTINES", proc_fields_info, create_schema_table, fill_schema_proc, make_proc_old_format, 0, -1, -1, 0, 0}, {"SCHEMATA", schema_fields_info, create_schema_table, fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0}, @@ -6550,12 +6550,12 @@ ST_SCHEMA_TABLE schema_tables[]= fill_status, make_old_format, 0, -1, -1, 0, 0}, {"SESSION_VARIABLES", variables_fields_info, create_schema_table, fill_variables, make_old_format, 0, -1, -1, 0, 0}, - {"STATISTICS", stat_fields_info, create_schema_table, + {"STATISTICS", stat_fields_info, create_schema_table, get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0, OPEN_TABLE_ONLY|OPTIMIZE_I_S_TABLE}, - {"STATUS", variables_fields_info, create_schema_table, fill_status, + {"STATUS", variables_fields_info, create_schema_table, fill_status, make_old_format, 0, -1, -1, 1, 0}, - {"TABLES", tables_fields_info, create_schema_table, + {"TABLES", tables_fields_info, create_schema_table, get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0, OPTIMIZE_I_S_TABLE}, {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table, @@ -6567,11 +6567,11 @@ ST_SCHEMA_TABLE schema_tables[]= {"TRIGGERS", triggers_fields_info, create_schema_table, get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0, OPEN_TABLE_ONLY}, - {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table, + {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table, fill_schema_user_privileges, 0, 0, -1, -1, 0, 0}, {"VARIABLES", variables_fields_info, create_schema_table, fill_variables, make_old_format, 0, -1, -1, 1, 0}, - {"VIEWS", view_fields_info, create_schema_table, + {"VIEWS", view_fields_info, create_schema_table, get_all_tables, 0, get_schema_views_record, 1, 2, 0, OPEN_VIEW_ONLY|OPTIMIZE_I_S_TABLE}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} @@ -6597,8 +6597,8 @@ int initialize_schema_table(st_plugin_int *plugin) { schema_table->create_table= create_schema_table; schema_table->old_format= make_old_format; - schema_table->idx_field1= -1, - schema_table->idx_field2= -1; + schema_table->idx_field1= -1, + schema_table->idx_field2= -1; /* Make the name available to the init() function. */ schema_table->table_name= plugin->name.str; @@ -6609,7 +6609,7 @@ int initialize_schema_table(st_plugin_int *plugin) plugin->name.str); goto err; } - + /* Make sure the plugin name is not set inside the init() function. */ schema_table->table_name= plugin->name.str; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ed5cbfcf8b4..bc3b0e8836b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3195,8 +3195,9 @@ bool mysql_create_table_no_lock(THD *thd, if (check_engine(thd, table_name, create_info)) DBUG_RETURN(TRUE); db_options= create_info->table_options; - if (create_info->row_type == ROW_TYPE_DYNAMIC) - db_options|=HA_OPTION_PACK_RECORD; + if (create_info->row_type != ROW_TYPE_FIXED && + create_info->row_type != ROW_TYPE_DEFAULT) + db_options|= HA_OPTION_PACK_RECORD; alias= table_case_name(create_info, table_name); if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, create_info->db_type))) @@ -5162,8 +5163,7 @@ compare_tables(TABLE *table, } /* Don't pack rows in old tables if the user has requested this. */ - if (create_info->row_type == ROW_TYPE_DYNAMIC || - (new_field->flags & BLOB_FLAG) || + if ((new_field->flags & BLOB_FLAG) || new_field->sql_type == MYSQL_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED) create_info->table_options|= HA_OPTION_PACK_RECORD; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index a48cff82715..90d7b4dfc60 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -63,9 +63,9 @@ bool select_union::send_data(List &values) if ((error= table->file->ha_write_row(table->record[0]))) { - /* create_myisam_from_heap will generate error if needed */ + /* create_internal_tmp_table_from_heap will generate error if needed */ if (table->file->is_fatal_error(error, HA_CHECK_DUP) && - create_myisam_from_heap(thd, table, &tmp_table_param, error, 1)) + create_internal_tmp_table_from_heap(thd, table, &tmp_table_param, error, 1)) return 1; } return 0; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index ecb7acda61b..3be29747553 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1678,7 +1678,7 @@ bool multi_update::send_data(List ¬_used_values) if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE) { if (error && - create_myisam_from_heap(thd, tmp_table, + create_internal_tmp_table_from_heap(thd, tmp_table, tmp_table_param + offset, error, 1)) { do_update= 0; diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 1ce85e22f2f..cd13f19d646 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -124,6 +124,10 @@ static MYSQL_SYSVAR_ULONG(checkpoint_interval, checkpoint_interval, " 0 means 'no automatic checkpoints'.", NULL, update_checkpoint_interval, 30, 0, UINT_MAX, 1); +static MYSQL_SYSVAR_BOOL(page_checksum, maria_page_checksums, 0, + "Maintain page checksums (can be overridden per table " + "with PAGE_CHECKSUM clause in CREATE TABLE)", 0, 0, 1); + static MYSQL_SYSVAR_ULONG(log_file_size, log_file_size, PLUGIN_VAR_RQCMDARG, "Limit for transaction log size", @@ -267,8 +271,10 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type, # error code */ -int table2maria(TABLE *table_arg, MARIA_KEYDEF **keydef_out, - MARIA_COLUMNDEF **recinfo_out, uint *records_out) +static int table2maria(TABLE *table_arg, data_file_type row_type, + MARIA_KEYDEF **keydef_out, + MARIA_COLUMNDEF **recinfo_out, uint *records_out, + MARIA_CREATE_INFO *create_info) { uint i, j, recpos, minpos, fieldpos, temp_length, length; enum ha_base_keytype type= HA_KEYTYPE_BINARY; @@ -281,6 +287,9 @@ int table2maria(TABLE *table_arg, MARIA_KEYDEF **keydef_out, uint options= share->db_options_in_use; DBUG_ENTER("table2maria"); + if (row_type == BLOCK_RECORD) + options|= HA_OPTION_PACK_RECORD; + if (!(my_multi_malloc(MYF(MY_WME), recinfo_out, (share->fields * 2 + 2) * sizeof(MARIA_COLUMNDEF), keydef_out, share->keys * sizeof(MARIA_KEYDEF), @@ -369,6 +378,8 @@ int table2maria(TABLE *table_arg, MARIA_KEYDEF **keydef_out, record= table_arg->record[0]; recpos= 0; recinfo_pos= recinfo; + create_info->null_bytes= table_arg->s->null_bytes; + while (recpos < (uint) share->reclength) { Field **field, *found= 0; @@ -394,13 +405,6 @@ int table2maria(TABLE *table_arg, MARIA_KEYDEF **keydef_out, } DBUG_PRINT("loop", ("found: 0x%lx recpos: %d minpos: %d length: %d", (long) found, recpos, minpos, length)); - if (recpos != minpos) - { - /* reserve space for null bits */ - bzero((char*) recinfo_pos, sizeof(*recinfo_pos)); - recinfo_pos->type= FIELD_NORMAL; - recinfo_pos++->length= (uint16) (minpos - recpos); - } if (!found) break; @@ -561,6 +565,7 @@ int maria_check_definition(MARIA_KEYDEF *t1_keyinfo, } } } + for (i= 0; i < t1_recs; i++) { MARIA_COLUMNDEF *t1_rec= &t1_recinfo[i]; @@ -1900,13 +1905,20 @@ int ha_maria::rnd_next(uchar *buf) } -int ha_maria::restart_rnd_next(uchar *buf, uchar *pos) +int ha_maria::remember_rnd_pos() { - return rnd_pos(buf, pos); + return (*file->s->scan_remember_pos)(file, &remember_pos); } -int ha_maria::rnd_pos(uchar * buf, uchar *pos) +int ha_maria::restart_rnd_next(uchar *buf) +{ + (*file->s->scan_restore_pos)(file, remember_pos); + return rnd_next(buf); +} + + +int ha_maria::rnd_pos(uchar *buf, uchar *pos) { ha_statistic_increment(&SSV::ha_read_rnd_count); int error= maria_rrnd(file, buf, my_get_ptr(pos, ref_length)); @@ -1915,7 +1927,7 @@ int ha_maria::rnd_pos(uchar * buf, uchar *pos) } -void ha_maria::position(const uchar * record) +void ha_maria::position(const uchar *record) { my_off_t row_position= maria_position(file); my_store_ptr(ref, ref_length, row_position); @@ -2172,9 +2184,10 @@ enum row_type ha_maria::get_row_type() const } -static enum data_file_type maria_row_type(HA_CREATE_INFO *info) +static enum data_file_type maria_row_type(HA_CREATE_INFO *info, + my_bool ignore_transactional) { - if (info->transactional == HA_CHOICE_YES) + if (info->transactional == HA_CHOICE_YES && ! ignore_transactional) return BLOCK_RECORD; switch (info->row_type) { case ROW_TYPE_FIXED: return STATIC_RECORD; @@ -2207,7 +2220,7 @@ int ha_maria::create(const char *name, register TABLE *table_arg, } } /* Note: BLOCK_RECORD is used if table is transactional */ - row_type= maria_row_type(ha_create_info); + row_type= maria_row_type(ha_create_info, 0); if (ha_create_info->transactional == HA_CHOICE_YES && ha_create_info->row_type != ROW_TYPE_PAGE && ha_create_info->row_type != ROW_TYPE_NOT_USED && @@ -2216,9 +2229,10 @@ int ha_maria::create(const char *name, register TABLE *table_arg, ER_ILLEGAL_HA_CREATE_OPTION, "Row format set to PAGE because of TRANSACTIONAL=1 option"); - if ((error= table2maria(table_arg, &keydef, &recinfo, &record_count))) - DBUG_RETURN(error); /* purecov: inspected */ bzero((char*) &create_info, sizeof(create_info)); + if ((error= table2maria(table_arg, row_type, &keydef, &recinfo, + &record_count, &create_info))) + DBUG_RETURN(error); /* purecov: inspected */ create_info.max_rows= share->max_rows; create_info.reloc_rows= share->min_rows; create_info.with_auto_increment= share->next_number_key_offset == 0; @@ -2253,7 +2267,8 @@ int ha_maria::create(const char *name, register TABLE *table_arg, create_flags|= HA_CREATE_CHECKSUM; if (options & HA_OPTION_DELAY_KEY_WRITE) create_flags|= HA_CREATE_DELAY_KEY_WRITE; - if (ha_create_info->page_checksum != HA_CHOICE_NO) + if ((ha_create_info->page_checksum == HA_CHOICE_UNDEF && maria_page_checksums) || + ha_create_info->page_checksum == HA_CHOICE_YES) create_flags|= HA_CREATE_PAGE_CHECKSUM; /* TODO: Check that the following fn_format is really needed */ @@ -2387,7 +2402,8 @@ bool ha_maria::check_if_incompatible_data(HA_CREATE_INFO *create_info, if (create_info->auto_increment_value != stats.auto_increment_value || create_info->data_file_name != data_file_name || create_info->index_file_name != index_file_name || - maria_row_type(create_info) != data_file_type || + (maria_row_type(create_info, 1) != data_file_type && + create_info->row_type != ROW_TYPE_DEFAULT) || table_changes == IS_EQUAL_NO || table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet return COMPATIBLE_DATA_NO; @@ -2658,6 +2674,7 @@ my_bool ha_maria::register_query_cache_table(THD *thd, char *table_name, static struct st_mysql_sys_var* system_variables[]= { MYSQL_SYSVAR(block_size), MYSQL_SYSVAR(checkpoint_interval), + MYSQL_SYSVAR(page_checksum), MYSQL_SYSVAR(log_file_size), MYSQL_SYSVAR(log_purge_type), MYSQL_SYSVAR(max_sort_file_size), diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h index 78d88cf52c6..cb4efffff5f 100644 --- a/storage/maria/ha_maria.h +++ b/storage/maria/ha_maria.h @@ -36,6 +36,7 @@ class ha_maria :public handler { MARIA_HA *file; ulonglong int_table_flags; + MARIA_RECORD_POS remember_pos; char *data_file_name, *index_file_name; enum data_file_type data_file_type; bool can_enable_indexes; @@ -101,7 +102,8 @@ public: int rnd_end(void); int rnd_next(uchar * buf); int rnd_pos(uchar * buf, uchar * pos); - int restart_rnd_next(uchar * buf, uchar * pos); + int remember_rnd_pos(); + int restart_rnd_next(uchar * buf); void position(const uchar * record); int info(uint); int extra(enum ha_extra_function operation); diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index a09348bd98a..447e0de9ad7 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -144,6 +144,7 @@ static inline my_bool write_changed_bitmap(MARIA_SHARE *share, DBUG_ASSERT(share->pagecache->block_size == bitmap->block_size); DBUG_ASSERT(bitmap->file.write_callback != 0); DBUG_PRINT("info", ("bitmap->non_flushable: %u", bitmap->non_flushable)); + if ((bitmap->non_flushable == 0) #ifdef WRONG_BITMAP_FLUSH || 1 @@ -176,10 +177,11 @@ static inline my_bool write_changed_bitmap(MARIA_SHARE *share, int res= pagecache_write(share->pagecache, &bitmap->file, bitmap->page, 0, (uchar*) bitmap->map, PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_READ, PAGECACHE_PIN, + PAGECACHE_LOCK_WRITE, PAGECACHE_PIN, PAGECACHE_WRITE_DELAY, &page_link.link, LSN_IMPOSSIBLE); page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; + page_link.changed= 1; push_dynamic(&bitmap->pinned_pages, (void*) &page_link); DBUG_RETURN(res); } @@ -217,12 +219,23 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file) sizeof(MARIA_PINNED_PAGE), 1, 1)) return 1; - bitmap->file.file= file; bitmap->block_size= share->block_size; - pagecache_file_init(bitmap->file, &maria_page_crc_check_bitmap, - (share->options & HA_OPTION_PAGE_CHECKSUM ? - &maria_page_crc_set_normal : - &maria_page_filler_set_bitmap), share); + bitmap->file.file= file; + bitmap->file.callback_data= (uchar*) share; + if (share->temporary) + { + bitmap->file.read_callback= &maria_page_crc_check_none; + bitmap->file.write_callback= &maria_page_filler_set_none; + } + else + { + bitmap->file.read_callback= &maria_page_crc_check_bitmap; + if (share->options & HA_OPTION_PAGE_CHECKSUM) + bitmap->file.write_callback= &maria_page_crc_set_normal; + else + bitmap->file.write_callback= &maria_page_filler_set_bitmap; + } + /* Size needs to be aligned on 6 */ aligned_bit_blocks= (share->block_size - PAGE_SUFFIX_SIZE) / 6; bitmap->total_size= aligned_bit_blocks * 6; @@ -2119,7 +2132,18 @@ my_bool _ma_bitmap_set_full_page_bits(MARIA_HA *info, void _ma_bitmap_flushable(MARIA_SHARE *share, int non_flushable_inc) { - MARIA_FILE_BITMAP *bitmap= &share->bitmap; + MARIA_FILE_BITMAP *bitmap; + + /* + Not transactional tables are never automaticly flushed and needs no + protection + */ +#ifndef EXTRA_DEBUG + if (!share->now_transactional) + return; +#endif + + bitmap= &share->bitmap; if (non_flushable_inc == -1) { pthread_mutex_lock(&bitmap->bitmap_lock); diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index bab1b54aa1b..c31238368de 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -502,7 +502,8 @@ my_bool _ma_init_block_record(MARIA_HA *info) sizeof(MARIA_BITMAP_BLOCK), default_extents, 64)) goto err; - if (!(info->cur_row.extents= my_malloc(default_extents * ROW_EXTENT_SIZE, + info->cur_row.extents_buffer_length= default_extents * ROW_EXTENT_SIZE; + if (!(info->cur_row.extents= my_malloc(info->cur_row.extents_buffer_length, MYF(MY_WME)))) goto err; @@ -1915,7 +1916,7 @@ static my_bool write_block_record(MARIA_HA *info, row_extents_first_part= data; data+= ROW_EXTENT_SIZE; } - if (share->base.pack_fields) + if (share->base.max_field_lengths) store_key_length_inc(data, row->field_lengths_length); if (share->calc_checksum) { @@ -3287,7 +3288,7 @@ my_bool _ma_delete_block_record(MARIA_HA *info, const uchar *record) delete_tails(info, info->cur_row.tail_positions)) goto err; - if (info->cur_row.extents && free_full_pages(info, &info->cur_row)) + if (info->cur_row.extents_count && free_full_pages(info, &info->cur_row)) goto err; if (share->now_transactional) @@ -4152,6 +4153,81 @@ void _ma_scan_end_block_record(MARIA_HA *info) DBUG_ENTER("_ma_scan_end_block_record"); my_free(info->scan.bitmap_buff, MYF(MY_ALLOW_ZERO_PTR)); info->scan.bitmap_buff= 0; + if (info->scan_save) + { + my_free(info->scan_save, MYF(0)); + info->scan_save= 0; + } + DBUG_VOID_RETURN; +} + + +/** + @brief Save current scan position + + @note + For the moment we can only remember one position, but this is + good enough for MySQL usage + + @Warning + When this function is called, we assume that the thread is not deleting + or updating the current row before ma_scan_restore_block_record() + is called! + + @return + @retval 0 ok + @retval HA_ERR_WRONG_IN_RECORD Could not allocate memory to hold position +*/ + +int _ma_scan_remember_block_record(MARIA_HA *info, + MARIA_RECORD_POS *lastpos) +{ + uchar *bitmap_buff; + DBUG_ENTER("_ma_scan_remember_block_record"); + if (!(info->scan_save)) + { + if (!(info->scan_save= my_malloc(ALIGN_SIZE(sizeof(*info->scan_save)) + + info->s->block_size * 2, + MYF(MY_WME)))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + info->scan_save->bitmap_buff= ((uchar*) info->scan_save + + ALIGN_SIZE(sizeof(*info->scan_save))); + } + /* Point to the last read row */ + *lastpos= info->cur_row.nextpos - 1; + info->scan.dir+= DIR_ENTRY_SIZE; + + /* Remember used bitmap and used head page */ + bitmap_buff= info->scan_save->bitmap_buff; + memcpy(info->scan_save, &info->scan, sizeof(*info->scan_save)); + info->scan_save->bitmap_buff= bitmap_buff; + memcpy(bitmap_buff, info->scan.bitmap_buff, info->s->block_size * 2); + DBUG_RETURN(0); +} + + +/** + @brief restore scan block it's original values + + @note + In theory we could swap bitmap buffers instead of copy them. + For the moment we don't do that because there are variables pointing + inside the buffers and it's a bit of hassle to either make them relative + or repoint them. +*/ + +void _ma_scan_restore_block_record(MARIA_HA *info, + MARIA_RECORD_POS lastpos) +{ + uchar *bitmap_buff; + DBUG_ENTER("_ma_scan_restore_block_record"); + + info->cur_row.nextpos= lastpos; + bitmap_buff= info->scan.bitmap_buff; + memcpy(&info->scan, info->scan_save, sizeof(*info->scan_save)); + info->scan.bitmap_buff= bitmap_buff; + memcpy(bitmap_buff, info->scan_save->bitmap_buff, info->s->block_size * 2); + DBUG_VOID_RETURN; } @@ -4204,7 +4280,10 @@ restart_record_read: record_pos++; #ifdef SANITY_CHECKS if (info->scan.dir < info->scan.dir_end) + { + DBUG_ASSERT(0); goto err; + } #endif } /* found row */ @@ -4217,7 +4296,10 @@ restart_record_read: #ifdef SANITY_CHECKS if (end_of_data > info->scan.dir_end || offset < PAGE_HEADER_SIZE || length < share->base.min_block_length) + { + DBUG_ASSERT(0); goto err; + } #endif DBUG_PRINT("info", ("rowid: %lu", (ulong) info->cur_row.lastpos)); DBUG_RETURN(_ma_read_block_record2(info, record, data, end_of_data)); @@ -4256,8 +4338,20 @@ restart_bitmap_scan: PAGECACHE_LOCK_LEFT_UNLOCKED, 0))) DBUG_RETURN(my_errno); if (((info->scan.page_buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != - HEAD_PAGE) || - (info->scan.number_of_rows= + HEAD_PAGE)) + { + /* + This may happen if someone has been deleting all rows + from a page since we read the bitmap, so it may be ok. + Print warning in debug log and continue. + */ + DBUG_PRINT("warning", + ("Found page of type %d when expecting head page", + (info->scan.page_buff[PAGE_TYPE_OFFSET] & + PAGE_TYPE_MASK))); + continue; + } + if ((info->scan.number_of_rows= (uint) (uchar) info->scan.page_buff[DIR_COUNT_OFFSET]) == 0) { DBUG_PRINT("error", ("Wrong page header")); @@ -4295,7 +4389,7 @@ restart_bitmap_scan: } DBUG_PRINT("info", ("Reading bitmap at %lu", (ulong) info->scan.bitmap_page)); - if (!(pagecache_read(share->pagecache, &info->dfile, + if (!(pagecache_read(share->pagecache, &info->s->bitmap.file, info->scan.bitmap_page, 0, info->scan.bitmap_buff, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_LEFT_UNLOCKED, 0))) @@ -5081,9 +5175,11 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, share->pagecache->readwrite_flags= share->pagecache->org_readwrite_flags; if (!buff) { - if (my_errno != HA_ERR_FILE_TOO_SHORT) + /* Skip errors when reading outside of file and uninitialized pages */ + if (my_errno != HA_ERR_FILE_TOO_SHORT && + my_errno != HA_ERR_WRONG_CRC) { - /* If not read outside of file */ + /* Fatal disk error when reading page */ pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, @@ -5091,8 +5187,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, DBUG_RETURN(my_errno); } /* Create new page */ - buff= info->keyread_buff; - info->keyread_buff_used= 1; + buff= pagecache_block_link_to_buffer(page_link.link); buff[PAGE_TYPE_OFFSET]= UNALLOCATED_PAGE; } else if (lsn_korr(buff) >= lsn) /* Test if already applied */ @@ -5532,7 +5627,8 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, org_readwrite_flags; if (!buff) { - if (my_errno != HA_ERR_FILE_TOO_SHORT) + if (my_errno != HA_ERR_FILE_TOO_SHORT && + my_errno != HA_ERR_WRONG_CRC) { /* If not read outside of file */ pagecache_unlock_by_link(share->pagecache, page_link.link, @@ -5547,8 +5643,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, pagecache (increased data_file_length but not physical file length), now reads page N+1: the read fails. */ - buff= info->keyread_buff; - info->keyread_buff_used= 1; + buff= pagecache_block_link_to_buffer(page_link.link); make_empty_page(info, buff, BLOB_PAGE); } else @@ -5648,7 +5743,7 @@ my_bool _ma_apply_undo_row_insert(MARIA_HA *info, LSN undo_lsn, delete_tails(info, info->cur_row.tail_positions)) goto err; - if (info->cur_row.extents && free_full_pages(info, &info->cur_row)) + if (info->cur_row.extents_count && free_full_pages(info, &info->cur_row)) goto err; checksum= 0; @@ -5844,6 +5939,7 @@ my_bool _ma_apply_undo_row_delete(MARIA_HA *info, LSN undo_lsn, /* Row is now up to date. Time to insert the record */ res= allocate_and_write_block_record(info, record, &row, undo_lsn); + info->cur_row.lastpos= row.lastpos; my_free(record, MYF(0)); DBUG_RETURN(res); } @@ -5879,6 +5975,7 @@ my_bool _ma_apply_undo_row_update(MARIA_HA *info, LSN undo_lsn, rownr= dirpos_korr(header); header+= DIRPOS_STORE_SIZE; record_pos= ma_recordpos(page, rownr); + info->cur_row.lastpos= record_pos; /* For key insert */ DBUG_PRINT("enter", ("Page: %lu rownr: %u", (ulong) page, rownr)); if (share->calc_checksum) diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index fc0ed6a6435..a834b4788df 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -159,6 +159,10 @@ my_bool _ma_cmp_block_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, const uchar *record, MARIA_RECORD_POS pos); my_bool _ma_scan_init_block_record(MARIA_HA *info); void _ma_scan_end_block_record(MARIA_HA *info); +int _ma_scan_remember_block_record(MARIA_HA *info, + MARIA_RECORD_POS *lastpos); +void _ma_scan_restore_block_record(MARIA_HA *info, + MARIA_RECORD_POS lastpos); MARIA_RECORD_POS _ma_write_init_block_record(MARIA_HA *info, const uchar *record); diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index ce08e076c77..c122ea6e7ba 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -922,8 +922,11 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, } if (keypos != endpos) { - _ma_check_print_error(param,"Keyblock size at page %s is not correct. Block length: %d key length: %d", - llstr(page,llbuff), used_length, (keypos - buff)); + _ma_check_print_error(param, + "Keyblock size at page %s is not correct. " + "Block length: %u key length: %u", + llstr(page, llbuff), used_length, + (uint) (keypos - buff)); goto err; } my_afree((uchar*) temp_buff); @@ -1376,7 +1379,7 @@ static int check_compressed_record(HA_CHECK *param, MARIA_HA *info, int extend, block_info.rec_len > (uint) share->max_pack_length) { _ma_check_print_error(param, - "Found block with wrong recordlength: %d at %s", + "Found block with wrong recordlength: %lu at %s", block_info.rec_len, llstr(start_recpos,llbuff)); got_error=1; goto end; @@ -1709,7 +1712,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, { /* Bitmap page */ if (pagecache_read(share->pagecache, - &info->dfile, + &info->s->bitmap.file, (pos / block_size), 1, bitmap_buff, PAGECACHE_PLAIN_PAGE, @@ -1717,7 +1720,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, { _ma_check_print_error(param, "Page %9s: Got error: %d when reading datafile", - my_errno, llstr(pos, llbuff)); + llstr(pos, llbuff), my_errno); goto err; } param->used+= block_size; @@ -1746,7 +1749,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, { _ma_check_print_error(param, "Page %9s: Got error: %d when reading datafile", - my_errno, llstr(pos, llbuff)); + llstr(pos, llbuff), my_errno); goto err; } page_type= page_buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK; @@ -4154,8 +4157,9 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) { if (!searching) _ma_check_print_info(param, - "Deleted block with impossible length %u at %s", - block_info.block_len,llstr(pos,llbuff)); + "Deleted block with impossible length %lu " + "at %s", + block_info.block_len,llstr(pos,llbuff)); error=1; } else @@ -4193,10 +4197,11 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) { if (!searching) _ma_check_print_info(param, - "Found block with impossible length %u at %s; Skipped", - block_info.block_len+ + "Found block with impossible length %lu " + "at %s; Skipped", + block_info.block_len+ (uint) (block_info.filepos-pos), - llstr(pos,llbuff)); + llstr(pos,llbuff)); if (found_record) goto try_next; searching=1; @@ -4393,9 +4398,11 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) block_info.rec_len > (uint) share->max_pack_length) { if (! searching) - _ma_check_print_info(param,"Found block with wrong recordlength: %d at %s\n", - block_info.rec_len, - llstr(sort_param->pos,llbuff)); + _ma_check_print_info(param, + "Found block with wrong recordlength: %lu " + "at %s\n", + block_info.rec_len, + llstr(sort_param->pos,llbuff)); continue; } if (_ma_read_cache(&sort_param->read_cache,(uchar*) sort_param->rec_buff, @@ -4918,9 +4925,9 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param) if (key_info->s->options & HA_OPTION_COMPRESS_RECORD) { _ma_check_print_error(param, - "Recover aborted; Can't run standard recovery on compressed tables " - "with errors in data-file. Use 'maria_chk --safe-recover' " - "to fix it",stderr);; + "Recover aborted; Can't run standard recovery on " + "compressed tables with errors in data-file. " + "Use 'maria_chk --safe-recover' to fix it"); DBUG_RETURN(1); } @@ -5801,8 +5808,16 @@ read_next_page: page, 0, info->scan.page_buff, PAGECACHE_READ_UNKNOWN_PAGE, PAGECACHE_LOCK_LEFT_UNLOCKED, 0))) + { + if (my_errno == HA_ERR_WRONG_CRC) + { + _ma_check_print_info(sort_info->param, + "Wrong CRC on page at %s", + llstr(page * share->block_size, llbuff)); + continue; + } DBUG_RETURN(my_errno); - + } page_type= (info->scan.page_buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK); if (page_type == HEAD_PAGE) diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c index 87021820be5..f058754c0ad 100644 --- a/storage/maria/ma_close.c +++ b/storage/maria/ma_close.c @@ -100,7 +100,7 @@ int maria_close(register MARIA_HA *info) File must be synced as it is going out of the maria_open_list and so becoming unknown to future Checkpoints. */ - if (my_sync(share->kfile.file, MYF(MY_WME))) + if (!share->temporary && my_sync(share->kfile.file, MYF(MY_WME))) error= my_errno; if (my_close(share->kfile.file, MYF(0))) error= my_errno; @@ -145,13 +145,16 @@ int maria_close(register MARIA_HA *info) Checkpoint. Fortunately in BLOCK_RECORD we close earlier under mutex. */ if (my_close(info->dfile.file, MYF(0))) - error = my_errno; + error= my_errno; } delete_dynamic(&info->pinned_pages); my_free(info, MYF(0)); if (error) + { + DBUG_PRINT("error", ("Got error on close: %d", my_errno)); DBUG_RETURN(my_errno= error); + } DBUG_RETURN(0); } /* maria_close */ diff --git a/storage/maria/ma_control_file.c b/storage/maria/ma_control_file.c index 4510cc11b20..36efb52acec 100644 --- a/storage/maria/ma_control_file.c +++ b/storage/maria/ma_control_file.c @@ -214,6 +214,7 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open() const char *errmsg; MY_STAT stat_buff; uint new_cf_create_time_size, new_cf_changeable_size, new_block_size; + uint retry; int open_flags= O_BINARY | /*O_DIRECT |*/ O_RDWR; int error= CONTROL_FILE_UNKNOWN_ERROR; DBUG_ENTER("ma_control_file_create_or_open"); @@ -347,6 +348,29 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open() CF_LSN_OFFSET); last_logno= uint4korr(buffer + new_cf_create_time_size + CF_FILENO_OFFSET); + retry= 0; + + /* + We can't here use the automatic wait in my_lock() as the alarm thread + may not yet exists. + */ + + while (my_lock(control_file_fd, F_WRLCK, 0L, F_TO_EOF, + MYF(MY_SEEK_NOT_DONE | MY_FORCE_LOCK | MY_NO_WAIT))) + { + if (retry == 0) + my_printf_error(HA_ERR_INITIALIZATION, + "Can't lock maria control file '%s' for exclusive use, " + "error: %d. Will retry for %d seconds", 0, + name, my_errno, MARIA_MAX_CONTROL_FILE_LOCK_RETRY); + if (retry++ > MARIA_MAX_CONTROL_FILE_LOCK_RETRY) + { + errmsg= "Could not get an exclusive lock; File is probably in use by another process"; + goto err; + } + sleep(1); + } + DBUG_RETURN(0); err: @@ -463,6 +487,9 @@ int ma_control_file_end() if (control_file_fd < 0) /* already closed */ DBUG_RETURN(0); + (void) my_lock(control_file_fd, F_UNLCK, 0L, F_TO_EOF, + MYF(MY_SEEK_NOT_DONE | MY_FORCE_LOCK)); + close_error= my_close(control_file_fd, MYF(MY_WME)); /* As my_close() frees structures even if close() fails, we do the same, diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 6fe0a772011..767242ec027 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -124,7 +124,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, (keys + uniques) * HA_MAX_KEY_SEG); - /* Start by checking fields and field-types used */ + /* Start by checking fields and field-types used */ varchar_length=long_varchar_count=packed= not_block_record_extra_length= pack_reclength= max_field_lengths= 0; @@ -147,8 +147,17 @@ int maria_create(const char *name, enum data_file_type datafile_type, reclength+= column->length; type= column->type; - if (type == FIELD_SKIP_PRESPACE && datafile_type == BLOCK_RECORD) - type= FIELD_NORMAL; /* SKIP_PRESPACE not supported */ + if (datafile_type == BLOCK_RECORD) + { + if (type == FIELD_SKIP_PRESPACE) + type= FIELD_NORMAL; /* SKIP_PRESPACE not supported */ + if (type == FIELD_NORMAL && + column->length > FULL_PAGE_SIZE(maria_block_size)) + { + /* FIELD_NORMAL can't be split over many blocks, convert to a CHAR */ + type= column->type= FIELD_SKIP_ENDSPACE; + } + } if (type != FIELD_NORMAL && type != FIELD_CHECK) { @@ -403,6 +412,17 @@ int maria_create(const char *name, enum data_file_type datafile_type, share.state.key_root[i]= HA_OFFSET_ERROR; length= real_length_diff= 0; min_key_length= key_length= pointer; + + if ((keydef->flag & (HA_SPATIAL | HA_FULLTEXT) && + ci->transactional)) + { + my_errno= HA_ERR_UNSUPPORTED; + my_message(HA_ERR_UNSUPPORTED, + "Maria can't yet handle SPATIAL or FULLTEXT keys in " + "transactional mode. For now use TRANSACTIONAL=0", MYF(0)); + goto err_no_lock; + } + if (keydef->flag & HA_SPATIAL) { #ifdef HAVE_SPATIAL @@ -623,7 +643,6 @@ int maria_create(const char *name, enum data_file_type datafile_type, } unique_key_parts=0; - offset=reclength-uniques*MARIA_UNIQUE_HASH_LENGTH; for (i=0, uniquedef=uniquedefs ; i < uniques ; i++ , uniquedef++) { uniquedef->key=keys+i; @@ -869,7 +888,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, #endif } /* Create extra keys for unique definitions */ - offset=reclength-uniques*MARIA_UNIQUE_HASH_LENGTH; + offset= real_reclength - uniques*MARIA_UNIQUE_HASH_LENGTH; bzero((char*) &tmp_keydef,sizeof(tmp_keydef)); bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg)); for (i=0; i < uniques ; i++) @@ -1049,10 +1068,6 @@ int maria_create(const char *name, enum data_file_type datafile_type, DROP+CREATE happened (applying REDOs to the wrong table). */ share.kfile.file= file; - pagecache_file_init(share.kfile, &maria_page_crc_check_index, - (share.options & HA_OPTION_PAGE_CHECKSUM ? - &maria_page_crc_set_index : - &maria_page_filler_set_normal), &share); if (_ma_update_create_rename_lsn_sub(&share, lsn, FALSE)) goto err; my_free(log_data, MYF(0)); @@ -1199,7 +1214,7 @@ uint maria_get_pointer_length(ulonglong file_length, uint def) For same kind of fields, keep fields in original order */ -static inline int sign(longlong a) +static inline int sign(long a) { return a < 0 ? -1 : (a > 0 ? 1 : 0); } @@ -1219,12 +1234,12 @@ static int compare_columns(MARIA_COLUMNDEF **a_ptr, MARIA_COLUMNDEF **b_ptr) { if (b_type != FIELD_NORMAL || b->null_bit) return -1; - return sign((long) (a->offset - b->offset)); + return sign((long) a->offset - (long) b->offset); } if (b_type == FIELD_NORMAL && !b->null_bit) return 1; if (a_type == b_type) - return sign((long) (a->offset - b->offset)); + return sign((long) a->offset - (long) b->offset); if (a_type == FIELD_NORMAL) return -1; if (b_type == FIELD_NORMAL) @@ -1233,11 +1248,17 @@ static int compare_columns(MARIA_COLUMNDEF **a_ptr, MARIA_COLUMNDEF **b_ptr) return 1; if (b_type == FIELD_BLOB) return -1; - return sign((long) (a->offset - b->offset)); + return sign((long) a->offset - (long) b->offset); } -/* Initialize data file */ +/** + @brief Initialize data file + + @note + In BLOCK_RECORD, a freshly created datafile is one page long; while in + other formats it is 0-byte long. + */ int _ma_initialize_data_file(MARIA_SHARE *share, File dfile) { @@ -1245,16 +1266,8 @@ int _ma_initialize_data_file(MARIA_SHARE *share, File dfile) { share->bitmap.block_size= share->base.block_size; share->bitmap.file.file = dfile; - pagecache_file_init(share->bitmap.file, &maria_page_crc_check_bitmap, - (share->options & HA_OPTION_PAGE_CHECKSUM ? - &maria_page_crc_set_normal : - &maria_page_filler_set_bitmap), share); return _ma_bitmap_create_first(share); } - /* - So, in BLOCK_RECORD, a freshly created datafile is one page long; while in - other formats it is 0-byte long. - */ return 0; } diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index 1388d81df67..67d3d8d7092 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -192,7 +192,11 @@ int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key, log_type= LOGREC_UNDO_KEY_DELETE_WITH_ROOT; } - key_length+= share->rec_reflength; + /* + Note that for delete key, we don't log the reference to the record. + This is because the row may be inserted at a different place when + we exceute the undo + */ log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data); log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) key_buff; diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c index 9f42f2beaa2..cb33160bdf6 100644 --- a/storage/maria/ma_dynrec.c +++ b/storage/maria/ma_dynrec.c @@ -1501,7 +1501,10 @@ my_bool _ma_cmp_dynamic_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, old_rec_buff_size= info->rec_buff_size; if (info->s->base.blobs) + { info->rec_buff= 0; + info->rec_buff_size= 0; + } error= _ma_read_dynamic_record(info, old_record, pos) != 0; if (!error) error=_ma_unique_comp(def, record, old_record, def->null_are_equal) != 0; diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index 62e091a8928..26e129245d6 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -224,7 +224,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, info->lock_wait= 0; break; case HA_EXTRA_NO_WAIT_LOCK: - info->lock_wait= MY_DONT_WAIT; + info->lock_wait= MY_SHORT_WAIT; break; case HA_EXTRA_NO_KEYS: /* we're going to modify pieces of the state, stall Checkpoint */ @@ -273,11 +273,12 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, break; case HA_EXTRA_FORCE_REOPEN: /* - Normally MySQL uses this case when it is going to close all open - instances of the table, thus going to flush all data/index/state. + MySQL uses this case after it has closed all other instances + of this table. We however do a flush here for additional safety. */ /** @todo consider porting these flush-es to MyISAM */ + DBUG_ASSERT(share->reopen == 1); error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX, FLUSH_FORCE_WRITE, FLUSH_FORCE_WRITE); if (!error && share->changed) @@ -287,19 +288,6 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, share->changed= 0; pthread_mutex_unlock(&share->intern_lock); } - - /** - @todo RECOVERY BUG - Though we flushed the state, IF some other thread may have the same - table (same MARIA_SHARE) open at this time then it may have a - more recent state to flush when it closes, thus we don't set - share->changed to 0 here. On the other hand, this means that when our - thread closes its table, it will flush the state again, then it would - overwrite any state written by yet another thread which may have opened - the table (new MARIA_SHARE) and done some updates. - ASK_MONTY about the IF above. See also same tag in - HA_EXTRA_PREPARE_FOR_DROP|RENAME. - */ pthread_mutex_lock(&THR_LOCK_maria); pthread_mutex_lock(&share->intern_lock); /* protect against Checkpoint */ /* this makes the share not be re-used next time the table is opened */ diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c index 40f6ef1ceba..071c49661ef 100644 --- a/storage/maria/ma_key_recover.c +++ b/storage/maria/ma_key_recover.c @@ -109,6 +109,20 @@ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn, page_store(log_pos + KEY_NR_STORE_SIZE, page); log_pos+= KEY_NR_STORE_SIZE + PAGE_STORE_SIZE; } + if (undo_type == LOGREC_UNDO_ROW_DELETE || + undo_type == LOGREC_UNDO_ROW_UPDATE) + { + /* + We need to store position to the row that was inserted to be + able to regenerate keys + */ + MARIA_RECORD_POS rowid= info->cur_row.lastpos; + ulonglong page= ma_recordpos_to_page(rowid); + uint dir_entry= ma_recordpos_to_dir_entry(rowid); + page_store(log_pos, page); + dirpos_store(log_pos+ PAGE_STORE_SIZE, dir_entry); + log_pos+= PAGE_STORE_SIZE + DIRPOS_STORE_SIZE; + } log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data); @@ -570,10 +584,15 @@ uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE, &page_link.link))) { - result= (uint) my_errno; - goto err; + if (my_errno != HA_ERR_FILE_TOO_SHORT && + my_errno != HA_ERR_WRONG_CRC) + { + result= 1; + goto err; + } + buff= pagecache_block_link_to_buffer(page_link.link); } - if (lsn_korr(buff) >= lsn) + else if (lsn_korr(buff) >= lsn) { /* Already applied */ result= 0; @@ -648,7 +667,7 @@ uint _ma_apply_redo_index_free_page(MARIA_HA *info, old_link= ((free_page != IMPOSSIBLE_PAGE_NO) ? (my_off_t) free_page * share->block_size : HA_OFFSET_ERROR); - if (!(buff= pagecache_read(share->pagecache, &info->s->kfile, + if (!(buff= pagecache_read(share->pagecache, &share->kfile, page, 0, 0, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE, &page_link.link))) @@ -664,7 +683,8 @@ uint _ma_apply_redo_index_free_page(MARIA_HA *info, } /* Free page */ bzero(buff + LSN_STORE_SIZE, share->keypage_header - LSN_STORE_SIZE); - _ma_store_keynr(info->s, buff, (uchar) MARIA_DELETE_KEY_NR); + _ma_store_keynr(share, buff, (uchar) MARIA_DELETE_KEY_NR); + _ma_store_page_used(share, buff, share->keypage_header + 8); mi_sizestore(buff + share->keypage_header, old_link); share->state.changed|= STATE_NOT_SORTED_PAGES; @@ -741,7 +761,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, /* Set header to point at key data */ header+= PAGE_STORE_SIZE; - if (!(buff= pagecache_read(share->pagecache, &info->s->kfile, + if (!(buff= pagecache_read(share->pagecache, &share->kfile, page, 0, 0, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE, &page_link.link))) @@ -920,7 +940,7 @@ my_bool _ma_apply_undo_key_insert(MARIA_HA *info, LSN undo_lsn, new_root= share->state.key_root[keynr]; res= _ma_ck_real_delete(info, share->keyinfo+keynr, key, - length - info->s->rec_reflength, &new_root); + length - share->rec_reflength, &new_root); msg.root= &share->state.key_root[keynr]; msg.value= new_root; @@ -937,7 +957,7 @@ my_bool _ma_apply_undo_key_insert(MARIA_HA *info, LSN undo_lsn, /** - @brief Undo of insert of key (ie, delete the inserted key) + @brief Undo of delete of key (ie, insert the deleted key) */ my_bool _ma_apply_undo_key_delete(MARIA_HA *info, LSN undo_lsn, @@ -959,11 +979,12 @@ my_bool _ma_apply_undo_key_delete(MARIA_HA *info, LSN undo_lsn, /* We have to copy key as _ma_ck_real_write_btree() may change it */ memcpy(key, header + KEY_NR_STORE_SIZE, length); - DBUG_DUMP("key", key, length); + _ma_dpointer(info, key + length, info->cur_row.lastpos); + DBUG_DUMP("key", key, length + share->rec_reflength); new_root= share->state.key_root[keynr]; res= _ma_ck_real_write_btree(info, share->keyinfo+keynr, key, - length - info->s->rec_reflength, + length, &new_root, share->keyinfo[keynr].write_comp_flag); @@ -1035,13 +1056,13 @@ my_bool _ma_lock_key_del(MARIA_HA *info, my_bool insert_at_end) void _ma_unlock_key_del(MARIA_HA *info) { - MARIA_SHARE *share= info->s; DBUG_ASSERT(info->used_key_del); if (info->used_key_del == 1) /* Ignore insert-with-append */ { + MARIA_SHARE *share= info->s; pthread_mutex_lock(&share->intern_lock); share->used_key_del= 0; - info->s->state.key_del= info->s->current_key_del; + share->state.key_del= info->s->current_key_del; pthread_mutex_unlock(&share->intern_lock); pthread_cond_signal(&share->intern_cond); } diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 5cb630e8a14..2a176d14454 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -2729,7 +2729,7 @@ static uchar *translog_get_page(TRANSLOG_VALIDATOR_DATA *data, uchar *buffer, supposed to be correct. */ if (translog_page_validator((uchar*) buffer, - LSN_OFFSET(addr), + LSN_OFFSET(addr) / TRANSLOG_PAGE_SIZE, (uchar*) &file_copy)) { DBUG_ASSERT(0); diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index f6eebbac261..54f23da4ec9 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -28,9 +28,6 @@ #include /* Prototype for getpid */ #endif #endif -#ifdef VMS -#include "static.c" -#endif static void setup_key_functions(MARIA_KEYDEF *keyinfo); static my_bool maria_scan_init_dummy(MARIA_HA *info); @@ -39,6 +36,11 @@ static my_bool maria_once_init_dummy(MARIA_SHARE *, File); static my_bool maria_once_end_dummy(MARIA_SHARE *); static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base); static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state); +static void set_data_pagecache_callbacks(PAGECACHE_FILE *file, + MARIA_SHARE *share); +static void set_index_pagecache_callbacks(PAGECACHE_FILE *file, + MARIA_SHARE *share); + #define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \ pos+=size;} @@ -144,17 +146,18 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode, info.this_loop=0; /* Update counter */ info.last_unique= share->state.unique; info.last_loop= share->state.update_count; - info.lock_type=F_UNLCK; info.quick_mode=0; info.bulk_insert=0; info.ft1_to_ft2=0; info.errkey= -1; info.page_changed=1; info.keyread_buff= info.buff + share->base.max_key_block_length; - pagecache_file_init(info.dfile, &maria_page_crc_check_data, - (share->options & HA_OPTION_PAGE_CHECKSUM ? - &maria_page_crc_set_normal : - &maria_page_filler_set_normal), share); + + info.lock_type= F_UNLCK; + if (share->options & HA_OPTION_TMP_TABLE) + info.lock_type= F_WRLCK; + + set_data_pagecache_callbacks(&info.dfile, share); bitmap_init(&info.changed_fields, changed_fields_bitmap, share->base.fields, 0); if ((*share->init)(&info)) @@ -178,15 +181,6 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode, share->r_locks++; share->tot_locks++; } - if (share->options & HA_OPTION_TMP_TABLE) - { - share->temporary= share->delay_key_write= 1; - - share->write_flag=MYF(MY_NABP); - share->w_locks++; /* We don't have to update status */ - share->tot_locks++; - info.lock_type=F_WRLCK; - } if ((share->options & HA_OPTION_DELAY_KEY_WRITE) && maria_delay_key_write) share->delay_key_write=1; @@ -717,11 +711,23 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) } errpos= 5; + if (open_flags & HA_OPEN_DELAY_KEY_WRITE) + share->options|= HA_OPTION_DELAY_KEY_WRITE; + if (mode == O_RDONLY) + share->options|= HA_OPTION_READ_ONLY_DATA; + share->is_log_table= FALSE; + + if (open_flags & HA_OPEN_TMP_TABLE) + { + share->options|= HA_OPTION_TMP_TABLE; + share->temporary= share->delay_key_write= 1; + share->write_flag=MYF(MY_NABP); + share->w_locks++; /* We don't have to update status */ + share->tot_locks++; + } + share->kfile.file= kfile; - pagecache_file_init(share->kfile, &maria_page_crc_check_index, - (share->options & HA_OPTION_PAGE_CHECKSUM ? - &maria_page_crc_set_index : - &maria_page_filler_set_normal), share); + set_index_pagecache_callbacks(&share->kfile, share); share->this_process=(ulong) getpid(); share->last_process= share->state.process; share->base.key_parts=key_parts; @@ -737,13 +743,6 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) _ma_setup_functions(share); if ((*share->once_init)(share, info.dfile.file)) goto err; - share->is_log_table= FALSE; - if (open_flags & HA_OPEN_TMP_TABLE) - share->options|= HA_OPTION_TMP_TABLE; - if (open_flags & HA_OPEN_DELAY_KEY_WRITE) - share->options|= HA_OPTION_DELAY_KEY_WRITE; - if (mode == O_RDONLY) - share->options|= HA_OPTION_READ_ONLY_DATA; #ifdef THREAD thr_lock_init(&share->lock); @@ -879,6 +878,9 @@ void _ma_setup_functions(register MARIA_SHARE *share) share->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->scan_remember_pos= _ma_def_scan_remember_pos; + share->scan_restore_pos= _ma_def_scan_restore_pos; + share->write_record_init= _ma_write_init_default; share->write_record_abort= _ma_write_abort_default; share->keypos_to_recpos= _ma_transparent_recpos; @@ -944,8 +946,10 @@ void _ma_setup_functions(register MARIA_SHARE *share) share->write_record_abort= _ma_write_abort_block_record; share->scan_init= _ma_scan_init_block_record; share->scan_end= _ma_scan_end_block_record; - share->read_record= _ma_read_block_record; share->scan= _ma_scan_block_record; + share->scan_remember_pos= _ma_scan_remember_block_record; + share->scan_restore_pos= _ma_scan_restore_block_record; + share->read_record= _ma_read_block_record; share->delete_record= _ma_delete_block_record; share->compare_record= _ma_compare_block_record; share->update_record= _ma_update_block_record; @@ -1002,7 +1006,8 @@ static void setup_key_functions(register MARIA_KEYDEF *keyinfo) if (keyinfo->seg[0].flag & HA_PACK_KEY) { /* Prefix compression */ if (!keyinfo->seg->charset || use_strnxfrm(keyinfo->seg->charset) || - (keyinfo->seg->flag & HA_NULL_PART)) + (keyinfo->seg->flag & HA_NULL_PART) || + keyinfo->seg->charset->mbminlen > 1) keyinfo->bin_search= _ma_seq_search; else keyinfo->bin_search= _ma_prefix_search; @@ -1474,12 +1479,14 @@ my_bool _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef) uchar buff[MARIA_COLUMNDEF_SIZE]; uchar *ptr=buff; - mi_int2store(ptr,(ulong) columndef->offset); ptr+= 2; - 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; + mi_int2store(ptr,(ulong) columndef->column_nr); ptr+= 2; + mi_int2store(ptr,(ulong) columndef->offset); ptr+= 2; + 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; ptr[0]= ptr[1]= ptr[2]= ptr[3]= 0; ptr+= 4; /* For future */ @@ -1488,6 +1495,7 @@ my_bool _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef) uchar *_ma_columndef_read(uchar *ptr, MARIA_COLUMNDEF *columndef) { + columndef->column_nr= mi_uint2korr(ptr); ptr+= 2; columndef->offset= mi_uint2korr(ptr); ptr+= 2; columndef->type= mi_sint2korr(ptr); ptr+= 2; columndef->length= mi_uint2korr(ptr); ptr+= 2; @@ -1526,6 +1534,46 @@ uchar *_ma_column_nr_read(uchar *ptr, uint16 *offsets, uint columns) } +static void set_data_pagecache_callbacks(PAGECACHE_FILE *file, + MARIA_SHARE *share) +{ + file->callback_data= (uchar*) share; + if (share->temporary) + { + file->read_callback= &maria_page_crc_check_none; + file->write_callback= &maria_page_filler_set_none; + } + else + { + file->read_callback= &maria_page_crc_check_data; + if (share->options & HA_OPTION_PAGE_CHECKSUM) + file->write_callback= &maria_page_crc_set_normal; + else + file->write_callback= &maria_page_filler_set_normal; + } +} + + +static void set_index_pagecache_callbacks(PAGECACHE_FILE *file, + MARIA_SHARE *share) +{ + file->callback_data= (uchar*) share; + if (share->temporary) + { + file->read_callback= &maria_page_crc_check_none; + file->write_callback= &maria_page_filler_set_none; + } + else + { + file->read_callback= &maria_page_crc_check_index; + if (share->options & HA_OPTION_PAGE_CHECKSUM) + file->write_callback= &maria_page_crc_set_index; + else + file->write_callback= &maria_page_filler_set_normal; + } +} + + /************************************************************************** Open data file We can't use dup() here as the data file descriptors need to have different @@ -1541,14 +1589,6 @@ int _ma_open_datafile(MARIA_HA *info, MARIA_SHARE *share, info->dfile.file= share->bitmap.file.file= my_open(share->data_file_name, share->mode | O_SHARE, MYF(MY_WME)); - pagecache_file_init(share->bitmap.file, &maria_page_crc_check_bitmap, - (share->options & HA_OPTION_PAGE_CHECKSUM ? - &maria_page_crc_set_normal : - &maria_page_filler_set_bitmap), share); - pagecache_file_init(info->dfile, &maria_page_crc_check_data, - (share->options & HA_OPTION_PAGE_CHECKSUM ? - &maria_page_crc_set_normal : - &maria_page_filler_set_normal), share); return info->dfile.file >= 0 ? 0 : 1; } @@ -1563,10 +1603,6 @@ int _ma_open_keyfile(MARIA_SHARE *share) share->kfile.file= my_open(share->unique_file_name, share->mode | O_SHARE, MYF(MY_WME)); - pagecache_file_init(share->kfile, &maria_page_crc_check_index, - (share->options & HA_OPTION_PAGE_CHECKSUM ? - &maria_page_crc_set_index : - &maria_page_filler_set_normal), share); pthread_mutex_unlock(&share->intern_lock); return (share->kfile.file < 0); } diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index ba4f14af54f..863f3eede3f 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -199,6 +199,7 @@ int _ma_dispose(register MARIA_HA *info, my_off_t pos, my_bool page_not_read) page_no= pos / block_size; bzero(buff, share->keypage_header); _ma_store_keynr(share, buff, (uchar) MARIA_DELETE_KEY_NR); + _ma_store_page_used(share, buff, share->keypage_header + 8); mi_sizestore(buff + share->keypage_header, old_link); share->state.changed|= STATE_NOT_SORTED_PAGES; diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index 69b7865574e..1a0f466c532 100755 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -318,7 +318,7 @@ struct st_pagecache_block_link /** @brief information describing a run of flush_pagecache_blocks_int() */ struct st_file_in_flush { - PAGECACHE_FILE file; + File file; /** @brief threads waiting for the thread currently flushing this file to be done @@ -2421,6 +2421,8 @@ retry: or waits until another thread reads it. What page to read is determined by a block parameter - reference to a hash link for this page. If an error occurs THE PCBLOCK_ERROR bit is set in the block status. + + On entry cache_lock is locked */ static void read_block(PAGECACHE *pagecache, @@ -2428,8 +2430,6 @@ static void read_block(PAGECACHE *pagecache, my_bool primary) { - /* On entry cache_lock is locked */ - DBUG_ENTER("read_block"); if (primary) { @@ -2456,21 +2456,17 @@ static void read_block(PAGECACHE *pagecache, if (error) block->status|= PCBLOCK_ERROR; else - block->status= PCBLOCK_READ; - - DBUG_PRINT("info", ("read_callback: 0x%lx data: 0x%lx", - (ulong) block->hash_link->file.read_callback, - (ulong) block->hash_link->file.callback_data)); - if ((*block->hash_link->file.read_callback)(block->buffer, - block->hash_link->pageno, - block->hash_link-> - file.callback_data)) { - DBUG_PRINT("error", ("read callback problem")); - block->status|= PCBLOCK_ERROR; + block->status|= PCBLOCK_READ; + if ((*block->hash_link->file.read_callback)(block->buffer, + block->hash_link->pageno, + block->hash_link-> + file.callback_data)) + { + DBUG_PRINT("error", ("read callback problem")); + block->status|= PCBLOCK_ERROR; + } } - - DBUG_PRINT("read_block", ("primary request: new page in cache")); /* Signal that all pending requests for this page now can be processed */ @@ -2796,6 +2792,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, } if (lsn != LSN_IMPOSSIBLE) check_and_set_lsn(pagecache, lsn, block); + block->status&= ~PCBLOCK_ERROR; } /* if we lock for write we must link the block to changed blocks */ @@ -3066,7 +3063,11 @@ restart: pagecache_pthread_mutex_unlock(&pagecache->cache_lock); if (status & PCBLOCK_ERROR) + { + DBUG_ASSERT(my_errno != 0); + DBUG_PRINT("error", ("Got error %d when doing page read", my_errno)); DBUG_RETURN((uchar *) 0); + } DBUG_RETURN(buff); } @@ -3412,7 +3413,11 @@ restart: if (write_mode == PAGECACHE_WRITE_DONE) { - if (!(block->status & PCBLOCK_ERROR)) + if (block->status & PCBLOCK_ERROR) + { + DBUG_PRINT("warning", ("Writing on page with error")); + } + else { /* Copy data from buff */ if (!(size & 511)) @@ -3646,7 +3651,10 @@ static int flush_cached_blocks(PAGECACHE *pagecache, /* undo the mark put by flush_pagecache_blocks_int(): */ block->status&= ~PCBLOCK_IN_FLUSH; rc|= PCFLUSH_PINNED; + DBUG_PRINT("warning", ("Page pinned")); unreg_request(pagecache, block, 1); + if (!*first_errno) + *first_errno= HA_ERR_INTERNAL_ERROR; continue; } /* if the block is not pinned then it is not write locked */ @@ -3671,7 +3679,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache, @todo If page is contiguous with next page to flush, group flushes in one single my_pwrite(). */ - error= pagecache_fwrite(pagecache, file, + error= pagecache_fwrite(pagecache, &block->hash_link->file, block->buffer, block->hash_link->pageno, block->type, @@ -3687,7 +3695,8 @@ static int flush_cached_blocks(PAGECACHE *pagecache, { block->status|= PCBLOCK_ERROR; if (!*first_errno) - *first_errno= errno ? errno : -1; + *first_errno= my_errno ? my_errno : -1; + rc|= PCFLUSH_ERROR; } #ifdef THREAD /* @@ -3789,12 +3798,12 @@ static int flush_pagecache_blocks_int(PAGECACHE *pagecache, #ifdef THREAD struct st_file_in_flush us_flusher, *other_flusher; - us_flusher.file= *file; + us_flusher.file= file->file; us_flusher.flush_queue.last_thread= NULL; us_flusher.first_in_switch= FALSE; while ((other_flusher= (struct st_file_in_flush *) - hash_search(&pagecache->files_in_flush, (uchar *)file, - sizeof(*file)))) + hash_search(&pagecache->files_in_flush, (uchar *)&file->file, + sizeof(file->file)))) { /* File is in flush already: wait, unless FLUSH_KEEP_LAZY. "Flusher" @@ -4031,8 +4040,12 @@ restart: #endif if (cache != cache_buff) my_free((uchar*) cache, MYF(0)); - if (last_errno) - errno= last_errno; /* Return first error */ + if (rc != 0) + { + if (last_errno) + my_errno= last_errno; /* Return first error */ + DBUG_PRINT("error", ("Got error: %d", my_errno)); + } DBUG_RETURN(rc); } diff --git a/storage/maria/ma_pagecrc.c b/storage/maria/ma_pagecrc.c index 131eb778d96..051448259e3 100644 --- a/storage/maria/ma_pagecrc.c +++ b/storage/maria/ma_pagecrc.c @@ -41,11 +41,11 @@ static uint32 maria_page_crc(ulong start, uchar *data, uint length) @retval 1 Error */ -static inline my_bool maria_page_crc_check(uchar *page, - pgcache_page_no_t page_no, - MARIA_SHARE *share, - uint32 no_crc_val, - int data_length) +static my_bool maria_page_crc_check(uchar *page, + pgcache_page_no_t page_no, + MARIA_SHARE *share, + uint32 no_crc_val, + int data_length) { uint32 crc= uint4korr(page + share->block_size - CRC_SIZE), new_crc; my_bool res; @@ -63,22 +63,24 @@ static inline my_bool maria_page_crc_check(uchar *page, */ if (crc >= MARIA_NO_CRC_BITMAP_PAGE) { - DBUG_PRINT("info", ("No crc: (0x%lx) crc: (0x%lx) page: %lu ", + DBUG_PRINT("info", ("No crc: %lu crc: %lu page: %lu ", (ulong) no_crc_val, (ulong) crc, (ulong) page_no)); -#ifndef DBUG_OFF if (crc != no_crc_val) - DBUG_PRINT("CRCerror", ("Wrong no CRC value")); -#endif - DBUG_RETURN(test(crc != no_crc_val)); + { + my_errno= HA_ERR_WRONG_CRC; + DBUG_PRINT("error", ("Wrong no CRC value")); + DBUG_RETURN(1); + } + DBUG_RETURN(0); } new_crc= maria_page_crc(page_no, page, data_length); DBUG_ASSERT(new_crc != no_crc_val); res= test(new_crc != crc); if (res) { - DBUG_PRINT("CRCerror", ("Page: %lu crc: 0x%lx calculated crc: 0x%lx", - (ulong) page_no, (ulong) crc, (ulong) new_crc)); - maria_mark_crashed_share(share); + DBUG_PRINT("error", ("Page: %lu crc: %lu calculated crc: %lu", + (ulong) page_no, (ulong) crc, (ulong) new_crc)); + my_errno= HA_ERR_WRONG_CRC; } DBUG_RETURN(res); } @@ -97,15 +99,13 @@ static inline my_bool maria_page_crc_check(uchar *page, my_bool maria_page_crc_set_normal(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr) + uchar *data_ptr) { MARIA_SHARE *share= (MARIA_SHARE *)data_ptr; int data_length= share->block_size - CRC_SIZE; uint32 crc= maria_page_crc(page_no, page, data_length); DBUG_ENTER("maria_page_crc_set"); - - DBUG_PRINT("info", ("Page %u crc: 0x%lx", - (uint)page_no, (ulong)crc)); + DBUG_PRINT("info", ("Page %lu crc: %lu", (ulong) page_no, (ulong)crc)); /* crc is on the stack so it is aligned, pagecache buffer is aligned, too */ int4store_aligned(page + data_length, crc); @@ -125,15 +125,15 @@ my_bool maria_page_crc_set_normal(uchar *page, my_bool maria_page_crc_set_index(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr) + uchar *data_ptr) { MARIA_SHARE *share= (MARIA_SHARE *)data_ptr; int data_length= _ma_get_page_used(share, page); uint32 crc= maria_page_crc(page_no, page, data_length); DBUG_ENTER("maria_page_crc_set"); - DBUG_PRINT("info", ("Page %u crc: 0x%lx", - (uint)page_no, (ulong)crc)); + DBUG_PRINT("info", ("Page %lu crc: %lu", + (ulong) page_no, (ulong) crc)); DBUG_ASSERT((uint)data_length <= share->block_size - CRC_SIZE); /* crc is on the stack so it is aligned, pagecache buffer is aligned, too */ int4store_aligned(page + share->block_size - CRC_SIZE, crc); @@ -157,7 +157,7 @@ my_bool maria_page_crc_set_index(uchar *page, my_bool maria_page_crc_check_data(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr) + uchar *data_ptr) { MARIA_SHARE *share= (MARIA_SHARE *)data_ptr; return (maria_page_crc_check(page, page_no, share, @@ -179,7 +179,7 @@ my_bool maria_page_crc_check_data(uchar *page, my_bool maria_page_crc_check_bitmap(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr) + uchar *data_ptr) { MARIA_SHARE *share= (MARIA_SHARE *)data_ptr; return (maria_page_crc_check(page, page_no, share, @@ -201,12 +201,34 @@ my_bool maria_page_crc_check_bitmap(uchar *page, my_bool maria_page_crc_check_index(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr) + uchar *data_ptr) { MARIA_SHARE *share= (MARIA_SHARE *)data_ptr; - return (maria_page_crc_check(page, page_no, share, + uint length= _ma_get_page_used(share, page); + if (length > share->block_size - CRC_SIZE) + { + DBUG_PRINT("error", ("Wrong page length: %u", length)); + return (my_errno= HA_ERR_WRONG_CRC); + } + return maria_page_crc_check(page, page_no, share, MARIA_NO_CRC_NORMAL_PAGE, - _ma_get_page_used(share, page))); + length); +} + + +/** + @brief Maria pages dumme read callback for temporary tables + + @retval 0 OK + @retval 1 Error +*/ + +my_bool maria_page_crc_check_none(uchar *page __attribute__((unused)), + pgcache_page_no_t page_no + __attribute__((unused)), + uchar *data_ptr __attribute__((unused))) +{ + return 0; } @@ -221,16 +243,18 @@ my_bool maria_page_crc_check_index(uchar *page, */ my_bool maria_page_filler_set_normal(uchar *page, - __attribute__((unused)) - pgcache_page_no_t page_no, - uchar* data_ptr) + pgcache_page_no_t page_no + __attribute__((unused)), + uchar *data_ptr) { DBUG_ENTER("maria_page_filler_set_normal"); + DBUG_ASSERT(page_no != 0); /* Catches some simple bugs */ int4store_aligned(page + ((MARIA_SHARE *)data_ptr)->block_size - CRC_SIZE, MARIA_NO_CRC_NORMAL_PAGE); DBUG_RETURN(0); } + /** @brief Maria pages write callback (sets the page filler for bitmap) @@ -242,12 +266,27 @@ my_bool maria_page_filler_set_normal(uchar *page, */ my_bool maria_page_filler_set_bitmap(uchar *page, - __attribute__((unused)) - pgcache_page_no_t page_no, - uchar* data_ptr) + pgcache_page_no_t page_no + __attribute__((unused)), + uchar *data_ptr) { DBUG_ENTER("maria_page_filler_set_bitmap"); int4store_aligned(page + ((MARIA_SHARE *)data_ptr)->block_size - CRC_SIZE, MARIA_NO_CRC_BITMAP_PAGE); DBUG_RETURN(0); } + + +/** + @brief Maria pages dummy write callback for temporary tables + + @retval 0 OK +*/ + +my_bool maria_page_filler_set_none(uchar *page __attribute__((unused)), + pgcache_page_no_t page_no + __attribute__((unused)), + uchar *data_ptr __attribute__((unused))) +{ + return 0; +} diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index 148d7129b60..03a0cca5bf3 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -161,6 +161,7 @@ void tprint(FILE *trace_file __attribute__ ((unused)), { va_list args; va_start(args, format); + DBUG_PRINT("info", ("%s", format)); if (trace_file != NULL) { if (procent_printed) @@ -181,6 +182,7 @@ void eprint(FILE *trace_file __attribute__ ((unused)), { va_list args; va_start(args, format); + DBUG_PRINT("error", ("%s", format)); if (procent_printed) { /* In silent mode, print on another line than the 0% 10% 20% line */ @@ -329,11 +331,17 @@ int maria_apply_log(LSN from_lsn, enum maria_apply_log_way apply, now= my_getsystime(); if (run_redo_phase(from_lsn, apply)) + { + ma_message_no_user(0, "Redo phase failed"); goto err; + } if ((uncommitted_trans= end_of_redo_phase(should_run_undo_phase)) == (uint)-1) + { + ma_message_no_user(0, "End of redo phase failed"); goto err; + } old_now= now; now= my_getsystime(); @@ -375,7 +383,10 @@ int maria_apply_log(LSN from_lsn, enum maria_apply_log_way apply, if (should_run_undo_phase) { if (run_undo_phase(uncommitted_trans)) + { + ma_message_no_user(0, "Undo phase failed"); goto err; + } } else if (uncommitted_trans > 0) { @@ -398,7 +409,10 @@ int maria_apply_log(LSN from_lsn, enum maria_apply_log_way apply, not want that (we want to keep some modules initialized for runtime). */ if (close_all_tables()) + { + ma_message_no_user(0, "closing of tables failed"); goto err; + } old_now= now; now= my_getsystime(); @@ -437,11 +451,13 @@ end: if (recovery_message_printed != REC_MSG_NONE) { fprintf(stderr, "\n"); - if (error) - ma_message_no_user(0, "recovery failed"); - else + if (!error) ma_message_no_user(ME_JUST_INFO, "recovery done"); } + if (error) + my_message(HA_ERR_INITIALIZATION, + "Maria recovery failed. Please run maria_chk -r on all maria " + "tables and delete all maria_log.######## files", MYF(0)); procent_printed= 0; /* we don't cleanly close tables if we hit some error (may corrupt them) */ DBUG_RETURN(error); @@ -1765,6 +1781,24 @@ prototype_redo_exec_hook(COMMIT) } +/* + Set position for next active record that will have key inserted +*/ + +static void set_lastpos(MARIA_HA *info, uchar *pos) +{ + ulonglong page; + uint dir_entry; + + /* If we have checksum, it's before rowid */ + if (info->s->calc_checksum) + pos+= HA_CHECKSUM_STORE_SIZE; + page= page_korr(pos); + dir_entry= dirpos_korr(pos + PAGE_STORE_SIZE); + info->cur_row.lastpos= ma_recordpos(page, dir_entry); +} + + prototype_redo_exec_hook(CLR_END) { MARIA_HA *info= get_MARIA_HA_from_UNDO_record(rec); @@ -1773,6 +1807,7 @@ prototype_redo_exec_hook(CLR_END) enum translog_record_type undone_record_type; const LOG_DESC *log_desc; my_bool row_entry= 0; + uchar *logpos; DBUG_ENTER("exec_REDO_LOGREC_CLR_END"); if (info == NULL) @@ -1786,6 +1821,19 @@ prototype_redo_exec_hook(CLR_END) set_undo_lsn_for_active_trans(rec->short_trid, previous_undo_lsn); tprint(tracef, " CLR_END was about %s, undo_lsn now LSN (%lu,0x%lx)\n", log_desc->name, LSN_IN_PARTS(previous_undo_lsn)); + + enlarge_buffer(rec); + if (log_record_buffer.str == NULL || + translog_read_record(rec->lsn, 0, rec->record_length, + log_record_buffer.str, NULL) != + rec->record_length) + { + eprint(tracef, "Failed to read record\n"); + return 1; + } + logpos= (log_record_buffer.str + LSN_STORE_SIZE + FILEID_STORE_SIZE + + CLR_TYPE_STORE_SIZE); + if (cmp_translog_addr(rec->lsn, share->state.is_of_horizon) >= 0) { tprint(tracef, " state older than record\n"); @@ -1793,6 +1841,7 @@ prototype_redo_exec_hook(CLR_END) case LOGREC_UNDO_ROW_DELETE: row_entry= 1; share->state.state.records++; + set_lastpos(info, logpos); break; case LOGREC_UNDO_ROW_INSERT: share->state.state.records--; @@ -1801,6 +1850,7 @@ prototype_redo_exec_hook(CLR_END) break; case LOGREC_UNDO_ROW_UPDATE: row_entry= 1; + set_lastpos(info, logpos); break; case LOGREC_UNDO_KEY_INSERT: case LOGREC_UNDO_KEY_DELETE: @@ -1810,18 +1860,8 @@ prototype_redo_exec_hook(CLR_END) { uint key_nr; my_off_t page; - uchar buff[KEY_NR_STORE_SIZE + PAGE_STORE_SIZE]; - if (translog_read_record(rec->lsn, LSN_STORE_SIZE + FILEID_STORE_SIZE + - CLR_TYPE_STORE_SIZE, - KEY_NR_STORE_SIZE + PAGE_STORE_SIZE, - buff, NULL) != - KEY_NR_STORE_SIZE + PAGE_STORE_SIZE) - { - eprint(tracef, "Failed to read record\n"); - DBUG_RETURN(1); - } - key_nr= key_nr_korr(buff); - page= page_korr(buff + KEY_NR_STORE_SIZE); + key_nr= key_nr_korr(logpos); + page= page_korr(logpos + KEY_NR_STORE_SIZE); share->state.key_root[key_nr]= (page == IMPOSSIBLE_PAGE_NO ? HA_OFFSET_ERROR : page * share->block_size); @@ -1831,19 +1871,21 @@ prototype_redo_exec_hook(CLR_END) DBUG_ASSERT(0); } if (row_entry && share->calc_checksum) - { - uchar buff[HA_CHECKSUM_STORE_SIZE]; - if (translog_read_record(rec->lsn, LSN_STORE_SIZE + FILEID_STORE_SIZE + - CLR_TYPE_STORE_SIZE, HA_CHECKSUM_STORE_SIZE, - buff, NULL) != HA_CHECKSUM_STORE_SIZE) - { - eprint(tracef, "Failed to read record\n"); - DBUG_RETURN(1); - } - share->state.state.checksum+= ha_checksum_korr(buff); - } + share->state.state.checksum+= ha_checksum_korr(logpos); share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED; } + else + { + /* We must set lastpos for upcoming undo delete keys */ + switch (undone_record_type) { + case LOGREC_UNDO_ROW_DELETE: + case LOGREC_UNDO_ROW_UPDATE: + set_lastpos(info, logpos); + break; + default: + break; + } + } if (row_entry) tprint(tracef, " rows' count %lu\n", (ulong)share->state.state.records); _ma_unpin_all_pages(info, rec->lsn); @@ -2436,6 +2478,8 @@ static uint end_of_redo_phase(my_bool prepare_for_undo_phase) static int run_undo_phase(uint uncommitted) { + DBUG_ENTER("run_undo_phase"); + if (uncommitted > 0) { checkpoint_useful= TRUE; @@ -2467,23 +2511,23 @@ static int run_undo_phase(uint uncommitted) LOG_DESC *log_desc; if (translog_read_record_header(trn->undo_lsn, &rec) == RECHEADER_READ_ERROR) - return 1; + DBUG_RETURN(1); log_desc= &log_record_type_descriptor[rec.type]; display_record_position(log_desc, &rec, 0); if (log_desc->record_execute_in_undo_phase(&rec, trn)) { tprint(tracef, "Got error %d when executing undo\n", my_errno); - return 1; + DBUG_RETURN(1); } } if (trnman_rollback_trn(trn)) - return 1; + DBUG_RETURN(1); /* We could want to span a few threads (4?) instead of 1 */ /* In the future, we want to have this phase *online* */ } } - return 0; + DBUG_RETURN(0); } @@ -2783,7 +2827,7 @@ static LSN parse_checkpoint_record(LSN lsn) */ if (ptr != (log_record_buffer.str + log_record_buffer.length)) { - tprint(tracef, "checkpoint record corrupted\n"); + eprint(tracef, "checkpoint record corrupted\n"); return LSN_ERROR; } set_if_smaller(start_address, minimum_rec_lsn_of_dirty_pages); @@ -2821,6 +2865,8 @@ static int close_all_tables(void) LIST *list_element, *next_open; MARIA_HA *info; TRANSLOG_ADDRESS addr; + DBUG_ENTER("close_all_tables"); + pthread_mutex_lock(&THR_LOCK_maria); if (maria_open_list == NULL) goto end; @@ -2862,7 +2908,7 @@ static int close_all_tables(void) } end: pthread_mutex_unlock(&THR_LOCK_maria); - return error; + DBUG_RETURN(error); } diff --git a/storage/maria/ma_scan.c b/storage/maria/ma_scan.c index f9657833fdd..48e9e3400ce 100644 --- a/storage/maria/ma_scan.c +++ b/storage/maria/ma_scan.c @@ -58,3 +58,16 @@ void maria_scan_end(MARIA_HA *info) { (*info->s->scan_end)(info); } + + +int _ma_def_scan_remember_pos(MARIA_HA *info, MARIA_RECORD_POS *lastpos) +{ + *lastpos= info->cur_row.lastpos; + return 0; +} + + +void _ma_def_scan_restore_pos(MARIA_HA *info, MARIA_RECORD_POS lastpos) +{ + info->cur_row.nextpos= lastpos; +} diff --git a/storage/maria/ma_static.c b/storage/maria/ma_static.c index 20c5c999a8f..33f6e9f9fbe 100644 --- a/storage/maria/ma_static.c +++ b/storage/maria/ma_static.c @@ -33,7 +33,7 @@ uchar maria_uuid[MY_UUID_SIZE]; uint maria_quick_table_bits=9; ulong maria_block_size= MARIA_KEY_BLOCK_LENGTH; my_bool maria_flush= 0, maria_single_user= 0; -my_bool maria_delay_key_write= 0; +my_bool maria_delay_key_write= 0, maria_page_checksums= 1; #if defined(THREAD) && !defined(DONT_USE_RW_LOCKS) ulong maria_concurrent_insert= 2; #else diff --git a/storage/maria/ma_test1.c b/storage/maria/ma_test1.c index 8bd241b56cf..363bceb7067 100644 --- a/storage/maria/ma_test1.c +++ b/storage/maria/ma_test1.c @@ -788,7 +788,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), key_type= HA_KEYTYPE_TEXT; break; case 'c': - create_flag|= HA_CREATE_CHECKSUM; + create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM; break; case 'R': /* Length of record pointer */ if (rec_pointer_size > 3) diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c index bf16311e26e..b196455e950 100644 --- a/storage/maria/ma_test2.c +++ b/storage/maria/ma_test2.c @@ -1105,7 +1105,7 @@ static void get_options(int argc, char **argv) opt_quick_mode=1; break; case 'c': - create_flag|= HA_CREATE_CHECKSUM; + create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM; break; case 'D': create_flag|=HA_CREATE_DELAY_KEY_WRITE; diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index a9d87a3026d..8eb9f135a36 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -1636,8 +1636,8 @@ static int maria_sort_records(HA_CHECK *param, share->state.key_root[sort_key], MYF(MY_NABP+MY_WME))) { - _ma_check_print_error(param,"Can't read indexpage from filepos: %s", - (ulong) share->state.key_root[sort_key]); + _ma_check_print_error(param, "Can't read indexpage from filepos: %s", + llstr(share->state.key_root[sort_key], llbuff)); goto err; } diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index ef8235cdcdf..46564420deb 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -40,6 +40,7 @@ #define MAX_NONMAPPED_INSERTS 1000 #define MARIA_MAX_TREE_LEVELS 32 +#define MARIA_MAX_CONTROL_FILE_LOCK_RETRY 30 /* Retry this many times */ struct st_transaction; @@ -126,7 +127,7 @@ typedef struct st_maria_state_info #define MARIA_KEYDEF_SIZE (2+ 5*2) #define MARIA_UNIQUEDEF_SIZE (2+1+1) #define HA_KEYSEG_SIZE (6+ 2*2 + 4*2) -#define MARIA_COLUMNDEF_SIZE (6+2+2+2+2+2+1+1) +#define MARIA_COLUMNDEF_SIZE (2*7+1+1+4) #define MARIA_BASE_INFO_SIZE (MY_UUID_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 */ @@ -277,6 +278,8 @@ typedef struct st_maria_share int (*scan)(MARIA_HA *, uchar *, MARIA_RECORD_POS, my_bool); /* End scan */ void (*scan_end)(MARIA_HA *); + int (*scan_remember_pos)(MARIA_HA *, MARIA_RECORD_POS*); + void (*scan_restore_pos)(MARIA_HA *, MARIA_RECORD_POS); /* Pre-write of row (some handlers may do the actual write here) */ MARIA_RECORD_POS (*write_record_init)(MARIA_HA *, const uchar *); /* Write record (or accept write_record_init) */ @@ -430,7 +433,7 @@ struct st_maria_handler MARIA_STATUS_INFO *state, save_state; 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_BLOCK_SCAN scan, *scan_save; MARIA_BLOB *blobs; /* Pointer to blobs */ MARIA_BIT_BUFF bit_buff; DYNAMIC_ARRAY bitmap_blocks; @@ -483,7 +486,7 @@ struct st_maria_handler enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */ uint save_lastkey_length; uint pack_key_length; /* For MARIAMRG */ - myf lock_wait; /* is 0 or MY_DONT_WAIT */ + myf lock_wait; /* is 0 or MY_SHORT_WAIT */ int errkey; /* Got last error on this key */ int lock_type; /* How database was locked */ int tmp_lock_type; /* When locked by readinfo */ @@ -999,6 +1002,9 @@ void _ma_restore_status(void *param); void _ma_copy_status(void *to, void *from); my_bool _ma_check_status(void *param); void _ma_reset_status(MARIA_HA *maria); +int _ma_def_scan_remember_pos(MARIA_HA *info, MARIA_RECORD_POS *lastpos); +void _ma_def_scan_restore_pos(MARIA_HA *info, MARIA_RECORD_POS lastpos); + #include "ma_commit.h" extern MARIA_HA *_ma_test_if_reopen(const char *filename); @@ -1023,9 +1029,12 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index, See ma_check_standalone.h . */ volatile int *_ma_killed_ptr(HA_CHECK *param); -void _ma_check_print_error _VARARGS((HA_CHECK *param, const char *fmt, ...)); -void _ma_check_print_warning _VARARGS((HA_CHECK *param, const char *fmt, ...)); -void _ma_check_print_info _VARARGS((HA_CHECK *param, const char *fmt, ...)); +void _ma_check_print_error _VARARGS((HA_CHECK *param, const char *fmt, ...)) + ATTRIBUTE_FORMAT(printf, 2, 3); +void _ma_check_print_warning _VARARGS((HA_CHECK *param, const char *fmt, ...)) + ATTRIBUTE_FORMAT(printf, 2, 3); +void _ma_check_print_info _VARARGS((HA_CHECK *param, const char *fmt, ...)) + ATTRIBUTE_FORMAT(printf, 2, 3); C_MODE_END int _ma_flush_pending_blocks(MARIA_SORT_PARAM *param); @@ -1056,23 +1065,29 @@ void _ma_tmp_disable_logging_for_table(MARIA_HA *info, #define MARIA_NO_CRC_BITMAP_PAGE 0xfffffffe extern my_bool maria_page_crc_set_index(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr); + uchar *data_ptr); extern my_bool maria_page_crc_set_normal(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr); + uchar *data_ptr); extern my_bool maria_page_crc_check_bitmap(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr); + uchar *data_ptr); extern my_bool maria_page_crc_check_data(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr); + uchar *data_ptr); extern my_bool maria_page_crc_check_index(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr); + uchar *data_ptr); +extern my_bool maria_page_crc_check_none(uchar *page, + pgcache_page_no_t page_no, + uchar *data_ptr); extern my_bool maria_page_filler_set_bitmap(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr); + uchar *data_ptr); extern my_bool maria_page_filler_set_normal(uchar *page, pgcache_page_no_t page_no, - uchar* data_ptr); + uchar *data_ptr); +extern my_bool maria_page_filler_set_none(uchar *page, + pgcache_page_no_t page_no, + uchar *data_ptr); extern PAGECACHE *maria_log_pagecache; diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 9278c717e85..d5c034b3c01 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -259,28 +259,28 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, { /* reserve space for null bits */ bzero((char*) recinfo_pos, sizeof(*recinfo_pos)); - recinfo_pos->type= (int) FIELD_NORMAL; + recinfo_pos->type= FIELD_NORMAL; recinfo_pos++->length= (uint16) (minpos - recpos); } if (!found) break; if (found->flags & BLOB_FLAG) - recinfo_pos->type= (int) FIELD_BLOB; + recinfo_pos->type= FIELD_BLOB; else if (found->type() == MYSQL_TYPE_VARCHAR) recinfo_pos->type= FIELD_VARCHAR; else if (!(options & HA_OPTION_PACK_RECORD)) - recinfo_pos->type= (int) FIELD_NORMAL; + recinfo_pos->type= FIELD_NORMAL; else if (found->zero_pack()) - recinfo_pos->type= (int) FIELD_SKIP_ZERO; + recinfo_pos->type= FIELD_SKIP_ZERO; else - recinfo_pos->type= (int) ((length <= 3 || - (found->flags & ZEROFILL_FLAG)) ? - FIELD_NORMAL : - found->type() == MYSQL_TYPE_STRING || - found->type() == MYSQL_TYPE_VAR_STRING ? - FIELD_SKIP_ENDSPACE : - FIELD_SKIP_PRESPACE); + recinfo_pos->type= ((length <= 3 || + (found->flags & ZEROFILL_FLAG)) ? + FIELD_NORMAL : + found->type() == MYSQL_TYPE_STRING || + found->type() == MYSQL_TYPE_VAR_STRING ? + FIELD_SKIP_ENDSPACE : + FIELD_SKIP_PRESPACE); if (found->null_ptr) { recinfo_pos->null_bit= found->null_bit; @@ -1683,9 +1683,15 @@ int ha_myisam::rnd_next(uchar *buf) return error; } -int ha_myisam::restart_rnd_next(uchar *buf, uchar *pos) +int ha_myisam::remember_rnd_pos() { - return rnd_pos(buf,pos); + position((uchar*) 0); + return 0; +} + +int ha_myisam::restart_rnd_next(uchar *buf) +{ + return rnd_pos(buf, ref); } int ha_myisam::rnd_pos(uchar *buf, uchar *pos) diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h index 729ad2ee87e..076e31c07e8 100644 --- a/storage/myisam/ha_myisam.h +++ b/storage/myisam/ha_myisam.h @@ -94,7 +94,8 @@ class ha_myisam: public handler int rnd_init(bool scan); int rnd_next(uchar *buf); int rnd_pos(uchar * buf, uchar *pos); - int restart_rnd_next(uchar *buf, uchar *pos); + int remember_rnd_pos(); + int restart_rnd_next(uchar *buf); void position(const uchar *record); int info(uint); int extra(enum ha_extra_function operation); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index a3a92f345e1..fc9d3a346dd 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -2145,7 +2145,7 @@ int lock_file(HA_CHECK *param, File file, my_off_t start, int lock_type, { if (my_lock(file,lock_type,start,F_TO_EOF, param->testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) : - MYF(MY_SEEK_NOT_DONE | MY_DONT_WAIT))) + MYF(MY_SEEK_NOT_DONE | MY_SHORT_WAIT))) { mi_check_print_error(param," %d when locking %s '%s'",my_errno,filetype,filename); param->error_printed=2; /* Don't give that data is crashed */ diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c index 33c9d1210ca..d798ef50d7e 100644 --- a/storage/myisam/mi_extra.c +++ b/storage/myisam/mi_extra.c @@ -216,7 +216,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) info->lock_wait=0; break; case HA_EXTRA_NO_WAIT_LOCK: - info->lock_wait=MY_DONT_WAIT; + info->lock_wait= MY_SHORT_WAIT; break; case HA_EXTRA_NO_KEYS: if (info->lock_type == F_UNLCK) diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index 68ecc1d6a2a..0c0e5261cc1 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -180,7 +180,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) { if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF, MYF(open_flags & HA_OPEN_WAIT_IF_LOCKED ? - 0 : MY_DONT_WAIT))) && + 0 : MY_SHORT_WAIT))) && !(open_flags & HA_OPEN_IGNORE_IF_LOCKED)) goto err; } diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 59d54bdc542..64c1a8214c3 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -284,7 +284,7 @@ struct st_myisam_info LIST open_list; IO_CACHE rec_cache; /* When cacheing records */ uint preload_buff_size; /* When preloading indexes */ - myf lock_wait; /* is 0 or MY_DONT_WAIT */ + myf lock_wait; /* is 0 or MY_SHORT_WAIT */ my_bool was_locked; /* Was locked in panic */ my_bool append_insert_at_end; /* Set if concurrent insert */ my_bool quick_mode;