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

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

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

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

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

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

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

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

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