1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-15 19:21:59 +03:00

Fix crash in error report of invalid tuple lock

My tweak of these error messages in commit c359a1b082 contained the
thinko that a query would always have rowMarks set for a query
containing a locking clause.  Not so: when declaring a cursor, for
instance, rowMarks isn't set at the point we're checking, so we'd be
dereferencing a NULL pointer.

The fix is to pass the lock strength to the function raising the error,
instead of trying to reverse-engineer it.  The result not only is more
robust, but it also seems cleaner overall.

Per report from Robert Haas.
This commit is contained in:
Alvaro Herrera
2013-08-02 12:49:03 -04:00
parent 05ee328d66
commit 88c556680c
9 changed files with 29 additions and 18 deletions

View File

@ -2243,7 +2243,7 @@ LCS_asString(LockClauseStrength strength)
* exported so planner can check again after rewriting, query pullup, etc
*/
void
CheckSelectLocking(Query *qry)
CheckSelectLocking(Query *qry, LockClauseStrength strength)
{
if (qry->setOperations)
ereport(ERROR,
@ -2251,56 +2251,49 @@ CheckSelectLocking(Query *qry)
/*------
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))));
LCS_asString(strength))));
if (qry->distinctClause != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
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))));
LCS_asString(strength))));
if (qry->groupClause != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
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))));
LCS_asString(strength))));
if (qry->havingQual != NULL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
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))));
LCS_asString(strength))));
if (qry->hasAggs)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
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))));
LCS_asString(strength))));
if (qry->hasWindowFuncs)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
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))));
LCS_asString(strength))));
if (expression_returns_set((Node *) qry->targetList))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/*------
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))));
LCS_asString(strength))));
}
/*
@ -2321,7 +2314,7 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
Index i;
LockingClause *allrels;
CheckSelectLocking(qry);
CheckSelectLocking(qry, lc->strength);
/* make a clause we can pass down to subqueries to select all rels */
allrels = makeNode(LockingClause);