1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge knielsen@10.100.52.19:/usr/local/mysql/mysql-4.1-mtr-fix

into  mysql.com:/data0/knielsen/mysql-4.1-mtr-fix
This commit is contained in:
unknown
2006-04-24 10:28:31 +02:00
46 changed files with 796 additions and 127 deletions

View File

@@ -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"

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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"

View File

@@ -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)) {

View File

@@ -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;

View File

@@ -34,20 +34,20 @@ static uint lengths[256];
static struct my_option my_long_options[] =
{
{"help", 'h', "Display help and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"help", '?', "Synonym for -h.",
0, 0, 0, GET_NO_ARG, 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},
{"dump", 'd', "Dump index (incl. data offsets and word weights).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"length", 'l', "Report length distribution.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"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},
{"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.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"help", 'h', "Display help and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"help", '?', "Synonym for -h.",
0, 0, 0, GET_NO_ARG, 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}
};

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -407,6 +407,14 @@ INSERT INTO t1 VALUES ('-1');
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
#

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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:

View File

@@ -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

View File

@@ -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 #

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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()

View File

@@ -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)

View File

@@ -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);

View File

@@ -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;

View File

@@ -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();

View File

@@ -2221,7 +2221,7 @@ 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(),
str->copy(res->ptr(), res->length(), from_cs,
cast_cs, &dummy_errors))
{
null_value= 1;
@@ -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;
}

View File

@@ -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:

View File

@@ -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

View File

@@ -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,

View File

@@ -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,40 +506,105 @@ 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)
/*
We are going to add 4 ` around the db/table names, so 1 does not look
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;
/*
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 `#'
*/
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.
*/
query_buf_size+= table->key_length+1;
tmp_names_len += table->next->key_length + 1;
}
if (tmp_names_len > max_names_len) max_names_len= tmp_names_len;
}
if ((query = alloc_root(thd->mem_root, query_buf_size)))
/* 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;
/*
Here we assume table_cache_key always starts
with \0 terminated db name
*/
end = strxmov(end,"`",table->table_cache_key,"`.`",
table->real_name,"`,", NullS);
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);
}
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);
/* The -1 is to remove last ',' */
Query_log_event qinfo(thd, query, (ulong)(end_cur - 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
@@ -543,6 +617,12 @@ void close_temporary_tables(THD *thd)
qinfo.error_code= 0;
mysql_bin_log.write(&qinfo);
}
else
{
next= table->next;
close_temporary(table, 1);
}
}
thd->temporary_tables=0;
}

View File

@@ -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; }

View File

@@ -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()))
if (!select_lex->master_unit()->fake_select_lex &&
select_lex->master_unit()->add_fake_select_lex(lex->thd))
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;
}
}
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)

View File

@@ -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,

View File

@@ -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 */

View File

@@ -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:

View File

@@ -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)