PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
extension.h File Reference
Include dependency graph for extension.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ObjectAddress CreateExtension (ParseState *pstate, CreateExtensionStmt *stmt)
 
void RemoveExtensionById (Oid extId)
 
ObjectAddress InsertExtensionTuple (const char *extName, Oid extOwner, Oid schemaOid, bool relocatable, const char *extVersion, Datum extConfig, Datum extCondition, List *requiredExtensions)
 
ObjectAddress ExecAlterExtensionStmt (ParseState *pstate, AlterExtensionStmt *stmt)
 
ObjectAddress ExecAlterExtensionContentsStmt (AlterExtensionContentsStmt *stmt, ObjectAddress *objAddress)
 
Oid get_extension_oid (const char *extname, bool missing_ok)
 
char * get_extension_name (Oid ext_oid)
 
ObjectAddress AlterExtensionNamespace (const char *extensionName, const char *newschema, Oid *oldschema)
 
void AlterExtensionOwner_oid (Oid extensionOid, Oid newOwnerId)
 

Variables

PGDLLIMPORT bool creating_extension
 
Oid CurrentExtensionObject
 

Function Documentation

ObjectAddress AlterExtensionNamespace ( const char *  extensionName,
const char *  newschema,
Oid oldschema 
)

Definition at line 2681 of file extension.c.

