33 * rtproc.c
44 * pg_amproc entries for rtrees.
55 *
6+ * NOTE: for largely-historical reasons, the intersection functions should
7+ * return a NULL pointer (*not* an SQL null value) to indicate "no
8+ * intersection". The size functions must be prepared to accept such
9+ * a pointer and return 0. This convention means that only pass-by-reference
10+ * data types can be used as the output of the union and intersection
11+ * routines, but that's not a big problem.
12+ *
13+ *
614 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
715 * Portions Copyright (c) 1994, Regents of the University of California
816 *
9- *
1017 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.28 2000/07/29 18:45:52 tgl Exp $
18+ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.29 2000/07/30 20:43:40 tgl Exp $
1219 *
1320 *-------------------------------------------------------------------------
1421 */
1825#include "utils/geo_decls.h"
1926
2027
21- BOX *
22- rt_box_union (BOX * a , BOX * b )
28+ Datum
29+ rt_box_union (PG_FUNCTION_ARGS )
2330{
31+ BOX * a = PG_GETARG_BOX_P (0 );
32+ BOX * b = PG_GETARG_BOX_P (1 );
2433BOX * n ;
2534
26- if ((n = (BOX * )palloc (sizeof (* n )))== (BOX * )NULL )
27- elog (ERROR ,"Cannot allocate box for union" );
35+ n = (BOX * )palloc (sizeof (BOX ));
2836
2937n -> high .x = Max (a -> high .x ,b -> high .x );
3038n -> high .y = Max (a -> high .y ,b -> high .y );
3139n -> low .x = Min (a -> low .x ,b -> low .x );
3240n -> low .y = Min (a -> low .y ,b -> low .y );
3341
34- return n ;
42+ PG_RETURN_BOX_P ( n ) ;
3543}
3644
37- BOX *
38- rt_box_inter (BOX * a , BOX * b )
45+ Datum
46+ rt_box_inter (PG_FUNCTION_ARGS )
3947{
48+ BOX * a = PG_GETARG_BOX_P (0 );
49+ BOX * b = PG_GETARG_BOX_P (1 );
4050BOX * n ;
4151
42- if ((n = (BOX * )palloc (sizeof (* n )))== (BOX * )NULL )
43- elog (ERROR ,"Cannot allocate box for union" );
52+ n = (BOX * )palloc (sizeof (BOX ));
4453
4554n -> high .x = Min (a -> high .x ,b -> high .x );
4655n -> high .y = Min (a -> high .y ,b -> high .y );
@@ -50,21 +59,26 @@ rt_box_inter(BOX *a, BOX *b)
5059if (n -> high .x < n -> low .x || n -> high .y < n -> low .y )
5160{
5261pfree (n );
53- return (BOX * )NULL ;
62+ /* Indicate "no intersection" by returning NULL pointer */
63+ n = NULL ;
5464}
5565
56- return n ;
66+ PG_RETURN_BOX_P ( n ) ;
5767}
5868
59- void
60- rt_box_size (BOX * a , float * size )
69+ Datum
70+ rt_box_size (PG_FUNCTION_ARGS )
6171{
72+ BOX * a = PG_GETARG_BOX_P (0 );
73+ /* NB: size is an output argument */
74+ float * size = (float * )PG_GETARG_POINTER (1 );
75+
6276if (a == (BOX * )NULL || a -> high .x <=a -> low .x || a -> high .y <=a -> low .y )
6377* size = 0.0 ;
6478else
6579* size = (float ) ((a -> high .x - a -> low .x )* (a -> high .y - a -> low .y ));
6680
67- return ;
81+ PG_RETURN_VOID () ;
6882}
6983
7084/*
@@ -75,10 +89,10 @@ rt_box_size(BOX *a, float *size)
7589 *as the return type for the size routine, so we no longer need to
7690 *have a special return type for big boxes.
7791 */
78- void
79- rt_bigbox_size (BOX * a , float * size )
92+ Datum
93+ rt_bigbox_size (PG_FUNCTION_ARGS )
8094{
81- rt_box_size (a , size );
95+ return rt_box_size (fcinfo );
8296}
8397
8498Datum
@@ -105,30 +119,6 @@ rt_poly_union(PG_FUNCTION_ARGS)
105119PG_RETURN_POLYGON_P (p );
106120}
107121
108- Datum
109- rt_poly_size (PG_FUNCTION_ARGS )
110- {
111- POLYGON * a = PG_GETARG_POLYGON_P (0 );
112- /* NB: size is an output argument */
113- float * size = (float * )PG_GETARG_POINTER (1 );
114- double xdim ,
115- ydim ;
116-
117- if (a == (POLYGON * )NULL ||
118- a -> boundbox .high .x <=a -> boundbox .low .x ||
119- a -> boundbox .high .y <=a -> boundbox .low .y )
120- * size = 0.0 ;
121- else
122- {
123- xdim = (a -> boundbox .high .x - a -> boundbox .low .x );
124- ydim = (a -> boundbox .high .y - a -> boundbox .low .y );
125-
126- * size = (float ) (xdim * ydim );
127- }
128-
129- PG_RETURN_VOID ();
130- }
131-
132122Datum
133123rt_poly_inter (PG_FUNCTION_ARGS )
134124{
@@ -146,16 +136,52 @@ rt_poly_inter(PG_FUNCTION_ARGS)
146136p -> boundbox .low .x = Max (a -> boundbox .low .x ,b -> boundbox .low .x );
147137p -> boundbox .low .y = Max (a -> boundbox .low .y ,b -> boundbox .low .y );
148138
149- /* Avoid leaking memory when handed toasted input. */
150- PG_FREE_IF_COPY (a ,0 );
151- PG_FREE_IF_COPY (b ,1 );
152-
153139if (p -> boundbox .high .x < p -> boundbox .low .x ||
154140p -> boundbox .high .y < p -> boundbox .low .y )
155141{
156142pfree (p );
157- PG_RETURN_NULL ();
143+ /* Indicate "no intersection" by returning NULL pointer */
144+ p = NULL ;
158145}
159146
147+ /* Avoid leaking memory when handed toasted input. */
148+ PG_FREE_IF_COPY (a ,0 );
149+ PG_FREE_IF_COPY (b ,1 );
150+
160151PG_RETURN_POLYGON_P (p );
161152}
153+
154+ Datum
155+ rt_poly_size (PG_FUNCTION_ARGS )
156+ {
157+ Pointer aptr = PG_GETARG_POINTER (0 );
158+ /* NB: size is an output argument */
159+ float * size = (float * )PG_GETARG_POINTER (1 );
160+ POLYGON * a ;
161+ double xdim ,
162+ ydim ;
163+
164+ /* Can't just use GETARG because of possibility that input is NULL;
165+ * since POLYGON is toastable, GETARG will try to inspect its value
166+ */
167+ if (aptr == NULL )
168+ {
169+ * size = 0.0 ;
170+ PG_RETURN_VOID ();
171+ }
172+ /* Now safe to apply GETARG */
173+ a = PG_GETARG_POLYGON_P (0 );
174+
175+ if (a -> boundbox .high .x <=a -> boundbox .low .x ||
176+ a -> boundbox .high .y <=a -> boundbox .low .y )
177+ * size = 0.0 ;
178+ else
179+ {
180+ xdim = (a -> boundbox .high .x - a -> boundbox .low .x );
181+ ydim = (a -> boundbox .high .y - a -> boundbox .low .y );
182+
183+ * size = (float ) (xdim * ydim );
184+ }
185+
186+ PG_RETURN_VOID ();
187+ }