mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 18:20:07 +01:00
Merge from main branch.
This commit is contained in:
commit
28e884d9e2
47 changed files with 3659 additions and 556 deletions
|
@ -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
|
||||
|
|
|
@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc)
|
|||
AC_CANONICAL_SYSTEM
|
||||
# The Docs Makefile.am parses this line!
|
||||
# remember to also change ndb version below and update version.c in ndb
|
||||
AM_INIT_AUTOMAKE(mysql, 5.0.68)
|
||||
AM_INIT_AUTOMAKE(mysql, 5.0.70)
|
||||
AM_CONFIG_HEADER([include/config.h:config.h.in])
|
||||
|
||||
PROTOCOL_VERSION=10
|
||||
|
@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0
|
|||
# ndb version
|
||||
NDB_VERSION_MAJOR=5
|
||||
NDB_VERSION_MINOR=0
|
||||
NDB_VERSION_BUILD=68
|
||||
NDB_VERSION_BUILD=70
|
||||
NDB_VERSION_STATUS=""
|
||||
|
||||
# Set all version vars based on $VERSION. How do we do this more elegant ?
|
||||
|
|
|
@ -2260,6 +2260,7 @@ buf_print(void)
|
|||
ut_a(buf_validate());
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*************************************************************************
|
||||
Returns the number of latched pages in the buffer pool. */
|
||||
|
||||
|
@ -2290,6 +2291,7 @@ buf_get_latched_pages_number(void)
|
|||
mutex_exit(&(buf_pool->mutex));
|
||||
return fixed_pages_number;
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*************************************************************************
|
||||
Returns the number of pending buf pool ios. */
|
||||
|
|
|
@ -3554,7 +3554,7 @@ loop:
|
|||
|
||||
ptr = dict_accept(ptr, "FOREIGN", &success);
|
||||
|
||||
if (!success) {
|
||||
if (!success || !ib_isspace(*ptr)) {
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
|
|
@ -495,7 +495,15 @@ Prints info of the buffer pool data structure. */
|
|||
void
|
||||
buf_print(void);
|
||||
/*============*/
|
||||
|
||||
/*************************************************************************
|
||||
Returns the number of latched pages in the buffer pool. */
|
||||
|
||||
ulint
|
||||
buf_get_latched_pages_number(void);
|
||||
/*==============================*/
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/************************************************************************
|
||||
Prints a page to stderr. */
|
||||
|
||||
|
@ -503,12 +511,7 @@ void
|
|||
buf_page_print(
|
||||
/*===========*/
|
||||
byte* read_buf); /* in: a database page */
|
||||
/*************************************************************************
|
||||
Returns the number of latched pages in the buffer pool. */
|
||||
|
||||
ulint
|
||||
buf_get_latched_pages_number(void);
|
||||
/*==============================*/
|
||||
/*************************************************************************
|
||||
Returns the number of pending buf pool ios. */
|
||||
|
||||
|
|
|
@ -531,7 +531,9 @@ struct export_var_struct{
|
|||
ulint innodb_buffer_pool_pages_dirty;
|
||||
ulint innodb_buffer_pool_pages_misc;
|
||||
ulint innodb_buffer_pool_pages_free;
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint innodb_buffer_pool_pages_latched;
|
||||
#endif /* UNIV_DEBUG */
|
||||
ulint innodb_buffer_pool_read_requests;
|
||||
ulint innodb_buffer_pool_reads;
|
||||
ulint innodb_buffer_pool_wait_free;
|
||||
|
|
|
@ -237,6 +237,7 @@ trx_undo_set_state_at_finish(
|
|||
/*=========================*/
|
||||
/* out: undo log segment header page,
|
||||
x-latched */
|
||||
trx_rseg_t* rseg, /* in: rollback segment memory object */
|
||||
trx_t* trx, /* in: transaction */
|
||||
trx_undo_t* undo, /* in: undo log memory copy */
|
||||
mtr_t* mtr); /* in: mtr */
|
||||
|
|
|
@ -1803,7 +1803,9 @@ srv_export_innodb_status(void)
|
|||
export_vars.innodb_buffer_pool_pages_data= UT_LIST_GET_LEN(buf_pool->LRU);
|
||||
export_vars.innodb_buffer_pool_pages_dirty= UT_LIST_GET_LEN(buf_pool->flush_list);
|
||||
export_vars.innodb_buffer_pool_pages_free= UT_LIST_GET_LEN(buf_pool->free);
|
||||
#ifdef UNIV_DEBUG
|
||||
export_vars.innodb_buffer_pool_pages_latched= buf_get_latched_pages_number();
|
||||
#endif /* UNIV_DEBUG */
|
||||
export_vars.innodb_buffer_pool_pages_total= buf_pool->curr_size;
|
||||
export_vars.innodb_buffer_pool_pages_misc= buf_pool->max_size -
|
||||
UT_LIST_GET_LEN(buf_pool->LRU) - UT_LIST_GET_LEN(buf_pool->free);
|
||||
|
|
|
@ -761,8 +761,8 @@ trx_commit_off_kernel(
|
|||
mutex_enter(&(rseg->mutex));
|
||||
|
||||
if (trx->insert_undo != NULL) {
|
||||
trx_undo_set_state_at_finish(trx, trx->insert_undo,
|
||||
&mtr);
|
||||
trx_undo_set_state_at_finish(
|
||||
rseg, trx, trx->insert_undo, &mtr);
|
||||
}
|
||||
|
||||
undo = trx->update_undo;
|
||||
|
@ -777,8 +777,8 @@ trx_commit_off_kernel(
|
|||
because only a single OS thread is allowed to do the
|
||||
transaction commit for this transaction. */
|
||||
|
||||
update_hdr_page = trx_undo_set_state_at_finish(trx,
|
||||
undo, &mtr);
|
||||
update_hdr_page = trx_undo_set_state_at_finish(
|
||||
rseg, trx, undo, &mtr);
|
||||
|
||||
/* We have to do the cleanup for the update log while
|
||||
holding the rseg mutex because update log headers
|
||||
|
|
|
@ -1724,6 +1724,7 @@ trx_undo_set_state_at_finish(
|
|||
/*=========================*/
|
||||
/* out: undo log segment header page,
|
||||
x-latched */
|
||||
trx_rseg_t* rseg, /* in: rollback segment memory object */
|
||||
trx_t* trx __attribute__((unused)), /* in: transaction */
|
||||
trx_undo_t* undo, /* in: undo log memory copy */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
|
@ -1732,8 +1733,10 @@ trx_undo_set_state_at_finish(
|
|||
trx_upagef_t* page_hdr;
|
||||
page_t* undo_page;
|
||||
ulint state;
|
||||
|
||||
ut_ad(trx && undo && mtr);
|
||||
|
||||
ut_ad(trx);
|
||||
ut_ad(undo);
|
||||
ut_ad(mtr);
|
||||
|
||||
if (undo->id >= TRX_RSEG_N_SLOTS) {
|
||||
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
|
||||
|
@ -1747,9 +1750,23 @@ trx_undo_set_state_at_finish(
|
|||
seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
|
||||
page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
|
||||
|
||||
if (undo->size == 1 && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
|
||||
< TRX_UNDO_PAGE_REUSE_LIMIT) {
|
||||
state = TRX_UNDO_CACHED;
|
||||
if (undo->size == 1
|
||||
&& mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
|
||||
< TRX_UNDO_PAGE_REUSE_LIMIT) {
|
||||
|
||||
/* This is a heuristic to avoid the problem of all UNDO
|
||||
slots ending up in one of the UNDO lists. Previously if
|
||||
the server crashed with all the slots in one of the lists,
|
||||
transactions that required the slots of a different type
|
||||
would fail for lack of slots. */
|
||||
|
||||
if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500
|
||||
&& UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) {
|
||||
|
||||
state = TRX_UNDO_CACHED;
|
||||
} else {
|
||||
state = TRX_UNDO_TO_FREE;
|
||||
}
|
||||
|
||||
} else if (undo->type == TRX_UNDO_INSERT) {
|
||||
|
||||
|
@ -1759,7 +1776,7 @@ trx_undo_set_state_at_finish(
|
|||
}
|
||||
|
||||
undo->state = state;
|
||||
|
||||
|
||||
mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, state, MLOG_2BYTES, mtr);
|
||||
|
||||
return(undo_page);
|
||||
|
|
|
@ -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
|
||||
|
|
6
mysql-test/r/innodb-autoinc-optimize.result
Normal file
6
mysql-test/r/innodb-autoinc-optimize.result
Normal file
|
@ -0,0 +1,6 @@
|
|||
drop table if exists t1;
|
||||
create table t1(a int not null auto_increment primary key) engine=innodb;
|
||||
insert into t1 set a = -1;
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
1
mysql-test/r/innodb_bug35220.result
Normal file
1
mysql-test/r/innodb_bug35220.result
Normal file
|
@ -0,0 +1 @@
|
|||
SET storage_engine=InnoDB;
|
|
@ -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
|
||||
|
|
16
mysql-test/t/innodb-autoinc-optimize.test
Normal file
16
mysql-test/t/innodb-autoinc-optimize.test
Normal file
|
@ -0,0 +1,16 @@
|
|||
-- source include/have_innodb.inc
|
||||
# embedded server ignores 'delayed', so skip this
|
||||
-- source include/not_embedded.inc
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
#
|
||||
# Bug 34286
|
||||
#
|
||||
create table t1(a int not null auto_increment primary key) engine=innodb;
|
||||
insert into t1 set a = -1;
|
||||
# NOTE: The database needs to be shutdown and restarted (here) for
|
||||
# the test to work. It's included for reference only.
|
||||
optimize table t1;
|
16
mysql-test/t/innodb_bug35220.test
Normal file
16
mysql-test/t/innodb_bug35220.test
Normal file
|
@ -0,0 +1,16 @@
|
|||
#
|
||||
# Bug#35220 ALTER TABLE too picky on reserved word "foreign"
|
||||
# http://bugs.mysql.com/35220
|
||||
#
|
||||
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
SET storage_engine=InnoDB;
|
||||
|
||||
# we care only that the following SQL commands do not produce errors
|
||||
-- disable_query_log
|
||||
-- disable_result_log
|
||||
|
||||
CREATE TABLE bug35220 (foreign_col INT, dummy_cant_delete_all_columns INT);
|
||||
ALTER TABLE bug35220 DROP foreign_col;
|
||||
DROP TABLE bug35220;
|
|
@ -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
|
||||
|
|
|
@ -244,8 +244,10 @@ struct show_var_st innodb_status_variables[]= {
|
|||
(char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG},
|
||||
{"buffer_pool_pages_free",
|
||||
(char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
|
||||
#ifdef UNIV_DEBUG
|
||||
{"buffer_pool_pages_latched",
|
||||
(char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG},
|
||||
#endif /* UNIV_DEBUG */
|
||||
{"buffer_pool_pages_misc",
|
||||
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
|
||||
{"buffer_pool_pages_total",
|
||||
|
@ -4250,7 +4252,7 @@ ha_innobase::rnd_pos(
|
|||
int error;
|
||||
uint keynr = active_index;
|
||||
DBUG_ENTER("rnd_pos");
|
||||
DBUG_DUMP("key", (uchar *)pos, ref_length);
|
||||
DBUG_DUMP("key", (uchar*) pos, ref_length);
|
||||
|
||||
statistic_increment(current_thd->status_var.ha_read_rnd_count,
|
||||
&LOCK_status);
|
||||
|
@ -6882,6 +6884,12 @@ ha_innobase::innobase_read_and_init_auto_inc(
|
|||
from a table when no table has been locked in ::external_lock(). */
|
||||
prebuilt->trx->n_mysql_tables_in_use++;
|
||||
|
||||
/* Since we will perform a MySQL SELECT query to determine the
|
||||
auto-inc value, set prebuilt->sql_stat_start = TRUE so that it
|
||||
is performed like any normal SELECT, regardless of the context
|
||||
we come here. */
|
||||
prebuilt->sql_stat_start = TRUE;
|
||||
|
||||
error = index_last(table->record[1]);
|
||||
|
||||
prebuilt->trx->n_mysql_tables_in_use--;
|
||||
|
|
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…
Add table
Reference in a new issue