By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
438,372 Members | 1,950 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 438,372 IT Pros & Developers. It's quick & easy.

C Programming with postgres.h - my function crashes the database backend

P: n/a
I've been trying to extend Postgres and create an enumerated type to
represent gender, as a precursor to more complex enumerated types. I've
created the C functions for input and output with the following code:

- ---- gender.c -----
#include "server/postgres.h"
#include <string.h>
#include "server/fmgr.h"

PG_FUNCTION_INFO_V1(enum_gender_in);

Datum enum_gender_in(PG_FUNCTION_ARGS) {
text *invalue = PG_GETARG_TEXT_P(0);

if ( strcmp ( VARDATA(invalue), "Male" ) ) { /* VARDATA gets the data portion of a "varlena" struct, which is typedef'd to "text" */
PG_RETURN_INT32( 0 );
}
PG_RETURN_INT32( 1 );
}

PG_FUNCTION_INFO_V1(enum_gender_out);

Datum enum_gender_out(PG_FUNCTION_ARGS) {
int32 internal = PG_GETARG_INT32(0);
text *outvalue;

if ( internal == 0 ) {
int32 male_struct_size = 5 * sizeof(char) + VARHDRSZ; /* Five characters ('Male\0') plus int32 */
outvalue = (text *) palloc ( male_struct_size );
VARATT_SIZEP(outvalue) = male_struct_size;
memcpy(VARDATA(outvalue), "Male\0", 5);
} else {
int32 female_struct_size = 7 * sizeof(char) + VARHDRSZ; /* Five characters ('Female\0') plus int32 */
outvalue = (text *) palloc ( female_struct_size );
VARATT_SIZEP(outvalue) = female_struct_size;
memcpy(VARDATA(outvalue), "Female\0", 5);
}
PG_RETURN_TEXT_P (outvalue);
}
- ---- end of gender.c -----

Once I've compiled this to a shared library file with no errors or
warnings (even with -Wall), I can load these functions in psql
without error, and create a table with the appropriate type:

test=# CREATE FUNCTION enum_gender_in (cstring) RETURNS enum_gender IMMUTABLE STRICT AS '/home/alex/epic/gender.so' LANGUAGE C;
NOTICE: ProcedureCreate: type enum_gender is not yet defined
CREATE FUNCTION

test=# CREATE FUNCTION enum_gender_out (enum_gender) RETURNS cstring IMMUTABLE STRICT AS '/home/alex/epic/gender.so' LANGUAGE C;
NOTICE: Argument type "enum_gender" is only a shell
CREATE FUNCTION

