diff options
author | unknown <pem@mysql.com> | 2003-04-23 09:22:54 +0200 |
---|---|---|
committer | unknown <pem@mysql.com> | 2003-04-23 09:22:54 +0200 |
commit | f525047d1eb2d1bad50cf453210939ceb15d7282 (patch) | |
tree | 9fbeeb35b26b022c208e85d02e688a47350e8cb5 /sql | |
parent | 4ed94fcd8ec8afc11e4208a5a3e83bd90b5fc644 (diff) | |
download | mariadb-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.cc | 2 | ||||
-rw-r--r-- | sql/sp_head.cc | 2 | ||||
-rw-r--r-- | sql/sp_head.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 33 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 87 |
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 { |