Merge mysql-5.0-bugteam into mysql-5.0
This commit is contained in:
commit
7e35139c8f
@ -259,6 +259,10 @@ get_one_option(int optid, const struct my_option *opt,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Run a command using the shell, storing its output in the supplied dynamic
|
||||
string.
|
||||
*/
|
||||
static int run_command(char* cmd,
|
||||
DYNAMIC_STRING *ds_res)
|
||||
{
|
||||
@ -331,36 +335,16 @@ static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Try to get the full path to this exceutable
|
||||
|
||||
Return 0 if path found
|
||||
|
||||
/**
|
||||
Look for the filename of given tool, with the presumption that it is in the
|
||||
same directory as mysql_upgrade and that the same executable-searching
|
||||
mechanism will be used when we run our sub-shells with popen() later.
|
||||
*/
|
||||
|
||||
static my_bool get_full_path_to_executable(char* path)
|
||||
static void find_tool(char *tool_executable_name, const char *tool_name,
|
||||
const char *self_name)
|
||||
{
|
||||
my_bool ret;
|
||||
DBUG_ENTER("get_full_path_to_executable");
|
||||
#ifdef __WIN__
|
||||
ret= (GetModuleFileName(NULL, path, FN_REFLEN) == 0);
|
||||
#else
|
||||
/* my_readlink returns 0 if a symlink was read */
|
||||
ret= (my_readlink(path, "/proc/self/exe", MYF(0)) != 0);
|
||||
/* Might also want to try with /proc/$$/exe if the above fails */
|
||||
#endif
|
||||
DBUG_PRINT("exit", ("path: %s", path));
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
char *last_fn_libchar;
|
||||
|
||||
|
||||
/*
|
||||
Look for the tool in the same directory as mysql_upgrade.
|
||||
*/
|
||||
|
||||
static void find_tool(char *tool_path, const char *tool_name)
|
||||
{
|
||||
char path[FN_REFLEN];
|
||||
DYNAMIC_STRING ds_tmp;
|
||||
DBUG_ENTER("find_tool");
|
||||
DBUG_PRINT("enter", ("progname: %s", my_progname));
|
||||
@ -368,77 +352,59 @@ static void find_tool(char *tool_path, const char *tool_name)
|
||||
if (init_dynamic_string(&ds_tmp, "", 32, 32))
|
||||
die("Out of memory");
|
||||
|
||||
/* Initialize path with the full path to this program */
|
||||
if (get_full_path_to_executable(path))
|
||||
last_fn_libchar= strrchr(self_name, FN_LIBCHAR);
|
||||
|
||||
if (last_fn_libchar == NULL)
|
||||
{
|
||||
/*
|
||||
Easy way to get full executable path failed, try
|
||||
other methods
|
||||
mysql_upgrade was found by the shell searching the path. A sibling
|
||||
next to us should be found the same way.
|
||||
*/
|
||||
if (my_progname[0] == FN_LIBCHAR)
|
||||
{
|
||||
/* 1. my_progname contains full path */
|
||||
strmake(path, my_progname, FN_REFLEN);
|
||||
}
|
||||
else if (my_progname[0] == '.')
|
||||
{
|
||||
/* 2. my_progname contains relative path, prepend wd */
|
||||
char buf[FN_REFLEN];
|
||||
my_getwd(buf, FN_REFLEN, MYF(0));
|
||||
my_snprintf(path, FN_REFLEN, "%s%s", buf, my_progname);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 3. Just go for it and hope tool is in path */
|
||||
path[0]= 0;
|
||||
}
|
||||
strncpy(tool_executable_name, tool_name, FN_REFLEN);
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("path: '%s'", path));
|
||||
|
||||
/* Chop off binary name (i.e mysql-upgrade) from path */
|
||||
dirname_part(path, path);
|
||||
|
||||
/*
|
||||
When running in a not yet installed build and using libtool,
|
||||
the program(mysql_upgrade) will be in .libs/ and executed
|
||||
through a libtool wrapper in order to use the dynamic libraries
|
||||
from this build. The same must be done for the tools(mysql and
|
||||
mysqlcheck). Thus if path ends in .libs/, step up one directory
|
||||
and execute the tools from there
|
||||
*/
|
||||
path[max((strlen(path)-1), 0)]= 0; /* Chop off last / */
|
||||
if (strncmp(path + dirname_length(path), ".libs", 5) == 0)
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("info", ("Chopping off .libs from '%s'", path));
|
||||
int len;
|
||||
|
||||
/* Chop off .libs */
|
||||
dirname_part(path, path);
|
||||
/*
|
||||
mysql_upgrade was run absolutely or relatively. We can find a sibling
|
||||
by replacing our name after the LIBCHAR with the new tool name.
|
||||
*/
|
||||
|
||||
/*
|
||||
When running in a not yet installed build and using libtool,
|
||||
the program(mysql_upgrade) will be in .libs/ and executed
|
||||
through a libtool wrapper in order to use the dynamic libraries
|
||||
from this build. The same must be done for the tools(mysql and
|
||||
mysqlcheck). Thus if path ends in .libs/, step up one directory
|
||||
and execute the tools from there
|
||||
*/
|
||||
if (((last_fn_libchar - 6) >= self_name) &&
|
||||
(strncmp(last_fn_libchar - 5, ".libs", 5) == 0) &&
|
||||
(*(last_fn_libchar - 6) == FN_LIBCHAR))
|
||||
{
|
||||
DBUG_PRINT("info", ("Chopping off \".libs\" from end of path"));
|
||||
last_fn_libchar -= 6;
|
||||
}
|
||||
|
||||
len= last_fn_libchar - self_name;
|
||||
|
||||
my_snprintf(tool_executable_name, FN_REFLEN, "%.*s%c%s",
|
||||
len, self_name, FN_LIBCHAR, tool_name);
|
||||
}
|
||||
|
||||
|
||||
DBUG_PRINT("info", ("path: '%s'", path));
|
||||
|
||||
/* Format name of the tool to search for */
|
||||
fn_format(tool_path, tool_name,
|
||||
path, "", MYF(MY_REPLACE_DIR));
|
||||
|
||||
verbose("Looking for '%s' in: %s", tool_name, tool_path);
|
||||
|
||||
/* Make sure the tool exists */
|
||||
if (my_access(tool_path, F_OK) != 0)
|
||||
die("Can't find '%s'", tool_path);
|
||||
verbose("Looking for '%s' as: %s", tool_name, tool_executable_name);
|
||||
|
||||
/*
|
||||
Make sure it can be executed
|
||||
*/
|
||||
if (run_tool(tool_path,
|
||||
if (run_tool(tool_executable_name,
|
||||
&ds_tmp, /* Get output from command, discard*/
|
||||
"--help",
|
||||
"2>&1",
|
||||
IF_WIN("> NUL", "> /dev/null"),
|
||||
NULL))
|
||||
die("Can't execute '%s'", tool_path);
|
||||
die("Can't execute '%s'", tool_executable_name);
|
||||
|
||||
dynstr_free(&ds_tmp);
|
||||
|
||||
@ -748,11 +714,20 @@ static const char *load_default_groups[]=
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char self_name[FN_REFLEN];
|
||||
|
||||
MY_INIT(argv[0]);
|
||||
#ifdef __NETWARE__
|
||||
setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
|
||||
#endif
|
||||
|
||||
#if __WIN__
|
||||
if (GetModuleFileName(NULL, self_name, FN_REFLEN) == 0)
|
||||
#endif
|
||||
{
|
||||
strncpy(self_name, argv[0], FN_REFLEN);
|
||||
}
|
||||
|
||||
if (init_dynamic_string(&ds_args, "", 512, 256))
|
||||
die("Out of memory");
|
||||
|
||||
@ -774,10 +749,10 @@ int main(int argc, char **argv)
|
||||
dynstr_append(&ds_args, " ");
|
||||
|
||||
/* Find mysql */
|
||||
find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"));
|
||||
find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"), self_name);
|
||||
|
||||
/* Find mysqlcheck */
|
||||
find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"));
|
||||
find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name);
|
||||
|
||||
/*
|
||||
Read the mysql_upgrade_info file to check if mysql_upgrade
|
||||
|
@ -131,3 +131,49 @@ drop table t1;
|
||||
select if(0, 18446744073709551610, 18446744073709551610);
|
||||
if(0, 18446744073709551610, 18446744073709551610)
|
||||
18446744073709551610
|
||||
CREATE TABLE t1(a DECIMAL(10,3));
|
||||
SELECT t1.a,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,0)))))))))))))))))))))))))))))) + 1
|
||||
FROM t1;
|
||||
a IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((R
|
||||
DROP TABLE t1;
|
||||
End of 5.0 tests
|
||||
|
@ -1246,4 +1246,19 @@ set global innodb_autoextend_increment=@my_innodb_autoextend_increment;
|
||||
set @my_innodb_commit_concurrency=@@global.innodb_commit_concurrency;
|
||||
set global innodb_commit_concurrency=0;
|
||||
set global innodb_commit_concurrency=@my_innodb_commit_concurrency;
|
||||
CREATE TABLE t1 (a int, b int, c int, PRIMARY KEY (a), KEY t1_b (b))
|
||||
ENGINE=InnoDB;
|
||||
INSERT INTO t1 (a,b,c) VALUES (1,1,1), (2,1,1), (3,1,1), (4,1,1);
|
||||
INSERT INTO t1 (a,b,c) SELECT a+4,b,c FROM t1;
|
||||
EXPLAIN SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range t1_b t1_b 5 NULL 4 Using where
|
||||
SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5;
|
||||
a b c
|
||||
8 1 1
|
||||
7 1 1
|
||||
6 1 1
|
||||
5 1 1
|
||||
4 1 1
|
||||
DROP TABLE t1;
|
||||
End of 5.0 tests
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4396,4 +4396,15 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,<exists>(select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` having (<cache>(1) = <ref_null_helper>(1))))
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(pk int PRIMARY KEY, a int, INDEX idx(a));
|
||||
INSERT INTO t1 VALUES (1, 10), (3, 30), (2, 20);
|
||||
CREATE TABLE t2(pk int PRIMARY KEY, a int, b int, INDEX idxa(a));
|
||||
INSERT INTO t2 VALUES (2, 20, 700), (1, 10, 200), (4, 10, 100);
|
||||
SELECT * FROM t1
|
||||
WHERE EXISTS (SELECT DISTINCT a FROM t2 WHERE t1.a < t2.a ORDER BY b);
|
||||
pk a
|
||||
1 10
|
||||
3 30
|
||||
2 20
|
||||
DROP TABLE t1,t2;
|
||||
End of 5.0 tests.
|
||||
|
@ -108,3 +108,46 @@ drop table t1;
|
||||
select if(0, 18446744073709551610, 18446744073709551610);
|
||||
|
||||
|
||||
#
|
||||
# Bug #37662: nested if() inside sum() is parsed in exponential time
|
||||
#
|
||||
|
||||
CREATE TABLE t1(a DECIMAL(10,3));
|
||||
|
||||
# check : should be fast. more than few secs means failure.
|
||||
SELECT t1.a,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,
|
||||
IF((ROUND(t1.a,2)=1), 2,0)))))))))))))))))))))))))))))) + 1
|
||||
FROM t1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
@ -996,4 +996,22 @@ set @my_innodb_commit_concurrency=@@global.innodb_commit_concurrency;
|
||||
set global innodb_commit_concurrency=0;
|
||||
set global innodb_commit_concurrency=@my_innodb_commit_concurrency;
|
||||
|
||||
#
|
||||
# Bug #37830: ORDER BY ASC/DESC - no difference
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (a int, b int, c int, PRIMARY KEY (a), KEY t1_b (b))
|
||||
ENGINE=InnoDB;
|
||||
|
||||
INSERT INTO t1 (a,b,c) VALUES (1,1,1), (2,1,1), (3,1,1), (4,1,1);
|
||||
INSERT INTO t1 (a,b,c) SELECT a+4,b,c FROM t1;
|
||||
|
||||
# should be range access
|
||||
EXPLAIN SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5;
|
||||
|
||||
# should produce '8 7 6 5 4' for a
|
||||
SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
@ -38,3 +38,59 @@ drop table t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t2
|
||||
SET @@global.query_cache_size=0;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
# Bug#33362: Query cache invalidation (truncate) may hang if cached query uses many tables
|
||||
#
|
||||
|
||||
let $c= 255;
|
||||
|
||||
while ($c)
|
||||
{
|
||||
eval CREATE TABLE t$c (a INT);
|
||||
eval INSERT INTO t$c VALUES ($c);
|
||||
dec $c;
|
||||
}
|
||||
|
||||
let $c= 254;
|
||||
let $str= t255;
|
||||
|
||||
while ($c)
|
||||
{
|
||||
let $str= t$c,$str;
|
||||
dec $c;
|
||||
}
|
||||
|
||||
eval CREATE TABLE t0 (a INT) ENGINE=MERGE UNION($str);
|
||||
SET GLOBAL query_cache_size = 1048576;
|
||||
FLUSH STATUS;
|
||||
SELECT a FROM t0 WHERE a = 1;
|
||||
SHOW STATUS LIKE "Qcache_queries_in_cache";
|
||||
|
||||
let $c= 255;
|
||||
let $i= 1;
|
||||
|
||||
FLUSH TABLES;
|
||||
|
||||
while ($c)
|
||||
{
|
||||
eval TRUNCATE TABLE t$c;
|
||||
eval SELECT a FROM t$i;
|
||||
dec $c;
|
||||
inc $i;
|
||||
}
|
||||
|
||||
SELECT a FROM t0;
|
||||
DROP TABLE t0;
|
||||
|
||||
let $c= 255;
|
||||
|
||||
while ($c)
|
||||
{
|
||||
eval DROP TABLE t$c;
|
||||
dec $c;
|
||||
}
|
||||
|
||||
SET @@global.query_cache_size = 0;
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
@ -3295,5 +3295,17 @@ EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 GROUP BY a);
|
||||
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug #38191: Server crash with subquery containing DISTINCT and ORDER BY
|
||||
#
|
||||
|
||||
CREATE TABLE t1(pk int PRIMARY KEY, a int, INDEX idx(a));
|
||||
INSERT INTO t1 VALUES (1, 10), (3, 30), (2, 20);
|
||||
CREATE TABLE t2(pk int PRIMARY KEY, a int, b int, INDEX idxa(a));
|
||||
INSERT INTO t2 VALUES (2, 20, 700), (1, 10, 200), (4, 10, 100);
|
||||
SELECT * FROM t1
|
||||
WHERE EXISTS (SELECT DISTINCT a FROM t2 WHERE t1.a < t2.a ORDER BY b);
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo End of 5.0 tests.
|
||||
|
||||
|
@ -1382,7 +1382,7 @@ restart:
|
||||
/* We don't need the page in the cache: we are going to write on disk */
|
||||
hash_link->requests--;
|
||||
unlink_hash(keycache, hash_link);
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
if (!(block->status & BLOCK_IN_FLUSH))
|
||||
{
|
||||
@ -1399,7 +1399,7 @@ restart:
|
||||
flag (see the code below that handles reading requests).
|
||||
*/
|
||||
free_block(keycache, block);
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
/* Wait intil the page is flushed on disk */
|
||||
hash_link->requests--;
|
||||
@ -1429,7 +1429,7 @@ restart:
|
||||
/* Invalidate page in the block if it has not been done yet */
|
||||
if (block->status)
|
||||
free_block(keycache, block);
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
if (page_status == PAGE_READ &&
|
||||
|
@ -202,7 +202,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
|
||||
{
|
||||
if (mem_root->error_handler)
|
||||
(*mem_root->error_handler)();
|
||||
return((gptr) 0); /* purecov: inspected */
|
||||
DBUG_RETURN((gptr) 0); /* purecov: inspected */
|
||||
}
|
||||
mem_root->block_num++;
|
||||
next->next= *prev;
|
||||
|
@ -2,6 +2,7 @@
|
||||
-- The system tables of MySQL Server
|
||||
--
|
||||
|
||||
set sql_mode='';
|
||||
set storage_engine=myisam;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges';
|
||||
|
@ -48,7 +48,8 @@ class Field
|
||||
Field(const Item &); /* Prevent use of these */
|
||||
void operator=(Field &);
|
||||
public:
|
||||
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
|
||||
static void *operator new(size_t size) throw ()
|
||||
{ return (void*) sql_alloc((uint) size); }
|
||||
static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); }
|
||||
|
||||
char *ptr; // Position to field in record
|
||||
|
12
sql/item.cc
12
sql/item.cc
@ -429,8 +429,11 @@ uint Item::decimal_precision() const
|
||||
Item_result restype= result_type();
|
||||
|
||||
if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
|
||||
return min(my_decimal_length_to_precision(max_length, decimals, unsigned_flag),
|
||||
DECIMAL_MAX_PRECISION);
|
||||
{
|
||||
uint prec=
|
||||
my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
|
||||
return min(prec, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
return min(max_length, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
|
||||
@ -6838,8 +6841,9 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
||||
if (Field::result_merge_type(fld_type) == DECIMAL_RESULT)
|
||||
{
|
||||
decimals= min(max(decimals, item->decimals), DECIMAL_MAX_SCALE);
|
||||
int precision= min(max(prev_decimal_int_part, item->decimal_int_part())
|
||||
+ decimals, DECIMAL_MAX_PRECISION);
|
||||
int item_int_part= item->decimal_int_part();
|
||||
int item_prec = max(prev_decimal_int_part, item_int_part) + decimals;
|
||||
int precision= min(item_prec, DECIMAL_MAX_PRECISION);
|
||||
unsigned_flag&= item->unsigned_flag;
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,
|
||||
unsigned_flag);
|
||||
|
@ -439,9 +439,9 @@ class Item {
|
||||
Item(const Item &); /* Prevent use of these */
|
||||
void operator=(Item &);
|
||||
public:
|
||||
static void *operator new(size_t size)
|
||||
static void *operator new(size_t size) throw ()
|
||||
{ return (void*) sql_alloc((uint) size); }
|
||||
static void *operator new(size_t size, MEM_ROOT *mem_root)
|
||||
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
|
||||
{ return (void*) alloc_root(mem_root, (uint) size); }
|
||||
static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
|
||||
static void operator delete(void *ptr, MEM_ROOT *mem_root) {}
|
||||
|
@ -2098,8 +2098,11 @@ Item_func_ifnull::fix_length_and_dec()
|
||||
|
||||
uint Item_func_ifnull::decimal_precision() const
|
||||
{
|
||||
int max_int_part=max(args[0]->decimal_int_part(),args[1]->decimal_int_part());
|
||||
return min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
|
||||
int arg0_int_part= args[0]->decimal_int_part();
|
||||
int arg1_int_part= args[1]->decimal_int_part();
|
||||
int max_int_part= max(arg0_int_part, arg1_int_part);
|
||||
int precision= max_int_part + decimals;
|
||||
return min(precision, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
|
||||
|
||||
@ -2281,8 +2284,9 @@ Item_func_if::fix_length_and_dec()
|
||||
|
||||
uint Item_func_if::decimal_precision() const
|
||||
{
|
||||
int precision=(max(args[1]->decimal_int_part(),args[2]->decimal_int_part())+
|
||||
decimals);
|
||||
int arg1_prec= args[1]->decimal_int_part();
|
||||
int arg2_prec= args[2]->decimal_int_part();
|
||||
int precision=max(arg1_prec,arg2_prec) + decimals;
|
||||
return min(precision, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
|
||||
|
@ -1156,9 +1156,10 @@ my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
|
||||
void Item_func_additive_op::result_precision()
|
||||
{
|
||||
decimals= max(args[0]->decimals, args[1]->decimals);
|
||||
int max_int_part= max(args[0]->decimal_precision() - args[0]->decimals,
|
||||
args[1]->decimal_precision() - args[1]->decimals);
|
||||
int precision= min(max_int_part + 1 + decimals, DECIMAL_MAX_PRECISION);
|
||||
int arg1_int= args[0]->decimal_precision() - args[0]->decimals;
|
||||
int arg2_int= args[1]->decimal_precision() - args[1]->decimals;
|
||||
int est_prec= max(arg1_int, arg2_int) + 1 + decimals;
|
||||
int precision= min(est_prec, DECIMAL_MAX_PRECISION);
|
||||
|
||||
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
||||
if (result_type() == INT_RESULT)
|
||||
@ -1267,8 +1268,8 @@ void Item_func_mul::result_precision()
|
||||
else
|
||||
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
||||
decimals= min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE);
|
||||
int precision= min(args[0]->decimal_precision() + args[1]->decimal_precision(),
|
||||
DECIMAL_MAX_PRECISION);
|
||||
uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
|
||||
uint precision= min(est_prec, DECIMAL_MAX_PRECISION);
|
||||
max_length= my_decimal_precision_to_length(precision, decimals,unsigned_flag);
|
||||
}
|
||||
|
||||
@ -1315,8 +1316,8 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
|
||||
|
||||
void Item_func_div::result_precision()
|
||||
{
|
||||
uint precision=min(args[0]->decimal_precision() + prec_increment,
|
||||
DECIMAL_MAX_PRECISION);
|
||||
uint arg_prec= args[0]->decimal_precision() + prec_increment;
|
||||
uint precision=min(arg_prec, DECIMAL_MAX_PRECISION);
|
||||
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
||||
if (result_type() == INT_RESULT)
|
||||
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
||||
|
@ -7099,7 +7099,8 @@ bool QUICK_RANGE_SELECT::row_in_ranges()
|
||||
|
||||
QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q,
|
||||
uint used_key_parts_arg)
|
||||
: QUICK_RANGE_SELECT(*q), rev_it(rev_ranges)
|
||||
: QUICK_RANGE_SELECT(*q), rev_it(rev_ranges),
|
||||
used_key_parts (used_key_parts_arg)
|
||||
{
|
||||
QUICK_RANGE *r;
|
||||
|
||||
@ -7141,10 +7142,11 @@ int QUICK_SELECT_DESC::get_next()
|
||||
int result;
|
||||
if (last_range)
|
||||
{ // Already read through key
|
||||
result = ((last_range->flag & EQ_RANGE)
|
||||
? file->index_next_same(record, (byte*) last_range->min_key,
|
||||
last_range->min_length) :
|
||||
file->index_prev(record));
|
||||
result = ((last_range->flag & EQ_RANGE &&
|
||||
used_key_parts <= head->key_info[index].key_parts) ?
|
||||
file->index_next_same(record, (byte*) last_range->min_key,
|
||||
last_range->min_length) :
|
||||
file->index_prev(record));
|
||||
if (!result)
|
||||
{
|
||||
if (cmp_prev(*rev_it.ref()) == 0)
|
||||
@ -7168,7 +7170,9 @@ int QUICK_SELECT_DESC::get_next()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (last_range->flag & EQ_RANGE)
|
||||
if (last_range->flag & EQ_RANGE &&
|
||||
used_key_parts <= head->key_info[index].key_parts)
|
||||
|
||||
{
|
||||
result= file->index_read(record, (byte*) last_range->max_key,
|
||||
last_range->max_length, HA_READ_KEY_EXACT);
|
||||
@ -7176,6 +7180,8 @@ int QUICK_SELECT_DESC::get_next()
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(last_range->flag & NEAR_MAX ||
|
||||
(last_range->flag & EQ_RANGE &&
|
||||
used_key_parts > head->key_info[index].key_parts) ||
|
||||
range_reads_after_key(last_range));
|
||||
result=file->index_read(record, (byte*) last_range->max_key,
|
||||
last_range->max_length,
|
||||
@ -7273,54 +7279,6 @@ bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg)
|
||||
}
|
||||
|
||||
|
||||
/* TRUE if we are reading over a key that may have a NULL value */
|
||||
|
||||
#ifdef NOT_USED
|
||||
bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
|
||||
uint used_key_parts)
|
||||
{
|
||||
uint offset, end;
|
||||
KEY_PART *key_part = key_parts,
|
||||
*key_part_end= key_part+used_key_parts;
|
||||
|
||||
for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ;
|
||||
offset < end && key_part != key_part_end ;
|
||||
offset+= key_part++->store_length)
|
||||
{
|
||||
if (!memcmp((char*) range_arg->min_key+offset,
|
||||
(char*) range_arg->max_key+offset,
|
||||
key_part->store_length))
|
||||
continue;
|
||||
|
||||
if (key_part->null_bit && range_arg->min_key[offset])
|
||||
return 1; // min_key is null and max_key isn't
|
||||
// Range doesn't cover NULL. This is ok if there is no more null parts
|
||||
break;
|
||||
}
|
||||
/*
|
||||
If the next min_range is > NULL, then we can use this, even if
|
||||
it's a NULL key
|
||||
Example: SELECT * FROM t1 WHERE a = 2 AND b >0 ORDER BY a DESC,b DESC;
|
||||
|
||||
*/
|
||||
if (key_part != key_part_end && key_part->null_bit)
|
||||
{
|
||||
if (offset >= range_arg->min_length || range_arg->min_key[offset])
|
||||
return 1; // Could be null
|
||||
key_part++;
|
||||
}
|
||||
/*
|
||||
If any of the key parts used in the ORDER BY could be NULL, we can't
|
||||
use the key to sort the data.
|
||||
*/
|
||||
for (; key_part != key_part_end ; key_part++)
|
||||
if (key_part->null_bit)
|
||||
return 1; // Covers null part
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void QUICK_RANGE_SELECT::add_info_string(String *str)
|
||||
{
|
||||
KEY *key_info= head->key_info + index;
|
||||
|
@ -667,12 +667,10 @@ public:
|
||||
int get_type() { return QS_TYPE_RANGE_DESC; }
|
||||
private:
|
||||
bool range_reads_after_key(QUICK_RANGE *range);
|
||||
#ifdef NOT_USED
|
||||
bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts);
|
||||
#endif
|
||||
int reset(void) { rev_it.rewind(); return QUICK_RANGE_SELECT::reset(); }
|
||||
List<QUICK_RANGE> rev_ranges;
|
||||
List_iterator<QUICK_RANGE> rev_it;
|
||||
uint used_key_parts;
|
||||
};
|
||||
|
||||
|
||||
|
@ -4737,7 +4737,7 @@ ER_SLAVE_IGNORED_TABLE
|
||||
swe "Slav SQL tråden ignorerade frågan pga en replicate-*-table regel"
|
||||
ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
eng "Variable '%-.64s' is a %s variable"
|
||||
serbian "Incorrect foreign key definition for '%-.64s': %s"
|
||||
serbian "Promenljiva '%-.64s' je %s promenljiva"
|
||||
ger "Variable '%-.64s' ist eine %s-Variable"
|
||||
spa "Variable '%-.64s' es una %s variable"
|
||||
swe "Variabel '%-.64s' är av typ %s"
|
||||
|
@ -446,7 +446,7 @@ sp_head::operator new(size_t size) throw()
|
||||
init_sql_alloc(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
|
||||
sp= (sp_head *) alloc_root(&own_root, size);
|
||||
if (sp == NULL)
|
||||
return NULL;
|
||||
DBUG_RETURN(NULL);
|
||||
sp->main_mem_root= own_root;
|
||||
DBUG_PRINT("info", ("mem_root 0x%lx", (ulong) &sp->mem_root));
|
||||
DBUG_RETURN(sp);
|
||||
|
@ -5430,7 +5430,6 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
|
||||
|
||||
while ((tmp_user_name= user_list++))
|
||||
{
|
||||
user_name= get_current_user(thd, tmp_user_name);
|
||||
if (!(user_name= get_current_user(thd, tmp_user_name)))
|
||||
{
|
||||
result= TRUE;
|
||||
|
@ -2516,7 +2516,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
|
||||
tmp++)
|
||||
unlink_table(tmp);
|
||||
}
|
||||
return (n);
|
||||
return test(n);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -111,7 +111,8 @@ class Select_materialize: public select_union
|
||||
select_result *result; /* the result object of the caller (PS or SP) */
|
||||
public:
|
||||
Materialized_cursor *materialized_cursor;
|
||||
Select_materialize(select_result *result_arg) :result(result_arg) {}
|
||||
Select_materialize(select_result *result_arg) :result(result_arg),
|
||||
materialized_cursor(0) {}
|
||||
virtual bool send_fields(List<Item> &list, uint flags);
|
||||
};
|
||||
|
||||
@ -155,6 +156,7 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result,
|
||||
if (! (sensitive_cursor= new (thd->mem_root) Sensitive_cursor(thd, result)))
|
||||
{
|
||||
delete result_materialize;
|
||||
result_materialize= NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -212,6 +214,7 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result,
|
||||
if ((rc= materialized_cursor->open(0)))
|
||||
{
|
||||
delete materialized_cursor;
|
||||
materialized_cursor= NULL;
|
||||
goto err_open;
|
||||
}
|
||||
|
||||
|
@ -331,11 +331,11 @@ public:
|
||||
bool no_table_names_allowed; /* used for global order by */
|
||||
bool no_error; /* suppress error message (convert it to warnings) */
|
||||
|
||||
static void *operator new(size_t size)
|
||||
static void *operator new(size_t size) throw ()
|
||||
{
|
||||
return (void*) sql_alloc((uint) size);
|
||||
}
|
||||
static void *operator new(size_t size, MEM_ROOT *mem_root)
|
||||
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
|
||||
{ return (void*) alloc_root(mem_root, (uint) size); }
|
||||
static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
|
||||
static void operator delete(void *ptr, MEM_ROOT *mem_root) {}
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
{
|
||||
return (void*) sql_alloc((uint) size);
|
||||
}
|
||||
static void *operator new[](size_t size)
|
||||
static void *operator new[](size_t size) throw ()
|
||||
{
|
||||
return (void*) sql_alloc((uint) size);
|
||||
}
|
||||
@ -466,7 +466,7 @@ public:
|
||||
struct ilink
|
||||
{
|
||||
struct ilink **prev,*next;
|
||||
static void *operator new(size_t size)
|
||||
static void *operator new(size_t size) throw ()
|
||||
{
|
||||
return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE));
|
||||
}
|
||||
|
@ -7069,11 +7069,23 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
||||
thd->thread_stack= (char*) &tmp_thd;
|
||||
thd->store_globals();
|
||||
}
|
||||
|
||||
if (thd)
|
||||
{
|
||||
(void)acl_reload(thd);
|
||||
(void)grant_reload(thd);
|
||||
bool reload_acl_failed= acl_reload(thd);
|
||||
bool reload_grants_failed= grant_reload(thd);
|
||||
|
||||
if (reload_acl_failed || reload_grants_failed)
|
||||
{
|
||||
result= 1;
|
||||
/*
|
||||
When an error is returned, my_message may have not been called and
|
||||
the client will hang waiting for a response.
|
||||
*/
|
||||
my_error(ER_UNKNOWN_ERROR, MYF(0), "FLUSH PRIVILEGES failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_thd)
|
||||
{
|
||||
delete tmp_thd;
|
||||
@ -7159,8 +7171,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
||||
tmp_write_to_binlog= 0;
|
||||
if (lock_global_read_lock(thd))
|
||||
return 1; // Killed
|
||||
result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1,
|
||||
tables);
|
||||
if (close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1,
|
||||
tables))
|
||||
result= 1;
|
||||
|
||||
if (make_global_read_lock_block_commit(thd)) // Killed
|
||||
{
|
||||
/* Don't leave things in a half-locked state */
|
||||
@ -7169,7 +7183,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
||||
}
|
||||
}
|
||||
else
|
||||
result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables);
|
||||
{
|
||||
if (close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables))
|
||||
result= 1;
|
||||
}
|
||||
my_dbopt_cleanup();
|
||||
}
|
||||
if (options & REFRESH_HOSTS)
|
||||
@ -7193,8 +7210,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
||||
#ifdef OPENSSL
|
||||
if (options & REFRESH_DES_KEY_FILE)
|
||||
{
|
||||
if (des_key_file)
|
||||
result=load_des_key_file(des_key_file);
|
||||
if (des_key_file && load_des_key_file(des_key_file))
|
||||
result= 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_REPLICATION
|
||||
|
@ -6469,6 +6469,12 @@ void JOIN::cleanup(bool full)
|
||||
if (tmp_join)
|
||||
tmp_table_param.copy_field= 0;
|
||||
group_fields.delete_elements();
|
||||
/*
|
||||
Ensure that the above delete_elements() would not be called
|
||||
twice for the same list.
|
||||
*/
|
||||
if (tmp_join && tmp_join != this)
|
||||
tmp_join->group_fields= group_fields;
|
||||
/*
|
||||
We can't call delete_elements() on copy_funcs as this will cause
|
||||
problems in free_elements() as some of the elements are then deleted.
|
||||
@ -12088,26 +12094,25 @@ part_of_refkey(TABLE *table,Field *field)
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
Test if one can use the key to resolve ORDER BY
|
||||
/**
|
||||
Test if a key can be used to resolve ORDER BY
|
||||
|
||||
SYNOPSIS
|
||||
test_if_order_by_key()
|
||||
order Sort order
|
||||
table Table to sort
|
||||
idx Index to check
|
||||
used_key_parts Return value for used key parts.
|
||||
used_key_parts is set to correct key parts used if return value != 0
|
||||
(On other cases, used_key_part may be changed).
|
||||
Note that the value may actually be greater than the number of index
|
||||
key parts. This can happen for storage engines that have the primary
|
||||
key parts as a suffix for every secondary key.
|
||||
|
||||
@param order Sort order
|
||||
@param table Table to sort
|
||||
@param idx Index to check
|
||||
@param[out] used_key_parts Return value for used key parts.
|
||||
|
||||
NOTES
|
||||
used_key_parts is set to correct key parts used if return value != 0
|
||||
(On other cases, used_key_part may be changed)
|
||||
|
||||
RETURN
|
||||
1 key is ok.
|
||||
0 Key can't be used
|
||||
-1 Reverse key can be used
|
||||
*****************************************************************************/
|
||||
@return indication if the key can be used for sorting
|
||||
@retval 1 key can be used for reading data in order.
|
||||
@retval 0 Key can't be used
|
||||
@retval -1 Reverse read on the key can be used
|
||||
*/
|
||||
|
||||
static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
|
||||
uint *used_key_parts)
|
||||
@ -12172,11 +12177,27 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
|
||||
reverse=flag; // Remember if reverse
|
||||
key_part++;
|
||||
}
|
||||
*used_key_parts= on_primary_key ? table->key_info[idx].key_parts :
|
||||
(uint) (key_part - table->key_info[idx].key_part);
|
||||
if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) &
|
||||
HA_READ_PREV))
|
||||
reverse= 0; // Index can't be used
|
||||
if (on_primary_key)
|
||||
{
|
||||
uint used_key_parts_secondary= table->key_info[idx].key_parts;
|
||||
uint used_key_parts_pk=
|
||||
(uint) (key_part - table->key_info[table->s->primary_key].key_part);
|
||||
*used_key_parts= used_key_parts_pk + used_key_parts_secondary;
|
||||
|
||||
if (reverse == -1 &&
|
||||
(!(table->file->index_flags(idx, used_key_parts_secondary - 1, 1) &
|
||||
HA_READ_PREV) ||
|
||||
!(table->file->index_flags(table->s->primary_key,
|
||||
used_key_parts_pk - 1, 1) & HA_READ_PREV)))
|
||||
reverse= 0; // Index can't be used
|
||||
}
|
||||
else
|
||||
{
|
||||
*used_key_parts= (uint) (key_part - table->key_info[idx].key_part);
|
||||
if (reverse == -1 &&
|
||||
!(table->file->index_flags(idx, *used_key_parts-1, 1) & HA_READ_PREV))
|
||||
reverse= 0; // Index can't be used
|
||||
}
|
||||
DBUG_RETURN(reverse);
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ public:
|
||||
Alloced_length=str.Alloced_length; alloced=0;
|
||||
str_charset=str.str_charset;
|
||||
}
|
||||
static void *operator new(size_t size, MEM_ROOT *mem_root)
|
||||
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
|
||||
{ return (void*) alloc_root(mem_root, (uint) size); }
|
||||
static void operator delete(void *ptr_arg,size_t size)
|
||||
{ TRASH(ptr_arg, size); }
|
||||
|
1775
sql/sql_yacc.yy
1775
sql/sql_yacc.yy
File diff suppressed because it is too large
Load Diff
@ -21,10 +21,35 @@
|
||||
extern "C" {
|
||||
void sql_alloc_error_handler(void)
|
||||
{
|
||||
THD *thd=current_thd;
|
||||
if (thd) // QQ; To be removed
|
||||
thd->fatal_error(); /* purecov: inspected */
|
||||
sql_print_error(ER(ER_OUT_OF_RESOURCES));
|
||||
|
||||
THD *thd=current_thd;
|
||||
if (thd)
|
||||
{
|
||||
/*
|
||||
This thread is Out Of Memory.
|
||||
An OOM condition is a fatal error.
|
||||
It should not be caught by error handlers in stored procedures.
|
||||
Also, recording that SQL condition in the condition area could
|
||||
cause more memory allocations, which in turn could raise more
|
||||
OOM conditions, causing recursion in the error handling code itself.
|
||||
As a result, my_error() should not be invoked, and the
|
||||
thread diagnostics area is set to an error status directly.
|
||||
The visible result for a client application will be:
|
||||
- a query fails with an ER_OUT_OF_RESOURCES error,
|
||||
returned in the error packet.
|
||||
- SHOW ERROR/SHOW WARNINGS may be empty.
|
||||
*/
|
||||
|
||||
NET *net= &thd->net;
|
||||
thd->fatal_error();
|
||||
if (!net->last_error[0]) // Return only first message
|
||||
{
|
||||
strmake(net->last_error, ER(ER_OUT_OF_RESOURCES),
|
||||
sizeof(net->last_error)-1);
|
||||
net->last_errno= ER_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,11 @@
|
||||
|
||||
rm -f TAGS
|
||||
filter='\.cc$\|\.c$\|\.h$\|\.yy$'
|
||||
files=`bk -r sfiles -gU | grep $filter `
|
||||
for f in $files ;
|
||||
|
||||
list="find . -type f"
|
||||
bzr root >/dev/null 2>/dev/null && list="bzr ls --kind=file --versioned"
|
||||
|
||||
$list |grep $filter |while read f;
|
||||
do
|
||||
etags -o TAGS --append $f
|
||||
done
|
||||
|
@ -16189,6 +16189,38 @@ static void test_bug32265()
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Bug#38486 Crash when using cursor protocol
|
||||
*/
|
||||
|
||||
static void test_bug38486(void)
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
const char *stmt_text;
|
||||
unsigned long type= CURSOR_TYPE_READ_ONLY;
|
||||
|
||||
DBUG_ENTER("test_bug38486");
|
||||
myheader("test_bug38486");
|
||||
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type);
|
||||
stmt_text= "CREATE TABLE t1 (a INT)";
|
||||
mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
|
||||
mysql_stmt_execute(stmt);
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type);
|
||||
stmt_text= "INSERT INTO t1 VALUES (1)";
|
||||
mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
|
||||
mysql_stmt_execute(stmt);
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Read and parse arguments and MySQL options from my.cnf
|
||||
*/
|
||||
@ -16483,6 +16515,7 @@ static struct my_tests_st my_tests[]= {
|
||||
{ "test_bug29306", test_bug29306 },
|
||||
{ "test_bug31669", test_bug31669 },
|
||||
{ "test_bug32265", test_bug32265 },
|
||||
{ "test_bug38486", test_bug38486 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user