Index: postgis/lwgeom_geos.c
===================================================================
--- postgis/lwgeom_geos.c	(revision 4200)
+++ postgis/lwgeom_geos.c	(working copy)
@@ -107,10 +107,13 @@
 	GEOSGeometry * geos_result=NULL;
 	int SRID=-1;
 	size_t offset = 0;
+	bits8 *bitmap;
+	int bitmask;
 #if POSTGIS_DEBUG_LEVEL > 0
 	static int call=1;
 #endif
 #if POSTGIS_GEOS_VERSION >= 31
+	int gotsrid = 0;
 	int allpolys=1;
 #endif
 
@@ -128,12 +131,21 @@
 
 	nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
 
+	bitmap = ARR_NULLBITMAP(array);
+
 	POSTGIS_DEBUGF(3, "unite_garray: number of elements: %d", nelems);
 
 	if ( nelems == 0 ) PG_RETURN_NULL();
 
 	/* One-element union is the element itself */
-	if ( nelems == 1 ) PG_RETURN_POINTER((PG_LWGEOM *)(ARR_DATA_PTR(array)));
+	if ( nelems == 1 )
+	{
+		/* If the element is a NULL then we need to handle it separately */
+		if (bitmap && (*bitmap & 1) == 0)
+			PG_RETURN_NULL();
+		else
+			PG_RETURN_POINTER((PG_LWGEOM *)(ARR_DATA_PTR(array)));
+	}
 
 	/* Ok, we really need geos now ;) */
 	initGEOS(lwnotice, lwnotice);
@@ -145,20 +157,43 @@
 	** If they are, we can use UnionCascaded for faster results.
 	*/
 	offset = 0;
+	bitmask = 1;
+	gotsrid = 0;
 	for ( i = 0; i < nelems; i++ )
 	{
-		PG_LWGEOM *pggeom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
-		int pgtype = TYPE_GETTYPE(pggeom->type);
-		offset += INTALIGN(VARSIZE(pggeom));
-		if ( ! i ) /* Initialize SRID */
+		/* Don't do anything for NULL values */
+		if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap)
 		{
-			SRID = pglwgeom_getSRID(pggeom);
-			if ( TYPE_HASZ(pggeom->type) ) is3d = 1;
+			PG_LWGEOM *pggeom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
+			int pgtype = TYPE_GETTYPE(pggeom->type);
+			offset += INTALIGN(VARSIZE(pggeom));
+			if ( ! gotsrid ) /* Initialize SRID */
+			{
+				SRID = pglwgeom_getSRID(pggeom);
+				gotsrid = 1;
+				if ( TYPE_HASZ(pggeom->type) ) is3d = 1;
+			}
+			else
+			{
+				errorIfSRIDMismatch(SRID, pglwgeom_getSRID(pggeom));
+			}
+
+			if ( pgtype != POLYGONTYPE && pgtype != MULTIPOLYGONTYPE )
+			{
+				allpolys = 0;
+				break;
+			}
 		}
-		if ( pgtype != POLYGONTYPE && pgtype != MULTIPOLYGONTYPE )
-		{
-			allpolys = 0;
-			break;
+
+		/* Advance NULL bitmap */
+		if (bitmap)
+                {
+			bitmask <<= 1;
+			if (bitmask == 0x100)
+			{
+				bitmap++;
+				bitmask = 1;
+			}
 		}
 	}
 
@@ -176,59 +211,83 @@
 		** First make an array of GEOS Polygons.
 		*/
 		offset = 0;
