Обсуждение: returning CHAR from C function

Поиск
Список
Период
Сортировка

returning CHAR from C function

От
elein
Дата:
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.

Re: returning CHAR from C function

От
Joe Conway
Дата:
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



Re: returning CHAR from C function

От
Joe Conway
Дата:
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



Re: returning CHAR from C function

От
elein
Дата:
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.

Re: returning CHAR from C function

От
Tom Lane
Дата:
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