PostgreSQL Source Code  git master
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 *objAddr)
 
Oid get_extension_oid (const char *extname, bool missing_ok)
 
char * get_extension_name (Oid ext_oid)
 
bool extension_file_exists (const char *extensionName)
 
ObjectAddress AlterExtensionNamespace (const char *extensionName, const char *newschema, Oid *oldschema)
 

Variables

PGDLLIMPORT bool creating_extension
 
PGDLLIMPORT Oid CurrentExtensionObject
 

Function Documentation

◆ AlterExtensionNamespace()

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

Definition at line 2774 of file extension.c.

References AccessShareLock, ACL_CREATE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, AlterObjectNamespace_oid(), BTEqualStrategyNumber, CatalogTupleUpdate(), changeDependencyFor(), ObjectAddress::classId, DEPENDENCY_EXTENSION, DependReferenceIndexId, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ExtensionOidIndexId, get_extension_oid(), get_namespace_name(), getExtensionOfObject(), getObjectDescription(), GETSTRUCT, GetUserId(), heap_copytuple(), HeapTupleIsValid, InvalidObjectAddress, InvalidOid, InvokeObjectPostAlterHook, sort-test::key, LookupCreationNamespace(), NameStr, new_object_addresses(), OBJECT_EXTENSION, OBJECT_SCHEMA, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, pg_extension_ownercheck(), pg_namespace_aclcheck(), relation_close(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by ExecAlterObjectSchemaStmt().

2775 {
2776  Oid extensionOid;
2777  Oid nspOid;
2778  Oid oldNspOid = InvalidOid;
2779  AclResult aclresult;
2780  Relation extRel;
2781  ScanKeyData key[2];
2782  SysScanDesc extScan;
2783  HeapTuple extTup;
2784  Form_pg_extension extForm;
2785  Relation depRel;
2786  SysScanDesc depScan;
2787  HeapTuple depTup;
2788  ObjectAddresses *objsMoved;
2789  ObjectAddress extAddr;
2790 
2791  extensionOid = get_extension_oid(extensionName, false);
2792 
2793  nspOid = LookupCreationNamespace(newschema);
2794 
2795  /*
2796  * Permission check: must own extension. Note that we don't bother to
2797  * check ownership of the individual member objects ...
2798  */
2799  if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2801  extensionName);
2802 
2803  /* Permission check: must have creation rights in target namespace */
2804  aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
2805  if (aclresult != ACLCHECK_OK)
2806  aclcheck_error(aclresult, OBJECT_SCHEMA, newschema);
2807 
2808  /*
2809  * If the schema is currently a member of the extension, disallow moving
2810  * the extension into the schema. That would create a dependency loop.
2811  */
2812  if (getExtensionOfObject(NamespaceRelationId, nspOid) == extensionOid)
2813  ereport(ERROR,
2814  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2815  errmsg("cannot move extension \"%s\" into schema \"%s\" "
2816  "because the extension contains the schema",
2817  extensionName, newschema)));
2818 
2819  /* Locate the pg_extension tuple */
2820  extRel = table_open(ExtensionRelationId, RowExclusiveLock);
2821 
2822  ScanKeyInit(&key[0],
2823  Anum_pg_extension_oid,
2824  BTEqualStrategyNumber, F_OIDEQ,
2825  ObjectIdGetDatum(extensionOid));
2826 
2827  extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2828  NULL, 1, key);
2829 
2830  extTup = systable_getnext(extScan);
2831 
2832  if (!HeapTupleIsValid(extTup)) /* should not happen */
2833  elog(ERROR, "could not find tuple for extension %u",
2834  extensionOid);
2835 
2836  /* Copy tuple so we can modify it below */
2837  extTup = heap_copytuple(extTup);
2838  extForm = (Form_pg_extension) GETSTRUCT(extTup);
2839 
2840  systable_endscan(extScan);
2841 
2842  /*
2843  * If the extension is already in the target schema, just silently do
2844  * nothing.
2845  */
2846  if (extForm->extnamespace == nspOid)
2847  {
2848  table_close(extRel, RowExclusiveLock);
2849  return InvalidObjectAddress;
2850  }
2851 
2852  /* Check extension is supposed to be relocatable */
2853  if (!extForm->extrelocatable)
2854  ereport(ERROR,
2855  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2856  errmsg("extension \"%s\" does not support SET SCHEMA",
2857  NameStr(extForm->extname))));
2858 
2859  objsMoved = new_object_addresses();
2860 
2861  /*
2862  * Scan pg_depend to find objects that depend directly on the extension,
2863  * and alter each one's schema.
2864  */
2865  depRel = table_open(DependRelationId, AccessShareLock);
2866 
2867  ScanKeyInit(&key[0],
2868  Anum_pg_depend_refclassid,
2869  BTEqualStrategyNumber, F_OIDEQ,
2870  ObjectIdGetDatum(ExtensionRelationId));
2871  ScanKeyInit(&key[1],
2872  Anum_pg_depend_refobjid,
2873  BTEqualStrategyNumber, F_OIDEQ,
2874  ObjectIdGetDatum(extensionOid));
2875 
2876  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
2877  NULL, 2, key);
2878 
2879  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
2880  {
2881  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
2882  ObjectAddress dep;
2883  Oid dep_oldNspOid;
2884 
2885  /*
2886  * Ignore non-membership dependencies. (Currently, the only other
2887  * case we could see here is a normal dependency from another
2888  * extension.)
2889  */
2890  if (pg_depend->deptype != DEPENDENCY_EXTENSION)
2891  continue;
2892 
2893  dep.classId = pg_depend->classid;
2894  dep.objectId = pg_depend->objid;
2895  dep.objectSubId = pg_depend->objsubid;
2896 
2897  if (dep.objectSubId != 0) /* should not happen */
2898  elog(ERROR, "extension should not have a sub-object dependency");
2899 
2900  /* Relocate the object */
2901  dep_oldNspOid = AlterObjectNamespace_oid(dep.classId,
2902  dep.objectId,
2903  nspOid,
2904  objsMoved);
2905 
2906  /*
2907  * Remember previous namespace of first object that has one
2908  */
2909  if (oldNspOid == InvalidOid && dep_oldNspOid != InvalidOid)
2910  oldNspOid = dep_oldNspOid;
2911 
2912  /*
2913  * If not all the objects had the same old namespace (ignoring any
2914  * that are not in namespaces), complain.
2915  */
2916  if (dep_oldNspOid != InvalidOid && dep_oldNspOid != oldNspOid)
2917  ereport(ERROR,
2918  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2919  errmsg("extension \"%s\" does not support SET SCHEMA",
2920  NameStr(extForm->extname)),
2921  errdetail("%s is not in the extension's schema \"%s\"",
2922  getObjectDescription(&dep),
2923  get_namespace_name(oldNspOid))));
2924  }
2925 
2926  /* report old schema, if caller wants it */
2927  if (oldschema)
2928  *oldschema = oldNspOid;
2929 
2930  systable_endscan(depScan);
2931 
2933 
2934  /* Now adjust pg_extension.extnamespace */
2935  extForm->extnamespace = nspOid;
2936 
2937  CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
2938 
2939  table_close(extRel, RowExclusiveLock);
2940 
2941  /* update dependencies to point to the new schema */
2942  changeDependencyFor(ExtensionRelationId, extensionOid,
2943  NamespaceRelationId, oldNspOid, nspOid);
2944 
2945  InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
2946 
2947  ObjectAddressSet(extAddr, ExtensionRelationId, extensionOid);
2948 
2949  return extAddr;
2950 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c:659
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid GetUserId(void)
Definition: miscinit.c:448
Oid LookupCreationNamespace(const char *nspname)
Definition: namespace.c:2936
#define DependReferenceIndexId
Definition: indexing.h:151
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:610
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2418
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4658
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
char * getObjectDescription(const ObjectAddress *object)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3327
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
ItemPointerData t_self
Definition: htup.h:65
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3155
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5216
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:957
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:71
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
#define ExtensionOidIndexId
Definition: indexing.h:323
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:50
AclResult
Definition: acl.h:177
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:140
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:824
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:346
Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid, ObjectAddresses *objsMoved)
Definition: alter.c:589
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:615
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ CreateExtension()

