Re: Revised Patch to allow multiple table locks in "Unison"

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Neil Padgett <npadgett(at)redhat(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Fernando Nasser <fnasser(at)cygnus(dot)com>, "pgsql-patches(at)postgresql(dot)org" <pgsql-patches(at)postgresql(dot)org>
Subject: Re: Revised Patch to allow multiple table locks in "Unison"
Date: 2001-08-02 22:23:03
Message-ID: 200108022223.f72MN3H26264@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-patches


Your patch has been added to the PostgreSQL unapplied patches list at:

http://candle.pha.pa.us/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

> Tom Lane wrote:
> >
> > Fernando Nasser <fnasser(at)cygnus(dot)com> writes:
> > > What about having the syntax
> > > LOCK a,b,c;
> > > now just as a shorthand for
> > > LOCK a;
> > > LOCK b;
> > > LOCK c;
> > > This would save typing and allow for Oracle compatibility.
> >
> > This seems fine to me (and in fact I thought we'd already agreed to it).
>
> Here's the patch then. =)
>
> Neil
>
> --
> Neil Padgett
> Red Hat Canada Ltd. E-Mail: npadgett(at)redhat(dot)com
> 2323 Yonge Street, Suite #300,
> Toronto, ON M4P 2C9
>
> Index: src/backend/commands/command.c
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/backend/commands/command.c,v
> retrieving revision 1.136
> diff -c -p -r1.136 command.c
> *** src/backend/commands/command.c 2001/07/16 05:06:57 1.136
> --- src/backend/commands/command.c 2001/07/31 22:04:05
> *************** needs_toast_table(Relation rel)
> *** 1984,1991 ****
> MAXALIGN(data_length);
> return (tuple_length > TOAST_TUPLE_THRESHOLD);
> }
> !
> !
> /*
> *
> * LOCK TABLE
> --- 1984,1990 ----
> MAXALIGN(data_length);
> return (tuple_length > TOAST_TUPLE_THRESHOLD);
> }
> !
> /*
> *
> * LOCK TABLE
> *************** needs_toast_table(Relation rel)
> *** 1994,2019 ****
> void
> LockTableCommand(LockStmt *lockstmt)
> {
> ! Relation rel;
> ! int aclresult;
>
> ! rel = heap_openr(lockstmt->relname, NoLock);
>
> ! if (rel->rd_rel->relkind != RELKIND_RELATION)
> ! elog(ERROR, "LOCK TABLE: %s is not a table", lockstmt->relname);
>
> ! if (lockstmt->mode == AccessShareLock)
> ! aclresult = pg_aclcheck(lockstmt->relname, GetUserId(), ACL_SELECT);
> ! else
> ! aclresult = pg_aclcheck(lockstmt->relname, GetUserId(),
> ! ACL_UPDATE | ACL_DELETE);
>
> ! if (aclresult != ACLCHECK_OK)
> ! elog(ERROR, "LOCK TABLE: permission denied");
>
> ! LockRelation(rel, lockstmt->mode);
>
> ! heap_close(rel, NoLock); /* close rel, keep lock */
> }
>
>
> --- 1993,2096 ----
> void
> LockTableCommand(LockStmt *lockstmt)
> {
> ! int relCnt;
> !
> ! relCnt = length(lockstmt -> rellist);
> !
> ! /* Handle a single relation lock specially to avoid overhead on
> likely the
> ! most common case */
> !
> ! if(relCnt == 1)
> ! {
> !
> ! /* Locking a single table */
> !
> ! Relation rel;
> ! int aclresult;
> ! char *relname;
> !
> ! relname = strVal(lfirst(lockstmt->rellist));
> !
> ! freeList(lockstmt->rellist);
> !
> ! rel = heap_openr(relname, NoLock);
> !
> ! if (rel->rd_rel->relkind != RELKIND_RELATION)
> ! elog(ERROR, "LOCK TABLE: %s is not a table", relname);
> !
> ! if (lockstmt->mode == AccessShareLock)
> ! aclresult = pg_aclcheck(relname, GetUserId(),
> ! ACL_SELECT);
> ! else
> ! aclresult = pg_aclcheck(relname, GetUserId(),
> ! ACL_UPDATE | ACL_DELETE);
> !
> ! if (aclresult != ACLCHECK_OK)
> ! elog(ERROR, "LOCK TABLE: permission denied");
> !
> ! LockRelation(rel, lockstmt->mode);
> !
> ! pfree(relname);
> !
> ! heap_close(rel, NoLock); /* close rel, keep lock */
> ! }
> ! else
> ! {
> ! List *p;
> ! Relation *RelationArray;
> ! Relation *pRel;
> !
> ! /* Locking multiple tables */
> !
> ! /* Create an array of relations */
> !
> ! RelationArray = palloc(relCnt * sizeof(Relation));
> ! pRel = RelationArray;
> !
> ! /* Iterate over the list and populate the relation array */
> !
> ! foreach(p, lockstmt->rellist)
> ! {
> ! char* relname = strVal(lfirst(p));
> ! int aclresult;
> !
> ! *pRel = heap_openr(relname, NoLock);
> !
> ! if ((*pRel)->rd_rel->relkind != RELKIND_RELATION)
> ! elog(ERROR, "LOCK TABLE: %s is not a table",
> ! relname);
> !
> ! if (lockstmt->mode == AccessShareLock)
> ! aclresult = pg_aclcheck(relname, GetUserId(),
> ! ACL_SELECT);
> ! else
> ! aclresult = pg_aclcheck(relname, GetUserId(),
> ! ACL_UPDATE | ACL_DELETE);
> !
> ! if (aclresult != ACLCHECK_OK)
> ! elog(ERROR, "LOCK TABLE: permission denied");
>
> ! pRel++;
> ! pfree(relname);
> ! }
>
> ! /* Now, lock all the relations, closing each after it is locked
> ! (Keeping the locks)
> ! */
>
> ! for(pRel = RelationArray;
> ! pRel < RelationArray + relCnt;
> ! pRel++)
> ! {
> ! LockRelation(*pRel, lockstmt->mode);
>
> ! heap_close(*pRel, NoLock);
> ! }
>
> ! /* Free the relation array */
>
> ! pfree(RelationArray);
> ! }
> }
>
>
> Index: src/backend/nodes/copyfuncs.c
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
> retrieving revision 1.148
> diff -c -p -r1.148 copyfuncs.c
> *** src/backend/nodes/copyfuncs.c 2001/07/16 19:07:37 1.148
> --- src/backend/nodes/copyfuncs.c 2001/07/31 22:04:06
> *************** _copyLockStmt(LockStmt *from)
> *** 2425,2432 ****
> {
> LockStmt *newnode = makeNode(LockStmt);
>
> ! if (from->relname)
> ! newnode->relname = pstrdup(from->relname);
> newnode->mode = from->mode;
>
> return newnode;
> --- 2425,2432 ----
> {
> LockStmt *newnode = makeNode(LockStmt);
>
> ! Node_Copy(from, newnode, rellist);
> !
> newnode->mode = from->mode;
>
> return newnode;
> Index: src/backend/nodes/equalfuncs.c
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
> retrieving revision 1.96
> diff -c -p -r1.96 equalfuncs.c
> *** src/backend/nodes/equalfuncs.c 2001/07/16 19:07:38 1.96
> --- src/backend/nodes/equalfuncs.c 2001/07/31 22:04:06
> *************** _equalDropUserStmt(DropUserStmt *a, Drop
> *** 1283,1289 ****
> static bool
> _equalLockStmt(LockStmt *a, LockStmt *b)
> {
> ! if (!equalstr(a->relname, b->relname))
> return false;
> if (a->mode != b->mode)
> return false;
> --- 1283,1289 ----
> static bool
> _equalLockStmt(LockStmt *a, LockStmt *b)
> {
> ! if (!equal(a->rellist, b->rellist))
> return false;
> if (a->mode != b->mode)
> return false;
> Index: src/backend/parser/gram.y
> ===================================================================
> RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/parser/gram.y,v
> retrieving revision 2.238
> diff -c -p -r2.238 gram.y
> *** src/backend/parser/gram.y 2001/07/16 19:07:40 2.238
> --- src/backend/parser/gram.y 2001/07/31 22:04:10
> *************** DeleteStmt: DELETE FROM relation_expr w
> *** 3280,3290 ****
> }
> ;
>
> ! LockStmt: LOCK_P opt_table relation_name opt_lock
> {
> LockStmt *n = makeNode(LockStmt);
>
> ! n->relname = $3;
> n->mode = $4;
> $$ = (Node *)n;
> }
> --- 3280,3290 ----
> }
> ;
>
> ! LockStmt: LOCK_P opt_table relation_name_list opt_lock
> {
> LockStmt *n = makeNode(LockStmt);
>
> ! n->rellist = $3;
> n->mode = $4;
> $$ = (Node *)n;
> }
> Index: src/include/nodes/parsenodes.h
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/include/nodes/parsenodes.h,v
> retrieving revision 1.136
> diff -c -p -r1.136 parsenodes.h
> *** src/include/nodes/parsenodes.h 2001/07/16 19:07:40 1.136
> --- src/include/nodes/parsenodes.h 2001/07/31 22:04:11
> *************** typedef struct VariableResetStmt
> *** 760,766 ****
> typedef struct LockStmt
> {
> NodeTag type;
> ! char *relname; /* relation to lock */
> int mode; /* lock mode */
> } LockStmt;
>
> --- 760,766 ----
> typedef struct LockStmt
> {
> NodeTag type;
> ! List *rellist; /* relations to lock */
> int mode; /* lock mode */
> } LockStmt;
>
> Index: src/interfaces/ecpg/preproc/preproc.y
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/interfaces/ecpg/preproc/preproc.y,v
> retrieving revision 1.146
> diff -c -p -r1.146 preproc.y
> *** src/interfaces/ecpg/preproc/preproc.y 2001/07/16 05:07:00 1.146
> --- src/interfaces/ecpg/preproc/preproc.y 2001/07/31 22:04:14
> *************** DeleteStmt: DELETE FROM relation_expr w
> *** 2421,2427 ****
> }
> ;
>
> ! LockStmt: LOCK_P opt_table relation_name opt_lock
> {
> $$ = cat_str(4, make_str("lock"), $2, $3, $4);
> }
> --- 2421,2427 ----
> }
> ;
>
> ! LockStmt: LOCK_P opt_table relation_name_list opt_lock
> {
> $$ = cat_str(4, make_str("lock"), $2, $3, $4);
> }
>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster
>

--
Bruce Momjian | http://candle.pha.pa.us
pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Oliver Elphick 2001-08-02 22:29:34 pg_dumpall problem in 7.1 and cvs
Previous Message Neil Padgett 2001-08-02 22:20:54 Re: Revised Patch to allow multiple table locks in "Unison"

Browse pgsql-patches by date

  From Date Subject
Next Message Tom Lane 2001-08-02 22:23:23 Re: Patch for Improved Syntax Error Reporting
Previous Message Bruce Momjian 2001-08-02 22:22:38 Re: Patch for Improved Syntax Error Reporting