Merge pull request #5143 from sysown/v3.0_fix-describe-portal-nodata-empty-query

Fix: return NoData for Describe (Portal) before Execute on empty statement
pull/5161/head
René Cannaò 7 months ago committed by GitHub
commit 2c9cea0014
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -495,7 +495,14 @@ handler_again:
break;
case PGRES_EMPTY_QUERY:
{
const unsigned int bytes_recv = query_result->add_empty_query_response(result.get());
unsigned int bytes_recv = 0;
if (fetch_result_end_st == ASYNC_STMT_EXECUTE_END) {
if ((query.extended_query_info->flags & PGSQL_EXTENDED_QUERY_FLAG_DESCRIBE_PORTAL) != 0) {
bytes_recv = query_result->add_no_data();
}
}
bytes_recv += query_result->add_empty_query_response(result.get());
update_bytes_recv(bytes_recv);
}
NEXT_IMMEDIATE(ASYNC_USE_RESULT_CONT);

@ -4992,6 +4992,61 @@ void test_explicit_txn_success_then_rollback_extended() {
}
}
void test_empty_query_describe_portal_returns_no_data() {
diag("Test %d: Describe Portal Returns No Data for empty query", test_count++);
auto conn = create_connection();
if (!conn) return;
try{
conn->prepareStatement("empty_query_stmt", "", false);
conn->bindStatement("empty_query_stmt", "", {}, {}, false);
conn->describePortal("", false);
conn->executeStatement(0, false);
conn->sendSync();
char type;
std::vector<uint8_t> buffer;
conn->readMessage(type, buffer);
ok(type == PgConnection::PARSE_COMPLETE, "Received ParseComplete for empty query");
conn->readMessage(type, buffer);
ok(type == PgConnection::BIND_COMPLETE, "Received BindComplete for empty query");
conn->readMessage(type, buffer);
ok(type == PgConnection::NO_DATA, "Received NoData for empty query");
conn->readMessage(type, buffer);
ok(type == PgConnection::EMPTY_QUERY_RESPONSE, "Received EmptyQueryResponse for empty query");
conn->readMessage(type, buffer);
ok(type == PgConnection::READY_FOR_QUERY, "Received ReadyForQuery after all commands");
}
catch (const PgException& e) {
ok(false, "Describe Portal Returns No Data for empty query failed with error:%s", e.what());
}
}
void test_empty_query_without_describe_portal() {
diag("Test %d: Execute empty query without Describe Portal", test_count++);
auto conn = create_connection();
if (!conn) return;
try {
conn->prepareStatement("empty_query2_stmt", "", false);
conn->bindStatement("empty_query2_stmt", "", {}, {}, false);
conn->executeStatement(0, false);
conn->sendSync();
char type;
std::vector<uint8_t> buffer;
conn->readMessage(type, buffer);
ok(type == PgConnection::PARSE_COMPLETE, "Received ParseComplete for empty query");
conn->readMessage(type, buffer);
ok(type == PgConnection::BIND_COMPLETE, "Received BindComplete for empty query");
conn->readMessage(type, buffer);
ok(type == PgConnection::EMPTY_QUERY_RESPONSE, "Received EmptyQueryResponse for empty query");
conn->readMessage(type, buffer);
ok(type == PgConnection::READY_FOR_QUERY, "Received ReadyForQuery after all commands");
}
catch (const PgException& e) {
ok(false, "Execute empty query without Describe Portal failed with error:%s", e.what());
}
}
int main(int argc, char** argv) {
if (cl.getEnv())
return exit_status();
@ -5002,7 +5057,7 @@ int main(int argc, char** argv) {
return exit_status();
}
plan(1052); // Adjust based on number of tests
plan(1061); // Adjust based on number of tests
auto admin_conn = createNewConnection(ConnType::ADMIN, "", false);
@ -5127,6 +5182,10 @@ int main(int argc, char** argv) {
test_explicit_txn_error_with_rollback_extended();
test_explicit_txn_error_with_commit_extended();
test_explicit_txn_success_then_rollback_extended();
// Empty query tests
test_empty_query_describe_portal_returns_no_data();
test_empty_query_without_describe_portal();
}
catch (const std::exception& e) {
diag("Fatal error: %s",e.what());

Loading…
Cancel
Save