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 2677 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().

2678 {
2679  Oid extensionOid;
2680  Oid nspOid;
2681  Oid oldNspOid = InvalidOid;
2682  AclResult aclresult;
2683  Relation extRel;
2684  ScanKeyData key[2];
2685  SysScanDesc extScan;
2686  HeapTuple extTup;
2687  Form_pg_extension extForm;
2688  Relation depRel;
2689  SysScanDesc depScan;
2690  HeapTuple depTup;
2691  ObjectAddresses *objsMoved;
2692  ObjectAddress extAddr;
2693 
2694  extensionOid = get_extension_oid(extensionName, false);
2695 
2696  nspOid = LookupCreationNamespace(newschema);
2697 
2698  /*
2699  * Permission check: must own extension. Note that we don't bother to
2700  * check ownership of the individual member objects ...
2701  */
2702  if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2704  extensionName);
2705 
2706  /* Permission check: must have creation rights in target namespace */
2707  aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
2708  if (aclresult != ACLCHECK_OK)
2709  aclcheck_error(aclresult, ACL_KIND_NAMESPACE, newschema);
2710 
2711  /*
2712  * If the schema is currently a member of the extension, disallow moving
2713  * the extension into the schema. That would create a dependency loop.
2714  */
2715  if (getExtensionOfObject(NamespaceRelationId, nspOid) == extensionOid)
2716  ereport(ERROR,
2717  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2718  errmsg("cannot move extension \"%s\" into schema \"%s\" "
2719  "because the extension contains the schema",
2720  extensionName, newschema)));
2721 
2722  /* Locate the pg_extension tuple */
2724 
2725  ScanKeyInit(&key[0],
2727  BTEqualStrategyNumber, F_OIDEQ,
2728  ObjectIdGetDatum(extensionOid));
2729 
2730  extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2731  NULL, 1, key);
2732 
2733  extTup = systable_getnext(extScan);
2734 
2735  if (!HeapTupleIsValid(extTup)) /* should not happen */
2736  elog(ERROR, "extension with oid %u does not exist", extensionOid);
2737 
2738  /* Copy tuple so we can modify it below */
2739  extTup = heap_copytuple(extTup);
2740  extForm = (Form_pg_extension) GETSTRUCT(extTup);
2741 
2742  systable_endscan(extScan);
2743 
2744  /*
2745  * If the extension is already in the target schema, just silently do
2746  * nothing.
2747  */
2748  if (extForm->extnamespace == nspOid)
2749  {
2750  heap_close(extRel, RowExclusiveLock);
2751  return InvalidObjectAddress;
2752  }
2753 
2754  /* Check extension is supposed to be relocatable */
2755  if (!extForm->extrelocatable)
2756  ereport(ERROR,
2757  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2758  errmsg("extension \"%s\" does not support SET SCHEMA",
2759  NameStr(extForm->extname))));
2760 
2761  objsMoved = new_object_addresses();
2762 
2763  /*
2764  * Scan pg_depend to find objects that depend directly on the extension,
2765  * and alter each one's schema.
2766  */
2768 
2769  ScanKeyInit(&key[0],
2771  BTEqualStrategyNumber, F_OIDEQ,
2773  ScanKeyInit(&key[1],
2775  BTEqualStrategyNumber, F_OIDEQ,
2776  ObjectIdGetDatum(extensionOid));
2777 
2778  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
2779  NULL, 2, key);
2780 
2781  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
2782  {
2783  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
2784  ObjectAddress dep;
2785  Oid dep_oldNspOid;
2786 
2787  /*
2788  * Ignore non-membership dependencies. (Currently, the only other
2789  * case we could see here is a normal dependency from another
2790  * extension.)
2791  */
2792  if (pg_depend->deptype != DEPENDENCY_EXTENSION)
2793  continue;
2794 
2795  dep.classId = pg_depend->classid;
2796  dep.objectId = pg_depend->objid;
2797  dep.objectSubId = pg_depend->objsubid;
2798 
2799  if (dep.objectSubId != 0) /* should not happen */
2800  elog(ERROR, "extension should not have a sub-object dependency");
2801 
2802  /* Relocate the object */
2803  dep_oldNspOid = AlterObjectNamespace_oid(dep.classId,
2804  dep.objectId,
2805  nspOid,
2806  objsMoved);
2807 
2808  /*
2809  * Remember previous namespace of first object that has one
2810  */
2811  if (oldNspOid == InvalidOid && dep_oldNspOid != InvalidOid)
2812  oldNspOid = dep_oldNspOid;
2813 
2814  /*
2815  * If not all the objects had the same old namespace (ignoring any
2816  * that are not in namespaces), complain.
2817  */
2818  if (dep_oldNspOid != InvalidOid && dep_oldNspOid != oldNspOid)
2819  ereport(ERROR,
2820  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2821  errmsg("extension \"%s\" does not support SET SCHEMA",
2822  NameStr(extForm->extname)),
2823  errdetail("%s is not in the extension's schema \"%s\"",
2824  getObjectDescription(&dep),
2825  get_namespace_name(oldNspOid))));
2826  }
2827 
2828  /* report old schema, if caller wants it */
2829  if (oldschema)
2830  *oldschema = oldNspOid;
2831 
2832  systable_endscan(depScan);
2833 
2835 
2836  /* Now adjust pg_extension.extnamespace */
2837  extForm->extnamespace = nspOid;
2838 
2839  CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
2840 
2841  heap_close(extRel, RowExclusiveLock);
2842 
2843  /* update dependencies to point to the new schema */
2845  NamespaceRelationId, oldNspOid, nspOid);
2846 
2848 
2849  ObjectAddressSet(extAddr, ExtensionRelationId, extensionOid);
2850 
2851  return extAddr;
2852 }
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:283
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
Oid LookupCreationNamespace(const char *nspname)
Definition: namespace.c:2786
#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:1260
#define heap_close(r, l)
Definition: heapam.h:97
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2039
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:3038
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:1284
#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:134
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:552
#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 1617 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().

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

Definition at line 3166 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().

3168 {
3169  ObjectAddress extension;
3170  ObjectAddress object;
3171  Relation relation;
3172  Oid oldExtension;
3173 
3174  extension.classId = ExtensionRelationId;
3175  extension.objectId = get_extension_oid(stmt->extname, false);
3176  extension.objectSubId = 0;
3177 
3178  /* Permission check: must own extension */
3179  if (!pg_extension_ownercheck(extension.objectId, GetUserId()))
3181  stmt->extname);
3182 
3183  /*
3184  * Translate the parser representation that identifies the object into an
3185  * ObjectAddress. get_object_address() will throw an error if the object
3186  * does not exist, and will also acquire a lock on the object to guard
3187  * against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
3188  */
3189  object = get_object_address(stmt->objtype, stmt->object,
3190  &relation, ShareUpdateExclusiveLock, false);
3191 
3192  Assert(object.objectSubId == 0);
3193  if (objAddr)
3194  *objAddr = object;
3195 
3196  /* Permission check: must own target object, too */
3197  check_object_ownership(GetUserId(), stmt->objtype, object,
3198  stmt->object, relation);
3199 
3200  /*
3201  * Check existing extension membership.
3202  */
3203  oldExtension = getExtensionOfObject(object.classId, object.objectId);
3204 
3205  if (stmt->action > 0)
3206  {
3207  /*
3208  * ADD, so complain if object is already attached to some extension.
3209  */
3210  if (OidIsValid(oldExtension))
3211  ereport(ERROR,
3212  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3213  errmsg("%s is already a member of extension \"%s\"",
3214  getObjectDescription(&object),
3215  get_extension_name(oldExtension))));
3216 
3217  /*
3218  * Prevent a schema from being added to an extension if the schema
3219  * contains the extension. That would create a dependency loop.
3220  */
3221  if (object.classId == NamespaceRelationId &&
3222  object.objectId == get_extension_schema(extension.objectId))
3223  ereport(ERROR,
3224  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3225  errmsg("cannot add schema \"%s\" to extension \"%s\" "
3226  "because the schema contains the extension",
3227  get_namespace_name(object.objectId),
3228  stmt->extname)));
3229 
3230  /*
3231  * OK, add the dependency.
3232  */
3233  recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
3234 
3235  /*
3236  * Also record the initial ACL on the object, if any.
3237  *
3238  * Note that this will handle the object's ACLs, as well as any ACLs
3239  * on object subIds. (In other words, when the object is a table,
3240  * this will record the table's ACL and the ACLs for the columns on
3241  * the table, if any).
3242  */
3243  recordExtObjInitPriv(object.objectId, object.classId);
3244  }
3245  else
3246  {
3247  /*
3248  * DROP, so complain if it's not a member.
3249  */
3250  if (oldExtension != extension.objectId)
3251  ereport(ERROR,
3252  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3253  errmsg("%s is not a member of extension \"%s\"",
3254  getObjectDescription(&object),
3255  stmt->extname)));
3256 
3257  /*
3258  * OK, drop the dependency.
3259  */
3260  if (deleteDependencyRecordsForClass(object.classId, object.objectId,
3262  DEPENDENCY_EXTENSION) != 1)
3263  elog(ERROR, "unexpected number of extension dependency records");
3264 
3265  /*
3266  * If it's a relation, it might have an entry in the extension's
3267  * extconfig array, which we must remove.
3268  */
3269  if (object.classId == RelationRelationId)
3270  extension_config_remove(extension.objectId, object.objectId);
3271 
3272  /*
3273  * Remove all the initial ACLs, if any.
3274  *
3275  * Note that this will remove the object's ACLs, as well as any ACLs
3276  * on object subIds. (In other words, when the object is a table,
3277  * this will remove the table's ACL and the ACLs for the columns on
3278  * the table, if any).
3279  */
3280  removeExtObjInitPriv(object.objectId, object.classId);
3281  }
3282 
3284 
3285  /*
3286  * If get_object_address() opened the relation for us, we close it to keep
3287  * the reference count correct - but we retain any locks acquired by
3288  * get_object_address() until commit time, to guard against concurrent
3289  * activity.
3290  */
3291  if (relation != NULL)
3292  relation_close(relation, NoLock);
3293 
3294  return extension;
3295 }
void recordExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:5327
#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:218
Oid GetUserId(void)
Definition: miscinit.c:283
#define RelationRelationId
Definition: pg_class.h:29
char * get_extension_name(Oid ext_oid)
Definition: extension.c:179
int errcode(int sqlerrcode)
Definition: elog.c:575
static void extension_config_remove(Oid extensionoid, Oid tableoid)
Definition: extension.c:2506
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1260
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:3038
#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:675
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:134
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:5616
ObjectAddress ExecAlterExtensionStmt ( ParseState pstate,
AlterExtensionStmt stmt 
)

Definition at line 2858 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().

2859 {
2860  DefElem *d_new_version = NULL;
2861  char *versionName;
2862  char *oldVersionName;
2863  ExtensionControlFile *control;
2864  Oid extensionOid;
2865  Relation extRel;
2866  ScanKeyData key[1];
2867  SysScanDesc extScan;
2868  HeapTuple extTup;
2869  List *updateVersions;
2870  Datum datum;
2871  bool isnull;
2872  ListCell *lc;
2873  ObjectAddress address;
2874 
2875  /*
2876  * We use global variables to track the extension being created, so we can
2877  * create/update only one extension at the same time.
2878  */
2879  if (creating_extension)
2880  ereport(ERROR,
2881  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2882  errmsg("nested ALTER EXTENSION is not supported")));
2883 
2884  /*
2885  * Look up the extension --- it must already exist in pg_extension
2886  */
2888 
2889  ScanKeyInit(&key[0],
2891  BTEqualStrategyNumber, F_NAMEEQ,
2892  CStringGetDatum(stmt->extname));
2893 
2894  extScan = systable_beginscan(extRel, ExtensionNameIndexId, true,
2895  NULL, 1, key);
2896 
2897  extTup = systable_getnext(extScan);
2898 
2899  if (!HeapTupleIsValid(extTup))
2900  ereport(ERROR,
2901  (errcode(ERRCODE_UNDEFINED_OBJECT),
2902  errmsg("extension \"%s\" does not exist",
2903  stmt->extname)));
2904 
2905  extensionOid = HeapTupleGetOid(extTup);
2906 
2907  /*
2908  * Determine the existing version we are updating from
2909  */
2911  RelationGetDescr(extRel), &isnull);
2912  if (isnull)
2913  elog(ERROR, "extversion is null");
2914  oldVersionName = text_to_cstring(DatumGetTextPP(datum));
2915 
2916  systable_endscan(extScan);
2917 
2918  heap_close(extRel, AccessShareLock);
2919 
2920  /* Permission check: must own extension */
2921  if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2923  stmt->extname);
2924 
2925  /*
2926  * Read the primary control file. Note we assume that it does not contain
2927  * any non-ASCII data, so there is no need to worry about encoding at this
2928  * point.
2929  */
2930  control = read_extension_control_file(stmt->extname);
2931 
2932  /*
2933  * Read the statement option list
2934  */
2935  foreach(lc, stmt->options)
2936  {
2937  DefElem *defel = (DefElem *) lfirst(lc);
2938 
2939  if (strcmp(defel->defname, "new_version") == 0)
2940  {
2941  if (d_new_version)
2942  ereport(ERROR,
2943  (errcode(ERRCODE_SYNTAX_ERROR),
2944  errmsg("conflicting or redundant options"),
2945  parser_errposition(pstate, defel->location)));
2946  d_new_version = defel;
2947  }
2948  else
2949  elog(ERROR, "unrecognized option: %s", defel->defname);
2950  }
2951 
2952  /*
2953  * Determine the version to update to
2954  */
2955  if (d_new_version && d_new_version->arg)
2956  versionName = strVal(d_new_version->arg);
2957  else if (control->default_version)
2958  versionName = control->default_version;
2959  else
2960  {
2961  ereport(ERROR,
2962  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2963  errmsg("version to install must be specified")));
2964  versionName = NULL; /* keep compiler quiet */
2965  }
2966  check_valid_version_name(versionName);
2967 
2968  /*
2969  * If we're already at that version, just say so
2970  */
2971  if (strcmp(oldVersionName, versionName) == 0)
2972  {
2973  ereport(NOTICE,
2974  (errmsg("version \"%s\" of extension \"%s\" is already installed",
2975  versionName, stmt->extname)));
2976  return InvalidObjectAddress;
2977  }
2978 
2979  /*
2980  * Identify the series of update script files we need to execute
2981  */
2982  updateVersions = identify_update_path(control,
2983  oldVersionName,
2984  versionName);
2985 
2986  /*
2987  * Update the pg_extension row and execute the update scripts, one at a
2988  * time
2989  */
2990  ApplyExtensionUpdates(extensionOid, control,
2991  oldVersionName, updateVersions,
2992  NULL, false, false);
2993 
2994  ObjectAddressSet(address, ExtensionRelationId, extensionOid);
2995 
2996  return address;
2997 }
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:602
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#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:3008
#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:1072
#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:723
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:721
#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:1284
static void check_valid_version_name(const char *versionname)
Definition: extension.c:302
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:720
#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 179 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().

180 {
181  char *result;
182  Relation rel;
183  SysScanDesc scandesc;
184  HeapTuple tuple;
185  ScanKeyData entry[1];
186 
188 
189  ScanKeyInit(&entry[0],
191  BTEqualStrategyNumber, F_OIDEQ,
192  ObjectIdGetDatum(ext_oid));
193 
194  scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
195  NULL, 1, entry);
196 
197  tuple = systable_getnext(scandesc);
198 
199  /* We assume that there can be at most one matching tuple */
200  if (HeapTupleIsValid(tuple))
201  result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname));
202  else
203  result = NULL;
204 
205  systable_endscan(scandesc);
206 
208 
209  return result;
210 }
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:1618
#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:1284
#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 134 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().

135 {
136  Oid result;
137  Relation rel;
138  SysScanDesc scandesc;
139  HeapTuple tuple;
140  ScanKeyData entry[1];
141 
143 
144  ScanKeyInit(&entry[0],
146  BTEqualStrategyNumber, F_NAMEEQ,
147  CStringGetDatum(extname));
148 
149  scandesc = systable_beginscan(rel, ExtensionNameIndexId, true,
150  NULL, 1, entry);
151 
152  tuple = systable_getnext(scandesc);
153 
154  /* We assume that there can be at most one matching tuple */
155  if (HeapTupleIsValid(tuple))
156  result = HeapTupleGetOid(tuple);
157  else
158  result = InvalidOid;
159 
160  systable_endscan(scandesc);
161 
163 
164  if (!OidIsValid(result) && !missing_ok)
165  ereport(ERROR,
166  (errcode(ERRCODE_UNDEFINED_OBJECT),
167  errmsg("extension \"%s\" does not exist",
168  extname)));
169 
170  return result;
171 }
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:1618
#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:1284
#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 1737 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().

1741 {
1742  Oid extensionOid;
1743  Relation rel;
1745  bool nulls[Natts_pg_extension];
1746  HeapTuple tuple;
1747  ObjectAddress myself;
1748  ObjectAddress nsp;
1749  ListCell *lc;
1750 
1751  /*
1752  * Build and insert the pg_extension tuple
1753  */
1755 
1756  memset(values, 0, sizeof(values));
1757  memset(nulls, 0, sizeof(nulls));
1758 
1759  values[Anum_pg_extension_extname - 1] =
1761  values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
1762  values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
1763  values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
1764  values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
1765 
1766  if (extConfig == PointerGetDatum(NULL))
1767  nulls[Anum_pg_extension_extconfig - 1] = true;
1768  else
1769  values[Anum_pg_extension_extconfig - 1] = extConfig;
1770 
1771  if (extCondition == PointerGetDatum(NULL))
1772  nulls[Anum_pg_extension_extcondition - 1] = true;
1773  else
1774  values[Anum_pg_extension_extcondition - 1] = extCondition;
1775 
1776  tuple = heap_form_tuple(rel->rd_att, values, nulls);
1777 
1778  extensionOid = CatalogTupleInsert(rel, tuple);
1779 
1780  heap_freetuple(tuple);
1782 
1783  /*
1784  * Record dependencies on owner, schema, and prerequisite extensions
1785  */
1786  recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
1787 
1788  myself.classId = ExtensionRelationId;
1789  myself.objectId = extensionOid;
1790  myself.objectSubId = 0;
1791 
1793  nsp.objectId = schemaOid;
1794  nsp.objectSubId = 0;
1795 
1796  recordDependencyOn(&myself, &nsp, DEPENDENCY_NORMAL);
1797 
1798  foreach(lc, requiredExtensions)
1799  {
1800  Oid reqext = lfirst_oid(lc);
1801  ObjectAddress otherext;
1802 
1803  otherext.classId = ExtensionRelationId;
1804  otherext.objectId = reqext;
1805  otherext.objectSubId = 0;
1806 
1807  recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
1808  }
1809  /* Post creation hook for new extension */
1811 
1812  return myself;
1813 }
#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:1374
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:1284
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 1822 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().

1823 {
1824  Relation rel;
1825  SysScanDesc scandesc;
1826  HeapTuple tuple;
1827  ScanKeyData entry[1];
1828 
1829  /*
1830  * Disallow deletion of any extension that's currently open for insertion;
1831  * else subsequent executions of recordDependencyOnCurrentExtension()
1832  * could create dangling pg_depend records that refer to a no-longer-valid
1833  * pg_extension OID. This is needed not so much because we think people
1834  * might write "DROP EXTENSION foo" in foo's own script files, as because
1835  * errors in dependency management in extension script files could give
1836  * rise to cases where an extension is dropped as a result of recursing
1837  * from some contained object. Because of that, we must test for the case
1838  * here, not at some higher level of the DROP EXTENSION command.
1839  */
1840  if (extId == CurrentExtensionObject)
1841  ereport(ERROR,
1842  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1843  errmsg("cannot drop extension \"%s\" because it is being modified",
1844  get_extension_name(extId))));
1845 
1847 
1848  ScanKeyInit(&entry[0],
1850  BTEqualStrategyNumber, F_OIDEQ,
1851  ObjectIdGetDatum(extId));
1852  scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
1853  NULL, 1, entry);
1854 
1855  tuple = systable_getnext(scandesc);
1856 
1857  /* We assume that there can be at most one matching tuple */
1858  if (HeapTupleIsValid(tuple))
1859  CatalogTupleDelete(rel, &tuple->t_self);
1860 
1861  systable_endscan(scandesc);
1862 
1864 }
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:179
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:1284
#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