Skip to content

Commit d35a1af

Browse files
committed
Convert range_in and multirange_in to report errors softly.
This is mostly straightforward, except that if the range type has a canonical function, that might throw an error during range input. (Such errors probably only occur for edge cases: in the in-core canonical functions, it happens only if a bound has the maximum valid value for the underlying type.) Hence, this patch extends the soft-error regime to allow canonical functions to return errors softly as well. Extensions implementing range canonical functions will need modification anyway because of the API change for range_serialize(); while at it, they might want to do something similar to what's been done here in the in-core canonical functions. Discussion: https://postgr.es/m/3284599.1671075185@sss.pgh.pa.us
1 parent 75f4922 commit d35a1af

12 files changed

+289
-66
lines changed

src/backend/utils/adt/multirangetypes.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ multirange_in(PG_FUNCTION_ARGS)
120120
char *input_str = PG_GETARG_CSTRING(0);
121121
Oid mltrngtypoid = PG_GETARG_OID(1);
122122
Oid typmod = PG_GETARG_INT32(2);
123+
Node *escontext = fcinfo->context;
123124
TypeCacheEntry *rangetyp;
124125
int32 ranges_seen = 0;
125126
int32 range_count = 0;
@@ -133,6 +134,7 @@ multirange_in(PG_FUNCTION_ARGS)
133134
const char *range_str_begin = NULL;
134135
int32 range_str_len;
135136
char *range_str;
137+
Datum range_datum;
136138

137139
cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_input);
138140
rangetyp = cache->typcache->rngtype;
@@ -144,7 +146,7 @@ multirange_in(PG_FUNCTION_ARGS)
144146
if (*ptr == '{')
145147
ptr++;
146148
else
147-
ereport(ERROR,
149+
ereturn(escontext, (Datum) 0,
148150
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
149151
errmsg("malformed multirange literal: \"%s\"",
150152
input_str),
@@ -157,7 +159,7 @@ multirange_in(PG_FUNCTION_ARGS)
157159
char ch = *ptr;
158160

159161
if (ch == '\0')
160-
ereport(ERROR,
162+
ereturn(escontext, (Datum) 0,
161163
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
162164
errmsg("malformed multirange literal: \"%s\"",
163165
input_str),
@@ -186,7 +188,7 @@ multirange_in(PG_FUNCTION_ARGS)
186188
parse_state = MULTIRANGE_AFTER_RANGE;
187189
}
188190
else
189-
ereport(ERROR,
191+
ereturn(escontext, (Datum) 0,
190192
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
191193
errmsg("malformed multirange literal: \"%s\"",
192194
input_str),
@@ -204,10 +206,14 @@ multirange_in(PG_FUNCTION_ARGS)
204206
repalloc(ranges, range_capacity * sizeof(RangeType *));
205207
}
206208
ranges_seen++;
207-
range = DatumGetRangeTypeP(InputFunctionCall(&cache->typioproc,
208-
range_str,
209-
cache->typioparam,
210-
typmod));
209+
if (!InputFunctionCallSafe(&cache->typioproc,
210+
range_str,
211+
cache->typioparam,
212+
typmod,
213+
escontext,
214+
&range_datum))
215+
PG_RETURN_NULL();
216+
range = DatumGetRangeTypeP(range_datum);
211217
if (!RangeIsEmpty(range))
212218
ranges[range_count++] = range;
213219
parse_state = MULTIRANGE_AFTER_RANGE;
@@ -256,7 +262,7 @@ multirange_in(PG_FUNCTION_ARGS)
256262
else if (ch == '}')
257263
parse_state = MULTIRANGE_FINISHED;
258264
else
259-
ereport(ERROR,
265+
ereturn(escontext, (Datum) 0,
260266
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
261267
errmsg("malformed multirange literal: \"%s\"",
262268
input_str),
@@ -280,7 +286,7 @@ multirange_in(PG_FUNCTION_ARGS)
280286
ptr++;
281287

282288
if (*ptr != '\0')
283-
ereport(ERROR,
289+
ereturn(escontext, (Datum) 0,
284290
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
285291
errmsg("malformed multirange literal: \"%s\"",
286292
input_str),
@@ -807,7 +813,7 @@ multirange_get_union_range(TypeCacheEntry *rangetyp,
807813
multirange_get_bounds(rangetyp, mr, 0, &lower, &tmp);
808814
multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1, &tmp, &upper);
809815

810-
return make_range(rangetyp, &lower, &upper, false);
816+
return make_range(rangetyp, &lower, &upper, false, NULL);
811817
}
812818

813819

@@ -2696,7 +2702,8 @@ range_merge_from_multirange(PG_FUNCTION_ARGS)
26962702
multirange_get_bounds(typcache->rngtype, mr, mr->rangeCount - 1,
26972703
&lastLower, &lastUpper);
26982704

2699-
result = make_range(typcache->rngtype, &firstLower, &lastUpper, false);
2705+
result = make_range(typcache->rngtype, &firstLower, &lastUpper,
2706+
false, NULL);
27002707
}
27012708

27022709
PG_RETURN_RANGE_P(result);

src/backend/utils/adt/multirangetypes_selfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ multirangesel(PG_FUNCTION_ARGS)
221221
upper.val = ((Const *) other)->constvalue;
222222
upper.infinite = false;
223223
upper.lower = false;
224-
constrange = range_serialize(typcache->rngtype, &lower, &upper, false);
224+
constrange = range_serialize(typcache->rngtype, &lower, &upper,
225+
false, NULL);
225226
constmultirange = make_multirange(typcache->type_id, typcache->rngtype,
226227
1, &constrange);
227228
}

0 commit comments

Comments
 (0)