+		bitmap = ARR_NULLBITMAP(array);
+		bitmask = 1;
 		for ( i = 0; i < nelems; i++ )
 		{
-			PG_LWGEOM *pggeom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
-			int pgtype = TYPE_GETTYPE(pggeom->type);
-			offset += INTALIGN(VARSIZE(pggeom));
-			if ( pgtype == POLYGONTYPE )
+			/* Don't do anything for NULL values */
+			if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap)
 			{
-				if ( curgeom == geoms_size )
+				PG_LWGEOM *pggeom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
+				int pgtype = TYPE_GETTYPE(pggeom->type);
+				offset += INTALIGN(VARSIZE(pggeom));
+				if ( pgtype == POLYGONTYPE )
 				{
-					geoms_size *= 2;
-					geoms = repalloc( geoms, sizeof(GEOSGeom) * geoms_size );
-				}
-				geoms[curgeom] = (GEOSGeometry *)POSTGIS2GEOS(pggeom);
-				curgeom++;
-			}
-			if ( pgtype == MULTIPOLYGONTYPE )
-			{
-				int j = 0;
-				LWGEOM_INSPECTED *lwgeom = lwgeom_inspect(SERIALIZED_FORM(pggeom));
-				for ( j = 0; j < lwgeom->ngeometries; j++ )
-				{
-					LWPOLY *lwpoly = NULL;
-					int k = 0;
 					if ( curgeom == geoms_size )
 					{
 						geoms_size *= 2;
 						geoms = repalloc( geoms, sizeof(GEOSGeom) * geoms_size );
 					}
-					/* This builds a LWPOLY on top of the serialized form */
-					lwpoly = lwgeom_getpoly_inspected(lwgeom, j);
-					geoms[curgeom] = LWGEOM2GEOS(lwpoly_as_lwgeom(lwpoly));
-					/* We delicately free the LWPOLY and POINTARRAY structs, leaving the serialized form below untouched. */
-					for ( k = 0; k < lwpoly->nrings; k++ )
+					geoms[curgeom] = (GEOSGeometry *)POSTGIS2GEOS(pggeom);
+					curgeom++;
+				}
+				if ( pgtype == MULTIPOLYGONTYPE )
+				{
+					int j = 0;
+					LWGEOM_INSPECTED *lwgeom = lwgeom_inspect(SERIALIZED_FORM(pggeom));
+					for ( j = 0; j < lwgeom->ngeometries; j++ )
 					{
-						lwfree(lwpoly->rings[k]);
+						LWPOLY *lwpoly = NULL;
+						int k = 0;
+						if ( curgeom == geoms_size )
+						{
+							geoms_size *= 2;
+							geoms = repalloc( geoms, sizeof(GEOSGeom) * geoms_size );
+						}
+						/* This builds a LWPOLY on top of the serialized form */
+						lwpoly = lwgeom_getpoly_inspected(lwgeom, j);
+						geoms[curgeom] = LWGEOM2GEOS(lwpoly_as_lwgeom(lwpoly));
+						/* We delicately free the LWPOLY and POINTARRAY structs, leaving the serialized form below untouched. */
+						for ( k = 0; k < lwpoly->nrings; k++ )
+						{
+							lwfree(lwpoly->rings[k]);
+						}
+						lwpoly_release(lwpoly);
+						curgeom++;
 					}
-					lwpoly_release(lwpoly);
-					curgeom++;
 				}
 			}
 
+			/* Advance NULL bitmap */
+			if (bitmap)
+			{
+				bitmask <<= 1;
+				if (bitmask == 0x100)
+				{
+					bitmap++;
+					bitmask = 1;
+				}
+			}
 		}
 		/*
 		** Take our GEOS Polygons and turn them into a GEOS MultiPolygon,
 		** then pass that into cascaded union.
 		*/
-		g1 = GEOSGeom_createCollection(GEOS_MULTIPOLYGON, geoms, curgeom);
-		if ( g1 ) g2 = GEOSUnionCascaded(g1);
-		if ( g2 ) GEOSSetSRID(g2, SRID);
-		if ( g2 ) result = GEOS2POSTGIS(g2, is3d);
-		/* Clean up the mess. */
-		if ( g1 ) GEOSGeom_destroy((GEOSGeometry *)g1);
-		if ( g2 ) GEOSGeom_destroy(g2);
+		if (curgeom > 0)
+		{
+			g1 = GEOSGeom_createCollection(GEOS_MULTIPOLYGON, geoms, curgeom);
+			if ( g1 ) g2 = GEOSUnionCascaded(g1);
+			if ( g2 ) GEOSSetSRID(g2, SRID);
+			if ( g2 ) result = GEOS2POSTGIS(g2, is3d);
+			/* Clean up the mess. */
+			if ( g1 ) GEOSGeom_destroy((GEOSGeometry *)g1);
+			if ( g2 ) GEOSGeom_destroy(g2);
+		}
+		else
+		{
+			/* All we found were NULLs, so let's return NULL */
+			PG_RETURN_NULL();
+		}
 	}
 	else
 	{
@@ -237,51 +296,77 @@
 		** Heterogeneous result, let's slog through this one union at a time.
 		*/
 		offset = 0;
+		bitmap = ARR_NULLBITMAP(array);
+		bitmask = 1;
 		for (i=0; i<nelems; i++)
 		{
-			PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
-			offset += INTALIGN(VARSIZE(geom));
-
-			pgis_geom = geom;
-
-			POSTGIS_DEBUGF(3, "geom %d @ %p", i, geom);
-
-			/* Check is3d flag */
-			if ( TYPE_HASZ(geom->type) ) is3d = 1;
-
-			/* Check SRID homogeneity and initialize geos result */
-			if ( ! i )
+			/* Don't do anything for NULL values */
+			if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap)
 			{
-				geos_result = (GEOSGeometry *)POSTGIS2GEOS(geom);
-				SRID = pglwgeom_getSRID(geom);
-				POSTGIS_DEBUGF(3, "first geom is a %s", lwgeom_typename(TYPE_GETTYPE(geom->type)));
-				continue;
+				PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
+				offset += INTALIGN(VARSIZE(geom));
+	
+				pgis_geom = geom;
+	
+				POSTGIS_DEBUGF(3, "geom %d @ %p", i, geom);
+	
+				/* Check is3d flag */
+				if ( TYPE_HASZ(geom->type) ) is3d = 1;
+	
+				/* Check SRID homogeneity and initialize geos result */
+				if ( ! geos_result )
+				{
+					geos_result = (GEOSGeometry *)POSTGIS2GEOS(geom);
+					SRID = pglwgeom_getSRID(geom);
+					POSTGIS_DEBUGF(3, "first geom is a %s", lwgeom_typename(TYPE_GETTYPE(geom->type)));
+				}
+				else
+				{
+					errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom));
+	
+					g1 = POSTGIS2GEOS(pgis_geom);
+	
+					POSTGIS_DEBUGF(3, "unite_garray(%d): adding geom %d to union (%s)",
+						call, i, lwgeom_typename(TYPE_GETTYPE(geom->type)));
+	
+					g2 = GEOSUnion(g1, geos_result);
+					if ( g2 == NULL )
+					{
+						GEOSGeom_destroy((GEOSGeometry *)g1);
+						GEOSGeom_destroy((GEOSGeometry *)geos_result);
+						elog(ERROR,"GEOS union() threw an error!");
+					}
+					GEOSGeom_destroy((GEOSGeometry *)g1);
+					GEOSGeom_destroy((GEOSGeometry *)geos_result);
+					geos_result = g2;
+				}
 			}
-			else
-			{
-				errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom));
-			}
 
-			g1 = POSTGIS2GEOS(pgis_geom);
-
-			POSTGIS_DEBUGF(3, "unite_garray(%d): adding geom %d to union (%s)",
-			               call, i, lwgeom_typename(TYPE_GETTYPE(geom->type)));
-
-			g2 = GEOSUnion(g1, geos_result);
-			if ( g2 == NULL )
+			/* Advance NULL bitmap */
+			if (bitmap)
 			{
-				GEOSGeom_destroy((GEOSGeometry *)g1);
-				GEOSGeom_destroy((GEOSGeometry *)geos_result);
-				elog(ERROR,"GEOS union() threw an error!");
+				bitmask <<= 1;
+				if (bitmask == 0x100)
+				{
+					bitmap++;
+					bitmask = 1;
+				}
 			}
