Merge from mysql-5.1.58-release

This commit is contained in:
Karen Langford 2011-07-06 00:56:51 +02:00
commit f6398a86dd
30 changed files with 594 additions and 679 deletions

View file

@ -176,11 +176,12 @@ SELECT @@session.sql_mode INTO @old_sql_mode;
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
EXPLAIN EXTENDED SELECT 1 FROM t1
WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
SHOW WARNINGS;
Level Code Message
Error 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
Note 1003 select 1 AS `1` from `test`.`t1` where <not>(<exists>(...))
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 SUBQUERY t system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
Note 1003 select 1 AS `1` from `test`.`t1` where 0
SET SESSION sql_mode=@old_sql_mode;
DROP TABLE t1;
End of 5.0 tests.

View file

@ -0,0 +1,38 @@
CREATE TABLE t1 (c1 longtext);
INSERT INTO t1 values ('a');
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR/B11764517.tmp';
show global variables like 'secure_file_priv';
Variable_name Value
secure_file_priv MYSQL_TMP_DIR/
SELECT load_file('MYSQL_TMP_DIR\\B11764517.tmp') AS x;
x
a
SELECT load_file('MYSQL_TMP_DIR/B11764517.tmp') AS x;
x
a
SELECT load_file('MYSQL_TMP_DIR_UCASE/B11764517.tmp') AS x;
x
a
SELECT load_file('MYSQL_TMP_DIR_LCASE/B11764517.tmp') AS x;
x
a
SELECT load_file('MYSQL_TMP_DIR\\..a..\\..\\..\\B11764517.tmp') AS x;
x
NULL
LOAD DATA INFILE 'MYSQL_TMP_DIR\\B11764517.tmp' INTO TABLE t1;
LOAD DATA INFILE 'MYSQL_TMP_DIR/B11764517.tmp' INTO TABLE t1;
LOAD DATA INFILE 'MYSQL_TMP_DIR_UCASE/B11764517.tmp' INTO TABLE t1;
LOAD DATA INFILE 'MYSQL_TMP_DIR_LCASE/B11764517.tmp' INTO TABLE t1;
LOAD DATA INFILE "MYSQL_TMP_DIR\\..a..\\..\\..\\B11764517.tmp" into table t1;
ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR\\..a..\\..\\..\\B11764517-2.tmp';
ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR\\B11764517-2.tmp';
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR/B11764517-3.tmp';
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR_UCASE/B11764517-4.tmp';
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR_LCASE/B11764517-5.tmp';
DROP TABLE t1;

View file

@ -567,3 +567,28 @@ DROP USER 'tester';
DROP USER 'Tester';
DROP DATABASE B48872;
End of 5.0 tests.
#
# Bug#11882603 SELECT_ACL ON ANY COLUMN IN MYSQL.PROC ALLOWS TO SEE
# DEFINITION OF ANY ROUTINE.
#
DROP DATABASE IF EXISTS db1;
CREATE DATABASE db1;
CREATE PROCEDURE db1.p1() SELECT 1;
CREATE USER user2@localhost IDENTIFIED BY '';
GRANT SELECT(db) ON mysql.proc TO user2@localhost;
# Connection con2 as user2
# The statement below before disclosed info from body_utf8 column.
SHOW CREATE PROCEDURE db1.p1;
ERROR 42000: PROCEDURE p1 does not exist
# Check that SHOW works with SELECT grant on whole table
# Connection default
GRANT SELECT ON mysql.proc TO user2@localhost;
# Connection con2
# This should work
SHOW CREATE PROCEDURE db1.p1;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci
# Connection default
DROP USER user2@localhost;
DROP DATABASE db1;

View file

@ -4435,6 +4435,32 @@ pk int_key
3 3
7 3
DROP TABLE t1,t2;
#
# Bug#12329653
# EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
#
CREATE TABLE t1(a1 int);
INSERT INTO t1 VALUES (1),(2);
SELECT @@session.sql_mode INTO @old_sql_mode;
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
1
1
1
PREPARE stmt FROM
'SELECT 1 UNION ALL
SELECT 1 FROM t1
ORDER BY
(SELECT 1 FROM t1 AS t1_0
WHERE 1 < SOME (SELECT a1 FROM t1)
)' ;
EXECUTE stmt ;
ERROR 21000: Subquery returns more than 1 row
EXECUTE stmt ;
ERROR 21000: Subquery returns more than 1 row
SET SESSION sql_mode=@old_sql_mode;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
End of 5.0 tests.
CREATE TABLE t1 (a INT, b INT);
INSERT INTO t1 VALUES (2,22),(1,11),(2,22);

View file

@ -1,3 +1,46 @@
set global innodb_file_per_table=on;
set global innodb_file_format='Barracuda';
CREATE TABLE t1_purge (
A INT,
B BLOB, C BLOB, D BLOB, E BLOB,
F BLOB, G BLOB, H BLOB,
PRIMARY KEY (B(767), C(767), D(767), E(767), A),
INDEX (A)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t1_purge VALUES (1,
REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766));
CREATE TABLE t2_purge (
A INT PRIMARY KEY,
B BLOB, C BLOB, D BLOB, E BLOB,
F BLOB, G BLOB, H BLOB, I BLOB,
J BLOB, K BLOB, L BLOB,
INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t2_purge VALUES (1,
REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766), REPEAT('i', 766),
REPEAT('j', 766), REPEAT('k', 766), REPEAT('l', 766));
CREATE TABLE t3_purge (
A INT,
B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
F VARCHAR(800), G VARCHAR(800), H VARCHAR(800),
PRIMARY KEY (B(767), C(767), D(767), E(767), A),
INDEX (A)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t3_purge SELECT * FROM t1_purge;
CREATE TABLE t4_purge (
A INT PRIMARY KEY,
B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
F VARCHAR(800), G VARCHAR(800), H VARCHAR(800), I VARCHAR(800),
J VARCHAR(800), K VARCHAR(800), L VARCHAR(800),
INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t4_purge SELECT * FROM t2_purge;
DELETE FROM t1_purge;
DELETE FROM t2_purge;
DELETE FROM t3_purge;
DELETE FROM t4_purge;
set global innodb_file_per_table=0;
set global innodb_file_format=Antelope;
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
commit;
@ -1183,3 +1226,4 @@ a b
3 a
3 b
DROP TABLE t1;
DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;

View file

@ -4,6 +4,65 @@ let $MYSQLD_DATADIR= `select @@datadir`;
let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
let $per_table=`select @@innodb_file_per_table`;
let $format=`select @@innodb_file_format`;
set global innodb_file_per_table=on;
set global innodb_file_format='Barracuda';
# Test an assertion failure on purge.
CREATE TABLE t1_purge (
A INT,
B BLOB, C BLOB, D BLOB, E BLOB,
F BLOB, G BLOB, H BLOB,
PRIMARY KEY (B(767), C(767), D(767), E(767), A),
INDEX (A)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t1_purge VALUES (1,
REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766));
CREATE TABLE t2_purge (
A INT PRIMARY KEY,
B BLOB, C BLOB, D BLOB, E BLOB,
F BLOB, G BLOB, H BLOB, I BLOB,
J BLOB, K BLOB, L BLOB,
INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t2_purge VALUES (1,
REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766), REPEAT('i', 766),
REPEAT('j', 766), REPEAT('k', 766), REPEAT('l', 766));
CREATE TABLE t3_purge (
A INT,
B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
F VARCHAR(800), G VARCHAR(800), H VARCHAR(800),
PRIMARY KEY (B(767), C(767), D(767), E(767), A),
INDEX (A)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t3_purge SELECT * FROM t1_purge;
CREATE TABLE t4_purge (
A INT PRIMARY KEY,
B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
F VARCHAR(800), G VARCHAR(800), H VARCHAR(800), I VARCHAR(800),
J VARCHAR(800), K VARCHAR(800), L VARCHAR(800),
INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t4_purge SELECT * FROM t2_purge;
# This would trigger the failure (Bug #12429576)
# if purge gets a chance to run before DROP TABLE t1_purge, ....
DELETE FROM t1_purge;
DELETE FROM t2_purge;
DELETE FROM t3_purge;
DELETE FROM t4_purge;
eval set global innodb_file_per_table=$per_table;
eval set global innodb_file_format=$format;
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
commit;
@ -360,8 +419,6 @@ disconnect b;
drop table t1;
let $per_table=`select @@innodb_file_per_table`;
let $format=`select @@innodb_file_format`;
set global innodb_file_per_table=on;
set global innodb_file_format='Barracuda';
# Test creating a table that could lead to undo log overflow.
@ -557,6 +614,7 @@ disconnect a;
disconnect b;
DROP TABLE t1;
DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;
#
# restore environment to the state it was before this test execution

View file

@ -1,5 +1,5 @@
#
# Test of different EXPLAIN's
# Test of different EXPLAINs
--disable_warnings
drop table if exists t1;
@ -157,11 +157,12 @@ CREATE TABLE t1 (f1 INT);
SELECT @@session.sql_mode INTO @old_sql_mode;
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
# EXPLAIN EXTENDED (with subselect). used to crash. should give NOTICE.
--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS
# EXPLAIN EXTENDED (with subselect). used to crash.
# This is actually a valid query for this sql_mode,
# but it was transformed in such a way that it failed, see
# Bug#12329653 - EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
EXPLAIN EXTENDED SELECT 1 FROM t1
WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
SHOW WARNINGS;
SET SESSION sql_mode=@old_sql_mode;

View file

@ -0,0 +1 @@
--secure_file_priv=$MYSQL_TMP_DIR

View file

@ -0,0 +1,79 @@
#
# Bug58747 breaks secure_file_priv+not secure yet+still accesses other folders
#
# we do the windows specific relative directory testing
--source include/windows.inc
CREATE TABLE t1 (c1 longtext);
INSERT INTO t1 values ('a');
LET $MYSQL_TMP_DIR_UCASE= `SELECT upper('$MYSQL_TMP_DIR')`;
LET $MYSQL_TMP_DIR_LCASE= `SELECT lower('$MYSQL_TMP_DIR')`;
#create the file
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR/B11764517.tmp';
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
show global variables like 'secure_file_priv';
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval SELECT load_file('$MYSQL_TMP_DIR\\\\B11764517.tmp') AS x;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval SELECT load_file('$MYSQL_TMP_DIR/B11764517.tmp') AS x;
--replace_result $MYSQL_TMP_DIR_UCASE MYSQL_TMP_DIR_UCASE
eval SELECT load_file('$MYSQL_TMP_DIR_UCASE/B11764517.tmp') AS x;
--replace_result $MYSQL_TMP_DIR_LCASE MYSQL_TMP_DIR_LCASE
eval SELECT load_file('$MYSQL_TMP_DIR_LCASE/B11764517.tmp') AS x;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval SELECT load_file('$MYSQL_TMP_DIR\\\\..a..\\\\..\\\\..\\\\B11764517.tmp') AS x;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval LOAD DATA INFILE '$MYSQL_TMP_DIR\\\\B11764517.tmp' INTO TABLE t1;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval LOAD DATA INFILE '$MYSQL_TMP_DIR/B11764517.tmp' INTO TABLE t1;
--replace_result $MYSQL_TMP_DIR_UCASE MYSQL_TMP_DIR_UCASE
eval LOAD DATA INFILE '$MYSQL_TMP_DIR_UCASE/B11764517.tmp' INTO TABLE t1;
--replace_result $MYSQL_TMP_DIR_LCASE MYSQL_TMP_DIR_LCASE
eval LOAD DATA INFILE '$MYSQL_TMP_DIR_LCASE/B11764517.tmp' INTO TABLE t1;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
--error ER_OPTION_PREVENTS_STATEMENT
eval LOAD DATA INFILE "$MYSQL_TMP_DIR\\\\..a..\\\\..\\\\..\\\\B11764517.tmp" into table t1;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
--error ER_OPTION_PREVENTS_STATEMENT
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR\\\\..a..\\\\..\\\\..\\\\B11764517-2.tmp';
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR\\\\B11764517-2.tmp';
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR/B11764517-3.tmp';
--replace_result $MYSQL_TMP_DIR_UCASE MYSQL_TMP_DIR_UCASE
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR_UCASE/B11764517-4.tmp';
--replace_result $MYSQL_TMP_DIR_LCASE MYSQL_TMP_DIR_LCASE
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR_LCASE/B11764517-5.tmp';
--error 0,1
--remove_file $MYSQL_TMP_DIR/B11764517.tmp;
--error 0,1
--remove_file $MYSQL_TMP_DIR/B11764517-2.tmp;
--error 0,1
--remove_file $MYSQL_TMP_DIR/B11764517-3.tmp;
--error 0,1
--remove_file $MYSQL_TMP_DIR/B11764517-4.tmp;
--error 0,1
--remove_file $MYSQL_TMP_DIR/B11764517-5.tmp;
DROP TABLE t1;

View file

@ -926,6 +926,43 @@ DROP DATABASE B48872;
--echo End of 5.0 tests.
--echo #
--echo # Bug#11882603 SELECT_ACL ON ANY COLUMN IN MYSQL.PROC ALLOWS TO SEE
--echo # DEFINITION OF ANY ROUTINE.
--echo #
--disable_warnings
DROP DATABASE IF EXISTS db1;
--enable_warnings
CREATE DATABASE db1;
CREATE PROCEDURE db1.p1() SELECT 1;
CREATE USER user2@localhost IDENTIFIED BY '';
GRANT SELECT(db) ON mysql.proc TO user2@localhost;
--echo # Connection con2 as user2
connect (con2, localhost, user2);
--echo # The statement below before disclosed info from body_utf8 column.
--error ER_SP_DOES_NOT_EXIST
SHOW CREATE PROCEDURE db1.p1;
--echo # Check that SHOW works with SELECT grant on whole table
--echo # Connection default
connection default;
GRANT SELECT ON mysql.proc TO user2@localhost;
--echo # Connection con2
connection con2;
--echo # This should work
SHOW CREATE PROCEDURE db1.p1;
--echo # Connection default
connection default;
disconnect con2;
DROP USER user2@localhost;
DROP DATABASE db1;
# Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc

View file

@ -3393,6 +3393,39 @@ ORDER BY outr.pk;
DROP TABLE t1,t2;
--echo #
--echo # Bug#12329653
--echo # EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
--echo #
CREATE TABLE t1(a1 int);
INSERT INTO t1 VALUES (1),(2);
SELECT @@session.sql_mode INTO @old_sql_mode;
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
## First a simpler query, illustrating the transformation
## '1 < some (...)' => '1 < max(...)'
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
## The query which made the server crash.
PREPARE stmt FROM
'SELECT 1 UNION ALL
SELECT 1 FROM t1
ORDER BY
(SELECT 1 FROM t1 AS t1_0
WHERE 1 < SOME (SELECT a1 FROM t1)
)' ;
--error ER_SUBQUERY_NO_1_ROW
EXECUTE stmt ;
--error ER_SUBQUERY_NO_1_ROW
EXECUTE stmt ;
SET SESSION sql_mode=@old_sql_mode;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
--echo End of 5.0 tests.

View file

@ -146,24 +146,23 @@ int my_realpath(char *to, const char *filename, myf MyFlags)
result= -1;
}
DBUG_RETURN(result);
#else
#ifdef _WIN32
int ret= GetFullPathName(filename,FN_REFLEN,
to,
NULL);
#elif defined(_WIN32)
int ret= GetFullPathName(filename,FN_REFLEN, to, NULL);
if (ret == 0 || ret > FN_REFLEN)
{
if (ret > FN_REFLEN)
my_errno= ENAMETOOLONG;
else
my_errno= EACCES;
my_errno= (ret > FN_REFLEN) ? ENAMETOOLONG : GetLastError();
if (MyFlags & MY_WME)
my_error(EE_REALPATH, MYF(0), filename, my_errno);
return -1;
/*
GetFullPathName didn't work : use my_load_path() which is a poor
substitute original name but will at least be able to resolve
paths that starts with '.'.
*/
my_load_path(to, filename, NullS);
return -1;
}
#else
my_load_path(to, filename, NullS);
#endif
return 0;
#endif
}

View file

@ -4466,14 +4466,14 @@ mark_non_agg_field:
SELECT_LEX *select_lex= cached_table ?
cached_table->select_lex : context->select_lex;
if (!thd->lex->in_sum_func)
select_lex->full_group_by_flag|= NON_AGG_FIELD_USED;
select_lex->set_non_agg_field_used(true);
else
{
if (outer_fixed)
thd->lex->in_sum_func->outer_fields.push_back(this);
else if (thd->lex->in_sum_func->nest_level !=
thd->lex->current_select->nest_level)
select_lex->full_group_by_flag|= NON_AGG_FIELD_USED;
select_lex->set_non_agg_field_used(true);
}
}
return FALSE;

View file

@ -1016,6 +1016,14 @@ Item_in_subselect::single_value_transformer(JOIN *join,
it.replace(item);
}
DBUG_EXECUTE("where",
print_where(item, "rewrite with MIN/MAX", QT_ORDINARY););
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
{
DBUG_ASSERT(select_lex->non_agg_field_used());
select_lex->set_non_agg_field_used(false);
}
save_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
/*

View file

@ -247,10 +247,10 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
in_sum_func->outer_fields.push_back(field);
}
else
sel->full_group_by_flag|= NON_AGG_FIELD_USED;
sel->set_non_agg_field_used(true);
}
if (sel->nest_level > aggr_level &&
(sel->full_group_by_flag & SUM_FUNC_USED) &&
(sel->agg_func_used()) &&
!sel->group_list.elements)
{
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
@ -259,7 +259,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
}
}
}
aggr_sel->full_group_by_flag|= SUM_FUNC_USED;
aggr_sel->set_agg_func_used(true);
update_used_tables();
thd->lex->in_sum_func= in_sum_func;
return FALSE;

View file

@ -1475,13 +1475,6 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
bool allow_null_cond, int *error);
extern Item **not_found_item;
/*
A set of constants used for checking non aggregated fields and sum
functions mixture in the ONLY_FULL_GROUP_BY_MODE.
*/
#define NON_AGG_FIELD_USED 1
#define SUM_FUNC_USED 2
/*
This enumeration type is used only by the function find_item_in_list
to return the info on how an item has been resolved against a list

View file

@ -8973,12 +8973,15 @@ fn_format_relative_to_data_home(char * to, const char *name,
bool is_secure_file_path(char *path)
{
char buff1[FN_REFLEN], buff2[FN_REFLEN];
size_t opt_secure_file_priv_len;
/*
All paths are secure if opt_secure_file_path is 0
*/
if (!opt_secure_file_priv)
return TRUE;
opt_secure_file_priv_len= strlen(opt_secure_file_priv);
if (strlen(path) >= FN_REFLEN)
return FALSE;
@ -8996,11 +8999,24 @@ bool is_secure_file_path(char *path)
return FALSE;
}
convert_dirname(buff2, buff1, NullS);
if (strncmp(opt_secure_file_priv, buff2, strlen(opt_secure_file_priv)))
return FALSE;
if (!lower_case_file_system)
{
if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len))
return FALSE;
}
else
{
if (files_charset_info->coll->strnncoll(files_charset_info,
(uchar *) buff2, strlen(buff2),
(uchar *) opt_secure_file_priv,
opt_secure_file_priv_len,
TRUE))
return FALSE;
}
return TRUE;
}
static int fix_paths(void)
{
char buff[FN_REFLEN],*pos;

View file

@ -2403,7 +2403,8 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access)
bzero((char*) &tables,sizeof(tables));
tables.db= (char*) "mysql";
tables.table_name= tables.alias= (char*) "proc";
*full_access= (!check_table_access(thd, SELECT_ACL, &tables, 1, TRUE) ||
*full_access= ((!check_table_access(thd, SELECT_ACL, &tables, 1, TRUE) &&
(tables.grant.privilege & SELECT_ACL) != 0) ||
(!strcmp(sp->m_definer_user.str,
thd->security_ctx->priv_user) &&
!strcmp(sp->m_definer_host.str,

View file

@ -21,23 +21,10 @@
#include "mysql_priv.h"
#ifdef HAVE_OPENSSL
/*
Without SSL the handshake consists of one packet. This packet
has both client capabilites and scrambled password.
With SSL the handshake might consist of two packets. If the first
packet (client capabilities) has CLIENT_SSL flag set, we have to
switch to SSL and read the second packet. The scrambled password
is in the second packet and client_capabilites field will be ignored.
Maybe it is better to accept flags other than CLIENT_SSL from the
second packet?
*/
#define SSL_HANDSHAKE_SIZE 2
#define NORMAL_HANDSHAKE_SIZE 6
#define MIN_HANDSHAKE_SIZE 2
#else
#define MIN_HANDSHAKE_SIZE 6
#endif /* HAVE_OPENSSL */
/** Size of the header fields of an authentication packet. */
#define AUTH_PACKET_HEADER_SIZE_PROTO_41 32
#define AUTH_PACKET_HEADER_SIZE_PROTO_40 5
#define AUTH_PACKET_HEADER_SIZE_CONNJ_SSL 4
#ifdef __WIN__
extern void win_install_sigabrt_handler();
@ -822,6 +809,14 @@ static int check_connection(THD *thd)
ulong pkt_len= 0;
char *end;
bool packet_has_required_size= false;
char *db;
size_t db_len;
char *passwd;
size_t passwd_len;
char *user;
size_t user_len;
DBUG_PRINT("info",
("New connection received on %s", vio_description(net->vio)));
#ifdef SIGNAL_WITH_VIO_CLOSE
@ -930,8 +925,7 @@ static int check_connection(THD *thd)
/* At this point we write connection message and read reply */
if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0,
(uchar*) buff, (size_t) (end-buff)) ||
(pkt_len= my_net_read(net)) == packet_error ||
pkt_len < MIN_HANDSHAKE_SIZE)
(pkt_len= my_net_read(net)) == packet_error)
{
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0));
@ -946,22 +940,82 @@ static int check_connection(THD *thd)
if (thd->packet.alloc(thd->variables.net_buffer_length))
return 1; /* The error is set by alloc(). */
thd->client_capabilities= uint2korr(net->read_pos);
uint charset_code= 0;
end= (char *)net->read_pos;
/*
In order to safely scan a head for '\0' string terminators
we must keep track of how many bytes remain in the allocated
buffer or we might read past the end of the buffer.
*/
size_t bytes_remaining_in_packet= pkt_len;
/*
Peek ahead on the client capability packet and determine which version of
the protocol should be used.
*/
if (bytes_remaining_in_packet < 2)
goto error;
thd->client_capabilities= uint2korr(end);
/*
Connector/J only sends client capabilities (4 bytes) before starting SSL
negotiation so we don't have char_set and other information for client in
packet read. In that case, skip reading those information. The below code
is patch for this.
*/
if(bytes_remaining_in_packet == AUTH_PACKET_HEADER_SIZE_CONNJ_SSL &&
(thd->client_capabilities & CLIENT_SSL))
{
thd->client_capabilities= uint4korr(end);
thd->max_client_packet_length= global_system_variables.max_allowed_packet;
charset_code= default_charset_info->number;
end+= AUTH_PACKET_HEADER_SIZE_CONNJ_SSL;
bytes_remaining_in_packet-= AUTH_PACKET_HEADER_SIZE_CONNJ_SSL;
goto skip_to_ssl;
}
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
packet_has_required_size= bytes_remaining_in_packet >=
AUTH_PACKET_HEADER_SIZE_PROTO_41;
else
packet_has_required_size= bytes_remaining_in_packet >=
AUTH_PACKET_HEADER_SIZE_PROTO_40;
if (!packet_has_required_size)
goto error;
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
thd->max_client_packet_length= uint4korr(net->read_pos+4);
DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
if (thd_init_client_charset(thd, (uint) net->read_pos[8]))
return 1;
thd->update_charset();
end= (char*) net->read_pos+32;
thd->client_capabilities= uint4korr(end);
thd->max_client_packet_length= uint4korr(end + 4);
charset_code= (uint)(uchar)*(end + 8);
/*
Skip 23 remaining filler bytes which have no particular meaning.
*/
end+= AUTH_PACKET_HEADER_SIZE_PROTO_41;
bytes_remaining_in_packet-= AUTH_PACKET_HEADER_SIZE_PROTO_41;
}
else
{
thd->max_client_packet_length= uint3korr(net->read_pos+2);
end= (char*) net->read_pos+5;
thd->client_capabilities= uint2korr(end);
thd->max_client_packet_length= uint3korr(end + 2);
end+= AUTH_PACKET_HEADER_SIZE_PROTO_40;
bytes_remaining_in_packet-= AUTH_PACKET_HEADER_SIZE_PROTO_40;
/**
Old clients didn't have their own charset. Instead the assumption
was that they used what ever the server used.
*/
charset_code= default_charset_info->number;
}
skip_to_ssl:
DBUG_PRINT("info", ("client_character_set: %u", charset_code));
if (thd_init_client_charset(thd, charset_code))
goto error;
thd->update_charset();
/*
Disable those bits which are not supported by the server.
This is a precautionary measure, if the client lies. See Bug#27944.
@ -972,43 +1026,64 @@ static int check_connection(THD *thd)
thd->variables.sql_mode|= MODE_IGNORE_SPACE;
#ifdef HAVE_OPENSSL
DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
/*
If client requested SSL then we must stop parsing, try to switch to SSL,
and wait for the client to send a new handshake packet.
The client isn't expected to send any more bytes until SSL is initialized.
*/
if (thd->client_capabilities & CLIENT_SSL)
{
/* Do the SSL layering. */
if (!ssl_acceptor_fd)
{
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0));
return 1;
}
goto error;
DBUG_PRINT("info", ("IO layer change in progress..."));
if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
{
DBUG_PRINT("error", ("Failed to accept new SSL connection"));
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0));
return 1;
goto error;
}
DBUG_PRINT("info", ("Reading user information over SSL layer"));
if ((pkt_len= my_net_read(net)) == packet_error ||
pkt_len < NORMAL_HANDSHAKE_SIZE)
if ((pkt_len= my_net_read(net)) == packet_error)
{
DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
pkt_len));
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0));
return 1;
goto error;
}
/*
A new packet was read and the statistics reflecting the remaining bytes
in the packet must be updated.
*/
bytes_remaining_in_packet= pkt_len;
/*
After the SSL handshake is performed the client resends the handshake
packet but because of legacy reasons we chose not to parse the packet
fields a second time and instead only assert the length of the packet.
*/
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
packet_has_required_size= bytes_remaining_in_packet >=
AUTH_PACKET_HEADER_SIZE_PROTO_41;
end= (char *)net->read_pos + AUTH_PACKET_HEADER_SIZE_PROTO_41;
bytes_remaining_in_packet -= AUTH_PACKET_HEADER_SIZE_PROTO_41;
}
else
{
packet_has_required_size= bytes_remaining_in_packet >=
AUTH_PACKET_HEADER_SIZE_PROTO_40;
end= (char *)net->read_pos + AUTH_PACKET_HEADER_SIZE_PROTO_40;
bytes_remaining_in_packet -= AUTH_PACKET_HEADER_SIZE_PROTO_40;
}
if (!packet_has_required_size)
goto error;
}
#endif /* HAVE_OPENSSL */
if (end > (char *)net->read_pos + pkt_len)
{
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0));
return 1;
}
if (thd->client_capabilities & CLIENT_INTERACTIVE)
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
@ -1028,29 +1103,17 @@ static int check_connection(THD *thd)
else
get_string= get_40_protocol_string;
/*
In order to safely scan a head for '\0' string terminators
we must keep track of how many bytes remain in the allocated
buffer or we might read past the end of the buffer.
*/
size_t bytes_remaining_in_packet= pkt_len - (end - (char *)net->read_pos);
size_t user_len;
char *user= get_string(&end, &bytes_remaining_in_packet, &user_len);
user= get_string(&end, &bytes_remaining_in_packet, &user_len);
if (user == NULL)
{
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0));
return 1;
}
goto error;
/*
Old clients send a null-terminated string as password; new clients send
the size (1 byte) + string (not null-terminated). Hence in case of empty
password both send '\0'.
*/
size_t passwd_len= 0;
char *passwd= NULL;
passwd_len= 0;
passwd= NULL;
if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
{
@ -1069,24 +1132,16 @@ static int check_connection(THD *thd)
}
if (passwd == NULL)
{
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0));
return 1;
}
goto error;
size_t db_len= 0;
char *db= NULL;
db_len= 0;
db= NULL;
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
{
db= get_string(&end, &bytes_remaining_in_packet, &db_len);
if (db == NULL)
{
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0));
return 1;
}
goto error;
}
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
@ -1134,11 +1189,14 @@ static int check_connection(THD *thd)
user[user_len]= '\0';
}
if (thd->main_security_ctx.user)
x_free(thd->main_security_ctx.user);
if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
return 1; /* The error is set by my_strdup(). */
return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
error:
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0));
return 1;
}
@ -1388,3 +1446,4 @@ end_thread:
}
}
#endif /* EMBEDDED_LIBRARY */

View file

@ -1623,6 +1623,8 @@ void st_select_lex::init_query()
nest_level= 0;
link_next= 0;
lock_option= TL_READ_DEFAULT;
m_non_agg_field_used= false;
m_agg_func_used= false;
}
void st_select_lex::init_select()
@ -1653,7 +1655,8 @@ void st_select_lex::init_select()
non_agg_fields.empty();
cond_value= having_value= Item::COND_UNDEF;
inner_refs_list.empty();
full_group_by_flag= 0;
m_non_agg_field_used= false;
m_agg_func_used= false;
}
/*

View file

@ -715,16 +715,7 @@ public:
joins on the right.
*/
List<String> *prev_join_using;
/*
Bitmap used in the ONLY_FULL_GROUP_BY_MODE to prevent mixture of aggregate
functions and non aggregated fields when GROUP BY list is absent.
Bits:
0 - non aggregated fields are used in this select,
defined as NON_AGG_FIELD_USED.
1 - aggregate functions are used in this select,
defined as SUM_FUNC_USED.
*/
uint8 full_group_by_flag;
void init_query();
void init_select();
st_select_lex_unit* master_unit();
@ -832,7 +823,22 @@ public:
void clear_index_hints(void) { index_hints= NULL; }
private:
/*
For MODE_ONLY_FULL_GROUP_BY we need to maintain two flags:
- Non-aggregated fields are used in this select.
- Aggregate functions are used in this select.
In MODE_ONLY_FULL_GROUP_BY only one of these may be true.
*/
bool non_agg_field_used() const { return m_non_agg_field_used; }
bool agg_func_used() const { return m_agg_func_used; }
void set_non_agg_field_used(bool val) { m_non_agg_field_used= val; }
void set_agg_func_used(bool val) { m_agg_func_used= val; }
private:
bool m_non_agg_field_used;
bool m_agg_func_used;
/* current index hint kind. used in filling up index_hints */
enum index_hint_type current_index_hint_type;
index_clause_map current_index_hint_clause;

