views:

62

answers:

1

Hi,

I'm working on a C application that is suppose to talk to PostgreSQL. Right now I need to handle notices and warnings sent by the server but I'm at a loss on how to make it work.

The (very unclear) documentation says we should use PQsetNoticeReceiver to set a method as the receiver of notifications, as the default receiver just forwards the notification to PQnoticeProcessor and this prints to stderr.

I've defined a method thus

static void noticeReceiver(void *arg, const PGresult *res)

and I'm setting it as the default notice receiver on startup thus

PQsetNoticeReceiver(conn, noticeReceiver, NULL);

In my method implementation I'm simply printing some random characters to screen but it doesn't get called. Step by step debugging shows that its being set as the default notice receiver but its never called.

Any ideas?

+2  A: 

The only way I could see it not working is if you change the connection after setting the receiver. Keep in mind that the receiver is a parameter of the connection, so if you disconnect and reconnect it would go away.

This works:

#include "libpq-fe.h"

static void myrecv(void *arg, const PGresult *res);

int main() {
    PGconn  *conn;
    PGresult *res;

    conn = PQconnectdb("");
    if (PQstatus(conn) == CONNECTION_BAD)
    {
        printf("connection error: %s\n",
                PQerrorMessage(conn));
        return -1;
    }

    PQsetNoticeReceiver(conn, myrecv, NULL);

    res = PQexec(conn, "select noisy_func();");
    if (PQresultStatus(res) == PGRES_FATAL_ERROR)
        printf("%s: error: %s\n",
                PQresStatus(PQresultStatus(res)),
                PQresultErrorMessage(res));

    return 0;
}

static void
myrecv(void *arg, const PGresult *res)
{
    printf("hey, got a notice saying \"%s\"\n",
            PQresultErrorField(res,
                PG_DIAG_MESSAGE_PRIMARY));
}
alvherre
Not doing that. I set the receiver as soon as the connection is marked successful and that's it. But it seems its not being called.
Rui Pacheco
Can you show example code? It certainly works for me.
alvherre
My method was called noticeReceiver and for some reason my app always called the default receiver. I changed the name of the method to myrecv as you have it and voila, it works.In other words, I wasted a day because of the method name.
Rui Pacheco
That's pretty weird. I could believe that there was a conflict with the default receiver if it was called defaultNoticeReceiver, but otherwise I don't see how that could have happened. Keep in mind they are referenced as pointers, not by name (except on the PQsetNoticeReceiver call itself).
alvherre