Implementation of COM_FIELD_LIST

Port from 1.4.16 to 2.0.6
pull/2189/head
René Cannaò 7 years ago
parent 7df2227c7c
commit f3e7f03998

@ -147,6 +147,9 @@ class MySQL_Data_Stream
uint8_t pkt_sid;
bool com_field_list;
char *com_field_wild;
MySQL_Data_Stream();
~MySQL_Data_Stream();

@ -30,6 +30,7 @@ class MySQL_ResultSet {
void add_eof();
void add_err(MySQL_Data_Stream *_myds);
bool get_resultset(PtrSizeArray *PSarrayFinal);
//bool generate_COM_FIELD_LIST_response(PtrSizeArray *PSarrayFinal);
unsigned char *buffer;
unsigned int buffer_used;
void buffer_to_PSarrayOut(bool _last=false);
@ -50,10 +51,10 @@ class MySQL_Prepared_Stmt_info {
class MySQL_Protocol {
private:
MySQL_Data_Stream **myds;
MySQL_Connection_userinfo *userinfo;
MySQL_Session *sess;
public:
MySQL_Data_Stream **myds;
#ifdef DEBUG
bool dump_pkt;
#endif
@ -108,5 +109,7 @@ class MySQL_Protocol {
void generate_STMT_PREPARE_RESPONSE_OK(uint8_t sequence_id, uint32_t stmt_id);
stmt_execute_metadata_t * get_binds_from_pkt(void *ptr, unsigned int size, MySQL_STMT_Global_info *stmt_info, stmt_execute_metadata_t **stmt_meta);
bool generate_COM_QUERY_from_COM_FIELD_LIST(PtrSize_t *pkt);
};
#endif /* __CLASS_MYSQL_PROTOCOL_H */

@ -231,3 +231,4 @@ char *escape_string_single_quotes(char *input, bool free_it);
int remove_spaces(const char *);
char *trim_spaces_in_place(char *str);
char *trim_spaces_and_quotes_in_place(char *str);
bool mywildcmp(const char *p, const char *str);

@ -2164,6 +2164,52 @@ stmt_execute_metadata_t * MySQL_Protocol::get_binds_from_pkt(void *ptr, unsigned
return ret;
}
bool MySQL_Protocol::generate_COM_QUERY_from_COM_FIELD_LIST(PtrSize_t *pkt) {
PtrSize_t n_pkt;
unsigned int o_pkt_size = pkt->size;
char *pkt_ptr = (char *)pkt->ptr;
pkt_ptr+=5;
// some sanity check
void *a = NULL;
a = memchr((void *)pkt_ptr, 0, o_pkt_size-5);
if (a==NULL) return false; // we failed to parse
char *tablename = strdup(pkt_ptr);
unsigned int wild_len = o_pkt_size - 5 - strlen(tablename) - 1;
char *wild = NULL;
if (wild_len > 0) {
pkt_ptr+=strlen(tablename);
pkt_ptr++;
wild=strndup(pkt_ptr,wild_len);
}
char *q = NULL;
if ((*myds)->com_field_wild) {
free((*myds)->com_field_wild);
(*myds)->com_field_wild=NULL;
}
if (wild) {
(*myds)->com_field_wild=strdup(wild);
}
char *qt = (char *)"SELECT * FROM %s WHERE 1=0";
q = (char *)malloc(strlen(qt)+strlen(tablename));
sprintf(q,qt,tablename);
l_free(pkt->size, pkt->ptr);
pkt->size = strlen(q)+5;
mysql_hdr Hdr;
Hdr.pkt_id=1;
Hdr.pkt_length = pkt->size - 4;
pkt->ptr=malloc(pkt->size);
memcpy(pkt->ptr,&Hdr,sizeof(mysql_hdr));
memset((char *)pkt->ptr+4,3,1); // COM_QUERY
memcpy((char *)pkt->ptr+5,q,pkt->size-5);
if (wild) free(wild);
free(tablename);
free(q);
return true;
}
MySQL_ResultSet::MySQL_ResultSet() {
buffer = NULL;
//reset_pid = true;
@ -2173,6 +2219,7 @@ void MySQL_ResultSet::init(MySQL_Protocol *_myprot, MYSQL_RES *_res, MYSQL *_my,
resultset_completed=false;
myprot=_myprot;
mysql=_my;
MySQL_Data_Stream * c_myds = *(myprot->myds);
if (buffer==NULL) {
//if (_stmt==NULL) { // we allocate this buffer only for not prepared statements
// removing the previous assumption. We allocate this buffer also for prepared statements
@ -2203,17 +2250,25 @@ void MySQL_ResultSet::init(MySQL_Protocol *_myprot, MYSQL_RES *_res, MYSQL *_my,
if (myprot==NULL) {
return; // this is a mirror
}
myprot->generate_pkt_column_count(false,&pkt.ptr,&pkt.size,sid,num_fields,this);
sid++;
//PSarrayOUT->add(pkt.ptr,pkt.size);
resultset_size+=pkt.size;
if (c_myds->com_field_list==false) {
myprot->generate_pkt_column_count(false,&pkt.ptr,&pkt.size,sid,num_fields,this);
sid++;
resultset_size+=pkt.size;
}
// columns description
for (unsigned int i=0; i<num_fields; i++) {
MYSQL_FIELD *field=mysql_fetch_field(result);
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);
//PSarrayOUT->add(pkt.ptr,pkt.size);
resultset_size+=pkt.size;
sid++;
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);
resultset_size+=pkt.size;
sid++;
} else {
if (c_myds->com_field_wild==NULL || mywildcmp(c_myds->com_field_wild,field->name)) {
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,true,4,(char *)"null",this);
resultset_size+=pkt.size;
sid++;
}
}
}
// first EOF
unsigned int nTrx=myds->sess->NumActiveTransactions();
@ -2230,9 +2285,11 @@ void MySQL_ResultSet::init(MySQL_Protocol *_myprot, MYSQL_RES *_res, MYSQL *_my,
if (RESULTSET_BUFLEN <= (buffer_used + 9)) {
buffer_to_PSarrayOut();
}
if (myds->com_field_list==false) {
myprot->generate_pkt_EOF(false, NULL, NULL, sid, 0, setStatus, this);
sid++;
resultset_size += 9;
}
//}
if (_stmt) { // binary protocol , we also assume we have ALL the resultset
buffer_to_PSarrayOut();
@ -2402,6 +2459,15 @@ void MySQL_ResultSet::add_err(MySQL_Data_Stream *_myds) {
resultset_completed=true;
}
/*
bool MySQL_ResultSet::get_COM_FIELD_LIST_response(PtrSizeArray *PSarrayFinal) {
transfer_started=true;
if (myprot) {
}
return resultset_completed;
}
*/
bool MySQL_ResultSet::get_resultset(PtrSizeArray *PSarrayFinal) {
transfer_started=true;
if (myprot) {

@ -2808,6 +2808,20 @@ __get_pkts_from_client:
c=*((unsigned char *)pkt.ptr+sizeof(mysql_hdr));
}
}
client_myds->com_field_list=false; // default
if (c == _MYSQL_COM_FIELD_LIST) {
if (session_type == PROXYSQL_SESSION_MYSQL) {
MySQL_Protocol *myprot=&client_myds->myprot;
bool rcp = myprot->generate_COM_QUERY_from_COM_FIELD_LIST(&pkt);
if (rcp) {
// all went well
c=*((unsigned char *)pkt.ptr+sizeof(mysql_hdr));
client_myds->com_field_list=true;
} else {
// parsing failed, proxysql will return not suppported command
}
}
}
switch ((enum_mysql_command)c) {
case _MYSQL_COM_QUERY:
__sync_add_and_fetch(&thread->status_variables.queries,1);
@ -5510,9 +5524,10 @@ void MySQL_Session::MySQL_Result_to_MySQL_wire(MYSQL *mysql, MySQL_ResultSet *My
bool transfer_started=MyRS->transfer_started;
bool resultset_completed=MyRS->get_resultset(client_myds->PSarrayOUT);
CurrentQuery.rows_sent = MyRS->num_rows;
bool com_field_list=client_myds->com_field_list;
assert(resultset_completed); // the resultset should always be completed if MySQL_Result_to_MySQL_wire is called
if (transfer_started==false) { // we have all the resultset when MySQL_Result_to_MySQL_wire was called
if (qpo && qpo->cache_ttl>0) { // the resultset should be cached
if (qpo && qpo->cache_ttl>0 && com_field_list==false) { // the resultset should be cached
if (mysql_errno(mysql)==0) { // no errors
if (
(qpo->cache_empty_result==1)

@ -107,6 +107,39 @@ char *trim_spaces_and_quotes_in_place(char *str) {
return str;
}
bool mywildcmp(const char *p, const char *str) {
if (*p == '\0') {
if (*str == '\0') {
return true;
} else {
return false;
}
}
if (*p == '_' || *p == *str) {
if (*str == '\0') {
return false;
} else {
return mywildcmp(p + 1, str + 1);
}
}
if (*p == '%') {
if (mywildcmp(p + 1, str)) {
return true;
} else {
if (*str == '\0') {
return false;
} else {
return mywildcmp(p, str + 1);
}
}
}
return false;
}
void * PtrSizeArray::operator new(size_t size) {
return l_alloc(size);
}

@ -216,10 +216,12 @@ MySQL_Data_Stream::MySQL_Data_Stream() {
CompPktOUT.partial=0;
multi_pkt.ptr=NULL;
multi_pkt.size=0;
statuses.questions = 0;
statuses.myconnpoll_get = 0;
statuses.myconnpoll_put = 0;
com_field_wild=NULL;
}
// Destructor
@ -242,6 +244,11 @@ MySQL_Data_Stream::~MySQL_Data_Stream() {
free_mysql_real_query();
if (com_field_wild) {
free(com_field_wild);
com_field_wild=NULL;
}
proxy_debug(PROXY_DEBUG_NET,1, "Shutdown Data Stream. Session=%p, DataStream=%p\n" , sess, this);
PtrSize_t pkt;
if (PSarrayIN) {

Loading…
Cancel
Save