#include "libpq/pqformat.h"
#include "miscadmin.h"
+#include "nodes/miscnodes.h"
#include "utils/float.h"
#include "utils/fmgrprotos.h"
#include "utils/geo_decls.h"
static float8 dist_ppoly_internal(Point *pt, POLYGON *poly);
/* Routines for encoding and decoding */
-static float8 single_decode(char *num, char **endptr_p,
- const char *type_name, const char *orig_string);
+static bool single_decode(char *num, float8 *x, char **endptr_p,
+ const char *type_name, const char *orig_string,
+ Node *escontext);
static void single_encode(float8 x, StringInfo str);
-static void pair_decode(char *str, float8 *x, float8 *y, char **endptr_p,
- const char *type_name, const char *orig_string);
+static bool pair_decode(char *str, float8 *x, float8 *y, char **endptr_p,
+ const char *type_name, const char *orig_string,
+ Node *escontext);
static void pair_encode(float8 x, float8 y, StringInfo str);
static int pair_count(char *s, char delim);
-static void path_decode(char *str, bool opentype, int npts, Point *p,
+static bool path_decode(char *str, bool opentype, int npts, Point *p,
bool *isopen, char **endptr_p,
- const char *type_name, const char *orig_string);
+ const char *type_name, const char *orig_string,
+ Node *escontext);
static char *path_encode(enum path_delim path_delim, int npts, Point *pt);
* and restore that order for text output - tgl 97/01/16
*/
-static float8
-single_decode(char *num, char **endptr_p,
- const char *type_name, const char *orig_string)
+static bool
+single_decode(char *num, float8 *x, char **endptr_p,
+ const char *type_name, const char *orig_string,
+ Node *escontext)
{
- return float8in_internal(num, endptr_p, type_name, orig_string, NULL);
+ *x = float8in_internal(num, endptr_p, type_name, orig_string, escontext);
+ return (!SOFT_ERROR_OCCURRED(escontext));
} /* single_decode() */
static void
pfree(xstr);
} /* single_encode() */
-static void
+static bool
pair_decode(char *str, float8 *x, float8 *y, char **endptr_p,
- const char *type_name, const char *orig_string)
+ const char *type_name, const char *orig_string,
+ Node *escontext)
{
bool has_delim;
if ((has_delim = (*str == LDELIM)))
str++;
- *x = float8in_internal(str, &str, type_name, orig_string, NULL);
+ if (!single_decode(str, x, &str, type_name, orig_string, escontext))
+ return false;
if (*str++ != DELIM)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s: \"%s\"",
- type_name, orig_string)));
+ goto fail;
- *y = float8in_internal(str, &str, type_name, orig_string, NULL);
+ if (!single_decode(str, y, &str, type_name, orig_string, escontext))
+ return false;
if (has_delim)
{
if (*str++ != RDELIM)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s: \"%s\"",
- type_name, orig_string)));
+ goto fail;
while (isspace((unsigned char) *str))
str++;
}
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)));
+ goto fail;
+ return true;
+
+fail:
+ ereturn(escontext, false,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
}
static void
pfree(ystr);
}
-static void
+static bool
path_decode(char *str, bool opentype, int npts, Point *p,
bool *isopen, char **endptr_p,
- const char *type_name, const char *orig_string)
+ const char *type_name, const char *orig_string,
+ Node *escontext)
{
int depth = 0;
char *cp;
{
/* no open delimiter allowed? */
if (!opentype)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s: \"%s\"",
- type_name, orig_string)));
+ goto fail;
depth++;
str++;
}
for (i = 0; i < npts; i++)
{
- pair_decode(str, &(p->x), &(p->y), &str, type_name, orig_string);
+ if (!pair_decode(str, &(p->x), &(p->y), &str, type_name, orig_string,
+ escontext))
+ return false;
if (*str == DELIM)
str++;
p++;
str++;
}
else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s: \"%s\"",
- type_name, orig_string)));
+ goto fail;
}
/* 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)));
+ goto fail;
+ return true;
+
+fail:
+ ereturn(escontext, false,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ type_name, orig_string)));
} /* path_decode() */
static char *
box_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
BOX *box = (BOX *) palloc(sizeof(BOX));
bool isopen;
float8 x,
y;
- path_decode(str, false, 2, &(box->high), &isopen, NULL, "box", str);
+ if (!path_decode(str, false, 2, &(box->high), &isopen, NULL, "box", str,
+ escontext))
+ PG_RETURN_NULL();
/* reorder corners if necessary... */
if (float8_lt(box->high.x, box->low.x))
***********************************************************************/
static bool
-line_decode(char *s, const char *str, LINE *line)
+line_decode(char *s, const char *str, LINE *line, Node *escontext)
{
/* s was already advanced over leading '{' */
- line->A = single_decode(s, &s, "line", str);
+ if (!single_decode(s, &line->A, &s, "line", str, escontext))
+ return false;
if (*s++ != DELIM)
+ goto fail;
+ if (!single_decode(s, &line->B, &s, "line", str, escontext))
return false;
- line->B = single_decode(s, &s, "line", str);
if (*s++ != DELIM)
+ goto fail;
+ if (!single_decode(s, &line->C, &s, "line", str, escontext))
return false;
- line->C = single_decode(s, &s, "line", str);
if (*s++ != RDELIM_L)
- return false;
+ goto fail;
while (isspace((unsigned char) *s))
s++;
if (*s != '\0')
- return false;
+ goto fail;
return true;
+
+fail:
+ ereturn(escontext, false,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ "line", str)));
}
Datum
line_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
LINE *line = (LINE *) palloc(sizeof(LINE));
LSEG lseg;
bool isopen;
s++;
if (*s == LDELIM_L)
{
- if (!line_decode(s + 1, str, line))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s: \"%s\"",
- "line", str)));
+ if (!line_decode(s + 1, str, line, escontext))
+ PG_RETURN_NULL();
if (FPzero(line->A) && FPzero(line->B))
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid line specification: A and B cannot both be zero")));
}
else
{
- path_decode(s, true, 2, &lseg.p[0], &isopen, NULL, "line", str);
+ if (!path_decode(s, true, 2, &lseg.p[0], &isopen, NULL, "line", str,
+ escontext))
+ PG_RETURN_NULL();
if (point_eq_point(&lseg.p[0], &lseg.p[1]))
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid line specification: must be two distinct points")));
+
+ /*
+ * XXX lseg_sl() and line_construct() can throw overflow/underflow
+ * errors. Eventually we should allow those to be soft, but the
+ * notational pain seems to outweigh the value for now.
+ */
line_construct(line, &lseg.p[0], lseg_sl(&lseg));
}
path_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
PATH *path;
bool isopen;
char *s;
int depth = 0;
if ((npts = pair_count(str, ',')) <= 0)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"",
"path", str)));
/* Check for integer overflow */
if (base_size / npts != sizeof(path->p[0]) || size <= base_size)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many points requested")));
SET_VARSIZE(path, size);
path->npts = npts;
- path_decode(s, true, npts, &(path->p[0]), &isopen, &s, "path", str);
+ if (!path_decode(s, true, npts, &(path->p[0]), &isopen, &s, "path", str,
+ escontext))
+ PG_RETURN_NULL();
if (depth >= 1)
{
if (*s++ != RDELIM)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"",
"path", str)));
s++;
}
if (*s != '\0')
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"",
"path", str)));
char *str = PG_GETARG_CSTRING(0);
Point *point = (Point *) palloc(sizeof(Point));
- pair_decode(str, &point->x, &point->y, NULL, "point", str);
+ /* Ignore failure from pair_decode, since our return value won't matter */
+ pair_decode(str, &point->x, &point->y, NULL, "point", str, fcinfo->context);
PG_RETURN_POINT_P(point);
}
lseg_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
LSEG *lseg = (LSEG *) palloc(sizeof(LSEG));
bool isopen;
- path_decode(str, true, 2, &lseg->p[0], &isopen, NULL, "lseg", str);
+ if (!path_decode(str, true, 2, &lseg->p[0], &isopen, NULL, "lseg", str,
+ escontext))
+ PG_RETURN_NULL();
+
PG_RETURN_LSEG_P(lseg);
}
poly_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
POLYGON *poly;
int npts;
int size;
bool isopen;
if ((npts = pair_count(str, ',')) <= 0)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"",
"polygon", str)));
/* Check for integer overflow */
if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many points requested")));
SET_VARSIZE(poly, size);
poly->npts = npts;
- path_decode(str, false, npts, &(poly->p[0]), &isopen, NULL, "polygon", str);
+ if (!path_decode(str, false, npts, &(poly->p[0]), &isopen, NULL, "polygon",
+ str, escontext))
+ PG_RETURN_NULL();
make_bound_box(poly);
circle_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
CIRCLE *circle = (CIRCLE *) palloc(sizeof(CIRCLE));
char *s,
*cp;
}
/* pair_decode will consume parens around the pair, if any */
- pair_decode(s, &circle->center.x, &circle->center.y, &s, "circle", str);
+ if (!pair_decode(s, &circle->center.x, &circle->center.y, &s, "circle", str,
+ escontext))
+ PG_RETURN_NULL();
if (*s == DELIM)
s++;
- circle->radius = single_decode(s, &s, "circle", str);
+ if (!single_decode(s, &circle->radius, &s, "circle", str, escontext))
+ PG_RETURN_NULL();
+
/* We have to accept NaN. */
if (circle->radius < 0.0)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"",
"circle", str)));
s++;
}
else
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"",
"circle", str)));
}
if (*s != '\0')
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"",
"circle", str)));