Skip to content

Commit 3a9a74a

Browse files
committed
Convert all remaining geometric operators to new fmgr style. This
allows fixing problems with operators that expected to be able to return a NULL, such as the '#' line-segment-intersection operator that tried to return NULL when the two segments don't intersect. (See, eg, bug report from 1-Nov-99 on pghackers.) Fix some other bugs in passing, such as backwards comparison in path_distance().
1 parent d70d46f commit 3a9a74a

File tree

8 files changed

+1748
-1585
lines changed

8 files changed

+1748
-1585
lines changed

src/backend/access/rtree/rtproc.c

Lines changed: 74 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,19 @@
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
*/
@@ -18,29 +25,31 @@
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);
2433
BOX *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

2937
n->high.x = Max(a->high.x, b->high.x);
3038
n->high.y = Max(a->high.y, b->high.y);
3139
n->low.x = Min(a->low.x, b->low.x);
3240
n->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);
4050
BOX *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

4554
n->high.x = Min(a->high.x, b->high.x);
4655
n->high.y = Min(a->high.y, b->high.y);
@@ -50,21 +59,26 @@ rt_box_inter(BOX *a, BOX *b)
5059
if (n->high.x < n->low.x || n->high.y < n->low.y)
5160
{
5261
pfree(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+
6276
if (a == (BOX *) NULL || a->high.x <= a->low.x || a->high.y <= a->low.y)
6377
*size = 0.0;
6478
else
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

8498
Datum
@@ -105,30 +119,6 @@ rt_poly_union(PG_FUNCTION_ARGS)
105119
PG_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-
132122
Datum
133123
rt_poly_inter(PG_FUNCTION_ARGS)
134124
{
@@ -146,16 +136,52 @@ rt_poly_inter(PG_FUNCTION_ARGS)
146136
p->boundbox.low.x = Max(a->boundbox.low.x, b->boundbox.low.x);
147137
p->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-
153139
if (p->boundbox.high.x < p->boundbox.low.x ||
154140
p->boundbox.high.y < p->boundbox.low.y)
155141
{
156142
pfree(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+
160151
PG_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+
}

src/backend/access/rtree/rtree.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.52 2000/07/14 22:17:36 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.53 2000/07/30 20:43:40 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -745,13 +745,16 @@ picksplit(Relation r,
745745
DatumGetPointer(FunctionCall2(&rtstate->interFn,
746746
PointerGetDatum(datum_alpha),
747747
PointerGetDatum(datum_beta)));
748+
/* The interFn may return a NULL pointer (not an SQL null!)
749+
* to indicate no intersection. sizeFn must cope with this.
750+
*/
748751
FunctionCall2(&rtstate->sizeFn,
749752
PointerGetDatum(inter_d),
750753
PointerGetDatum(&size_inter));
751754
size_waste = size_union - size_inter;
752755

753-
pfree(union_d);
754-
756+
if (union_d != (char *) NULL)
757+
pfree(union_d);
755758
if (inter_d != (char *) NULL)
756759
pfree(inter_d);
757760

@@ -1051,7 +1054,8 @@ _rtdump(Relation r)
10511054
itoffno = ItemPointerGetOffsetNumber(&(itup->t_tid));
10521055
datum = ((char *) itup);
10531056
datum += sizeof(IndexTupleData);
1054-
itkey = (char *) box_out((BOX *) datum);
1057+
itkey = DatumGetCString(DirectFunctionCall1(box_out,
1058+
PointerGetDatum(datum)));
10551059
printf("\t[%d] size %d heap <%d,%d> key:%s\n",
10561060
offnum, IndexTupleSize(itup), itblkno, itoffno, itkey);
10571061
pfree(itkey);

0 commit comments

Comments
 (0)