Skip to content

Commit 878ce16

Browse files
committed
Convert contrib/seg's input function to report errors softly
Reviewed by Tom Lane Discussion: https://postgr.es/m/a8dc5700-c341-3ba8-0507-cc09881e6200@dunslane.net
1 parent 7a31033 commit 878ce16

File tree

6 files changed

+70
-18
lines changed

6 files changed

+70
-18
lines changed

contrib/seg/expected/seg.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,3 +1273,23 @@ FROM test_seg WHERE s @> '11.2..11.3' OR s IS NULL ORDER BY s;
12731273
| |
12741274
(144 rows)
12751275

1276+
-- test non error throwing API
1277+
SELECT str as seg,
1278+
pg_input_is_valid(str,'seg') as ok,
1279+
pg_input_error_message(str,'seg') as errmsg
1280+
FROM unnest(ARRAY['-1 .. 1'::text,
1281+
'100(+-)1',
1282+
'',
1283+
'ABC',
1284+
'1 e7',
1285+
'1e700']) str;
1286+
seg | ok | errmsg
1287+
----------+----+---------------------------------------
1288+
-1 .. 1 | t |
1289+
100(+-)1 | t |
1290+
| f | bad seg representation
1291+
ABC | f | bad seg representation
1292+
1 e7 | f | bad seg representation
1293+
1e700 | f | "1e700" is out of range for type real
1294+
(6 rows)
1295+

contrib/seg/seg.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ seg_in(PG_FUNCTION_ARGS)
108108

109109
seg_scanner_init(str);
110110

111-
if (seg_yyparse(result) != 0)
112-
seg_yyerror(result, "bogus input");
111+
if (seg_yyparse(result, fcinfo->context) != 0)
112+
seg_yyerror(result, fcinfo->context, "bogus input");
113113

114114
seg_scanner_finish();
115115

contrib/seg/segdata.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ extern int significant_digits(const char *s);
1616

1717
/* in segscan.l */
1818
extern int seg_yylex(void);
19-
extern void seg_yyerror(SEG *result, const char *message) pg_attribute_noreturn();
19+
extern void seg_yyerror(SEG *result, struct Node *escontext,
20+
const char *message);
2021
extern void seg_scanner_init(const char *str);
2122
extern void seg_scanner_finish(void);
2223

2324
/* in segparse.y */
24-
extern int seg_yyparse(SEG *result);
25+
extern int seg_yyparse(SEG *result, struct Node *escontext);

contrib/seg/segparse.y

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
#include <math.h>
88

99
#include "fmgr.h"
10+
#include "nodes/miscnodes.h"
1011
#include "utils/builtins.h"
12+
#include "utils/float.h"
1113

1214
#include "segdata.h"
1315

@@ -19,7 +21,7 @@
1921
#define YYMALLOC palloc
2022
#define YYFREE pfree
2123

22-
static float seg_atof(const char *value);
24+
static bool seg_atof(char *value, float *result, struct Node *escontext);
2325

2426
static int sig_digits(const char *value);
2527

@@ -35,6 +37,7 @@ static char strbuf[25] = {
3537

3638
/* BISON Declarations */
3739
%parse-param {SEG *result}
40+
%parse-param {struct Node *escontext}
3841
%expect 0
3942
%name-prefix="seg_yy"
4043

@@ -77,7 +80,7 @@ range: boundary PLUMIN deviation
7780
result->lower = $1.val;
7881
result->upper = $3.val;
7982
if ( result->lower > result->upper ) {
80-
ereport(ERROR,
83+
errsave(escontext,
8184
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
8285
errmsg("swapped boundaries: %g is greater than %g",
8386
result->lower, result->upper)));
@@ -121,7 +124,10 @@ range: boundary PLUMIN deviation
121124
boundary: SEGFLOAT
122125
{
123126
/* temp variable avoids a gcc 3.3.x bug on Sparc64 */
124-
float val = seg_atof($1);
127+
float val;
128+
129+
if (!seg_atof($1, &val, escontext))
130+
YYABORT;
125131

126132
$$.ext = '\0';
127133
$$.sigd = sig_digits($1);
@@ -130,7 +136,10 @@ boundary: SEGFLOAT
130136
| EXTENSION SEGFLOAT
131137
{
132138
/* temp variable avoids a gcc 3.3.x bug on Sparc64 */
133-
float val = seg_atof($2);
139+
float val;
140+
141+
if (!seg_atof($2, &val, escontext))
142+
YYABORT;
134143

135144
$$.ext = $1[0];
136145
$$.sigd = sig_digits($2);
@@ -141,7 +150,10 @@ boundary: SEGFLOAT
141150
deviation: SEGFLOAT
142151
{
143152
/* temp variable avoids a gcc 3.3.x bug on Sparc64 */
144-
float val = seg_atof($1);
153+
float val;
154+
155+
if (!seg_atof($1, &val, escontext))
156+
YYABORT;
145157

146158
$$.ext = '\0';
147159
$$.sigd = sig_digits($1);
@@ -152,13 +164,13 @@ deviation: SEGFLOAT
152164
%%
153165

154166

155-
static float
156-
seg_atof(const char *value)
167+
static bool
168+
seg_atof(char *value, float *result, struct Node *escontext)
157169
{
158-
Datum datum;
159-
160-
datum = DirectFunctionCall1(float4in, CStringGetDatum(value));
161-
return DatumGetFloat4(datum);
170+
*result = float4in_internal(value, NULL, "seg", value, escontext);
171+
if (SOFT_ERROR_OCCURRED(escontext))
172+
return false;
173+
return true;
162174
}
163175

164176
static int

contrib/seg/segscan.l

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*/
55
#include "postgres.h"
66

7+
#include "nodes/miscnodes.h"
8+
79
/*
810
* NB: include segparse.h only AFTER including segdata.h, because segdata.h
911
* contains the definition for SEG.
@@ -65,19 +67,23 @@ float ({integer}|{real})([eE]{integer})?
6567
/* LCOV_EXCL_STOP */
6668

6769
void
68-
seg_yyerror(SEG *result, const char *message)
70+
seg_yyerror(SEG *result, struct Node *escontext, const char *message)
6971
{
72+
/* if we already reported an error, don't overwrite it */
73+
if (SOFT_ERROR_OCCURRED(escontext))
74+
return;
75+
7076
if (*yytext == YY_END_OF_BUFFER_CHAR)
7177
{
72-
ereport(ERROR,
78+
errsave(escontext,
7379
(errcode(ERRCODE_SYNTAX_ERROR),
7480
errmsg("bad seg representation"),
7581
/* translator: %s is typically "syntax error" */
7682
errdetail("%s at end of input", message)));
7783
}
7884
else
7985
{
80-
ereport(ERROR,
86+
errsave(escontext,
8187
(errcode(ERRCODE_SYNTAX_ERROR),
8288
errmsg("bad seg representation"),
8389
/* translator: first %s is typically "syntax error" */

contrib/seg/sql/seg.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,16 @@ SELECT * FROM test_seg WHERE s @> '11..11.3' GROUP BY s;
238238
-- Test functions
239239
SELECT seg_lower(s), seg_center(s), seg_upper(s)
240240
FROM test_seg WHERE s @> '11.2..11.3' OR s IS NULL ORDER BY s;
241+
242+
243+
-- test non error throwing API
244+
245+
SELECT str as seg,
246+
pg_input_is_valid(str,'seg') as ok,
247+
pg_input_error_message(str,'seg') as errmsg
248+
FROM unnest(ARRAY['-1 .. 1'::text,
249+
'100(+-)1',
250+
'',
251+
'ABC',
252+
'1 e7',
253+
'1e700']) str;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy