Commit dfed4478 authored by unknown's avatar unknown

merge 5.3->5.5

parents 668a5a4a c98a054f
......@@ -42,3 +42,47 @@ select * from t1 where a in ('4828532208463511553');
a
4828532208463511553
drop table t1;
#End of 4.1 tests
#
# MDEV-5103: server crashed on singular Item_equal
#
CREATE TABLE `t1` (
`tipo` enum('p','r') NOT NULL DEFAULT 'r',
`arquivo_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`arquivo_md5` char(32) NOT NULL,
`conteudo` longblob NOT NULL,
`usuario` varchar(15) NOT NULL,
`datahora_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`tipo_arquivo` varchar(255) NOT NULL,
`nome_arquivo` varchar(255) NOT NULL,
`tamanho_arquivo` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`tipo`,`arquivo_id`),
UNIQUE KEY `tipo` (`tipo`,`arquivo_md5`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO `t1` (`tipo`, `arquivo_id`, `arquivo_md5`, `conteudo`, `usuario`, `datahora_gmt`, `tipo_arquivo`, `nome_arquivo`, `tamanho_arquivo`) VALUES
('r', 1, 'ad18832202b199728921807033a8a515', '', 'rspadim', '2013-10-05 13:55:50', '001_cbr643', 'CBR6431677410201314132.ret', 21306);
CREATE TABLE `t2` (
`tipo` enum('p','r') NOT NULL DEFAULT 'p',
`arquivo_id` bigint(20) NOT NULL DEFAULT '0',
`usuario` varchar(25) NOT NULL,
`datahora` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`erros` longblob NOT NULL,
`importados` bigint(20) unsigned NOT NULL DEFAULT '0',
`n_importados` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`tipo`,`arquivo_id`,`datahora`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO `t2` (`tipo`, `arquivo_id`, `usuario`, `datahora`, `erros`, `importados`, `n_importados`) VALUES
('r', 1, 'rspadim', '2013-10-05 14:25:30', '', 32, 0);
SELECT
arquivo_id,usuario,datahora_gmt,tipo_arquivo,nome_arquivo,tamanho_arquivo
FROM t1 AS a
WHERE datahora_gmt>='0000-00-00 00:00:00' AND
datahora_gmt<='2013-10-07 02:59:59' AND tipo='r' AND
(tipo_arquivo,arquivo_id) NOT IN
(SELECT tipo_arquivo,arquivo_id
FROM t2
WHERE (tipo_arquivo,arquivo_id)=(a.tipo_arquivo,a.arquivo_id))
ORDER BY arquivo_id DESC;
arquivo_id usuario datahora_gmt tipo_arquivo nome_arquivo tamanho_arquivo
drop table t2, t1;
#End of 5.3 tests
......@@ -4921,6 +4921,37 @@ q 1 q
q 1 q
drop view v1;
drop table t1,t2;
#
# MDEV-5153: Server crashes in Item_ref::fix_fields on 2nd execution
# of PS with LEFT JOIN and MERGE view or SELECT SQ
#
CREATE TABLE t1 (i1 INT, c1 VARCHAR(6)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
CREATE TABLE t2 (c2 VARCHAR(6)) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('foobar'),('qux');
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1 WHERE ( c1 ) IN ( SELECT c2 FROM t2 ) AND i1 <= 2 ;
PREPARE stmt FROM 'SELECT * FROM t1 LEFT JOIN v1 ON (v1.i1 = t1.i1)';
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
drop view v1;
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1 WHERE ( c1, c1 ) IN ( SELECT c2, c2 FROM t2 ) AND i1 <= 2 ;
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
deallocate prepare stmt;
drop view v1;
drop table t1,t2;
# -----------------------------------------------------------------
# -- End of 5.3 tests.
# -----------------------------------------------------------------
......
......@@ -43,4 +43,54 @@ select * from t1 where a = '4828532208463511553';
select * from t1 where a in ('4828532208463511553');
drop table t1;
# End of 4.1 tests
--echo #End of 4.1 tests
--echo #
--echo # MDEV-5103: server crashed on singular Item_equal
--echo #
CREATE TABLE `t1` (
`tipo` enum('p','r') NOT NULL DEFAULT 'r',
`arquivo_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`arquivo_md5` char(32) NOT NULL,
`conteudo` longblob NOT NULL,
`usuario` varchar(15) NOT NULL,
`datahora_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`tipo_arquivo` varchar(255) NOT NULL,
`nome_arquivo` varchar(255) NOT NULL,
`tamanho_arquivo` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`tipo`,`arquivo_id`),
UNIQUE KEY `tipo` (`tipo`,`arquivo_md5`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO `t1` (`tipo`, `arquivo_id`, `arquivo_md5`, `conteudo`, `usuario`, `datahora_gmt`, `tipo_arquivo`, `nome_arquivo`, `tamanho_arquivo`) VALUES
('r', 1, 'ad18832202b199728921807033a8a515', '', 'rspadim', '2013-10-05 13:55:50', '001_cbr643', 'CBR6431677410201314132.ret', 21306);
CREATE TABLE `t2` (
`tipo` enum('p','r') NOT NULL DEFAULT 'p',
`arquivo_id` bigint(20) NOT NULL DEFAULT '0',
`usuario` varchar(25) NOT NULL,
`datahora` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`erros` longblob NOT NULL,
`importados` bigint(20) unsigned NOT NULL DEFAULT '0',
`n_importados` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`tipo`,`arquivo_id`,`datahora`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO `t2` (`tipo`, `arquivo_id`, `usuario`, `datahora`, `erros`, `importados`, `n_importados`) VALUES
('r', 1, 'rspadim', '2013-10-05 14:25:30', '', 32, 0);
SELECT
arquivo_id,usuario,datahora_gmt,tipo_arquivo,nome_arquivo,tamanho_arquivo
FROM t1 AS a
WHERE datahora_gmt>='0000-00-00 00:00:00' AND
datahora_gmt<='2013-10-07 02:59:59' AND tipo='r' AND
(tipo_arquivo,arquivo_id) NOT IN
(SELECT tipo_arquivo,arquivo_id
FROM t2
WHERE (tipo_arquivo,arquivo_id)=(a.tipo_arquivo,a.arquivo_id))
ORDER BY arquivo_id DESC;
drop table t2, t1;
--echo #End of 5.3 tests
......@@ -4845,6 +4845,34 @@ SELECT * FROM t2 LEFT JOIN v1 ON ( c=b AND a IN ( 1,6 ) );
drop view v1;
drop table t1,t2;
--echo #
--echo # MDEV-5153: Server crashes in Item_ref::fix_fields on 2nd execution
--echo # of PS with LEFT JOIN and MERGE view or SELECT SQ
--echo #
CREATE TABLE t1 (i1 INT, c1 VARCHAR(6)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
CREATE TABLE t2 (c2 VARCHAR(6)) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('foobar'),('qux');
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1 WHERE ( c1 ) IN ( SELECT c2 FROM t2 ) AND i1 <= 2 ;
PREPARE stmt FROM 'SELECT * FROM t1 LEFT JOIN v1 ON (v1.i1 = t1.i1)';
EXECUTE stmt;
EXECUTE stmt;
drop view v1;
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1 WHERE ( c1, c1 ) IN ( SELECT c2, c2 FROM t2 ) AND i1 <= 2 ;
EXECUTE stmt;
EXECUTE stmt;
deallocate prepare stmt;
drop view v1;
drop table t1,t2;
--echo # -----------------------------------------------------------------
--echo # -- End of 5.3 tests.
--echo # -----------------------------------------------------------------
......
......@@ -1438,9 +1438,11 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg)
bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
{
DBUG_ENTER("Item_in_optimizer::fix_left");
if ((!args[0]->fixed && args[0]->fix_fields(thd, args)) ||
(!cache && !(cache= Item_cache::get_cache(args[0]))))
return 1;
DBUG_RETURN(1);
DBUG_PRINT("info", ("actual fix fields"));
cache->setup(args[0]);
if (cache->cols() == 1)
......@@ -1466,11 +1468,15 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"SUBQUERY in ROW in left expression of IN/ALL/ANY");
return 1;
DBUG_RETURN(1);
}
Item *element=args[0]->element_index(i);
if (element->used_tables() || !element->const_item())
((Item_cache *)cache->element_index(i))->set_used_tables(OUTER_REF_TABLE_BIT);
{
((Item_cache *)cache->element_index(i))->
set_used_tables(OUTER_REF_TABLE_BIT);
cache->set_used_tables(OUTER_REF_TABLE_BIT);
}
else
((Item_cache *)cache->element_index(i))->set_used_tables(0);
}
......@@ -1484,7 +1490,7 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
cache->store(args[0]);
cache->cache_value();
}
return 0;
DBUG_RETURN(0);
}
......@@ -5681,6 +5687,12 @@ void Item_equal::add_const(Item *c, Item *f)
func->quick_fix_field();
cond_false= !func->val_int();
}
/*
TODO: also support the case where Item_equal becomes singular with
this->is_cond_true()=1. When I attempted to mark the item as constant,
the optimizer attempted to remove it, however it is still referenced from
COND_EQUAL and I got a crash.
*/
if (cond_false)
const_item_cache= 1;
}
......@@ -5885,7 +5897,8 @@ void Item_equal::merge_into_list(List<Item_equal> *list,
void Item_equal::sort(Item_field_cmpfunc compare, void *arg)
{
bubble_sort<Item>(&equal_items, compare, arg);
if (equal_items.elements > 1)
bubble_sort<Item>(&equal_items, compare, arg);
}
......@@ -5999,6 +6012,12 @@ bool Item_equal::fix_fields(THD *thd, Item **ref)
void Item_equal::update_used_tables()
{
not_null_tables_cache= used_tables_cache= 0;
/*
TODO: also support the case where Item_equal becomes singular with
this->is_cond_true()=1. When I attempted to mark the item as constant,
the optimizer attempted to remove it, however it is still referenced from
COND_EQUAL and I got a crash.
*/
if ((const_item_cache= cond_false))
return;
Item_equal_fields_iterator it(*this);
......@@ -6048,6 +6067,8 @@ longlong Item_equal::val_int()
{
if (cond_false)
return 0;
if (is_cond_true())
return 1;
Item *item= get_const();
Item_equal_fields_iterator it(*this);
if (!item)
......@@ -6072,6 +6093,11 @@ longlong Item_equal::val_int()
void Item_equal::fix_length_and_dec()
{
Item *item= get_first(NO_PARTICULAR_TAB, NULL);
if (!item)
{
DBUG_ASSERT(is_cond_true()); // it should be the only constant
item= equal_items.head();
}
eval_item= cmp_item::get_comparator(item->cmp_type(), item,
item->collation.collation);
}
......
......@@ -1718,6 +1718,7 @@ public:
Item_equal(Item_equal *item_equal);
/* Currently the const item is always the first in the list of equal items */
inline Item* get_const() { return with_const ? equal_items.head() : NULL; }
inline bool is_cond_true() { return equal_items.elements == 1; }
void add_const(Item *c, Item *f = NULL);
/** Add a non-constant item to the multiple equality */
void add(Item *f) { equal_items.push_back(f); }
......
......@@ -2264,11 +2264,11 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
DBUG_RETURN(true);
Item *item_eq=
new Item_func_eq(new
Item_ref(&select_lex->context,
(*optimizer->get_cache())->
addr(i),
(char *)"<no matter>",
(char *)in_left_expr_name),
Item_direct_ref(&select_lex->context,
(*optimizer->get_cache())->
addr(i),
(char *)"<no matter>",
(char *)in_left_expr_name),
new
Item_ref(&select_lex->context,
select_lex->ref_pointer_array + i,
......@@ -2549,7 +2549,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg)
bool
Item_in_subselect::select_in_like_transformer(JOIN *join)
{
Query_arena *arena, backup;
Query_arena *arena= 0, backup;
SELECT_LEX *current= thd->lex->current_select;
const char *save_where= thd->where;
bool trans_res= true;
......@@ -2571,9 +2571,6 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
}
}
if (changed)
DBUG_RETURN(false);
thd->where= "IN/ALL/ANY subquery";
/*
......@@ -2584,25 +2581,29 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
note: we won't need Item_in_optimizer when handling degenerate cases
like "... IN (SELECT 1)"
*/
arena= thd->activate_stmt_arena_if_needed(&backup);
if (!optimizer)
{
arena= thd->activate_stmt_arena_if_needed(&backup);
result= (!(optimizer= new Item_in_optimizer(left_expr, this)));
if (arena)
thd->restore_active_arena(arena, &backup);
if (result)
goto err;
goto out;
}
thd->lex->current_select= current->return_after_parsing();
result= (!left_expr->fixed &&
left_expr->fix_fields(thd, optimizer->arguments()));
result= optimizer->fix_left(thd, optimizer->arguments());
/* fix_fields can change reference to left_expr, we need reassign it */
left_expr= optimizer->arguments()[0];
thd->lex->current_select= current;
if (changed)
{
trans_res= false;
goto out;
}
if (result)
goto err;
goto out;
/*
Both transformers call fix_fields() only for Items created inside them,
......@@ -2611,7 +2612,6 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
of Item, we have to call fix_fields() for it only with original arena to
avoid memory leack)
*/
arena= thd->activate_stmt_arena_if_needed(&backup);
if (left_expr->cols() == 1)
trans_res= single_value_transformer(join);
else
......@@ -2626,9 +2626,9 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
}
trans_res= row_value_transformer(join);
}
out:
if (arena)
thd->restore_active_arena(arena, &backup);
err:
thd->where= save_where;
DBUG_RETURN(trans_res);
}
......
......@@ -1268,11 +1268,11 @@ void get_delayed_table_estimates(TABLE *table,
@brief Replaces an expression destructively inside the expression tree of
the WHERE clase.
@note Because of current requirements for semijoin flattening, we do not
need to recurse here, hence this function will only examine the top-level
AND conditions. (see JOIN::prepare, comment starting with "Check if the
subquery predicate can be executed via materialization".
@note We substitute AND/OR structure because it was copied by
copy_andor_structure and some changes could be done in the copy but
should be left permanent, also there could be several layers of AND over
AND and OR over OR because ::fix_field() possibly is not called.
@param join The top-level query.
@param old_cond The expression to be replaced.
@param new_cond The expression to be substituted.
......@@ -1300,13 +1300,20 @@ static bool replace_where_subcondition(JOIN *join, Item **expr,
Item *item;
while ((item= li++))
{
if (item == old_cond)
if (item == old_cond)
{
li.replace(new_cond);
if (do_fix_fields)
new_cond->fix_fields(join->thd, li.ref());
return FALSE;
}
else if (item->type() == Item::COND_ITEM)
{
DBUG_ASSERT(!(*expr)->fixed);
replace_where_subcondition(join, li.ref(),
old_cond, new_cond,
do_fix_fields);
}
}
}
/*
......
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