mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 10:14:19 +01:00
Merge quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/50
into quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/maint/mrg0306/50 sql/mysqld.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_parse.cc: Auto merged
This commit is contained in:
commit
30c1622ec4
10 changed files with 523 additions and 425 deletions
|
@ -3114,8 +3114,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
|||
|
||||
ex.skip_lines = skip_lines;
|
||||
List<Item> field_list;
|
||||
thd->main_lex.select_lex.context.resolve_in_table_list_only(&tables);
|
||||
set_fields(tables.db, field_list, &thd->main_lex.select_lex.context);
|
||||
thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
|
||||
set_fields(tables.db, field_list, &thd->lex->select_lex.context);
|
||||
thd->variables.pseudo_thread_id= thread_id;
|
||||
if (net)
|
||||
{
|
||||
|
|
|
@ -1600,18 +1600,6 @@ static void network_init(void)
|
|||
|
||||
#endif /*!EMBEDDED_LIBRARY*/
|
||||
|
||||
void MYSQLerror(const char *s)
|
||||
{
|
||||
THD *thd=current_thd;
|
||||
char *yytext= (char*) thd->lex->tok_start;
|
||||
/* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
|
||||
if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
|
||||
s=ER(ER_SYNTAX_ERROR);
|
||||
my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s,
|
||||
(yytext ? (char*) yytext : ""),
|
||||
thd->lex->yylineno);
|
||||
}
|
||||
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
/*
|
||||
|
|
|
@ -166,14 +166,10 @@ Open_tables_state::Open_tables_state(ulong version_arg)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Pass nominal parameters to Statement constructor only to ensure that
|
||||
the destructor works OK in case of error. The main_mem_root will be
|
||||
re-initialized in init().
|
||||
*/
|
||||
|
||||
THD::THD()
|
||||
:Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0),
|
||||
:Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
|
||||
/* statement id */ 0),
|
||||
Open_tables_state(refresh_version),
|
||||
lock_id(&main_lock_id),
|
||||
user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0),
|
||||
|
@ -184,6 +180,12 @@ THD::THD()
|
|||
{
|
||||
ulong tmp;
|
||||
|
||||
/*
|
||||
Pass nominal parameters to init_alloc_root only to ensure that
|
||||
the destructor works OK in case of an error. The main_mem_root
|
||||
will be re-initialized in init_for_queries().
|
||||
*/
|
||||
init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
|
||||
stmt_arena= this;
|
||||
thread_stack= 0;
|
||||
db= 0;
|
||||
|
@ -477,6 +479,7 @@ THD::~THD()
|
|||
#ifndef DBUG_OFF
|
||||
dbug_sentry= THD_SENTRY_GONE;
|
||||
#endif
|
||||
free_root(&main_mem_root, MYF(0));
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -1623,18 +1626,17 @@ void Query_arena::cleanup_stmt()
|
|||
Statement functions
|
||||
*/
|
||||
|
||||
Statement::Statement(enum enum_state state_arg, ulong id_arg,
|
||||
ulong alloc_block_size, ulong prealloc_size)
|
||||
:Query_arena(&main_mem_root, state_arg),
|
||||
Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg,
|
||||
enum enum_state state_arg, ulong id_arg)
|
||||
:Query_arena(mem_root_arg, state_arg),
|
||||
id(id_arg),
|
||||
set_query_id(1),
|
||||
lex(&main_lex),
|
||||
lex(lex_arg),
|
||||
query(0),
|
||||
query_length(0),
|
||||
cursor(0)
|
||||
{
|
||||
name.str= NULL;
|
||||
init_sql_alloc(&main_mem_root, alloc_block_size, prealloc_size);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1676,7 +1678,7 @@ void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
|
|||
|
||||
void THD::end_statement()
|
||||
{
|
||||
/* Cleanup SQL processing state to resuse this statement in next query. */
|
||||
/* Cleanup SQL processing state to reuse this statement in next query. */
|
||||
lex_end(lex);
|
||||
delete lex->result;
|
||||
lex->result= 0;
|
||||
|
@ -1717,12 +1719,6 @@ void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
|
|||
|
||||
Statement::~Statement()
|
||||
{
|
||||
/*
|
||||
We must free `main_mem_root', not `mem_root' (pointer), to work
|
||||
correctly if this statement is used as a backup statement,
|
||||
for which `mem_root' may point to some other statement.
|
||||
*/
|
||||
free_root(&main_mem_root, MYF(0));
|
||||
}
|
||||
|
||||
C_MODE_START
|
||||
|
|
|
@ -753,8 +753,10 @@ public:
|
|||
|
||||
class Server_side_cursor;
|
||||
|
||||
/*
|
||||
State of a single command executed against this connection.
|
||||
/**
|
||||
@class Statement
|
||||
@brief State of a single command executed against this connection.
|
||||
|
||||
One connection can contain a lot of simultaneously running statements,
|
||||
some of which could be:
|
||||
- prepared, that is, contain placeholders,
|
||||
|
@ -772,10 +774,6 @@ class Statement: public ilink, public Query_arena
|
|||
Statement(const Statement &rhs); /* not implemented: */
|
||||
Statement &operator=(const Statement &rhs); /* non-copyable */
|
||||
public:
|
||||
/* FIXME: these must be protected */
|
||||
MEM_ROOT main_mem_root;
|
||||
LEX main_lex;
|
||||
|
||||
/*
|
||||
Uniquely identifies each statement object in thread scope; change during
|
||||
statement lifetime. FIXME: must be const
|
||||
|
@ -819,10 +817,10 @@ public:
|
|||
public:
|
||||
|
||||
/* This constructor is called for backup statements */
|
||||
Statement() { clear_alloc_root(&main_mem_root); }
|
||||
Statement() {}
|
||||
|
||||
Statement(enum enum_state state_arg, ulong id_arg,
|
||||
ulong alloc_block_size, ulong prealloc_size);
|
||||
Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg,
|
||||
enum enum_state state_arg, ulong id_arg);
|
||||
virtual ~Statement();
|
||||
|
||||
/* Assign execution context (note: not all members) of given stmt to self */
|
||||
|
@ -834,7 +832,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
Container for all statements created/used in a connection.
|
||||
Statements in Statement_map have unique Statement::id (guaranteed by id
|
||||
assignment in Statement::Statement)
|
||||
|
@ -914,6 +912,10 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state);
|
|||
bool xid_cache_insert(XID_STATE *xid_state);
|
||||
void xid_cache_delete(XID_STATE *xid_state);
|
||||
|
||||
/**
|
||||
@class Security_context
|
||||
@brief A set of THD members describing the current authenticated user.
|
||||
*/
|
||||
|
||||
class Security_context {
|
||||
public:
|
||||
|
@ -943,7 +945,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
A registry for item tree transformations performed during
|
||||
query optimization. We register only those changes which require
|
||||
a rollback to re-execute a prepared statement or stored procedure
|
||||
|
@ -954,7 +956,7 @@ struct Item_change_record;
|
|||
typedef I_List<Item_change_record> Item_change_list;
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
Type of prelocked mode.
|
||||
See comment for THD::prelocked_mode for complete description.
|
||||
*/
|
||||
|
@ -963,7 +965,7 @@ enum prelocked_mode_type {NON_PRELOCKED= 0, PRELOCKED= 1,
|
|||
PRELOCKED_UNDER_LOCK_TABLES= 2};
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
Class that holds information about tables which were opened and locked
|
||||
by the thread. It is also used to save/restore this information in
|
||||
push_open_tables_state()/pop_open_tables_state().
|
||||
|
@ -1048,14 +1050,17 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/* class to save context when executing a function or trigger */
|
||||
/**
|
||||
@class Sub_statement_state
|
||||
@brief Used to save context when executing a function or trigger
|
||||
*/
|
||||
|
||||
/* Defines used for Sub_statement_state::in_sub_stmt */
|
||||
|
||||
#define SUB_STMT_TRIGGER 1
|
||||
#define SUB_STMT_FUNCTION 2
|
||||
|
||||
|
||||
class Sub_statement_state
|
||||
{
|
||||
public:
|
||||
|
@ -1114,7 +1119,8 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
@class THD
|
||||
For each client connection we create a separate thread with THD serving as
|
||||
a thread/connection descriptor
|
||||
*/
|
||||
|
@ -1726,6 +1732,22 @@ public:
|
|||
private:
|
||||
/** The current internal error handler for this thread, or NULL. */
|
||||
Internal_error_handler *m_internal_handler;
|
||||
/**
|
||||
The lex to hold the parsed tree of conventional (non-prepared) queries.
|
||||
Whereas for prepared and stored procedure statements we use an own lex
|
||||
instance for each new query, for conventional statements we reuse
|
||||
the same lex. (@see mysql_parse for details).
|
||||
*/
|
||||
LEX main_lex;
|
||||
/**
|
||||
This memory root is used for two purposes:
|
||||
- for conventional queries, to allocate structures stored in main_lex
|
||||
during parsing, and allocate runtime data (execution plan, etc.)
|
||||
during execution.
|
||||
- for prepared queries, only to allocate runtime data. The parsed
|
||||
tree itself is reused between executions and thus is stored elsewhere.
|
||||
*/
|
||||
MEM_ROOT main_mem_root;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1648,6 +1648,36 @@ void st_select_lex::print_limit(THD *thd, String *str)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Restore the LEX and THD in case of a parse error.
|
||||
|
||||
This is a clean up call that is invoked by the Bison generated
|
||||
parser before returning an error from MYSQLparse. If your
|
||||
semantic actions manipulate with the global thread state (which
|
||||
is a very bad practice and should not normally be employed) and
|
||||
need a clean-up in case of error, and you can not use %destructor
|
||||
rule in the grammar file itself, this function should be used
|
||||
to implement the clean up.
|
||||
*/
|
||||
|
||||
void st_lex::cleanup_lex_after_parse_error(THD *thd)
|
||||
{
|
||||
/*
|
||||
Delete sphead for the side effect of restoring of the original
|
||||
LEX state, thd->lex, thd->mem_root and thd->free_list if they
|
||||
were replaced when parsing stored procedure statements. We
|
||||
will never use sphead object after a parse error, so it's okay
|
||||
to delete it only for the sake of the side effect.
|
||||
TODO: make this functionality explicit in sp_head class.
|
||||
Sic: we must nullify the member of the main lex, not the
|
||||
current one that will be thrown away
|
||||
*/
|
||||
if (thd->lex->sphead)
|
||||
{
|
||||
delete thd->lex->sphead;
|
||||
thd->lex->sphead= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize (or reset) Query_tables_list object.
|
||||
|
|
|
@ -1182,6 +1182,10 @@ typedef struct st_lex : public Query_tables_list
|
|||
{
|
||||
return context_stack.head();
|
||||
}
|
||||
/*
|
||||
Restore the LEX and THD in case of a parse error.
|
||||
*/
|
||||
static void cleanup_lex_after_parse_error(THD *thd);
|
||||
|
||||
void reset_n_backup_query_tables_list(Query_tables_list *backup);
|
||||
void restore_backup_query_tables_list(Query_tables_list *backup);
|
||||
|
|
|
@ -4517,9 +4517,6 @@ end_with_restore_list:
|
|||
clean up the environment.
|
||||
*/
|
||||
create_sp_error:
|
||||
lex->unit.cleanup();
|
||||
delete lex->sphead;
|
||||
lex->sphead= 0;
|
||||
if (sp_result != SP_OK )
|
||||
goto error;
|
||||
send_ok(thd);
|
||||
|
@ -4890,9 +4887,6 @@ create_sp_error:
|
|||
/* Conditionally writes to binlog. */
|
||||
res= mysql_create_or_drop_trigger(thd, all_tables, 1);
|
||||
|
||||
/* We don't care about trigger body after this point */
|
||||
delete lex->sphead;
|
||||
lex->sphead= 0;
|
||||
break;
|
||||
}
|
||||
case SQLCOM_DROP_TRIGGER:
|
||||
|
@ -5915,15 +5909,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
if (thd->net.report_error)
|
||||
{
|
||||
if (thd->lex->sphead)
|
||||
{
|
||||
delete thd->lex->sphead;
|
||||
thd->lex->sphead= NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (! thd->net.report_error)
|
||||
{
|
||||
/*
|
||||
Binlog logs a string starting from thd->query and having length
|
||||
|
@ -5943,7 +5929,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
|
|||
query_cache_end_of_result(thd);
|
||||
}
|
||||
}
|
||||
lex->unit.cleanup();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5951,19 +5936,14 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
|
|||
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
|
||||
thd->is_fatal_error));
|
||||
|
||||
/*
|
||||
The first thing we do after parse error is freeing sp_head to
|
||||
ensure that we have restored original memroot.
|
||||
*/
|
||||
if (thd->lex->sphead)
|
||||
{
|
||||
/* Clean up after failed stored procedure/function */
|
||||
delete thd->lex->sphead;
|
||||
thd->lex->sphead= NULL;
|
||||
}
|
||||
query_cache_abort(&thd->net);
|
||||
lex->unit.cleanup();
|
||||
}
|
||||
if (thd->lex->sphead)
|
||||
{
|
||||
delete thd->lex->sphead;
|
||||
thd->lex->sphead= 0;
|
||||
}
|
||||
lex->unit.cleanup();
|
||||
thd->proc_info="freeing items";
|
||||
thd->end_statement();
|
||||
thd->cleanup_after_query();
|
||||
|
|
|
@ -99,9 +99,12 @@ public:
|
|||
#endif
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
Prepared_statement: a statement that can contain placeholders
|
||||
******************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
@class Prepared_statement
|
||||
@brief Prepared_statement: a statement that can contain placeholders
|
||||
*/
|
||||
|
||||
class Prepared_statement: public Statement
|
||||
{
|
||||
|
@ -141,6 +144,16 @@ public:
|
|||
bool execute(String *expanded_query, bool open_cursor);
|
||||
/* Destroy this statement */
|
||||
bool deallocate();
|
||||
private:
|
||||
/**
|
||||
Store the parsed tree of a prepared statement here.
|
||||
*/
|
||||
LEX main_lex;
|
||||
/**
|
||||
The memory root to allocate parsed tree elements (instances of Item,
|
||||
SELECT_LEX and other classes).
|
||||
*/
|
||||
MEM_ROOT main_mem_root;
|
||||
};
|
||||
|
||||
|
||||
|
@ -2034,6 +2047,7 @@ void mysql_sql_stmt_prepare(THD *thd)
|
|||
delete stmt;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
if (thd->stmt_map.insert(thd, stmt))
|
||||
{
|
||||
/* The statement is deleted and an error is set if insert fails */
|
||||
|
@ -2629,17 +2643,18 @@ Select_fetch_protocol_prep::send_data(List<Item> &fields)
|
|||
****************************************************************************/
|
||||
|
||||
Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg)
|
||||
:Statement(INITIALIZED, ++thd_arg->statement_id_counter,
|
||||
thd_arg->variables.query_alloc_block_size,
|
||||
thd_arg->variables.query_prealloc_size),
|
||||
:Statement(&main_lex, &main_mem_root,
|
||||
INITIALIZED, ++thd_arg->statement_id_counter),
|
||||
thd(thd_arg),
|
||||
result(thd_arg),
|
||||
protocol(protocol_arg),
|
||||
param_array(0),
|
||||
param_count(0),
|
||||
last_errno(0),
|
||||
flags((uint) IS_IN_USE)
|
||||
flags((uint) IS_IN_USE)
|
||||
{
|
||||
init_alloc_root(&main_mem_root, thd_arg->variables.query_alloc_block_size,
|
||||
thd_arg->variables.query_prealloc_size);
|
||||
*last_error= '\0';
|
||||
}
|
||||
|
||||
|
@ -2688,6 +2703,7 @@ Prepared_statement::~Prepared_statement()
|
|||
*/
|
||||
free_items();
|
||||
delete lex->result;
|
||||
free_root(&main_mem_root, MYF(0));
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -2703,6 +2719,7 @@ void Prepared_statement::cleanup_stmt()
|
|||
DBUG_ENTER("Prepared_statement::cleanup_stmt");
|
||||
DBUG_PRINT("enter",("stmt: %p", this));
|
||||
|
||||
DBUG_ASSERT(lex->sphead == 0);
|
||||
/* The order is important */
|
||||
lex->unit.cleanup();
|
||||
cleanup_items(free_list);
|
||||
|
@ -2789,15 +2806,6 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
|||
error= MYSQLparse((void *)thd) || thd->is_fatal_error ||
|
||||
thd->net.report_error || init_param_array(this);
|
||||
|
||||
/*
|
||||
The first thing we do after parse error is freeing sp_head to
|
||||
ensure that we have restored original memroot.
|
||||
*/
|
||||
if (error && lex->sphead)
|
||||
{
|
||||
delete lex->sphead;
|
||||
lex->sphead= NULL;
|
||||
}
|
||||
/*
|
||||
While doing context analysis of the query (in check_prepared_statement)
|
||||
we allocate a lot of additional memory: for open tables, JOINs, derived
|
||||
|
@ -2823,12 +2831,18 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
|||
if (error == 0)
|
||||
error= check_prepared_statement(this, name.str != 0);
|
||||
|
||||
/* Free sp_head if check_prepared_statement() failed. */
|
||||
if (error && lex->sphead)
|
||||
/*
|
||||
Currently CREATE PROCEDURE/TRIGGER/EVENT are prohibited in prepared
|
||||
statements: ensure we have no memory leak here if by someone tries
|
||||
to PREPARE stmt FROM "CREATE PROCEDURE ..."
|
||||
*/
|
||||
DBUG_ASSERT(lex->sphead == NULL || error != 0);
|
||||
if (lex->sphead)
|
||||
{
|
||||
delete lex->sphead;
|
||||
lex->sphead= NULL;
|
||||
}
|
||||
|
||||
lex_end(lex);
|
||||
cleanup_stmt();
|
||||
thd->restore_backup_statement(this, &stmt_backup);
|
||||
|
|
|
@ -983,11 +983,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
|||
thd->spcont= 0;
|
||||
if (MYSQLparse((void *)thd) || thd->is_fatal_error)
|
||||
{
|
||||
/*
|
||||
Free lex associated resources.
|
||||
QQ: Do we really need all this stuff here ?
|
||||
*/
|
||||
delete lex.sphead;
|
||||
/* Currently sphead is always deleted in case of a parse error */
|
||||
DBUG_ASSERT(lex.sphead == 0);
|
||||
goto err_with_lex_cleanup;
|
||||
}
|
||||
|
||||
|
|
721
sql/sql_yacc.yy
721
sql/sql_yacc.yy
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue