]> granicus.if.org Git - postgresql/commitdiff
Tweak FOR UPDATE/SHARE error message wording (again)
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 23 Jul 2013 18:03:09 +0000 (14:03 -0400)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 23 Jul 2013 18:03:09 +0000 (14:03 -0400)
In commit 0ac5ad5134 I changed some error messages from "FOR
UPDATE/SHARE" to a rather long gobbledygook which nobody liked.  Then,
in commit cb9b66d31 I changed them again, but the alternative chosen
there was deemed suboptimal by Peter Eisentraut, who in message
1373937980.20441.8.camel@vanquo.pezone.net proposed an alternative
involving a dynamically-constructed string based on the actual locking
strength specified in the SQL command.  This patch implements that
suggestion.

src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/plan/planner.c
src/backend/parser/analyze.c
src/include/parser/analyze.h

index 839ed9dde4049a7bff81d6909776f0ba3e4550a9..8efb94b44d448f9016cb80af7eb4e639feccc004 100644 (file)
@@ -26,6 +26,7 @@
 #include "optimizer/prep.h"
 #include "optimizer/restrictinfo.h"
 #include "optimizer/var.h"
+#include "parser/analyze.h"
 #include "rewrite/rewriteManip.h"
 #include "utils/lsyscache.h"
 
@@ -883,7 +884,10 @@ make_outerjoininfo(PlannerInfo *root,
                        (jointype == JOIN_FULL && bms_is_member(rc->rti, left_rels)))
                        ereport(ERROR,
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                        errmsg("row-level locks cannot be applied to the nullable side of an outer join")));
+                                        /*------
+                                         translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                        errmsg("%s cannot be applied to the nullable side of an outer join",
+                                                       LCS_asString(rc->strength))));
        }
 
        sjinfo->syn_lefthand = left_rels;
index 01e2fa32a3cb8c4568522602bfb0fc1195d22d75..9ff8050080f2d54f61f6e331edc3f805e76c8cd3 100644 (file)
@@ -1107,7 +1107,11 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
                if (parse->rowMarks)
                        ereport(ERROR,
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                        errmsg("row-level locks are not allowed with UNION/INTERSECT/EXCEPT")));
+                                        /*------
+                                          translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                        errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
+                                                       LCS_asString(((RowMarkClause *)
+                                                                                 linitial(parse->rowMarks))->strength))));
 
                /*
                 * Calculate pathkeys that represent result ordering requirements
index 16ff23443c5900c6f587b3595914af6757a7ce50..39036fbc868d6ce9571dc1fe29564caa0eb4d01d 100644 (file)
@@ -1221,7 +1221,11 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
        if (stmt->lockingClause)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("SELECT FOR UPDATE/SHARE cannot be applied to VALUES")));
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("%s cannot be applied to VALUES",
+                                               LCS_asString(((LockingClause *)
+                                                                         linitial(stmt->lockingClause))->strength))));
 
        qry->rtable = pstate->p_rtable;
        qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
@@ -1312,7 +1316,11 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
        if (lockingClause)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("SELECT FOR UPDATE/SHARE is not allowed with UNION/INTERSECT/EXCEPT")));
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
+                                               LCS_asString(((LockingClause *)
+                                                                         linitial(lockingClause))->strength))));
 
        /* Process the WITH clause independently of all else */
        if (withClause)
@@ -1506,7 +1514,11 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
        if (stmt->lockingClause)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("SELECT FOR UPDATE/SHARE is not allowed with UNION/INTERSECT/EXCEPT")));
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
+                                               LCS_asString(((LockingClause *)
+                                                                         linitial(stmt->lockingClause))->strength))));
 
        /*
         * If an internal node of a set-op tree has ORDER BY, LIMIT, FOR UPDATE,
@@ -2063,21 +2075,33 @@ transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
        if (result->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("DECLARE CURSOR WITH HOLD ... FOR UPDATE/SHARE is not supported"),
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
+                                               LCS_asString(((RowMarkClause *)
+                                                                         linitial(result->rowMarks))->strength)),
                                 errdetail("Holdable cursors must be READ ONLY.")));
 
        /* FOR UPDATE and SCROLL are not compatible */
        if (result->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-               errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
+                                               LCS_asString(((RowMarkClause *)
+                                                                         linitial(result->rowMarks))->strength)),
                                 errdetail("Scrollable cursors must be READ ONLY.")));
 
        /* FOR UPDATE and INSENSITIVE are not compatible */
        if (result->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("DECLARE INSENSITIVE CURSOR ... FOR UPDATE/SHARE is not supported"),
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("DECLARE INSENSITIVE CURSOR ... %s is not supported",
+                                               LCS_asString(((RowMarkClause *)
+                                                                         linitial(result->rowMarks))->strength)),
                                 errdetail("Insensitive cursors must be READ ONLY.")));
 
        /* We won't need the raw querytree any more */
@@ -2196,6 +2220,23 @@ transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
 }
 
 
+char *
+LCS_asString(LockClauseStrength strength)
+{
+       switch (strength)
+       {
+               case LCS_FORKEYSHARE:
+                       return "FOR KEY SHARE";
+               case LCS_FORSHARE:
+                       return "FOR SHARE";
+               case LCS_FORNOKEYUPDATE:
+                       return "FOR NO KEY UPDATE";
+               case LCS_FORUPDATE:
+                       return "FOR UPDATE";
+       }
+       return "FOR some";      /* shouldn't happen */
+}
+
 /*
  * Check for features that are not supported with FOR [KEY] UPDATE/SHARE.
  *
@@ -2207,31 +2248,59 @@ CheckSelectLocking(Query *qry)
        if (qry->setOperations)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("row-level locks are not allowed with UNION/INTERSECT/EXCEPT")));
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
+                                               LCS_asString(((RowMarkClause *)
+                                                                         linitial(qry->rowMarks))->strength))));
        if (qry->distinctClause != NIL)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                       errmsg("row-level locks are not allowed with DISTINCT clause")));
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("%s is not allowed with DISTINCT clause",
+                                               LCS_asString(((RowMarkClause *)
+                                                                         linitial(qry->rowMarks))->strength))));
        if (qry->groupClause != NIL)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                       errmsg("row-level locks are not allowed with GROUP BY clause")));
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("%s is not allowed with GROUP BY clause",
+                                               LCS_asString(((RowMarkClause *)
+                                                                         linitial(qry->rowMarks))->strength))));
        if (qry->havingQual != NULL)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                         errmsg("row-level locks are not allowed with HAVING clause")));
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("%s is not allowed with HAVING clause",
+                                               LCS_asString(((RowMarkClause *)
+                                                                         linitial(qry->rowMarks))->strength))));
        if (qry->hasAggs)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-               errmsg("row-level locks are not allowed with aggregate functions")));
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("%s is not allowed with aggregate functions",
+                                               LCS_asString(((RowMarkClause *)
+                                                                         linitial(qry->rowMarks))->strength))));
        if (qry->hasWindowFuncs)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                  errmsg("row-level locks are not allowed with window functions")));
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("%s is not allowed with window functions",
+                                               LCS_asString(((RowMarkClause *)
+                                                                         linitial(qry->rowMarks))->strength))));
        if (expression_returns_set((Node *) qry->targetList))
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("row-level locks are not allowed with set-returning functions in the target list")));
+                                /*------
+                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                errmsg("%s is not allowed with set-returning functions in the target list",
+                                               LCS_asString(((RowMarkClause *)
+                                                                         linitial(qry->rowMarks))->strength))));
 }
 
 /*
@@ -2307,7 +2376,10 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
                        if (thisrel->catalogname || thisrel->schemaname)
                                ereport(ERROR,
                                                (errcode(ERRCODE_SYNTAX_ERROR),
-                                                errmsg("row-level locks must specify unqualified relation names"),
+                                                /*------
+                                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                                errmsg("%s must specify unqualified relation names",
+                                                               LCS_asString(lc->strength)),
                                                 parser_errposition(pstate, thisrel->location)));
 
                        i = 0;
@@ -2337,25 +2409,37 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
                                                case RTE_JOIN:
                                                        ereport(ERROR,
                                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                                                        errmsg("row-level locks cannot be applied to a join"),
+                                                                        /*------
+                                                                          translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                                                        errmsg("%s cannot be applied to a join",
+                                                                                       LCS_asString(lc->strength)),
                                                         parser_errposition(pstate, thisrel->location)));
                                                        break;
                                                case RTE_FUNCTION:
                                                        ereport(ERROR,
                                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                                                        errmsg("row-level locks cannot be applied to a function"),
+                                                                        /*------
+                                                                          translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                                                        errmsg("%s cannot be applied to a function",
+                                                                                       LCS_asString(lc->strength)),
                                                         parser_errposition(pstate, thisrel->location)));
                                                        break;
                                                case RTE_VALUES:
                                                        ereport(ERROR,
                                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                                                        errmsg("row-level locks cannot be applied to VALUES"),
+                                                                        /*------
+                                                                          translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                                                        errmsg("%s cannot be applied to VALUES",
+                                                                                       LCS_asString(lc->strength)),
                                                         parser_errposition(pstate, thisrel->location)));
                                                        break;
                                                case RTE_CTE:
                                                        ereport(ERROR,
                                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                                                        errmsg("row-level locks cannot be applied to a WITH query"),
+                                                                        /*------
+                                                                          translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                                                        errmsg("%s cannot be applied to a WITH query",
+                                                                                       LCS_asString(lc->strength)),
                                                         parser_errposition(pstate, thisrel->location)));
                                                        break;
                                                default:
@@ -2369,8 +2453,11 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
                        if (rt == NULL)
                                ereport(ERROR,
                                                (errcode(ERRCODE_UNDEFINED_TABLE),
-                                                errmsg("relation \"%s\" in row-level lock clause not found in FROM clause",
-                                                               thisrel->relname),
+                                                /*------
+                                                  translator: %s is a SQL row locking clause such as FOR UPDATE */
+                                                errmsg("relation \"%s\" in %s clause not found in FROM clause",
+                                                               thisrel->relname,
+                                                               LCS_asString(lc->strength)),
                                                 parser_errposition(pstate, thisrel->location)));
                }
        }
index 2f988d402190762145ac1e059c88a447ce593677..b24b205e45866c716fe90932d3ff0a317a9ffa75 100644 (file)
@@ -36,6 +36,7 @@ extern Query *transformStmt(ParseState *pstate, Node *parseTree);
 
 extern bool analyze_requires_snapshot(Node *parseTree);
 
+extern char *LCS_asString(LockClauseStrength strength);
 extern void CheckSelectLocking(Query *qry);
 extern void applyLockingClause(Query *qry, Index rtindex,
                                   LockClauseStrength strength, bool noWait, bool pushedDown);