Skip to content

Commit 986085a

Browse files
committed
Improve the representation of FOR UPDATE/FOR SHARE so that we can
support both FOR UPDATE and FOR SHARE in one command, as well as both NOWAIT and normal WAIT behavior. The more general code is actually simpler and cleaner.
1 parent 931bfc9 commit 986085a

29 files changed

+321
-246
lines changed

doc/src/sgml/ref/select.sgml

+20-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/select.sgml,v 1.90 2005/11/01 21:09:51 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/select.sgml,v 1.91 2006/04/30 18:30:38 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -30,7 +30,7 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="parameter">expression</replac
3030
[ ORDER BY <replaceable class="parameter">expression</replaceable> [ ASC | DESC | USING <replaceable class="parameter">operator</replaceable> ] [, ...] ]
3131
[ LIMIT { <replaceable class="parameter">count</replaceable> | ALL } ]
3232
[ OFFSET <replaceable class="parameter">start</replaceable> ]
33-
[ FOR { UPDATE | SHARE } [ OF <replaceable class="parameter">table_name</replaceable> [, ...] ] [ NOWAIT ] ]
33+
[ FOR { UPDATE | SHARE } [ OF <replaceable class="parameter">table_name</replaceable> [, ...] ] [ NOWAIT ] [...] ]
3434

3535
where <replaceable class="parameter">from_item</replaceable> can be one of:
3636

@@ -142,8 +142,8 @@ where <replaceable class="parameter">from_item</replaceable> can be one of:
142142

143143
<listitem>
144144
<para>
145-
If the <literal>FOR UPDATE</literal> or <literal>FOR SHARE</literal>
146-
clause is specified, the
145+
If <literal>FOR UPDATE</literal> or <literal>FOR SHARE</literal>
146+
is specified, the
147147
<command>SELECT</command> statement locks the selected rows
148148
against concurrent updates. (See <xref linkend="sql-for-update-share"
149149
endterm="sql-for-update-share-title"> below.)
@@ -852,19 +852,27 @@ FOR SHARE [ OF <replaceable class="parameter">table_name</replaceable> [, ...] ]
852852
from performing <command>SELECT FOR SHARE</command>.
853853
</para>
854854

855-
<para>
856-
It is currently not allowed for a single <command>SELECT</command>
857-
statement to include both <literal>FOR UPDATE</literal> and
858-
<literal>FOR SHARE</literal>, nor can different parts of the statement use
859-
both <literal>NOWAIT</> and normal waiting mode.
860-
</para>
861-
862855
<para>
863856
If specific tables are named in <literal>FOR UPDATE</literal>
864857
or <literal>FOR SHARE</literal>,
865858
then only rows coming from those tables are locked; any other
866859
tables used in the <command>SELECT</command> are simply read as
867-
usual.
860+
usual. A <literal>FOR UPDATE</literal> or <literal>FOR SHARE</literal>
861+
clause without a table list affects all tables used in the command.
862+
If <literal>FOR UPDATE</literal> or <literal>FOR SHARE</literal> is
863+
applied to a view or sub-query, it affects all tables used in
864+
the view or sub-query.
865+
</para>
866+
867+
<para>
868+
Multiple <literal>FOR UPDATE</literal> and <literal>FOR SHARE</literal>
869+
clauses can be written if it is necessary to specify different locking
870+
behavior for different tables. If the same table is mentioned (or
871+
implicitly affected) by both <literal>FOR UPDATE</literal> and
872+
<literal>FOR SHARE</literal> clauses, then it is processed as
873+
<literal>FOR UPDATE</literal>. Similarly, a table is processed
874+
as <literal>NOWAIT</> if that is specified in any of the clauses
875+
affecting it.
868876
</para>
869877

870878
<para>

doc/src/sgml/ref/select_into.sgml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/select_into.sgml,v 1.36 2005/08/01 20:31:04 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/select_into.sgml,v 1.37 2006/04/30 18:30:38 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -31,7 +31,7 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replac
3131
[ ORDER BY <replaceable class="PARAMETER">expression</replaceable> [ ASC | DESC | USING <replaceable class="PARAMETER">operator</replaceable> ] [, ...] ]
3232
[ LIMIT { <replaceable class="PARAMETER">count</replaceable> | ALL } ]
3333
[ OFFSET <replaceable class="PARAMETER">start</replaceable> ]
34-
[ FOR { UPDATE | SHARE } [ OF <replaceable class="parameter">table_name</replaceable> [, ...] ] [ NOWAIT ] ]
34+
[ FOR { UPDATE | SHARE } [ OF <replaceable class="parameter">table_name</replaceable> [, ...] ] [ NOWAIT ] [...] ]
3535
</synopsis>
3636
</refsynopsisdiv>
3737

