mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
Tweak FOR UPDATE/SHARE error message wording (again)
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.
This commit is contained in:
parent
765ad89be3
commit
c359a1b082
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user