Subject: variable size data types..

From: [email-masked] (Bruce Taneja.)
Date: Tue, 7 Jun 1994 02:03:54 -0400 (EDT)

Howdy Paul & folks,

Dunno if this is a more of a C question than a postgres question
but since it concerns postgres's variable user defined (array) 
data types, here goes:

example:

	typedef struct {

		int size; 	/* size of this mem glob */
		int n_points;	/* number of points struct nested */
		POINT points[1];/* the first one*/
		int n_circles;	/* the number of circles */
		CIRCLE circles[1]; /* the 1st one*/

		} CIRCLES_N_POINTS;

Next step is to parse my append statement and decide how much space
I require to palloc, once I have determined that and palloced that
space, I start putting the points in : points[0], points[1], points[2]
.. and similarly parsed circles data in circles[0], circles[1], ...

Understandably, the space for these "arrays" is being sliced out of
the palloced glob of memory ..

Now what is the guarantee that C does not write my circles "array"
data over my points "array" data ??? 

The way I see it , C can distinctly identify the CIRCLES_N_POINTS struct
but not the contiguous space following the struct, so both times when
we start to write in locations points[1] and circles[1], the same space
lying right after the struct is going to be used overwriting the previous
data .. or am I (happily) mistaken?..

and, if I am (sadly) right, then what is the solution to having two complex 
variable sized arrays in your defined variable size complex data type?

Perhaps the C gurus or postgres gurus would like to educate the dumb
old me ..
 
thanx for help in advance!
Bruce!

==============================================================================
   To add/remove yourself to/from the POSTGRES mailing list: send mail with 
   the subject line ADD or DEL to "[email-masked]"

   If this fails, send mail to "[email-masked]" and
   a human will deal with it.  DO NOT post to the "postgres" mailing list.
==============================================================================

---

From: Jolly Chen <[email-masked]>
Date: Tue, 07 Jun 1994 16:05:28 -0700

> Perhaps the C gurus or postgres gurus would like to educate the dumb

One way to accomplish this is to swizzle the pointers explicitly
yourself.  So, you can do something like:

typedef struct {
 		int size; 	/* size of this mem glob */
 		int n_points;	/* number of points struct nested */
		POINT* points;
 		int n_circles;	/* the number of circles */
		CIRCLE* circles;
		char blob;  /* space holder for variable sized storage */
 		} CIRCLES_N_POINTS;
 
When you palloc space for the structure, you need to account for
the space needed by the variable-length arrays of points and circles.
(You also should be careful of architecture-specific alignment padding
that may be needed)

Then, in your adt code, you need to "swizzle" your pointers whenever you
get the data structure back from the database. Based on the other fields
in your structure, you can calculate how far to offset into the blob
field for your pointers.    For example, you may do 

	CIRCLES_N_POINTS* c;
	
	c->points = c->blob;
	c->circles = c->blob + n_points * sizeof(POINT);

or something like that. 

After you've manually swizzled the pointers, you can use the pointer
fields normally.  Since your storage was palloc'd in one chunk, as long
as you have your size stated corrected, postgres will store your entire
contiguous hunk of bytes as your adt.  Just be sure to swizzle your
pointers everytime you get the adt out of the database, because the
unswizzled fields are meaningless when you first read them out of the
database. 

- Jolly Chen