Add more ALTER <object> .. SET SCHEMA commands.
authorRobert Haas <[email protected]>
Fri, 26 Nov 2010 22:27:23 +0000 (17:27 -0500)
committerRobert Haas <[email protected]>
Fri, 26 Nov 2010 22:31:54 +0000 (17:31 -0500)
This adds support for changing the schema of a conversion, operator,
operator class, operator family, text search configuration, text search
dictionary, text search parser, or text search template.

Dimitri Fontaine, with assorted corrections and other kibitzing.

21 files changed:
doc/src/sgml/ref/alter_conversion.sgml
doc/src/sgml/ref/alter_opclass.sgml
doc/src/sgml/ref/alter_operator.sgml
doc/src/sgml/ref/alter_opfamily.sgml
doc/src/sgml/ref/alter_tsconfig.sgml
doc/src/sgml/ref/alter_tsdictionary.sgml
doc/src/sgml/ref/alter_tsparser.sgml
doc/src/sgml/ref/alter_tstemplate.sgml
src/backend/commands/alter.c
src/backend/commands/conversioncmds.c
src/backend/commands/opclasscmds.c
src/backend/commands/operatorcmds.c
src/backend/commands/tsearchcmds.c
src/backend/parser/gram.y
src/backend/tcop/utility.c
src/bin/psql/tab-complete.c
src/include/commands/alter.h
src/include/commands/conversioncmds.h
src/include/commands/defrem.h
src/test/regress/expected/alter_table.out
src/test/regress/sql/alter_table.sql

index 0ad8fff18263ec51ed6f92e984774ad86f611434..4f2269b84990837c51324a1283527da94be830ae 100644 (file)
@@ -23,6 +23,7 @@ PostgreSQL documentation
 <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,6 +76,15 @@ ALTER CONVERSION <replaceable>name</replaceable> OWNER TO <replaceable>new_owner
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">new_schema</replaceable></term>
+    <listitem>
+     <para>
+      The new schema for the conversion.
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
  </refsect1>
 
index 90c53c6c05dca3b79aca305ec3732acac0657bde..c70f6cd6a2b7f7f5a699a9b5531e0d83d28302de 100644 (file)
@@ -23,6 +23,7 @@ PostgreSQL documentation
 <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,6 +86,15 @@ ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="p
      </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>
 
index 615a1a66d39607f3053e4602a097d8c2a4ef4fba..a52f9f9cb460fd3bbc58904b46d90a88fc8ad754 100644 (file)
@@ -22,6 +22,7 @@ PostgreSQL documentation
  <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,6 +86,15 @@ ALTER OPERATOR <replaceable>name</replaceable> ( { <replaceable>left_type</repla
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">new_schema</replaceable></term>
+    <listitem>
+     <para>
+      The new schema for the operator.
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
  </refsect1>
 
index 3c8ca21f61e996ea0195a71ed1fe846855af0938..e22b4728d9c98f18331f55089201c409ca7d5b8d 100644 (file)
@@ -31,6 +31,7 @@ ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="
   } [, ... ]
 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>
 
@@ -216,6 +217,15 @@ ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class="
      </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>
index 95843ac93e7310679e017fac9b204a71f4cc0fcb..deef329b295f2bffa7652669f40a5cdf8503a3e7 100644 (file)
@@ -33,6 +33,7 @@ ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable>
     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,6 +124,15 @@ ALTER TEXT SEARCH CONFIGURATION <replaceable>name</replaceable> OWNER TO <replac
      </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>
index 6858b9143a1fb8d8579e4ec5d3eab1cd38252f0d..7c12037041552e13dd8be5c5168a827a834dbea9 100644 (file)
@@ -26,6 +26,7 @@ ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> (
 )
 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,6 +97,15 @@ ALTER TEXT SEARCH DICTIONARY <replaceable>name</replaceable> OWNER TO <replaceab
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">new_schema</replaceable></term>
+    <listitem>
+     <para>
+      The new schema for the text search dictionary.
+     </para>
+    </listitem>
+   </varlistentry>
  </variablelist>
 
   <para>
index 2de260a7abd17a7a5886cad68a617cdc813dc785..8c082433b05276c0db5dcb832ec182261aa88c15 100644 (file)
@@ -22,6 +22,7 @@ PostgreSQL documentation
  <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,6 +61,15 @@ ALTER TEXT SEARCH PARSER <replaceable>name</replaceable> RENAME TO <replaceable>
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">new_schema</replaceable></term>
+    <listitem>
+     <para>
+      The new schema for the text search parser.
+     </para>
+    </listitem>
+   </varlistentry>
  </variablelist>
  </refsect1>
 
index b729fdee9124903ab766b3fbca74a54ac2752872..e4f0ff3b1eb7e002e1343b42f1cc3f415ce9bd66 100644 (file)
@@ -22,6 +22,7 @@ PostgreSQL documentation
  <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,6 +61,15 @@ ALTER TEXT SEARCH TEMPLATE <replaceable>name</replaceable> RENAME TO <replaceabl
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">new_schema</replaceable></term>
+    <listitem>
+     <para>
+      The new schema for the text search template.
+     </para>
+    </listitem>
+   </varlistentry>
  </variablelist>
  </refsect1>
 
index 0d0227d04ad96f0389e7caa2be797f220970562b..6c9ba1eb3595d95bbfb4fce67c17ee51416d20d7 100644 (file)
  */
 #include "postgres.h"
 
+#include "catalog/dependency.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,6 +36,7 @@
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
+#include "utils/syscache.h"
 
 
 /*
@@ -178,11 +182,27 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
                                   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:
@@ -191,6 +211,22 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
                                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);
@@ -202,6 +238,104 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
    }
 }
 
+/*
+ * 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;
+   bool       *nulls;
+   bool       *replaces;
+
+   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 to update tuple */
+   values = palloc0(rel->rd_att->natts * sizeof(Datum));
+   nulls = palloc0(rel->rd_att->natts * sizeof(bool));
+   replaces = palloc0(rel->rd_att->natts * sizeof(bool));
+   values[Anum_namespace - 1] = nspOid;
+   replaces[Anum_namespace - 1] = true;
+   newtup = heap_modify_tuple(tup, rel->rd_att, values, nulls, replaces);
+
+   /* Perform actual update */
+   simple_heap_update(rel, &tup->t_self, newtup);
+   CatalogUpdateIndexes(rel, newtup);
+
+   /* Release memory */
+   pfree(values);
+   pfree(nulls);
+   pfree(replaces);
+
+   /* 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.
index 73a3d026e1ed1456250255b29fa468681b00a656..521132a5e5aa98a3d4d500aca94181783d54b838 100644 (file)
@@ -19,7 +19,9 @@
 #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"
@@ -326,3 +328,29 @@ AlterConversionOwner_internal(Relation rel, Oid conversionOid, Oid newOwnerId)
 
    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);
+}
index 5055fb17cde0964c26b12a4917de2e9af0f42875..5598d82270959e9c435a5b4a6b2e42e6cca673a7 100644 (file)
@@ -31,6 +31,7 @@
 #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"
@@ -1988,6 +1989,41 @@ AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
    }
 }
 
+/*
+ * 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;
+   Oid         oid;
+   Oid         nspOid;
+
+   Assert(list_length(argam) == 1);
+
+   amOid = get_am_oid(access_method, false);
+
+   rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
+
+   /* Look up the opclass. */
+   oid = get_opclass_oid(amOid, name, false);
+
+   /* get schema OID */
+   nspOid = LookupCreationNamespace(newschema);
+
+   AlterObjectNamespace(rel, CLAOID, OperatorClassRelationId,
+                        oid, nspOid,
+                        Anum_pg_opfamily_opfname,
+                        Anum_pg_opfamily_opfnamespace,
+                        Anum_pg_opfamily_opfowner,
+                        ACL_KIND_OPCLASS,
+                        false);
+
+   heap_close(rel, NoLock);
+}
+
 /*
  * Change opfamily owner by name
  */
@@ -2144,3 +2180,37 @@ get_am_oid(const char *amname, bool missing_ok)
                 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;
+   Oid         nspOid;
+   Oid         oid;
+
+   Assert(list_length(argam) == 1);
+   amOid = get_am_oid(access_method, false);
+
+   rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
+
+   /* Look up the opfamily */
+   oid = get_opfamily_oid(amOid, name, false);
+
+   /* get schema OID */
+   nspOid = LookupCreationNamespace(newschema);
+
+   AlterObjectNamespace(rel, OPFAMILYOID, OperatorFamilyRelationId,
+                        oid, nspOid,
+                        Anum_pg_opfamily_opfname,
+                        Anum_pg_opfamily_opfnamespace,
+                        Anum_pg_opfamily_opfowner,
+                        ACL_KIND_OPFAMILY,
+                        false);
+
+   heap_close(rel, NoLock);
+}
index 503cf0f23db7c0274009cf8bc7d9957dec70d67d..2578eaf4f883e35b518b893ace01ff6321f9bee8 100644 (file)
@@ -39,7 +39,9 @@
 #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,3 +454,35 @@ AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId)
 
    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);
+}
index 412b1d278d5876cd90958478dc4740e361cfd776..6746ac0c62ced90655bb2184da84d81945aa9343 100644 (file)
@@ -32,6 +32,7 @@
 #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"
@@ -397,6 +398,30 @@ RenameTSParser(List *oldname, const char *newname)
    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);
+}
+
 /* ---------------------- TS Dictionary commands -----------------------*/
 
 /*
@@ -627,6 +652,32 @@ RenameTSDictionary(List *oldname, const char *newname)
    heap_freetuple(tup);
 }
 
+/*
+ * ALTER TEXT SEARCH DICTIONARY 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);
+}
+
 /*
  * DROP TEXT SEARCH DICTIONARY
  */
@@ -1110,6 +1161,31 @@ RenameTSTemplate(List *oldname, const char *newname)
    heap_freetuple(tup);
 }
 
+/*
+ * 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);
+}
+
 /*
  * DROP TEXT SEARCH TEMPLATE
  */
@@ -1511,6 +1587,32 @@ RenameTSConfiguration(List *oldname, const char *newname)
    heap_freetuple(tup);
 }
 
+/*
+ * 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);
+}
+
 /*
  * DROP TEXT SEARCH CONFIGURATION
  */
index 1c17be8921452ed6d43b59e2d3a251f602575b6c..9ec75f776cff61bd1ae497234c31154acb52c3dc 100644 (file)
@@ -6051,6 +6051,14 @@ AlterObjectSchemaStmt:
                    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);
@@ -6068,6 +6076,33 @@ AlterObjectSchemaStmt:
                    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);
@@ -6076,6 +6111,38 @@ AlterObjectSchemaStmt:
                    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);
index 2300e882499d52563aea46b57c85cd650ebdf37c..803c6036ab8f1a8a538d6e035c04c28da5b4655d 100644 (file)
@@ -1694,9 +1694,21 @@ CreateCommandTag(Node *parsetree)
                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;
index 2c368504ecf368670eece1c9c060ca15f46fcaa3..4c468a858cefd84f9525d47538c50f68b8caf919 100644 (file)
@@ -741,10 +741,9 @@ psql_completion(char *text, int start, int end)
        }
    }
 
-   /* ALTER CONVERSION,SCHEMA <name> */
+   /* ALTER SCHEMA <name> */
    else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
-            (pg_strcasecmp(prev2_wd, "CONVERSION") == 0 ||
-             pg_strcasecmp(prev2_wd, "SCHEMA") == 0))
+             pg_strcasecmp(prev2_wd, "SCHEMA") == 0)
    {
        static const char *const list_ALTERGEN[] =
        {"OWNER TO", "RENAME TO", NULL};
@@ -752,6 +751,16 @@ psql_completion(char *text, int start, int end)
        COMPLETE_WITH_LIST(list_ALTERGEN);
    }
 
+   /* ALTER CONVERSION <name> */
+   else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
+            pg_strcasecmp(prev2_wd, "CONVERSION") == 0)
+   {
+       static const char *const list_ALTERGEN[] =
+       {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL};
+
+       COMPLETE_WITH_LIST(list_ALTERGEN);
+   }
+
    /* ALTER DATABASE <name> */
    else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
             pg_strcasecmp(prev2_wd, "DATABASE") == 0)
@@ -1237,17 +1246,22 @@ psql_completion(char *text, int start, int end)
             pg_strcasecmp(prev3_wd, "SEARCH") == 0 &&
             (pg_strcasecmp(prev2_wd, "TEMPLATE") == 0 ||
              pg_strcasecmp(prev2_wd, "PARSER") == 0))
-       COMPLETE_WITH_CONST("RENAME TO");
+   {
+       static const char *const list_ALTERTEXTSEARCH2[] =
+       {"RENAME TO", "SET SCHEMA", NULL};
+
+       COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH2);
+   }
 
    else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
             pg_strcasecmp(prev4_wd, "TEXT") == 0 &&
             pg_strcasecmp(prev3_wd, "SEARCH") == 0 &&
             pg_strcasecmp(prev2_wd, "DICTIONARY") == 0)
    {
-       static const char *const list_ALTERTEXTSEARCH2[] =
-       {"OWNER TO", "RENAME TO", NULL};
+       static const char *const list_ALTERTEXTSEARCH3[] =
+       {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL};
 
-       COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH2);
+       COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH3);
    }
 
    else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
@@ -1255,10 +1269,10 @@ psql_completion(char *text, int start, int end)
             pg_strcasecmp(prev3_wd, "SEARCH") == 0 &&
             pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0)
    {
-       static const char *const list_ALTERTEXTSEARCH3[] =
-       {"ADD MAPPING FOR", "ALTER MAPPING", "DROP MAPPING FOR", "OWNER TO", "RENAME TO", NULL};
+       static const char *const list_ALTERTEXTSEARCH4[] =
+       {"ADD MAPPING FOR", "ALTER MAPPING", "DROP MAPPING FOR", "OWNER TO", "RENAME TO", "SET SCHEMA", NULL};
 
-       COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH3);
+       COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH4);
    }
 
    /* complete ALTER TYPE <foo> with actions */
index 5cee895f6c0e8e734cb5ffc7191cdebdb505fcd9..a833f19a7320c51fa439fb8fd9a5b633368bd941 100644 (file)
 #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 */
index 049e8c49acca5e581cdb8ff458cbc0d883d41a82..41056ea32057990a3a339e81808dad556d31750d 100644 (file)
@@ -22,5 +22,6 @@ extern void DropConversionsCommand(DropStmt *drop);
 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);
 
 #endif   /* CONVERSIONCMDS_H */
index 1dc1a7d1944bc6afc01b78efb3330e5742a5fd1b..86d62af9ed2b9e0c6098bb6842ce9426ac9b5875 100644 (file)
@@ -76,6 +76,7 @@ extern void RemoveOperatorById(Oid operOid);
 extern void AlterOperatorOwner(List *name, TypeName *typeName1,
                   TypeName *typename2, Oid newOwnerId);
 extern void AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId);
+extern void AlterOperatorNamespace(List *names, List *argtypes, const char *newschema);
 extern Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok);
 extern Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok);
 
@@ -100,13 +101,16 @@ extern void RenameOpClass(List *name, const char *access_method, const char *new
 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 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);
 
 /* commands/tsearchcmds.c */
 extern void DefineTSParser(List *names, List *parameters);
 extern void RenameTSParser(List *oldname, const char *newname);
+extern void AlterTSParserNamespace(List *name, const char *newschema);
 extern void RemoveTSParsers(DropStmt *drop);
 extern void RemoveTSParserById(Oid prsId);
 
@@ -116,9 +120,11 @@ extern void RemoveTSDictionaries(DropStmt *drop);
 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 DefineTSTemplate(List *names, List *parameters);
 extern void RenameTSTemplate(List *oldname, const char *newname);
+extern void AlterTSTemplateNamespace(List *name, const char *newschema);
 extern void RemoveTSTemplates(DropStmt *stmt);
 extern void RemoveTSTemplateById(Oid tmplId);
 
@@ -128,6 +134,7 @@ extern void RemoveTSConfigurations(DropStmt *stmt);
 extern void RemoveTSConfigurationById(Oid cfgId);
 extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
 extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId);
+extern void AlterTSConfigurationNamespace(List *name, const char *newschema);
 
 extern text *serialize_deflist(List *deflist);
 extern List *deserialize_deflist(Datum txt);
index b68dfd4fc2641d2fbb0d3d79dc9af0b1483c711d..e415730bd09fb67c57963ba819353c17efec67a3 100644 (file)
@@ -1645,13 +1645,32 @@ create view alter1.v1 as select * from alter1.t1;
 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,12 +1701,20 @@ select alter2.plus1(41);
 
 -- clean up
 drop schema alter2 cascade;
-NOTICE:  drop cascades to 5 other objects
+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
 --
index 98a68d587729cd49d375fe588b915ee04132c9c0..4895768d7feacb960d764c67752bb148e3f1e455 100644 (file)
@@ -1206,6 +1206,21 @@ 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);
 
@@ -1213,7 +1228,16 @@ 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;