View file

@ -350,21 +350,21 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
#if !defined(__WIN__) && ! defined(__NETWARE__)
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(MY_WME)))
DBUG_RETURN(TRUE);
if (!my_stat(name, &stat_info, MYF(MY_WME)))
DBUG_RETURN(TRUE);
// if we are not in slave thread, the file must be:
if (!thd->slave_thread &&
!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
((stat_info.st_mode & S_IFREG) == S_IFREG ||
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
((stat_info.st_mode & S_IFREG) == S_IFREG || // and a regular file
(stat_info.st_mode & S_IFIFO) == S_IFIFO))) // or FIFO
{
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
DBUG_RETURN(TRUE);
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
DBUG_RETURN(TRUE);
}
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
is_fifo = 1;
is_fifo= 1;
#endif
if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)

View file

@ -930,9 +930,6 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
const char *save_where;
char* db_name;
char db_name_string[FN_REFLEN];
bool save_use_only_table_context;
uint8 saved_full_group_by_flag;
nesting_map saved_allow_sum_func;
DBUG_ENTER("fix_fields_part_func");
if (part_info->fixed)
@ -999,23 +996,26 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
of interesting side effects, both desirable and undesirable.
*/
save_use_only_table_context= thd->lex->use_only_table_context;
thd->lex->use_only_table_context= TRUE;
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
saved_full_group_by_flag= thd->lex->current_select->full_group_by_flag;
saved_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func= 0;
{
const bool save_use_only_table_context= thd->lex->use_only_table_context;
thd->lex->use_only_table_context= TRUE;
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
const bool save_agg_field= thd->lex->current_select->non_agg_field_used();
const bool save_agg_func= thd->lex->current_select->agg_func_used();
const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func= 0;
error= func_expr->fix_fields(thd, (Item**)&func_expr);
error= func_expr->fix_fields(thd, (Item**)&func_expr);
/*
Restore full_group_by_flag and allow_sum_func,
fix_fields should not affect mysql_select later, see Bug#46923.
*/
thd->lex->current_select->full_group_by_flag= saved_full_group_by_flag;
thd->lex->allow_sum_func= saved_allow_sum_func;
thd->lex->use_only_table_context= save_use_only_table_context;
/*
Restore agg_field/agg_func and allow_sum_func,
fix_fields should not affect mysql_select later, see Bug#46923.
*/
thd->lex->current_select->set_non_agg_field_used(save_agg_field);
thd->lex->current_select->set_agg_func_used(save_agg_func);
thd->lex->allow_sum_func= saved_allow_sum_func;
thd->lex->use_only_table_context= save_use_only_table_context;
}
context->table_list= save_table_list;
context->first_name_resolution_table= save_first_table;

