Commit dba4dce2 authored by unknown's avatar unknown

Desperate attempt to push part of prepared statements cleanup which was

reviewed in Saint-Petersbourg (including post-review fixes).


include/my_sys.h:
  Added clear_alloc_root (reset alloc root without freeing its memory)
sql/item.h:
  - rename setup_param -> set_parap (function assigns parameter value to item)
sql/mysql_priv.h:
  - all return values are void, because return value is never checked in
      dispatch_command
  - removed unused declaration of setup_param_functions
sql/protocol.h:
  - unused declarations of setup_params_data* removed
sql/sql_class.cc:
  Cleanup:
    - bzero(mem_root) replaced with clear_alloc_root
    - query_id and command members moved back to THD from Statement
  Assignment of mem_root, free_list, query_id and command optimized
  away from set_statement().
sql/sql_class.h:
  - query_id and command moved back to THD from Statement
sql/sql_lex.h:
  - better type for param_list
  - param_count is the same thing as param_list.elements
sql/sql_parse.cc:
  - comments for dispatch_command
sql/sql_prepare.cc:
  Cleanup:
  - added comments to many functions and removed trailing spaces in many 
    lines, some stale comments removed.
  - it's faster to iterate using pointers, than classes
  - Renames: error_in_prepare renamed to get_longdata_error (because it is set
    when there is an error in mysql_send_longdata, rather than in
    mysql_prepare), embedded versions of placeholder assignement functions
    now have prefix emb_, setup_ functions renamed to set_, because they
    perform assignment, not installation, setup_params_data now doesn't
    call insert_params and was renamed to setup_set_param_functions,
  - find_prepared_statement should not send error if called from no-reply
    calls, like mysql_stmt_reset
  - error reporting is checked up, to always report errors and not report
    errors twice. send_prep_stmt can be done mostly in send_prepare_result, 
    rather than in test_* functions.
  - now we don't need to reinit THD->mem_root/free_list in mysql_stmt_execute,
    because it's not reset there.
tests/client_test.c:
  - removed second call to test_subqueries
parent f58aa06f
......@@ -714,6 +714,7 @@ extern void my_free_lock(byte *ptr,myf flags);
#define my_free_lock(A,B) my_free((A),(B))
#endif
#define alloc_root_inited(A) ((A)->min_malloc != 0)
#define clear_alloc_root(A) bzero((void *) (A), sizeof(MEM_ROOT))
extern void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size);
extern gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size);
......
......@@ -375,9 +375,9 @@ class Item_param :public Item
bool get_time(TIME *tm);
void reset() {}
#ifndef EMBEDDED_LIBRARY
void (*setup_param_func)(Item_param *param, uchar **pos);
void (*set_param_func)(Item_param *param, uchar **pos);
#else
void (*setup_param_func)(Item_param *param, uchar **pos, ulong data_len);
void (*set_param_func)(Item_param *param, uchar **pos, ulong data_len);
#endif
enum Item_result result_type () const
{ return item_result_type; }
......
......@@ -620,14 +620,13 @@ int mysqld_show_column_types(THD *thd);
int mysqld_help (THD *thd, const char *text);
/* sql_prepare.cc */
bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
void mysql_stmt_execute(THD *thd, char *packet);
void mysql_stmt_free(THD *thd, char *packet);
void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter);
void setup_param_functions(Item_param *param, uchar param_type);
/* sql_error.cc */
MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
......
......@@ -178,8 +178,3 @@ char *net_store_data(char *to,const char *from, uint length);
char *net_store_data(char *to,int32 from);
char *net_store_data(char *to,longlong from);
#ifdef EMBEDDED_LIBRARY
bool setup_params_data(struct st_prep_stmt *stmt);
bool setup_params_data_withlog(struct st_prep_stmt *stmt);
#endif
......@@ -145,8 +145,7 @@ THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
init();
/* Initialize sub structures */
bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
bzero((char*) &warn_root,sizeof(warn_root));
clear_alloc_root(&transaction.mem_root);
init_alloc_root(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
user_connect=(USER_CONN *)0;
hash_init(&user_vars, &my_charset_bin, USER_VARS_HASH_SIZE, 0, 0,
......@@ -331,7 +330,7 @@ THD::~THD()
dbug_sentry = THD_SENTRY_GONE;
#endif
/* Reset stmt_backup.mem_root to not double-free memory from thd.mem_root */
init_alloc_root(&stmt_backup.mem_root, 0, 0);
clear_alloc_root(&stmt_backup.mem_root);
DBUG_VOID_RETURN;
}
......@@ -1185,10 +1184,8 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
Statement::Statement(THD *thd)
:id(++thd->statement_id_counter),
query_id(thd->query_id),
set_query_id(1),
allow_sum_func(0),
command(thd->command),
lex(&main_lex),
query(0),
query_length(0),
......@@ -1207,10 +1204,8 @@ Statement::Statement(THD *thd)
Statement::Statement()
:id(0),
query_id(0), /* initialized later */
set_query_id(1),
allow_sum_func(0), /* initialized later */
command(COM_SLEEP), /* initialized later */
lex(&main_lex),
query(0), /* these two are set */
query_length(0), /* in alloc_query() */
......@@ -1229,15 +1224,11 @@ Statement::Type Statement::type() const
void Statement::set_statement(Statement *stmt)
{
id= stmt->id;
query_id= stmt->query_id;
set_query_id= stmt->set_query_id;
allow_sum_func= stmt->allow_sum_func;
command= stmt->command;
lex= stmt->lex;
query= stmt->query;
query_length= stmt->query_length;
free_list= stmt->free_list;
mem_root= stmt->mem_root;
}
......
......@@ -434,15 +434,6 @@ class Statement
*/
ulong id;
/*
Id of current query. Statement can be reused to execute several queries
query_id is global in context of the whole MySQL server.
ID is automatically generated from mutex-protected counter.
It's used in handler code for various purposes: to check which columns
from table are necessary for this select, to check if it's necessary to
update auto-updatable fields (like auto_increment and timestamp).
*/
ulong query_id;
/*
- if set_query_id=1, we set field->query_id for all fields. In that case
field list can not contain duplicates.
......@@ -461,11 +452,6 @@ class Statement
See item_sum.cc for details.
*/
bool allow_sum_func;
/*
Type of current query: COM_PREPARE, COM_QUERY, etc. Set from
first byte of the packet in do_command()
*/
enum enum_server_command command;
LEX *lex; // parse tree descriptor
/*
......@@ -676,6 +662,11 @@ class THD :public ilink,
uint dbug_sentry; // watch out for memory corruption
#endif
struct st_my_thread_var *mysys_var;
/*
Type of current query: COM_PREPARE, COM_QUERY, etc. Set from
first byte of the packet in do_command()
*/
enum enum_server_command command;
uint32 server_id;
uint32 file_id; // for LOAD DATA INFILE
/*
......@@ -751,6 +742,15 @@ class THD :public ilink,
List <MYSQL_ERROR> warn_list;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count;
/*
Id of current query. Statement can be reused to execute several queries
query_id is global in context of the whole MySQL server.
ID is automatically generated from mutex-protected counter.
It's used in handler code for various purposes: to check which columns
from table are necessary for this select, to check if it's necessary to
update auto-updatable fields (like auto_increment and timestamp).
*/
ulong query_id;
ulong warn_id, version, options, thread_id, col_access;
/* Statement id is thread-wide. This counter is used to generate ids */
......
......@@ -552,7 +552,7 @@ typedef struct st_lex
List<Item> *insert_list,field_list,value_list;
List<List_item> many_values;
List<set_var_base> var_list;
List<Item> param_list;
List<Item_param> param_list;
SQL_LIST proc_list, auxilliary_table_list, save_list;
TYPELIB *interval;
create_field *last_field;
......@@ -577,7 +577,6 @@ typedef struct st_lex
uint uint_geom_type;
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
uint param_count;
uint slave_thd_opt;
uint8 describe;
bool drop_if_exists, drop_temporary, local_file;
......
......@@ -1232,10 +1232,34 @@ bool do_command(THD *thd)
command_name[command]));
}
net->read_timeout=old_timeout; // restore it
/*
packet_length contains length of data, as it was stored in packet
header. In case of malformed header, packet_length can be zero.
If packet_length is not zero, my_net_read ensures that this number
of bytes was actually read from network. Additionally my_net_read
sets packet[packet_length]= 0 (thus if packet_length == 0,
command == packet[0] == COM_SLEEP).
In dispatch_command packet[packet_length] points beyond the end of packet.
*/
DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length));
}
#endif /* EMBEDDED_LIBRARY */
/*
Perform one connection-level (COM_XXXX) command.
SYNOPSIS
dispatch_command()
thd connection handle
command type of command to perform
packet data for the command, packet is always null-terminated
packet_length length of packet + 1 (to show that data is
null-terminated) except for COM_SLEEP, where it
can be zero.
RETURN VALUE
0 ok
1 request of thread shutdown, i. e. if command is
COM_QUIT/COM_SHUTDOWN
*/
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length)
......
This diff is collapsed.
......@@ -4478,11 +4478,17 @@ text_string:
param_marker:
'?'
{
LEX *lex=Lex;
if (YYTHD->command == COM_PREPARE)
THD *thd=YYTHD;
LEX *lex= thd->lex;
if (thd->command == COM_PREPARE)
{
lex->param_list.push_back($$=new Item_param((uint)(lex->tok_start-(uchar *)YYTHD->query)));
lex->param_count++;
Item_param *item= new Item_param((uint) (lex->tok_start -
(uchar *) thd->query));
if (!($$= item) || lex->param_list.push_back(item))
{
send_error(thd, ER_OUT_OF_RESOURCES);
YYABORT;
}
}
else
{
......
......@@ -8470,8 +8470,6 @@ int main(int argc, char **argv)
start_time= time((time_t *)0);
test_subqueries();
client_query(); /* simple client query test */
#if NOT_YET_WORKING
/* Used for internal new development debugging */
......
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