mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 11:01:52 +01:00
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0
into sanja.is.com.ua:/home/bell/mysql/bk/work-5.0
This commit is contained in:
commit
5c7955bd54
19 changed files with 492 additions and 279 deletions
|
@ -23,3 +23,23 @@ select 1;
|
||||||
show status like 'last_query_cost';
|
show status like 'last_query_cost';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Last_query_cost 0.000000
|
Last_query_cost 0.000000
|
||||||
|
FLUSH STATUS;
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
Variable_name Value
|
||||||
|
Max_used_connections 1
|
||||||
|
SET @save_thread_cache_size=@@thread_cache_size;
|
||||||
|
SET GLOBAL thread_cache_size=3;
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
Variable_name Value
|
||||||
|
Max_used_connections 3
|
||||||
|
FLUSH STATUS;
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
Variable_name Value
|
||||||
|
Max_used_connections 2
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
Variable_name Value
|
||||||
|
Max_used_connections 3
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
Variable_name Value
|
||||||
|
Max_used_connections 4
|
||||||
|
SET GLOBAL thread_cache_size=@save_thread_cache_size;
|
||||||
|
|
|
@ -952,3 +952,16 @@ load data infile '../std_data_ln/words.dat' into table t1 (a) set b:= f1();
|
||||||
drop table t1;
|
drop table t1;
|
||||||
drop function f1;
|
drop function f1;
|
||||||
drop function f2;
|
drop function f2;
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
conn_id INT,
|
||||||
|
trigger_conn_id INT
|
||||||
|
);
|
||||||
|
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
|
||||||
|
SET NEW.trigger_conn_id = CONNECTION_ID();
|
||||||
|
INSERT INTO t1 (conn_id, trigger_conn_id) VALUES (CONNECTION_ID(), -1);
|
||||||
|
INSERT INTO t1 (conn_id, trigger_conn_id) VALUES (CONNECTION_ID(), -1);
|
||||||
|
SELECT * FROM t1 WHERE conn_id != trigger_conn_id;
|
||||||
|
conn_id trigger_conn_id
|
||||||
|
DROP TRIGGER t1_bi;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
|
@ -36,11 +36,111 @@ reap;
|
||||||
show status like 'Table_lock%';
|
show status like 'Table_lock%';
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
disconnect con2;
|
||||||
|
disconnect con1;
|
||||||
|
connection default;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
|
||||||
#
|
#
|
||||||
# lost_query_cost
|
# last_query_cost
|
||||||
#
|
#
|
||||||
|
|
||||||
select 1;
|
select 1;
|
||||||
show status like 'last_query_cost';
|
show status like 'last_query_cost';
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test for Bug #15933 max_used_connections is wrong after FLUSH STATUS
|
||||||
|
# if connections are cached
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The first suggested fix from the bug report was chosen
|
||||||
|
# (see http://bugs.mysql.com/bug.php?id=15933):
|
||||||
|
#
|
||||||
|
# a) On flushing the status, set max_used_connections to
|
||||||
|
# threads_connected, not to 0.
|
||||||
|
#
|
||||||
|
# b) Check if it is necessary to increment max_used_connections when
|
||||||
|
# taking a thread from the cache as well as when creating new threads
|
||||||
|
#
|
||||||
|
|
||||||
|
# Wait for at most $disconnect_timeout seconds for disconnects to finish.
|
||||||
|
let $disconnect_timeout = 10;
|
||||||
|
|
||||||
|
# Wait for any previous disconnects to finish.
|
||||||
|
FLUSH STATUS;
|
||||||
|
--disable_query_log
|
||||||
|
--disable_result_log
|
||||||
|
eval SET @wait_left = $disconnect_timeout;
|
||||||
|
let $max_used_connections = `SHOW STATUS LIKE 'max_used_connections'`;
|
||||||
|
eval SET @max_used_connections = SUBSTRING('$max_used_connections', 21)+0;
|
||||||
|
let $wait_more = `SELECT @max_used_connections != 1 && @wait_left > 0`;
|
||||||
|
while ($wait_more)
|
||||||
|
{
|
||||||
|
sleep 1;
|
||||||
|
FLUSH STATUS;
|
||||||
|
SET @wait_left = @wait_left - 1;
|
||||||
|
let $max_used_connections = `SHOW STATUS LIKE 'max_used_connections'`;
|
||||||
|
eval SET @max_used_connections = SUBSTRING('$max_used_connections', 21)+0;
|
||||||
|
let $wait_more = `SELECT @max_used_connections != 1 && @wait_left > 0`;
|
||||||
|
}
|
||||||
|
--enable_query_log
|
||||||
|
--enable_result_log
|
||||||
|
|
||||||
|
# Prerequisite.
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
|
||||||
|
# Save original setting.
|
||||||
|
SET @save_thread_cache_size=@@thread_cache_size;
|
||||||
|
SET GLOBAL thread_cache_size=3;
|
||||||
|
|
||||||
|
connect (con1,localhost,root,,);
|
||||||
|
connect (con2,localhost,root,,);
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
disconnect con2;
|
||||||
|
|
||||||
|
# Check that max_used_connections still reflects maximum value.
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
|
||||||
|
# Check that after flush max_used_connections equals to current number
|
||||||
|
# of connections. First wait for previous disconnect to finish.
|
||||||
|
FLUSH STATUS;
|
||||||
|
--disable_query_log
|
||||||
|
--disable_result_log
|
||||||
|
eval SET @wait_left = $disconnect_timeout;
|
||||||
|
let $max_used_connections = `SHOW STATUS LIKE 'max_used_connections'`;
|
||||||
|
eval SET @max_used_connections = SUBSTRING('$max_used_connections', 21)+0;
|
||||||
|
let $wait_more = `SELECT @max_used_connections != 2 && @wait_left > 0`;
|
||||||
|
while ($wait_more)
|
||||||
|
{
|
||||||
|
sleep 1;
|
||||||
|
FLUSH STATUS;
|
||||||
|
SET @wait_left = @wait_left - 1;
|
||||||
|
let $max_used_connections = `SHOW STATUS LIKE 'max_used_connections'`;
|
||||||
|
eval SET @max_used_connections = SUBSTRING('$max_used_connections', 21)+0;
|
||||||
|
let $wait_more = `SELECT @max_used_connections != 2 && @wait_left > 0`;
|
||||||
|
}
|
||||||
|
--enable_query_log
|
||||||
|
--enable_result_log
|
||||||
|
# Check that we don't count disconnected thread any longer.
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
|
||||||
|
# Check that max_used_connections is updated when cached thread is
|
||||||
|
# reused...
|
||||||
|
connect (con2,localhost,root,,);
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
|
||||||
|
# ...and when new thread is created.
|
||||||
|
connect (con3,localhost,root,,);
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
|
||||||
|
# Restore original setting.
|
||||||
|
connection default;
|
||||||
|
SET GLOBAL thread_cache_size=@save_thread_cache_size;
|
||||||
|
|
||||||
|
disconnect con3;
|
||||||
|
disconnect con2;
|
||||||
|
disconnect con1;
|
||||||
|
|
||||||
|
# End of 5.0 tests
|
||||||
|
|
|
@ -1114,3 +1114,31 @@ load data infile '../std_data_ln/words.dat' into table t1 (a) set b:= f1();
|
||||||
drop table t1;
|
drop table t1;
|
||||||
drop function f1;
|
drop function f1;
|
||||||
drop function f2;
|
drop function f2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test for Bug #16461 connection_id() does not work properly inside trigger
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
conn_id INT,
|
||||||
|
trigger_conn_id INT
|
||||||
|
);
|
||||||
|
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
|
||||||
|
SET NEW.trigger_conn_id = CONNECTION_ID();
|
||||||
|
|
||||||
|
INSERT INTO t1 (conn_id, trigger_conn_id) VALUES (CONNECTION_ID(), -1);
|
||||||
|
|
||||||
|
connect (con1,localhost,root,,);
|
||||||
|
INSERT INTO t1 (conn_id, trigger_conn_id) VALUES (CONNECTION_ID(), -1);
|
||||||
|
connection default;
|
||||||
|
disconnect con1;
|
||||||
|
|
||||||
|
SELECT * FROM t1 WHERE conn_id != trigger_conn_id;
|
||||||
|
|
||||||
|
DROP TRIGGER t1_bi;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
# End of 5.0 tests
|
||||||
|
|
16
sql/item.cc
16
sql/item.cc
|
@ -644,22 +644,6 @@ Item *Item_num::safe_charset_converter(CHARSET_INFO *tocs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item *Item_static_int_func::safe_charset_converter(CHARSET_INFO *tocs)
|
|
||||||
{
|
|
||||||
Item_string *conv;
|
|
||||||
char buf[64];
|
|
||||||
String *s, tmp(buf, sizeof(buf), &my_charset_bin);
|
|
||||||
s= val_str(&tmp);
|
|
||||||
if ((conv= new Item_static_string_func(func_name, s->ptr(), s->length(),
|
|
||||||
s->charset())))
|
|
||||||
{
|
|
||||||
conv->str_value.copy();
|
|
||||||
conv->str_value.mark_as_const();
|
|
||||||
}
|
|
||||||
return conv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Item *Item_static_float_func::safe_charset_converter(CHARSET_INFO *tocs)
|
Item *Item_static_float_func::safe_charset_converter(CHARSET_INFO *tocs)
|
||||||
{
|
{
|
||||||
Item_string *conv;
|
Item_string *conv;
|
||||||
|
|
12
sql/item.h
12
sql/item.h
|
@ -1387,18 +1387,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_static_int_func :public Item_int
|
|
||||||
{
|
|
||||||
const char *func_name;
|
|
||||||
public:
|
|
||||||
Item_static_int_func(const char *str_arg, longlong i, uint length)
|
|
||||||
:Item_int(NullS, i, length), func_name(str_arg)
|
|
||||||
{}
|
|
||||||
Item *safe_charset_converter(CHARSET_INFO *tocs);
|
|
||||||
void print(String *str) { str->append(func_name); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Item_uint :public Item_int
|
class Item_uint :public Item_int
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -71,14 +71,8 @@ Item *create_func_ceiling(Item* a)
|
||||||
|
|
||||||
Item *create_func_connection_id(void)
|
Item *create_func_connection_id(void)
|
||||||
{
|
{
|
||||||
THD *thd=current_thd;
|
current_thd->lex->safe_to_cache_query= 0;
|
||||||
thd->lex->safe_to_cache_query= 0;
|
return new Item_func_connection_id();
|
||||||
return new Item_static_int_func("connection_id()",
|
|
||||||
(longlong)
|
|
||||||
((thd->slave_thread) ?
|
|
||||||
thd->variables.pseudo_thread_id :
|
|
||||||
thd->thread_id),
|
|
||||||
10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *create_func_conv(Item* a, Item *b, Item *c)
|
Item *create_func_conv(Item* a, Item *b, Item *c)
|
||||||
|
|
|
@ -559,6 +559,31 @@ String *Item_int_func::val_str(String *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_func_connection_id::fix_length_and_dec()
|
||||||
|
{
|
||||||
|
Item_int_func::fix_length_and_dec();
|
||||||
|
max_length= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_connection_id::fix_fields(THD *thd, Item **ref)
|
||||||
|
{
|
||||||
|
if (Item_int_func::fix_fields(thd, ref))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
To replicate CONNECTION_ID() properly we should use
|
||||||
|
pseudo_thread_id on slave, which contains the value of thread_id
|
||||||
|
on master.
|
||||||
|
*/
|
||||||
|
value= ((thd->slave_thread) ?
|
||||||
|
thd->variables.pseudo_thread_id :
|
||||||
|
thd->thread_id);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check arguments here to determine result's type for a numeric
|
Check arguments here to determine result's type for a numeric
|
||||||
function of two arguments.
|
function of two arguments.
|
||||||
|
|
|
@ -279,6 +279,18 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Item_func_connection_id :public Item_int_func
|
||||||
|
{
|
||||||
|
longlong value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const char *func_name() const { return "connection_id"; }
|
||||||
|
void fix_length_and_dec();
|
||||||
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
|
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_signed :public Item_int_func
|
class Item_func_signed :public Item_int_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1097,6 +1097,7 @@ File open_binlog(IO_CACHE *log, const char *log_file_name,
|
||||||
|
|
||||||
/* mysqld.cc */
|
/* mysqld.cc */
|
||||||
extern void MYSQLerror(const char*);
|
extern void MYSQLerror(const char*);
|
||||||
|
void refresh_status(THD *thd);
|
||||||
|
|
||||||
/* item_func.cc */
|
/* item_func.cc */
|
||||||
extern bool check_reserved_words(LEX_STRING *name);
|
extern bool check_reserved_words(LEX_STRING *name);
|
||||||
|
|
|
@ -1664,17 +1664,6 @@ void end_thread(THD *thd, bool put_in_cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Start a cached thread. LOCK_thread_count is locked on entry */
|
|
||||||
|
|
||||||
static void start_cached_thread(THD *thd)
|
|
||||||
{
|
|
||||||
thread_cache.append(thd);
|
|
||||||
wake_thread++;
|
|
||||||
thread_count++;
|
|
||||||
pthread_cond_signal(&COND_thread_cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void flush_thread_cache()
|
void flush_thread_cache()
|
||||||
{
|
{
|
||||||
(void) pthread_mutex_lock(&LOCK_thread_count);
|
(void) pthread_mutex_lock(&LOCK_thread_count);
|
||||||
|
@ -3806,6 +3795,25 @@ static bool read_init_file(char *file_name)
|
||||||
|
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|
/*
|
||||||
|
Create new thread to handle incoming connection.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
create_new_thread()
|
||||||
|
thd in/out Thread handle of future thread.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
This function will create new thread to handle the incoming
|
||||||
|
connection. If there are idle cached threads one will be used.
|
||||||
|
'thd' will be pushed into 'threads'.
|
||||||
|
|
||||||
|
In single-threaded mode (#define ONE_THREAD) connection will be
|
||||||
|
handled inside this function.
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
none
|
||||||
|
*/
|
||||||
|
|
||||||
static void create_new_thread(THD *thd)
|
static void create_new_thread(THD *thd)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("create_new_thread");
|
DBUG_ENTER("create_new_thread");
|
||||||
|
@ -3829,11 +3837,12 @@ static void create_new_thread(THD *thd)
|
||||||
thd->real_id=pthread_self(); // Keep purify happy
|
thd->real_id=pthread_self(); // Keep purify happy
|
||||||
|
|
||||||
/* Start a new thread to handle connection */
|
/* Start a new thread to handle connection */
|
||||||
|
thread_count++;
|
||||||
|
|
||||||
#ifdef ONE_THREAD
|
#ifdef ONE_THREAD
|
||||||
if (test_flags & TEST_NO_THREADS) // For debugging under Linux
|
if (test_flags & TEST_NO_THREADS) // For debugging under Linux
|
||||||
{
|
{
|
||||||
thread_cache_size=0; // Safety
|
thread_cache_size=0; // Safety
|
||||||
thread_count++;
|
|
||||||
threads.append(thd);
|
threads.append(thd);
|
||||||
thd->real_id=pthread_self();
|
thd->real_id=pthread_self();
|
||||||
(void) pthread_mutex_unlock(&LOCK_thread_count);
|
(void) pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
@ -3842,18 +3851,20 @@ static void create_new_thread(THD *thd)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
if (thread_count-delayed_insert_threads > max_used_connections)
|
||||||
|
max_used_connections=thread_count-delayed_insert_threads;
|
||||||
|
|
||||||
if (cached_thread_count > wake_thread)
|
if (cached_thread_count > wake_thread)
|
||||||
{
|
{
|
||||||
start_cached_thread(thd);
|
thread_cache.append(thd);
|
||||||
|
wake_thread++;
|
||||||
|
pthread_cond_signal(&COND_thread_cache);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
thread_count++;
|
|
||||||
thread_created++;
|
thread_created++;
|
||||||
threads.append(thd);
|
threads.append(thd);
|
||||||
if (thread_count-delayed_insert_threads > max_used_connections)
|
|
||||||
max_used_connections=thread_count-delayed_insert_threads;
|
|
||||||
DBUG_PRINT("info",(("creating thread %d"), thd->thread_id));
|
DBUG_PRINT("info",(("creating thread %d"), thd->thread_id));
|
||||||
thd->connect_time = time(NULL);
|
thd->connect_time = time(NULL);
|
||||||
if ((error=pthread_create(&thd->real_id,&connection_attrib,
|
if ((error=pthread_create(&thd->real_id,&connection_attrib,
|
||||||
|
@ -7407,6 +7418,36 @@ static void create_pid_file()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Clear most status variables */
|
||||||
|
void refresh_status(THD *thd)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&LOCK_status);
|
||||||
|
|
||||||
|
/* We must update the global status before cleaning up the thread */
|
||||||
|
add_to_status(&global_status_var, &thd->status_var);
|
||||||
|
bzero((char*) &thd->status_var, sizeof(thd->status_var));
|
||||||
|
|
||||||
|
for (struct show_var_st *ptr=status_vars; ptr->name; ptr++)
|
||||||
|
{
|
||||||
|
if (ptr->type == SHOW_LONG)
|
||||||
|
*(ulong*) ptr->value= 0;
|
||||||
|
}
|
||||||
|
/* Reset the counters of all key caches (default and named). */
|
||||||
|
process_key_caches(reset_key_cache_counters);
|
||||||
|
pthread_mutex_unlock(&LOCK_status);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set max_used_connections to the number of currently open
|
||||||
|
connections. Lock LOCK_thread_count out of LOCK_status to avoid
|
||||||
|
deadlocks. Status reset becomes not atomic, but status data is
|
||||||
|
not exact anyway.
|
||||||
|
*/
|
||||||
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
|
max_used_connections= thread_count-delayed_insert_threads;
|
||||||
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
Instantiate have_xyx for missing storage engines
|
Instantiate have_xyx for missing storage engines
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -1214,7 +1214,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
|
||||||
DBUG_ENTER("sp_head::execute_function");
|
DBUG_ENTER("sp_head::execute_function");
|
||||||
DBUG_PRINT("info", ("function %s", m_name.str));
|
DBUG_PRINT("info", ("function %s", m_name.str));
|
||||||
|
|
||||||
params = m_pcont->context_pvars();
|
params = m_pcont->context_var_count();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check that the function is called with all specified arguments.
|
Check that the function is called with all specified arguments.
|
||||||
|
@ -1391,7 +1391,7 @@ bool
|
||||||
sp_head::execute_procedure(THD *thd, List<Item> *args)
|
sp_head::execute_procedure(THD *thd, List<Item> *args)
|
||||||
{
|
{
|
||||||
bool err_status= FALSE;
|
bool err_status= FALSE;
|
||||||
uint params = m_pcont->context_pvars();
|
uint params = m_pcont->context_var_count();
|
||||||
sp_rcontext *save_spcont, *octx;
|
sp_rcontext *save_spcont, *octx;
|
||||||
sp_rcontext *nctx = NULL;
|
sp_rcontext *nctx = NULL;
|
||||||
DBUG_ENTER("sp_head::execute_procedure");
|
DBUG_ENTER("sp_head::execute_procedure");
|
||||||
|
@ -1443,15 +1443,15 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
||||||
for (uint i= 0 ; i < params ; i++)
|
for (uint i= 0 ; i < params ; i++)
|
||||||
{
|
{
|
||||||
Item *arg_item= it_args++;
|
Item *arg_item= it_args++;
|
||||||
sp_pvar_t *pvar= m_pcont->find_pvar(i);
|
sp_variable_t *spvar= m_pcont->find_variable(i);
|
||||||
|
|
||||||
if (!arg_item)
|
if (!arg_item)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!pvar)
|
if (!spvar)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pvar->mode != sp_param_in)
|
if (spvar->mode != sp_param_in)
|
||||||
{
|
{
|
||||||
if (!arg_item->is_splocal() && !item_is_user_var(arg_item))
|
if (!arg_item->is_splocal() && !item_is_user_var(arg_item))
|
||||||
{
|
{
|
||||||
|
@ -1461,7 +1461,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pvar->mode == sp_param_out)
|
if (spvar->mode == sp_param_out)
|
||||||
{
|
{
|
||||||
Item_null *null_item= new Item_null();
|
Item_null *null_item= new Item_null();
|
||||||
|
|
||||||
|
@ -1521,9 +1521,9 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
||||||
if (!arg_item)
|
if (!arg_item)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
sp_pvar_t *pvar= m_pcont->find_pvar(i);
|
sp_variable_t *spvar= m_pcont->find_variable(i);
|
||||||
|
|
||||||
if (pvar->mode == sp_param_in)
|
if (spvar->mode == sp_param_in)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (arg_item->is_splocal())
|
if (arg_item->is_splocal())
|
||||||
|
@ -2388,7 +2388,7 @@ sp_instr_set::print(String *str)
|
||||||
{
|
{
|
||||||
/* set name@offset ... */
|
/* set name@offset ... */
|
||||||
int rsrv = SP_INSTR_UINT_MAXLEN+6;
|
int rsrv = SP_INSTR_UINT_MAXLEN+6;
|
||||||
sp_pvar_t *var = m_ctx->find_pvar(m_offset);
|
sp_variable_t *var = m_ctx->find_variable(m_offset);
|
||||||
|
|
||||||
/* 'var' should always be non-null, but just in case... */
|
/* 'var' should always be non-null, but just in case... */
|
||||||
if (var)
|
if (var)
|
||||||
|
@ -3004,8 +3004,8 @@ sp_instr_cfetch::execute(THD *thd, uint *nextp)
|
||||||
void
|
void
|
||||||
sp_instr_cfetch::print(String *str)
|
sp_instr_cfetch::print(String *str)
|
||||||
{
|
{
|
||||||
List_iterator_fast<struct sp_pvar> li(m_varlist);
|
List_iterator_fast<struct sp_variable> li(m_varlist);
|
||||||
sp_pvar_t *pv;
|
sp_variable_t *pv;
|
||||||
LEX_STRING n;
|
LEX_STRING n;
|
||||||
my_bool found= m_ctx->find_cursor(m_cursor, &n);
|
my_bool found= m_ctx->find_cursor(m_cursor, &n);
|
||||||
/* cfetch name@offset vars... */
|
/* cfetch name@offset vars... */
|
||||||
|
|
|
@ -44,7 +44,7 @@ class sp_instr;
|
||||||
class sp_instr_opt_meta;
|
class sp_instr_opt_meta;
|
||||||
class sp_instr_jump_if_not;
|
class sp_instr_jump_if_not;
|
||||||
struct sp_cond_type;
|
struct sp_cond_type;
|
||||||
struct sp_pvar;
|
struct sp_variable;
|
||||||
|
|
||||||
class sp_name : public Sql_alloc
|
class sp_name : public Sql_alloc
|
||||||
{
|
{
|
||||||
|
@ -1074,7 +1074,7 @@ public:
|
||||||
|
|
||||||
virtual void print(String *str);
|
virtual void print(String *str);
|
||||||
|
|
||||||
void add_to_varlist(struct sp_pvar *var)
|
void add_to_varlist(struct sp_variable *var)
|
||||||
{
|
{
|
||||||
m_varlist.push_back(var);
|
m_varlist.push_back(var);
|
||||||
}
|
}
|
||||||
|
@ -1082,7 +1082,7 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint m_cursor;
|
uint m_cursor;
|
||||||
List<struct sp_pvar> m_varlist;
|
List<struct sp_variable> m_varlist;
|
||||||
|
|
||||||
}; // class sp_instr_cfetch : public sp_instr
|
}; // class sp_instr_cfetch : public sp_instr
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,10 @@
|
||||||
#include "sp_head.h"
|
#include "sp_head.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity check for SQLSTATEs. Will not check if it's really an existing
|
Sanity check for SQLSTATEs. Will not check if it's really an existing
|
||||||
* state (there are just too many), but will check length and bad characters.
|
state (there are just too many), but will check length and bad characters.
|
||||||
* Returns TRUE if it's ok, FALSE if it's bad.
|
Returns TRUE if it's ok, FALSE if it's bad.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
sp_cond_check(LEX_STRING *sqlstate)
|
sp_cond_check(LEX_STRING *sqlstate)
|
||||||
{
|
{
|
||||||
|
@ -51,25 +51,25 @@ sp_cond_check(LEX_STRING *sqlstate)
|
||||||
}
|
}
|
||||||
|
|
||||||
sp_pcontext::sp_pcontext(sp_pcontext *prev)
|
sp_pcontext::sp_pcontext(sp_pcontext *prev)
|
||||||
:Sql_alloc(), m_total_pvars(0), m_csubsize(0), m_hsubsize(0),
|
:Sql_alloc(), m_max_var_index(0), m_max_cursor_index(0), m_max_handler_index(0),
|
||||||
m_handlers(0), m_parent(prev), m_pboundary(0)
|
m_context_handlers(0), m_parent(prev), m_pboundary(0)
|
||||||
{
|
{
|
||||||
VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
|
VOID(my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *), 16, 8));
|
||||||
VOID(my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), 16, 8));
|
VOID(my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), 16, 8));
|
||||||
VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8));
|
VOID(my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *), 16, 8));
|
||||||
VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8));
|
VOID(my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING), 16, 8));
|
||||||
VOID(my_init_dynamic_array(&m_handler, sizeof(sp_cond_type_t *), 16, 8));
|
VOID(my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *), 16, 8));
|
||||||
m_label.empty();
|
m_label.empty();
|
||||||
m_children.empty();
|
m_children.empty();
|
||||||
if (!prev)
|
if (!prev)
|
||||||
{
|
{
|
||||||
m_poffset= m_coffset= 0;
|
m_var_offset= m_cursor_offset= 0;
|
||||||
m_num_case_exprs= 0;
|
m_num_case_exprs= 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_poffset= prev->m_poffset + prev->m_total_pvars;
|
m_var_offset= prev->m_var_offset + prev->m_max_var_index;
|
||||||
m_coffset= prev->current_cursors();
|
m_cursor_offset= prev->current_cursor_count();
|
||||||
m_num_case_exprs= prev->get_num_case_exprs();
|
m_num_case_exprs= prev->get_num_case_exprs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,11 +85,11 @@ sp_pcontext::destroy()
|
||||||
|
|
||||||
m_children.empty();
|
m_children.empty();
|
||||||
m_label.empty();
|
m_label.empty();
|
||||||
delete_dynamic(&m_pvar);
|
delete_dynamic(&m_vars);
|
||||||
delete_dynamic(&m_case_expr_id_lst);
|
delete_dynamic(&m_case_expr_id_lst);
|
||||||
delete_dynamic(&m_cond);
|
delete_dynamic(&m_conds);
|
||||||
delete_dynamic(&m_cursor);
|
delete_dynamic(&m_cursors);
|
||||||
delete_dynamic(&m_handler);
|
delete_dynamic(&m_handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
sp_pcontext *
|
sp_pcontext *
|
||||||
|
@ -105,15 +105,15 @@ sp_pcontext::push_context()
|
||||||
sp_pcontext *
|
sp_pcontext *
|
||||||
sp_pcontext::pop_context()
|
sp_pcontext::pop_context()
|
||||||
{
|
{
|
||||||
m_parent->m_total_pvars= m_parent->m_total_pvars + m_total_pvars;
|
m_parent->m_max_var_index+= m_max_var_index;
|
||||||
|
|
||||||
uint submax= max_handlers();
|
uint submax= max_handler_index();
|
||||||
if (submax > m_parent->m_hsubsize)
|
if (submax > m_parent->m_max_handler_index)
|
||||||
m_parent->m_hsubsize= submax;
|
m_parent->m_max_handler_index= submax;
|
||||||
|
|
||||||
submax= max_cursors();
|
submax= max_cursor_index();
|
||||||
if (submax > m_parent->m_csubsize)
|
if (submax > m_parent->m_max_cursor_index)
|
||||||
m_parent->m_csubsize= submax;
|
m_parent->m_max_cursor_index= submax;
|
||||||
|
|
||||||
if (m_num_case_exprs > m_parent->m_num_case_exprs)
|
if (m_num_case_exprs > m_parent->m_num_case_exprs)
|
||||||
m_parent->m_num_case_exprs= m_num_case_exprs;
|
m_parent->m_num_case_exprs= m_num_case_exprs;
|
||||||
|
@ -130,12 +130,12 @@ sp_pcontext::diff_handlers(sp_pcontext *ctx, bool exclusive)
|
||||||
|
|
||||||
while (pctx && pctx != ctx)
|
while (pctx && pctx != ctx)
|
||||||
{
|
{
|
||||||
n+= pctx->m_handlers;
|
n+= pctx->m_context_handlers;
|
||||||
last_ctx= pctx;
|
last_ctx= pctx;
|
||||||
pctx= pctx->parent_context();
|
pctx= pctx->parent_context();
|
||||||
}
|
}
|
||||||
if (pctx)
|
if (pctx)
|
||||||
return (exclusive && last_ctx ? n - last_ctx->m_handlers : n);
|
return (exclusive && last_ctx ? n - last_ctx->m_context_handlers : n);
|
||||||
return 0; // Didn't find ctx
|
return 0; // Didn't find ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,32 +148,33 @@ sp_pcontext::diff_cursors(sp_pcontext *ctx, bool exclusive)
|
||||||
|
|
||||||
while (pctx && pctx != ctx)
|
while (pctx && pctx != ctx)
|
||||||
{
|
{
|
||||||
n+= pctx->m_cursor.elements;
|
n+= pctx->m_cursors.elements;
|
||||||
last_ctx= pctx;
|
last_ctx= pctx;
|
||||||
pctx= pctx->parent_context();
|
pctx= pctx->parent_context();
|
||||||
}
|
}
|
||||||
if (pctx)
|
if (pctx)
|
||||||
return (exclusive && last_ctx ? n - last_ctx->m_cursor.elements : n);
|
return (exclusive && last_ctx ? n - last_ctx->m_cursors.elements : n);
|
||||||
return 0; // Didn't find ctx
|
return 0; // Didn't find ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This does a linear search (from newer to older variables, in case
|
/*
|
||||||
** we have shadowed names).
|
This does a linear search (from newer to older variables, in case
|
||||||
** It's possible to have a more efficient allocation and search method,
|
we have shadowed names).
|
||||||
** but it might not be worth it. The typical number of parameters and
|
It's possible to have a more efficient allocation and search method,
|
||||||
** variables will in most cases be low (a handfull).
|
but it might not be worth it. The typical number of parameters and
|
||||||
** ...and, this is only called during parsing.
|
variables will in most cases be low (a handfull).
|
||||||
|
...and, this is only called during parsing.
|
||||||
*/
|
*/
|
||||||
sp_pvar_t *
|
sp_variable_t *
|
||||||
sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
|
sp_pcontext::find_variable(LEX_STRING *name, my_bool scoped)
|
||||||
{
|
{
|
||||||
uint i= m_pvar.elements - m_pboundary;
|
uint i= m_vars.elements - m_pboundary;
|
||||||
|
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
sp_pvar_t *p;
|
sp_variable_t *p;
|
||||||
|
|
||||||
get_dynamic(&m_pvar, (gptr)&p, i);
|
get_dynamic(&m_vars, (gptr)&p, i);
|
||||||
if (my_strnncoll(system_charset_info,
|
if (my_strnncoll(system_charset_info,
|
||||||
(const uchar *)name->str, name->length,
|
(const uchar *)name->str, name->length,
|
||||||
(const uchar *)p->name.str, p->name.length) == 0)
|
(const uchar *)p->name.str, p->name.length) == 0)
|
||||||
|
@ -182,7 +183,7 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!scoped && m_parent)
|
if (!scoped && m_parent)
|
||||||
return m_parent->find_pvar(name, scoped);
|
return m_parent->find_variable(name, scoped);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,40 +193,40 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
|
||||||
- When evaluating parameters at the beginning, and setting out parameters
|
- When evaluating parameters at the beginning, and setting out parameters
|
||||||
at the end, of invokation. (Top frame only, so no recursion then.)
|
at the end, of invokation. (Top frame only, so no recursion then.)
|
||||||
- For printing of sp_instr_set. (Debug mode only.)
|
- For printing of sp_instr_set. (Debug mode only.)
|
||||||
*/
|
*/
|
||||||
sp_pvar_t *
|
sp_variable_t *
|
||||||
sp_pcontext::find_pvar(uint offset)
|
sp_pcontext::find_variable(uint offset)
|
||||||
{
|
{
|
||||||
if (m_poffset <= offset && offset < m_poffset + m_pvar.elements)
|
if (m_var_offset <= offset && offset < m_var_offset + m_vars.elements)
|
||||||
{ // This frame
|
{ // This frame
|
||||||
sp_pvar_t *p;
|
sp_variable_t *p;
|
||||||
|
|
||||||
get_dynamic(&m_pvar, (gptr)&p, offset - m_poffset);
|
get_dynamic(&m_vars, (gptr)&p, offset - m_var_offset);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
if (m_parent)
|
if (m_parent)
|
||||||
return m_parent->find_pvar(offset); // Some previous frame
|
return m_parent->find_variable(offset); // Some previous frame
|
||||||
return NULL; // index out of bounds
|
return NULL; // index out of bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
sp_pvar_t *
|
sp_variable_t *
|
||||||
sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
|
sp_pcontext::push_variable(LEX_STRING *name, enum enum_field_types type,
|
||||||
sp_param_mode_t mode)
|
sp_param_mode_t mode)
|
||||||
{
|
{
|
||||||
sp_pvar_t *p= (sp_pvar_t *)sql_alloc(sizeof(sp_pvar_t));
|
sp_variable_t *p= (sp_variable_t *)sql_alloc(sizeof(sp_variable_t));
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
++m_total_pvars;
|
++m_max_var_index;
|
||||||
|
|
||||||
p->name.str= name->str;
|
p->name.str= name->str;
|
||||||
p->name.length= name->length;
|
p->name.length= name->length;
|
||||||
p->type= type;
|
p->type= type;
|
||||||
p->mode= mode;
|
p->mode= mode;
|
||||||
p->offset= current_pvars();
|
p->offset= current_var_count();
|
||||||
p->dflt= NULL;
|
p->dflt= NULL;
|
||||||
insert_dynamic(&m_pvar, (gptr)&p);
|
insert_dynamic(&m_vars, (gptr)&p);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -272,23 +273,23 @@ sp_pcontext::push_cond(LEX_STRING *name, sp_cond_type_t *val)
|
||||||
p->name.str= name->str;
|
p->name.str= name->str;
|
||||||
p->name.length= name->length;
|
p->name.length= name->length;
|
||||||
p->val= val;
|
p->val= val;
|
||||||
insert_dynamic(&m_cond, (gptr)&p);
|
insert_dynamic(&m_conds, (gptr)&p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See comment for find_pvar() above
|
See comment for find_variable() above
|
||||||
*/
|
*/
|
||||||
sp_cond_type_t *
|
sp_cond_type_t *
|
||||||
sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
|
sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
|
||||||
{
|
{
|
||||||
uint i= m_cond.elements;
|
uint i= m_conds.elements;
|
||||||
|
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
sp_cond_t *p;
|
sp_cond_t *p;
|
||||||
|
|
||||||
get_dynamic(&m_cond, (gptr)&p, i);
|
get_dynamic(&m_conds, (gptr)&p, i);
|
||||||
if (my_strnncoll(system_charset_info,
|
if (my_strnncoll(system_charset_info,
|
||||||
(const uchar *)name->str, name->length,
|
(const uchar *)name->str, name->length,
|
||||||
(const uchar *)p->name.str, p->name.length) == 0)
|
(const uchar *)p->name.str, p->name.length) == 0)
|
||||||
|
@ -302,20 +303,20 @@ sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This only searches the current context, for error checking of
|
This only searches the current context, for error checking of
|
||||||
* duplicates.
|
duplicates.
|
||||||
* Returns TRUE if found.
|
Returns TRUE if found.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
sp_pcontext::find_handler(sp_cond_type_t *cond)
|
sp_pcontext::find_handler(sp_cond_type_t *cond)
|
||||||
{
|
{
|
||||||
uint i= m_handler.elements;
|
uint i= m_handlers.elements;
|
||||||
|
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
sp_cond_type_t *p;
|
sp_cond_type_t *p;
|
||||||
|
|
||||||
get_dynamic(&m_handler, (gptr)&p, i);
|
get_dynamic(&m_handlers, (gptr)&p, i);
|
||||||
if (cond->type == p->type)
|
if (cond->type == p->type)
|
||||||
{
|
{
|
||||||
switch (p->type)
|
switch (p->type)
|
||||||
|
@ -341,31 +342,31 @@ sp_pcontext::push_cursor(LEX_STRING *name)
|
||||||
{
|
{
|
||||||
LEX_STRING n;
|
LEX_STRING n;
|
||||||
|
|
||||||
if (m_cursor.elements == m_csubsize)
|
if (m_cursors.elements == m_max_cursor_index)
|
||||||
m_csubsize+= 1;
|
m_max_cursor_index+= 1;
|
||||||
n.str= name->str;
|
n.str= name->str;
|
||||||
n.length= name->length;
|
n.length= name->length;
|
||||||
insert_dynamic(&m_cursor, (gptr)&n);
|
insert_dynamic(&m_cursors, (gptr)&n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See comment for find_pvar() above
|
See comment for find_variable() above
|
||||||
*/
|
*/
|
||||||
my_bool
|
my_bool
|
||||||
sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
|
sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
|
||||||
{
|
{
|
||||||
uint i= m_cursor.elements;
|
uint i= m_cursors.elements;
|
||||||
|
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
LEX_STRING n;
|
LEX_STRING n;
|
||||||
|
|
||||||
get_dynamic(&m_cursor, (gptr)&n, i);
|
get_dynamic(&m_cursors, (gptr)&n, i);
|
||||||
if (my_strnncoll(system_charset_info,
|
if (my_strnncoll(system_charset_info,
|
||||||
(const uchar *)name->str, name->length,
|
(const uchar *)name->str, name->length,
|
||||||
(const uchar *)n.str, n.length) == 0)
|
(const uchar *)n.str, n.length) == 0)
|
||||||
{
|
{
|
||||||
*poff= m_coffset + i;
|
*poff= m_cursor_offset + i;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,10 +381,10 @@ sp_pcontext::retrieve_field_definitions(List<create_field> *field_def_lst)
|
||||||
{
|
{
|
||||||
/* Put local/context fields in the result list. */
|
/* Put local/context fields in the result list. */
|
||||||
|
|
||||||
for (uint i = 0; i < m_pvar.elements; ++i)
|
for (uint i = 0; i < m_vars.elements; ++i)
|
||||||
{
|
{
|
||||||
sp_pvar_t *var_def;
|
sp_variable_t *var_def;
|
||||||
get_dynamic(&m_pvar, (gptr) &var_def, i);
|
get_dynamic(&m_vars, (gptr) &var_def, i);
|
||||||
|
|
||||||
field_def_lst->push_back(&var_def->field_def);
|
field_def_lst->push_back(&var_def->field_def);
|
||||||
}
|
}
|
||||||
|
@ -400,17 +401,17 @@ sp_pcontext::retrieve_field_definitions(List<create_field> *field_def_lst)
|
||||||
/*
|
/*
|
||||||
Find a cursor by offset from the top.
|
Find a cursor by offset from the top.
|
||||||
This is only used for debugging.
|
This is only used for debugging.
|
||||||
*/
|
*/
|
||||||
my_bool
|
my_bool
|
||||||
sp_pcontext::find_cursor(uint offset, LEX_STRING *n)
|
sp_pcontext::find_cursor(uint offset, LEX_STRING *n)
|
||||||
{
|
{
|
||||||
if (m_coffset <= offset && offset < m_coffset + m_cursor.elements)
|
if (m_cursor_offset <= offset &&
|
||||||
|
offset < m_cursor_offset + m_cursors.elements)
|
||||||
{ // This frame
|
{ // This frame
|
||||||
get_dynamic(&m_cursor, (gptr)n, offset - m_coffset);
|
get_dynamic(&m_cursors, (gptr)n, offset - m_cursor_offset);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (m_parent)
|
if (m_parent)
|
||||||
return m_parent->find_cursor(offset, n); // Some previous frame
|
return m_parent->find_cursor(offset, n); // Some previous frame
|
||||||
return FALSE; // index out of bounds
|
return FALSE; // index out of bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,22 +29,23 @@ typedef enum
|
||||||
sp_param_inout
|
sp_param_inout
|
||||||
} sp_param_mode_t;
|
} sp_param_mode_t;
|
||||||
|
|
||||||
typedef struct sp_pvar
|
typedef struct sp_variable
|
||||||
{
|
{
|
||||||
LEX_STRING name;
|
LEX_STRING name;
|
||||||
enum enum_field_types type;
|
enum enum_field_types type;
|
||||||
sp_param_mode_t mode;
|
sp_param_mode_t mode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
offset -- basically, this is an index of variable in the scope of root
|
offset -- this the index to the variable's value in the runtime frame.
|
||||||
parsing context. This means, that all variables in a stored routine
|
This is calculated during parsing and used when creating sp_instr_set
|
||||||
have distinct indexes/offsets.
|
instructions and Item_splocal items.
|
||||||
|
I.e. values are set/referred by array indexing in runtime.
|
||||||
*/
|
*/
|
||||||
uint offset;
|
uint offset;
|
||||||
|
|
||||||
Item *dflt;
|
Item *dflt;
|
||||||
create_field field_def;
|
create_field field_def;
|
||||||
} sp_pvar_t;
|
} sp_variable_t;
|
||||||
|
|
||||||
|
|
||||||
#define SP_LAB_REF 0 // Unresolved reference (for goto)
|
#define SP_LAB_REF 0 // Unresolved reference (for goto)
|
||||||
|
@ -76,9 +77,10 @@ typedef struct sp_cond_type
|
||||||
uint mysqlerr;
|
uint mysqlerr;
|
||||||
} sp_cond_type_t;
|
} sp_cond_type_t;
|
||||||
|
|
||||||
/* Sanity check for SQLSTATEs. Will not check if it's really an existing
|
/*
|
||||||
* state (there are just too many), but will check length bad characters.
|
Sanity check for SQLSTATEs. Will not check if it's really an existing
|
||||||
*/
|
state (there are just too many), but will check length bad characters.
|
||||||
|
*/
|
||||||
extern bool
|
extern bool
|
||||||
sp_cond_check(LEX_STRING *sqlstate);
|
sp_cond_check(LEX_STRING *sqlstate);
|
||||||
|
|
||||||
|
@ -90,7 +92,17 @@ typedef struct sp_cond
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This seems to be an "SP parsing context" or something.
|
The parse-time context, used to keep track on declared variables/parameters,
|
||||||
|
conditions, handlers, cursors and labels, during parsing.
|
||||||
|
sp_contexts are organized as a tree, with one object for each begin-end
|
||||||
|
block, plus a root-context for the parameters.
|
||||||
|
This is used during parsing for looking up defined names (e.g. declared
|
||||||
|
variables and visible labels), for error checking, and to calculate offsets
|
||||||
|
to be used at runtime. (During execution variable values, active handlers
|
||||||
|
and cursors, etc, are referred to by an index in a stack.)
|
||||||
|
The pcontext tree is also kept during execution and is used for error
|
||||||
|
checking (e.g. correct number of parameters), and in the future, used by
|
||||||
|
the debugger.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class sp_pcontext : public Sql_alloc
|
class sp_pcontext : public Sql_alloc
|
||||||
|
@ -134,50 +146,64 @@ class sp_pcontext : public Sql_alloc
|
||||||
// Parameters and variables
|
// Parameters and variables
|
||||||
//
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
The maximum number of variables used in this and all child contexts
|
||||||
|
In the root, this gives us the number of slots needed for variables
|
||||||
|
during execution.
|
||||||
|
*/
|
||||||
inline uint
|
inline uint
|
||||||
total_pvars()
|
max_var_index()
|
||||||
{
|
{
|
||||||
return m_total_pvars;
|
return m_max_var_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The current number of variables used in the parents (from the root),
|
||||||
|
including this context.
|
||||||
|
*/
|
||||||
inline uint
|
inline uint
|
||||||
current_pvars()
|
current_var_count()
|
||||||
{
|
{
|
||||||
return m_poffset + m_pvar.elements;
|
return m_var_offset + m_vars.elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The number of variables in this context alone */
|
||||||
inline uint
|
inline uint
|
||||||
context_pvars()
|
context_var_count()
|
||||||
{
|
{
|
||||||
return m_pvar.elements;
|
return m_vars.elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Map index in this pcontext to runtime offset */
|
||||||
inline uint
|
inline uint
|
||||||
pvar_context2index(uint i)
|
var_context2runtime(uint i)
|
||||||
{
|
{
|
||||||
return m_poffset + i;
|
return m_var_offset + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set type of variable. 'i' is the offset from the top */
|
||||||
inline void
|
inline void
|
||||||
set_type(uint i, enum enum_field_types type)
|
set_type(uint i, enum enum_field_types type)
|
||||||
{
|
{
|
||||||
sp_pvar_t *p= find_pvar(i);
|
sp_variable_t *p= find_variable(i);
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
p->type= type;
|
p->type= type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set default value of variable. 'i' is the offset from the top */
|
||||||
inline void
|
inline void
|
||||||
set_default(uint i, Item *it)
|
set_default(uint i, Item *it)
|
||||||
{
|
{
|
||||||
sp_pvar_t *p= find_pvar(i);
|
sp_variable_t *p= find_variable(i);
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
p->dflt= it;
|
p->dflt= it;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp_pvar_t *
|
sp_variable_t *
|
||||||
push_pvar(LEX_STRING *name, enum enum_field_types type, sp_param_mode_t mode);
|
push_variable(LEX_STRING *name, enum enum_field_types type,
|
||||||
|
sp_param_mode_t mode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Retrieve definitions of fields from the current context and its
|
Retrieve definitions of fields from the current context and its
|
||||||
|
@ -187,12 +213,12 @@ class sp_pcontext : public Sql_alloc
|
||||||
retrieve_field_definitions(List<create_field> *field_def_lst);
|
retrieve_field_definitions(List<create_field> *field_def_lst);
|
||||||
|
|
||||||
// Find by name
|
// Find by name
|
||||||
sp_pvar_t *
|
sp_variable_t *
|
||||||
find_pvar(LEX_STRING *name, my_bool scoped=0);
|
find_variable(LEX_STRING *name, my_bool scoped=0);
|
||||||
|
|
||||||
// Find by offset
|
// Find by offset (from the top)
|
||||||
sp_pvar_t *
|
sp_variable_t *
|
||||||
find_pvar(uint offset);
|
find_variable(uint offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set the current scope boundary (for default values).
|
Set the current scope boundary (for default values).
|
||||||
|
@ -280,7 +306,7 @@ class sp_pcontext : public Sql_alloc
|
||||||
pop_cond(uint num)
|
pop_cond(uint num)
|
||||||
{
|
{
|
||||||
while (num--)
|
while (num--)
|
||||||
pop_dynamic(&m_cond);
|
pop_dynamic(&m_conds);
|
||||||
}
|
}
|
||||||
|
|
||||||
sp_cond_type_t *
|
sp_cond_type_t *
|
||||||
|
@ -293,22 +319,22 @@ class sp_pcontext : public Sql_alloc
|
||||||
inline void
|
inline void
|
||||||
push_handler(sp_cond_type_t *cond)
|
push_handler(sp_cond_type_t *cond)
|
||||||
{
|
{
|
||||||
insert_dynamic(&m_handler, (gptr)&cond);
|
insert_dynamic(&m_handlers, (gptr)&cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
find_handler(sp_cond_type *cond);
|
find_handler(sp_cond_type *cond);
|
||||||
|
|
||||||
inline uint
|
inline uint
|
||||||
max_handlers()
|
max_handler_index()
|
||||||
{
|
{
|
||||||
return m_hsubsize + m_handlers;
|
return m_max_handler_index + m_context_handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
add_handlers(uint n)
|
add_handlers(uint n)
|
||||||
{
|
{
|
||||||
m_handlers+= n;
|
m_context_handlers+= n;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -326,51 +352,51 @@ class sp_pcontext : public Sql_alloc
|
||||||
find_cursor(uint offset, LEX_STRING *n);
|
find_cursor(uint offset, LEX_STRING *n);
|
||||||
|
|
||||||
inline uint
|
inline uint
|
||||||
max_cursors()
|
max_cursor_index()
|
||||||
{
|
{
|
||||||
return m_csubsize + m_cursor.elements;
|
return m_max_cursor_index + m_cursors.elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint
|
inline uint
|
||||||
current_cursors()
|
current_cursor_count()
|
||||||
{
|
{
|
||||||
return m_coffset + m_cursor.elements;
|
return m_cursor_offset + m_cursors.elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
m_total_pvars -- number of variables (including all types of arguments)
|
m_max_var_index -- number of variables (including all types of arguments)
|
||||||
in this context including all children contexts.
|
in this context including all children contexts.
|
||||||
|
|
||||||
m_total_pvars >= m_pvar.elements.
|
m_max_var_index >= m_vars.elements.
|
||||||
|
|
||||||
m_total_pvars of the root parsing context contains number of all
|
m_max_var_index of the root parsing context contains number of all
|
||||||
variables (including arguments) in all enclosed contexts.
|
variables (including arguments) in all enclosed contexts.
|
||||||
*/
|
*/
|
||||||
uint m_total_pvars;
|
uint m_max_var_index;
|
||||||
|
|
||||||
// The maximum sub context's framesizes
|
// The maximum sub context's framesizes
|
||||||
uint m_csubsize;
|
uint m_max_cursor_index;
|
||||||
uint m_hsubsize;
|
uint m_max_handler_index;
|
||||||
uint m_handlers; // No. of handlers in this context
|
uint m_context_handlers; // No. of handlers in this context
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
sp_pcontext *m_parent; // Parent context
|
sp_pcontext *m_parent; // Parent context
|
||||||
|
|
||||||
/*
|
/*
|
||||||
m_poffset -- basically, this is an index of the first variable in this
|
m_var_offset -- this is an index of the first variable in this
|
||||||
parsing context.
|
parsing context.
|
||||||
|
|
||||||
m_poffset is 0 for root context.
|
m_var_offset is 0 for root context.
|
||||||
|
|
||||||
Since now each variable is stored in separate place, no reuse is done,
|
Since now each variable is stored in separate place, no reuse is done,
|
||||||
so m_poffset is different for all enclosed contexts.
|
so m_var_offset is different for all enclosed contexts.
|
||||||
*/
|
*/
|
||||||
uint m_poffset;
|
uint m_var_offset;
|
||||||
|
|
||||||
uint m_coffset; // Cursor offset for this context
|
uint m_cursor_offset; // Cursor offset for this context
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Boundary for finding variables in this context. This is the number
|
Boundary for finding variables in this context. This is the number
|
||||||
|
@ -382,11 +408,11 @@ private:
|
||||||
|
|
||||||
int m_num_case_exprs;
|
int m_num_case_exprs;
|
||||||
|
|
||||||
DYNAMIC_ARRAY m_pvar; // Parameters/variables
|
DYNAMIC_ARRAY m_vars; // Parameters/variables
|
||||||
DYNAMIC_ARRAY m_case_expr_id_lst; /* Stack of CASE expression ids. */
|
DYNAMIC_ARRAY m_case_expr_id_lst; /* Stack of CASE expression ids. */
|
||||||
DYNAMIC_ARRAY m_cond; // Conditions
|
DYNAMIC_ARRAY m_conds; // Conditions
|
||||||
DYNAMIC_ARRAY m_cursor; // Cursors
|
DYNAMIC_ARRAY m_cursors; // Cursors
|
||||||
DYNAMIC_ARRAY m_handler; // Handlers, for checking of duplicates
|
DYNAMIC_ARRAY m_handlers; // Handlers, for checking for duplicates
|
||||||
|
|
||||||
List<sp_label_t> m_label; // The label list
|
List<sp_label_t> m_label; // The label list
|
||||||
|
|
||||||
|
|
|
@ -73,16 +73,16 @@ bool sp_rcontext::init(THD *thd)
|
||||||
|
|
||||||
return
|
return
|
||||||
!(m_handler=
|
!(m_handler=
|
||||||
(sp_handler_t*)thd->alloc(m_root_parsing_ctx->max_handlers() *
|
(sp_handler_t*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
|
||||||
sizeof(sp_handler_t))) ||
|
sizeof(sp_handler_t))) ||
|
||||||
!(m_hstack=
|
!(m_hstack=
|
||||||
(uint*)thd->alloc(m_root_parsing_ctx->max_handlers() *
|
(uint*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
|
||||||
sizeof(uint))) ||
|
sizeof(uint))) ||
|
||||||
!(m_in_handler=
|
!(m_in_handler=
|
||||||
(uint*)thd->alloc(m_root_parsing_ctx->max_handlers() *
|
(uint*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
|
||||||
sizeof(uint))) ||
|
sizeof(uint))) ||
|
||||||
!(m_cstack=
|
!(m_cstack=
|
||||||
(sp_cursor**)thd->alloc(m_root_parsing_ctx->max_cursors() *
|
(sp_cursor**)thd->alloc(m_root_parsing_ctx->max_cursor_index() *
|
||||||
sizeof(sp_cursor*))) ||
|
sizeof(sp_cursor*))) ||
|
||||||
!(m_case_expr_holders=
|
!(m_case_expr_holders=
|
||||||
(Item_cache**)thd->calloc(m_root_parsing_ctx->get_num_case_exprs() *
|
(Item_cache**)thd->calloc(m_root_parsing_ctx->get_num_case_exprs() *
|
||||||
|
@ -105,12 +105,12 @@ sp_rcontext::init_var_table(THD *thd)
|
||||||
{
|
{
|
||||||
List<create_field> field_def_lst;
|
List<create_field> field_def_lst;
|
||||||
|
|
||||||
if (!m_root_parsing_ctx->total_pvars())
|
if (!m_root_parsing_ctx->max_var_index())
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst);
|
m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst);
|
||||||
|
|
||||||
DBUG_ASSERT(field_def_lst.elements == m_root_parsing_ctx->total_pvars());
|
DBUG_ASSERT(field_def_lst.elements == m_root_parsing_ctx->max_var_index());
|
||||||
|
|
||||||
if (!(m_var_table= create_virtual_tmp_table(thd, field_def_lst)))
|
if (!(m_var_table= create_virtual_tmp_table(thd, field_def_lst)))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -134,7 +134,7 @@ bool
|
||||||
sp_rcontext::init_var_items()
|
sp_rcontext::init_var_items()
|
||||||
{
|
{
|
||||||
uint idx;
|
uint idx;
|
||||||
uint num_vars= m_root_parsing_ctx->total_pvars();
|
uint num_vars= m_root_parsing_ctx->max_var_index();
|
||||||
|
|
||||||
if (!(m_var_items= (Item**) sql_alloc(num_vars * sizeof (Item *))))
|
if (!(m_var_items= (Item**) sql_alloc(num_vars * sizeof (Item *))))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -381,7 +381,7 @@ sp_cursor::destroy()
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
|
sp_cursor::fetch(THD *thd, List<struct sp_variable> *vars)
|
||||||
{
|
{
|
||||||
if (! server_side_cursor)
|
if (! server_side_cursor)
|
||||||
{
|
{
|
||||||
|
@ -528,9 +528,9 @@ int Select_fetch_into_spvars::prepare(List<Item> &fields, SELECT_LEX_UNIT *u)
|
||||||
|
|
||||||
bool Select_fetch_into_spvars::send_data(List<Item> &items)
|
bool Select_fetch_into_spvars::send_data(List<Item> &items)
|
||||||
{
|
{
|
||||||
List_iterator_fast<struct sp_pvar> pv_iter(*spvar_list);
|
List_iterator_fast<struct sp_variable> spvar_iter(*spvar_list);
|
||||||
List_iterator_fast<Item> item_iter(items);
|
List_iterator_fast<Item> item_iter(items);
|
||||||
sp_pvar_t *pv;
|
sp_variable_t *spvar;
|
||||||
Item *item;
|
Item *item;
|
||||||
|
|
||||||
/* Must be ensured by the caller */
|
/* Must be ensured by the caller */
|
||||||
|
@ -540,9 +540,9 @@ bool Select_fetch_into_spvars::send_data(List<Item> &items)
|
||||||
Assign the row fetched from a server side cursor to stored
|
Assign the row fetched from a server side cursor to stored
|
||||||
procedure variables.
|
procedure variables.
|
||||||
*/
|
*/
|
||||||
for (; pv= pv_iter++, item= item_iter++; )
|
for (; spvar= spvar_iter++, item= item_iter++; )
|
||||||
{
|
{
|
||||||
if (thd->spcont->set_variable(thd, pv->offset, item))
|
if (thd->spcont->set_variable(thd, spvar->offset, item))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
struct sp_cond_type;
|
struct sp_cond_type;
|
||||||
class sp_cursor;
|
class sp_cursor;
|
||||||
struct sp_pvar;
|
struct sp_variable;
|
||||||
class sp_lex_keeper;
|
class sp_lex_keeper;
|
||||||
class sp_instr_cpush;
|
class sp_instr_cpush;
|
||||||
|
|
||||||
|
@ -265,12 +265,12 @@ private:
|
||||||
|
|
||||||
class Select_fetch_into_spvars: public select_result_interceptor
|
class Select_fetch_into_spvars: public select_result_interceptor
|
||||||
{
|
{
|
||||||
List<struct sp_pvar> *spvar_list;
|
List<struct sp_variable> *spvar_list;
|
||||||
uint field_count;
|
uint field_count;
|
||||||
public:
|
public:
|
||||||
Select_fetch_into_spvars() {} /* Remove gcc warning */
|
Select_fetch_into_spvars() {} /* Remove gcc warning */
|
||||||
uint get_field_count() { return field_count; }
|
uint get_field_count() { return field_count; }
|
||||||
void set_spvar_list(List<struct sp_pvar> *vars) { spvar_list= vars; }
|
void set_spvar_list(List<struct sp_variable> *vars) { spvar_list= vars; }
|
||||||
|
|
||||||
virtual bool send_eof() { return FALSE; }
|
virtual bool send_eof() { return FALSE; }
|
||||||
virtual bool send_data(List<Item> &items);
|
virtual bool send_data(List<Item> &items);
|
||||||
|
@ -307,7 +307,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fetch(THD *, List<struct sp_pvar> *vars);
|
fetch(THD *, List<struct sp_variable> *vars);
|
||||||
|
|
||||||
inline sp_instr_cpush *
|
inline sp_instr_cpush *
|
||||||
get_instr()
|
get_instr()
|
||||||
|
|
|
@ -74,7 +74,6 @@ static void decrease_user_connections(USER_CONN *uc);
|
||||||
static bool check_db_used(THD *thd,TABLE_LIST *tables);
|
static bool check_db_used(THD *thd,TABLE_LIST *tables);
|
||||||
static bool check_multi_update_lock(THD *thd);
|
static bool check_multi_update_lock(THD *thd);
|
||||||
static void remove_escape(char *name);
|
static void remove_escape(char *name);
|
||||||
static void refresh_status(THD *thd);
|
|
||||||
static bool append_file_to_dir(THD *thd, const char **filename_ptr,
|
static bool append_file_to_dir(THD *thd, const char **filename_ptr,
|
||||||
const char *table_name);
|
const char *table_name);
|
||||||
|
|
||||||
|
@ -6709,27 +6708,6 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Clear most status variables */
|
|
||||||
|
|
||||||
static void refresh_status(THD *thd)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&LOCK_status);
|
|
||||||
|
|
||||||
/* We must update the global status before cleaning up the thread */
|
|
||||||
add_to_status(&global_status_var, &thd->status_var);
|
|
||||||
bzero((char*) &thd->status_var, sizeof(thd->status_var));
|
|
||||||
|
|
||||||
for (struct show_var_st *ptr=status_vars; ptr->name; ptr++)
|
|
||||||
{
|
|
||||||
if (ptr->type == SHOW_LONG)
|
|
||||||
*(ulong*) ptr->value= 0;
|
|
||||||
}
|
|
||||||
/* Reset the counters of all key caches (default and named). */
|
|
||||||
process_key_caches(reset_key_cache_counters);
|
|
||||||
pthread_mutex_unlock(&LOCK_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* If pointer is not a null pointer, append filename to it */
|
/* If pointer is not a null pointer, append filename to it */
|
||||||
|
|
||||||
static bool append_file_to_dir(THD *thd, const char **filename_ptr,
|
static bool append_file_to_dir(THD *thd, const char **filename_ptr,
|
||||||
|
|
|
@ -1461,22 +1461,23 @@ sp_fdparam:
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_pcontext *spc= lex->spcont;
|
sp_pcontext *spc= lex->spcont;
|
||||||
|
|
||||||
if (spc->find_pvar(&$1, TRUE))
|
if (spc->find_variable(&$1, TRUE))
|
||||||
{
|
{
|
||||||
my_error(ER_SP_DUP_PARAM, MYF(0), $1.str);
|
my_error(ER_SP_DUP_PARAM, MYF(0), $1.str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
sp_pvar_t *pvar= spc->push_pvar(&$1, (enum enum_field_types)$3,
|
sp_variable_t *spvar= spc->push_variable(&$1,
|
||||||
sp_param_in);
|
(enum enum_field_types)$3,
|
||||||
|
sp_param_in);
|
||||||
|
|
||||||
if (lex->sphead->fill_field_definition(YYTHD, lex,
|
if (lex->sphead->fill_field_definition(YYTHD, lex,
|
||||||
(enum enum_field_types) $3,
|
(enum enum_field_types) $3,
|
||||||
&pvar->field_def))
|
&spvar->field_def))
|
||||||
{
|
{
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
pvar->field_def.field_name= pvar->name.str;
|
spvar->field_def.field_name= spvar->name.str;
|
||||||
pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
|
spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -1497,22 +1498,23 @@ sp_pdparam:
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_pcontext *spc= lex->spcont;
|
sp_pcontext *spc= lex->spcont;
|
||||||
|
|
||||||
if (spc->find_pvar(&$3, TRUE))
|
if (spc->find_variable(&$3, TRUE))
|
||||||
{
|
{
|
||||||
my_error(ER_SP_DUP_PARAM, MYF(0), $3.str);
|
my_error(ER_SP_DUP_PARAM, MYF(0), $3.str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
sp_pvar_t *pvar= spc->push_pvar(&$3, (enum enum_field_types)$4,
|
sp_variable_t *spvar= spc->push_variable(&$3,
|
||||||
(sp_param_mode_t)$1);
|
(enum enum_field_types)$4,
|
||||||
|
(sp_param_mode_t)$1);
|
||||||
|
|
||||||
if (lex->sphead->fill_field_definition(YYTHD, lex,
|
if (lex->sphead->fill_field_definition(YYTHD, lex,
|
||||||
(enum enum_field_types) $4,
|
(enum enum_field_types) $4,
|
||||||
&pvar->field_def))
|
&spvar->field_def))
|
||||||
{
|
{
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
pvar->field_def.field_name= pvar->name.str;
|
spvar->field_def.field_name= spvar->name.str;
|
||||||
pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
|
spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -1576,7 +1578,7 @@ sp_decl:
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_pcontext *pctx= lex->spcont;
|
sp_pcontext *pctx= lex->spcont;
|
||||||
uint num_vars= pctx->context_pvars();
|
uint num_vars= pctx->context_var_count();
|
||||||
enum enum_field_types var_type= (enum enum_field_types) $4;
|
enum enum_field_types var_type= (enum enum_field_types) $4;
|
||||||
Item *dflt_value_item= $5;
|
Item *dflt_value_item= $5;
|
||||||
create_field *create_field_op;
|
create_field *create_field_op;
|
||||||
|
@ -1589,23 +1591,23 @@ sp_decl:
|
||||||
|
|
||||||
for (uint i = num_vars-$2 ; i < num_vars ; i++)
|
for (uint i = num_vars-$2 ; i < num_vars ; i++)
|
||||||
{
|
{
|
||||||
uint var_idx= pctx->pvar_context2index(i);
|
uint var_idx= pctx->var_context2runtime(i);
|
||||||
sp_pvar_t *pvar= pctx->find_pvar(var_idx);
|
sp_variable_t *spvar= pctx->find_variable(var_idx);
|
||||||
|
|
||||||
if (!pvar)
|
if (!spvar)
|
||||||
YYABORT;
|
YYABORT;
|
||||||
|
|
||||||
pvar->type= var_type;
|
spvar->type= var_type;
|
||||||
pvar->dflt= dflt_value_item;
|
spvar->dflt= dflt_value_item;
|
||||||
|
|
||||||
if (lex->sphead->fill_field_definition(YYTHD, lex, var_type,
|
if (lex->sphead->fill_field_definition(YYTHD, lex, var_type,
|
||||||
&pvar->field_def))
|
&spvar->field_def))
|
||||||
{
|
{
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
pvar->field_def.field_name= pvar->name.str;
|
spvar->field_def.field_name= spvar->name.str;
|
||||||
pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
|
spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
|
||||||
|
|
||||||
/* The last instruction is responsible for freeing LEX. */
|
/* The last instruction is responsible for freeing LEX. */
|
||||||
|
|
||||||
|
@ -1642,7 +1644,7 @@ sp_decl:
|
||||||
sp_pcontext *ctx= lex->spcont;
|
sp_pcontext *ctx= lex->spcont;
|
||||||
sp_instr_hpush_jump *i=
|
sp_instr_hpush_jump *i=
|
||||||
new sp_instr_hpush_jump(sp->instructions(), ctx, $2,
|
new sp_instr_hpush_jump(sp->instructions(), ctx, $2,
|
||||||
ctx->current_pvars());
|
ctx->current_var_count());
|
||||||
|
|
||||||
sp->add_instr(i);
|
sp->add_instr(i);
|
||||||
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
|
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
|
||||||
|
@ -1659,7 +1661,7 @@ sp_decl:
|
||||||
if ($2 == SP_HANDLER_CONTINUE)
|
if ($2 == SP_HANDLER_CONTINUE)
|
||||||
{
|
{
|
||||||
i= new sp_instr_hreturn(sp->instructions(), ctx,
|
i= new sp_instr_hreturn(sp->instructions(), ctx,
|
||||||
ctx->current_pvars());
|
ctx->current_var_count());
|
||||||
sp->add_instr(i);
|
sp->add_instr(i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1690,7 +1692,7 @@ sp_decl:
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
i= new sp_instr_cpush(sp->instructions(), ctx, $5,
|
i= new sp_instr_cpush(sp->instructions(), ctx, $5,
|
||||||
ctx->current_cursors());
|
ctx->current_cursor_count());
|
||||||
sp->add_instr(i);
|
sp->add_instr(i);
|
||||||
ctx->push_cursor(&$2);
|
ctx->push_cursor(&$2);
|
||||||
$$.vars= $$.conds= $$.hndlrs= 0;
|
$$.vars= $$.conds= $$.hndlrs= 0;
|
||||||
|
@ -1845,12 +1847,12 @@ sp_decl_idents:
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_pcontext *spc= lex->spcont;
|
sp_pcontext *spc= lex->spcont;
|
||||||
|
|
||||||
if (spc->find_pvar(&$1, TRUE))
|
if (spc->find_variable(&$1, TRUE))
|
||||||
{
|
{
|
||||||
my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
|
my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
spc->push_pvar(&$1, (enum_field_types)0, sp_param_in);
|
spc->push_variable(&$1, (enum_field_types)0, sp_param_in);
|
||||||
$$= 1;
|
$$= 1;
|
||||||
}
|
}
|
||||||
| sp_decl_idents ',' ident
|
| sp_decl_idents ',' ident
|
||||||
|
@ -1860,12 +1862,12 @@ sp_decl_idents:
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_pcontext *spc= lex->spcont;
|
sp_pcontext *spc= lex->spcont;
|
||||||
|
|
||||||
if (spc->find_pvar(&$3, TRUE))
|
if (spc->find_variable(&$3, TRUE))
|
||||||
{
|
{
|
||||||
my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
|
my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
spc->push_pvar(&$3, (enum_field_types)0, sp_param_in);
|
spc->push_variable(&$3, (enum_field_types)0, sp_param_in);
|
||||||
$$= $1 + 1;
|
$$= $1 + 1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -2198,9 +2200,9 @@ sp_fetch_list:
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp= lex->sphead;
|
sp_head *sp= lex->sphead;
|
||||||
sp_pcontext *spc= lex->spcont;
|
sp_pcontext *spc= lex->spcont;
|
||||||
sp_pvar_t *spv;
|
sp_variable_t *spv;
|
||||||
|
|
||||||
if (!spc || !(spv = spc->find_pvar(&$1)))
|
if (!spc || !(spv = spc->find_variable(&$1)))
|
||||||
{
|
{
|
||||||
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
|
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
|
@ -2219,9 +2221,9 @@ sp_fetch_list:
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp= lex->sphead;
|
sp_head *sp= lex->sphead;
|
||||||
sp_pcontext *spc= lex->spcont;
|
sp_pcontext *spc= lex->spcont;
|
||||||
sp_pvar_t *spv;
|
sp_variable_t *spv;
|
||||||
|
|
||||||
if (!spc || !(spv = spc->find_pvar(&$3)))
|
if (!spc || !(spv = spc->find_variable(&$3)))
|
||||||
{
|
{
|
||||||
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str);
|
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
|
@ -5868,9 +5870,9 @@ select_var_ident:
|
||||||
| ident_or_text
|
| ident_or_text
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
sp_pvar_t *t;
|
sp_variable_t *t;
|
||||||
|
|
||||||
if (!lex->spcont || !(t=lex->spcont->find_pvar(&$1)))
|
if (!lex->spcont || !(t=lex->spcont->find_variable(&$1)))
|
||||||
{
|
{
|
||||||
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
|
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
|
@ -7200,10 +7202,10 @@ order_ident:
|
||||||
simple_ident:
|
simple_ident:
|
||||||
ident
|
ident
|
||||||
{
|
{
|
||||||
sp_pvar_t *spv;
|
sp_variable_t *spv;
|
||||||
LEX *lex = Lex;
|
LEX *lex = Lex;
|
||||||
sp_pcontext *spc = lex->spcont;
|
sp_pcontext *spc = lex->spcont;
|
||||||
if (spc && (spv = spc->find_pvar(&$1)))
|
if (spc && (spv = spc->find_variable(&$1)))
|
||||||
{
|
{
|
||||||
/* We're compiling a stored procedure and found a variable */
|
/* We're compiling a stored procedure and found a variable */
|
||||||
Item_splocal *splocal;
|
Item_splocal *splocal;
|
||||||
|
@ -7947,7 +7949,7 @@ sys_option_value:
|
||||||
{
|
{
|
||||||
/* An SP local variable */
|
/* An SP local variable */
|
||||||
sp_pcontext *ctx= lex->spcont;
|
sp_pcontext *ctx= lex->spcont;
|
||||||
sp_pvar_t *spv;
|
sp_variable_t *spv;
|
||||||
sp_instr_set *sp_set;
|
sp_instr_set *sp_set;
|
||||||
Item *it;
|
Item *it;
|
||||||
if ($1)
|
if ($1)
|
||||||
|
@ -7956,7 +7958,7 @@ sys_option_value:
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
spv= ctx->find_pvar(&$2.base_name);
|
spv= ctx->find_variable(&$2.base_name);
|
||||||
|
|
||||||
if ($4)
|
if ($4)
|
||||||
it= $4;
|
it= $4;
|
||||||
|
@ -8006,7 +8008,7 @@ option_value:
|
||||||
|
|
||||||
names.str= (char *)"names";
|
names.str= (char *)"names";
|
||||||
names.length= 5;
|
names.length= 5;
|
||||||
if (spc && spc->find_pvar(&names))
|
if (spc && spc->find_variable(&names))
|
||||||
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
|
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
|
||||||
else
|
else
|
||||||
yyerror(ER(ER_SYNTAX_ERROR));
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
|
@ -8036,7 +8038,7 @@ option_value:
|
||||||
|
|
||||||
pw.str= (char *)"password";
|
pw.str= (char *)"password";
|
||||||
pw.length= 8;
|
pw.length= 8;
|
||||||
if (spc && spc->find_pvar(&pw))
|
if (spc && spc->find_variable(&pw))
|
||||||
{
|
{
|
||||||
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
|
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
|
@ -8058,10 +8060,10 @@ internal_variable_name:
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_pcontext *spc= lex->spcont;
|
sp_pcontext *spc= lex->spcont;
|
||||||
sp_pvar_t *spv;
|
sp_variable_t *spv;
|
||||||
|
|
||||||
/* We have to lookup here since local vars can shadow sysvars */
|
/* We have to lookup here since local vars can shadow sysvars */
|
||||||
if (!spc || !(spv = spc->find_pvar(&$1)))
|
if (!spc || !(spv = spc->find_variable(&$1)))
|
||||||
{
|
{
|
||||||
/* Not an SP local variable */
|
/* Not an SP local variable */
|
||||||
sys_var *tmp=find_sys_var($1.str, $1.length);
|
sys_var *tmp=find_sys_var($1.str, $1.length);
|
||||||
|
|
Loading…
Add table
Reference in a new issue