mirror of
https://github.com/MariaDB/server.git
synced 2026-05-06 15:15:34 +02:00
WL#962: Added simple, read-only, non-scrolling, asensitive cursors in SPs, using the
(updated) Protocol_cursor class. Also did some bug fixes. Docs/sp-imp-spec.txt: Added CURSOR docs (and fixed typos) Docs/sp-implemented.txt: Updated for CURSORs include/mysqld_error.h: New error codes/messages for CURSORs libmysqld/Makefile.am: SP cursors now needs this. mysql-test/r/sp-error.result: New tests for cursors. mysql-test/r/sp.result: New tests for cursors. mysql-test/t/sp-error.test: New tests for cursors. mysql-test/t/sp.test: New tests for cursors. sql/protocol.cc: We now always have Protocol_cursor (SPs use it) sql/protocol.h: Fixed bugs in Protocol_cursor (for SPs) sql/protocol_cursor.cc: Fixed bugs in Protocol_cursor (for SPs) sql/share/czech/errmsg.txt: New error codes/messages for CURSORs sql/share/danish/errmsg.txt: New error codes/messages for CURSORs sql/share/dutch/errmsg.txt: New error codes/messages for CURSORs sql/share/english/errmsg.txt: New error codes/messages for CURSORs sql/share/estonian/errmsg.txt: New error codes/messages for CURSORs sql/share/french/errmsg.txt: New error codes/messages for CURSORs sql/share/german/errmsg.txt: New error codes/messages for CURSORs sql/share/greek/errmsg.txt: New error codes/messages for CURSORs sql/share/hungarian/errmsg.txt: New error codes/messages for CURSORs sql/share/italian/errmsg.txt: New error codes/messages for CURSORs sql/share/japanese/errmsg.txt: New error codes/messages for CURSORs sql/share/korean/errmsg.txt: New error codes/messages for CURSORs sql/share/norwegian-ny/errmsg.txt: New error codes/messages for CURSORs sql/share/norwegian/errmsg.txt: New error codes/messages for CURSORs sql/share/polish/errmsg.txt: New error codes/messages for CURSORs sql/share/portuguese/errmsg.txt: New error codes/messages for CURSORs sql/share/romanian/errmsg.txt: New error codes/messages for CURSORs sql/share/russian/errmsg.txt: New error codes/messages for CURSORs sql/share/serbian/errmsg.txt: New error codes/messages for CURSORs sql/share/slovak/errmsg.txt: New error codes/messages for CURSORs sql/share/spanish/errmsg.txt: New error codes/messages for CURSORs sql/share/swedish/errmsg.txt: New error codes/messages for CURSORs sql/share/ukrainian/errmsg.txt: New error codes/messages for CURSORs sql/sp_head.cc: Added cursor support. Also fixed problems with item_lists, where pointers and ref_pointer_arrays. sql/sp_head.h: Added cursor support sql/sp_pcontext.cc: Added cursor support sql/sp_pcontext.h: Added cursor support sql/sp_rcontext.cc: Added cursor support, in particular the new sp_cursor class. sql/sp_rcontext.h: Added cursor support, in particular the new sp_cursor class. sql/sql_lex.h: We sometimes need to copy item_lists in LEX when executing substatements in SPs sql/sql_yacc.yy: Added minimal cursor support (not the full syntax yet).
This commit is contained in:
parent
4379cbcf30
commit
04c6b9b8d8
42 changed files with 1290 additions and 71 deletions
|
|
@ -23,16 +23,20 @@
|
|||
#endif
|
||||
|
||||
#include "mysql_priv.h"
|
||||
#include "mysql.h"
|
||||
#include "sp_head.h"
|
||||
#include "sp_rcontext.h"
|
||||
#include "sp_pcontext.h"
|
||||
|
||||
sp_rcontext::sp_rcontext(uint fsize, uint hmax)
|
||||
: m_count(0), m_fsize(fsize), m_result(NULL), m_hcount(0), m_hsp(0)
|
||||
sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax)
|
||||
: m_count(0), m_fsize(fsize), m_result(NULL), m_hcount(0), m_hsp(0),
|
||||
m_hfound(-1), m_ccount(0)
|
||||
{
|
||||
m_frame= (Item **)sql_alloc(fsize * sizeof(Item*));
|
||||
m_outs= (int *)sql_alloc(fsize * sizeof(int));
|
||||
m_handler= (sp_handler_t *)sql_alloc(hmax * sizeof(sp_handler_t));
|
||||
m_hstack= (uint *)sql_alloc(hmax * sizeof(uint));
|
||||
m_cstack= (sp_cursor **)sql_alloc(cmax * sizeof(sp_cursor *));
|
||||
m_saved.empty();
|
||||
}
|
||||
|
||||
|
|
@ -93,3 +97,141 @@ sp_rcontext::restore_variables(uint fp)
|
|||
while (i-- > fp)
|
||||
m_frame[i]= m_saved.pop();
|
||||
}
|
||||
|
||||
void
|
||||
sp_rcontext::push_cursor(LEX *lex)
|
||||
{
|
||||
m_cstack[m_ccount++]= new sp_cursor(lex);
|
||||
}
|
||||
|
||||
void
|
||||
sp_rcontext::pop_cursors(uint count)
|
||||
{
|
||||
while (count--)
|
||||
{
|
||||
delete m_cstack[--m_ccount];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* sp_cursor
|
||||
*
|
||||
*/
|
||||
|
||||
// We have split this in two to make it easy for sp_instr_copen
|
||||
// to reuse the sp_instr::exec_stmt() code.
|
||||
LEX *
|
||||
sp_cursor::pre_open(THD *thd)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (m_isopen)
|
||||
{
|
||||
send_error(thd, ER_SP_CURSOR_ALREADY_OPEN);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bzero((char *)&m_mem_root, sizeof(m_mem_root));
|
||||
init_alloc_root(&m_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
|
||||
if ((m_prot= new Protocol_cursor(thd, &m_mem_root)) == NULL)
|
||||
return NULL;
|
||||
|
||||
m_oprot= thd->protocol; // Save the original protocol
|
||||
thd->protocol= m_prot;
|
||||
|
||||
m_ovio= thd->net.vio; // Prevent send_eof()
|
||||
thd->net.vio= 0;
|
||||
return m_lex;
|
||||
}
|
||||
|
||||
void
|
||||
sp_cursor::post_open(THD *thd, my_bool isopen)
|
||||
{
|
||||
thd->net.vio= m_ovio; // Restore the originals
|
||||
thd->protocol= m_oprot;
|
||||
m_isopen= isopen;
|
||||
m_current_row= m_prot->data;
|
||||
}
|
||||
|
||||
int
|
||||
sp_cursor::close(THD *thd)
|
||||
{
|
||||
if (! m_isopen)
|
||||
{
|
||||
send_error(thd, ER_SP_CURSOR_NOT_OPEN);
|
||||
return -1;
|
||||
}
|
||||
destroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
sp_cursor::destroy()
|
||||
{
|
||||
delete m_prot;
|
||||
m_prot= NULL;
|
||||
free_root(&m_mem_root, MYF(0));
|
||||
bzero((char *)&m_mem_root, sizeof(m_mem_root));
|
||||
m_isopen= FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
|
||||
{
|
||||
List_iterator_fast<struct sp_pvar> li(*vars);
|
||||
sp_pvar_t *pv;
|
||||
MYSQL_ROW row;
|
||||
uint fldcount;
|
||||
MYSQL_FIELD *fields= m_prot->fields;
|
||||
|
||||
if (! m_isopen)
|
||||
{
|
||||
send_error(thd, ER_SP_CURSOR_NOT_OPEN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (m_current_row == NULL)
|
||||
{
|
||||
send_error(thd, ER_SP_FETCH_NO_DATA);
|
||||
return -1;
|
||||
}
|
||||
|
||||
row= m_current_row->data;
|
||||
for (fldcount= 0 ; (pv= li++) ; fldcount++)
|
||||
{
|
||||
Item *it;
|
||||
const char *s;
|
||||
|
||||
if (fldcount >= m_prot->get_field_count())
|
||||
{
|
||||
send_error(thd, ER_SP_WRONG_NO_OF_FETCH_ARGS);
|
||||
return -1;
|
||||
}
|
||||
s= row[fldcount];
|
||||
switch (sp_map_result_type(pv->type))
|
||||
{
|
||||
case INT_RESULT:
|
||||
it= new Item_int(s);
|
||||
break;
|
||||
case REAL_RESULT:
|
||||
it= new Item_real(s, strlen(s));
|
||||
break;
|
||||
default:
|
||||
{
|
||||
uint len= strlen(s);
|
||||
it= new Item_string(thd->strmake(s, len), len, thd->db_charset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
thd->spcont->set_item(pv->offset, it);
|
||||
}
|
||||
if (fldcount < m_prot->get_field_count())
|
||||
{
|
||||
send_error(thd, ER_SP_WRONG_NO_OF_FETCH_ARGS);
|
||||
return -1;
|
||||
}
|
||||
m_current_row= m_current_row->next;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue