Fix two UseDeclareFetch bugs.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 11 Apr 2014 12:14:26 +0000 (15:14 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 11 Apr 2014 12:16:16 +0000 (15:16 +0300)
1. NOTICE messages were not delivered to the application, if they arrived
as response to the DECLARE CURSOR statement.

2. Array-bound parameters on SELECT-queries caused a "cursor already open"
error.

These bugs were found by running the regression suite with
UseDeclareFetch=1. It's now clean.

convert.c
statement.c
statement.h

index 3fc68d648eb3ff58c47a1b27a1008ff2cbaa14e7..1fef061334d5d42848df28bfa0281f090e5a9051 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -3296,7 +3296,7 @@ inner_process_tokens(QueryParse *qp, QueryBuild *qb)
        if (0 == (qb->flags & FLGB_CREATE_KEYSET))
        {
            qb->errornumber = STMT_SEQUENCE_ERROR;
-           qb->errormsg = "Should come here only when hamdling updatable cursors";
+           qb->errormsg = "Should come here only when handling updatable cursors";
            return SQL_ERROR;
        }
        CVT_APPEND_STR(qb, ", \"ctid");
index 19510bf541226bf2ccf2b4a88801cd143711723e..0d23ffe0eb1a6bf507033994950a828ce1219dfb 100644 (file)
@@ -2048,6 +2048,12 @@ inolog("get_Result=%p %p %d\n", res, SC_get_Result(self), self->curr_param_resul
        res = CC_send_query_append(conn, self->stmt_with_params, qryi, qflag, SC_get_ancestor(self), appendq);
        if (useCursor && QR_command_maybe_successful(res))
        {
+           /*
+            * If we sent a DECLARE CURSOR + FETCH, throw away the result of
+            * the DECLARE CURSOR statement, and only return the result of the
+            * FETCH to the caller. However, if we received any NOTICEs as
+            * part of the DECLARE CURSOR, carry those over.
+            */
            if (appendq)
            {
                QResultClass    *qres, *nres;
@@ -2060,6 +2066,15 @@ inolog("get_Result=%p %p %d\n", res, SC_get_Result(self), self->curr_param_resul
                        break;
                    }
                    nres = qres->next;
+                   if (nres && QR_get_notice(qres) != NULL)
+                   {
+                       if (QR_command_successful(nres) &&
+                           QR_command_nonfatal(qres))
+                       {
+                           QR_set_rstatus(nres, PORES_NONFATAL_ERROR);
+                       }
+                       QR_add_notice(nres, QR_get_notice(qres));
+                   }
                    qres->next = NULL;
                    QR_Destructor(qres);
                    qres = nres;
index aa847e621daa13a2d73061f4112d9953e1a9d536..6a138be0ae284a09457db1e08ef3391332cd5f23 100644 (file)
@@ -422,7 +422,13 @@ enum
 #define SC_ref_CC_error(a) ((a->ref_CC_error) = TRUE)
 void SC_forget_unnamed(StatementClass *self);
 #define SC_can_parse_statement(a) (STMT_TYPE_SELECT == (a)->statement_type)
-#define SC_may_use_cursor(a) (STMT_TYPE_SELECT == (a)->statement_type || STMT_TYPE_WITH == (a)->statement_type)
+/*
+ * DECLARE CURSOR + FETCH can only be used with SELECT-type queries. And
+ * it's not currently supported with array-bound parameters.
+ */
+#define SC_may_use_cursor(a) \
+   (SC_get_APDF(a)->paramset_size <= 1 &&                              \
+    (STMT_TYPE_SELECT == (a)->statement_type || STMT_TYPE_WITH == (a)->statement_type) )
 #define SC_may_fetch_rows(a) (STMT_TYPE_SELECT == (a)->statement_type || STMT_TYPE_WITH == (a)->statement_type)
 #define SC_can_req_colinfo(a) (STMT_TYPE_SELECT == (a)->statement_type || \
         STMT_TYPE_WITH == (a)->statement_type || \
@@ -501,8 +507,6 @@ BOOL    SC_SetExecuting(StatementClass *self, BOOL on);
 BOOL   SC_SetCancelRequest(StatementClass *self);
 BOOL   SC_AcceptedCancelRequest(const StatementClass *self);
 
-DescriptorClass    *SC_set_ARD(StatementClass *stmt, DescriptorClass *desc);
-DescriptorClass    *SC_set_APD(StatementClass *stmt, DescriptorClass *desc);
 int        enqueueNeedDataCallback(StatementClass *self, NeedDataCallfunc, void *);
 RETCODE        dequeueNeedDataCallback(RETCODE, StatementClass *self);
 void       cancelNeedDataState(StatementClass *self);