Commit dfcc502a authored by unknown's avatar unknown

Finished merging wl5986 started by Igor.

parent 2534521f
......@@ -2501,12 +2501,12 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath)
xpath->item= new Item_func_get_user_var(name);
else
{
sp_variable_t *spv;
sp_variable *spv;
sp_pcontext *spc;
LEX *lex;
if ((lex= current_thd->lex) &&
(spc= lex->spcont) &&
(spv= spc->find_variable(&name)))
(spv= spc->find_variable(name, false)))
{
Item_splocal *splocal= new Item_splocal(name, spv->offset, spv->type, 0);
#ifndef DBUG_OFF
......
......@@ -5060,7 +5060,7 @@ public:
select_value_catcher(Item_subselect *item_arg)
:select_subselect(item_arg)
{}
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
int setup(List<Item> *items);
bool assigned; /* TRUE <=> we've caught a value */
uint n_elements; /* How many elements we get */
......@@ -5088,7 +5088,7 @@ int select_value_catcher::setup(List<Item> *items)
}
int select_value_catcher::send_data(List<Item> &items)
bool select_value_catcher::send_data(List<Item> &items)
{
DBUG_ENTER("select_value_catcher::send_data");
DBUG_ASSERT(!assigned);
......
This diff is collapsed.
......@@ -30,8 +30,9 @@
#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_class.h" // THD, set_var.h: THD
#include "set_var.h" // Item
#include "sp.h"
#include "sp_pcontext.h" // sp_pcontext
#include <stddef.h>
#include "sp.h"
/**
@defgroup Stored_Routines Stored Routines
......@@ -39,6 +40,11 @@
@{
*/
// Values for the type enum. This reflects the order of the enum declaration
// in the CREATE TABLE command.
//#define TYPE_ENUM_FUNCTION 1 #define TYPE_ENUM_PROCEDURE 2 #define
//TYPE_ENUM_TRIGGER 3 #define TYPE_ENUM_PROXY 4
Item_result
sp_map_result_type(enum enum_field_types type);
......@@ -48,12 +54,9 @@ sp_map_item_type(enum enum_field_types type);
uint
sp_get_flags_for_command(LEX *lex);
struct sp_label;
class sp_instr;
class sp_instr_opt_meta;
class sp_instr_jump_if_not;
struct sp_cond_type;
struct sp_variable;
/*************************************************************************/
......@@ -602,7 +605,7 @@ public:
Get the continuation destination of this instruction.
@return the continuation destination
*/
virtual uint get_cont_dest();
virtual uint get_cont_dest() const;
/*
Execute core function of instruction after all preparations (e.g.
......@@ -874,7 +877,7 @@ public:
virtual void set_destination(uint old_dest, uint new_dest)
= 0;
virtual uint get_cont_dest();
virtual uint get_cont_dest() const;
protected:
......@@ -1025,15 +1028,21 @@ class sp_instr_hpush_jump : public sp_instr_jump
public:
sp_instr_hpush_jump(uint ip, sp_pcontext *ctx, int htype, uint fp)
: sp_instr_jump(ip, ctx), m_type(htype), m_frame(fp), m_opt_hpop(0)
sp_instr_hpush_jump(uint ip,
sp_pcontext *ctx,
sp_handler *handler)
:sp_instr_jump(ip, ctx),
m_handler(handler),
m_opt_hpop(0),
m_frame(ctx->current_var_count())
{
m_cond.empty();
DBUG_ASSERT(m_handler->condition_values.elements == 0);
}
virtual ~sp_instr_hpush_jump()
{
m_cond.empty();
m_handler->condition_values.empty();
m_handler= NULL;
}
virtual int execute(THD *thd, uint *nextp);
......@@ -1057,17 +1066,24 @@ public:
m_opt_hpop= dest;
}
inline void add_condition(struct sp_cond_type *cond)
{
m_cond.push_front(cond);
}
void add_condition(sp_condition_value *condition_value)
{ m_handler->condition_values.push_back(condition_value); }
sp_handler *get_handler()
{ return m_handler; }
private:
private:
/// Handler.
sp_handler *m_handler;
/// hpop marking end of handler scope.
uint m_opt_hpop;
int m_type; ///< Handler type
// This attribute is needed for SHOW PROCEDURE CODE only (i.e. it's needed in
// debug version only). It's used in print().
uint m_frame;
uint m_opt_hpop; // hpop marking end of handler scope.
List<struct sp_cond_type> m_cond;
}; // class sp_instr_hpush_jump : public sp_instr_jump
......@@ -1104,8 +1120,9 @@ class sp_instr_hreturn : public sp_instr_jump
public:
sp_instr_hreturn(uint ip, sp_pcontext *ctx, uint fp)
: sp_instr_jump(ip, ctx), m_frame(fp)
sp_instr_hreturn(uint ip, sp_pcontext *ctx)
:sp_instr_jump(ip, ctx),
m_frame(ctx->current_var_count())
{}
virtual ~sp_instr_hreturn()
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -99,29 +99,65 @@ template <class Elem> class Dynamic_array
DYNAMIC_ARRAY array;
public:
Dynamic_array(uint prealloc=16, uint increment=16)
{
init(prealloc, increment);
}
void init(uint prealloc=16, uint increment=16)
{
my_init_dynamic_array(&array, sizeof(Elem), prealloc, increment,
MYF(MY_THREAD_SPECIFIC));
}
/**
@note Though formally this could be declared "const" it would be
misleading at it returns a non-const pointer to array's data.
*/
Elem& at(int idx)
{
return *(((Elem*)array.buffer) + idx);
}
/// Const variant of at(), which cannot change data
const Elem& at(int idx) const
{
return *(((Elem*)array.buffer) + idx);
}
/// @returns pointer to first element; undefined behaviour if array is empty
Elem *front()
{
DBUG_ASSERT(array.elements >= 1);
return (Elem*)array.buffer;
}
/// @returns pointer to first element; undefined behaviour if array is empty
const Elem *front() const
{
DBUG_ASSERT(array.elements >= 1);
return (const Elem*)array.buffer;
}
/// @returns pointer to last element; undefined behaviour if array is empty.
Elem *back()
{
return ((Elem*)array.buffer) + array.elements;
DBUG_ASSERT(array.elements >= 1);
return ((Elem*)array.buffer) + (array.elements - 1);
}
/// @returns pointer to last element; undefined behaviour if array is empty.
const Elem *back() const
{
DBUG_ASSERT(array.elements >= 1);
return ((const Elem*)array.buffer) + (array.elements - 1);
}
bool append(Elem &el)
/**
@retval false ok
@retval true OOM, @c my_error() has been called.
*/
bool append(const Elem &el)
{
return (insert_dynamic(&array, (uchar*)&el));
return insert_dynamic(&array, &el);
}
/// Pops the last element. Does nothing if array is empty.
......@@ -135,91 +171,37 @@ public:
delete_dynamic_element(&array, idx);
}
int elements()
int elements() const
{
return array.elements;
}
~Dynamic_array()
{
delete_dynamic(&array);
}
typedef int (*CMP_FUNC)(const Elem *el1, const Elem *el2);
void sort(CMP_FUNC cmp_func)
{
my_qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func);
}
};
/*
Array of pointers to Elem that uses memory from MEM_ROOT
MEM_ROOT has no realloc() so this is supposed to be used for cases when
reallocations are rare.
*/
template <class Elem> class Array
{
enum {alloc_increment = 16};
Elem **buffer;
uint n_elements, max_element;
public:
Array(MEM_ROOT *mem_root, uint prealloc=16)
{
buffer= (Elem**)alloc_root(mem_root, prealloc * sizeof(Elem**));
max_element = buffer? prealloc : 0;
n_elements= 0;
}
Elem& at(int idx)
{
return *(((Elem*)buffer) + idx);
}
Elem **front()
{
return buffer;
}
Elem **back()
void elements(uint num_elements)
{
return buffer + n_elements;
DBUG_ASSERT(num_elements <= array.max_element);
array.elements= num_elements;
}
bool append(MEM_ROOT *mem_root, Elem *el)
void clear()
{
if (n_elements == max_element)
{
Elem **newbuf;
if (!(newbuf= (Elem**)alloc_root(mem_root, (n_elements + alloc_increment)*
sizeof(Elem**))))
{
return FALSE;
}
memcpy(newbuf, buffer, n_elements*sizeof(Elem*));
buffer= newbuf;
}
buffer[n_elements++]= el;
return FALSE;
elements(0);
}
int elements()
void set(uint idx, const Elem &el)
{
return n_elements;
set_dynamic(&array, &el, idx);
}
void clear()
~Dynamic_array()
{
n_elements= 0;
delete_dynamic(&array);
}
typedef int (*CMP_FUNC)(Elem * const *el1, Elem *const *el2);
typedef int (*CMP_FUNC)(const Elem *el1, const Elem *el2);
void sort(CMP_FUNC cmp_func)
{
my_qsort(buffer, n_elements, sizeof(Elem*), (qsort_cmp)cmp_func);
my_qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func);
}
};
......
......@@ -72,6 +72,8 @@
char internal_table_name[2]= "*";
char empty_c_string[1]= {0}; /* used for not defined db */
LEX_STRING EMPTY_STR= { (char *) "", 0 };
const char * const THD::DEFAULT_WHERE= "field list";
/****************************************************************************
......@@ -2454,7 +2456,7 @@ void select_send::cleanup()
/* Send data to client. Returns 0 if ok */
int select_send::send_data(List<Item> &items)
bool select_send::send_data(List<Item> &items)
{
Protocol *protocol= thd->protocol;
DBUG_ENTER("select_send::send_data");
......@@ -2744,7 +2746,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
(int) (uchar) (x) == line_sep_char || \
!(x))
int select_export::send_data(List<Item> &items)
bool select_export::send_data(List<Item> &items)
{
DBUG_ENTER("select_export::send_data");
......@@ -3003,7 +3005,7 @@ select_dump::prepare(List<Item> &list __attribute__((unused)),
}
int select_dump::send_data(List<Item> &items)
bool select_dump::send_data(List<Item> &items)
{
List_iterator_fast<Item> li(items);
char buff[MAX_FIELD_WIDTH];
......@@ -3051,7 +3053,7 @@ select_subselect::select_subselect(Item_subselect *item_arg)
}
int select_singlerow_subselect::send_data(List<Item> &items)
bool select_singlerow_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_singlerow_subselect::send_data");
Item_singlerow_subselect *it= (Item_singlerow_subselect *)item;
......@@ -3085,7 +3087,7 @@ void select_max_min_finder_subselect::cleanup()
}
int select_max_min_finder_subselect::send_data(List<Item> &items)
bool select_max_min_finder_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_max_min_finder_subselect::send_data");
Item_maxmin_subselect *it= (Item_maxmin_subselect *)item;
......@@ -3202,7 +3204,7 @@ bool select_max_min_finder_subselect::cmp_str()
return (sortcmp(val1, val2, cache->collation.collation) < 0);
}
int select_exists_subselect::send_data(List<Item> &items)
bool select_exists_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_exists_subselect::send_data");
Item_exists_subselect *it= (Item_exists_subselect *)item;
......@@ -3585,7 +3587,7 @@ Statement_map::~Statement_map()
my_hash_free(&st_hash);
}
int select_dumpvar::send_data(List<Item> &items)
bool select_dumpvar::send_data(List<Item> &items)
{
List_iterator_fast<my_var> var_li(var_list);
List_iterator<Item> it(items);
......@@ -3691,7 +3693,7 @@ void select_materialize_with_stats::cleanup()
@return FALSE on success
*/
int select_materialize_with_stats::send_data(List<Item> &items)
bool select_materialize_with_stats::send_data(List<Item> &items)
{
List_iterator_fast<Item> item_it(items);
Item *cur_item;
......
......@@ -121,6 +121,7 @@ enum enum_filetype { FILETYPE_CSV, FILETYPE_XML };
extern char internal_table_name[2];
extern char empty_c_string[1];
extern LEX_STRING EMPTY_STR;
extern MYSQL_PLUGIN_IMPORT const char **errmesg;
extern bool volatile shutdown_in_progress;
......@@ -3465,7 +3466,7 @@ public:
send_data returns 0 on ok, 1 on error and -1 if data was ignored, for
example for a duplicate row entry written to a temp table.
*/
virtual int send_data(List<Item> &items)=0;
virtual bool send_data(List<Item> &items)=0;
virtual ~select_result_sink() {};
};
......@@ -3557,7 +3558,7 @@ public:
TABLE *dst_table; /* table to write into */
/* The following is called in the child thread: */
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
};
......@@ -3592,7 +3593,7 @@ class select_send :public select_result {
public:
select_send() :is_result_set_started(FALSE) {}
bool send_result_set_metadata(List<Item> &list, uint flags);
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
bool send_eof();
virtual bool check_simple_select() const { return FALSE; }
void abort_result_set();
......@@ -3655,7 +3656,7 @@ public:
select_export(sql_exchange *ex) :select_to_file(ex) {}
~select_export();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
};
......@@ -3663,7 +3664,7 @@ class select_dump :public select_to_file {
public:
select_dump(sql_exchange *ex) :select_to_file(ex) {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
};
......@@ -3682,7 +3683,7 @@ class select_insert :public select_result_interceptor {
~select_insert();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
virtual int prepare2(void);
virtual int send_data(List<Item> &items);
virtual bool send_data(List<Item> &items);
virtual void store_values(List<Item> &values);
virtual bool can_rollback_data() { return 0; }
void send_error(uint errcode,const char *err);
......@@ -3865,7 +3866,7 @@ public:
select_union() :write_err(0), table(0), records(0) { tmp_table_param.init(); }
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
bool send_eof();
bool flush();
void cleanup();
......@@ -3884,7 +3885,7 @@ protected:
Item_subselect *item;
public:
select_subselect(Item_subselect *item);
int send_data(List<Item> &items)=0;
bool send_data(List<Item> &items)=0;
bool send_eof() { return 0; };
};
......@@ -3895,7 +3896,7 @@ public:
select_singlerow_subselect(Item_subselect *item_arg)
:select_subselect(item_arg)
{}
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
};
......@@ -3945,7 +3946,7 @@ public:
bool bit_fields_as_long,
bool create_table);
bool init_result_table(ulonglong select_options);
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
void cleanup();
ha_rows get_null_count_of_col(uint idx)
{
......@@ -3979,7 +3980,7 @@ public:
:select_subselect(item_arg), cache(0), fmax(mx), is_all(all)
{}
void cleanup();
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
bool cmp_real();
bool cmp_int();
bool cmp_decimal();
......@@ -3992,7 +3993,7 @@ class select_exists_subselect :public select_subselect
public:
select_exists_subselect(Item_subselect *item_arg)
:select_subselect(item_arg){}
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
};
......@@ -4244,7 +4245,7 @@ public:
multi_delete(TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
void send_error(uint errcode,const char *err);
int do_deletes();
......@@ -4292,7 +4293,7 @@ public:
enum_duplicates handle_duplicates, bool ignore);
~multi_update();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
void send_error(uint errcode,const char *err);
int do_updates();
......@@ -4335,7 +4336,7 @@ public:
select_dumpvar() { var_list.empty(); row_count= 0;}
~select_dumpvar() {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
bool send_data(List<Item> &items);
bool send_eof();
virtual bool check_simple_select() const;
void cleanup();
......
......@@ -759,7 +759,7 @@ multi_delete::~multi_delete()
}
int multi_delete::send_data(List<Item> &values)
bool multi_delete::send_data(List<Item> &values)
{
int secure_counter= delete_while_scanning ? -1 : 0;
TABLE_LIST *del_table;
......
......@@ -1001,3 +1001,32 @@ uint32 convert_error_message(char *to, uint32 to_length, CHARSET_INFO *to_cs,
*errors= error_count;
return (uint32) (to - to_start);
}
/**
Sanity check for SQLSTATEs. The function does not check if it's really an
existing SQL-state (there are just too many), it just checks string length and
looks for bad characters.
@param sqlstate the condition SQLSTATE.
@retval true if it's ok.
@retval false if it's bad.
*/
bool is_sqlstate_valid(const LEX_STRING *sqlstate)
{
if (sqlstate->length != 5)
return false;
for (int i= 0 ; i < 5 ; ++i)
{
char c = sqlstate->str[i];
if ((c < '0' || '9' < c) &&
(c < 'A' || 'Z' < c))
return false;
}
return true;
}
......@@ -3537,7 +3537,7 @@ select_insert::~select_insert()
}
int select_insert::send_data(List<Item> &values)
bool select_insert::send_data(List<Item> &values)
{
DBUG_ENTER("select_insert::send_data");
bool error=0;
......
......@@ -126,7 +126,7 @@ class Select_fetch_protocol_binary: public select_send
public:
Select_fetch_protocol_binary(THD *thd);
virtual bool send_result_set_metadata(List<Item> &list, uint flags);
virtual int send_data(List<Item> &items);
virtual bool send_data(List<Item> &items);
virtual bool send_eof();
#ifdef EMBEDDED_LIBRARY
void begin_dataset()
......@@ -3057,7 +3057,7 @@ bool Select_fetch_protocol_binary::send_eof()
}
int
bool
Select_fetch_protocol_binary::send_data(List<Item> &fields)
{
Protocol *save_protocol= thd->protocol;
......
......@@ -2367,7 +2367,7 @@ void Show_explain_request::call_in_target_thread()
}
int select_result_explain_buffer::send_data(List<Item> &items)
bool select_result_explain_buffer::send_data(List<Item> &items)
{
int res;
THD *cur_thd= current_thd;
......@@ -5713,16 +5713,16 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
for (uint i= 0 ; i < params ; i++)
{
const char *tmp_buff;
sp_variable_t *spvar= spcont->find_variable(i);
sp_variable *spvar= spcont->find_variable(i);
field_def= &spvar->field_def;
switch (spvar->mode) {
case sp_param_in:
case sp_variable::MODE_IN:
tmp_buff= "IN";
break;
case sp_param_out:
case sp_variable::MODE_OUT:
tmp_buff= "OUT";
break;
case sp_param_inout:
case sp_variable::MODE_INOUT:
tmp_buff= "INOUT";
break;
default:
......
......@@ -115,8 +115,8 @@ void Sql_cmd_common_signal::eval_defaults(THD *thd, Sql_condition *cond)
/*
SIGNAL is restricted in sql_yacc.yy to only signal SQLSTATE conditions.
*/
DBUG_ASSERT(m_cond->type == sp_cond_type::state);
sqlstate= m_cond->sqlstate;
DBUG_ASSERT(m_cond->type == sp_condition_value::SQLSTATE);
sqlstate= m_cond->sql_state;
cond->set_sqlstate(sqlstate);
}
else
......@@ -488,8 +488,8 @@ bool Sql_cmd_signal::execute(THD *thd)
bool Sql_cmd_resignal::execute(THD *thd)
{
Sql_condition_info *signaled;
Diagnostics_area *da= thd->get_stmt_da();
const sp_rcontext::Sql_condition_info *signaled;
int result= TRUE;
DBUG_ENTER("Resignal_statement::execute");
......@@ -505,16 +505,31 @@ bool Sql_cmd_resignal::execute(THD *thd)
}
Sql_condition signaled_err(thd->mem_root);
signaled_err.set(signaled->m_sql_errno,
signaled->m_sql_state,
signaled->m_level,
signaled->m_message);
signaled_err.set(signaled->sql_errno,
signaled->sql_state,
signaled->level,
signaled->message);
if (m_cond == NULL)
{
/* RESIGNAL without signal_value */
result= raise_condition(thd, &signaled_err);
DBUG_RETURN(result);
query_cache_abort(&thd->query_cache_tls);
/* Keep handled conditions. */
da->unmark_sql_conditions_from_removal();
/* Check if the old condition still exists. */
if (da->has_sql_condition(signaled->message, strlen(signaled->message)))
{
/* Make room for the new RESIGNAL condition. */
da->reserve_space(thd, 1);
}
else
{
/* Make room for old condition + the new RESIGNAL condition. */
da->reserve_space(thd, 2);
da->push_warning(thd, &signaled_err);
}
}
/* RESIGNAL with signal_value */
......
......@@ -29,7 +29,7 @@ protected:
@param cond the condition signaled if any, or NULL.
@param set collection of signal condition item assignments.
*/
Sql_cmd_common_signal(const sp_cond_type *cond,
Sql_cmd_common_signal(const sp_condition_value *cond,
const Set_signal_information& set)
: Sql_cmd(),
m_cond(cond),
......@@ -80,7 +80,7 @@ protected:
The condition to signal or resignal.
This member is optional and can be NULL (RESIGNAL).
*/
const sp_cond_type *m_cond;
const sp_condition_value *m_cond;
/**
Collection of 'SET item = value' assignments in the
......@@ -100,7 +100,7 @@ public:
@param cond the SQL condition to signal (required).
@param set the collection of signal informations to signal.
*/
Sql_cmd_signal(const sp_cond_type *cond,
Sql_cmd_signal(const sp_condition_value *cond,
const Set_signal_information& set)
: Sql_cmd_common_signal(cond, set)
{}
......@@ -127,7 +127,7 @@ public:
@param cond the SQL condition to resignal (optional, may be NULL).
@param set the collection of signal informations to resignal.
*/
Sql_cmd_resignal(const sp_cond_type *cond,
Sql_cmd_resignal(const sp_condition_value *cond,
const Set_signal_information& set)
: Sql_cmd_common_signal(cond, set)
{}
......
......@@ -52,7 +52,7 @@ int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
}
int select_union::send_data(List<Item> &values)
bool select_union::send_data(List<Item> &values)
{
if (unit->offset_limit_cnt)
{ // using limit offset,count
......
......@@ -1829,7 +1829,7 @@ multi_update::~multi_update()
}
int multi_update::send_data(List<Item> &not_used_values)
bool multi_update::send_data(List<Item> &not_used_values)
{
TABLE_LIST *cur_table;
DBUG_ENTER("multi_update::send_data");
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment