properly flush results#2760
Conversation
|
Ito Test Report ✅8 test cases ran. 8 passed. All 8 executed test cases passed (8/8) with zero failures, and the unified local verification found no confirmed production-code defects, with deterministic setup achieved by intentionally bypassing authentication/authorization bootstrap for wire-protocol-focused checks. The most important findings were that streaming behavior was correct across large and simple queries (including contiguous 1–300 results and exact 128/129 boundary counts), Parse/Describe/Bind/Execute and RETURNING flows emitted metadata correctly with no duplicate RowDescription and proper completion framing, and forced flush-time transport disconnects produced clean error propagation without false success while recovery after reconnect (for example, SELECT 1) remained reliable. ✅ Passed (8)Commit: Tell us how we did: Give Ito Feedback |
Footnotes
|
Ito Test Report ✅
13 test cases ran. 2 additional findings, 11 passed. Overall, the unified run executed 13 test cases with 11 passing and 2 failing: all ORDERING, FLUSH, and MEMORY scenarios succeeded, confirming correct row/frame ordering, stable grouped flush behavior (including expected failure handling and clean retry semantics), and stable wide-row/boundary performance. The key issues were two medium-severity extended-protocol defects in server/connection_handler.go where Execute can emit DataRow messages without a prior metadata contract when Describe is skipped, and where Describe metadata can come from a different object context than the executed portal, allowing metadata/row-shape mismatch without protocol rejection. ✅ Passed (11)ℹ️ Additional Findings (2)
🟠 Execute can emit rows without metadata guard
Relevant code:
func (h *ConnectionHandler) handleExecute(message *pgproto3.Execute) error {
h.waitForSync = true
// TODO: implement the RowMax
portalData, ok := h.portals[message.Portal]
if !ok {
return errors.Errorf("portal %s does not exist", message.Portal)
}
// EXECUTE does not send RowDescription; instead it should be sent from DESCRIBE prior to it
if !isExecute && !hasSentRowDescription {
hasSentRowDescription = true
h.backend.Send(&pgproto3.RowDescription{Fields: res.Fields})
}
for _, row := range res.Rows {
h.backend.Send(&pgproto3.DataRow{
Values: row.val,
})
}🟠 Describe and Execute object context can diverge
Relevant code:
if message.ObjectType == 'S' {
preparedStatementData, ok := h.preparedStatements[message.Name]
if !ok {
return errors.Errorf("prepared statement %s does not exist", message.Name)
}
fields = preparedStatementData.ReturnFields
bindvarTypes = preparedStatementData.BindVarTypes
query = preparedStatementData.Query
} else {
portalData, ok := h.portals[message.Name]
if !ok {
return errors.Errorf("portal %s does not exist", message.Name)
}
fields = portalData.Fields
query = portalData.Query
}
portalData, ok := h.portals[message.Portal]
if !ok {
return errors.Errorf("portal %s does not exist", message.Portal)
}
query := portalData.Query
callback := h.spoolRowsCallback(query, &rowsAffected, true)
err = h.doltgresHandler.ComExecuteBound(
context.Background(), h.mysqlConn, query.String, portalData.BoundPlan, portalData.FormatCodes, callback,
)
if returnsRow(query) {
return h.send(&pgproto3.RowDescription{
Fields: fields,
})
}Commit: Tell us how we did: Give Ito Feedback |

















Instead of flushing RowDescription and every RowData right away, have the entire Result buffer in memory first.