summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <pem@mysql.com>2003-04-23 09:22:54 +0200
committerunknown <pem@mysql.com>2003-04-23 09:22:54 +0200
commitf525047d1eb2d1bad50cf453210939ceb15d7282 (patch)
tree9fbeeb35b26b022c208e85d02e688a47350e8cb5 /sql
parent4ed94fcd8ec8afc11e4208a5a3e83bd90b5fc644 (diff)
downloadmariadb-git-f525047d1eb2d1bad50cf453210939ceb15d7282.tar.gz
Made multiple queries (SELECT without INTO) work in SPs.
This included bug fixes in the 4.1 protocol (actually send and receive the server_status flags). libmysql/libmysql.c: Pick up the server_status (with the 4.1 protocol) as well. mysql-test/r/sp-error.result: Test for "bad selects" in non-CLIENT_MULTI_QUERIES clients (as mysqltest for the momen; this test will have to go away eventually). mysql-test/t/sp-error.test: Test for "bad selects" in non-CLIENT_MULTI_QUERIES clients (as mysqltest for the momen; this test will have to go away eventually). sql/protocol.cc: Actually send the server_status flags in send_eof() (4.1 protocol), not just zero. sql/sp_head.cc: Made multiple queries (SELECT without INTO) work in SPs. sql/sp_head.h: Made multiple queries (SELECT without INTO) work in SPs. sql/sql_parse.cc: Made multiple queries (SELECT without INTO) work in SPs. sql/sql_yacc.yy: Made multiple queries (SELECT without INTO) work in SPs.
Diffstat (limited to 'sql')
-rw-r--r--sql/protocol.cc2
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sp_head.h2
-rw-r--r--sql/sql_parse.cc33
-rw-r--r--sql/sql_yacc.yy87
5 files changed, 87 insertions, 39 deletions
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 99b815a7840..eede2496e0c 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -360,7 +360,7 @@ send_eof(THD *thd, bool no_flush)
uint tmp= min(thd->total_warn_count, 65535);
buff[0]=254;
int2store(buff+1, tmp);
- int2store(buff+3, 0); // No flags yet
+ int2store(buff+3, thd->server_status);
VOID(my_net_write(net,(char*) buff,5));
VOID(net_flush(net));
}
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index a10fc5792dc..82019186a01 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -92,7 +92,7 @@ eval_func_item(THD *thd, Item *it, enum enum_field_types type)
}
sp_head::sp_head(LEX_STRING *name, LEX *lex)
- : Sql_alloc(), m_simple_case(FALSE)
+ : Sql_alloc(), m_simple_case(FALSE), m_multi_query(FALSE)
{
DBUG_ENTER("sp_head::sp_head");
const char *dstr = (const char*)lex->buf;
diff --git a/sql/sp_head.h b/sql/sp_head.h
index afc7822cca3..b79dfdab8e9 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -46,6 +46,8 @@ public:
int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
enum enum_field_types m_returns; // For FUNCTIONs only
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
+ my_bool m_multi_query; // TRUE if a procedure with SELECT(s)
+ uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
#if 0
// We're not using this at the moment.
List<char *> m_calls; // Called procedures.
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f3154277d94..b0a183f0711 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3043,8 +3043,8 @@ mysql_execute_command(THD *thd)
net_printf(thd, ER_SP_STORE_FAILED, SP_TYPE_STRING(lex), name);
goto error;
}
+ break;
}
- break;
case SQLCOM_CALL:
{
sp_head *sp;
@@ -3057,17 +3057,40 @@ mysql_execute_command(THD *thd)
}
else
{
+ uint smrx;
+ LINT_INIT(smrx);
+
#ifndef EMBEDDED_LIBRARY
// When executing substatements, they're assumed to send_error when
// it happens, but not to send_ok.
my_bool nsok= thd->net.no_send_ok;
-
thd->net.no_send_ok= TRUE;
#endif
+ if (sp->m_multi_query)
+ {
+ if (! (thd->client_capabilities & CLIENT_MULTI_QUERIES))
+ {
+ send_error(thd, ER_SP_BADSELECT);
+#ifndef EMBEDDED_LIBRARY
+ thd->net.no_send_ok= nsok;
+#endif
+ sp->destroy(); // QQ Free memory. Remove this when caching!!!
+ goto error;
+ }
+ smrx= thd->server_status & SERVER_MORE_RESULTS_EXISTS;
+ thd->server_status |= SERVER_MORE_RESULTS_EXISTS;
+ }
+
res= sp->execute_procedure(thd, &lex->value_list);
+
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
#endif
+ if (sp->m_multi_query)
+ {
+ if (! smrx)
+ thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+ }
sp->destroy(); // QQ Free memory. Remove this when caching!!!
@@ -3076,8 +3099,8 @@ mysql_execute_command(THD *thd)
else
goto error; // Substatement should already have sent error
}
+ break;
}
- break;
case SQLCOM_ALTER_PROCEDURE:
case SQLCOM_ALTER_FUNCTION:
{
@@ -3099,8 +3122,8 @@ mysql_execute_command(THD *thd)
sp->destroy(); // QQ Free memory. Remove this when caching!!!
send_ok(thd);
}
+ break;
}
- break;
case SQLCOM_DROP_PROCEDURE:
case SQLCOM_DROP_FUNCTION:
{
@@ -3149,8 +3172,8 @@ mysql_execute_command(THD *thd)
lex->udf.name.str);
goto error;
}
+ break;
}
- break;
default: /* Impossible */
send_ok(thd);
break;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 04b4ae07bfc..dba829d2183 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -940,6 +940,14 @@ create:
lex->spcont= new sp_pcontext();
lex->sphead= new sp_head(&$3, lex);
lex->sphead->m_type= TYPE_ENUM_PROCEDURE;
+ /*
+ * We have to turn of CLIENT_MULTI_QUERIES while parsing a
+ * stored procedure, otherwise yylex will chop it into pieces
+ * at each ';'.
+ */
+ lex->sphead->m_old_cmq=
+ YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
+ YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
}
'(' sp_pdparam_list ')'
{
@@ -947,7 +955,12 @@ create:
}
sp_proc_stmt
{
- Lex->sql_command= SQLCOM_CREATE_PROCEDURE;
+ LEX *lex= Lex;
+
+ lex->sql_command= SQLCOM_CREATE_PROCEDURE;
+ /* Restore flag if it was cleared above */
+ if (lex->sphead->m_old_cmq)
+ YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
}
;
@@ -976,6 +989,14 @@ create_function_tail:
lex->spcont= new sp_pcontext();
lex->sphead= new sp_head(&lex->udf.name, lex);
lex->sphead->m_type= TYPE_ENUM_FUNCTION;
+ /*
+ * We have to turn of CLIENT_MULTI_QUERIES while parsing a
+ * stored procedure, otherwise yylex will chop it into pieces
+ * at each ';'.
+ */
+ lex->sphead->m_old_cmq=
+ YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
+ YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
}
sp_fdparam_list ')'
{
@@ -987,7 +1008,12 @@ create_function_tail:
}
sp_proc_stmt
{
- Lex->sql_command = SQLCOM_CREATE_SPFUNCTION;
+ LEX *lex= Lex;
+
+ lex->sql_command = SQLCOM_CREATE_SPFUNCTION;
+ /* Restore flag if it was cleared above */
+ if (lex->sphead->m_old_cmq)
+ YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
}
;
@@ -1140,40 +1166,37 @@ sp_proc_stmt:
if (lex->sql_command == SQLCOM_SELECT && !lex->result)
{
- send_error(YYTHD, ER_SP_BADSELECT);
- YYABORT;
+ /* We maybe have one or more SELECT without INTO */
+ lex->sphead->m_multi_query= TRUE;
}
- else
+ /* Don't add an instruction for empty SET statements.
+ ** (This happens if the SET only contained local variables,
+ ** which get their set instructions generated separately.)
+ */
+ if (lex->sql_command != SQLCOM_SET_OPTION ||
+ !lex->var_list.is_empty())
{
- /* Don't add an instruction for empty SET statements.
- ** (This happens if the SET only contained local variables,
- ** which get their set instructions generated separately.)
+ /* Currently we can't handle queries inside a FUNCTION,
+ ** because of the way table locking works.
+ ** This is unfortunate, and limits the usefulness of functions
+ ** a great deal, but it's nothing we can do about this at the
+ ** moment.
*/
- if (lex->sql_command != SQLCOM_SET_OPTION ||
- !lex->var_list.is_empty())
+ if (lex->sphead->m_type == TYPE_ENUM_FUNCTION &&
+ lex->sql_command != SQLCOM_SET_OPTION)
{
- /* Currently we can't handle queries inside a FUNCTION,
- ** because of the way table locking works.
- ** This is unfortunate, and limits the usefulness of functions
- ** a great deal, but it's nothing we can do about this at the
- ** moment.
- */
- if (lex->sphead->m_type == TYPE_ENUM_FUNCTION &&
- lex->sql_command != SQLCOM_SET_OPTION)
- {
- send_error(YYTHD, ER_SP_BADQUERY);
- YYABORT;
- }
- else
- {
- sp_instr_stmt *i= new sp_instr_stmt(lex->sphead->instructions());
-
- i->set_lex(lex);
- lex->sphead->add_instr(i);
- }
- }
- lex->sphead->restore_lex(YYTHD);
- }
+ send_error(YYTHD, ER_SP_BADQUERY);
+ YYABORT;
+ }
+ else
+ {
+ sp_instr_stmt *i=new sp_instr_stmt(lex->sphead->instructions());
+
+ i->set_lex(lex);
+ lex->sphead->add_instr(i);
+ }
+ }
+ lex->sphead->restore_lex(YYTHD);
}
| RETURN_SYM expr
{