Thread: Creating server-side functions: one simple error
Hi, I have to create my own function in C lanuage, which will use SPI. The problem that when I had done all things, PostgreSQL says: isbs=# select pgf1test('123'); ERROR: Can't find function pgf1test in file /usr/local/pgsql/lib/pgf1test.so I don't know where problems is. The program is very short, please point me where my mistake? pgf1test.c ---------- #include "executor/spi.h" #include <ctype.h> Datum pgf1test(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(pgf1test); Datum pgf1test(PG_FUNCTION_ARGS) { // text tnum = PG_GETARG_NAME(0); char *cnum = PG_GETARG_CSTRING(0); PG_RETURN_INT32( atoi(cnum) ); } compile.sh ---------- #!/bin/sh NAME=pgf1test gcc -pipe -O2 -Wall -Wmissing-prototypes -Wmissing-declarations -fpic -DPIC \ -I. -I/usr/home/rd/postgresql/src/include -c -o ${NAME}.o ${NAME}.c /usr/libexec/elf/ld -x -shared -o ${NAME}.so ${NAME}.o rm ${NAME}.o pgf1test-createfunc.sql ----------------------- CREATE OR REPLACE FUNCTION pgf1test (text) RETURNS int4 AS '$libdir/pgf1test' LANGUAGE 'C' WITH (isStrict); All that files worked well - I have created .so object and installed it into /usr/local/pgsql/lib/, after that I execute pgf1test-createfunc.sql - it's complete successfully, but isbs=# select pgf1test('123'); ERROR: Can't find function pgf1test in file /usr/local/pgsql/lib/pgf1test.so show errors. Why PostgreSQL can't found C-function? I know that problem is not complex, and it's very simple question for you. Thanks. --- best regards, Ruslan A Dautkhanov
Ruslan A Dautkhanov <rusland@scn.ru> writes: > I have to create my own function in C lanuage, which > will use SPI. The problem that when I had done all things, > PostgreSQL says: > isbs=# select pgf1test('123'); > ERROR: Can't find function pgf1test in file /usr/local/pgsql/lib/pgf1test.so But it got past the CREATE FUNCTION command without complaint? That's odd, because CREATE FUNCTION should make the same check. Does the behavior change if you start a fresh session? If so, see the LOAD command, which you need to use (or start a fresh session) after any change of the shared library file. regards, tom lane
Tom Lane wrote: > Ruslan A Dautkhanov <rusland@scn.ru> writes: > > I have to create my own function in C lanuage, which > > will use SPI. The problem that when I had done all things, > > PostgreSQL says: > > isbs=# select pgf1test('123'); > > ERROR: Can't find function pgf1test in file /usr/local/pgsql/lib/pgf1test.so > > But it got past the CREATE FUNCTION command without complaint? That's > odd, because CREATE FUNCTION should make the same check. > > Does the behavior change if you start a fresh session? If so, see > the LOAD command, which you need to use (or start a fresh session) > after any change of the shared library file. > > regards, tom lane Yes, you right, I just must run LOAD - after LOAD had complete all works good. Thanks. Btw, how I can convert TEXT field to a CString one? I had tried to use char *cnum = PG_GETARG_CSTRING(0) instead of text tnum = PG_GETARG_NAME(0), but it's not worked properly. Is any function to convert text object to a null-terminated string??? Thanks again. -- best regards, Ruslan A Dautkhanov rusland@scn.ru
Ruslan A Dautkhanov wrote: > Btw, how I can convert TEXT field to a CString one? I had tried to use > char *cnum = PG_GETARG_CSTRING(0) instead of > text tnum = PG_GETARG_NAME(0), but it's not worked properly. Is any function > to convert text object to a null-terminated string??? Thanks again. > I like to use the following macros: /* convert C string to text pointer */ #define GET_TEXT(cstrp) \ DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp))) /* convert text pointer to C string */ #define GET_STR(textp) \ DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp))) then you can do, e.g. char *cnum = GET_STR(PG_GETARG_TEXT_P(0)); BTW, there are lots of good examples of C functions in contrib. HTH, Joe
Joe Conway wrote: > Ruslan A Dautkhanov wrote: > > Btw, how I can convert TEXT field to a CString one? I had tried to use > > char *cnum = PG_GETARG_CSTRING(0) instead of > > text tnum = PG_GETARG_NAME(0), but it's not worked properly. Is any function > > to convert text object to a null-terminated string??? Thanks again. > > > > I like to use the following macros: > > /* convert C string to text pointer */ > #define GET_TEXT(cstrp) \ > DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp))) > /* convert text pointer to C string */ > #define GET_STR(textp) \ > DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp))) > > then you can do, e.g. > char *cnum = GET_STR(PG_GETARG_TEXT_P(0)); Thanks, this worked good. I had finished testing of creating server-side functions and starts creating my business-oriented things on SPI, and I have trap again - I can't translate datetime column, which pass to my procedure. I must convert it to UNIX 1970-seconds counter for my internal needs, but I havn't found _any_ PG_GETARG_* function in fmgr.h, which can read time types as procedure's arguments. Sorry for this question, but PG_GETARG_* function is not documented anywhere... --- best regards, Ruslan A Dautkhanov rusland@scn.ru
Ruslan A Dautkhanov <rusland@scn.ru> writes: > SPI, and I have trap again - I can't translate datetime column, which > pass to my procedure. I must convert it to UNIX 1970-seconds counter for > my internal needs, but I havn't found _any_ PG_GETARG_* function in fmgr.h, > which can read time types as procedure's arguments. Not all the GETARG functions are in fmgr.h, only the most widely used types. See utils/timestamp.h. regards, tom lane
Tom Lane wrote: > Ruslan A Dautkhanov <rusland@scn.ru> writes: > > SPI, and I have trap again - I can't translate datetime column, which > > pass to my procedure. I must convert it to UNIX 1970-seconds counter for > > my internal needs, but I havn't found _any_ PG_GETARG_* function in fmgr.h, > > which can read time types as procedure's arguments. > > Not all the GETARG functions are in fmgr.h, only the most widely used > types. See utils/timestamp.h. Hi! Yes, you right, it's works well - I'm using PG_GETARG_TIMESTAMPTZ() from utils/timestamp.h. But I have another problem when I try to compile procedure with my own library, which used C++-like things. More exactly, problem begins when I include .h file - it's not compiled since it used C++ constructions. That is why I had renamed .c file to .cc - gcc understand source as C++ code now. After this I have no problems in my header files, but have many in PG's header files, for example: 1. In file included from /usr/home/rd/postgresql/src/include/executor/spi.h:22, from remain_time.cc:2: /usr/home/rd/postgresql/src/include/nodes/primnodes.h:529: syntax error before `using' 2. In file included from /usr/home/rd/postgresql/src/include/nodes/relation.h:18, from /usr/home/rd/postgresql/src/include/executor/spi.h:23, from remain_time.cc:2: /usr/home/rd/postgresql/src/include/nodes/parsenodes.h:967: syntax error before `typename' ... (other similar errors on different parsenodes.h's lines) ... other errors on PG's headers when I tries to create procedure as C++ function. Is this mean, that PostgreSQL not C++-ready for compiling server-side functions, doesn't it? Is any methods exists for compiling procedure in C++ (namespace modifications etc)?? Thanks for your help. --- best regards, Ruslan A Dautkhanov rusland@scn.ru
This will not work if there is no EOS on the data portion of the string. Text fields are not usually stored with the EOS on them, are they? elein elein@norcov.com On Wednesday 09 October 2002 21:14, Joe Conway wrote: > Ruslan A Dautkhanov wrote: > > Btw, how I can convert TEXT field to a CString one? I had tried to use > > char *cnum =3D PG_GETARG_CSTRING(0) instead of > > text tnum =3D PG_GETARG_NAME(0), but it's not worked properly. Is a= ny > > function to convert text object to a null-terminated string??? Thanks > > again. > > I like to use the following macros: > > /* convert C string to text pointer */ > #define GET_TEXT(cstrp) \ > DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp))) > /* convert text pointer to C string */ > #define GET_STR(textp) \ > DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp))) > > then you can do, e.g. > char *cnum =3D GET_STR(PG_GETARG_TEXT_P(0)); > > BTW, there are lots of good examples of C functions in contrib. > > HTH, > > Joe > > > ---------------------------(end of broadcast)--------------------------- > TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
Ruslan A Dautkhanov writes: > Is this mean, that PostgreSQL not C++-ready for compiling server-side > functions, doesn't it? PostgreSQL is written in C and does not claim to be compilable by a C++ compiler. That includes the header files. > Is any methods exists for compiling procedure in > C++ (namespace modifications etc)?? Thanks for your help. Make a small wrapper that you compile with a C compiler and put the actual C++ implementation into a separate file. Maybe you could make a complete C++ language handler out of that. -- Peter Eisentraut peter_e@gmx.net
elein (by way of elein ) wrote: > This will not work if there is no EOS on the data portion of the > string. Text fields are not usually stored with the EOS on them, > are they? Yes, the TEXT data type is NULL terminated. Joe