View file

@ -426,19 +426,18 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
int res;
nesting_map save_allow_sum_func=thd->lex->allow_sum_func ;
/*
Need to save the value, so we can turn off only the new NON_AGG_FIELD
Need to save the value, so we can turn off only any new non_agg_field_used
additions coming from the WHERE
*/
uint8 saved_flag= thd->lex->current_select->full_group_by_flag;
const bool saved_non_agg_field_used=
thd->lex->current_select->non_agg_field_used();
DBUG_ENTER("setup_without_group");
thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
res= setup_conds(thd, tables, leaves, conds);
/* it's not wrong to have non-aggregated columns in a WHERE */
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
thd->lex->current_select->full_group_by_flag= saved_flag |
(thd->lex->current_select->full_group_by_flag & ~NON_AGG_FIELD_USED);
thd->lex->current_select->set_non_agg_field_used(saved_non_agg_field_used);
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
@ -644,7 +643,8 @@ JOIN::prepare(Item ***rref_pointer_array,
aggregate functions with implicit grouping (there is no GROUP BY).
*/
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !group_list &&
select_lex->full_group_by_flag == (NON_AGG_FIELD_USED | SUM_FUNC_USED))
select_lex->non_agg_field_used() &&
select_lex->agg_func_used())
{
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));

View file

@ -37,6 +37,11 @@
* row/row0row.c, row/row0vers.c, trx/trx0rec.c:
Instrumentation for Bug#12612184 Race condition in row_upd_clust_rec()
2011-05-19 The InnoDB Team
* row/row0row.c:
Fix Bug#12429576 Assertion failure on purge of column prefix index
2011-04-07 The InnoDB Team
* handler/ha_innodb.cc, handler/ha_innodb.h, handler/handler0alter.cc:

View file

@ -156,8 +156,6 @@ row_build_index_entry(
each off-page column. */
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
len -= BTR_EXTERN_FIELD_REF_SIZE;
ut_a(ind_field->prefix_len <= len
|| dict_index_is_clust(index));
}
/* If a column prefix index, take only the prefix. */

View file

@ -1,60 +0,0 @@
-- Copyright (c) 2005 MySQL AB
-- Use is subject to license terms.
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; version 2 of the License.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
CREATE DATABASE IF NOT EXISTS BANK default charset=latin1 default collate=latin1_bin;
USE BANK;
DROP TABLE IF EXISTS GL;
CREATE TABLE GL ( TIME BIGINT UNSIGNED NOT NULL,
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
BALANCE INT UNSIGNED NOT NULL,
DEPOSIT_COUNT INT UNSIGNED NOT NULL,
DEPOSIT_SUM INT UNSIGNED NOT NULL,
WITHDRAWAL_COUNT INT UNSIGNED NOT NULL,
WITHDRAWAL_SUM INT UNSIGNED NOT NULL,
PURGED INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (TIME,ACCOUNT_TYPE))
ENGINE = NDB;
DROP TABLE IF EXISTS ACCOUNT;
CREATE TABLE ACCOUNT ( ACCOUNT_ID INT UNSIGNED NOT NULL,
OWNER INT UNSIGNED NOT NULL,
BALANCE INT UNSIGNED NOT NULL,
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (ACCOUNT_ID))
ENGINE = NDB;
DROP TABLE IF EXISTS TRANSACTION;
CREATE TABLE TRANSACTION ( TRANSACTION_ID BIGINT UNSIGNED NOT NULL,
ACCOUNT INT UNSIGNED NOT NULL,
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
OTHER_ACCOUNT INT UNSIGNED NOT NULL,
TRANSACTION_TYPE INT UNSIGNED NOT NULL,
TIME BIGINT UNSIGNED NOT NULL,
AMOUNT INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (TRANSACTION_ID,ACCOUNT))
ENGINE = NDB;
DROP TABLE IF EXISTS SYSTEM_VALUES;
CREATE TABLE SYSTEM_VALUES ( SYSTEM_VALUES_ID INT UNSIGNED NOT NULL,
VALUE BIGINT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (SYSTEM_VALUES_ID))
ENGINE = NDB;
DROP TABLE IF EXISTS ACCOUNT_TYPE;
CREATE TABLE ACCOUNT_TYPE ( ACCOUNT_TYPE_ID INT UNSIGNED NOT NULL,
DESCRIPTION CHAR(64) NOT NULL,
PRIMARY KEY USING HASH (ACCOUNT_TYPE_ID))
ENGINE = NDB;

