Greetings everyone,

Beginner in PostgreSQL internals, seeking the insight of more experienced.

" (At present, the extra field is unused and will always point to an empty 
string.)" - http://www.postgresql.org/docs/8.0/static/libpq-notify.html
regarding PGnotify returned by PQnotifies

I would like to implement the functionality that is the idea behind that
extra message field: I would like to be able to give NOTIFY an extra 
string parameter, and I would like that string to end up in that extra 
field of that PGnotify structure above.

I have been using PostgreSQL for different projects in the last 5-6 years,
but have never looked under the hood until now. Please guide me.

Pointers to previous relevant discussions would also be kindly welcomed.

----------------

Command/syntax:

Being unfamiliar with flex/yacc/bison, I chose the simplest route, and 
added an optional Sconst:

opt_notifymessage:
                        Sconst  { $$ = $1; }
                        | /*EMPTY*/     { $$ = ""; }

----------------

Storage:

In this scenario, we need to store the message with each notification, so
notifications would no longer be conceptually unique(relname), but
unique(relname,message) instead. As a result, they will need a separate
table. I therefore invented pg_notify:

pg_notify:
        NameData        relname;
        int4            senderpid;
        int4            recipientpid;
        NameData        message; //FIXME: what about type text instead?

and as senderpid now has a place in pg_notify, I removed it from
pg_listener:

pg_listener:
        NameData        relname;
        int4            listenerpid;

----------------

backend/commands/async.c:

Async_Notify - now takes NotifyStmt * as input

AtCommit_Notify - scans pg_listener, and for each tuple that has pending
                  notifies for its relname, inserts a tuple into pg_notify

ProcessIncomingNotify - now scans pg_notify instead of pg_listener, 
                        delivers notifies sent to that BE PID,
                        and deletes their tuples

NotifyMyFrontend - now has got a new parameter, char *message, that it
                   sends to the frontend

----------------

Issues:

I don't know much about string internals in PostgreSQL, so I just
duplicated code for the string type already used in pg_listener: NameData;  
but NameData is limited to NAMEDATALEN bytes (64 currently) and for
certain applications this might be a limiting factor. It would be nice to
have something longer - say NOTIFYMESSAGELEN = 256 bytes? I guess it would
be easy to come up with another, size-limited string type, but then again
256 - nevertheless sufficient for my current application, where 64
wouldn't do - is just another arbitrary number, and as such, hard to
objectively reason for or against.

Is text/bpchar/varlena (with its TOASTedness) viable here and for this
purpose? Its capacity would certainly waive that concern.

I am also not very proficient in char* and NameData semantics, storage
issues and accessors - please scrutinize the code in this respect as well.

My modifications leave behavior of LISTEN/NOTIFY mostly unchanged, 
but they change the structure and behavior of pg_listener. Should we worry 
about this and try to add code to emulate the old behavior?

-----------------

I attached a - never compiled, never tested - patch, as a vehicle to
demonstrate my ideas, solicit further discussion and ask for guidance.

Thank you in advance.

Best Regards,
Andras
diff -Nru postgresql-8.0.2-vanilla/src/backend/catalog/Makefile 
postgresql-8.0.2/src/backend/catalog/Makefile
--- postgresql-8.0.2-vanilla/src/backend/catalog/Makefile       2004-07-21 
22:34:45.000000000 +0200
+++ postgresql-8.0.2/src/backend/catalog/Makefile       2005-05-07 
05:51:05.840517947 +0200
@@ -30,7 +30,7 @@
        pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h \
        pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
        pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
-       pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h pg_cast.h \
+       pg_rewrite.h pg_trigger.h pg_listener.h pg_notify.h pg_description.h 
pg_cast.h \
        pg_namespace.h pg_conversion.h pg_database.h pg_shadow.h pg_group.h \
        pg_tablespace.h pg_depend.h indexing.h \
     )
