Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f31a931

Browse filesBrowse files
committed
Improve contrib/cube's handling of zero-D cubes, infinities, and NaNs.
It's always been possible to create a zero-dimensional cube by converting from a zero-length float8 array, but cube_in failed to accept the '()' representation that cube_out produced for that case, resulting in a dump/reload hazard. Make it accept the case. Also fix a couple of other places that didn't behave sanely for zero-dimensional cubes: cube_size would produce 1.0 when surely the answer should be 0.0, and g_cube_distance risked a divide-by-zero failure. Likewise, it's always been possible to create cubes containing float8 infinity or NaN coordinate values, but cube_in couldn't parse such input, and cube_out produced platform-dependent spellings of the values. Convert them to use float8in_internal and float8out_internal so that the behavior will be the same as for float8, as we recently did for the core geometric types (cf commit 50861cd). As in that commit, I don't pretend that this patch fixes all insane corner-case behaviors that may exist for NaNs, but it's a step forward. (This change allows removal of the separate cube_1.out and cube_3.out expected-files, as the platform dependency that previously required them is now gone: an underflowing coordinate value will now produce an error not plus or minus zero.) Make errors from cube_in follow project conventions as to spelling ("invalid input syntax for cube" not "bad cube representation") and errcode (INVALID_TEXT_REPRESENTATION not SYNTAX_ERROR). Also a few marginal code cleanups and comment improvements. Tom Lane, reviewed by Amul Sul Discussion: <15085.1472494782@sss.pgh.pa.us>
1 parent 51c3e9f commit f31a931
Copy full SHA for f31a931

File tree

Expand file treeCollapse file tree

9 files changed

+275
-3626
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+275
-3626
lines changed

‎contrib/cube/cube.c

Copy file name to clipboardExpand all lines: contrib/cube/cube.c
+20-50Lines changed: 20 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ cube_in(PG_FUNCTION_ARGS)
122122
cube_scanner_init(str);
123123

124124
if (cube_yyparse(&result) != 0)
125-
cube_yyerror(&result, "bogus input");
125+
cube_yyerror(&result, "cube parser failed");
126126

127127
cube_scanner_finish();
128128

@@ -254,12 +254,9 @@ cube_subset(PG_FUNCTION_ARGS)
254254
for (i = 0; i < dim; i++)
255255
{
256256
if ((dx[i] <= 0) || (dx[i] > DIM(c)))
257-
{
258-
pfree(result);
259257
ereport(ERROR,
260258
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
261259
errmsg("Index out of bounds")));
262-
}
263260
result->x[i] = c->x[dx[i] - 1];
264261
if (!IS_POINT(c))
265262
result->x[i + dim] = c->x[dx[i] + DIM(c) - 1];
@@ -276,27 +273,15 @@ cube_out(PG_FUNCTION_ARGS)
276273
StringInfoData buf;
277274
int dim = DIM(cube);
278275
int i;
279-
int ndig;
280276

281277
initStringInfo(&buf);
282278

283-
/*
284-
* Get the number of digits to display.
285-
*/
286-
ndig = DBL_DIG + extra_float_digits;
287-
if (ndig < 1)
288-
ndig = 1;
289-
290-
/*
291-
* while printing the first (LL) corner, check if it is equal to the
292-
* second one
293-
*/
294279
appendStringInfoChar(&buf, '(');
295280
for (i = 0; i < dim; i++)
296281
{
297282
if (i > 0)
298283
appendStringInfoString(&buf, ", ");
299-
appendStringInfo(&buf, "%.*g", ndig, LL_COORD(cube, i));
284+
appendStringInfoString(&buf, float8out_internal(LL_COORD(cube, i)));
300285
}
301286
appendStringInfoChar(&buf, ')');
302287

@@ -307,7 +292,7 @@ cube_out(PG_FUNCTION_ARGS)
307292
{
308293
if (i > 0)
309294
appendStringInfoString(&buf, ", ");
310-
appendStringInfo(&buf, "%.*g", ndig, UR_COORD(cube, i));
295+
appendStringInfoString(&buf, float8out_internal(UR_COORD(cube, i)));
311296
}
312297
appendStringInfoChar(&buf, ')');
313298
}
@@ -370,9 +355,6 @@ g_cube_union(PG_FUNCTION_ARGS)
370355
NDBOX *tmp;
371356
int i;
372357

373-
/*
374-
* fprintf(stderr, "union\n");
375-
*/
376358
tmp = DatumGetNDBOX(entryvec->vector[0].key);
377359

378360
/*
@@ -441,9 +423,6 @@ g_cube_penalty(PG_FUNCTION_ARGS)
441423
rt_cube_size(DatumGetNDBOX(origentry->key), &tmp2);
442424
*result = (float) (tmp1 - tmp2);
443425

444-
/*
445-
* fprintf(stderr, "penalty\n"); fprintf(stderr, "\t%g\n", *result);
446-
*/
447426
PG_RETURN_FLOAT8(*result);
448427
}
449428

@@ -484,9 +463,6 @@ g_cube_picksplit(PG_FUNCTION_ARGS)
484463
*right;
485464
OffsetNumber maxoff;
486465

