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

Commit 653aa60

Browse files
committed
Provide an error cursor for "can't subscript" error messages.
Commit c7aba7c didn't add this, but after more fooling with the feature I feel that it'd be useful. To make this possible, refactor getSubscriptingRoutines() so that the caller is responsible for throwing any error. (In clauses.c, I just chose to make the most conservative assumption rather than throwing an error. We don't expect failures there anyway really, so the code space for an error message would be a poor investment.)
1 parent d2a2808 commit 653aa60

File tree

5 files changed

+21
-7
lines changed

5 files changed

+21
-7
lines changed

src/backend/executor/execExpr.c

+8
Original file line numberDiff line numberDiff line change
@@ -2536,6 +2536,14 @@ ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref,
25362536

25372537
/* Look up the subscripting support methods */
25382538
sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
2539+
if (!sbsroutines)
2540+
ereport(ERROR,
2541+
(errcode(ERRCODE_DATATYPE_MISMATCH),
2542+
errmsg("cannot subscript type %s because it does not support subscripting",
2543+
format_type_be(sbsref->refcontainertype)),
2544+
state->parent ?
2545+
executor_errposition(state->parent->state,
2546+
exprLocation((Node *) sbsref)) : 0));
25392547

25402548
/* Allocate sbsrefstate, with enough space for per-subscript arrays too */
25412549
sbsrefstate = palloc0(MAXALIGN(sizeof(SubscriptingRefState)) +

src/backend/optimizer/util/clauses.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ contain_nonstrict_functions_walker(Node *node, void *context)
848848
return true;
849849
/* Otherwise we must look up the subscripting support methods */
850850
sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
851-
if (!sbsroutines->fetch_strict)
851+
if (!(sbsroutines && sbsroutines->fetch_strict))
852852
return true;
853853
/* else fall through to check args */
854854
}
@@ -1144,7 +1144,8 @@ contain_leaked_vars_walker(Node *node, void *context)
11441144
/* Consult the subscripting support method info */
11451145
sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype,
11461146
NULL);
1147-
if (!(sbsref->refassgnexpr != NULL ?
1147+
if (!sbsroutines ||
1148+
!(sbsref->refassgnexpr != NULL ?
11481149
sbsroutines->store_leakproof :
11491150
sbsroutines->fetch_leakproof))
11501151
{

src/backend/parser/parse_node.c

+6
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,12 @@ transformContainerSubscripts(ParseState *pstate,
271271
* functions and typelem.
272272
*/
273273
sbsroutines = getSubscriptingRoutines(containerType, &elementType);
274+
if (!sbsroutines)
275+
ereport(ERROR,
276+
(errcode(ERRCODE_DATATYPE_MISMATCH),
277+
errmsg("cannot subscript type %s because it does not support subscripting",
278+
format_type_be(containerType)),
279+
parser_errposition(pstate, exprLocation(containerBase))));
274280

275281
/*
276282
* Detect whether any of the indirection items are slice specifiers.

src/backend/utils/cache/lsyscache.c

+2-5
Original file line numberDiff line numberDiff line change
@@ -3031,7 +3031,7 @@ get_typsubscript(Oid typid, Oid *typelemp)
30313031
* getSubscriptingRoutines
30323032
*
30333033
* Given the type OID, fetch the type's subscripting methods struct.
3034-
* Fail if type is not subscriptable.
3034+
* Return NULL if type is not subscriptable.
30353035
*
30363036
* If typelemp isn't NULL, we also store the type's typelem value there.
30373037
* This saves some callers an extra catalog lookup.
@@ -3042,10 +3042,7 @@ getSubscriptingRoutines(Oid typid, Oid *typelemp)
30423042
RegProcedure typsubscript = get_typsubscript(typid, typelemp);
30433043

30443044
if (!OidIsValid(typsubscript))
3045-
ereport(ERROR,
3046-
(errcode(ERRCODE_DATATYPE_MISMATCH),
3047-
errmsg("cannot subscript type %s because it does not support subscripting",
3048-
format_type_be(typid))));
3045+
return NULL;
30493046

30503047
return (const struct SubscriptRoutines *)
30513048
DatumGetPointer(OidFunctionCall0(typsubscript));

src/test/regress/expected/arrays.out

+2
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ ERROR: array subscript in assignment must not be null
238238
-- Un-subscriptable type
239239
SELECT (now())[1];
240240
ERROR: cannot subscript type timestamp with time zone because it does not support subscripting
241+
LINE 1: SELECT (now())[1];
242+
^
241243
-- test slices with empty lower and/or upper index
242244
CREATE TEMP TABLE arrtest_s (
243245
a int2[],

0 commit comments

Comments
 (0)