diff -Nru postgresql-8.0.2-vanilla/src/backend/commands/async.c 
postgresql-8.0.2/src/backend/commands/async.c
--- postgresql-8.0.2-vanilla/src/backend/commands/async.c       2004-12-31 
22:59:41.000000000 +0100
+++ postgresql-8.0.2/src/backend/commands/async.c       2005-05-12 
07:49:37.240803594 +0200
@@ -81,6 +81,7 @@
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/pg_listener.h"
+#include "catalog/pg_notify.h"
 #include "commands/async.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
@@ -131,7 +132,7 @@
 static void Async_UnlistenAll(void);
 static void Async_UnlistenOnExit(int code, Datum arg);
 static void ProcessIncomingNotify(void);
-static void NotifyMyFrontEnd(char *relname, int32 listenerPID);
+static void NotifyMyFrontEnd(char *relname, int32 listenerPID, char *message);
 static bool AsyncExistsPendingNotify(const char *relname);
 static void ClearPendingNotifies(void);
 
@@ -152,26 +153,25 @@
  *--------------------------------------------------------------
  */
 void
-Async_Notify(char *relname)
+Async_Notify(NotifyStmt *stmt)
 {
        if (Trace_notify)
-               elog(DEBUG1, "Async_Notify(%s)", relname);
+               if (stmt->message[0] != '\0')
+                       elog(DEBUG1, "Async_Notify(%s,%s)", 
stmt->relation->relname, stmt->message);
+               else
+                       elog(DEBUG1, "Async_Notify(%s)", 
stmt->relation->relname);
 
-       /* no point in making duplicate entries in the list ... */
-       if (!AsyncExistsPendingNotify(relname))
-       {
-               /*
-                * The name list needs to live until end of transaction, so 
store
-                * it in the transaction context.
-                */
-               MemoryContext oldcontext;
+       /*
+        * The notify list needs to live until end of transaction, so store
+        * it in the transaction context.
+        */
+       MemoryContext oldcontext;
 
-               oldcontext = MemoryContextSwitchTo(CurTransactionContext);
+       oldcontext = MemoryContextSwitchTo(CurTransactionContext);
 
-               pendingNotifies = lcons(pstrdup(relname), pendingNotifies);
+       pendingNotifies = lcons(stmt, pendingNotifies); //FIXME: shouldn't we 
use a copy of the statement here?
 
-               MemoryContextSwitchTo(oldcontext);
-       }
+       MemoryContextSwitchTo(oldcontext);
 }
 
 /*
@@ -242,7 +242,7 @@
        i = 0;
        values[i++] = (Datum) relname;
        values[i++] = (Datum) pid;
-       values[i++] = (Datum) 0;        /* no notifies pending */
+       //values[i++] = (Datum) 0;      /* no notifies pending */
 
        tuple = heap_formtuple(RelationGetDescr(lRel), values, nulls);
        simple_heap_insert(lRel, tuple);
@@ -433,14 +433,14 @@
 void
 AtCommit_Notify(void)
 {
-       Relation        lRel;
+       Relation        lRel,
+                       nRel;
        TupleDesc       tdesc;
        HeapScanDesc scan;
        HeapTuple       lTuple,
-                               rTuple;
-       Datum           value[Natts_pg_listener];
-       char            repl[Natts_pg_listener],
-                               nulls[Natts_pg_listener];
+                               nTuple;
+       Datum           value[Natts_pg_notify];
+       char            nulls[Natts_pg_notify];
 
        if (pendingNotifies == NIL)
                return;                                 /* no NOTIFY statements 
in this
@@ -459,14 +459,16 @@
        if (Trace_notify)
                elog(DEBUG1, "AtCommit_Notify");
 
-       /* preset data to update notify column to MyProcPid */
-       nulls[0] = nulls[1] = nulls[2] = ' ';
-       repl[0] = repl[1] = repl[2] = ' ';
-       repl[Anum_pg_listener_notify - 1] = 'r';
-       value[0] = value[1] = value[2] = (Datum) 0;
-       value[Anum_pg_listener_notify - 1] = Int32GetDatum(MyProcPid);
+       for (i = 0; i < Natts_pg_listener; i++)
+       {
+               nulls[i] = ' ';
+               values[i] = PointerGetDatum(NULL);
+       }
+
+       value[Anum_pg_notify_senderpid - 1] = Int32GetDatum(MyProcPid);
 
        lRel = heap_openr(ListenerRelationName, ExclusiveLock);
+       nRel = heap_openr(NotifyRelationName, ExclusiveLock);
        tdesc = RelationGetDescr(lRel);
        scan = heap_beginscan(lRel, SnapshotNow, 0, NULL);
 
@@ -476,103 +478,61 @@
                char       *relname = NameStr(listener->relname);
                int32           listenerPID = listener->listenerpid;
 
-               if (!AsyncExistsPendingNotify(relname))
-                       continue;
-
-               if (listenerPID == MyProcPid)
-               {
-                       /*
-                        * Self-notify: no need to bother with table update. 
Indeed,
-                        * we *must not* clear the notification field in this 
path, or
-                        * we could lose an outside notify, which'd be bad for
-                        * applications that ignore self-notify messages.
-                        */
+               ListCell *cell;
+               foreach(cell, pendingNotifies) {
+                       NotifyStmt *stmt = (NotifyStmt *) lfirst(cell);
 
-                       if (Trace_notify)
-                               elog(DEBUG1, "AtCommit_Notify: notifying self");
+                       if (strncmp(stmt->relation->relname, relname, 
NAMEDATALEN))
+                               continue;
 
-                       NotifyMyFrontEnd(relname, listenerPID);
-               }
-               else
-               {
-                       if (Trace_notify)
-                               elog(DEBUG1, "AtCommit_Notify: notifying pid 
%d",
-                                        listenerPID);
-
-                       /*
-                        * If someone has already notified this listener, we 
don't
-                        * bother modifying the table, but we do still send a 
SIGUSR2
-                        * signal, just in case that backend missed the earlier 
signal
-                        * for some reason.  It's OK to send the signal first, 
because
-                        * the other guy can't read pg_listener until we unlock 
it.
-                        */
-                       if (kill(listenerPID, SIGUSR2) < 0)
+                       if (listenerPID == MyProcPid)
                        {
                                /*
-                                * Get rid of pg_listener entry if it refers to 
a PID that
-                                * no longer exists.  Presumably, that backend 
crashed
-                                * without deleting its pg_listener entries. 
This code
-                                * used to only delete the entry if 
errno==ESRCH, but as
-                                * far as I can see we should just do it for 
any failure
-                                * (certainly at least for EPERM too...)
+                                * Self-notify: no need to bother with table 
update. Indeed,
+                                * we *must not* clear the notification field 
in this path, or
+                                * we could lose an outside notify, which'd be 
bad for
+                                * applications that ignore self-notify 
messages.
                                 */
-                               simple_heap_delete(lRel, &lTuple->t_self);
+
+                               if (Trace_notify)
+                                       elog(DEBUG1, "AtCommit_Notify: 
notifying self");
+
+                               NotifyMyFrontEnd(relname, listenerPID, message);
                        }
-                       else if (listener->notification == 0)
+                       else
                        {
-                               ItemPointerData ctid;
-                               int                     result;
-
-                               rTuple = heap_modifytuple(lTuple, lRel,
-                                                                               
  value, nulls, repl);
+                               if (Trace_notify)
+                                       elog(DEBUG1, "AtCommit_Notify: 
notifying pid %d",
+                                                listenerPID);
 
                                /*
-                                * We cannot use simple_heap_update here 
because the tuple
-                                * could have been modified by an uncommitted 
transaction;
-                                * specifically, since UNLISTEN releases 
exclusive lock on
-                                * the table before commit, the other guy could 
already
-                                * have tried to unlisten.      There are no 
other cases where
-                                * we should be able to see an uncommitted 
update or
-                                * delete. Therefore, our response to a
-                                * HeapTupleBeingUpdated result is just to 
ignore it.  We
-                                * do *not* wait for the other guy to commit 
--- that
-                                * would risk deadlock, and we don't want to 
block while
-                                * holding the table lock anyway for 
performance reasons.
-                                * We also ignore HeapTupleUpdated, which could 
occur if
-                                * the other guy commits between our 
heap_getnext and
-                                * heap_update calls.
+                                * If someone has already notified this 
listener, we don't
+                                * bother modifying the table, but we do still 
send a SIGUSR2
+                                * signal, just in case that backend missed the 
earlier signal
+                                * for some reason.  It's OK to send the signal 
first, because
+                                * the other guy can't read pg_listener until 
we unlock it.
                                 */
-                               result = heap_update(lRel, &lTuple->t_self, 
rTuple,
-                                                                        &ctid,
-                                                                        
GetCurrentCommandId(), InvalidSnapshot,
-                                                                        false 
/* no wait for commit */ );
-                               switch (result)
+                               if (kill(listenerPID, SIGUSR2) < 0)
                                {
-                                       case HeapTupleSelfUpdated:
-                                               /* Tuple was already updated in 
current command? */
-                                               elog(ERROR, "tuple already 
updated by self");
-                                               break;
-
-                                       case HeapTupleMayBeUpdated:
-                                               /* done successfully */
-
-#ifdef NOT_USED                                        /* currently there are 
no indexes */
-                                               CatalogUpdateIndexes(lRel, 
rTuple);
-#endif
-                                               break;
+                                       /*
+                                        * Get rid of pg_listener entry if it 
refers to a PID that
+                                        * no longer exists.  Presumably, that 
backend crashed
+                                        * without deleting its pg_listener 
entries. This code
+                                        * used to only delete the entry if 
errno==ESRCH, but as
+                                        * far as I can see we should just do 
it for any failure
+                                        * (certainly at least for EPERM too...)
+                                        */
+                                       simple_heap_delete(lRel, 
&lTuple->t_self);
+                                       //FIXME: we ought to delete pending 
notifications from pg_notify as well
+                               }
+                               else // if (listener->notification == 0) // we 
want to insert each notification
+                               {
+                                       value[Anum_pg_notify_relname - 1] = 
(Datum) relname;
+                                       value[Anum_pg_notify_recipientpid - 1] 
= Int32GetDatum(listenerPID);
+                                       value[Anum_pg_notify_message - 1] = 
(Datum) stmt->message;
 
-                                       case HeapTupleBeingUpdated:
-                                               /* ignore uncommitted tuples */
-                                               break;
-
-                                       case HeapTupleUpdated:
-                                               /* ignore just-committed tuples 
*/
-                                               break;
-
-                                       default:
-                                               elog(ERROR, "unrecognized 
heap_update status: %u",
-                                                        result);
-                                               break;
+                                       nTuple = 
heap_formtuple(RelationGetDescr(nRel), values, nulls);
+                                       simple_heap_insert(nRel, nTuple);
                                }
                        }
                }
@@ -587,6 +547,7 @@
         * Else they might disregard the signal, which would make the
         * application programmer very unhappy.
         */
+       heap_close(nRel, NoLock);
        heap_close(lRel, NoLock);
 
        ClearPendingNotifies();
@@ -870,8 +831,7 @@
  *             Deal with arriving NOTIFYs from other backends.
  *             This is called either directly from the SIGUSR2 signal handler,
  *             or the next time control reaches the outer idle loop.
- *             Scan pg_listener for arriving notifies, report them to my front 
end,
- *             and clear the notification field in pg_listener until next time.
+ *             Scan pg_notify for arriving notifies and report them to my 
front end.
  *
  *             NOTE: since we are outside any transaction, we must create our 
own.
  * --------------------------------------------------------------
@@ -883,11 +843,7 @@
        TupleDesc       tdesc;
        ScanKeyData key[1];
        HeapScanDesc scan;
-       HeapTuple       lTuple,
-                               rTuple;
-       Datum           value[Natts_pg_listener];
-       char            repl[Natts_pg_listener],
-                               nulls[Natts_pg_listener];
+       HeapTuple       lTuple;
        bool            catchup_enabled;
 
        /* Must prevent SIGUSR1 interrupt while I am running */
@@ -902,53 +858,43 @@
 
        StartTransactionCommand();
 
-       lRel = heap_openr(ListenerRelationName, ExclusiveLock);
+       lRel = heap_openr(NotifyRelationName, ExclusiveLock);
        tdesc = RelationGetDescr(lRel);
 
-       /* Scan only entries with my listenerPID */
+       /* Scan only entries with my recipientPID */
        ScanKeyInit(&key[0],
-                               Anum_pg_listener_pid,
+                               Anum_pg_notify_recipientpid,
                                BTEqualStrategyNumber, F_INT4EQ,
                                Int32GetDatum(MyProcPid));
        scan = heap_beginscan(lRel, SnapshotNow, 1, key);
 
-       /* Prepare data for rewriting 0 into notification field */
-       nulls[0] = nulls[1] = nulls[2] = ' ';
-       repl[0] = repl[1] = repl[2] = ' ';
-       repl[Anum_pg_listener_notify - 1] = 'r';
-       value[0] = value[1] = value[2] = (Datum) 0;
-       value[Anum_pg_listener_notify - 1] = Int32GetDatum(0);
-
        while ((lTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
        {
-               Form_pg_listener listener = (Form_pg_listener) 
GETSTRUCT(lTuple);
-               char       *relname = NameStr(listener->relname);
-               int32           sourcePID = listener->notification;
+               Form_pg_notify notify = (Form_pg_notify) GETSTRUCT(lTuple);
+               char       *relname = NameStr(notify->relname);
+               int32           sourcePID = notify->senderpid;
+               char       *message = NameStr(notify->message);
+
+               /* Notify the frontend */
+
+               if (Trace_notify)
+                       elog(DEBUG1, "ProcessIncomingNotify: received %s(%s) 
from %d",
+                                relname, message, (int) sourcePID);
 
-               if (sourcePID != 0)
-               {
-                       /* Notify the frontend */
+               NotifyMyFrontEnd(relname, sourcePID, message);
 
-                       if (Trace_notify)
-                               elog(DEBUG1, "ProcessIncomingNotify: received 
%s from %d",
-                                        relname, (int) sourcePID);
-
-                       NotifyMyFrontEnd(relname, sourcePID);
-
-                       /*
-                        * Rewrite the tuple with 0 in notification column.
-                        *
-                        * simple_heap_update is safe here because no one else 
would have
-                        * tried to UNLISTEN us, so there can be no uncommitted
-                        * changes.
-                        */
-                       rTuple = heap_modifytuple(lTuple, lRel, value, nulls, 
repl);
-                       simple_heap_update(lRel, &lTuple->t_self, rTuple);
+               /*
+                * Delete the tuple.
+                *
+                * simple_heap_delete is safe here because no one else would 
have
+                * tried to process notifies with our PID, so there can be no 
uncommitted
+                * changes.
+                */
+               simple_heap_delete(lRel, &lTuple->t_self);
 
 #ifdef NOT_USED                                        /* currently there are 
no indexes */
-                       CatalogUpdateIndexes(lRel, rTuple);
+               CatalogUpdateIndexes(lRel, rTuple);
 #endif
-               }
        }
        heap_endscan(scan);
 
@@ -982,7 +928,7 @@
  * Send NOTIFY message to my front end.
  */
 static void
-NotifyMyFrontEnd(char *relname, int32 listenerPID)
+NotifyMyFrontEnd(char *relname, int32 listenerPID, char *message)
 {
        if (whereToSendOutput == Remote)
        {
@@ -993,8 +939,7 @@
                pq_sendstring(&buf, relname);
                if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
                {
-                       /* XXX Add parameter string here later */
-                       pq_sendstring(&buf, "");
+                       pq_sendstring(&buf, message);
                }
                pq_endmessage(&buf);
 
@@ -1006,23 +951,17 @@
                 */
        }
        else
-               elog(INFO, "NOTIFY for %s", relname);
+               if (message[0] != '\0')
+                       elog(INFO, "NOTIFY for %s: %s", relname, message);
+               else
+                       elog(INFO, "NOTIFY for %s", relname);
 }
 
-/* Does pendingNotifies include the given relname? */
+/* Does pendingNotifies already have a statement identical to the given one? */
 static bool
-AsyncExistsPendingNotify(const char *relname)
+AsyncExistsPendingNotify(NotifyStmt *stmt)
 {
-       ListCell   *p;
-
-       foreach(p, pendingNotifies)
-       {
-               /* Use NAMEDATALEN for relname comparison.        DZ - 
26-08-1996 */
-               if (strncmp((const char *) lfirst(p), relname, NAMEDATALEN) == 
0)
-                       return true;
-       }
-
-       return false;
+       return list_member(pendingNotifies, stmt);
 }
 
 /* Clear the pendingNotifies list. */
diff -Nru postgresql-8.0.2-vanilla/src/backend/nodes/copyfuncs.c 
postgresql-8.0.2/src/backend/nodes/copyfuncs.c
--- postgresql-8.0.2-vanilla/src/backend/nodes/copyfuncs.c      2004-12-31 
22:59:55.000000000 +0100
+++ postgresql-8.0.2/src/backend/nodes/copyfuncs.c      2005-05-07 
05:59:04.948033379 +0200
@@ -1991,6 +1991,7 @@
        NotifyStmt *newnode = makeNode(NotifyStmt);
 
        COPY_NODE_FIELD(relation);
+       COPY_STRING_FIELD(message);
 
        return newnode;
 }
diff -Nru postgresql-8.0.2-vanilla/src/backend/nodes/equalfuncs.c 
postgresql-8.0.2/src/backend/nodes/equalfuncs.c
--- postgresql-8.0.2-vanilla/src/backend/nodes/equalfuncs.c     2004-12-31 
22:59:55.000000000 +0100
+++ postgresql-8.0.2/src/backend/nodes/equalfuncs.c     2005-05-12 
07:54:25.612788790 +0200
@@ -1041,6 +1041,7 @@
 _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
 {
        COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(message);
 
        return true;
 }
diff -Nru postgresql-8.0.2-vanilla/src/backend/nodes/outfuncs.c 
postgresql-8.0.2/src/backend/nodes/outfuncs.c
--- postgresql-8.0.2-vanilla/src/backend/nodes/outfuncs.c       2004-12-31 
22:59:55.000000000 +0100
+++ postgresql-8.0.2/src/backend/nodes/outfuncs.c       2005-05-12 
07:09:35.167695542 +0200
@@ -1172,6 +1172,7 @@
        WRITE_NODE_TYPE("NOTIFY");
 
        WRITE_NODE_FIELD(relation);
+       WRITE_STRING_FIELD(message);
 }
 
 static void
diff -Nru postgresql-8.0.2-vanilla/src/backend/nodes/readfuncs.c 
postgresql-8.0.2/src/backend/nodes/readfuncs.c
--- postgresql-8.0.2-vanilla/src/backend/nodes/readfuncs.c      2004-12-31 
22:59:55.000000000 +0100
+++ postgresql-8.0.2/src/backend/nodes/readfuncs.c      2005-05-12 
07:09:50.317705869 +0200
@@ -169,6 +169,7 @@
        READ_LOCALS(NotifyStmt);
 
        READ_NODE_FIELD(relation);
+       READ_STRING_FIELD(message);
 
        READ_DONE();
 }
diff -Nru postgresql-8.0.2-vanilla/src/backend/parser/gram.y 
postgresql-8.0.2/src/backend/parser/gram.y
--- postgresql-8.0.2-vanilla/src/backend/parser/gram.y  2004-12-31 
23:00:27.000000000 +0100
+++ postgresql-8.0.2/src/backend/parser/gram.y  2005-05-07 06:15:48.957070922 
+0200
@@ -3911,14 +3911,20 @@
  *
  *****************************************************************************/
 
-NotifyStmt: NOTIFY qualified_name
+NotifyStmt: NOTIFY qualified_name opt_notifymessage
                                {
                                        NotifyStmt *n = makeNode(NotifyStmt);
                                        n->relation = $2;
+                                       n->message = $3;
                                        $$ = (Node *)n;
                                }
                ;
 
+opt_notifymessage:
+                       Sconst  { $$ = $1; }
+                       | /*EMPTY*/     { $$ = ""; }
+               ;
+
 ListenStmt: LISTEN qualified_name
                                {
                                        ListenStmt *n = makeNode(ListenStmt);
diff -Nru postgresql-8.0.2-vanilla/src/backend/tcop/utility.c 
postgresql-8.0.2/src/backend/tcop/utility.c
--- postgresql-8.0.2-vanilla/src/backend/tcop/utility.c 2005-01-24 
18:46:29.000000000 +0100
+++ postgresql-8.0.2/src/backend/tcop/utility.c 2005-05-07 05:10:28.696829622 
+0200
@@ -779,7 +779,7 @@
                        {
                                NotifyStmt *stmt = (NotifyStmt *) parsetree;
 
-                               Async_Notify(stmt->relation->relname);
+                               Async_Notify(stmt);
                        }
                        break;
 
diff -Nru postgresql-8.0.2-vanilla/src/include/catalog/catname.h 
postgresql-8.0.2/src/include/catalog/catname.h
--- postgresql-8.0.2-vanilla/src/include/catalog/catname.h      2004-12-31 
23:03:24.000000000 +0100
+++ postgresql-8.0.2/src/include/catalog/catname.h      2005-05-07 
05:26:05.552087319 +0200
@@ -32,6 +32,7 @@
 #define  LanguageRelationName "pg_language"
 #define  LargeObjectRelationName "pg_largeobject"
 #define  ListenerRelationName "pg_listener"
+#define  NotifyRelationName "pg_notify"
 #define  NamespaceRelationName "pg_namespace"
 #define  OperatorClassRelationName "pg_opclass"
 #define  OperatorRelationName "pg_operator"
diff -Nru postgresql-8.0.2-vanilla/src/include/catalog/pg_listener.h 
postgresql-8.0.2/src/include/catalog/pg_listener.h
--- postgresql-8.0.2-vanilla/src/include/catalog/pg_listener.h  2004-12-31 
23:03:24.000000000 +0100
+++ postgresql-8.0.2/src/include/catalog/pg_listener.h  2005-05-07 
05:46:37.722805287 +0200
@@ -36,7 +36,6 @@
 {
        NameData        relname;
        int4            listenerpid;
-       int4            notification;
 } FormData_pg_listener;
 
 /* ----------------
@@ -50,10 +49,9 @@
  *             compiler constants for pg_listener
  * ----------------
  */
-#define Natts_pg_listener                                              3
+#define Natts_pg_listener                                              2
 #define Anum_pg_listener_relname                               1
 #define Anum_pg_listener_pid                                   2
-#define Anum_pg_listener_notify                                        3
 
 /* ----------------
  *             initial contents of pg_listener are NOTHING.
diff -Nru postgresql-8.0.2-vanilla/src/include/catalog/pg_notify.h 
postgresql-8.0.2/src/include/catalog/pg_notify.h
--- postgresql-8.0.2-vanilla/src/include/catalog/pg_notify.h    1970-01-01 
01:00:00.000000000 +0100
+++ postgresql-8.0.2/src/include/catalog/pg_notify.h    2005-05-07 
08:00:53.316391409 +0200
@@ -0,0 +1,65 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_notify.h
+ *       Asynchronous notification
+ *
+ *
+ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL: pgsql/src/include/catalog/pg_notify.h,v 1.18 2004/12/31 
22:03:24 pgsql Exp $
+ *
+ * NOTES
+ *       the genbki.sh script reads this file and generates .bki
+ *       information from the DATA() statements.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_NOTIFY_H
+#define PG_NOTIFY_H
+
+/* ----------------
+ *             postgres.h contains the system type definitions and the
+ *             CATALOG(), BOOTSTRAP and DATA() sugar words so this file
+ *             can be read by both genbki.sh and the C compiler.
+ * ----------------
+ */
+
+/* ----------------------------------------------------------------
+ *             pg_notify definition.
+ *
+ *             cpp turns this into typedef struct FormData_pg_notify
+ * ----------------------------------------------------------------
+ */
+
+CATALOG(pg_notify) BKI_WITHOUT_OIDS
+{
+       NameData        relname;
+       int4            senderpid;
+       int4            recipientpid;
+       NameData        message; //FIXME: what about type text instead?
+} FormData_pg_notify;
+
+/* ----------------
+ *             Form_pg_notify corresponds to a pointer to a tuple with
+ *             the format of pg_notify relation.
+ * ----------------
+ */
+typedef FormData_pg_notify *Form_pg_notify;
+
+/* ----------------
+ *             compiler constants for pg_notify
+ * ----------------
+ */
+#define Natts_pg_notify                                                4
+#define Anum_pg_notify_relname                         1
+#define Anum_pg_notify_senderpid                               2
+#define Anum_pg_notify_recipientpid                            3
+#define Anum_pg_notify_message                                 4
+
+/* ----------------
+ *             initial contents of pg_notify are NOTHING.
+ * ----------------
+ */
+
+#endif   /* PG_NOTIFY_H */
diff -Nru postgresql-8.0.2-vanilla/src/include/commands/async.h 
postgresql-8.0.2/src/include/commands/async.h
--- postgresql-8.0.2-vanilla/src/include/commands/async.h       2004-12-31 
23:03:28.000000000 +0100
+++ postgresql-8.0.2/src/include/commands/async.h       2005-05-12 
08:46:02.056984528 +0200
@@ -16,7 +16,7 @@
 extern bool Trace_notify;
 
 /* notify-related SQL statements */
-extern void Async_Notify(char *relname);
+extern void Async_Notify(NotifyStmt *stmt);
 extern void Async_Listen(char *relname, int pid);
 extern void Async_Unlisten(char *relname, int pid);
 
diff -Nru postgresql-8.0.2-vanilla/src/include/nodes/parsenodes.h 
postgresql-8.0.2/src/include/nodes/parsenodes.h
--- postgresql-8.0.2-vanilla/src/include/nodes/parsenodes.h     2004-12-31 
23:03:34.000000000 +0100
+++ postgresql-8.0.2/src/include/nodes/parsenodes.h     2005-05-12 
07:10:42.282451376 +0200
@@ -1500,6 +1500,7 @@
 {
        NodeTag         type;
        RangeVar   *relation;           /* qualified name to notify */
+       char        *message;           /* message to send with notify */
 } NotifyStmt;
 
 /* ----------------------
diff -Nru postgresql-8.0.2-vanilla/src/tools/pgindent/pgindent 
postgresql-8.0.2/src/tools/pgindent/pgindent
--- postgresql-8.0.2-vanilla/src/tools/pgindent/pgindent        2004-10-07 
16:15:50.000000000 +0200
+++ postgresql-8.0.2/src/tools/pgindent/pgindent        2005-05-07 
05:49:01.211821875 +0200
@@ -497,6 +497,7 @@
 -TFormData_pg_language \
 -TFormData_pg_largeobject \
 -TFormData_pg_listener \
+-TFormData_pg_notify \
 -TFormData_pg_namespace \
 -TFormData_pg_opclass \
 -TFormData_pg_operator \
@@ -527,6 +528,7 @@
 -TForm_pg_language \
 -TForm_pg_largeobject \
 -TForm_pg_listener \
+-TForm_pg_notify \
 -TForm_pg_namespace \
 -TForm_pg_opclass \
 -TForm_pg_operator \
---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to