summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/cube/cube.c3
-rw-r--r--contrib/cube/cubedata.h7
-rw-r--r--contrib/cube/cubeparse.y76
-rw-r--r--contrib/cube/cubescan.l8
-rw-r--r--contrib/cube/expected/cube.out25
-rw-r--r--contrib/cube/sql/cube.sql6
6 files changed, 95 insertions, 30 deletions
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c
index 4f32c5dc1d5..1fc447511a1 100644
--- a/contrib/cube/cube.c
+++ b/contrib/cube/cube.c
@@ -123,8 +123,9 @@ cube_in(PG_FUNCTION_ARGS)
cube_scanner_init(str, &scanbuflen);
- cube_yyparse(&result, scanbuflen);
+ cube_yyparse(&result, scanbuflen, fcinfo->context);
+ /* We might as well run this even on failure. */
cube_scanner_finish();
PG_RETURN_NDBOX_P(result);
diff --git a/contrib/cube/cubedata.h b/contrib/cube/cubedata.h
index 640a7ca5800..96fa41a04e7 100644
--- a/contrib/cube/cubedata.h
+++ b/contrib/cube/cubedata.h
@@ -61,9 +61,12 @@ typedef struct NDBOX
/* in cubescan.l */
extern int cube_yylex(void);
-extern void cube_yyerror(NDBOX **result, Size scanbuflen, const char *message) pg_attribute_noreturn();
+extern void cube_yyerror(NDBOX **result, Size scanbuflen,
+ struct Node *escontext,
+ const char *message);
extern void cube_scanner_init(const char *str, Size *scanbuflen);
extern void cube_scanner_finish(void);
/* in cubeparse.y */
-extern int cube_yyparse(NDBOX **result, Size scanbuflen);
+extern int cube_yyparse(NDBOX **result, Size scanbuflen,
+ struct Node *escontext);
diff --git a/contrib/cube/cubeparse.y b/contrib/cube/cubeparse.y
index 977dcba9650..44450d10274 100644
--- a/contrib/cube/cubeparse.y
+++ b/contrib/cube/cubeparse.y
@@ -7,6 +7,7 @@
#include "postgres.h"
#include "cubedata.h"
+#include "nodes/miscnodes.h"
#include "utils/float.h"
/* All grammar constructs return strings */
@@ -21,14 +22,17 @@
#define YYFREE pfree
static int item_count(const char *s, char delim);
-static NDBOX *write_box(int dim, char *str1, char *str2);
-static NDBOX *write_point_as_box(int dim, char *str);
+static bool write_box(int dim, char *str1, char *str2,
+ NDBOX **result, struct Node *escontext);
+static bool write_point_as_box(int dim, char *str,
+ NDBOX **result, struct Node *escontext);
%}
/* BISON Declarations */
%parse-param {NDBOX **result}
%parse-param {Size scanbuflen}
+%parse-param {struct Node *escontext}
%expect 0
%name-prefix="cube_yy"
@@ -45,7 +49,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
dim = item_count($2, ',');
if (item_count($4, ',') != dim)
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for cube"),
errdetail("Different point dimensions in (%s) and (%s).",
@@ -54,7 +58,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
}
if (dim > CUBE_MAX_DIM)
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for cube"),
errdetail("A cube cannot have more than %d dimensions.",
@@ -62,7 +66,8 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
YYABORT;
}
- *result = write_box( dim, $2, $4 );
+ if (!write_box(dim, $2, $4, result, escontext))
+ YYABORT;
}
| paren_list COMMA paren_list
@@ -72,7 +77,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
dim = item_count($1, ',');
if (item_count($3, ',') != dim)
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for cube"),
errdetail("Different point dimensions in (%s) and (%s).",
@@ -81,7 +86,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
}
if (dim > CUBE_MAX_DIM)
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for cube"),
errdetail("A cube cannot have more than %d dimensions.",
@@ -89,7 +94,8 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
YYABORT;
}
- *result = write_box( dim, $1, $3 );
+ if (!write_box(dim, $1, $3, result, escontext))
+ YYABORT;
}
| paren_list
@@ -99,7 +105,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
dim = item_count($1, ',');
if (dim > CUBE_MAX_DIM)
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for cube"),
errdetail("A cube cannot have more than %d dimensions.",
@@ -107,7 +113,8 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
YYABORT;
}
- *result = write_point_as_box(dim, $1);
+ if (!write_point_as_box(dim, $1, result, escontext))
+ YYABORT;
}
| list
@@ -117,7 +124,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
dim = item_count($1, ',');
if (dim > CUBE_MAX_DIM)
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for cube"),
errdetail("A cube cannot have more than %d dimensions.",
@@ -125,7 +132,8 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
YYABORT;
}
- *result = write_point_as_box(dim, $1);
+ if (!write_point_as_box(dim, $1, result, escontext))
+ YYABORT;
}
;
@@ -173,8 +181,9 @@ item_count(const char *s, char delim)
return nitems;
}
-static NDBOX *
-write_box(int dim, char *str1, char *str2)
+static bool
+write_box(int dim, char *str1, char *str2,
+ NDBOX **result, struct Node *escontext)
{
NDBOX *bp;
char *s;
@@ -190,18 +199,26 @@ write_box(int dim, char *str1, char *str2)
s = str1;
i = 0;
if (dim > 0)
- bp->x[i++] = float8in_internal(s, &endptr, "cube", str1);
+ {
+ bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+ }
while ((s = strchr(s, ',')) != NULL)
{
s++;
- bp->x[i++] = float8in_internal(s, &endptr, "cube", str1);
+ bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
}
Assert(i == dim);
s = str2;
if (dim > 0)
{
- bp->x[i] = float8in_internal(s, &endptr, "cube", str2);
+ bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
/* code this way to do right thing with NaN */
point &= (bp->x[i] == bp->x[0]);
i++;
@@ -209,7 +226,9 @@ write_box(int dim, char *str1, char *str2)
while ((s = strchr(s, ',')) != NULL)
{
s++;
- bp->x[i] = float8in_internal(s, &endptr, "cube", str2);
+ bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
point &= (bp->x[i] == bp->x[i - dim]);
i++;
}
@@ -229,11 +248,13 @@ write_box(int dim, char *str1, char *str2)
SET_POINT_BIT(bp);
}
- return bp;
+ *result = bp;
+ return true;
}
-static NDBOX *
-write_point_as_box(int dim, char *str)
+static bool
+write_point_as_box(int dim, char *str,
+ NDBOX **result, struct Node *escontext)
{
NDBOX *bp;
int i,
@@ -250,13 +271,20 @@ write_point_as_box(int dim, char *str)
s = str;
i = 0;
if (dim > 0)
- bp->x[i++] = float8in_internal(s, &endptr, "cube", str);
+ {
+ bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+ }
while ((s = strchr(s, ',')) != NULL)
{
s++;
- bp->x[i++] = float8in_internal(s, &endptr, "cube", str);
+ bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
}
Assert(i == dim);
- return bp;
+ *result = bp;
+ return true;
}
diff --git a/contrib/cube/cubescan.l b/contrib/cube/cubescan.l
index 6b316f2d545..49cb6992165 100644
--- a/contrib/cube/cubescan.l
+++ b/contrib/cube/cubescan.l
@@ -72,11 +72,13 @@ NaN [nN][aA][nN]
/* result and scanbuflen are not used, but Bison expects this signature */
void
-cube_yyerror(NDBOX **result, Size scanbuflen, const char *message)
+cube_yyerror(NDBOX **result, Size scanbuflen,
+ struct Node *escontext,
+ const char *message)
{
if (*yytext == YY_END_OF_BUFFER_CHAR)
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for cube"),
/* translator: %s is typically "syntax error" */
@@ -84,7 +86,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen, const char *message)
}
else
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for cube"),
/* translator: first %s is typically "syntax error" */
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
index 5b89cb1a26b..dc23e5ccc01 100644
--- a/contrib/cube/expected/cube.out
+++ b/contrib/cube/expected/cube.out
@@ -325,6 +325,31 @@ SELECT '-1e-700'::cube AS cube; -- out of range
ERROR: "-1e-700" is out of range for type double precision
LINE 1: SELECT '-1e-700'::cube AS cube;
^
+-- Also try it with non-error-throwing API
+SELECT pg_input_is_valid('(1,2)', 'cube');
+ pg_input_is_valid
+-------------------
+ t
+(1 row)
+
+SELECT pg_input_is_valid('[(1),]', 'cube');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_is_valid('-1e-700', 'cube');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('-1e-700', 'cube');
+ pg_input_error_message
+-----------------------------------------------------
+ "-1e-700" is out of range for type double precision
+(1 row)
+
--
-- Testing building cubes from float8 values
--
diff --git a/contrib/cube/sql/cube.sql b/contrib/cube/sql/cube.sql
index 7f8b2e39799..384883d16e9 100644
--- a/contrib/cube/sql/cube.sql
+++ b/contrib/cube/sql/cube.sql
@@ -79,6 +79,12 @@ SELECT '1,2a'::cube AS cube; -- 7
SELECT '1..2'::cube AS cube; -- 7
SELECT '-1e-700'::cube AS cube; -- out of range
+-- Also try it with non-error-throwing API
+SELECT pg_input_is_valid('(1,2)', 'cube');
+SELECT pg_input_is_valid('[(1),]', 'cube');
+SELECT pg_input_is_valid('-1e-700', 'cube');
+SELECT pg_input_error_message('-1e-700', 'cube');
+
--
-- Testing building cubes from float8 values
--