60{
63 int nargs;
67 char *channel;
68 char operation;
70 bool foundPK;
71
74
75 /* make sure it's called as a trigger */
78 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
79 errmsg(
"triggered_change_notification: must be called as trigger")));
80
81 /* and that it's called after the change */
84 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
85 errmsg(
"triggered_change_notification: must be called after the change")));
86
87 /* and that it's called for each row */
90 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
91 errmsg(
"triggered_change_notification: must be called for each row")));
92
94 operation = 'I';
96 operation = 'U';
98 operation = 'D';
99 else
100 {
101 elog(
ERROR,
"triggered_change_notification: trigger fired by unrecognized operation");
102 operation = 'X'; /* silence compiler warning */
103 }
104
107 if (nargs > 1)
109 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
110 errmsg(
"triggered_change_notification: must not be called with more than one parameter")));
111
112 if (nargs == 0)
113 channel = "tcn";
114 else
115 channel = trigger->tgargs[0];
116
117 /* get tuple data */
121
122 foundPK = false;
123
124 /*
125 * Get the list of index OIDs for the table from the relcache, and look up
126 * each one in the pg_index syscache until we find one marked primary key
127 * (hopefully there isn't more than one such).
128 */
130
131 foreach(indexoidscan, indexoidlist)
132 {
136
139 elog(
ERROR,
"cache lookup failed for index %u", indexoid);
141 /* we're only interested if it is the primary key and valid */
143 {
144 int indnkeyatts =
index->indnkeyatts;
145
146 if (indnkeyatts > 0)
147 {
149
150 foundPK = true;
151
155
156 for (
i = 0;
i < indnkeyatts;
i++)
157 {
158 int colno =
index->indkey.values[
i];
160
165 }
166
168 }
170 break;
171 }
173 }
174
176
177 if (!foundPK)
179 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
180 errmsg(
"triggered_change_notification: must be called on a table with a primary key")));
181
182 return PointerGetDatum(NULL);
/* after trigger; value doesn't matter */
183}
void Async_Notify(const char *channel, const char *payload)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
void list_free(List *list)
FormData_pg_attribute * Form_pg_attribute
FormData_pg_index * Form_pg_index
static Datum PointerGetDatum(const void *X)
static Datum ObjectIdGetDatum(Oid X)
#define RelationGetRelationName(relation)
List * RelationGetIndexList(Relation relation)
char * SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
StringInfo makeStringInfo(void)
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
static void strcpy_quoted(StringInfo r, const char *s, const char q)
#define TRIGGER_FIRED_BY_DELETE(event)
#define CALLED_AS_TRIGGER(fcinfo)
#define TRIGGER_FIRED_FOR_ROW(event)
#define TRIGGER_FIRED_AFTER(event)
#define TRIGGER_FIRED_BY_INSERT(event)
#define TRIGGER_FIRED_BY_UPDATE(event)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)