mirror of
https://github.com/MariaDB/server.git
synced 2025-08-05 13:16:09 +03:00
Merge tulin@bk-internal.mysql.com:/home/bk/mysql-5.0
into dl145b.mysql.com:/home/ndbdev/tomas/mysql-5.1 sql/mysql_priv.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_yacc.yy: Auto merged
This commit is contained in:
@@ -672,3 +672,17 @@ select default(t30.s1) from t30;
|
|||||||
end|
|
end|
|
||||||
drop procedure bug10969|
|
drop procedure bug10969|
|
||||||
drop table t1|
|
drop table t1|
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
create procedure p() deallocate prepare stmt;
|
||||||
|
ERROR 0A000: DEALLOCATE is not allowed in stored procedures
|
||||||
|
create function f() returns int begin deallocate prepare stmt;
|
||||||
|
ERROR 0A000: DEALLOCATE is not allowed in stored procedures
|
||||||
|
create procedure p() prepare stmt from "select 1";
|
||||||
|
ERROR 0A000: PREPARE is not allowed in stored procedures
|
||||||
|
create function f() returns int begin prepare stmt from "select 1";
|
||||||
|
ERROR 0A000: PREPARE is not allowed in stored procedures
|
||||||
|
create procedure p() execute stmt;
|
||||||
|
ERROR 0A000: EXECUTE is not allowed in stored procedures
|
||||||
|
create function f() returns int begin execute stmt;
|
||||||
|
ERROR 0A000: EXECUTE is not allowed in stored procedures
|
||||||
|
deallocate prepare stmt;
|
||||||
|
@@ -40,3 +40,18 @@ Id User Host db Command Time State Info
|
|||||||
unlock tables;
|
unlock tables;
|
||||||
drop procedure bug9486;
|
drop procedure bug9486;
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
|
drop procedure if exists bug11158;
|
||||||
|
create procedure bug11158() delete t1 from t1, t2 where t1.id = t2.id;
|
||||||
|
create table t1 (id int, j int);
|
||||||
|
insert into t1 values (1, 1), (2, 2);
|
||||||
|
create table t2 (id int);
|
||||||
|
insert into t2 values (1);
|
||||||
|
call bug11158();
|
||||||
|
select * from t1;
|
||||||
|
id j
|
||||||
|
2 2
|
||||||
|
lock tables t2 read;
|
||||||
|
call bug11158();
|
||||||
|
unlock tables;
|
||||||
|
drop procedure bug11158;
|
||||||
|
drop table t1, t2;
|
||||||
|
@@ -965,3 +965,24 @@ drop procedure bug10969|
|
|||||||
drop table t1|
|
drop table t1|
|
||||||
|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#10975, #10605, #7115: Dynamic SQL by means of
|
||||||
|
# PREPARE/EXECUTE/DEALLOCATE is not supported yet.
|
||||||
|
# Check that an error message is returned.
|
||||||
|
#
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
--error ER_SP_BADSTATEMENT
|
||||||
|
create procedure p() deallocate prepare stmt;
|
||||||
|
--error ER_SP_BADSTATEMENT
|
||||||
|
create function f() returns int begin deallocate prepare stmt;
|
||||||
|
--error ER_SP_BADSTATEMENT
|
||||||
|
create procedure p() prepare stmt from "select 1";
|
||||||
|
--error ER_SP_BADSTATEMENT
|
||||||
|
create function f() returns int begin prepare stmt from "select 1";
|
||||||
|
--error ER_SP_BADSTATEMENT
|
||||||
|
create procedure p() execute stmt;
|
||||||
|
--error ER_SP_BADSTATEMENT
|
||||||
|
create function f() returns int begin execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
|
||||||
|
@@ -84,6 +84,32 @@ reap;
|
|||||||
drop procedure bug9486;
|
drop procedure bug9486;
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#11158: Can't perform multi-delete in stored procedure
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
drop procedure if exists bug11158;
|
||||||
|
--enable_warnings
|
||||||
|
create procedure bug11158() delete t1 from t1, t2 where t1.id = t2.id;
|
||||||
|
create table t1 (id int, j int);
|
||||||
|
insert into t1 values (1, 1), (2, 2);
|
||||||
|
create table t2 (id int);
|
||||||
|
insert into t2 values (1);
|
||||||
|
# Procedure should work and cause proper effect (delete only first row)
|
||||||
|
call bug11158();
|
||||||
|
select * from t1;
|
||||||
|
# Also let us test that we obtain only read (and thus non exclusive) lock
|
||||||
|
# for table from which we are not going to delete rows.
|
||||||
|
connection con2root;
|
||||||
|
lock tables t2 read;
|
||||||
|
connection con1root;
|
||||||
|
call bug11158();
|
||||||
|
connection con2root;
|
||||||
|
unlock tables;
|
||||||
|
connection con1root;
|
||||||
|
# Clean-up
|
||||||
|
drop procedure bug11158;
|
||||||
|
drop table t1, t2;
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#NNNN: New bug synopsis
|
# BUG#NNNN: New bug synopsis
|
||||||
|
@@ -486,7 +486,7 @@ bool check_merge_table_access(THD *thd, char *db,
|
|||||||
TABLE_LIST *table_list);
|
TABLE_LIST *table_list);
|
||||||
bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
|
bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
|
||||||
bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
|
bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
|
||||||
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count);
|
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);
|
||||||
bool mysql_multi_update_prepare(THD *thd);
|
bool mysql_multi_update_prepare(THD *thd);
|
||||||
bool mysql_multi_delete_prepare(THD *thd);
|
bool mysql_multi_delete_prepare(THD *thd);
|
||||||
bool mysql_insert_select_prepare(THD *thd);
|
bool mysql_insert_select_prepare(THD *thd);
|
||||||
@@ -581,6 +581,7 @@ void mysql_init_query(THD *thd, uchar *buf, uint length);
|
|||||||
bool mysql_new_select(LEX *lex, bool move_down);
|
bool mysql_new_select(LEX *lex, bool move_down);
|
||||||
void create_select_for_variable(const char *var_name);
|
void create_select_for_variable(const char *var_name);
|
||||||
void mysql_init_multi_delete(LEX *lex);
|
void mysql_init_multi_delete(LEX *lex);
|
||||||
|
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
|
||||||
void init_max_user_conn(void);
|
void init_max_user_conn(void);
|
||||||
void init_update_queries(void);
|
void init_update_queries(void);
|
||||||
void free_max_user_conn(void);
|
void free_max_user_conn(void);
|
||||||
|
@@ -42,7 +42,6 @@ static my_bool open_new_frm(const char *path, const char *alias,
|
|||||||
uint db_stat, uint prgflag,
|
uint db_stat, uint prgflag,
|
||||||
uint ha_open_flags, TABLE *outparam,
|
uint ha_open_flags, TABLE *outparam,
|
||||||
TABLE_LIST *table_desc, MEM_ROOT *mem_root);
|
TABLE_LIST *table_desc, MEM_ROOT *mem_root);
|
||||||
static void relink_tables_for_multidelete(THD *thd);
|
|
||||||
|
|
||||||
extern "C" byte *table_cache_key(const byte *record,uint *length,
|
extern "C" byte *table_cache_key(const byte *record,uint *length,
|
||||||
my_bool not_used __attribute__((unused)))
|
my_bool not_used __attribute__((unused)))
|
||||||
@@ -2089,7 +2088,6 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables)
|
|||||||
(thd->fill_derived_tables() &&
|
(thd->fill_derived_tables() &&
|
||||||
mysql_handle_derived(thd->lex, &mysql_derived_filling)))
|
mysql_handle_derived(thd->lex, &mysql_derived_filling)))
|
||||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||||
relink_tables_for_multidelete(thd);
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2119,36 +2117,10 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables)
|
|||||||
if (open_tables(thd, &tables, &counter) ||
|
if (open_tables(thd, &tables, &counter) ||
|
||||||
mysql_handle_derived(thd->lex, &mysql_derived_prepare))
|
mysql_handle_derived(thd->lex, &mysql_derived_prepare))
|
||||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||||
relink_tables_for_multidelete(thd); // Not really needed, but
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Let us propagate pointers to open tables from global table list
|
|
||||||
to table lists for multi-delete
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void relink_tables_for_multidelete(THD *thd)
|
|
||||||
{
|
|
||||||
if (thd->lex->all_selects_list->next_select_in_list())
|
|
||||||
{
|
|
||||||
for (SELECT_LEX *sl= thd->lex->all_selects_list;
|
|
||||||
sl;
|
|
||||||
sl= sl->next_select_in_list())
|
|
||||||
{
|
|
||||||
for (TABLE_LIST *cursor= (TABLE_LIST *) sl->table_list.first;
|
|
||||||
cursor;
|
|
||||||
cursor=cursor->next_local)
|
|
||||||
{
|
|
||||||
if (cursor->correspondent_table)
|
|
||||||
cursor->table= cursor->correspondent_table->table;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mark all real tables in the list as free for reuse.
|
Mark all real tables in the list as free for reuse.
|
||||||
|
|
||||||
|
@@ -752,7 +752,12 @@ typedef struct st_lex
|
|||||||
uint grant, grant_tot_col, which_columns;
|
uint grant, grant_tot_col, which_columns;
|
||||||
uint fk_delete_opt, fk_update_opt, fk_match_option;
|
uint fk_delete_opt, fk_update_opt, fk_match_option;
|
||||||
uint slave_thd_opt, start_transaction_opt;
|
uint slave_thd_opt, start_transaction_opt;
|
||||||
uint table_count; /* used when usual update transformed in multiupdate */
|
/*
|
||||||
|
In LEX representing update which were transformed to multi-update
|
||||||
|
stores total number of tables. For LEX representing multi-delete
|
||||||
|
holds number of tables from which we will delete records.
|
||||||
|
*/
|
||||||
|
uint table_count;
|
||||||
uint8 describe;
|
uint8 describe;
|
||||||
uint8 derived_tables;
|
uint8 derived_tables;
|
||||||
uint8 create_view_algorithm;
|
uint8 create_view_algorithm;
|
||||||
|
@@ -3295,10 +3295,9 @@ end_with_restore_list:
|
|||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
TABLE_LIST *aux_tables=
|
TABLE_LIST *aux_tables=
|
||||||
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
|
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
|
||||||
uint table_count;
|
|
||||||
multi_delete *result;
|
multi_delete *result;
|
||||||
|
|
||||||
if ((res= multi_delete_precheck(thd, all_tables, &table_count)))
|
if ((res= multi_delete_precheck(thd, all_tables)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* condition will be TRUE on SP re-excuting */
|
/* condition will be TRUE on SP re-excuting */
|
||||||
@@ -3315,7 +3314,7 @@ end_with_restore_list:
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
|
if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
|
||||||
table_count)))
|
lex->table_count)))
|
||||||
{
|
{
|
||||||
res= mysql_select(thd, &select_lex->ref_pointer_array,
|
res= mysql_select(thd, &select_lex->ref_pointer_array,
|
||||||
select_lex->get_table_list(),
|
select_lex->get_table_list(),
|
||||||
@@ -6805,23 +6804,19 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
|
|||||||
multi_delete_precheck()
|
multi_delete_precheck()
|
||||||
thd Thread handler
|
thd Thread handler
|
||||||
tables Global/local table list
|
tables Global/local table list
|
||||||
table_count Pointer to table counter
|
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
FALSE OK
|
FALSE OK
|
||||||
TRUE error
|
TRUE error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
|
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
|
||||||
{
|
{
|
||||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||||
TABLE_LIST *aux_tables=
|
TABLE_LIST *aux_tables=
|
||||||
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
|
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
|
||||||
TABLE_LIST *target_tbl;
|
|
||||||
DBUG_ENTER("multi_delete_precheck");
|
DBUG_ENTER("multi_delete_precheck");
|
||||||
|
|
||||||
*table_count= 0;
|
|
||||||
|
|
||||||
/* sql_yacc guarantees that tables and aux_tables are not zero */
|
/* sql_yacc guarantees that tables and aux_tables are not zero */
|
||||||
DBUG_ASSERT(aux_tables != 0);
|
DBUG_ASSERT(aux_tables != 0);
|
||||||
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
|
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
|
||||||
@@ -6834,9 +6829,35 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
|
|||||||
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
|
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
for (target_tbl= aux_tables; target_tbl; target_tbl= target_tbl->next_local)
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Link tables in auxilary table list of multi-delete with corresponding
|
||||||
|
elements in main table list, and set proper locks for them.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
multi_delete_set_locks_and_link_aux_tables()
|
||||||
|
lex - pointer to LEX representing multi-delete
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
FALSE - success
|
||||||
|
TRUE - error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
|
||||||
{
|
{
|
||||||
(*table_count)++;
|
TABLE_LIST *tables= (TABLE_LIST*)lex->select_lex.table_list.first;
|
||||||
|
TABLE_LIST *target_tbl;
|
||||||
|
DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables");
|
||||||
|
|
||||||
|
lex->table_count= 0;
|
||||||
|
|
||||||
|
for (target_tbl= (TABLE_LIST *)lex->auxilliary_table_list.first;
|
||||||
|
target_tbl; target_tbl= target_tbl->next_local)
|
||||||
|
{
|
||||||
|
lex->table_count++;
|
||||||
/* All tables in aux_tables must be found in FROM PART */
|
/* All tables in aux_tables must be found in FROM PART */
|
||||||
TABLE_LIST *walk;
|
TABLE_LIST *walk;
|
||||||
for (walk= tables; walk; walk= walk->next_local)
|
for (walk= tables; walk; walk= walk->next_local)
|
||||||
@@ -6854,14 +6875,6 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
|
|||||||
}
|
}
|
||||||
walk->lock_type= target_tbl->lock_type;
|
walk->lock_type= target_tbl->lock_type;
|
||||||
target_tbl->correspondent_table= walk; // Remember corresponding table
|
target_tbl->correspondent_table= walk; // Remember corresponding table
|
||||||
|
|
||||||
/* in case of subselects, we need to set lock_type in
|
|
||||||
* corresponding table in list of all tables */
|
|
||||||
if (walk->correspondent_table)
|
|
||||||
{
|
|
||||||
target_tbl->correspondent_table= walk->correspondent_table;
|
|
||||||
walk->correspondent_table->lock_type= walk->lock_type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
@@ -1402,8 +1402,6 @@ static bool mysql_test_multiupdate(Prepared_statement *stmt,
|
|||||||
static bool mysql_test_multidelete(Prepared_statement *stmt,
|
static bool mysql_test_multidelete(Prepared_statement *stmt,
|
||||||
TABLE_LIST *tables)
|
TABLE_LIST *tables)
|
||||||
{
|
{
|
||||||
uint fake_counter;
|
|
||||||
|
|
||||||
stmt->thd->lex->current_select= &stmt->thd->lex->select_lex;
|
stmt->thd->lex->current_select= &stmt->thd->lex->select_lex;
|
||||||
if (add_item_to_list(stmt->thd, new Item_null()))
|
if (add_item_to_list(stmt->thd, new Item_null()))
|
||||||
{
|
{
|
||||||
@@ -1411,7 +1409,7 @@ static bool mysql_test_multidelete(Prepared_statement *stmt,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (multi_delete_precheck(stmt->thd, tables, &fake_counter) ||
|
if (multi_delete_precheck(stmt->thd, tables) ||
|
||||||
select_like_stmt_test_with_open_n_lock(stmt, tables,
|
select_like_stmt_test_with_open_n_lock(stmt, tables,
|
||||||
&mysql_multi_delete_prepare,
|
&mysql_multi_delete_prepare,
|
||||||
OPTION_SETUP_TABLES_DONE))
|
OPTION_SETUP_TABLES_DONE))
|
||||||
|
@@ -919,6 +919,11 @@ deallocate:
|
|||||||
yyerror(ER(ER_SYNTAX_ERROR));
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
if (lex->sphead)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_BADSTATEMENT, MYF(0), "DEALLOCATE");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
lex->sql_command= SQLCOM_DEALLOCATE_PREPARE;
|
lex->sql_command= SQLCOM_DEALLOCATE_PREPARE;
|
||||||
lex->prepared_stmt_name= $3;
|
lex->prepared_stmt_name= $3;
|
||||||
};
|
};
|
||||||
@@ -939,6 +944,11 @@ prepare:
|
|||||||
yyerror(ER(ER_SYNTAX_ERROR));
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
if (lex->sphead)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_BADSTATEMENT, MYF(0), "PREPARE");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
lex->sql_command= SQLCOM_PREPARE;
|
lex->sql_command= SQLCOM_PREPARE;
|
||||||
lex->prepared_stmt_name= $2;
|
lex->prepared_stmt_name= $2;
|
||||||
};
|
};
|
||||||
@@ -969,6 +979,11 @@ execute:
|
|||||||
yyerror(ER(ER_SYNTAX_ERROR));
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
if (lex->sphead)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_BADSTATEMENT, MYF(0), "EXECUTE");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
lex->sql_command= SQLCOM_EXECUTE;
|
lex->sql_command= SQLCOM_EXECUTE;
|
||||||
lex->prepared_stmt_name= $2;
|
lex->prepared_stmt_name= $2;
|
||||||
}
|
}
|
||||||
@@ -6132,10 +6147,17 @@ single_multi:
|
|||||||
| table_wild_list
|
| table_wild_list
|
||||||
{ mysql_init_multi_delete(Lex); }
|
{ mysql_init_multi_delete(Lex); }
|
||||||
FROM join_table_list where_clause
|
FROM join_table_list where_clause
|
||||||
|
{
|
||||||
|
if (multi_delete_set_locks_and_link_aux_tables(Lex))
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
| FROM table_wild_list
|
| FROM table_wild_list
|
||||||
{ mysql_init_multi_delete(Lex); }
|
{ mysql_init_multi_delete(Lex); }
|
||||||
USING join_table_list where_clause
|
USING join_table_list where_clause
|
||||||
{}
|
{
|
||||||
|
if (multi_delete_set_locks_and_link_aux_tables(Lex))
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
table_wild_list:
|
table_wild_list:
|
||||||
|
Reference in New Issue
Block a user