PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
extension.h File Reference
Include dependency graph for extension.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ObjectAddress CreateExtension (ParseState *pstate, CreateExtensionStmt *stmt)
 
void RemoveExtensionById (Oid extId)
 
ObjectAddress InsertExtensionTuple (const char *extName, Oid extOwner, Oid schemaOid, bool relocatable, const char *extVersion, Datum extConfig, Datum extCondition, List *requiredExtensions)
 
ObjectAddress ExecAlterExtensionStmt (ParseState *pstate, AlterExtensionStmt *stmt)
 
ObjectAddress ExecAlterExtensionContentsStmt (AlterExtensionContentsStmt *stmt, ObjectAddress *objAddress)
 
Oid get_extension_oid (const char *extname, bool missing_ok)
 
char * get_extension_name (Oid ext_oid)
 
ObjectAddress AlterExtensionNamespace (List *names, const char *newschema, Oid *oldschema)
 
void AlterExtensionOwner_oid (Oid extensionOid, Oid newOwnerId)
 

Variables

PGDLLIMPORT bool creating_extension
 
Oid CurrentExtensionObject
 

Function Documentation

ObjectAddress AlterExtensionNamespace ( List names,
const char *  newschema,
Oid oldschema 
)

Definition at line 2675 of file extension.c.

References AccessShareLock, ACL_CREATE, ACL_KIND_EXTENSION, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, AlterObjectNamespace_oid(), Anum_pg_depend_refclassid, Anum_pg_depend_refobjid, BTEqualStrategyNumber, CatalogTupleUpdate(), changeDependencyFor(), ObjectAddress::classId, DEPENDENCY_EXTENSION, DependReferenceIndexId, DependRelationId, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ExtensionOidIndexId, ExtensionRelationId, get_extension_oid(), get_namespace_name(), getExtensionOfObject(), getObjectDescription(), GETSTRUCT, GetUserId(), heap_close, heap_copytuple(), heap_open(), HeapTupleIsValid, InvalidObjectAddress, InvalidOid, InvokeObjectPostAlterHook, linitial, list_length(), LookupCreationNamespace(), NamespaceRelationId, NameStr, new_object_addresses(), NULL, ObjectAddressSet, ObjectAddress::objectId, ObjectIdAttributeNumber, ObjectIdGetDatum, ObjectAddress::objectSubId, pg_extension_ownercheck(), pg_namespace_aclcheck(), relation_close(), RowExclusiveLock, ScanKeyInit(), strVal, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by ExecAlterObjectSchemaStmt().