-			GEOSGeom_destroy((GEOSGeometry *)g1);
-			GEOSGeom_destroy((GEOSGeometry *)geos_result);
-			geos_result = g2;
+			
 		}
 
-		GEOSSetSRID(geos_result, SRID);
-		result = GEOS2POSTGIS(geos_result, is3d);
-		GEOSGeom_destroy(geos_result);
+		/* If geos_result is set then we found at least one non-NULL geometry */
+		if (geos_result)
+		{
+			GEOSSetSRID(geos_result, SRID);
+			result = GEOS2POSTGIS(geos_result, is3d);
+			GEOSGeom_destroy(geos_result);
+		}
+		else
+		{
+			/* All we found were NULLs, so let's return NULL */
+			PG_RETURN_NULL();
+		}
 
 #if POSTGIS_GEOS_VERSION >= 31
 	}
@@ -289,8 +374,8 @@
 
 	if ( result == NULL )
 	{
-		elog(ERROR, "Union returned a NULL geometry.");
-		PG_RETURN_NULL(); /* never get here */
+		/* Union returned a NULL geometry */
+		PG_RETURN_NULL();
 	}
 
 	PG_RETURN_POINTER(result);
@@ -2768,7 +2853,10 @@
 	GEOSGeometry *geos_result;
 	const GEOSGeometry **vgeoms;
 	int SRID=-1;
+	int cnt = 0;
 	size_t offset;
+	bits8 *bitmap;
+	int bitmask;
 #if POSTGIS_DEBUG_LEVEL >= 3
 	static int call=1;
 #endif
@@ -2795,33 +2883,51 @@
 
 	vgeoms = palloc(sizeof(GEOSGeometry *)*nelems);
 	offset = 0;
+	cnt = 0;
+	bitmap = ARR_NULLBITMAP(array);
+	bitmask = 1;
 	for (i=0; i<nelems; i++)
 	{
-		PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
-		offset += INTALIGN(VARSIZE(geom));
-
-		vgeoms[i] = (GEOSGeometry *)POSTGIS2GEOS(geom);
-		if ( ! i )
+		/* Don't do anything for NULL values */
+		if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap)
 		{
-			SRID = pglwgeom_getSRID(geom);
+			PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
+			offset += INTALIGN(VARSIZE(geom));
+	
+			vgeoms[cnt] = (GEOSGeometry *)POSTGIS2GEOS(geom);
+			if ( ! cnt )
+			{
+				SRID = pglwgeom_getSRID(geom);
+			}
+			else
+			{
+				if ( SRID != pglwgeom_getSRID(geom) )
+				{
+					elog(ERROR, "polygonize: operation on mixed SRID geometries");
+					PG_RETURN_NULL();
+				}
+			}
 		}
-		else
-		{
-			if ( SRID != pglwgeom_getSRID(geom) )
+
+		/* Advance NULL bitmap */
+		if (bitmap)
+                {
+			bitmask <<= 1;
+			if (bitmask == 0x100)
 			{
-				elog(ERROR, "polygonize: operation on mixed SRID geometries");
-				PG_RETURN_NULL();
+				bitmap++;
+				bitmask = 1;
 			}
 		}
 	}
 
 	POSTGIS_DEBUG(3, "polygonize_garray: invoking GEOSpolygonize");
 
-	geos_result = GEOSPolygonize(vgeoms, nelems);
+	geos_result = GEOSPolygonize(vgeoms, cnt);
 
 	POSTGIS_DEBUG(3, "polygonize_garray: GEOSpolygonize returned");
 
-	for (i=0; i<nelems; ++i) GEOSGeom_destroy((GEOSGeometry *)vgeoms[i]);
+	for (i=0; i<cnt; ++i) GEOSGeom_destroy((GEOSGeometry *)vgeoms[i]);
 	pfree(vgeoms);
 
 	if ( ! geos_result ) PG_RETURN_NULL();
Index: postgis/lwgeom_functions_basic.c
===================================================================
--- postgis/lwgeom_functions_basic.c	(revision 4200)
+++ postgis/lwgeom_functions_basic.c	(working copy)
@@ -1948,8 +1948,11 @@
 	unsigned int outtype;
 	int i;
 	int SRID=-1;
+	int cnt = 0;
 	size_t offset;
 	BOX2DFLOAT4 *box=NULL;
+	bits8 *bitmap;
+	int bitmask;
 
 	POSTGIS_DEBUG(2, "LWGEOM_collect_garray called.");
 
@@ -1989,83 +1992,107 @@
 	lwgeoms = palloc(sizeof(LWGEOM *)*nelems);
 	outtype = 0;
 	offset = 0;
+	cnt = 0;
+	bitmap = ARR_NULLBITMAP(array);
+	bitmask = 1;
+
 	for (i=0; i<nelems; i++)
 	{
-		PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
-		unsigned int intype = TYPE_GETTYPE(geom->type);
-
-		offset += INTALIGN(VARSIZE(geom));
-
-		lwgeoms[i] = lwgeom_deserialize(SERIALIZED_FORM(geom));
-
-		POSTGIS_DEBUGF(3, "LWGEOM_collect_garray: geom %d deserialized", i);
-
-		if ( ! i )
+		/* Don't do anything for NULL values */
+		if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap)
 		{
-			/* Get first geometry SRID */
-			SRID = lwgeoms[i]->SRID;
-
-			/* COMPUTE_BBOX WHEN_SIMPLE */
-			if ( lwgeoms[i]->bbox )
+			PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
+			unsigned int intype = TYPE_GETTYPE(geom->type);
+	
+			offset += INTALIGN(VARSIZE(geom));
+	
+			lwgeoms[cnt] = lwgeom_deserialize(SERIALIZED_FORM(geom));
+	
+			POSTGIS_DEBUGF(3, "LWGEOM_collect_garray: geom %d deserialized", i);
+	
+			if ( ! cnt )
 			{
-				box = box2d_clone(lwgeoms[i]->bbox);
+				/* Get first geometry SRID */
+				SRID = lwgeoms[cnt]->SRID;
+	
+				/* COMPUTE_BBOX WHEN_SIMPLE */
+				if ( lwgeoms[cnt]->bbox )
+				{
+					box = box2d_clone(lwgeoms[cnt]->bbox);
+				}
 			}
-		}
-		else
-		{
-			/* Check SRID homogeneity */
-			if ( lwgeoms[i]->SRID != SRID )
+			else
 			{
-				elog(ERROR,
-				     "Operation on mixed SRID geometries");
-				PG_RETURN_NULL();
-			}
-
-			/* COMPUTE_BBOX WHEN_SIMPLE */
-			if ( box )
-			{
-				if ( lwgeoms[i]->bbox )
+				/* Check SRID homogeneity */
+				if ( lwgeoms[cnt]->SRID != SRID )
 				{
-					box->xmin = LW_MIN(box->xmin, lwgeoms[i]->bbox->xmin);
-					box->ymin = LW_MIN(box->ymin, lwgeoms[i]->bbox->ymin);
-					box->xmax = LW_MAX(box->xmax, lwgeoms[i]->bbox->xmax);
-					box->ymax = LW_MAX(box->ymax, lwgeoms[i]->bbox->ymax);
+					elog(ERROR,
+					"Operation on mixed SRID geometries");
+					PG_RETURN_NULL();
 				}
-				else
+	
+				/* COMPUTE_BBOX WHEN_SIMPLE */
+				if ( box )
 				{
-					pfree(box);
-					box = NULL;
+					if ( lwgeoms[cnt]->bbox )
+					{
+						box->xmin = LW_MIN(box->xmin, lwgeoms[cnt]->bbox->xmin);
+						box->ymin = LW_MIN(box->ymin, lwgeoms[cnt]->bbox->ymin);
+						box->xmax = LW_MAX(box->xmax, lwgeoms[cnt]->bbox->xmax);
+						box->ymax = LW_MAX(box->ymax, lwgeoms[cnt]->bbox->ymax);
+					}
+					else
+					{
+						pfree(box);
+						box = NULL;
+					}
 				}
 			}
-		}
 
+			lwgeom_dropSRID(lwgeoms[cnt]);
+			lwgeom_drop_bbox(lwgeoms[cnt]);
+	
+			/* Output type not initialized */
+			if ( ! outtype )
+			{
+				/* Input is single, make multi */
+				if ( intype < 4 ) outtype = intype+3;
+				/* Input is multi, make collection */
+				else outtype = COLLECTIONTYPE;
+			}
+	
+			/* Input type not compatible with output */
+			/* make output type a collection */
+			else if ( outtype != COLLECTIONTYPE && intype != outtype-3 )
+			{
+				outtype = COLLECTIONTYPE;
+			}
 
-		lwgeom_dropSRID(lwgeoms[i]);
-		lwgeom_drop_bbox(lwgeoms[i]);
-
-		/* Output type not initialized */
-		if ( ! outtype )
-		{
-			/* Input is single, make multi */
-			if ( intype < 4 ) outtype = intype+3;
-			/* Input is multi, make collection */
-			else outtype = COLLECTIONTYPE;
+			/* Keep a count of the number of collection elements (no NULLs) */
+			cnt++;
 		}
 
-		/* Input type not compatible with output */
-		/* make output type a collection */
-		else if ( outtype != COLLECTIONTYPE && intype != outtype-3 )
-		{
-			outtype = COLLECTIONTYPE;
+		/* Advance NULL bitmap */
+		if (bitmap)
+                {
+			bitmask <<= 1;
+			if (bitmask == 0x100)
+			{
+				bitmap++;
+				bitmask = 1;
+			}
 		}
-
 	}
 
+	/* If we didn't find a non-NULL geometry, simply return NULL */
+	if ( ! cnt )
+		PG_RETURN_NULL();
+
 	POSTGIS_DEBUGF(3, "LWGEOM_collect_garray: outtype = %d", outtype);
 
 	outlwg = (LWGEOM *)lwcollection_construct(
 	             outtype, SRID,
-	             box, nelems, lwgeoms);
+	             box, cnt, lwgeoms);
 
 	result = pglwgeom_serialize(outlwg);
 
@@ -2129,6 +2156,8 @@
 	int i;
 	size_t offset;
 	int SRID=-1;
+	bits8 *bitmap;
+	int bitmask;
 
 	POSTGIS_DEBUG(2, "LWGEOM_makeline_garray called.");
 
@@ -2169,34 +2198,51 @@
 	lwpoints = palloc(sizeof(LWGEOM *)*nelems);
 	npoints = 0;
 	offset = 0;
+	bitmap = ARR_NULLBITMAP(array);
+	bitmask = 1;
 	for (i=0; i<nelems; i++)
 	{
-		PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
-		offset += INTALIGN(VARSIZE(geom));
-
-		if ( TYPE_GETTYPE(geom->type) != POINTTYPE ) continue;
-
-		lwpoints[npoints++] =
-		    lwpoint_deserialize(SERIALIZED_FORM(geom));
-
-		/* Check SRID homogeneity */
-		if ( npoints == 1 )
+		/* Don't do anything for NULL values */
+		if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap)
 		{
-			/* Get first geometry SRID */
-			SRID = lwpoints[npoints-1]->SRID;
+			PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
+			offset += INTALIGN(VARSIZE(geom));
+	
+			if ( TYPE_GETTYPE(geom->type) != POINTTYPE ) continue;
+	
+			lwpoints[npoints++] =
+			lwpoint_deserialize(SERIALIZED_FORM(geom));
+	
+			/* Check SRID homogeneity */
+			if ( npoints == 1 )
+			{
+				/* Get first geometry SRID */
+				SRID = lwpoints[npoints-1]->SRID;
+			}
+			else
+			{
+				if ( lwpoints[npoints-1]->SRID != SRID )
+				{
+					elog(ERROR,
+					"Operation on mixed SRID geometries");
+					PG_RETURN_NULL();
+				}
+			}
+	
+			POSTGIS_DEBUGF(3, "LWGEOM_makeline_garray: element %d deserialized",
+				i);
 		}
-		else
-		{
-			if ( lwpoints[npoints-1]->SRID != SRID )
+
+		/* Advance NULL bitmap */
+		if (bitmap)
+                {
+			bitmask <<= 1;
+			if (bitmask == 0x100)
 			{
-				elog(ERROR,
-				     "Operation on mixed SRID geometries");
-				PG_RETURN_NULL();
+				bitmap++;
+				bitmask = 1;
 			}
 		}
-
-		POSTGIS_DEBUGF(3, "LWGEOM_makeline_garray: element %d deserialized",
-		               i);
 	}
 
 	/* Return null on 0-points input array */
Index: postgis/lwgeom_accum.c
===================================================================
--- postgis/lwgeom_accum.c	(revision 4200)
+++ postgis/lwgeom_accum.c	(working copy)
@@ -21,6 +21,7 @@
 #include "lwgeom_pg.h"
 
 /* Local prototypes */
+Datum PGISDirectFunctionCall1(PGFunction func, Datum arg1);
 Datum pgis_geometry_accum_transfn(PG_FUNCTION_ARGS);
 Datum pgis_geometry_accum_finalfn(PG_FUNCTION_ARGS);
 Datum pgis_geometry_union_finalfn(PG_FUNCTION_ARGS);
@@ -210,7 +211,9 @@
 	p = (pgis_abs*) PG_GETARG_POINTER(0);
 
 	geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
-	result = DirectFunctionCall1( pgis_union_geometry_array, geometry_array );
+	result = PGISDirectFunctionCall1( pgis_union_geometry_array, geometry_array );
+	if (!result)
+		PG_RETURN_NULL();
 
 	PG_RETURN_DATUM(result);
 }
@@ -233,7 +236,9 @@
 	p = (pgis_abs*) PG_GETARG_POINTER(0);
 
 	geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
-	result = DirectFunctionCall1( LWGEOM_collect_garray, geometry_array );
+	result = PGISDirectFunctionCall1( LWGEOM_collect_garray, geometry_array );
+	if (!result)
+		PG_RETURN_NULL();
 
 	PG_RETURN_DATUM(result);
 }
@@ -256,7 +261,9 @@
 	p = (pgis_abs*) PG_GETARG_POINTER(0);
 
 	geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
-	result = DirectFunctionCall1( polygonize_garray, geometry_array );
+	result = PGISDirectFunctionCall1( polygonize_garray, geometry_array );
+	if (!result)
+		PG_RETURN_NULL();
 
 	PG_RETURN_DATUM(result);
 }
@@ -279,8 +286,33 @@
 	p = (pgis_abs*) PG_GETARG_POINTER(0);
 
 	geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
-	result = DirectFunctionCall1( LWGEOM_makeline_garray, geometry_array );
+	result = PGISDirectFunctionCall1( LWGEOM_makeline_garray, geometry_array );
+	if (!result)
+		PG_RETURN_NULL();
 
 	PG_RETURN_DATUM(result);
 }
 
+/**
+* A modified version of PostgreSQL's DirectFunctionCall1 which allows NULL results; this
+* is required for aggregates that return NULL.
+*/
+Datum
+PGISDirectFunctionCall1(PGFunction func, Datum arg1)
+{
+        FunctionCallInfoData fcinfo;
+        Datum           result;
+
+        InitFunctionCallInfoData(fcinfo, NULL, 1, NULL, NULL);
+
+        fcinfo.arg[0] = arg1;
+        fcinfo.argnull[0] = false;
+
+        result = (*func) (&fcinfo);
+
+        /* Check for null result, returning a "NULL" Datum if indicated */
+        if (fcinfo.isnull)
+                return (Datum) 0;
+
+        return result;
+}