ObjectAddress CreateExtension ( ParseState pstate,
CreateExtensionStmt stmt 
)

Definition at line 1667 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, CreateExtensionStmt::options, and parser_errposition().

Referenced by ProcessUtilitySlow().

1668 {
1669  DefElem *d_schema = NULL;
1670  DefElem *d_new_version = NULL;
1671  DefElem *d_cascade = NULL;
1672  char *schemaName = NULL;
1673  char *versionName = NULL;
1674  bool cascade = false;
1675  ListCell *lc;
1676 
1677  /* Check extension name validity before any filesystem access */
1679 
1680  /*
1681  * Check for duplicate extension name. The unique index on
1682  * pg_extension.extname would catch this anyway, and serves as a backstop
1683  * in case of race conditions; but this is a friendlier error message, and
1684  * besides we need a check to support IF NOT EXISTS.
1685  */
1686  if (get_extension_oid(stmt->extname, true) != InvalidOid)
1687  {
1688  if (stmt->if_not_exists)
1689  {
1690  ereport(NOTICE,
1692  errmsg("extension \"%s\" already exists, skipping",
1693  stmt->extname)));
1694  return InvalidObjectAddress;
1695  }
1696  else
1697  ereport(ERROR,
1699  errmsg("extension \"%s\" already exists",
1700  stmt->extname)));
1701  }
1702 
1703  /*
1704  * We use global variables to track the extension being created, so we can
1705  * create only one extension at the same time.
1706  */
1707  if (creating_extension)
1708  ereport(ERROR,
1709  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1710  errmsg("nested CREATE EXTENSION is not supported")));
1711 
1712  /* Deconstruct the statement option list */
1713  foreach(lc, stmt->options)
1714  {
1715  DefElem *defel = (DefElem *) lfirst(lc);
1716 
1717  if (strcmp(defel->defname, "schema") == 0)
1718  {
1719  if (d_schema)
1720  ereport(ERROR,
1721  (errcode(ERRCODE_SYNTAX_ERROR),
1722  errmsg("conflicting or redundant options"),
1723  parser_errposition(pstate, defel->location)));
1724  d_schema = defel;
1725  schemaName = defGetString(d_schema);
1726  }
1727  else if (strcmp(defel->defname, "new_version") == 0)
1728  {
1729  if (d_new_version)
1730  ereport(ERROR,
1731  (errcode(ERRCODE_SYNTAX_ERROR),
1732  errmsg("conflicting or redundant options"),
1733  parser_errposition(pstate, defel->location)));
1734  d_new_version = defel;
1735  versionName = defGetString(d_new_version);
1736  }
1737  else if (strcmp(defel->defname, "cascade") == 0)
1738  {
1739  if (d_cascade)
1740  ereport(ERROR,
1741  (errcode(ERRCODE_SYNTAX_ERROR),
1742  errmsg("conflicting or redundant options"),
1743  parser_errposition(pstate, defel->location)));
1744  d_cascade = defel;
1745  cascade = defGetBoolean(d_cascade);
1746  }
1747  else
1748  elog(ERROR, "unrecognized option: %s", defel->defname);
1749  }
1750 
1751  /* Call CreateExtensionInternal to do the real work. */
1752  return CreateExtensionInternal(stmt->extname,
1753  schemaName,
1754  versionName,
1755  cascade,
1756  NIL,
1757  true);
1758 }
#define NIL
Definition: pg_list.h:65
static void check_valid_extension_name(const char *extensionname)
Definition: extension.c:261
int errcode(int sqlerrcode)
Definition: elog.c:610
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:735
static ObjectAddress CreateExtensionInternal(char *extensionName, char *schemaName, const char *versionName, bool cascade, List *parents, bool is_create)
Definition: extension.c:1357
#define InvalidOid
Definition: postgres_ext.h:36
bool creating_extension
Definition: extension.c:71
#define ereport(elevel,...)
Definition: elog.h:144
#define NOTICE
Definition: elog.h:37
#define lfirst(lc)
Definition: pg_list.h:190
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:140
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
char * defname
Definition: parsenodes.h:732
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31

◆ ExecAlterExtensionContentsStmt()

ObjectAddress ExecAlterExtensionContentsStmt ( AlterExtensionContentsStmt stmt,
ObjectAddress objAddr 
)

Definition at line 3264 of file extension.c.

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

Referenced by ProcessUtilitySlow().

3266 {
3267  ObjectAddress extension;
3268  ObjectAddress object;
3269  Relation relation;
3270  Oid oldExtension;
3271 
3272  extension.classId = ExtensionRelationId;
3273  extension.objectId = get_extension_oid(stmt->extname, false);
3274  extension.objectSubId = 0;
3275 
3276  /* Permission check: must own extension */
3277  if (!pg_extension_ownercheck(extension.objectId, GetUserId()))
3279  stmt->extname);
3280 
3281  /*
3282  * Translate the parser representation that identifies the object into an
3283  * ObjectAddress. get_object_address() will throw an error if the object
3284  * does not exist, and will also acquire a lock on the object to guard
3285  * against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
3286  */
3287  object = get_object_address(stmt->objtype, stmt->object,
3288  &relation, ShareUpdateExclusiveLock, false);
3289 
3290  Assert(object.objectSubId == 0);
3291  if (objAddr)
3292  *objAddr = object;
3293 
3294  /* Permission check: must own target object, too */
3295  check_object_ownership(GetUserId(), stmt->objtype, object,
3296  stmt->object, relation);
3297 
3298  /*
3299  * Check existing extension membership.
3300  */
3301  oldExtension = getExtensionOfObject(object.classId, object.objectId);
3302 
3303  if (stmt->action > 0)
3304  {
3305  /*
3306  * ADD, so complain if object is already attached to some extension.
3307  */
3308  if (OidIsValid(oldExtension))
3309  ereport(ERROR,
3310  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3311  errmsg("%s is already a member of extension \"%s\"",
3312  getObjectDescription(&object),
3313  get_extension_name(oldExtension))));
3314 
3315  /*
3316  * Prevent a schema from being added to an extension if the schema
3317  * contains the extension. That would create a dependency loop.
3318  */
3319  if (object.classId == NamespaceRelationId &&
3320  object.objectId == get_extension_schema(extension.objectId))
3321  ereport(ERROR,
3322  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3323  errmsg("cannot add schema \"%s\" to extension \"%s\" "
3324  "because the schema contains the extension",
3325  get_namespace_name(object.objectId),
3326  stmt->extname)));
3327 
3328  /*
3329  * OK, add the dependency.
3330  */
3331  recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
3332 
3333  /*
3334  * Also record the initial ACL on the object, if any.
3335  *
3336  * Note that this will handle the object's ACLs, as well as any ACLs
3337  * on object subIds. (In other words, when the object is a table,
3338  * this will record the table's ACL and the ACLs for the columns on
3339  * the table, if any).
3340  */
3341  recordExtObjInitPriv(object.objectId, object.classId);
3342  }
3343  else
3344  {
3345  /*
3346  * DROP, so complain if it's not a member.
3347  */
3348  if (oldExtension != extension.objectId)
3349  ereport(ERROR,
3350  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3351  errmsg("%s is not a member of extension \"%s\"",
3352  getObjectDescription(&object),
3353  stmt->extname)));
3354 
3355  /*
3356  * OK, drop the dependency.
3357  */
3358  if (deleteDependencyRecordsForClass(object.classId, object.objectId,
3359  ExtensionRelationId,
3360  DEPENDENCY_EXTENSION) != 1)
3361  elog(ERROR, "unexpected number of extension dependency records");
3362 
3363  /*
3364  * If it's a relation, it might have an entry in the extension's
3365  * extconfig array, which we must remove.
3366  */
3367  if (object.classId == RelationRelationId)
3368  extension_config_remove(extension.objectId, object.objectId);
3369 
3370  /*
3371  * Remove all the initial ACLs, if any.
3372  *
3373  * Note that this will remove the object's ACLs, as well as any ACLs
3374  * on object subIds. (In other words, when the object is a table,
3375  * this will remove the table's ACL and the ACLs for the columns on
3376  * the table, if any).
3377  */
3378  removeExtObjInitPriv(object.objectId, object.classId);
3379  }
3380 
3381  InvokeObjectPostAlterHook(ExtensionRelationId, extension.objectId, 0);
3382 
3383  /*
3384  * If get_object_address() opened the relation for us, we close it to keep
3385  * the reference count correct - but we retain any locks acquired by
3386  * get_object_address() until commit time, to guard against concurrent
3387  * activity.
3388  */
3389  if (relation != NULL)
3390  relation_close(relation, NoLock);
3391 
3392  return extension;
3393 }
void recordExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:5529
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c:659
static Oid get_extension_schema(Oid ext_oid)
Definition: extension.c:224
Oid GetUserId(void)
Definition: miscinit.c:448
char * get_extension_name(Oid ext_oid)
Definition: extension.c:185
int errcode(int sqlerrcode)
Definition: elog.c:610
static void extension_config_remove(Oid extensionoid, Oid tableoid)
Definition: extension.c:2605
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
char * getObjectDescription(const ObjectAddress *object)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3327
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3155
#define NoLock
Definition: lockdefs.h:34
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5216
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:240
#define ereport(elevel,...)
Definition: elog.h:144
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:738
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:140
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
void removeExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:5827

◆ ExecAlterExtensionStmt()

ObjectAddress ExecAlterExtensionStmt ( ParseState pstate,
AlterExtensionStmt stmt 
)

Definition at line 2956 of file extension.c.

References AccessShareLock, aclcheck_error(), ACLCHECK_NOT_OWNER, ApplyExtensionUpdates(), DefElem::arg, BTEqualStrategyNumber, check_valid_version_name(), creating_extension, CStringGetDatum, DatumGetTextPP, ExtensionControlFile::default_version, DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, ExtensionNameIndexId, AlterExtensionStmt::extname, GETSTRUCT, GetUserId(), heap_getattr, HeapTupleIsValid, identify_update_path(), InvalidObjectAddress, sort-test::key, lfirst, DefElem::location, NOTICE, OBJECT_EXTENSION, ObjectAddressSet, AlterExtensionStmt::options, parser_errposition(), pg_extension_ownercheck(), read_extension_control_file(), RelationGetDescr, ScanKeyInit(), strVal, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and text_to_cstring().

Referenced by ProcessUtilitySlow().

2957 {
2958  DefElem *d_new_version = NULL;
2959  char *versionName;
2960  char *oldVersionName;
2961  ExtensionControlFile *control;
2962  Oid extensionOid;
2963  Relation extRel;
2964  ScanKeyData key[1];
2965  SysScanDesc extScan;
2966  HeapTuple extTup;
2967  List *updateVersions;
2968  Datum datum;
2969  bool isnull;
2970  ListCell *lc;
2971  ObjectAddress address;
2972 
2973  /*
2974  * We use global variables to track the extension being created, so we can
2975  * create/update only one extension at the same time.
2976  */
2977  if (creating_extension)
2978  ereport(ERROR,
2979  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2980  errmsg("nested ALTER EXTENSION is not supported")));
2981 
2982  /*
2983  * Look up the extension --- it must already exist in pg_extension
2984  */
2985  extRel = table_open(ExtensionRelationId, AccessShareLock);
2986 
2987  ScanKeyInit(&key[0],
2988  Anum_pg_extension_extname,
2989  BTEqualStrategyNumber, F_NAMEEQ,
2990  CStringGetDatum(stmt->extname));
2991 
2992  extScan = systable_beginscan(extRel, ExtensionNameIndexId, true,
2993  NULL, 1, key);
2994 
2995  extTup = systable_getnext(extScan);
2996 
2997  if (!HeapTupleIsValid(extTup))
2998  ereport(ERROR,
2999  (errcode(ERRCODE_UNDEFINED_OBJECT),
3000  errmsg("extension \"%s\" does not exist",
3001  stmt->extname)));
3002 
3003  extensionOid = ((Form_pg_extension) GETSTRUCT(extTup))->oid;
3004 
3005  /*
3006  * Determine the existing version we are updating from
3007  */
3008  datum = heap_getattr(extTup, Anum_pg_extension_extversion,
3009  RelationGetDescr(extRel), &isnull);
3010  if (isnull)
3011  elog(ERROR, "extversion is null");
3012  oldVersionName = text_to_cstring(DatumGetTextPP(datum));
3013 
3014  systable_endscan(extScan);
3015 
3016  table_close(extRel, AccessShareLock);
3017 
3018  /* Permission check: must own extension */
3019  if (!pg_extension_ownercheck(extensionOid, GetUserId()))
3021  stmt->extname);
3022 
3023  /*
3024  * Read the primary control file. Note we assume that it does not contain
3025  * any non-ASCII data, so there is no need to worry about encoding at this
3026  * point.
3027  */
3028  control = read_extension_control_file(stmt->extname);
3029 
3030  /*
3031  * Read the statement option list
3032  */
3033  foreach(lc, stmt->options)
3034  {
3035  DefElem *defel = (DefElem *) lfirst(lc);
3036 
3037  if (strcmp(defel->defname, "new_version") == 0)
3038  {
3039  if (d_new_version)
3040  ereport(ERROR,
3041  (errcode(ERRCODE_SYNTAX_ERROR),
3042  errmsg("conflicting or redundant options"),
3043  parser_errposition(pstate, defel->location)));
3044  d_new_version = defel;
3045  }
3046  else
3047  elog(ERROR, "unrecognized option: %s", defel->defname);
3048  }
3049 
3050  /*
3051  * Determine the version to update to
3052  */
3053  if (d_new_version && d_new_version->arg)
3054  versionName = strVal(d_new_version->arg);
3055  else if (control->default_version)
3056  versionName = control->default_version;
3057  else
3058  {
3059  ereport(ERROR,
3060  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3061  errmsg("version to install must be specified")));
3062  versionName = NULL; /* keep compiler quiet */
3063  }
3064  check_valid_version_name(versionName);
3065 
3066  /*
3067  * If we're already at that version, just say so
3068  */
3069  if (strcmp(oldVersionName, versionName) == 0)
3070  {
3071  ereport(NOTICE,
3072  (errmsg("version \"%s\" of extension \"%s\" is already installed",
3073  versionName, stmt->extname)));
3074  return InvalidObjectAddress;
3075  }
3076 
3077  /*
3078  * Identify the series of update script files we need to execute
3079  */
3080  updateVersions = identify_update_path(control,
3081  oldVersionName,
3082  versionName);
3083 
3084  /*
3085  * Update the pg_extension row and execute the update scripts, one at a
3086  * time
3087  */
3088  ApplyExtensionUpdates(extensionOid, control,
3089  oldVersionName, updateVersions,
3090  NULL, false, false);
3091 
3092  ObjectAddressSet(address, ExtensionRelationId, extensionOid);
3093 
3094  return address;
3095 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ExtensionNameIndexId
Definition: indexing.h:325
static ExtensionControlFile * read_extension_control_file(const char *extname)
Definition: extension.c:616
#define RelationGetDescr(relation)
Definition: rel.h:482
Oid GetUserId(void)
Definition: miscinit.c:448
#define DatumGetTextPP(X)
Definition: fmgr.h:291
static void ApplyExtensionUpdates(Oid extensionOid, ExtensionControlFile *pcontrol, const char *initialVersion, List *updateVersions, char *origSchemaName, bool cascade, bool is_create)
Definition: extension.c:3106
#define AccessShareLock
Definition: lockdefs.h:36
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:610
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:356
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3327
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ERROR
Definition: elog.h:43
static List * identify_update_path(ExtensionControlFile *control, const char *oldVersion, const char *newVersion)
Definition: extension.c:1166
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5216
int location
Definition: parsenodes.h:735
#define CStringGetDatum(X)
Definition: postgres.h:578
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:50
Node * arg
Definition: parsenodes.h:733
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
char * default_version
Definition: extension.c:81
uintptr_t Datum
Definition: postgres.h:367
static void check_valid_version_name(const char *versionname)
Definition: extension.c:308
bool creating_extension
Definition: extension.c:71
#define ereport(elevel,...)
Definition: elog.h:144
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:190
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
char * text_to_cstring(const text *t)
Definition: varlena.c:205
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
char * defname
Definition: parsenodes.h:732
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ extension_file_exists()

