Re: user defined type

From: Michael Fuhr <mike(at)fuhr(dot)org>
To: Kjetil Haaland <kjetil(dot)haaland(at)student(dot)uib(dot)no>
Cc: pgsql-novice(at)postgresql(dot)org
Subject: Re: user defined type
Date: 2004-11-09 18:07:25
Message-ID: 20041109180725.GA31357@winnie.fuhr.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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/

In response to

Responses

Browse pgsql-novice by date

  From Date Subject
Next Message Kumar S 2004-11-09 20:34:47 VACUUM ANALYZE : Is this a time consuming procedure?
Previous Message Venkateswaran Udayasankar 2004-11-09 16:52:58 Question on stored proecdure parameter