View file

@ -1,25 +0,0 @@
-- Copyright (c) 2005 MySQL AB
-- Use is subject to license terms.
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; version 2 of the License.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
create database if not exists TEST_DB;
use TEST_DB;
drop table if exists T1;
create table T1 (KOL1 int unsigned not null,
KOL2 int unsigned not null,
KOL3 int unsigned not null,
KOL4 int unsigned not null,
KOL5 int unsigned not null,
primary key using hash(KOL1)) engine=ndb;

View file

@ -1,196 +0,0 @@
# Copyright (C) 2005 MySQL AB
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; version 2
# of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA
use strict;
use IO::Socket;
use DBI;
# mgm info
my $mgmhost = "localhost";
my $mgmport = 38101;
# location of ndb_x_fs
my $datadir = "c2";
my @schemafiles = <$datadir/ndb_*_fs/D[12]/DBDICT/P0.SchemaLog>;
@schemafiles or die "no schemafiles in $datadir";
my $dsn;
$dsn = "dbi:mysql:test:localhost;port=38100";
# this works better for me
my $cnf = $ENV{MYSQL_HOME} . "/var/my.cnf";
$dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$cnf";
my $dbh;
$dbh = DBI->connect($dsn, 'root', undef, { RaiseError => 0, PrintError => 0 });
$dbh or die $DBI::errstr;
# mgm commands
my $mgm = undef;
sub mgmconnect {
$mgm = IO::Socket::INET->new(
Proto => "tcp",
PeerHost => $mgmhost,
PeerPort => $mgmport);
$mgm or die "connect to mgm failed: $!";
$mgm->autoflush(1);
};
mgmconnect();
warn "connected to mgm $mgmhost $mgmport\n";
my $nodeinfo = {};
sub getnodeinfo {
$nodeinfo = {};
$mgm->print("get status\n");
$mgm->print("\n");
while (defined($_ = $mgm->getline)) {
/^node\s+status/ && last;
}
while (defined($_ = $mgm->getline)) {
/^\s*$/ && last;
/^node\.(\d+)\.(\w+):\s*(\S+)/ && ($nodeinfo->{$1}{$2} = $3);
}
}
getnodeinfo();
my @dbnode = ();
for my $n (keys %$nodeinfo) {
my $p = $nodeinfo->{$n};
($p->{type} eq 'NDB') && push(@dbnode, $n);
}
@dbnode = sort { $a <=> $b } @dbnode;
@dbnode or die "mgm error, found no db nodes";
warn "db nodes: @dbnode\n";
sub restartnode {
my($n, $initialstart) = @_;
warn "restart node $n initialstart=$initialstart\n";
$mgm->print("restart node\n");
$mgm->print("node: $n\n");
$mgm->print("initialstart: $initialstart\n");
$mgm->print("\n");
while (1) {
sleep 5;
getnodeinfo();
my $status = $nodeinfo->{$n}{status};
my $sp = $nodeinfo->{$n}{startphase};
warn "node $n status: $status sp: $sp\n";
last if $status eq 'STARTED';
}
}
sub restartall {
warn "restart all\n";
$mgm->print("restart all\n");
$mgm->print("\n");
while (1) {
sleep 5;
getnodeinfo();
my $ok = 1;
for my $n (@dbnode) {
my $status = $nodeinfo->{$n}{status};
my $sp = $nodeinfo->{$n}{startphase};
warn "node $n status: $status sp: $sp\n";
$ok = 0 if $status ne 'STARTED';
}
last if $ok;
}
}
# the sql stuff
my $maxtab = 300;
my @tab = ();
sub create {
my($n) = @_;
my $sql = "create table t$n (a int primary key, b varchar(20), key (b)) engine=ndb";
warn "create t$n\n";
$dbh->do($sql) or die "$sql\n$DBI::errstr";
}
sub drop {
my($n) = @_;
my $sql = "drop table t$n";
warn "drop t$n\n";
$dbh->do($sql) or die "$sql\n$DBI::errstr";
}
sub dropall {
for my $n (0..($maxtab-1)) {
my $sql = "drop table if exists t$n";
$dbh->do($sql) or die "$sql\n$DBI::errstr";
}
}
sub createdrop {
my $n = int(rand($maxtab));
if (! $tab[$n]) {
create($n);
$tab[$n] = 1;
} else {
drop($n);
$tab[$n] = 0;
}
}
sub checkschemafiles {
system("printSchemaFile -ce @schemafiles");
$? == 0 or die "schemafiles check failed";
}
sub randomrestart {
my($k) = @_;
my $s = int(rand(500));
if ($s < 2) {
my $i = $k % scalar(@dbnode);
my $n = $dbnode[$i];
my $initialstart = ($s < 1 ? 0 : 1);
restartnode($n, $initialstart);
return 1;
}
if ($s < 3) {
restartall();
return 1;
}
return 0;
}
# deterministic
srand(1);
warn "drop any old tables\n";
dropall();
my $loop = 1000000;
for my $k (0..($loop-1)) {
warn "$k\n";
createdrop();
checkschemafiles();
if (randomrestart($k)) {
checkschemafiles();
}
}
$dbh->disconnect or die $DBI::errstr;
# vim: set sw=2:

View file