References AccessShareLock, ACL_CREATE, ACL_KIND_EXTENSION, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, AlterObjectNamespace_oid(), Anum_pg_depend_refclassid, Anum_pg_depend_refobjid, BTEqualStrategyNumber, CatalogTupleUpdate(), changeDependencyFor(), ObjectAddress::classId, DEPENDENCY_EXTENSION, DependReferenceIndexId, DependRelationId, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ExtensionOidIndexId, ExtensionRelationId, get_extension_oid(), get_namespace_name(), getExtensionOfObject(), getObjectDescription(), GETSTRUCT, GetUserId(), heap_close, heap_copytuple(), heap_open(), HeapTupleIsValid, InvalidObjectAddress, InvalidOid, InvokeObjectPostAlterHook, LookupCreationNamespace(), NamespaceRelationId, NameStr, new_object_addresses(), NULL, ObjectAddressSet, ObjectAddress::objectId, ObjectIdAttributeNumber, ObjectIdGetDatum, ObjectAddress::objectSubId, pg_extension_ownercheck(), pg_namespace_aclcheck(), relation_close(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by ExecAlterObjectSchemaStmt().

2682 {
2683  Oid extensionOid;
2684  Oid nspOid;
2685  Oid oldNspOid = InvalidOid;
2686  AclResult aclresult;
2687  Relation extRel;
2688  ScanKeyData key[2];
2689  SysScanDesc extScan;
2690  HeapTuple extTup;
2691  Form_pg_extension extForm;
2692  Relation depRel;
2693  SysScanDesc depScan;
2694  HeapTuple depTup;
2695  ObjectAddresses *objsMoved;
2696  ObjectAddress extAddr;
2697 
2698  extensionOid = get_extension_oid(extensionName, false);
2699 
2700  nspOid = LookupCreationNamespace(newschema);
2701 
2702  /*
2703  * Permission check: must own extension. Note that we don't bother to
2704  * check ownership of the individual member objects ...
2705  */
2706  if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2708  extensionName);
2709 
2710  /* Permission check: must have creation rights in target namespace */
2711  aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
2712  if (aclresult != ACLCHECK_OK)
2713  aclcheck_error(aclresult, ACL_KIND_NAMESPACE, newschema);
2714 
2715  /*
2716  * If the schema is currently a member of the extension, disallow moving
2717  * the extension into the schema. That would create a dependency loop.
2718  */
2719  if (getExtensionOfObject(NamespaceRelationId, nspOid) == extensionOid)
2720  ereport(ERROR,
2721  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2722  errmsg("cannot move extension \"%s\" into schema \"%s\" "
2723  "because the extension contains the schema",
2724  extensionName, newschema)));
2725 
2726  /* Locate the pg_extension tuple */
2728 
2729  ScanKeyInit(&key[0],
2731  BTEqualStrategyNumber, F_OIDEQ,
2732  ObjectIdGetDatum(extensionOid));
2733 
2734  extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2735  NULL, 1, key);
2736 
2737  extTup = systable_getnext(extScan);
2738 
2739  if (!HeapTupleIsValid(extTup)) /* should not happen */
2740  elog(ERROR, "could not find tuple for extension %u",
2741  extensionOid);
2742 
2743  /* Copy tuple so we can modify it below */
2744  extTup = heap_copytuple(extTup);
2745  extForm = (Form_pg_extension) GETSTRUCT(extTup);
2746 
2747  systable_endscan(extScan);
2748 
2749  /*
2750  * If the extension is already in the target schema, just silently do
2751  * nothing.
2752  */
2753  if (extForm->extnamespace == nspOid)
2754  {
2755  heap_close(extRel, RowExclusiveLock);
2756  return InvalidObjectAddress;
2757  }
2758 
2759  /* Check extension is supposed to be relocatable */
2760  if (!extForm->extrelocatable)
2761  ereport(ERROR,
2762  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2763  errmsg("extension \"%s\" does not support SET SCHEMA",
2764  NameStr(extForm->extname))));
2765 
2766  objsMoved = new_object_addresses();
2767 
2768  /*
2769  * Scan pg_depend to find objects that depend directly on the extension,
2770  * and alter each one's schema.
2771  */
2773 
2774  ScanKeyInit(&key[0],
2776  BTEqualStrategyNumber, F_OIDEQ,
2778  ScanKeyInit(&key[1],
2780  BTEqualStrategyNumber, F_OIDEQ,
2781  ObjectIdGetDatum(extensionOid));
2782 
2783  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
2784  NULL, 2, key);
2785 
2786  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
2787  {
2788  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
2789  ObjectAddress dep;
2790  Oid dep_oldNspOid;
2791 
2792  /*
2793  * Ignore non-membership dependencies. (Currently, the only other
2794  * case we could see here is a normal dependency from another
2795  * extension.)
2796  */
2797  if (pg_depend->deptype != DEPENDENCY_EXTENSION)
2798  continue;
2799 
2800  dep.classId = pg_depend->classid;
2801  dep.objectId = pg_depend->objid;
2802  dep.objectSubId = pg_depend->objsubid;
2803 
2804  if (dep.objectSubId != 0) /* should not happen */
2805  elog(ERROR, "extension should not have a sub-object dependency");
2806 
2807  /* Relocate the object */
2808  dep_oldNspOid = AlterObjectNamespace_oid(dep.classId,
2809  dep.objectId,
2810  nspOid,
2811  objsMoved);
2812 
2813  /*
2814  * Remember previous namespace of first object that has one
2815  */
2816  if (oldNspOid == InvalidOid && dep_oldNspOid != InvalidOid)
2817  oldNspOid = dep_oldNspOid;
2818 
2819  /*
2820  * If not all the objects had the same old namespace (ignoring any
2821  * that are not in namespaces), complain.
2822  */
2823  if (dep_oldNspOid != InvalidOid && dep_oldNspOid != oldNspOid)
2824  ereport(ERROR,
2825  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2826  errmsg("extension \"%s\" does not support SET SCHEMA",
2827  NameStr(extForm->extname)),
2828  errdetail("%s is not in the extension's schema \"%s\"",
2829  getObjectDescription(&dep),
2830  get_namespace_name(oldNspOid))));
2831  }
2832 
2833  /* report old schema, if caller wants it */
2834  if (oldschema)
2835  *oldschema = oldNspOid;
2836 
2837  systable_endscan(depScan);
2838 
2840 
2841  /* Now adjust pg_extension.extnamespace */
2842  extForm->extnamespace = nspOid;
2843 
2844  CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
2845 
2846  heap_close(extRel, RowExclusiveLock);
2847 
2848  /* update dependencies to point to the new schema */
2850  NamespaceRelationId, oldNspOid, nspOid);
2851 
2853 
2854  ObjectAddressSet(extAddr, ExtensionRelationId, extensionOid);
2855 
2856  return extAddr;
2857 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
#define Anum_pg_depend_refobjid
Definition: pg_depend.h:72
#define NamespaceRelationId
Definition: pg_namespace.h:34
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c:447
#define Anum_pg_depend_refclassid
Definition: pg_depend.h:71
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:284
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
Oid LookupCreationNamespace(const char *nspname)
Definition: namespace.c:2896
#define DependReferenceIndexId
Definition: indexing.h:147
#define DependRelationId
Definition: pg_depend.h:29
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
#define heap_close(r, l)
Definition: heapam.h:97
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2052
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4484
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
char * getObjectDescription(const ObjectAddress *object)
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
ItemPointerData t_self
Definition: htup.h:65
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5042
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:61
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define ExtensionOidIndexId
Definition: indexing.h:319
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:51
AclResult
Definition: acl.h:170
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:135
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:295
Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid, ObjectAddresses *objsMoved)
Definition: alter.c:553
#define NameStr(name)
Definition: c.h:499
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define ExtensionRelationId
Definition: pg_extension.h:29
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void AlterExtensionOwner_oid ( Oid  extensionOid,
Oid  newOwnerId 
)
ObjectAddress CreateExtension ( ParseState pstate,
CreateExtensionStmt stmt 
)

Definition at line 1621 of file extension.c.

References check_valid_extension_name(), CreateExtensionInternal(), creating_extension, defGetBoolean(), defGetString(), DefElem::defname, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, CreateExtensionStmt::extname, get_extension_oid(), CreateExtensionStmt::if_not_exists, InvalidObjectAddress, InvalidOid, lfirst, DefElem::location, NIL, NOTICE, NULL, CreateExtensionStmt::options, and parser_errposition().

Referenced by ProcessUtilitySlow().

1622 {
1623  DefElem *d_schema = NULL;
1624  DefElem *d_new_version = NULL;
1625  DefElem *d_old_version = NULL;
1626  DefElem *d_cascade = NULL;
1627  char *schemaName = NULL;
1628  char *versionName = NULL;
1629  char *oldVersionName = NULL;
1630  bool cascade = false;
1631  ListCell *lc;
1632 
1633  /* Check extension name validity before any filesystem access */
1635 
1636  /*
1637  * Check for duplicate extension name. The unique index on
1638  * pg_extension.extname would catch this anyway, and serves as a backstop
1639  * in case of race conditions; but this is a friendlier error message, and
1640  * besides we need a check to support IF NOT EXISTS.
1641  */
1642  if (get_extension_oid(stmt->extname, true) != InvalidOid)
1643  {
1644  if (stmt->if_not_exists)
1645  {
1646  ereport(NOTICE,
1648  errmsg("extension \"%s\" already exists, skipping",
1649  stmt->extname)));
1650  return InvalidObjectAddress;
1651  }
1652  else
1653  ereport(ERROR,
1655  errmsg("extension \"%s\" already exists",
1656  stmt->extname)));
1657  }
1658 
1659  /*
1660  * We use global variables to track the extension being created, so we can
1661  * create only one extension at the same time.
1662  */
1663  if (creating_extension)
1664  ereport(ERROR,
1665  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1666  errmsg("nested CREATE EXTENSION is not supported")));
1667 
1668  /* Deconstruct the statement option list */
1669  foreach(lc, stmt->options)
1670  {
1671  DefElem *defel = (DefElem *) lfirst(lc);
1672 
1673  if (strcmp(defel->defname, "schema") == 0)
1674  {
1675  if (d_schema)
1676  ereport(ERROR,
1677  (errcode(ERRCODE_SYNTAX_ERROR),
1678  errmsg("conflicting or redundant options"),
1679  parser_errposition(pstate, defel->location)));
1680  d_schema = defel;
1681  schemaName = defGetString(d_schema);
1682  }
1683  else if (strcmp(defel->defname, "new_version") == 0)
1684  {
1685  if (d_new_version)
1686  ereport(ERROR,
1687  (errcode(ERRCODE_SYNTAX_ERROR),
1688  errmsg("conflicting or redundant options"),
1689  parser_errposition(pstate, defel->location)));
1690  d_new_version = defel;
1691  versionName = defGetString(d_new_version);
1692  }
1693  else if (strcmp(defel->defname, "old_version") == 0)
1694  {
1695  if (d_old_version)
1696  ereport(ERROR,
1697  (errcode(ERRCODE_SYNTAX_ERROR),
1698  errmsg("conflicting or redundant options"),
1699  parser_errposition(pstate, defel->location)));
1700  d_old_version = defel;
1701  oldVersionName = defGetString(d_old_version);
1702  }
1703  else if (strcmp(defel->defname, "cascade") == 0)
1704  {
1705  if (d_cascade)
1706  ereport(ERROR,
1707  (errcode(ERRCODE_SYNTAX_ERROR),
1708  errmsg("conflicting or redundant options"),
1709  parser_errposition(pstate, defel->location)));
1710  d_cascade = defel;
1711  cascade = defGetBoolean(d_cascade);
1712  }
1713  else
1714  elog(ERROR, "unrecognized option: %s", defel->defname);
1715  }
1716 
1717  /* Call CreateExtensionInternal to do the real work. */
1718  return CreateExtensionInternal(stmt->extname,
1719  schemaName,
1720  versionName,
1721  oldVersionName,
1722  cascade,
1723  NIL,
1724  true);
1725 }
#define NIL
Definition: pg_list.h:69
static void check_valid_extension_name(const char *extensionname)
Definition: extension.c:256
int errcode(int sqlerrcode)
Definition: elog.c:575
bool defGetBoolean(DefElem *def)
Definition: define.c:111
#define ERROR
Definition: elog.h:43
char * defGetString(DefElem *def)
Definition: define.c:49
int location
Definition: parsenodes.h:722
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidOid
Definition: postgres_ext.h:36
bool creating_extension
Definition: extension.c:67
#define NOTICE
Definition: elog.h:37
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:135
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:719
#define elog
Definition: elog.h:219
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
static ObjectAddress CreateExtensionInternal(char *extensionName, char *schemaName, char *versionName, char *oldVersionName, bool cascade, List *parents, bool is_create)
Definition: extension.c:1267
ObjectAddress ExecAlterExtensionContentsStmt ( AlterExtensionContentsStmt stmt,
ObjectAddress objAddress 
)

