Thread: returning CHAR from C function
SuSE 7.3 Postgres7.3b5 I hope this is a simple user error. I am trying to return the first character of a text type in a C function. I did the obvious thing and it crashed the server. I stole text_char out of utils/adt/char.c and it crashed the server. I suspect I have some incorrect expectations of PG_RETURN_CHAR() or PG_RETURN_CHAR() maybe should call CharGetDatum, not DatumGetChar(). Or?? fmgr.h:#define PG_GETARG_CHAR(n) DatumGetChar(PG_GETARG_DATUM(n)) postgres.h:#define DatumGetChar(X) ((char) GET_1_BYTE(X)) postgres.h:#define GET_1_BYTE(datum) (((Datum) (datum)) & 0x000000ff) postgres.h:#define CharGetDatum(X) ((Datum) SET_1_BYTE(X)) Code follows... Thanks, Elein ----- retchar.c --------------- /* * FUNCTION: input text/cstring, return char. # */ #include "postgres.h" #include "fmgr.h" PG_FUNCTION_INFO_V1(retchar); PG_FUNCTION_INFO_V1(retchar1); /* * Fetch first character of text. * Returns char */ Datum retchar( PG_FUNCTION_ARGS ) { text *val = (text *) PG_GETARG_TEXT_P(0); char retdata = *(VARDATA(val)) ; PG_RETURN_CHAR( retdata ); } /* Verbatim from utils/adt/char.c; changed name of function only; */ Datum retchar0(PG_FUNCTION_ARGS) { text *arg1 = PG_GETARG_TEXT_P(0); char result; /* * An empty input string is converted to \0 (for consistency with * charin). If the input is longer than one character, the excess data * is silently discarded. */ if (VARSIZE(arg1) > VARHDRSZ) result = *(VARDATA(arg1)); else result = '\0'; PG_RETURN_CHAR(result); } ----- retchar.sql --------------- -- -- retchar function definitions -- drop function retchar(text); create function retchar(text) returns char as '$libdir/retchar.so' language 'c'; drop function retchar0(text); create function retchar0(text) returns char as '$libdir/retchar.so' language 'c'; ---------- retchar_test.sql ------------- \echo both selects crash server select retchar('abc'); select retchar1('abc'); -- ---------------------------------------------------------------------------------------- elein@varlena.com Database Consulting www.varlena.com I have always depended on the [QA] of strangers.
elein wrote: > create function retchar(text) > returns char > as '$libdir/retchar.so' > language 'c'; > I get similar results. It looks like the cause is that in the create function statement above the "returns char" is interpreted as returning type 1042 (==bpchar), instead of type 18 (==char), which is what you need (and intended). I'm not sure what the proper way to define a function returning type char is, but I did this: regression=# update pg_proc set prorettype = 18 where proname = 'retchar'; UPDATE 1 regression=# select retchar('abc'); retchar --------- a (1 row) then the function works fine :-) Joe
Joe Conway wrote: > instead of type 18 (==char), which is what you need (and intended). I'm > not sure what the proper way to define a function returning type char > is As a follow up, this works: create OR REPLACE function retchar(text) returns "char" as '$libdir/retchar.so' language 'c'; The quotes must prevent the typename from being rewritten to bpchar. HTH, Joe
Joe, Thank you for your confirmation. It sounds like a bug to me even with the work around. I'll report it. elein On Saturday 30 November 2002 15:56, Joe Conway wrote: > Joe Conway wrote: > > instead of type 18 (==char), which is what you need (and intended). I'm > > not sure what the proper way to define a function returning type char > > is > > As a follow up, this works: > > create OR REPLACE function retchar(text) > returns "char" > as '$libdir/retchar.so' > language 'c'; > > The quotes must prevent the typename from being rewritten to bpchar. > > HTH, > > Joe > > > > ---------------------------(end of broadcast)--------------------------- > TIP 4: Don't 'kill -9' the postmaster -- ---------------------------------------------------------------------------------------- elein@varlena.com Database Consulting www.varlena.com I have always depended on the [QA] of strangers.
Joe Conway <mail@joeconway.com> writes: > As a follow up, this works: > create OR REPLACE function retchar(text) > returns "char" Yes. This is even documented in a reasonably prominent place, ie the definition of "char" at the bottom of http://www.ca.postgresql.org/users-lounge/docs/7.2/postgres/datatype-character.html To wit: the single-byte char type must be spelled "char" (with the double quotes), not char (which is defined by SQL92 as character(1), a completely different type). This is pretty ugly, but I don't see a way to migrate to something less confusing without breaking lots of existing code. regards, tom lane