mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Improve portability of I/O behavior for the geometric types.
Formerly, the geometric I/O routines such as box_in and point_out relied directly on strtod() and sprintf() for conversion of the float8 component values of their data types. However, the behavior of those functions is pretty platform-dependent, especially for edge-case values such as infinities and NaNs. This was exposed by commit acdf2a8b372aec1d, which added test cases involving boxes with infinity endpoints, and immediately failed on Windows and AIX buildfarm members. We solved these problems years ago in the main float8in and float8out functions, so let's fix it by making the geometric types use that code instead of depending directly on the platform-supplied functions. To do this, refactor the float8in code so that it can be used to parse just part of a string, and as a convenience make the guts of float8out usable without going through DirectFunctionCall. While at it, get rid of geo_ops.c's fairly shaky assumptions about the maximum output string length for a double, by having it build results in StringInfo buffers instead of fixed-length strings. In passing, convert all the "invalid input syntax for type foo" messages in this area of the code into "invalid input syntax for type %s" to reduce the number of distinct translatable strings, per recent discussion. We would have needed a fair number of the latter anyway for code-sharing reasons, so we might as well just go whole hog. Note: this patch is by no means intended to guarantee that the geometric types uniformly behave sanely for infinity or NaN component values. But any bugs we have in that line were there all along, they were just harder to reach in a platform-independent way.
This commit is contained in:
parent
818e593736
commit
50861cd683
@ -411,17 +411,35 @@ Datum
|
|||||||
float8in(PG_FUNCTION_ARGS)
|
float8in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *num = PG_GETARG_CSTRING(0);
|
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;
|
double val;
|
||||||
char *endptr;
|
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 */
|
/* skip leading whitespace */
|
||||||
while (*num != '\0' && isspace((unsigned char) *num))
|
while (*num != '\0' && isspace((unsigned char) *num))
|
||||||
num++;
|
num++;
|
||||||
@ -433,8 +451,8 @@ float8in(PG_FUNCTION_ARGS)
|
|||||||
if (*num == '\0')
|
if (*num == '\0')
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
orig_num)));
|
type_name, orig_string)));
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
val = strtod(num, &endptr);
|
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
|
* 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
|
* detect whether it's a "real" out-of-range condition by checking
|
||||||
* to see if the result is zero or huge.
|
* 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)
|
if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
|
||||||
|
{
|
||||||
|
char *errnumber = pstrdup(num);
|
||||||
|
|
||||||
|
errnumber[endptr - num] = '\0';
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("\"%s\" is out of range for type double precision",
|
errmsg("\"%s\" is out of range for type double precision",
|
||||||
orig_num)));
|
errnumber)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
orig_num)));
|
type_name, orig_string)));
|
||||||
}
|
}
|
||||||
#ifdef HAVE_BUGGY_SOLARIS_STRTOD
|
#ifdef HAVE_BUGGY_SOLARIS_STRTOD
|
||||||
else
|
else
|
||||||
@ -527,16 +554,16 @@ float8in(PG_FUNCTION_ARGS)
|
|||||||
while (*endptr != '\0' && isspace((unsigned char) *endptr))
|
while (*endptr != '\0' && isspace((unsigned char) *endptr))
|
||||||
endptr++;
|
endptr++;
|
||||||
|
|
||||||
/* if there is any junk left at the end of the string, bail out */
|
/* report stopping point if wanted, else complain if not end of string */
|
||||||
if (*endptr != '\0')
|
if (endptr_p)
|
||||||
|
*endptr_p = endptr;
|
||||||
|
else if (*endptr != '\0')
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
orig_num)));
|
type_name, orig_string)));
|
||||||
|
|
||||||
CHECKFLOATVAL(val, true, true);
|
return val;
|
||||||
|
|
||||||
PG_RETURN_FLOAT8(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -547,10 +574,24 @@ Datum
|
|||||||
float8out(PG_FUNCTION_ARGS)
|
float8out(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
float8 num = PG_GETARG_FLOAT8(0);
|
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);
|
char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
|
||||||
|
|
||||||
if (isnan(num))
|
if (isnan(num))
|
||||||
PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
|
return strcpy(ascii, "NaN");
|
||||||
|
|
||||||
switch (is_infinite(num))
|
switch (is_infinite(num))
|
||||||
{
|
{
|
||||||
@ -571,7 +612,7 @@ float8out(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_RETURN_CSTRING(ascii);
|
return ascii;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -57,12 +57,16 @@ static void make_bound_box(POLYGON *poly);
|
|||||||
static bool plist_same(int npts, Point *p1, Point *p2);
|
static bool plist_same(int npts, Point *p1, Point *p2);
|
||||||
static Point *point_construct(double x, double y);
|
static Point *point_construct(double x, double y);
|
||||||
static Point *point_copy(Point *pt);
|
static Point *point_copy(Point *pt);
|
||||||
static int single_decode(char *str, float8 *x, char **ss);
|
static double single_decode(char *num, char **endptr_p,
|
||||||
static int single_encode(float8 x, char *str);
|
const char *type_name, const char *orig_string);
|
||||||
static int pair_decode(char *str, float8 *x, float8 *y, char **s);
|
static void single_encode(float8 x, StringInfo str);
|
||||||
static int pair_encode(float8 x, float8 y, char *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 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 char *path_encode(enum path_delim path_delim, int npts, Point *pt);
|
||||||
static void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2);
|
static void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2);
|
||||||
static double box_ar(BOX *box);
|
static double box_ar(BOX *box);
|
||||||
@ -91,10 +95,6 @@ static double dist_ppoly_internal(Point *pt, POLYGON *poly);
|
|||||||
#define LDELIM_C '<'
|
#define LDELIM_C '<'
|
||||||
#define RDELIM_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.
|
* 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
|
* and restore that order for text output - tgl 97/01/16
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static double
|
||||||
single_decode(char *str, float8 *x, char **s)
|
single_decode(char *num, char **endptr_p,
|
||||||
|
const char *type_name, const char *orig_string)
|
||||||
{
|
{
|
||||||
char *cp;
|
return float8in_internal(num, endptr_p, type_name, orig_string);
|
||||||
|
|
||||||
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;
|
|
||||||
} /* single_decode() */
|
} /* single_decode() */
|
||||||
|
|
||||||
static int
|
static void
|
||||||
single_encode(float8 x, char *str)
|
single_encode(float8 x, StringInfo str)
|
||||||
{
|
{
|
||||||
int ndig = DBL_DIG + extra_float_digits;
|
char *xstr = float8out_internal(x);
|
||||||
|
|
||||||
if (ndig < 1)
|
appendStringInfoString(str, xstr);
|
||||||
ndig = 1;
|
pfree(xstr);
|
||||||
|
|
||||||
sprintf(str, "%.*g", ndig, x);
|
|
||||||
return TRUE;
|
|
||||||
} /* single_encode() */
|
} /* single_encode() */
|
||||||
|
|
||||||
static int
|
static void
|
||||||
pair_decode(char *str, float8 *x, float8 *y, char **s)
|
pair_decode(char *str, double *x, double *y, char **endptr_p,
|
||||||
|
const char *type_name, const char *orig_string)
|
||||||
{
|
{
|
||||||
int has_delim;
|
bool has_delim;
|
||||||
char *cp;
|
|
||||||
|
|
||||||
if (!PointerIsValid(str))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
while (isspace((unsigned char) *str))
|
while (isspace((unsigned char) *str))
|
||||||
str++;
|
str++;
|
||||||
if ((has_delim = (*str == LDELIM)))
|
if ((has_delim = (*str == LDELIM)))
|
||||||
str++;
|
str++;
|
||||||
|
|
||||||
while (isspace((unsigned char) *str))
|
*x = float8in_internal(str, &str, type_name, orig_string);
|
||||||
str++;
|
|
||||||
*x = strtod(str, &cp);
|
if (*str++ != DELIM)
|
||||||
if (cp <= str)
|
ereport(ERROR,
|
||||||
return FALSE;
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
while (isspace((unsigned char) *cp))
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
cp++;
|
type_name, orig_string)));
|
||||||
if (*cp++ != DELIM)
|
|
||||||
return FALSE;
|
*y = float8in_internal(str, &str, type_name, orig_string);
|
||||||
while (isspace((unsigned char) *cp))
|
|
||||||
cp++;
|
|
||||||
*y = strtod(cp, &str);
|
|
||||||
if (str <= cp)
|
|
||||||
return FALSE;
|
|
||||||
while (isspace((unsigned char) *str))
|
|
||||||
str++;
|
|
||||||
if (has_delim)
|
if (has_delim)
|
||||||
{
|
{
|
||||||
if (*str != RDELIM)
|
if (*str++ != RDELIM)
|
||||||
return FALSE;
|
ereport(ERROR,
|
||||||
str++;
|
(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++;
|
||||||
}
|
}
|
||||||
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
|
static void
|
||||||
pair_encode(float8 x, float8 y, char *str)
|
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)
|
appendStringInfo(str, "%s,%s", xstr, ystr);
|
||||||
ndig = 1;
|
pfree(xstr);
|
||||||
|
pfree(ystr);
|
||||||
sprintf(str, "%.*g,%.*g", ndig, x, ndig, y);
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p)
|
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;
|
int depth = 0;
|
||||||
char *s,
|
char *cp;
|
||||||
*cp;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
s = str;
|
while (isspace((unsigned char) *str))
|
||||||
while (isspace((unsigned char) *s))
|
str++;
|
||||||
s++;
|
if ((*isopen = (*str == LDELIM_EP)))
|
||||||
if ((*isopen = (*s == LDELIM_EP)))
|
|
||||||
{
|
{
|
||||||
/* no open delimiter allowed? */
|
/* no open delimiter allowed? */
|
||||||
if (!opentype)
|
if (!opentype)
|
||||||
return FALSE;
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
|
type_name, orig_string)));
|
||||||
depth++;
|
depth++;
|
||||||
s++;
|
str++;
|
||||||
while (isspace((unsigned char) *s))
|
|
||||||
s++;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (*s == LDELIM)
|
else if (*str == LDELIM)
|
||||||
{
|
{
|
||||||
cp = (s + 1);
|
cp = (str + 1);
|
||||||
while (isspace((unsigned char) *cp))
|
while (isspace((unsigned char) *cp))
|
||||||
cp++;
|
cp++;
|
||||||
if (*cp == LDELIM)
|
if (*cp == LDELIM)
|
||||||
{
|
{
|
||||||
#ifdef NOT_USED
|
|
||||||
/* nested delimiters with only one point? */
|
|
||||||
if (npts <= 1)
|
|
||||||
return FALSE;
|
|
||||||
#endif
|
|
||||||
depth++;
|
depth++;
|
||||||
s = cp;
|
str = cp;
|
||||||
}
|
}
|
||||||
else if (strrchr(s, LDELIM) == s)
|
else if (strrchr(str, LDELIM) == str)
|
||||||
{
|
{
|
||||||
depth++;
|
depth++;
|
||||||
s = cp;
|
str = cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < npts; i++)
|
for (i = 0; i < npts; i++)
|
||||||
{
|
{
|
||||||
if (!pair_decode(s, &(p->x), &(p->y), &s))
|
pair_decode(str, &(p->x), &(p->y), &str, type_name, orig_string);
|
||||||
return FALSE;
|
if (*str == DELIM)
|
||||||
|
str++;
|
||||||
if (*s == DELIM)
|
|
||||||
s++;
|
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (isspace((unsigned char) *str))
|
||||||
|
str++;
|
||||||
while (depth > 0)
|
while (depth > 0)
|
||||||
{
|
{
|
||||||
if ((*s == RDELIM)
|
if ((*str == RDELIM)
|
||||||
|| ((*s == RDELIM_EP) && (*isopen) && (depth == 1)))
|
|| ((*str == RDELIM_EP) && (*isopen) && (depth == 1)))
|
||||||
{
|
{
|
||||||
depth--;
|
depth--;
|
||||||
s++;
|
str++;
|
||||||
while (isspace((unsigned char) *s))
|
while (isspace((unsigned char) *str))
|
||||||
s++;
|
str++;
|
||||||
}
|
}
|
||||||
else
|
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() */
|
} /* path_decode() */
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
path_encode(enum path_delim path_delim, int npts, Point *pt)
|
path_encode(enum path_delim path_delim, int npts, Point *pt)
|
||||||
{
|
{
|
||||||
int size = npts * (P_MAXLEN + 3) + 2;
|
StringInfoData str;
|
||||||
char *result;
|
|
||||||
char *cp;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Check for integer overflow */
|
initStringInfo(&str);
|
||||||
if ((size - 2) / npts != (P_MAXLEN + 3))
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
|
||||||
errmsg("too many points requested")));
|
|
||||||
|
|
||||||
result = palloc(size);
|
|
||||||
|
|
||||||
cp = result;
|
|
||||||
switch (path_delim)
|
switch (path_delim)
|
||||||
{
|
{
|
||||||
case PATH_CLOSED:
|
case PATH_CLOSED:
|
||||||
*cp++ = LDELIM;
|
appendStringInfoChar(&str, LDELIM);
|
||||||
break;
|
break;
|
||||||
case PATH_OPEN:
|
case PATH_OPEN:
|
||||||
*cp++ = LDELIM_EP;
|
appendStringInfoChar(&str, LDELIM_EP);
|
||||||
break;
|
break;
|
||||||
case PATH_NONE:
|
case PATH_NONE:
|
||||||
break;
|
break;
|
||||||
@ -317,32 +288,27 @@ path_encode(enum path_delim path_delim, int npts, Point *pt)
|
|||||||
|
|
||||||
for (i = 0; i < npts; i++)
|
for (i = 0; i < npts; i++)
|
||||||
{
|
{
|
||||||
*cp++ = LDELIM;
|
if (i > 0)
|
||||||
if (!pair_encode(pt->x, pt->y, cp))
|
appendStringInfoChar(&str, DELIM);
|
||||||
ereport(ERROR,
|
appendStringInfoChar(&str, LDELIM);
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
pair_encode(pt->x, pt->y, &str);
|
||||||
errmsg("could not format \"path\" value")));
|
appendStringInfoChar(&str, RDELIM);
|
||||||
|
|
||||||
cp += strlen(cp);
|
|
||||||
*cp++ = RDELIM;
|
|
||||||
*cp++ = DELIM;
|
|
||||||
pt++;
|
pt++;
|
||||||
}
|
}
|
||||||
cp--;
|
|
||||||
switch (path_delim)
|
switch (path_delim)
|
||||||
{
|
{
|
||||||
case PATH_CLOSED:
|
case PATH_CLOSED:
|
||||||
*cp++ = RDELIM;
|
appendStringInfoChar(&str, RDELIM);
|
||||||
break;
|
break;
|
||||||
case PATH_OPEN:
|
case PATH_OPEN:
|
||||||
*cp++ = RDELIM_EP;
|
appendStringInfoChar(&str, RDELIM_EP);
|
||||||
break;
|
break;
|
||||||
case PATH_NONE:
|
case PATH_NONE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*cp = '\0';
|
|
||||||
|
|
||||||
return result;
|
return str.data;
|
||||||
} /* path_encode() */
|
} /* path_encode() */
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
/*-------------------------------------------------------------
|
||||||
@ -387,16 +353,11 @@ box_in(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
BOX *box = (BOX *) palloc(sizeof(BOX));
|
BOX *box = (BOX *) palloc(sizeof(BOX));
|
||||||
int isopen;
|
bool isopen;
|
||||||
char *s;
|
|
||||||
double x,
|
double x,
|
||||||
y;
|
y;
|
||||||
|
|
||||||
if ((!path_decode(FALSE, 2, str, &isopen, &s, &(box->high)))
|
path_decode(str, false, 2, &(box->high), &isopen, NULL, "box", str);
|
||||||
|| (*s != '\0'))
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type box: \"%s\"", str)));
|
|
||||||
|
|
||||||
/* reorder corners if necessary... */
|
/* reorder corners if necessary... */
|
||||||
if (box->high.x < box->low.x)
|
if (box->high.x < box->low.x)
|
||||||
@ -935,43 +896,22 @@ box_diagonal(PG_FUNCTION_ARGS)
|
|||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
line_decode(const char *str, LINE *line)
|
line_decode(char *s, const char *str, LINE *line)
|
||||||
{
|
{
|
||||||
char *tail;
|
/* s was already advanced over leading '{' */
|
||||||
|
line->A = single_decode(s, &s, "line", str);
|
||||||
while (isspace((unsigned char) *str))
|
if (*s++ != DELIM)
|
||||||
str++;
|
|
||||||
if (*str++ != '{')
|
|
||||||
return false;
|
return false;
|
||||||
line->A = strtod(str, &tail);
|
line->B = single_decode(s, &s, "line", str);
|
||||||
if (tail <= str)
|
if (*s++ != DELIM)
|
||||||
return false;
|
return false;
|
||||||
str = tail;
|
line->C = single_decode(s, &s, "line", str);
|
||||||
while (isspace((unsigned char) *str))
|
if (*s++ != '}')
|
||||||
str++;
|
|
||||||
if (*str++ != DELIM)
|
|
||||||
return false;
|
return false;
|
||||||
line->B = strtod(str, &tail);
|
while (isspace((unsigned char) *s))
|
||||||
if (tail <= str)
|
s++;
|
||||||
|
if (*s != '\0')
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -979,33 +919,35 @@ Datum
|
|||||||
line_in(PG_FUNCTION_ARGS)
|
line_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
LINE *line;
|
LINE *line = (LINE *) palloc(sizeof(LINE));
|
||||||
LSEG lseg;
|
LSEG lseg;
|
||||||
int isopen;
|
bool isopen;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
line = (LINE *) palloc(sizeof(LINE));
|
s = str;
|
||||||
|
while (isspace((unsigned char) *s))
|
||||||
if (path_decode(TRUE, 2, str, &isopen, &s, &(lseg.p[0])) && *s == '\0')
|
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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid line specification: must be two distinct points")));
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
|
"line", str)));
|
||||||
line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
|
|
||||||
}
|
|
||||||
else if (line_decode(str, line))
|
|
||||||
{
|
|
||||||
if (FPzero(line->A) && FPzero(line->B))
|
if (FPzero(line->A) && FPzero(line->B))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(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
|
||||||
ereport(ERROR,
|
{
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
path_decode(s, true, 2, &(lseg.p[0]), &isopen, NULL, "line", str);
|
||||||
errmsg("invalid input syntax for type line: \"%s\"", 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);
|
PG_RETURN_LINE_P(line);
|
||||||
}
|
}
|
||||||
@ -1015,12 +957,11 @@ Datum
|
|||||||
line_out(PG_FUNCTION_ARGS)
|
line_out(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
LINE *line = PG_GETARG_LINE_P(0);
|
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)
|
PG_RETURN_CSTRING(psprintf("{%s,%s,%s}", astr, bstr, cstr));
|
||||||
ndig = 1;
|
|
||||||
|
|
||||||
PG_RETURN_CSTRING(psprintf("{%.*g,%.*g,%.*g}", ndig, line->A, ndig, line->B, ndig, line->C));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1367,7 +1308,7 @@ path_in(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
PATH *path;
|
PATH *path;
|
||||||
int isopen;
|
bool isopen;
|
||||||
char *s;
|
char *s;
|
||||||
int npts;
|
int npts;
|
||||||
int size;
|
int size;
|
||||||
@ -1377,7 +1318,8 @@ path_in(PG_FUNCTION_ARGS)
|
|||||||
if ((npts = pair_count(str, ',')) <= 0)
|
if ((npts = pair_count(str, ',')) <= 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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;
|
s = str;
|
||||||
while (isspace((unsigned char) *s))
|
while (isspace((unsigned char) *s))
|
||||||
@ -1404,11 +1346,23 @@ path_in(PG_FUNCTION_ARGS)
|
|||||||
SET_VARSIZE(path, size);
|
SET_VARSIZE(path, size);
|
||||||
path->npts = npts;
|
path->npts = npts;
|
||||||
|
|
||||||
if ((!path_decode(TRUE, npts, s, &isopen, &s, &(path->p[0])))
|
path_decode(s, true, npts, &(path->p[0]), &isopen, &s, "path", str);
|
||||||
&& (!((depth == 0) && (*s == '\0'))) && !((depth >= 1) && (*s == RDELIM)))
|
|
||||||
|
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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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);
|
path->closed = (!isopen);
|
||||||
/* prevent instability in unused pad bytes */
|
/* prevent instability in unused pad bytes */
|
||||||
@ -1782,21 +1736,9 @@ Datum
|
|||||||
point_in(PG_FUNCTION_ARGS)
|
point_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
Point *point;
|
Point *point = (Point *) palloc(sizeof(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;
|
|
||||||
|
|
||||||
|
pair_decode(str, &point->x, &point->y, NULL, "point", str);
|
||||||
PG_RETURN_POINT_P(point);
|
PG_RETURN_POINT_P(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2008,18 +1950,10 @@ Datum
|
|||||||
lseg_in(PG_FUNCTION_ARGS)
|
lseg_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
LSEG *lseg;
|
LSEG *lseg = (LSEG *) palloc(sizeof(LSEG));
|
||||||
int isopen;
|
bool 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)));
|
|
||||||
|
|
||||||
|
path_decode(str, true, 2, &(lseg->p[0]), &isopen, NULL, "lseg", str);
|
||||||
PG_RETURN_LSEG_P(lseg);
|
PG_RETURN_LSEG_P(lseg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3480,13 +3414,13 @@ poly_in(PG_FUNCTION_ARGS)
|
|||||||
int npts;
|
int npts;
|
||||||
int size;
|
int size;
|
||||||
int base_size;
|
int base_size;
|
||||||
int isopen;
|
bool isopen;
|
||||||
char *s;
|
|
||||||
|
|
||||||
if ((npts = pair_count(str, ',')) <= 0)
|
if ((npts = pair_count(str, ',')) <= 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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;
|
base_size = sizeof(poly->p[0]) * npts;
|
||||||
size = offsetof(POLYGON, p) +base_size;
|
size = offsetof(POLYGON, p) +base_size;
|
||||||
@ -3502,11 +3436,7 @@ poly_in(PG_FUNCTION_ARGS)
|
|||||||
SET_VARSIZE(poly, size);
|
SET_VARSIZE(poly, size);
|
||||||
poly->npts = npts;
|
poly->npts = npts;
|
||||||
|
|
||||||
if ((!path_decode(FALSE, npts, str, &isopen, &s, &(poly->p[0])))
|
path_decode(str, false, npts, &(poly->p[0]), &isopen, NULL, "polygon", str);
|
||||||
|| (*s != '\0'))
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type polygon: \"%s\"", str)));
|
|
||||||
|
|
||||||
make_bound_box(poly);
|
make_bound_box(poly);
|
||||||
|
|
||||||
@ -4595,13 +4525,11 @@ Datum
|
|||||||
circle_in(PG_FUNCTION_ARGS)
|
circle_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
CIRCLE *circle;
|
CIRCLE *circle = (CIRCLE *) palloc(sizeof(CIRCLE));
|
||||||
char *s,
|
char *s,
|
||||||
*cp;
|
*cp;
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
|
|
||||||
circle = (CIRCLE *) palloc(sizeof(CIRCLE));
|
|
||||||
|
|
||||||
s = str;
|
s = str;
|
||||||
while (isspace((unsigned char) *s))
|
while (isspace((unsigned char) *s))
|
||||||
s++;
|
s++;
|
||||||
@ -4615,20 +4543,17 @@ circle_in(PG_FUNCTION_ARGS)
|
|||||||
s = cp;
|
s = cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pair_decode(s, &circle->center.x, &circle->center.y, &s))
|
pair_decode(s, &circle->center.x, &circle->center.y, &s, "circle", str);
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type circle: \"%s\"", str)));
|
|
||||||
|
|
||||||
if (*s == DELIM)
|
if (*s == DELIM)
|
||||||
s++;
|
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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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)
|
while (depth > 0)
|
||||||
{
|
{
|
||||||
@ -4643,13 +4568,15 @@ circle_in(PG_FUNCTION_ARGS)
|
|||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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')
|
if (*s != '\0')
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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);
|
PG_RETURN_CIRCLE_P(circle);
|
||||||
}
|
}
|
||||||
@ -4660,32 +4587,19 @@ Datum
|
|||||||
circle_out(PG_FUNCTION_ARGS)
|
circle_out(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
CIRCLE *circle = PG_GETARG_CIRCLE_P(0);
|
CIRCLE *circle = PG_GETARG_CIRCLE_P(0);
|
||||||
char *result;
|
StringInfoData str;
|
||||||
char *cp;
|
|
||||||
|
|
||||||
result = palloc(2 * P_MAXLEN + 6);
|
initStringInfo(&str);
|
||||||
|
|
||||||
cp = result;
|
appendStringInfoChar(&str, LDELIM_C);
|
||||||
*cp++ = LDELIM_C;
|
appendStringInfoChar(&str, LDELIM);
|
||||||
*cp++ = LDELIM;
|
pair_encode(circle->center.x, circle->center.y, &str);
|
||||||
if (!pair_encode(circle->center.x, circle->center.y, cp))
|
appendStringInfoChar(&str, RDELIM);
|
||||||
ereport(ERROR,
|
appendStringInfoChar(&str, DELIM);
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
single_encode(circle->radius, &str);
|
||||||
errmsg("could not format \"circle\" value")));
|
appendStringInfoChar(&str, RDELIM_C);
|
||||||
|
|
||||||
cp += strlen(cp);
|
PG_RETURN_CSTRING(str.data);
|
||||||
*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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -343,6 +343,9 @@ extern float get_float4_infinity(void);
|
|||||||
extern double get_float8_nan(void);
|
extern double get_float8_nan(void);
|
||||||
extern float get_float4_nan(void);
|
extern float get_float4_nan(void);
|
||||||
extern int is_infinite(double val);
|
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 float4in(PG_FUNCTION_ARGS);
|
||||||
extern Datum float4out(PG_FUNCTION_ARGS);
|
extern Datum float4out(PG_FUNCTION_ARGS);
|
||||||
|
@ -232,15 +232,15 @@ INSERT INTO box_temp
|
|||||||
('(-infinity,-infinity)(infinity,infinity)');
|
('(-infinity,-infinity)(infinity,infinity)');
|
||||||
SET enable_seqscan = false;
|
SET enable_seqscan = false;
|
||||||
SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
|
SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
|
||||||
f1
|
f1
|
||||||
------------------
|
----------------------------
|
||||||
(2,2),(1,1)
|
(2,2),(1,1)
|
||||||
(4,4),(2,2)
|
(4,4),(2,2)
|
||||||
(6,6),(3,3)
|
(6,6),(3,3)
|
||||||
(8,8),(4,4)
|
(8,8),(4,4)
|
||||||
(-0,100),(0,0)
|
(-0,100),(0,0)
|
||||||
(0,inf),(0,100)
|
(0,Infinity),(0,100)
|
||||||
(0,inf),(-inf,0)
|
(0,Infinity),(-Infinity,0)
|
||||||
(7 rows)
|
(7 rows)
|
||||||
|
|
||||||
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
|
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)
|
(2 rows)
|
||||||
|
|
||||||
SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
|
SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
|
||||||
f1
|
f1
|
||||||
------------------
|
----------------------------
|
||||||
(2,2),(1,1)
|
(2,2),(1,1)
|
||||||
(4,4),(2,2)
|
(4,4),(2,2)
|
||||||
(6,6),(3,3)
|
(6,6),(3,3)
|
||||||
(8,8),(4,4)
|
(8,8),(4,4)
|
||||||
(10,10),(5,5)
|
(10,10),(5,5)
|
||||||
(-0,100),(0,0)
|
(-0,100),(0,0)
|
||||||
(0,inf),(0,100)
|
(0,Infinity),(0,100)
|
||||||
(0,inf),(-inf,0)
|
(0,Infinity),(-Infinity,0)
|
||||||
(8 rows)
|
(8 rows)
|
||||||
|
|
||||||
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
|
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)
|
(2 rows)
|
||||||
|
|
||||||
SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
|
SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
|
||||||
f1
|
f1
|
||||||
-----------------------
|
-------------------------------------------
|
||||||
(20,20),(10,10)
|
(20,20),(10,10)
|
||||||
(22,22),(11,11)
|
(22,22),(11,11)
|
||||||
(24,24),(12,12)
|
(24,24),(12,12)
|
||||||
@ -289,7 +289,7 @@ SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
|
|||||||
(46,46),(23,23)
|
(46,46),(23,23)
|
||||||
(48,48),(24,24)
|
(48,48),(24,24)
|
||||||
(50,50),(25,25)
|
(50,50),(25,25)
|
||||||
(inf,inf),(-inf,-inf)
|
(Infinity,Infinity),(-Infinity,-Infinity)
|
||||||
(17 rows)
|
(17 rows)
|
||||||
|
|
||||||
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
|
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)
|
(2 rows)
|
||||||
|
|
||||||
SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49.99)';
|
SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49.99)';
|
||||||
f1
|
f1
|
||||||
-------------------
|
----------------------
|
||||||
(100,100),(50,50)
|
(100,100),(50,50)
|
||||||
(0,inf),(0,100)
|
(0,Infinity),(0,100)
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49.99)';
|
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)
|
(2 rows)
|
||||||
|
|
||||||
SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
|
SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
|
||||||
f1
|
f1
|
||||||
-------------------
|
----------------------
|
||||||
(82,82),(41,41)
|
(82,82),(41,41)
|
||||||
(84,84),(42,42)
|
(84,84),(42,42)
|
||||||
(86,86),(43,43)
|
(86,86),(43,43)
|
||||||
@ -401,7 +401,7 @@ SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
|
|||||||
(96,96),(48,48)
|
(96,96),(48,48)
|
||||||
(98,98),(49,49)
|
(98,98),(49,49)
|
||||||
(100,100),(50,50)
|
(100,100),(50,50)
|
||||||
(0,inf),(0,100)
|
(0,Infinity),(0,100)
|
||||||
(11 rows)
|
(11 rows)
|
||||||
|
|
||||||
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
|
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)
|
(2 rows)
|
||||||
|
|
||||||
SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,16)';
|
SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,16)';
|
||||||
f1
|
f1
|
||||||
-----------------------
|
-------------------------------------------
|
||||||
(16,16),(8,8)
|
(16,16),(8,8)
|
||||||
(18,18),(9,9)
|
(18,18),(9,9)
|
||||||
(20,20),(10,10)
|
(20,20),(10,10)
|
||||||
(inf,inf),(-inf,-inf)
|
(Infinity,Infinity),(-Infinity,-Infinity)
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,15)';
|
EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,15)';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user