Thanks to visit codestin.com
Credit goes to github.com

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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 3 additions & 2 deletions
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

Lines changed: 6 additions & 0 deletions
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

Lines changed: 2 additions & 5 deletions
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

Lines changed: 2 additions & 0 deletions
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)