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
This commit is contained in:
parent
7a310338f4
commit
878ce16056
@ -1273,3 +1273,23 @@ FROM test_seg WHERE s @> '11.2..11.3' OR s IS NULL ORDER BY s;
|
|||||||
| |
|
| |
|
||||||
(144 rows)
|
(144 rows)
|
||||||
|
|
||||||
|
-- test non error throwing API
|
||||||
|
SELECT str as seg,
|
||||||
|
pg_input_is_valid(str,'seg') as ok,
|
||||||
|
pg_input_error_message(str,'seg') as errmsg
|
||||||
|
FROM unnest(ARRAY['-1 .. 1'::text,
|
||||||
|
'100(+-)1',
|
||||||
|
'',
|
||||||
|
'ABC',
|
||||||
|
'1 e7',
|
||||||
|
'1e700']) str;
|
||||||
|
seg | ok | errmsg
|
||||||
|
----------+----+---------------------------------------
|
||||||
|
-1 .. 1 | t |
|
||||||
|
100(+-)1 | t |
|
||||||
|
| f | bad seg representation
|
||||||
|
ABC | f | bad seg representation
|
||||||
|
1 e7 | f | bad seg representation
|
||||||
|
1e700 | f | "1e700" is out of range for type real
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
@ -108,8 +108,8 @@ seg_in(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
seg_scanner_init(str);
|
seg_scanner_init(str);
|
||||||
|
|
||||||
if (seg_yyparse(result) != 0)
|
if (seg_yyparse(result, fcinfo->context) != 0)
|
||||||
seg_yyerror(result, "bogus input");
|
seg_yyerror(result, fcinfo->context, "bogus input");
|
||||||
|
|
||||||
seg_scanner_finish();
|
seg_scanner_finish();
|
||||||
|
|
||||||
|
@ -16,9 +16,10 @@ extern int significant_digits(const char *s);
|
|||||||
|
|
||||||
/* in segscan.l */
|
/* in segscan.l */
|
||||||
extern int seg_yylex(void);
|
extern int seg_yylex(void);
|
||||||
extern void seg_yyerror(SEG *result, const char *message) pg_attribute_noreturn();
|
extern void seg_yyerror(SEG *result, struct Node *escontext,
|
||||||
|
const char *message);
|
||||||
extern void seg_scanner_init(const char *str);
|
extern void seg_scanner_init(const char *str);
|
||||||
extern void seg_scanner_finish(void);
|
extern void seg_scanner_finish(void);
|
||||||
|
|
||||||
/* in segparse.y */
|
/* in segparse.y */
|
||||||
extern int seg_yyparse(SEG *result);
|
extern int seg_yyparse(SEG *result, struct Node *escontext);
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
|
#include "nodes/miscnodes.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
#include "utils/float.h"
|
||||||
|
|
||||||
#include "segdata.h"
|
#include "segdata.h"
|
||||||
|
|
||||||
@ -19,7 +21,7 @@
|
|||||||
#define YYMALLOC palloc
|
#define YYMALLOC palloc
|
||||||
#define YYFREE pfree
|
#define YYFREE pfree
|
||||||
|
|
||||||
static float seg_atof(const char *value);
|
static bool seg_atof(char *value, float *result, struct Node *escontext);
|
||||||
|
|
||||||
static int sig_digits(const char *value);
|
static int sig_digits(const char *value);
|
||||||
|
|
||||||
@ -35,6 +37,7 @@ static char strbuf[25] = {
|
|||||||
|
|
||||||
/* BISON Declarations */
|
/* BISON Declarations */
|
||||||
%parse-param {SEG *result}
|
%parse-param {SEG *result}
|
||||||
|
%parse-param {struct Node *escontext}
|
||||||
%expect 0
|
%expect 0
|
||||||
%name-prefix="seg_yy"
|
%name-prefix="seg_yy"
|
||||||
|
|
||||||
@ -77,7 +80,7 @@ range: boundary PLUMIN deviation
|
|||||||
result->lower = $1.val;
|
result->lower = $1.val;
|
||||||
result->upper = $3.val;
|
result->upper = $3.val;
|
||||||
if ( result->lower > result->upper ) {
|
if ( result->lower > result->upper ) {
|
||||||
ereport(ERROR,
|
errsave(escontext,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("swapped boundaries: %g is greater than %g",
|
errmsg("swapped boundaries: %g is greater than %g",
|
||||||
result->lower, result->upper)));
|
result->lower, result->upper)));
|
||||||
@ -121,7 +124,10 @@ range: boundary PLUMIN deviation
|
|||||||
boundary: SEGFLOAT
|
boundary: SEGFLOAT
|
||||||
{
|
{
|
||||||
/* temp variable avoids a gcc 3.3.x bug on Sparc64 */
|
/* temp variable avoids a gcc 3.3.x bug on Sparc64 */
|
||||||
float val = seg_atof($1);
|
float val;
|
||||||
|
|
||||||
|
if (!seg_atof($1, &val, escontext))
|
||||||
|
YYABORT;
|
||||||
|
|
||||||
$$.ext = '\0';
|
$$.ext = '\0';
|
||||||
$$.sigd = sig_digits($1);
|
$$.sigd = sig_digits($1);
|
||||||
@ -130,7 +136,10 @@ boundary: SEGFLOAT
|
|||||||
| EXTENSION SEGFLOAT
|
| EXTENSION SEGFLOAT
|
||||||
{
|
{
|
||||||
/* temp variable avoids a gcc 3.3.x bug on Sparc64 */
|
/* temp variable avoids a gcc 3.3.x bug on Sparc64 */
|
||||||
float val = seg_atof($2);
|
float val;
|
||||||
|
|
||||||
|
if (!seg_atof($2, &val, escontext))
|
||||||
|
YYABORT;
|
||||||
|
|
||||||
$$.ext = $1[0];
|
$$.ext = $1[0];
|
||||||
$$.sigd = sig_digits($2);
|
$$.sigd = sig_digits($2);
|
||||||
@ -141,7 +150,10 @@ boundary: SEGFLOAT
|
|||||||
deviation: SEGFLOAT
|
deviation: SEGFLOAT
|
||||||
{
|
{
|
||||||
/* temp variable avoids a gcc 3.3.x bug on Sparc64 */
|
/* temp variable avoids a gcc 3.3.x bug on Sparc64 */
|
||||||
float val = seg_atof($1);
|
float val;
|
||||||
|
|
||||||
|
if (!seg_atof($1, &val, escontext))
|
||||||
|
YYABORT;
|
||||||
|
|
||||||
$$.ext = '\0';
|
$$.ext = '\0';
|
||||||
$$.sigd = sig_digits($1);
|
$$.sigd = sig_digits($1);
|
||||||
@ -152,13 +164,13 @@ deviation: SEGFLOAT
|
|||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
||||||
static float
|
static bool
|
||||||
seg_atof(const char *value)
|
seg_atof(char *value, float *result, struct Node *escontext)
|
||||||
{
|
{
|
||||||
Datum datum;
|
*result = float4in_internal(value, NULL, "seg", value, escontext);
|
||||||
|
if (SOFT_ERROR_OCCURRED(escontext))
|
||||||
datum = DirectFunctionCall1(float4in, CStringGetDatum(value));
|
return false;
|
||||||
return DatumGetFloat4(datum);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
#include "nodes/miscnodes.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NB: include segparse.h only AFTER including segdata.h, because segdata.h
|
* NB: include segparse.h only AFTER including segdata.h, because segdata.h
|
||||||
* contains the definition for SEG.
|
* contains the definition for SEG.
|
||||||
@ -65,11 +67,15 @@ float ({integer}|{real})([eE]{integer})?
|
|||||||
/* LCOV_EXCL_STOP */
|
/* LCOV_EXCL_STOP */
|
||||||
|
|
||||||
void
|
void
|
||||||
seg_yyerror(SEG *result, const char *message)
|
seg_yyerror(SEG *result, struct Node *escontext, const char *message)
|
||||||
{
|
{
|
||||||
|
/* if we already reported an error, don't overwrite it */
|
||||||
|
if (SOFT_ERROR_OCCURRED(escontext))
|
||||||
|
return;
|
||||||
|
|
||||||
if (*yytext == YY_END_OF_BUFFER_CHAR)
|
if (*yytext == YY_END_OF_BUFFER_CHAR)
|
||||||
{
|
{
|
||||||
ereport(ERROR,
|
errsave(escontext,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("bad seg representation"),
|
errmsg("bad seg representation"),
|
||||||
/* translator: %s is typically "syntax error" */
|
/* translator: %s is typically "syntax error" */
|
||||||
@ -77,7 +83,7 @@ seg_yyerror(SEG *result, const char *message)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ereport(ERROR,
|
errsave(escontext,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("bad seg representation"),
|
errmsg("bad seg representation"),
|
||||||
/* translator: first %s is typically "syntax error" */
|
/* translator: first %s is typically "syntax error" */
|
||||||
|
@ -238,3 +238,16 @@ SELECT * FROM test_seg WHERE s @> '11..11.3' GROUP BY s;
|
|||||||
-- Test functions
|
-- Test functions
|
||||||
SELECT seg_lower(s), seg_center(s), seg_upper(s)
|
SELECT seg_lower(s), seg_center(s), seg_upper(s)
|
||||||
FROM test_seg WHERE s @> '11.2..11.3' OR s IS NULL ORDER BY s;
|
FROM test_seg WHERE s @> '11.2..11.3' OR s IS NULL ORDER BY s;
|
||||||
|
|
||||||
|
|
||||||
|
-- test non error throwing API
|
||||||
|
|
||||||
|
SELECT str as seg,
|
||||||
|
pg_input_is_valid(str,'seg') as ok,
|
||||||
|
pg_input_error_message(str,'seg') as errmsg
|
||||||
|
FROM unnest(ARRAY['-1 .. 1'::text,
|
||||||
|
'100(+-)1',
|
||||||
|
'',
|
||||||
|
'ABC',
|
||||||
|
'1 e7',
|
||||||
|
'1e700']) str;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user