Robert Haas <robertmh...@gmail.com> writes:
> On Sat, Nov 20, 2010 at 11:23 PM, Robert Haas <robertmh...@gmail.com> wrote:
>> Ah, nuts.  I see now there's a v7.  Never mind...
>
> OK.  I looked at the right version, now.  Hopefully.

Yeah, that was the most recent one and I linked it in the commit fest
application. Given the very fast feedback I got, there has been a lot of
activity and patches versions produced, so that's easy to get confused.

> It seems we have no regression tests at all for any of the existing
> SET SCHEMA commands.  This seems like a good time to correct that
> oversight, and also add some for the new commands you're adding here.

Yeah, it's time for me to have a look at regression tests :)

Please find attached set_schema.v8.patch with tests for the added
commands in the patch.

> (It might be helpful to submit the regression tests for the existing
> commands as a separate patch.) Also, you're missing psql tab
> completion support, which would be nice to have.

Do you still want me to prepare another patch for adding in the tests
the "set schema" variants that already existed but are not yet covered?
Which are the one you did spot, btw?

Completion support for psql. Isn't that stepping on David's toes? :)
I'll see about that later if needed, maybe sometime tomorrow…

Regards,
-- 
Dimitri Fontaine
http://2ndQuadrant.fr     PostgreSQL : Expertise, Formation et Support

*** a/doc/src/sgml/ref/alter_conversion.sgml
--- b/doc/src/sgml/ref/alter_conversion.sgml
***************
*** 23,28 **** PostgreSQL documentation
--- 23,29 ----
  <synopsis>
  ALTER CONVERSION <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
  ALTER CONVERSION <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ ALTER CONVERSION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
  </synopsis>
   </refsynopsisdiv>
    
***************
*** 75,80 **** ALTER CONVERSION <replaceable>name</replaceable> OWNER TO <replaceable>new_owner
--- 76,90 ----
       </para>
      </listitem>
     </varlistentry>
+ 
+    <varlistentry>
+     <term><replaceable class="parameter">new_schema</replaceable></term>
+     <listitem>
+      <para>
+       The new schema of the conversion.
+      </para>
+     </listitem>
+    </varlistentry>
    </variablelist>
   </refsect1>
  
*** a/doc/src/sgml/ref/alter_opclass.sgml
--- b/doc/src/sgml/ref/alter_opclass.sgml
***************
*** 23,28 **** PostgreSQL documentation
--- 23,29 ----
  <synopsis>
  ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> RENAME TO <replaceable>new_name</replaceable>
  ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
  </synopsis>
   </refsynopsisdiv>
    
***************
*** 85,90 **** ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="p
--- 86,100 ----
       </para>
      </listitem>
     </varlistentry>
+ 
+    <varlistentry>
+     <term><replaceable class="parameter">new_schema</replaceable></term>
+     <listitem>
+      <para>
+       The new schema for the operator class.
+      </para>
+     </listitem>
+    </varlistentry>
   </variablelist>
   </refsect1>
  
*** a/doc/src/sgml/ref/alter_operator.sgml
--- b/doc/src/sgml/ref/alter_operator.sgml
***************
*** 22,27 **** PostgreSQL documentation
--- 22,28 ----
   <refsynopsisdiv>
  <synopsis>
  ALTER OPERATOR <replaceable>name</replaceable> ( { <replaceable>left_type</replaceable> | NONE } , { <replaceable>right_type</replaceable> | NONE } ) OWNER TO <replaceable>new_owner</replaceable>
+ ALTER OPERATOR <replaceable>name</replaceable> ( { <replaceable>left_type</replaceable> | NONE } , { <replaceable>right_type</replaceable> | NONE } ) SET SCHEMA <replaceable>new_schema</replaceable>
  </synopsis>
   </refsynopsisdiv>
    
***************
*** 85,90 **** ALTER OPERATOR <replaceable>name</replaceable> ( { <replaceable>left_type</repla
--- 86,100 ----
       </para>
      </listitem>
     </varlistentry>
+ 
+    <varlistentry>
+     <term><replaceable class="parameter">new_schema</replaceable></term>
+     <listitem>
+      <para>
+       The new schema of the operator.
+      </para>
+     </listitem>
+    </varlistentry>
    </variablelist>
   </refsect1>
  
*** a/doc/src/sgml/ref/alter_opfamily.sgml
--- b/doc/src/sgml/ref/alter_opfamily.sgml
***************
*** 31,36 **** ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="
--- 31,37 ----
    } [, ... ]
  ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> RENAME TO <replaceable>new_name</replaceable>
  ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
  </synopsis>
   </refsynopsisdiv>
    
***************
*** 200,205 **** ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="
--- 201,215 ----
       </para>
      </listitem>
     </varlistentry>
+ 
+    <varlistentry>
+     <term><replaceable class="parameter">new_schema</replaceable></term>
+     <listitem>
+      <para>
+       The new schema for the operator family.
+      </para>
+     </listitem>
+    </varlistentry>
   </variablelist>
  
    <para>
*** a/doc/src/sgml/ref/alter_tsconfig.sgml
--- b/doc/src/sgml/ref/alter_tsconfig.sgml
***************
*** 33,38 **** ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable>
--- 33,39 ----
      DROP MAPPING [ IF EXISTS ] FOR <replaceable class="parameter">token_type</replaceable> [, ... ]
  ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
  ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
  </synopsis>
   </refsynopsisdiv>
    
***************
*** 123,128 **** ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> OWNER TO <replac
--- 124,138 ----
       </para>
      </listitem>
     </varlistentry>
+ 
+    <varlistentry>
+     <term><replaceable class="parameter">new_schema</replaceable></term>
+     <listitem>
+      <para>
+       The new schema for the text search configuration.
+      </para>
+     </listitem>
+    </varlistentry>
   </variablelist>
  
    <para>
*** a/doc/src/sgml/ref/alter_tsdictionary.sgml
--- b/doc/src/sgml/ref/alter_tsdictionary.sgml
***************
*** 26,31 **** ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> (
--- 26,32 ----
  )
  ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
  ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
+ ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
  </synopsis>
   </refsynopsisdiv>
    
***************
*** 96,101 **** ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> OWNER TO <replaceab
--- 97,111 ----
       </para>
      </listitem>
     </varlistentry>
+ 
+    <varlistentry>
+     <term><replaceable class="parameter">new_schema</replaceable></term>
+     <listitem>
+      <para>
+       The new schema of the text search dictionary.
+      </para>
+     </listitem>
+    </varlistentry>
   </variablelist>
  
    <para>
*** a/doc/src/sgml/ref/alter_tsparser.sgml
--- b/doc/src/sgml/ref/alter_tsparser.sgml
***************
*** 22,27 **** PostgreSQL documentation
--- 22,28 ----
   <refsynopsisdiv>
  <synopsis>
  ALTER TEXT SEARCH PARSER <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
+ ALTER TEXT SEARCH PARSER <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
  </synopsis>
   </refsynopsisdiv>
    
***************
*** 60,65 **** ALTER TEXT SEARCH PARSER <replaceable>name</replaceable> RENAME TO <replaceable>
--- 61,75 ----
       </para>
      </listitem>
     </varlistentry>
+ 
+    <varlistentry>
+     <term><replaceable class="parameter">new_schema</replaceable></term>
+     <listitem>
+      <para>
+       The new schema of the text search parser.
+      </para>
+     </listitem>
+    </varlistentry>
   </variablelist>
   </refsect1>
  
*** a/doc/src/sgml/ref/alter_tstemplate.sgml
--- b/doc/src/sgml/ref/alter_tstemplate.sgml
***************
*** 22,27 **** PostgreSQL documentation
--- 22,28 ----
   <refsynopsisdiv>
  <synopsis>
  ALTER TEXT SEARCH TEMPLATE <replaceable>name</replaceable> RENAME TO <replaceable>new_name</replaceable>
+ ALTER TEXT SEARCH TEMPLATE <replaceable>name</replaceable> SET SCHEMA <replaceable>new_schema</replaceable>
  </synopsis>
   </refsynopsisdiv>
    
***************
*** 60,65 **** ALTER TEXT SEARCH TEMPLATE <replaceable>name</replaceable> RENAME TO <replaceabl
--- 61,75 ----
       </para>
      </listitem>
     </varlistentry>
+ 
+    <varlistentry>
+     <term><replaceable class="parameter">new_schema</replaceable></term>
+     <listitem>
+      <para>
+       The new schema of the text search template.
+      </para>
+     </listitem>
+    </varlistentry>
   </variablelist>
   </refsect1>
  
*** a/src/backend/catalog/dependency.c
--- b/src/backend/catalog/dependency.c
***************
*** 2706,2711 **** getObjectDescription(const ObjectAddress *object)
--- 2706,2726 ----
  }
  
  /*
+  * getObjectDescriptionOids: as above, except the object is specified by Oids
+  */
+ char *
+ getObjectDescriptionOids(Oid classid, Oid objid)
+ {
+ 	ObjectAddress	address;
+ 
+ 	address.classId = classid;
+ 	address.objectId = objid;
+ 	address.objectSubId = 0;
+ 
+ 	return getObjectDescription(&address);
+ }
+ 
+ /*
   * subroutine for getObjectDescription: describe a relation
   */
  static void
*** a/src/backend/catalog/namespace.c
--- b/src/backend/catalog/namespace.c
***************
*** 2340,2345 **** LookupCreationNamespace(const char *nspname)
--- 2340,2372 ----
  }
  
  /*
+  * Check new namespace validity in ALTER OBJECT ... SET SCHEMA ... and
+  * ereport(ERROR, ...) in case of any problem.
+  */
+ void
+ CheckSetNamespace(Oid oldNspOid, Oid nspOid, Oid classid, Oid objid)
+ {
+ 	if (oldNspOid == nspOid)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_DUPLICATE_OBJECT),
+ 				 errmsg("%s already exists in schema \"%s\"",
+ 						getObjectDescriptionOids(classid, objid),
+ 						get_namespace_name(nspOid))));
+ 
+ 	/* disallow renaming into or out of temp schemas */
+ 	if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 				 errmsg("cannot move objects into or out of temporary schemas")));
+ 
+ 	/* same for TOAST schema */
+ 	if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 				 errmsg("cannot move objects into or out of TOAST schema")));
+ }
+ 
+ /*
   * QualifiedNameGetCreationNamespace
   *		Given a possibly-qualified name for an object (in List-of-Values
   *		format), determine what namespace the object should be created in.
*** a/src/backend/commands/alter.c
--- b/src/backend/commands/alter.c
***************
*** 14,21 ****
--- 14,23 ----
   */
  #include "postgres.h"
  
+ #include "catalog/indexing.h"
  #include "catalog/namespace.h"
  #include "catalog/pg_largeobject.h"
+ #include "catalog/pg_namespace.h"
  #include "commands/alter.h"
  #include "commands/conversioncmds.h"
  #include "commands/dbcommands.h"
***************
*** 33,38 ****
--- 35,41 ----
  #include "utils/acl.h"
  #include "utils/builtins.h"
  #include "utils/lsyscache.h"
