summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorknielsen@mysql.com <>2006-04-24 10:28:31 +0200
committerknielsen@mysql.com <>2006-04-24 10:28:31 +0200
commitafeb3c06f7b5790c119e1e6516e870d7207f3fbe (patch)
tree2f9e65cb329d9e676087e17b954cba671e1228e7
parent408599af843730e73b95de55ade0bce3e211fd71 (diff)
parentf7394c26f53d40ccb432426e0a67b83218b6b82f (diff)
downloadmariadb-git-afeb3c06f7b5790c119e1e6516e870d7207f3fbe.tar.gz
Merge knielsen@10.100.52.19:/usr/local/mysql/mysql-4.1-mtr-fix
into mysql.com:/data0/knielsen/mysql-4.1-mtr-fix
-rw-r--r--innobase/dict/dict0dict.c35
-rw-r--r--innobase/dict/dict0mem.c15
-rw-r--r--innobase/include/dict0dict.h9
-rw-r--r--innobase/include/dict0mem.h7
-rw-r--r--innobase/include/univ.i3
-rw-r--r--innobase/row/row0mysql.c14
-rw-r--r--myisam/mi_packrec.c14
-rw-r--r--myisam/myisam_ftdump.c14
-rw-r--r--mysql-test/r/case.result8
-rw-r--r--mysql-test/r/ctype_ucs.result12
-rw-r--r--mysql-test/r/func_compress.result7
-rw-r--r--mysql-test/r/func_gconcat.result10
-rw-r--r--mysql-test/r/key_cache.result42
-rw-r--r--mysql-test/r/order_by.result32
-rw-r--r--mysql-test/r/rpl_deadlock.result105
-rw-r--r--mysql-test/r/rpl_relayrotate.result7
-rw-r--r--mysql-test/r/rpl_temporary.result14
-rw-r--r--mysql-test/t/case.test11
-rw-r--r--mysql-test/t/ctype_ucs.test8
-rw-r--r--mysql-test/t/disabled.def3
-rw-r--r--mysql-test/t/func_compress.test9
-rw-r--r--mysql-test/t/func_gconcat.test11
-rw-r--r--mysql-test/t/key_cache.test41
-rw-r--r--mysql-test/t/order_by.test14
-rw-r--r--mysql-test/t/rpl_deadlock.test16
-rw-r--r--mysql-test/t/rpl_relayrotate.test8
-rw-r--r--mysql-test/t/rpl_temporary.test28
-rw-r--r--mysql-test/t/rpl_until.test4
-rw-r--r--mysys/mf_keycache.c12
-rw-r--r--ndb/src/kernel/SimBlockList.cpp4
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp5
-rw-r--r--sql/item_cmpfunc.cc23
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_strfunc.cc1
-rw-r--r--sql/item_sum.h7
-rw-r--r--sql/item_timefunc.cc28
-rw-r--r--sql/item_timefunc.h2
-rw-r--r--sql/lock.cc54
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/sql_base.cc160
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_parse.cc74
-rw-r--r--sql/sql_select.cc8
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_yacc.yy24
-rw-r--r--sql/unireg.h1
46 files changed, 790 insertions, 121 deletions
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 093df5118af..4b23ce047b2 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -1377,6 +1377,38 @@ dict_col_reposition_in_cache(
HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col);
}
+/********************************************************************
+If the given column name is reserved for InnoDB system columns, return
+TRUE.*/
+
+ibool
+dict_col_name_is_reserved(
+/*======================*/
+ /* out: TRUE if name is reserved */
+ const char* name) /* in: column name */
+{
+ /* This check reminds that if a new system column is added to
+ the program, it should be dealt with here. */
+#if DATA_N_SYS_COLS != 4
+#error "DATA_N_SYS_COLS != 4"
+#endif
+
+ static const char* reserved_names[] = {
+ "DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR", "DB_MIX_ID"
+ };
+
+ ulint i;
+
+ for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
+ if (strcmp(name, reserved_names[i]) == 0) {
+
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
/**************************************************************************
Adds an index to the dictionary cache. */
@@ -2160,8 +2192,9 @@ dict_foreign_error_report(
fputs(msg, file);
fputs(" Constraint:\n", file);
dict_print_info_on_foreign_key_in_create_format(file, NULL, fk);
+ putc('\n', file);
if (fk->foreign_index) {
- fputs("\nThe index in the foreign key in table is ", file);
+ fputs("The index in the foreign key in table is ", file);
ut_print_name(file, NULL, fk->foreign_index->name);
fputs(
"\nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n"
diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c
index 1d45585aac1..5a2b2e005d0 100644
--- a/innobase/dict/dict0mem.c
+++ b/innobase/dict/dict0mem.c
@@ -94,6 +94,21 @@ dict_mem_table_create(
return(table);
}
+/********************************************************************
+Free a table memory object. */
+
+void
+dict_mem_table_free(
+/*================*/
+ dict_table_t* table) /* in: table */
+{
+ ut_ad(table);
+ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+
+ mutex_free(&(table->autoinc_mutex));
+ mem_heap_free(table->heap);
+}
+
/**************************************************************************
Creates a cluster memory object. */
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index bf1382e8bb2..1226055e135 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -98,6 +98,15 @@ ulint
dict_col_get_clust_pos(
/*===================*/
dict_col_t* col);
+/********************************************************************
+If the given column name is reserved for InnoDB system columns, return
+TRUE. */
+
+ibool
+dict_col_name_is_reserved(
+/*======================*/
+ /* out: TRUE if name is reserved */
+ const char* name); /* in: column name */
/************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index 1e496a25477..5c3a4ed76d4 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -55,6 +55,13 @@ dict_mem_table_create(
is ignored if the table is made
a member of a cluster */
ulint n_cols); /* in: number of columns */
+/********************************************************************
+Free a table memory object. */
+
+void
+dict_mem_table_free(
+/*================*/
+ dict_table_t* table); /* in: table */
/**************************************************************************
Creates a cluster memory object. */
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index 625978ffc38..6939edbcaf8 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -242,6 +242,9 @@ contains the sum of the following flag and the locally stored len. */
#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE)
+/* Compile-time constant of the given array's size. */
+#define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
#include <stdio.h>
#include "ut0dbg.h"
#include "ut0ut.h"
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index ba50e6a3511..23d019b6f78 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -1474,6 +1474,7 @@ row_create_table_for_mysql(
const char* table_name;
ulint table_name_len;
ulint err;
+ ulint i;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
#ifdef UNIV_SYNC_DEBUG
@@ -1510,6 +1511,19 @@ row_create_table_for_mysql(
return(DB_ERROR);
}
+ /* Check that no reserved column names are used. */
+ for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
+ dict_col_t* col = dict_table_get_nth_col(table, i);
+
+ if (dict_col_name_is_reserved(col->name)) {
+
+ dict_mem_table_free(table);
+ trx_commit_for_mysql(trx);
+
+ return(DB_ERROR);
+ }
+ }
+
trx_start_if_not_started(trx);
if (row_mysql_is_recovered_tmp_table(table->name)) {
diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c
index 322420b71db..bd2d162d100 100644
--- a/myisam/mi_packrec.c
+++ b/myisam/mi_packrec.c
@@ -1158,16 +1158,22 @@ my_bool _mi_memmap_file(MI_INFO *info)
MYISAM_SHARE *share=info->s;
DBUG_ENTER("mi_memmap_file");
- if (!info->s->file_map)
+ if (!share->file_map)
{
+ my_off_t data_file_length= share->state.state.data_file_length;
+ if (data_file_length > (my_off_t) (~((size_t) 0)) - MEMMAP_EXTRA_MARGIN)
+ {
+ DBUG_PRINT("warning", ("File is too large for mmap"));
+ DBUG_RETURN(0);
+ }
if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) <
- share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN)
+ data_file_length + MEMMAP_EXTRA_MARGIN)
{
DBUG_PRINT("warning",("File isn't extended for memmap"));
DBUG_RETURN(0);
}
file_map=(byte*)
- mmap(0,share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN,PROT_READ,
+ mmap(0, data_file_length + MEMMAP_EXTRA_MARGIN, PROT_READ,
MAP_SHARED | MAP_NORESERVE,info->dfile,0L);
if (file_map == (byte*) MAP_FAILED)
{
@@ -1175,7 +1181,7 @@ my_bool _mi_memmap_file(MI_INFO *info)
my_errno=errno;
DBUG_RETURN(0);
}
- info->s->file_map=file_map;
+ share->file_map= file_map;
}
info->opt_flag|= MEMMAP_USED;
info->read_record=share->read_record=_mi_read_mempack_record;
diff --git a/myisam/myisam_ftdump.c b/myisam/myisam_ftdump.c
index 28aac0a8ecf..809d7bcca89 100644
--- a/myisam/myisam_ftdump.c
+++ b/myisam/myisam_ftdump.c
@@ -34,20 +34,20 @@ static uint lengths[256];
static struct my_option my_long_options[] =
{
- {"dump", 'd', "Dump index (incl. data offsets and word weights).",
+ {"help", 'h', "Display help and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"stats", 's', "Report global stats.",
+ {"help", '?', "Synonym for -h.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"verbose", 'v', "Be verbose.",
- (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"count", 'c', "Calculate per-word stats (counts and global weights).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"length", 'l', "Report length distribution.",
+ {"dump", 'd', "Dump index (incl. data offsets and word weights).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"help", 'h', "Display help and exit.",
+ {"length", 'l', "Report length distribution.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"help", '?', "Synonym for -h.",
+ {"stats", 's', "Report global stats.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"verbose", 'v', "Be verbose.",
+ (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index fb0bc19a67e..a5495d0fc3e 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -169,3 +169,11 @@ SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END;
case+union+test
case+union+test
nobug
+create table t1(a float, b int default 3);
+insert into t1 (a) values (2), (11), (8);
+select min(a), min(case when 1=1 then a else NULL end),
+min(case when 1!=1 then NULL else a end)
+from t1 where b=3 group by b;
+min(a) min(case when 1=1 then a else NULL end) min(case when 1!=1 then NULL else a end)
+2 2 2
+drop table t1;
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 0e12ec88662..8869604b128 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -666,6 +666,18 @@ Warnings:
Warning 1265 Data truncated for column 'Field1' at row 1
DROP TABLE t1;
SET NAMES latin1;
+SELECT CONVERT(103, CHAR(50) UNICODE);
+CONVERT(103, CHAR(50) UNICODE)
+103
+SELECT CONVERT(103.0, CHAR(50) UNICODE);
+CONVERT(103.0, CHAR(50) UNICODE)
+103.0
+SELECT CONVERT(-103, CHAR(50) UNICODE);
+CONVERT(-103, CHAR(50) UNICODE)
+-103
+SELECT CONVERT(-103.0, CHAR(50) UNICODE);
+CONVERT(-103.0, CHAR(50) UNICODE)
+-103.0
CREATE TABLE t1 (
a varchar(255) NOT NULL default '',
KEY a (a)
diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result
index 9bc8e417e19..8d6fa9927ce 100644
--- a/mysql-test/r/func_compress.result
+++ b/mysql-test/r/func_compress.result
@@ -72,3 +72,10 @@ set @@max_allowed_packet=1048576*100;
select compress(repeat('aaaaaaaaaa', IF(XXX, 10, 10000000))) is null;
compress(repeat('aaaaaaaaaa', IF(XXX, 10, 10000000))) is null
0
+create table t1(a blob);
+insert into t1 values(NULL), (compress('a'));
+select uncompress(a), uncompressed_length(a) from t1;
+uncompress(a) uncompressed_length(a)
+NULL NULL
+a 1
+drop table t1;
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 3cb8da7f63f..2c79b8f8ab1 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -604,3 +604,13 @@ count(distinct (f1+1))
1
3
drop table t1;
+create table t1 (f1 int unsigned, f2 varchar(255));
+insert into t1 values (1,repeat('a',255)),(2,repeat('b',255));
+select f2,group_concat(f1) from t1 group by f2;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 t1 f2 f2 253 255 255 Y 0 0 8
+def group_concat(f1) 252 400 1 Y 128 0 63
+f2 group_concat(f1)
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 2
+drop table t1;
diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result
index 41aaa21eea3..15dc244693d 100644
--- a/mysql-test/r/key_cache.result
+++ b/mysql-test/r/key_cache.result
@@ -287,3 +287,45 @@ check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
+CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY);
+SET GLOBAL key_cache_block_size=1536;
+INSERT INTO t1 VALUES (1);
+SELECT @@key_cache_block_size;
+@@key_cache_block_size
+1536
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+DROP TABLE t1;
+CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int);
+CREATE TABLE t2(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int);
+SET GLOBAL key_cache_block_size=1536;
+INSERT INTO t1 VALUES (1,0);
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4181
+SELECT @@key_cache_block_size;
+@@key_cache_block_size
+1536
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+DROP TABLE t1,t2;
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index ee8ca5f0328..8126e223f55 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -788,3 +788,35 @@ a
2
2
DROP TABLE t1;
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1,30), (2,20), (1,10), (2,30), (1,20), (2,10);
+(SELECT b,a FROM t1 ORDER BY a,b) ORDER BY b,a;
+b a
+10 1
+10 2
+20 1
+20 2
+30 1
+30 2
+(SELECT b FROM t1 ORDER BY b DESC) ORDER BY b ASC;
+b
+10
+10
+20
+20
+30
+30
+(SELECT b,a FROM t1 ORDER BY b,a) ORDER BY a,b;
+b a
+10 1
+20 1
+30 1
+10 2
+20 2
+30 2
+(SELECT b,a FROM t1 ORDER by b,a LIMIT 3) ORDER by a,b;
+b a
+10 1
+20 1
+10 2
+DROP TABLE t1;
diff --git a/mysql-test/r/rpl_deadlock.result b/mysql-test/r/rpl_deadlock.result
index 8eb9d64fcae..db88cf73c03 100644
--- a/mysql-test/r/rpl_deadlock.result
+++ b/mysql-test/r/rpl_deadlock.result
@@ -44,8 +44,39 @@ select * from t2;
a
22
show slave status;
-Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 13110 # # master-bin.000001 Yes Yes 0 0 13110 # None 0 No #
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 13110
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 13110
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
stop slave;
change master to master_log_pos=401;
begin;
@@ -62,8 +93,39 @@ select * from t2;
a
22
show slave status;
-Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 13110 # # master-bin.000001 Yes Yes 0 0 13110 # None 0 No #
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 13110
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running #
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 13110
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
set global max_relay_log_size=0;
stop slave;
change master to master_log_pos=401;
@@ -82,6 +144,37 @@ select * from t2;
a
22
show slave status;
-Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 13110 # # master-bin.000001 Yes Yes 0 0 13110 # None 0 No #
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 13110
+Relay_Log_File #
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running #
+Slave_SQL_Running Yes
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 13110
+Relay_Log_Space #
+Until_Condition None
+Until_Log_File
+Until_Log_Pos 0
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
drop table t1,t2,t3,t4;
diff --git a/mysql-test/r/rpl_relayrotate.result b/mysql-test/r/rpl_relayrotate.result
index bf9bbbb9b93..20f19973d83 100644
--- a/mysql-test/r/rpl_relayrotate.result
+++ b/mysql-test/r/rpl_relayrotate.result
@@ -10,10 +10,7 @@ reset slave;
start slave;
stop slave;
start slave;
-select master_pos_wait('master-bin.001',3000)>=0;
-master_pos_wait('master-bin.001',3000)>=0
-1
-select * from t1 where a=8000;
-a
+select max(a) from t1;
+max(a)
8000
drop table t1;
diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result
index b9865d282fa..cd67d2592a8 100644
--- a/mysql-test/r/rpl_temporary.result
+++ b/mysql-test/r/rpl_temporary.result
@@ -89,3 +89,17 @@ f
7
drop table t1,t2;
create temporary table t3 (f int);
+set @session.pseudo_thread_id=100;
+create temporary table t101 (id int);
+create temporary table t102 (id int);
+set @session.pseudo_thread_id=200;
+create temporary table t201 (id int);
+create temporary table `#not_user_table_prefixed_with_hash_sign_no_harm` (id int);
+set @con1_id=connection_id();
+kill @con1_id;
+create table t1(f int);
+insert into t1 values (1);
+select * from t1 /* must be 1 */;
+f
+1
+drop table t1;
diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test
index fbbbce15576..fd1b6e5247f 100644
--- a/mysql-test/t/case.test
+++ b/mysql-test/t/case.test
@@ -119,4 +119,15 @@ SELECT 'case+union+test'
UNION
SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END;
+#
+# Bug #17896: problem with MIN(CASE...)
+#
+
+create table t1(a float, b int default 3);
+insert into t1 (a) values (2), (11), (8);
+select min(a), min(case when 1=1 then a else NULL end),
+ min(case when 1!=1 then NULL else a end)
+from t1 where b=3 group by b;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index bd37d008173..2cbabf88ee0 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -408,6 +408,14 @@ DROP TABLE t1;
SET NAMES latin1;
#
+# Bug#18691 Converting number to UNICODE string returns invalid result
+#
+SELECT CONVERT(103, CHAR(50) UNICODE);
+SELECT CONVERT(103.0, CHAR(50) UNICODE);
+SELECT CONVERT(-103, CHAR(50) UNICODE);
+SELECT CONVERT(-103.0, CHAR(50) UNICODE);
+
+#
# Bug#9557 MyISAM utf8 table crash
#
CREATE TABLE t1 (
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index 3eae8d230d8..9bfe9567d83 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -10,6 +10,3 @@
#
##############################################################################
-rpl_relayrotate : Unstable test case, bug#12429
-rpl_until : Unstable test case, bug#12429
-rpl_deadlock : Unstable test case, bug#12429
diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test
index 6b85062b9fa..0f3c3cab307 100644
--- a/mysql-test/t/func_compress.test
+++ b/mysql-test/t/func_compress.test
@@ -45,4 +45,13 @@ set @@max_allowed_packet=1048576*100;
--replace_result "''" XXX "'1'" XXX
eval select compress(repeat('aaaaaaaaaa', IF('$LOW_MEMORY', 10, 10000000))) is null;
+#
+# Bug #18643: problem with null values
+#
+
+create table t1(a blob);
+insert into t1 values(NULL), (compress('a'));
+select uncompress(a), uncompressed_length(a) from t1;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index f116aa6f164..8f50690dd8b 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -390,4 +390,15 @@ insert into t1 values(1),(2),(3);
select f1, group_concat(f1+1) from t1 group by f1 with rollup;
select count(distinct (f1+1)) from t1 group by f1 with rollup;
drop table t1;
+
+#
+# Bug#14169 type of group_concat() result changed to blob if tmp_table was used
+#
+create table t1 (f1 int unsigned, f2 varchar(255));
+insert into t1 values (1,repeat('a',255)),(2,repeat('b',255));
+--enable_metadata
+select f2,group_concat(f1) from t1 group by f2;
+--disable_metadata
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test
index 5d0f904a716..6e772a7a9ad 100644
--- a/mysql-test/t/key_cache.test
+++ b/mysql-test/t/key_cache.test
@@ -149,6 +149,7 @@ show status like 'key_blocks_used';
--replace_result 1812 KEY_BLOCKS_UNUSED 1793 KEY_BLOCKS_UNUSED 1674 KEY_BLOCKS_UNUSED 1818 KEY_BLOCKS_UNUSED 1824 KEY_BLOCKS_UNUSED
show status like 'key_blocks_unused';
+
# Cleanup
# We don't reset keycache2 as we want to ensure that mysqld will reset it
set global keycache2.key_buffer_size=0;
@@ -157,7 +158,7 @@ set global keycache2.key_buffer_size=0;
set global keycache3.key_buffer_size=100;
set global keycache3.key_buffer_size=0;
-# Test case for buf 6447
+# Test case for bug 6447
create table t1 (mytext text, FULLTEXT (mytext));
insert t1 values ('aaabbb');
@@ -168,4 +169,42 @@ check table t1;
drop table t1;
+#
+# Bug #19079: corrupted index when key_cache_block_size is not multiple of
+# myisam_block_size
+
+CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY);
+SET GLOBAL key_cache_block_size=1536;
+INSERT INTO t1 VALUES (1);
+SELECT @@key_cache_block_size;
+CHECK TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int);
+CREATE TABLE t2(a int NOT NULL AUTO_INCREMENT PRIMARY KEY, b int);
+SET GLOBAL key_cache_block_size=1536;
+INSERT INTO t1 VALUES (1,0);
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+INSERT INTO t2(b) SELECT b FROM t1;
+INSERT INTO t1(b) SELECT b FROM t2;
+SELECT COUNT(*) FROM t1;
+SELECT @@key_cache_block_size;
+CHECK TABLE t1;
+DROP TABLE t1,t2;
+
# End of 4.1 tests
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index 4b7ec84dc54..1664afc70f9 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -545,4 +545,18 @@ SELECT a FROM t1 ORDER BY a;
(SELECT a FROM t1) ORDER BY a;
DROP TABLE t1;
+#
+# Bug #18767: global ORDER BY applied to a SELECT with ORDER BY either was
+# ignored or 'concatened' to the latter.
+
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1,30), (2,20), (1,10), (2,30), (1,20), (2,10);
+
+(SELECT b,a FROM t1 ORDER BY a,b) ORDER BY b,a;
+(SELECT b FROM t1 ORDER BY b DESC) ORDER BY b ASC;
+(SELECT b,a FROM t1 ORDER BY b,a) ORDER BY a,b;
+(SELECT b,a FROM t1 ORDER by b,a LIMIT 3) ORDER by a,b;
+
+DROP TABLE t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/rpl_deadlock.test b/mysql-test/t/rpl_deadlock.test
index d3bc31addff..e8ba6d6faec 100644
--- a/mysql-test/t/rpl_deadlock.test
+++ b/mysql-test/t/rpl_deadlock.test
@@ -58,7 +58,7 @@ while ($1)
enable_query_log;
select * from t1 for update;
start slave;
---sleep 3 # hope that slave is blocked now
+--real_sleep 3 # hope that slave is blocked now
insert into t2 values(22); # provoke deadlock, slave should be victim
commit;
sync_with_master;
@@ -67,7 +67,9 @@ select * from t2;
# check that no error is reported
--replace_column 1 # 8 # 9 # 23 # 33 #
--replace_result $MASTER_MYPORT MASTER_MYPORT
+--vertical_results
show slave status;
+--horizontal_results
# 2) Test lock wait timeout
@@ -76,15 +78,17 @@ change master to master_log_pos=401; # the BEGIN log event
begin;
select * from t2 for update; # hold lock
start slave;
---sleep 10 # slave should have blocked, and be retrying
+--real_sleep 10 # slave should have blocked, and be retrying
commit;
sync_with_master;
select * from t1; # check that slave succeeded finally
select * from t2;
# check that no error is reported
---replace_column 1 # 8 # 9 # 23 # 33 #
+--replace_column 1 # 8 # 9 # 11 # 23 # 33 #
--replace_result $MASTER_MYPORT MASTER_MYPORT
+--vertical_results
show slave status;
+--horizontal_results
# Now we repeat 2), but with BEGIN in the same relay log as
# COMMIT (to see if seeking into hot log is ok).
@@ -97,14 +101,16 @@ change master to master_log_pos=401;
begin;
select * from t2 for update;
start slave;
---sleep 10
+--real_sleep 10
commit;
sync_with_master;
select * from t1;
select * from t2;
---replace_column 1 # 8 # 9 # 23 # 33 #
+--replace_column 1 # 8 # 9 # 11 # 23 # 33 #
--replace_result $MASTER_MYPORT MASTER_MYPORT
+--vertical_results
show slave status;
+--horizontal_results
connection master;
drop table t1,t2,t3,t4;
diff --git a/mysql-test/t/rpl_relayrotate.test b/mysql-test/t/rpl_relayrotate.test
index 1dab8bf4ed5..04f03367e20 100644
--- a/mysql-test/t/rpl_relayrotate.test
+++ b/mysql-test/t/rpl_relayrotate.test
@@ -52,11 +52,9 @@ start slave;
# which proves that the transaction restarted at
# the right place.
# We must wait for the transaction to commit before
-# reading, MASTER_POS_WAIT() will do it for sure
-# (the only statement with position>=3000 is COMMIT).
-select master_pos_wait('master-bin.001',3000)>=0;
-select * from t1 where a=8000;
-
+# reading:
+sync_with_master;
+select max(a) from t1;
connection master;
# The following DROP is a very important cleaning task:
diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test
index 8dead9138c1..71d7b32b7c9 100644
--- a/mysql-test/t/rpl_temporary.test
+++ b/mysql-test/t/rpl_temporary.test
@@ -128,6 +128,32 @@ drop table t1,t2;
create temporary table t3 (f int);
sync_with_master;
-# The server will now close done
+#
+# BUG#17263 incorrect generation DROP temp tables
+# Temporary tables of connection are dropped in batches
+# where a batch correspond to pseudo_thread_id
+# value was set up at the moment of temp table creation
+#
+connection con1;
+set @session.pseudo_thread_id=100;
+create temporary table t101 (id int);
+create temporary table t102 (id int);
+set @session.pseudo_thread_id=200;
+create temporary table t201 (id int);
+create temporary table `#not_user_table_prefixed_with_hash_sign_no_harm` (id int);
+set @con1_id=connection_id();
+kill @con1_id;
+
+#now do something to show that slave is ok after DROP temp tables
+connection master;
+create table t1(f int);
+insert into t1 values (1);
+
+sync_slave_with_master;
+#connection slave;
+select * from t1 /* must be 1 */;
+
+connection master;
+drop table t1;
# End of 4.1 tests
diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test
index 57ebc67db1d..990f00fdc63 100644
--- a/mysql-test/t/rpl_until.test
+++ b/mysql-test/t/rpl_until.test
@@ -26,6 +26,7 @@ show binlog events;
connection slave;
start slave until master_log_file='master-bin.000001', master_log_pos=244;
sleep 2;
+wait_for_slave_to_stop;
# here table should be still not deleted
select * from t1;
--replace_result $MASTER_MYPORT MASTER_MYPORT
@@ -37,6 +38,7 @@ start slave until master_log_file='master-no-such-bin.000001', master_log_pos=29
# again this table should be still not deleted
select * from t1;
sleep 2;
+wait_for_slave_to_stop;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 #
show slave status;
@@ -44,6 +46,7 @@ show slave status;
# try replicate all until second insert to t2;
start slave until relay_log_file='slave-relay-bin.000002', relay_log_pos=537;
sleep 4;
+wait_for_slave_to_stop;
select * from t2;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 #
@@ -61,6 +64,7 @@ stop slave;
start slave until master_log_file='master-bin.000001', master_log_pos=561;
# 2 is not enough when running with valgrind
--real_sleep 4
+wait_for_slave_to_stop;
# here the sql slave thread should be stopped
--replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004
--replace_column 1 # 9 # 23 # 33 #
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index ca683f16415..88b5051c52b 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -1741,6 +1741,7 @@ byte *key_cache_read(KEY_CACHE *keycache,
uint status;
int page_st;
+ offset= (uint) (filepos & (keycache->key_cache_block_size-1));
/* Read data in key_cache_block_size increments */
do
{
@@ -1750,7 +1751,6 @@ byte *key_cache_read(KEY_CACHE *keycache,
keycache_pthread_mutex_unlock(&keycache->cache_lock);
goto no_key_cache;
}
- offset= (uint) (filepos & (keycache->key_cache_block_size-1));
filepos-= offset;
read_length= length;
set_if_smaller(read_length, keycache->key_cache_block_size-offset);
@@ -1826,6 +1826,7 @@ byte *key_cache_read(KEY_CACHE *keycache,
#endif
buff+= read_length;
filepos+= read_length+offset;
+ offset= 0;
} while ((length-= read_length));
DBUG_RETURN(start);
@@ -1877,17 +1878,17 @@ int key_cache_insert(KEY_CACHE *keycache,
uint read_length;
int page_st;
int error;
+ uint offset;
+ offset= (uint) (filepos & (keycache->key_cache_block_size-1));
do
{
- uint offset;
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (!keycache->can_be_used)
{
keycache_pthread_mutex_unlock(&keycache->cache_lock);
DBUG_RETURN(0);
}
- offset= (uint) (filepos & (keycache->key_cache_block_size-1));
/* Read data into key cache from buff in key_cache_block_size incr. */
filepos-= offset;
read_length= length;
@@ -1945,6 +1946,7 @@ int key_cache_insert(KEY_CACHE *keycache,
buff+= read_length;
filepos+= read_length+offset;
+ offset= 0;
} while ((length-= read_length));
}
@@ -2011,17 +2013,17 @@ int key_cache_write(KEY_CACHE *keycache,
/* Key cache is used */
uint read_length;
int page_st;
+ uint offset;
+ offset= (uint) (filepos & (keycache->key_cache_block_size-1));
do
{
- uint offset;
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (!keycache->can_be_used)
{
keycache_pthread_mutex_unlock(&keycache->cache_lock);
goto no_key_cache;
}
- offset= (uint) (filepos & (keycache->key_cache_block_size-1));
/* Write data in key_cache_block_size increments */
filepos-= offset;
read_length= length;
diff --git a/ndb/src/kernel/SimBlockList.cpp b/ndb/src/kernel/SimBlockList.cpp
index 6029fc7e225..271d515dc92 100644
--- a/ndb/src/kernel/SimBlockList.cpp
+++ b/ndb/src/kernel/SimBlockList.cpp
@@ -111,8 +111,12 @@ SimBlockList::unload(){
if(theList != 0){
for(int i = 0; i<noOfBlocks; i++){
if(theList[i] != 0){
+#ifdef VM_TRACE
theList[i]->~SimulatedBlock();
free(theList[i]);
+#else
+ delete(theList[i]);
+#endif
theList[i] = 0;
}
}
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
index cb20fb2ca22..f9414eb8848 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
@@ -25,7 +25,10 @@
void Ndbcntr::initData()
{
-
+ c_start.reset();
+ cmasterNodeId = 0;
+ cnoStartNodes = 0;
+ cnoWaitrep = 0;
// Records with constant sizes
ndbBlocksRec = new NdbBlocksRec[ZSIZE_NDB_BLOCKS_REC];
}//Ndbcntr::initData()
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index f9aa220c181..3c41fb56d89 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -37,10 +37,25 @@ static Item_result item_store_type(Item_result a,Item_result b)
static void agg_result_type(Item_result *type, Item **items, uint nitems)
{
- uint i;
- type[0]= items[0]->result_type();
- for (i=1 ; i < nitems ; i++)
- type[0]= item_store_type(type[0], items[i]->result_type());
+ Item **item, **item_end;
+
+ *type= STRING_RESULT;
+ /* Skip beginning NULL items */
+ for (item= items, item_end= item + nitems; item < item_end; item++)
+ {
+ if ((*item)->type() != Item::NULL_ITEM)
+ {
+ *type= (*item)->result_type();
+ item++;
+ break;
+ }
+ }
+ /* Combine result types. Note: NULL items don't affect the result */
+ for (; item < item_end; item++)
+ {
+ if ((*item)->type() != Item::NULL_ITEM)
+ *type= item_store_type(type[0], (*item)->result_type());
+ }
}
static void agg_cmp_type(Item_result *type, Item **items, uint nitems)
diff --git a/sql/item_func.cc b/sql/item_func.cc
index d0d2eca7233..174a8c55d01 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -307,7 +307,7 @@ Field *Item_func::tmp_table_field(TABLE *t_arg)
res= new Field_double(max_length, maybe_null, name, t_arg, decimals);
break;
case STRING_RESULT:
- if (max_length > 255)
+ if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB)
res= new Field_blob(max_length, maybe_null, name, t_arg, collation.collation);
else
res= new Field_string(max_length, maybe_null, name, t_arg, collation.collation);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 04765e18191..f0127ed2a5d 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2850,6 +2850,7 @@ String *Item_func_uncompress::val_str(String *str)
if (!res)
goto err;
+ null_value= 0;
if (res->is_empty())
return res;
diff --git a/sql/item_sum.h b/sql/item_sum.h
index c972240fcba..0cc2a20faa3 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -729,6 +729,13 @@ class Item_func_group_concat : public Item_sum
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
const char *func_name() const { return "group_concat"; }
virtual Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const
+ {
+ if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB)
+ return FIELD_TYPE_BLOB;
+ else
+ return MYSQL_TYPE_VAR_STRING;
+ }
void clear();
bool add();
void reset_field();
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index d6b57464d59..f3d6858755c 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2221,8 +2221,8 @@ String *Item_char_typecast::val_str(String *str)
// Convert character set if differ
uint dummy_errors;
if (!(res= args[0]->val_str(&tmp_value)) ||
- str->copy(res->ptr(), res->length(), res->charset(),
- cast_cs, &dummy_errors))
+ str->copy(res->ptr(), res->length(), from_cs,
+ cast_cs, &dummy_errors))
{
null_value= 1;
return 0;
@@ -2261,14 +2261,32 @@ void Item_char_typecast::fix_length_and_dec()
For single-byte character sets we allow just to copy
from the argument. A single-byte character sets string
is always well-formed.
+
+ There is a special trick to convert form a number to ucs2.
+ As numbers have my_charset_bin as their character set,
+ it wouldn't do conversion to ucs2 without an additional action.
+ To force conversion, we should pretend to be non-binary.
+ Let's choose from_cs this way:
+ - If the argument in a number and cast_cs is ucs2 (i.e. mbminlen > 1),
+ then from_cs is set to latin1, to perform latin1 -> ucs2 conversion.
+ - If the argument is a number and cast_cs is ASCII-compatible
+ (i.e. mbminlen == 1), then from_cs is set to cast_cs,
+ which allows just to take over the args[0]->val_str() result
+ and thus avoid unnecessary character set conversion.
+ - If the argument is not a number, then from_cs is set to
+ the argument's charset.
*/
+ from_cs= (args[0]->result_type() == INT_RESULT ||
+ args[0]->result_type() == REAL_RESULT) ?
+ (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) :
+ args[0]->collation.collation;
charset_conversion= (cast_cs->mbmaxlen > 1) ||
- !my_charset_same(args[0]->collation.collation, cast_cs) &&
- args[0]->collation.collation != &my_charset_bin &&
+ !my_charset_same(from_cs, cast_cs) &&
+ from_cs != &my_charset_bin &&
cast_cs != &my_charset_bin;
collation.set(cast_cs, DERIVATION_IMPLICIT);
char_length= (cast_length >= 0) ? cast_length :
- args[0]->max_length/args[0]->collation.collation->mbmaxlen;
+ args[0]->max_length/from_cs->mbmaxlen;
max_length= char_length * cast_cs->mbmaxlen;
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index ce9d6b0a7aa..163b1591e52 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -681,7 +681,7 @@ public:
class Item_char_typecast :public Item_typecast
{
int cast_length;
- CHARSET_INFO *cast_cs;
+ CHARSET_INFO *cast_cs, *from_cs;
bool charset_conversion;
String tmp_value;
public:
diff --git a/sql/lock.cc b/sql/lock.cc
index fe59039dde3..ab4a81034ba 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -78,6 +78,7 @@ extern HASH open_cache;
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
uint flags, TABLE **write_locked);
+static void reset_lock_data(MYSQL_LOCK *sql_lock);
static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
static void print_lock_error(int error);
@@ -120,12 +121,16 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
*/
if (wait_if_global_read_lock(thd, 1, 1))
{
+ /* Clear the lock type of all lock data to avoid reusage. */
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
break;
- }
+ }
if (thd->version != refresh_version)
{
+ /* Clear the lock type of all lock data to avoid reusage. */
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
goto retry;
}
@@ -134,6 +139,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
thd->proc_info="System lock";
if (lock_external(thd, tables, count))
{
+ /* Clear the lock type of all lock data to avoid reusage. */
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
thd->proc_info=0;
@@ -639,6 +646,9 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
if (table->db_stat & HA_READ_ONLY)
{
my_error(ER_OPEN_AS_READONLY,MYF(0),table->table_name);
+ /* Clear the lock type of the lock data that are stored already. */
+ sql_lock->lock_count= locks - sql_lock->locks;
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
DBUG_RETURN(0);
}
@@ -663,6 +673,48 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
}
+/*
+ Reset lock type in lock data.
+
+ SYNOPSIS
+ reset_lock_data()
+ sql_lock The MySQL lock.
+
+ DESCRIPTION
+
+ After a locking error we want to quit the locking of the table(s).
+ The test case in the bug report for Bug #18544 has the following
+ cases: 1. Locking error in lock_external() due to InnoDB timeout.
+ 2. Locking error in get_lock_data() due to missing write permission.
+ 3. Locking error in wait_if_global_read_lock() due to lock conflict.
+
+ In all these cases we have already set the lock type into the lock
+ data of the open table(s). If the table(s) are in the open table
+ cache, they could be reused with the non-zero lock type set. This
+ could lead to ignoring a different lock type with the next lock.
+
+ Clear the lock type of all lock data. This ensures that the next
+ lock request will set its lock type properly.
+
+ RETURN
+ void
+*/
+
+static void reset_lock_data(MYSQL_LOCK *sql_lock)
+{
+ THR_LOCK_DATA **ldata;
+ THR_LOCK_DATA **ldata_end;
+
+ for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
+ ldata < ldata_end;
+ ldata++)
+ {
+ /* Reset lock type. */
+ (*ldata)->type= TL_UNLOCK;
+ }
+}
+
+
/*****************************************************************************
Lock table based on the name.
This is used when we need total access to a closed, not open table
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index e68762868a4..740e1a419c7 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -5253,7 +5253,7 @@ The minimum value for this variable is 4096.",
(gptr*) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG,
REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
{"max_prepared_stmt_count", OPT_MAX_PREPARED_STMT_COUNT,
- "Maximum numbrer of prepared statements in the server.",
+ "Maximum number of prepared statements in the server.",
(gptr*) &max_prepared_stmt_count, (gptr*) &max_prepared_stmt_count,
0, GET_ULONG, REQUIRED_ARG, 16382, 0, 1*1024*1024, 0, 1, 0},
{"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE,
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 223e8482f49..60e91aff3f9 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -483,13 +483,22 @@ void close_temporary(TABLE *table,bool delete_table)
DBUG_VOID_RETURN;
}
+/* close_temporary_tables' internal, 4 is due to uint4korr definition */
+static inline uint tmpkeyval(THD *thd, TABLE *table)
+{
+ return uint4korr(table->table_cache_key + table->key_length - 4);
+}
+
+/* Creates one DROP TEMPORARY TABLE binlog event for each pseudo-thread */
void close_temporary_tables(THD *thd)
{
- TABLE *table,*next;
- char *query, *end;
- uint query_buf_size;
- bool found_user_tables = 0;
+ TABLE *next,
+ *prev_table /* prev link is not maintained in TABLE's double-linked list */,
+ *table;
+ char *query= (gptr) 0, *end;
+ uint query_buf_size, max_names_len;
+ bool found_user_tables;
if (!thd->temporary_tables)
return;
@@ -497,51 +506,122 @@ void close_temporary_tables(THD *thd)
LINT_INIT(end);
query_buf_size= 50; // Enough for DROP ... TABLE IF EXISTS
- for (table=thd->temporary_tables ; table ; table=table->next)
+ /*
+ insertion sort of temp tables by pseudo_thread_id to build ordered list
+ of sublists of equal pseudo_thread_id
+ */
+ for (prev_table= thd->temporary_tables,
+ table= prev_table->next,
+ found_user_tables= (prev_table->real_name[0] != '#');
+ table;
+ prev_table= table, table= table->next)
+ {
+ TABLE *prev_sorted /* same as for prev_table */,
+ *sorted;
/*
- We are going to add 4 ` around the db/table names, so 1 does not look
- enough; indeed it is enough, because table->key_length is greater (by 8,
- because of server_id and thread_id) than db||table.
+ table not created directly by the user is moved to the tail.
+ Fixme/todo: nothing (I checked the manual) prevents user to create temp
+ with `#'
*/
- query_buf_size+= table->key_length+1;
-
- if ((query = alloc_root(thd->mem_root, query_buf_size)))
+ if (table->real_name[0] == '#')
+ continue;
+ else
+ {
+ found_user_tables = 1;
+ }
+ for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table;
+ prev_sorted= sorted, sorted= sorted->next)
+ {
+ if (sorted->real_name[0] == '#' || tmpkeyval(thd, sorted) > tmpkeyval(thd, table))
+ {
+ /* move into the sorted part of the list from the unsorted */
+ prev_table->next= table->next;
+ table->next= sorted;
+ if (prev_sorted)
+ {
+ prev_sorted->next= table;
+ }
+ else
+ {
+ thd->temporary_tables= table;
+ }
+ table= prev_table;
+ break;
+ }
+ }
+ }
+ /*
+ calc query_buf_size as max per sublists, one sublist per pseudo thread id.
+ Also stop at first occurence of `#'-named table that starts
+ all implicitly created temp tables
+ */
+ for (max_names_len= 0, table=thd->temporary_tables;
+ table && table->real_name[0] != '#';
+ table=table->next)
+ {
+ uint tmp_names_len;
+ for (tmp_names_len= table->key_length + 1;
+ table->next && table->real_name[0] != '#' &&
+ tmpkeyval(thd, table) == tmpkeyval(thd, table->next);
+ table=table->next)
+ {
+ /*
+ We are going to add 4 ` around the db/table names, so 1 might not look
+ enough; indeed it is enough, because table->key_length is greater (by 8,
+ because of server_id and thread_id) than db||table.
+ */
+ tmp_names_len += table->next->key_length + 1;
+ }
+ if (tmp_names_len > max_names_len) max_names_len= tmp_names_len;
+ }
+
+ /* allocate */
+ if (found_user_tables && mysql_bin_log.is_open() &&
+ (query = alloc_root(thd->mem_root, query_buf_size+= max_names_len)))
// Better add "if exists", in case a RESET MASTER has been done
- end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ");
+ end= strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ");
- for (table=thd->temporary_tables ; table ; table=next)
+ /* scan sorted tmps to generate sequence of DROP */
+ for (table=thd->temporary_tables; table; table= next)
{
- if (query) // we might be out of memory, but this is not fatal
+ if (query // we might be out of memory, but this is not fatal
+ && table->real_name[0] != '#')
{
- // skip temporary tables not created directly by the user
- if (table->real_name[0] != '#')
- found_user_tables = 1;
+ char *end_cur;
+ /* Set pseudo_thread_id to be that of the processed table */
+ thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
+ /* Loop forward through all tables within the sublist of
+ common pseudo_thread_id to create single DROP query */
+ for (end_cur= end;
+ table && table->real_name[0] != '#' &&
+ tmpkeyval(thd, table) == thd->variables.pseudo_thread_id;
+ table= next)
+ {
+ end_cur= strxmov(end_cur, "`", table->table_cache_key, "`.`",
+ table->real_name, "`,", NullS);
+ next= table->next;
+ close_temporary(table, 1);
+ }
+ thd->clear_error();
+ /* The -1 is to remove last ',' */
+ Query_log_event qinfo(thd, query, (ulong)(end_cur - query) - 1, 0, FALSE);
/*
- Here we assume table_cache_key always starts
- with \0 terminated db name
+ Imagine the thread had created a temp table, then was doing a SELECT, and
+ the SELECT was killed. Then it's not clever to mark the statement above as
+ "killed", because it's not really a statement updating data, and there
+ are 99.99% chances it will succeed on slave.
+ If a real update (one updating a persistent table) was killed on the
+ master, then this real update will be logged with error_code=killed,
+ rightfully causing the slave to stop.
*/
- end = strxmov(end,"`",table->table_cache_key,"`.`",
- table->real_name,"`,", NullS);
+ qinfo.error_code= 0;
+ mysql_bin_log.write(&qinfo);
+ }
+ else
+ {
+ next= table->next;
+ close_temporary(table, 1);
}
- next=table->next;
- close_temporary(table);
- }
- if (query && found_user_tables && mysql_bin_log.is_open())
- {
- /* The -1 is to remove last ',' */
- thd->clear_error();
- Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0, FALSE);
- /*
- Imagine the thread had created a temp table, then was doing a SELECT, and
- the SELECT was killed. Then it's not clever to mark the statement above as
- "killed", because it's not really a statement updating data, and there
- are 99.99% chances it will succeed on slave.
- If a real update (one updating a persistent table) was killed on the
- master, then this real update will be logged with error_code=killed,
- rightfully causing the slave to stop.
- */
- qinfo.error_code= 0;
- mysql_bin_log.write(&qinfo);
}
thd->temporary_tables=0;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 47908ba8685..bd79a194122 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -400,6 +400,7 @@ public:
bool check_updateable(char *db, char *table);
void print(String *str);
+ bool add_fake_select_lex(THD *thd);
ulong init_prepare_fake_select_lex(THD *thd);
int change_result(select_subselect *result, select_subselect *old_result);
inline bool is_prepared() { return prepared; }
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 21a335637b9..e25a428aaa7 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4189,23 +4189,9 @@ mysql_new_select(LEX *lex, bool move_down)
else
{
select_lex->include_neighbour(lex->current_select);
- SELECT_LEX_UNIT *unit= select_lex->master_unit();
- SELECT_LEX *fake= unit->fake_select_lex;
- if (!fake)
- {
- /*
- as far as we included SELECT_LEX for UNION unit should have
- fake SELECT_LEX for UNION processing
- */
- if (!(fake= unit->fake_select_lex= new(lex->thd->mem_root) SELECT_LEX()))
- return 1;
- fake->include_standalone(unit,
- (SELECT_LEX_NODE**)&unit->fake_select_lex);
- fake->select_number= INT_MAX;
- fake->make_empty_select();
- fake->linkage= GLOBAL_OPTIONS_TYPE;
- fake->select_limit= HA_POS_ERROR;
- }
+ if (!select_lex->master_unit()->fake_select_lex &&
+ select_lex->master_unit()->add_fake_select_lex(lex->thd))
+ return 1;
}
select_lex->master_unit()->global_parameters= select_lex;
@@ -4975,6 +4961,60 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
}
+/*
+ Create a fake SELECT_LEX for a unit
+
+ SYNOPSIS:
+ add_fake_select_lex()
+ thd thread handle
+
+ DESCRIPTION
+ The method create a fake SELECT_LEX object for a unit.
+ This object is created for any union construct containing a union
+ operation and also for any single select union construct of the form
+ (SELECT ... ORDER BY order_list [LIMIT n]) ORDER BY ...
+ or of the form
+ (SELECT ... ORDER BY LIMIT n) ORDER BY ...
+
+ NOTES
+ The object is used to retrieve rows from the temporary table
+ where the result on the union is obtained.
+
+ RETURN VALUES
+ 1 on failure to create the object
+ 0 on success
+*/
+
+bool st_select_lex_unit::add_fake_select_lex(THD *thd)
+{
+ SELECT_LEX *first_sl= first_select();
+ DBUG_ENTER("add_fake_select_lex");
+ DBUG_ASSERT(!fake_select_lex);
+
+ if (!(fake_select_lex= new (thd->mem_root) SELECT_LEX()))
+ DBUG_RETURN(1);
+ fake_select_lex->include_standalone(this,
+ (SELECT_LEX_NODE**)&fake_select_lex);
+ fake_select_lex->select_number= INT_MAX;
+ fake_select_lex->make_empty_select();
+ fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE;
+ fake_select_lex->select_limit= HA_POS_ERROR;
+
+ if (!first_sl->next_select())
+ {
+ /*
+ This works only for
+ (SELECT ... ORDER BY list [LIMIT n]) ORDER BY order_list [LIMIT m],
+ (SELECT ... LIMIT n) ORDER BY order_list [LIMIT m]
+ just before the parser starts processing order_list
+ */
+ global_parameters= fake_select_lex;
+ fake_select_lex->no_table_names_allowed= 1;
+ thd->lex->current_select= fake_select_lex;
+ }
+ DBUG_RETURN(0);
+}
+
void add_join_on(TABLE_LIST *b,Item *expr)
{
if (expr)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index d7aa617cffd..46dba61cfc5 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -171,7 +171,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
register SELECT_LEX *select_lex = &lex->select_lex;
DBUG_ENTER("handle_select");
- if (select_lex->next_select())
+ if (select_lex->next_select() || select_lex->master_unit()->fake_select_lex)
res=mysql_union(thd, lex, result, &lex->unit);
else
res= mysql_select(thd, &select_lex->ref_pointer_array,
@@ -4925,7 +4925,8 @@ static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
if ((type= item->field_type()) == MYSQL_TYPE_DATETIME ||
type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE)
new_field= item->tmp_table_field_from_field_type(table);
- else if (item->max_length/item->collation.collation->mbmaxlen > 255)
+ else if (item->max_length/item->collation.collation->mbmaxlen >
+ CONVERT_IF_BIGGER_TO_BLOB)
{
if (convert_blob_length)
new_field= new Field_varstring(convert_blob_length, maybe_null,
@@ -5028,7 +5029,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
return new Field_longlong(item_sum->max_length,maybe_null,
item->name,table,item->unsigned_flag);
case STRING_RESULT:
- if (item_sum->max_length > 255)
+ if (item_sum->max_length/item_sum->collation.collation->mbmaxlen >
+ CONVERT_IF_BIGGER_TO_BLOB)
{
if (convert_blob_length)
return new Field_varstring(convert_blob_length, maybe_null,
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 8bb53f7b573..0948602bbb4 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -184,7 +184,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
thd_arg->lex->current_select= sl= first_select= first_select_in_union();
found_rows_for_union= first_select->options & OPTION_FOUND_ROWS;
- is_union= test(first_select->next_select());
+ is_union= test(first_select->next_select() || fake_select_lex);
/* Global option */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 05d95b57abb..162b4183c84 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -3790,15 +3790,33 @@ order_clause:
ORDER_SYM BY
{
LEX *lex=Lex;
- if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- lex->current_select->olap !=
- UNSPECIFIED_OLAP_TYPE)
+ SELECT_LEX *sel= lex->current_select;
+ SELECT_LEX_UNIT *unit= sel-> master_unit();
+ if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
+ sel->olap != UNSPECIFIED_OLAP_TYPE)
{
net_printf(lex->thd, ER_WRONG_USAGE,
"CUBE/ROLLUP",
"ORDER BY");
YYABORT;
}
+ if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
+ {
+ /*
+ A query of the of the form (SELECT ...) ORDER BY order_list is
+ executed in the same way as the query
+ SELECT ... ORDER BY order_list
+ unless the SELECT construct contains ORDER BY or LIMIT clauses.
+ Otherwise we create a fake SELECT_LEX if it has not been created
+ yet.
+ */
+ SELECT_LEX *first_sl= unit->first_select();
+ if (!first_sl->next_select() &&
+ (first_sl->order_list.elements ||
+ first_sl->select_limit != HA_POS_ERROR) &&
+ unit->add_fake_select_lex(lex->thd))
+ YYABORT;
+ }
} order_list;
order_list:
diff --git a/sql/unireg.h b/sql/unireg.h
index 70df9a89c8f..3fb30315c81 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -60,6 +60,7 @@
#define MAX_MBWIDTH 3 /* Max multibyte sequence */
#define MAX_FIELD_CHARLENGTH 255
+#define CONVERT_IF_BIGGER_TO_BLOB 255
/* Max column width +1 */
#define MAX_FIELD_WIDTH (MAX_FIELD_CHARLENGTH*MAX_MBWIDTH+1)