Robert Haas <robertmh...@gmail.com> writes: > Please do. Tab completion support should really be included in the > patch - adding it as a separate patch is better than not having it, of > course.
Please find attached version 9 of the patch, which includes psql completion support of the "SET SCHEMA" variant of already supported ALTER commands. That means I didn't add ALTER OPERATOR [CLASS,FAMILY] completion support, my guess being there's no demand here, or the existing syntax variants would be there already. And if there's demand, I don't feel like it should be implemented as part of this very patch. 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> *************** *** 216,221 **** ALTER OPERATOR FAMILY <replaceable>name</replaceable> USING <replaceable class=" --- 217,231 ---- </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/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" /* *************** *** 178,188 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) --- 181,207 ---- 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,196 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) --- 210,231 ---- 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); *************** *** 203,208 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) --- 238,337 ---- } /* + * 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 *************** *** 1875,1887 **** 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) --- 1875,1881 ---- *************** *** 1894,1899 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg, --- 1888,1908 ---- 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); *************** *** 1901,1909 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg, oldNspOid = proc->pronamespace; - /* get schema OID and check its permissions */ - nspOid = LookupCreationNamespace(newschema); - /* common checks on switching namespaces */ CheckSetNamespace(oldNspOid, nspOid, ProcedureRelationId, procOid); --- 1910,1915 ---- *************** *** 1916,1922 **** 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 */ --- 1922,1928 ---- (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 */ *************** *** 1930,1936 **** 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); --- 1936,1942 ---- 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 *************** *** 31,36 **** --- 31,37 ---- #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" *************** *** 1989,1994 **** AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) --- 1990,2057 ---- } /* + * 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 *************** *** 2144,2146 **** get_am_oid(const char *amname, bool missing_ok) --- 2207,2303 ---- 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 *************** *** 32,37 **** --- 32,38 ---- #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,402 **** RenameTSParser(List *oldname, const char *newname) --- 398,442 ---- 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 -----------------------*/ /* *************** *** 628,633 **** RenameTSDictionary(List *oldname, const char *newname) --- 668,716 ---- } /* + * 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 *************** *** 1111,1116 **** RenameTSTemplate(List *oldname, const char *newname) --- 1194,1241 ---- } /* + * 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 *************** *** 1512,1517 **** RenameTSConfiguration(List *oldname, const char *newname) --- 1637,1686 ---- } /* + * 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 *************** *** 6051,6056 **** AlterObjectSchemaStmt: --- 6051,6064 ---- 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,6073 **** AlterObjectSchemaStmt: --- 6076,6108 ---- 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,6081 **** AlterObjectSchemaStmt: --- 6111,6148 ---- 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/bin/psql/tab-complete.c --- b/src/bin/psql/tab-complete.c *************** *** 741,750 **** psql_completion(char *text, int start, int end) } } ! /* ALTER CONVERSION,SCHEMA <name> */ else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && ! (pg_strcasecmp(prev2_wd, "CONVERSION") == 0 || ! pg_strcasecmp(prev2_wd, "SCHEMA") == 0)) { static const char *const list_ALTERGEN[] = {"OWNER TO", "RENAME TO", NULL}; --- 741,749 ---- } } ! /* ALTER SCHEMA <name> */ else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && ! pg_strcasecmp(prev2_wd, "SCHEMA") == 0) { static const char *const list_ALTERGEN[] = {"OWNER TO", "RENAME TO", NULL}; *************** *** 752,757 **** psql_completion(char *text, int start, int end) --- 751,766 ---- 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,1253 **** 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"); 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}; ! COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH2); } else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && --- 1246,1267 ---- pg_strcasecmp(prev3_wd, "SEARCH") == 0 && (pg_strcasecmp(prev2_wd, "TEMPLATE") == 0 || pg_strcasecmp(prev2_wd, "PARSER") == 0)) ! { ! 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_ALTERTEXTSEARCH3[] = ! {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; ! COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH3); } else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && *************** *** 1255,1264 **** 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}; ! COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH3); } /* complete ALTER TYPE <foo> with actions */ --- 1269,1278 ---- pg_strcasecmp(prev3_wd, "SEARCH") == 0 && pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0) { ! 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_ALTERTEXTSEARCH4); } /* complete ALTER TYPE <foo> with actions */ *** a/src/include/catalog/dependency.h --- b/src/include/catalog/dependency.h *************** *** 167,172 **** extern ObjectClass getObjectClass(const ObjectAddress *object); --- 167,174 ---- extern char *getObjectDescription(const ObjectAddress *object); extern char *getObjectDescriptionOids(Oid classid, Oid objid); + 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/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