+ #include "utils/syscache.h"
  
  
  /*
***************
*** 182,192 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
--- 185,211 ----
  								   stmt->newschema);
  			break;
  
+ 		case OBJECT_CONVERSION:
+ 			AlterConversionNamespace(stmt->object, stmt->newschema);
+ 			break;
+ 
  		case OBJECT_FUNCTION:
  			AlterFunctionNamespace(stmt->object, stmt->objarg, false,
  								   stmt->newschema);
  			break;
  
+ 		case OBJECT_OPERATOR:
+ 			AlterOperatorNamespace(stmt->object, stmt->objarg, stmt->newschema);
+ 			break;
+ 
+ 		case OBJECT_OPCLASS:
+ 			AlterOpClassNamespace(stmt->object, stmt->objarg, stmt->newschema);
+ 			break;
+ 
+ 		case OBJECT_OPFAMILY:
+ 			AlterOpFamilyNamespace(stmt->object, stmt->objarg, stmt->newschema);
+ 			break;
+ 
  		case OBJECT_SEQUENCE:
  		case OBJECT_TABLE:
  		case OBJECT_VIEW:
***************
*** 195,200 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
--- 214,235 ----
  								stmt->objectType, AccessExclusiveLock);
  			break;
  
+ 		case OBJECT_TSPARSER:
+ 			AlterTSParserNamespace(stmt->object, stmt->newschema);
+ 			break;
+ 
+ 		case OBJECT_TSDICTIONARY:
+ 			AlterTSDictionaryNamespace(stmt->object, stmt->newschema);
+ 			break;
+ 
+ 		case OBJECT_TSTEMPLATE:
+ 			AlterTSTemplateNamespace(stmt->object, stmt->newschema);
+ 			break;
+ 
+ 		case OBJECT_TSCONFIGURATION:
+ 			AlterTSConfigurationNamespace(stmt->object, stmt->newschema);
+ 			break;
+ 
  		case OBJECT_TYPE:
  		case OBJECT_DOMAIN:
  			AlterTypeNamespace(stmt->object, stmt->newschema);
***************
*** 207,212 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
--- 242,341 ----
  }
  
  /*
+  * Generic function to change the namespace of a given object, for simple
+  * cases (won't work for tables or functions, objects which have more than 2
+  * key-attributes to use when searching for their syscache entries --- we
+  * don't want nor need to get this generic here).
+  *
+  * The AlterFooNamespace() calls just above will call a function whose job
+  * is to lookup the arguments for the generic function here.
+  *
+  * Relation must already by open, it's the responsibility of the caller to
+  * close it.
+  */
+ void
+ AlterObjectNamespace(Relation rel, int cacheId,
+ 					 Oid classId, Oid objid, Oid nspOid,
+ 					 int Anum_name, int Anum_namespace, int Anum_owner,
+ 					 AclObjectKind acl_kind,
+ 					 bool superuser_only)
+ {
+ 	Oid			oldNspOid;
+ 	Datum       name, namespace;
+ 	bool        isnull;
+ 	HeapTuple	tup, newtup = NULL;
+ 	Datum		values[rel->rd_att->natts];
+ 	bool		nulls[rel->rd_att->natts];
+ 	bool		replaces[rel->rd_att->natts];
+ 	int			i;
+ 
+ 	tup = SearchSysCacheCopy1(cacheId, ObjectIdGetDatum(objid));
+ 	if (!HeapTupleIsValid(tup)) /* should not happen */
+ 		elog(ERROR, "cache lookup failed for object %u: %s",
+ 			 objid, getObjectDescriptionOids(classId, objid));
+ 
+ 	name = heap_getattr(tup, Anum_name, rel->rd_att, &isnull);
+ 	namespace = heap_getattr(tup, Anum_namespace, rel->rd_att, &isnull);
+ 	oldNspOid = DatumGetObjectId(namespace);
+ 
+ 	/* Check basic namespace related issues */
+ 	CheckSetNamespace(oldNspOid, nspOid, classId, objid);
+ 
+ 	/* check for duplicate name (more friendly than unique-index failure) */
+ 	if (SearchSysCacheExists2(cacheId, name, ObjectIdGetDatum(nspOid)))
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_DUPLICATE_OBJECT),
+ 				 errmsg("%s already exists in schema \"%s\"",
+ 						getObjectDescriptionOids(classId, objid),
+ 						get_namespace_name(nspOid))));
+ 
+ 	/* Superusers can always do it */
+ 	if (!superuser())
+ 	{
+ 		Datum       owner;
+ 		Oid			ownerId;
+ 		AclResult	aclresult;
+ 
+ 		if (superuser_only)
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 					 (errmsg("must be superuser to SET SCHEMA of %s",
+ 							 getObjectDescriptionOids(classId, objid)))));
+ 
+ 		/* Otherwise, must be owner of the existing object */
+ 		owner = heap_getattr(tup, Anum_owner, rel->rd_att, &isnull);
+ 		ownerId = DatumGetObjectId(owner);
+ 
+ 		if (!has_privs_of_role(GetUserId(), ownerId))
+ 			aclcheck_error(ACLCHECK_NOT_OWNER, acl_kind,
+ 						   NameStr(*(DatumGetName(name))));
+ 
+ 		/* owner must have CREATE privilege on namespace */
+ 		aclresult = pg_namespace_aclcheck(oldNspOid, GetUserId(), ACL_CREATE);
+ 		if (aclresult != ACLCHECK_OK)
+ 			aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+ 						   get_namespace_name(oldNspOid));
+ 	}
+ 
+ 	/* prepare a new version of the tuple using nspId */
+ 	values[Anum_namespace - 1] = nspOid;
+ 	for (i = 0; i < rel->rd_att->natts; i++)
+ 	{
+ 		nulls[i]    = i != Anum_namespace - 1;
+ 		replaces[i] = i == Anum_namespace - 1;
+ 	}
+ 
+ 	newtup = heap_modify_tuple(tup, rel->rd_att, values, nulls, replaces);
+ 	simple_heap_update(rel, &tup->t_self, newtup);
+ 	CatalogUpdateIndexes(rel, newtup);
+ 
+ 	/* update dependencies to point to the new schema */
+ 	changeDependencyFor(classId, objid,
+ 						NamespaceRelationId, oldNspOid, nspOid);
+ }
+ 
+ 
+ /*
   * Executes an ALTER OBJECT / OWNER TO statement.  Based on the object
   * type, the function appropriate to that type is executed.
   */
*** a/src/backend/commands/conversioncmds.c
--- b/src/backend/commands/conversioncmds.c
***************
*** 19,25 ****
--- 19,27 ----
  #include "catalog/indexing.h"
  #include "catalog/pg_conversion.h"
  #include "catalog/pg_conversion_fn.h"
+ #include "catalog/pg_namespace.h"
  #include "catalog/pg_type.h"
+ #include "commands/alter.h"
  #include "commands/conversioncmds.h"
  #include "mb/pg_wchar.h"
  #include "miscadmin.h"
***************
*** 30,36 ****
  #include "utils/rel.h"
  #include "utils/syscache.h"
  
! static void AlterConversionOwner_internal(Relation rel, Oid conversionOid,
  							  Oid newOwnerId);
  
  /*
--- 32,38 ----
  #include "utils/rel.h"
  #include "utils/syscache.h"
  
! static void AlterConversionOwner_internal(Relation rel, Oid convOid,
  							  Oid newOwnerId);
  
  /*
***************
*** 326,328 **** AlterConversionOwner_internal(Relation rel, Oid conversionOid, Oid newOwnerId)
--- 328,376 ----
  
  	heap_freetuple(tup);
  }
+ 
+ /*
+  * Execute ALTER CONVERSION SET SCHEMA
+  */
+ void
+ AlterConversionNamespace(List *name, const char *newschema)
+ {
+ 	Oid			convOid, nspOid;
+ 	Relation	rel;
+ 
+ 	rel = heap_open(ConversionRelationId, RowExclusiveLock);
+ 
+ 	convOid = get_conversion_oid(name, false);
+ 
+ 	/* get schema OID */
+ 	nspOid = LookupCreationNamespace(newschema);
+ 
+ 	AlterObjectNamespace(rel, CONVOID, ConversionRelationId, convOid, nspOid,
+ 						 Anum_pg_conversion_conname,
+ 						 Anum_pg_conversion_connamespace,
+ 						 Anum_pg_conversion_conowner,
+ 						 ACL_KIND_CONVERSION,
+ 						 false);
+ 
+ 	heap_close(rel, NoLock);
+ }
+ 
+ /*
+  * Change conversion schema, by oid
+  */
+ void
+ AlterConversionNamespace_oid(Oid convOid, Oid newNspOid)
+ {
+ 	Relation	rel;
+ 
+ 	rel = heap_open(ConversionRelationId, RowExclusiveLock);
+ 
+ 	AlterObjectNamespace(rel, CONVOID, ConversionRelationId, convOid, newNspOid,
+ 						 Anum_pg_conversion_conname,
+ 						 Anum_pg_conversion_connamespace,
+ 						 Anum_pg_conversion_conowner,
+ 						 ACL_KIND_CONVERSION,
+ 						 false);
+ 
+ 	heap_close(rel, NoLock);
+ }
*** a/src/backend/commands/functioncmds.c
--- b/src/backend/commands/functioncmds.c
***************
*** 1870,1882 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
  					   const char *newschema)
  {
  	Oid			procOid;
- 	Oid			oldNspOid;
  	Oid			nspOid;
- 	HeapTuple	tup;
- 	Relation	procRel;
- 	Form_pg_proc proc;
- 
- 	procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
  
  	/* get function OID */
  	if (isagg)
--- 1870,1876 ----
***************
*** 1889,1894 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
--- 1883,1903 ----
  		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
  					   NameListToString(name));
  
+ 	nspOid = LookupCreationNamespace(newschema);
+ 
+ 	AlterFunctionNamespace_oid(procOid, nspOid);
+ }
+ 
+ void
+ AlterFunctionNamespace_oid(Oid procOid, Oid nspOid)
+ {
+ 	Oid			oldNspOid;
+ 	HeapTuple	tup;
+ 	Relation	procRel;
+ 	Form_pg_proc proc;
+ 
+ 	procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
+ 
  	tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procOid));
  	if (!HeapTupleIsValid(tup))
  		elog(ERROR, "cache lookup failed for function %u", procOid);