doc/src/sgml/sql.sgml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/sql.sgml,v 1.39 2006/03/10 19:10:49 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/sql.sgml,v 1.40 2006/04/30 18:30:38 tgl Exp $ -->
22

33
<chapter id="sql-intro">
44
<title>SQL</title>
@@ -863,7 +863,7 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replac
863863
[ ORDER BY <replaceable class="PARAMETER">expression</replaceable> [ ASC | DESC | USING <replaceable class="PARAMETER">operator</replaceable> ] [, ...] ]
864864
[ LIMIT { <replaceable class="PARAMETER">count</replaceable> | ALL } ]
865865
[ OFFSET <replaceable class="PARAMETER">start</replaceable> ]
866-
[ FOR { UPDATE | SHARE } [ OF <replaceable class="parameter">table_name</replaceable> [, ...] ] [ NOWAIT ] ]
866+
[ FOR { UPDATE | SHARE } [ OF <replaceable class="parameter">table_name</replaceable> [, ...] ] [ NOWAIT ] [...] ]
867867
</synopsis>
868868
</para>
869869

src/backend/executor/execMain.c

+18-25
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.269 2006/03/05 15:58:25 momjian Exp $
29+
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.270 2006/04/30 18:30:38 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -452,6 +452,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
452452
Relation intoRelationDesc;
453453
bool do_select_into;
454454
TupleDesc tupType;
455+
ListCell *l;
455456

456457
/*
457458
* Do permissions checks. It's sufficient to examine the query's top
@@ -486,7 +487,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
486487
* parseTree->resultRelations identifies them all
487488
*/
488489
ResultRelInfo *resultRelInfo;
489-
ListCell *l;
490490

491491
numResultRelations = list_length(resultRelations);
492492
resultRelInfos = (ResultRelInfo *)
@@ -549,26 +549,21 @@ InitPlan(QueryDesc *queryDesc, int eflags)
549549
* Have to lock relations selected FOR UPDATE/FOR SHARE
550550
*/
551551
estate->es_rowMarks = NIL;
552-
estate->es_forUpdate = parseTree->forUpdate;
553-
estate->es_rowNoWait = parseTree->rowNoWait;
554-
if (parseTree->rowMarks != NIL)
552+
foreach(l, parseTree->rowMarks)
555553
{
556-
ListCell *l;
557-
558-
foreach(l, parseTree->rowMarks)
559-
{
560-
Index rti = lfirst_int(l);
561-
Oid relid = getrelid(rti, rangeTable);
562-
Relation relation;
563-
ExecRowMark *erm;
564-
565-
relation = heap_open(relid, RowShareLock);
566-
erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
567-
erm->relation = relation;
568-
erm->rti = rti;
569-
snprintf(erm->resname, sizeof(erm->resname), "ctid%u", rti);
570-
estate->es_rowMarks = lappend(estate->es_rowMarks, erm);
571-
}
554+
RowMarkClause *rc = (RowMarkClause *) lfirst(l);
555+
Oid relid = getrelid(rc->rti, rangeTable);
556+
Relation relation;
557+
ExecRowMark *erm;
558+
559+
relation = heap_open(relid, RowShareLock);
560+
erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
561+
erm->relation = relation;
562+
erm->rti = rc->rti;
563+
erm->forUpdate = rc->forUpdate;
564+
erm->noWait = rc->noWait;
565+
snprintf(erm->resname, sizeof(erm->resname), "ctid%u", rc->rti);
566+
estate->es_rowMarks = lappend(estate->es_rowMarks, erm);
572567
}
573568

574569
/*
@@ -1222,15 +1217,15 @@ lnext: ;
12221217

12231218
tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
12241219

1225-
if (estate->es_forUpdate)
1220+
if (erm->forUpdate)
12261221
lockmode = LockTupleExclusive;
12271222
else
12281223
lockmode = LockTupleShared;
12291224

12301225
test = heap_lock_tuple(erm->relation, &tuple, &buffer,
12311226
&update_ctid, &update_xmax,
12321227
estate->es_snapshot->curcid,
1233-
lockmode, estate->es_rowNoWait);
1228+
lockmode, erm->noWait);
12341229
ReleaseBuffer(buffer);
12351230
switch (test)
12361231
{
@@ -2258,8 +2253,6 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
22582253
epqstate->es_param_exec_vals = (ParamExecData *)
22592254
palloc0(estate->es_topPlan->nParamExec * sizeof(ParamExecData));
22602255
epqstate->es_rowMarks = estate->es_rowMarks;
2261-
epqstate->es_forUpdate = estate->es_forUpdate;
2262-
epqstate->es_rowNoWait = estate->es_rowNoWait;
22632256
epqstate->es_instrument = estate->es_instrument;
22642257
epqstate->es_select_into = estate->es_select_into;
22652258
epqstate->es_into_oids = estate->es_into_oids;

src/backend/executor/execUtils.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.133 2006/03/05 15:58:26 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.134 2006/04/30 18:30:38 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -204,8 +204,6 @@ CreateExecutorState(void)
204204
estate->es_processed = 0;
205205
estate->es_lastoid = InvalidOid;
206206
estate->es_rowMarks = NIL;
207-
estate->es_forUpdate = false;
208-
estate->es_rowNoWait = false;
209207

210208
estate->es_instrument = false;
211209
estate->es_select_into = false;

src/backend/nodes/copyfuncs.c

+18-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.334 2006/04/22 01:25:58 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.335 2006/04/30 18:30:38 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1409,6 +1409,18 @@ _copyGroupClause(GroupClause *from)
14091409
return newnode;
14101410
}
14111411

1412+
static RowMarkClause *
1413+
_copyRowMarkClause(RowMarkClause *from)
1414+
{
1415+
RowMarkClause *newnode = makeNode(RowMarkClause);
1416+
1417+
COPY_SCALAR_FIELD(rti);
1418+
COPY_SCALAR_FIELD(forUpdate);
1419+
COPY_SCALAR_FIELD(noWait);
1420+
1421+
return newnode;
1422+
}
1423+
14121424
static A_Expr *
14131425
_copyAExpr(A_Expr *from)
14141426
{
@@ -1650,7 +1662,7 @@ _copyLockingClause(LockingClause *from)
16501662

16511663
COPY_NODE_FIELD(lockedRels);
16521664
COPY_SCALAR_FIELD(forUpdate);
1653-
COPY_SCALAR_FIELD(nowait);
1665+
COPY_SCALAR_FIELD(noWait);
16541666

16551667
return newnode;
16561668
}
@@ -1673,16 +1685,14 @@ _copyQuery(Query *from)
16731685
COPY_SCALAR_FIELD(hasSubLinks);
16741686
COPY_NODE_FIELD(rtable);
16751687
COPY_NODE_FIELD(jointree);
1676-
COPY_NODE_FIELD(rowMarks);
1677-
COPY_SCALAR_FIELD(forUpdate);
1678-
COPY_SCALAR_FIELD(rowNoWait);
16791688
COPY_NODE_FIELD(targetList);
16801689
COPY_NODE_FIELD(groupClause);
16811690
COPY_NODE_FIELD(havingQual);
16821691
COPY_NODE_FIELD(distinctClause);
16831692
COPY_NODE_FIELD(sortClause);
16841693
COPY_NODE_FIELD(limitOffset);
16851694
COPY_NODE_FIELD(limitCount);
1695+
COPY_NODE_FIELD(rowMarks);
16861696
COPY_NODE_FIELD(setOperations);
16871697
COPY_NODE_FIELD(resultRelations);
16881698

@@ -3284,6 +3294,9 @@ copyObject(void *from)
32843294
case T_GroupClause:
32853295
retval = _copyGroupClause(from);
32863296
break;
3297+
case T_RowMarkClause:
3298+
retval = _copyRowMarkClause(from);
3299+
break;
32873300
case T_FkConstraint:
32883301
retval = _copyFkConstraint(from);
32893302
break;

src/backend/nodes/equalfuncs.c

+16-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* Portions Copyright (c) 1994, Regents of the University of California
1919
*
2020
* IDENTIFICATION
21-
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.270 2006/04/22 01:25:59 tgl Exp $
21+
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.271 2006/04/30 18:30:38 tgl Exp $
2222
*
2323
*-------------------------------------------------------------------------
2424
*/
@@ -665,16 +665,14 @@ _equalQuery(Query *a, Query *b)
665665
COMPARE_SCALAR_FIELD(hasSubLinks);
666666
COMPARE_NODE_FIELD(rtable);
667667
COMPARE_NODE_FIELD(jointree);
668-
COMPARE_NODE_FIELD(rowMarks);
669-
COMPARE_SCALAR_FIELD(forUpdate);
670-
COMPARE_SCALAR_FIELD(rowNoWait);
671668
COMPARE_NODE_FIELD(targetList);
672669
COMPARE_NODE_FIELD(groupClause);
673670
COMPARE_NODE_FIELD(havingQual);
674671
COMPARE_NODE_FIELD(distinctClause);
675672
COMPARE_NODE_FIELD(sortClause);
676673
COMPARE_NODE_FIELD(limitOffset);
677674
COMPARE_NODE_FIELD(limitCount);
675+
COMPARE_NODE_FIELD(rowMarks);
678676
COMPARE_NODE_FIELD(setOperations);
679677
COMPARE_NODE_FIELD(resultRelations);
680678

