mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-28 20:41:48 +02:00
Consolidate DROP handling for some object types.
This gets rid of a significant amount of duplicative code. KaiGai Kohei, reviewed in earlier versions by Dimitri Fontaine, with further review and cleanup by me.
This commit is contained in:
parent
3301c83536
commit
82a4a777d9
@ -66,6 +66,174 @@
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
/*
|
||||
* ObjectProperty
|
||||
*
|
||||
* This array provides a common part of system object structure; to help
|
||||
* consolidate routines to handle various kind of object classes.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Oid class_oid; /* oid of catalog */
|
||||
Oid oid_index_oid; /* oid of index on system oid column */
|
||||
int oid_catcache_id; /* id of catcache on system oid column */
|
||||
AttrNumber attnum_namespace; /* attnum of namespace field */
|
||||
} ObjectPropertyType;
|
||||
|
||||
static ObjectPropertyType ObjectProperty[] =
|
||||
{
|
||||
{
|
||||
CastRelationId,
|
||||
CastOidIndexId,
|
||||
-1,
|
||||
InvalidAttrNumber
|
||||
},
|
||||
{
|
||||
CollationRelationId,
|
||||
CollationOidIndexId,
|
||||
COLLOID,
|
||||
Anum_pg_collation_collnamespace
|
||||
},
|
||||
{
|
||||
ConstraintRelationId,
|
||||
ConstraintOidIndexId,
|
||||
CONSTROID,
|
||||
Anum_pg_constraint_connamespace
|
||||
},
|
||||
{
|
||||
ConversionRelationId,
|
||||
ConversionOidIndexId,
|
||||
CONVOID,
|
||||
Anum_pg_conversion_connamespace
|
||||
},
|
||||
{
|
||||
DatabaseRelationId,
|
||||
DatabaseOidIndexId,
|
||||
DATABASEOID,
|
||||
InvalidAttrNumber
|
||||
},
|
||||
{
|
||||
ExtensionRelationId,
|
||||
ExtensionOidIndexId,
|
||||
-1,
|
||||
Anum_pg_extension_extnamespace
|
||||
},
|
||||
{
|
||||
ForeignDataWrapperRelationId,
|
||||
ForeignDataWrapperOidIndexId,
|
||||
FOREIGNDATAWRAPPEROID,
|
||||
InvalidAttrNumber
|
||||
},
|
||||
{
|
||||
ForeignServerRelationId,
|
||||
ForeignServerOidIndexId,
|
||||
FOREIGNSERVEROID,
|
||||
InvalidAttrNumber
|
||||
},
|
||||
{
|
||||
ProcedureRelationId,
|
||||
ProcedureOidIndexId,
|
||||
PROCOID,
|
||||
Anum_pg_proc_pronamespace
|
||||
},
|
||||
{
|
||||
LanguageRelationId,
|
||||
LanguageOidIndexId,
|
||||
LANGOID,
|
||||
InvalidAttrNumber,
|
||||
},
|
||||
{
|
||||
LargeObjectMetadataRelationId,
|
||||
LargeObjectMetadataOidIndexId,
|
||||
-1,
|
||||
InvalidAttrNumber
|
||||
},
|
||||
{
|
||||
OperatorClassRelationId,
|
||||
OpclassOidIndexId,
|
||||
CLAOID,
|
||||
Anum_pg_opclass_opcnamespace,
|
||||
},
|
||||
{
|
||||
OperatorRelationId,
|
||||
OperatorOidIndexId,
|
||||
OPEROID,
|
||||
Anum_pg_operator_oprnamespace
|
||||
},
|
||||
{
|
||||
OperatorFamilyRelationId,
|
||||
OpfamilyOidIndexId,
|
||||
OPFAMILYOID,
|
||||
Anum_pg_opfamily_opfnamespace
|
||||
},
|
||||
{
|
||||
AuthIdRelationId,
|
||||
AuthIdOidIndexId,
|
||||
AUTHOID,
|
||||
InvalidAttrNumber
|
||||
},
|
||||
{
|
||||
RewriteRelationId,
|
||||
RewriteOidIndexId,
|
||||
-1,
|
||||
InvalidAttrNumber
|
||||
},
|
||||
{
|
||||
NamespaceRelationId,
|
||||
NamespaceOidIndexId,
|
||||
NAMESPACEOID,
|
||||
InvalidAttrNumber
|
||||
},
|
||||
{
|
||||
RelationRelationId,
|
||||
ClassOidIndexId,
|
||||
RELOID,
|
||||
Anum_pg_class_relnamespace
|
||||
},
|
||||
{
|
||||
TableSpaceRelationId,
|
||||
TablespaceOidIndexId,
|
||||
TABLESPACEOID,
|
||||
InvalidAttrNumber
|
||||
},
|
||||
{
|
||||
TriggerRelationId,
|
||||
TriggerOidIndexId,
|
||||
-1,
|
||||
InvalidAttrNumber
|
||||
},
|
||||
{
|
||||
TSConfigRelationId,
|
||||
TSConfigOidIndexId,
|
||||
TSCONFIGOID,
|
||||
Anum_pg_ts_config_cfgnamespace
|
||||
},
|
||||
{
|
||||
TSDictionaryRelationId,
|
||||
TSDictionaryOidIndexId,
|
||||
TSDICTOID,
|
||||
Anum_pg_ts_dict_dictnamespace
|
||||
},
|
||||
{
|
||||
TSParserRelationId,
|
||||
TSParserOidIndexId,
|
||||
TSPARSEROID,
|
||||
Anum_pg_ts_parser_prsnamespace
|
||||
},
|
||||
{
|
||||
TSTemplateRelationId,
|
||||
TSTemplateOidIndexId,
|
||||
TSTEMPLATEOID,
|
||||
Anum_pg_ts_template_tmplnamespace,
|
||||
},
|
||||
{
|
||||
TypeRelationId,
|
||||
TypeOidIndexId,
|
||||
TYPEOID,
|
||||
Anum_pg_type_typnamespace
|
||||
}
|
||||
};
|
||||
|
||||
static ObjectAddress get_object_address_unqualified(ObjectType objtype,
|
||||
List *qualname, bool missing_ok);
|
||||
static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
|
||||
@ -81,148 +249,7 @@ static ObjectAddress get_object_address_type(ObjectType objtype,
|
||||
static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
|
||||
List *objargs, bool missing_ok);
|
||||
static bool object_exists(ObjectAddress address);
|
||||
|
||||
/*
|
||||
* ObjectProperty
|
||||
*
|
||||
* This array provides a common part of system object structure; to help
|
||||
* consolidate routines to handle various kind of object classes.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Oid class_oid; /* oid of catalog */
|
||||
Oid oid_index_oid; /* oid of index on system oid column */
|
||||
int oid_catcache_id; /* id of catcache on system oid column */
|
||||
} ObjectPropertyType;
|
||||
|
||||
static ObjectPropertyType ObjectProperty[] =
|
||||
{
|
||||
{
|
||||
CastRelationId,
|
||||
CastOidIndexId,
|
||||
-1
|
||||
},
|
||||
{
|
||||
CollationRelationId,
|
||||
CollationOidIndexId,
|
||||
COLLOID
|
||||
},
|
||||
{
|
||||
ConstraintRelationId,
|
||||
ConstraintOidIndexId,
|
||||
CONSTROID
|
||||
},
|
||||
{
|
||||
ConversionRelationId,
|
||||
ConversionOidIndexId,
|
||||
CONVOID
|
||||
},
|
||||
{
|
||||
DatabaseRelationId,
|
||||
DatabaseOidIndexId,
|
||||
DATABASEOID
|
||||
},
|
||||
{
|
||||
ExtensionRelationId,
|
||||
ExtensionOidIndexId,
|
||||
-1
|
||||
},
|
||||
{
|
||||
ForeignDataWrapperRelationId,
|
||||
ForeignDataWrapperOidIndexId,
|
||||
FOREIGNDATAWRAPPEROID
|
||||
},
|
||||
{
|
||||
ForeignServerRelationId,
|
||||
ForeignServerOidIndexId,
|
||||
FOREIGNSERVEROID
|
||||
},
|
||||
{
|
||||
ProcedureRelationId,
|
||||
ProcedureOidIndexId,
|
||||
PROCOID
|
||||
},
|
||||
{
|
||||
LanguageRelationId,
|
||||
LanguageOidIndexId,
|
||||
LANGOID
|
||||
},
|
||||
{
|
||||
LargeObjectMetadataRelationId,
|
||||
LargeObjectMetadataOidIndexId,
|
||||
-1
|
||||
},
|
||||
{
|
||||
OperatorClassRelationId,
|
||||
OpclassOidIndexId,
|
||||
CLAOID
|
||||
},
|
||||
{
|
||||
OperatorRelationId,
|
||||
OperatorOidIndexId,
|
||||
OPEROID
|
||||
},
|
||||
{
|
||||
OperatorFamilyRelationId,
|
||||
OpfamilyOidIndexId,
|
||||
OPFAMILYOID
|
||||
},
|
||||
{
|
||||
AuthIdRelationId,
|
||||
AuthIdOidIndexId,
|
||||
AUTHOID
|
||||
},
|
||||
{
|
||||
RewriteRelationId,
|
||||
RewriteOidIndexId,
|
||||
-1
|
||||
},
|
||||
{
|
||||
NamespaceRelationId,
|
||||
NamespaceOidIndexId,
|
||||
NAMESPACEOID
|
||||
},
|
||||
{
|
||||
RelationRelationId,
|
||||
ClassOidIndexId,
|
||||
RELOID
|
||||
},
|
||||
{
|
||||
TableSpaceRelationId,
|
||||
TablespaceOidIndexId,
|
||||
TABLESPACEOID,
|
||||
},
|
||||
{
|
||||
TriggerRelationId,
|
||||
TriggerOidIndexId,
|
||||
-1
|
||||
},
|
||||
{
|
||||
TSConfigRelationId,
|
||||
TSConfigOidIndexId,
|
||||
TSCONFIGOID
|
||||
},
|
||||
{
|
||||
TSDictionaryRelationId,
|
||||
TSDictionaryOidIndexId,
|
||||
TSDICTOID
|
||||
},
|
||||
{
|
||||
TSParserRelationId,
|
||||
TSParserOidIndexId,
|
||||
TSPARSEROID
|
||||
},
|
||||
{
|
||||
TSTemplateRelationId,
|
||||
TSTemplateOidIndexId,
|
||||
TSTEMPLATEOID
|
||||
},
|
||||
{
|
||||
TypeRelationId,
|
||||
TypeOidIndexId,
|
||||
TYPEOID
|
||||
}
|
||||
};
|
||||
static ObjectPropertyType *get_object_property_data(Oid class_id);
|
||||
|
||||
/*
|
||||
* Translate an object name and arguments (as passed by the parser) to an
|
||||
@ -828,6 +855,7 @@ object_exists(ObjectAddress address)
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc sd;
|
||||
bool found;
|
||||
ObjectPropertyType *property;
|
||||
|
||||
/* Sub-objects require special treatment. */
|
||||
if (address.objectSubId != 0)
|
||||
@ -847,9 +875,6 @@ object_exists(ObjectAddress address)
|
||||
}
|
||||
return found;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index;
|
||||
|
||||
/*
|
||||
* Weird backward compatibility hack: ObjectAddress notation uses
|
||||
@ -861,21 +886,11 @@ object_exists(ObjectAddress address)
|
||||
|
||||
/*
|
||||
* For object types that have a relevant syscache, we use it; for
|
||||
* everything else, we'll have to do an index-scan. Search the
|
||||
* ObjectProperty array to find out which it is.
|
||||
* everything else, we'll have to do an index-scan.
|
||||
*/
|
||||
for (index = 0; index < lengthof(ObjectProperty); index++)
|
||||
{
|
||||
if (ObjectProperty[index].class_oid == address.classId)
|
||||
{
|
||||
cache = ObjectProperty[index].oid_catcache_id;
|
||||
indexoid = ObjectProperty[index].oid_index_oid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index == lengthof(ObjectProperty))
|
||||
elog(ERROR, "unrecognized classid: %u", address.classId);
|
||||
}
|
||||
property = get_object_property_data(address.classId);
|
||||
cache = property->oid_catcache_id;
|
||||
indexoid = property->oid_index_oid;
|
||||
|
||||
/* Found a syscache? */
|
||||
if (cache != -1)
|
||||
@ -895,7 +910,6 @@ object_exists(ObjectAddress address)
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check ownership of an object previously identified by get_object_address.
|
||||
*/
|
||||
@ -1060,3 +1074,58 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
|
||||
(int) objtype);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_object_namespace
|
||||
*
|
||||
* Find the schema containing the specified object. For non-schema objects,
|
||||
* this function returns InvalidOid.
|
||||
*/
|
||||
Oid
|
||||
get_object_namespace(const ObjectAddress *address)
|
||||
{
|
||||
int cache;
|
||||
HeapTuple tuple;
|
||||
bool isnull;
|
||||
Oid oid;
|
||||
ObjectPropertyType *property;
|
||||
|
||||
/* If not owned by a namespace, just return InvalidOid. */
|
||||
property = get_object_property_data(address->classId);
|
||||
if (property->attnum_namespace == InvalidAttrNumber)
|
||||
return InvalidOid;
|
||||
|
||||
/* Currently, we can only handle object types with system caches. */
|
||||
cache = property->oid_catcache_id;
|
||||
Assert(cache != -1);
|
||||
|
||||
/* Fetch tuple from syscache and extract namespace attribute. */
|
||||
tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "cache lookup failed for cache %d oid %u",
|
||||
cache, address->objectId);
|
||||
oid = DatumGetObjectId(SysCacheGetAttr(cache,
|
||||
tuple,
|
||||
property->attnum_namespace,
|
||||
&isnull));
|
||||
Assert(!isnull);
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
return oid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find ObjectProperty structure by class_id.
|
||||
*/
|
||||
static ObjectPropertyType *
|
||||
get_object_property_data(Oid class_id)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; index < lengthof(ObjectProperty); index++)
|
||||
if (ObjectProperty[index].class_oid == class_id)
|
||||
return &ObjectProperty[index];
|
||||
|
||||
elog(ERROR, "unrecognized class id: %u", class_id);
|
||||
return NULL; /* not reached */
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = aggregatecmds.o alter.o analyze.o async.o cluster.o comment.o \
|
||||
collationcmds.o constraint.o conversioncmds.o copy.o \
|
||||
dbcommands.o define.o discard.o explain.o extension.o \
|
||||
dbcommands.o define.o discard.o dropcmds.o explain.o extension.o \
|
||||
foreigncmds.o functioncmds.o \
|
||||
indexcmds.o lockcmds.o operatorcmds.o opclasscmds.o \
|
||||
portalcmds.o prepare.o proclang.o \
|
||||
|
@ -144,67 +144,6 @@ DefineCollation(List *names, List *parameters)
|
||||
(void) pg_newlocale_from_collation(newoid);
|
||||
}
|
||||
|
||||
/*
|
||||
* DROP COLLATION
|
||||
*/
|
||||
void
|
||||
DropCollationsCommand(DropStmt *drop)
|
||||
{
|
||||
ObjectAddresses *objects;
|
||||
ListCell *cell;
|
||||
|
||||
/*
|
||||
* First we identify all the collations, then we delete them in a single
|
||||
* performMultipleDeletions() call. This is to avoid unwanted DROP
|
||||
* RESTRICT errors if one of the collations depends on another. (Not that
|
||||
* that is very likely, but we may as well do this consistently.)
|
||||
*/
|
||||
objects = new_object_addresses();
|
||||
|
||||
foreach(cell, drop->objects)
|
||||
{
|
||||
List *name = (List *) lfirst(cell);
|
||||
Oid collationOid;
|
||||
HeapTuple tuple;
|
||||
Form_pg_collation coll;
|
||||
ObjectAddress object;
|
||||
|
||||
collationOid = get_collation_oid(name, drop->missing_ok);
|
||||
|
||||
if (!OidIsValid(collationOid))
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("collation \"%s\" does not exist, skipping",
|
||||
NameListToString(name))));
|
||||
continue;
|
||||
}
|
||||
|
||||
tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(collationOid));
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "cache lookup failed for collation %u",
|
||||
collationOid);
|
||||
coll = (Form_pg_collation) GETSTRUCT(tuple);
|
||||
|
||||
/* Permission check: must own collation or its namespace */
|
||||
if (!pg_collation_ownercheck(collationOid, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(coll->collnamespace, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
|
||||
NameStr(coll->collname));
|
||||
|
||||
object.classId = CollationRelationId;
|
||||
object.objectId = collationOid;
|
||||
object.objectSubId = 0;
|
||||
|
||||
add_exact_object_address(&object, objects);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
}
|
||||
|
||||
performMultipleDeletions(objects, drop->behavior);
|
||||
|
||||
free_object_addresses(objects);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rename collation
|
||||
*/
|
||||
|
@ -117,67 +117,6 @@ CreateConversionCommand(CreateConversionStmt *stmt)
|
||||
from_encoding, to_encoding, funcoid, stmt->def);
|
||||
}
|
||||
|
||||
/*
|
||||
* DROP CONVERSION
|
||||
*/
|
||||
void
|
||||
DropConversionsCommand(DropStmt *drop)
|
||||
{
|
||||
ObjectAddresses *objects;
|
||||
ListCell *cell;
|
||||
|
||||
/*
|
||||
* First we identify all the conversions, then we delete them in a single
|
||||
* performMultipleDeletions() call. This is to avoid unwanted DROP
|
||||
* RESTRICT errors if one of the conversions depends on another. (Not that
|
||||
* that is very likely, but we may as well do this consistently.)
|
||||
*/
|
||||
objects = new_object_addresses();
|
||||
|
||||
foreach(cell, drop->objects)
|
||||
{
|
||||
List *name = (List *) lfirst(cell);
|
||||
Oid conversionOid;
|
||||
HeapTuple tuple;
|
||||
Form_pg_conversion con;
|
||||
ObjectAddress object;
|
||||
|
||||
conversionOid = get_conversion_oid(name, drop->missing_ok);
|
||||
|
||||
if (!OidIsValid(conversionOid))
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("conversion \"%s\" does not exist, skipping",
|
||||
NameListToString(name))));
|
||||
continue;
|
||||
}
|
||||
|
||||
tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conversionOid));
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "cache lookup failed for conversion %u",
|
||||
conversionOid);
|
||||
con = (Form_pg_conversion) GETSTRUCT(tuple);
|
||||
|
||||
/* Permission check: must own conversion or its namespace */
|
||||
if (!pg_conversion_ownercheck(conversionOid, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(con->connamespace, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
|
||||
NameStr(con->conname));
|
||||
|
||||
object.classId = ConversionRelationId;
|
||||
object.objectId = conversionOid;
|
||||
object.objectSubId = 0;
|
||||
|
||||
add_exact_object_address(&object, objects);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
}
|
||||
|
||||
performMultipleDeletions(objects, drop->behavior);
|
||||
|
||||
free_object_addresses(objects);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rename conversion
|
||||
*/
|
||||
|
147
src/backend/commands/dropcmds.c
Normal file
147
src/backend/commands/dropcmds.c
Normal file
@ -0,0 +1,147 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* dropcmds.c
|
||||
* handle various "DROP" operations
|
||||
*
|
||||
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/backend/catalog/dropcmds.c
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/objectaddress.h"
|
||||
#include "catalog/pg_class.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "parser/parse_type.h"
|
||||
#include "utils/acl.h"
|
||||
|
||||
static void does_not_exist_skipping(ObjectType objtype, List *objname);
|
||||
|
||||
/*
|
||||
* Drop one or more objects.
|
||||
*
|
||||
* We don't currently handle all object types here. Relations, for example,
|
||||
* require special handling, because (for example) indexes have additional
|
||||
* locking requirements.
|
||||
*
|
||||
* We look up all the objects first, and then delete them in a single
|
||||
* performMultipleDeletions() call. This avoids unnecessary DROP RESTRICT
|
||||
* errors if there are dependencies between them.
|
||||
*/
|
||||
void
|
||||
RemoveObjects(DropStmt *stmt)
|
||||
{
|
||||
ObjectAddresses *objects;
|
||||
ListCell *cell1;
|
||||
|
||||
objects = new_object_addresses();
|
||||
|
||||
foreach(cell1, stmt->objects)
|
||||
{
|
||||
ObjectAddress address;
|
||||
List *objname = lfirst(cell1);
|
||||
Relation relation = NULL;
|
||||
Oid namespaceId;
|
||||
|
||||
/* Get an ObjectAddress for the object. */
|
||||
address = get_object_address(stmt->removeType,
|
||||
objname, NIL,
|
||||
&relation,
|
||||
AccessExclusiveLock,
|
||||
stmt->missing_ok);
|
||||
|
||||
/* Issue NOTICE if supplied object was not found. */
|
||||
if (!OidIsValid(address.objectId))
|
||||
{
|
||||
does_not_exist_skipping(stmt->removeType, objname);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check permissions. */
|
||||
namespaceId = get_object_namespace(&address);
|
||||
if (!OidIsValid(namespaceId) ||
|
||||
!pg_namespace_ownercheck(namespaceId, GetUserId()))
|
||||
check_object_ownership(GetUserId(), stmt->removeType, address,
|
||||
objname, NIL, relation);
|
||||
|
||||
/* Release any relcache reference count, but keep lock until commit. */
|
||||
if (relation)
|
||||
heap_close(relation, NoLock);
|
||||
|
||||
add_exact_object_address(&address, objects);
|
||||
}
|
||||
|
||||
/* Here we really delete them. */
|
||||
performMultipleDeletions(objects, stmt->behavior);
|
||||
|
||||
free_object_addresses(objects);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a NOTICE stating that the named object was not found, and is
|
||||
* being skipped. This is only relevant when "IF EXISTS" is used; otherwise,
|
||||
* get_object_address() will throw an ERROR.
|
||||
*/
|
||||
static void
|
||||
does_not_exist_skipping(ObjectType objtype, List *objname)
|
||||
{
|
||||
const char *msg = NULL;
|
||||
char *name = NULL;
|
||||
|
||||
switch (objtype)
|
||||
{
|
||||
case OBJECT_TYPE:
|
||||
case OBJECT_DOMAIN:
|
||||
msg = gettext_noop("type \"%s\" does not exist, skipping");
|
||||
name = TypeNameToString(makeTypeNameFromNameList(objname));
|
||||
break;
|
||||
case OBJECT_COLLATION:
|
||||
msg = gettext_noop("collation \"%s\" does not exist, skipping");
|
||||
name = NameListToString(objname);
|
||||
break;
|
||||
case OBJECT_CONVERSION:
|
||||
msg = gettext_noop("conversion \"%s\" does not exist, skipping");
|
||||
name = NameListToString(objname);
|
||||
break;
|
||||
case OBJECT_SCHEMA:
|
||||
msg = gettext_noop("schema \"%s\" does not exist, skipping");
|
||||
name = NameListToString(objname);
|
||||
break;
|
||||
case OBJECT_TSPARSER:
|
||||
msg = gettext_noop("text search parser \"%s\" does not exist, skipping");
|
||||
name = NameListToString(objname);
|
||||
break;
|
||||
case OBJECT_TSDICTIONARY:
|
||||
msg = gettext_noop("text search dictionary \"%s\" does not exist, skipping");
|
||||
name = NameListToString(objname);
|
||||
break;
|
||||
case OBJECT_TSTEMPLATE:
|
||||
msg = gettext_noop("text search template \"%s\" does not exist, skipping");
|
||||
name = NameListToString(objname);
|
||||
break;
|
||||
case OBJECT_TSCONFIGURATION:
|
||||
msg = gettext_noop("text search configuration \"%s\" does not exist, skipping");
|
||||
name = NameListToString(objname);
|
||||
break;
|
||||
case OBJECT_EXTENSION:
|
||||
msg = gettext_noop("extension \"%s\" does not exist, skipping");
|
||||
name = NameListToString(objname);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unexpected object type (%d)", (int)objtype);
|
||||
break;
|
||||
}
|
||||
|
||||
ereport(NOTICE, (errmsg(msg, name)));
|
||||
}
|
@ -1563,69 +1563,6 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
|
||||
return extensionOid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RemoveExtensions
|
||||
* Implements DROP EXTENSION.
|
||||
*/
|
||||
void
|
||||
RemoveExtensions(DropStmt *drop)
|
||||
{
|
||||
ObjectAddresses *objects;
|
||||
ListCell *cell;
|
||||
|
||||
/*
|
||||
* First we identify all the extensions, then we delete them in a single
|
||||
* performMultipleDeletions() call. This is to avoid unwanted DROP
|
||||
* RESTRICT errors if one of the extensions depends on another.
|
||||
*/
|
||||
objects = new_object_addresses();
|
||||
|
||||
foreach(cell, drop->objects)
|
||||
{
|
||||
List *names = (List *) lfirst(cell);
|
||||
char *extensionName;
|
||||
Oid extensionId;
|
||||
ObjectAddress object;
|
||||
|
||||
if (list_length(names) != 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("extension name cannot be qualified")));
|
||||
extensionName = strVal(linitial(names));
|
||||
|
||||
extensionId = get_extension_oid(extensionName, drop->missing_ok);
|
||||
|
||||
if (!OidIsValid(extensionId))
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("extension \"%s\" does not exist, skipping",
|
||||
extensionName)));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Permission check: must own extension */
|
||||
if (!pg_extension_ownercheck(extensionId, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
|
||||
extensionName);
|
||||
|
||||
object.classId = ExtensionRelationId;
|
||||
object.objectId = extensionId;
|
||||
object.objectSubId = 0;
|
||||
|
||||
add_exact_object_address(&object, objects);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the deletions. Objects contained in the extension(s) are removed by
|
||||
* means of their dependency links to the extensions.
|
||||
*/
|
||||
performMultipleDeletions(objects, drop->behavior);
|
||||
|
||||
free_object_addresses(objects);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Guts of extension deletion.
|
||||
*
|
||||
|
@ -146,69 +146,6 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
|
||||
SetUserIdAndSecContext(saved_uid, save_sec_context);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RemoveSchemas
|
||||
* Implements DROP SCHEMA.
|
||||
*/
|
||||
void
|
||||
RemoveSchemas(DropStmt *drop)
|
||||
{
|
||||
ObjectAddresses *objects;
|
||||
ListCell *cell;
|
||||
|
||||
/*
|
||||
* First we identify all the schemas, then we delete them in a single
|
||||
* performMultipleDeletions() call. This is to avoid unwanted DROP
|
||||
* RESTRICT errors if one of the schemas depends on another.
|
||||
*/
|
||||
objects = new_object_addresses();
|
||||
|
||||
foreach(cell, drop->objects)
|
||||
{
|
||||
List *names = (List *) lfirst(cell);
|
||||
char *namespaceName;
|
||||
Oid namespaceId;
|
||||
ObjectAddress object;
|
||||
|
||||
if (list_length(names) != 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("schema name cannot be qualified")));
|
||||
namespaceName = strVal(linitial(names));
|
||||
|
||||
namespaceId = get_namespace_oid(namespaceName, drop->missing_ok);
|
||||
|
||||
if (!OidIsValid(namespaceId))
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("schema \"%s\" does not exist, skipping",
|
||||
namespaceName)));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Permission check */
|
||||
if (!pg_namespace_ownercheck(namespaceId, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
|
||||
namespaceName);
|
||||
|
||||
object.classId = NamespaceRelationId;
|
||||
object.objectId = namespaceId;
|
||||
object.objectSubId = 0;
|
||||
|
||||
add_exact_object_address(&object, objects);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the deletions. Objects contained in the schema(s) are removed by
|
||||
* means of their dependency links to the schema.
|
||||
*/
|
||||
performMultipleDeletions(objects, drop->behavior);
|
||||
|
||||
free_object_addresses(objects);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Guts of schema deletion.
|
||||
*/
|
||||
|
@ -278,65 +278,6 @@ DefineTSParser(List *names, List *parameters)
|
||||
heap_close(prsRel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* DROP TEXT SEARCH PARSER
|
||||
*/
|
||||
void
|
||||
RemoveTSParsers(DropStmt *drop)
|
||||
{
|
||||
ObjectAddresses *objects;
|
||||
ListCell *cell;
|
||||
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to drop text search parsers")));
|
||||
|
||||
/*
|
||||
* First we identify all the objects, then we delete them in a single
|
||||
* performMultipleDeletions() call. This is to avoid unwanted DROP
|
||||
* RESTRICT errors if one of the objects depends on another.
|
||||
*/
|
||||
objects = new_object_addresses();
|
||||
|
||||
foreach(cell, drop->objects)
|
||||
{
|
||||
List *names = (List *) lfirst(cell);
|
||||
Oid prsOid;
|
||||
ObjectAddress object;
|
||||
|
||||
prsOid = get_ts_parser_oid(names, true);
|
||||
|
||||
if (!OidIsValid(prsOid))
|
||||
{
|
||||
if (!drop->missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("text search parser \"%s\" does not exist",
|
||||
NameListToString(names))));
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("text search parser \"%s\" does not exist, skipping",
|
||||
NameListToString(names))));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
object.classId = TSParserRelationId;
|
||||
object.objectId = prsOid;
|
||||
object.objectSubId = 0;
|
||||
|
||||
add_exact_object_address(&object, objects);
|
||||
}
|
||||
|
||||
performMultipleDeletions(objects, drop->behavior);
|
||||
|
||||
free_object_addresses(objects);
|
||||
}
|
||||
|
||||
/*
|
||||
* Guts of TS parser deletion.
|
||||
*/
|
||||
@ -730,76 +671,6 @@ AlterTSDictionaryNamespace_oid(Oid dictId, Oid newNspOid)
|
||||
return oldNspOid;
|
||||
}
|
||||
|
||||
/*
|
||||
* DROP TEXT SEARCH DICTIONARY
|
||||
*/
|
||||
void
|
||||
RemoveTSDictionaries(DropStmt *drop)
|
||||
{
|
||||
ObjectAddresses *objects;
|
||||
ListCell *cell;
|
||||
|
||||
/*
|
||||
* First we identify all the objects, then we delete them in a single
|
||||
* performMultipleDeletions() call. This is to avoid unwanted DROP
|
||||
* RESTRICT errors if one of the objects depends on another.
|
||||
*/
|
||||
objects = new_object_addresses();
|
||||
|
||||
foreach(cell, drop->objects)
|
||||
{
|
||||
List *names = (List *) lfirst(cell);
|
||||
Oid dictOid;
|
||||
ObjectAddress object;
|
||||
HeapTuple tup;
|
||||
Oid namespaceId;
|
||||
|
||||
dictOid = get_ts_dict_oid(names, true);
|
||||
|
||||
if (!OidIsValid(dictOid))
|
||||
{
|
||||
if (!drop->missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("text search dictionary \"%s\" does not exist",
|
||||
NameListToString(names))));
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("text search dictionary \"%s\" does not exist, skipping",
|
||||
NameListToString(names))));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictOid));
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for text search dictionary %u",
|
||||
dictOid);
|
||||
|
||||
/* Permission check: must own dictionary or its namespace */
|
||||
namespaceId = ((Form_pg_ts_dict) GETSTRUCT(tup))->dictnamespace;
|
||||
if (!pg_ts_dict_ownercheck(dictOid, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(namespaceId, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
|
||||
NameListToString(names));
|
||||
|
||||
object.classId = TSDictionaryRelationId;
|
||||
object.objectId = dictOid;
|
||||
object.objectSubId = 0;
|
||||
|
||||
add_exact_object_address(&object, objects);
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
}
|
||||
|
||||
performMultipleDeletions(objects, drop->behavior);
|
||||
|
||||
free_object_addresses(objects);
|
||||
}
|
||||
|
||||
/*
|
||||
* Guts of TS dictionary deletion.
|
||||
*/
|
||||
@ -1262,65 +1133,6 @@ AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid)
|
||||
return oldNspOid;
|
||||
}
|
||||
|
||||
/*
|
||||
* DROP TEXT SEARCH TEMPLATE
|
||||
*/
|
||||
void
|
||||
RemoveTSTemplates(DropStmt *drop)
|
||||
{
|
||||
ObjectAddresses *objects;
|
||||
ListCell *cell;
|
||||
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to drop text search templates")));
|
||||
|
||||
/*
|
||||
* First we identify all the objects, then we delete them in a single
|
||||
* performMultipleDeletions() call. This is to avoid unwanted DROP
|
||||
* RESTRICT errors if one of the objects depends on another.
|
||||
*/
|
||||
objects = new_object_addresses();
|
||||
|
||||
foreach(cell, drop->objects)
|
||||
{
|
||||
List *names = (List *) lfirst(cell);
|
||||
Oid tmplOid;
|
||||
ObjectAddress object;
|
||||
|
||||
tmplOid = get_ts_template_oid(names, true);
|
||||
|
||||
if (!OidIsValid(tmplOid))
|
||||
{
|
||||
if (!drop->missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("text search template \"%s\" does not exist",
|
||||
NameListToString(names))));
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("text search template \"%s\" does not exist, skipping",
|
||||
NameListToString(names))));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
object.classId = TSTemplateRelationId;
|
||||
object.objectId = tmplOid;
|
||||
object.objectSubId = 0;
|
||||
|
||||
add_exact_object_address(&object, objects);
|
||||
}
|
||||
|
||||
performMultipleDeletions(objects, drop->behavior);
|
||||
|
||||
free_object_addresses(objects);
|
||||
}
|
||||
|
||||
/*
|
||||
* Guts of TS template deletion.
|
||||
*/
|
||||
@ -1714,72 +1526,6 @@ AlterTSConfigurationNamespace_oid(Oid cfgId, Oid newNspOid)
|
||||
return oldNspOid;
|
||||
}
|
||||
|
||||
/*
|
||||
* DROP TEXT SEARCH CONFIGURATION
|
||||
*/
|
||||
void
|
||||
RemoveTSConfigurations(DropStmt *drop)
|
||||
{
|
||||
ObjectAddresses *objects;
|
||||
ListCell *cell;
|
||||
|
||||
/*
|
||||
* First we identify all the objects, then we delete them in a single
|
||||
* performMultipleDeletions() call. This is to avoid unwanted DROP
|
||||
* RESTRICT errors if one of the objects depends on another.
|
||||
*/
|
||||
objects = new_object_addresses();
|
||||
|
||||
foreach(cell, drop->objects)
|
||||
{
|
||||
List *names = (List *) lfirst(cell);
|
||||
Oid cfgOid;
|
||||
Oid namespaceId;
|
||||
ObjectAddress object;
|
||||
HeapTuple tup;
|
||||
|
||||
tup = GetTSConfigTuple(names);
|
||||
|
||||
if (!HeapTupleIsValid(tup))
|
||||
{
|
||||
if (!drop->missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("text search configuration \"%s\" does not exist",
|
||||
NameListToString(names))));
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("text search configuration \"%s\" does not exist, skipping",
|
||||
NameListToString(names))));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Permission check: must own configuration or its namespace */
|
||||
cfgOid = HeapTupleGetOid(tup);
|
||||
namespaceId = ((Form_pg_ts_config) GETSTRUCT(tup))->cfgnamespace;
|
||||
if (!pg_ts_config_ownercheck(cfgOid, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(namespaceId, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
|
||||
NameListToString(names));
|
||||
|
||||
object.classId = TSConfigRelationId;
|
||||
object.objectId = cfgOid;
|
||||
object.objectSubId = 0;
|
||||
|
||||
add_exact_object_address(&object, objects);
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
}
|
||||
|
||||
performMultipleDeletions(objects, drop->behavior);
|
||||
|
||||
free_object_addresses(objects);
|
||||
}
|
||||
|
||||
/*
|
||||
* Guts of TS configuration deletion.
|
||||
*/
|
||||
|
@ -618,98 +618,6 @@ DefineType(List *names, List *parameters)
|
||||
pfree(array_type);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RemoveTypes
|
||||
* Implements DROP TYPE and DROP DOMAIN
|
||||
*
|
||||
* Note: if DOMAIN is specified, we enforce that each type is a domain, but
|
||||
* we don't enforce the converse for DROP TYPE
|
||||
*/
|
||||
void
|
||||
RemoveTypes(DropStmt *drop)
|
||||
{
|
||||
ObjectAddresses *objects;
|
||||
ListCell *cell;
|
||||
|
||||
/*
|
||||
* First we identify all the types, then we delete them in a single
|
||||
* performMultipleDeletions() call. This is to avoid unwanted DROP
|
||||
* RESTRICT errors if one of the types depends on another.
|
||||
*/
|
||||
objects = new_object_addresses();
|
||||
|
||||
foreach(cell, drop->objects)
|
||||
{
|
||||
List *names = (List *) lfirst(cell);
|
||||
TypeName *typename;
|
||||
Oid typeoid;
|
||||
HeapTuple tup;
|
||||
ObjectAddress object;
|
||||
Form_pg_type typ;
|
||||
|
||||
/* Make a TypeName so we can use standard type lookup machinery */
|
||||
typename = makeTypeNameFromNameList(names);
|
||||
|
||||
/* Use LookupTypeName here so that shell types can be removed. */
|
||||
tup = LookupTypeName(NULL, typename, NULL);
|
||||
if (tup == NULL)
|
||||
{
|
||||
if (!drop->missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist",
|
||||
TypeNameToString(typename))));
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("type \"%s\" does not exist, skipping",
|
||||
TypeNameToString(typename))));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
typeoid = typeTypeId(tup);
|
||||
typ = (Form_pg_type) GETSTRUCT(tup);
|
||||
|
||||
/* Permission check: must own type or its namespace */
|
||||
if (!pg_type_ownercheck(typeoid, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(typ->typnamespace, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
|
||||
format_type_be(typeoid));
|
||||
|
||||
if (drop->removeType == OBJECT_DOMAIN)
|
||||
{
|
||||
/* Check that this is actually a domain */
|
||||
if (typ->typtype != TYPTYPE_DOMAIN)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is not a domain",
|
||||
TypeNameToString(typename))));
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: we need no special check for array types here, as the normal
|
||||
* treatment of internal dependencies handles it just fine
|
||||
*/
|
||||
|
||||
object.classId = TypeRelationId;
|
||||
object.objectId = typeoid;
|
||||
object.objectSubId = 0;
|
||||
|
||||
add_exact_object_address(&object, objects);
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
}
|
||||
|
||||
performMultipleDeletions(objects, drop->behavior);
|
||||
|
||||
free_object_addresses(objects);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Guts of type deletion.
|
||||
*/
|
||||
|
@ -644,62 +644,19 @@ standard_ProcessUtility(Node *parsetree,
|
||||
break;
|
||||
|
||||
case T_DropStmt:
|
||||
{
|
||||
DropStmt *stmt = (DropStmt *) parsetree;
|
||||
|
||||
switch (stmt->removeType)
|
||||
switch (((DropStmt *) parsetree)->removeType)
|
||||
{
|
||||
case OBJECT_TABLE:
|
||||
case OBJECT_SEQUENCE:
|
||||
case OBJECT_VIEW:
|
||||
case OBJECT_INDEX:
|
||||
case OBJECT_FOREIGN_TABLE:
|
||||
RemoveRelations(stmt);
|
||||
RemoveRelations((DropStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case OBJECT_TYPE:
|
||||
case OBJECT_DOMAIN:
|
||||
RemoveTypes(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_COLLATION:
|
||||
DropCollationsCommand(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_CONVERSION:
|
||||
DropConversionsCommand(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_SCHEMA:
|
||||
RemoveSchemas(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_TSPARSER:
|
||||
RemoveTSParsers(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_TSDICTIONARY:
|
||||
RemoveTSDictionaries(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_TSTEMPLATE:
|
||||
RemoveTSTemplates(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_TSCONFIGURATION:
|
||||
RemoveTSConfigurations(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_EXTENSION:
|
||||
RemoveExtensions(stmt);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unrecognized drop object type: %d",
|
||||
(int) stmt->removeType);
|
||||
RemoveObjects((DropStmt *) parsetree);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case T_TruncateStmt:
|
||||
|
@ -35,4 +35,6 @@ extern void check_object_ownership(Oid roleid,
|
||||
ObjectType objtype, ObjectAddress address,
|
||||
List *objname, List *objargs, Relation relation);
|
||||
|
||||
extern Oid get_object_namespace(const ObjectAddress *address);
|
||||
|
||||
#endif /* PARSE_OBJECT_H */
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "nodes/parsenodes.h"
|
||||
|
||||
extern void DefineCollation(List *names, List *parameters);
|
||||
extern void DropCollationsCommand(DropStmt *drop);
|
||||
extern void RenameCollation(List *name, const char *newname);
|
||||
extern void AlterCollationOwner(List *name, Oid newOwnerId);
|
||||
extern void AlterCollationOwner_oid(Oid collationOid, Oid newOwnerId);
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "nodes/parsenodes.h"
|
||||
|
||||
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
|
||||
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);
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
#include "nodes/parsenodes.h"
|
||||
|
||||
/* commands/dropcmds.c */
|
||||
extern void RemoveObjects(DropStmt *stmt);
|
||||
|
||||
/* commands/indexcmds.c */
|
||||
extern Oid DefineIndex(RangeVar *heapRelation,
|
||||
@ -122,12 +124,10 @@ extern void DefineTSParser(List *names, List *parameters);
|
||||
extern void RenameTSParser(List *oldname, const char *newname);
|
||||
extern void AlterTSParserNamespace(List *name, const char *newschema);
|
||||
extern Oid AlterTSParserNamespace_oid(Oid prsId, Oid newNspOid);
|
||||
extern void RemoveTSParsers(DropStmt *drop);
|
||||
extern void RemoveTSParserById(Oid prsId);
|
||||
|
||||
extern void DefineTSDictionary(List *names, List *parameters);
|
||||
extern void RenameTSDictionary(List *oldname, const char *newname);
|
||||
extern void RemoveTSDictionaries(DropStmt *drop);
|
||||
extern void RemoveTSDictionaryById(Oid dictId);
|
||||
extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt);
|
||||
extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId);
|
||||
@ -138,12 +138,10 @@ extern void DefineTSTemplate(List *names, List *parameters);
|
||||
extern void RenameTSTemplate(List *oldname, const char *newname);
|
||||
extern void AlterTSTemplateNamespace(List *name, const char *newschema);
|
||||
extern Oid 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 RemoveTSConfigurations(DropStmt *stmt);
|
||||
extern void RemoveTSConfigurationById(Oid cfgId);
|
||||
extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
|
||||
extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId);
|
||||
|
@ -29,7 +29,6 @@ extern Oid CurrentExtensionObject;
|
||||
|
||||
extern void CreateExtension(CreateExtensionStmt *stmt);
|
||||
|
||||
extern void RemoveExtensions(DropStmt *stmt);
|
||||
extern void RemoveExtensionById(Oid extId);
|
||||
|
||||
extern Oid InsertExtensionTuple(const char *extName, Oid extOwner,
|
||||
|
@ -20,7 +20,6 @@
|
||||
extern void CreateSchemaCommand(CreateSchemaStmt *parsetree,
|
||||
const char *queryString);
|
||||
|
||||
extern void RemoveSchemas(DropStmt *drop);
|
||||
extern void RemoveSchemaById(Oid schemaOid);
|
||||
|
||||
extern void RenameSchema(const char *oldname, const char *newname);
|
||||
|
@ -20,7 +20,6 @@
|
||||
#define DEFAULT_TYPDELIM ','
|
||||
|
||||
extern void DefineType(List *names, List *parameters);
|
||||
extern void RemoveTypes(DropStmt *drop);
|
||||
extern void RemoveTypeById(Oid typeOid);
|
||||
extern void DefineDomain(CreateDomainStmt *stmt);
|
||||
extern void DefineEnum(CreateEnumStmt *stmt);
|
||||
|
Loading…
Reference in New Issue
Block a user