diff --git a/include/PgSQL_Protocol.h b/include/PgSQL_Protocol.h index 37141a8a8..fe1c994d6 100644 --- a/include/PgSQL_Protocol.h +++ b/include/PgSQL_Protocol.h @@ -836,6 +836,7 @@ public: //bool generate_describe_completion_packet(bool send, bool ready, const PgSQL_Describe_Prepared_Info* desc, uint8_t stmt_type, char trx_state, PtrSize_t* _ptr = NULL); bool generate_close_completion_packet(bool send, bool ready, char trx_state, PtrSize_t* _ptr = NULL); bool generate_bind_completion_packet(bool send, bool ready, char trx_state, PtrSize_t* _ptr = NULL); + bool generate_no_data_packet(bool send, PtrSize_t* _ptr = NULL); // temporary overriding generate_pkt_OK to avoid crash. FIXME remove this bool generate_pkt_OK(bool send, void** ptr, unsigned int* len, uint8_t sequence_id, unsigned int affected_rows, diff --git a/lib/PgSQL_Connection.cpp b/lib/PgSQL_Connection.cpp index 776790366..fcccccc97 100644 --- a/lib/PgSQL_Connection.cpp +++ b/lib/PgSQL_Connection.cpp @@ -2168,6 +2168,14 @@ int PgSQL_Connection::async_send_simple_command(short event, char* stmt, unsigne return -2; } if (async_state_machine == ASYNC_QUERY_END) { + // We just needed to know if the query was successful, not. + // We discard the result. + if (query_result) { + assert(!query_result_reuse); + query_result->clear(); + query_result_reuse = query_result; + query_result = NULL; + } compute_unknown_transaction_status(); if (is_error_present()) { return -1; diff --git a/lib/PgSQL_Protocol.cpp b/lib/PgSQL_Protocol.cpp index e5e5d51f9..8c914412d 100644 --- a/lib/PgSQL_Protocol.cpp +++ b/lib/PgSQL_Protocol.cpp @@ -1664,6 +1664,22 @@ bool PgSQL_Protocol::generate_bind_completion_packet(bool send, bool ready, char return true; } +bool PgSQL_Protocol::generate_no_data_packet(bool send, PtrSize_t* _ptr) { + // to avoid memory leak + assert(send == true || _ptr); + PG_pkt pgpkt(5); + pgpkt.put_char('n'); + pgpkt.put_uint32(4); // size of the NoData packet (Fixed 4 bytes) + auto buff = pgpkt.detach(); + if (send == true) { + (*myds)->PSarrayOUT->add((void*)buff.first, buff.second); + } else { + _ptr->ptr = buff.first; + _ptr->size = buff.second; + } + return true; +} + bool PgSQL_Protocol::generate_parse_completion_packet(bool send, bool ready, char trx_state, PtrSize_t* _ptr) { // to avoid memory leak assert(send == true || _ptr); diff --git a/lib/PgSQL_Session.cpp b/lib/PgSQL_Session.cpp index b557001e4..9af9b2534 100644 --- a/lib/PgSQL_Session.cpp +++ b/lib/PgSQL_Session.cpp @@ -4114,9 +4114,15 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___handle_ } client_myds->DSS = STATE_QUERY_SENT_NET; + + if (extended_query_phase != EXTQ_PHASE_IDLE && + (CurrentQuery.extended_query_info.flags & PGSQL_EXTENDED_QUERY_FLAG_DESCRIBE_PORTAL) != 0) { + client_myds->myprot.generate_no_data_packet(true); + } + bool send_ready_packet = is_extended_query_ready_for_query(); unsigned int nTrx = NumActiveTransactions(); const char txn_state = (nTrx ? 'T' : 'I'); - client_myds->myprot.generate_ok_packet(true, true, NULL, 0, dig, txn_state, NULL, param_status); + client_myds->myprot.generate_ok_packet(true, send_ready_packet, NULL, 0, dig, txn_state, NULL, param_status); RequestEnd(NULL, false); return true; } else { @@ -4212,9 +4218,15 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___handle_ } } client_myds->DSS = STATE_QUERY_SENT_NET; + + if (extended_query_phase != EXTQ_PHASE_IDLE && + (CurrentQuery.extended_query_info.flags & PGSQL_EXTENDED_QUERY_FLAG_DESCRIBE_PORTAL) != 0) { + client_myds->myprot.generate_no_data_packet(true); + } + bool send_ready_packet = is_extended_query_ready_for_query(); unsigned int nTrx = NumActiveTransactions(); const char txn_state = (nTrx ? 'T' : 'I'); - client_myds->myprot.generate_ok_packet(true, true, NULL, 0, dig, txn_state, NULL, param_status); + client_myds->myprot.generate_ok_packet(true, send_ready_packet, NULL, 0, dig, txn_state, NULL, param_status); if (mirror == false) { RequestEnd(NULL, false); @@ -4258,9 +4270,14 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___handle_ if (handled) { client_myds->DSS = STATE_QUERY_SENT_NET; + if (extended_query_phase != EXTQ_PHASE_IDLE && + (CurrentQuery.extended_query_info.flags & PGSQL_EXTENDED_QUERY_FLAG_DESCRIBE_PORTAL) != 0) { + client_myds->myprot.generate_no_data_packet(true); + } + bool send_ready_packet = is_extended_query_ready_for_query(); unsigned int nTrx = NumActiveTransactions(); const char txn_state = (nTrx ? 'T' : 'I'); - client_myds->myprot.generate_ok_packet(true, true, NULL, 0, dig, txn_state, NULL, {}); + client_myds->myprot.generate_ok_packet(true, send_ready_packet, NULL, 0, dig, txn_state, NULL, {}); if (mirror == false) { RequestEnd(NULL, false); @@ -4304,9 +4321,14 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___handle_ } client_myds->DSS = STATE_QUERY_SENT_NET; + if (extended_query_phase != EXTQ_PHASE_IDLE && + (CurrentQuery.extended_query_info.flags & PGSQL_EXTENDED_QUERY_FLAG_DESCRIBE_PORTAL) != 0) { + client_myds->myprot.generate_no_data_packet(true); + } + bool send_ready_packet = is_extended_query_ready_for_query(); unsigned int nTrx = NumActiveTransactions(); const char txn_state = (nTrx ? 'T' : 'I'); - client_myds->myprot.generate_ok_packet(true, true, NULL, 0, dig, txn_state, NULL, {}); + client_myds->myprot.generate_ok_packet(true, send_ready_packet, NULL, 0, dig, txn_state, NULL, {}); if (mirror == false) { RequestEnd(NULL, false);