HowTo - Create PostgreSQL C library functions
The first thing you should do is reading the extensive official manual of PostgreSQL C library functions. This page serves as additional example only that demonstrates how you can handle bytea values in C. When starting to program your own library, you need a Makefile. The example below is a very flexible one that I got from a geek on #postgres. Before using, please adapt the module and source file names accordingly. Example Makefile for C library function:
MODULES = randomness PG_CONFIG = pg_config PGXS = $(shell $(PG_CONFIG) --pgxs) INCLUDEDIR = $(shell $(PG_CONFIG) --includedir-server) include $(PGXS) randomness.so: randomness.o cc -shared -o randomness.so randomness.o randomness.o: randomness.c cc -o randomness.o -c randomness.c $(CFLAGS) -I$(INCLUDEDIR) Now let's start with some the fun stuff. I'll give an example of a C function int32 x := bytea_size(bytea) that returns the size of a bytea field: Example C library function: bytea_size(bytea)
1 #include "postgres.h" 2 #include "fmgr.h" 3 #include "miscadmin.h" 4 5 #ifdef PG_MODULE_MAGIC 6 PG_MODULE_MAGIC; 7 #endif 8 9 Datum bytea_size(PG_FUNCTION_ARGS); 10 11 PG_FUNCTION_INFO_V1(bytea_size); 12 Datum 13 bytea_size(PG_FUNCTION_ARGS) { 14 bytea *data = PG_GETARG_BYTEA_P(0); 15 unsigned char *ptr = (unsigned char *) VARDATA(data); 16 int32 tcount = 0, i; 17 18 // count characters 19 for (i = VARSIZE(data) - VARHDRSZ; i; i--) { 20 if (!i%1000) CHECK_FOR_INTERRUPTS(); 21 unsigned char c = *ptr++; // get the char 22 tcount++; 23 } 24 25 PG_RETURN_INT32(tcount); 26 } Obviously, the code uses 'Version 1 Calling Conventions', what you should also always do. I will spare you all details that you understand since reading the official docs. Here what's probably new to you (and some lessons I learned):
If you are finished writing the C function, try compiling it until you don't get compiler-warnings anymore. Then you should copy the new shared object (.so) file to your pgsql library directory. If you don't know where that is, check it out using (on Linux): [user@db ~]# pg_config --pkglibdir /usr/lib/pgsql We're about to finish. The last thing you need to do is creating the SQL function that bases on your created C function. In our example, this would work with: CREATE FUNCTION bytea_size(bytea) RETURNS integer AS 'randomness', 'bytea_size' LANGUAGE C STRICT; That's all! What regards the C function part, we're done. If you create something sensible and want to share this to the community, then publish your project on pgFoundry. What drove me to C language functions was the missing support of estimating the randomness of data in PostgreSQL. I'll publish another article about the 'pg-randomness' project as soon as it's public in pgFoundry.
Yours
|