Ticket #210: postgis-nullfix.patch
| File postgis-nullfix.patch, 19.8 KB (added by mcayland, 3 years ago) |
|---|
-
postgis/lwgeom_geos.c
107 107 GEOSGeometry * geos_result=NULL; 108 108 int SRID=-1; 109 109 size_t offset = 0; 110 bits8 *bitmap; 111 int bitmask; 110 112 #if POSTGIS_DEBUG_LEVEL > 0 111 113 static int call=1; 112 114 #endif 113 115 #if POSTGIS_GEOS_VERSION >= 31 116 int gotsrid = 0; 114 117 int allpolys=1; 115 118 #endif 116 119 … … 128 131 129 132 nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); 130 133 134 bitmap = ARR_NULLBITMAP(array); 135 131 136 POSTGIS_DEBUGF(3, "unite_garray: number of elements: %d", nelems); 132 137 133 138 if ( nelems == 0 ) PG_RETURN_NULL(); 134 139 135 140 /* One-element union is the element itself */ 136 if ( nelems == 1 ) PG_RETURN_POINTER((PG_LWGEOM *)(ARR_DATA_PTR(array))); 141 if ( nelems == 1 ) 142 { 143 /* If the element is a NULL then we need to handle it separately */ 144 if (bitmap && (*bitmap & 1) == 0) 145 PG_RETURN_NULL(); 146 else 147 PG_RETURN_POINTER((PG_LWGEOM *)(ARR_DATA_PTR(array))); 148 } 137 149 138 150 /* Ok, we really need geos now ;) */ 139 151 initGEOS(lwnotice, lwnotice); … … 145 157 ** If they are, we can use UnionCascaded for faster results. 146 158 */ 147 159 offset = 0; 160 bitmask = 1; 161 gotsrid = 0; 148 162 for ( i = 0; i < nelems; i++ ) 149 163 { 150 PG_LWGEOM *pggeom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 151 int pgtype = TYPE_GETTYPE(pggeom->type); 152 offset += INTALIGN(VARSIZE(pggeom)); 153 if ( ! i ) /* Initialize SRID */ 164 /* Don't do anything for NULL values */ 165 if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap) 154 166 { 155 SRID = pglwgeom_getSRID(pggeom); 156 if ( TYPE_HASZ(pggeom->type) ) is3d = 1; 167 PG_LWGEOM *pggeom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 168 int pgtype = TYPE_GETTYPE(pggeom->type); 169 offset += INTALIGN(VARSIZE(pggeom)); 170 if ( ! gotsrid ) /* Initialize SRID */ 171 { 172 SRID = pglwgeom_getSRID(pggeom); 173 gotsrid = 1; 174 if ( TYPE_HASZ(pggeom->type) ) is3d = 1; 175 } 176 else 177 { 178 errorIfSRIDMismatch(SRID, pglwgeom_getSRID(pggeom)); 179 } 180 181 if ( pgtype != POLYGONTYPE && pgtype != MULTIPOLYGONTYPE ) 182 { 183 allpolys = 0; 184 break; 185 } 157 186 } 158 if ( pgtype != POLYGONTYPE && pgtype != MULTIPOLYGONTYPE ) 159 { 160 allpolys = 0; 161 break; 187 188 /* Advance NULL bitmap */ 189 if (bitmap) 190 { 191 bitmask <<= 1; 192 if (bitmask == 0x100) 193 { 194 bitmap++; 195 bitmask = 1; 196 } 162 197 } 163 198 } 164 199 … … 176 211 ** First make an array of GEOS Polygons. 177 212 */ 178 213 offset = 0; 214 bitmap = ARR_NULLBITMAP(array); 215 bitmask = 1; 179 216 for ( i = 0; i < nelems; i++ ) 180 217 { 181 PG_LWGEOM *pggeom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 182 int pgtype = TYPE_GETTYPE(pggeom->type); 183 offset += INTALIGN(VARSIZE(pggeom)); 184 if ( pgtype == POLYGONTYPE ) 218 /* Don't do anything for NULL values */ 219 if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap) 185 220 { 186 if ( curgeom == geoms_size ) 221 PG_LWGEOM *pggeom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 222 int pgtype = TYPE_GETTYPE(pggeom->type); 223 offset += INTALIGN(VARSIZE(pggeom)); 224 if ( pgtype == POLYGONTYPE ) 187 225 { 188 geoms_size *= 2;189 geoms = repalloc( geoms, sizeof(GEOSGeom) * geoms_size );190 }191 geoms[curgeom] = (GEOSGeometry *)POSTGIS2GEOS(pggeom);192 curgeom++;193 }194 if ( pgtype == MULTIPOLYGONTYPE )195 {196 int j = 0;197 LWGEOM_INSPECTED *lwgeom = lwgeom_inspect(SERIALIZED_FORM(pggeom));198 for ( j = 0; j < lwgeom->ngeometries; j++ )199 {200 LWPOLY *lwpoly = NULL;201 int k = 0;202 226 if ( curgeom == geoms_size ) 203 227 { 204 228 geoms_size *= 2; 205 229 geoms = repalloc( geoms, sizeof(GEOSGeom) * geoms_size ); 206 230 } 207 /* This builds a LWPOLY on top of the serialized form */ 208 lwpoly = lwgeom_getpoly_inspected(lwgeom, j); 209 geoms[curgeom] = LWGEOM2GEOS(lwpoly_as_lwgeom(lwpoly)); 210 /* We delicately free the LWPOLY and POINTARRAY structs, leaving the serialized form below untouched. */ 211 for ( k = 0; k < lwpoly->nrings; k++ ) 231 geoms[curgeom] = (GEOSGeometry *)POSTGIS2GEOS(pggeom); 232 curgeom++; 233 } 234 if ( pgtype == MULTIPOLYGONTYPE ) 235 { 236 int j = 0; 237 LWGEOM_INSPECTED *lwgeom = lwgeom_inspect(SERIALIZED_FORM(pggeom)); 238 for ( j = 0; j < lwgeom->ngeometries; j++ ) 212 239 { 213 lwfree(lwpoly->rings[k]); 240 LWPOLY *lwpoly = NULL; 241 int k = 0; 242 if ( curgeom == geoms_size ) 243 { 244 geoms_size *= 2; 245 geoms = repalloc( geoms, sizeof(GEOSGeom) * geoms_size ); 246 } 247 /* This builds a LWPOLY on top of the serialized form */ 248 lwpoly = lwgeom_getpoly_inspected(lwgeom, j); 249 geoms[curgeom] = LWGEOM2GEOS(lwpoly_as_lwgeom(lwpoly)); 250 /* We delicately free the LWPOLY and POINTARRAY structs, leaving the serialized form below untouched. */ 251 for ( k = 0; k < lwpoly->nrings; k++ ) 252 { 253 lwfree(lwpoly->rings[k]); 254 } 255 lwpoly_release(lwpoly); 256 curgeom++; 214 257 } 215 lwpoly_release(lwpoly);216 curgeom++;217 258 } 218 259 } 219 260 261 /* Advance NULL bitmap */ 262 if (bitmap) 263 { 264 bitmask <<= 1; 265 if (bitmask == 0x100) 266 { 267 bitmap++; 268 bitmask = 1; 269 } 270 } 220 271 } 221 272 /* 222 273 ** Take our GEOS Polygons and turn them into a GEOS MultiPolygon, 223 274 ** then pass that into cascaded union. 224 275 */ 225 g1 = GEOSGeom_createCollection(GEOS_MULTIPOLYGON, geoms, curgeom); 226 if ( g1 ) g2 = GEOSUnionCascaded(g1); 227 if ( g2 ) GEOSSetSRID(g2, SRID); 228 if ( g2 ) result = GEOS2POSTGIS(g2, is3d); 229 /* Clean up the mess. */ 230 if ( g1 ) GEOSGeom_destroy((GEOSGeometry *)g1); 231 if ( g2 ) GEOSGeom_destroy(g2); 276 if (curgeom > 0) 277 { 278 g1 = GEOSGeom_createCollection(GEOS_MULTIPOLYGON, geoms, curgeom); 279 if ( g1 ) g2 = GEOSUnionCascaded(g1); 280 if ( g2 ) GEOSSetSRID(g2, SRID); 281 if ( g2 ) result = GEOS2POSTGIS(g2, is3d); 282 /* Clean up the mess. */ 283 if ( g1 ) GEOSGeom_destroy((GEOSGeometry *)g1); 284 if ( g2 ) GEOSGeom_destroy(g2); 285 } 286 else 287 { 288 /* All we found were NULLs, so let's return NULL */ 289 PG_RETURN_NULL(); 290 } 232 291 } 233 292 else 234 293 { … … 237 296 ** Heterogeneous result, let's slog through this one union at a time. 238 297 */ 239 298 offset = 0; 299 bitmap = ARR_NULLBITMAP(array); 300 bitmask = 1; 240 301 for (i=0; i<nelems; i++) 241 302 { 242 PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 243 offset += INTALIGN(VARSIZE(geom)); 244 245 pgis_geom = geom; 246 247 POSTGIS_DEBUGF(3, "geom %d @ %p", i, geom); 248 249 /* Check is3d flag */ 250 if ( TYPE_HASZ(geom->type) ) is3d = 1; 251 252 /* Check SRID homogeneity and initialize geos result */ 253 if ( ! i ) 303 /* Don't do anything for NULL values */ 304 if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap) 254 305 { 255 geos_result = (GEOSGeometry *)POSTGIS2GEOS(geom); 256 SRID = pglwgeom_getSRID(geom); 257 POSTGIS_DEBUGF(3, "first geom is a %s", lwgeom_typename(TYPE_GETTYPE(geom->type))); 258 continue; 306 PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 307 offset += INTALIGN(VARSIZE(geom)); 308 309 pgis_geom = geom; 310 311 POSTGIS_DEBUGF(3, "geom %d @ %p", i, geom); 312 313 /* Check is3d flag */ 314 if ( TYPE_HASZ(geom->type) ) is3d = 1; 315 316 /* Check SRID homogeneity and initialize geos result */ 317 if ( ! geos_result ) 318 { 319 geos_result = (GEOSGeometry *)POSTGIS2GEOS(geom); 320 SRID = pglwgeom_getSRID(geom); 321 POSTGIS_DEBUGF(3, "first geom is a %s", lwgeom_typename(TYPE_GETTYPE(geom->type))); 322 } 323 else 324 { 325 errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom)); 326 327 g1 = POSTGIS2GEOS(pgis_geom); 328 329 POSTGIS_DEBUGF(3, "unite_garray(%d): adding geom %d to union (%s)", 330 call, i, lwgeom_typename(TYPE_GETTYPE(geom->type))); 331 332 g2 = GEOSUnion(g1, geos_result); 333 if ( g2 == NULL ) 334 { 335 GEOSGeom_destroy((GEOSGeometry *)g1); 336 GEOSGeom_destroy((GEOSGeometry *)geos_result); 337 elog(ERROR,"GEOS union() threw an error!"); 338 } 339 GEOSGeom_destroy((GEOSGeometry *)g1); 340 GEOSGeom_destroy((GEOSGeometry *)geos_result); 341 geos_result = g2; 342 } 259 343 } 260 else261 {262 errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom));263 }264 344 265 g1 = POSTGIS2GEOS(pgis_geom); 266 267 POSTGIS_DEBUGF(3, "unite_garray(%d): adding geom %d to union (%s)", 268 call, i, lwgeom_typename(TYPE_GETTYPE(geom->type))); 269 270 g2 = GEOSUnion(g1, geos_result); 271 if ( g2 == NULL ) 345 /* Advance NULL bitmap */ 346 if (bitmap) 272 347 { 273 GEOSGeom_destroy((GEOSGeometry *)g1); 274 GEOSGeom_destroy((GEOSGeometry *)geos_result); 275 elog(ERROR,"GEOS union() threw an error!"); 348 bitmask <<= 1; 349 if (bitmask == 0x100) 350 { 351 bitmap++; 352 bitmask = 1; 353 } 276 354 } 277 GEOSGeom_destroy((GEOSGeometry *)g1); 278 GEOSGeom_destroy((GEOSGeometry *)geos_result); 279 geos_result = g2; 355 280 356 } 281 357 282 GEOSSetSRID(geos_result, SRID); 283 result = GEOS2POSTGIS(geos_result, is3d); 284 GEOSGeom_destroy(geos_result); 358 /* If geos_result is set then we found at least one non-NULL geometry */ 359 if (geos_result) 360 { 361 GEOSSetSRID(geos_result, SRID); 362 result = GEOS2POSTGIS(geos_result, is3d); 363 GEOSGeom_destroy(geos_result); 364 } 365 else 366 { 367 /* All we found were NULLs, so let's return NULL */ 368 PG_RETURN_NULL(); 369 } 285 370 286 371 #if POSTGIS_GEOS_VERSION >= 31 287 372 } … … 289 374 290 375 if ( result == NULL ) 291 376 { 292 elog(ERROR, "Union returned a NULL geometry.");293 PG_RETURN_NULL(); /* never get here */377 /* Union returned a NULL geometry */ 378 PG_RETURN_NULL(); 294 379 } 295 380 296 381 PG_RETURN_POINTER(result); … … 2768 2853 GEOSGeometry *geos_result; 2769 2854 const GEOSGeometry **vgeoms; 2770 2855 int SRID=-1; 2856 int cnt = 0; 2771 2857 size_t offset; 2858 bits8 *bitmap; 2859 int bitmask; 2772 2860 #if POSTGIS_DEBUG_LEVEL >= 3 2773 2861 static int call=1; 2774 2862 #endif … … 2795 2883 2796 2884 vgeoms = palloc(sizeof(GEOSGeometry *)*nelems); 2797 2885 offset = 0; 2886 cnt = 0; 2887 bitmap = ARR_NULLBITMAP(array); 2888 bitmask = 1; 2798 2889 for (i=0; i<nelems; i++) 2799 2890 { 2800 PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 2801 offset += INTALIGN(VARSIZE(geom)); 2802 2803 vgeoms[i] = (GEOSGeometry *)POSTGIS2GEOS(geom); 2804 if ( ! i ) 2891 /* Don't do anything for NULL values */ 2892 if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap) 2805 2893 { 2806 SRID = pglwgeom_getSRID(geom); 2894 PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 2895 offset += INTALIGN(VARSIZE(geom)); 2896 2897 vgeoms[cnt] = (GEOSGeometry *)POSTGIS2GEOS(geom); 2898 if ( ! cnt ) 2899 { 2900 SRID = pglwgeom_getSRID(geom); 2901 } 2902 else 2903 { 2904 if ( SRID != pglwgeom_getSRID(geom) ) 2905 { 2906 elog(ERROR, "polygonize: operation on mixed SRID geometries"); 2907 PG_RETURN_NULL(); 2908 } 2909 } 2807 2910 } 2808 else 2809 { 2810 if ( SRID != pglwgeom_getSRID(geom) ) 2911 2912 /* Advance NULL bitmap */ 2913 if (bitmap) 2914 { 2915 bitmask <<= 1; 2916 if (bitmask == 0x100) 2811 2917 { 2812 elog(ERROR, "polygonize: operation on mixed SRID geometries");2813 PG_RETURN_NULL();2918 bitmap++; 2919 bitmask = 1; 2814 2920 } 2815 2921 } 2816 2922 } 2817 2923 2818 2924 POSTGIS_DEBUG(3, "polygonize_garray: invoking GEOSpolygonize"); 2819 2925 2820 geos_result = GEOSPolygonize(vgeoms, nelems);2926 geos_result = GEOSPolygonize(vgeoms, cnt); 2821 2927 2822 2928 POSTGIS_DEBUG(3, "polygonize_garray: GEOSpolygonize returned"); 2823 2929 2824 for (i=0; i< nelems; ++i) GEOSGeom_destroy((GEOSGeometry *)vgeoms[i]);2930 for (i=0; i<cnt; ++i) GEOSGeom_destroy((GEOSGeometry *)vgeoms[i]); 2825 2931 pfree(vgeoms); 2826 2932 2827 2933 if ( ! geos_result ) PG_RETURN_NULL(); -
postgis/lwgeom_functions_basic.c
1948 1948 unsigned int outtype; 1949 1949 int i; 1950 1950 int SRID=-1; 1951 int cnt = 0; 1951 1952 size_t offset; 1952 1953 BOX2DFLOAT4 *box=NULL; 1954 bits8 *bitmap; 1955 int bitmask; 1953 1956 1954 1957 POSTGIS_DEBUG(2, "LWGEOM_collect_garray called."); 1955 1958 … … 1989 1992 lwgeoms = palloc(sizeof(LWGEOM *)*nelems); 1990 1993 outtype = 0; 1991 1994 offset = 0; 1995 cnt = 0; 1996 bitmap = ARR_NULLBITMAP(array); 1997 bitmask = 1; 1998 1992 1999 for (i=0; i<nelems; i++) 1993 2000 { 1994 PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 1995 unsigned int intype = TYPE_GETTYPE(geom->type); 1996 1997 offset += INTALIGN(VARSIZE(geom)); 1998 1999 lwgeoms[i] = lwgeom_deserialize(SERIALIZED_FORM(geom)); 2000 2001 POSTGIS_DEBUGF(3, "LWGEOM_collect_garray: geom %d deserialized", i); 2002 2003 if ( ! i ) 2001 /* Don't do anything for NULL values */ 2002 if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap) 2004 2003 { 2005 /* Get first geometry SRID */ 2006 SRID = lwgeoms[i]->SRID; 2007 2008 /* COMPUTE_BBOX WHEN_SIMPLE */ 2009 if ( lwgeoms[i]->bbox ) 2004 PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 2005 unsigned int intype = TYPE_GETTYPE(geom->type); 2006 2007 offset += INTALIGN(VARSIZE(geom)); 2008 2009 lwgeoms[cnt] = lwgeom_deserialize(SERIALIZED_FORM(geom)); 2010 2011 POSTGIS_DEBUGF(3, "LWGEOM_collect_garray: geom %d deserialized", i); 2012 2013 if ( ! cnt ) 2010 2014 { 2011 box = box2d_clone(lwgeoms[i]->bbox); 2015 /* Get first geometry SRID */ 2016 SRID = lwgeoms[cnt]->SRID; 2017 2018 /* COMPUTE_BBOX WHEN_SIMPLE */ 2019 if ( lwgeoms[cnt]->bbox ) 2020 { 2021 box = box2d_clone(lwgeoms[cnt]->bbox); 2022 } 2012 2023 } 2013 } 2014 else 2015 { 2016 /* Check SRID homogeneity */ 2017 if ( lwgeoms[i]->SRID != SRID ) 2024 else 2018 2025 { 2019 elog(ERROR, 2020 "Operation on mixed SRID geometries"); 2021 PG_RETURN_NULL(); 2022 } 2023 2024 /* COMPUTE_BBOX WHEN_SIMPLE */ 2025 if ( box ) 2026 { 2027 if ( lwgeoms[i]->bbox ) 2026 /* Check SRID homogeneity */ 2027 if ( lwgeoms[cnt]->SRID != SRID ) 2028 2028 { 2029 box->xmin = LW_MIN(box->xmin, lwgeoms[i]->bbox->xmin); 2030 box->ymin = LW_MIN(box->ymin, lwgeoms[i]->bbox->ymin); 2031 box->xmax = LW_MAX(box->xmax, lwgeoms[i]->bbox->xmax); 2032 box->ymax = LW_MAX(box->ymax, lwgeoms[i]->bbox->ymax); 2029 elog(ERROR, 2030 "Operation on mixed SRID geometries"); 2031 PG_RETURN_NULL(); 2033 2032 } 2034 else 2033 2034 /* COMPUTE_BBOX WHEN_SIMPLE */ 2035 if ( box ) 2035 2036 { 2036 pfree(box); 2037 box = NULL; 2037 if ( lwgeoms[cnt]->bbox ) 2038 { 2039 box->xmin = LW_MIN(box->xmin, lwgeoms[cnt]->bbox->xmin); 2040 box->ymin = LW_MIN(box->ymin, lwgeoms[cnt]->bbox->ymin); 2041 box->xmax = LW_MAX(box->xmax, lwgeoms[cnt]->bbox->xmax); 2042 box->ymax = LW_MAX(box->ymax, lwgeoms[cnt]->bbox->ymax); 2043 } 2044 else 2045 { 2046 pfree(box); 2047 box = NULL; 2048 } 2038 2049 } 2039 2050 } 2040 }2041 2051 2052 lwgeom_dropSRID(lwgeoms[cnt]); 2053 lwgeom_drop_bbox(lwgeoms[cnt]); 2054 2055 /* Output type not initialized */ 2056 if ( ! outtype ) 2057 { 2058 /* Input is single, make multi */ 2059 if ( intype < 4 ) outtype = intype+3; 2060 /* Input is multi, make collection */ 2061 else outtype = COLLECTIONTYPE; 2062 } 2063 2064 /* Input type not compatible with output */ 2065 /* make output type a collection */ 2066 else if ( outtype != COLLECTIONTYPE && intype != outtype-3 ) 2067 { 2068 outtype = COLLECTIONTYPE; 2069 } 2042 2070 2043 lwgeom_dropSRID(lwgeoms[i]); 2044 lwgeom_drop_bbox(lwgeoms[i]); 2045 2046 /* Output type not initialized */ 2047 if ( ! outtype ) 2048 { 2049 /* Input is single, make multi */ 2050 if ( intype < 4 ) outtype = intype+3; 2051 /* Input is multi, make collection */ 2052 else outtype = COLLECTIONTYPE; 2071 /* Keep a count of the number of collection elements (no NULLs) */ 2072 cnt++; 2053 2073 } 2054 2074 2055 /* Input type not compatible with output */ 2056 /* make output type a collection */ 2057 else if ( outtype != COLLECTIONTYPE && intype != outtype-3 ) 2058 { 2059 outtype = COLLECTIONTYPE; 2075 /* Advance NULL bitmap */ 2076 if (bitmap) 2077 { 2078 bitmask <<= 1; 2079 if (bitmask == 0x100) 2080 { 2081 bitmap++; 2082 bitmask = 1; 2083 } 2060 2084 } 2061 2062 2085 } 2063 2086 2087 /* If we didn't find a non-NULL geometry, simply return NULL */ 2088 if ( ! cnt ) 2089 PG_RETURN_NULL(); 2090 2064 2091 POSTGIS_DEBUGF(3, "LWGEOM_collect_garray: outtype = %d", outtype); 2065 2092 2066 2093 outlwg = (LWGEOM *)lwcollection_construct( 2067 2094 outtype, SRID, 2068 box, nelems, lwgeoms);2095 box, cnt, lwgeoms); 2069 2096 2070 2097 result = pglwgeom_serialize(outlwg); 2071 2098 … … 2129 2156 int i; 2130 2157 size_t offset; 2131 2158 int SRID=-1; 2159 bits8 *bitmap; 2160 int bitmask; 2132 2161 2133 2162 POSTGIS_DEBUG(2, "LWGEOM_makeline_garray called."); 2134 2163 … … 2169 2198 lwpoints = palloc(sizeof(LWGEOM *)*nelems); 2170 2199 npoints = 0; 2171 2200 offset = 0; 2201 bitmap = ARR_NULLBITMAP(array); 2202 bitmask = 1; 2172 2203 for (i=0; i<nelems; i++) 2173 2204 { 2174 PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 2175 offset += INTALIGN(VARSIZE(geom)); 2176 2177 if ( TYPE_GETTYPE(geom->type) != POINTTYPE ) continue; 2178 2179 lwpoints[npoints++] = 2180 lwpoint_deserialize(SERIALIZED_FORM(geom)); 2181 2182 /* Check SRID homogeneity */ 2183 if ( npoints == 1 ) 2205 /* Don't do anything for NULL values */ 2206 if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap) 2184 2207 { 2185 /* Get first geometry SRID */ 2186 SRID = lwpoints[npoints-1]->SRID; 2208 PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset); 2209 offset += INTALIGN(VARSIZE(geom)); 2210 2211 if ( TYPE_GETTYPE(geom->type) != POINTTYPE ) continue; 2212 2213 lwpoints[npoints++] = 2214 lwpoint_deserialize(SERIALIZED_FORM(geom)); 2215 2216 /* Check SRID homogeneity */ 2217 if ( npoints == 1 ) 2218 { 2219 /* Get first geometry SRID */ 2220 SRID = lwpoints[npoints-1]->SRID; 2221 } 2222 else 2223 { 2224 if ( lwpoints[npoints-1]->SRID != SRID ) 2225 { 2226 elog(ERROR, 2227 "Operation on mixed SRID geometries"); 2228 PG_RETURN_NULL(); 2229 } 2230 } 2231 2232 POSTGIS_DEBUGF(3, "LWGEOM_makeline_garray: element %d deserialized", 2233 i); 2187 2234 } 2188 else 2189 { 2190 if ( lwpoints[npoints-1]->SRID != SRID ) 2235 2236 /* Advance NULL bitmap */ 2237 if (bitmap) 2238 { 2239 bitmask <<= 1; 2240 if (bitmask == 0x100) 2191 2241 { 2192 elog(ERROR, 2193 "Operation on mixed SRID geometries"); 2194 PG_RETURN_NULL(); 2242 bitmap++; 2243 bitmask = 1; 2195 2244 } 2196 2245 } 2197 2198 POSTGIS_DEBUGF(3, "LWGEOM_makeline_garray: element %d deserialized",2199 i);2200 2246 } 2201 2247 2202 2248 /* Return null on 0-points input array */ -
postgis/lwgeom_accum.c
21 21 #include "lwgeom_pg.h" 22 22 23 23 /* Local prototypes */ 24 Datum PGISDirectFunctionCall1(PGFunction func, Datum arg1); 24 25 Datum pgis_geometry_accum_transfn(PG_FUNCTION_ARGS); 25 26 Datum pgis_geometry_accum_finalfn(PG_FUNCTION_ARGS); 26 27 Datum pgis_geometry_union_finalfn(PG_FUNCTION_ARGS); … … 210 211 p = (pgis_abs*) PG_GETARG_POINTER(0); 211 212 212 213 geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo); 213 result = DirectFunctionCall1( pgis_union_geometry_array, geometry_array ); 214 result = PGISDirectFunctionCall1( pgis_union_geometry_array, geometry_array ); 215 if (!result) 216 PG_RETURN_NULL(); 214 217 215 218 PG_RETURN_DATUM(result); 216 219 } … … 233 236 p = (pgis_abs*) PG_GETARG_POINTER(0); 234 237 235 238 geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo); 236 result = DirectFunctionCall1( LWGEOM_collect_garray, geometry_array ); 239 result = PGISDirectFunctionCall1( LWGEOM_collect_garray, geometry_array ); 240 if (!result) 241 PG_RETURN_NULL(); 237 242 238 243 PG_RETURN_DATUM(result); 239 244 } … … 256 261 p = (pgis_abs*) PG_GETARG_POINTER(0); 257 262 258 263 geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo); 259 result = DirectFunctionCall1( polygonize_garray, geometry_array ); 264 result = PGISDirectFunctionCall1( polygonize_garray, geometry_array ); 265 if (!result) 266 PG_RETURN_NULL(); 260 267 261 268 PG_RETURN_DATUM(result); 262 269 } … … 279 286 p = (pgis_abs*) PG_GETARG_POINTER(0); 280 287 281 288 geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo); 282 result = DirectFunctionCall1( LWGEOM_makeline_garray, geometry_array ); 289 result = PGISDirectFunctionCall1( LWGEOM_makeline_garray, geometry_array ); 290 if (!result) 291 PG_RETURN_NULL(); 283 292 284 293 PG_RETURN_DATUM(result); 285 294 } 286 295 296 /** 297 * A modified version of PostgreSQL's DirectFunctionCall1 which allows NULL results; this 298 * is required for aggregates that return NULL. 299 */ 300 Datum 301 PGISDirectFunctionCall1(PGFunction func, Datum arg1) 302 { 303 FunctionCallInfoData fcinfo; 304 Datum result; 305 306 InitFunctionCallInfoData(fcinfo, NULL, 1, NULL, NULL); 307 308 fcinfo.arg[0] = arg1; 309 fcinfo.argnull[0] = false; 310 311 result = (*func) (&fcinfo); 312 313 /* Check for null result, returning a "NULL" Datum if indicated */ 314 if (fcinfo.isnull) 315 return (Datum) 0; 316 317 return result; 318 }
