summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_global.h5
-rw-r--r--include/my_pthread.h16
-rw-r--r--include/thr_alarm.h3
-rw-r--r--myisam/mi_create.c13
-rw-r--r--myisam/mi_dynrec.c4
-rw-r--r--myisam/mi_open.c15
-rw-r--r--myisam/mi_update.c3
-rw-r--r--myisam/mi_write.c2
-rw-r--r--mysql-test/Makefile.am2
-rw-r--r--mysql-test/r/merge.result22
-rw-r--r--mysql-test/r/myisam.result21
-rw-r--r--mysql-test/r/ps.result15
-rw-r--r--mysql-test/r/symlink.result15
-rw-r--r--mysql-test/t/merge.test29
-rw-r--r--mysql-test/t/myisam.test27
-rw-r--r--mysql-test/t/ps.test18
-rw-r--r--mysql-test/t/symlink.test19
-rw-r--r--mysql-test/valgrind.supp437
-rw-r--r--mysys/default.c4
-rw-r--r--mysys/my_pthread.c6
-rw-r--r--mysys/my_thr_init.c21
-rw-r--r--mysys/thr_alarm.c26
-rw-r--r--sql/examples/ha_tina.cc12
-rw-r--r--sql/examples/ha_tina.h2
-rw-r--r--sql/field_conv.cc4
-rw-r--r--sql/ha_myisam.cc491
-rw-r--r--sql/ha_myisammrg.cc42
-rw-r--r--sql/handler.cc4
-rw-r--r--sql/lock.cc2
-rw-r--r--sql/mysqld.cc41
-rw-r--r--sql/sql_update.cc131
-rw-r--r--sql/table.cc2
-rw-r--r--vio/viosslfactories.c4
33 files changed, 1105 insertions, 353 deletions
diff --git a/include/my_global.h b/include/my_global.h
index bd54ba1cf89..b7b200fdcf4 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -415,10 +415,7 @@ int __void__;
#endif
/* Define some useful general macros */
-#if defined(__cplusplus) && defined(__GNUC__)
-#define max(a, b) ((a) >? (b))
-#define min(a, b) ((a) <? (b))
-#elif !defined(max)
+#if !defined(max)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
diff --git a/include/my_pthread.h b/include/my_pthread.h
index b852cfaad3d..14dbc9825d4 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -28,14 +28,6 @@
extern "C" {
#endif /* __cplusplus */
-/* Thread library */
-
-#define THD_LIB_OTHER 1
-#define THD_LIB_NPTL 2
-#define THD_LIB_LT 4
-
-extern uint thd_lib_detected;
-
#if defined(__WIN__) || defined(OS2)
#ifdef OS2
@@ -684,6 +676,14 @@ extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
*/
extern pthread_t shutdown_th, main_th, signal_th;
+/* Which kind of thread library is in use */
+
+#define THD_LIB_OTHER 1
+#define THD_LIB_NPTL 2
+#define THD_LIB_LT 4
+
+extern uint thd_lib_detected;
+
/* statistics_xxx functions are for not essential statistic */
#ifndef thread_safe_increment
diff --git a/include/thr_alarm.h b/include/thr_alarm.h
index 0c26a67acf4..1d7ebbcb9f5 100644
--- a/include/thr_alarm.h
+++ b/include/thr_alarm.h
@@ -93,6 +93,9 @@ typedef struct st_alarm {
my_bool malloced;
} ALARM;
+extern uint thr_client_alarm;
+extern pthread_t alarm_thread;
+
#define thr_alarm_init(A) (*(A))=0
#define thr_alarm_in_use(A) (*(A)!= 0)
void init_thr_alarm(uint max_alarm);
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index c1310a8012d..da9e0887b00 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -768,18 +768,19 @@ uint mi_get_pointer_length(ulonglong file_length, uint def)
if (file_length) /* If not default */
{
#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
- if (file_length >= (longlong) 1 << 56)
+ if (file_length >= ULL(1) << 56)
def=8;
+ else
#endif
- if (file_length >= (longlong) 1 << 48)
+ if (file_length >= ULL(1) << 48)
def=7;
- if (file_length >= (longlong) 1 << 40)
+ else if (file_length >= ULL(1) << 40)
def=6;
- else if (file_length >= (longlong) 1 << 32)
+ else if (file_length >= ULL(1) << 32)
def=5;
- else if (file_length >= (1L << 24))
+ else if (file_length >= ULL(1) << 24)
def=4;
- else if (file_length >= (1L << 16))
+ else if (file_length >= ULL(1) << 16)
def=3;
else
def=2;
diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c
index 727f44341b1..260f461685e 100644
--- a/myisam/mi_dynrec.c
+++ b/myisam/mi_dynrec.c
@@ -81,7 +81,7 @@ int _mi_write_blob_record(MI_INFO *info, const byte *record)
#endif
if (!(rec_buff=(byte*) my_alloca(reclength)))
{
- my_errno=ENOMEM;
+ my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
return(-1);
}
reclength2= _mi_rec_pack(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
@@ -115,7 +115,7 @@ int _mi_update_blob_record(MI_INFO *info, my_off_t pos, const byte *record)
#endif
if (!(rec_buff=(byte*) my_alloca(reclength)))
{
- my_errno=ENOMEM;
+ my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
return(-1);
}
reclength=_mi_rec_pack(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 4efe6f42d5e..b007eb63e63 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -315,7 +315,13 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
{
disk_pos=mi_keyseg_read(disk_pos, pos);
-
+ if (pos->flag & HA_BLOB_PART &&
+ ! (share->options & (HA_OPTION_COMPRESS_RECORD |
+ HA_OPTION_PACK_RECORD)))
+ {
+ my_errno= HA_ERR_CRASHED;
+ goto err;
+ }
if (pos->type == HA_KEYTYPE_TEXT || pos->type == HA_KEYTYPE_VARTEXT)
{
if (!pos->language)
@@ -429,6 +435,13 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
offset+=share->rec[i].length;
}
share->rec[i].type=(int) FIELD_LAST; /* End marker */
+ if (offset > share->base.reclength)
+ {
+ /* purecov: begin inspected */
+ my_errno= HA_ERR_CRASHED;
+ goto err;
+ /* purecov: end */
+ }
if (! lock_error)
{
diff --git a/myisam/mi_update.c b/myisam/mi_update.c
index 00eee18bfab..d5a580748fc 100644
--- a/myisam/mi_update.c
+++ b/myisam/mi_update.c
@@ -193,7 +193,8 @@ err:
save_errno=my_errno;
if (changed)
key_changed|= HA_STATE_CHANGED;
- if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL)
+ if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_OUT_OF_MEM ||
+ my_errno == HA_ERR_RECORD_FILE_FULL)
{
info->errkey= (int) i;
flag=0;
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index f8a5c6fa652..030c4ac5fc7 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -164,7 +164,7 @@ int mi_write(MI_INFO *info, byte *record)
err:
save_errno=my_errno;
if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL ||
- my_errno == HA_ERR_NULL_IN_SPATIAL)
+ my_errno == HA_ERR_NULL_IN_SPATIAL || my_errno == HA_ERR_OUT_OF_MEM)
{
if (info->bulk_insert)
{
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index f8bf5c490f0..5b0a8afe98e 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -33,7 +33,7 @@ endif
benchdir_root= $(prefix)
testdir = $(benchdir_root)/mysql-test
EXTRA_SCRIPTS = mysql-test-run-shell.sh install_test_db.sh \
- $(PRESCRIPTS)
+ valgrind.supp $(PRESCRIPTS)
EXTRA_DIST = $(EXTRA_SCRIPTS)
GENSCRIPTS = mysql-test-run-shell mysql-test-run install_test_db mtr
PRESCRIPTS = mysql-test-run.pl
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index a1ef7597143..eb333cdadb7 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -770,7 +770,7 @@ CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES(2),(1);
CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1);
SELECT * FROM t2 WHERE a=2;
-ERROR HY000: Got error 124 from storage engine
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
DROP TABLE t1, t2;
CREATE TABLE t1(a INT) ENGINE=MEMORY;
CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1);
@@ -781,3 +781,23 @@ CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3);
SELECT * FROM t2;
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
DROP TABLE t2;
+CREATE TABLE t1(a INT, b TEXT);
+CREATE TABLE tm1(a TEXT, b INT) ENGINE=MERGE UNION=(t1);
+SELECT * FROM tm1;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+DROP TABLE t1, tm1;
+CREATE TABLE t1(a SMALLINT, b SMALLINT);
+CREATE TABLE tm1(a INT) ENGINE=MERGE UNION=(t1);
+SELECT * FROM tm1;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+DROP TABLE t1, tm1;
+CREATE TABLE t1(a SMALLINT, b SMALLINT, KEY(a, b));
+CREATE TABLE tm1(a SMALLINT, b SMALLINT, KEY(a)) ENGINE=MERGE UNION=(t1);
+SELECT * FROM tm1;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+DROP TABLE t1, tm1;
+CREATE TABLE t1(a SMALLINT, b SMALLINT, KEY(b));
+CREATE TABLE tm1(a SMALLINT, b SMALLINT, KEY(a)) ENGINE=MERGE UNION=(t1);
+SELECT * FROM tm1;
+ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+DROP TABLE t1, tm1;
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index 0fd14b08a41..4b17e8c9840 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -923,4 +923,25 @@ SET @@myisam_repair_threads=1;
SHOW VARIABLES LIKE 'myisam_repair%';
Variable_name Value
myisam_repair_threads 1
+CREATE TABLE t1(a VARCHAR(16));
+INSERT INTO t1 VALUES('aaaaaaaa'),(NULL);
+UPDATE t1 AS ta1, t1 AS ta2 SET ta1.a='aaaaaaaaaaaaaaaa';
+SELECT * FROM t1;
+a
+aaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaa
+DROP TABLE t1;
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES(1),(2);
+UPDATE t1,t1 AS t2 SET t1.a=t1.a+2 WHERE t1.a=t2.a-1;
+SELECT * FROM t1 ORDER BY a;
+a
+2
+3
+DROP TABLE t1;
+CREATE TABLE t1 (c1 TEXT) AVG_ROW_LENGTH=70100 MAX_ROWS=4100100100;
+SHOW TABLE STATUS LIKE 't1';
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 MyISAM 9 Dynamic X X X 72057594037927935 X X X X X X latin1_swedish_ci X max_rows=4100100100 avg_row_length=70100
+DROP TABLE t1;
End of 4.1 tests
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 0d6b01f3481..d8a75737efc 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -1087,19 +1087,4 @@ t2 CREATE TABLE `t2` (
drop database mysqltest;
deallocate prepare stmt1;
deallocate prepare stmt2;
-execute stmt;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `c` char(10) default NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/'
-drop table t1;
-execute stmt;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `c` char(10) default NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/'
-drop table t1;
-deallocate prepare stmt;
End of 4.1 tests.
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index bc7d3275754..9b21dc7e952 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -123,4 +123,19 @@ select * from t1;
a
42
drop table t1;
+execute stmt;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c` char(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/'
+drop table t1;
+execute stmt;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c` char(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/'
+drop table t1;
+deallocate prepare stmt;
End of 4.1 tests
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index bb03b7b8d62..700a807e62c 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -383,7 +383,7 @@ drop table t1, t2, t3;
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES(2),(1);
CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1);
---error 1030
+--error 1168
SELECT * FROM t2 WHERE a=2;
DROP TABLE t1, t2;
@@ -401,4 +401,31 @@ CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3);
SELECT * FROM t2;
DROP TABLE t2;
+#
+# Underlying table definition conformance tests.
+#
+CREATE TABLE t1(a INT, b TEXT);
+CREATE TABLE tm1(a TEXT, b INT) ENGINE=MERGE UNION=(t1);
+--error 1168
+SELECT * FROM tm1;
+DROP TABLE t1, tm1;
+
+CREATE TABLE t1(a SMALLINT, b SMALLINT);
+CREATE TABLE tm1(a INT) ENGINE=MERGE UNION=(t1);
+--error 1168
+SELECT * FROM tm1;
+DROP TABLE t1, tm1;
+
+CREATE TABLE t1(a SMALLINT, b SMALLINT, KEY(a, b));
+CREATE TABLE tm1(a SMALLINT, b SMALLINT, KEY(a)) ENGINE=MERGE UNION=(t1);
+--error 1168
+SELECT * FROM tm1;
+DROP TABLE t1, tm1;
+
+CREATE TABLE t1(a SMALLINT, b SMALLINT, KEY(b));
+CREATE TABLE tm1(a SMALLINT, b SMALLINT, KEY(a)) ENGINE=MERGE UNION=(t1);
+--error 1168
+SELECT * FROM tm1;
+DROP TABLE t1, tm1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index 960d060f6a7..68c7b55c501 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -855,4 +855,31 @@ DROP TABLE t1;
SET @@myisam_repair_threads=1;
SHOW VARIABLES LIKE 'myisam_repair%';
+#
+# BUG#21310 - Trees in SQL causing a "crashed" table with MyISAM storage
+# engine
+#
+
+# A simplified test case that reflect crashed table issue.
+CREATE TABLE t1(a VARCHAR(16));
+INSERT INTO t1 VALUES('aaaaaaaa'),(NULL);
+UPDATE t1 AS ta1, t1 AS ta2 SET ta1.a='aaaaaaaaaaaaaaaa';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# A test case that reflect wrong result set.
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES(1),(2);
+UPDATE t1,t1 AS t2 SET t1.a=t1.a+2 WHERE t1.a=t2.a-1;
+SELECT * FROM t1 ORDER BY a;
+DROP TABLE t1;
+
+#
+# Bug#24607 - MyISAM pointer size determined incorrectly
+#
+CREATE TABLE t1 (c1 TEXT) AVG_ROW_LENGTH=70100 MAX_ROWS=4100100100;
+--replace_column 5 X 6 X 7 X 9 X 10 X 11 X 12 X 13 X 14 X 16 X
+SHOW TABLE STATUS LIKE 't1';
+DROP TABLE t1;
+
--echo End of 4.1 tests
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index c963e59110f..a0133897f50 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -1128,22 +1128,4 @@ drop database mysqltest;
deallocate prepare stmt1;
deallocate prepare stmt2;
#
-# CREATE TABLE with DATA DIRECTORY option
-#
-# Protect ourselves from data left in tmp/ by a previos possibly failed
-# test
---system rm -f $MYSQLTEST_VARDIR/tmp/t1.*
---disable_query_log
-eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'";
---enable_query_log
-execute stmt;
---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-show create table t1;
-drop table t1;
-execute stmt;
---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-show create table t1;
-drop table t1;
-deallocate prepare stmt;
-#
--echo End of 4.1 tests.
diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test
index 23fd779ee13..010ef496399 100644
--- a/mysql-test/t/symlink.test
+++ b/mysql-test/t/symlink.test
@@ -170,4 +170,23 @@ connection default;
select * from t1;
drop table t1;
+#
+# CREATE TABLE with DATA DIRECTORY option
+#
+# Protect ourselves from data left in tmp/ by a previos possibly failed
+# test
+--system rm -f $MYSQLTEST_VARDIR/tmp/t1.*
+--disable_query_log
+eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'";
+--enable_query_log
+execute stmt;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+show create table t1;
+drop table t1;
+execute stmt;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+show create table t1;
+drop table t1;
+deallocate prepare stmt;
+
--echo End of 4.1 tests
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
new file mode 100644
index 00000000000..716dca491ce
--- /dev/null
+++ b/mysql-test/valgrind.supp
@@ -0,0 +1,437 @@
+#
+# Suppress some common (not fatal) errors in system libraries found by valgrind
+#
+
+#
+# Pthread doesn't free all thread specific memory before program exists
+#
+{
+ pthread allocate_tls memory loss
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_allocate_tls
+ fun:allocate_stack
+ fun:pthread_create*
+}
+
+{
+ pthread allocate_tls memory loss
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_allocate_tls
+ fun:pthread_create*
+}
+
+{
+ pthread allocate_dtv memory loss
+ Memcheck:Leak
+ fun:calloc
+ fun:allocate_dtv
+ fun:_dl_allocate_tls_storage
+ fun:__GI__dl_allocate_tls
+ fun:pthread_create
+}
+
+{
+ pthread allocate_dtv memory loss second
+ Memcheck:Leak
+ fun:calloc
+ fun:allocate_dtv
+ fun:_dl_allocate_tls
+ fun:pthread_create*
+}
+
+{
+ pthread memalign memory loss
+ Memcheck:Leak
+ fun:memalign
+ fun:_dl_allocate_tls_storage
+ fun:__GI__dl_allocate_tls
+ fun:pthread_create
+}
+
+{
+ pthread pthread_key_create
+ Memcheck:Leak
+ fun:malloc
+ fun:*
+ fun:*
+ fun:pthread_key_create
+ fun:my_thread_global_init
+}
+
+{
+ pthread strstr uninit
+ Memcheck:Cond
+ fun:strstr
+ obj:/lib/tls/libpthread.so.*
+ obj:/lib/tls/libpthread.so.*
+ fun:call_init
+ fun:_dl_init
+ obj:/lib/ld-*.so
+}
+
+{
+ pthread errno
+ Memcheck:Leak
+ fun:calloc
+ fun:_dlerror_run
+ fun:dlsym
+ fun:__errno_location
+}
+
+
+#
+# Warnings in libz becasue it works with aligned memory(?)
+#
+
+{
+ libz tr_flush_block
+ Memcheck:Cond
+ fun:_tr_flush_block
+ fun:deflate_slow
+ fun:deflate
+ fun:do_flush
+ fun:gzclose
+}
+
+{
+ libz tr_flush_block2
+ Memcheck:Cond
+ fun:_tr_flush_block
+ fun:deflate_slow
+ fun:deflate
+ fun:compress2
+}
+
+{
+ libz longest_match
+ Memcheck:Cond
+ fun:longest_match
+ fun:deflate_slow
+ fun:deflate
+ fun:do_flush
+}
+
+{
+ libz longest_match2
+ Memcheck:Cond
+ fun:longest_match
+ fun:deflate_slow
+ fun:deflate
+ fun:compress2
+}
+
+{
+ libz longest_match 3
+ Memcheck:Cond
+ fun:longest_match
+ fun:deflate_slow
+ fun:deflate
+ fun:gzclose
+}
+
+{
+ libz longest_match 4
+ Memcheck:Cond
+ fun:longest_match
+ fun:deflate_slow
+ fun:deflate
+ fun:gzflush
+}
+
+{
+ libz deflate
+ Memcheck:Cond
+ obj:*/libz.so.*
+ obj:*/libz.so.*
+ fun:deflate
+ fun:compress2
+}
+
+{
+ libz deflate2
+ Memcheck:Cond
+ obj:*/libz.so.*
+ obj:*/libz.so.*
+ fun:deflate
+ obj:*/libz.so.*
+ fun:gzflush
+}
+
+
+#
+# Warning from my_thread_init becasue mysqld dies before kill thread exists
+#
+
+{
+ my_thread_init kill thread memory loss second
+ Memcheck:Leak
+ fun:calloc
+ fun:my_thread_init
+ fun:kill_server_thread
+}
+
+#
+# Leaks reported in _dl_* internal functions on Linux amd64 / glibc2.3.2.
+#
+
+{
+ _dl_start invalid write8
+ Memcheck:Addr8
+ fun:_dl_start
+}
+
+{
+ _dl_start invalid write4
+ Memcheck:Addr4
+ fun:_dl_start
+}
+
+{
+ _dl_start/_dl_setup_hash invalid read8
+ Memcheck:Addr8
+ fun:_dl_setup_hash
+ fun:_dl_start
+}
+
+{
+ _dl_sysdep_start invalid write8
+ Memcheck:Addr8
+ fun:_dl_sysdep_start
+}
+
+{
+ _dl_init invalid write8
+ Memcheck:Addr8
+ fun:_dl_init
+}
+
+{
+ _dl_init invalid write4
+ Memcheck:Addr4
+ fun:_dl_init
+}
+
+{
+ _dl_init/_dl_init invalid read8
+ Memcheck:Addr8
+ fun:_dl_debug_initialize
+ fun:_dl_init
+}
+
+{
+ _dl_init/_dl_debug_state invalid read8
+ Memcheck:Addr8
+ fun:_dl_debug_state
+ fun:_dl_init
+}
+
+{
+ init invalid write8
+ Memcheck:Addr8
+ fun:init
+}
+
+{
+ fixup invalid write8
+ Memcheck:Addr8
+ fun:fixup
+}
+
+{
+ fixup/_dl_lookup_versioned_symbol invalid read8
+ Memcheck:Addr8
+ fun:_dl_lookup_versioned_symbol
+ fun:fixup
+}
+
+{
+ _dl_runtime_resolve invalid read8
+ Memcheck:Addr8
+ fun:_dl_runtime_resolve
+}
+
+{
+ __libc_start_main invalid write8
+ Memcheck:Addr8
+ fun:__libc_start_main
+}
+
+{
+ __libc_start_main/__sigjmp_save invalid write4
+ Memcheck:Addr4
+ fun:__sigjmp_save
+ fun:__libc_start_main
+}
+
+#
+# These seem to be libc threading stuff, not related to MySQL code (allocations
+# during pthread_exit()). Googling shows other projects also using these
+# suppressions.
+#
+# Note that these all stem from pthread_exit() deeper in the call stack, but
+# Valgrind only allows the top four calls in the suppressions.
+#
+
+{
+ libc pthread_exit 1
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_new_object
+ fun:_dl_map_object_from_fd
+ fun:_dl_map_object
+}
+
+{
+ libc pthread_exit 2
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_map_object
+ fun:dl_open_worker
+ fun:_dl_catch_error
+}
+
+{
+ libc pthread_exit 3
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_map_object_deps
+ fun:dl_open_worker
+ fun:_dl_catch_error
+}
+
+{
+ libc pthread_exit 4
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_check_map_versions
+ fun:dl_open_worker
+ fun:_dl_catch_error
+}
+
+{
+ libc pthread_exit 5
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_new_object
+ fun:_dl_map_object_from_fd
+ fun:_dl_map_object
+}
+
+
+
+#
+# This is seen internally in the system libraries on 64-bit RHAS3.
+#
+
+{
+ __lll_mutex_unlock_wake uninitialized
+ Memcheck:Param
+ futex(utime)
+ fun:__lll_mutex_unlock_wake
+}
+
+#
+# BUG#19940: NDB sends uninitialized parts of field buffers across the wire.
+# This is "works as designed"; the uninitialized part is not used at the
+# other end (but Valgrind cannot see this).
+#
+{
+ bug19940
+ Memcheck:Param
+ socketcall.sendto(msg)
+ fun:send
+ fun:_ZN15TCP_Transporter6doSendEv
+ fun:_ZN19TransporterRegistry11performSendEv
+ fun:_ZN19TransporterRegistry14forceSendCheckEi
+}
+
+{
+ OpenSSL_1
+ Memcheck:Cond
+ fun:BN_num_bits_word
+ fun:BN_num_bits
+ fun:BN_mod_exp_mont_consttime
+ fun:BN_mod_exp_mont
+ obj:*libcrypto.so.*
+ obj:*libcrypto.so.*
+ fun:DH_generate_key
+ fun:ssl3_ctx_ctrl
+ fun:SSL_CTX_ctrl
+ fun:new_VioSSLAcceptorFd
+ fun:main
+}
+
+{
+ OpenSSL_2
+ Memcheck:Value4
+ fun:BN_num_bits_word
+ fun:BN_num_bits
+ fun:BN_mod_exp_mont_consttime
+ fun:BN_mod_exp_mont
+ obj:*libcrypto.so.*
+ obj:*libcrypto.so.*
+ fun:DH_generate_key
+ fun:ssl3_ctx_ctrl
+ fun:SSL_CTX_ctrl
+ fun:new_VioSSLAcceptorFd
+ fun:main
+}
+
+{
+ OpenSSL_3
+ Memcheck:Value4
+ fun:BN_mod_exp_mont_consttime
+ fun:BN_mod_exp_mont
+ obj:*libcrypto.so.*
+ obj:*libcrypto.so.*
+ fun:DH_generate_key
+ fun:ssl3_ctx_ctrl
+ fun:SSL_CTX_ctrl
+ fun:new_VioSSLAcceptorFd
+ fun:main
+}
+
+{
+ OpenSSL_4
+ Memcheck:Cond
+ fun:BN_bin2bn
+ obj:*libcrypto.so.*
+ obj:*libcrypto.so.*
+ fun:DH_generate_key
+ fun:ssl3_ctx_ctrl
+ fun:SSL_CTX_ctrl
+ fun:new_VioSSLAcceptorFd
+ fun:main
+}
+
+{
+ OpenSSL_5
+ Memcheck:Leak
+ fun:realloc
+ obj:*libcrypto.so.*
+ fun:CRYPTO_realloc
+ fun:lh_insert
+ fun:OBJ_NAME_add
+ fun:EVP_add_cipher
+ fun:OpenSSL_add_all_ciphers
+ fun:OPENSSL_add_all_algorithms_noconf
+ fun:new_VioSSLAcceptorFd
+ fun:main
+}
+
+{
+ OpenSSL_6
+ Memcheck:Leak
+ fun:malloc
+ obj:*libcrypto.so.*
+ fun:CRYPTO_malloc
+ fun:lh_new
+ fun:OBJ_NAME_init
+ fun:OBJ_NAME_add
+ fun:EVP_add_cipher
+ fun:SSL_library_init
+ fun:new_VioSSLAcceptorFd
+ fun:main
+}
diff --git a/mysys/default.c b/mysys/default.c
index 6e40c48d82a..fadf6efbc5b 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -308,7 +308,7 @@ static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
{
char **ext;
- for (ext= (char**) f_extensions; *ext; *ext++)
+ for (ext= (char**) f_extensions; *ext; ext++)
{
int error;
if ((error= search_default_file_with_ext(args, alloc, dir, *ext,
@@ -708,7 +708,7 @@ void print_defaults(const char *conf_file, const char **groups)
#endif
for (dirs=default_directories ; *dirs; dirs++)
{
- for (ext= (char**) f_extensions; *ext; *ext++)
+ for (ext= (char**) f_extensions; *ext; ext++)
{
const char *pos;
char *end;
diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c
index 49a1ea79f65..14ba6aabf0e 100644
--- a/mysys/my_pthread.c
+++ b/mysys/my_pthread.c
@@ -318,8 +318,6 @@ void sigwait_handle_sig(int sig)
pthread_mutex_unlock(&LOCK_sigwait);
}
-extern pthread_t alarm_thread;
-
void *sigwait_thread(void *set_arg)
{
sigset_t *set=(sigset_t*) set_arg;
@@ -338,7 +336,9 @@ void *sigwait_thread(void *set_arg)
sigaction(i, &sact, (struct sigaction*) 0);
}
}
- sigaddset(set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1);
+ /* Ensure that init_thr_alarm() is called */
+ DBUG_ASSERT(thr_client_alarm);
+ sigaddset(set, thr_client_alarm);
pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0);
alarm_thread=pthread_self(); /* For thr_alarm */
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 878e1f6bfc6..42f025c39f3 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -21,6 +21,7 @@
#include "mysys_priv.h"
#include <m_string.h>
+#include <signal.h>
#ifdef THREAD
#ifdef USE_TLS
@@ -44,6 +45,8 @@ pthread_mutexattr_t my_fast_mutexattr;
pthread_mutexattr_t my_errorcheck_mutexattr;
#endif
+static uint get_thread_lib(void);
+
/*
initialize thread environment
@@ -57,6 +60,8 @@ pthread_mutexattr_t my_errorcheck_mutexattr;
my_bool my_thread_global_init(void)
{
+ thd_lib_detected= get_thread_lib();
+
if (pthread_key_create(&THR_KEY_mysys,0))
{
fprintf(stderr,"Can't initialize threads: error %d\n",errno);
@@ -290,4 +295,20 @@ const char *my_thread_name(void)
}
#endif /* DBUG_OFF */
+
+static uint get_thread_lib(void)
+{
+ char buff[64];
+
+#ifdef _CS_GNU_LIBPTHREAD_VERSION
+ confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
+
+ if (!strncasecmp(buff, "NPTL", 4))
+ return THD_LIB_NPTL;
+ if (!strncasecmp(buff, "linuxthreads", 12))
+ return THD_LIB_LT;
+#endif
+ return THD_LIB_OTHER;
+}
+
#endif /* THREAD */
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index 063f57715c4..759544af17b 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -36,6 +36,7 @@
#define ETIME ETIMEDOUT
#endif
+uint thr_client_alarm;
static int alarm_aborted=1; /* No alarm thread */
my_bool thr_alarm_inited= 0;
volatile my_bool alarm_thread_running= 0;
@@ -77,12 +78,15 @@ void init_thr_alarm(uint max_alarms)
sigfillset(&full_signal_set); /* Neaded to block signals */
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
pthread_cond_init(&COND_alarm,NULL);
+ if (thd_lib_detected == THD_LIB_LT)
+ thr_client_alarm= SIGALRM;
+ else
+ thr_client_alarm= SIGUSR1;
#ifndef USE_ALARM_THREAD
if (thd_lib_detected != THD_LIB_LT)
#endif
{
- my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1,
- thread_alarm);
+ my_sigset(thr_client_alarm, thread_alarm);
}
sigemptyset(&s);
sigaddset(&s, THR_SERVER_ALARM);
@@ -103,8 +107,7 @@ void init_thr_alarm(uint max_alarms)
pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */
if (thd_lib_detected == THD_LIB_LT)
{
- my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1,
- process_alarm); /* Linuxthreads */
+ my_sigset(thr_client_alarm, process_alarm); /* Linuxthreads */
pthread_sigmask(SIG_UNBLOCK, &s, NULL);
}
#else
@@ -284,8 +287,7 @@ sig_handler process_alarm(int sig __attribute__((unused)))
printf("thread_alarm in process_alarm\n"); fflush(stdout);
#endif
#ifdef DONT_REMEMBER_SIGNAL
- my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1,
- process_alarm); /* int. thread system calls */
+ my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */
#endif
return;
}
@@ -332,8 +334,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
alarm_data=(ALARM*) queue_element(&alarm_queue,i);
alarm_data->alarmed=1; /* Info to thread */
if (pthread_equal(alarm_data->thread,alarm_thread) ||
- pthread_kill(alarm_data->thread,
- thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1))
+ pthread_kill(alarm_data->thread, thr_client_alarm))
{
#ifdef MAIN
printf("Warning: pthread_kill couldn't find thread!!!\n");
@@ -357,8 +358,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
alarm_data->alarmed=1; /* Info to thread */
DBUG_PRINT("info",("sending signal to waiting thread"));
if (pthread_equal(alarm_data->thread,alarm_thread) ||
- pthread_kill(alarm_data->thread,
- thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1))
+ pthread_kill(alarm_data->thread, thr_client_alarm))
{
#ifdef MAIN
printf("Warning: pthread_kill couldn't find thread!!!\n");
@@ -947,7 +947,7 @@ static void *signal_hand(void *arg __attribute__((unused)))
#endif
#endif /* OS2 */
printf("server alarm: %d thread alarm: %d\n",
- THR_SERVER_ALARM, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1);
+ THR_SERVER_ALARM, thr_client_alarm);
DBUG_PRINT("info",("Starting signal and alarm handling thread"));
for(;;)
{
@@ -1019,11 +1019,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
sigaddset(&set,SIGTSTP);
#endif
sigaddset(&set,THR_SERVER_ALARM);
- sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1);
+ sigdelset(&set, thr_client_alarm);
(void) pthread_sigmask(SIG_SETMASK,&set,NULL);
#ifdef NOT_USED
sigemptyset(&set);
- sigaddset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1);
+ sigaddset(&set, thr_client_alarm);
VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0));
#endif
#endif /* OS2 */
diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc
index 0091e1f40a0..a3b05d298c2 100644
--- a/sql/examples/ha_tina.cc
+++ b/sql/examples/ha_tina.cc
@@ -220,6 +220,18 @@ static int free_share(TINA_SHARE *share)
}
+bool tina_end()
+{
+ if (tina_init)
+ {
+ hash_free(&tina_open_tables);
+ VOID(pthread_mutex_destroy(&tina_mutex));
+ }
+ tina_init= 0;
+ return FALSE;
+}
+
+
/*
Finds the end of a line.
Currently only supports files written on a UNIX OS.
diff --git a/sql/examples/ha_tina.h b/sql/examples/ha_tina.h
index d8cd0fa9cfe..266db1bc1fe 100644
--- a/sql/examples/ha_tina.h
+++ b/sql/examples/ha_tina.h
@@ -136,3 +136,5 @@ class ha_tina: public handler
int find_current_row(byte *buf);
int chain_append();
};
+
+bool tina_end();
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index d61b3735c91..59b550572c3 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -605,6 +605,10 @@ void field_conv(Field *to,Field *from)
from->charset() == to->charset() &&
to->table->db_low_byte_first == from->table->db_low_byte_first)
{ // Identical fields
+#ifdef HAVE_purify
+ /* This may happen if one does 'UPDATE ... SET x=x' */
+ if (to->ptr != from->ptr)
+#endif
memcpy(to->ptr,from->ptr,to->pack_length());
return;
}
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 2e29d929352..2cec03a51db 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -91,6 +91,296 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
return;
}
+
+/*
+ Convert TABLE object to MyISAM key and column definition
+
+ SYNOPSIS
+ table2myisam()
+ table_arg in TABLE object.
+ keydef_out out MyISAM key definition.
+ recinfo_out out MyISAM column definition.
+ records_out out Number of fields.
+
+ DESCRIPTION
+ This function will allocate and initialize MyISAM key and column
+ definition for further use in mi_create or for a check for underlying
+ table conformance in merge engine.
+
+ RETURN VALUE
+ 0 OK
+ !0 error code
+*/
+
+int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
+ MI_COLUMNDEF **recinfo_out, uint *records_out)
+{
+ uint i, j, recpos, minpos, fieldpos, temp_length, length;
+ uint options= table_arg->db_options_in_use;
+ enum ha_base_keytype type= HA_KEYTYPE_BINARY;
+ KEY *pos;
+ MI_KEYDEF *keydef;
+ MI_COLUMNDEF *recinfo, *recinfo_pos;
+ HA_KEYSEG *keyseg;
+
+ DBUG_ENTER("table2myisam");
+ if (!(my_multi_malloc(MYF(MY_WME),
+ recinfo_out, (table_arg->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
+ keydef_out, table_arg->keys * sizeof(MI_KEYDEF),
+ &keyseg,
+ (table_arg->key_parts + table_arg->keys) * sizeof(HA_KEYSEG),
+ NullS)))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
+ keydef= *keydef_out;
+ recinfo= *recinfo_out;
+ pos= table_arg->key_info;
+ for (i= 0; i < table_arg->keys; i++, pos++)
+ {
+ keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
+ keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
+ (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
+ pos->algorithm;
+ keydef[i].seg= keyseg;
+ keydef[i].keysegs= pos->key_parts;
+ for (j= 0; j < pos->key_parts; j++)
+ {
+ keydef[i].seg[j].flag= pos->key_part[j].key_part_flag;
+ Field *field= pos->key_part[j].field;
+ type= field->key_type();
+
+ if (options & HA_OPTION_PACK_KEYS ||
+ (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
+ HA_SPACE_PACK_USED)))
+ {
+ if (pos->key_part[j].length > 8 &&
+ (type == HA_KEYTYPE_TEXT ||
+ type == HA_KEYTYPE_NUM ||
+ (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
+ {
+ /* No blobs here */
+ if (j == 0)
+ keydef[i].flag|= HA_PACK_KEY;
+ if (!(field->flags & ZEROFILL_FLAG) &&
+ (field->type() == FIELD_TYPE_STRING ||
+ field->type() == FIELD_TYPE_VAR_STRING ||
+ ((int) (pos->key_part[j].length - field->decimals())) >= 4))
+ keydef[i].seg[j].flag|= HA_SPACE_PACK;
+ }
+ else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
+ keydef[i].flag|= HA_BINARY_PACK_KEY;
+ }
+ keydef[i].seg[j].type= (int) type;
+ keydef[i].seg[j].start= pos->key_part[j].offset;
+ keydef[i].seg[j].length= pos->key_part[j].length;
+ keydef[i].seg[j].bit_start= keydef[i].seg[j].bit_end= 0;
+ keydef[i].seg[j].language= field->charset()->number;
+
+ if (field->null_ptr)
+ {
+ keydef[i].seg[j].null_bit= field->null_bit;
+ keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
+ (uchar*) table_arg->record[0]);
+ }
+ else
+ {
+ keydef[i].seg[j].null_bit= 0;
+ keydef[i].seg[j].null_pos= 0;
+ }
+ if (field->type() == FIELD_TYPE_BLOB ||
+ field->type() == FIELD_TYPE_GEOMETRY)
+ {
+ keydef[i].seg[j].flag|= HA_BLOB_PART;
+ /* save number of bytes used to pack length */
+ keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
+ table_arg->blob_ptr_size);
+ }
+ }
+ keyseg+= pos->key_parts;
+ }
+ if (table_arg->found_next_number_field)
+ keydef[table_arg->next_number_index].flag|= HA_AUTO_KEY;
+ recpos= 0;
+ recinfo_pos= recinfo;
+ while (recpos < (uint) table_arg->reclength)
+ {
+ Field **field, *found= 0;
+ minpos= table_arg->reclength;
+ length= 0;
+
+ for (field= table_arg->field; *field; field++)
+ {
+ if ((fieldpos= (*field)->offset()) >= recpos &&
+ fieldpos <= minpos)
+ {
+ /* skip null fields */
+ if (!(temp_length= (*field)->pack_length()))
+ continue; /* Skip null-fields */
+ if (! found || fieldpos < minpos ||
+ (fieldpos == minpos && temp_length < length))
+ {
+ minpos= fieldpos;
+ found= *field;
+ length= temp_length;
+ }
+ }
+ }
+ DBUG_PRINT("loop", ("found: %lx recpos: %d minpos: %d length: %d",
+ (long) found, recpos, minpos, length));
+ if (recpos != minpos)
+ { // Reserved space (Null bits?)
+ bzero((char*) recinfo_pos, sizeof(*recinfo_pos));
+ recinfo_pos->type= (int) FIELD_NORMAL;
+ recinfo_pos++->length= (uint16) (minpos - recpos);
+ }
+ if (!found)
+ break;
+
+ if (found->flags & BLOB_FLAG)
+ {
+ recinfo_pos->type= (int) FIELD_BLOB;
+ }
+ else if (!(options & HA_OPTION_PACK_RECORD))
+ recinfo_pos->type= (int) FIELD_NORMAL;
+ else if (found->zero_pack())
+ recinfo_pos->type= (int) FIELD_SKIP_ZERO;
+ else
+ recinfo_pos->type= (int) ((length <= 3 ||
+ (found->flags & ZEROFILL_FLAG)) ?
+ FIELD_NORMAL :
+ found->type() == FIELD_TYPE_STRING ||
+ found->type() == FIELD_TYPE_VAR_STRING ?
+ FIELD_SKIP_ENDSPACE :
+ FIELD_SKIP_PRESPACE);
+ if (found->null_ptr)
+ {
+ recinfo_pos->null_bit= found->null_bit;
+ recinfo_pos->null_pos= (uint) (found->null_ptr -
+ (uchar*) table_arg->record[0]);
+ }
+ else
+ {
+ recinfo_pos->null_bit= 0;
+ recinfo_pos->null_pos= 0;
+ }
+ (recinfo_pos++)->length= (uint16) length;
+ recpos= minpos + length;
+ DBUG_PRINT("loop", ("length: %d type: %d",
+ recinfo_pos[-1].length,recinfo_pos[-1].type));
+ }
+ *records_out= (uint) (recinfo_pos - recinfo);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Check for underlying table conformance
+
+ SYNOPSIS
+ check_definition()
+ t1_keyinfo in First table key definition
+ t1_recinfo in First table record definition
+ t1_keys in Number of keys in first table
+ t1_recs in Number of records in first table
+ t2_keyinfo in Second table key definition
+ t2_recinfo in Second table record definition
+ t2_keys in Number of keys in second table
+ t2_recs in Number of records in second table
+ strict in Strict check switch
+
+ DESCRIPTION
+ This function compares two MyISAM definitions. By intention it was done
+ to compare merge table definition against underlying table definition.
+ It may also be used to compare dot-frm and MYI definitions of MyISAM
+ table as well to compare different MyISAM table definitions.
+
+ For merge table it is not required that number of keys in merge table
+ must exactly match number of keys in underlying table. When calling this
+ function for underlying table conformance check, 'strict' flag must be
+ set to false, and converted merge definition must be passed as t1_*.
+
+ Otherwise 'strict' flag must be set to 1 and it is not required to pass
+ converted dot-frm definition as t1_*.
+
+ RETURN VALUE
+ 0 - Equal definitions.
+ 1 - Different definitions.
+*/
+
+int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
+ uint t1_keys, uint t1_recs,
+ MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
+ uint t2_keys, uint t2_recs, bool strict)
+{
+ uint i, j;
+ DBUG_ENTER("check_definition");
+ if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
+ {
+ DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
+ t1_keys, t2_keys));
+ DBUG_RETURN(1);
+ }
+ if (t1_recs != t2_recs)
+ {
+ DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u",
+ t1_recs, t2_recs));
+ DBUG_RETURN(1);
+ }
+ for (i= 0; i < t1_keys; i++)
+ {
+ HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
+ HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
+ if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs ||
+ t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg)
+ {
+ DBUG_PRINT("error", ("Key %d has different definition", i));
+ DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d",
+ t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg));
+ DBUG_PRINT("error", ("t2_keysegs=%d, t2_key_alg=%d",
+ t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg));
+ DBUG_RETURN(1);
+ }
+ for (j= t1_keyinfo[i].keysegs; j--;)
+ {
+ if (t1_keysegs[j].type != t2_keysegs[j].type ||
+ t1_keysegs[j].language != t2_keysegs[j].language ||
+ t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
+ t1_keysegs[j].length != t2_keysegs[j].length)
+ {
+ DBUG_PRINT("error", ("Key segment %d (key %d) has different "
+ "definition", j, i));
+ DBUG_PRINT("error", ("t1_type=%d, t1_language=%d, t1_null_bit=%d, "
+ "t1_length=%d",
+ t1_keysegs[j].type, t1_keysegs[j].language,
+ t1_keysegs[j].null_bit, t1_keysegs[j].length));
+ DBUG_PRINT("error", ("t2_type=%d, t2_language=%d, t2_null_bit=%d, "
+ "t2_length=%d",
+ t2_keysegs[j].type, t2_keysegs[j].language,
+ t2_keysegs[j].null_bit, t2_keysegs[j].length));
+
+ DBUG_RETURN(1);
+ }
+ }
+ }
+ for (i= 0; i < t1_recs; i++)
+ {
+ MI_COLUMNDEF *t1_rec= &t1_recinfo[i];
+ MI_COLUMNDEF *t2_rec= &t2_recinfo[i];
+ if (t1_rec->type != t2_rec->type ||
+ t1_rec->length != t2_rec->length ||
+ t1_rec->null_bit != t2_rec->null_bit)
+ {
+ DBUG_PRINT("error", ("Field %d has different definition", i));
+ DBUG_PRINT("error", ("t1_type=%d, t1_length=%d, t1_null_bit=%d",
+ t1_rec->type, t1_rec->length, t1_rec->null_bit));
+ DBUG_PRINT("error", ("t2_type=%d, t2_length=%d, t2_null_bit=%d",
+ t2_rec->type, t2_rec->length, t2_rec->null_bit));
+ DBUG_RETURN(1);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
extern "C" {
volatile my_bool *killed_ptr(MI_CHECK *param)
@@ -1345,181 +1635,30 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
HA_CREATE_INFO *info)
{
int error;
- uint i,j,recpos,minpos,fieldpos,temp_length,length, create_flags= 0;
- bool found_real_auto_increment=0;
- enum ha_base_keytype type;
+ uint create_flags= 0, options= table_arg->db_options_in_use, records;
char buff[FN_REFLEN];
- KEY *pos;
MI_KEYDEF *keydef;
- MI_COLUMNDEF *recinfo,*recinfo_pos;
- HA_KEYSEG *keyseg;
- uint options=table_arg->db_options_in_use;
- DBUG_ENTER("ha_myisam::create");
-
- type=HA_KEYTYPE_BINARY; // Keep compiler happy
- if (!(my_multi_malloc(MYF(MY_WME),
- &recinfo,(table_arg->fields*2+2)*sizeof(MI_COLUMNDEF),
- &keydef, table_arg->keys*sizeof(MI_KEYDEF),
- &keyseg,
- ((table_arg->key_parts + table_arg->keys) *
- sizeof(HA_KEYSEG)),
- NullS)))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
-
- pos=table_arg->key_info;
- for (i=0; i < table_arg->keys ; i++, pos++)
- {
- keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
- keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
- (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
- pos->algorithm;
- keydef[i].seg=keyseg;
- keydef[i].keysegs=pos->key_parts;
- for (j=0 ; j < pos->key_parts ; j++)
- {
- keydef[i].seg[j].flag=pos->key_part[j].key_part_flag;
- Field *field=pos->key_part[j].field;
- type=field->key_type();
-
- if (options & HA_OPTION_PACK_KEYS ||
- (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
- HA_SPACE_PACK_USED)))
- {
- if (pos->key_part[j].length > 8 &&
- (type == HA_KEYTYPE_TEXT ||
- type == HA_KEYTYPE_NUM ||
- (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
- {
- /* No blobs here */
- if (j == 0)
- keydef[i].flag|=HA_PACK_KEY;
- if (!(field->flags & ZEROFILL_FLAG) &&
- (field->type() == FIELD_TYPE_STRING ||
- field->type() == FIELD_TYPE_VAR_STRING ||
- ((int) (pos->key_part[j].length - field->decimals()))
- >= 4))
- keydef[i].seg[j].flag|=HA_SPACE_PACK;
- }
- else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
- keydef[i].flag|= HA_BINARY_PACK_KEY;
- }
- keydef[i].seg[j].type= (int) type;
- keydef[i].seg[j].start= pos->key_part[j].offset;
- keydef[i].seg[j].length= pos->key_part[j].length;
- keydef[i].seg[j].bit_start=keydef[i].seg[j].bit_end=0;
- keydef[i].seg[j].language = field->charset()->number;
-
- if (field->null_ptr)
- {
- keydef[i].seg[j].null_bit=field->null_bit;
- keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
- (uchar*) table_arg->record[0]);
- }
- else
- {
- keydef[i].seg[j].null_bit=0;
- keydef[i].seg[j].null_pos=0;
- }
- if (field->type() == FIELD_TYPE_BLOB ||
- field->type() == FIELD_TYPE_GEOMETRY)
- {
- keydef[i].seg[j].flag|=HA_BLOB_PART;
- /* save number of bytes used to pack length */
- keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
- table_arg->blob_ptr_size);
- }
- }
- keyseg+=pos->key_parts;
- }
-
- if (table_arg->found_next_number_field)
- {
- keydef[table_arg->next_number_index].flag|= HA_AUTO_KEY;
- found_real_auto_increment= table_arg->next_number_key_offset == 0;
- }
-
- recpos=0; recinfo_pos=recinfo;
- while (recpos < (uint) table_arg->reclength)
- {
- Field **field,*found=0;
- minpos=table_arg->reclength; length=0;
-
- for (field=table_arg->field ; *field ; field++)
- {
- if ((fieldpos=(*field)->offset()) >= recpos &&
- fieldpos <= minpos)
- {
- /* skip null fields */
- if (!(temp_length= (*field)->pack_length()))
- continue; /* Skip null-fields */
- if (! found || fieldpos < minpos ||
- (fieldpos == minpos && temp_length < length))
- {
- minpos=fieldpos; found= *field; length=temp_length;
- }
- }
- }
- DBUG_PRINT("loop",("found: %lx recpos: %d minpos: %d length: %d",
- found,recpos,minpos,length));
- if (recpos != minpos)
- { // Reserved space (Null bits?)
- bzero((char*) recinfo_pos,sizeof(*recinfo_pos));
- recinfo_pos->type=(int) FIELD_NORMAL;
- recinfo_pos++->length= (uint16) (minpos-recpos);
- }
- if (! found)
- break;
-
- if (found->flags & BLOB_FLAG)
- {
- recinfo_pos->type= (int) FIELD_BLOB;
- }
- else if (!(options & HA_OPTION_PACK_RECORD))
- recinfo_pos->type= (int) FIELD_NORMAL;
- else if (found->zero_pack())
- recinfo_pos->type= (int) FIELD_SKIP_ZERO;
- else
- recinfo_pos->type= (int) ((length <= 3 ||
- (found->flags & ZEROFILL_FLAG)) ?
- FIELD_NORMAL :
- found->type() == FIELD_TYPE_STRING ||
- found->type() == FIELD_TYPE_VAR_STRING ?
- FIELD_SKIP_ENDSPACE :
- FIELD_SKIP_PRESPACE);
- if (found->null_ptr)
- {
- recinfo_pos->null_bit=found->null_bit;
- recinfo_pos->null_pos= (uint) (found->null_ptr-
- (uchar*) table_arg->record[0]);
- }
- else
- {
- recinfo_pos->null_bit=0;
- recinfo_pos->null_pos=0;
- }
- (recinfo_pos++) ->length=(uint16) length;
- recpos=minpos+length;
- DBUG_PRINT("loop",("length: %d type: %d",
- recinfo_pos[-1].length,recinfo_pos[-1].type));
-
- }
+ MI_COLUMNDEF *recinfo;
MI_CREATE_INFO create_info;
- bzero((char*) &create_info,sizeof(create_info));
- create_info.max_rows=table_arg->max_rows;
- create_info.reloc_rows=table_arg->min_rows;
- create_info.with_auto_increment=found_real_auto_increment;
- create_info.auto_increment=(info->auto_increment_value ?
- info->auto_increment_value -1 :
- (ulonglong) 0);
+ DBUG_ENTER("ha_myisam::create");
+ if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
+ DBUG_RETURN(error); /* purecov: inspected */
+ bzero((char*) &create_info, sizeof(create_info));
+ create_info.max_rows= table_arg->max_rows;
+ create_info.reloc_rows= table_arg->min_rows;
+ create_info.with_auto_increment= table_arg->next_number_key_offset == 0;
+ create_info.auto_increment= (info->auto_increment_value ?
+ info->auto_increment_value -1 :
+ (ulonglong) 0);
create_info.data_file_length= ((ulonglong) table_arg->max_rows *
- table_arg->avg_row_length);
- create_info.raid_type=info->raid_type;
+ table_arg->avg_row_length);
+ create_info.raid_type= info->raid_type;
create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks :
- RAID_DEFAULT_CHUNKS);
- create_info.raid_chunksize=(info->raid_chunksize ? info->raid_chunksize :
- RAID_DEFAULT_CHUNKSIZE);
+ RAID_DEFAULT_CHUNKS);
+ create_info.raid_chunksize= (info->raid_chunksize ? info->raid_chunksize :
+ RAID_DEFAULT_CHUNKSIZE);
create_info.data_file_name= info->data_file_name;
- create_info.index_file_name=info->index_file_name;
+ create_info.index_file_name= info->index_file_name;
if (info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= HA_CREATE_TMP_TABLE;
@@ -1531,13 +1670,13 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
create_flags|= HA_CREATE_DELAY_KEY_WRITE;
/* TODO: Check that the following fn_format is really needed */
- error=mi_create(fn_format(buff,name,"","",2+4),
- table_arg->keys,keydef,
- (uint) (recinfo_pos-recinfo), recinfo,
- 0, (MI_UNIQUEDEF*) 0,
- &create_info, create_flags);
-
- my_free((gptr) recinfo,MYF(0));
+ error= mi_create(fn_format(buff, name, "", "",
+ MY_UNPACK_FILENAME|MY_REPLACE_EXT),
+ table_arg->keys, keydef,
+ records, recinfo,
+ 0, (MI_UNIQUEDEF*) 0,
+ &create_info, create_flags);
+ my_free((gptr) recinfo, MYF(0));
DBUG_RETURN(error);
}
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 1fed5cc35f0..53923add49a 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -32,6 +32,13 @@
** MyISAM MERGE tables
*****************************************************************************/
+extern int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
+ MI_COLUMNDEF **recinfo_out, uint *records_out);
+extern int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
+ uint t1_keys, uint t1_recs,
+ MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
+ uint t2_keys, uint t2_recs, bool strict);
+
const char **ha_myisammrg::bas_ext() const
{ static const char *ext[]= { ".MRG", NullS }; return ext; }
@@ -49,6 +56,12 @@ const char *ha_myisammrg::index_type(uint key_number)
int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
{
+ MI_KEYDEF *keyinfo;
+ MI_COLUMNDEF *recinfo;
+ MYRG_TABLE *u_table;
+ uint recs;
+ uint keys= table->keys;
+ int error;
char name_buff[FN_REFLEN];
DBUG_PRINT("info", ("ha_myisammrg::open"));
@@ -69,20 +82,45 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
if (table->reclength != mean_rec_length && mean_rec_length)
{
- DBUG_PRINT("error",("reclength: %d mean_rec_length: %d",
+ DBUG_PRINT("error",("reclength: %d mean_rec_length: %lu",
table->reclength, mean_rec_length));
+ error= HA_ERR_WRONG_MRG_TABLE_DEF;
goto err;
}
+ if ((error= table2myisam(table, &keyinfo, &recinfo, &recs)))
+ {
+ /* purecov: begin inspected */
+ DBUG_PRINT("error", ("Failed to convert TABLE object to MyISAM "
+ "key and column definition"));
+ goto err;
+ /* purecov: end */
+ }
+ for (u_table= file->open_tables; u_table < file->end_table; u_table++)
+ {
+ if (check_definition(keyinfo, recinfo, keys, recs,
+ u_table->table->s->keyinfo, u_table->table->s->rec,
+ u_table->table->s->base.keys,
+ u_table->table->s->base.fields, false))
+ {
+ my_free((gptr) recinfo, MYF(0));
+ error= HA_ERR_WRONG_MRG_TABLE_DEF;
+ goto err;
+ }
+ }
+ my_free((gptr) recinfo, MYF(0));
#if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4
/* Merge table has more than 2G rows */
if (table->crashed)
+ {
+ error= HA_ERR_WRONG_MRG_TABLE_DEF;
goto err;
+ }
#endif
return (0);
err:
myrg_close(file);
file=0;
- return (my_errno= HA_ERR_WRONG_MRG_TABLE_DEF);
+ return (my_errno= error);
}
int ha_myisammrg::close(void)
diff --git a/sql/handler.cc b/sql/handler.cc
index 0476b855e3c..82fff72f0da 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -341,6 +341,10 @@ int ha_panic(enum ha_panic_function flag)
if (have_archive_db == SHOW_OPTION_YES)
error|= archive_db_end();
#endif
+#ifdef HAVE_CSV_DB
+ if (have_csv_db == SHOW_OPTION_YES)
+ error|= tina_end();
+#endif
return error;
} /* ha_panic */
diff --git a/sql/lock.cc b/sql/lock.cc
index ab4a81034ba..3b2b2857f65 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -528,7 +528,7 @@ int mysql_lock_have_duplicate(THD *thd, TABLE *table, TABLE_LIST *tables)
for (; tables; tables= tables->next)
{
table2= tables->table;
- if (table2->tmp_table == TMP_TABLE)
+ if (table2->tmp_table == TMP_TABLE || table == table2)
continue;
/* All tables in list must be in lock. */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 3488ccf3607..460bf2e7308 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -451,6 +451,7 @@ pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped,
pthread_cond_t COND_thread_cache,COND_flush_thread_cache;
pthread_t signal_thread;
pthread_attr_t connection_attrib;
+static uint thr_kill_signal;
/* replication parameters, if master_host is not NULL, we are a slave */
uint master_port= MYSQL_PORT, master_connect_retry = 60;
@@ -582,7 +583,6 @@ static void clean_up_mutexes(void);
static void wait_for_signal_thread_to_end(void);
static int test_if_case_insensitive(const char *dir_name);
static void create_pid_file();
-static uint get_thread_lib(void);
#ifndef EMBEDDED_LIBRARY
/****************************************************************************
@@ -622,8 +622,7 @@ static void close_connections(void)
DBUG_PRINT("info",("Waiting for select thread"));
#ifndef DONT_USE_THR_ALARM
- if (pthread_kill(select_thread,
- thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1))
+ if (pthread_kill(select_thread, thr_client_alarm))
break; // allready dead
#endif
set_timespec(abstime, 2);
@@ -1071,7 +1070,10 @@ void clean_up(bool print_message)
#endif
#ifdef HAVE_OPENSSL
if (ssl_acceptor_fd)
+ {
+ SSL_CTX_free(ssl_acceptor_fd->ssl_context);
my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
+ }
#endif /* HAVE_OPENSSL */
#ifdef USE_REGEX
my_regex_end();
@@ -2047,8 +2049,7 @@ static void init_signals(void)
if (test_flags & TEST_SIGINT)
{
- my_sigset(thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2,
- end_thread_signal);
+ my_sigset(thr_kill_signal, end_thread_signal);
}
my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
@@ -2108,10 +2109,10 @@ static void init_signals(void)
if (test_flags & TEST_SIGINT)
{
// May be SIGINT
- sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2);
+ sigdelset(&set, thr_kill_signal);
}
// For alarms
- sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1);
+ sigdelset(&set, thr_client_alarm);
sigprocmask(SIG_SETMASK,&set,NULL);
pthread_sigmask(SIG_SETMASK,&set,NULL);
DBUG_VOID_RETURN;
@@ -2167,7 +2168,7 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
*/
init_thr_alarm(max_connections +
global_system_variables.max_insert_delayed_threads + 10);
- if (thd_lib_detected != THD_LIB_LT && test_flags & TEST_SIGINT)
+ if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
{
(void) sigemptyset(&set); // Setup up SIGINT for debug
(void) sigaddset(&set,SIGINT); // For debugging
@@ -3140,6 +3141,13 @@ int main(int argc, char **argv)
MY_INIT(argv[0]); // init my_sys library & pthreads
+ /* Set signal used to kill MySQL */
+#if defined(SIGUSR2)
+ thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
+#else
+ thr_kill_signal= SIGINT;
+#endif
+
#ifdef _CUSTOMSTARTUPCONFIG_
if (_cust_check_startup())
{
@@ -3148,7 +3156,6 @@ int main(int argc, char **argv)
}
#endif
- thd_lib_detected= get_thread_lib();
if (init_common_variables(MYSQL_CONFIG_NAME,
argc, argv, load_default_groups))
unireg_abort(1); // Will do exit
@@ -7019,22 +7026,6 @@ static void create_pid_file()
}
-static uint get_thread_lib(void)
-{
- char buff[64];
-
-#ifdef _CS_GNU_LIBPTHREAD_VERSION
- confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
-
- if (!strncasecmp(buff, "NPTL", 4))
- return THD_LIB_NPTL;
- else if (!strncasecmp(buff, "linuxthreads", 12))
- return THD_LIB_LT;
-#endif
- return THD_LIB_OTHER;
-}
-
-
/*****************************************************************************
Instantiate templates
*****************************************************************************/
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 20df3b3ab4a..7ed1b48d7aa 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -23,8 +23,6 @@
#include "mysql_priv.h"
#include "sql_select.h"
-static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields);
-
/* Return 0 if row hasn't changed */
static bool compare_record(TABLE *table, ulong query_id)
@@ -846,27 +844,69 @@ int multi_update::prepare(List<Item> &not_used_values,
for (i=0 ; i < table_count ; i++)
set_if_bigger(max_fields, fields_for_table[i]->elements);
copy_field= new Copy_field[max_fields];
+ DBUG_RETURN(thd->is_fatal_error != 0);
+}
- /*
- Mark all copies of tables that are updates to ensure that
- init_read_record() will not try to enable a cache on them
- The problem is that for queries like
+/*
+ Check if table is safe to update on fly
- UPDATE t1, t1 AS t2 SET t1.b=t2.c WHERE t1.a=t2.a;
+ SYNOPSIS
+ safe_update_on_fly()
+ thd Thread handler
+ join_tab How table is used in join
+ all_tables List of tables
+ fields Fields that are updated
- the row buffer may contain things that doesn't match what is on disk
- which will cause an error when reading a row.
- (This issue is mostly relevent for MyISAM tables)
- */
- for (table_ref= all_tables; table_ref; table_ref=table_ref->next)
- {
- TABLE *table=table_ref->table;
- if ((tables_to_update & table->map) &&
- mysql_lock_have_duplicate(thd, table, update_tables))
- table->no_cache= 1; // Disable row cache
+ NOTES
+ We can update the first table in join on the fly if we know that
+ a row in this table will never be read twice. This is true under
+ the following conditions:
+
+ - We are doing a table scan and the data is in a separate file (MyISAM) or
+ if we don't update a clustered key.
+
+ - We are doing a range scan and we don't update the scan key or
+ the primary key for a clustered table handler.
+
+ - Table is not joined to itself.
+
+ WARNING
+ This code is a bit dependent of how make_join_readinfo() works.
+
+ RETURN
+ 0 Not safe to update
+ 1 Safe to update
+*/
+
+static bool safe_update_on_fly(THD *thd, JOIN_TAB *join_tab,
+ TABLE_LIST *all_tables, List<Item> *fields)
+{
+ TABLE *table= join_tab->table;
+ /* First check if a table is not joined to itself. */
+ if (mysql_lock_have_duplicate(thd, table, all_tables))
+ return 0;
+ switch (join_tab->type) {
+ case JT_SYSTEM:
+ case JT_CONST:
+ case JT_EQ_REF:
+ return 1; // At most one matching row
+ case JT_REF:
+ return !check_if_key_used(table, join_tab->ref.key, *fields);
+ case JT_ALL:
+ /* If range search on index */
+ if (join_tab->quick)
+ return !check_if_key_used(table, join_tab->quick->index,
+ *fields);
+ /* If scanning in clustered key */
+ if ((table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
+ table->primary_key < MAX_KEY)
+ return !check_if_key_used(table, table->primary_key, *fields);
+ return 1;
+ default:
+ break; // Avoid compler warning
}
- DBUG_RETURN(thd->is_fatal_error != 0);
+ return 0;
}
@@ -905,7 +945,7 @@ multi_update::initialize_tables(JOIN *join)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
if (table == main_table) // First table in join
{
- if (safe_update_on_fly(join->join_tab, &temp_fields))
+ if (safe_update_on_fly(thd, join->join_tab, all_tables, &temp_fields))
{
table_to_update= main_table; // Update table on the fly
continue;
@@ -951,59 +991,6 @@ multi_update::initialize_tables(JOIN *join)
DBUG_RETURN(0);
}
-/*
- Check if table is safe to update on fly
-
- SYNOPSIS
- safe_update_on_fly
- join_tab How table is used in join
- fields Fields that are updated
-
- NOTES
- We can update the first table in join on the fly if we know that
- a row in this tabel will never be read twice. This is true under
- the folloing conditions:
-
- - We are doing a table scan and the data is in a separate file (MyISAM) or
- if we don't update a clustered key.
-
- - We are doing a range scan and we don't update the scan key or
- the primary key for a clustered table handler.
-
- WARNING
- This code is a bit dependent of how make_join_readinfo() works.
-
- RETURN
- 0 Not safe to update
- 1 Safe to update
-*/
-
-static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields)
-{
- TABLE *table= join_tab->table;
- switch (join_tab->type) {
- case JT_SYSTEM:
- case JT_CONST:
- case JT_EQ_REF:
- return 1; // At most one matching row
- case JT_REF:
- return !check_if_key_used(table, join_tab->ref.key, *fields);
- case JT_ALL:
- /* If range search on index */
- if (join_tab->quick)
- return !check_if_key_used(table, join_tab->quick->index,
- *fields);
- /* If scanning in clustered key */
- if ((table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
- table->primary_key < MAX_KEY)
- return !check_if_key_used(table, table->primary_key, *fields);
- return 1;
- default:
- break; // Avoid compler warning
- }
- return 0;
-}
-
multi_update::~multi_update()
{
diff --git a/sql/table.cc b/sql/table.cc
index aff1e6d11f6..dab2f978327 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -373,6 +373,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
memcpy(comment_pos, disk_buff+read_length-com_length, com_length);
fix_type_pointers(&int_array,&outparam->fieldnames,1,&names);
+ if (outparam->fieldnames.count != outparam->fields)
+ goto err_not_open;
fix_type_pointers(&int_array,outparam->intervals,interval_count,
&names);
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 46306cf48bb..1ac5d96d158 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -289,6 +289,8 @@ new_VioSSLConnectorFd(const char* key_file,
DBUG_RETURN(ptr);
ctor_failure:
DBUG_PRINT("exit", ("there was an error"));
+ if (ptr->ssl_context)
+ SSL_CTX_free(ptr->ssl_context);
my_free((gptr)ptr,MYF(0));
DBUG_RETURN(0);
}
@@ -390,6 +392,8 @@ new_VioSSLAcceptorFd(const char *key_file,
ctor_failure:
DBUG_PRINT("exit", ("there was an error"));
+ if (ptr->ssl_context)
+ SSL_CTX_free(ptr->ssl_context);
my_free((gptr) ptr,MYF(0));
DBUG_RETURN(0);
}