487-
/*
488-
* fprintf(stderr, "picksplit\n");
489-
*/
490466
maxoff = entryvec->n - 2;
491467
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
492468
v->spl_left = (OffsetNumber *) palloc(nbytes);
@@ -617,9 +593,6 @@ g_cube_same(PG_FUNCTION_ARGS)
617593
else
618594
*result = FALSE;
619595

620-
/*
621-
* fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE" ));
622-
*/
623596
PG_RETURN_NDBOX(result);
624597
}
625598

@@ -633,9 +606,6 @@ g_cube_leaf_consistent(NDBOX *key,
633606
{
634607
bool retval;
635608

636-
/*
637-
* fprintf(stderr, "leaf_consistent, %d\n", strategy);
638-
*/
639609
switch (strategy)
640610
{
641611
case RTOverlapStrategyNumber:
@@ -665,9 +635,6 @@ g_cube_internal_consistent(NDBOX *key,
665635
{
666636
bool retval;
667637

668-
/*
669-
* fprintf(stderr, "internal_consistent, %d\n", strategy);
670-
*/
671638
switch (strategy)
672639
{
673640
case RTOverlapStrategyNumber:
@@ -865,30 +832,35 @@ cube_size(PG_FUNCTION_ARGS)
865832
{
866833
NDBOX *a = PG_GETARG_NDBOX(0);
867834
double result;
868-
int i;
869-
870-
result = 1.0;
871-
for (i = 0; i < DIM(a); i++)
872-
result = result * Abs((LL_COORD(a, i) - UR_COORD(a, i)));
873835

836+
rt_cube_size(a, &result);
874837
PG_FREE_IF_COPY(a, 0);
875838
PG_RETURN_FLOAT8(result);
876839
}
877840

878841
void
879842
rt_cube_size(NDBOX *a, double *size)
880843
{
844+
double result;
881845
int i;
882846

883847
if (a == (NDBOX *) NULL)
884-
*size = 0.0;
848+
{
849+
/* special case for GiST */
850+
result = 0.0;
851+
}
852+
else if (IS_POINT(a) || DIM(a) == 0)
853+
{
854+
/* necessarily has zero size */
855+
result = 0.0;
856+
}
885857
else
886858
{
887-
*size = 1.0;
859+
result = 1.0;
888860
for (i = 0; i < DIM(a); i++)
889-
*size = (*size) * Abs(UR_COORD(a, i) - LL_COORD(a, i));
861+
result *= Abs(UR_COORD(a, i) - LL_COORD(a, i));
890862
}
891-
return;
863+
*size = result;
892864
}
893865

894866
/* make up a metric in which one box will be 'lower' than the other
@@ -1155,10 +1127,6 @@ cube_overlap_v0(NDBOX *a, NDBOX *b)
11551127
{
11561128
int i;
11571129

1158-
/*
1159-
* This *very bad* error was found in the source: if ( (a==NULL) ||
1160-
* (b=NULL) ) return(FALSE);
1161-
*/
11621130
if ((a == NULL) || (b == NULL))
11631131
return (FALSE);
11641132

@@ -1370,7 +1338,9 @@ g_cube_distance(PG_FUNCTION_ARGS)
13701338
{
13711339
int coord = PG_GETARG_INT32(1);
13721340

1373-
if (IS_POINT(cube))
1341+
if (DIM(cube) == 0)
1342+
retval = 0.0;
1343+
else if (IS_POINT(cube))
13741344
retval = cube->x[(coord - 1) % DIM(cube)];
13751345
else
13761346
retval = Min(cube->x[(coord - 1) % DIM(cube)],

‎contrib/cube/cubedata.h

Copy file name to clipboardExpand all lines: contrib/cube/cubedata.h
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
/* contrib/cube/cubedata.h */
22

3+
/*
4+
* This limit is pretty arbitrary, but don't make it so large that you
5+
* risk overflow in sizing calculations.
6+
*/
37
#define CUBE_MAX_DIM (100)
48

59
typedef struct NDBOX
@@ -29,6 +33,7 @@ typedef struct NDBOX
2933
double x[FLEXIBLE_ARRAY_MEMBER];
3034
} NDBOX;
3135

36+
/* NDBOX access macros */
3237
#define POINT_BIT 0x80000000
3338
#define DIM_MASK 0x7fffffff
3439

@@ -43,10 +48,12 @@ typedef struct NDBOX
4348
#define POINT_SIZE(_dim) (offsetof(NDBOX, x) + sizeof(double)*(_dim))
4449
#define CUBE_SIZE(_dim) (offsetof(NDBOX, x) + sizeof(double)*(_dim)*2)
4550

51+
/* fmgr interface macros */
4652
#define DatumGetNDBOX(x) ((NDBOX *) PG_DETOAST_DATUM(x))
4753
#define PG_GETARG_NDBOX(x) DatumGetNDBOX(PG_GETARG_DATUM(x))
4854
#define PG_RETURN_NDBOX(x) PG_RETURN_POINTER(x)
4955

56+
/* GiST operator strategy numbers */
5057
#define CubeKNNDistanceCoord 15 /* ~> */
5158
#define CubeKNNDistanceTaxicab 16 /* <#> */
5259
#define CubeKNNDistanceEuclid 17 /* <-> */

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.