@ -1,235 +0,0 @@
# Copyright (C) 2005 MySQL AB
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; version 2
# of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA
#
# test range scan bounds
# give option --all to test all cases
# set MYSQL_HOME to installation top
#
use strict;
use integer;
use Getopt::Long;
use DBI;
my $opt_all = 0;
my $opt_cnt = 5;
my $opt_verbose = 0;
GetOptions("all" => \$opt_all, "cnt=i" => \$opt_cnt, "verbose" => \$opt_verbose)
or die "options are: --all --cnt=N --verbose";
my $mysql_home = $ENV{MYSQL_HOME};
defined($mysql_home) or die "no MYSQL_HOME";
my $dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$mysql_home/var/my.cnf";
my $opts = { RaiseError => 0, PrintError => 0, AutoCommit => 1, };
my $dbh;
my $sth;
my $sql;
$dbh = DBI->connect($dsn, "root", undef, $opts) or die $DBI::errstr;
my $table = 't';
$sql = "drop table if exists $table";
$dbh->do($sql) or die $DBI::errstr;
sub cut ($$$) {
my($op, $key, $val) = @_;
$op = '==' if $op eq '=';
my(@w) = @$val;
eval "\@w = grep(\$_ $op $key, \@w)";
$@ and die $@;
return [ @w ];
}
sub mkdummy ($) {
my ($val) = @_;
return {
'dummy' => 1,
'exp' => '9 = 9',
'res' => $val,
};
}
sub mkone ($$$$) {
my($col, $op, $key, $val) = @_;
my $res = cut($op, $key, $val);
return {
'exp' => "$col $op $key",
'res' => $res,
};
}
sub mktwo ($$$$$$) {
my($col, $op1, $key1, $op2, $key2, $val) = @_;
my $res = cut($op2, $key2, cut($op1, $key1, $val));
return {
'exp' => "$col $op1 $key1 and $col $op2 $key2",
'res' => $res,
};
}
sub mkall ($$$$) {
my($col, $key1, $key2, $val) = @_;
my @a = ();
my $p = mkdummy($val);
push(@a, $p) if $opt_all;
my @ops = qw(< <= = >= >);
for my $op (@ops) {
my $p = mkone($col, $op, $key1, $val);
push(@a, $p) if $opt_all || @{$p->{res}} != 0;
}
my @ops1 = $opt_all ? @ops : qw(= >= >);
my @ops2 = $opt_all ? @ops : qw(<= <);
for my $op1 (@ops1) {
for my $op2 (@ops2) {
my $p = mktwo($col, $op1, $key1, $op2, $key2, $val);
push(@a, $p) if $opt_all || @{$p->{res}} != 0;
}
}
warn scalar(@a)." cases\n" if $opt_verbose;
return \@a;
}
my $casecnt = 0;
sub verify ($$$) {
my($sql, $ord, $res) = @_;
warn "$sql\n" if $opt_verbose;
$sth = $dbh->prepare($sql) or die "prepare: $sql: $DBI::errstr";
$sth->execute() or die "execute: $sql: $DBI::errstr";
#
# BUG: execute can return success on error so check again
#
$sth->err and die "execute: $sql: $DBI::errstr";
my @out = ();
for my $b (@{$res->[0]}) {
for my $c (@{$res->[1]}) {
for my $d (@{$res->[2]}) {
push(@out, [$b, $c, $d]);
}
}
}
if ($ord) {
@out = sort {
$ord * ($a->[0] - $b->[0]) ||
$ord * ($a->[1] - $b->[1]) ||
$ord * ($a->[2] - $b->[2]) ||
0
} @out;
}
my $cnt = scalar @out;
my $n = 0;
while (1) {
my $row = $sth->fetchrow_arrayref;
$row || last;
@$row == 3 or die "bad row: $sql: @$row";
for my $v (@$row) {
$v =~ s/^\s+|\s+$//g;
$v =~ /^\d+$/ or die "bad value: $sql: $v";
}
if ($ord) {
my $out = $out[$n];
$row->[0] == $out->[0] &&
$row->[1] == $out->[1] &&
$row->[2] == $out->[2] or
die "$sql: row $n: got row @$row != @$out";
}
$n++;
}
$sth->err and die "fetch: $sql: $DBI::errstr";
$n == $cnt or die "verify: $sql: got row count $n != $cnt";
$casecnt++;
}
for my $nn ("bcd", "") {
my %nn;
for my $x (qw(b c d)) {
$nn{$x} = $nn =~ /$x/ ? "not null" : "null";
}
warn "create table\n";
$sql = <<EOF;
create table $table (
a int primary key,
b int $nn{b},
c int $nn{c},
d int $nn{d},
index (b, c, d)
) engine=ndb
EOF
$dbh->do($sql) or die $DBI::errstr;
warn "insert\n";
$sql = "insert into $table values(?, ?, ?, ?)";
$sth = $dbh->prepare($sql) or die $DBI::errstr;
my @val = (0..($opt_cnt-1));
my $v0 = 0;
for my $v1 (@val) {
for my $v2 (@val) {
for my $v3 (@val) {
$sth->bind_param(1, $v0) or die $DBI::errstr;
$sth->bind_param(2, $v1) or die $DBI::errstr;
$sth->bind_param(3, $v2) or die $DBI::errstr;
$sth->bind_param(4, $v3) or die $DBI::errstr;
$sth->execute or die $DBI::errstr;
$v0++;
}
}
}
warn "generate cases\n";
my $key1 = 1;
my $key2 = 3;
my $a1 = mkall('b', $key1, $key2, \@val);
my $a2 = mkall('c', $key1, $key2, \@val);
my $a3 = mkall('d', $key1, $key2, \@val);
warn "select\n";
for my $ord (0, +1, -1) {
my $orderby =
$ord == 0 ? "" :
$ord == +1 ? " order by b, c, d" :
$ord == -1 ? " order by b desc, c desc, d desc" : die "not here";
for my $p1 (@$a1) {
my $res = [ $p1->{res}, \@val, \@val ];
$sql = "select b, c, d from $table" .
" where $p1->{exp}" .
$orderby;
verify($sql, $ord, $res);
for my $p2 (@$a2) {
my $res = [ $p1->{res}, $p2->{res}, \@val ];
$sql = "select b, c, d from $table" .
" where $p1->{exp} and $p2->{exp}" .
$orderby;
verify($sql, $ord, $res);
for my $p3 (@$a3) {
my $res = [ $p1->{res}, $p2->{res}, $p3->{res} ];
$sql = "select b, c, d from $table" .
" where $p1->{exp} and $p2->{exp} and $p3->{exp}" .
$orderby;
verify($sql, $ord, $res);
}
}
}
}
warn "drop table\n";
$sql = "drop table $table";
$dbh->do($sql) or die $DBI::errstr;
}
warn "verified $casecnt cases\n";
warn "done\n";
# vim: set sw=2: