Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ccff2d2

Browse files
committed
Convert a few datatype input functions to use "soft" error reporting.
This patch converts the input functions for bool, int2, int4, int8, float4, float8, numeric, and contrib/cube to the new soft-error style. array_in and record_in are also converted. There's lots more to do, but this is enough to provide proof-of-concept that the soft-error API is usable, as well as reference examples for how to convert input functions. This patch is mostly by me, but it owes very substantial debt to earlier work by Nikita Glukhov, Andrew Dunstan, and Amul Sul. Thanks to Andres Freund for review. Discussion: https://postgr.es/m/3bbbb0df-7382-bf87-9737-340ba096e034@postgrespro.ru
1 parent 1939d26 commit ccff2d2

39 files changed

+727
-238
lines changed

contrib/cube/cube.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,9 @@ cube_in(PG_FUNCTION_ARGS)
123123

124124
cube_scanner_init(str, &scanbuflen);
125125

126-
cube_yyparse(&result, scanbuflen);
126+
cube_yyparse(&result, scanbuflen, fcinfo->context);
127127

128+
/* We might as well run this even on failure. */
128129
cube_scanner_finish();
129130

130131
PG_RETURN_NDBOX_P(result);

contrib/cube/cubedata.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,12 @@ typedef struct NDBOX
6161

6262
/* in cubescan.l */
6363
extern int cube_yylex(void);
64-
extern void cube_yyerror(NDBOX **result, Size scanbuflen, const char *message) pg_attribute_noreturn();
64+
extern void cube_yyerror(NDBOX **result, Size scanbuflen,
65+
struct Node *escontext,
66+
const char *message);
6567
extern void cube_scanner_init(const char *str, Size *scanbuflen);
6668
extern void cube_scanner_finish(void);
6769

6870
/* in cubeparse.y */
69-
extern int cube_yyparse(NDBOX **result, Size scanbuflen);
71+
extern int cube_yyparse(NDBOX **result, Size scanbuflen,
72+
struct Node *escontext);

contrib/cube/cubeparse.y

+52-24
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "postgres.h"
88

99
#include "cubedata.h"
10+
#include "nodes/miscnodes.h"
1011
#include "utils/float.h"
1112

1213
/* All grammar constructs return strings */
@@ -21,14 +22,17 @@
2122
#define YYFREE pfree
2223

2324
static int item_count(const char *s, char delim);
24-
static NDBOX *write_box(int dim, char *str1, char *str2);
25-
static NDBOX *write_point_as_box(int dim, char *str);
25+
static bool write_box(int dim, char *str1, char *str2,
26+
NDBOX **result, struct Node *escontext);
27+
static bool write_point_as_box(int dim, char *str,
28+
NDBOX **result, struct Node *escontext);
2629

2730
%}
2831

2932
/* BISON Declarations */
3033
%parse-param {NDBOX **result}
3134
%parse-param {Size scanbuflen}
35+
%parse-param {struct Node *escontext}
3236
%expect 0
3337
%name-prefix="cube_yy"
3438

@@ -45,7 +49,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
4549
dim = item_count($2, ',');
4650
if (item_count($4, ',') != dim)
4751
{
48-
ereport(ERROR,
52+
errsave(escontext,
4953
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5054
errmsg("invalid input syntax for cube"),
5155
errdetail("Different point dimensions in (%s) and (%s).",
@@ -54,15 +58,16 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
5458
}
5559
if (dim > CUBE_MAX_DIM)
5660
{
57-
ereport(ERROR,
61+
errsave(escontext,
5862
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5963
errmsg("invalid input syntax for cube"),
6064
errdetail("A cube cannot have more than %d dimensions.",
6165
CUBE_MAX_DIM)));
6266
YYABORT;
6367
}
6468

65-
*result = write_box( dim, $2, $4 );
69+
if (!write_box(dim, $2, $4, result, escontext))
70+
YYABORT;
6671
}
6772

6873
| paren_list COMMA paren_list
@@ -72,7 +77,7 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
7277
dim = item_count($1, ',');
7378
if (item_count($3, ',') != dim)
7479
{
75-
ereport(ERROR,
80+
errsave(escontext,
7681
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7782
errmsg("invalid input syntax for cube"),
7883
errdetail("Different point dimensions in (%s) and (%s).",
@@ -81,15 +86,16 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
8186
}
8287
if (dim > CUBE_MAX_DIM)
8388
{
84-
ereport(ERROR,
89+
errsave(escontext,
8590
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
8691
errmsg("invalid input syntax for cube"),
8792
errdetail("A cube cannot have more than %d dimensions.",
8893
CUBE_MAX_DIM)));
8994
YYABORT;
9095
}
9196

92-
*result = write_box( dim, $1, $3 );
97+
if (!write_box(dim, $1, $3, result, escontext))
98+
YYABORT;
9399
}
94100

95101
| paren_list
@@ -99,15 +105,16 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
99105
dim = item_count($1, ',');
100106
if (dim > CUBE_MAX_DIM)
101107
{
102-
ereport(ERROR,
108+
errsave(escontext,
103109
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
104110
errmsg("invalid input syntax for cube"),
105111
errdetail("A cube cannot have more than %d dimensions.",
106112
CUBE_MAX_DIM)));
107113
YYABORT;
108114
}
109115

110-
*result = write_point_as_box(dim, $1);
116+
if (!write_point_as_box(dim, $1, result, escontext))
117+
YYABORT;
111118
}
112119

113120
| list
@@ -117,15 +124,16 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET
117124
dim = item_count($1, ',');
118125
if (dim > CUBE_MAX_DIM)
119126
{
120-
ereport(ERROR,
127+
errsave(escontext,
121128
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
122129
errmsg("invalid input syntax for cube"),
123130
errdetail("A cube cannot have more than %d dimensions.",
124131
CUBE_MAX_DIM)));
125132
YYABORT;
126133
}
127134

128-
*result = write_point_as_box(dim, $1);
135+
if (!write_point_as_box(dim, $1, result, escontext))
136+
YYABORT;
129137
}
130138
;
131139

@@ -173,8 +181,9 @@ item_count(const char *s, char delim)
173181
return nitems;
174182
}
175183

176-
static NDBOX *
177-
write_box(int dim, char *str1, char *str2)
184+
static bool
185+
write_box(int dim, char *str1, char *str2,
186+
NDBOX **result, struct Node *escontext)
178187
{
179188
NDBOX *bp;
180189
char *s;
@@ -190,26 +199,36 @@ write_box(int dim, char *str1, char *str2)
190199
s = str1;
191200
i = 0;
192201
if (dim > 0)
193-
bp->x[i++] = float8in_internal(s, &endptr, "cube", str1);
202+
{
203+
bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
204+
if (SOFT_ERROR_OCCURRED(escontext))
205+
return false;
206+
}
194207
while ((s = strchr(s, ',')) != NULL)
195208
{
196209
s++;
197-
bp->x[i++] = float8in_internal(s, &endptr, "cube", str1);
210+
bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
211+
if (SOFT_ERROR_OCCURRED(escontext))
212+
return false;
198213
}
199214
Assert(i == dim);
200215

201216
s = str2;
202217
if (dim > 0)
203218
{
204-
bp->x[i] = float8in_internal(s, &endptr, "cube", str2);
219+
bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
220+
if (SOFT_ERROR_OCCURRED(escontext))
221+
return false;
205222
/* code this way to do right thing with NaN */
206223
point &= (bp->x[i] == bp->x[0]);
207224
i++;
208225
}
209226
while ((s = strchr(s, ',')) != NULL)
210227
{
211228
s++;
212-
bp->x[i] = float8in_internal(s, &endptr, "cube", str2);
229+
bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
230+
if (SOFT_ERROR_OCCURRED(escontext))
231+
return false;
213232
point &= (bp->x[i] == bp->x[i - dim]);
214233
i++;
215234
}
@@ -229,11 +248,13 @@ write_box(int dim, char *str1, char *str2)
229248
SET_POINT_BIT(bp);
230249
}
231250

232-
return bp;
251+
*result = bp;
252+
return true;
233253
}
234254