***************
*** 1896,1910 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
  
  	oldNspOid = proc->pronamespace;
  
- 	/* get schema OID and check its permissions */
- 	nspOid = LookupCreationNamespace(newschema);
- 
  	if (oldNspOid == nspOid)
  		ereport(ERROR,
  				(errcode(ERRCODE_DUPLICATE_FUNCTION),
  				 errmsg("function \"%s\" is already in schema \"%s\"",
! 						NameListToString(name),
! 						newschema)));
  
  	/* disallow renaming into or out of temp schemas */
  	if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
--- 1905,1916 ----
  
  	oldNspOid = proc->pronamespace;
  
  	if (oldNspOid == nspOid)
  		ereport(ERROR,
  				(errcode(ERRCODE_DUPLICATE_FUNCTION),
  				 errmsg("function \"%s\" is already in schema \"%s\"",
! 						NameStr(proc->proname),
! 						get_namespace_name(nspOid))));
  
  	/* disallow renaming into or out of temp schemas */
  	if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
***************
*** 1927,1933 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
  				(errcode(ERRCODE_DUPLICATE_FUNCTION),
  				 errmsg("function \"%s\" already exists in schema \"%s\"",
  						NameStr(proc->proname),
! 						newschema)));
  
  	/* OK, modify the pg_proc row */
  
--- 1933,1939 ----
  				(errcode(ERRCODE_DUPLICATE_FUNCTION),
  				 errmsg("function \"%s\" already exists in schema \"%s\"",
  						NameStr(proc->proname),
! 						get_namespace_name(nspOid))));
  
  	/* OK, modify the pg_proc row */
  
***************
*** 1941,1947 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
  	if (changeDependencyFor(ProcedureRelationId, procOid,
  							NamespaceRelationId, oldNspOid, nspOid) != 1)
  		elog(ERROR, "failed to change schema dependency for function \"%s\"",
! 			 NameListToString(name));
  
  	heap_freetuple(tup);
  
--- 1947,1953 ----
  	if (changeDependencyFor(ProcedureRelationId, procOid,
  							NamespaceRelationId, oldNspOid, nspOid) != 1)
  		elog(ERROR, "failed to change schema dependency for function \"%s\"",
! 			 NameStr(proc->proname));
  
  	heap_freetuple(tup);
  
*** a/src/backend/commands/opclasscmds.c
--- b/src/backend/commands/opclasscmds.c
***************
*** 30,35 ****
--- 30,36 ----
  #include "catalog/pg_opfamily.h"
  #include "catalog/pg_proc.h"
  #include "catalog/pg_type.h"
+ #include "commands/alter.h"
  #include "commands/defrem.h"
  #include "miscadmin.h"
  #include "parser/parse_func.h"
***************
*** 1912,1917 **** AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
--- 1913,1980 ----
  }
  
  /*
+  * ALTER OPERATOR CLASS any_name USING access_method SET SCHEMA name
+  */
+ void
+ AlterOpClassNamespace(List *name, List *argam, const char *newschema)
+ {
+ 	Oid			amOid;
+ 	char       *access_method = linitial(argam);
+ 	Relation	rel;
+ 	HeapTuple	tup, origtup;
+ 	Oid			nspOid;
+ 
+ 	Assert(list_length(argam) == 1);
+ 
+ 	amOid = get_am_oid(access_method, false);
+ 
+ 	rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
+ 
+ 	/* Look up the opclass. */
+ 	origtup = OpClassCacheLookup(amOid, name, false);
+ 	tup = heap_copytuple(origtup);
+ 	ReleaseSysCache(origtup);
+ 
+ 	/* get schema OID */
+ 	nspOid = LookupCreationNamespace(newschema);
+ 
+ 	AlterObjectNamespace(rel, CLAOID, OperatorClassRelationId,
+ 						 HeapTupleGetOid(tup), nspOid,
+ 						 Anum_pg_opfamily_opfname,
+ 						 Anum_pg_opfamily_opfnamespace,
+ 						 Anum_pg_opfamily_opfowner,
+ 						 ACL_KIND_OPCLASS,
+ 						 false);
+ 
+ 	heap_freetuple(tup);
+ 	heap_close(rel, NoLock);
+ }
+ 
+ void
+ AlterOpClassNamespace_oid(Oid opclassOid, Oid newNspOid)
+ {
+ 	HeapTuple	tup;
+ 	Relation	rel;
+ 
+ 	rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
+ 
+ 	tup = SearchSysCacheCopy1(CLAOID, ObjectIdGetDatum(opclassOid));
+ 	if (!HeapTupleIsValid(tup))
+ 		elog(ERROR, "cache lookup failed for opclass %u", opclassOid);
+ 
+ 	AlterObjectNamespace(rel, CLAOID, OperatorClassRelationId,
+ 						 HeapTupleGetOid(tup), newNspOid,
+ 						 Anum_pg_opfamily_opfname,
+ 						 Anum_pg_opfamily_opfnamespace,
+ 						 Anum_pg_opfamily_opfowner,
+ 						 ACL_KIND_OPCLASS,
+ 						 false);
+ 
+ 	heap_freetuple(tup);
+ 	heap_close(rel, NoLock);
+ }
+ 
+ /*
   * Change opfamily owner by name
   */
  void
***************
*** 2067,2069 **** get_am_oid(const char *amname, bool missing_ok)
--- 2130,2226 ----
  				 errmsg("access method \"%s\" does not exist", amname)));
  	return oid;
  }
+ 
+ /*
+  * ALTER OPERATOR FAMILY any_name USING access_method SET SCHEMA name
+  */
+ void
+ AlterOpFamilyNamespace(List *name, List *argam, const char *newschema)
+ {
+ 	Oid			amOid;
+ 	char       *access_method = linitial(argam);
+ 	Relation	rel;
+ 	HeapTuple	tup;
+ 	char	   *opfname, *schemaname;
+ 	Oid			nspOid;
+ 
+ 	Assert(list_length(argam) == 1);
+ 	amOid = get_am_oid(access_method, false);
+ 
+ 	rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
+ 
+ 	/*
+ 	 * Look up the opfamily
+ 	 */
+ 	DeconstructQualifiedName(name, &schemaname, &opfname);
+ 
+ 	if (schemaname)
+ 	{
+ 		Oid			namespaceOid;
+ 
+ 		namespaceOid = LookupExplicitNamespace(schemaname);
+ 
+ 		tup = SearchSysCacheCopy3(OPFAMILYAMNAMENSP,
+ 								  ObjectIdGetDatum(amOid),
+ 								  PointerGetDatum(opfname),
+ 								  ObjectIdGetDatum(namespaceOid));
+ 		if (!HeapTupleIsValid(tup))
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_UNDEFINED_OBJECT),
+ 					 errmsg("operator family \"%s\" does not exist for access method \"%s\"",
+ 							opfname, access_method)));
+ 	}
+ 	else
+ 	{
+ 		Oid			opfOid;
+ 
+ 		opfOid = OpfamilynameGetOpfid(amOid, opfname);
+ 		if (!OidIsValid(opfOid))
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_UNDEFINED_OBJECT),
+ 					 errmsg("operator family \"%s\" does not exist for access method \"%s\"",
+ 							opfname, access_method)));
+ 
+ 		tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfOid));
+ 		if (!HeapTupleIsValid(tup))		/* should not happen */
+ 			elog(ERROR, "cache lookup failed for opfamily %u", opfOid);
+ 	}
+ 
+ 	/* get schema OID */
+ 	nspOid = LookupCreationNamespace(newschema);
+ 
+ 	AlterObjectNamespace(rel, OPFAMILYOID, OperatorFamilyRelationId,
+ 						 HeapTupleGetOid(tup), nspOid,
+ 						 Anum_pg_opfamily_opfname,
+ 						 Anum_pg_opfamily_opfnamespace,
+ 						 Anum_pg_opfamily_opfowner,
+ 						 ACL_KIND_OPFAMILY,
+ 						 false);
+ 
+ 	heap_freetuple(tup);
+ 	heap_close(rel, NoLock);
+ }
+ 
+ void
+ AlterOpFamilyNamespace_oid(Oid opfamilyOid, Oid newNspOid)
+ {
+ 	HeapTuple	tup;
+ 	Relation	rel;
+ 
+ 	rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
+ 
+ 	tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfamilyOid));
+ 	if (!HeapTupleIsValid(tup))
+ 		elog(ERROR, "cache lookup failed for opfamily %u", opfamilyOid);
+ 
+ 	AlterObjectNamespace(rel, OPFAMILYOID, OperatorFamilyRelationId,
+ 						 opfamilyOid, newNspOid,
+ 						 Anum_pg_opfamily_opfname,
+ 						 Anum_pg_opfamily_opfnamespace,
+ 						 Anum_pg_opfamily_opfowner,
+ 						 ACL_KIND_OPFAMILY,
+ 						 false);
+ 
+ 	heap_freetuple(tup);
+ 	heap_close(rel, NoLock);
+ }
*** a/src/backend/commands/operatorcmds.c
--- b/src/backend/commands/operatorcmds.c
***************
*** 39,45 ****
--- 39,47 ----
  #include "catalog/indexing.h"
  #include "catalog/namespace.h"
  #include "catalog/pg_operator.h"
+ #include "catalog/pg_namespace.h"
  #include "catalog/pg_type.h"
+ #include "commands/alter.h"
  #include "commands/defrem.h"
  #include "miscadmin.h"
  #include "parser/parse_func.h"
***************
*** 452,454 **** AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId)
--- 454,505 ----
  
  	heap_freetuple(tup);
  }
+ 
+ /*
+  * Execute ALTER OPERATOR SET SCHEMA
+  */
+ void
+ AlterOperatorNamespace(List *names, List *argtypes, const char *newschema)
+ {
+ 	List	   *operatorName = names;
+ 	TypeName   *typeName1 = (TypeName *) linitial(argtypes);
+ 	TypeName   *typeName2 = (TypeName *) lsecond(argtypes);
+ 	Oid			operOid, nspOid;
+ 	Relation	rel;
+ 
+ 	rel = heap_open(OperatorRelationId, RowExclusiveLock);
+ 
+ 	Assert(list_length(argtypes) == 2);
+ 	operOid = LookupOperNameTypeNames(NULL, operatorName,
+ 									  typeName1, typeName2,
+ 									  false, -1);
+ 
+ 	/* get schema OID */
+ 	nspOid = LookupCreationNamespace(newschema);
+ 
+ 	AlterObjectNamespace(rel, OPEROID, OperatorRelationId, operOid, nspOid,
+ 						 Anum_pg_operator_oprname,
+ 						 Anum_pg_operator_oprnamespace,
+ 						 Anum_pg_operator_oprowner,
+ 						 ACL_KIND_OPER,
+ 						 false);
+ 
+ 	heap_close(rel, NoLock);
+ }
+ 
+ void
+ AlterOperatorNamespace_oid(Oid operOid, Oid newNspOid)
+ {
+ 	Relation	rel;
+ 
+ 	rel = heap_open(OperatorRelationId, RowExclusiveLock);
+ 
+ 	AlterObjectNamespace(rel, OPEROID, OperatorRelationId, operOid, newNspOid,
+ 						 Anum_pg_operator_oprname,
+ 						 Anum_pg_operator_oprnamespace,
+ 						 Anum_pg_operator_oprowner,
+ 						 ACL_KIND_OPER,
+ 						 false);
+ 
+ 	heap_close(rel, NoLock);
+ }
*** a/src/backend/commands/tsearchcmds.c
--- b/src/backend/commands/tsearchcmds.c
***************
*** 31,36 ****
--- 31,37 ----
  #include "catalog/pg_ts_parser.h"
  #include "catalog/pg_ts_template.h"
  #include "catalog/pg_type.h"
+ #include "commands/alter.h"
  #include "commands/defrem.h"
  #include "miscadmin.h"
  #include "nodes/makefuncs.h"
***************
*** 393,398 **** RenameTSParser(List *oldname, const char *newname)
--- 394,438 ----
  	heap_freetuple(tup);
  }
  
+ /*
+  * ALTER TEXT SEARCH PARSER any_name SET SCHEMA name
+  */
+ void
+ AlterTSParserNamespace(List *name, const char *newschema)
+ {
+ 	Oid			prsId, nspOid;
+ 	Relation	rel;
+ 
+ 	rel = heap_open(TSParserRelationId, RowExclusiveLock);
+ 
+ 	prsId = get_ts_parser_oid(name, false);
+ 
+ 	/* get schema OID */
+ 	nspOid = LookupCreationNamespace(newschema);
+ 
+ 	AlterObjectNamespace(rel, TSPARSEROID, TSParserRelationId, prsId, nspOid,
+ 						 Anum_pg_ts_parser_prsname,
+ 						 Anum_pg_ts_parser_prsnamespace,
+ 						 -1, -1, true);
+ 
+ 	heap_close(rel, NoLock);
+ }
+ 
+ void
+ AlterTSParserNamespace_oid(Oid prsId, Oid newNspOid)
+ {
+ 	Relation	rel;
+ 
+ 	rel = heap_open(TSParserRelationId, RowExclusiveLock);
+ 
+ 	AlterObjectNamespace(rel, TSPARSEROID, TSParserRelationId, prsId, newNspOid,
+ 						 Anum_pg_ts_parser_prsname,
+ 						 Anum_pg_ts_parser_prsnamespace,
+ 						 -1, -1, true);
+ 
+ 	heap_close(rel, NoLock);
+ }
+ 
  /* ---------------------- TS Dictionary commands -----------------------*/
  
  /*
***************
*** 620,625 **** RenameTSDictionary(List *oldname, const char *newname)
--- 660,708 ----
  }
  
  /*
+  * ALTER TEXT SEARCH PARSER any_name SET SCHEMA name
+  */
+ void
+ AlterTSDictionaryNamespace(List *name, const char *newschema)
+ {
+ 	Oid			dictId, nspOid;
+ 	Relation	rel;
+ 
+ 	rel = heap_open(TSDictionaryRelationId, RowExclusiveLock);
+ 
+ 	dictId = get_ts_dict_oid(name, false);
+ 
+ 	/* get schema OID */
+ 	nspOid = LookupCreationNamespace(newschema);
+ 
+ 	AlterObjectNamespace(rel, TSDICTOID, TSDictionaryRelationId, dictId, nspOid,
+ 						 Anum_pg_ts_dict_dictname,
+ 						 Anum_pg_ts_dict_dictnamespace,
+ 						 Anum_pg_ts_dict_dictowner,
+ 						 ACL_KIND_TSDICTIONARY,
+ 						 true);
+ 
+ 	heap_close(rel, NoLock);
+ }
+ 
+ void
+ AlterTSDictionaryNamespace_oid(Oid dictId, Oid newNspOid)
+ {
+ 	Relation	rel;
+ 
+ 	rel = heap_open(TSDictionaryRelationId, RowExclusiveLock);
+ 
+ 	AlterObjectNamespace(rel, TSDICTOID, TSDictionaryRelationId, dictId, newNspOid,
+ 						 Anum_pg_ts_dict_dictname,
+ 						 Anum_pg_ts_dict_dictnamespace,
+ 						 Anum_pg_ts_dict_dictowner,
+ 						 ACL_KIND_TSDICTIONARY,
+ 						 false);
+ 
+ 	heap_close(rel, NoLock);
+ }
+ 
+ /*
   * DROP TEXT SEARCH DICTIONARY
   */
  void
***************
*** 1100,1105 **** RenameTSTemplate(List *oldname, const char *newname)
--- 1183,1230 ----
  }
  
  /*
+  * ALTER TEXT SEARCH TEMPLATE any_name SET SCHEMA name
+  */
+ void
+ AlterTSTemplateNamespace(List *name, const char *newschema)
+ {
+ 	Oid			tmplId, nspOid;
+ 	Relation	rel;
+ 
+ 	rel = heap_open(TSTemplateRelationId, RowExclusiveLock);
+ 
+ 	tmplId = get_ts_template_oid(name, false);
+ 
+ 	/* get schema OID */
+ 	nspOid = LookupCreationNamespace(newschema);
+ 
+ 	AlterObjectNamespace(rel, TSTEMPLATEOID, TSTemplateRelationId,
+ 						 tmplId, nspOid,
+ 						 Anum_pg_ts_template_tmplname,
+ 						 Anum_pg_ts_template_tmplnamespace,
+ 						 -1, -1, true);
+ 
+ 	heap_close(rel, NoLock);
+ }
+ 
+ void
+ AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid)
+ {
+ 	Relation	rel;
+ 
+ 	rel = heap_open(TSTemplateRelationId, RowExclusiveLock);
+ 
+ 	AlterObjectNamespace(rel, TSTEMPLATEOID, TSTemplateRelationId,
+ 						 tmplId, newNspOid,
+ 						 Anum_pg_ts_template_tmplname,
+ 						 Anum_pg_ts_template_tmplnamespace,
+ 						 -1, -1, true);
+ 
+ 	heap_close(rel, NoLock);
+ }
+ 
+ 
+ /*
   * DROP TEXT SEARCH TEMPLATE
   */
  void
***************
*** 1498,1503 **** RenameTSConfiguration(List *oldname, const char *newname)
--- 1623,1672 ----
  }
  
  /*
+  * ALTER TEXT SEARCH CONFIGURATION any_name SET SCHEMA name
+  */
+ void
+ AlterTSConfigurationNamespace(List *name, const char *newschema)
+ {
+ 	Oid			cfgId, nspOid;
+ 	Relation	rel;
+ 
+ 	rel = heap_open(TSConfigRelationId, RowExclusiveLock);
+ 
+ 	cfgId = get_ts_config_oid(name, false);
+ 
+ 	/* get schema OID */
+ 	nspOid = LookupCreationNamespace(newschema);
+ 
+ 	AlterObjectNamespace(rel, TSCONFIGOID, TSConfigRelationId, cfgId, nspOid,
+ 						 Anum_pg_ts_config_cfgname,
+ 						 Anum_pg_ts_config_cfgnamespace,
+ 						 Anum_pg_ts_config_cfgowner,
+ 						 ACL_KIND_TSCONFIGURATION,
+ 						 false);
+ 
+ 	heap_close(rel, NoLock);
+ }
+ 
+ void
+ AlterTSConfigurationNamespace_oid(Oid cfgId, Oid newNspOid)
+ {
+ 	Relation	rel;
+ 
+ 	rel = heap_open(TSConfigRelationId, RowExclusiveLock);
+ 
+ 	AlterObjectNamespace(rel, TSCONFIGOID, TSConfigRelationId, cfgId, newNspOid,
+ 						 Anum_pg_ts_config_cfgname,
+ 						 Anum_pg_ts_config_cfgnamespace,
+ 						 Anum_pg_ts_config_cfgowner,
+ 						 ACL_KIND_TSCONFIGURATION,
+ 						 false);
+ 
+ 	heap_close(rel, NoLock);
+ }
+ 
+ 
+ /*
   * DROP TEXT SEARCH CONFIGURATION
   */
  void
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 6040,6045 **** AlterObjectSchemaStmt:
--- 6040,6053 ----
  					n->newschema = $7;
  					$$ = (Node *)n;
  				}
+ 			| ALTER CONVERSION_P any_name SET SCHEMA name
+ 				{
+ 					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ 					n->objectType = OBJECT_CONVERSION;
+ 					n->object = $3;
+ 					n->newschema = $6;
+ 					$$ = (Node *)n;
+ 				}
  			| ALTER DOMAIN_P any_name SET SCHEMA name
  				{
  					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
***************
*** 6057,6062 **** AlterObjectSchemaStmt:
--- 6065,6097 ----
  					n->newschema = $6;
  					$$ = (Node *)n;
  				}
+ 			| ALTER OPERATOR any_operator oper_argtypes SET SCHEMA name
+ 				{
+ 					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ 					n->objectType = OBJECT_OPERATOR;
+ 					n->object = $3;
+ 					n->objarg = $4;
+ 					n->newschema = $7;
+ 					$$ = (Node *)n;
+ 				}
+ 			| ALTER OPERATOR CLASS any_name USING access_method SET SCHEMA name
+ 				{
+ 					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ 					n->objectType = OBJECT_OPCLASS;
+ 					n->object = $4;
+ 					n->objarg = list_make1($6);
+ 					n->newschema = $9;
+ 					$$ = (Node *)n;
+ 				}
+ 			| ALTER OPERATOR FAMILY any_name USING access_method SET SCHEMA name
+ 				{
+ 					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ 					n->objectType = OBJECT_OPFAMILY;
+ 					n->object = $4;
+ 					n->objarg = list_make1($6);
+ 					n->newschema = $9;
+ 					$$ = (Node *)n;
+ 				}
  			| ALTER TABLE relation_expr SET SCHEMA name
  				{
  					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
***************
*** 6065,6070 **** AlterObjectSchemaStmt:
--- 6100,6137 ----
  					n->newschema = $6;
  					$$ = (Node *)n;
  				}
