diff --git a/include/mysql.h b/include/mysql.h index a4e4e9fcee4..6ec64220706 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -250,7 +250,6 @@ typedef struct st_mysql LIST *stmts; /* list of all statements */ const struct st_mysql_methods *methods; - struct st_mysql_res *result; void *thd; } MYSQL; @@ -359,6 +358,8 @@ int STDCALL mysql_send_query(MYSQL *mysql, const char *q, unsigned long length); int STDCALL mysql_real_query(MYSQL *mysql, const char *q, unsigned long length); +MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql); + /* perform query on master */ my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q, unsigned long length); @@ -427,6 +428,8 @@ MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result, MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result); MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result); +MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table, + const char *wild); unsigned long STDCALL mysql_escape_string(char *to,const char *from, unsigned long from_length); unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, @@ -538,9 +541,7 @@ typedef struct st_mysql_stmt #define mysql_read_query_result(mysql) (*(mysql)->methods->read_query_result)(mysql) -#define mysql_store_result(mysql) (*(mysql)->methods->store_result)(mysql) #define mysql_use_result(mysql) (*(mysql)->methods->use_result)(mysql) -#define mysql_list_fields(mysql, table, wild) (*(mysql)->methods->list_fields)(mysql, table, wild) typedef struct st_mysql_methods { @@ -552,12 +553,14 @@ typedef struct st_mysql_methods const char *arg, unsigned long arg_length, my_bool skip_check); - MYSQL_RES * (STDCALL *store_result)(MYSQL *mysql); + MYSQL_DATA *(STDCALL *read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields, + uint fields); MYSQL_RES * (STDCALL *use_result)(MYSQL *mysql); void (STDCALL *fetch_lengths)(unsigned long *to, MYSQL_ROW column, uint field_count); - MYSQL_RES * (STDCALL *list_fields)(MYSQL *mysql, const char *table, - const char *wild); + MYSQL_FIELD * (STDCALL *list_fields)(MYSQL *mysql); + my_bool (STDCALL *read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt); + int (STDCALL *stmt_execute)(MYSQL_STMT *stmt); } MYSQL_METHODS; MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query, diff --git a/include/sql_common.h b/include/sql_common.h index 9fea46be298..1f442339c4f 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -28,14 +28,19 @@ my_ulonglong net_field_length_ll(uchar **packet); MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, my_bool default_value, uint server_capabilities); void free_rows(MYSQL_DATA *cur); -MYSQL_DATA *read_rows (MYSQL *mysql,MYSQL_FIELD *fields, - uint field_count); my_bool mysql_autenticate(MYSQL *mysql, const char *passwd); void free_old_query(MYSQL *mysql); void end_server(MYSQL *mysql); my_bool mysql_reconnect(MYSQL *mysql); void mysql_read_default_options(struct st_mysql_options *options, const char *filename,const char *group); +my_bool STDCALL +cli_advanced_command(MYSQL *mysql, enum enum_server_command command, + const char *header, ulong header_length, + const char *arg, ulong arg_length, my_bool skip_check); + +void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode, + const char *sqlstate); #ifdef __cplusplus } #endif diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index 9cafd7182d0..9866c772d3a 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -41,5 +41,17 @@ my_bool send_file_to_server(MYSQL *mysql, const char *filename); #define reset_sigpipe(mysql) #endif -MYSQL_RES * STDCALL cli_list_fields(MYSQL *mysql, const char *table, const char *wild); +void mysql_read_default_options(struct st_mysql_options *options, + const char *filename,const char *group); +MYSQL * STDCALL +cli_mysql_real_connect(MYSQL *mysql,const char *host, const char *user, + const char *passwd, const char *db, + uint port, const char *unix_socket,ulong client_flag); +void STDCALL cli_mysql_close(MYSQL *mysql); + +MYSQL_FIELD * STDCALL cli_list_fields(MYSQL *mysql); +my_bool STDCALL cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt); +MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, + uint fields); +int STDCALL cli_stmt_execute(MYSQL_STMT *stmt); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 68f596c833d..bfa7e4e9357 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -973,6 +973,19 @@ mysql_list_tables(MYSQL *mysql, const char *wild) DBUG_RETURN (mysql_store_result(mysql)); } +MYSQL_FIELD * STDCALL cli_list_fields(MYSQL *mysql) +{ + MYSQL_DATA *query; + if (!(query= cli_read_rows(mysql,(MYSQL_FIELD*) 0, + protocol_41(mysql) ? 8 : 6))) + return NULL; + + mysql->field_count= query->rows; + return unpack_fields(query,&mysql->field_alloc, + query->rows, 1, mysql->server_capabilities); +} + + /************************************************************************** List all fields in a table If wild is given then only the fields matching wild is returned @@ -981,36 +994,29 @@ mysql_list_tables(MYSQL *mysql, const char *wild) **************************************************************************/ MYSQL_RES * STDCALL -cli_list_fields(MYSQL *mysql, const char *table, const char *wild) +mysql_list_fields(MYSQL *mysql, const char *table, const char *wild) { - MYSQL_RES *result; - MYSQL_DATA *query; + MYSQL_RES *result; + MYSQL_FIELD *fields; char buff[257],*end; DBUG_ENTER("mysql_list_fields"); DBUG_PRINT("enter",("table: '%s' wild: '%s'",table,wild ? wild : "")); - LINT_INIT(query); - end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128); + free_old_query(mysql); if (simple_command(mysql,COM_FIELD_LIST,buff,(ulong) (end-buff),1) || - !(query = read_rows(mysql,(MYSQL_FIELD*) 0, - protocol_41(mysql) ? 8 : 6))) + !(fields= (*mysql->methods->list_fields)(mysql))) DBUG_RETURN(NULL); - free_old_query(mysql); if (!(result = (MYSQL_RES *) my_malloc(sizeof(MYSQL_RES), MYF(MY_WME | MY_ZEROFILL)))) - { - free_rows(query); DBUG_RETURN(NULL); - } + result->methods= mysql->methods; result->field_alloc=mysql->field_alloc; mysql->fields=0; - result->field_count = (uint) query->rows; - result->fields= unpack_fields(query,&result->field_alloc, - result->field_count, 1, - mysql->server_capabilities); + result->field_count = mysql->field_count; + result->fields= fields; result->eof=1; DBUG_RETURN(result); } @@ -1031,8 +1037,8 @@ mysql_list_processes(MYSQL *mysql) free_old_query(mysql); pos=(uchar*) mysql->net.read_pos; field_count=(uint) net_field_length(&pos); - if (!(fields = read_rows(mysql,(MYSQL_FIELD*) 0, - protocol_41(mysql) ? 7 : 5))) + if (!(fields = (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*) 0, + protocol_41(mysql) ? 7 : 5))) DBUG_RETURN(NULL); if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0, mysql->server_capabilities))) @@ -1488,8 +1494,8 @@ static void set_stmt_error(MYSQL_STMT * stmt, int errcode, Copy error message to statement handler */ -static void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode, - const char *sqlstate) +void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode, + const char *sqlstate) { DBUG_ENTER("set_stmt_error_msg"); DBUG_PRINT("enter", ("error: %d/%s '%s'", errcode, sqlstate, err)); @@ -1563,7 +1569,7 @@ static my_bool my_realloc_str(NET *net, ulong length) 1 error */ -static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) +my_bool STDCALL cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) { uchar *pos; uint field_count; @@ -1586,25 +1592,25 @@ static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) mysql->server_status|= SERVER_STATUS_IN_TRANS; mysql->extra_info= net_field_length_ll(&pos); - if (!(fields_data= read_rows(mysql, (MYSQL_FIELD*) 0, 7))) + if (!(fields_data= (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,7))) DBUG_RETURN(1); if (!(stmt->fields= unpack_fields(fields_data,&stmt->mem_root, field_count,0, mysql->server_capabilities))) DBUG_RETURN(1); } - if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root, - sizeof(MYSQL_BIND)* - (param_count + - field_count)))) - { - set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); - DBUG_RETURN(0); - } - stmt->bind= (stmt->params + param_count); stmt->field_count= (uint) field_count; stmt->param_count= (ulong) param_count; - mysql->status= MYSQL_STATUS_READY; + if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root, + sizeof(MYSQL_BIND)* + (stmt->param_count + + stmt->field_count)))) + { + set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); + DBUG_RETURN(1); + } + stmt->bind= stmt->params + stmt->param_count; + DBUG_RETURN(0); } @@ -1648,14 +1654,16 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length) } init_alloc_root(&stmt->mem_root,8192,0); - if (read_prepare_result(mysql, stmt)) + if ((*mysql->methods->read_prepare_result)(mysql, stmt)) { stmt_close(stmt, 1); DBUG_RETURN(0); } + stmt->state= MY_ST_PREPARE; stmt->mysql= mysql; mysql->stmts= list_add(mysql->stmts, &stmt->list); + mysql->status= MYSQL_STATUS_READY; stmt->list.data= stmt; DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count)); DBUG_RETURN(stmt); @@ -1971,36 +1979,21 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length) mysql->last_used_con= mysql; int4store(buff, stmt->stmt_id); /* Send stmt id to server */ - if ((*mysql->methods->advanced_command)(mysql, COM_EXECUTE, buff, - MYSQL_STMT_HEADER, packet, - length, 1) || + if (cli_advanced_command(mysql, COM_EXECUTE, buff, + MYSQL_STMT_HEADER, packet, + length, 1) || mysql_read_query_result(mysql)) { set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); DBUG_RETURN(1); } - stmt->state= MY_ST_EXECUTE; - mysql_free_result(stmt->result); - stmt->result= (MYSQL_RES *)0; - stmt->result_buffered= 0; - stmt->current_row= 0; DBUG_RETURN(0); } - -/* - Execute the prepare query -*/ - -int STDCALL mysql_execute(MYSQL_STMT *stmt) +int STDCALL cli_stmt_execute(MYSQL_STMT *stmt) { - DBUG_ENTER("mysql_execute"); + DBUG_ENTER("cli_stmt_execute"); - if (stmt->state == MY_ST_UNKNOWN) - { - set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); - DBUG_RETURN(1); - } if (stmt->param_count) { NET *net= &stmt->mysql->net; @@ -2061,6 +2054,30 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt) DBUG_RETURN((int) execute(stmt,0,0)); } +/* + Execute the prepare query +*/ + +int STDCALL mysql_execute(MYSQL_STMT *stmt) +{ + DBUG_ENTER("mysql_execute"); + + if (stmt->state == MY_ST_UNKNOWN) + { + set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); + DBUG_RETURN(1); + } + if ((*stmt->mysql->methods->stmt_execute)(stmt)) + DBUG_RETURN(1); + + stmt->state= MY_ST_EXECUTE; + mysql_free_result(stmt->result); + stmt->result= (MYSQL_RES *)0; + stmt->result_buffered= 0; + stmt->current_row= 0; + DBUG_RETURN(0); +} + /* Return total parameters count in the statement diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h index dfc06e38ab2..833cc1b1f80 100644 --- a/libmysqld/embedded_priv.h +++ b/libmysqld/embedded_priv.h @@ -26,4 +26,7 @@ C_MODE_START extern void lib_connection_phase(NET *net, int phase); extern void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db); extern void *create_embedded_thd(int client_flag, char *db); +extern MYSQL_METHODS embedded_methods; +void free_old_query(MYSQL *mysql); +extern my_bool server_inited; C_MODE_END diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index c894621be54..16a5b6b769c 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -50,7 +50,7 @@ static bool check_user(THD *thd, enum_server_command command, char * get_mysql_home(){ return mysql_home;}; char * get_mysql_real_data_home(){ return mysql_real_data_home;}; -my_bool STDCALL +static my_bool STDCALL emb_advanced_command(MYSQL *mysql, enum enum_server_command command, const char *header, ulong header_length, const char *arg, ulong arg_length, my_bool skip_check) @@ -94,6 +94,116 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, return result; } +static MYSQL_DATA * STDCALL +emb_read_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields __attribute__((unused)), + uint fields __attribute__((unused))) +{ + MYSQL_DATA *result= ((THD*)mysql->thd)->data; + if (!result) + { + if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), + MYF(MY_WME | MY_ZEROFILL)))) + { + NET *net = &mysql->net; + net->last_errno=CR_OUT_OF_MEMORY; + strmov(net->sqlstate, unknown_sqlstate); + strmov(net->last_error,ER(net->last_errno)); + return NULL; + } + return result; + } + *result->prev_ptr= NULL; + ((THD*)mysql->thd)->data= NULL; + return result; +} + +static MYSQL_FIELD * STDCALL emb_list_fields(MYSQL *mysql) +{ + return mysql->fields; +} + +static my_bool STDCALL emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) +{ + THD *thd= (THD*)mysql->thd; + stmt->stmt_id= thd->client_stmt_id; + stmt->param_count= thd->client_param_count; + stmt->field_count= mysql->field_count; + + if (stmt->field_count != 0) + { + if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) + mysql->server_status|= SERVER_STATUS_IN_TRANS; + + stmt->fields= mysql->fields; + stmt->mem_root= mysql->field_alloc; + } + + if (!(stmt->bind= + (MYSQL_BIND *) alloc_root(&stmt->mem_root, + sizeof(MYSQL_BIND)*stmt->field_count))) + { + set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); + return 1; + } + stmt->params= NULL; // we don't need parameter's buffer in embedded library + + return 0; +} + +/************************************************************************** + Get column lengths of the current row + If one uses mysql_use_result, res->lengths contains the length information, + else the lengths are calculated from the offset between pointers. +**************************************************************************/ + +static void STDCALL emb_fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count) +{ + MYSQL_ROW end; + + for (end=column + field_count; column != end ; column++,to++) + *to= *column ? *(uint *)((*column) - sizeof(uint)) : 0; +} + +static my_bool STDCALL emb_mysql_read_query_result(MYSQL *mysql) +{ + if (mysql->net.last_errno) + return -1; + + if (mysql->field_count) + mysql->status=MYSQL_STATUS_GET_RESULT; + + return 0; +} + +static int STDCALL emb_stmt_execute(MYSQL_STMT *stmt) +{ + DBUG_ENTER("emb_stmt_execute"); + THD *thd= (THD*)stmt->mysql->thd; + thd->client_param_count= stmt->param_count; + thd->client_parameters= stmt->params; + if (emb_advanced_command(stmt->mysql, COM_EXECUTE,0,0, + (const char*)&stmt->stmt_id,sizeof(stmt->stmt_id),1) + || emb_mysql_read_query_result(stmt->mysql)) + { + NET *net= &stmt->mysql->net; + set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + +MYSQL_METHODS embedded_methods= +{ + emb_mysql_read_query_result, + emb_advanced_command, + emb_read_rows, + mysql_store_result, + emb_fetch_lengths, + emb_list_fields, + emb_read_prepare_result, + emb_stmt_execute +}; + C_MODE_END void THD::clear_error() @@ -334,6 +444,8 @@ void *create_embedded_thd(int client_flag, char *db) thd->master_access= ~NO_ACCESS; thd->net.query_cache_query= 0; + thd->data= 0; + return thd; } @@ -343,35 +455,29 @@ bool Protocol::send_fields(List *list, uint flag) { List_iterator_fast it(*list); Item *item; - MYSQL_FIELD *field, *client_field; + MYSQL_FIELD *client_field; MYSQL *mysql= thd->mysql; + MEM_ROOT *field_alloc; DBUG_ENTER("send_fields"); field_count= list->elements; - if (!(mysql->result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+ - sizeof(ulong) * (field_count + 1), - MYF(MY_WME | MY_ZEROFILL)))) - goto err; - mysql->result->lengths= (ulong *)(mysql->result + 1); - - mysql->field_count=field_count; - alloc= &mysql->field_alloc; - field= (MYSQL_FIELD *)alloc_root(alloc, sizeof(MYSQL_FIELD) * field_count); - if (!field) + field_alloc= &mysql->field_alloc; + if (!(client_field= thd->mysql->fields= + (MYSQL_FIELD *)alloc_root(field_alloc, + sizeof(MYSQL_FIELD) * field_count))) goto err; - client_field= field; while ((item= it++)) { Send_field server_field; item->make_field(&server_field); - client_field->db= strdup_root(alloc, server_field.db_name); - client_field->table= strdup_root(alloc, server_field.table_name); - client_field->name= strdup_root(alloc, server_field.col_name); - client_field->org_table= strdup_root(alloc, server_field.org_table_name); - client_field->org_name= strdup_root(alloc, server_field.org_col_name); + client_field->db= strdup_root(field_alloc, server_field.db_name); + client_field->table= strdup_root(field_alloc, server_field.table_name); + client_field->name= strdup_root(field_alloc, server_field.col_name); + client_field->org_table= strdup_root(field_alloc, server_field.org_table_name); + client_field->org_name= strdup_root(field_alloc, server_field.org_col_name); client_field->length= server_field.length; client_field->type= server_field.type; client_field->flags= server_field.flags; @@ -392,31 +498,16 @@ bool Protocol::send_fields(List *list, uint flag) String tmp(buff, sizeof(buff), default_charset_info), *res; if (!(res=item->val_str(&tmp))) - client_field->def= strdup_root(alloc, ""); + client_field->def= strdup_root(field_alloc, ""); else - client_field->def= strdup_root(alloc, tmp.ptr()); + client_field->def= strdup_root(field_alloc, tmp.ptr()); } else client_field->def=0; client_field->max_length= 0; ++client_field; } - mysql->result->fields = field; - - if (!(mysql->result->data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), - MYF(MY_WME | MY_ZEROFILL)))) - goto err; - - init_alloc_root(&mysql->result->data->alloc,8192,0); /* Assume rowlength < 8192 */ - mysql->result->data->alloc.min_malloc=sizeof(MYSQL_ROWS); - mysql->result->data->rows=0; - mysql->result->data->fields=field_count; - mysql->result->field_count=field_count; - mysql->result->data->prev_ptr= &mysql->result->data->data; - - mysql->result->field_alloc= mysql->field_alloc; - mysql->result->current_field=0; - mysql->result->current_row=0; + thd->mysql->field_count= field_count; DBUG_RETURN(prepare_for_send(list)); err: @@ -456,13 +547,27 @@ send_eof(THD *thd, bool no_flush) void Protocol_simple::prepare_for_resend() { - MYSQL_ROWS *cur; - MYSQL_DATA *result= thd->mysql->result->data; + MYSQL_ROWS *cur; + MYSQL_DATA *data= thd->data; DBUG_ENTER("send_data"); - alloc= &result->alloc; - result->rows++; + if (!data) + { + if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), + MYF(MY_WME | MY_ZEROFILL)))) + goto err; + + alloc= &data->alloc; + init_alloc_root(alloc,8192,0); /* Assume rowlength < 8192 */ + alloc->min_malloc=sizeof(MYSQL_ROWS); + data->rows=0; + data->fields=field_count; + data->prev_ptr= &data->data; + thd->data= data; + } + + data->rows++; if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *)))) { my_error(ER_OUT_OF_RESOURCES,MYF(0)); @@ -470,11 +575,11 @@ void Protocol_simple::prepare_for_resend() } cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS)); - *result->prev_ptr= cur; - result->prev_ptr= &cur->next; + *data->prev_ptr= cur; + data->prev_ptr= &cur->next; next_field=cur->data; - next_mysql_field= thd->mysql->result->fields; - + next_mysql_field= thd->mysql->fields; +err: DBUG_VOID_RETURN; } diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index 56be78e3509..96e77aa340f 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -24,6 +24,7 @@ #include #include #include +#include "client_settings.h" #ifdef HAVE_PWD_H #include #endif @@ -58,29 +59,11 @@ #define closesocket(A) close(A) #endif -void free_old_query(MYSQL *mysql); -my_bool STDCALL -emb_advanced_command(MYSQL *mysql, enum enum_server_command command, - const char *header, ulong header_length, - const char *arg, ulong arg_length, my_bool skip_check); - -/* From client.c */ -void mysql_read_default_options(struct st_mysql_options *options, - const char *filename,const char *group); -MYSQL * STDCALL -cli_mysql_real_connect(MYSQL *mysql,const char *host, const char *user, - const char *passwd, const char *db, - uint port, const char *unix_socket,ulong client_flag); - -void STDCALL cli_mysql_close(MYSQL *mysql); - #ifdef HAVE_GETPWUID struct passwd *getpwuid(uid_t); char* getlogin(void); #endif -extern char server_inited; - #ifdef __WIN__ static my_bool is_NT(void) { @@ -165,73 +148,6 @@ static inline int mysql_init_charset(MYSQL *mysql) return 0; } -/************************************************************************** - Get column lengths of the current row - If one uses mysql_use_result, res->lengths contains the length information, - else the lengths are calculated from the offset between pointers. -**************************************************************************/ - -static void STDCALL emb_fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count) -{ - MYSQL_ROW end; - - for (end=column + field_count; column != end ; column++,to++) - *to= *column ? *(uint *)((*column) - sizeof(uint)) : 0; -} - -/************************************************************************** - List all fields in a table - If wild is given then only the fields matching wild is returned - Instead of this use query: - show fields in 'table' like "wild" -**************************************************************************/ - -static MYSQL_RES * STDCALL -emb_list_fields(MYSQL *mysql, const char *table, const char *wild) -{ - MYSQL_RES *result; - MYSQL_DATA *query; - char buff[257],*end; - DBUG_ENTER("mysql_list_fields"); - DBUG_PRINT("enter",("table: '%s' wild: '%s'",table,wild ? wild : "")); - - LINT_INIT(query); - - end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128); - if (simple_command(mysql,COM_FIELD_LIST,buff,(ulong) (end-buff),1)) - DBUG_RETURN(NULL); - - result= mysql->result; - if (!result) - return 0; - - result->methods= mysql->methods; - result->eof=1; - - DBUG_RETURN(result); -} - - - -/* -** Note that the mysql argument must be initialized with mysql_init() -** before calling mysql_real_connect ! -*/ - -static my_bool STDCALL emb_mysql_read_query_result(MYSQL *mysql); -static MYSQL_RES * STDCALL emb_mysql_store_result(MYSQL *mysql); -static MYSQL_RES * STDCALL emb_mysql_use_result(MYSQL *mysql); - -static MYSQL_METHODS embedded_methods= -{ - emb_mysql_read_query_result, - emb_advanced_command, - emb_mysql_store_result, - emb_mysql_use_result, - emb_fetch_lengths, - emb_list_fields -}; - MYSQL * STDCALL mysql_real_connect(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, @@ -379,58 +295,3 @@ void STDCALL mysql_close(MYSQL *mysql) DBUG_VOID_RETURN; } -static my_bool STDCALL emb_mysql_read_query_result(MYSQL *mysql) -{ - if (mysql->net.last_errno) - return -1; - - if (mysql->field_count) - { - mysql->status=MYSQL_STATUS_GET_RESULT; - mysql->affected_rows= mysql->result->row_count= mysql->result->data->rows; - mysql->result->data_cursor= mysql->result->data->data; - } - - return 0; -} - -/************************************************************************** -** Alloc result struct for buffered results. All rows are read to buffer. -** mysql_data_seek may be used. -**************************************************************************/ -static MYSQL_RES * STDCALL emb_mysql_store_result(MYSQL *mysql) -{ - MYSQL_RES *result= mysql->result; - if (!result) - return 0; - - result->methods= mysql->methods; - mysql->result= NULL; - *result->data->prev_ptr= 0; - result->eof= 1; - result->lengths= (ulong*)(result + 1); - mysql->affected_rows= result->row_count= result->data->rows; - result->data_cursor= result->data->data; - - mysql->status=MYSQL_STATUS_READY; /* server is ready */ - return result; -} - -/************************************************************************** -** Alloc struct for use with unbuffered reads. Data is fetched by domand -** when calling to mysql_fetch_row. -** mysql_data_seek is a noop. -** -** No other queries may be specified with the same MYSQL handle. -** There shouldn't be much processing per row because mysql server shouldn't -** have to wait for the client (and will not wait more than 30 sec/packet). -**************************************************************************/ - -static MYSQL_RES * STDCALL emb_mysql_use_result(MYSQL *mysql) -{ - DBUG_ENTER("mysql_use_result"); - if (mysql->options.separate_thread) - DBUG_RETURN(0); - - DBUG_RETURN(emb_mysql_store_result(mysql)); -} diff --git a/sql-common/client.c b/sql-common/client.c index 6372adb8550..73fe9e4663c 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -636,10 +636,10 @@ void free_rows(MYSQL_DATA *cur) } } -static my_bool STDCALL +my_bool STDCALL cli_advanced_command(MYSQL *mysql, enum enum_server_command command, - const char *header, ulong header_length, - const char *arg, ulong arg_length, my_bool skip_check) + const char *header, ulong header_length, + const char *arg, ulong arg_length, my_bool skip_check) { NET *net= &mysql->net; my_bool result= 1; @@ -1139,8 +1139,8 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, /* Read all rows (fields or data) from server */ -MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - uint fields) +MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, + uint fields) { uint field; ulong pkt_len; @@ -1150,7 +1150,7 @@ MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, MYSQL_DATA *result; MYSQL_ROWS **prev_ptr,*cur; NET *net = &mysql->net; - DBUG_ENTER("read_rows"); + DBUG_ENTER("cli_read_rows"); if ((pkt_len= net_safe_read(mysql)) == packet_error) DBUG_RETURN(0); @@ -1397,17 +1397,18 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) */ static my_bool STDCALL cli_mysql_read_query_result(MYSQL *mysql); -static MYSQL_RES * STDCALL cli_mysql_store_result(MYSQL *mysql); static MYSQL_RES * STDCALL cli_mysql_use_result(MYSQL *mysql); static MYSQL_METHODS client_methods= { cli_mysql_read_query_result, cli_advanced_command, - cli_mysql_store_result, + cli_read_rows, cli_mysql_use_result, cli_fetch_lengths, - cli_list_fields + cli_list_fields, + cli_read_prepare_result, + cli_stmt_execute }; MYSQL * STDCALL @@ -2264,7 +2265,8 @@ get_info: mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */ - if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0,protocol_41(mysql) ? 7 : 5))) + if (!(fields=(*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0, + protocol_41(mysql) ? 7 : 5))) DBUG_RETURN(1); if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc, (uint) field_count,0, @@ -2326,7 +2328,7 @@ mysql_real_query(MYSQL *mysql, const char *query, ulong length) mysql_data_seek may be used. **************************************************************************/ -static MYSQL_RES * STDCALL cli_mysql_store_result(MYSQL *mysql) +MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql) { MYSQL_RES *result; DBUG_ENTER("mysql_store_result"); @@ -2355,7 +2357,8 @@ static MYSQL_RES * STDCALL cli_mysql_store_result(MYSQL *mysql) result->methods= mysql->methods; result->eof=1; /* Marker for buffered */ result->lengths=(ulong*) (result+1); - if (!(result->data=read_rows(mysql,mysql->fields,mysql->field_count))) + if (!(result->data= + (*mysql->methods->read_rows)(mysql,mysql->fields,mysql->field_count))) { my_free((gptr) result,MYF(0)); DBUG_RETURN(0); diff --git a/sql/client_settings.h b/sql/client_settings.h index e31a75bdddd..266f6807a36 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -33,4 +33,6 @@ #undef _CUSTOMCONFIG_ #define cli_list_fields NULL +#define cli_read_prepare_result NULL +#define cli_stmt_execute NULL diff --git a/sql/sql_class.h b/sql/sql_class.h index e0358fc25e9..da6e47e4ac7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -422,6 +422,9 @@ class THD :public ilink public: #ifdef EMBEDDED_LIBRARY struct st_mysql *mysql; + struct st_mysql_data *data; + unsigned long client_stmt_id; + unsigned long client_param_count; #endif NET net; // client connection descriptor LEX lex; // parse tree descriptor diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 4abbbcaff1f..edbcdce4e43 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -142,6 +142,7 @@ void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used) Send prepared stmt info to client after prepare */ +#ifndef EMBEDDED_LIBRARY static bool send_prep_stmt(PREP_STMT *stmt, uint columns) { NET *net=&stmt->thd->net; @@ -150,14 +151,21 @@ static bool send_prep_stmt(PREP_STMT *stmt, uint columns) int4store(buff+1, stmt->stmt_id); int2store(buff+5, columns); int2store(buff+7, stmt->param_count); -#ifndef EMBEDDED_LIBRARY /* This should be fixed to work with prepared statements */ return (my_net_write(net, buff, sizeof(buff)) || net_flush(net)); -#else - return true; -#endif } +#else +static bool send_prep_stmt(PREP_STMT *stmt, uint columns __attribute__((unused))) +{ + THD *thd= stmt->thd; + + thd->client_stmt_id= stmt->stmt_id; + thd->client_param_count= stmt->param_count; + + return 0; +} +#endif /*!EMBEDDED_LIBRAYR*/ /* Send information about all item parameters