Definition at line 3171 of file extension.c.

References ACL_KIND_EXTENSION, aclcheck_error(), ACLCHECK_NOT_OWNER, AlterExtensionContentsStmt::action, Assert, check_object_ownership(), ObjectAddress::classId, deleteDependencyRecordsForClass(), DEPENDENCY_EXTENSION, elog, ereport, errcode(), errmsg(), ERROR, extension_config_remove(), ExtensionRelationId, AlterExtensionContentsStmt::extname, get_extension_name(), get_extension_oid(), get_extension_schema(), get_namespace_name(), get_object_address(), getExtensionOfObject(), getObjectDescription(), GetUserId(), InvokeObjectPostAlterHook, NamespaceRelationId, NoLock, NULL, AlterExtensionContentsStmt::object, ObjectAddress::objectId, ObjectAddress::objectSubId, AlterExtensionContentsStmt::objtype, OidIsValid, pg_extension_ownercheck(), recordDependencyOn(), recordExtObjInitPriv(), relation_close(), RelationRelationId, removeExtObjInitPriv(), and ShareUpdateExclusiveLock.

Referenced by ProcessUtilitySlow().

3173 {
3174  ObjectAddress extension;
3175  ObjectAddress object;
3176  Relation relation;
3177  Oid oldExtension;
3178 
3179  extension.classId = ExtensionRelationId;
3180  extension.objectId = get_extension_oid(stmt->extname, false);
3181  extension.objectSubId = 0;
3182 
3183  /* Permission check: must own extension */
3184  if (!pg_extension_ownercheck(extension.objectId, GetUserId()))
3186  stmt->extname);
3187 
3188  /*
3189  * Translate the parser representation that identifies the object into an
3190  * ObjectAddress. get_object_address() will throw an error if the object
3191  * does not exist, and will also acquire a lock on the object to guard
3192  * against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
3193  */
3194  object = get_object_address(stmt->objtype, stmt->object,
3195  &relation, ShareUpdateExclusiveLock, false);
3196 
3197  Assert(object.objectSubId == 0);
3198  if (objAddr)
3199  *objAddr = object;
3200 
3201  /* Permission check: must own target object, too */
3202  check_object_ownership(GetUserId(), stmt->objtype, object,
3203  stmt->object, relation);
3204 
3205  /*
3206  * Check existing extension membership.
3207  */
3208  oldExtension = getExtensionOfObject(object.classId, object.objectId);
3209 
3210  if (stmt->action > 0)
3211  {
3212  /*
3213  * ADD, so complain if object is already attached to some extension.
3214  */
3215  if (OidIsValid(oldExtension))
3216  ereport(ERROR,
3217  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3218  errmsg("%s is already a member of extension \"%s\"",
3219  getObjectDescription(&object),
3220  get_extension_name(oldExtension))));
3221 
3222  /*
3223  * Prevent a schema from being added to an extension if the schema
3224  * contains the extension. That would create a dependency loop.
3225  */
3226  if (object.classId == NamespaceRelationId &&
3227  object.objectId == get_extension_schema(extension.objectId))
3228  ereport(ERROR,
3229  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3230  errmsg("cannot add schema \"%s\" to extension \"%s\" "
3231  "because the schema contains the extension",
3232  get_namespace_name(object.objectId),
3233  stmt->extname)));
3234 
3235  /*
3236  * OK, add the dependency.
3237  */
3238  recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
3239 
3240  /*
3241  * Also record the initial ACL on the object, if any.
3242  *
3243  * Note that this will handle the object's ACLs, as well as any ACLs
3244  * on object subIds. (In other words, when the object is a table,
3245  * this will record the table's ACL and the ACLs for the columns on
3246  * the table, if any).
3247  */
3248  recordExtObjInitPriv(object.objectId, object.classId);
3249  }
3250  else
3251  {
3252  /*
3253  * DROP, so complain if it's not a member.
3254  */
3255  if (oldExtension != extension.objectId)
3256  ereport(ERROR,
3257  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3258  errmsg("%s is not a member of extension \"%s\"",
3259  getObjectDescription(&object),
3260  stmt->extname)));
3261 
3262  /*
3263  * OK, drop the dependency.
3264  */
3265  if (deleteDependencyRecordsForClass(object.classId, object.objectId,
3267  DEPENDENCY_EXTENSION) != 1)
3268  elog(ERROR, "unexpected number of extension dependency records");
3269 
3270  /*
3271  * If it's a relation, it might have an entry in the extension's
3272  * extconfig array, which we must remove.
3273  */
3274  if (object.classId == RelationRelationId)
3275  extension_config_remove(extension.objectId, object.objectId);
3276 
3277  /*
3278  * Remove all the initial ACLs, if any.
3279  *
3280  * Note that this will remove the object's ACLs, as well as any ACLs
3281  * on object subIds. (In other words, when the object is a table,
3282  * this will remove the table's ACL and the ACLs for the columns on
3283  * the table, if any).
3284  */
3285  removeExtObjInitPriv(object.objectId, object.classId);
3286  }
3287 
3289 
3290  /*
3291  * If get_object_address() opened the relation for us, we close it to keep
3292  * the reference count correct - but we retain any locks acquired by
3293  * get_object_address() until commit time, to guard against concurrent
3294  * activity.
3295  */
3296  if (relation != NULL)
3297  relation_close(relation, NoLock);
3298 
3299  return extension;
3300 }
void recordExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:5328
#define NamespaceRelationId
Definition: pg_namespace.h:34
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c:447
static Oid get_extension_schema(Oid ext_oid)
Definition: extension.c:219
Oid GetUserId(void)
Definition: miscinit.c:284
#define RelationRelationId
Definition: pg_class.h:29
char * get_extension_name(Oid ext_oid)
Definition: extension.c:180
int errcode(int sqlerrcode)
Definition: elog.c:575
static void extension_config_remove(Oid extensionoid, Oid tableoid)
Definition: extension.c:2510
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
char * getObjectDescription(const ObjectAddress *object)
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
#define NoLock
Definition: lockdefs.h:34
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5042
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:241
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
ObjectAddress get_object_address(ObjectType objtype, Node *object, Relation *relp, LOCKMODE lockmode, bool missing_ok)
void check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, Node *object, Relation relation)
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:135
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define ExtensionRelationId
Definition: pg_extension.h:29
void removeExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:5617
ObjectAddress ExecAlterExtensionStmt ( ParseState pstate,
AlterExtensionStmt stmt 
)