bool extension_file_exists ( const char *  extensionName)

Definition at line 2224 of file extension.c.

References AllocateDir(), dirent::d_name, FreeDir(), get_extension_control_directory(), is_extension_control_filename(), pstrdup(), and ReadDir().

Referenced by CreateFunction(), and ExecuteDoStmt().

2225 {
2226  bool result = false;
2227  char *location;
2228  DIR *dir;
2229  struct dirent *de;
2230 
2231  location = get_extension_control_directory();
2232  dir = AllocateDir(location);
2233 
2234  /*
2235  * If the control directory doesn't exist, we want to silently return
2236  * false. Any other error will be reported by ReadDir.
2237  */
2238  if (dir == NULL && errno == ENOENT)
2239  {
2240  /* do nothing */
2241  }
2242  else
2243  {
2244  while ((de = ReadDir(dir, location)) != NULL)
2245  {
2246  char *extname;
2247 
2249  continue;
2250 
2251  /* extract extension name from 'name.control' filename */
2252  extname = pstrdup(de->d_name);
2253  *strrchr(extname, '.') = '\0';
2254 
2255  /* ignore it if it's an auxiliary control file */
2256  if (strstr(extname, "--"))
2257  continue;
2258 
2259  /* done if it matches request */
2260  if (strcmp(extname, extensionName) == 0)
2261  {
2262  result = true;
2263  break;
2264  }
2265  }
2266 
2267  FreeDir(dir);
2268  }
2269 
2270  return result;
2271 }
char * pstrdup(const char *in)
Definition: mcxt.c:1186
Definition: dirent.h:9
Definition: dirent.c:25
static bool is_extension_control_filename(const char *filename)
Definition: extension.c:355
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2581
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2647
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2699
static char * get_extension_control_directory(void)
Definition: extension.c:371

