Commit 70abdf3a authored by venu@myvenu.com's avatar venu@myvenu.com

Merge myvenu.com:/home/venu/bk/src-4.1

into myvenu.com:/home/venu/work/sql/dev-4.1
parents c025981c e01a6c83
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <my_global.h>
#include "mysql.h" #include "mysql.h"
#define INSERT_QUERY "insert into test (name,num) values ('item %d', %d)" #define INSERT_QUERY "insert into test (name,num) values ('item %d', %d)"
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "my_global.h"
#include "mysql.h" #include "mysql.h"
#define SELECT_QUERY "select name from test where num = %d" #define SELECT_QUERY "select name from test where num = %d"
......
...@@ -61,6 +61,8 @@ typedef int my_socket; ...@@ -61,6 +61,8 @@ typedef int my_socket;
#define CHECK_EXTRA_ARGUMENTS #define CHECK_EXTRA_ARGUMENTS
#endif #endif
#include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */
extern unsigned int mysql_port; extern unsigned int mysql_port;
extern char *mysql_unix_port; extern char *mysql_unix_port;
...@@ -213,6 +215,8 @@ typedef struct st_mysql ...@@ -213,6 +215,8 @@ typedef struct st_mysql
struct st_mysql* last_used_slave; /* needed for round-robin slave pick */ struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
/* needed for send/read/store/use result to work correctly with replication */ /* needed for send/read/store/use result to work correctly with replication */
struct st_mysql* last_used_con; struct st_mysql* last_used_con;
LIST *stmts; /* list of all statements */
} MYSQL; } MYSQL;
...@@ -457,6 +461,7 @@ typedef struct st_mysql_stmt ...@@ -457,6 +461,7 @@ typedef struct st_mysql_stmt
MYSQL_RES *result; /* resultset */ MYSQL_RES *result; /* resultset */
MYSQL_BIND *bind; /* row binding */ MYSQL_BIND *bind; /* row binding */
MYSQL_FIELD *fields; /* prepare meta info */ MYSQL_FIELD *fields; /* prepare meta info */
LIST list; /* list to keep track of all stmts */
char *query; /* query buffer */ char *query; /* query buffer */
MEM_ROOT mem_root; /* root allocations */ MEM_ROOT mem_root; /* root allocations */
MYSQL_RES tmp_result; /* Used by mysql_prepare_result */ MYSQL_RES tmp_result; /* Used by mysql_prepare_result */
...@@ -469,8 +474,8 @@ typedef struct st_mysql_stmt ...@@ -469,8 +474,8 @@ typedef struct st_mysql_stmt
char last_error[MYSQL_ERRMSG_SIZE]; /* error message */ char last_error[MYSQL_ERRMSG_SIZE]; /* error message */
my_bool long_alloced; /* flag to indicate long alloced */ my_bool long_alloced; /* flag to indicate long alloced */
my_bool send_types_to_server; /* to indicate types supply to server */ my_bool send_types_to_server; /* to indicate types supply to server */
my_bool param_buffers; /* to indicate the param bound buffers */ my_bool param_buffers; /* to indicate the param bound buffers */
my_bool res_buffers; /* to indicate the result bound buffers */ my_bool res_buffers; /* to indicate the output bound buffers */
} MYSQL_STMT; } MYSQL_STMT;
......
...@@ -114,6 +114,7 @@ static my_bool send_file_to_server(MYSQL *mysql,const char *filename); ...@@ -114,6 +114,7 @@ static my_bool send_file_to_server(MYSQL *mysql,const char *filename);
static sig_handler pipe_sig_handler(int sig); static sig_handler pipe_sig_handler(int sig);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
const char *from, ulong length); const char *from, ulong length);
static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list);
static my_bool org_my_init_done=0; static my_bool org_my_init_done=0;
...@@ -2436,6 +2437,16 @@ mysql_close(MYSQL *mysql) ...@@ -2436,6 +2437,16 @@ mysql_close(MYSQL *mysql)
} }
mysql->rpl_pivot=0; mysql->rpl_pivot=0;
} }
if (mysql->stmts)
{
/* Free any open prepared statements */
LIST *element, *next_element;
for (element= mysql->stmts; element; element= next_element)
{
next_element= element->next;
stmt_close((MYSQL_STMT *)element->data, 0);
}
}
if (mysql != mysql->master) if (mysql != mysql->master)
mysql_close(mysql->master); mysql_close(mysql->master);
if (mysql->free_me) if (mysql->free_me)
...@@ -3675,18 +3686,20 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length) ...@@ -3675,18 +3686,20 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length)
} }
if (simple_command(mysql, COM_PREPARE, query, length, 1)) if (simple_command(mysql, COM_PREPARE, query, length, 1))
{ {
mysql_stmt_close(stmt); stmt_close(stmt, 1);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
init_alloc_root(&stmt->mem_root,8192,0); init_alloc_root(&stmt->mem_root,8192,0);
if (read_prepare_result(mysql, stmt)) if (read_prepare_result(mysql, stmt))
{ {
mysql_stmt_close(stmt); stmt_close(stmt, 1);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
stmt->state= MY_ST_PREPARE; stmt->state= MY_ST_PREPARE;
stmt->mysql= mysql; stmt->mysql= mysql;
mysql->stmts= list_add(mysql->stmts, &stmt->list);
stmt->list.data= stmt;
DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count)); DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count));
DBUG_RETURN(stmt); DBUG_RETURN(stmt);
} }
...@@ -4304,7 +4317,6 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) ...@@ -4304,7 +4317,6 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/* /*
Fetch row data to bind buffers Fetch row data to bind buffers
*/ */
...@@ -4387,27 +4399,42 @@ int STDCALL mysql_fetch(MYSQL_STMT *stmt) ...@@ -4387,27 +4399,42 @@ int STDCALL mysql_fetch(MYSQL_STMT *stmt)
*********************************************************************/ *********************************************************************/
/* /*
Close the statement handle by freeing all resources Close the statement handle by freeing all alloced resources
*/
my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) SYNOPSIS
mysql_stmt_close()
stmt Statement handle
skip_list Flag to indicate delete from list or not
RETURN VALUES
0 ok
1 error
*/
static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list)
{ {
my_bool error=0; my_bool error=0;
DBUG_ENTER("mysql_stmt_close"); DBUG_ENTER("mysql_stmt_close");
if (stmt->state != MY_ST_UNKNOWN) DBUG_ASSERT(stmt != 0);
if (stmt->state == MY_ST_PREPARE || stmt->state == MY_ST_EXECUTE)
{ {
char buff[4]; char buff[4];
int4store(buff, stmt->stmt_id); int4store(buff, stmt->stmt_id);
error= simple_command(stmt->mysql, COM_CLOSE_STMT, buff, 4, 0); error= simple_command(stmt->mysql, COM_CLOSE_STMT, buff, 4, 1);
} }
mysql_free_result(stmt->result); mysql_free_result(stmt->result);
free_root(&stmt->mem_root, MYF(0)); free_root(&stmt->mem_root, MYF(0));
my_free((gptr) stmt->query, MYF(MY_WME | MY_ALLOW_ZERO_PTR)); my_free((gptr) stmt->query, MYF(MY_WME | MY_ALLOW_ZERO_PTR));
if (!skip_list)
stmt->mysql->stmts= list_delete(stmt->mysql->stmts, &stmt->list);
my_free((gptr) stmt, MYF(MY_WME)); my_free((gptr) stmt, MYF(MY_WME));
DBUG_RETURN(error); DBUG_RETURN(error);
} }
my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
{
return stmt_close(stmt, 0);
}
/* /*
Return statement error code Return statement error code
*/ */
......
...@@ -516,7 +516,7 @@ int compare_prep_stmt(void *not_used, PREP_STMT *stmt, ulong *key); ...@@ -516,7 +516,7 @@ int compare_prep_stmt(void *not_used, PREP_STMT *stmt, ulong *key);
void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used); void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used);
bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length); bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
void mysql_stmt_execute(THD *thd, char *packet); void mysql_stmt_execute(THD *thd, char *packet);
void mysql_stm_close(THD *thd, char *packet); void mysql_stmt_free(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter); List<Item> &values, ulong counter);
......
...@@ -74,7 +74,7 @@ const char *command_name[]={ ...@@ -74,7 +74,7 @@ const char *command_name[]={
"Drop DB", "Refresh", "Shutdown", "Statistics", "Processlist", "Drop DB", "Refresh", "Shutdown", "Statistics", "Processlist",
"Connect","Kill","Debug","Ping","Time","Delayed_insert","Change user", "Connect","Kill","Debug","Ping","Time","Delayed_insert","Change user",
"Binlog Dump","Table Dump", "Connect Out", "Register Slave", "Binlog Dump","Table Dump", "Connect Out", "Register Slave",
"Prepare", "Prepare Execute", "Long Data" "Prepare", "Prepare Execute", "Long Data", "Close stmt"
}; };
static char empty_c_string[1]= {0}; // Used for not defined 'db' static char empty_c_string[1]= {0}; // Used for not defined 'db'
...@@ -1004,6 +1004,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1004,6 +1004,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
mysql_stmt_prepare(thd, packet, packet_length); mysql_stmt_prepare(thd, packet, packet_length);
break; break;
} }
case COM_CLOSE_STMT:
{
mysql_stmt_free(thd, packet);
break;
}
case COM_QUERY: case COM_QUERY:
{ {
if (alloc_query(thd, packet, packet_length)) if (alloc_query(thd, packet, packet_length))
......
...@@ -20,32 +20,47 @@ This file contains the implementation of prepare and executes. ...@@ -20,32 +20,47 @@ This file contains the implementation of prepare and executes.
Prepare: Prepare:
- Server gets the query from client with command 'COM_PREPARE' - Server gets the query from client with command 'COM_PREPARE';
in the following format:
[COM_PREPARE:1] [query]
- Parse the query and recognize any parameter markers '?' and - Parse the query and recognize any parameter markers '?' and
store its information list lex->param_list store its information list in lex->param_list
- Allocate a new statement for this prepare; and keep this in
'thd->prepared_statements' pool.
- Without executing the query, return back to client the total - Without executing the query, return back to client the total
number of parameters along with result-set metadata information number of parameters along with result-set metadata information
(if any) (if any) in the following format:
[STMT_ID:4][Columns:2][Param_count:2][Columns meta info][Params meta info]
Prepare-execute: Prepare-execute:
- Server gets the command 'COM_EXECUTE' to execute the - Server gets the command 'COM_EXECUTE' to execute the
previously prepared query. If there is any param markers; then client previously prepared query. If there is any param markers; then client
will send the data in the following format: will send the data in the following format:
[null_bits][types_specified(0/1)][[length][data]][[length][data] .. [length][data]. [COM_EXECUTE:1]
[STMT_ID:4]
[NULL_BITS:(param_count+7)/8)]
[TYPES_SUPPLIED_BY_CLIENT(0/1):1]
[[length]data]
[[length]data] .. [[length]data].
(Note: Except for string/binary types; all other types will not be
supplied with length field)
- Replace the param items with this new data. If it is a first execute - Replace the param items with this new data. If it is a first execute
or types altered by client; then setup the conversion routines. or types altered by client; then setup the conversion routines.
- Execute the query without re-parsing and send back the results - Execute the query without re-parsing and send back the results
to client to client
Long data handling: Long data handling:
- Server gets the long data in pieces with command type 'COM_LONG_DATA'. - Server gets the long data in pieces with command type 'COM_LONG_DATA'.
- The packet recieved will have the format as: - The packet recieved will have the format as:
[COM_LONG_DATA:1][parameter_number:2][type:2][data] [COM_LONG_DATA:1][STMT_ID:4][parameter_number:2][type:2][data]
- Checks if the type is specified by client, and if yes reads the type, - Checks if the type is specified by client, and if yes reads the type,
and stores the data in that format. and stores the data in that format.
- It's up to the client to check for read data ended. The server doesn't - It's up to the client to check for read data ended. The server doesn't
care. care; and also server doesn't notify to the client that it got the
data or not; if there is any error; then during execute; the error
will be returned
***********************************************************************/ ***********************************************************************/
...@@ -238,9 +253,9 @@ static void setup_param_str(Item_param *param, uchar **pos) ...@@ -238,9 +253,9 @@ static void setup_param_str(Item_param *param, uchar **pos)
*pos+=len; *pos+=len;
} }
static void setup_param_functions(Item_param *param, uchar read_pos) static void setup_param_functions(Item_param *param, uchar param_type)
{ {
switch (read_pos) { switch (param_type) {
case FIELD_TYPE_TINY: case FIELD_TYPE_TINY:
param->setup_param_func= setup_param_tiny; param->setup_param_func= setup_param_tiny;
param->item_result_type = INT_RESULT; param->item_result_type = INT_RESULT;
...@@ -286,7 +301,6 @@ static bool setup_params_data(PREP_STMT *stmt) ...@@ -286,7 +301,6 @@ static bool setup_params_data(PREP_STMT *stmt)
uchar *pos=(uchar*) thd->net.read_pos+1+MYSQL_STMT_HEADER; //skip header uchar *pos=(uchar*) thd->net.read_pos+1+MYSQL_STMT_HEADER; //skip header
uchar *read_pos= pos+(stmt->param_count+7) / 8; //skip null bits uchar *read_pos= pos+(stmt->param_count+7) / 8; //skip null bits
ulong param_no;
if (*read_pos++) //types supplied / first execute if (*read_pos++) //types supplied / first execute
{ {
...@@ -304,7 +318,7 @@ static bool setup_params_data(PREP_STMT *stmt) ...@@ -304,7 +318,7 @@ static bool setup_params_data(PREP_STMT *stmt)
} }
param_iterator.rewind(); param_iterator.rewind();
} }
param_no= 0; ulong param_no= 0;
while ((param= (Item_param *)param_iterator++)) while ((param= (Item_param *)param_iterator++))
{ {
if (!param->long_data_supplied) if (!param->long_data_supplied)
...@@ -319,7 +333,6 @@ static bool setup_params_data(PREP_STMT *stmt) ...@@ -319,7 +333,6 @@ static bool setup_params_data(PREP_STMT *stmt)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/* /*
Validates insert fields Validates insert fields
*/ */
...@@ -473,7 +486,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, ...@@ -473,7 +486,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
List<Item> all_fields(fields); List<Item> all_fields(fields);
DBUG_ENTER("mysql_test_select_fields"); DBUG_ENTER("mysql_test_select_fields");
if (!(table = open_ltable(thd,tables,tables->lock_type))) if (!(table = open_ltable(thd,tables,TL_READ)))
DBUG_RETURN(1); DBUG_RETURN(1);
thd->used_tables=0; // Updated by setup_fields thd->used_tables=0; // Updated by setup_fields
...@@ -627,8 +640,8 @@ static bool init_param_items(THD *thd, PREP_STMT *stmt) ...@@ -627,8 +640,8 @@ static bool init_param_items(THD *thd, PREP_STMT *stmt)
{ {
DBUG_PRINT("info",("param: %lx", to)); DBUG_PRINT("info",("param: %lx", to));
} }
return 0;
#endif #endif
return 0;
} }
/* /*
...@@ -671,7 +684,6 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) ...@@ -671,7 +684,6 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
stmt.mem_root= thd->mem_root; stmt.mem_root= thd->mem_root;
tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0); tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0);
thd->mem_root= thd_root; // restore main mem_root thd->mem_root= thd_root; // restore main mem_root
thd->last_prepared_stmt= &stmt;
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
...@@ -722,7 +734,6 @@ void mysql_stmt_execute(THD *thd, char *packet) ...@@ -722,7 +734,6 @@ void mysql_stmt_execute(THD *thd, char *packet)
have re-check on setup_* and other things .. have re-check on setup_* and other things ..
*/ */
mysql_execute_command(stmt->thd); mysql_execute_command(stmt->thd);
thd->last_prepared_stmt= stmt;
if (!(specialflag & SPECIAL_NO_PRIOR)) if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR); my_pthread_setprio(pthread_self(), WAIT_PRIOR);
...@@ -775,11 +786,11 @@ void mysql_stmt_reset(THD *thd, char *packet) ...@@ -775,11 +786,11 @@ void mysql_stmt_reset(THD *thd, char *packet)
Delete a prepared statement from memory Delete a prepared statement from memory
*/ */
void mysql_stmt_close(THD *thd, char *packet) void mysql_stmt_free(THD *thd, char *packet)
{ {
ulong stmt_id= uint4korr(packet); ulong stmt_id= uint4korr(packet);
PREP_STMT *stmt; PREP_STMT *stmt;
DBUG_ENTER("mysql_stmt_close"); DBUG_ENTER("mysql_stmt_free");
if (!(stmt=find_prepared_statement(thd, stmt_id, "close"))) if (!(stmt=find_prepared_statement(thd, stmt_id, "close")))
{ {
......
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