git.postgresql.org Git - postgresql.git/commitdiff

git projects / postgresql.git / commitdiff
? search:
summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d2a2808)
Provide an error cursor for "can't subscript" error messages.
2020年12月11日 22:54:10 +0000 (17:54 -0500)
2020年12月11日 23:58:21 +0000 (18:58 -0500)
Commit c7aba7c14 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.)


diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 0134ecc261e1345a1673140a06819466aa84cae6..5c3210a9ccaddf8d0c8d4db9cdba7ced1599c1b4 100644 (file)
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2536,6 +2536,14 @@ ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref,
/* Look up the subscripting support methods */
sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
+ if (!sbsroutines)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("cannot subscript type %s because it does not support subscripting",
+ format_type_be(sbsref->refcontainertype)),
+ state->parent ?
+ executor_errposition(state->parent->state,
+ exprLocation((Node *) sbsref)) : 0));
/* Allocate sbsrefstate, with enough space for per-subscript arrays too */
sbsrefstate = palloc0(MAXALIGN(sizeof(SubscriptingRefState)) +
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index e3a81a7a02a51e897cda7e96c73797eb0b119705..8f5cbf99f43e01c0b9ea26490dc0ad8d58f84d14 100644 (file)
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -848,7 +848,7 @@ contain_nonstrict_functions_walker(Node *node, void *context)
return true;
/* Otherwise we must look up the subscripting support methods */
sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
- if (!sbsroutines->fetch_strict)
+ if (!(sbsroutines && sbsroutines->fetch_strict))
return true;
/* else fall through to check args */
}
@@ -1144,7 +1144,8 @@ contain_leaked_vars_walker(Node *node, void *context)
/* Consult the subscripting support method info */
sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype,
NULL);
- if (!(sbsref->refassgnexpr != NULL ?
+ if (!sbsroutines ||
+ !(sbsref->refassgnexpr != NULL ?
sbsroutines->store_leakproof :
sbsroutines->fetch_leakproof))
{
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index e90f6c9d0106b60873f77b42dd9118bc1572bf30..3e20dfff2e250dc04abbb6163c67d818e3ed5682 100644 (file)
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -271,6 +271,12 @@ transformContainerSubscripts(ParseState *pstate,
* functions and typelem.
*/
sbsroutines = getSubscriptingRoutines(containerType, &elementType);
+ if (!sbsroutines)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("cannot subscript type %s because it does not support subscripting",
+ format_type_be(containerType)),
+ parser_errposition(pstate, exprLocation(containerBase))));
/*
* Detect whether any of the indirection items are slice specifiers.
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 7dd4945446223248fdb913388437b928b7b9d82b..204bcd03c0b3b0709a999e4a286492226dc59b86 100644 (file)
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -3031,7 +3031,7 @@ get_typsubscript(Oid typid, Oid *typelemp)
* getSubscriptingRoutines
*
* Given the type OID, fetch the type's subscripting methods struct.
- * Fail if type is not subscriptable.
+ * Return NULL if type is not subscriptable.
*
* If typelemp isn't NULL, we also store the type's typelem value there.
* This saves some callers an extra catalog lookup.
@@ -3042,10 +3042,7 @@ getSubscriptingRoutines(Oid typid, Oid *typelemp)
RegProcedure typsubscript = get_typsubscript(typid, typelemp);
if (!OidIsValid(typsubscript))
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("cannot subscript type %s because it does not support subscripting",
- format_type_be(typid))));
+ return NULL;
return (const struct SubscriptRoutines *)
DatumGetPointer(OidFunctionCall0(typsubscript));
diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out
index 0254fac801178b6b117c880457d0344457a0008b..8bc7721e7d5db9c0ad7785c08116f53351a8558b 100644 (file)
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -238,6 +238,8 @@ ERROR: array subscript in assignment must not be null
-- Un-subscriptable type
SELECT (now())[1];
ERROR: cannot subscript type timestamp with time zone because it does not support subscripting
+LINE 1: SELECT (now())[1];
+ ^
-- test slices with empty lower and/or upper index
CREATE TEMP TABLE arrtest_s (
a int2[],
This is the main PostgreSQL git repository.
RSS Atom

AltStyle によって変換されたページ (->オリジナル) /