diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 54e787bb206da692df5f7f1f42ea31d33f88abdc..bb646807c575c7aa85dedabbb3e3499ffb66c5ab 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -73,6 +73,7 @@ static HTAB *createConnHash(void);
 static void createNewConnection(const char *name, remoteConn * rconn);
 static void deleteConnection(const char *name);
 static char **get_pkey_attnames(Oid relid, int16 *numatts);
+static char **get_text_array_contents(ArrayType *array, int *numitems);
 static char *get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
 static char *get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pkattvals);
 static char *get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
@@ -1120,29 +1121,18 @@ PG_FUNCTION_INFO_V1(dblink_build_sql_insert);
 Datum
 dblink_build_sql_insert(PG_FUNCTION_ARGS)
 {
+	text	   *relname_text = PG_GETARG_TEXT_P(0);
+	int2vector *pkattnums = (int2vector *) PG_GETARG_POINTER(1);
+	int32		pknumatts_tmp = PG_GETARG_INT32(2);
+	ArrayType  *src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
+	ArrayType  *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
 	Oid			relid;
-	text	   *relname_text;
-	int2vector *pkattnums;
-	int			pknumatts_tmp;
 	int16		pknumatts = 0;
 	char	  **src_pkattvals;
 	char	  **tgt_pkattvals;
-	ArrayType  *src_pkattvals_arry;
-	ArrayType  *tgt_pkattvals_arry;
-	int			src_ndim;
-	int		   *src_dim;
 	int			src_nitems;
-	int			tgt_ndim;
-	int		   *tgt_dim;
 	int			tgt_nitems;
-	int			i;
-	char	   *ptr;
 	char	   *sql;
-	int16		typlen;
-	bool		typbyval;
-	char		typalign;
-
-	relname_text = PG_GETARG_TEXT_P(0);
 
 	/*
 	 * Convert relname to rel OID.
@@ -1154,34 +1144,27 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
 				 errmsg("relation \"%s\" does not exist",
 						GET_STR(relname_text))));
 
-	pkattnums = (int2vector *) PG_GETARG_POINTER(1);
-	pknumatts_tmp = PG_GETARG_INT32(2);
-	if (pknumatts_tmp <= SHRT_MAX)
-		pknumatts = pknumatts_tmp;
-	else
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("input for number of primary key " \
-						"attributes too large")));
-
 	/*
 	 * There should be at least one key attribute
 	 */
-	if (pknumatts == 0)
+	if (pknumatts_tmp <= 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("number of key attributes must be > 0")));
 
-	src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
-	tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
+	if (pknumatts_tmp <= SHRT_MAX)
+		pknumatts = pknumatts_tmp;
+	else
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("input for number of primary key " \
+						"attributes too large")));
 
 	/*
 	 * Source array is made up of key values that will be used to locate the
 	 * tuple of interest from the local system.
 	 */
-	src_ndim = ARR_NDIM(src_pkattvals_arry);
-	src_dim = ARR_DIMS(src_pkattvals_arry);
-	src_nitems = ArrayGetNItems(src_ndim, src_dim);
+	src_pkattvals = get_text_array_contents(src_pkattvals_arry, &src_nitems);
 
 	/*
 	 * There should be one source array key value for each key attnum
@@ -1192,29 +1175,11 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
 				 errmsg("source key array length must match number of key " \
 						"attributes")));
 
-	/*
-	 * get array of pointers to c-strings from the input source array
-	 */
-	Assert(ARR_ELEMTYPE(src_pkattvals_arry) == TEXTOID);
-	get_typlenbyvalalign(ARR_ELEMTYPE(src_pkattvals_arry),
-						 &typlen, &typbyval, &typalign);
-
-	src_pkattvals = (char **) palloc(src_nitems * sizeof(char *));
-	ptr = ARR_DATA_PTR(src_pkattvals_arry);
-	for (i = 0; i < src_nitems; i++)
-	{
-		src_pkattvals[i] = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(ptr)));
-		ptr = att_addlength(ptr, typlen, PointerGetDatum(ptr));
-		ptr = (char *) att_align(ptr, typalign);
-	}
-
 	/*
 	 * Target array is made up of key values that will be used to build the
 	 * SQL string for use on the remote system.
 	 */