235-
static NDBOX *
236-
write_point_as_box(int dim, char *str)
255+
static bool
256+
write_point_as_box(int dim, char *str,
257+
NDBOX **result, struct Node *escontext)
237258
{
238259
NDBOX *bp;
239260
int i,
@@ -250,13 +271,20 @@ write_point_as_box(int dim, char *str)
250271
s = str;
251272
i = 0;
252273
if (dim > 0)
253-
bp->x[i++] = float8in_internal(s, &endptr, "cube", str);
274+
{
275+
bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
276+
if (SOFT_ERROR_OCCURRED(escontext))
277+
return false;
278+
}
254279
while ((s = strchr(s, ',')) != NULL)
255280
{
256281
s++;
257-
bp->x[i++] = float8in_internal(s, &endptr, "cube", str);
282+
bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
283+
if (SOFT_ERROR_OCCURRED(escontext))
284+
return false;
258285
}
259286
Assert(i == dim);
260287

261-
return bp;
288+
*result = bp;
289+
return true;
262290
}

contrib/cube/cubescan.l

+5-3
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,21 @@ NaN [nN][aA][nN]
7272

7373
/* result and scanbuflen are not used, but Bison expects this signature */
7474
void
75-
cube_yyerror(NDBOX **result, Size scanbuflen, const char *message)
75+
cube_yyerror(NDBOX **result, Size scanbuflen,
76+
struct Node *escontext,
77+
const char *message)
7678
{
7779
if (*yytext == YY_END_OF_BUFFER_CHAR)
7880
{
79-
ereport(ERROR,
81+
errsave(escontext,
8082
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
8183
errmsg("invalid input syntax for cube"),
8284
/* translator: %s is typically "syntax error" */
8385
errdetail("%s at end of input", message)));
8486
}
8587
else
8688
{
87-
ereport(ERROR,
89+
errsave(escontext,
8890
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
8991
errmsg("invalid input syntax for cube"),
9092
/* translator: first %s is typically "syntax error" */

contrib/cube/expected/cube.out

+25
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,31 @@ SELECT '-1e-700'::cube AS cube; -- out of range
325325
ERROR: "-1e-700" is out of range for type double precision
326326
LINE 1: SELECT '-1e-700'::cube AS cube;
327327
^
328+
-- Also try it with non-error-throwing API
329+
SELECT pg_input_is_valid('(1,2)', 'cube');
330+
pg_input_is_valid
331+
-------------------
332+
t
333+
(1 row)
334+
335+
SELECT pg_input_is_valid('[(1),]', 'cube');
336+
pg_input_is_valid
337+
-------------------
338+
f
339+
(1 row)
340+
341+
SELECT pg_input_is_valid('-1e-700', 'cube');
342+
pg_input_is_valid
343+
-------------------
344+
f
345+
(1 row)
346+
347+
SELECT pg_input_error_message('-1e-700', 'cube');
348+
pg_input_error_message
349+
-----------------------------------------------------
350+
"-1e-700" is out of range for type double precision
351+
(1 row)
352+
328353
--
329354
-- Testing building cubes from float8 values
330355
--

contrib/cube/sql/cube.sql

+6
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ SELECT '1,2a'::cube AS cube; -- 7
7979
SELECT '1..2'::cube AS cube; -- 7
8080
SELECT '-1e-700'::cube AS cube; -- out of range
8181

82+
-- Also try it with non-error-throwing API
83+
SELECT pg_input_is_valid('(1,2)', 'cube');
84+
SELECT pg_input_is_valid('[(1),]', 'cube');
85+
SELECT pg_input_is_valid('-1e-700', 'cube');
86+
SELECT pg_input_error_message('-1e-700', 'cube');
87+
8288
--
8389
-- Testing building cubes from float8 values
8490
--

0 commit comments

Comments
 (0)