◆ get_extension_name()

char* get_extension_name ( Oid  ext_oid)

Definition at line 185 of file extension.c.

References AccessShareLock, BTEqualStrategyNumber, ExtensionOidIndexId, GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, pstrdup(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

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

186 {
187  char *result;
188  Relation rel;
189  SysScanDesc scandesc;
190  HeapTuple tuple;
191  ScanKeyData entry[1];
192 
193  rel = table_open(ExtensionRelationId, AccessShareLock);
194 
195  ScanKeyInit(&entry[0],
196  Anum_pg_extension_oid,
197  BTEqualStrategyNumber, F_OIDEQ,
198  ObjectIdGetDatum(ext_oid));
199 
200  scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
201  NULL, 1, entry);
202 
203  tuple = systable_getnext(scandesc);
204 
205  /* We assume that there can be at most one matching tuple */
206  if (HeapTupleIsValid(tuple))
207  result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname));
208  else
209  result = NULL;
210 
211  systable_endscan(scandesc);
212 
214 
215  return result;
216 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
char * pstrdup(const char *in)
Definition: mcxt.c:1186
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ExtensionOidIndexId
Definition: indexing.h:323
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:50
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define NameStr(name)
Definition: c.h:615
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ get_extension_oid()

Oid get_extension_oid ( const char *  extname,
bool  missing_ok 
)

