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"))); + initStringInfo(&str); - result = palloc(size); - - 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++ != '{') + /* s was already advanced over leading '{' */ + line->A = single_decode(s, &s, "line", str); + if (*s++ != DELIM) return false; - line->A = strtod(str, &tail); - if (tail <= str) + line->B = single_decode(s, &s, "line", str); + if (*s++ != DELIM) return false; - str = tail; - while (isspace((unsigned char) *str)) - str++; - if (*str++ != DELIM) + line->C = single_decode(s, &s, "line", str); + if (*s++ != '}') return false; - line->B = strtod(str, &tail); - if (tail <= str) + while (isspace((unsigned char) *s)) + s++; + if (*s != '\0') return false; - str = tail; - while (isspace((unsigned char) *str)) - str++; - if (*str++ != DELIM) - return false; - line->C = strtod(str, &tail); - if (tail <= str) - return false; - str = tail; - while (isspace((unsigned char) *str)) - str++; - if (*str++ != '}') - return false; - while (isspace((unsigned char) *str)) - str++; - if (*str) - 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; + StringInfoData str; - result = palloc(2 * P_MAXLEN + 6); + initStringInfo(&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"))); + 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); - 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"))); - - cp += strlen(cp); - *cp++ = RDELIM_C; - *cp = '\0'; - - 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)';