1

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?

5
  • Are you sure your programme receives any notices/warnings? Commented Jan 4, 2010 at 19:24
  • I see them on the console, but I want to trap and handle them. I just don't know what I'm doing wrong when I pass my method to the PQ function. Commented Jan 4, 2010 at 19:27
  • Excuse my ignorance of C but your declaration and the one from the docs don't look very similar to me. Commented Jan 4, 2010 at 19:38
  • Can you elaborate? Maybe that could help. Commented Jan 4, 2010 at 20:08
  • Ah, ignore that - after some reading on the subject of C function pointers I believe you're alright there. Commented Jan 4, 2010 at 21:22

1 Answer 1

4

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));
}
Sign up to request clarification or add additional context in comments.

3 Comments

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.
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.
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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.