Definition at line 140 of file extension.c.

References AccessShareLock, BTEqualStrategyNumber, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, ExtensionNameIndexId, GETSTRUCT, HeapTupleIsValid, InvalidOid, OidIsValid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

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

141 {
142  Oid result;
143  Relation rel;
144  SysScanDesc scandesc;
145  HeapTuple tuple;
146  ScanKeyData entry[1];
147 
148  rel = table_open(ExtensionRelationId, AccessShareLock);
149 
150  ScanKeyInit(&entry[0],
151  Anum_pg_extension_extname,
152  BTEqualStrategyNumber, F_NAMEEQ,
153  CStringGetDatum(extname));
154 
155  scandesc = systable_beginscan(rel, ExtensionNameIndexId, true,
156  NULL, 1, entry);
157 
158  tuple = systable_getnext(scandesc);
159 
160  /* We assume that there can be at most one matching tuple */
161  if (HeapTupleIsValid(tuple))
162  result = ((Form_pg_extension) GETSTRUCT(tuple))->oid;
163  else
164  result = InvalidOid;
165 
166  systable_endscan(scandesc);
167 
169 
170  if (!OidIsValid(result) && !missing_ok)
171  ereport(ERROR,
172  (errcode(ERRCODE_UNDEFINED_OBJECT),
173  errmsg("extension \"%s\" does not exist",
174  extname)));
175 
176  return result;
177 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ExtensionNameIndexId
Definition: indexing.h:325
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ERROR
Definition: elog.h:43
#define CStringGetDatum(X)
Definition: postgres.h:578
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:50
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:824
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ InsertExtensionTuple()

ObjectAddress InsertExtensionTuple ( const char *  extName,
Oid  extOwner,
Oid  schemaOid,
bool  relocatable,
const char *  extVersion,
Datum  extConfig,
Datum  extCondition,
List requiredExtensions 
)

Definition at line 1774 of file extension.c.

References BoolGetDatum, CatalogTupleInsert(), ObjectAddress::classId, CStringGetDatum, CStringGetTextDatum, DEPENDENCY_NORMAL, DirectFunctionCall1, ExtensionOidIndexId, GetNewOidWithIndex(), heap_form_tuple(), heap_freetuple(), InvokeObjectPostCreateHook, lfirst_oid, namein(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, PointerGetDatum, RelationData::rd_att, recordDependencyOn(), recordDependencyOnOwner(), RowExclusiveLock, table_close(), table_open(), and values.

Referenced by binary_upgrade_create_empty_extension(), and CreateExtensionInternal().

1778 {
1779  Oid extensionOid;
1780  Relation rel;
1781  Datum values[Natts_pg_extension];
1782  bool nulls[Natts_pg_extension];
1783  HeapTuple tuple;
1784  ObjectAddress myself;
1785  ObjectAddress nsp;
1786  ListCell *lc;
1787 
1788  /*
1789  * Build and insert the pg_extension tuple
1790  */
1791  rel = table_open(ExtensionRelationId, RowExclusiveLock);
1792 
1793  memset(values, 0, sizeof(values));
1794  memset(nulls, 0, sizeof(nulls));
1795 
1796  extensionOid = GetNewOidWithIndex(rel, ExtensionOidIndexId,
1797  Anum_pg_extension_oid);
1798  values[Anum_pg_extension_oid - 1] = ObjectIdGetDatum(extensionOid);
1799  values[Anum_pg_extension_extname - 1] =
1801  values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
1802  values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
1803  values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
1804  values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
1805 
1806  if (extConfig == PointerGetDatum(NULL))
1807  nulls[Anum_pg_extension_extconfig - 1] = true;
1808  else
1809  values[Anum_pg_extension_extconfig - 1] = extConfig;
1810 
1811  if (extCondition == PointerGetDatum(NULL))
1812  nulls[Anum_pg_extension_extcondition - 1] = true;
1813  else
1814  values[Anum_pg_extension_extcondition - 1] = extCondition;
1815 
1816  tuple = heap_form_tuple(rel->rd_att, values, nulls);
1817 
1818  CatalogTupleInsert(rel, tuple);
1819 
1820  heap_freetuple(tuple);
1822 
1823  /*
1824  * Record dependencies on owner, schema, and prerequisite extensions
1825  */
1826  recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
1827 
1828  myself.classId = ExtensionRelationId;
1829  myself.objectId = extensionOid;
1830  myself.objectSubId = 0;
1831 
1832  nsp.classId = NamespaceRelationId;
1833  nsp.objectId = schemaOid;
1834  nsp.objectSubId = 0;
1835 
1836  recordDependencyOn(&myself, &nsp, DEPENDENCY_NORMAL);
1837 
1838  foreach(lc, requiredExtensions)
1839  {
1840  Oid reqext = lfirst_oid(lc);
1841  ObjectAddress otherext;
1842 
1843  otherext.classId = ExtensionRelationId;
1844  otherext.objectId = reqext;
1845  otherext.objectSubId = 0;
1846 
1847  recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
1848  }
1849  /* Post creation hook for new extension */
1850  InvokeObjectPostCreateHook(ExtensionRelationId, extensionOid, 0);
1851 
1852  return myself;
1853 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:317
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define PointerGetDatum(X)
Definition: postgres.h:556
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:624
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:164
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ExtensionOidIndexId
Definition: indexing.h:323
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
#define BoolGetDatum(X)
Definition: postgres.h:402
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define CStringGetTextDatum(s)
Definition: builtins.h:87
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ RemoveExtensionById()

void RemoveExtensionById ( Oid  extId)

Definition at line 1862 of file extension.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), CurrentExtensionObject, ereport, errcode(), errmsg(), ERROR, ExtensionOidIndexId, get_extension_name(), HeapTupleIsValid, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

1863 {
1864  Relation rel;
1865  SysScanDesc scandesc;
1866  HeapTuple tuple;
1867  ScanKeyData entry[1];
1868 
1869  /*
1870  * Disallow deletion of any extension that's currently open for insertion;
1871  * else subsequent executions of recordDependencyOnCurrentExtension()
1872  * could create dangling pg_depend records that refer to a no-longer-valid
1873  * pg_extension OID. This is needed not so much because we think people
1874  * might write "DROP EXTENSION foo" in foo's own script files, as because
1875  * errors in dependency management in extension script files could give
1876  * rise to cases where an extension is dropped as a result of recursing
1877  * from some contained object. Because of that, we must test for the case
1878  * here, not at some higher level of the DROP EXTENSION command.
1879  */
1880  if (extId == CurrentExtensionObject)
1881  ereport(ERROR,
1882  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1883  errmsg("cannot drop extension \"%s\" because it is being modified",
1884  get_extension_name(extId))));
1885 
1886  rel = table_open(ExtensionRelationId, RowExclusiveLock);
1887 
1888  ScanKeyInit(&entry[0],
1889  Anum_pg_extension_oid,
1890  BTEqualStrategyNumber, F_OIDEQ,
1891  ObjectIdGetDatum(extId));
1892  scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
1893  NULL, 1, entry);
1894 
1895  tuple = systable_getnext(scandesc);
1896 
1897  /* We assume that there can be at most one matching tuple */
1898  if (HeapTupleIsValid(tuple))
1899  CatalogTupleDelete(rel, &tuple->t_self);
1900 
1901  systable_endscan(scandesc);
1902 
1904 }
Oid CurrentExtensionObject
Definition: extension.c:72
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
char * get_extension_name(Oid ext_oid)
Definition: extension.c:185
int errcode(int sqlerrcode)
Definition: elog.c:610
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ExtensionOidIndexId
Definition: indexing.h:323
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:824
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

Variable Documentation

◆ creating_extension

◆ CurrentExtensionObject