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
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? |