test=# CREATE TYPE enum_gender (
test(# INPUT = enum_gender_in,
test(# OUTPUT = enum_gender_out,
test(# INTERNALLENGTH = 2,
test(# PASSEDBYVALUE
test(# );
CREATE TYPE

test=# CREATE TABLE people (
test(# id serial,
test(# name text,
test(# gender enum_gender
test(# );
NOTICE: CREATE TABLE will create implicit sequence 'people_id_seq' for SERIAL column 'people.id'
CREATE TABLE

So far so good. However, the real problem comes when I try to insert
something into the table I've just created:

test=# INSERT INTO people (name, gender) VALUES ('Alex', 'Male');
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
!#

I'm fairly sure there's a bug in my C code somewhere, but I can't spot
it. Admittedly, my C is pretty rusty, and I've not been able to find any
useful documentation for the internal C structures in postgres, other
than the source code itself. Any links to HOWTOs or similar would also
be appreciated.

Can I request a feature enhancement of built-in enumerated types for Postgres? ;)

Alex
--
Mail: Alex Page <al*******@cancer.org.uk>
Real: Systems/Network Assistant, Epidemiology Unit, Oxford
Tel: 01865 302 223 (external) / 223 (internal)
PGP: 8868 21D7 3D35 DD77 9D06 BF0A 0746 2DE6 55EA 367E

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)

iD8DBQE/zNJdB0Yt5lXqNn4RAqXCAJoCfoEvJTLZcXss0b4acrdMkhAIAg CgqXEa
Wt8/m0Y/8vJRF3dzE9FCeM4=
=DXlV
-----END PGP SIGNATURE-----

Nov 12 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
On Tue, Dec 02, 2003 at 05:56:45PM +0000, Alex Page wrote:
Datum enum_gender_in(PG_FUNCTION_ARGS) {
text *invalue = PG_GETARG_TEXT_P(0);

if ( strcmp ( VARDATA(invalue), "Male" ) ) { /* VARDATA gets the data portion of a "varlena" struct, which is typedef'd to "text" */
PG_RETURN_INT32( 0 );
}
PG_RETURN_INT32( 1 );
}


VARDATA is not 0-terminated, so you can't use strcmp on it. Maybe you
should use memcmp instead.

--
Alvaro Herrera (<alvherre[a]dcc.uchile.cl>)
"Nunca se desea ardientemente lo que solo se desea por razón" (F. Alexandre)

---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to ma*******@postgresql.org

Nov 12 '05 #2

P: n/a
>
Datum enum_gender_in(PG_FUNCTION_ARGS) {
text *invalue = PG_GETARG_TEXT_P(0);

PG_FUNCTION_INFO_V1(enum_gender_out);

Datum enum_gender_out(PG_FUNCTION_ARGS) {
PG_RETURN_TEXT_P (outvalue);
}


IN function takes a C-string, not a text and
OUT functions should return C-string, not a text.
--
Teodor Sigaev E-mail: te****@sigaev.ru
---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/docs/faqs/FAQ.html

Nov 12 '05 #3

P: n/a
Alvaro Herrera wrote:
On Tue, Dec 02, 2003 at 05:56:45PM +0000, Alex Page wrote:
Datum enum_gender_in(PG_FUNCTION_ARGS) {
text *invalue = PG_GETARG_TEXT_P(0);

if ( strcmp ( VARDATA(invalue), "Male" ) ) { /* VARDATA gets the data portion of a "varlena" struct, which is typedef'd to "text" */
PG_RETURN_INT32( 0 );
}
PG_RETURN_INT32( 1 );
}


VARDATA is not 0-terminated, so you can't use strcmp on it. Maybe you
should use memcmp instead.


First of all, the argument to a type input procedure is a nul terminated
CString, not text.

Alex, why don't you look at an existing datatype in backend/utils/adt?
Jan

--
#================================================= =====================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#================================================= = Ja******@Yahoo.com #
---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
joining column's datatypes do not match

Nov 12 '05 #4

P: n/a
On Tue, Dec 02, 2003 at 01:54:06PM -0500, Jan Wieck wrote:
First of all, the argument to a type input procedure is a nul terminated
CString, not text.
Oops! Thanks for that, I'll see if I can get this working now.
Alex, why don't you look at an existing datatype in backend/utils/adt?


I don't seem to have this file in my Postgres installation. Is it
available somewhere?

Alex
--
Mail: Alex Page <al*******@cancer.org.uk>
Real: Systems/Network Assistant, Epidemiology Unit, Oxford
Tel: 01865 302 223 (external) / 223 (internal)
PGP: 8868 21D7 3D35 DD77 9D06 BF0A 0746 2DE6 55EA 367E

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)

iD8DBQE/zhYXB0Yt5lXqNn4RAjrfAKC7EH3cAco5AFzdMAye9M0aWWxgww CfXUP3
tyMgVkW6KlUwDylfCW9Nt+o=
=GFo5
-----END PGP SIGNATURE-----

Nov 12 '05 #5

P: n/a
Alex Page wrote:
On Tue, Dec 02, 2003 at 01:54:06PM -0500, Jan Wieck wrote:
First of all, the argument to a type input procedure is a nul terminated
CString, not text.


Oops! Thanks for that, I'll see if I can get this working now.
Alex, why don't you look at an existing datatype in backend/utils/adt?


I don't seem to have this file in my Postgres installation. Is it
available somewhere?


It is the directory of the PostgreSQL source tree where all the builtin
data types live and you can find it here:

http://developer.postgresql.org/cvsw...end/utils/adt/
Jan

--
#================================================= =====================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#================================================= = Ja******@Yahoo.com #
---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

Nov 12 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.