Definition at line 2863 of file extension.c.

References AccessShareLock, ACL_KIND_EXTENSION, aclcheck_error(), ACLCHECK_NOT_OWNER, Anum_pg_extension_extname, Anum_pg_extension_extversion, ApplyExtensionUpdates(), DefElem::arg, BTEqualStrategyNumber, check_valid_version_name(), creating_extension, CStringGetDatum, DatumGetTextPP, ExtensionControlFile::default_version, DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, ExtensionNameIndexId, ExtensionRelationId, AlterExtensionStmt::extname, GetUserId(), heap_close, heap_getattr, heap_open(), HeapTupleGetOid, HeapTupleIsValid, identify_update_path(), InvalidObjectAddress, lfirst, DefElem::location, NOTICE, NULL, ObjectAddressSet, AlterExtensionStmt::options, parser_errposition(), pg_extension_ownercheck(), read_extension_control_file(), RelationGetDescr, ScanKeyInit(), strVal, systable_beginscan(), systable_endscan(), systable_getnext(), and text_to_cstring().

Referenced by ProcessUtilitySlow().

2864 {
2865  DefElem *d_new_version = NULL;
2866  char *versionName;
2867  char *oldVersionName;
2868  ExtensionControlFile *control;
2869  Oid extensionOid;
2870  Relation extRel;
2871  ScanKeyData key[1];
2872  SysScanDesc extScan;
2873  HeapTuple extTup;
2874  List *updateVersions;
2875  Datum datum;
2876  bool isnull;
2877  ListCell *lc;
2878  ObjectAddress address;
2879 
2880  /*
2881  * We use global variables to track the extension being created, so we can
2882  * create/update only one extension at the same time.
2883  */
2884  if (creating_extension)
2885  ereport(ERROR,
2886  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2887  errmsg("nested ALTER EXTENSION is not supported")));
2888 
2889  /*
2890  * Look up the extension --- it must already exist in pg_extension
2891  */
2893 
2894  ScanKeyInit(&key[0],
2896  BTEqualStrategyNumber, F_NAMEEQ,
2897  CStringGetDatum(stmt->extname));
2898 
2899  extScan = systable_beginscan(extRel, ExtensionNameIndexId, true,
2900  NULL, 1, key);
2901 
2902  extTup = systable_getnext(extScan);
2903 
2904  if (!HeapTupleIsValid(extTup))
2905  ereport(ERROR,
2906  (errcode(ERRCODE_UNDEFINED_OBJECT),
2907  errmsg("extension \"%s\" does not exist",
2908  stmt->extname)));
2909 
2910  extensionOid = HeapTupleGetOid(extTup);
2911 
2912  /*
2913  * Determine the existing version we are updating from
2914  */
2916  RelationGetDescr(extRel), &isnull);
2917  if (isnull)
2918  elog(ERROR, "extversion is null");
2919  oldVersionName = text_to_cstring(DatumGetTextPP(datum));
2920 
2921  systable_endscan(extScan);
2922 
2923  heap_close(extRel, AccessShareLock);
2924 
2925  /* Permission check: must own extension */
2926  if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2928  stmt->extname);
2929 
2930  /*
2931  * Read the primary control file. Note we assume that it does not contain
2932  * any non-ASCII data, so there is no need to worry about encoding at this
2933  * point.
2934  */
2935  control = read_extension_control_file(stmt->extname);
2936 
2937  /*
2938  * Read the statement option list
2939  */
2940  foreach(lc, stmt->options)
2941  {
2942  DefElem *defel = (DefElem *) lfirst(lc);
2943 
2944  if (strcmp(defel->defname, "new_version") == 0)
2945  {
2946  if (d_new_version)
2947  ereport(ERROR,
2948  (errcode(ERRCODE_SYNTAX_ERROR),
2949  errmsg("conflicting or redundant options"),
2950  parser_errposition(pstate, defel->location)));
2951  d_new_version = defel;
2952  }
2953  else
2954  elog(ERROR, "unrecognized option: %s", defel->defname);
2955  }
2956 
2957  /*
2958  * Determine the version to update to
2959  */
2960  if (d_new_version && d_new_version->arg)
2961  versionName = strVal(d_new_version->arg);
2962  else if (control->default_version)
2963  versionName = control->default_version;
2964  else
2965  {
2966  ereport(ERROR,
2967  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2968  errmsg("version to install must be specified")));
2969  versionName = NULL; /* keep compiler quiet */
2970  }
2971  check_valid_version_name(versionName);
2972 
2973  /*
2974  * If we're already at that version, just say so
2975  */
2976  if (strcmp(oldVersionName, versionName) == 0)
2977  {
2978  ereport(NOTICE,
2979  (errmsg("version \"%s\" of extension \"%s\" is already installed",
2980  versionName, stmt->extname)));
2981  return InvalidObjectAddress;
2982  }
2983 
2984  /*
2985  * Identify the series of update script files we need to execute
2986  */
2987  updateVersions = identify_update_path(control,
2988  oldVersionName,
2989  versionName);
2990 
2991  /*
2992  * Update the pg_extension row and execute the update scripts, one at a
2993  * time
2994  */
2995  ApplyExtensionUpdates(extensionOid, control,
2996  oldVersionName, updateVersions,
2997  NULL, false, false);
2998 
2999  ObjectAddressSet(address, ExtensionRelationId, extensionOid);
3000 
3001  return address;
3002 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define ExtensionNameIndexId
Definition: indexing.h:321
static ExtensionControlFile * read_extension_control_file(const char *extname)
Definition: extension.c:603
#define RelationGetDescr(relation)
Definition: rel.h:428
Oid GetUserId(void)
Definition: miscinit.c:284
#define Anum_pg_extension_extversion
Definition: pg_extension.h:63
#define DatumGetTextPP(X)
Definition: fmgr.h:256
static void ApplyExtensionUpdates(Oid extensionOid, ExtensionControlFile *pcontrol, const char *initialVersion, List *updateVersions, char *origSchemaName, bool cascade, bool is_create)
Definition: extension.c:3013
#define AccessShareLock
Definition: lockdefs.h:36
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ERROR
Definition: elog.h:43
static List * identify_update_path(ExtensionControlFile *control, const char *oldVersion, const char *newVersion)
Definition: extension.c:1076
#define Anum_pg_extension_extname
Definition: pg_extension.h:59
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5042
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
int location
Definition: parsenodes.h:722
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:720
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
char * default_version
Definition: extension.c:77
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
static void check_valid_version_name(const char *versionname)
Definition: extension.c:303
bool creating_extension
Definition: extension.c:67
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
char * text_to_cstring(const text *t)
Definition: varlena.c:182
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
char * defname
Definition: parsenodes.h:719
#define elog
Definition: elog.h:219
#define ExtensionRelationId
Definition: pg_extension.h:29
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
char* get_extension_name ( Oid  ext_oid)

