C Programming with postgres.h - my function crashes the database backend - Mailing list pgsql-general
From | Alex Page |
---|---|
Subject | C Programming with postgres.h - my function crashes the database backend |
Date | |
Msg-id | 20031202175645.GW22296@halcyon.ox.icnet.uk Whole thread Raw |
Responses |
Re: C Programming with postgres.h - my function crashes the database backend
Re: C Programming with postgres.h - my function crashes |
List | 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 istypedef'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' LANGUAGEC; 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' LANGUAGEC; 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.page@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
Attachment
pgsql-general by date: