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

2705 {
2706  Oid extensionOid;
2707  Oid nspOid;
2708  Oid oldNspOid = InvalidOid;
2709  AclResult aclresult;
2710  Relation extRel;
2711  ScanKeyData key[2];
2712  SysScanDesc extScan;
2713  HeapTuple extTup;
2714  Form_pg_extension extForm;
2715  Relation depRel;
2716  SysScanDesc depScan;
2717  HeapTuple depTup;
2718  ObjectAddresses *objsMoved;
2719  ObjectAddress extAddr;
2720 
2721  extensionOid = get_extension_oid(extensionName, false);
2722 
2723  nspOid = LookupCreationNamespace(newschema);
2724 
2725  /*
2726  * Permission check: must own extension. Note that we don't bother to
2727  * check ownership of the individual member objects ...
2728  */
2729  if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2731  extensionName);
2732 
2733  /* Permission check: must have creation rights in target namespace */
2734  aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
2735  if (aclresult != ACLCHECK_OK)
2736  aclcheck_error(aclresult, OBJECT_SCHEMA, newschema);
2737 
2738  /*
2739  * If the schema is currently a member of the extension, disallow moving
2740  * the extension into the schema. That would create a dependency loop.
2741  */
2742  if (getExtensionOfObject(NamespaceRelationId, nspOid) == extensionOid)
2743  ereport(ERROR,
2744  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2745  errmsg("cannot move extension \"%s\" into schema \"%s\" "
2746  "because the extension contains the schema",
2747  extensionName, newschema)));
2748 
2749  /* Locate the pg_extension tuple */
2750  extRel = table_open(ExtensionRelationId, RowExclusiveLock);
2751 
2752  ScanKeyInit(&key[0],
2753  Anum_pg_extension_oid,
2754  BTEqualStrategyNumber, F_OIDEQ,
2755  ObjectIdGetDatum(extensionOid));
2756 
2757  extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2758  NULL, 1, key);
2759 
2760  extTup = systable_getnext(extScan);
2761 
2762  if (!HeapTupleIsValid(extTup)) /* should not happen */
2763  elog(ERROR, "could not find tuple for extension %u",
2764  extensionOid);
2765 
2766  /* Copy tuple so we can modify it below */
2767  extTup = heap_copytuple(extTup);
2768  extForm = (Form_pg_extension) GETSTRUCT(extTup);
2769 
2770  systable_endscan(extScan);
2771 
2772  /*
2773  * If the extension is already in the target schema, just silently do
2774  * nothing.
2775  */
2776  if (extForm->extnamespace == nspOid)
2777  {
2778  table_close(extRel, RowExclusiveLock);
2779  return InvalidObjectAddress;
2780  }
2781 
2782  /* Check extension is supposed to be relocatable */
2783  if (!extForm->extrelocatable)
2784  ereport(ERROR,
2785  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2786  errmsg("extension \"%s\" does not support SET SCHEMA",
2787  NameStr(extForm->extname))));
2788 
2789  objsMoved = new_object_addresses();
2790 
2791  /*
2792  * Scan pg_depend to find objects that depend directly on the extension,
2793  * and alter each one's schema.
2794  */
2795  depRel = table_open(DependRelationId, AccessShareLock);
2796 
2797  ScanKeyInit(&key[0],
2798  Anum_pg_depend_refclassid,
2799  BTEqualStrategyNumber, F_OIDEQ,
2800  ObjectIdGetDatum(ExtensionRelationId));
2801  ScanKeyInit(&key[1],
2802  Anum_pg_depend_refobjid,
2803  BTEqualStrategyNumber, F_OIDEQ,
2804  ObjectIdGetDatum(extensionOid));
2805 
2806  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
2807  NULL, 2, key);
2808 
2809  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
2810  {
2811  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
2812  ObjectAddress dep;
2813  Oid dep_oldNspOid;
2814 
2815  /*
2816  * Ignore non-membership dependencies. (Currently, the only other
2817  * case we could see here is a normal dependency from another
2818  * extension.)
2819  */
2820  if (pg_depend->deptype != DEPENDENCY_EXTENSION)
2821  continue;
2822 
2823  dep.classId = pg_depend->classid;
2824  dep.objectId = pg_depend->objid;
2825  dep.objectSubId = pg_depend->objsubid;
2826 
2827  if (dep.objectSubId != 0) /* should not happen */
2828  elog(ERROR, "extension should not have a sub-object dependency");
2829 
2830  /* Relocate the object */
2831  dep_oldNspOid = AlterObjectNamespace_oid(dep.classId,
2832  dep.objectId,
2833  nspOid,
2834  objsMoved);
2835 
2836  /*
2837  * Remember previous namespace of first object that has one
2838  */
2839  if (oldNspOid == InvalidOid && dep_oldNspOid != InvalidOid)
2840  oldNspOid = dep_oldNspOid;
2841 
2842  /*
2843  * If not all the objects had the same old namespace (ignoring any
2844  * that are not in namespaces), complain.
2845  */
2846  if (dep_oldNspOid != InvalidOid && dep_oldNspOid != oldNspOid)
2847  ereport(ERROR,
2848  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2849  errmsg("extension \"%s\" does not support SET SCHEMA",
2850  NameStr(extForm->extname)),
2851  errdetail("%s is not in the extension's schema \"%s\"",
2852  getObjectDescription(&dep),
2853  get_namespace_name(oldNspOid))));
2854  }
2855 
2856  /* report old schema, if caller wants it */
2857  if (oldschema)
2858  *oldschema = oldNspOid;
2859 
2860  systable_endscan(depScan);
2861 
2863 
2864  /* Now adjust pg_extension.extnamespace */
2865  extForm->extnamespace = nspOid;
2866 
2867  CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
2868 
2869  table_close(extRel, RowExclusiveLock);
2870 
2871  /* update dependencies to point to the new schema */
2872  changeDependencyFor(ExtensionRelationId, extensionOid,
2873  NamespaceRelationId, oldNspOid, nspOid);
2874 
2875  InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
2876 
2877  ObjectAddressSet(extAddr, ExtensionRelationId, extensionOid);
2878 
2879  return extAddr;
2880 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c:610
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid GetUserId(void)
Definition: miscinit.c:380
Oid LookupCreationNamespace(const char *nspname)
Definition: namespace.c:2928
#define DependReferenceIndexId
Definition: indexing.h:151
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:608
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2402
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4692
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
char * getObjectDescription(const ObjectAddress *object)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#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:3094
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5250
#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 ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define ExtensionOidIndexId
Definition: indexing.h:326
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:50
AclResult
Definition: acl.h:177
#define InvalidOid
Definition: postgres_ext.h:36
#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:138
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:822
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:297
Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid, ObjectAddresses *objsMoved)
Definition: alter.c:563
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:610
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 1643 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().

1644 {
1645  DefElem *d_schema = NULL;
1646  DefElem *d_new_version = NULL;
1647  DefElem *d_old_version = NULL;
1648  DefElem *d_cascade = NULL;
1649  char *schemaName = NULL;
1650  char *versionName = NULL;
1651  char *oldVersionName = NULL;
1652  bool cascade = false;
1653  ListCell *lc;
1654 
1655  /* Check extension name validity before any filesystem access */
1657 
1658  /*
1659  * Check for duplicate extension name. The unique index on
1660  * pg_extension.extname would catch this anyway, and serves as a backstop
1661  * in case of race conditions; but this is a friendlier error message, and
1662  * besides we need a check to support IF NOT EXISTS.
1663  */
1664  if (get_extension_oid(stmt->extname, true) != InvalidOid)
1665  {
1666  if (stmt->if_not_exists)
1667  {
1668  ereport(NOTICE,
1670  errmsg("extension \"%s\" already exists, skipping",
1671  stmt->extname)));
1672  return InvalidObjectAddress;
1673  }
1674  else
1675  ereport(ERROR,
1677  errmsg("extension \"%s\" already exists",
1678  stmt->extname)));
1679  }
1680 
1681  /*
1682  * We use global variables to track the extension being created, so we can
1683  * create only one extension at the same time.
1684  */
1685  if (creating_extension)
1686  ereport(ERROR,
1687  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1688  errmsg("nested CREATE EXTENSION is not supported")));
1689 
1690  /* Deconstruct the statement option list */
1691  foreach(lc, stmt->options)
1692  {
1693  DefElem *defel = (DefElem *) lfirst(lc);
1694 
1695  if (strcmp(defel->defname, "schema") == 0)
1696  {
1697  if (d_schema)
1698  ereport(ERROR,
1699  (errcode(ERRCODE_SYNTAX_ERROR),
1700  errmsg("conflicting or redundant options"),
1701  parser_errposition(pstate, defel->location)));
1702  d_schema = defel;
1703  schemaName = defGetString(d_schema);
1704  }
1705  else if (strcmp(defel->defname, "new_version") == 0)
1706  {
1707  if (d_new_version)
1708  ereport(ERROR,
1709  (errcode(ERRCODE_SYNTAX_ERROR),
1710  errmsg("conflicting or redundant options"),
1711  parser_errposition(pstate, defel->location)));
1712  d_new_version = defel;
1713  versionName = defGetString(d_new_version);
1714  }
1715  else if (strcmp(defel->defname, "old_version") == 0)
1716  {
1717  if (d_old_version)
1718  ereport(ERROR,
1719  (errcode(ERRCODE_SYNTAX_ERROR),
1720  errmsg("conflicting or redundant options"),
1721  parser_errposition(pstate, defel->location)));
1722  d_old_version = defel;
1723  oldVersionName = defGetString(d_old_version);
1724  }
1725  else if (strcmp(defel->defname, "cascade") == 0)
1726  {
1727  if (d_cascade)
1728  ereport(ERROR,
1729  (errcode(ERRCODE_SYNTAX_ERROR),
1730  errmsg("conflicting or redundant options"),
1731  parser_errposition(pstate, defel->location)));
1732  d_cascade = defel;
1733  cascade = defGetBoolean(d_cascade);
1734  }
1735  else
1736  elog(ERROR, "unrecognized option: %s", defel->defname);
1737  }
1738 
1739  /* Call CreateExtensionInternal to do the real work. */
1740  return CreateExtensionInternal(stmt->extname,
1741  schemaName,
1742  versionName,
1743  oldVersionName,
1744  cascade,
1745  NIL,
1746  true);
1747 }
#define NIL
Definition: pg_list.h:65
static ObjectAddress CreateExtensionInternal(char *extensionName, char *schemaName, const char *versionName, const char *oldVersionName, bool cascade, List *parents, bool is_create)
Definition: extension.c:1282
static void check_valid_extension_name(const char *extensionname)
Definition: extension.c:259
int errcode(int sqlerrcode)
Definition: elog.c:608
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:733
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvalidOid
Definition: postgres_ext.h:36
bool creating_extension
Definition: extension.c:70
#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:138
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
char * defname
Definition: parsenodes.h:730
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31

