mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Fixed BUG#1965: Opening a cursor hangs client when malformed select fails
and BUG#1966: "select 1 into a" on top-level hangs client include/mysql_com.h: Added no_send_eof flag to NET for SP cursors (the simple read-only version). mysql-test/r/sp-error.result: Added tests for BUG#1965 and BUG#1966. mysql-test/t/sp-error.test: Added tests for BUG#1965 and BUG#1966. sql/net_serv.cc: Added no_send_eof flag to NET for SP cursors (the simple read-only version). sql/protocol.cc: Added no_send_eof flag to NET for SP cursors (the simple read-only version). sql/sp_rcontext.cc: Use net->no_send_eof flag to prevent eofs during cursor open (instead of the dirty vio=0 which didn't work). sql/sp_rcontext.h: Use net->no_send_eof flag to prevent eofs during cursor open (instead of the dirty vio=0 which didn't work). sql/sql_yacc.yy: Give error message if doing SELECT ... INTO localvar even if it's outside an SP.
This commit is contained in:
@ -157,7 +157,8 @@ typedef struct st_net {
|
|||||||
unsigned int *return_status;
|
unsigned int *return_status;
|
||||||
unsigned char reading_or_writing;
|
unsigned char reading_or_writing;
|
||||||
char save_char;
|
char save_char;
|
||||||
my_bool no_send_ok;
|
my_bool no_send_ok; /* For SPs and other things that do multiple stmts */
|
||||||
|
my_bool no_send_eof; /* For SPs' first version read-only cursors */
|
||||||
/*
|
/*
|
||||||
Pointer to query object in query cache, do not equal NULL (0) for
|
Pointer to query object in query cache, do not equal NULL (0) for
|
||||||
queries in cache that have not stored its results yet
|
queries in cache that have not stored its results yet
|
||||||
|
@ -259,4 +259,15 @@ declare c cursor for select * from t1;
|
|||||||
declare c cursor for select field from t1;
|
declare c cursor for select field from t1;
|
||||||
end;
|
end;
|
||||||
ERROR 42000: Duplicate cursor: c
|
ERROR 42000: Duplicate cursor: c
|
||||||
|
create procedure bug1965()
|
||||||
|
begin
|
||||||
|
declare c cursor for select val from t1 order by valname;
|
||||||
|
open c;
|
||||||
|
close c;
|
||||||
|
end;
|
||||||
|
call bug1965();
|
||||||
|
ERROR 42S22: Unknown column 'valname' in 'order clause'
|
||||||
|
drop procedure bug1965;
|
||||||
|
select 1 into a;
|
||||||
|
ERROR 42000: Undeclared variable: a
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -341,6 +341,27 @@ begin
|
|||||||
declare c cursor for select field from t1;
|
declare c cursor for select field from t1;
|
||||||
end|
|
end|
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#1965
|
||||||
|
#
|
||||||
|
create procedure bug1965()
|
||||||
|
begin
|
||||||
|
declare c cursor for select val from t1 order by valname;
|
||||||
|
open c;
|
||||||
|
close c;
|
||||||
|
end|
|
||||||
|
|
||||||
|
--error 1054
|
||||||
|
call bug1965()|
|
||||||
|
drop procedure bug1965|
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#1966
|
||||||
|
#
|
||||||
|
--error 1308
|
||||||
|
select 1 into a|
|
||||||
|
|
||||||
|
|
||||||
drop table t1|
|
drop table t1|
|
||||||
|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
|
@ -123,6 +123,7 @@ my_bool my_net_init(NET *net, Vio* vio)
|
|||||||
net->buff_end=net->buff+net->max_packet;
|
net->buff_end=net->buff+net->max_packet;
|
||||||
net->vio = vio;
|
net->vio = vio;
|
||||||
net->no_send_ok = 0;
|
net->no_send_ok = 0;
|
||||||
|
net->no_send_eof = 0;
|
||||||
net->error=0; net->return_errno=0; net->return_status=0;
|
net->error=0; net->return_errno=0; net->return_status=0;
|
||||||
net->pkt_nr=net->compress_pkt_nr=0;
|
net->pkt_nr=net->compress_pkt_nr=0;
|
||||||
net->write_pos=net->read_pos = net->buff;
|
net->write_pos=net->read_pos = net->buff;
|
||||||
|
@ -347,7 +347,7 @@ send_eof(THD *thd, bool no_flush)
|
|||||||
static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
|
static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
|
||||||
NET *net= &thd->net;
|
NET *net= &thd->net;
|
||||||
DBUG_ENTER("send_eof");
|
DBUG_ENTER("send_eof");
|
||||||
if (net->vio != 0)
|
if (net->vio != 0 && !net->no_send_eof)
|
||||||
{
|
{
|
||||||
if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41))
|
if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41))
|
||||||
{
|
{
|
||||||
|
@ -149,15 +149,15 @@ sp_cursor::pre_open(THD *thd)
|
|||||||
m_oprot= thd->protocol; // Save the original protocol
|
m_oprot= thd->protocol; // Save the original protocol
|
||||||
thd->protocol= m_prot;
|
thd->protocol= m_prot;
|
||||||
|
|
||||||
m_ovio= thd->net.vio; // Prevent send_eof()
|
m_nseof= thd->net.no_send_eof;
|
||||||
thd->net.vio= 0;
|
thd->net.no_send_eof= TRUE;
|
||||||
return m_lex;
|
return m_lex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sp_cursor::post_open(THD *thd, my_bool isopen)
|
sp_cursor::post_open(THD *thd, my_bool isopen)
|
||||||
{
|
{
|
||||||
thd->net.vio= m_ovio; // Restore the originals
|
thd->net.no_send_eof= m_nseof; // Restore the originals
|
||||||
thd->protocol= m_oprot;
|
thd->protocol= m_oprot;
|
||||||
m_isopen= isopen;
|
m_isopen= isopen;
|
||||||
m_current_row= m_prot->data;
|
m_current_row= m_prot->data;
|
||||||
|
@ -240,7 +240,7 @@ private:
|
|||||||
LEX *m_lex;
|
LEX *m_lex;
|
||||||
Protocol_cursor *m_prot;
|
Protocol_cursor *m_prot;
|
||||||
my_bool m_isopen;
|
my_bool m_isopen;
|
||||||
Vio *m_ovio; // Original vio
|
my_bool m_nseof; // Original no_send_eof
|
||||||
Protocol *m_oprot; // Original protcol
|
Protocol *m_oprot; // Original protcol
|
||||||
MYSQL_ROWS *m_current_row;
|
MYSQL_ROWS *m_current_row;
|
||||||
|
|
||||||
|
@ -4555,12 +4555,11 @@ select_var_ident:
|
|||||||
| ident_or_text
|
| ident_or_text
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
if (!lex->spcont)
|
|
||||||
YYABORT;
|
|
||||||
sp_pvar_t *t;
|
sp_pvar_t *t;
|
||||||
if (!(t=lex->spcont->find_pvar(&$1)))
|
|
||||||
|
if (!lex->spcont || !(t=lex->spcont->find_pvar(&$1)))
|
||||||
{
|
{
|
||||||
send_error(lex->thd, ER_SP_UNDECLARED_VAR);
|
net_printf(YYTHD, ER_SP_UNDECLARED_VAR, $1.str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
if (! lex->result)
|
if (! lex->result)
|
||||||
|
Reference in New Issue
Block a user