Definition at line 180 of file extension.c.

References AccessShareLock, BTEqualStrategyNumber, ExtensionOidIndexId, ExtensionRelationId, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, NameStr, NULL, ObjectIdAttributeNumber, ObjectIdGetDatum, pstrdup(), result, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by ExecAlterExtensionContentsStmt(), getObjectDescription(), getObjectIdentityParts(), recordDependencyOnCurrentExtension(), and RemoveExtensionById().

181 {
182  char *result;
183  Relation rel;
184  SysScanDesc scandesc;
185  HeapTuple tuple;
186  ScanKeyData entry[1];
187 
189 
190  ScanKeyInit(&entry[0],
192  BTEqualStrategyNumber, F_OIDEQ,
193  ObjectIdGetDatum(ext_oid));
194 
195  scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
196  NULL, 1, entry);
197 
198  tuple = systable_getnext(scandesc);
199 
200  /* We assume that there can be at most one matching tuple */
201  if (HeapTupleIsValid(tuple))
202  result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname));
203  else
204  result = NULL;
205 
206  systable_endscan(scandesc);
207 
209 
210  return result;
211 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
char * pstrdup(const char *in)
Definition: mcxt.c:1077
#define AccessShareLock
Definition: lockdefs.h:36
return result
Definition: formatting.c:1633
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ExtensionOidIndexId
Definition: indexing.h:319
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:51
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define NameStr(name)
Definition: c.h:499
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ExtensionRelationId
Definition: pg_extension.h:29
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Oid get_extension_oid ( const char *  extname,
bool  missing_ok 
)

Definition at line 135 of file extension.c.

References AccessShareLock, Anum_pg_extension_extname, BTEqualStrategyNumber, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, ExtensionNameIndexId, ExtensionRelationId, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvalidOid, NULL, OidIsValid, result, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by AlterExtensionNamespace(), binary_upgrade_create_empty_extension(), CreateExtension(), ExecAlterExtensionContentsStmt(), ExtractExtensionList(), get_object_address_unqualified(), and get_required_extension().

136 {
137  Oid result;
138  Relation rel;
139  SysScanDesc scandesc;
140  HeapTuple tuple;
141  ScanKeyData entry[1];
142 
144 
145  ScanKeyInit(&entry[0],
147  BTEqualStrategyNumber, F_NAMEEQ,
148  CStringGetDatum(extname));
149 
150  scandesc = systable_beginscan(rel, ExtensionNameIndexId, true,
151  NULL, 1, entry);
152 
153  tuple = systable_getnext(scandesc);
154 
155  /* We assume that there can be at most one matching tuple */
156  if (HeapTupleIsValid(tuple))
157  result = HeapTupleGetOid(tuple);
158  else
159  result = InvalidOid;
160 
161  systable_endscan(scandesc);
162 
164 
165  if (!OidIsValid(result) && !missing_ok)
166  ereport(ERROR,
167  (errcode(ERRCODE_UNDEFINED_OBJECT),
168  errmsg("extension \"%s\" does not exist",
169  extname)));
170 
171  return result;
172 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define ExtensionNameIndexId
Definition: indexing.h:321
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
return result
Definition: formatting.c:1633
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ERROR
Definition: elog.h:43
#define Anum_pg_extension_extname
Definition: pg_extension.h:59
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ExtensionRelationId
Definition: pg_extension.h:29
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ObjectAddress InsertExtensionTuple ( const char *  extName,
Oid  extOwner,
Oid  schemaOid,
bool  relocatable,
const char *  extVersion,
Datum  extConfig,
Datum  extCondition,
List requiredExtensions 
)

Definition at line 1741 of file extension.c.

References Anum_pg_extension_extcondition, Anum_pg_extension_extconfig, Anum_pg_extension_extname, Anum_pg_extension_extnamespace, Anum_pg_extension_extowner, Anum_pg_extension_extrelocatable, Anum_pg_extension_extversion, BoolGetDatum, CatalogTupleInsert(), ObjectAddress::classId, CStringGetDatum, CStringGetTextDatum, DEPENDENCY_NORMAL, DirectFunctionCall1, ExtensionRelationId, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), InvokeObjectPostCreateHook, lfirst_oid, namein(), NamespaceRelationId, Natts_pg_extension, NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, PointerGetDatum, RelationData::rd_att, recordDependencyOn(), recordDependencyOnOwner(), RowExclusiveLock, and values.

Referenced by binary_upgrade_create_empty_extension(), and CreateExtensionInternal().

1745 {
1746  Oid extensionOid;
1747  Relation rel;
1749  bool nulls[Natts_pg_extension];
1750  HeapTuple tuple;
1751  ObjectAddress myself;
1752  ObjectAddress nsp;
1753  ListCell *lc;
1754 
1755  /*
1756  * Build and insert the pg_extension tuple
1757  */
1759 
1760  memset(values, 0, sizeof(values));
1761  memset(nulls, 0, sizeof(nulls));
1762 
1763  values[Anum_pg_extension_extname - 1] =
1765  values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
1766  values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
1767  values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
1768  values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
1769 
1770  if (extConfig == PointerGetDatum(NULL))
1771  nulls[Anum_pg_extension_extconfig - 1] = true;
1772  else
1773  values[Anum_pg_extension_extconfig - 1] = extConfig;
1774 
1775  if (extCondition == PointerGetDatum(NULL))
1776  nulls[Anum_pg_extension_extcondition - 1] = true;
1777  else
1778  values[Anum_pg_extension_extcondition - 1] = extCondition;
1779 
1780  tuple = heap_form_tuple(rel->rd_att, values, nulls);
1781 
1782  extensionOid = CatalogTupleInsert(rel, tuple);
1783 
1784  heap_freetuple(tuple);
1786 
1787  /*
1788  * Record dependencies on owner, schema, and prerequisite extensions
1789  */
1790  recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
1791 
1792  myself.classId = ExtensionRelationId;
1793  myself.objectId = extensionOid;
1794  myself.objectSubId = 0;
1795 
1797  nsp.objectId = schemaOid;
1798  nsp.objectSubId = 0;
1799 
1800  recordDependencyOn(&myself, &nsp, DEPENDENCY_NORMAL);
1801 
1802  foreach(lc, requiredExtensions)
1803  {
1804  Oid reqext = lfirst_oid(lc);
1805  ObjectAddress otherext;
1806 
1807  otherext.classId = ExtensionRelationId;
1808  otherext.objectId = reqext;
1809  otherext.objectSubId = 0;
1810 
1811  recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
1812  }
1813  /* Post creation hook for new extension */
1815 
1816  return myself;
1817 }
#define NamespaceRelationId
Definition: pg_namespace.h:34
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
#define Anum_pg_extension_extrelocatable
Definition: pg_extension.h:62
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define PointerGetDatum(X)
Definition: postgres.h:562
#define Anum_pg_extension_extversion
Definition: pg_extension.h:63
#define Anum_pg_extension_extconfig
Definition: pg_extension.h:64
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:584
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:159
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Anum_pg_extension_extname
Definition: pg_extension.h:59
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:584
#define Anum_pg_extension_extcondition
Definition: pg_extension.h:65
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
#define BoolGetDatum(X)
Definition: postgres.h:408
#define Anum_pg_extension_extowner
Definition: pg_extension.h:60
#define NULL
Definition: c.h:229
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define Natts_pg_extension
Definition: pg_extension.h:58
#define CStringGetTextDatum(s)
Definition: builtins.h:91
#define Anum_pg_extension_extnamespace
Definition: pg_extension.h:61
#define ExtensionRelationId
Definition: pg_extension.h:29
#define lfirst_oid(lc)
Definition: pg_list.h:108
void RemoveExtensionById ( Oid  extId)

Definition at line 1826 of file extension.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), CurrentExtensionObject, ereport, errcode(), errmsg(), ERROR, ExtensionOidIndexId, ExtensionRelationId, get_extension_name(), heap_close, heap_open(), HeapTupleIsValid, NULL, ObjectIdAttributeNumber, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by doDeletion().

1827 {
1828  Relation rel;
1829  SysScanDesc scandesc;
1830  HeapTuple tuple;
1831  ScanKeyData entry[1];
1832 
1833  /*
1834  * Disallow deletion of any extension that's currently open for insertion;
1835  * else subsequent executions of recordDependencyOnCurrentExtension()
1836  * could create dangling pg_depend records that refer to a no-longer-valid
1837  * pg_extension OID. This is needed not so much because we think people
1838  * might write "DROP EXTENSION foo" in foo's own script files, as because
1839  * errors in dependency management in extension script files could give
1840  * rise to cases where an extension is dropped as a result of recursing
1841  * from some contained object. Because of that, we must test for the case
1842  * here, not at some higher level of the DROP EXTENSION command.
1843  */
1844  if (extId == CurrentExtensionObject)
1845  ereport(ERROR,
1846  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1847  errmsg("cannot drop extension \"%s\" because it is being modified",
1848  get_extension_name(extId))));
1849 
1851 
1852  ScanKeyInit(&entry[0],
1854  BTEqualStrategyNumber, F_OIDEQ,
1855  ObjectIdGetDatum(extId));
1856  scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
1857  NULL, 1, entry);
1858 
1859  tuple = systable_getnext(scandesc);
1860 
1861  /* We assume that there can be at most one matching tuple */
1862  if (HeapTupleIsValid(tuple))
1863  CatalogTupleDelete(rel, &tuple->t_self);
1864 
1865  systable_endscan(scandesc);
1866 
1868 }
Oid CurrentExtensionObject
Definition: extension.c:68
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
char * get_extension_name(Oid ext_oid)
Definition: extension.c:180
int errcode(int sqlerrcode)
Definition: elog.c:575
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define ExtensionOidIndexId
Definition: indexing.h:319
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ExtensionRelationId
Definition: pg_extension.h:29
#define BTEqualStrategyNumber
Definition: stratnum.h:31

Variable Documentation