Re: user defined type

Поиск
Список
Период
Сортировка
От Michael Fuhr
Тема Re: user defined type
Дата
Msg-id 20041109180725.GA31357@winnie.fuhr.org
обсуждение исходный текст
Ответ на Re: user defined type  (Kjetil Haaland <kjetil.haaland@student.uib.no>)
Ответы Re: user defined type  (Kjetil Haaland <kjetil.haaland@student.uib.no>)
Список 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 по дате отправления:

Предыдущее
От: Michael Fuhr
Дата:
Сообщение: Re: Getting a trigger to call a function...
Следующее
От: Kumar S
Дата:
Сообщение: VACUUM ANALYZE : Is this a time consuming procedure?