Fwd: [GENERAL] returning CHAR from C function

Started by eleinover 23 years ago5 messagesbugs
Jump to latest
#1elein
elein@sbcglobal.net

Joe Conway confirmed this problem and said that it seems
that the function definition is rewritten to return
1042 (==bpchar), instead of type 18 (==char).

The workaround is to change the SQL definition to have
the function return "char" instead of char (no quotes).

I think it is still a bug, though not high priority since it has
a workaround.

elein@varlena.com

---------- Forwarded Message ----------

Subject: [GENERAL] returning CHAR from C function
Date: Sat, 30 Nov 2002 14:55:43 -0800
From: elein <elein@sbcglobal.net>
To: pgsql-general@postgresql.org
Cc: elein@varlena.com

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.

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: elein (#1)
Re: Fwd: [GENERAL] returning CHAR from C function

elein <elein@sbcglobal.net> writes:

I think it is still a bug,

Not unless you can define an upward-compatible migration path to some
non-spec-conflicting typename (I'd favor char1, if we were going to
rename the type).

regards, tom lane

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: elein (#1)
Re: Fwd: [GENERAL] returning CHAR from C function

elein <elein@sbcglobal.net> writes:

I think I do not know the background on this.

I think it's mostly historical. The one-byte "char" datatype seems to
date back to Berkeley days, long before there was any concern for SQL
compliance (it's there in Postgres 4.2). "bpchar" was apparently added
in Postgres95 in order to provide SQL-like functionality --- but they
didn't pay any attention to duplicating the SQL name for it. The
keyword CHARACTER was added later, translating it to the internal name
bpchar in the parser. Eventually the keyword CHAR was added too, and
translated.

The real question at this point is what would break if we renamed "char"
to "char1". Since it's used extensively in the system catalogs, I'm
sure there would be some unhappiness involved. I am dubious that
merely avoiding confusion is a sufficient reason to change.

regards, tom lane

#4elein
elein@sbcglobal.net
In reply to: Tom Lane (#2)
Re: Fwd: [GENERAL] returning CHAR from C function

I think I do not know the background on this.
Could you explain why the char type is converted
to bpchar when a function is defined to return a char?
Are only C functions affected? Is char as a type deprecated
in favor of bpchar? Should something in the fmgr interface
change to support this?

I thought that char was always one character and
char(n) was similar to varchar(n) but with different
semantics wrt spaces. char1 works for me if char
is really usurped by bpchar.

We can take it off line except personal mail from me
to you tends to bounce. I just want to understand this.

Thanks,
elein
elein@varlena.com

On Saturday 30 November 2002 20:44, you wrote:

elein <elein@sbcglobal.net> writes:

I think it is still a bug,

Not unless you can define an upward-compatible migration path to some
non-spec-conflicting typename (I'd favor char1, if we were going to
rename the type).

regards, tom lane

--
----------------------------------------------------------------------------------------
elein@varlena.com Database Consulting www.varlena.com
I have always depended on the [QA] of strangers.

#5elein
elein@sbcglobal.net
In reply to: Tom Lane (#3)
Re: Fwd: [GENERAL] returning CHAR from C function

Thanks. This is helpful. The only inconsistency
on the postgresql side is the PG_RETURN_CHAR which does return
the one character, not the bpchar. Perhaps a PG_RETURN_CHAR1
or PG_RETURN_CHAR_REALLY would help. I think the only people
who would get caught with it as it is are those writing C functions to return
one character chars, so obviously documentation should be able
to solve the inconsistency as well.

elein

On Sunday 01 December 2002 16:54, Tom Lane wrote:

elein <elein@sbcglobal.net> writes:

I think I do not know the background on this.

I think it's mostly historical. The one-byte "char" datatype seems to
date back to Berkeley days, long before there was any concern for SQL
compliance (it's there in Postgres 4.2). "bpchar" was apparently added
in Postgres95 in order to provide SQL-like functionality --- but they
didn't pay any attention to duplicating the SQL name for it. The
keyword CHARACTER was added later, translating it to the internal name
bpchar in the parser. Eventually the keyword CHAR was added too, and
translated.

The real question at this point is what would break if we renamed "char"
to "char1". Since it's used extensively in the system catalogs, I'm
sure there would be some unhappiness involved. I am dubious that
merely avoiding confusion is a sufficient reason to change.

regards, tom lane

---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to majordomo@postgresql.org so that your
message can get through to the mailing list cleanly

--
----------------------------------------------------------------------------------------
elein@varlena.com Database Consulting www.varlena.com
I have always depended on the [QA] of strangers.