mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 05:52:27 +01:00
Merge gleb.loc:/home/uchum/work/bk/5.1
into gleb.loc:/home/uchum/work/bk/5.1-opt
This commit is contained in:
commit
be6ee4314e
14 changed files with 287 additions and 34 deletions
|
@ -4673,9 +4673,17 @@ int cli_read_binary_rows(MYSQL_STMT *stmt)
|
|||
MYSQL *mysql= stmt->mysql;
|
||||
MYSQL_DATA *result= &stmt->result;
|
||||
MYSQL_ROWS *cur, **prev_ptr= &result->data;
|
||||
NET *net = &mysql->net;
|
||||
NET *net;
|
||||
|
||||
if (!mysql)
|
||||
{
|
||||
set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate);
|
||||
return 1;
|
||||
}
|
||||
|
||||
DBUG_ENTER("cli_read_binary_rows");
|
||||
|
||||
net = &mysql->net;
|
||||
mysql= mysql->last_used_con;
|
||||
|
||||
while ((pkt_len= cli_safe_read(mysql)) != packet_error)
|
||||
|
|
|
@ -939,6 +939,36 @@ alter table t1 add index(a(1024));
|
|||
show create table t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug #28570: handler::index_read() is called with different find_flag when
|
||||
# ORDER BY is used
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (
|
||||
a INT,
|
||||
b INT,
|
||||
KEY (b)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
INSERT INTO t1 VALUES (1,10), (2,10), (2,20), (3,30);
|
||||
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1 WHERE b=20 FOR UPDATE;
|
||||
|
||||
--connect (conn2, localhost, root,,test)
|
||||
|
||||
# This statement gives a "failed: 1205: Lock wait timeout exceeded; try
|
||||
# restarting transaction" message when the bug is present.
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1 WHERE b=10 ORDER BY A FOR UPDATE;
|
||||
ROLLBACK;
|
||||
|
||||
--disconnect conn2
|
||||
--connection default
|
||||
|
||||
ROLLBACK;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
||||
# Fix for BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY
|
||||
|
|
|
@ -1123,6 +1123,24 @@ t1 CREATE TABLE `t1` (
|
|||
KEY `a` (`a`(255))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (
|
||||
a INT,
|
||||
b INT,
|
||||
KEY (b)
|
||||
) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES (1,10), (2,10), (2,20), (3,30);
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1 WHERE b=20 FOR UPDATE;
|
||||
a b
|
||||
2 20
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1 WHERE b=10 ORDER BY A FOR UPDATE;
|
||||
a b
|
||||
1 10
|
||||
2 10
|
||||
ROLLBACK;
|
||||
ROLLBACK;
|
||||
DROP TABLE t1;
|
||||
End of 5.0 tests
|
||||
CREATE TABLE `t2` (
|
||||
`k` int(11) NOT NULL auto_increment,
|
||||
|
|
|
@ -3990,4 +3990,61 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||
EXPLAIN SELECT c1 FROM t1 WHERE (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT COUNT(c2))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) > 0;
|
||||
ERROR HY000: Too high level of nesting for select
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (
|
||||
c1 int(11) NOT NULL AUTO_INCREMENT,
|
||||
c2 varchar(1000) DEFAULT NULL,
|
||||
c3 bigint(20) DEFAULT NULL,
|
||||
c4 bigint(20) DEFAULT NULL,
|
||||
PRIMARY KEY (c1)
|
||||
);
|
||||
EXPLAIN EXTENDED
|
||||
SELECT join_2.c1
|
||||
FROM
|
||||
t1 AS join_0,
|
||||
t1 AS join_1,
|
||||
t1 AS join_2,
|
||||
t1 AS join_3,
|
||||
t1 AS join_4,
|
||||
t1 AS join_5,
|
||||
t1 AS join_6,
|
||||
t1 AS join_7
|
||||
WHERE
|
||||
join_0.c1=join_1.c1 AND
|
||||
join_1.c1=join_2.c1 AND
|
||||
join_2.c1=join_3.c1 AND
|
||||
join_3.c1=join_4.c1 AND
|
||||
join_4.c1=join_5.c1 AND
|
||||
join_5.c1=join_6.c1 AND
|
||||
join_6.c1=join_7.c1
|
||||
OR
|
||||
join_0.c2 < '?' AND
|
||||
join_1.c2 < '?' AND
|
||||
join_2.c2 > '?' AND
|
||||
join_2.c2 < '!' AND
|
||||
join_3.c2 > '?' AND
|
||||
join_4.c2 = '?' AND
|
||||
join_5.c2 <> '?' AND
|
||||
join_6.c2 <> '?' AND
|
||||
join_7.c2 >= '?' AND
|
||||
join_0.c1=join_1.c1 AND
|
||||
join_1.c1=join_2.c1 AND
|
||||
join_2.c1=join_3.c1 AND
|
||||
join_3.c1=join_4.c1 AND
|
||||
join_4.c1=join_5.c1 AND
|
||||
join_5.c1=join_6.c1 AND
|
||||
join_6.c1=join_7.c1
|
||||
GROUP BY
|
||||
join_3.c1,
|
||||
join_2.c1,
|
||||
join_7.c1,
|
||||
join_1.c1,
|
||||
join_0.c1;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
Warnings:
|
||||
Note 1003 select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0'
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Note 1003 select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0'
|
||||
DROP TABLE t1;
|
||||
End of 5.0 tests
|
||||
|
|
|
@ -3389,4 +3389,64 @@ eval EXPLAIN SELECT c1 FROM t1 WHERE $q > 0;
|
|||
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug #30396: crash for a join with equalities and sargable predicates
|
||||
# in disjunctive parts of the WHERE condition
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (
|
||||
c1 int(11) NOT NULL AUTO_INCREMENT,
|
||||
c2 varchar(1000) DEFAULT NULL,
|
||||
c3 bigint(20) DEFAULT NULL,
|
||||
c4 bigint(20) DEFAULT NULL,
|
||||
PRIMARY KEY (c1)
|
||||
);
|
||||
|
||||
EXPLAIN EXTENDED
|
||||
SELECT join_2.c1
|
||||
FROM
|
||||
t1 AS join_0,
|
||||
t1 AS join_1,
|
||||
t1 AS join_2,
|
||||
t1 AS join_3,
|
||||
t1 AS join_4,
|
||||
t1 AS join_5,
|
||||
t1 AS join_6,
|
||||
t1 AS join_7
|
||||
WHERE
|
||||
join_0.c1=join_1.c1 AND
|
||||
join_1.c1=join_2.c1 AND
|
||||
join_2.c1=join_3.c1 AND
|
||||
join_3.c1=join_4.c1 AND
|
||||
join_4.c1=join_5.c1 AND
|
||||
join_5.c1=join_6.c1 AND
|
||||
join_6.c1=join_7.c1
|
||||
OR
|
||||
join_0.c2 < '?' AND
|
||||
join_1.c2 < '?' AND
|
||||
join_2.c2 > '?' AND
|
||||
join_2.c2 < '!' AND
|
||||
join_3.c2 > '?' AND
|
||||
join_4.c2 = '?' AND
|
||||
join_5.c2 <> '?' AND
|
||||
join_6.c2 <> '?' AND
|
||||
join_7.c2 >= '?' AND
|
||||
join_0.c1=join_1.c1 AND
|
||||
join_1.c1=join_2.c1 AND
|
||||
join_2.c1=join_3.c1 AND
|
||||
join_3.c1=join_4.c1 AND
|
||||
join_4.c1=join_5.c1 AND
|
||||
join_5.c1=join_6.c1 AND
|
||||
join_6.c1=join_7.c1
|
||||
GROUP BY
|
||||
join_3.c1,
|
||||
join_2.c1,
|
||||
join_7.c1,
|
||||
join_1.c1,
|
||||
join_0.c1;
|
||||
|
||||
SHOW WARNINGS;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
|
|
@ -2676,6 +2676,7 @@ int ha_partition::write_row(uchar * buf)
|
|||
uint32 part_id;
|
||||
int error;
|
||||
longlong func_value;
|
||||
bool autoincrement_lock= false;
|
||||
#ifdef NOT_NEEDED
|
||||
uchar *rec0= m_rec0;
|
||||
#endif
|
||||
|
@ -2691,7 +2692,21 @@ int ha_partition::write_row(uchar * buf)
|
|||
or a new row, then update the auto_increment value in the record.
|
||||
*/
|
||||
if (table->next_number_field && buf == table->record[0])
|
||||
{
|
||||
/*
|
||||
Some engines (InnoDB for example) can change autoincrement
|
||||
counter only after 'table->write_row' operation.
|
||||
So if another thread gets inside the ha_partition::write_row
|
||||
before it is complete, it gets same auto_increment value,
|
||||
which means DUP_KEY error (bug #27405)
|
||||
Here we separate the access using table_share->mutex, and
|
||||
use autoincrement_lock variable to avoid unnecessary locks.
|
||||
Probably not an ideal solution.
|
||||
*/
|
||||
autoincrement_lock= true;
|
||||
pthread_mutex_lock(&table_share->mutex);
|
||||
update_auto_increment();
|
||||
}
|
||||
|
||||
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
|
||||
#ifdef NOT_NEEDED
|
||||
|
@ -2712,11 +2727,15 @@ int ha_partition::write_row(uchar * buf)
|
|||
if (unlikely(error))
|
||||
{
|
||||
m_part_info->err_value= func_value;
|
||||
DBUG_RETURN(error);
|
||||
goto exit;
|
||||
}
|
||||
m_last_part= part_id;
|
||||
DBUG_PRINT("info", ("Insert in partition %d", part_id));
|
||||
DBUG_RETURN(m_file[part_id]->write_row(buf));
|
||||
error= m_file[part_id]->write_row(buf);
|
||||
exit:
|
||||
if (autoincrement_lock)
|
||||
pthread_mutex_unlock(&table_share->mutex);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3186,7 +3186,8 @@ int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
|
|||
read_range_first()
|
||||
start_key Start key. Is 0 if no min range
|
||||
end_key End key. Is 0 if no max range
|
||||
eq_range_arg Set to 1 if start_key == end_key
|
||||
eq_range_arg Set to 1 if start_key == end_key and the range endpoints
|
||||
will not change during query execution.
|
||||
sorted Set to 1 if result should be sorted per key
|
||||
|
||||
NOTES
|
||||
|
|
|
@ -1570,7 +1570,6 @@ public:
|
|||
the current and level */
|
||||
COND_EQUAL()
|
||||
{
|
||||
max_members= 0;
|
||||
upper_levels= 0;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7815,8 +7815,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
|||
range->min_keypart_map= range->max_keypart_map=
|
||||
make_prev_keypart_map(ref->key_parts);
|
||||
range->flag= ((ref->key_length == key_info->key_length &&
|
||||
(key_info->flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
|
||||
HA_NOSAME) ? EQ_RANGE : 0);
|
||||
(key_info->flags & HA_END_SPACE_KEY) == 0) ? EQ_RANGE : 0);
|
||||
|
||||
if (!(quick->key_parts=key_part=(KEY_PART *)
|
||||
alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts)))
|
||||
|
|
|
@ -6738,6 +6738,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
|||
DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns));
|
||||
select_lex->cond_count= 0;
|
||||
select_lex->between_count= 0;
|
||||
select_lex->max_equal_elems= 0;
|
||||
|
||||
for (table= tables; table; table= table->next_local)
|
||||
{
|
||||
|
|
|
@ -1517,6 +1517,7 @@ void st_select_lex::init_query()
|
|||
*/
|
||||
parent_lex->push_context(&context);
|
||||
cond_count= between_count= with_wild= 0;
|
||||
max_equal_elems= 0;
|
||||
conds_processed_with_permanent_arena= 0;
|
||||
ref_pointer_array= 0;
|
||||
select_n_where_fields= 0;
|
||||
|
|
|
@ -607,6 +607,7 @@ public:
|
|||
uint select_n_having_items;
|
||||
uint cond_count; /* number of arguments of and/or/xor in where/having/on */
|
||||
uint between_count; /* number of between predicates in where/having/on */
|
||||
uint max_equal_elems; /* maximal number of elements in multiple equalities */
|
||||
/*
|
||||
Number of fields used in select list or where clause of current select
|
||||
and all inner subselects.
|
||||
|
|
|
@ -3562,10 +3562,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
|
|||
uint and_level,i,found_eq_constant;
|
||||
KEY_FIELD *key_fields, *end, *field;
|
||||
uint sz;
|
||||
uint m= 1;
|
||||
|
||||
if (cond_equal && cond_equal->max_members)
|
||||
m= cond_equal->max_members;
|
||||
uint m= max(select_lex->max_equal_elems,1);
|
||||
|
||||
/*
|
||||
We use the same piece of memory to store both KEY_FIELD
|
||||
|
@ -3585,7 +3582,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
|
|||
it is considered as sargable only for its first argument.
|
||||
Multiple equality can add elements that are filled after
|
||||
substitution of field arguments by equal fields. There
|
||||
can be not more than cond_equal->max_members such substitutions.
|
||||
can be not more than select_lex->max_equal_elems such
|
||||
substitutions.
|
||||
*/
|
||||
sz= max(sizeof(KEY_FIELD),sizeof(SARGABLE_PARAM))*
|
||||
(((thd->lex->current_select->cond_count+1)*2 +
|
||||
|
@ -7388,8 +7386,7 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal,
|
|||
just an argument of a comparison predicate.
|
||||
The function also determines the maximum number of members in
|
||||
equality lists of each Item_cond_and object assigning it to
|
||||
cond_equal->max_members of this object and updating accordingly
|
||||
the upper levels COND_EQUAL structures.
|
||||
thd->lex->current_select->max_equal_elems.
|
||||
|
||||
NOTES
|
||||
Multiple equality predicate =(f1,..fn) is equivalent to the conjuction of
|
||||
|
@ -7434,7 +7431,6 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
|
|||
COND_EQUAL *inherited)
|
||||
{
|
||||
Item_equal *item_equal;
|
||||
uint members;
|
||||
COND_EQUAL cond_equal;
|
||||
cond_equal.upper_levels= inherited;
|
||||
|
||||
|
@ -7472,19 +7468,8 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
|
|||
{
|
||||
item_equal->fix_length_and_dec();
|
||||
item_equal->update_used_tables();
|
||||
members= item_equal->members();
|
||||
if (cond_equal.max_members < members)
|
||||
cond_equal.max_members= members;
|
||||
}
|
||||
members= cond_equal.max_members;
|
||||
if (inherited && inherited->max_members < members)
|
||||
{
|
||||
do
|
||||
{
|
||||
inherited->max_members= members;
|
||||
inherited= inherited->upper_levels;
|
||||
}
|
||||
while (inherited);
|
||||
set_if_bigger(thd->lex->current_select->max_equal_elems,
|
||||
item_equal->members());
|
||||
}
|
||||
|
||||
((Item_cond_and*)cond)->cond_equal= cond_equal;
|
||||
|
@ -7539,10 +7524,12 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
|
|||
{
|
||||
item_equal->fix_length_and_dec();
|
||||
item_equal->update_used_tables();
|
||||
return item_equal;
|
||||
}
|
||||
else
|
||||
return eq_list.pop();
|
||||
item_equal= (Item_equal *) eq_list.pop();
|
||||
set_if_bigger(thd->lex->current_select->max_equal_elems,
|
||||
item_equal->members());
|
||||
return item_equal;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -7558,9 +7545,8 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
|
|||
{
|
||||
item_equal->fix_length_and_dec();
|
||||
item_equal->update_used_tables();
|
||||
members= item_equal->members();
|
||||
if (cond_equal.max_members < members)
|
||||
cond_equal.max_members= members;
|
||||
set_if_bigger(thd->lex->current_select->max_equal_elems,
|
||||
item_equal->members());
|
||||
}
|
||||
and_cond->cond_equal= cond_equal;
|
||||
args->concat((List<Item> *)&cond_equal.current_level);
|
||||
|
|
|
@ -16269,6 +16269,78 @@ static void test_bug27592()
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
static void test_bug29948()
|
||||
{
|
||||
MYSQL *dbc=NULL;
|
||||
MYSQL_STMT *stmt=NULL;
|
||||
MYSQL_BIND bind;
|
||||
|
||||
int res=0;
|
||||
my_bool auto_reconnect=1, error=0, is_null=0;
|
||||
char kill_buf[20];
|
||||
const char *query;
|
||||
int buf;
|
||||
unsigned long length, cursor_type;
|
||||
|
||||
dbc = mysql_init(NULL);
|
||||
DIE_UNLESS(dbc);
|
||||
|
||||
mysql_options(dbc, MYSQL_OPT_RECONNECT, (char*)&auto_reconnect);
|
||||
if (!mysql_real_connect(dbc, opt_host, opt_user,
|
||||
opt_password, current_db, opt_port,
|
||||
opt_unix_socket,
|
||||
(CLIENT_FOUND_ROWS | CLIENT_MULTI_STATEMENTS |
|
||||
CLIENT_MULTI_RESULTS)))
|
||||
{
|
||||
printf("connection failed: %s (%d)", mysql_error(dbc),
|
||||
mysql_errno(dbc));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bind.buffer_type= MYSQL_TYPE_LONG;
|
||||
bind.buffer= (char *)&buf;
|
||||
bind.is_null= &is_null;
|
||||
bind.error= &error;
|
||||
bind.length= &length;
|
||||
|
||||
res= mysql_query(dbc, "DROP TABLE IF EXISTS t1");
|
||||
myquery(res);
|
||||
res= mysql_query(dbc, "CREATE TABLE t1 (a INT)");
|
||||
myquery(res);
|
||||
res= mysql_query(dbc, "INSERT INTO t1 VALUES(1)");
|
||||
myquery(res);
|
||||
|
||||
stmt= mysql_stmt_init(dbc);
|
||||
check_stmt(stmt);
|
||||
|
||||
cursor_type= CURSOR_TYPE_READ_ONLY;
|
||||
res= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void *)&cursor_type);
|
||||
myquery(res);
|
||||
|
||||
query= "SELECT * from t1 where a=?";
|
||||
res= mysql_stmt_prepare(stmt, query, strlen(query));
|
||||
myquery(res);
|
||||
|
||||
res= mysql_stmt_bind_param(stmt, &bind);
|
||||
myquery(res);
|
||||
|
||||
res= mysql_stmt_execute(stmt);
|
||||
check_execute(stmt, res);
|
||||
|
||||
res= mysql_stmt_bind_result(stmt,&bind);
|
||||
check_execute(stmt, res);
|
||||
|
||||
sprintf(kill_buf, "kill %ld", dbc->thread_id);
|
||||
mysql_query(dbc, kill_buf);
|
||||
|
||||
res= mysql_stmt_store_result(stmt);
|
||||
DIE_UNLESS(res);
|
||||
|
||||
mysql_stmt_free_result(stmt);
|
||||
mysql_stmt_close(stmt);
|
||||
mysql_query(dbc, "DROP TABLE t1");
|
||||
mysql_close(dbc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -16670,6 +16742,7 @@ static struct my_tests_st my_tests[]= {
|
|||
{ "test_bug28505", test_bug28505 },
|
||||
{ "test_bug28934", test_bug28934 },
|
||||
{ "test_bug27592", test_bug27592 },
|
||||
{ "test_bug29948", test_bug29948 },
|
||||
{ "test_bug29687", test_bug29687 },
|
||||
{ "test_bug29692", test_bug29692 },
|
||||
{ "test_bug29306", test_bug29306 },
|
||||
|
|
Loading…
Reference in a new issue