Skip to content

Instantly share code, notes, and snippets.

@tallpeak
Last active August 7, 2020 17:19
Show Gist options
  • Save tallpeak/da9b309a2d87c64320d33b7b4011f1b2 to your computer and use it in GitHub Desktop.
Save tallpeak/da9b309a2d87c64320d33b7b4011f1b2 to your computer and use it in GitHub Desktop.
UPC checkdigit calculation as a Postgresql C extension function
~/src/postgresql-12.2/src/tutorial# cat upc_checksum.c
#include "postgres.h"
#include <string.h>
#include "fmgr.h"
#include "utils/geo_decls.h"
PG_MODULE_MAGIC;
/* by value */
PG_FUNCTION_INFO_V1(upc_checksum);
Datum
upc_checksum(PG_FUNCTION_ARGS)
{
text *upc = PG_GETARG_TEXT_PP(0);
int sum = 0;
int mult = 3;
char *pstart = VARDATA_ANY(upc);
char *p = pstart + VARSIZE_ANY_EXHDR(upc);
while (--p >= pstart) {
unsigned int digit = *p - '0';
if (digit < 10) {
sum += digit * mult;
mult ^= 2;
}
}
sum = (500 - sum) % 10;
// sum = ( 10 - ( sum % 10 ) ) % 10;
PG_RETURN_INT32(sum);
}
Putting the function into a path that is accessible (I know /tmp is a bad choice, but it worked)
% cat upc_checksum.sh
cc -fPIC -c upc_checksum.c -I/usr/local/pgsql/include/server/
cc -shared -o upc_checksum.so upc_checksum.o
cp upc_checksum.* /tmp/
Installing the function:
% psql postgres
[local] root@streetpulse=# drop FUNCTION upc_checksum;
DROP FUNCTION
Time: 4.181 ms
[local] root@streetpulse=# CREATE FUNCTION upc_checksum(text) RETURNS integer
AS '/tmp/upc_checksum.so', 'upc_checksum'
LANGUAGE C STRICT;
CREATE FUNCTION
Time: 5.101 ms
[local] root@streetpulse=# DO $proc$
DECLARE
StartTime timestamptz;
EndTime timestamptz;
Delta double precision;
rc int;
BEGIN
StartTime := clock_timestamp();
SELECT count(*) into rc
from tbl_superfile
where right(upc14,1)<>upc_checksum(upc_number||'')::text;
EndTime := clock_timestamp();
Delta := ( extract(epoch from EndTime) - extract(epoch from StartTime) );
RAISE NOTICE 'Duration in secs=%, rc=%', Delta, rc;
END;
$proc$;
NOTICE: 00000: Duration in secs=3.3357880115509033, rc=6037
LOCATION: exec_stmt_raise, pl_exec.c:3827
DO
Time: 3339.333 ms (00:03.339)
Ref: https://www.postgresql.org/docs/13/xfunc-c.html#XFUNC-C-DYNLOAD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment