diff options
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/cube/cube.c | 3 | ||||
-rw-r--r-- | contrib/cube/cubedata.h | 7 | ||||
-rw-r--r-- | contrib/cube/cubeparse.y | 76 | ||||
-rw-r--r-- | contrib/cube/cubescan.l | 8 | ||||
-rw-r--r-- | contrib/cube/expected/cube.out | 25 | ||||
-rw-r--r-- | contrib/cube/sql/cube.sql | 6 |
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 -- |