Re: Turning off cluster patch

Поиск
Список
Период
Сортировка
Искать
От
Bruce Momjian
Тема
Re: Turning off cluster patch
Дата
Msg-id
200404290443.i3T4hJh01589@candle.pha.pa.us
Ответ на
Turning off cluster patch (Christopher Kings-Lynne)
Список
Дерево обсуждения
Turning off cluster patch Christopher Kings-Lynne <chriskl@familyhealth.com.au>
Re: Turning off cluster patch Bruce Momjian <pgman@candle.pha.pa.us>

Patch withdrawn by author.

---------------------------------------------------------------------------

Christopher Kings-Lynne wrote:
> Hi,
> 
> The attached patch adds a new command:
> 
> ALTER TABLE [ONLY] foo SET WITHOUT CLUSTER;
> 
> I would probably have preferred the DROP CLUSTER syntax, but it doesn't 
> seem easy to get working without shift/reduce problems.
> 
> It has support for inheritance.
> 
> I have also fixed the previously detailed security errors:
> 
> * Ownership is now checked
> * Can now not cluster system catalogs
> * Checks that what you are clustering is actually a table
> 
> And it fixes a related bug in the SET WITHOUT OIDS implementation:
> 
> * Checks that what you are dropping OIDS from is actually a table
> 
> I have included a documentation update and a regression test.
> 
> Chris
> 
> 

