diff options
author | venu@myvenu.com <> | 2003-01-03 03:52:53 -0800 |
---|---|---|
committer | venu@myvenu.com <> | 2003-01-03 03:52:53 -0800 |
commit | 5c4b7a2e9623b6a9ceb2294d9b8ddc5c4bdba762 (patch) | |
tree | 50be559285aec39876c9ff87a9e77e4a437fa64c | |
parent | d5631610db5fe99f26c15e73624eea3e3ea1708d (diff) | |
download | mariadb-git-5c4b7a2e9623b6a9ceb2294d9b8ddc5c4bdba762.tar.gz |
Binary protocol changes (to monty)
-rw-r--r-- | libmysql/libmysql.c | 165 | ||||
-rw-r--r-- | sql/field.cc | 35 | ||||
-rw-r--r-- | sql/field.h | 6 | ||||
-rw-r--r-- | sql/protocol.cc | 37 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 34 |
5 files changed, 173 insertions, 104 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index d0fc83bbeb3..d6d2dca9af0 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1739,6 +1739,7 @@ static void mysql_once_init() #define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME)) +#ifdef HAVE_OPENSSL my_bool STDCALL mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , const char *key __attribute__((unused)), @@ -1747,15 +1748,14 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , const char *capath __attribute__((unused)), const char *cipher __attribute__((unused))) { -#ifdef HAVE_OPENSSL mysql->options.ssl_key= strdup_if_not_null(key); mysql->options.ssl_cert= strdup_if_not_null(cert); mysql->options.ssl_ca= strdup_if_not_null(ca); mysql->options.ssl_capath= strdup_if_not_null(capath); mysql->options.ssl_cipher= strdup_if_not_null(cipher); -#endif return 0; } +#endif /************************************************************************** @@ -1763,10 +1763,10 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , NB! Errors are not reported until you do mysql_real_connect. **************************************************************************/ +#ifdef HAVE_OPENSLL static void mysql_ssl_free(MYSQL *mysql __attribute__((unused))) { -#ifdef HAVE_OPENSLL my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); @@ -1780,8 +1780,8 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) mysql->options.ssl_cipher= 0; mysql->options.use_ssl = FALSE; mysql->connector_fd = 0; -#endif /* HAVE_OPENSLL */ } +#endif /* HAVE_OPENSLL */ /************************************************************************** Connect to sql server @@ -3824,12 +3824,13 @@ static my_bool my_realloc_str(NET *net, ulong length) 1 error */ -static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) +static my_bool read_prepare_result(MYSQL_STMT *stmt) { uchar *pos; uint field_count; + ulong length, param_count; MYSQL_DATA *fields_data; - ulong length; + MYSQL *mysql= stmt->mysql; DBUG_ENTER("read_prepare_result"); mysql= mysql->last_used_con; @@ -3837,9 +3838,9 @@ static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) DBUG_RETURN(1); pos=(uchar*) mysql->net.read_pos; - stmt->stmt_id= uint4korr(pos); pos+=4; - field_count= uint2korr(pos); pos+=2; - stmt->param_count=uint2korr(pos); pos+=2; + stmt->stmt_id= uint4korr(pos); pos+=4; + field_count= uint2korr(pos); pos+=2; + param_count= uint2korr(pos); pos+=2; if (field_count != 0) { @@ -3862,9 +3863,10 @@ static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) set_stmt_error(stmt, CR_OUT_OF_MEMORY); DBUG_RETURN(0); } - stmt->bind= (stmt->params + stmt->param_count); - stmt->field_count= (uint) field_count; - mysql->status= MYSQL_STATUS_READY; + stmt->bind= (stmt->params + stmt->param_count); + stmt->field_count= (uint) field_count; + stmt->param_count= (ulong) param_count; + stmt->mysql->status= MYSQL_STATUS_READY; DBUG_RETURN(0); } @@ -3908,13 +3910,13 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length) } init_alloc_root(&stmt->mem_root,8192,0); - if (read_prepare_result(mysql, stmt)) + stmt->mysql= mysql; + if (read_prepare_result(stmt)) { stmt_close(stmt, 1); DBUG_RETURN(0); } stmt->state= MY_ST_PREPARE; - stmt->mysql= mysql; mysql->stmts= list_add(mysql->stmts, &stmt->list); stmt->list.data= stmt; DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count)); @@ -3925,18 +3927,41 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length) /* Returns prepared meta information in the form of resultset to client. +TODO : Return param information also */ +MYSQL_RES *prepare_result(MYSQL_FIELD *fields, unsigned long count) +{ + MYSQL_RES *result; + + if (!count || !fields) + return 0; + + if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+ + sizeof(ulong)*count, + MYF(MY_WME | MY_ZEROFILL)))) + return 0; + + result->eof=1; /* Marker for buffered */ + result->fields= fields; + result->field_count= count; + return result; +} + MYSQL_RES * STDCALL mysql_prepare_result(MYSQL_STMT *stmt) { MYSQL_RES *result; DBUG_ENTER("mysql_prepare_result"); - - if (!stmt->fields) + + if (!stmt->field_count || !stmt->fields) DBUG_RETURN(0); - result= &stmt->tmp_result; - bzero((char*) result, sizeof(MYSQL_RES)); + + if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+ + sizeof(ulong)*stmt->field_count, + MYF(MY_WME | MY_ZEROFILL)))) + return 0; + result->eof=1; /* Marker for buffered */ result->fields= stmt->fields; result->field_count= stmt->field_count; @@ -4088,12 +4113,13 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param) DBUG_ENTER("store_param"); DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %d", param->buffer_type, param->buffer ? param->buffer : "0", *param->length)); - - if (param->is_null || param->buffer_type == MYSQL_TYPE_NULL) + + if (param->is_null || param->buffer_type == MYSQL_TYPE_NULL || + *param->length == MYSQL_NULL_DATA) store_param_null(net, param); else { - /* Allocate for worst case (long string) */ + /* Allocate for worst case (long string) */ if ((my_realloc_str(net, 9 + *param->length))) DBUG_RETURN(1); (*param->store_param_func)(net, param); @@ -4101,7 +4127,6 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param) DBUG_RETURN(0); } - /* Send the prepare query to server for execution */ @@ -4125,13 +4150,6 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length) } stmt->state= MY_ST_EXECUTE; mysql_free_result(stmt->result); -#if USED_IN_FETCH - if (stmt->res_buffers) /* Result buffers exists, cache results */ - { - mysql_free_result(stmt->result); - stmt->result= mysql_store_result(mysql); - } - #endif DBUG_RETURN(0); } @@ -4420,21 +4438,21 @@ static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row) static void fetch_result_short(MYSQL_BIND *param, uchar **row) { - short value= *(short *)row; - int2store(param->buffer, value); + short value= (short)**row; + int2store(param->buffer, value); *row+=2; } static void fetch_result_int32(MYSQL_BIND *param, uchar **row) { - int32 value= *(int32 *)row; + int32 value= (int32)**row; int4store(param->buffer, value); *row+=4; } static void fetch_result_int64(MYSQL_BIND *param, uchar **row) { - longlong value= *(longlong *)row; + longlong value= (longlong)**row; int8store(param->buffer, value); *row+=8; } @@ -4443,7 +4461,7 @@ static void fetch_result_float(MYSQL_BIND *param, uchar **row) { float value; float4get(value,*row); - float4store(param->buffer, *row); + float4store(param->buffer, value); *row+=4; } @@ -4459,6 +4477,7 @@ static void fetch_result_str(MYSQL_BIND *param, uchar **row) { ulong length= net_field_length(row); memcpy(param->buffer, (char *)*row, length); + *(param->buffer+length)= '\0'; /* do we need this for all cases.. I doubt */ *param->length= length; *row+=length; } @@ -4537,41 +4556,46 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) Fetch row data to bind buffers */ -static my_bool -stmt_fetch_row(MYSQL_STMT *stmt, uchar **row) +static void +stmt_fetch_row(MYSQL_STMT *stmt, uchar *row) { MYSQL_BIND *bind, *end; - uchar *null_ptr= (uchar*) *row, bit; - - row+= (stmt->field_count+9)/8; - bit= 4; /* First 2 bits are reserved */ - + MYSQL_FIELD *field; + uchar *null_ptr, bit; + + null_ptr= row; + row+= (stmt->field_count+9)/8; /* skip null bits */ + bit= 4; /* first 2 bits are reserved */ + /* Copy complete row to application buffers */ - for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count; - bind < end; - bind++) - { + for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count, + field= stmt->fields; + bind < end && field; + bind++, field++) + { if (*null_ptr & bit) - bind->is_null= 1; + *bind->length= MYSQL_NULL_DATA; else - { - bind->is_null= 0; - (*bind->fetch_result)(bind, row); - } + /* TODO: Add conversion routines code here */ + (*bind->fetch_result)(bind, &row); if (! (bit<<=1) & 255) { - bit=1; /* To next byte */ + bit= 1; /* To next byte */ null_ptr++; } } - return 0; } static int read_binary_data(MYSQL *mysql) -{ +{ + /* TODO : Changes needed based on logic of use_result/store_result + Currently by default it is use_result. In case of + store_result, the data packet must point to already + read data. + */ if (packet_error == net_safe_read(mysql)) return -1; - if (mysql->net.read_pos[0]) + if (mysql->net.read_pos[0] == 254) return 1; /* End of data */ return 0; } @@ -4584,29 +4608,24 @@ static int read_binary_data(MYSQL *mysql) int STDCALL mysql_fetch(MYSQL_STMT *stmt) { MYSQL *mysql= stmt->mysql; + int res; DBUG_ENTER("mysql_fetch"); - if (stmt->res_buffers) + if (!(res= read_binary_data(mysql))) { - int res; - if (!(res= read_binary_data(mysql))) - { - if (stmt->res_buffers) - DBUG_RETURN((int) stmt_fetch_row(stmt,(uchar **) &mysql->net.read_pos+1)); - DBUG_RETURN(0); - } - DBUG_PRINT("info", ("end of data")); - mysql->status= MYSQL_STATUS_READY; - - if (res < 0) /* Network error */ - { - set_stmt_errmsg(stmt,(char *)mysql->net.last_error, - mysql->net.last_errno); - DBUG_RETURN(MYSQL_STATUS_ERROR); - } - DBUG_RETURN(MYSQL_NO_DATA); /* no more data */ + if (stmt->res_buffers) + stmt_fetch_row(stmt, mysql->net.read_pos+1); + DBUG_RETURN(0); + } + mysql->status= MYSQL_STATUS_READY; + if (res < 0) /* Network error */ + { + set_stmt_errmsg(stmt,(char *)mysql->net.last_error, + mysql->net.last_errno); + DBUG_RETURN(MYSQL_STATUS_ERROR); } - DBUG_RETURN(0); //?? do we need to set MYSQL_STATUS_READY ? + DBUG_PRINT("info", ("end of data")); + DBUG_RETURN(MYSQL_NO_DATA); /* no more data */ } diff --git a/sql/field.cc b/sql/field.cc index 9acf2e14829..c8e71e8060b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2599,7 +2599,7 @@ String *Field_double::val_str(String *val_buffer, bool Field_double::send_binary(Protocol *protocol) { - return protocol->store((float) Field_double::val_real(), dec, (String*) 0); + return protocol->store((double) Field_double::val_real(), dec, (String*) 0); } @@ -3169,7 +3169,7 @@ bool Field_time::send_binary(Protocol *protocol) Field_time::get_time(&tm); tm.day= tm.hour/3600; // Move hours to days tm.hour-= tm.day*3600; - return protocol->store(&tm); + return protocol->store_time(&tm); } @@ -3254,6 +3254,13 @@ int Field_year::store(longlong nr) return 0; } +bool Field_year::send_binary(Protocol *protocol) +{ + ulonglong tmp= Field_year::val_int(); + TIME tm; + tm.year= (uint32) tmp; + return protocol->store_date(&tm); +} double Field_year::val_real(void) { @@ -3371,6 +3378,16 @@ int Field_date::store(longlong nr) return error; } +bool Field_date::send_binary(Protocol *protocol) +{ + longlong tmp= Field_date::val_int(); + TIME tm; + tm.year= (uint32) tmp/10000L % 10000; + tm.month= (uint32) tmp/100 % 100; + tm.day= (uint32) tmp % 100; + return protocol->store_date(&tm); +} + double Field_date::val_real(void) { @@ -3544,7 +3561,12 @@ void Field_newdate::store_time(TIME *ltime,timestamp_type type) int3store(ptr,tmp); } - +bool Field_newdate::send_binary(Protocol *protocol) +{ + TIME tm; + Field_newdate::get_date(&tm,0); + return protocol->store_date(&tm); +} double Field_newdate::val_real(void) { @@ -3705,6 +3727,13 @@ void Field_datetime::store_time(TIME *ltime,timestamp_type type) longlongstore(ptr,tmp); } +bool Field_datetime::send_binary(Protocol *protocol) +{ + TIME tm; + Field_datetime::get_date(&tm, 1); + return protocol->store(&tm); +} + double Field_datetime::val_real(void) { diff --git a/sql/field.h b/sql/field.h index 40578d19c82..67bae7302f9 100644 --- a/sql/field.h +++ b/sql/field.h @@ -166,7 +166,7 @@ public: ptr-=row_offset; return tmp; } - bool send_binary(Protocol *protocol); + virtual bool send_binary(Protocol *protocol); virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0) { uint32 length=pack_length(); @@ -792,7 +792,6 @@ public: double val_real(void); longlong val_int(void); String *val_str(String*,String *); - bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); void sql_type(String &str) const; @@ -833,7 +832,6 @@ public: double val_real(void); longlong val_int(void); String *val_str(String*,String *); - bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type); @@ -876,7 +874,6 @@ public: double val_real(void); longlong val_int(void); String *val_str(String*,String *); - bool send_binary(Protocol *protocol); int cmp(const char *,const char*); int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length); int cmp_offset(uint offset); @@ -982,7 +979,6 @@ public: double val_real(void); longlong val_int(void); String *val_str(String*,String *); - bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return (uint32) packlength; } diff --git a/sql/protocol.cc b/sql/protocol.cc index 9d7dc66b452..63bca9b70b3 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -616,7 +616,7 @@ bool Protocol_simple::store_null() field_pos++; #endif char buff[1]; - buff[0]= 251; + buff[0]= (char)251; return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC); } @@ -774,13 +774,27 @@ bool Protocol_simple::store_time(TIME *tm) /**************************************************************************** Functions to handle the binary protocol used with prepared statements + + Data format: + + [ok:1] <-- reserved ok packet + [null_field:(field_count+7+2)/8] <-- reserved to send null data. The size is + calculated using: + bit_fields= (field_count+7+2)/8; + 2 bits are reserved + [[length]data] <-- data field (the length applies only for + string/binary/time/timestamp fields and + rest of them are not sent as they have + the default length that client understands + based on the field type + [..]..[[length]data] <-- data ****************************************************************************/ bool Protocol_prep::prepare_for_send(List<Item> *item_list) { - field_count=item_list->elements; - bit_fields= (field_count+3)/8; - if (packet->alloc(bit_fields)) + field_count= item_list->elements; + bit_fields= (field_count+9)/8; + if (packet->alloc(bit_fields+1)) return 1; /* prepare_for_resend will be called after this one */ return 0; @@ -789,9 +803,8 @@ bool Protocol_prep::prepare_for_send(List<Item> *item_list) void Protocol_prep::prepare_for_resend() { - packet->length(bit_fields); - bzero((char*) packet->ptr()+1, bit_fields-1); - packet[0]=1; // Marker for ok packet + packet->length(bit_fields+1); + bzero((char*) packet->ptr(), 1+bit_fields); field_pos=0; } @@ -813,7 +826,7 @@ bool Protocol_prep::store(const char *from,uint length) bool Protocol_prep::store_null() { - uint offset=(field_pos+2)/8, bit= (1 << ((field_pos+2) & 7)); + uint offset= (field_pos+2)/8+1, bit= (1 << ((field_pos+2) & 7)); /* Room for this as it's allocated in prepare_for_send */ char *to= (char*) packet->ptr()+offset; *to= (char) ((uchar) *to | (uchar) bit); @@ -926,6 +939,7 @@ bool Protocol_prep::store(TIME *tm) { #ifndef DEBUG_OFF DBUG_ASSERT(field_types == 0 || + field_types[field_pos] == MYSQL_TYPE_YEAR || field_types[field_pos] == MYSQL_TYPE_DATETIME || field_types[field_pos] == MYSQL_TYPE_DATE || field_types[field_pos] == MYSQL_TYPE_TIMESTAMP); @@ -987,3 +1001,10 @@ bool Protocol_prep::store_time(TIME *tm) buff[0]=(char) length; // Length is stored first return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC); } + +#if 0 +bool Protocol_prep::send_fields(List<Item> *list, uint flag) +{ + return prepare_for_send(list); +}; +#endif diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 704acc9c1c2..93004ce2937 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -440,10 +440,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list, COND *conds) { THD *thd= stmt->thd; - TABLE *table; DBUG_ENTER("mysql_test_upd_fields"); - if (!(table = open_ltable(thd,table_list,table_list->lock_type))) + if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(1); if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) || @@ -477,13 +476,12 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, COND *conds, ORDER *order, ORDER *group, Item *having) { - TABLE *table; bool hidden_group_fields; THD *thd= stmt->thd; List<Item> all_fields(fields); DBUG_ENTER("mysql_test_select_fields"); - if (!(table = open_ltable(thd,tables,TL_READ))) + if (open_and_lock_tables(thd, tables)) DBUG_RETURN(1); thd->used_tables=0; // Updated by setup_fields @@ -512,7 +510,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, sending any info on where clause. */ if (send_prep_stmt(stmt, fields.elements) || - thd->protocol_prep.send_fields(&fields,0) || + thd->protocol_simple.send_fields(&fields,0) || send_item_params(stmt)) DBUG_RETURN(1); DBUG_RETURN(0); @@ -626,14 +624,17 @@ static bool parse_prepare_query(PREP_STMT *stmt, /* Initialize parameter items in statement */ -static bool init_param_items(THD *thd, PREP_STMT *stmt) + +static bool init_param_items( PREP_STMT *stmt) { + List<Item> ¶ms= stmt->thd->lex.param_list; Item_param **to; + if (!(stmt->param= to= (Item_param **) my_malloc(sizeof(Item_param *)*(stmt->param_count+1), MYF(MY_WME)))) return 1; - List_iterator<Item> param_iterator(thd->lex.param_list); + List_iterator<Item> param_iterator(params); while ((*(to++) = (Item_param *)param_iterator++)); return 0; } @@ -659,29 +660,32 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) DBUG_ENTER("mysql_stmt_prepare"); bzero((char*) &stmt, sizeof(stmt)); - stmt.thd= thd; + stmt.stmt_id= ++thd->current_stmt_id; init_sql_alloc(&stmt.mem_root, 8192, 8192); + + stmt.thd= thd; + stmt.thd->mem_root= stmt.mem_root; - thd->mem_root= stmt.mem_root; - if (alloc_query(thd, packet, packet_length)) + if (alloc_query(stmt.thd, packet, packet_length)) goto err; + if (parse_prepare_query(&stmt, thd->query, thd->query_length)) goto err; if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),WAIT_PRIOR); - if (init_param_items(thd, &stmt)) + if (init_param_items(&stmt)) goto err; - stmt.mem_root= thd->mem_root; + stmt.mem_root= stmt.thd->mem_root; tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0); thd->mem_root= thd_root; // restore main mem_root DBUG_RETURN(0); err: - stmt.mem_root= thd->mem_root; + stmt.mem_root= stmt.thd->mem_root; free_prep_stmt(&stmt, free_free, (void*) 0); thd->mem_root = thd_root; // restore main mem_root DBUG_RETURN(1); @@ -727,9 +731,9 @@ void mysql_stmt_execute(THD *thd, char *packet) mysql_delete(), mysql_update() and mysql_select() to not to have re-check on setup_* and other things .. */ - thd->protocol= &thd->protocol_prep; // Switch to binary protocol + stmt->thd->protocol= &thd->protocol_prep; // Switch to binary protocol mysql_execute_command(stmt->thd); - thd->protocol= &thd->protocol_simple; // Use normal protocol + stmt->thd->protocol= &thd->protocol_simple; // Use normal protocol if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); |