Handle notice messages in libpq_bind_and_exec(). Sets and resets a notify receiver
authorHiroshi Inoue <h-inoue@dream.email.ne.jp>
Sat, 16 May 2020 04:49:48 +0000 (13:49 +0900)
committerHiroshi Inoue <h-inoue@dream.email.ne.jp>
Sat, 16 May 2020 06:31:21 +0000 (15:31 +0900)
around PQexecParams() or PQexecPrepared().

connection.c
connection.h
results.c
statement.c

index 0eddcd2735e1661c14a19f8fea0e1b40a35396f4..5408d88e8be4c76d31d5fffdcd55817fcdb2fa18 100644 (file)
@@ -984,17 +984,6 @@ cleanup:
    LIBPQ_update_transaction_status(self);
 }
 
-/*
- * This is a libpq notice receiver callback, for handling incoming NOTICE
- * messages while processing a query.
- */
-typedef struct
-{
-   ConnectionClass *conn;
-   const char *comment;
-   QResultClass *res;
-} notice_receiver_arg;
-
 void
 receive_libpq_notice(void *arg, const PGresult *pgres)
 {
index 817563fbc05b48b8e97079c7c7b2dbb259a19703..5ae7b9b1f65d6f664600fdde816686ee908e99bb 100644 (file)
@@ -483,6 +483,19 @@ enum {
 #define    NO_TRANS        1L
 #define    CONN_DEAD       (1L << 1) /* connection is no longer valid */
 
+/*
+ * This is a libpq notice receiver callback, for handling incoming NOTICE
+ * messages while processing a query.
+ */
+typedef struct
+{
+   ConnectionClass *conn;
+   const char *comment;
+   QResultClass *res;
+} notice_receiver_arg;
+
+void receive_libpq_notice(void *arg, const PGresult *pgres);
+
 /*
  * internal savepoint related
  */
index eec6a484d42aa0f960f9c61dbb488ed8d84f1e21..9be2d52d646498cd115eed09fc832a27121865da 100644 (file)
--- a/results.c
+++ b/results.c
@@ -1985,6 +1985,7 @@ PGAPI_MoreResults(HSTMT hstmt)
    if (res)
    {
        SQLSMALLINT num_p;
+       int errnum = 0, curerr;
 
        if (stmt->multi_statement < 0)
            PGAPI_NumParams(stmt, &num_p);
@@ -2002,6 +2003,24 @@ PGAPI_MoreResults(HSTMT hstmt)
        stmt->diag_row_count = res->recent_processed_row_count;
        SC_set_rowset_start(stmt, -1, FALSE);
        stmt->currTuple = -1;
+
+       if (!QR_command_maybe_successful(res))
+       {
+           ret = SQL_ERROR;
+           errnum = STMT_EXEC_ERROR;
+       }
+       else if (NULL != QR_get_notice(res))
+       {
+           ret = SQL_SUCCESS_WITH_INFO;
+           errnum = STMT_INFO_ONLY;
+       }
+       if (0 != errnum)
+       {
+           curerr = SC_get_errornumber(stmt);
+           if (0 == curerr ||
+               (0 > curerr && errnum > 0))
+               SC_set_errornumber(stmt, errnum);
+       }
    }
    else
    {
index 1f52338a01370d8f5ed2a6a7dae9111e6b70e9d4..4255f92a6428bf9c0228d550b789c43702f167b8 100644 (file)
@@ -2453,6 +2453,23 @@ static void log_params(int nParams, const Oid *paramTypes, const UCHAR * const *
    }
 }
 
+static
+QResultClass *add_libpq_notice_receiver(StatementClass *stmt, notice_receiver_arg *nrarg)
+{
+   QResultClass *res = NULL, *newres = NULL;
+
+   if (stmt->curr_param_result)
+       for (res = SC_get_Result(stmt); NULL != res && NULL != res->next; res = res->next);
+   if (!res)
+       newres = res = QR_Constructor();
+   nrarg->conn = SC_get_conn(stmt);
+   nrarg->comment = __FUNCTION__;
+   nrarg->res = res;
+   PQsetNoticeReceiver(nrarg->conn->pqconn, receive_libpq_notice, nrarg);
+
+   return newres;
+}
+
 static QResultClass *
 libpq_bind_and_exec(StatementClass *stmt)
 {
@@ -2470,6 +2487,7 @@ libpq_bind_and_exec(StatementClass *stmt)
    QResultClass *res = NULL;
    char       *cmdtag;
    char       *rowcount;
+   notice_receiver_arg nrarg;
 
    if (!RequestStart(stmt, conn, func))
        return NULL;
@@ -2526,6 +2544,8 @@ libpq_bind_and_exec(StatementClass *stmt)
        pstmt = stmt->processed_statements;
        QLOG(0, "PQexecParams: %p '%s' nParams=%d\n", conn->pqconn, pstmt->query, nParams);
        log_params(nParams, paramTypes, (const UCHAR * const *) paramValues, paramLengths, paramFormats, resultFormat);
+       /* set notice receiver */
+       newres = add_libpq_notice_receiver(stmt, &nrarg);
        pgres = PQexecParams(conn->pqconn,
                             pstmt->query,
                             nParams,
@@ -2551,27 +2571,20 @@ libpq_bind_and_exec(StatementClass *stmt)
        /* already prepared */
        QLOG(0, "PQexecPrepared: %p plan=%s nParams=%d\n", conn->pqconn, plan_name, nParams);
        log_params(nParams, paramTypes, (const UCHAR * const *) paramValues, paramLengths, paramFormats, resultFormat);
+       /* set notice receiver */
+       newres = add_libpq_notice_receiver(stmt, &nrarg);
        pgres = PQexecPrepared(conn->pqconn,
                               plan_name,   /* portal name == plan name */
                               nParams,
                               (const char **) paramValues, paramLengths, paramFormats,
                               resultFormat);
    }
-   if (stmt->curr_param_result)
-   {
-       for (res = SC_get_Result(stmt); NULL != res && NULL != res->next; res = res->next) ;
-   }
-   else
-       res = NULL;
-
-   if (!res)
+   /* reset notice receiver */
+   PQsetNoticeReceiver(conn->pqconn, receive_libpq_notice, NULL);
+   if (!(res = nrarg.res))
    {
-       newres = res = QR_Constructor();
-       if (!res)
-       {
-           SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory while allocating result set", func);
-           goto cleanup;
-       }
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory while allocating result set", func);
+       goto cleanup;
    }
 
    /* 3. Receive results */