> Index: doc/src/sgml/ref/alter_table.sgml
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/ref/alter_table.sgml,v
> retrieving revision 1.68
> diff -c -r1.68 alter_table.sgml
> *** doc/src/sgml/ref/alter_table.sgml	24 Mar 2004 09:49:20 -0000	1.68
> --- doc/src/sgml/ref/alter_table.sgml	28 Apr 2004 07:59:10 -0000
> ***************
> *** 47,52 ****
> --- 47,54 ----
>       OWNER TO new_owner
>   ALTER TABLE name
>       CLUSTER ON index_name
> + ALTER TABLE [ ONLY ] name
> +     SET WITHOUT CLUSTER
>   
>    
>   
> ***************
> *** 218,223 ****
> --- 220,235 ----
>       
>      
>   
> +    
> +     SET WITHOUT CLUSTER
> +     
> +      
> +       This form disables future  on
> +       any indexes on a table. 
> +      
> +     
> +    
> +  
>     
>     
>   
> Index: src/backend/commands/tablecmds.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/backend/commands/tablecmds.c,v
> retrieving revision 1.102
> diff -c -r1.102 tablecmds.c
> *** src/backend/commands/tablecmds.c	1 Apr 2004 21:28:44 -0000	1.102
> --- src/backend/commands/tablecmds.c	28 Apr 2004 07:59:12 -0000
> ***************
> *** 2433,2438 ****
> --- 2433,2444 ----
>   
>   	rel = heap_open(myrelid, AccessExclusiveLock);
>   
> + 	if (rel->rd_rel->relkind != RELKIND_RELATION)
> + 		ereport(ERROR,
> + 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
> + 				 errmsg("\"%s\" is not a table",
> + 						RelationGetRelationName(rel))));
> + 
>   	/*
>   	 * check to see if we actually need to change anything
>   	 */
> ***************
> *** 3902,3908 ****
>    * The only thing we have to do is to change the indisclustered bits.
>    */
>   void
> ! AlterTableClusterOn(Oid relOid, const char *indexName)
>   {
>   	Relation	rel,
>   				pg_index;
> --- 3908,3914 ----
>    * The only thing we have to do is to change the indisclustered bits.
>    */
>   void
> ! AlterTableClusterOn(Oid relOid, const char *indexName, bool recurse)
>   {
>   	Relation	rel,
>   				pg_index;
> ***************
> *** 3913,3942 ****
>   
>   	rel = heap_open(relOid, AccessExclusiveLock);
>   
> ! 	indexOid = get_relname_relid(indexName, rel->rd_rel->relnamespace);
> ! 
> ! 	if (!OidIsValid(indexOid))
>   		ereport(ERROR,
> ! 				(errcode(ERRCODE_UNDEFINED_OBJECT),
> ! 				 errmsg("index \"%s\" for table \"%s\" does not exist",
> ! 						indexName, NameStr(rel->rd_rel->relname))));
>   
> ! 	indexTuple = SearchSysCache(INDEXRELID,
> ! 								ObjectIdGetDatum(indexOid),
> ! 								0, 0, 0);
> ! 	if (!HeapTupleIsValid(indexTuple))
> ! 		elog(ERROR, "cache lookup failed for index %u", indexOid);
> ! 	indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
>   
>   	/*
> ! 	 * If this is the same index the relation was previously clustered on,
> ! 	 * no need to do anything.
>   	 */
> ! 	if (indexForm->indisclustered)
>   	{
> ! 		ReleaseSysCache(indexTuple);
> ! 		heap_close(rel, NoLock);
> ! 		return;
>   	}
>   
>   	pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
> --- 3919,4005 ----
>   
>   	rel = heap_open(relOid, AccessExclusiveLock);
>   
> ! 	/* Only allow cluster on regular tables */
> ! 	if (rel->rd_rel->relkind != RELKIND_RELATION)
>   		ereport(ERROR,
> ! 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
> ! 				 errmsg("\"%s\" is not a table",
> ! 						RelationGetRelationName(rel))));
>   
> ! 	/* Permissions checks */
> ! 	if (!pg_class_ownercheck(relOid, GetUserId()))
> ! 		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
> ! 					   RelationGetRelationName(rel));
> ! 
> ! 	/* Don't allow clustering on system catalogs */
> ! 	if (!allowSystemTableMods && IsSystemRelation(rel))
> ! 		ereport(ERROR,
> ! 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> ! 				 errmsg("permission denied: \"%s\" is a system catalog",
> ! 						RelationGetRelationName(rel))));
>   
>   	/*
> ! 	 * Process child tables if requested. Only if we're turning off clustering.
>   	 */
> ! 	if (recurse && indexName == NULL)
>   	{
> ! 		List	   *child,
> ! 				   *children;
> ! 
> ! 		/* This routine is actually in the planner */
> ! 		children = find_all_inheritors(relOid);
> ! 
> ! 		/*
> ! 		 * find_all_inheritors does the recursive search of the
> ! 		 * inheritance hierarchy, so all we have to do is process all of
> ! 		 * the relids in the list that it returns.
> ! 		 */
> ! 		foreach(child, children)
> ! 		{
> ! 			Oid	childrelid = lfirsto(child);
> ! 			if (childrelid == relOid)
> ! 				continue;
> ! 			AlterTableClusterOn(childrelid, indexName, FALSE);
> ! 		}
> ! 	}
> ! 
> ! 	/* Now proceed with the actions on just this table. */
> ! 
> ! 	/*
> ! 	 * We only fetch the index if indexName is not null.  A null index
> !          * name indicates that we're removing all clustering on this table.
> ! 	 */
> ! 	if (indexName != NULL) {
> ! 		indexOid = get_relname_relid(indexName, rel->rd_rel->relnamespace);
> ! 
> ! 		if (!OidIsValid(indexOid))
> ! 			ereport(ERROR,
> ! 					(errcode(ERRCODE_UNDEFINED_OBJECT),
> ! 					 errmsg("index \"%s\" for table \"%s\" does not exist",
> ! 							indexName, NameStr(rel->rd_rel->relname))));
> ! 
> ! 		indexTuple = SearchSysCache(INDEXRELID,
> ! 									ObjectIdGetDatum(indexOid),
> ! 									0, 0, 0);
> ! 		if (!HeapTupleIsValid(indexTuple))
> ! 			elog(ERROR, "cache lookup failed for index %u", indexOid);
> ! 		indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
> ! 
> ! 		/*
> ! 		 * If this is the same index the relation was previously clustered on,
> ! 		 * no need to do anything.
> ! 		 */
> ! 		if (indexForm->indisclustered)
> ! 		{
> ! 			ReleaseSysCache(indexTuple);
> ! 			heap_close(rel, NoLock);
> ! 			return;
> ! 		}
> ! 	}
> ! 	else {
> ! 		/* Set to NULL to prevent compiler warnings */
> ! 		indexTuple = NULL;
> ! 		indexForm = NULL;
>   	}
>   
>   	pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
> ***************
> *** 3959,3965 ****
>   
>   		/*
>   		 * Unset the bit if set.  We know it's wrong because we checked
> ! 		 * this earlier.
>   		 */
>   		if (idxForm->indisclustered)
>   		{
> --- 4022,4028 ----
>   
>   		/*
>   		 * Unset the bit if set.  We know it's wrong because we checked
> ! 		 * this earlier.  If we're removing all clustering, we do this too.
>   		 */
>   		if (idxForm->indisclustered)
>   		{
> ***************
> *** 3967,3973 ****
>   			simple_heap_update(pg_index, &idxtuple->t_self, idxtuple);
>   			CatalogUpdateIndexes(pg_index, idxtuple);
>   		}
> ! 		else if (idxForm->indexrelid == indexForm->indexrelid)
>   		{
>   			idxForm->indisclustered = true;
>   			simple_heap_update(pg_index, &idxtuple->t_self, idxtuple);
> --- 4030,4040 ----
>   			simple_heap_update(pg_index, &idxtuple->t_self, idxtuple);
>   			CatalogUpdateIndexes(pg_index, idxtuple);
>   		}
> ! 		/*
> ! 		 * If the index is the one we're clustering, set its cluster flag to true.
> ! 		 * However, we do this only if we're not removing all clustering.
> ! 		 */
> ! 		else if (indexName != NULL && idxForm->indexrelid == indexForm->indexrelid)
>   		{
>   			idxForm->indisclustered = true;
>   			simple_heap_update(pg_index, &idxtuple->t_self, idxtuple);
> ***************
> *** 3978,3984 ****
>   
>   	heap_close(pg_index, RowExclusiveLock);
>   
> ! 	ReleaseSysCache(indexTuple);
>   
>   	heap_close(rel, NoLock);	/* close rel, but keep lock till commit */
>   }
> --- 4045,4051 ----
>   
>   	heap_close(pg_index, RowExclusiveLock);
>   
> ! 	if (indexName != NULL) ReleaseSysCache(indexTuple);
>   
>   	heap_close(rel, NoLock);	/* close rel, but keep lock till commit */
>   }
> Index: src/backend/parser/gram.y
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/backend/parser/gram.y,v
> retrieving revision 2.452
> diff -c -r2.452 gram.y
> *** src/backend/parser/gram.y	21 Apr 2004 00:34:18 -0000	2.452
> --- src/backend/parser/gram.y	28 Apr 2004 07:59:13 -0000
> ***************
> *** 1250,1255 ****
> --- 1250,1264 ----
>   					n->name = $6;
>   					$$ = (Node *)n;
>   				}
> + 			/* ALTER TABLE  SET WITHOUT CLUSTER */ 
> + 			| ALTER TABLE relation_expr SET WITHOUT CLUSTER
> + 				{
> + 					AlterTableStmt *n = makeNode(AlterTableStmt);
> + 					n->subtype = 'l';
> + 					n->relation = $3;
> + 					n->name = NULL;
> + 					$$ = (Node *)n;
> + 				}
>   		;
>   
>   alter_column_default:
> Index: src/backend/tcop/utility.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/backend/tcop/utility.c,v
> retrieving revision 1.213
> diff -c -r1.213 utility.c
> *** src/backend/tcop/utility.c	22 Apr 2004 02:58:20 -0000	1.213
> --- src/backend/tcop/utility.c	28 Apr 2004 07:59:14 -0000
> ***************
> *** 603,609 ****
>   										get_usesysid(stmt->name));
>   						break;
>   					case 'L':	/* CLUSTER ON */
> ! 						AlterTableClusterOn(relid, stmt->name);
>   						break;
>   					case 'o':	/* SET WITHOUT OIDS */
>   						AlterTableAlterOids(relid,
> --- 603,612 ----
>   										get_usesysid(stmt->name));
>   						break;
>   					case 'L':	/* CLUSTER ON */
> ! 						AlterTableClusterOn(relid, stmt->name, false);
> ! 						break;
> ! 					case 'l':	/* SET WITHOUT CLUSTER */
> ! 						AlterTableClusterOn(relid, stmt->name, interpretInhOption(stmt->relation->inhOpt));
>   						break;
>   					case 'o':	/* SET WITHOUT OIDS */
>   						AlterTableAlterOids(relid,
> Index: src/include/commands/tablecmds.h
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/include/commands/tablecmds.h,v
> retrieving revision 1.15
> diff -c -r1.15 tablecmds.h
> *** src/include/commands/tablecmds.h	23 Mar 2004 19:35:17 -0000	1.15
> --- src/include/commands/tablecmds.h	28 Apr 2004 07:59:14 -0000
> ***************
> *** 43,49 ****
>   						 const char *constrName,
>   						 DropBehavior behavior);
>   
> ! extern void AlterTableClusterOn(Oid relOid, const char *indexName);
>   
>   extern void AlterTableCreateToastTable(Oid relOid, bool silent);
>   
> --- 43,49 ----
>   						 const char *constrName,
>   						 DropBehavior behavior);
>   
> ! extern void AlterTableClusterOn(Oid relOid, const char *indexName, bool recurse);
>   
>   extern void AlterTableCreateToastTable(Oid relOid, bool silent);
>   
> Index: src/test/regress/expected/cluster.out
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/test/regress/expected/cluster.out,v
> retrieving revision 1.14
> diff -c -r1.14 cluster.out
> *** src/test/regress/expected/cluster.out	2 Oct 2003 06:32:46 -0000	1.14
> --- src/test/regress/expected/cluster.out	28 Apr 2004 07:59:14 -0000
> ***************
> *** 297,302 ****
> --- 297,313 ----
>    clstr_tst_b_c
>   (1 row)
>   
> + -- Try turning off all clustering
> + ALTER TABLE clstr_tst SET WITHOUT CLUSTER;
> + SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2
> + WHERE pg_class.oid=indexrelid
> + 	AND indrelid=pg_class_2.oid
> + 	AND pg_class_2.relname = 'clstr_tst'
> +  	AND indisclustered;
> +   relname 
> +  ---------
> +  (0 rows)
> + 
>   -- Verify that clustering all tables does in fact cluster the right ones
>   CREATE USER clstr_user;
>   CREATE TABLE clstr_1 (a INT PRIMARY KEY);
> Index: src/test/regress/sql/cluster.sql
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/test/regress/sql/cluster.sql,v
> retrieving revision 1.7
> diff -c -r1.7 cluster.sql
> *** src/test/regress/sql/cluster.sql	20 Mar 2003 18:52:48 -0000	1.7
> --- src/test/regress/sql/cluster.sql	28 Apr 2004 07:59:14 -0000
> ***************
> *** 95,100 ****
> --- 95,108 ----
>   	AND pg_class_2.relname = 'clstr_tst'
>   	AND indisclustered;
>   
> + -- Try turning off all clustering
> + ALTER TABLE clstr_tst SET WITHOUT CLUSTER;
> + SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2
> + WHERE pg_class.oid=indexrelid
> + 	AND indrelid=pg_class_2.oid
> + 	AND pg_class_2.relname = 'clstr_tst'
> + 	AND indisclustered;
> + 
>   -- Verify that clustering all tables does in fact cluster the right ones
>   CREATE USER clstr_user;
>   CREATE TABLE clstr_1 (a INT PRIMARY KEY);

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 7: don't forget to increase your free space map settings

-- 
  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
В списке pgsql-patches по дате отправления
От: Bruce Momjian
Дата:
От: Bruce Momjian
Дата:
Сообщение: Re: FW: Timezone library
FAQ