-	tgt_ndim = ARR_NDIM(tgt_pkattvals_arry);
-	tgt_dim = ARR_DIMS(tgt_pkattvals_arry);
-	tgt_nitems = ArrayGetNItems(tgt_ndim, tgt_dim);
+	tgt_pkattvals = get_text_array_contents(tgt_pkattvals_arry, &tgt_nitems);
 
 	/*
 	 * There should be one target array key value for each key attnum
@@ -1225,22 +1190,6 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
 				 errmsg("target key array length must match number of key " \
 						"attributes")));
 
-	/*
-	 * get array of pointers to c-strings from the input target array
-	 */
-	Assert(ARR_ELEMTYPE(tgt_pkattvals_arry) == TEXTOID);
-	get_typlenbyvalalign(ARR_ELEMTYPE(tgt_pkattvals_arry),
-						 &typlen, &typbyval, &typalign);
-
-	tgt_pkattvals = (char **) palloc(tgt_nitems * sizeof(char *));
-	ptr = ARR_DATA_PTR(tgt_pkattvals_arry);
-	for (i = 0; i < tgt_nitems; i++)
-	{
-		tgt_pkattvals[i] = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(ptr)));
-		ptr = att_addlength(ptr, typlen, PointerGetDatum(ptr));
-		ptr = (char *) att_align(ptr, typalign);
-	}
-
 	/*
 	 * Prep work is finally done. Go get the SQL string.
 	 */
@@ -1272,24 +1221,15 @@ PG_FUNCTION_INFO_V1(dblink_build_sql_delete);
 Datum
 dblink_build_sql_delete(PG_FUNCTION_ARGS)
 {
+	text	   *relname_text = PG_GETARG_TEXT_P(0);
+	int2vector *pkattnums = (int2vector *) PG_GETARG_POINTER(1);
+	int32		pknumatts_tmp = PG_GETARG_INT32(2);
+	ArrayType  *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
 	Oid			relid;
-	text	   *relname_text;
-	int2vector *pkattnums;
-	int			pknumatts_tmp;
 	int16		pknumatts = 0;
 	char	  **tgt_pkattvals;
-	ArrayType  *tgt_pkattvals_arry;
-	int			tgt_ndim;
-	int		   *tgt_dim;
 	int			tgt_nitems;
-	int			i;
-	char	   *ptr;
 	char	   *sql;
-	int16		typlen;
-	bool		typbyval;
-	char		typalign;
-
-	relname_text = PG_GETARG_TEXT_P(0);
 
 	/*
 	 * Convert relname to rel OID.
@@ -1301,33 +1241,27 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
 				 errmsg("relation \"%s\" does not exist",
 						GET_STR(relname_text))));
 
-	pkattnums = (int2vector *) PG_GETARG_POINTER(1);
-	pknumatts_tmp = PG_GETARG_INT32(2);
-	if (pknumatts_tmp <= SHRT_MAX)
-		pknumatts = pknumatts_tmp;
-	else
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("input for number of primary key " \
-						"attributes too large")));
-
 	/*
 	 * There should be at least one key attribute
 	 */
-	if (pknumatts == 0)
+	if (pknumatts_tmp <= 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("number of key attributes must be > 0")));
 
-	tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
+	if (pknumatts_tmp <= SHRT_MAX)
+		pknumatts = pknumatts_tmp;
+	else
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("input for number of primary key " \
+						"attributes too large")));
 
 	/*
 	 * Target array is made up of key values that will be used to build the
 	 * SQL string for use on the remote system.
 	 */
-	tgt_ndim = ARR_NDIM(tgt_pkattvals_arry);
-	tgt_dim = ARR_DIMS(tgt_pkattvals_arry);
-	tgt_nitems = ArrayGetNItems(tgt_ndim, tgt_dim);
+	tgt_pkattvals = get_text_array_contents(tgt_pkattvals_arry, &tgt_nitems);
 
 	/*
 	 * There should be one target array key value for each key attnum
@@ -1338,22 +1272,6 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
 				 errmsg("target key array length must match number of key " \
 						"attributes")));
 
-	/*
-	 * get array of pointers to c-strings from the input target array
-	 */
-	Assert(ARR_ELEMTYPE(tgt_pkattvals_arry) == TEXTOID);
-	get_typlenbyvalalign(ARR_ELEMTYPE(tgt_pkattvals_arry),
-						 &typlen, &typbyval, &typalign);
-
-	tgt_pkattvals = (char **) palloc(tgt_nitems * sizeof(char *));
-	ptr = ARR_DATA_PTR(tgt_pkattvals_arry);
-	for (i = 0; i < tgt_nitems; i++)
-	{
-		tgt_pkattvals[i] = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(ptr)));
-		ptr = att_addlength(ptr, typlen, PointerGetDatum(ptr));
-		ptr = (char *) att_align(ptr, typalign);
-	}
-
 	/*
 	 * Prep work is finally done. Go get the SQL string.
 	 */
@@ -1389,29 +1307,18 @@ PG_FUNCTION_INFO_V1(dblink_build_sql_update);
 Datum
 dblink_build_sql_update(PG_FUNCTION_ARGS)
 {
+	text	   *relname_text = PG_GETARG_TEXT_P(0);
+	int2vector *pkattnums = (int2vector *) PG_GETARG_POINTER(1);
+	int32		pknumatts_tmp = PG_GETARG_INT32(2);
+	ArrayType  *src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
+	ArrayType  *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
 	Oid			relid;
-	text	   *relname_text;
-	int2vector *pkattnums;
-	int			pknumatts_tmp;
 	int16		pknumatts = 0;
 	char	  **src_pkattvals;
 	char	  **tgt_pkattvals;
-	ArrayType  *src_pkattvals_arry;
-	ArrayType  *tgt_pkattvals_arry;
-	int			src_ndim;
-	int		   *src_dim;
 	int			src_nitems;
-	int			tgt_ndim;
-	int		   *tgt_dim;
 	int			tgt_nitems;
-	int			i;
-	char	   *ptr;
 	char	   *sql;
-	int16		typlen;
-	bool		typbyval;
-	char		typalign;
-
-	relname_text = PG_GETARG_TEXT_P(0);
 
 	/*
 	 * Convert relname to rel OID.
@@ -1423,34 +1330,27 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
 				 errmsg("relation \"%s\" does not exist",
 						GET_STR(relname_text))));
 
-	pkattnums = (int2vector *) PG_GETARG_POINTER(1);
-	pknumatts_tmp = PG_GETARG_INT32(2);
-	if (pknumatts_tmp <= SHRT_MAX)
-		pknumatts = pknumatts_tmp;
-	else
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("input for number of primary key " \
-						"attributes too large")));
-
 	/*
 	 * There should be one source array key values for each key attnum
 	 */
-	if (pknumatts == 0)
+	if (pknumatts_tmp <= 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("number of key attributes must be > 0")));
 
-	src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
-	tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
+	if (pknumatts_tmp <= SHRT_MAX)
+		pknumatts = pknumatts_tmp;
+	else
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("input for number of primary key " \
+						"attributes too large")));
 
 	/*
 	 * Source array is made up of key values that will be used to locate the
 	 * tuple of interest from the local system.
 	 */
-	src_ndim = ARR_NDIM(src_pkattvals_arry);
-	src_dim = ARR_DIMS(src_pkattvals_arry);
-	src_nitems = ArrayGetNItems(src_ndim, src_dim);
+	src_pkattvals = get_text_array_contents(src_pkattvals_arry, &src_nitems);
 
 	/*
 	 * There should be one source array key value for each key attnum
@@ -1461,29 +1361,11 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
 				 errmsg("source key array length must match number of key " \
 						"attributes")));
 
-	/*
-	 * get array of pointers to c-strings from the input source array
-	 */
-	Assert(ARR_ELEMTYPE(src_pkattvals_arry) == TEXTOID);
-	get_typlenbyvalalign(ARR_ELEMTYPE(src_pkattvals_arry),
-						 &typlen, &typbyval, &typalign);
-
-	src_pkattvals = (char **) palloc(src_nitems * sizeof(char *));
-	ptr = ARR_DATA_PTR(src_pkattvals_arry);
-	for (i = 0; i < src_nitems; i++)
-	{
-		src_pkattvals[i] = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(ptr)));
-		ptr = att_addlength(ptr, typlen, PointerGetDatum(ptr));
-		ptr = (char *) att_align(ptr, typalign);
-	}
-
 	/*
 	 * Target array is made up of key values that will be used to build the
 	 * SQL string for use on the remote system.
 	 */
-	tgt_ndim = ARR_NDIM(tgt_pkattvals_arry);
-	tgt_dim = ARR_DIMS(tgt_pkattvals_arry);
-	tgt_nitems = ArrayGetNItems(tgt_ndim, tgt_dim);
+	tgt_pkattvals = get_text_array_contents(tgt_pkattvals_arry, &tgt_nitems);
 
 	/*
 	 * There should be one target array key value for each key attnum
@@ -1494,22 +1376,6 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
 				 errmsg("target key array length must match number of key " \
 						"attributes")));
 
-	/*
-	 * get array of pointers to c-strings from the input target array
-	 */
-	Assert(ARR_ELEMTYPE(tgt_pkattvals_arry) == TEXTOID);
-	get_typlenbyvalalign(ARR_ELEMTYPE(tgt_pkattvals_arry),
-						 &typlen, &typbyval, &typalign);
-
-	tgt_pkattvals = (char **) palloc(tgt_nitems * sizeof(char *));
-	ptr = ARR_DATA_PTR(tgt_pkattvals_arry);
-	for (i = 0; i < tgt_nitems; i++)
-	{
-		tgt_pkattvals[i] = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(ptr)));
-		ptr = att_addlength(ptr, typlen, PointerGetDatum(ptr));
-		ptr = (char *) att_align(ptr, typalign);
-	}
-
 	/*
 	 * Prep work is finally done. Go get the SQL string.
 	 */
@@ -1598,6 +1464,67 @@ get_pkey_attnames(Oid relid, int16 *numatts)
 	return result;
 }
 
+/*
+ * Deconstruct a text[] into C-strings (note any NULL elements will be
+ * returned as NULL pointers)
+ */
+static char **
+get_text_array_contents(ArrayType *array, int *numitems)
+{
+	int			ndim = ARR_NDIM(array);
+	int		   *dims = ARR_DIMS(array);
+	int			nitems;
+	int16		typlen;
+	bool		typbyval;
+	char		typalign;
+	char	  **values;
+	char	   *ptr;
+	bits8	   *bitmap;
+	int			bitmask;
+	int			i;
+
+	Assert(ARR_ELEMTYPE(array) == TEXTOID);
+
+	*numitems = nitems = ArrayGetNItems(ndim, dims);
+
+	get_typlenbyvalalign(ARR_ELEMTYPE(array),
+						 &typlen, &typbyval, &typalign);
+
+	values = (char **) palloc(nitems * sizeof(char *));
+
+	ptr = ARR_DATA_PTR(array);
+	bitmap = ARR_NULLBITMAP(array);
+	bitmask = 1;
+
+	for (i = 0; i < nitems; i++)
+	{
+		if (bitmap && (*bitmap & bitmask) == 0)
+		{
+			values[i] = NULL;
+		}
+		else
+		{
+			values[i] = DatumGetCString(DirectFunctionCall1(textout,
+														PointerGetDatum(ptr)));
+			ptr = att_addlength(ptr, typlen, PointerGetDatum(ptr));
+			ptr = (char *) att_align(ptr, typalign);
+		}
+
+		/* advance bitmap pointer if any */
+		if (bitmap)
+		{
+			bitmask <<= 1;
+			if (bitmask == 0x100)
+			{
+				bitmap++;
+				bitmask = 1;
+			}
+		}
+	}
+
+	return values;
+}
+
 static char *
 get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
 {
@@ -1665,7 +1592,7 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 			key = -1;
 
 		if (key > -1)
-			val = pstrdup(tgt_pkattvals[key]);
+			val = tgt_pkattvals[key] ? pstrdup(tgt_pkattvals[key]) : NULL;
 		else
 			val = SPI_getvalue(tuple, tupdesc, i + 1);
 
@@ -1697,7 +1624,6 @@ get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pka
 	int			natts;
 	StringInfo	str = makeStringInfo();
 	char	   *sql;
-	char	   *val = NULL;
 	int			i;
 
 	/* get relation name including any needed schema prefix and quoting */
@@ -1721,17 +1647,13 @@ get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pka
 		appendStringInfo(str, "%s",
 		   quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));
 
-		if (tgt_pkattvals != NULL)
-			val = pstrdup(tgt_pkattvals[i]);
-		else
+		if (tgt_pkattvals == NULL)
 			/* internal error */
 			elog(ERROR, "target key array must not be NULL");
 
-		if (val != NULL)
-		{
-			appendStringInfo(str, " = %s", quote_literal_cstr(val));
-			pfree(val);
-		}
+		if (tgt_pkattvals[i] != NULL)
+			appendStringInfo(str, " = %s",
+							 quote_literal_cstr(tgt_pkattvals[i]));
 		else
 			appendStringInfo(str, " IS NULL");
 	}
@@ -1795,7 +1717,7 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 			key = -1;
 
 		if (key > -1)
-			val = pstrdup(tgt_pkattvals[key]);
+			val = tgt_pkattvals[key] ?  pstrdup(tgt_pkattvals[key]) : NULL;
 		else
 			val = SPI_getvalue(tuple, tupdesc, i + 1);
 
@@ -1822,7 +1744,7 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 		   quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));
 
 		if (tgt_pkattvals != NULL)
-			val = pstrdup(tgt_pkattvals[i]);
+			val = tgt_pkattvals[i] ?  pstrdup(tgt_pkattvals[i]) : NULL;
 		else
 			val = SPI_getvalue(tuple, tupdesc, pkattnum);
 
@@ -1905,7 +1827,6 @@ get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **
 	int			ret;
 	HeapTuple	tuple;
 	int			i;
-	char	   *val = NULL;
 
 	/* get relation name including any needed schema prefix and quoting */
 	relname = generate_relation_name(relid);
@@ -1940,12 +1861,9 @@ get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **
 		appendStringInfo(str, "%s",
 		   quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));
 
-		val = pstrdup(src_pkattvals[i]);
-		if (val != NULL)
-		{
-			appendStringInfo(str, " = %s", quote_literal_cstr(val));
-			pfree(val);
-		}
+		if (src_pkattvals[i] != NULL)
+			appendStringInfo(str, " = %s",
+							 quote_literal_cstr(src_pkattvals[i]));
 		else
 			appendStringInfo(str, " IS NULL");
 	}
diff --git a/contrib/tsearch2/rank.c b/contrib/tsearch2/rank.c
index e678b205d624cbc4a489e1e4518f9f93904158e0..d5cb777401785e4d2c34303fc869ab39b9362f85 100644
--- a/contrib/tsearch2/rank.c
+++ b/contrib/tsearch2/rank.c
@@ -3,20 +3,20 @@
  * Teodor Sigaev <teodor@sigaev.ru>
  */
 #include "postgres.h"
+
 #include <math.h>
 
 #include "access/gist.h"
 #include "access/itup.h"
-#include "utils/builtins.h"
+#include "catalog/namespace.h"
+#include "commands/trigger.h"
+#include "executor/spi.h"
 #include "fmgr.h"
 #include "funcapi.h"
-#include "storage/bufpage.h"
-#include "executor/spi.h"
-#include "commands/trigger.h"
 #include "nodes/pg_list.h"
-#include "catalog/namespace.h"
-
+#include "storage/bufpage.h"
 #include "utils/array.h"
+#include "utils/builtins.h"
 
 #include "tsvector.h"
 #include "query.h"
@@ -354,6 +354,7 @@ rank(PG_FUNCTION_ARGS)
 	int			method = DEF_NORM_METHOD;
 	float		res = 0.0;
 	float		ws[lengthof(weights)];
+	float4	   *arrdata;
 	int			i;
 
 	if (ARR_NDIM(win) != 1)
@@ -366,9 +367,15 @@ rank(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 				 errmsg("array of weight is too short")));
 
+	if (ARR_HASNULL(win))
+		ereport(ERROR,
+				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+				 errmsg("array of weight must not contain nulls")));
+
+	arrdata = (float4 *) ARR_DATA_PTR(win);
 	for (i = 0; i < lengthof(weights); i++)
 	{
-		ws[i] = (((float4 *) ARR_DATA_PTR(win))[i] >= 0) ? ((float4 *) ARR_DATA_PTR(win))[i] : weights[i];
+		ws[i] = (arrdata[i] >= 0) ? arrdata[i] : weights[i];
 		if (ws[i] > 1.0)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
diff --git a/contrib/tsearch2/snowball/header.h b/contrib/tsearch2/snowball/header.h
index ad07388154ce0b9e24d00d9ffc3c6918c388d57c..3889ede53e6ba01ddf9c0ff2e9f103fcd4a379ae 100644
--- a/contrib/tsearch2/snowball/header.h
+++ b/contrib/tsearch2/snowball/header.h
@@ -3,9 +3,6 @@
 
 #include "api.h"
 
-#define MAXINT INT_MAX
-#define MININT INT_MIN
-
 #define HEAD 2*sizeof(int)
 
 #define SIZE(p)		   ((int *)(p))[-1]
diff --git a/contrib/tsearch2/ts_cfg.c b/contrib/tsearch2/ts_cfg.c
index a1fcf0b4f27e730b8c485008dd14010d0d3d026f..50a355e464a1b49c4933e33b5db219aff30f7237 100644
--- a/contrib/tsearch2/ts_cfg.c
+++ b/contrib/tsearch2/ts_cfg.c
@@ -113,6 +113,8 @@ init_cfg(Oid id, TSCfgInfo * cfg)
 			ts_error(ERROR, "Wrong dimension");
 		if (ARRNELEMS(a) < 1)
 			continue;
+		if (ARR_HASNULL(a))
+			ts_error(ERROR, "Array must not contain nulls");
 
 		cfg->map[lexid].len = ARRNELEMS(a);
 		cfg->map[lexid].dict_id = (Datum *) malloc(sizeof(Datum) * cfg->map[lexid].len);
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index a1080b59f6083d4fc44d4d85fb66bd93ff0f3457..9282c417d0110bab5e4f2c2c15a6b3769f2647a1 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.128 2005/11/17 22:14:52 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.129 2005/11/18 02:38:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -67,6 +67,7 @@ static List *cached_membership_roles = NIL;
 static const char *getid(const char *s, char *n);
 static void putid(char *p, const char *s);
 static Acl *allocacl(int n);
+static void check_acl(const Acl *acl);
 static const char *aclparse(const char *s, AclItem *aip);
 static bool aclitem_match(const AclItem *a1, const AclItem *a2);
 static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
@@ -359,6 +360,26 @@ allocacl(int n)
 	return new_acl;
 }
 
+/*
+ * Verify that an ACL array is acceptable (one-dimensional and has no nulls)
+ */
+static void
+check_acl(const Acl *acl)
+{
+	if (ARR_ELEMTYPE(acl) != ACLITEMOID)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("ACL array contains wrong datatype")));
+	if (ARR_NDIM(acl) != 1)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("ACL arrays must be one-dimensional")));
+	if (ARR_HASNULL(acl))
+		ereport(ERROR,
+				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+				 errmsg("ACL arrays must not contain nulls")));
+}
+
 /*
  * aclitemin
  *		Allocates storage for, and fills in, a new AclItem given a string
@@ -612,15 +633,8 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
 	int			dst,
 				num;
 
-	/* These checks for null input are probably dead code, but... */
-	if (!old_acl || ACL_NUM(old_acl) < 0)
-		old_acl = allocacl(0);
-	if (!mod_aip)
-	{
-		new_acl = allocacl(ACL_NUM(old_acl));
-		memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
-		return new_acl;
-	}
+	/* Caller probably already checked old_acl, but be safe */
+	check_acl(old_acl);
 
 	/* If granting grant options, check for circularity */
 	if (modechg != ACL_MODECHG_DEL &&
@@ -740,6 +754,8 @@ aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
 				targ,
 				num;
 
+	check_acl(old_acl);
+
 	/*
 	 * Make a copy of the given ACL, substituting new owner ID for old
 	 * wherever it appears as either grantor or grantee.  Also note if the new
@@ -836,6 +852,8 @@ check_circularity(const Acl *old_acl, const AclItem *mod_aip,
 				num;
 	AclMode		own_privs;
 
+	check_acl(old_acl);
+
 	/*
 	 * For now, grant options can only be granted to roles, not PUBLIC.
 	 * Otherwise we'd have to work a bit harder here.
@@ -916,6 +934,8 @@ recursive_revoke(Acl *acl,
 	int			i,
 				num;
 
+	check_acl(acl);
+
 	/* The owner can never truly lose grant options, so short-circuit */
 	if (grantee == ownerId)
 		return acl;
@@ -1005,6 +1025,8 @@ aclmask(const Acl *acl, Oid roleid, Oid ownerId,
 	if (acl == NULL)
 		elog(ERROR, "null ACL");
 
+	check_acl(acl);
+
 	/* Quick exit for mask == 0 */
 	if (mask == 0)
 		return 0;
@@ -1091,6 +1113,8 @@ aclmask_direct(const Acl *acl, Oid roleid, Oid ownerId,
 	if (acl == NULL)
 		elog(ERROR, "null ACL");
 
+	check_acl(acl);
+
 	/* Quick exit for mask == 0 */
 	if (mask == 0)
 		return 0;
@@ -1151,6 +1175,8 @@ aclmembers(const Acl *acl, Oid **roleids)
 		return 0;
 	}
 
+	check_acl(acl);
+
 	/* Allocate the worst-case space requirement */
 	list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
 	acldat = ACL_DAT(acl);
@@ -1240,6 +1266,7 @@ aclcontains(PG_FUNCTION_ARGS)
 	int			i,
 				num;
 
+	check_acl(acl);
 	num = ACL_NUM(acl);
 	aidat = ACL_DAT(acl);
 	for (i = 0; i < num; ++i)
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 1f6c176f640b209c37b6b33ff70ce77828452c74..dd877c7d3f0b9c8a9f002eef1919537be505d383 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.139 2005/10/29 00:31:51 petere Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.140 2005/11/18 02:38:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2491,16 +2491,18 @@ array_to_text(PG_FUNCTION_ARGS)
 	int			nitems,
 			   *dims,
 				ndims;
-	char	   *p;
 	Oid			element_type;
 	int			typlen;
 	bool		typbyval;
 	char		typalign;
 	StringInfo	result_str = makeStringInfo();
+	bool		printed = false;
+	char	   *p;
+	bits8	   *bitmap;
+	int			bitmask;
 	int			i;
 	ArrayMetaState *my_extra;
 
-	p = ARR_DATA_PTR(v);
 	ndims = ARR_NDIM(v);
 	dims = ARR_DIMS(v);
 	nitems = ArrayGetNItems(ndims, dims);
@@ -2522,7 +2524,7 @@ array_to_text(PG_FUNCTION_ARGS)
 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
 													  sizeof(ArrayMetaState));
 		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-		my_extra->element_type = InvalidOid;
+		my_extra->element_type = ~element_type;
 	}
 
 	if (my_extra->element_type != element_type)
@@ -2542,23 +2544,47 @@ array_to_text(PG_FUNCTION_ARGS)
 	typbyval = my_extra->typbyval;
 	typalign = my_extra->typalign;
 
+	p = ARR_DATA_PTR(v);
+	bitmap = ARR_NULLBITMAP(v);
+	bitmask = 1;
+
 	for (i = 0; i < nitems; i++)
 	{
 		Datum		itemvalue;
 		char	   *value;
 
-		itemvalue = fetch_att(p, typbyval, typlen);
+		/* Get source element, checking for NULL */
+		if (bitmap && (*bitmap & bitmask) == 0)
+		{
+			/* we ignore nulls */
+		}
+		else
+		{
+			itemvalue = fetch_att(p, typbyval, typlen);
 
-		value = DatumGetCString(FunctionCall1(&my_extra->proc,
-											  itemvalue));
+			value = DatumGetCString(FunctionCall1(&my_extra->proc,
+												  itemvalue));
 
-		if (i > 0)
-			appendStringInfo(result_str, "%s%s", fldsep, value);
-		else
-			appendStringInfoString(result_str, value);
+			if (printed)
+				appendStringInfo(result_str, "%s%s", fldsep, value);
+			else
+				appendStringInfoString(result_str, value);
+			printed = true;
+
+			p = att_addlength(p, typlen, PointerGetDatum(p));
+			p = (char *) att_align(p, typalign);
+		}
 
-		p = att_addlength(p, typlen, PointerGetDatum(p));
-		p = (char *) att_align(p, typalign);
+		/* advance bitmap pointer if any */
+		if (bitmap)
+		{
+			bitmask <<= 1;
+			if (bitmask == 0x100)
+			{
+				bitmap++;
+				bitmask = 1;
+			}
+		}
 	}
 
 	PG_RETURN_TEXT_P(PG_STR_GET_TEXT(result_str->data));
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index c668382ba31b113c53af2c24aa5ccc22510d085d..8699913eb95cf1a1e7be656e3ccd42846c36d4df 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.87 2005/11/17 22:14:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.88 2005/11/18 02:38:24 tgl Exp $
  *
  * NOTES
  *	  An ACL array is simply an array of AclItems, representing the union
@@ -78,9 +78,9 @@ typedef struct AclItem
 #define ACLITEM_ALL_GOPTION_BITS	((AclMode) 0xFFFF << 16)
 
 /*
- * Definitions for convenient access to Acl (array of AclItem) and IdList
- * (array of Oid).	These are standard PostgreSQL arrays, but are restricted
- * to have one dimension.  We also ignore the lower bound when reading,
+ * Definitions for convenient access to Acl (array of AclItem).
+ * These are standard PostgreSQL arrays, but are restricted to have one
+ * dimension and no nulls.  We also ignore the lower bound when reading,
  * and set it to one when writing.
  *
  * CAUTION: as of PostgreSQL 7.1, these arrays are toastable (just like all
@@ -100,16 +100,6 @@ typedef ArrayType Acl;
 #define ACL_N_SIZE(N)			(ARR_OVERHEAD_NONULLS(1) + ((N) * sizeof(AclItem)))
 #define ACL_SIZE(ACL)			ARR_SIZE(ACL)
 
-/*
- * IdList		a one-dimensional array of Oid
- */
-typedef ArrayType IdList;
-
-#define IDLIST_NUM(IDL)			(ARR_DIMS(IDL)[0])
-#define IDLIST_DAT(IDL)			((Oid *) ARR_DATA_PTR(IDL))
-#define IDLIST_N_SIZE(N)		(ARR_OVERHEAD_NONULLS(1) + ((N) * sizeof(Oid)))
-#define IDLIST_SIZE(IDL)		ARR_SIZE(IDL)
-
 /*
  * fmgr macros for these types
  */
@@ -123,13 +113,6 @@ typedef ArrayType IdList;
 #define PG_GETARG_ACL_P_COPY(n)    DatumGetAclPCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_ACL_P(x)		   PG_RETURN_POINTER(x)
 
-#define DatumGetIdListP(X)		   ((IdList *) PG_DETOAST_DATUM(X))
-#define DatumGetIdListPCopy(X)	   ((IdList *) PG_DETOAST_DATUM_COPY(X))
-#define PG_GETARG_IDLIST_P(n)	   DatumGetIdListP(PG_GETARG_DATUM(n))
-#define PG_GETARG_IDLIST_P_COPY(n) DatumGetIdListPCopy(PG_GETARG_DATUM(n))
-#define PG_RETURN_IDLIST_P(x)	   PG_RETURN_POINTER(x)
-
-
 /*
  * ACL modification opcodes for aclupdate
  */
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 608854cbb5fba4adeebbea6755f35725c26ea762..58f6d814b8f9bd6300506180ea01fa11e9cdc9c0 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.155 2005/11/17 22:14:55 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.156 2005/11/18 02:38:24 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -3241,8 +3241,7 @@ exec_assign_value(PLpgSQL_execstate * estate,
 				int			i;
 				PLpgSQL_expr *subscripts[MAXDIM];
 				int			subscriptvals[MAXDIM];
-				bool		havenullsubscript,
-							oldarrayisnull;
+				bool		oldarrayisnull;
 				Oid			arraytypeid,
 							arrayelemtypeid;
 				int16		arraytyplen,
@@ -3295,9 +3294,9 @@ exec_assign_value(PLpgSQL_execstate * estate,
 				arraytyplen = get_typlen(arraytypeid);
 
 				/*
-				 * Evaluate the subscripts, switch into left-to-right order
+				 * Evaluate the subscripts, switch into left-to-right order.
+				 * Like ExecEvalArrayRef(), complain if any subscript is null.
 				 */
-				havenullsubscript = false;
 				for (i = 0; i < nsubscripts; i++)
 				{
 					bool		subisnull;
@@ -3306,43 +3305,39 @@ exec_assign_value(PLpgSQL_execstate * estate,
 						exec_eval_integer(estate,
 										  subscripts[nsubscripts - 1 - i],
 										  &subisnull);
-					havenullsubscript |= subisnull;
+					if (subisnull)
+						ereport(ERROR,
+								(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+								 errmsg("array subscript in assignment must not be NULL")));
 				}
 
-				/*
-				 * Skip the assignment if we have any nulls in the subscripts
-				 * or the righthand side. This is pretty bogus but it
-				 * corresponds to the current behavior of ExecEvalArrayRef().
-				 */
-				if (havenullsubscript || *isNull)
-					return;
+				/* Coerce source value to match array element type. */
+				coerced_value = exec_simple_cast_value(value,
+													   valtype,
+													   arrayelemtypeid,
+													   -1,
+													   *isNull);
 
 				/*
 				 * If the original array is null, cons up an empty array so
 				 * that the assignment can proceed; we'll end with a
 				 * one-element array containing just the assigned-to
 				 * subscript.  This only works for varlena arrays, though; for
-				 * fixed-length array types we skip the assignment. Again,
-				 * this corresponds to the current behavior of
+				 * fixed-length array types we skip the assignment.  We can't
+				 * support assignment of a null entry into a fixed-length
+				 * array, either, so that's a no-op too.  This is all ugly
+				 * but corresponds to the current behavior of
 				 * ExecEvalArrayRef().
 				 */
-				if (oldarrayisnull)
-				{
-					if (arraytyplen > 0)		/* fixed-length array? */
-						return;
+				if (arraytyplen > 0 &&		/* fixed-length array? */
+					(oldarrayisnull || *isNull))
+					return;
 
+				if (oldarrayisnull)
 					oldarrayval = construct_empty_array(arrayelemtypeid);
-				}
 				else
 					oldarrayval = (ArrayType *) DatumGetPointer(oldarraydatum);
 
-				/* Coerce source value to match array element type. */
-				coerced_value = exec_simple_cast_value(value,
-													   valtype,
-													   arrayelemtypeid,
-													   -1,
-													   *isNull);
-
 				/*
 				 * Build the modified array value.
 				 */