Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 653aa60

Browse filesBrowse 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
Copy full SHA for 653aa60

File tree

Expand file treeCollapse file tree

5 files changed

+21
-7
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+21
-7
lines changed

‎src/backend/executor/execExpr.c

Copy file name to clipboardExpand all lines: src/backend/executor/execExpr.c
+8Lines 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

Copy file name to clipboardExpand all lines: src/backend/optimizer/util/clauses.c
+3-2Lines 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

Copy file name to clipboardExpand all lines: src/backend/parser/parse_node.c
+6Lines 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

Copy file name to clipboardExpand all lines: src/backend/utils/cache/lsyscache.c
+2-5Lines 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

Copy file name to clipboardExpand all lines: src/test/regress/expected/arrays.out
+2Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.