Re: user defined type - Mailing list pgsql-novice
From | Michael Fuhr |
---|---|
Subject | Re: user defined type |
Date | |
Msg-id | 20041109180725.GA31357@winnie.fuhr.org Whole thread Raw |
In response to | Re: user defined type (Kjetil Haaland <kjetil.haaland@student.uib.no>) |
Responses |
Re: user defined type
|
List | pgsql-novice |
On Tue, Nov 09, 2004 at 01:38:29PM +0100, Kjetil Haaland wrote: > On Monday 08 November 2004 22:24, Michael Fuhr wrote: > > On Mon, Nov 08, 2004 at 01:26:55PM +0100, Kjetil Haaland wrote: > > > typedef struct alignres { > > > int value; > > > char *fstring; > > > }alignres; > > > > If you want to store character data, I think the characters must > > be stored in the structure itself; I don't think using a pointer > > will work (somebody please correct me if I'm mistaken). So instead > > of "char *fstring" you'll need "char fstring[x]", where "x" is the > > maximum size of the character data. You could also use "char fstring[1]" > > and allocate the alignres structure to be as big as necessary; if > > you do that then you might want to review the paragraph regarding > > TOAST-able types near the end of the "User-Defined Types" section > > of the documentation. > > > > http://www.postgresql.org/docs/7.4/static/xtypes.html > > > > Make sure your CREATE TYPE statement has "internallength" set > > correctly: either to the fixed size of the structure (including > > character data) or to "variable". If you use "variable" then make > > sure you add the required length field to the beginning of the > > structure. See the CREATE TYPE documentation for more info. > I want to use the fstring[1] way, because i don't know how large > my string will be. You say that i can allocate the hole structure, > where should i do this? in the in-data-function? Yes, in alignres_in() you'd allocate enough memory to hold all of the data: the size of the structure plus the length of the string. If you don't mind a little waste then here's a simple way to do it: char *in = PG_GETARG_CSTRING(0); alignres *result; result = palloc(sizeof(*result) + strlen(in)); (Note that the compiler evalutes sizeof(*result), so you don't have to worry that you're dereferencing an unassigned pointer at run time. This syntax removes the need to specify the type name again, which eases maintenance.) I don't think you need to add an extra byte to allow for the string's terminating NUL because sizeof(*result) already accounts for one byte of the string (and probably a little extra, due to alignment). Double-check my thinking, though, and add an extra byte if you think it's necessary. > It also says in the documentation that if I use the random for > internallength when i create my type I have to set the length in > the structure. Is this set in the declaration of the structure or > in some of the methods? The internallength specification is "variable", not "random." The length is an int32 at the beginning of the data: typedef struct alignres { int32 length; int value; char fstring[1]; } alignres; Before returning, set the length field to the total size of the data. Here's where I think you could eliminate any wasted space that you allocated -- after you've parsed the data you know exactly how long fstring is, so you could add only that much to sizeof(*result): result->length = sizeof(*result) + strlen(fstring); Again, I don't think you need to add an extra byte to account for the string's terminating NUL because sizeof(*result) already includes one byte for the string. -- Michael Fuhr http://www.fuhr.org/~mfuhr/
pgsql-novice by date: