disallow LOCK on a view - the Tom Lane remix

Started by Mark Hollomonover 25 years ago4 messages
#1Mark Hollomon
mhh@mindspring.com
1 attachment(s)

Here is a patch against CVS (without my earlier patch)
to disallow

LOCK x

if x is a view.

It does not use the SPI interface.

--
Mark Hollomon
mhh@mindspring.com

Attachments:

lock.patchtext/plain; charset=us-asciiDownload
*** command.c.orig	Tue Aug 29 10:39:42 2000
--- command.c	Tue Aug 29 14:58:24 2000
***************
*** 26,31 ****
--- 26,32 ----
  #include "catalog/indexing.h"
  #include "catalog/pg_attrdef.h"
  #include "catalog/pg_opclass.h"
+ #include "catalog/pg_rewrite.h"
  #include "commands/command.h"
  #include "executor/spi.h"
  #include "catalog/heap.h"
***************
*** 54,59 ****
--- 55,64 ----
  
  
  static bool needs_toast_table(Relation rel);
+ static bool is_viewr(char *relname);
+ static bool is_view(Relation rel);
+ 
+ 
  
  
  /* --------------------------------
***************
*** 1086,1094 ****
  AlterTableAddConstraint(char *relationName,
  						bool inh, Node *newConstraint)
  {
- 	char rulequery[41+NAMEDATALEN]; 
- 	void *qplan;
- 	char nulls[1]="";
  
  	if (newConstraint == NULL)
  		elog(ERROR, "ALTER TABLE / ADD CONSTRAINT passed invalid constraint.");
--- 1091,1096 ----
***************
*** 1099,1117 ****
  #endif
  
  	/* check to see if the table to be constrained is a view. */
! 	sprintf(rulequery, "select * from pg_views where viewname='%s'", relationName);
! 	if (SPI_connect()!=SPI_OK_CONNECT)
! 		elog(ERROR, "ALTER TABLE: Unable to determine if %s is a view - SPI_connect failure..", relationName);
!         qplan=SPI_prepare(rulequery, 0, NULL);
! 	if (!qplan)
! 		elog(ERROR, "ALTER TABLE: Unable to determine if %s is a view - SPI_prepare failure.", relationName);
! 	qplan=SPI_saveplan(qplan);
! 	if (SPI_execp(qplan, NULL, nulls, 1)!=SPI_OK_SELECT) 
! 		elog(ERROR, "ALTER TABLE: Unable to determine if %s is a view - SPI_execp failure.", relationName);
!         if (SPI_processed != 0)
!                 elog(ERROR, "ALTER TABLE: Cannot add constraints to views.");
!         if (SPI_finish() != SPI_OK_FINISH)
!                 elog(NOTICE, "SPI_finish() failed in ALTER TABLE");
  		
  	switch (nodeTag(newConstraint))
  	{
--- 1101,1108 ----
  #endif
  
  	/* check to see if the table to be constrained is a view. */
! 	if (is_viewr(relationName))
! 		 elog(ERROR, "ALTER TABLE: Cannot add constraints to views.");
  		
  	switch (nodeTag(newConstraint))
  	{
***************
*** 1254,1272 ****
  				}
  
  				/* check to see if the referenced table is a view. */
! 				sprintf(rulequery, "select * from pg_views where viewname='%s'", fkconstraint->pktable_name);
! 				if (SPI_connect()!=SPI_OK_CONNECT)
! 					elog(ERROR, "ALTER TABLE: Unable to determine if %s is a view.", relationName);
! 			        qplan=SPI_prepare(rulequery, 0, NULL);
! 				if (!qplan)
! 					elog(ERROR, "ALTER TABLE: Unable to determine if %s is a view.", relationName);
! 				qplan=SPI_saveplan(qplan);
! 				if (SPI_execp(qplan, NULL, nulls, 1)!=SPI_OK_SELECT) 
! 					elog(ERROR, "ALTER TABLE: Unable to determine if %s is a view.", relationName);
! 			        if (SPI_processed != 0)
! 			                elog(ERROR, "ALTER TABLE: Cannot add constraints to views.");
! 			        if (SPI_finish() != SPI_OK_FINISH)
! 			                elog(NOTICE, "SPI_finish() failed in RI_FKey_check()");
  
  				/*
  				 * Grab an exclusive lock on the pk table, so that someone
--- 1245,1252 ----
  				}
  
  				/* check to see if the referenced table is a view. */
! 				if (is_viewr(fkconstraint->pktable_name))
! 				 elog(ERROR, "ALTER TABLE: Cannot add constraints to views.");
  
  				/*
  				 * Grab an exclusive lock on the pk table, so that someone
***************
*** 1637,1642 ****
--- 1617,1625 ----
  
  	rel = heap_openr(lockstmt->relname, NoLock);
  
+ 	if (is_view(rel)) 
+ 			elog(ERROR, "LOCK TABLE: cannot lock a view");
+ 
  	if (lockstmt->mode == AccessShareLock)
  		aclresult = pg_aclcheck(lockstmt->relname, GetPgUserName(), ACL_RD);
  	else
***************
*** 1650,1652 ****
--- 1633,1698 ----
  	heap_close(rel, NoLock);	/* close rel, keep lock */
  }
  
+ 
+ static
+ bool
+ is_viewr(char *name)
+ {
+ 	Relation rel = heap_openr(name, NoLock);
+ 
+ 	bool retval = is_view(rel);
+ 
+ 	heap_close(rel, NoLock);
+ 
+ 	return retval;
+ }
+ 
+ static
+ bool
+ is_view (Relation rel)
+ {
+ 	Relation	RewriteRelation;
+ 	HeapScanDesc scanDesc;
+ 	ScanKeyData scanKeyData;
+ 	HeapTuple	tuple;
+ 	Form_pg_rewrite data;
+ 
+ 
+ 	bool retval = 0;
+ 
+ 	/*
+ 	 * Open the pg_rewrite relation.
+ 	 */
+ 	RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock);
+ 
+ 	/*
+ 	 * Scan the RuleRelation ('pg_rewrite') for all the tuples that has
+ 	 * the same ev_class as the relation being checked.
+ 	 */
+ 	ScanKeyEntryInitialize(&scanKeyData,
+ 						   0,
+ 						   Anum_pg_rewrite_ev_class,
+ 						   F_OIDEQ,
+ 						   ObjectIdGetDatum(rel->rd_id));
+ 	scanDesc = heap_beginscan(RewriteRelation,
+ 							  0, SnapshotNow, 1, &scanKeyData);
+ 
+ 	while (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0)))
+ 	{
+ 		if (tuple->t_data != NULL) 
+ 		{
+ 			data = (Form_pg_rewrite) GETSTRUCT(tuple);
+ 			if (data->ev_type == '1')
+ 			{
+ 				retval = 1;
+ 				break;
+ 			}
+ 		}
+ 
+ 	}
+ 
+ 	heap_endscan(scanDesc);
+ 	heap_close(RewriteRelation, RowExclusiveLock);
+ 	
+   return retval;
+ }
#2Alfred Perlstein
bright@wintelcom.net
In reply to: Mark Hollomon (#1)
Re: disallow LOCK on a view - the Tom Lane remix

* Mark Hollomon <mhh@mindspring.com> [000829 17:13] wrote:

On Tue, Aug 29, 2000 at 04:14:00PM -0700, Alfred Perlstein wrote:

Ok, I'm wondering if this patch will cause problems locking a table
that has had:

CREATE RULE "_RETfoo" AS ON SELECT TO foo DO INSTEAD SELECT * FROM foo1;

I need to be able to lock the table 'foo' exclusively while I swap
out the underlying rule to forward to another table.

Yes, it would. 'foo' would be seen as view.

Okay, this gives me a reason to to do it the hard way.

I will try to add a relisview attribute to pg_class.
That way, we can differentiate between tables with rules
and things created with 'CREATE VIEW'.

Hmmm... guess I'll need to change the definition of the pg_views
view as well.

Ok, thanks I appreciate you taking my situation into consideration.

thanks,
--
-Alfred Perlstein - [bright@wintelcom.net|alfred@freebsd.org]

#3Mark Hollomon
mhh@nortelnetworks.com
In reply to: Mark Hollomon (#1)
Re: disallow LOCK on a view - the Tom Lane remix

Tom Lane wrote:

BTW, this seems to be a counterexample for my prior suggestion that
pg_class should have a "relviewrule" OID column. If it did, you'd
have to update that field when doing something like the above.
Pain-in-the-neck factor looms large...

I was already considering the possiblity of a 'ALTER VIEW' command that
would effectively allow you do that.

CREATE VIEW bar as select * from foo1;
ALTER VIEW bar as select * from foo2;

It would update the "relviewrule" field.
--

Mark Hollomon
mhh@nortelnetworks.com
ESN 451-9008 (302)454-9008

#4Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Mark Hollomon (#1)
Re: [HACKERS] disallow LOCK on a view - the Tom Lane remix

OK, previous patch unapplied, and this patch was applied.

Here is a patch against CVS (without my earlier patch)
to disallow

LOCK x

if x is a view.

It does not use the SPI interface.

--
Mark Hollomon
mhh@mindspring.com

[ Attachment, skipping... ]

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