3
3
* rtproc.c
4
4
* pg_amproc entries for rtrees.
5
5
*
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
+ *
6
14
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7
15
* Portions Copyright (c) 1994, Regents of the University of California
8
16
*
9
- *
10
17
* 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 $
12
19
*
13
20
*-------------------------------------------------------------------------
14
21
*/
18
25
#include "utils/geo_decls.h"
19
26
20
27
21
- BOX *
22
- rt_box_union (BOX * a , BOX * b )
28
+ Datum
29
+ rt_box_union (PG_FUNCTION_ARGS )
23
30
{
31
+ BOX * a = PG_GETARG_BOX_P (0 );
32
+ BOX * b = PG_GETARG_BOX_P (1 );
24
33
BOX * n ;
25
34
26
- if ((n = (BOX * )palloc (sizeof (* n )))== (BOX * )NULL )
27
- elog (ERROR ,"Cannot allocate box for union" );
35
+ n = (BOX * )palloc (sizeof (BOX ));
28
36
29
37
n -> high .x = Max (a -> high .x ,b -> high .x );
30
38
n -> high .y = Max (a -> high .y ,b -> high .y );
31
39
n -> low .x = Min (a -> low .x ,b -> low .x );
32
40
n -> low .y = Min (a -> low .y ,b -> low .y );
33
41
34
- return n ;
42
+ PG_RETURN_BOX_P ( n ) ;
35
43
}
36
44
37
- BOX *
38
- rt_box_inter (BOX * a , BOX * b )
45
+ Datum
46
+ rt_box_inter (PG_FUNCTION_ARGS )
39
47
{
48
+ BOX * a = PG_GETARG_BOX_P (0 );
49
+ BOX * b = PG_GETARG_BOX_P (1 );
40
50
BOX * n ;
41
51
42
- if ((n = (BOX * )palloc (sizeof (* n )))== (BOX * )NULL )
43
- elog (ERROR ,"Cannot allocate box for union" );
52
+ n = (BOX * )palloc (sizeof (BOX ));
44
53
45
54
n -> high .x = Min (a -> high .x ,b -> high .x );
46
55
n -> high .y = Min (a -> high .y ,b -> high .y );
@@ -50,21 +59,26 @@ rt_box_inter(BOX *a, BOX *b)
50
59
if (n -> high .x < n -> low .x || n -> high .y < n -> low .y )
51
60
{
52
61
pfree (n );
53
- return (BOX * )NULL ;
62
+ /* Indicate "no intersection" by returning NULL pointer */
63
+ n = NULL ;
54
64
}
55
65
56
- return n ;
66
+ PG_RETURN_BOX_P ( n ) ;
57
67
}
58
68
59
- void
60
- rt_box_size (BOX * a , float * size )
69
+ Datum
70
+ rt_box_size (PG_FUNCTION_ARGS )
61
71
{
72
+ BOX * a = PG_GETARG_BOX_P (0 );
73
+ /* NB: size is an output argument */
74
+ float * size = (float * )PG_GETARG_POINTER (1 );
75
+
62
76
if (a == (BOX * )NULL || a -> high .x <=a -> low .x || a -> high .y <=a -> low .y )
63
77
* size = 0.0 ;
64
78
else
65
79
* size = (float ) ((a -> high .x - a -> low .x )* (a -> high .y - a -> low .y ));
66
80
67
- return ;
81
+ PG_RETURN_VOID () ;
68
82
}
69
83
70
84
/*
@@ -75,10 +89,10 @@ rt_box_size(BOX *a, float *size)
75
89
*as the return type for the size routine, so we no longer need to
76
90
*have a special return type for big boxes.
77
91
*/
78
- void
79
- rt_bigbox_size (BOX * a , float * size )
92
+ Datum
93
+ rt_bigbox_size (PG_FUNCTION_ARGS )
80
94
{
81
- rt_box_size (a , size );
95
+ return rt_box_size (fcinfo );
82
96
}
83
97
84
98
Datum
@@ -105,30 +119,6 @@ rt_poly_union(PG_FUNCTION_ARGS)
105
119
PG_RETURN_POLYGON_P (p );
106
120
}
107
121
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
-
132
122
Datum
133
123
rt_poly_inter (PG_FUNCTION_ARGS )
134
124
{
@@ -146,16 +136,52 @@ rt_poly_inter(PG_FUNCTION_ARGS)
146
136
p -> boundbox .low .x = Max (a -> boundbox .low .x ,b -> boundbox .low .x );
147
137
p -> boundbox .low .y = Max (a -> boundbox .low .y ,b -> boundbox .low .y );
148
138
149
- /* Avoid leaking memory when handed toasted input. */
150
- PG_FREE_IF_COPY (a ,0 );
151
- PG_FREE_IF_COPY (b ,1 );
152
-
153
139
if (p -> boundbox .high .x < p -> boundbox .low .x ||
154
140
p -> boundbox .high .y < p -> boundbox .low .y )
155
141
{
156
142
pfree (p );
157
- PG_RETURN_NULL ();
143
+ /* Indicate "no intersection" by returning NULL pointer */
144
+ p = NULL ;
158
145
}
159
146
147
+ /* Avoid leaking memory when handed toasted input. */
148
+ PG_FREE_IF_COPY (a ,0 );
149
+ PG_FREE_IF_COPY (b ,1 );
150
+
160
151
PG_RETURN_POLYGON_P (p );
161
152
}
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
+ }