From: mj Date: Thu, 27 Sep 2001 19:29:17 +0000 (+0000) Subject: Renamed the trigger.c to dupetrigger.c to enlarge the namespace for X-Git-Tag: prexmlproducerconfig~409 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=ed37df176cb24f284a0ae0628598c37882915b11;p=mir.git Renamed the trigger.c to dupetrigger.c to enlarge the namespace for additional triggers. Cleaned up Makefile and the other files. --- diff --git a/dbscripts/dupetrigger/INSTALL b/dbscripts/dupetrigger/INSTALL index 8571231f..e7687f7d 100755 --- a/dbscripts/dupetrigger/INSTALL +++ b/dbscripts/dupetrigger/INSTALL @@ -5,5 +5,3 @@ To install the trigger do the following: # psql -U postgres Mir < postgresql.script (This installs the the trigger binary and creates a new trigger.) - -# rm /tmp/trigger.so diff --git a/dbscripts/dupetrigger/Makefile b/dbscripts/dupetrigger/Makefile index ad1c52c7..6185ec2d 100755 --- a/dbscripts/dupetrigger/Makefile +++ b/dbscripts/dupetrigger/Makefile @@ -2,18 +2,25 @@ CC=gcc PGINC=/usr/include/postgresql +CFLAGS=-I$(PGINC) -trigger.so: trigger.o - $(CC) -shared -dynamic -o trigger.so trigger.o - cp trigger.so /tmp - chmod 755 /tmp/trigger.so +# If changed, also change postgresql.script +INSTALLDIR=../../../Mir/src -trigger.o: trigger.c - $(CC) -I$(PGINC) -c trigger.c -o trigger.o +install: dupetrigger.so + cp dupetrigger.so $(INSTALLDIR) + chmod 755 $(INSTALLDIR)/dupetrigger.so + # + # Now, change the path to dupetrigger.so in postgresql.script to the + # absolute path where dupetrigger.so is installed (this + # is typically ../../../Mir/src) + +dupetrigger.so: dupetrigger.o + $(CC) -shared -dynamic -o dupetrigger.so dupetrigger.o clean: - rm -rf trigger.o trigger.so + rm -rf dupetrigger.o dupetrigger.so tidy: clean diff --git a/dbscripts/dupetrigger/README b/dbscripts/dupetrigger/README index 58561771..a506867e 100755 --- a/dbscripts/dupetrigger/README +++ b/dbscripts/dupetrigger/README @@ -8,9 +8,9 @@ this somehow. Because Indymedia databases will hopefully grow big very fast, we want to do this check as fast as possible. So Mir simply issues the INSERT. By this INSERT statement, a trigger gets, -well, triggered that calculate a CRC-32 checksum of the comment and searches -for rows with the same checksum. If it finds the checksum, the INSERT gets -aborted. If the checksum isn't found, it is appended to the row and the -INSERT is executed. +well, triggered that calculates a CRC-32 checksum of the comment and +searches for rows with the same checksum. If it finds the checksum, the +INSERT gets aborted. If the checksum isn't found, it is appended to the row +and the INSERT is executed. The trigger works for INSERTs and UPDATEs. diff --git a/dbscripts/dupetrigger/dupetrigger.c b/dbscripts/dupetrigger/dupetrigger.c new file mode 100755 index 00000000..66f61e18 --- /dev/null +++ b/dbscripts/dupetrigger/dupetrigger.c @@ -0,0 +1,209 @@ +// +// +// This File contructs a PostgreSQL trigger. +// The trigger is fired BEFORE an INSERT or UPDATE of an article +// or comment. It first calculates a CRC32 checksum of the row to be +// inserted or updated and checks whether there exists already another +// row with the same checksum and the same content. In this case, +// the trigger returns NULL and thus, aborts the SQL command. +// +// Author: Matthias Jordan +// + + +#include "executor/spi.h" +#include "commands/trigger.h" +#include "string.h" + +extern Datum dupecheck(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(dupecheck); + + + + +// +// +// CRC32 stuff +// + +// crc32 table based on the following polynom +#define CRC32_POLY 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */ + +u_long crc32_table[256] = + {0x0000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x54bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0xe56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0xfdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; + + +static u_long crc32(u_char *buf, unsigned len) +{ + u_char *p; + u_long crc; + + crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ + for (p = buf; len > 0; ++p, --len) + { + crc = (crc << 8) ^ crc32_table[(crc >> 24) ^ *p]; + } + return ~crc; /* transmit complement, per CRC-32 spec */ +} /* crc32 */ + + + + + +// +// +// Trigger stuff +// + + + + +Datum dupecheck(PG_FUNCTION_ARGS) +{ + TriggerData *trigdata = (TriggerData *) fcinfo->context; + TupleDesc tupdesc; + HeapTuple rettuple; + bool isnull; + int ret = 0, i, fnumber; + long rowstrlen = 0, + crc; + int maxitems = 3, + num; + char *items[maxitems], + *rowstring, + *query; + + + /* Make sure trigdata is pointing at what I expect */ + if (!CALLED_AS_TRIGGER(fcinfo)) + elog(ERROR, "dupecheck: not fired by trigger manager"); + + /* tuple to return to Executor */ + if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) + rettuple = trigdata->tg_newtuple; + else + rettuple = trigdata->tg_trigtuple; + + if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) + return PointerGetDatum(NULL); + + tupdesc = trigdata->tg_relation->rd_att; + + /* Connect to SPI manager */ + if ((ret = SPI_connect()) < 0) + ret = SPI_connect(); + elog(NOTICE, "dupecheck: SPI_connect returned %d", ret); + + // Now we are connected to the database's SPI manager + // We will now construct a string of some important row values. + // First, we determine how long the string will be to allocate memory + // To include an additional item, add another SPI_getvalue line and + // increase maxitems above by 1 + + items[0] = SPI_getvalue(rettuple, tupdesc, SPI_fnumber(tupdesc, "creator")); + items[1] = SPI_getvalue(rettuple, tupdesc, SPI_fnumber(tupdesc, "title")); + items[2] = SPI_getvalue(rettuple, tupdesc, SPI_fnumber(tupdesc, "description")); + + for (i=0; (i < maxitems); i++) + { + rowstrlen += strlen(items[i]); + } + rowstrlen++; // add space for 0-terminator + + rowstring = malloc(rowstrlen); + if (rowstring == NULL) + { + // Big problem. + return PointerGetDatum(NULL); + } + + *rowstring = 0; + for (i=0; (i < maxitems); i++) + { + strcat(rowstring, items[i]); + } + + // rowstring now contains the data of the maxitems important + // items of the table record. Now we calculate the CRC-32 checksum + // of the rowstring + + crc = crc32(rowstring, rowstrlen - 1); + + // Now we allocate some space and construct the SQL query + query = malloc(47 + 11 + 2 + 1); // SELECT part + crc32 + "';" + 0-term + if (query == NULL) + { + // Big problem + return PointerGetDatum(NULL); + } + + sprintf(query, "SELECT count(*) FROM comment WHERE checksum='%ld';", crc); + ret = SPI_exec(query, 2); + num = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull); + + if ((ret == SPI_OK_SELECT) && (num > 0)) + { + elog(NOTICE, "dupecheck: UBD prevented (dupe dropped)"); + return PointerGetDatum(NULL); + } + else + { + // The checksum wasn't found. So we modify the tuple to be + // inserted and add the fresh checksum. + int attnum; + Datum value; + char nulls = 0; + + elog(NOTICE, "dupecheck: Adding checksum to INSERT"); + attnum = SPI_fnumber(tupdesc, "checksum"); + value = (Datum) crc; + rettuple = SPI_modifytuple(trigdata->tg_relation, rettuple, 1, &attnum, &value, &nulls); + } + + SPI_finish(); + return PointerGetDatum(rettuple); +} + diff --git a/dbscripts/dupetrigger/postgresql.sript b/dbscripts/dupetrigger/postgresql.sript index d1f43c44..28e9027c 100755 --- a/dbscripts/dupetrigger/postgresql.sript +++ b/dbscripts/dupetrigger/postgresql.sript @@ -1,5 +1,6 @@ \connect - postgres DROP FUNCTION dupecheck(); DROP TRIGGER dupetrigger ON comment; -CREATE FUNCTION dupecheck() RETURNS OPAQUE AS '/tmp/trigger.so' LANGUAGE 'C'; +CREATE FUNCTION dupecheck() RETURNS OPAQUE AS '/path/to/dupetrigger.so' LANGUAGE 'C'; CREATE TRIGGER dupetrigger BEFORE INSERT OR UPDATE ON comment FOR EACH ROW EXECUTE PROCEDURE dupecheck(); +CREATE INDEX comment_checksum_index on comment (checksum); diff --git a/dbscripts/dupetrigger/trigger.c b/dbscripts/dupetrigger/trigger.c deleted file mode 100755 index 66f61e18..00000000 --- a/dbscripts/dupetrigger/trigger.c +++ /dev/null @@ -1,209 +0,0 @@ -// -// -// This File contructs a PostgreSQL trigger. -// The trigger is fired BEFORE an INSERT or UPDATE of an article -// or comment. It first calculates a CRC32 checksum of the row to be -// inserted or updated and checks whether there exists already another -// row with the same checksum and the same content. In this case, -// the trigger returns NULL and thus, aborts the SQL command. -// -// Author: Matthias Jordan -// - - -#include "executor/spi.h" -#include "commands/trigger.h" -#include "string.h" - -extern Datum dupecheck(PG_FUNCTION_ARGS); - -PG_FUNCTION_INFO_V1(dupecheck); - - - - -// -// -// CRC32 stuff -// - -// crc32 table based on the following polynom -#define CRC32_POLY 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */ - -u_long crc32_table[256] = - {0x0000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, - 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, - 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, - 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, - 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, - 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, - 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, - 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x54bf6a4, - 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, - 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, - 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, - 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, - 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, - 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, - 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, - 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, - 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, - 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0xe56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, - 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, - 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, - 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, - 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, - 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, - 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0xfdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, - 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, - 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, - 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, - 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, - 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; - - -static u_long crc32(u_char *buf, unsigned len) -{ - u_char *p; - u_long crc; - - crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ - for (p = buf; len > 0; ++p, --len) - { - crc = (crc << 8) ^ crc32_table[(crc >> 24) ^ *p]; - } - return ~crc; /* transmit complement, per CRC-32 spec */ -} /* crc32 */ - - - - - -// -// -// Trigger stuff -// - - - - -Datum dupecheck(PG_FUNCTION_ARGS) -{ - TriggerData *trigdata = (TriggerData *) fcinfo->context; - TupleDesc tupdesc; - HeapTuple rettuple; - bool isnull; - int ret = 0, i, fnumber; - long rowstrlen = 0, - crc; - int maxitems = 3, - num; - char *items[maxitems], - *rowstring, - *query; - - - /* Make sure trigdata is pointing at what I expect */ - if (!CALLED_AS_TRIGGER(fcinfo)) - elog(ERROR, "dupecheck: not fired by trigger manager"); - - /* tuple to return to Executor */ - if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) - rettuple = trigdata->tg_newtuple; - else - rettuple = trigdata->tg_trigtuple; - - if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) - return PointerGetDatum(NULL); - - tupdesc = trigdata->tg_relation->rd_att; - - /* Connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - ret = SPI_connect(); - elog(NOTICE, "dupecheck: SPI_connect returned %d", ret); - - // Now we are connected to the database's SPI manager - // We will now construct a string of some important row values. - // First, we determine how long the string will be to allocate memory - // To include an additional item, add another SPI_getvalue line and - // increase maxitems above by 1 - - items[0] = SPI_getvalue(rettuple, tupdesc, SPI_fnumber(tupdesc, "creator")); - items[1] = SPI_getvalue(rettuple, tupdesc, SPI_fnumber(tupdesc, "title")); - items[2] = SPI_getvalue(rettuple, tupdesc, SPI_fnumber(tupdesc, "description")); - - for (i=0; (i < maxitems); i++) - { - rowstrlen += strlen(items[i]); - } - rowstrlen++; // add space for 0-terminator - - rowstring = malloc(rowstrlen); - if (rowstring == NULL) - { - // Big problem. - return PointerGetDatum(NULL); - } - - *rowstring = 0; - for (i=0; (i < maxitems); i++) - { - strcat(rowstring, items[i]); - } - - // rowstring now contains the data of the maxitems important - // items of the table record. Now we calculate the CRC-32 checksum - // of the rowstring - - crc = crc32(rowstring, rowstrlen - 1); - - // Now we allocate some space and construct the SQL query - query = malloc(47 + 11 + 2 + 1); // SELECT part + crc32 + "';" + 0-term - if (query == NULL) - { - // Big problem - return PointerGetDatum(NULL); - } - - sprintf(query, "SELECT count(*) FROM comment WHERE checksum='%ld';", crc); - ret = SPI_exec(query, 2); - num = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull); - - if ((ret == SPI_OK_SELECT) && (num > 0)) - { - elog(NOTICE, "dupecheck: UBD prevented (dupe dropped)"); - return PointerGetDatum(NULL); - } - else - { - // The checksum wasn't found. So we modify the tuple to be - // inserted and add the fresh checksum. - int attnum; - Datum value; - char nulls = 0; - - elog(NOTICE, "dupecheck: Adding checksum to INSERT"); - attnum = SPI_fnumber(tupdesc, "checksum"); - value = (Datum) crc; - rettuple = SPI_modifytuple(trigdata->tg_relation, rettuple, 1, &attnum, &value, &nulls); - } - - SPI_finish(); - return PointerGetDatum(rettuple); -} -