Commit 1fbcaf2e authored by Michael Widenius's avatar Michael Widenius

Merge with 5.2

parents a4579c3e 4c576fd4
...@@ -535,3 +535,34 @@ HAVING ...@@ -535,3 +535,34 @@ HAVING
field4 != 6; field4 != 6;
field1 field2 field3 field4 field5 field6 field1 field2 field3 field4 field5 field6
drop table t0,t1,t2,t3,t4,t5,t6; drop table t0,t1,t2,t3,t4,t5,t6;
#
# BUG#675118: Elimination of a table results in an invalid execution plan
#
CREATE TABLE t1 (f1 int(11), PRIMARY KEY (f1)) ;
CREATE TABLE t2 (f4 varchar(1024), KEY (f4)) ;
Warnings:
Warning 1071 Specified key was too long; max key length is 1000 bytes
INSERT IGNORE INTO t2 VALUES ('xcddwntkbxyorzdv'),
('cnxxcddwntkbxyor'),('r'),('r'), ('did'),('I'),('when'),
('hczkfqjeggivdvac'),('e'),('okay'),('up');
CREATE TABLE t3 (f4 varchar(1024), f1 int(11), f2 int(11)) ;
INSERT IGNORE INTO t3 VALUES ('f','4','0'),('n','5','-996540416');
CREATE TABLE t4 (f1 int(11), f3 varchar(10)) ;
INSERT IGNORE INTO t4 VALUES ('8','n'),('9','nwzcerzsgx'),('10','c');
CREATE TABLE t5 (f5 int(11), KEY (f5)) ;
EXPLAIN
SELECT t3.f2
FROM t2
LEFT JOIN t3
LEFT JOIN t4
LEFT JOIN t1 ON t4.f1 = t1.f1
JOIN t5 ON t4.f3 ON t3.f1 = t5.f5 ON t2.f4 = t3.f4
WHERE t3.f2 ;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using where
1 SIMPLE t5 ref f5 f5 5 test.t3.f1 2 Using index
1 SIMPLE t4 ALL NULL NULL NULL NULL 3
1 SIMPLE t2 ALL f4 NULL NULL NULL 11 Using where; Using join buffer
# ^^ The above must not produce a QEP of t3,t5,t2,t4
# as that violates the "no interleaving of outer join nests" rule.
DROP TABLE t1,t2,t3,t4,t5;
...@@ -688,3 +688,13 @@ HANDLER t1 READ a NEXT; ...@@ -688,3 +688,13 @@ HANDLER t1 READ a NEXT;
a a
HANDLER t1 CLOSE; HANDLER t1 CLOSE;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (f1 integer, f2 integer, primary key (f1), key (f2)) engine=innodb;
INSERT INTO t1 VALUES (1,1),(2,2),(3,3);
HANDLER t1 OPEN;
HANDLER t1 READ FIRST WHERE f2 <= 1;
f1 f2
1 1
HANDLER t1 READ `PRIMARY` PREV;
f1 f2
3 3
DROP TABLE t1;
...@@ -15,3 +15,14 @@ let $engine_type= InnoDB; ...@@ -15,3 +15,14 @@ let $engine_type= InnoDB;
--source init.inc --source init.inc
--source handler.inc --source handler.inc
#
# LP#697610 ha_index_prev(uchar*): Assertion `inited==INDEX'
#
CREATE TABLE t1 (f1 integer, f2 integer, primary key (f1), key (f2)) engine=innodb;
INSERT INTO t1 VALUES (1,1),(2,2),(3,3);
HANDLER t1 OPEN;
HANDLER t1 READ FIRST WHERE f2 <= 1;
HANDLER t1 READ `PRIMARY` PREV;
DROP TABLE t1;
...@@ -467,3 +467,35 @@ HAVING ...@@ -467,3 +467,35 @@ HAVING
field4 != 6; field4 != 6;
drop table t0,t1,t2,t3,t4,t5,t6; drop table t0,t1,t2,t3,t4,t5,t6;
--echo #
--echo # BUG#675118: Elimination of a table results in an invalid execution plan
--echo #
CREATE TABLE t1 (f1 int(11), PRIMARY KEY (f1)) ;
CREATE TABLE t2 (f4 varchar(1024), KEY (f4)) ;
INSERT IGNORE INTO t2 VALUES ('xcddwntkbxyorzdv'),
('cnxxcddwntkbxyor'),('r'),('r'), ('did'),('I'),('when'),
('hczkfqjeggivdvac'),('e'),('okay'),('up');
CREATE TABLE t3 (f4 varchar(1024), f1 int(11), f2 int(11)) ;
INSERT IGNORE INTO t3 VALUES ('f','4','0'),('n','5','-996540416');
CREATE TABLE t4 (f1 int(11), f3 varchar(10)) ;
INSERT IGNORE INTO t4 VALUES ('8','n'),('9','nwzcerzsgx'),('10','c');
CREATE TABLE t5 (f5 int(11), KEY (f5)) ;
EXPLAIN
SELECT t3.f2
FROM t2
LEFT JOIN t3
LEFT JOIN t4
LEFT JOIN t1 ON t4.f1 = t1.f1
JOIN t5 ON t4.f3 ON t3.f1 = t5.f5 ON t2.f4 = t3.f4
WHERE t3.f2 ;
--echo # ^^ The above must not produce a QEP of t3,t5,t2,t4
--echo # as that violates the "no interleaving of outer join nests" rule.
DROP TABLE t1,t2,t3,t4,t5;
...@@ -1559,16 +1559,20 @@ public: ...@@ -1559,16 +1559,20 @@ public:
DBUG_ENTER("ha_index_init"); DBUG_ENTER("ha_index_init");
DBUG_ASSERT(inited==NONE); DBUG_ASSERT(inited==NONE);
if (!(result= index_init(idx, sorted))) if (!(result= index_init(idx, sorted)))
inited=INDEX; {
end_range= NULL; inited= INDEX;
active_index= idx;
end_range= NULL;
}
DBUG_RETURN(result); DBUG_RETURN(result);
} }
int ha_index_end() int ha_index_end()
{ {
DBUG_ENTER("ha_index_end"); DBUG_ENTER("ha_index_end");
DBUG_ASSERT(inited==INDEX); DBUG_ASSERT(inited==INDEX);
inited=NONE; inited= NONE;
end_range= NULL; active_index= MAX_KEY;
end_range= NULL;
DBUG_RETURN(index_end()); DBUG_RETURN(index_end());
} }
/* This is called after index_init() if we need to do a index scan */ /* This is called after index_init() if we need to do a index scan */
...@@ -1751,7 +1755,12 @@ public: ...@@ -1751,7 +1755,12 @@ public:
as there may be several calls to this routine. as there may be several calls to this routine.
*/ */
virtual void column_bitmaps_signal(); virtual void column_bitmaps_signal();
uint get_index(void) const { return active_index; } /*
We have to check for inited as some engines, like innodb, sets
active_index during table scan.
*/
uint get_index(void) const
{ return inited == INDEX ? active_index : MAX_KEY; }
virtual int close(void)=0; virtual int close(void)=0;
/** /**
...@@ -2261,8 +2270,8 @@ private: ...@@ -2261,8 +2270,8 @@ private:
*/ */
virtual int open(const char *name, int mode, uint test_if_locked)=0; virtual int open(const char *name, int mode, uint test_if_locked)=0;
virtual int index_init(uint idx, bool sorted) { active_index= idx; return 0; } virtual int index_init(uint idx, bool sorted) { return 0; }
virtual int index_end() { active_index= MAX_KEY; return 0; } virtual int index_end() { return 0; }
/** /**
rnd_init() can be called two times without rnd_end() in between rnd_init() can be called two times without rnd_end() in between
(it only makes sense if scan=1). (it only makes sense if scan=1).
......
...@@ -1813,7 +1813,7 @@ typedef struct st_nested_join ...@@ -1813,7 +1813,7 @@ typedef struct st_nested_join
2. All child join nest nodes are fully covered. 2. All child join nest nodes are fully covered.
*/ */
bool is_fully_covered() const { return join_list.elements == counter; } bool is_fully_covered() const { return n_tables == counter; }
} NESTED_JOIN; } NESTED_JOIN;
......
...@@ -2453,7 +2453,6 @@ int ha_federated::index_init(uint keynr, bool sorted) ...@@ -2453,7 +2453,6 @@ int ha_federated::index_init(uint keynr, bool sorted)
{ {
DBUG_ENTER("ha_federated::index_init"); DBUG_ENTER("ha_federated::index_init");
DBUG_PRINT("info", ("table: '%s' key: %u", table->s->table_name.str, keynr)); DBUG_PRINT("info", ("table: '%s' key: %u", table->s->table_name.str, keynr));
active_index= keynr;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -2589,7 +2588,6 @@ int ha_federated::index_end(void) ...@@ -2589,7 +2588,6 @@ int ha_federated::index_end(void)
{ {
DBUG_ENTER("ha_federated::index_end"); DBUG_ENTER("ha_federated::index_end");
free_result(); free_result();
active_index= MAX_KEY;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
......
...@@ -228,7 +228,7 @@ static MYSQL_SYSVAR_ULONGLONG(pagecache_buffer_size, pagecache_buffer_size, ...@@ -228,7 +228,7 @@ static MYSQL_SYSVAR_ULONGLONG(pagecache_buffer_size, pagecache_buffer_size,
"The size of the buffer used for index blocks for Aria tables. " "The size of the buffer used for index blocks for Aria tables. "
"Increase this to get better index handling (for all reads and " "Increase this to get better index handling (for all reads and "
"multiple writes) to as much as you can afford.", 0, 0, "multiple writes) to as much as you can afford.", 0, 0,
KEY_CACHE_SIZE, 0, ~(ulong) 0, 1); KEY_CACHE_SIZE, 8192*16L, ~(ulong) 0, 1);
static MYSQL_SYSVAR_ULONG(pagecache_division_limit, pagecache_division_limit, static MYSQL_SYSVAR_ULONG(pagecache_division_limit, pagecache_division_limit,
PLUGIN_VAR_RQCMDARG, PLUGIN_VAR_RQCMDARG,
......
/* Copyright (C) 2000-2008 MySQL AB /* Copyright (C) 2000-2008 MySQL AB, 2008-2011 Monty Program Ab
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -760,6 +760,8 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, ...@@ -760,6 +760,8 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem,
{ {
if (blocks < 8) if (blocks < 8)
{ {
my_message(ENOMEM, "Not enough memory to allocate 8 pagecache pages",
MYF(0));
my_errno= ENOMEM; my_errno= ENOMEM;
goto err; goto err;
} }
...@@ -4214,6 +4216,7 @@ static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block) ...@@ -4214,6 +4216,7 @@ static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block)
DBUG_ASSERT(block->rlocks == 0); DBUG_ASSERT(block->rlocks == 0);
DBUG_ASSERT(block->rlocks_queue == 0); DBUG_ASSERT(block->rlocks_queue == 0);
DBUG_ASSERT(block->pins == 0); DBUG_ASSERT(block->pins == 0);
DBUG_ASSERT((block->status & ~(PCBLOCK_ERROR | PCBLOCK_READ | PCBLOCK_IN_FLUSH | PCBLOCK_CHANGED | PCBLOCK_REASSIGNED)) == 0);
block->status= 0; block->status= 0;
#ifndef DBUG_OFF #ifndef DBUG_OFF
block->type= PAGECACHE_EMPTY_PAGE; block->type= PAGECACHE_EMPTY_PAGE;
...@@ -4542,6 +4545,7 @@ static int flush_pagecache_blocks_int(PAGECACHE *pagecache, ...@@ -4542,6 +4545,7 @@ static int flush_pagecache_blocks_int(PAGECACHE *pagecache,
KEYCACHE_DBUG_ASSERT(count<= pagecache->blocks_used); KEYCACHE_DBUG_ASSERT(count<= pagecache->blocks_used);
} }
} }
count++; /* Allocate one extra for easy end-of-buffer test */
/* Allocate a new buffer only if its bigger than the one we have */ /* Allocate a new buffer only if its bigger than the one we have */
if (count > FLUSH_CACHE && if (count > FLUSH_CACHE &&
!(cache= !(cache=
...@@ -4579,22 +4583,24 @@ restart: ...@@ -4579,22 +4583,24 @@ restart:
DBUG_ASSERT(filter_res == FLUSH_FILTER_OK); DBUG_ASSERT(filter_res == FLUSH_FILTER_OK);
} }
{ {
DBUG_ASSERT(!(block->status & PCBLOCK_IN_FLUSH));
/* /*
Mark the block with BLOCK_IN_FLUSH in order not to let We care only for the blocks for which flushing was not
other threads to use it for new pages and interfere with initiated by other threads as a result of page swapping
our sequence of flushing dirty file pages
*/ */
block->status|= PCBLOCK_IN_FLUSH;
if (! (block->status & PCBLOCK_IN_SWITCH)) if (! (block->status & PCBLOCK_IN_SWITCH))
{ {
/* /*
We care only for the blocks for which flushing was not Mark the block with BLOCK_IN_FLUSH in order not to let
initiated by other threads as a result of page swapping other threads to use it for new pages and interfere with
our sequence of flushing dirty file pages
*/ */
block->status|= PCBLOCK_IN_FLUSH;
reg_requests(pagecache, block, 1); reg_requests(pagecache, block, 1);
if (type != FLUSH_IGNORE_CHANGED) if (type != FLUSH_IGNORE_CHANGED)
{ {
*pos++= block;
/* It's not a temporary file */ /* It's not a temporary file */
if (pos == end) if (pos == end)
{ {
...@@ -4614,7 +4620,6 @@ restart: ...@@ -4614,7 +4620,6 @@ restart:
*/ */
goto restart; goto restart;
} }
*pos++= block;
} }
else else
{ {
......
...@@ -192,14 +192,18 @@ static struct my_option my_long_options[] = ...@@ -192,14 +192,18 @@ static struct my_option my_long_options[] =
{"display-only", 'd', "display brief info read from records' header", {"display-only", 'd', "display brief info read from records' header",
&opt_display_only, &opt_display_only, 0, GET_BOOL, &opt_display_only, &opt_display_only, 0, GET_BOOL,
NO_ARG,0, 0, 0, 0, 0, 0}, NO_ARG,0, 0, 0, 0, 0, 0},
{ "end-lsn", 'e', "Stop applying at this lsn. If end-lsn is used, UNDO:s "
"will not be applied", &opt_end_lsn, &opt_end_lsn,
0, GET_ULL, REQUIRED_ARG, 0, 0, ~(longlong) 0, 0, 0, 0 },
{"aria-log-dir-path", 'l', {"aria-log-dir-path", 'l',
"Path to the directory where to store transactional log", "Path to the directory where to store transactional log",
(uchar **) &maria_data_root, (uchar **) &maria_data_root, 0, (uchar **) &maria_data_root, (uchar **) &maria_data_root, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ "page-buffer-size", 'P', "", { "page-buffer-size", 'P',
"The size of the buffer used for index blocks for Maria tables",
&opt_page_buffer_size, &opt_page_buffer_size, 0, &opt_page_buffer_size, &opt_page_buffer_size, 0,
GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT,
(long) USE_BUFFER_INIT, (long) ~(ulong) 0, (long) MALLOC_OVERHEAD, 1024L*1024L, (long) ~(ulong) 0, (long) MALLOC_OVERHEAD,
(long) IO_SIZE, 0}, (long) IO_SIZE, 0},
{ "start-from-lsn", 'o', "Start reading log from this lsn", { "start-from-lsn", 'o', "Start reading log from this lsn",
&opt_start_from_lsn, &opt_start_from_lsn, &opt_start_from_lsn, &opt_start_from_lsn,
...@@ -207,18 +211,12 @@ static struct my_option my_long_options[] = ...@@ -207,18 +211,12 @@ static struct my_option my_long_options[] =
{"start-from-checkpoint", 'C', "Start applying from last checkpoint", {"start-from-checkpoint", 'C', "Start applying from last checkpoint",
&opt_start_from_checkpoint, &opt_start_from_checkpoint, 0, &opt_start_from_checkpoint, &opt_start_from_checkpoint, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{ "end-lsn", 'e', "Stop applying at this lsn. If end-lsn is used, UNDO:s "
"will not be applied", &opt_end_lsn, &opt_end_lsn,
0, GET_ULL, REQUIRED_ARG, 0, 0, ~(longlong) 0, 0, 0, 0 },
{"silent", 's', "Print less information during apply/undo phase", {"silent", 's', "Print less information during apply/undo phase",
&opt_silent, &opt_silent, 0, &opt_silent, &opt_silent, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"tables-to-redo", 'T', {"tables-to-redo", 'T',
"List of tables sepearated with , that we should apply REDO on. Use this if you only want to recover some tables", "List of tables sepearated with , that we should apply REDO on. Use this if you only want to recover some tables",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"verbose", 'v', "Print more information during apply/undo phase",
&maria_recovery_verbose, &maria_recovery_verbose, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"tmpdir", 't', "Path for temporary files. Multiple paths can be specified, " {"tmpdir", 't', "Path for temporary files. Multiple paths can be specified, "
"separated by " "separated by "
#if defined( __WIN__) || defined(__NETWARE__) #if defined( __WIN__) || defined(__NETWARE__)
...@@ -230,6 +228,9 @@ static struct my_option my_long_options[] = ...@@ -230,6 +228,9 @@ static struct my_option my_long_options[] =
{"undo", 'u', "Apply UNDO records to tables. (disable with --disable-undo)", {"undo", 'u', "Apply UNDO records to tables. (disable with --disable-undo)",
(uchar **) &opt_apply_undo, (uchar **) &opt_apply_undo, 0, (uchar **) &opt_apply_undo, (uchar **) &opt_apply_undo, 0,
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"verbose", 'v', "Print more information during apply/undo phase",
&maria_recovery_verbose, &maria_recovery_verbose, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Print version and exit.", {"version", 'V', "Print version and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment