From e5403b226012013e92e742d066da05372ea235c4 Mon Sep 17 00:00:00 2001 From: Hiroshi Inoue Date: Tue, 24 Oct 2006 11:24:35 +0000 Subject: [PATCH] Avoid backend crash caused by Execute Requests for committed holdable cursors. --- qresult.c | 27 +++++++++++++++++---------- results.c | 8 +++++++- statement.c | 18 ++++++++++++++---- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/qresult.c b/qresult.c index d11b8e7..680bc60 100644 --- a/qresult.c +++ b/qresult.c @@ -806,6 +806,7 @@ QR_next_tuple(QResultClass *self, StatementClass *stmt) ConnInfo *ci = NULL; BOOL msg_truncated, rcvend, internally_invoked = FALSE; BOOL reached_eof_now = FALSE, curr_eof; /* detecting EOF is pretty important */ + BOOL ExecuteRequest = FALSE; Int4 response_length; inolog("Oh %p->fetch_number=%d\n", self, self->fetch_number); @@ -1060,8 +1061,11 @@ inolog("clear obsolete %d tuples\n", num_backend_rows); if (enlargeKeyCache(self, self->cache_size - num_backend_rows, "Out of memory while reading tuples") < 0) return FALSE; - if (PROTOCOL_74(ci)) + if (PROTOCOL_74(ci) + && !QR_is_permanent(self) /* Execute seems an invalid operation after COMMIT */ + ) { + ExecuteRequest = TRUE; if (!SendExecuteRequest(stmt, QR_get_cursor(self), fetch_size)) return FALSE; @@ -1119,6 +1123,8 @@ inolog("reached_eof_now=%d\n", reached_eof_now); for (rcvend = FALSE; !rcvend;) { id = SOCK_get_id(sock); + if (0 != SOCK_get_errcode(sock)) + break; response_length = SOCK_get_response_length(sock); inolog("id='%c' response_length=%d\n", id, response_length); switch (id) @@ -1184,7 +1190,7 @@ inolog("id='%c' response_length=%d\n", id, response_length); QR_set_no_fetching_tuples(self); if (internally_invoked) { - if (PROTOCOL_74(ci)) /* Execute completed without accepting Portal Suspend */ + if (ExecuteRequest) /* Execute completed without accepting Portal Suspend */ reached_eof_now = TRUE; else if (cur_fetch < fetch_size) reached_eof_now = TRUE; @@ -1248,16 +1254,17 @@ inolog("id='%c' response_length=%d\n", id, response_length); rcvend = TRUE; } if (0 != SOCK_get_errcode(sock)) - { - if (QR_command_maybe_successful(self)) - { - QR_set_message(self, "Communication error while getting a tuple"); - QR_set_rstatus(self, PORES_FATAL_ERROR); - } - CC_on_abort(conn, CONN_DEAD); - ret = FALSE; break; + } + if (0 != SOCK_get_errcode(sock)) + { + if (QR_command_maybe_successful(self)) + { + QR_set_message(self, "Communication error while getting a tuple"); + QR_set_rstatus(self, PORES_FATAL_ERROR); } + CC_on_abort(conn, CONN_DEAD); + ret = FALSE; } if (!ret) return ret; diff --git a/results.c b/results.c index ab92f6f..3dbf09c 100644 --- a/results.c +++ b/results.c @@ -1746,6 +1746,8 @@ inolog("num_tuples=%d\n", num_tuples); currp = -1; stmt->bind_row = 0; /* set the binding location */ result = SC_fetch(stmt); + if (SQL_ERROR == result) + goto cleanup; if (SQL_NO_DATA_FOUND != result && res->keyset) { currp = GIdx2KResIdx(SC_get_rowset_start(stmt), stmt, res); @@ -1758,7 +1760,7 @@ inolog("currp=%d\n", currp); goto cleanup; } } - for (i = 0, fc_io = 0; SQL_NO_DATA_FOUND != result; currp++) + for (i = 0, fc_io = 0; SQL_NO_DATA_FOUND != result && SQL_ERROR != result; currp++) { fc_io++; currp_is_valid = FALSE; @@ -1781,6 +1783,8 @@ inolog("ExtFetch result=%d\n", result); inolog("just skipping deleted row %d\n", currp); QR_set_rowset_size(res, (Int4) (rowsetSize - i + fc_io)); result = SC_fetch(stmt); + if (SQL_ERROR == result) + break; continue; } @@ -1819,6 +1823,8 @@ inolog("just skipping deleted row %d\n", currp); stmt->bind_row = (SQLSETPOSIROW) i; /* set the binding location */ result = SC_fetch(stmt); } + if (SQL_ERROR == result) + goto cleanup; /* Save the fetch count for SQLSetPos */ stmt->last_fetch_count = i; diff --git a/statement.c b/statement.c index b7529a3..4a1f657 100644 --- a/statement.c +++ b/statement.c @@ -1363,7 +1363,7 @@ inolog("%s statement=%p ommitted=0\n", func, self); return SQL_NO_DATA_FOUND; } - mylog("**** SC_fetch: non-cursor_result\n"); + mylog("**** %s: non-cursor_result\n", func); (self->currTuple)++; } else @@ -1372,7 +1372,7 @@ inolog("%s statement=%p ommitted=0\n", func, self); retval = QR_next_tuple(res, self); if (retval < 0) { - mylog("**** SC_fetch: end_tuples\n"); + mylog("**** %s: end_tuples\n", func); if (QR_get_cursor(res) && SQL_CURSOR_FORWARD_ONLY == self->options.cursor_type && QR_once_reached_eof(res)) @@ -1383,8 +1383,18 @@ inolog("%s statement=%p ommitted=0\n", func, self); (self->currTuple)++; /* all is well */ else { - mylog("SC_fetch: error\n"); - SC_set_error(self, STMT_EXEC_ERROR, "Error fetching next row", func); + ConnectionClass *conn = SC_get_conn(self); + + mylog("%s: error\n", func); + switch (conn->status) + { + case CONN_NOT_CONNECTED: + case CONN_DOWN: + SC_set_error(self, STMT_BAD_ERROR, "Error fetching next row", func); + break; + default: + SC_set_error(self, STMT_EXEC_ERROR, "Error fetching next row", func); + } return SQL_ERROR; } } -- 2.39.5