@@ -1688,7 +1686,7 @@ _equalLockingClause(LockingClause *a, LockingClause *b)
16881686
{
16891687
COMPARE_NODE_FIELD(lockedRels);
16901688
COMPARE_SCALAR_FIELD(forUpdate);
1691-
COMPARE_SCALAR_FIELD(nowait);
1689+
COMPARE_SCALAR_FIELD(noWait);
16921690

16931691
return true;
16941692
}
@@ -1723,6 +1721,16 @@ _equalSortClause(SortClause *a, SortClause *b)
17231721
return true;
17241722
}
17251723

1724+
static bool
1725+
_equalRowMarkClause(RowMarkClause *a, RowMarkClause *b)
1726+
{
1727+
COMPARE_SCALAR_FIELD(rti);
1728+
COMPARE_SCALAR_FIELD(forUpdate);
1729+
COMPARE_SCALAR_FIELD(noWait);
1730+
1731+
return true;
1732+
}
1733+
17261734
static bool
17271735
_equalFkConstraint(FkConstraint *a, FkConstraint *b)
17281736
{
@@ -2297,6 +2305,9 @@ equal(void *a, void *b)
22972305
/* GroupClause is equivalent to SortClause */
22982306
retval = _equalSortClause(a, b);
22992307
break;
2308+
case T_RowMarkClause:
2309+
retval = _equalRowMarkClause(a, b);
2310+
break;
23002311
case T_FkConstraint:
23012312
retval = _equalFkConstraint(a, b);
23022313
break;

src/backend/nodes/outfuncs.c

+16-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.273 2006/04/22 01:25:59 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.274 2006/04/30 18:30:39 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1418,7 +1418,7 @@ _outLockingClause(StringInfo str, LockingClause *node)
14181418

14191419
WRITE_NODE_FIELD(lockedRels);
14201420
WRITE_BOOL_FIELD(forUpdate);
1421-
WRITE_BOOL_FIELD(nowait);
1421+
WRITE_BOOL_FIELD(noWait);
14221422
}
14231423

14241424
static void
@@ -1514,16 +1514,14 @@ _outQuery(StringInfo str, Query *node)
15141514
WRITE_BOOL_FIELD(hasSubLinks);
15151515
WRITE_NODE_FIELD(rtable);
15161516
WRITE_NODE_FIELD(jointree);
1517-
WRITE_NODE_FIELD(rowMarks);
1518-
WRITE_BOOL_FIELD(forUpdate);
1519-
WRITE_BOOL_FIELD(rowNoWait);
15201517
WRITE_NODE_FIELD(targetList);
15211518
WRITE_NODE_FIELD(groupClause);
15221519
WRITE_NODE_FIELD(havingQual);
15231520
WRITE_NODE_FIELD(distinctClause);
15241521
WRITE_NODE_FIELD(sortClause);
15251522
WRITE_NODE_FIELD(limitOffset);
15261523
WRITE_NODE_FIELD(limitCount);
1524+
WRITE_NODE_FIELD(rowMarks);
15271525
WRITE_NODE_FIELD(setOperations);
15281526
WRITE_NODE_FIELD(resultRelations);
15291527
}
@@ -1546,6 +1544,16 @@ _outGroupClause(StringInfo str, GroupClause *node)
15461544
WRITE_OID_FIELD(sortop);
15471545
}
15481546

1547+
static void
1548+
_outRowMarkClause(StringInfo str, RowMarkClause *node)
1549+
{
1550+
WRITE_NODE_TYPE("ROWMARKCLAUSE");
1551+
1552+
WRITE_UINT_FIELD(rti);
1553+
WRITE_BOOL_FIELD(forUpdate);
1554+
WRITE_BOOL_FIELD(noWait);
1555+
}
1556+
15491557
static void
15501558
_outSetOperationStmt(StringInfo str, SetOperationStmt *node)
15511559
{
@@ -2113,6 +2121,9 @@ _outNode(StringInfo str, void *obj)
21132121
case T_GroupClause:
21142122
_outGroupClause(str, obj);
21152123
break;
2124+
case T_RowMarkClause:
2125+
_outRowMarkClause(str, obj);
2126+
break;
21162127
case T_SetOperationStmt:
21172128
_outSetOperationStmt(str, obj);
21182129
break;

0 commit comments

Comments
 (0)