◆ ExecAlterExtensionContentsStmt()

ObjectAddress ExecAlterExtensionContentsStmt ( AlterExtensionContentsStmt stmt,
ObjectAddress objAddr 
)

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

3196 {
3197  ObjectAddress extension;
3198  ObjectAddress object;
3199  Relation relation;
3200  Oid oldExtension;
3201 
3202  extension.classId = ExtensionRelationId;
3203  extension.objectId = get_extension_oid(stmt->extname, false);
3204  extension.objectSubId = 0;
3205 
3206  /* Permission check: must own extension */
3207  if (!pg_extension_ownercheck(extension.objectId, GetUserId()))
3209  stmt->extname);
3210 
3211  /*
3212  * Translate the parser representation that identifies the object into an
3213  * ObjectAddress. get_object_address() will throw an error if the object
3214  * does not exist, and will also acquire a lock on the object to guard
3215  * against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
3216  */
3217  object = get_object_address(stmt->objtype, stmt->object,
3218  &relation, ShareUpdateExclusiveLock, false);
3219 
3220  Assert(object.objectSubId == 0);
3221  if (objAddr)
3222  *objAddr = object;
3223 
3224  /* Permission check: must own target object, too */
3225  check_object_ownership(GetUserId(), stmt->objtype, object,
3226  stmt->object, relation);
3227 
3228  /*
3229  * Check existing extension membership.
3230  */
3231  oldExtension = getExtensionOfObject(object.classId, object.objectId);
3232 
3233  if (stmt->action > 0)
3234  {
3235  /*
3236  * ADD, so complain if object is already attached to some extension.
3237  */
3238  if (OidIsValid(oldExtension))
3239  ereport(ERROR,
3240  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3241  errmsg("%s is already a member of extension \"%s\"",
3242  getObjectDescription(&object),
3243  get_extension_name(oldExtension))));
3244 
3245  /*
3246  * Prevent a schema from being added to an extension if the schema
3247  * contains the extension. That would create a dependency loop.
3248  */
3249  if (object.classId == NamespaceRelationId &&
3250  object.objectId == get_extension_schema(extension.objectId))
3251  ereport(ERROR,
3252  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3253  errmsg("cannot add schema \"%s\" to extension \"%s\" "
3254  "because the schema contains the extension",
3255  get_namespace_name(object.objectId),
3256  stmt->extname)));
3257 
3258  /*
3259  * OK, add the dependency.
3260  */
3261  recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
3262 
3263  /*
3264  * Also record the initial ACL on the object, if any.
3265  *
3266  * Note that this will handle the object's ACLs, as well as any ACLs
3267  * on object subIds. (In other words, when the object is a table,
3268  * this will record the table's ACL and the ACLs for the columns on
3269  * the table, if any).
3270  */
3271  recordExtObjInitPriv(object.objectId, object.classId);
3272  }
3273  else
3274  {
3275  /*
3276  * DROP, so complain if it's not a member.
3277  */
3278  if (oldExtension != extension.objectId)
3279  ereport(ERROR,
3280  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3281  errmsg("%s is not a member of extension \"%s\"",
3282  getObjectDescription(&object),
3283  stmt->extname)));
3284 
3285  /*
3286  * OK, drop the dependency.
3287  */
3288  if (deleteDependencyRecordsForClass(object.classId, object.objectId,
3289  ExtensionRelationId,
3290  DEPENDENCY_EXTENSION) != 1)
3291  elog(ERROR, "unexpected number of extension dependency records");
3292 
3293  /*
3294  * If it's a relation, it might have an entry in the extension's
3295  * extconfig array, which we must remove.
3296  */
3297  if (object.classId == RelationRelationId)
3298  extension_config_remove(extension.objectId, object.objectId);
3299 
3300  /*
3301  * Remove all the initial ACLs, if any.
3302  *
3303  * Note that this will remove the object's ACLs, as well as any ACLs
3304  * on object subIds. (In other words, when the object is a table,
3305  * this will remove the table's ACL and the ACLs for the columns on
3306  * the table, if any).
3307  */
3308  removeExtObjInitPriv(object.objectId, object.classId);
3309  }
3310 
3311  InvokeObjectPostAlterHook(ExtensionRelationId, extension.objectId, 0);
3312 
3313  /*
3314  * If get_object_address() opened the relation for us, we close it to keep
3315  * the reference count correct - but we retain any locks acquired by
3316  * get_object_address() until commit time, to guard against concurrent
3317  * activity.
3318  */
3319  if (relation != NULL)
3320  relation_close(relation, NoLock);
3321 
3322  return extension;
3323 }
void recordExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:5563
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c:610
static Oid get_extension_schema(Oid ext_oid)
Definition: extension.c:222
Oid GetUserId(void)
Definition: miscinit.c:380
char * get_extension_name(Oid ext_oid)
Definition: extension.c:183
int errcode(int sqlerrcode)
Definition: elog.c:608
static void extension_config_remove(Oid extensionoid, Oid tableoid)
Definition: extension.c:2535
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:639
char * getObjectDescription(const ObjectAddress *object)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
#define NoLock
Definition: lockdefs.h:34
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5250
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:240
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:733
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:138
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
void removeExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:5853

◆ ExecAlterExtensionStmt()

ObjectAddress ExecAlterExtensionStmt ( ParseState pstate,
AlterExtensionStmt stmt 
)

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

2887 {
2888  DefElem *d_new_version = NULL;
2889  char *versionName;
2890  char *oldVersionName;
2891  ExtensionControlFile *control;
2892  Oid extensionOid;
2893  Relation extRel;
2894  ScanKeyData key[1];
2895  SysScanDesc extScan;
2896  HeapTuple extTup;
2897  List *updateVersions;
2898  Datum datum;
2899  bool isnull;
2900  ListCell *lc;
2901  ObjectAddress address;
2902 
2903  /*
2904  * We use global variables to track the extension being created, so we can
2905  * create/update only one extension at the same time.
2906  */
2907  if (creating_extension)
2908  ereport(ERROR,
2909  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2910  errmsg("nested ALTER EXTENSION is not supported")));
2911 
2912  /*
2913  * Look up the extension --- it must already exist in pg_extension
2914  */
2915  extRel = table_open(ExtensionRelationId, AccessShareLock);
2916 
2917  ScanKeyInit(&key[0],
2918  Anum_pg_extension_extname,
2919  BTEqualStrategyNumber, F_NAMEEQ,
2920  CStringGetDatum(stmt->extname));
2921 
2922  extScan = systable_beginscan(extRel, ExtensionNameIndexId, true,
2923  NULL, 1, key);
2924 
2925  extTup = systable_getnext(extScan);
2926 
2927  if (!HeapTupleIsValid(extTup))
2928  ereport(ERROR,
2929  (errcode(ERRCODE_UNDEFINED_OBJECT),
2930  errmsg("extension \"%s\" does not exist",
2931  stmt->extname)));
2932 
2933  extensionOid = ((Form_pg_extension) GETSTRUCT(extTup))->oid;
2934 
2935  /*
2936  * Determine the existing version we are updating from
2937  */
2938  datum = heap_getattr(extTup, Anum_pg_extension_extversion,
2939  RelationGetDescr(extRel), &isnull);
2940  if (isnull)
2941  elog(ERROR, "extversion is null");
2942  oldVersionName = text_to_cstring(DatumGetTextPP(datum));
2943 
2944  systable_endscan(extScan);
2945 
2946  table_close(extRel, AccessShareLock);
2947 
2948  /* Permission check: must own extension */
2949  if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2951  stmt->extname);
2952 
2953  /*
2954  * Read the primary control file. Note we assume that it does not contain
2955  * any non-ASCII data, so there is no need to worry about encoding at this
2956  * point.
2957  */
2958  control = read_extension_control_file(stmt->extname);
2959 
2960  /*
2961  * Read the statement option list
2962  */
2963  foreach(lc, stmt->options)
2964  {
2965  DefElem *defel = (DefElem *) lfirst(lc);
2966 
2967  if (strcmp(defel->defname, "new_version") == 0)
2968  {
2969  if (d_new_version)
2970  ereport(ERROR,
2971  (errcode(ERRCODE_SYNTAX_ERROR),
2972  errmsg("conflicting or redundant options"),
2973  parser_errposition(pstate, defel->location)));
2974  d_new_version = defel;
2975  }
2976  else
2977  elog(ERROR, "unrecognized option: %s", defel->defname);
2978  }
2979 
2980  /*
2981  * Determine the version to update to
2982  */
2983  if (d_new_version && d_new_version->arg)
2984  versionName = strVal(d_new_version->arg);
2985  else if (control->default_version)
2986  versionName = control->default_version;
2987  else
2988  {
2989  ereport(ERROR,
2990  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2991  errmsg("version to install must be specified")));
2992  versionName = NULL; /* keep compiler quiet */
2993  }
2994  check_valid_version_name(versionName);
2995 
2996  /*
2997  * If we're already at that version, just say so
2998  */
2999  if (strcmp(oldVersionName, versionName) == 0)
3000  {
3001  ereport(NOTICE,
3002  (errmsg("version \"%s\" of extension \"%s\" is already installed",
3003  versionName, stmt->extname)));
3004  return InvalidObjectAddress;
3005  }
3006 
3007  /*
3008  * Identify the series of update script files we need to execute
3009  */
3010  updateVersions = identify_update_path(control,
3011  oldVersionName,
3012  versionName);
3013 
3014  /*
3015  * Update the pg_extension row and execute the update scripts, one at a
3016  * time
3017  */
3018  ApplyExtensionUpdates(extensionOid, control,
3019  oldVersionName, updateVersions,
3020  NULL, false, false);
3021 
3022  ObjectAddressSet(address, ExtensionRelationId, extensionOid);
3023 
3024  return address;
3025 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ExtensionNameIndexId
Definition: indexing.h:328
static ExtensionControlFile * read_extension_control_file(const char *extname)
Definition: extension.c:606
#define RelationGetDescr(relation)
Definition: rel.h:449
Oid GetUserId(void)
Definition: miscinit.c:380
#define DatumGetTextPP(X)
Definition: fmgr.h:286
static void ApplyExtensionUpdates(Oid extensionOid, ExtensionControlFile *pcontrol, const char *initialVersion, List *updateVersions, char *origSchemaName, bool cascade, bool is_create)
Definition: extension.c:3036
#define AccessShareLock
Definition: lockdefs.h:36
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:608
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:352
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ERROR
Definition: elog.h:43
static List * identify_update_path(ExtensionControlFile *control, const char *oldVersion, const char *newVersion)
Definition: extension.c:1091
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5250
int location
Definition: parsenodes.h:733
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ereport(elevel, rest)
Definition: elog.h:141
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:50
Node * arg
Definition: parsenodes.h:731
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
char * default_version
Definition: extension.c:80
uintptr_t Datum
Definition: postgres.h:367
static void check_valid_version_name(const char *versionname)
Definition: extension.c:306
bool creating_extension
Definition: extension.c:70
#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:204
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
char * defname
Definition: parsenodes.h:730
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ get_extension_name()

char* get_extension_name ( Oid  ext_oid)

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

184 {
185  char *result;
186  Relation rel;
187  SysScanDesc scandesc;
188  HeapTuple tuple;
189  ScanKeyData entry[1];
190 
191  rel = table_open(ExtensionRelationId, AccessShareLock);
192 
193  ScanKeyInit(&entry[0],
194  Anum_pg_extension_oid,
195  BTEqualStrategyNumber, F_OIDEQ,
196  ObjectIdGetDatum(ext_oid));
197 
198  scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
199  NULL, 1, entry);
200 
201  tuple = systable_getnext(scandesc);
202 
203  /* We assume that there can be at most one matching tuple */
204  if (HeapTupleIsValid(tuple))
205  result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname));
206  else
207  result = NULL;
208 
209  systable_endscan(scandesc);
210 
212 
213  return result;
214 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#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:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ExtensionOidIndexId
Definition: indexing.h:326
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:50
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define NameStr(name)
Definition: c.h:610
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 138 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().

139 {
140  Oid result;
141  Relation rel;
142  SysScanDesc scandesc;
143  HeapTuple tuple;
144  ScanKeyData entry[1];
145 
146  rel = table_open(ExtensionRelationId, AccessShareLock);
147 
148  ScanKeyInit(&entry[0],
149  Anum_pg_extension_extname,
150  BTEqualStrategyNumber, F_NAMEEQ,
151  CStringGetDatum(extname));
152 
153  scandesc = systable_beginscan(rel, ExtensionNameIndexId, true,
154  NULL, 1, entry);
155 
156  tuple = systable_getnext(scandesc);
157 
158  /* We assume that there can be at most one matching tuple */
159  if (HeapTupleIsValid(tuple))
160  result = ((Form_pg_extension) GETSTRUCT(tuple))->oid;
161  else
162  result = InvalidOid;
163 
164  systable_endscan(scandesc);
165 
167 
168  if (!OidIsValid(result) && !missing_ok)
169  ereport(ERROR,
170  (errcode(ERRCODE_UNDEFINED_OBJECT),
171  errmsg("extension \"%s\" does not exist",
172  extname)));
173 
174  return result;
175 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ExtensionNameIndexId
Definition: indexing.h:328
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:608
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:639
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ERROR
Definition: elog.h:43
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ereport(elevel, rest)
Definition: elog.h:141
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:50
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:822
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 1763 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().

1767 {
1768  Oid extensionOid;
1769  Relation rel;
1770  Datum values[Natts_pg_extension];
1771  bool nulls[Natts_pg_extension];
1772  HeapTuple tuple;
1773  ObjectAddress myself;
1774  ObjectAddress nsp;
1775  ListCell *lc;
1776 
1777  /*
1778  * Build and insert the pg_extension tuple
1779  */
1780  rel = table_open(ExtensionRelationId, RowExclusiveLock);
1781 
1782  memset(values, 0, sizeof(values));
1783  memset(nulls, 0, sizeof(nulls));
1784 
1785  extensionOid = GetNewOidWithIndex(rel, ExtensionOidIndexId,
1786  Anum_pg_extension_oid);
1787  values[Anum_pg_extension_oid - 1] = ObjectIdGetDatum(extensionOid);
1788  values[Anum_pg_extension_extname - 1] =
1790  values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
1791  values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
1792  values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
1793  values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
1794 
1795  if (extConfig == PointerGetDatum(NULL))
1796  nulls[Anum_pg_extension_extconfig - 1] = true;
1797  else
1798  values[Anum_pg_extension_extconfig - 1] = extConfig;
1799 
1800  if (extCondition == PointerGetDatum(NULL))
1801  nulls[Anum_pg_extension_extcondition - 1] = true;
1802  else
1803  values[Anum_pg_extension_extcondition - 1] = extCondition;
1804 
1805  tuple = heap_form_tuple(rel->rd_att, values, nulls);
1806 
1807  CatalogTupleInsert(rel, tuple);
1808 
1809  heap_freetuple(tuple);
1811 
1812  /*
1813  * Record dependencies on owner, schema, and prerequisite extensions
1814  */
1815  recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
1816 
1817  myself.classId = ExtensionRelationId;
1818  myself.objectId = extensionOid;
1819  myself.objectSubId = 0;
1820 
1821  nsp.classId = NamespaceRelationId;
1822  nsp.objectId = schemaOid;
1823  nsp.objectSubId = 0;
1824 
1825  recordDependencyOn(&myself, &nsp, DEPENDENCY_NORMAL);
1826 
1827  foreach(lc, requiredExtensions)
1828  {
1829  Oid reqext = lfirst_oid(lc);
1830  ObjectAddress otherext;
1831 
1832  otherext.classId = ExtensionRelationId;
1833  otherext.objectId = reqext;
1834  otherext.objectSubId = 0;
1835 
1836  recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
1837  }
1838  /* Post creation hook for new extension */
1839  InvokeObjectPostCreateHook(ExtensionRelationId, extensionOid, 0);
1840 
1841  return myself;
1842 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
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:145
#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:615
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:326
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:84
#define BoolGetDatum(X)
Definition: postgres.h:402
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define CStringGetTextDatum(s)
Definition: builtins.h:83
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 1851 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().

1852 {
1853  Relation rel;
1854  SysScanDesc scandesc;
1855  HeapTuple tuple;
1856  ScanKeyData entry[1];
1857 
1858  /*
1859  * Disallow deletion of any extension that's currently open for insertion;
1860  * else subsequent executions of recordDependencyOnCurrentExtension()
1861  * could create dangling pg_depend records that refer to a no-longer-valid
1862  * pg_extension OID. This is needed not so much because we think people
1863  * might write "DROP EXTENSION foo" in foo's own script files, as because
1864  * errors in dependency management in extension script files could give
1865  * rise to cases where an extension is dropped as a result of recursing
1866  * from some contained object. Because of that, we must test for the case
1867  * here, not at some higher level of the DROP EXTENSION command.
1868  */
1869  if (extId == CurrentExtensionObject)
1870  ereport(ERROR,
1871  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1872  errmsg("cannot drop extension \"%s\" because it is being modified",
1873  get_extension_name(extId))));
1874 
1875  rel = table_open(ExtensionRelationId, RowExclusiveLock);
1876 
1877  ScanKeyInit(&entry[0],
1878  Anum_pg_extension_oid,
1879  BTEqualStrategyNumber, F_OIDEQ,
1880  ObjectIdGetDatum(extId));
1881  scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
1882  NULL, 1, entry);
1883 
1884  tuple = systable_getnext(scandesc);
1885 
1886  /* We assume that there can be at most one matching tuple */
1887  if (HeapTupleIsValid(tuple))
1888  CatalogTupleDelete(rel, &tuple->t_self);
1889 
1890  systable_endscan(scandesc);
1891 
1893 }
Oid CurrentExtensionObject
Definition: extension.c:71
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
char * get_extension_name(Oid ext_oid)
Definition: extension.c:183
int errcode(int sqlerrcode)
Definition: elog.c:608
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:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#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 ereport(elevel, rest)
Definition: elog.h:141
#define ExtensionOidIndexId
Definition: indexing.h:326
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:822
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