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

From: Alex Page <alex(dot)page(at)cancer(dot)org(dot)uk>
To: pgsql-general(at)postgresql(dot)org
Subject: C Programming with postgres.h - my function crashes the database backend
Date: 2003-12-02 17:56:45
Message-ID: 20031202175645.GW22296@halcyon.ox.icnet.uk
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

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 <alex(dot)page(at)cancer(dot)org(dot)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

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Randolf Richardson 2003-12-02 18:05:13 Re: PostgreSQL Advocacy, Thoughts and Comments
Previous Message Franco Bruno Borghesi 2003-12-02 17:31:11 Re: how many quotes?