mirror of
https://github.com/postgres/postgres.git
synced 2025-09-03 15:22:11 +03:00
Convert the geometric input functions to report errors softly.
Convert box_in, circle_in, line_in, lseg_in, path_in, point_in, and poly_in to the new style. line_in still throws hard errors for overflows/underflows that can occur when the input is specified as two points rather than in the canonical "Ax + By + C = 0" style. I'm not too concerned about that: it won't be reached in normal dump/restore cases, and it's fairly debatable that such conversion should ever have been made part of a type input function in the first place. But in any case, I don't want to extend the soft error conventions into float.h without more discussion than this patch has had. Amul Sul, minor mods by me Discussion: https://postgr.es/m/CAAJ_b97KeDWUdpTKGOaFYPv0OicjOu6EW+QYWj-Ywrgj_aEy1g@mail.gmail.com
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "libpq/pqformat.h"
|
#include "libpq/pqformat.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
|
#include "nodes/miscnodes.h"
|
||||||
#include "utils/float.h"
|
#include "utils/float.h"
|
||||||
#include "utils/fmgrprotos.h"
|
#include "utils/fmgrprotos.h"
|
||||||
#include "utils/geo_decls.h"
|
#include "utils/geo_decls.h"
|
||||||
@@ -130,16 +131,19 @@ static bool plist_same(int npts, Point *p1, Point *p2);
|
|||||||
static float8 dist_ppoly_internal(Point *pt, POLYGON *poly);
|
static float8 dist_ppoly_internal(Point *pt, POLYGON *poly);
|
||||||
|
|
||||||
/* Routines for encoding and decoding */
|
/* Routines for encoding and decoding */
|
||||||
static float8 single_decode(char *num, char **endptr_p,
|
static bool single_decode(char *num, float8 *x, char **endptr_p,
|
||||||
const char *type_name, const char *orig_string);
|
const char *type_name, const char *orig_string,
|
||||||
|
Node *escontext);
|
||||||
static void single_encode(float8 x, StringInfo str);
|
static void single_encode(float8 x, StringInfo str);
|
||||||
static void pair_decode(char *str, float8 *x, float8 *y, char **endptr_p,
|
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);
|
||||||
static void pair_encode(float8 x, float8 y, StringInfo str);
|
static void pair_encode(float8 x, float8 y, StringInfo str);
|
||||||
static int pair_count(char *s, char delim);
|
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,
|
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);
|
static char *path_encode(enum path_delim path_delim, int npts, Point *pt);
|
||||||
|
|
||||||
|
|
||||||
@@ -185,11 +189,13 @@ static char *path_encode(enum path_delim path_delim, int npts, Point *pt);
|
|||||||
* and restore that order for text output - tgl 97/01/16
|
* and restore that order for text output - tgl 97/01/16
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static float8
|
static bool
|
||||||
single_decode(char *num, char **endptr_p,
|
single_decode(char *num, float8 *x, char **endptr_p,
|
||||||
const char *type_name, const char *orig_string)
|
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() */
|
} /* single_decode() */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -201,9 +207,10 @@ single_encode(float8 x, StringInfo str)
|
|||||||
pfree(xstr);
|
pfree(xstr);
|
||||||
} /* single_encode() */
|
} /* single_encode() */
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
pair_decode(char *str, float8 *x, float8 *y, char **endptr_p,
|
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;
|
bool has_delim;
|
||||||
|
|
||||||
@@ -212,23 +219,19 @@ pair_decode(char *str, float8 *x, float8 *y, char **endptr_p,
|
|||||||
if ((has_delim = (*str == LDELIM)))
|
if ((has_delim = (*str == LDELIM)))
|
||||||
str++;
|
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)
|
if (*str++ != DELIM)
|
||||||
ereport(ERROR,
|
goto fail;
|
||||||
(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, NULL);
|
if (!single_decode(str, y, &str, type_name, orig_string, escontext))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (has_delim)
|
if (has_delim)
|
||||||
{
|
{
|
||||||
if (*str++ != RDELIM)
|
if (*str++ != RDELIM)
|
||||||
ereport(ERROR,
|
goto fail;
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
|
||||||
type_name, orig_string)));
|
|
||||||
while (isspace((unsigned char) *str))
|
while (isspace((unsigned char) *str))
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
@@ -237,10 +240,14 @@ pair_decode(char *str, float8 *x, float8 *y, char **endptr_p,
|
|||||||
if (endptr_p)
|
if (endptr_p)
|
||||||
*endptr_p = str;
|
*endptr_p = str;
|
||||||
else if (*str != '\0')
|
else if (*str != '\0')
|
||||||
ereport(ERROR,
|
goto fail;
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
return true;
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
|
||||||
type_name, orig_string)));
|
fail:
|
||||||
|
ereturn(escontext, false,
|
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
|
type_name, orig_string)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -254,10 +261,11 @@ pair_encode(float8 x, float8 y, StringInfo str)
|
|||||||
pfree(ystr);
|
pfree(ystr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
path_decode(char *str, bool opentype, int npts, Point *p,
|
path_decode(char *str, bool opentype, int npts, Point *p,
|
||||||
bool *isopen, char **endptr_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;
|
int depth = 0;
|
||||||
char *cp;
|
char *cp;
|
||||||
@@ -269,10 +277,7 @@ path_decode(char *str, bool opentype, int npts, Point *p,
|
|||||||
{
|
{
|
||||||
/* no open delimiter allowed? */
|
/* no open delimiter allowed? */
|
||||||
if (!opentype)
|
if (!opentype)
|
||||||
ereport(ERROR,
|
goto fail;
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
|
||||||
type_name, orig_string)));
|
|
||||||
depth++;
|
depth++;
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
@@ -295,7 +300,9 @@ path_decode(char *str, bool opentype, int npts, Point *p,
|
|||||||
|
|
||||||
for (i = 0; i < npts; i++)
|
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)
|
if (*str == DELIM)
|
||||||
str++;
|
str++;
|
||||||
p++;
|
p++;
|
||||||
@@ -311,20 +318,21 @@ path_decode(char *str, bool opentype, int npts, Point *p,
|
|||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
goto fail;
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
|
||||||
type_name, orig_string)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* report stopping point if wanted, else complain if not end of string */
|
/* report stopping point if wanted, else complain if not end of string */
|
||||||
if (endptr_p)
|
if (endptr_p)
|
||||||
*endptr_p = str;
|
*endptr_p = str;
|
||||||
else if (*str != '\0')
|
else if (*str != '\0')
|
||||||
ereport(ERROR,
|
goto fail;
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
return true;
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
|
||||||
type_name, orig_string)));
|
fail:
|
||||||
|
ereturn(escontext, false,
|
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
|
type_name, orig_string)));
|
||||||
} /* path_decode() */
|
} /* path_decode() */
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
@@ -413,12 +421,15 @@ Datum
|
|||||||
box_in(PG_FUNCTION_ARGS)
|
box_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
BOX *box = (BOX *) palloc(sizeof(BOX));
|
BOX *box = (BOX *) palloc(sizeof(BOX));
|
||||||
bool isopen;
|
bool isopen;
|
||||||
float8 x,
|
float8 x,
|
||||||
y;
|
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... */
|
/* reorder corners if necessary... */
|
||||||
if (float8_lt(box->high.x, box->low.x))
|
if (float8_lt(box->high.x, box->low.x))
|
||||||
@@ -935,29 +946,39 @@ box_diagonal(PG_FUNCTION_ARGS)
|
|||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
static bool
|
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 '{' */
|
/* s was already advanced over leading '{' */
|
||||||
line->A = single_decode(s, &s, "line", str);
|
if (!single_decode(s, &line->A, &s, "line", str, escontext))
|
||||||
if (*s++ != DELIM)
|
|
||||||
return false;
|
return false;
|
||||||
line->B = single_decode(s, &s, "line", str);
|
|
||||||
if (*s++ != DELIM)
|
if (*s++ != DELIM)
|
||||||
|
goto fail;
|
||||||
|
if (!single_decode(s, &line->B, &s, "line", str, escontext))
|
||||||
|
return false;
|
||||||
|
if (*s++ != DELIM)
|
||||||
|
goto fail;
|
||||||
|
if (!single_decode(s, &line->C, &s, "line", str, escontext))
|
||||||
return false;
|
return false;
|
||||||
line->C = single_decode(s, &s, "line", str);
|
|
||||||
if (*s++ != RDELIM_L)
|
if (*s++ != RDELIM_L)
|
||||||
return false;
|
goto fail;
|
||||||
while (isspace((unsigned char) *s))
|
while (isspace((unsigned char) *s))
|
||||||
s++;
|
s++;
|
||||||
if (*s != '\0')
|
if (*s != '\0')
|
||||||
return false;
|
goto fail;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ereturn(escontext, false,
|
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
|
"line", str)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
line_in(PG_FUNCTION_ARGS)
|
line_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
LINE *line = (LINE *) palloc(sizeof(LINE));
|
LINE *line = (LINE *) palloc(sizeof(LINE));
|
||||||
LSEG lseg;
|
LSEG lseg;
|
||||||
bool isopen;
|
bool isopen;
|
||||||
@@ -968,23 +989,28 @@ line_in(PG_FUNCTION_ARGS)
|
|||||||
s++;
|
s++;
|
||||||
if (*s == LDELIM_L)
|
if (*s == LDELIM_L)
|
||||||
{
|
{
|
||||||
if (!line_decode(s + 1, str, line))
|
if (!line_decode(s + 1, str, line, escontext))
|
||||||
ereport(ERROR,
|
PG_RETURN_NULL();
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
|
||||||
"line", str)));
|
|
||||||
if (FPzero(line->A) && FPzero(line->B))
|
if (FPzero(line->A) && FPzero(line->B))
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid line specification: A and B cannot both be zero")));
|
errmsg("invalid line specification: A and B cannot both be zero")));
|
||||||
}
|
}
|
||||||
else
|
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]))
|
if (point_eq_point(&lseg.p[0], &lseg.p[1]))
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid line specification: must be two distinct points")));
|
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));
|
line_construct(line, &lseg.p[0], lseg_sl(&lseg));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1375,6 +1401,7 @@ Datum
|
|||||||
path_in(PG_FUNCTION_ARGS)
|
path_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
PATH *path;
|
PATH *path;
|
||||||
bool isopen;
|
bool isopen;
|
||||||
char *s;
|
char *s;
|
||||||
@@ -1384,7 +1411,7 @@ path_in(PG_FUNCTION_ARGS)
|
|||||||
int depth = 0;
|
int depth = 0;
|
||||||
|
|
||||||
if ((npts = pair_count(str, ',')) <= 0)
|
if ((npts = pair_count(str, ',')) <= 0)
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
"path", str)));
|
"path", str)));
|
||||||
@@ -1405,7 +1432,7 @@ path_in(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Check for integer overflow */
|
/* Check for integer overflow */
|
||||||
if (base_size / npts != sizeof(path->p[0]) || size <= base_size)
|
if (base_size / npts != sizeof(path->p[0]) || size <= base_size)
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("too many points requested")));
|
errmsg("too many points requested")));
|
||||||
|
|
||||||
@@ -1414,12 +1441,14 @@ path_in(PG_FUNCTION_ARGS)
|
|||||||
SET_VARSIZE(path, size);
|
SET_VARSIZE(path, size);
|
||||||
path->npts = npts;
|
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 (depth >= 1)
|
||||||
{
|
{
|
||||||
if (*s++ != RDELIM)
|
if (*s++ != RDELIM)
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
"path", str)));
|
"path", str)));
|
||||||
@@ -1427,7 +1456,7 @@ path_in(PG_FUNCTION_ARGS)
|
|||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
if (*s != '\0')
|
if (*s != '\0')
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
"path", str)));
|
"path", str)));
|
||||||
@@ -1803,7 +1832,8 @@ point_in(PG_FUNCTION_ARGS)
|
|||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
Point *point = (Point *) palloc(sizeof(Point));
|
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);
|
PG_RETURN_POINT_P(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2034,10 +2064,14 @@ Datum
|
|||||||
lseg_in(PG_FUNCTION_ARGS)
|
lseg_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
LSEG *lseg = (LSEG *) palloc(sizeof(LSEG));
|
LSEG *lseg = (LSEG *) palloc(sizeof(LSEG));
|
||||||
bool isopen;
|
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);
|
PG_RETURN_LSEG_P(lseg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3380,6 +3414,7 @@ Datum
|
|||||||
poly_in(PG_FUNCTION_ARGS)
|
poly_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
POLYGON *poly;
|
POLYGON *poly;
|
||||||
int npts;
|
int npts;
|
||||||
int size;
|
int size;
|
||||||
@@ -3387,7 +3422,7 @@ poly_in(PG_FUNCTION_ARGS)
|
|||||||
bool isopen;
|
bool isopen;
|
||||||
|
|
||||||
if ((npts = pair_count(str, ',')) <= 0)
|
if ((npts = pair_count(str, ',')) <= 0)
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
"polygon", str)));
|
"polygon", str)));
|
||||||
@@ -3397,7 +3432,7 @@ poly_in(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Check for integer overflow */
|
/* Check for integer overflow */
|
||||||
if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
|
if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("too many points requested")));
|
errmsg("too many points requested")));
|
||||||
|
|
||||||
@@ -3406,7 +3441,9 @@ poly_in(PG_FUNCTION_ARGS)
|
|||||||
SET_VARSIZE(poly, size);
|
SET_VARSIZE(poly, size);
|
||||||
poly->npts = npts;
|
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);
|
make_bound_box(poly);
|
||||||
|
|
||||||
@@ -4573,6 +4610,7 @@ Datum
|
|||||||
circle_in(PG_FUNCTION_ARGS)
|
circle_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
CIRCLE *circle = (CIRCLE *) palloc(sizeof(CIRCLE));
|
CIRCLE *circle = (CIRCLE *) palloc(sizeof(CIRCLE));
|
||||||
char *s,
|
char *s,
|
||||||
*cp;
|
*cp;
|
||||||
@@ -4594,15 +4632,19 @@ circle_in(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* pair_decode will consume parens around the pair, if any */
|
/* 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)
|
if (*s == DELIM)
|
||||||
s++;
|
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. */
|
/* We have to accept NaN. */
|
||||||
if (circle->radius < 0.0)
|
if (circle->radius < 0.0)
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
"circle", str)));
|
"circle", str)));
|
||||||
@@ -4617,14 +4659,14 @@ circle_in(PG_FUNCTION_ARGS)
|
|||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
"circle", str)));
|
"circle", str)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*s != '\0')
|
if (*s != '\0')
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
"circle", str)));
|
"circle", str)));
|
||||||
|
@@ -639,3 +639,28 @@ WHERE seq.id IS NULL OR idx.id IS NULL;
|
|||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
RESET enable_indexscan;
|
RESET enable_indexscan;
|
||||||
RESET enable_bitmapscan;
|
RESET enable_bitmapscan;
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('200', 'box');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('200', 'box');
|
||||||
|
pg_input_error_message
|
||||||
|
------------------------------------------
|
||||||
|
invalid input syntax for type box: "200"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('((200,300),(500, xyz))', 'box');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('((200,300),(500, xyz))', 'box');
|
||||||
|
pg_input_error_message
|
||||||
|
-------------------------------------------------------------
|
||||||
|
invalid input syntax for type box: "((200,300),(500, xyz))"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@@ -5295,3 +5295,28 @@ SELECT * FROM polygon_tbl WHERE f1 @> '((1,1),(2,2),(2,1))'::polygon
|
|||||||
((2,0),(2,4),(0,0))
|
((2,0),(2,4),(0,0))
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('(1', 'circle');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('1,', 'circle');
|
||||||
|
pg_input_error_message
|
||||||
|
--------------------------------------------
|
||||||
|
invalid input syntax for type circle: "1,"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('(1,2),-1', 'circle');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('(1,2),-1', 'circle');
|
||||||
|
pg_input_error_message
|
||||||
|
--------------------------------------------------
|
||||||
|
invalid input syntax for type circle: "(1,2),-1"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@@ -85,3 +85,64 @@ select '{nan, 1, nan}'::line = '{nan, 1, nan}'::line as true,
|
|||||||
t | f
|
t | f
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('{1, 1}', 'line');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('{1, 1}', 'line');
|
||||||
|
pg_input_error_message
|
||||||
|
----------------------------------------------
|
||||||
|
invalid input syntax for type line: "{1, 1}"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('{0, 0, 0}', 'line');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('{0, 0, 0}', 'line');
|
||||||
|
pg_input_error_message
|
||||||
|
---------------------------------------------------------
|
||||||
|
invalid line specification: A and B cannot both be zero
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('{1, 1, a}', 'line');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('{1, 1, a}', 'line');
|
||||||
|
pg_input_error_message
|
||||||
|
-------------------------------------------------
|
||||||
|
invalid input syntax for type line: "{1, 1, a}"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('{1, 1, 1e400}', 'line');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('{1, 1, 1e400}', 'line');
|
||||||
|
pg_input_error_message
|
||||||
|
---------------------------------------------------
|
||||||
|
"1e400" is out of range for type double precision
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('(1, 1), (1, 1e400)', 'line');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('(1, 1), (1, 1e400)', 'line');
|
||||||
|
pg_input_error_message
|
||||||
|
---------------------------------------------------
|
||||||
|
"1e400" is out of range for type double precision
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@@ -42,3 +42,16 @@ select * from LSEG_TBL;
|
|||||||
[(NaN,1),(NaN,90)]
|
[(NaN,1),(NaN,90)]
|
||||||
(8 rows)
|
(8 rows)
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('[(1,2),(3)]', 'lseg');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('[(1,2),(3)]', 'lseg');
|
||||||
|
pg_input_error_message
|
||||||
|
---------------------------------------------------
|
||||||
|
invalid input syntax for type lseg: "[(1,2),(3)]"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@@ -80,3 +80,28 @@ SELECT popen(f1) AS open_path FROM PATH_TBL;
|
|||||||
[(11,12),(13,14)]
|
[(11,12),(13,14)]
|
||||||
(9 rows)
|
(9 rows)
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('[(1,2),(3)]', 'path');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('[(1,2),(3)]', 'path');
|
||||||
|
pg_input_error_message
|
||||||
|
---------------------------------------------------
|
||||||
|
invalid input syntax for type path: "[(1,2),(3)]"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('[(1,2,6),(3,4,6)]', 'path');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('[(1,2,6),(3,4,6)]', 'path');
|
||||||
|
pg_input_error_message
|
||||||
|
---------------------------------------------------------
|
||||||
|
invalid input syntax for type path: "[(1,2,6),(3,4,6)]"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@@ -463,3 +463,16 @@ SELECT COUNT(*) FROM point_gist_tbl WHERE f1 ~= '(0.0000018,0.0000018)'::point;
|
|||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
RESET enable_indexscan;
|
RESET enable_indexscan;
|
||||||
RESET enable_bitmapscan;
|
RESET enable_bitmapscan;
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('1,y', 'point');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('1,y', 'point');
|
||||||
|
pg_input_error_message
|
||||||
|
--------------------------------------------
|
||||||
|
invalid input syntax for type point: "1,y"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@@ -306,3 +306,28 @@ WHERE seq.id IS NULL OR idx.id IS NULL;
|
|||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
RESET enable_indexscan;
|
RESET enable_indexscan;
|
||||||
RESET enable_bitmapscan;
|
RESET enable_bitmapscan;
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('(2.0,0.8,0.1)', 'polygon');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('(2.0,0.8,0.1)', 'polygon');
|
||||||
|
pg_input_error_message
|
||||||
|
--------------------------------------------------------
|
||||||
|
invalid input syntax for type polygon: "(2.0,0.8,0.1)"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('(2.0,xyz)', 'polygon');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('(2.0,xyz)', 'polygon');
|
||||||
|
pg_input_error_message
|
||||||
|
----------------------------------------------------
|
||||||
|
invalid input syntax for type polygon: "(2.0,xyz)"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@@ -281,3 +281,9 @@ WHERE seq.id IS NULL OR idx.id IS NULL;
|
|||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
RESET enable_indexscan;
|
RESET enable_indexscan;
|
||||||
RESET enable_bitmapscan;
|
RESET enable_bitmapscan;
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('200', 'box');
|
||||||
|
SELECT pg_input_error_message('200', 'box');
|
||||||
|
SELECT pg_input_is_valid('((200,300),(500, xyz))', 'box');
|
||||||
|
SELECT pg_input_error_message('((200,300),(500, xyz))', 'box');
|
||||||
|
@@ -523,3 +523,9 @@ SELECT * FROM polygon_tbl WHERE f1 @> '((1,1),(2,2),(2,1))'::polygon
|
|||||||
ORDER BY (poly_center(f1))[0];
|
ORDER BY (poly_center(f1))[0];
|
||||||
SELECT * FROM polygon_tbl WHERE f1 @> '((1,1),(2,2),(2,1))'::polygon
|
SELECT * FROM polygon_tbl WHERE f1 @> '((1,1),(2,2),(2,1))'::polygon
|
||||||
ORDER BY (poly_center(f1))[0];
|
ORDER BY (poly_center(f1))[0];
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('(1', 'circle');
|
||||||
|
SELECT pg_input_error_message('1,', 'circle');
|
||||||
|
SELECT pg_input_is_valid('(1,2),-1', 'circle');
|
||||||
|
SELECT pg_input_error_message('(1,2),-1', 'circle');
|
||||||
|
@@ -40,3 +40,15 @@ select * from LINE_TBL;
|
|||||||
|
|
||||||
select '{nan, 1, nan}'::line = '{nan, 1, nan}'::line as true,
|
select '{nan, 1, nan}'::line = '{nan, 1, nan}'::line as true,
|
||||||
'{nan, 1, nan}'::line = '{nan, 2, nan}'::line as false;
|
'{nan, 1, nan}'::line = '{nan, 2, nan}'::line as false;
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('{1, 1}', 'line');
|
||||||
|
SELECT pg_input_error_message('{1, 1}', 'line');
|
||||||
|
SELECT pg_input_is_valid('{0, 0, 0}', 'line');
|
||||||
|
SELECT pg_input_error_message('{0, 0, 0}', 'line');
|
||||||
|
SELECT pg_input_is_valid('{1, 1, a}', 'line');
|
||||||
|
SELECT pg_input_error_message('{1, 1, a}', 'line');
|
||||||
|
SELECT pg_input_is_valid('{1, 1, 1e400}', 'line');
|
||||||
|
SELECT pg_input_error_message('{1, 1, 1e400}', 'line');
|
||||||
|
SELECT pg_input_is_valid('(1, 1), (1, 1e400)', 'line');
|
||||||
|
SELECT pg_input_error_message('(1, 1), (1, 1e400)', 'line');
|
||||||
|
@@ -22,3 +22,7 @@ INSERT INTO LSEG_TBL VALUES ('[(,2),(3,4)]');
|
|||||||
INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)');
|
INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)');
|
||||||
|
|
||||||
select * from LSEG_TBL;
|
select * from LSEG_TBL;
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('[(1,2),(3)]', 'lseg');
|
||||||
|
SELECT pg_input_error_message('[(1,2),(3)]', 'lseg');
|
||||||
|
@@ -42,3 +42,9 @@ SELECT f1 AS closed_path FROM PATH_TBL WHERE isclosed(f1);
|
|||||||
SELECT pclose(f1) AS closed_path FROM PATH_TBL;
|
SELECT pclose(f1) AS closed_path FROM PATH_TBL;
|
||||||
|
|
||||||
SELECT popen(f1) AS open_path FROM PATH_TBL;
|
SELECT popen(f1) AS open_path FROM PATH_TBL;
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('[(1,2),(3)]', 'path');
|
||||||
|
SELECT pg_input_error_message('[(1,2),(3)]', 'path');
|
||||||
|
SELECT pg_input_is_valid('[(1,2,6),(3,4,6)]', 'path');
|
||||||
|
SELECT pg_input_error_message('[(1,2,6),(3,4,6)]', 'path');
|
||||||
|
@@ -96,3 +96,7 @@ SELECT COUNT(*) FROM point_gist_tbl WHERE f1 ~= '(0.0000018,0.0000018)'::point;
|
|||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
RESET enable_indexscan;
|
RESET enable_indexscan;
|
||||||
RESET enable_bitmapscan;
|
RESET enable_bitmapscan;
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('1,y', 'point');
|
||||||
|
SELECT pg_input_error_message('1,y', 'point');
|
||||||
|
@@ -140,3 +140,9 @@ WHERE seq.id IS NULL OR idx.id IS NULL;
|
|||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
RESET enable_indexscan;
|
RESET enable_indexscan;
|
||||||
RESET enable_bitmapscan;
|
RESET enable_bitmapscan;
|
||||||
|
|
||||||
|
-- test non-error-throwing API for some core types
|
||||||
|
SELECT pg_input_is_valid('(2.0,0.8,0.1)', 'polygon');
|
||||||
|
SELECT pg_input_error_message('(2.0,0.8,0.1)', 'polygon');
|
||||||
|
SELECT pg_input_is_valid('(2.0,xyz)', 'polygon');
|
||||||
|
SELECT pg_input_error_message('(2.0,xyz)', 'polygon');
|
||||||
|
Reference in New Issue
Block a user