aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/float.c85
-rw-r--r--src/backend/utils/adt/geo_ops.c458
-rw-r--r--src/include/utils/builtins.h3
-rw-r--r--src/test/regress/expected/box.out40
4 files changed, 272 insertions, 314 deletions
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index d4e5d553477..4ee93ac04e1 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -411,17 +411,35 @@ Datum
float8in(PG_FUNCTION_ARGS)
{
char *num = PG_GETARG_CSTRING(0);
- char *orig_num;
+
+ PG_RETURN_FLOAT8(float8in_internal(num, NULL, "double precision", num));
+}
+
+/*
+ * float8in_internal - guts of float8in()
+ *
+ * This is exposed for use by functions that want a reasonably
+ * platform-independent way of inputting doubles. The behavior is
+ * essentially like strtod + ereport on error, but note the following
+ * differences:
+ * 1. Both leading and trailing whitespace are skipped.
+ * 2. If endptr_p is NULL, we throw error if there's trailing junk.
+ * Otherwise, it's up to the caller to complain about trailing junk.
+ * 3. In event of a syntax error, the report mentions the given type_name
+ * and prints orig_string as the input; this is meant to support use of
+ * this function with types such as "box" and "point", where what we are
+ * parsing here is just a substring of orig_string.
+ *
+ * "num" could validly be declared "const char *", but that results in an
+ * unreasonable amount of extra casting both here and in callers, so we don't.
+ */
+double
+float8in_internal(char *num, char **endptr_p,
+ const char *type_name, const char *orig_string)
+{
double val;
char *endptr;
- /*
- * endptr points to the first character _after_ the sequence we recognized
- * as a valid floating point number. orig_num points to the original input
- * string.
- */
- orig_num = num;
-
/* skip leading whitespace */
while (*num != '\0' && isspace((unsigned char) *num))
num++;
@@ -433,8 +451,8 @@ float8in(PG_FUNCTION_ARGS)
if (*num == '\0')
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type double precision: \"%s\"",
- orig_num)));
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
errno = 0;
val = strtod(num, &endptr);
@@ -497,18 +515,27 @@ float8in(PG_FUNCTION_ARGS)
* precision). We'd prefer not to throw error for that, so try to
* detect whether it's a "real" out-of-range condition by checking
* to see if the result is zero or huge.
+ *
+ * On error, we intentionally complain about double precision not
+ * the given type name, and we print only the part of the string
+ * that is the current number.
*/
if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
+ {
+ char *errnumber = pstrdup(num);
+
+ errnumber[endptr - num] = '\0';
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("\"%s\" is out of range for type double precision",
- orig_num)));
+ errnumber)));
+ }
}
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type double precision: \"%s\"",
- orig_num)));
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
}
#ifdef HAVE_BUGGY_SOLARIS_STRTOD
else
@@ -527,16 +554,16 @@ float8in(PG_FUNCTION_ARGS)
while (*endptr != '\0' && isspace((unsigned char) *endptr))
endptr++;
- /* if there is any junk left at the end of the string, bail out */
- if (*endptr != '\0')
+ /* report stopping point if wanted, else complain if not end of string */
+ if (endptr_p)
+ *endptr_p = endptr;
+ else if (*endptr != '\0')
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type double precision: \"%s\"",
- orig_num)));
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
- CHECKFLOATVAL(val, true, true);
-
- PG_RETURN_FLOAT8(val);
+ return val;
}
/*
@@ -547,10 +574,24 @@ Datum
float8out(PG_FUNCTION_ARGS)
{
float8 num = PG_GETARG_FLOAT8(0);
+
+ PG_RETURN_CSTRING(float8out_internal(num));
+}
+
+/*
+ * float8out_internal - guts of float8out()
+ *
+ * This is exposed for use by functions that want a reasonably
+ * platform-independent way of outputting doubles.
+ * The result is always palloc'd.
+ */
+char *
+float8out_internal(double num)
+{
char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
if (isnan(num))
- PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
+ return strcpy(ascii, "NaN");
switch (is_infinite(num))
{
@@ -571,7 +612,7 @@ float8out(PG_FUNCTION_ARGS)
}
}
- PG_RETURN_CSTRING(ascii);
+ return ascii;
}
/*
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index b84673d64c1..657bcee4fd4 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -57,12 +57,16 @@ static void make_bound_box(POLYGON *poly);
static bool plist_same(int npts, Point *p1, Point *p2);
static Point *point_construct(double x, double y);
static Point *point_copy(Point *pt);
-static int single_decode(char *str, float8 *x, char **ss);
-static int single_encode(float8 x, char *str);
-static int pair_decode(char *str, float8 *x, float8 *y, char **s);
-static int pair_encode(float8 x, float8 y, char *str);
+static double single_decode(char *num, char **endptr_p,
+ const char *type_name, const char *orig_string);
+static void single_encode(float8 x, StringInfo str);
+static void pair_decode(char *str, double *x, double *y, char **endptr_p,
+ const char *type_name, const char *orig_string);
+static void pair_encode(float8 x, float8 y, StringInfo str);
static int pair_count(char *s, char delim);
-static int path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p);
+static void path_decode(char *str, bool opentype, int npts, Point *p,
+ bool *isopen, char **endptr_p,
+ const char *type_name, const char *orig_string);
static char *path_encode(enum path_delim path_delim, int npts, Point *pt);
static void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2);
static double box_ar(BOX *box);
@@ -91,10 +95,6 @@ static double dist_ppoly_internal(Point *pt, POLYGON *poly);
#define LDELIM_C '<'
#define RDELIM_C '>'
-/* Maximum number of characters printed by pair_encode() */
-/* ...+3+7 : 3 accounts for extra_float_digits max value */
-#define P_MAXLEN (2*(DBL_DIG+3+7)+1)
-
/*
* Geometric data types are composed of points.
@@ -121,195 +121,166 @@ static double dist_ppoly_internal(Point *pt, POLYGON *poly);
* and restore that order for text output - tgl 97/01/16
*/
-static int
-single_decode(char *str, float8 *x, char **s)
+static double
+single_decode(char *num, char **endptr_p,
+ const char *type_name, const char *orig_string)
{
- char *cp;
-
- if (!PointerIsValid(str))
- return FALSE;
-
- *x = strtod(str, &cp);
-
-#ifdef GEODEBUG
- printf("single_decode- decoded first %d chars of \"%s\" to %g\n",
- (int) (cp - str), str, *x);
-#endif
-
- if (s != NULL)
- {
- while (isspace((unsigned char) *cp))
- cp++;
- *s = cp;
- }
-
- return TRUE;
+ return float8in_internal(num, endptr_p, type_name, orig_string);
} /* single_decode() */
-static int
-single_encode(float8 x, char *str)
+static void
+single_encode(float8 x, StringInfo str)
{
- int ndig = DBL_DIG + extra_float_digits;
+ char *xstr = float8out_internal(x);
- if (ndig < 1)
- ndig = 1;
-
- sprintf(str, "%.*g", ndig, x);
- return TRUE;
+ appendStringInfoString(str, xstr);
+ pfree(xstr);
} /* single_encode() */
-static int
-pair_decode(char *str, float8 *x, float8 *y, char **s)
+static void
+pair_decode(char *str, double *x, double *y, char **endptr_p,
+ const char *type_name, const char *orig_string)
{
- int has_delim;
- char *cp;
-
- if (!PointerIsValid(str))
- return FALSE;
+ bool has_delim;
while (isspace((unsigned char) *str))
str++;
if ((has_delim = (*str == LDELIM)))
str++;
- while (isspace((unsigned char) *str))
- str++;
- *x = strtod(str, &cp);
- if (cp <= str)
- return FALSE;
- while (isspace((unsigned char) *cp))
- cp++;
- if (*cp++ != DELIM)
- return FALSE;
- while (isspace((unsigned char) *cp))
- cp++;
- *y = strtod(cp, &str);
- if (str <= cp)
- return FALSE;
- while (isspace((unsigned char) *str))
- str++;
+ *x = float8in_internal(str, &str, type_name, orig_string);
+
+ if (*str++ != DELIM)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
+
+ *y = float8in_internal(str, &str, type_name, orig_string);
+
if (has_delim)
{
- if (*str != RDELIM)
- return FALSE;
- str++;
+ if (*str++ != RDELIM)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
while (isspace((unsigned char) *str))
str++;
}
- if (s != NULL)
- *s = str;
- return TRUE;
+ /* report stopping point if wanted, else complain if not end of string */
+ if (endptr_p)
+ *endptr_p = str;
+ else if (*str != '\0')
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
}
-static int
-pair_encode(float8 x, float8 y, char *str)
+static void
+pair_encode(float8 x, float8 y, StringInfo str)
{
- int ndig = DBL_DIG + extra_float_digits;
+ char *xstr = float8out_internal(x);
+ char *ystr = float8out_internal(y);
- if (ndig < 1)
- ndig = 1;
-
- sprintf(str, "%.*g,%.*g", ndig, x, ndig, y);
- return TRUE;
+ appendStringInfo(str, "%s,%s", xstr, ystr);
+ pfree(xstr);
+ pfree(ystr);
}
-static int
-path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p)
+static void
+path_decode(char *str, bool opentype, int npts, Point *p,
+ bool *isopen, char **endptr_p,
+ const char *type_name, const char *orig_string)
{
int depth = 0;
- char *s,
- *cp;
+ char *cp;
int i;
- s = str;
- while (isspace((unsigned char) *s))
- s++;
- if ((*isopen = (*s == LDELIM_EP)))
+ while (isspace((unsigned char) *str))
+ str++;
+ if ((*isopen = (*str == LDELIM_EP)))
{
/* no open delimiter allowed? */
if (!opentype)
- return FALSE;
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
depth++;
- s++;
- while (isspace((unsigned char) *s))
- s++;
-
+ str++;
}
- else if (*s == LDELIM)
+ else if (*str == LDELIM)
{
- cp = (s + 1);
+ cp = (str + 1);
while (isspace((unsigned char) *cp))
cp++;
if (*cp == LDELIM)
{
-#ifdef NOT_USED
- /* nested delimiters with only one point? */
- if (npts <= 1)
- return FALSE;
-#endif
depth++;
- s = cp;
+ str = cp;
}
- else if (strrchr(s, LDELIM) == s)
+ else if (strrchr(str, LDELIM) == str)
{
depth++;
- s = cp;
+ str = cp;
}
}
for (i = 0; i < npts; i++)
{
- if (!pair_decode(s, &(p->x), &(p->y), &s))
- return FALSE;
-
- if (*s == DELIM)
- s++;
+ pair_decode(str, &(p->x), &(p->y), &str, type_name, orig_string);
+ if (*str == DELIM)
+ str++;
p++;
}
+ while (isspace((unsigned char) *str))
+ str++;
while (depth > 0)
{
- if ((*s == RDELIM)
- || ((*s == RDELIM_EP) && (*isopen) && (depth == 1)))
+ if ((*str == RDELIM)
+ || ((*str == RDELIM_EP) && (*isopen) && (depth == 1)))
{
depth--;
- s++;
- while (isspace((unsigned char) *s))
- s++;
+ str++;
+ while (isspace((unsigned char) *str))
+ str++;
}
else
- return FALSE;
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
}
- *ss = s;
- return TRUE;
+ /* report stopping point if wanted, else complain if not end of string */
+ if (endptr_p)
+ *endptr_p = str;
+ else if (*str != '\0')
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
} /* path_decode() */
static char *
path_encode(enum path_delim path_delim, int npts, Point *pt)
{
- int size = npts * (P_MAXLEN + 3) + 2;
- char *result;
- char *cp;
+ StringInfoData str;
int i;
- /* Check for integer overflow */
- if ((size - 2) / npts != (P_MAXLEN + 3))
- ereport(ERROR,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("too many points requested")));
-
- result = palloc(size);
+ initStringInfo(&str);
- cp = result;
switch (path_delim)
{
case PATH_CLOSED:
- *cp++ = LDELIM;
+ appendStringInfoChar(&str, LDELIM);
break;
case PATH_OPEN:
- *cp++ = LDELIM_EP;
+ appendStringInfoChar(&str, LDELIM_EP);
break;
case PATH_NONE:
break;
@@ -317,32 +288,27 @@ path_encode(enum path_delim path_delim, int npts, Point *pt)
for (i = 0; i < npts; i++)
{
- *cp++ = LDELIM;
- if (!pair_encode(pt->x, pt->y, cp))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("could not format \"path\" value")));
-
- cp += strlen(cp);
- *cp++ = RDELIM;
- *cp++ = DELIM;
+ if (i > 0)
+ appendStringInfoChar(&str, DELIM);
+ appendStringInfoChar(&str, LDELIM);
+ pair_encode(pt->x, pt->y, &str);
+ appendStringInfoChar(&str, RDELIM);
pt++;
}
- cp--;
+
switch (path_delim)
{
case PATH_CLOSED:
- *cp++ = RDELIM;
+ appendStringInfoChar(&str, RDELIM);
break;
case PATH_OPEN:
- *cp++ = RDELIM_EP;
+ appendStringInfoChar(&str, RDELIM_EP);
break;
case PATH_NONE:
break;
}
- *cp = '\0';
- return result;
+ return str.data;
} /* path_encode() */
/*-------------------------------------------------------------
@@ -387,16 +353,11 @@ box_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
BOX *box = (BOX *) palloc(sizeof(BOX));
- int isopen;
- char *s;
+ bool isopen;
double x,
y;
- if ((!path_decode(FALSE, 2, str, &isopen, &s, &(box->high)))
- || (*s != '\0'))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type box: \"%s\"", str)));
+ path_decode(str, false, 2, &(box->high), &isopen, NULL, "box", str);
/* reorder corners if necessary... */
if (box->high.x < box->low.x)
@@ -935,43 +896,22 @@ box_diagonal(PG_FUNCTION_ARGS)
***********************************************************************/
static bool
-line_decode(const char *str, LINE *line)
+line_decode(char *s, const char *str, LINE *line)
{
- char *tail;
-
- while (isspace((unsigned char) *str))
- str++;
- if (*str++ != '{')
- return false;
- line->A = strtod(str, &tail);
- if (tail <= str)
- return false;
- str = tail;
- while (isspace((unsigned char) *str))
- str++;
- if (*str++ != DELIM)
- return false;
- line->B = strtod(str, &tail);
- if (tail <= str)
+ /* s was already advanced over leading '{' */
+ line->A = single_decode(s, &s, "line", str);
+ if (*s++ != DELIM)
return false;
- str = tail;
- while (isspace((unsigned char) *str))
- str++;
- if (*str++ != DELIM)
+ line->B = single_decode(s, &s, "line", str);
+ if (*s++ != DELIM)
return false;
- line->C = strtod(str, &tail);
- if (tail <= str)
- return false;
- str = tail;
- while (isspace((unsigned char) *str))
- str++;
- if (*str++ != '}')
+ line->C = single_decode(s, &s, "line", str);
+ if (*s++ != '}')
return false;
- while (isspace((unsigned char) *str))
- str++;
- if (*str)
+ while (isspace((unsigned char) *s))
+ s++;
+ if (*s != '\0')
return false;
-
return true;
}
@@ -979,33 +919,35 @@ Datum
line_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
- LINE *line;
+ LINE *line = (LINE *) palloc(sizeof(LINE));
LSEG lseg;
- int isopen;
+ bool isopen;
char *s;
- line = (LINE *) palloc(sizeof(LINE));
-
- if (path_decode(TRUE, 2, str, &isopen, &s, &(lseg.p[0])) && *s == '\0')
+ s = str;
+ while (isspace((unsigned char) *s))
+ s++;
+ if (*s == '{')
{
- if (FPeq(lseg.p[0].x, lseg.p[1].x) && FPeq(lseg.p[0].y, lseg.p[1].y))
+ if (!line_decode(s + 1, str, line))
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid line specification: must be two distinct points")));
-
- line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
- }
- else if (line_decode(str, line))
- {
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ "line", str)));
if (FPzero(line->A) && FPzero(line->B))
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid line specification: A and B cannot both be zero")));
}
else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type line: \"%s\"", str)));
+ {
+ path_decode(s, true, 2, &(lseg.p[0]), &isopen, NULL, "line", str);
+ if (FPeq(lseg.p[0].x, lseg.p[1].x) && FPeq(lseg.p[0].y, lseg.p[1].y))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid line specification: must be two distinct points")));
+ line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
+ }
PG_RETURN_LINE_P(line);
}
@@ -1015,12 +957,11 @@ Datum
line_out(PG_FUNCTION_ARGS)
{
LINE *line = PG_GETARG_LINE_P(0);
- int ndig = DBL_DIG + extra_float_digits;
+ char *astr = float8out_internal(line->A);
+ char *bstr = float8out_internal(line->B);
+ char *cstr = float8out_internal(line->C);
- if (ndig < 1)
- ndig = 1;
-
- PG_RETURN_CSTRING(psprintf("{%.*g,%.*g,%.*g}", ndig, line->A, ndig, line->B, ndig, line->C));
+ PG_RETURN_CSTRING(psprintf("{%s,%s,%s}", astr, bstr, cstr));
}
/*
@@ -1367,7 +1308,7 @@ path_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
PATH *path;
- int isopen;
+ bool isopen;
char *s;
int npts;
int size;
@@ -1377,7 +1318,8 @@ path_in(PG_FUNCTION_ARGS)
if ((npts = pair_count(str, ',')) <= 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type path: \"%s\"", str)));
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ "path", str)));
s = str;
while (isspace((unsigned char) *s))
@@ -1404,11 +1346,23 @@ path_in(PG_FUNCTION_ARGS)
SET_VARSIZE(path, size);
path->npts = npts;
- if ((!path_decode(TRUE, npts, s, &isopen, &s, &(path->p[0])))
- && (!((depth == 0) && (*s == '\0'))) && !((depth >= 1) && (*s == RDELIM)))
+ path_decode(s, true, npts, &(path->p[0]), &isopen, &s, "path", str);
+
+ if (depth >= 1)
+ {
+ if (*s++ != RDELIM)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ "path", str)));
+ while (isspace((unsigned char) *s))
+ s++;
+ }
+ if (*s != '\0')
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type path: \"%s\"", str)));
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ "path", str)));
path->closed = (!isopen);
/* prevent instability in unused pad bytes */
@@ -1782,21 +1736,9 @@ Datum
point_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
- Point *point;
- double x,
- y;
- char *s;
-
- if (!pair_decode(str, &x, &y, &s) || (*s != '\0'))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type point: \"%s\"", str)));
-
- point = (Point *) palloc(sizeof(Point));
-
- point->x = x;
- point->y = y;
+ Point *point = (Point *) palloc(sizeof(Point));
+ pair_decode(str, &point->x, &point->y, NULL, "point", str);
PG_RETURN_POINT_P(point);
}
@@ -2008,18 +1950,10 @@ Datum
lseg_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
- LSEG *lseg;
- int isopen;
- char *s;
-
- lseg = (LSEG *) palloc(sizeof(LSEG));
-
- if ((!path_decode(TRUE, 2, str, &isopen, &s, &(lseg->p[0])))
- || (*s != '\0'))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type lseg: \"%s\"", str)));
+ LSEG *lseg = (LSEG *) palloc(sizeof(LSEG));
+ bool isopen;
+ path_decode(str, true, 2, &(lseg->p[0]), &isopen, NULL, "lseg", str);
PG_RETURN_LSEG_P(lseg);
}
@@ -3480,13 +3414,13 @@ poly_in(PG_FUNCTION_ARGS)
int npts;
int size;
int base_size;
- int isopen;
- char *s;
+ bool isopen;
if ((npts = pair_count(str, ',')) <= 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type polygon: \"%s\"", str)));
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ "polygon", str)));
base_size = sizeof(poly->p[0]) * npts;
size = offsetof(POLYGON, p) +base_size;
@@ -3502,11 +3436,7 @@ poly_in(PG_FUNCTION_ARGS)
SET_VARSIZE(poly, size);
poly->npts = npts;
- if ((!path_decode(FALSE, npts, str, &isopen, &s, &(poly->p[0])))
- || (*s != '\0'))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type polygon: \"%s\"", str)));
+ path_decode(str, false, npts, &(poly->p[0]), &isopen, NULL, "polygon", str);
make_bound_box(poly);
@@ -4595,13 +4525,11 @@ Datum
circle_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
- CIRCLE *circle;
+ CIRCLE *circle = (CIRCLE *) palloc(sizeof(CIRCLE));
char *s,
*cp;
int depth = 0;
- circle = (CIRCLE *) palloc(sizeof(CIRCLE));
-
s = str;
while (isspace((unsigned char) *s))
s++;
@@ -4615,20 +4543,17 @@ circle_in(PG_FUNCTION_ARGS)
s = cp;
}
- if (!pair_decode(s, &circle->center.x, &circle->center.y, &s))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type circle: \"%s\"", str)));
+ pair_decode(s, &circle->center.x, &circle->center.y, &s, "circle", str);
if (*s == DELIM)
s++;
- while (isspace((unsigned char) *s))
- s++;
- if ((!single_decode(s, &circle->radius, &s)) || (circle->radius < 0))
+ circle->radius = single_decode(s, &s, "circle", str);
+ if (circle->radius < 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type circle: \"%s\"", str)));
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ "circle", str)));
while (depth > 0)
{
@@ -4643,13 +4568,15 @@ circle_in(PG_FUNCTION_ARGS)
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type circle: \"%s\"", str)));
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ "circle", str)));
}
if (*s != '\0')
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type circle: \"%s\"", str)));
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ "circle", str)));
PG_RETURN_CIRCLE_P(circle);
}
@@ -4660,32 +4587,19 @@ Datum
circle_out(PG_FUNCTION_ARGS)
{
CIRCLE *circle = PG_GETARG_CIRCLE_P(0);
- char *result;
- char *cp;
-
- result = palloc(2 * P_MAXLEN + 6);
+ StringInfoData str;
- cp = result;
- *cp++ = LDELIM_C;
- *cp++ = LDELIM;
- if (!pair_encode(circle->center.x, circle->center.y, cp))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("could not format \"circle\" value")));
-
- cp += strlen(cp);
- *cp++ = RDELIM;
- *cp++ = DELIM;
- if (!single_encode(circle->radius, cp))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("could not format \"circle\" value")));
+ initStringInfo(&str);
- cp += strlen(cp);
- *cp++ = RDELIM_C;
- *cp = '\0';
+ appendStringInfoChar(&str, LDELIM_C);
+ appendStringInfoChar(&str, LDELIM);
+ pair_encode(circle->center.x, circle->center.y, &str);
+ appendStringInfoChar(&str, RDELIM);
+ appendStringInfoChar(&str, DELIM);
+ single_encode(circle->radius, &str);
+ appendStringInfoChar(&str, RDELIM_C);
- PG_RETURN_CSTRING(result);
+ PG_RETURN_CSTRING(str.data);
}
/*
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 206288da810..d5c4b01ada4 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -343,6 +343,9 @@ extern float get_float4_infinity(void);
extern double get_float8_nan(void);
extern float get_float4_nan(void);
extern int is_infinite(double val);
+extern double float8in_internal(char *num, char **endptr_p,
+ const char *type_name, const char *orig_string);
+extern char *float8out_internal(double num);
extern Datum float4in(PG_FUNCTION_ARGS);
extern Datum float4out(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/box.out b/src/test/regress/expected/box.out
index 300190f762d..7e251a3a569 100644
--- a/src/test/regress/expected/box.out
+++ b/src/test/regress/expected/box.out
@@ -232,15 +232,15 @@ INSERT INTO box_temp
('(-infinity,-infinity)(infinity,infinity)');
SET enable_seqscan = false;
SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
- f1
-------------------
+ f1
+----------------------------
(2,2),(1,1)
(4,4),(2,2)
(6,6),(3,3)
(8,8),(4,4)
(-0,100),(0,0)
- (0,inf),(0,100)
- (0,inf),(-inf,0)
+ (0,Infinity),(0,100)
+ (0,Infinity),(-Infinity,0)
(7 rows)
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
@@ -251,16 +251,16 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
(2 rows)
SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
- f1
-------------------
+ f1
+----------------------------
(2,2),(1,1)
(4,4),(2,2)
(6,6),(3,3)
(8,8),(4,4)
(10,10),(5,5)
(-0,100),(0,0)
- (0,inf),(0,100)
- (0,inf),(-inf,0)
+ (0,Infinity),(0,100)
+ (0,Infinity),(-Infinity,0)
(8 rows)
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
@@ -271,8 +271,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
(2 rows)
SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
- f1
------------------------
+ f1
+-------------------------------------------
(20,20),(10,10)
(22,22),(11,11)
(24,24),(12,12)
@@ -289,7 +289,7 @@ SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
(46,46),(23,23)
(48,48),(24,24)
(50,50),(25,25)
- (inf,inf),(-inf,-inf)
+ (Infinity,Infinity),(-Infinity,-Infinity)
(17 rows)
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
@@ -375,10 +375,10 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &<| '(10,4.3333334),(5,1)';
(2 rows)
SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49.99)';
- f1
--------------------
+ f1
+----------------------
(100,100),(50,50)
- (0,inf),(0,100)
+ (0,Infinity),(0,100)
(2 rows)
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49.99)';
@@ -389,8 +389,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49
(2 rows)
SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
- f1
--------------------
+ f1
+----------------------
(82,82),(41,41)
(84,84),(42,42)
(86,86),(43,43)
@@ -401,7 +401,7 @@ SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
(96,96),(48,48)
(98,98),(49,49)
(100,100),(50,50)
- (0,inf),(0,100)
+ (0,Infinity),(0,100)
(11 rows)
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
@@ -412,12 +412,12 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
(2 rows)
SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,16)';
- f1
------------------------
+ f1
+-------------------------------------------
(16,16),(8,8)
(18,18),(9,9)
(20,20),(10,10)
- (inf,inf),(-inf,-inf)
+ (Infinity,Infinity),(-Infinity,-Infinity)
(4 rows)
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,15)';