+ 			| ALTER TEXT_P SEARCH PARSER any_name SET SCHEMA name
+ 				{
+ 					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ 					n->objectType = OBJECT_TSPARSER;
+ 					n->object = $5;
+ 					n->newschema = $8;
+ 					$$ = (Node *)n;
+ 				}
+ 			| ALTER TEXT_P SEARCH DICTIONARY any_name SET SCHEMA name
+ 				{
+ 					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ 					n->objectType = OBJECT_TSDICTIONARY;
+ 					n->object = $5;
+ 					n->newschema = $8;
+ 					$$ = (Node *)n;
+ 				}
+ 			| ALTER TEXT_P SEARCH TEMPLATE any_name SET SCHEMA name
+ 				{
+ 					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ 					n->objectType = OBJECT_TSTEMPLATE;
+ 					n->object = $5;
+ 					n->newschema = $8;
+ 					$$ = (Node *)n;
+ 				}
+ 			| ALTER TEXT_P SEARCH CONFIGURATION any_name SET SCHEMA name
+ 				{
+ 					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ 					n->objectType = OBJECT_TSCONFIGURATION;
+ 					n->object = $5;
+ 					n->newschema = $8;
+ 					$$ = (Node *)n;
+ 				}
  			| ALTER SEQUENCE qualified_name SET SCHEMA name
  				{
  					AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
***************
*** 1694,1702 **** CreateCommandTag(Node *parsetree)
--- 1694,1714 ----
  				case OBJECT_AGGREGATE:
  					tag = "ALTER AGGREGATE";
  					break;
+ 				case OBJECT_CONVERSION:
+ 					tag = "ALTER CONVERSION";
+ 					break;
  				case OBJECT_DOMAIN:
  					tag = "ALTER DOMAIN";
  					break;
+ 				case OBJECT_OPERATOR:
+ 					tag = "ALTER OPERATOR";
+ 					break;
+ 				case OBJECT_OPCLASS:
+ 					tag = "ALTER OPERATOR CLASS";
+ 					break;
+ 				case OBJECT_OPFAMILY:
+ 					tag = "ALTER OPERATOR FAMILY";
+ 					break;
  				case OBJECT_FUNCTION:
  					tag = "ALTER FUNCTION";
  					break;
*** a/src/include/catalog/dependency.h
--- b/src/include/catalog/dependency.h
***************
*** 166,171 **** extern ObjectClass getObjectClass(const ObjectAddress *object);
--- 166,173 ----
  
  extern char *getObjectDescription(const ObjectAddress *object);
  
+ extern char *getObjectDescriptionOids(Oid classid, Oid objid);
+ 
  extern ObjectAddresses *new_object_addresses(void);
  
  extern void add_exact_object_address(const ObjectAddress *object,
*** a/src/include/catalog/namespace.h
--- b/src/include/catalog/namespace.h
***************
*** 94,99 **** extern Oid	LookupExplicitNamespace(const char *nspname);
--- 94,101 ----
  extern Oid	get_namespace_oid(const char *nspname, bool missing_ok);
  
  extern Oid	LookupCreationNamespace(const char *nspname);
+ extern void CheckSetNamespace(Oid oldNspOid, Oid nspOid, Oid classid,
+ 							  Oid objid);
  extern Oid	QualifiedNameGetCreationNamespace(List *names, char **objname_p);
  extern RangeVar *makeRangeVarFromNameList(List *names);
  extern char *NameListToString(List *names);
*** a/src/include/commands/alter.h
--- b/src/include/commands/alter.h
***************
*** 15,23 ****
--- 15,30 ----
  #define ALTER_H
  
  #include "nodes/parsenodes.h"
+ #include "utils/acl.h"
+ #include "utils/relcache.h"
  
  extern void ExecRenameStmt(RenameStmt *stmt);
  extern void ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
+ extern void AlterObjectNamespace(Relation rel, int cacheId,
+ 								 Oid classId, Oid objid, Oid nspId,
+ 								 int Anum_name, int Anum_namespace, int Anum_owner,
+ 								 AclObjectKind acl_kind,
+ 								 bool superuser_only);
  extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
  
  #endif   /* ALTER_H */
*** a/src/include/commands/conversioncmds.h
--- b/src/include/commands/conversioncmds.h
***************
*** 22,26 **** extern void DropConversionsCommand(DropStmt *drop);
--- 22,29 ----
  extern void RenameConversion(List *name, const char *newname);
  extern void AlterConversionOwner(List *name, Oid newOwnerId);
  extern void AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId);
+ extern void AlterConversionNamespace(List *name, const char *newschema);
+ extern void AlterConversionNamespace_oid(Oid convOid, Oid newNspOid);
+ 
  
  #endif   /* CONVERSIONCMDS_H */
*** a/src/include/commands/defrem.h
--- b/src/include/commands/defrem.h
***************
*** 66,71 **** extern void DropCast(DropCastStmt *stmt);
--- 66,72 ----
  extern void DropCastById(Oid castOid);
  extern void AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
  					   const char *newschema);
+ extern void AlterFunctionNamespace_oid(Oid procOid, Oid nspOid);
  extern void ExecuteDoStmt(DoStmt *stmt);
  extern Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok);
  
***************
*** 78,83 **** extern void AlterOperatorOwner(List *name, TypeName *typeName1,
--- 79,86 ----
  extern void AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId);
  extern Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok);
  extern Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok);
+ extern void AlterOperatorNamespace_oid(Oid operOid, Oid newNspOid);
+ extern void AlterOperatorNamespace(List *names, List *argtypes, const char *newschema);
  
  /* commands/aggregatecmds.c */
  extern void DefineAggregate(List *name, List *args, bool oldstyle,
***************
*** 100,114 **** extern void RenameOpClass(List *name, const char *access_method, const char *new
--- 103,123 ----
  extern void RenameOpFamily(List *name, const char *access_method, const char *newname);
  extern void AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId);
  extern void AlterOpClassOwner_oid(Oid opclassOid, Oid newOwnerId);
+ extern void AlterOpClassNamespace(List *name, List *argam, const char *newschema);
+ extern void AlterOpClassNamespace_oid(Oid opclassOid, Oid newNspOid);
  extern void AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwnerId);
  extern void AlterOpFamilyOwner_oid(Oid opfamilyOid, Oid newOwnerId);
  extern Oid get_am_oid(const char *amname, bool missing_ok);
+ extern void AlterOpFamilyNamespace(List *name, List *argam, const char *newschema);
+ extern void AlterOpFamilyNamespace_oid(Oid opfamilyOid, Oid newNspOid);
  
  /* commands/tsearchcmds.c */
  extern void DefineTSParser(List *names, List *parameters);
  extern void RenameTSParser(List *oldname, const char *newname);
  extern void RemoveTSParsers(DropStmt *drop);
  extern void RemoveTSParserById(Oid prsId);
+ extern void AlterTSParserNamespace(List *name, const char *newschema);
+ extern void AlterTSParserNamespace_oid(Oid prsId, Oid newNspOid);
  
  extern void DefineTSDictionary(List *names, List *parameters);
  extern void RenameTSDictionary(List *oldname, const char *newname);
***************
*** 116,129 **** extern void RemoveTSDictionaries(DropStmt *drop);
--- 125,144 ----
  extern void RemoveTSDictionaryById(Oid dictId);
  extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt);
  extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId);
+ extern void AlterTSDictionaryNamespace(List *name, const char *newschema);
+ extern void AlterTSDictionaryNamespace_oid(Oid dictId, Oid newNspOid);
  
  extern void DefineTSTemplate(List *names, List *parameters);
  extern void RenameTSTemplate(List *oldname, const char *newname);
+ extern void AlterTSTemplateNamespace(List *name, const char *newschema);
+ extern void AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid);
  extern void RemoveTSTemplates(DropStmt *stmt);
  extern void RemoveTSTemplateById(Oid tmplId);
  
  extern void DefineTSConfiguration(List *names, List *parameters);
  extern void RenameTSConfiguration(List *oldname, const char *newname);
+ extern void AlterTSConfigurationNamespace(List *name, const char *newschema);
+ extern void AlterTSConfigurationNamespace_oid(Oid cfgId, Oid newNspOid);
  extern void RemoveTSConfigurations(DropStmt *stmt);
  extern void RemoveTSConfigurationById(Oid cfgId);
  extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
*** a/src/test/regress/expected/alter_table.out
--- b/src/test/regress/expected/alter_table.out
***************
*** 1645,1657 **** create view alter1.v1 as select * from alter1.t1;
--- 1645,1676 ----
  create function alter1.plus1(int) returns int as 'select $1+1' language sql;
  create domain alter1.posint integer check (value > 0);
  create type alter1.ctype as (f1 int, f2 text);
+ create function alter1.same(alter1.ctype, alter1.ctype) returns boolean language sql 
+ as 'select $1.f1 is not distinct from $2.f1 and $1.f2 is not distinct from $2.f2';
+ create operator alter1.=(procedure = alter1.same, leftarg  = alter1.ctype, rightarg = alter1.ctype);
+ create operator class alter1.ctype_hash_ops default for type alter1.ctype using hash as
+   operator 1 alter1.=(alter1.ctype, alter1.ctype);
+ create conversion alter1.ascii_to_utf8 for 'sql_ascii' to 'utf8' from ascii_to_utf8;
+ create text search parser alter1.prs(start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype);
+ create text search configuration alter1.cfg(parser = alter1.prs);
+ create text search template alter1.tmpl(init = dsimple_init, lexize = dsimple_lexize);
+ create text search dictionary alter1.dict(template = alter1.tmpl);
  insert into alter1.t1(f2) values(11);
  insert into alter1.t1(f2) values(12);
  alter table alter1.t1 set schema alter2;
  alter table alter1.v1 set schema alter2;
  alter function alter1.plus1(int) set schema alter2;
  alter domain alter1.posint set schema alter2;
+ alter operator class alter1.ctype_hash_ops using hash set schema alter2;
+ alter operator family alter1.ctype_hash_ops using hash set schema alter2;
+ alter operator alter1.=(alter1.ctype, alter1.ctype) set schema alter2;
+ alter function alter1.same(alter1.ctype, alter1.ctype) set schema alter2;
  alter type alter1.ctype set schema alter2;
+ alter conversion alter1.ascii_to_utf8 set schema alter2;
+ alter text search parser alter1.prs set schema alter2;
+ alter text search configuration alter1.cfg set schema alter2;
+ alter text search template alter1.tmpl set schema alter2;
+ alter text search dictionary alter1.dict set schema alter2;
  -- this should succeed because nothing is left in alter1
  drop schema alter1;
  insert into alter2.t1(f2) values(13);
***************
*** 1682,1693 **** select alter2.plus1(41);
  
  -- clean up
  drop schema alter2 cascade;
! NOTICE:  drop cascades to 5 other objects
  DETAIL:  drop cascades to table alter2.t1
  drop cascades to view alter2.v1
  drop cascades to function alter2.plus1(integer)
  drop cascades to type alter2.posint
  drop cascades to type alter2.ctype
  --
  -- composite types
  --
--- 1701,1720 ----
  
  -- clean up
  drop schema alter2 cascade;
! NOTICE:  drop cascades to 13 other objects
  DETAIL:  drop cascades to table alter2.t1
  drop cascades to view alter2.v1
  drop cascades to function alter2.plus1(integer)
  drop cascades to type alter2.posint
+ drop cascades to operator family alter2.ctype_hash_ops for access method hash
  drop cascades to type alter2.ctype
+ drop cascades to function alter2.same(alter2.ctype,alter2.ctype)
+ drop cascades to operator alter2.=(alter2.ctype,alter2.ctype)
+ drop cascades to conversion ascii_to_utf8
+ drop cascades to text search parser prs
+ drop cascades to text search configuration cfg
+ drop cascades to text search template tmpl
+ drop cascades to text search dictionary dict
  --
  -- composite types
  --
*** a/src/test/regress/sql/alter_table.sql
--- b/src/test/regress/sql/alter_table.sql
***************
*** 1206,1211 **** create domain alter1.posint integer check (value > 0);
--- 1206,1226 ----
  
  create type alter1.ctype as (f1 int, f2 text);
  
+ create function alter1.same(alter1.ctype, alter1.ctype) returns boolean language sql 
+ as 'select $1.f1 is not distinct from $2.f1 and $1.f2 is not distinct from $2.f2';
+ 
+ create operator alter1.=(procedure = alter1.same, leftarg  = alter1.ctype, rightarg = alter1.ctype);
+ 
+ create operator class alter1.ctype_hash_ops default for type alter1.ctype using hash as
+   operator 1 alter1.=(alter1.ctype, alter1.ctype);
+ 
+ create conversion alter1.ascii_to_utf8 for 'sql_ascii' to 'utf8' from ascii_to_utf8;
+ 
+ create text search parser alter1.prs(start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype);
+ create text search configuration alter1.cfg(parser = alter1.prs);
+ create text search template alter1.tmpl(init = dsimple_init, lexize = dsimple_lexize);
+ create text search dictionary alter1.dict(template = alter1.tmpl);
+ 
  insert into alter1.t1(f2) values(11);
  insert into alter1.t1(f2) values(12);
  
***************
*** 1213,1219 **** alter table alter1.t1 set schema alter2;
--- 1228,1243 ----
  alter table alter1.v1 set schema alter2;
  alter function alter1.plus1(int) set schema alter2;
  alter domain alter1.posint set schema alter2;
+ alter operator class alter1.ctype_hash_ops using hash set schema alter2;
+ alter operator family alter1.ctype_hash_ops using hash set schema alter2;
+ alter operator alter1.=(alter1.ctype, alter1.ctype) set schema alter2;
+ alter function alter1.same(alter1.ctype, alter1.ctype) set schema alter2;
  alter type alter1.ctype set schema alter2;
+ alter conversion alter1.ascii_to_utf8 set schema alter2;
+ alter text search parser alter1.prs set schema alter2;
+ alter text search configuration alter1.cfg set schema alter2;
+ alter text search template alter1.tmpl set schema alter2;
+ alter text search dictionary alter1.dict set schema alter2;
  
  -- this should succeed because nothing is left in alter1
  drop schema alter1;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to