Implemented MySQL_Protocol::generate_pkt_field2()

`generate_pkt_field2` is a less generic version of `generate_pkt_field`
and it is meant to be used only for queries executed on backend.
The function takes a `MYSQL_FIELD` as one of its arguments, thus a lot of
lengths do not need to be computed
pull/3246/head
René Cannaò 5 years ago
parent bd60db2751
commit dacea25866

@ -97,6 +97,7 @@ class MySQL_Protocol {
// bool generate_pkt_column_count(MySQL_Data_Stream *myds, bool send, void **ptr, unsigned int *len, uint8_t sequence_id, uint64_t count);
bool generate_pkt_column_count(bool send, void **ptr, unsigned int *len, uint8_t sequence_id, uint64_t count, MySQL_ResultSet *myrs=NULL);
// bool generate_pkt_field(MySQL_Data_Stream *myds, bool send, void **ptr, unsigned int *len, uint8_t sequence_id, char *schema, char *table, char *org_table, char *name, char *org_name, uint16_t charset, uint32_t column_length, uint8_t type, uint16_t flags, uint8_t decimals, bool field_list, uint64_t defvalue_length, char *defvalue);
bool generate_pkt_field2(void **ptr, unsigned int *len, uint8_t sequence_id, MYSQL_FIELD *field, MySQL_ResultSet *myrs);
bool generate_pkt_field(bool send, void **ptr, unsigned int *len, uint8_t sequence_id, char *schema, char *table, char *org_table, char *name, char *org_name, uint16_t charset, uint32_t column_length, uint8_t type, uint16_t flags, uint8_t decimals, bool field_list, uint64_t defvalue_length, char *defvalue, MySQL_ResultSet *myrs=NULL);
bool generate_pkt_row(bool send, void **ptr, unsigned int *len, uint8_t sequence_id, int colnums, unsigned long *fieldslen, char **fieldstxt);
uint8_t generate_pkt_row3(MySQL_ResultSet *myrs, unsigned int *len, uint8_t sequence_id, int colnums, unsigned long *fieldslen, char **fieldstxt);

@ -798,6 +798,130 @@ bool MySQL_Protocol::generate_pkt_column_count(bool send, void **ptr, unsigned i
return true;
}
// this is an optimized version of generate_pkt_field() that uses MYSQL_FIELD
// in order to avoid recomputing the length of the various fields
// it also cannot handle field_list
bool MySQL_Protocol::generate_pkt_field2(void **ptr, unsigned int *len, uint8_t sequence_id, MYSQL_FIELD *field, MySQL_ResultSet *myrs) {
if ((*myds)->sess->mirror==true) {
return true;
}
//char *def=(char *)"def";
//uint32_t def_strlen = field->catalog_length;
char def_prefix;
uint8_t def_len=mysql_encode_length(field->catalog_length, &def_prefix);
//uint32_t schema_strlen=strlen(schema);
char schema_prefix;
uint8_t schema_len=mysql_encode_length(field->db_length, &schema_prefix);
//uint32_t table_strlen=strlen(table);
char table_prefix;
uint8_t table_len=mysql_encode_length(field->table_length, &table_prefix);
//uint32_t org_table_strlen=strlen(org_table);
char org_table_prefix;
uint8_t org_table_len=mysql_encode_length(field->org_table_length, &org_table_prefix);
//uint32_t name_strlen=strlen(name);
char name_prefix;
uint8_t name_len=mysql_encode_length(field->name_length, &name_prefix);
//uint32_t org_name_strlen=strlen(org_name);
char org_name_prefix;
uint8_t org_name_len=mysql_encode_length(field->org_name_length, &org_name_prefix);
/*
char defvalue_length_prefix;
uint8_t defvalue_length_len=0;
if (field_list) {
defvalue_length_len=mysql_encode_length(field->def_length, &defvalue_length_prefix);
}
*/
mysql_hdr myhdr;
myhdr.pkt_id=sequence_id;
myhdr.pkt_length = def_len + field->catalog_length
+ schema_len + field->db_length
+ table_len + field->table_length
+ org_table_len + field->org_table_length
+ name_len + field->name_length
+ org_name_len + field->org_name_length
+ 1 // filler
+ sizeof(uint16_t) // charset
+ sizeof(uint32_t) // column_length
+ sizeof(uint8_t) // type
+ sizeof(uint16_t) // flags
+ sizeof(uint8_t) // decimals
+ 2; // filler
/*
if (field_list) {
myhdr.pkt_length += defvalue_length_len + strlen(defvalue);
}
*/
unsigned int size=myhdr.pkt_length+sizeof(mysql_hdr);
unsigned char *_ptr = NULL;
/* myrs always passed
if (myrs) {
*/
if ( size<=(RESULTSET_BUFLEN-myrs->buffer_used) ) {
// there is space in the buffer, add the data to it
_ptr = myrs->buffer + myrs->buffer_used;
myrs->buffer_used += size;
} else {
// there is no space in the buffer, we flush the buffer and recreate it
myrs->buffer_to_PSarrayOut();
// now we can check again if there is space in the buffer
if ( size<=(RESULTSET_BUFLEN-myrs->buffer_used) ) {
// there is space in the NEW buffer, add the data to it
_ptr = myrs->buffer + myrs->buffer_used;
myrs->buffer_used += size;
} else {
// a new buffer is not enough to store the new row
_ptr=(unsigned char *)l_alloc(size);
}
}
/* myrs always passed
} else {
_ptr=(unsigned char *)l_alloc(size);
}
*/
memcpy(_ptr, &myhdr, sizeof(mysql_hdr));
int l=sizeof(mysql_hdr);
l+=write_encoded_length_and_string(_ptr+l, field->catalog_length, def_len, def_prefix, field->catalog);
l+=write_encoded_length_and_string(_ptr+l, field->db_length, schema_len, schema_prefix, field->db);
l+=write_encoded_length_and_string(_ptr+l, field->table_length, table_len, table_prefix, field->table);
l+=write_encoded_length_and_string(_ptr+l, field->org_table_length, org_table_len, org_table_prefix, field->org_table);
l+=write_encoded_length_and_string(_ptr+l, field->name_length, name_len, name_prefix, field->name);
l+=write_encoded_length_and_string(_ptr+l, field->org_name_length, org_name_len, org_name_prefix, field->org_name);
_ptr[l]=0x0c; l++;
memcpy(_ptr+l,&field->charsetnr,sizeof(uint16_t)); l+=sizeof(uint16_t);
memcpy(_ptr+l,&field->length,sizeof(uint32_t)); l+=sizeof(uint32_t);
_ptr[l]=field->type; l++;
memcpy(_ptr+l,&field->flags,sizeof(uint16_t)); l+=sizeof(uint16_t);
_ptr[l]=field->decimals; l++;
_ptr[l]=0x00; l++;
_ptr[l]=0x00; l++;
if (len) { *len=size; }
if (ptr) { *ptr=(void *)_ptr; }
#ifdef DEBUG
if (dump_pkt) { __dump_pkt(__func__,_ptr,size); }
#endif
/* myrs always passed
if (myrs) {
*/
if (_ptr >= myrs->buffer && _ptr < myrs->buffer+RESULTSET_BUFLEN) {
// we are writing within the buffer, do not add to PSarrayOUT
} else {
// we are writing outside the buffer, add to PSarrayOUT
myrs->PSarrayOUT.add(_ptr,size);
}
/* myrs always passed
}
*/
return true;
}
bool MySQL_Protocol::generate_pkt_field(bool send, void **ptr, unsigned int *len, uint8_t sequence_id, char *schema, char *table, char *org_table, char *name, char *org_name, uint16_t charset, uint32_t column_length, uint8_t type, uint16_t flags, uint8_t decimals, bool field_list, uint64_t defvalue_length, char *defvalue, MySQL_ResultSet *myrs) {
if ((*myds)->sess->mirror==true) {
@ -2415,7 +2539,9 @@ void MySQL_ResultSet::init(MySQL_Protocol *_myprot, MYSQL_RES *_res, MYSQL *_my,
for (unsigned int i=0; i<num_fields; i++) {
MYSQL_FIELD *field=mysql_fetch_field(result);
if (c_myds->com_field_list==false) {
myprot->generate_pkt_field(false,&pkt.ptr,&pkt.size,sid,field->db,field->table,field->org_table,field->name,field->org_name,field->charsetnr,field->length,field->type,field->flags,field->decimals,false,0,NULL,this);
// we are replacing generate_pkt_field() with a more efficient version
//myprot->generate_pkt_field(false,&pkt.ptr,&pkt.size,sid,field->db,field->table,field->org_table,field->name,field->org_name,field->charsetnr,field->length,field->type,field->flags,field->decimals,false,0,NULL,this);
myprot->generate_pkt_field2(&pkt.ptr,&pkt.size,sid,field,this);
resultset_size+=pkt.size;
sid++;
} else {

Loading…
Cancel
Save