From ad8f54cdb5776146f17d1038bb295b5f13b549f1 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Mon, 16 Feb 2015 03:53:38 +0900
Subject: [PATCH 3/3] Update varlena in c.h to use FLEXIBLE_ARRAY_MEMBER

Places using a variable-length variable not at the end of a structure
are changed with workaround, without impacting what those features do.
---
 src/backend/access/heap/tuptoaster.c       | 16 ++++++------
 src/backend/storage/large_object/inv_api.c | 40 ++++++++++++++----------------
 src/include/c.h                            |  2 +-
 src/include/catalog/pg_authid.h            |  8 +++---
 4 files changed, 31 insertions(+), 35 deletions(-)

diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index f8c1401..a8f178c 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -1365,12 +1365,7 @@ toast_save_datum(Relation rel, Datum value,
 	CommandId	mycid = GetCurrentCommandId(true);
 	struct varlena *result;
 	struct varatt_external toast_pointer;
-	struct
-	{
-		struct varlena hdr;
-		char		data[TOAST_MAX_CHUNK_SIZE]; /* make struct big enough */
-		int32		align_it;	/* ensure struct is aligned well enough */
-	}			chunk_data;
+	struct varlena *chunk_data;
 	int32		chunk_size;
 	int32		chunk_seq = 0;
 	char	   *data_p;
@@ -1381,6 +1376,9 @@ toast_save_datum(Relation rel, Datum value,
 
 	Assert(!VARATT_IS_EXTERNAL(value));
 
+	chunk_data = (struct varlena *)
+		palloc(MAXALIGN(TOAST_MAX_CHUNK_SIZE + VARHDRSZ));
+
 	/*
 	 * Open the toast relation and its indexes.  We can use the index to check
 	 * uniqueness of the OID we assign to the toasted item, even though it has
@@ -1523,7 +1521,7 @@ toast_save_datum(Relation rel, Datum value,
 	 * Initialize constant parts of the tuple data
 	 */
 	t_values[0] = ObjectIdGetDatum(toast_pointer.va_valueid);
-	t_values[2] = PointerGetDatum(&chunk_data);
+	t_values[2] = PointerGetDatum(chunk_data);
 	t_isnull[0] = false;
 	t_isnull[1] = false;
 	t_isnull[2] = false;
@@ -1546,8 +1544,8 @@ toast_save_datum(Relation rel, Datum value,
 		 * Build a tuple and store it
 		 */
 		t_values[1] = Int32GetDatum(chunk_seq++);
-		SET_VARSIZE(&chunk_data, chunk_size + VARHDRSZ);
-		memcpy(VARDATA(&chunk_data), data_p, chunk_size);
+		SET_VARSIZE(chunk_data, chunk_size + VARHDRSZ);
+		memcpy(VARDATA(chunk_data), data_p, chunk_size);
 		toasttup = heap_form_tuple(toasttupDesc, t_values, t_isnull);
 
 		heap_insert(toastrel, toasttup, mycid, options, NULL);
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index a19c401..b44fae7 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -562,13 +562,8 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 	bool		neednextpage;
 	bytea	   *datafield;
 	bool		pfreeit;
-	struct
-	{
-		bytea		hdr;
-		char		data[LOBLKSIZE];	/* make struct big enough */
-		int32		align_it;	/* ensure struct is aligned well enough */
-	}			workbuf;
-	char	   *workb = VARDATA(&workbuf.hdr);
+	bytea	   *workbuf;
+	char	   *workb;
 	HeapTuple	newtup;
 	Datum		values[Natts_pg_largeobject];
 	bool		nulls[Natts_pg_largeobject];
@@ -591,6 +586,9 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 				 errmsg("invalid large object write request size: %d",
 						nbytes)));
 
+	workbuf = (bytea *) palloc(MAXALIGN(LOBLKSIZE + VARHDRSZ));
+	workb = VARDATA(workbuf);
+
 	open_lo_relation();
 
 	indstate = CatalogOpenIndexes(lo_heap_r);
@@ -664,7 +662,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 			off += n;
 			/* compute valid length of new page */
 			len = (len >= off) ? len : off;
-			SET_VARSIZE(&workbuf.hdr, len + VARHDRSZ);
+			SET_VARSIZE(workbuf, len + VARHDRSZ);
 
 			/*
 			 * Form and insert updated tuple
@@ -672,7 +670,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 			memset(values, 0, sizeof(values));
 			memset(nulls, false, sizeof(nulls));
 			memset(replace, false, sizeof(replace));
-			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
+			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(workbuf);
 			replace[Anum_pg_largeobject_data - 1] = true;
 			newtup = heap_modify_tuple(oldtuple, RelationGetDescr(lo_heap_r),
 									   values, nulls, replace);
@@ -708,7 +706,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 			obj_desc->offset += n;
 			/* compute valid length of new page */
 			len = off + n;
-			SET_VARSIZE(&workbuf.hdr, len + VARHDRSZ);
+			SET_VARSIZE(workbuf, len + VARHDRSZ);
 
 			/*
 			 * Form and insert updated tuple
@@ -717,7 +715,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
 			memset(nulls, false, sizeof(nulls));
 			values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id);
 			values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno);
-			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
+			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(workbuf);
 			newtup = heap_form_tuple(lo_heap_r->rd_att, values, nulls);
 			simple_heap_insert(lo_heap_r, newtup);
 			CatalogIndexInsert(indstate, newtup);
@@ -748,13 +746,8 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 	SysScanDesc sd;
 	HeapTuple	oldtuple;
 	Form_pg_largeobject olddata;
-	struct
-	{
-		bytea		hdr;
-		char		data[LOBLKSIZE];	/* make struct big enough */
-		int32		align_it;	/* ensure struct is aligned well enough */
-	}			workbuf;
-	char	   *workb = VARDATA(&workbuf.hdr);
+	bytea	   *workbuf;
+	char	   *workb;
 	HeapTuple	newtup;
 	Datum		values[Natts_pg_largeobject];
 	bool		nulls[Natts_pg_largeobject];
@@ -776,6 +769,9 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 				 errmsg_internal("invalid large object truncation target: " INT64_FORMAT,
 								 len)));
 
+	workbuf = (bytea *) palloc(MAXALIGN(LOBLKSIZE + VARHDRSZ));
+	workb = VARDATA(workbuf);
+
 	open_lo_relation();
 
 	indstate = CatalogOpenIndexes(lo_heap_r);
@@ -834,7 +830,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 			MemSet(workb + pagelen, 0, off - pagelen);
 
 		/* compute length of new page */
-		SET_VARSIZE(&workbuf.hdr, off + VARHDRSZ);
+		SET_VARSIZE(workbuf, off + VARHDRSZ);
 
 		/*
 		 * Form and insert updated tuple
@@ -842,7 +838,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 		memset(values, 0, sizeof(values));
 		memset(nulls, false, sizeof(nulls));
 		memset(replace, false, sizeof(replace));
-		values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
+		values[Anum_pg_largeobject_data - 1] = PointerGetDatum(workbuf);
 		replace[Anum_pg_largeobject_data - 1] = true;
 		newtup = heap_modify_tuple(oldtuple, RelationGetDescr(lo_heap_r),
 								   values, nulls, replace);
@@ -873,7 +869,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 			MemSet(workb, 0, off);
 
 		/* compute length of new page */
-		SET_VARSIZE(&workbuf.hdr, off + VARHDRSZ);
+		SET_VARSIZE(workbuf, off + VARHDRSZ);
 
 		/*
 		 * Form and insert new tuple
@@ -882,7 +878,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
 		memset(nulls, false, sizeof(nulls));
 		values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id);
 		values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno);
-		values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
+		values[Anum_pg_largeobject_data - 1] = PointerGetDatum(workbuf);
 		newtup = heap_form_tuple(lo_heap_r->rd_att, values, nulls);
 		simple_heap_insert(lo_heap_r, newtup);
 		CatalogIndexInsert(indstate, newtup);
diff --git a/src/include/c.h b/src/include/c.h
index bbd0d53..36ec468 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -391,7 +391,7 @@ typedef struct
 struct varlena
 {
 	char		vl_len_[4];		/* Do not touch this field directly! */
-	char		vl_dat[1];
+	char		vl_dat[FLEXIBLE_ARRAY_MEMBER];
 };
 
 #define VARHDRSZ		((int32) sizeof(int32))
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index e01e6aa..d8789a5 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -56,8 +56,10 @@ CATALOG(pg_authid,1260) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2842) BKI_SCHEMA_MAC
 	int32		rolconnlimit;	/* max connections allowed (-1=no limit) */
 
 	/* remaining fields may be null; use heap_getattr to read them! */
-	text		rolpassword;	/* password, if any */
 	timestamptz rolvaliduntil;	/* password expiration time, if any */
+#ifdef CATALOG_VARLEN
+	text		rolpassword;	/* password, if any */
+#endif
 } FormData_pg_authid;
 
 #undef timestamptz
@@ -85,8 +87,8 @@ typedef FormData_pg_authid *Form_pg_authid;
 #define Anum_pg_authid_rolreplication	8
 #define Anum_pg_authid_rolbypassrls		9
 #define Anum_pg_authid_rolconnlimit		10
-#define Anum_pg_authid_rolpassword		11
-#define Anum_pg_authid_rolvaliduntil	12
+#define Anum_pg_authid_rolvaliduntil	11
+#define Anum_pg_authid_rolpassword		12
 
 /* ----------------
  *		initial contents of pg_authid
-- 
2.3.0

