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 2779 of file extension.c.

References AccessShareLock, ACL_CREATE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, AlterObjectNamespace_oid(), BTEqualStrategyNumber, CatalogTupleUpdate(), changeDependencyFor(), ObjectAddress::classId, DEPENDENCY_EXTENSION, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, 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().

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

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

Referenced by ProcessUtilitySlow().

1682 {
1683  DefElem *d_schema = NULL;
1684  DefElem *d_new_version = NULL;
1685  DefElem *d_cascade = NULL;
1686  char *schemaName = NULL;
1687  char *versionName = NULL;
1688  bool cascade = false;
1689  ListCell *lc;
1690 
1691  /* Check extension name validity before any filesystem access */
1693 
1694  /*
1695  * Check for duplicate extension name. The unique index on
1696  * pg_extension.extname would catch this anyway, and serves as a backstop
1697  * in case of race conditions; but this is a friendlier error message, and
1698  * besides we need a check to support IF NOT EXISTS.
1699  */
1700  if (get_extension_oid(stmt->extname, true) != InvalidOid)
1701  {
1702  if (stmt->if_not_exists)
1703  {
1704  ereport(NOTICE,
1706  errmsg("extension \"%s\" already exists, skipping",
1707  stmt->extname)));
1708  return InvalidObjectAddress;
1709  }
1710  else
1711  ereport(ERROR,
1713  errmsg("extension \"%s\" already exists",
1714  stmt->extname)));
1715  }
1716 
1717  /*
1718  * We use global variables to track the extension being created, so we can
1719  * create only one extension at the same time.
1720  */
1721  if (creating_extension)
1722  ereport(ERROR,
1723  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1724  errmsg("nested CREATE EXTENSION is not supported")));
1725 
1726  /* Deconstruct the statement option list */
1727  foreach(lc, stmt->options)
1728  {
1729  DefElem *defel = (DefElem *) lfirst(lc);
1730 
1731  if (strcmp(defel->defname, "schema") == 0)
1732  {
1733  if (d_schema)
1734  errorConflictingDefElem(defel, pstate);
1735  d_schema = defel;
1736  schemaName = defGetString(d_schema);
1737  }
1738  else if (strcmp(defel->defname, "new_version") == 0)
1739  {
1740  if (d_new_version)
1741  errorConflictingDefElem(defel, pstate);
1742  d_new_version = defel;
1743  versionName = defGetString(d_new_version);
1744  }
1745  else if (strcmp(defel->defname, "cascade") == 0)
1746  {
1747  if (d_cascade)
1748  errorConflictingDefElem(defel, pstate);
1749  d_cascade = defel;
1750  cascade = defGetBoolean(d_cascade);
1751  }
1752  else
1753  elog(ERROR, "unrecognized option: %s", defel->defname);
1754  }
1755 
1756  /* Call CreateExtensionInternal to do the real work. */
1757  return CreateExtensionInternal(stmt->extname,
1758  schemaName,
1759  versionName,
1760  cascade,
1761  NIL,
1762  true);
1763 }
#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:698
bool defGetBoolean(DefElem *def)
Definition: define.c:111
#define ERROR
Definition: elog.h:46
char * defGetString(DefElem *def)
Definition: define.c:49
static ObjectAddress CreateExtensionInternal(char *extensionName, char *schemaName, const char *versionName, bool cascade, List *parents, bool is_create)
Definition: extension.c:1371
#define InvalidOid
Definition: postgres_ext.h:36
bool creating_extension
Definition: extension.c:71
#define ereport(elevel,...)
Definition: elog.h:157
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:355
#define NOTICE
Definition: elog.h:37
#define lfirst(lc)
Definition: pg_list.h:169
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:909
#define elog(elevel,...)
Definition: elog.h:232
char * defname
Definition: parsenodes.h:746
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

◆ ExecAlterExtensionContentsStmt()

ObjectAddress ExecAlterExtensionContentsStmt ( AlterExtensionContentsStmt stmt,
ObjectAddress objAddr 
)

Definition at line 3266 of file extension.c.

References AccessShareLock, aclcheck_error(), ACLCHECK_NOT_OWNER, AlterExtensionContentsStmt::action, Assert, check_object_ownership(), deleteDependencyRecordsForClass(), DEPENDENCY_EXTENSION, elog, ereport, errcode(), errmsg(), ERROR, extension_config_remove(), AlterExtensionContentsStmt::extname, get_extension_name(), get_extension_schema(), get_namespace_name(), get_object_address(), getExtensionOfObject(), getObjectDescription(), GetUserId(), InvokeObjectPostAlterHook, makeString(), NoLock, AlterExtensionContentsStmt::object, OBJECT_DATABASE, OBJECT_EXTENSION, OBJECT_INDEX, OBJECT_PUBLICATION, OBJECT_ROLE, OBJECT_STATISTIC_EXT, OBJECT_SUBSCRIPTION, OBJECT_TABLESPACE, ObjectAddress::objectId, AlterExtensionContentsStmt::objtype, OidIsValid, pg_extension_ownercheck(), recordDependencyOn(), recordExtObjInitPriv(), relation_close(), removeExtObjInitPriv(), and ShareUpdateExclusiveLock.

Referenced by ProcessUtilitySlow().

3268 {
3269  ObjectAddress extension;
3270  ObjectAddress object;
3271  Relation relation;
3272  Oid oldExtension;
3273 
3274  switch (stmt->objtype)
3275  {
3276  case OBJECT_DATABASE:
3277  case OBJECT_EXTENSION:
3278  case OBJECT_INDEX:
3279  case OBJECT_PUBLICATION:
3280  case OBJECT_ROLE:
3281  case OBJECT_STATISTIC_EXT:
3282  case OBJECT_SUBSCRIPTION:
3283  case OBJECT_TABLESPACE:
3284  ereport(ERROR,
3285  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3286  errmsg("cannot add an object of this type to an extension")));
3287  break;
3288  default:
3289  /* OK */
3290  break;
3291  }
3292 
3293  /*
3294  * Find the extension and acquire a lock on it, to ensure it doesn't get
3295  * dropped concurrently. A sharable lock seems sufficient: there's no
3296  * reason not to allow other sorts of manipulations, such as add/drop of
3297  * other objects, to occur concurrently. Concurrently adding/dropping the
3298  * *same* object would be bad, but we prevent that by using a non-sharable
3299  * lock on the individual object, below.
3300  */
3302  (Node *) makeString(stmt->extname),
3303  &relation, AccessShareLock, false);
3304 
3305  /* Permission check: must own extension */
3306  if (!pg_extension_ownercheck(extension.objectId, GetUserId()))
3308  stmt->extname);
3309 
3310  /*
3311  * Translate the parser representation that identifies the object into an
3312  * ObjectAddress. get_object_address() will throw an error if the object
3313  * does not exist, and will also acquire a lock on the object to guard
3314  * against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
3315  */
3316  object = get_object_address(stmt->objtype, stmt->object,
3317  &relation, ShareUpdateExclusiveLock, false);
3318 
3319  Assert(object.objectSubId == 0);
3320  if (objAddr)
3321  *objAddr = object;
3322 
3323  /* Permission check: must own target object, too */
3324  check_object_ownership(GetUserId(), stmt->objtype, object,
3325  stmt->object, relation);
3326 
3327  /*
3328  * Check existing extension membership.
3329  */
3330  oldExtension = getExtensionOfObject(object.classId, object.objectId);
3331 
3332  if (stmt->action > 0)
3333  {
3334  /*
3335  * ADD, so complain if object is already attached to some extension.
3336  */
3337  if (OidIsValid(oldExtension))
3338  ereport(ERROR,
3339  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3340  errmsg("%s is already a member of extension \"%s\"",
3341  getObjectDescription(&object, false),
3342  get_extension_name(oldExtension))));
3343 
3344  /*
3345  * Prevent a schema from being added to an extension if the schema
3346  * contains the extension. That would create a dependency loop.
3347  */
3348  if (object.classId == NamespaceRelationId &&
3349  object.objectId == get_extension_schema(extension.objectId))
3350  ereport(ERROR,
3351  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3352  errmsg("cannot add schema \"%s\" to extension \"%s\" "
3353  "because the schema contains the extension",
3354  get_namespace_name(object.objectId),
3355  stmt->extname)));
3356 
3357  /*
3358  * OK, add the dependency.
3359  */
3360  recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
3361 
3362  /*
3363  * Also record the initial ACL on the object, if any.
3364  *
3365  * Note that this will handle the object's ACLs, as well as any ACLs
3366  * on object subIds. (In other words, when the object is a table,
3367  * this will record the table's ACL and the ACLs for the columns on
3368  * the table, if any).
3369  */
3370  recordExtObjInitPriv(object.objectId, object.classId);
3371  }
3372  else
3373  {
3374  /*
3375  * DROP, so complain if it's not a member.
3376  */
3377  if (oldExtension != extension.objectId)
3378  ereport(ERROR,
3379  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3380  errmsg("%s is not a member of extension \"%s\"",
3381  getObjectDescription(&object, false),
3382  stmt->extname)));
3383 
3384  /*
3385  * OK, drop the dependency.
3386  */
3387  if (deleteDependencyRecordsForClass(object.classId, object.objectId,
3388  ExtensionRelationId,
3389  DEPENDENCY_EXTENSION) != 1)
3390  elog(ERROR, "unexpected number of extension dependency records");
3391 
3392  /*
3393  * If it's a relation, it might have an entry in the extension's
3394  * extconfig array, which we must remove.
3395  */
3396  if (object.classId == RelationRelationId)
3397  extension_config_remove(extension.objectId, object.objectId);
3398 
3399  /*
3400  * Remove all the initial ACLs, if any.
3401  *
3402  * Note that this will remove the object's ACLs, as well as any ACLs
3403  * on object subIds. (In other words, when the object is a table,
3404  * this will remove the table's ACL and the ACLs for the columns on
3405  * the table, if any).
3406  */
3407  removeExtObjInitPriv(object.objectId, object.classId);
3408  }
3409 
3410  InvokeObjectPostAlterHook(ExtensionRelationId, extension.objectId, 0);
3411 
3412  /*
3413  * If get_object_address() opened the relation for us, we close it to keep
3414  * the reference count correct - but we retain any locks acquired by
3415  * get_object_address() until commit time, to guard against concurrent
3416  * activity.
3417  */
3418  if (relation != NULL)
3419  relation_close(relation, NoLock);
3420 
3421  return extension;
3422 }
Value * makeString(char *str)
Definition: value.c:53
void recordExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:5627
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c:667
static Oid get_extension_schema(Oid ext_oid)
Definition: extension.c:224
Oid GetUserId(void)
Definition: miscinit.c:478
char * get_extension_name(Oid ext_oid)
Definition: extension.c:185
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:539
int errcode(int sqlerrcode)
Definition: elog.c:698
static void extension_config_remove(Oid extensionoid, Oid tableoid)
Definition: extension.c:2610
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:710
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define ERROR
Definition: elog.h:46
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
#define NoLock
Definition: lockdefs.h:34
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5314
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:286
#define ereport(elevel,...)
Definition: elog.h:157
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:804
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)
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
void removeExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:5925

◆ ExecAlterExtensionStmt()

ObjectAddress ExecAlterExtensionStmt ( ParseState pstate,
AlterExtensionStmt stmt 
)

Definition at line 2961 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, errorConflictingDefElem(), AlterExtensionStmt::extname, GETSTRUCT, GetUserId(), heap_getattr, HeapTupleIsValid, identify_update_path(), InvalidObjectAddress, sort-test::key, lfirst, NOTICE, OBJECT_EXTENSION, ObjectAddressSet, AlterExtensionStmt::options, 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().

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

2230 {
2231  bool result = false;
2232  char *location;
2233  DIR *dir;
2234  struct dirent *de;
2235 
2236  location = get_extension_control_directory();
2237  dir = AllocateDir(location);
2238 
2239  /*
2240  * If the control directory doesn't exist, we want to silently return
2241  * false. Any other error will be reported by ReadDir.
2242  */
2243  if (dir == NULL && errno == ENOENT)
2244  {
2245  /* do nothing */
2246  }
2247  else
2248  {
2249  while ((de = ReadDir(dir, location)) != NULL)
2250  {
2251  char *extname;
2252 
2254  continue;
2255 
2256  /* extract extension name from 'name.control' filename */
2257  extname = pstrdup(de->d_name);
2258  *strrchr(extname, '.') = '\0';
2259 
2260  /* ignore it if it's an auxiliary control file */
2261  if (strstr(extname, "--"))
2262  continue;
2263 
2264  /* done if it matches request */
2265  if (strcmp(extname, extensionName) == 0)
2266  {
2267  result = true;
2268  break;
2269  }
2270  }
2271 
2272  FreeDir(dir);
2273  }
2274 
2275  return result;
2276 }
char * pstrdup(const char *in)
Definition: mcxt.c:1299
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:2678
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2744
char d_name[MAX_PATH]
Definition: dirent.h:15
int FreeDir(DIR *dir)
Definition: fd.c:2796
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, 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:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
char * pstrdup(const char *in)
Definition: mcxt.c:1299
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:52
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define NameStr(name)
Definition: c.h:681
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, 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(), 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:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ERROR
Definition: elog.h:46
#define CStringGetDatum(X)
Definition: postgres.h:622
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:52
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:909
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 1779 of file extension.c.

References add_exact_object_address(), BoolGetDatum, CatalogTupleInsert(), CStringGetDatum, CStringGetTextDatum, DEPENDENCY_NORMAL, DirectFunctionCall1, free_object_addresses(), GetNewOidWithIndex(), heap_form_tuple(), heap_freetuple(), InvokeObjectPostCreateHook, lfirst_oid, namein(), new_object_addresses(), ObjectAddressSet, ObjectIdGetDatum, PointerGetDatum, RelationData::rd_att, record_object_address_dependencies(), recordDependencyOnOwner(), RowExclusiveLock, table_close(), table_open(), and values.

Referenced by binary_upgrade_create_empty_extension(), and CreateExtensionInternal().

1783 {
1784  Oid extensionOid;
1785  Relation rel;
1786  Datum values[Natts_pg_extension];
1787  bool nulls[Natts_pg_extension];
1788  HeapTuple tuple;
1789  ObjectAddress myself;
1790  ObjectAddress nsp;
1791  ObjectAddresses *refobjs;
1792  ListCell *lc;
1793 
1794  /*
1795  * Build and insert the pg_extension tuple
1796  */
1797  rel = table_open(ExtensionRelationId, RowExclusiveLock);
1798 
1799  memset(values, 0, sizeof(values));
1800  memset(nulls, 0, sizeof(nulls));
1801 
1802  extensionOid = GetNewOidWithIndex(rel, ExtensionOidIndexId,
1803  Anum_pg_extension_oid);
1804  values[Anum_pg_extension_oid - 1] = ObjectIdGetDatum(extensionOid);
1805  values[Anum_pg_extension_extname - 1] =
1807  values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
1808  values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
1809  values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
1810  values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
1811 
1812  if (extConfig == PointerGetDatum(NULL))
1813  nulls[Anum_pg_extension_extconfig - 1] = true;
1814  else
1815  values[Anum_pg_extension_extconfig - 1] = extConfig;
1816 
1817  if (extCondition == PointerGetDatum(NULL))
1818  nulls[Anum_pg_extension_extcondition - 1] = true;
1819  else
1820  values[Anum_pg_extension_extcondition - 1] = extCondition;
1821 
1822  tuple = heap_form_tuple(rel->rd_att, values, nulls);
1823 
1824  CatalogTupleInsert(rel, tuple);
1825 
1826  heap_freetuple(tuple);
1828 
1829  /*
1830  * Record dependencies on owner, schema, and prerequisite extensions
1831  */
1832  recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
1833 
1834  refobjs = new_object_addresses();
1835 
1836  ObjectAddressSet(myself, ExtensionRelationId, extensionOid);
1837 
1838  ObjectAddressSet(nsp, NamespaceRelationId, schemaOid);
1839  add_exact_object_address(&nsp, refobjs);
1840 
1841  foreach(lc, requiredExtensions)
1842  {
1843  Oid reqext = lfirst_oid(lc);
1844  ObjectAddress otherext;
1845 
1846  ObjectAddressSet(otherext, ExtensionRelationId, reqext);
1847  add_exact_object_address(&otherext, refobjs);
1848  }
1849 
1850  /* Record all of them (this includes duplicate elimination) */
1852  free_object_addresses(refobjs);
1853 
1854  /* Post creation hook for new extension */
1855  InvokeObjectPostCreateHook(ExtensionRelationId, extensionOid, 0);
1856 
1857  return myself;
1858 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define PointerGetDatum(X)
Definition: postgres.h:600
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2691
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2482
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:163
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2427
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2722
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:110
#define BoolGetDatum(X)
Definition: postgres.h:446
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define CStringGetTextDatum(s)
Definition: builtins.h:82
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ RemoveExtensionById()

void RemoveExtensionById ( Oid  extId)

Definition at line 1867 of file extension.c.

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

Referenced by doDeletion().

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