On Fri, 2005-06-24 at 22:32 -0400, Bruce Momjian wrote:
> Are you working on a updated version of this?

I will work on new version during this week.

        Karel


> ---------------------------------------------------------------------------
> 
> Bruce Momjian wrote:
> > 
> > Uh, seems the code has drifted too much and now I can't apply this. 
> > Would you redo this against current CVS?  Thanks.
> > 
> > ---------------------------------------------------------------------------
> > 
> > Hans-Juergen Schoenig wrote:
> > > Folks,
> > > 
> > > We have implemented SELECT FOR UPDATE NOWAIT for PostgreSQL.
> > > The patch attached to this email contains all the required code 
> > > including ECPG updates and some documentation.
> > > It would be nice if this patch would be included in PostgreSQL 8.1
> > > 
> > >   Best regards,
> > > 
> > >           Ewald Geschwinde & Hans-Juergen Schoenig
> > > 
> > > --
> > > Cybertec Geschwinde u Schoenig GmbH.
> > > Schoengrabern 134, A-2020 Hollabrunn, Austria
> > > Tel: +43/660/816 40 77
> > > www.cybertec.at, www.postgresql.at
> > 
> > [ text/x-patch is unsupported, treating like TEXT/PLAIN ]
> > 
> > > diff -r -c postgresql-8.0.0rc2.orig/doc/src/sgml/ref/select.sgml 
> > > postgresql-8.0.0rc2/doc/src/sgml/ref/select.sgml
> > > *** postgresql-8.0.0rc2.orig/doc/src/sgml/ref/select.sgml Sat Nov 27 
> > > 22:27:07 2004
> > > --- postgresql-8.0.0rc2/doc/src/sgml/ref/select.sgml      Mon Dec 27 
> > > 10:57:05 2004
> > > ***************
> > > *** 30,36 ****
> > >       [ ORDER BY <replaceable class="parameter">expression</replaceable> 
> > > [ ASC | DESC | USING <replaceable 
> > > class="parameter">operator</replaceable> ] [, ...] ]
> > >       [ LIMIT { <replaceable class="parameter">count</replaceable> | ALL 
> > > } ]
> > >       [ OFFSET <replaceable class="parameter">start</replaceable> ]
> > > !     [ FOR UPDATE [ OF <replaceable 
> > > class="parameter">table_name</replaceable> [, ...] ] ]
> > >   
> > >   where <replaceable class="parameter">from_item</replaceable> can be one 
> > > of:
> > >   
> > > --- 30,36 ----
> > >       [ ORDER BY <replaceable class="parameter">expression</replaceable> 
> > > [ ASC | DESC | USING <replaceable 
> > > class="parameter">operator</replaceable> ] [, ...] ]
> > >       [ LIMIT { <replaceable class="parameter">count</replaceable> | ALL 
> > > } ]
> > >       [ OFFSET <replaceable class="parameter">start</replaceable> ]
> > > !     [ FOR UPDATE [ OF <replaceable 
> > > class="parameter">table_name</replaceable> [, ...] ] [NOWAIT] ]
> > >   
> > >   where <replaceable class="parameter">from_item</replaceable> can be one 
> > > of:
> > >   
> > > ***************
> > > *** 772,778 ****
> > >      <para>
> > >       The <literal>FOR UPDATE</literal> clause has this form:
> > >   <synopsis>
> > > ! FOR UPDATE [ OF <replaceable class="parameter">table_name</replaceable> 
> > > [, ...] ]
> > >   </synopsis>
> > >      </para>
> > >   
> > > --- 772,778 ----
> > >      <para>
> > >       The <literal>FOR UPDATE</literal> clause has this form:
> > >   <synopsis>
> > > ! FOR UPDATE [ OF <replaceable class="parameter">table_name</replaceable> 
> > > [, ...] ] [NOWAIT]
> > >   </synopsis>
> > >      </para>
> > >   
> > > ***************
> > > *** 789,796 ****
> > >       has already locked a selected row or rows, <command>SELECT FOR
> > >       UPDATE</command> will wait for the other transaction to complete,
> > >       and will then lock and return the updated row (or no row, if the
> > > !     row was deleted).  For further discussion see <xref
> > > !     linkend="mvcc">.
> > >      </para>
> > >   
> > >      <para>
> > > --- 789,802 ----
> > >       has already locked a selected row or rows, <command>SELECT FOR
> > >       UPDATE</command> will wait for the other transaction to complete,
> > >       and will then lock and return the updated row (or no row, if the
> > > !     row was deleted).  If the current transaction is not supposed to
> > > !     wait on other transactions to commit the NOWAIT option can be
> > > !     used.  If <command>SELECT FOR UPDATE NOWAIT</command> finds out
> > > !     that somebody else is holding a lock an error will be thrown.
> > > !     This will only happen in case of row level locks - if somebody
> > > !     holds a table lock <command>SELECT FOR UPDATE NOWAIT</command>
> > > !     will still wait for concurrent transactions.  For further 
> > > !     discussion see <xref linkend="mvcc">.
> > >      </para>
> > >   
> > >      <para>
> > > diff -r -c postgresql-8.0.0rc2.orig/doc/src/sgml/sql.sgml 
> > > postgresql-8.0.0rc2/doc/src/sgml/sql.sgml
> > > *** postgresql-8.0.0rc2.orig/doc/src/sgml/sql.sgml        Mon Nov 15 
> > > 07:32:14 2004
> > > --- postgresql-8.0.0rc2/doc/src/sgml/sql.sgml     Mon Dec 27 10:57:05 2004
> > > ***************
> > > *** 866,872 ****
> > >       [ ORDER BY <replaceable class="PARAMETER">expression</replaceable> 
> > > [ ASC | DESC | USING <replaceable 
> > > class="PARAMETER">operator</replaceable> ] [, ...] ]
> > >       [ LIMIT { <replaceable class="PARAMETER">count</replaceable> | ALL 
> > > } ]
> > >       [ OFFSET <replaceable class="PARAMETER">start</replaceable> ]
> > > !     [ FOR UPDATE [ OF <replaceable 
> > > class="PARAMETER">class_name</replaceable> [, ...] ] ]
> > >        </synopsis>
> > >       </para>
> > >   
> > > --- 866,872 ----
> > >       [ ORDER BY <replaceable class="PARAMETER">expression</replaceable> 
> > > [ ASC | DESC | USING <replaceable 
> > > class="PARAMETER">operator</replaceable> ] [, ...] ]
> > >       [ LIMIT { <replaceable class="PARAMETER">count</replaceable> | ALL 
> > > } ]
> > >       [ OFFSET <replaceable class="PARAMETER">start</replaceable> ]
> > > !     [ FOR UPDATE [ OF <replaceable 
> > > class="PARAMETER">class_name</replaceable> [, ...] ] [NOWAIT] ]
> > >        </synopsis>
> > >       </para>
> > >   
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/access/heap/heapam.c 
> > > postgresql-8.0.0rc2/src/backend/access/heap/heapam.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/access/heap/heapam.c     Sun Nov 
> > > 14 03:04:12 2004
> > > --- postgresql-8.0.0rc2/src/backend/access/heap/heapam.c  Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 16,21 ****
> > > --- 16,22 ----
> > >    *              relation_openrv - open any relation specified by a 
> > > RangeVar
> > >    *              relation_openr  - open a system relation by name
> > >    *              relation_close  - close any relation
> > > +  *              conditional_relation_open - open with option not to wait
> > >    *              heap_open               - open a heap relation by 
> > > relation OID
> > >    *              heap_openrv             - open a heap relation 
> > > specified by a RangeVar
> > >    *              heap_openr              - open a system heap relation 
> > > by name
> > > ***************
> > > *** 1828,1834 ****
> > >    */
> > >   int
> > >   heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer,
> > > !                                  CommandId cid)
> > >   {
> > >           TransactionId xid = GetCurrentTransactionId();
> > >           ItemPointer tid = &(tuple->t_self);
> > > --- 1829,1835 ----
> > >    */
> > >   int
> > >   heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer,
> > > !                                  CommandId cid, bool nowait)
> > >   {
> > >           TransactionId xid = GetCurrentTransactionId();
> > >           ItemPointer tid = &(tuple->t_self);
> > > ***************
> > > *** 1858,1866 ****
> > >           {
> > >                   TransactionId xwait = 
> > > HeapTupleHeaderGetXmax(tuple->t_data);
> > >   
> > > -                 /* sleep until concurrent transaction ends */
> > >                   LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
> > > !                 XactLockTableWait(xwait);
> > >   
> > >                   LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
> > >                   if (!TransactionIdDidCommit(xwait))
> > > --- 1859,1881 ----
> > >           {
> > >                   TransactionId xwait = 
> > > HeapTupleHeaderGetXmax(tuple->t_data);
> > >   
> > >                   LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
> > > ! 
> > > !                 if (nowait)
> > > !                 {
> > > !                         /* rather error than sleep until concurrent 
> > > transaction ends */ 
> > > !                         if (!ConditionalXactLockTableWait(xwait))
> > > !                         {
> > > !                                 ReleaseBuffer(*buffer);
> > > !                                 ereport(ERROR,
> > > !                                         
> > > (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> > > !                                          errmsg("data in table \"%s\" 
> > > was modify by concurrent trasaction.", 
> > > !                                                  
> > > RelationGetRelationName(relation))));
> > > !                         }
> > > !                 }
> > > !                 else
> > > !                         /* sleep until concurrent transaction ends */
> > > !                         XactLockTableWait(xwait);
> > >   
> > >                   LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
> > >                   if (!TransactionIdDidCommit(xwait))
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/commands/trigger.c 
> > > postgresql-8.0.0rc2/src/backend/commands/trigger.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/commands/trigger.c       Tue Dec 
> > >  7 00:57:17 2004
> > > --- postgresql-8.0.0rc2/src/backend/commands/trigger.c    Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 1574,1580 ****
> > >                   *newSlot = NULL;
> > >                   tuple.t_self = *tid;
> > >   ltrmark:;
> > > !                 test = heap_mark4update(relation, &tuple, &buffer, cid);
> > >                   switch (test)
> > >                   {
> > >                           case HeapTupleSelfUpdated:
> > > --- 1574,1580 ----
> > >                   *newSlot = NULL;
> > >                   tuple.t_self = *tid;
> > >   ltrmark:;
> > > !                 test = heap_mark4update(relation, &tuple, &buffer, cid, 
> > > estate->es_nowait);
> > >                   switch (test)
> > >                   {
> > >                           case HeapTupleSelfUpdated:
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/executor/execMain.c 
> > > postgresql-8.0.0rc2/src/backend/executor/execMain.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/executor/execMain.c      Thu Oct 
> > >  7 20:38:49 2004
> > > --- postgresql-8.0.0rc2/src/backend/executor/execMain.c   Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 558,563 ****
> > > --- 558,564 ----
> > >           /*
> > >            * Have to lock relations selected for update
> > >            */
> > > +         estate->es_nowait = parseTree->nowait;
> > >           estate->es_rowMark = NIL;
> > >           if (parseTree->rowMarks != NIL)
> > >           {
> > > ***************
> > > *** 1133,1139 ****
> > >   
> > >                                           tuple.t_self = *((ItemPointer) 
> > > DatumGetPointer(datum));
> > >                                           test = 
> > > heap_mark4update(erm->relation, &tuple, &buffer,
> > > !                                                                         
> > >                 estate->es_snapshot->curcid);
> > >                                           ReleaseBuffer(buffer);
> > >                                           switch (test)
> > >                                           {
> > > --- 1134,1140 ----
> > >   
> > >                                           tuple.t_self = *((ItemPointer) 
> > > DatumGetPointer(datum));
> > >                                           test = 
> > > heap_mark4update(erm->relation, &tuple, &buffer,
> > > !                                                         
> > > estate->es_snapshot->curcid, estate->es_nowait);
> > >                                           ReleaseBuffer(buffer);
> > >                                           switch (test)
> > >                                           {
> > > ***************
> > > *** 2082,2087 ****
> > > --- 2083,2089 ----
> > >           epqstate->es_instrument = estate->es_instrument;
> > >           epqstate->es_select_into = estate->es_select_into;
> > >           epqstate->es_into_oids = estate->es_into_oids;
> > > +         epqstate->es_nowait = estate->es_nowait;
> > >           epqstate->es_topPlan = estate->es_topPlan;
> > >   
> > >           /*
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/executor/execUtils.c 
> > > postgresql-8.0.0rc2/src/backend/executor/execUtils.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/executor/execUtils.c     Fri Oct 
> > >  1 01:21:23 2004
> > > --- postgresql-8.0.0rc2/src/backend/executor/execUtils.c  Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 203,209 ****
> > >           estate->es_instrument = false;
> > >           estate->es_select_into = false;
> > >           estate->es_into_oids = false;
> > > ! 
> > >           estate->es_exprcontexts = NIL;
> > >   
> > >           estate->es_per_tuple_exprcontext = NULL;
> > > --- 203,210 ----
> > >           estate->es_instrument = false;
> > >           estate->es_select_into = false;
> > >           estate->es_into_oids = false;
> > > !         estate->es_nowait = false;
> > > !         
> > >           estate->es_exprcontexts = NIL;
> > >   
> > >           estate->es_per_tuple_exprcontext = NULL;
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/nodes/copyfuncs.c 
> > > postgresql-8.0.0rc2/src/backend/nodes/copyfuncs.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/nodes/copyfuncs.c        Sun Dec 
> > > 12 00:26:33 2004
> > > --- postgresql-8.0.0rc2/src/backend/nodes/copyfuncs.c     Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 1426,1431 ****
> > > --- 1426,1442 ----
> > >           return newnode;
> > >   }
> > >   
> > > + static ForUpdate *
> > > + _copyForUpdate(ForUpdate *from)
> > > + {
> > > +         ForUpdate *newnode = makeNode(ForUpdate);
> > > + 
> > > +         COPY_NODE_FIELD(update_list);
> > > +         COPY_SCALAR_FIELD(nowait);
> > > + 
> > > +         return newnode;
> > > + }
> > > + 
> > >   static RangeSubselect *
> > >   _copyRangeSubselect(RangeSubselect *from)
> > >   {
> > > ***************
> > > *** 1537,1542 ****
> > > --- 1548,1554 ----
> > >           COPY_NODE_FIELD(groupClause);
> > >           COPY_NODE_FIELD(havingQual);
> > >           COPY_NODE_FIELD(distinctClause);
> > > +         COPY_SCALAR_FIELD(nowait);
> > >           COPY_NODE_FIELD(sortClause);
> > >           COPY_NODE_FIELD(limitOffset);
> > >           COPY_NODE_FIELD(limitCount);
> > > ***************
> > > *** 1611,1617 ****
> > >           COPY_NODE_FIELD(sortClause);
> > >           COPY_NODE_FIELD(limitOffset);
> > >           COPY_NODE_FIELD(limitCount);
> > > !         COPY_NODE_FIELD(forUpdate);
> > >           COPY_SCALAR_FIELD(op);
> > >           COPY_SCALAR_FIELD(all);
> > >           COPY_NODE_FIELD(larg);
> > > --- 1623,1629 ----
> > >           COPY_NODE_FIELD(sortClause);
> > >           COPY_NODE_FIELD(limitOffset);
> > >           COPY_NODE_FIELD(limitCount);
> > > !         COPY_NODE_FIELD(forupdateClause);
> > >           COPY_SCALAR_FIELD(op);
> > >           COPY_SCALAR_FIELD(all);
> > >           COPY_NODE_FIELD(larg);
> > > ***************
> > > *** 3065,3070 ****
> > > --- 3077,3085 ----
> > >                   case T_SortBy:
> > >                           retval = _copySortBy(from);
> > >                           break;
> > > +                 case T_ForUpdate:
> > > +                         retval = _copyForUpdate(from);
> > > +                         break;
> > >                   case T_RangeSubselect:
> > >                           retval = _copyRangeSubselect(from);
> > >                           break;
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/nodes/equalfuncs.c 
> > > postgresql-8.0.0rc2/src/backend/nodes/equalfuncs.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/nodes/equalfuncs.c       Sun Dec 
> > > 12 00:26:33 2004
> > > --- postgresql-8.0.0rc2/src/backend/nodes/equalfuncs.c    Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 656,661 ****
> > > --- 656,662 ----
> > >           COMPARE_NODE_FIELD(groupClause);
> > >           COMPARE_NODE_FIELD(havingQual);
> > >           COMPARE_NODE_FIELD(distinctClause);
> > > +         COMPARE_SCALAR_FIELD(nowait);
> > >           COMPARE_NODE_FIELD(sortClause);
> > >           COMPARE_NODE_FIELD(limitOffset);
> > >           COMPARE_NODE_FIELD(limitCount);
> > > ***************
> > > *** 719,725 ****
> > >           COMPARE_NODE_FIELD(sortClause);
> > >           COMPARE_NODE_FIELD(limitOffset);
> > >           COMPARE_NODE_FIELD(limitCount);
> > > !         COMPARE_NODE_FIELD(forUpdate);
> > >           COMPARE_SCALAR_FIELD(op);
> > >           COMPARE_SCALAR_FIELD(all);
> > >           COMPARE_NODE_FIELD(larg);
> > > --- 720,726 ----
> > >           COMPARE_NODE_FIELD(sortClause);
> > >           COMPARE_NODE_FIELD(limitOffset);
> > >           COMPARE_NODE_FIELD(limitCount);
> > > !         COMPARE_NODE_FIELD(forupdateClause);
> > >           COMPARE_SCALAR_FIELD(op);
> > >           COMPARE_SCALAR_FIELD(all);
> > >           COMPARE_NODE_FIELD(larg);
> > > ***************
> > > *** 1577,1582 ****
> > > --- 1578,1592 ----
> > >   }
> > >   
> > >   static bool
> > > + _equalForUpdate(ForUpdate *a, ForUpdate *b)
> > > + {
> > > +         COMPARE_SCALAR_FIELD(nowait);
> > > +         COMPARE_NODE_FIELD(update_list);
> > > + 
> > > +         return true;
> > > + }
> > > + 
> > > + static bool
> > >   _equalRangeSubselect(RangeSubselect *a, RangeSubselect *b)
> > >   {
> > >           COMPARE_NODE_FIELD(subquery);
> > > ***************
> > > *** 2202,2207 ****
> > > --- 2212,2220 ----
> > >                   case T_SortBy:
> > >                           retval = _equalSortBy(a, b);
> > >                           break;
> > > +                 case T_ForUpdate:
> > > +                         retval = _equalForUpdate(a, b);
> > > +                         break;
> > >                   case T_RangeSubselect:
> > >                           retval = _equalRangeSubselect(a, b);
> > >                           break;
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/nodes/outfuncs.c 
> > > postgresql-8.0.0rc2/src/backend/nodes/outfuncs.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/nodes/outfuncs.c Sun Dec 12 
> > > 00:26:33 2004
> > > --- postgresql-8.0.0rc2/src/backend/nodes/outfuncs.c      Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 1202,1208 ****
> > >           WRITE_NODE_FIELD(sortClause);
> > >           WRITE_NODE_FIELD(limitOffset);
> > >           WRITE_NODE_FIELD(limitCount);
> > > !         WRITE_NODE_FIELD(forUpdate);
> > >           WRITE_ENUM_FIELD(op, SetOperation);
> > >           WRITE_BOOL_FIELD(all);
> > >           WRITE_NODE_FIELD(larg);
> > > --- 1202,1208 ----
> > >           WRITE_NODE_FIELD(sortClause);
> > >           WRITE_NODE_FIELD(limitOffset);
> > >           WRITE_NODE_FIELD(limitCount);
> > > !         WRITE_NODE_FIELD(forupdateClause);
> > >           WRITE_ENUM_FIELD(op, SetOperation);
> > >           WRITE_BOOL_FIELD(all);
> > >           WRITE_NODE_FIELD(larg);
> > > ***************
> > > *** 1323,1328 ****
> > > --- 1323,1329 ----
> > >           WRITE_NODE_FIELD(groupClause);
> > >           WRITE_NODE_FIELD(havingQual);
> > >           WRITE_NODE_FIELD(distinctClause);
> > > +         WRITE_BOOL_FIELD(nowait);
> > >           WRITE_NODE_FIELD(sortClause);
> > >           WRITE_NODE_FIELD(limitOffset);
> > >           WRITE_NODE_FIELD(limitCount);
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/nodes/readfuncs.c 
> > > postgresql-8.0.0rc2/src/backend/nodes/readfuncs.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/nodes/readfuncs.c        Sun Dec 
> > > 12 00:26:34 2004
> > > --- postgresql-8.0.0rc2/src/backend/nodes/readfuncs.c     Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 149,154 ****
> > > --- 149,155 ----
> > >           READ_NODE_FIELD(groupClause);
> > >           READ_NODE_FIELD(havingQual);
> > >           READ_NODE_FIELD(distinctClause);
> > > +         READ_BOOL_FIELD(nowait);
> > >           READ_NODE_FIELD(sortClause);
> > >           READ_NODE_FIELD(limitOffset);
> > >           READ_NODE_FIELD(limitCount);
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/parser/analyze.c 
> > > postgresql-8.0.0rc2/src/backend/parser/analyze.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/parser/analyze.c Wed Nov 17 
> > > 00:34:26 2004
> > > --- postgresql-8.0.0rc2/src/backend/parser/analyze.c      Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 135,141 ****
> > >                                              bool isAddConstraint);
> > >   static void applyColumnNames(List *dst, List *src);
> > >   static List *getSetColTypes(ParseState *pstate, Node *node);
> > > ! static void transformForUpdate(Query *qry, List *forUpdate);
> > >   static void transformConstraintAttrs(List *constraintList);
> > >   static void transformColumnType(ParseState *pstate, ColumnDef *column);
> > >   static void release_pstate_resources(ParseState *pstate);
> > > --- 135,141 ----
> > >                                              bool isAddConstraint);
> > >   static void applyColumnNames(List *dst, List *src);
> > >   static List *getSetColTypes(ParseState *pstate, Node *node);
> > > ! static void transformForUpdate(Query *qry, Node *forupdateClause);
> > >   static void transformConstraintAttrs(List *constraintList);
> > >   static void transformColumnType(ParseState *pstate, ColumnDef *column);
> > >   static void release_pstate_resources(ParseState *pstate);
> > > ***************
> > > *** 1804,1810 ****
> > >           qry->commandType = CMD_SELECT;
> > >   
> > >           /* make FOR UPDATE clause available to addRangeTableEntry */
> > > !         pstate->p_forUpdate = stmt->forUpdate;
> > >   
> > >           /* process the FROM clause */
> > >           transformFromClause(pstate, stmt->fromClause);
> > > --- 1804,1810 ----
> > >           qry->commandType = CMD_SELECT;
> > >   
> > >           /* make FOR UPDATE clause available to addRangeTableEntry */
> > > !         pstate->p_forUpdate = stmt->forupdateClause ? ((ForUpdate 
> > > *)stmt->forupdateClause)->update_list : NIL;
> > >   
> > >           /* process the FROM clause */
> > >           transformFromClause(pstate, stmt->fromClause);
> > > ***************
> > > *** 1864,1871 ****
> > >           if (pstate->p_hasAggs || qry->groupClause)
> > >                   parseCheckAggregates(pstate, qry);
> > >   
> > > !         if (stmt->forUpdate != NIL)
> > > !                 transformForUpdate(qry, stmt->forUpdate);
> > >   
> > >           return qry;
> > >   }
> > > --- 1864,1871 ----
> > >           if (pstate->p_hasAggs || qry->groupClause)
> > >                   parseCheckAggregates(pstate, qry);
> > >   
> > > !         if (stmt->forupdateClause)
> > > !                 transformForUpdate(qry, stmt->forupdateClause);
> > >   
> > >           return qry;
> > >   }
> > > ***************
> > > *** 1893,1899 ****
> > >           List       *sortClause;
> > >           Node       *limitOffset;
> > >           Node       *limitCount;
> > > !         List       *forUpdate;
> > >           Node       *node;
> > >           ListCell   *left_tlist,
> > >                              *dtlist;
> > > --- 1893,1899 ----
> > >           List       *sortClause;
> > >           Node       *limitOffset;
> > >           Node       *limitCount;
> > > !         Node       *forUpdate;
> > >           Node       *node;
> > >           ListCell   *left_tlist,
> > >                              *dtlist;
> > > ***************
> > > *** 1931,1942 ****
> > >           sortClause = stmt->sortClause;
> > >           limitOffset = stmt->limitOffset;
> > >           limitCount = stmt->limitCount;
> > > !         forUpdate = stmt->forUpdate;
> > >   
> > >           stmt->sortClause = NIL;
> > >           stmt->limitOffset = NULL;
> > >           stmt->limitCount = NULL;
> > > !         stmt->forUpdate = NIL;
> > >   
> > >           /* We don't support forUpdate with set ops at the moment. */
> > >           if (forUpdate)
> > > --- 1931,1942 ----
> > >           sortClause = stmt->sortClause;
> > >           limitOffset = stmt->limitOffset;
> > >           limitCount = stmt->limitCount;
> > > !         forUpdate = stmt->forupdateClause;
> > >   
> > >           stmt->sortClause = NIL;
> > >           stmt->limitOffset = NULL;
> > >           stmt->limitCount = NULL;
> > > !         stmt->forupdateClause = NULL;
> > >   
> > >           /* We don't support forUpdate with set ops at the moment. */
> > >           if (forUpdate)
> > > ***************
> > > *** 2080,2086 ****
> > >           if (pstate->p_hasAggs || qry->groupClause)
> > >                   parseCheckAggregates(pstate, qry);
> > >   
> > > !         if (forUpdate != NIL)
> > >                   transformForUpdate(qry, forUpdate);
> > >   
> > >           return qry;
> > > --- 2080,2086 ----
> > >           if (pstate->p_hasAggs || qry->groupClause)
> > >                   parseCheckAggregates(pstate, qry);
> > >   
> > > !         if (forUpdate)
> > >                   transformForUpdate(qry, forUpdate);
> > >   
> > >           return qry;
> > > ***************
> > > *** 2105,2111 ****
> > >                                   (errcode(ERRCODE_SYNTAX_ERROR),
> > >                                    errmsg("INTO is only allowed on first 
> > > SELECT of UNION/INTERSECT/EXCEPT")));
> > >           /* We don't support forUpdate with set ops at the moment. */
> > > !         if (stmt->forUpdate)
> > >                   ereport(ERROR,
> > >                                   (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> > >                                    errmsg("SELECT FOR UPDATE is not 
> > > allowed with UNION/INTERSECT/EXCEPT")));
> > > --- 2105,2111 ----
> > >                                   (errcode(ERRCODE_SYNTAX_ERROR),
> > >                                    errmsg("INTO is only allowed on first 
> > > SELECT of UNION/INTERSECT/EXCEPT")));
> > >           /* We don't support forUpdate with set ops at the moment. */
> > > !         if (stmt->forupdateClause)
> > >                   ereport(ERROR,
> > >                                   (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> > >                                    errmsg("SELECT FOR UPDATE is not 
> > > allowed with UNION/INTERSECT/EXCEPT")));
> > > ***************
> > > *** 2125,2131 ****
> > >           {
> > >                   Assert(stmt->larg != NULL && stmt->rarg != NULL);
> > >                   if (stmt->sortClause || stmt->limitOffset || 
> > > stmt->limitCount ||
> > > !                         stmt->forUpdate)
> > >                           isLeaf = true;
> > >                   else
> > >                           isLeaf = false;
> > > --- 2125,2131 ----
> > >           {
> > >                   Assert(stmt->larg != NULL && stmt->rarg != NULL);
> > >                   if (stmt->sortClause || stmt->limitOffset || 
> > > stmt->limitCount ||
> > > !                         stmt->forupdateClause)
> > >                           isLeaf = true;
> > >                   else
> > >                           isLeaf = false;
> > > ***************
> > > *** 2737,2752 ****
> > >    * in rewriteHandler.c.
> > >    */
> > >   static void
> > > ! transformForUpdate(Query *qry, List *forUpdate)
> > >   {
> > >           List       *rowMarks = qry->rowMarks;
> > >           ListCell   *l;
> > >           ListCell   *rt;
> > > !         Index           i;
> > >   
> > >           CheckSelectForUpdate(qry);
> > >   
> > > !         if (linitial(forUpdate) == NULL)
> > >           {
> > >                   /* all regular tables used in query */
> > >                   i = 0;
> > > --- 2737,2761 ----
> > >    * in rewriteHandler.c.
> > >    */
> > >   static void
> > > ! transformForUpdate(Query *qry, Node *forupdateClause)
> > >   {
> > >           List       *rowMarks = qry->rowMarks;
> > >           ListCell   *l;
> > >           ListCell   *rt;
> > > !         Index      i;
> > > !         ForUpdate  *fu = (ForUpdate *) forupdateClause;
> > > !         ForUpdate  empty;
> > > !         List       *update_list;
> > >   
> > >           CheckSelectForUpdate(qry);
> > >   
> > > !         update_list = fu->update_list;
> > > !         qry->nowait = fu->nowait;
> > > ! 
> > > !         memset(&empty, 0, sizeof(ForUpdate));
> > > !         empty.nowait = FALSE;
> > > !         
> > > !         if (linitial(update_list) == NULL)
> > >           {
> > >                   /* all regular tables used in query */
> > >                   i = 0;
> > > ***************
> > > *** 2768,2774 ****
> > >                                            * FOR UPDATE of subquery is 
> > > propagated to subquery's
> > >                                            * rels
> > >                                            */
> > > !                                         
> > > transformForUpdate(rte->subquery, list_make1(NULL));
> > >                                           break;
> > >                                   default:
> > >                                           /* ignore JOIN, SPECIAL, 
> > > FUNCTION RTEs */
> > > --- 2777,2785 ----
> > >                                            * FOR UPDATE of subquery is 
> > > propagated to subquery's
> > >                                            * rels
> > >                                            */
> > > !                                         empty.update_list = 
> > > list_make1(NULL);
> > > !                                         
> > > transformForUpdate(rte->subquery, (Node *) &empty);
> > > !                                         empty.update_list = NIL;
> > >                                           break;
> > >                                   default:
> > >                                           /* ignore JOIN, SPECIAL, 
> > > FUNCTION RTEs */
> > > ***************
> > > *** 2779,2785 ****
> > >           else
> > >           {
> > >                   /* just the named tables */
> > > !                 foreach(l, forUpdate)
> > >                   {
> > >                           char       *relname = strVal(lfirst(l));
> > >   
> > > --- 2790,2796 ----
> > >           else
> > >           {
> > >                   /* just the named tables */
> > > !                 foreach(l, update_list)
> > >                   {
> > >                           char       *relname = strVal(lfirst(l));
> > >   
> > > ***************
> > > *** 2804,2810 ****
> > >                                                            * FOR UPDATE 
> > > of subquery is propagated to
> > >                                                            * subquery's 
> > > rels
> > >                                                            */
> > > !                                                         
> > > transformForUpdate(rte->subquery, list_make1(NULL));
> > >                                                           break;
> > >                                                   case RTE_JOIN:
> > >                                                           ereport(ERROR,
> > > --- 2815,2823 ----
> > >                                                            * FOR UPDATE 
> > > of subquery is propagated to
> > >                                                            * subquery's 
> > > rels
> > >                                                            */
> > > !                                                         
> > > empty.update_list = list_make1(NULL);
> > > !                                                         
> > > transformForUpdate(rte->subquery, (Node *) &empty);
> > > !                                                         
> > > empty.update_list = NULL;
> > >                                                           break;
> > >                                                   case RTE_JOIN:
> > >                                                           ereport(ERROR,
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/parser/gram.y 
> > > postgresql-8.0.0rc2/src/backend/parser/gram.y
> > > *** postgresql-8.0.0rc2.orig/src/backend/parser/gram.y    Mon Nov  8 
> > > 05:02:20 2004
> > > --- postgresql-8.0.0rc2/src/backend/parser/gram.y Mon Dec 27 10:56:52 2004
> > > ***************
> > > *** 87,93 ****
> > >   static List *extractArgTypes(List *parameters);
> > >   static SelectStmt *findLeftmostSelect(SelectStmt *node);
> > >   static void insertSelectOptions(SelectStmt *stmt,
> > > !                                                                 List 
> > > *sortClause, List *forUpdate,
> > >                                                                   Node 
> > > *limitOffset, Node *limitCount);
> > >   static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node 
> > > *rarg);
> > >   static Node *doNegate(Node *n);
> > > --- 87,93 ----
> > >   static List *extractArgTypes(List *parameters);
> > >   static SelectStmt *findLeftmostSelect(SelectStmt *node);
> > >   static void insertSelectOptions(SelectStmt *stmt,
> > > !                                                                 List 
> > > *sortClause, Node *forUpdate,
> > >                                                                   Node 
> > > *limitOffset, Node *limitCount);
> > >   static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node 
> > > *rarg);
> > >   static Node *doNegate(Node *n);
> > > ***************
> > > *** 239,245 ****
> > >   %type <oncommit> OnCommitOption
> > >   %type <withoids> OptWithOids WithOidsAs
> > >   
> > > ! %type <list>    for_update_clause opt_for_update_clause update_list
> > >   %type <boolean> opt_all
> > >   
> > >   %type <node>    join_outer join_qual
> > > --- 239,247 ----
> > >   %type <oncommit> OnCommitOption
> > >   %type <withoids> OptWithOids WithOidsAs
> > >   
> > > ! %type <node>    for_update_clause opt_for_update_clause
> > > ! %type <list>    update_list
> > > ! 
> > >   %type <boolean> opt_all
> > >   
> > >   %type <node>    join_outer join_qual
> > > ***************
> > > *** 4801,4807 ****
> > >                           simple_select                                   
> > >         { $$ = $1; }
> > >                           | select_clause sort_clause
> > >                                   {
> > > !                                         insertSelectOptions((SelectStmt 
> > > *) $1, $2, NIL,
> > >                                                                           
> > >         NULL, NULL);
> > >                                           $$ = $1;
> > >                                   }
> > > --- 4803,4809 ----
> > >                           simple_select                                   
> > >         { $$ = $1; }
> > >                           | select_clause sort_clause
> > >                                   {
> > > !                                         insertSelectOptions((SelectStmt 
> > > *) $1, $2, NULL,
> > >                                                                           
> > >         NULL, NULL);
> > >                                           $$ = $1;
> > >                                   }
> > > ***************
> > > *** 4862,4867 ****
> > > --- 4864,4870 ----
> > >                                           n->whereClause = $6;
> > >                                           n->groupClause = $7;
> > >                                           n->havingClause = $8;
> > > +                                         n->forupdateClause = NULL;
> > >                                           $$ = (Node *)n;
> > >                                   }
> > >                           | select_clause UNION opt_all select_clause
> > > ***************
> > > *** 5053,5060 ****
> > >                   ;
> > >   
> > >   for_update_clause:
> > > !                         FOR UPDATE update_list                          
> > >         { $$ = $3; }
> > > !                         | FOR READ ONLY                                 
> > >                 { $$ = NULL; }
> > >                   ;
> > >   
> > >   opt_for_update_clause:
> > > --- 5056,5069 ----
> > >                   ;
> > >   
> > >   for_update_clause:
> > > !                         FOR UPDATE update_list opt_nowait       
> > > !                                 { 
> > > !                                         ForUpdate *n = 
> > > makeNode(ForUpdate);
> > > !                                         n->update_list = $3;
> > > !                                         n->nowait = $4;
> > > !                                         $$ = (Node *) n;
> > > !                                 }
> > > !                         | FOR READ ONLY                                 
> > >                 { $$ = NULL; }  
> > >                   ;
> > >   
> > >   opt_for_update_clause:
> > > ***************
> > > *** 8284,8290 ****
> > >    */
> > >   static void
> > >   insertSelectOptions(SelectStmt *stmt,
> > > !                                         List *sortClause, List 
> > > *forUpdate,
> > >                                           Node *limitOffset, Node 
> > > *limitCount)
> > >   {
> > >           /*
> > > --- 8293,8299 ----
> > >    */
> > >   static void
> > >   insertSelectOptions(SelectStmt *stmt,
> > > !                                         List *sortClause, Node 
> > > *forUpdate,
> > >                                           Node *limitOffset, Node 
> > > *limitCount)
> > >   {
> > >           /*
> > > ***************
> > > *** 8301,8311 ****
> > >           }
> > >           if (forUpdate)
> > >           {
> > > !                 if (stmt->forUpdate)
> > >                           ereport(ERROR,
> > >                                           (errcode(ERRCODE_SYNTAX_ERROR),
> > >                                            errmsg("multiple FOR UPDATE 
> > > clauses not allowed")));
> > > !                 stmt->forUpdate = forUpdate;
> > >           }
> > >           if (limitOffset)
> > >           {
> > > --- 8310,8320 ----
> > >           }
> > >           if (forUpdate)
> > >           {
> > > !                 if (stmt->forupdateClause)
> > >                           ereport(ERROR,
> > >                                           (errcode(ERRCODE_SYNTAX_ERROR),
> > >                                            errmsg("multiple FOR UPDATE 
> > > clauses not allowed")));
> > > !                 stmt->forupdateClause = forUpdate;
> > >           }
> > >           if (limitOffset)
> > >           {
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/parser/parse_type.c 
> > > postgresql-8.0.0rc2/src/backend/parser/parse_type.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/parser/parse_type.c      Wed Dec 
> > > 15 21:15:17 2004
> > > --- postgresql-8.0.0rc2/src/backend/parser/parse_type.c   Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 432,438 ****
> > >                   stmt->sortClause != NIL ||
> > >                   stmt->limitOffset != NULL ||
> > >                   stmt->limitCount != NULL ||
> > > !                 stmt->forUpdate != NIL ||
> > >                   stmt->op != SETOP_NONE)
> > >                   goto fail;
> > >           if (list_length(stmt->targetList) != 1)
> > > --- 432,438 ----
> > >                   stmt->sortClause != NIL ||
> > >                   stmt->limitOffset != NULL ||
> > >                   stmt->limitCount != NULL ||
> > > !                 stmt->forupdateClause != NULL ||
> > >                   stmt->op != SETOP_NONE)
> > >                   goto fail;
> > >           if (list_length(stmt->targetList) != 1)
> > > diff -r -c postgresql-8.0.0rc2.orig/src/backend/storage/lmgr/lmgr.c 
> > > postgresql-8.0.0rc2/src/backend/storage/lmgr/lmgr.c
> > > *** postgresql-8.0.0rc2.orig/src/backend/storage/lmgr/lmgr.c      Thu Sep 
> > > 16 18:58:33 2004
> > > --- postgresql-8.0.0rc2/src/backend/storage/lmgr/lmgr.c   Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 393,395 ****
> > > --- 393,435 ----
> > >           if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
> > >                   TransactionIdAbort(xid);
> > >   }
> > > + 
> > > + /*
> > > +  * As above, but only lock if we can get the lock without blocking.
> > > +  * Returns TRUE if the lock was acquired. 
> > > +  */
> > > + bool
> > > + ConditionalXactLockTableWait(TransactionId xid)
> > > + {
> > > +         LOCKTAG         tag;
> > > +         TransactionId myxid = GetTopTransactionId();
> > > + 
> > > +         for (;;)
> > > +         {
> > > +                 Assert(TransactionIdIsValid(xid));
> > > +                 Assert(!TransactionIdEquals(xid, myxid));
> > > + 
> > > +                 MemSet(&tag, 0, sizeof(tag));
> > > +                 tag.relId = XactLockTableId;
> > > +                 tag.dbId = InvalidOid;
> > > +                 tag.objId.xid = xid;
> > > + 
> > > +                 if (!LockAcquire(LockTableId, &tag, myxid, ShareLock, 
> > > true))
> > > +                         return FALSE;
> > > +                 LockRelease(LockTableId, &tag, myxid, ShareLock);
> > > + 
> > > +                 if (!TransactionIdIsInProgress(xid))
> > > +                         break;
> > > +                 xid = SubTransGetParent(xid);
> > > +         }
> > > + 
> > > +         /*
> > > +          * Transaction was committed/aborted/crashed - we have to update
> > > +          * pg_clog if transaction is still marked as running.
> > > +          */
> > > +         if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
> > > +                 TransactionIdAbort(xid);
> > > +         
> > > +         return TRUE;
> > > + }
> > > + 
> > > diff -r -c postgresql-8.0.0rc2.orig/src/bin/psql/sql_help.h 
> > > postgresql-8.0.0rc2/src/bin/psql/sql_help.h
> > > *** postgresql-8.0.0rc2.orig/src/bin/psql/sql_help.h      Tue Dec 21 
> > > 05:22:44 2004
> > > --- postgresql-8.0.0rc2/src/bin/psql/sql_help.h   Mon Dec 27 10:57:05 2004
> > > ***************
> > > *** 383,393 ****
> > >   
> > >       { "SELECT",
> > >         N_("retrieve rows from a table or view"),
> > > !       N_("SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]\n    
> > > * | expression [ AS output_name ] [, ...]\n    [ FROM from_item [, ...] 
> > > ]\n    [ WHERE condition ]\n    [ GROUP BY expression [, ...] ]\n    [ 
> > > HAVING condition [, ...] ]\n    [ { UNION | INTERSECT | EXCEPT } [ ALL ] 
> > > select ]\n    [ ORDER BY expression [ ASC | DESC | USING operator ] [, 
> > > ...] ]\n    [ LIMIT { count | ALL } ]\n    [ OFFSET start ]\n    [ FOR 
> > > UPDATE [ OF table_name [, ...] ] ]\n\nwhere from_item can be one of:\n\n  
> > >   [ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] 
> > > ]\n    ( select ) [ AS ] alias [ ( column_alias [, ...] ) ]\n    
> > > function_name ( [ argument [, ...] ] ) [ AS ] alias [ ( column_alias [, 
> > > ...] | column_definition [, ...] ) ]\n    function_name ( [ argument [, 
> > > ...] ] ) AS ( column_definition [, ...] )\n    from_item [ NATURAL ] 
> > > join_type from_item [ ON join_condition | USING ( join_column [, ...] ) 
> > > ]") },
> > >   
> > >       { "SELECT INTO",
> > >         N_("define a new table from the results of a query"),
> > > !       N_("SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]\n    
> > > * | expression [ AS output_name ] [, ...]\n    INTO [ TEMPORARY | TEMP ] 
> > > [ TABLE ] new_table\n    [ FROM from_item [, ...] ]\n    [ WHERE 
> > > condition ]\n    [ GROUP BY expression [, ...] ]\n    [ HAVING condition 
> > > [, ...] ]\n    [ { UNION | INTERSECT | EXCEPT } [ ALL ] select ]\n    [ 
> > > ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]\n    [ 
> > > LIMIT { count | ALL } ]\n    [ OFFSET start ]\n    [ FOR UPDATE [ OF 
> > > tablename [, ...] ] ]") },
> > >   
> > >       { "SET",
> > >         N_("change a run-time parameter"),
> > > --- 383,393 ----
> > >   
> > >       { "SELECT",
> > >         N_("retrieve rows from a table or view"),
> > > !       N_("SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]\n    
> > > * | expression [ AS output_name ] [, ...]\n    [ FROM from_item [, ...] 
> > > ]\n    [ WHERE condition ]\n    [ GROUP BY expression [, ...] ]\n    [ 
> > > HAVING condition [, ...] ]\n    [ { UNION | INTERSECT | EXCEPT } [ ALL ] 
> > > select ]\n    [ ORDER BY expression [ ASC | DESC | USING operator ] [, 
> > > ...] ]\n    [ LIMIT { count | ALL } ]\n    [ OFFSET start ]\n    [ FOR 
> > > UPDATE [ OF table_name [, ...] ] [NOWAIT] ]\n\nwhere from_item can be one 
> > > of:\n\n    [ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, 
> > > ...] ) ] ]\n    ( select ) [ AS ] alias [ ( column_alias [, ...] ) ]\n    
> > > function_name ( [ argument [, ...] ] ) [ AS ] alias [ ( column_alias [, 
> > > ...] | column_definition [, ...] ) ]\n    function_name ( [ argument [, 
> > > ...] ] ) AS ( column_definition [, ...] )\n    from_item [ NATURAL ] 
> > > join_type from_item [ ON join_condition | USING ( join_column [, ...] ) 
> > > ]") },
> > >   
> > >       { "SELECT INTO",
> > >         N_("define a new table from the results of a query"),
> > > !       N_("SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]\n    
> > > * | expression [ AS output_name ] [, ...]\n    INTO [ TEMPORARY | TEMP ] 
> > > [ TABLE ] new_table\n    [ FROM from_item [, ...] ]\n    [ WHERE 
> > > condition ]\n    [ GROUP BY expression [, ...] ]\n    [ HAVING condition 
> > > [, ...] ]\n    [ { UNION | INTERSECT | EXCEPT } [ ALL ] select ]\n    [ 
> > > ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]\n    [ 
> > > LIMIT { count | ALL } ]\n    [ OFFSET start ]\n    [ FOR UPDATE [ OF 
> > > tablename [, ...] ] [NOWAIT] ]") },
> > >   
> > >       { "SET",
> > >         N_("change a run-time parameter"),
> > > diff -r -c postgresql-8.0.0rc2.orig/src/include/access/heapam.h 
> > > postgresql-8.0.0rc2/src/include/access/heapam.h
> > > *** postgresql-8.0.0rc2.orig/src/include/access/heapam.h  Sun Aug 29 
> > > 07:06:55 2004
> > > --- postgresql-8.0.0rc2/src/include/access/heapam.h       Mon Dec 27 
> > > 10:57:05 2004
> > > ***************
> > > *** 164,170 ****
> > >   extern int heap_update(Relation relation, ItemPointer otid, HeapTuple 
> > > tup,
> > >                   ItemPointer ctid, CommandId cid, Snapshot crosscheck, 
> > > bool wait);
> > >   extern int heap_mark4update(Relation relation, HeapTuple tup,
> > > !                                  Buffer *userbuf, CommandId cid);
> > >   
> > >   extern Oid      simple_heap_insert(Relation relation, HeapTuple tup);
> > >   extern void simple_heap_delete(Relation relation, ItemPointer tid);
> > > --- 164,170 ----
> > >   extern int heap_update(Relation relation, ItemPointer otid, HeapTuple 
> > > tup,
> > >                   ItemPointer ctid, CommandId cid, Snapshot crosscheck, 
> > > bool wait);
> > >   extern int heap_mark4update(Relation relation, HeapTuple tup,
> > > !                                  Buffer *userbuf, CommandId cid, bool 
> > > nowait);
> > >   
> > >   extern Oid      simple_heap_insert(Relation relation, HeapTuple tup);
> > >   extern void simple_heap_delete(Relation relation, ItemPointer tid);
> > > diff -r -c postgresql-8.0.0rc2.orig/src/include/nodes/execnodes.h 
> > > postgresql-8.0.0rc2/src/include/nodes/execnodes.h
> > > *** postgresql-8.0.0rc2.orig/src/include/nodes/execnodes.h        Sun Dec 
> > > 12 00:26:49 2004
> > > --- postgresql-8.0.0rc2/src/include/nodes/execnodes.h     Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 308,313 ****
> > > --- 308,314 ----
> > >           bool            es_instrument;  /* true requests runtime 
> > > instrumentation */
> > >           bool            es_select_into; /* true if doing SELECT INTO */
> > >           bool            es_into_oids;   /* true to generate OIDs in 
> > > SELECT INTO */
> > > +         bool            es_nowait;      /* SELECT FOR UPDATE NOWAIT */
> > >   
> > >           List       *es_exprcontexts;    /* List of ExprContexts within 
> > > EState */
> > >   
> > > diff -r -c postgresql-8.0.0rc2.orig/src/include/nodes/nodes.h 
> > > postgresql-8.0.0rc2/src/include/nodes/nodes.h
> > > *** postgresql-8.0.0rc2.orig/src/include/nodes/nodes.h    Sun Dec 12 
> > > 00:26:49 2004
> > > --- postgresql-8.0.0rc2/src/include/nodes/nodes.h Mon Dec 27 10:56:52 2004
> > > ***************
> > > *** 302,307 ****
> > > --- 302,308 ----
> > >           T_CompositeTypeStmt,
> > >           T_InhRelation,
> > >           T_FunctionParameter,
> > > +         T_ForUpdate,
> > >   
> > >           /*
> > >            * TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see 
> > > fmgr.h)
> > > diff -r -c postgresql-8.0.0rc2.orig/src/include/nodes/parsenodes.h 
> > > postgresql-8.0.0rc2/src/include/nodes/parsenodes.h
> > > *** postgresql-8.0.0rc2.orig/src/include/nodes/parsenodes.h       Fri Nov 
> > >  5 20:16:38 2004
> > > --- postgresql-8.0.0rc2/src/include/nodes/parsenodes.h    Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 103,108 ****
> > > --- 103,110 ----
> > >   
> > >           List       *sortClause;         /* a list of SortClause's */
> > >   
> > > +         bool       nowait;              /* are we in NOWAIT mode? */
> > > + 
> > >           Node       *limitOffset;        /* # of result tuples to skip */
> > >           Node       *limitCount;         /* # of result tuples to return 
> > > */
> > >   
> > > ***************
> > > *** 422,427 ****
> > > --- 424,439 ----
> > >           Node       *arg;                        /* a (Value *) or a 
> > > (TypeName *) */
> > >   } DefElem;
> > >   
> > > + /*
> > > +  * ForUpdate -
> > > +  *       used in raw parsetrees output only
> > > +  */
> > > + typedef struct ForUpdate
> > > + {
> > > +         NodeTag         type;
> > > +         List            *update_list;   /* list of tables */
> > > +         bool            nowait;         /* NOWAIT option */
> > > + } ForUpdate;
> > >   
> > >   
> > > /****************************************************************************
> > >    *      Nodes for a Query tree
> > > ***************
> > > *** 686,692 ****
> > >           List       *sortClause;         /* sort clause (a list of 
> > > SortBy's) */
> > >           Node       *limitOffset;        /* # of result tuples to skip */
> > >           Node       *limitCount;         /* # of result tuples to return 
> > > */
> > > !         List       *forUpdate;          /* FOR UPDATE clause */
> > >   
> > >           /*
> > >            * These fields are used only in upper-level SelectStmts.
> > > --- 698,704 ----
> > >           List       *sortClause;         /* sort clause (a list of 
> > > SortBy's) */
> > >           Node       *limitOffset;        /* # of result tuples to skip */
> > >           Node       *limitCount;         /* # of result tuples to return 
> > > */
> > > !         Node       *forupdateClause;    /* FOR UPDATE clause (ForUpdate 
> > > node) */
> > >   
> > >           /*
> > >            * These fields are used only in upper-level SelectStmts.
> > > diff -r -c postgresql-8.0.0rc2.orig/src/include/storage/lmgr.h 
> > > postgresql-8.0.0rc2/src/include/storage/lmgr.h
> > > *** postgresql-8.0.0rc2.orig/src/include/storage/lmgr.h   Thu Sep 16 
> > > 18:58:42 2004
> > > --- postgresql-8.0.0rc2/src/include/storage/lmgr.h        Mon Dec 27 
> > > 10:56:52 2004
> > > ***************
> > > *** 60,64 ****
> > > --- 60,65 ----
> > >   extern void XactLockTableInsert(TransactionId xid);
> > >   extern void XactLockTableDelete(TransactionId xid);
> > >   extern void XactLockTableWait(TransactionId xid);
> > > + extern bool ConditionalXactLockTableWait(TransactionId xid);
> > >   
> > >   #endif   /* LMGR_H */
> > 
> > -- 
> >   Bruce Momjian                        |  http://candle.pha.pa.us
> >   pgman@candle.pha.pa.us               |  (610) 359-1001
> >   +  If your life is a hard drive,     |  13 Roberts Road
> >   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
> > 
> > ---------------------------(end of broadcast)---------------------------
> > TIP 4: Don't 'kill -9' the postmaster
> > 
> 
> -- 
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>        choose an index scan if your joining column's datatypes do not
>        match
-- 
Karel Zak <[EMAIL PROTECTED]>


---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend

Reply via email to