2676 {
2677  char *extensionName;
2678  Oid extensionOid;
2679  Oid nspOid;
2680  Oid oldNspOid = InvalidOid;
2681  AclResult aclresult;
2682  Relation extRel;
2683  ScanKeyData key[2];
2684  SysScanDesc extScan;
2685  HeapTuple extTup;
2686  Form_pg_extension extForm;
2687  Relation depRel;
2688  SysScanDesc depScan;
2689  HeapTuple depTup;
2690  ObjectAddresses *objsMoved;
2691  ObjectAddress extAddr;
2692 
2693  if (list_length(names) != 1)
2694  ereport(ERROR,
2695  (errcode(ERRCODE_SYNTAX_ERROR),
2696  errmsg("extension name cannot be qualified")));
2697  extensionName = strVal(linitial(names));
2698 
2699  extensionOid = get_extension_oid(extensionName, false);
2700 
2701  nspOid = LookupCreationNamespace(newschema);
2702 
2703  /*
2704  * Permission check: must own extension. Note that we don't bother to
2705  * check ownership of the individual member objects ...
2706  */
2707  if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2709  extensionName);
2710 
2711  /* Permission check: must have creation rights in target namespace */
2712  aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
2713  if (aclresult != ACLCHECK_OK)
2714  aclcheck_error(aclresult, ACL_KIND_NAMESPACE, newschema);
2715 
2716  /*
2717  * If the schema is currently a member of the extension, disallow moving
2718  * the extension into the schema. That would create a dependency loop.
2719  */
2720  if (getExtensionOfObject(NamespaceRelationId, nspOid) == extensionOid)
2721  ereport(ERROR,
2722  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2723  errmsg("cannot move extension \"%s\" into schema \"%s\" "
2724  "because the extension contains the schema",
2725  extensionName, newschema)));
2726 
2727  /* Locate the pg_extension tuple */
2729 
2730  ScanKeyInit(&key[0],
2732  BTEqualStrategyNumber, F_OIDEQ,
2733  ObjectIdGetDatum(extensionOid));
2734 
2735  extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2736  NULL, 1, key);
2737 
2738  extTup = systable_getnext(extScan);
2739 
2740  if (!HeapTupleIsValid(extTup)) /* should not happen */
2741  elog(ERROR, "extension with oid %u does not exist", extensionOid);
2742 
2743  /* Copy tuple so we can modify it below */
2744  extTup = heap_copytuple(extTup);
2745  extForm = (Form_pg_extension) GETSTRUCT(extTup);
2746 
2747  systable_endscan(extScan);
2748 
2749  /*
2750  * If the extension is already in the target schema, just silently do
2751  * nothing.
2752  */
2753  if (extForm->extnamespace == nspOid)
2754  {
2755  heap_close(extRel, RowExclusiveLock);
2756  return InvalidObjectAddress;
2757  }
2758 
2759  /* Check extension is supposed to be relocatable */
2760  if (!extForm->extrelocatable)
2761  ereport(ERROR,
2762  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2763  errmsg("extension \"%s\" does not support SET SCHEMA",
2764  NameStr(extForm->extname))));
2765 
2766  objsMoved = new_object_addresses();
2767 
2768  /*
2769  * Scan pg_depend to find objects that depend directly on the extension,
2770  * and alter each one's schema.
2771  */
2773 
2774  ScanKeyInit(&key[0],
2776  BTEqualStrategyNumber, F_OIDEQ,
2778  ScanKeyInit(&key[1],
2780  BTEqualStrategyNumber, F_OIDEQ,
2781  ObjectIdGetDatum(extensionOid));
2782 
2783  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
2784  NULL, 2, key);
2785 
2786  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
2787  {
2788  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
2789  ObjectAddress dep;
2790  Oid dep_oldNspOid;
2791 
2792  /*
2793  * Ignore non-membership dependencies. (Currently, the only other
2794  * case we could see here is a normal dependency from another
2795  * extension.)
2796  */
2797  if (pg_depend->deptype != DEPENDENCY_EXTENSION)
2798  continue;
2799 
2800  dep.classId = pg_depend->classid;
2801  dep.objectId = pg_depend->objid;
2802  dep.objectSubId = pg_depend->objsubid;
2803 
2804  if (dep.objectSubId != 0) /* should not happen */
2805  elog(ERROR, "extension should not have a sub-object dependency");
2806 
2807  /* Relocate the object */
2808  dep_oldNspOid = AlterObjectNamespace_oid(dep.classId,
2809  dep.objectId,
2810  nspOid,
2811  objsMoved);
2812 
2813  /*
2814  * Remember previous namespace of first object that has one
2815  */
2816  if (oldNspOid == InvalidOid && dep_oldNspOid != InvalidOid)
2817  oldNspOid = dep_oldNspOid;
2818 
2819  /*
2820  * If not all the objects had the same old namespace (ignoring any
2821  * that are not in namespaces), complain.
2822  */
2823  if (dep_oldNspOid != InvalidOid && dep_oldNspOid != oldNspOid)
2824  ereport(ERROR,
2825  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2826  errmsg("extension \"%s\" does not support SET SCHEMA",
2827  NameStr(extForm->extname)),
2828  errdetail("%s is not in the extension's schema \"%s\"",
2829  getObjectDescription(&dep),
2830  get_namespace_name(oldNspOid))));
2831  }
2832 
2833  /* report old schema, if caller wants it */
2834  if (oldschema)
2835  *oldschema = oldNspOid;
2836 
2837  systable_endscan(depScan);
2838 
2840 
2841  /* Now adjust pg_extension.extnamespace */
2842  extForm->extnamespace = nspOid;
2843 
2844  CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
2845 
2846  heap_close(extRel, RowExclusiveLock);
2847 
2848  /* update dependencies to point to the new schema */
2850  NamespaceRelationId, oldNspOid, nspOid);
2851 
2853 
2854  ObjectAddressSet(extAddr, ExtensionRelationId, extensionOid);
2855 
2856  return extAddr;
2857 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
#define Anum_pg_depend_refobjid
Definition: pg_depend.h:72
#define NamespaceRelationId
Definition: pg_namespace.h:34
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c:447
#define Anum_pg_depend_refclassid
Definition: pg_depend.h:71
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:283
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
Oid LookupCreationNamespace(const char *nspname)
Definition: namespace.c:2730
#define DependReferenceIndexId
Definition: indexing.h:147
#define DependRelationId
Definition: pg_depend.h:29
#define AccessShareLock
Definition: lockdefs.h:36
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
#define heap_close(r, l)
Definition: heapam.h:97
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2026
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4459
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
char * getObjectDescription(const ObjectAddress *object)
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define linitial(l)
Definition: pg_list.h:110
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:75
ItemPointerData t_self
Definition: htup.h:65
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5017
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:61
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define ExtensionOidIndexId
Definition: indexing.h:312
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:51
AclResult
Definition: acl.h:170
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
static int list_length(const List *l)
Definition: pg_list.h:89
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:134
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:295
Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid, ObjectAddresses *objsMoved)
Definition: alter.c:531
#define NameStr(name)
Definition: c.h:495
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define ExtensionRelationId
Definition: pg_extension.h:29
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void AlterExtensionOwner_oid ( Oid  extensionOid,
Oid  newOwnerId 
)
ObjectAddress CreateExtension ( ParseState pstate,
CreateExtensionStmt stmt 
)

Definition at line 1615 of file extension.c.

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

Referenced by ProcessUtilitySlow().

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

Definition at line 3171 of file extension.c.

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

Referenced by ProcessUtilitySlow().

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

Definition at line 2863 of file extension.c.

References AccessShareLock, ACL_KIND_EXTENSION, aclcheck_error(), ACLCHECK_NOT_OWNER, Anum_pg_extension_extname, Anum_pg_extension_extversion, ApplyExtensionUpdates(), DefElem::arg, BTEqualStrategyNumber, check_valid_version_name(), creating_extension, CStringGetDatum, DatumGetTextPP, ExtensionControlFile::default_version, DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, ExtensionNameIndexId, ExtensionRelationId, AlterExtensionStmt::extname, GetUserId(), heap_close, heap_getattr, heap_open(), HeapTupleGetOid, HeapTupleIsValid, identify_update_path(), InvalidObjectAddress, lfirst, DefElem::location, NOTICE, NULL, ObjectAddressSet, AlterExtensionStmt::options, parser_errposition(), pg_extension_ownercheck(), read_extension_control_file(), RelationGetDescr, ScanKeyInit(), strVal, systable_beginscan(), systable_endscan(), systable_getnext(), and text_to_cstring().

Referenced by ProcessUtilitySlow().

2864 {
2865  DefElem *d_new_version = NULL;
2866  char *versionName;
2867  char *oldVersionName;
2868  ExtensionControlFile *control;
2869  Oid extensionOid;
2870  Relation extRel;
2871  ScanKeyData key[1];
2872  SysScanDesc extScan;
2873  HeapTuple extTup;
2874  List *updateVersions;
2875  Datum datum;
2876  bool isnull;
2877  ListCell *lc;
2878  ObjectAddress address;
2879 
2880  /*
2881  * We use global variables to track the extension being created, so we can
2882  * create/update only one extension at the same time.
2883  */
2884  if (creating_extension)
2885  ereport(ERROR,
2886  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2887  errmsg("nested ALTER EXTENSION is not supported")));
2888 
2889  /*
2890  * Look up the extension --- it must already exist in pg_extension
2891  */
2893 
2894  ScanKeyInit(&key[0],
2896  BTEqualStrategyNumber, F_NAMEEQ,
2897  CStringGetDatum(stmt->extname));
2898 
2899  extScan = systable_beginscan(extRel, ExtensionNameIndexId, true,
2900  NULL, 1, key);
2901 
2902  extTup = systable_getnext(extScan);
2903 
2904  if (!HeapTupleIsValid(extTup))
2905  ereport(ERROR,
2906  (errcode(ERRCODE_UNDEFINED_OBJECT),
2907  errmsg("extension \"%s\" does not exist",
2908  stmt->extname)));
2909 
2910  extensionOid = HeapTupleGetOid(extTup);
2911 
2912  /*
2913  * Determine the existing version we are updating from
2914  */
2916  RelationGetDescr(extRel), &isnull);
2917  if (isnull)
2918  elog(ERROR, "extversion is null");
2919  oldVersionName = text_to_cstring(DatumGetTextPP(datum));
2920 
2921  systable_endscan(extScan);
2922 
2923  heap_close(extRel, AccessShareLock);
2924 
2925  /* Permission check: must own extension */
2926  if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2928  stmt->extname);
2929 
2930  /*
2931  * Read the primary control file. Note we assume that it does not contain
2932  * any non-ASCII data, so there is no need to worry about encoding at this
2933  * point.
2934  */
2935  control = read_extension_control_file(stmt->extname);
2936 
2937  /*
2938  * Read the statement option list
2939  */
2940  foreach(lc, stmt->options)
2941  {
2942  DefElem *defel = (DefElem *) lfirst(lc);
2943 
2944  if (strcmp(defel->defname, "new_version") == 0)
2945  {
2946  if (d_new_version)
2947  ereport(ERROR,
2948  (errcode(ERRCODE_SYNTAX_ERROR),
2949  errmsg("conflicting or redundant options"),
2950  parser_errposition(pstate, defel->location)));
2951  d_new_version = defel;
2952  }
2953  else
2954  elog(ERROR, "unrecognized option: %s", defel->defname);
2955  }
2956 
2957  /*
2958  * Determine the version to update to
2959  */
2960  if (d_new_version && d_new_version->arg)
2961  versionName = strVal(d_new_version->arg);
2962  else if (control->default_version)
2963  versionName = control->default_version;
2964  else
2965  {
2966  ereport(ERROR,
2967  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2968  errmsg("version to install must be specified")));
2969  versionName = NULL; /* keep compiler quiet */
2970  }
2971  check_valid_version_name(versionName);
2972 
2973  /*
2974  * If we're already at that version, just say so
2975  */
2976  if (strcmp(oldVersionName, versionName) == 0)
2977  {
2978  ereport(NOTICE,
2979  (errmsg("version \"%s\" of extension \"%s\" is already installed",
2980  versionName, stmt->extname)));
2981  return InvalidObjectAddress;
2982  }
2983 
2984  /*
2985  * Identify the series of update script files we need to execute
2986  */
2987  updateVersions = identify_update_path(control,
2988  oldVersionName,
2989  versionName);
2990 
2991  /*
2992  * Update the pg_extension row and execute the update scripts, one at a
2993  * time
2994  */
2995  ApplyExtensionUpdates(extensionOid, control,
2996  oldVersionName, updateVersions,
2997  NULL, false, false);
2998 
2999  ObjectAddressSet(address, ExtensionRelationId, extensionOid);
3000 
3001  return address;
3002 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define ExtensionNameIndexId
Definition: indexing.h:314
static ExtensionControlFile * read_extension_control_file(const char *extname)
Definition: extension.c:602
#define RelationGetDescr(relation)
Definition: rel.h:425
Oid GetUserId(void)
Definition: miscinit.c:283
#define Anum_pg_extension_extversion
Definition: pg_extension.h:63
#define DatumGetTextPP(X)
Definition: fmgr.h:249
static void ApplyExtensionUpdates(Oid extensionOid, ExtensionControlFile *pcontrol, const char *initialVersion, List *updateVersions, char *origSchemaName, bool cascade, bool is_create)
Definition: extension.c:3013
#define AccessShareLock
Definition: lockdefs.h:36
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ERROR
Definition: elog.h:43
static List * identify_update_path(ExtensionControlFile *control, const char *oldVersion, const char *newVersion)
Definition: extension.c:1070
#define Anum_pg_extension_extname
Definition: pg_extension.h:59
bool pg_extension_ownercheck(Oid ext_oid, Oid roleid)
Definition: aclchk.c:5017
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
int location
Definition: parsenodes.h:678
#define CStringGetDatum(X)
Definition: postgres.h:586
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:676
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
char * default_version
Definition: extension.c:77
uintptr_t Datum
Definition: postgres.h:374
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
static void check_valid_version_name(const char *versionname)
Definition: extension.c:302
bool creating_extension
Definition: extension.c:67
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:109
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
char * text_to_cstring(const text *t)
Definition: varlena.c:184
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
char * defname
Definition: parsenodes.h:675
#define elog
Definition: elog.h:219
#define ExtensionRelationId
Definition: pg_extension.h:29
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
char* get_extension_name ( Oid  ext_oid)

Definition at line 179 of file extension.c.

References AccessShareLock, BTEqualStrategyNumber, ExtensionOidIndexId, ExtensionRelationId, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, NameStr, NULL, ObjectIdAttributeNumber, ObjectIdGetDatum, pstrdup(), ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

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

180 {
181  char *result;
182  Relation rel;
183  SysScanDesc scandesc;
184  HeapTuple tuple;
185  ScanKeyData entry[1];
186 
188 
189  ScanKeyInit(&entry[0],
191  BTEqualStrategyNumber, F_OIDEQ,
192  ObjectIdGetDatum(ext_oid));
193 
194  scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
195  NULL, 1, entry);
196 
197  tuple = systable_getnext(scandesc);
198 
199  /* We assume that there can be at most one matching tuple */
200  if (HeapTupleIsValid(tuple))
201  result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname));
202  else
203  result = NULL;
204 
205  systable_endscan(scandesc);
206 
208 
209  return result;
210 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
char * pstrdup(const char *in)
Definition: mcxt.c:1165
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ExtensionOidIndexId
Definition: indexing.h:312
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:51
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define NameStr(name)
Definition: c.h:495
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ExtensionRelationId
Definition: pg_extension.h:29
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Oid get_extension_oid ( const char *  extname,
bool  missing_ok 
)

Definition at line 134 of file extension.c.

References AccessShareLock, Anum_pg_extension_extname, BTEqualStrategyNumber, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, ExtensionNameIndexId, ExtensionRelationId, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvalidOid, NULL, OidIsValid, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

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

135 {
136  Oid result;
137  Relation rel;
138  SysScanDesc scandesc;
139  HeapTuple tuple;
140  ScanKeyData entry[1];
141 
143 
144  ScanKeyInit(&entry[0],
146  BTEqualStrategyNumber, F_NAMEEQ,
147  CStringGetDatum(extname));
148 
149  scandesc = systable_beginscan(rel, ExtensionNameIndexId, true,
150  NULL, 1, entry);
151 
152  tuple = systable_getnext(scandesc);
153 
154  /* We assume that there can be at most one matching tuple */
155  if (HeapTupleIsValid(tuple))
156  result = HeapTupleGetOid(tuple);
157  else
158  result = InvalidOid;
159 
160  systable_endscan(scandesc);
161 
163 
164  if (!OidIsValid(result) && !missing_ok)
165  ereport(ERROR,
166  (errcode(ERRCODE_UNDEFINED_OBJECT),
167  errmsg("extension \"%s\" does not exist",
168  extname)));
169 
170  return result;
171 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define ExtensionNameIndexId
Definition: indexing.h:314
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ERROR
Definition: elog.h:43
#define Anum_pg_extension_extname
Definition: pg_extension.h:59
#define CStringGetDatum(X)
Definition: postgres.h:586
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ExtensionRelationId
Definition: pg_extension.h:29
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ObjectAddress InsertExtensionTuple ( const char *  extName,
Oid  extOwner,
Oid  schemaOid,
bool  relocatable,
const char *  extVersion,
Datum  extConfig,
Datum  extCondition,
List requiredExtensions 
)

Definition at line 1735 of file extension.c.

References Anum_pg_extension_extcondition, Anum_pg_extension_extconfig, Anum_pg_extension_extname, Anum_pg_extension_extnamespace, Anum_pg_extension_extowner, Anum_pg_extension_extrelocatable, Anum_pg_extension_extversion, BoolGetDatum, CatalogTupleInsert(), ObjectAddress::classId, CStringGetDatum, CStringGetTextDatum, DEPENDENCY_NORMAL, DirectFunctionCall1, ExtensionRelationId, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), InvokeObjectPostCreateHook, lfirst_oid, namein(), NamespaceRelationId, Natts_pg_extension, NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, PointerGetDatum, RelationData::rd_att, recordDependencyOn(), recordDependencyOnOwner(), RowExclusiveLock, and values.

Referenced by binary_upgrade_create_empty_extension(), and CreateExtensionInternal().

1739 {
1740  Oid extensionOid;
1741  Relation rel;
1743  bool nulls[Natts_pg_extension];
1744  HeapTuple tuple;
1745  ObjectAddress myself;
1746  ObjectAddress nsp;
1747  ListCell *lc;
1748 
1749  /*
1750  * Build and insert the pg_extension tuple
1751  */
1753 
1754  memset(values, 0, sizeof(values));
1755  memset(nulls, 0, sizeof(nulls));
1756 
1757  values[Anum_pg_extension_extname - 1] =
1759  values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
1760  values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
1761  values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
1762  values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
1763 
1764  if (extConfig == PointerGetDatum(NULL))
1765  nulls[Anum_pg_extension_extconfig - 1] = true;
1766  else
1767  values[Anum_pg_extension_extconfig - 1] = extConfig;
1768 
1769  if (extCondition == PointerGetDatum(NULL))
1770  nulls[Anum_pg_extension_extcondition - 1] = true;
1771  else
1772  values[Anum_pg_extension_extcondition - 1] = extCondition;
1773 
1774  tuple = heap_form_tuple(rel->rd_att, values, nulls);
1775 
1776  extensionOid = CatalogTupleInsert(rel, tuple);
1777 
1778  heap_freetuple(tuple);
1780 
1781  /*
1782  * Record dependencies on owner, schema, and prerequisite extensions
1783  */
1784  recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
1785 
1786  myself.classId = ExtensionRelationId;
1787  myself.objectId = extensionOid;
1788  myself.objectSubId = 0;
1789 
1791  nsp.objectId = schemaOid;
1792  nsp.objectSubId = 0;
1793 
1794  recordDependencyOn(&myself, &nsp, DEPENDENCY_NORMAL);
1795 
1796  foreach(lc, requiredExtensions)
1797  {
1798  Oid reqext = lfirst_oid(lc);
1799  ObjectAddress otherext;
1800 
1801  otherext.classId = ExtensionRelationId;
1802  otherext.objectId = reqext;
1803  otherext.objectSubId = 0;
1804 
1805  recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
1806  }
1807  /* Post creation hook for new extension */
1809 
1810  return myself;
1811 }
#define NamespaceRelationId
Definition: pg_namespace.h:34
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
#define Anum_pg_extension_extrelocatable
Definition: pg_extension.h:62
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define PointerGetDatum(X)
Definition: postgres.h:564
#define Anum_pg_extension_extversion
Definition: pg_extension.h:63
#define Anum_pg_extension_extconfig
Definition: pg_extension.h:64
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:158
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Anum_pg_extension_extname
Definition: pg_extension.h:59
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:586
#define Anum_pg_extension_extcondition
Definition: pg_extension.h:65
uintptr_t Datum
Definition: postgres.h:374
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
TupleDesc rd_att
Definition: rel.h:114
#define BoolGetDatum(X)
Definition: postgres.h:410
#define Anum_pg_extension_extowner
Definition: pg_extension.h:60
#define NULL
Definition: c.h:226
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define Natts_pg_extension
Definition: pg_extension.h:58
#define CStringGetTextDatum(s)
Definition: builtins.h:90
#define Anum_pg_extension_extnamespace
Definition: pg_extension.h:61
#define ExtensionRelationId
Definition: pg_extension.h:29
#define lfirst_oid(lc)
Definition: pg_list.h:108
void RemoveExtensionById ( Oid  extId)

Definition at line 1820 of file extension.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), CurrentExtensionObject, ereport, errcode(), errmsg(), ERROR, ExtensionOidIndexId, ExtensionRelationId, get_extension_name(), heap_close, heap_open(), HeapTupleIsValid, NULL, ObjectIdAttributeNumber, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by doDeletion().

1821 {
1822  Relation rel;
1823  SysScanDesc scandesc;
1824  HeapTuple tuple;
1825  ScanKeyData entry[1];
1826 
1827  /*
1828  * Disallow deletion of any extension that's currently open for insertion;
1829  * else subsequent executions of recordDependencyOnCurrentExtension()
1830  * could create dangling pg_depend records that refer to a no-longer-valid
1831  * pg_extension OID. This is needed not so much because we think people
1832  * might write "DROP EXTENSION foo" in foo's own script files, as because
1833  * errors in dependency management in extension script files could give
1834  * rise to cases where an extension is dropped as a result of recursing
1835  * from some contained object. Because of that, we must test for the case
1836  * here, not at some higher level of the DROP EXTENSION command.
1837  */
1838  if (extId == CurrentExtensionObject)
1839  ereport(ERROR,
1840  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1841  errmsg("cannot drop extension \"%s\" because it is being modified",
1842  get_extension_name(extId))));
1843 
1845 
1846  ScanKeyInit(&entry[0],
1848  BTEqualStrategyNumber, F_OIDEQ,
1849  ObjectIdGetDatum(extId));
1850  scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
1851  NULL, 1, entry);
1852 
1853  tuple = systable_getnext(scandesc);
1854 
1855  /* We assume that there can be at most one matching tuple */
1856  if (HeapTupleIsValid(tuple))
1857  CatalogTupleDelete(rel, &tuple->t_self);
1858 
1859  systable_endscan(scandesc);
1860 
1862 }
Oid CurrentExtensionObject
Definition: extension.c:68
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
char * get_extension_name(Oid ext_oid)
Definition: extension.c:179
int errcode(int sqlerrcode)
Definition: elog.c:575
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define ExtensionOidIndexId
Definition: indexing.h:312
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ExtensionRelationId
Definition: pg_extension.h:29
#define BTEqualStrategyNumber
Definition: stratnum.h:31

Variable Documentation