PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
tablecmds.h File Reference
#include "access/htup.h"
#include "catalog/dependency.h"
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
#include "storage/lock.h"
#include "utils/relcache.h"
Include dependency graph for tablecmds.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ObjectAddress DefineRelation (CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress)
 
void RemoveRelations (DropStmt *drop)
 
Oid AlterTableLookupRelation (AlterTableStmt *stmt, LOCKMODE lockmode)
 
void AlterTable (Oid relid, LOCKMODE lockmode, AlterTableStmt *stmt)
 
LOCKMODE AlterTableGetLockLevel (List *cmds)
 
void ATExecChangeOwner (Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
 
void AlterTableInternal (Oid relid, List *cmds, bool recurse)
 
Oid AlterTableMoveAll (AlterTableMoveAllStmt *stmt)
 
ObjectAddress AlterTableNamespace (AlterObjectSchemaStmt *stmt, Oid *oldschema)
 
void AlterTableNamespaceInternal (Relation rel, Oid oldNspOid, Oid nspOid, ObjectAddresses *objsMoved)
 
void AlterRelationNamespaceInternal (Relation classRel, Oid relOid, Oid oldNspOid, Oid newNspOid, bool hasDependEntry, ObjectAddresses *objsMoved)
 
void CheckTableNotInUse (Relation rel, const char *stmt)
 
void ExecuteTruncate (TruncateStmt *stmt)
 
void SetRelationHasSubclass (Oid relationId, bool relhassubclass)
 
ObjectAddress renameatt (RenameStmt *stmt)
 
ObjectAddress renameatt_type (RenameStmt *stmt)
 
ObjectAddress RenameConstraint (RenameStmt *stmt)
 
ObjectAddress RenameRelation (RenameStmt *stmt)
 
void RenameRelationInternal (Oid myrelid, const char *newrelname, bool is_internal)
 
void find_composite_type_dependencies (Oid typeOid, Relation origRelation, const char *origTypeName)
 
void check_of_type (HeapTuple typetuple)
 
void register_on_commit_action (Oid relid, OnCommitAction action)
 
void remove_on_commit_action (Oid relid)
 
void PreCommit_on_commit_actions (void)
 
void AtEOXact_on_commit_actions (bool isCommit)
 
void AtEOSubXact_on_commit_actions (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
void RangeVarCallbackOwnsTable (const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
 
void RangeVarCallbackOwnsRelation (const RangeVar *relation, Oid relId, Oid oldRelId, void *noCatalogs)
 

Function Documentation

void AlterRelationNamespaceInternal ( Relation  classRel,
Oid  relOid,
Oid  oldNspOid,
Oid  newNspOid,
bool  hasDependEntry,
ObjectAddresses objsMoved 
)

Definition at line 11466 of file tablecmds.c.

References add_exact_object_address(), Assert, CatalogUpdateIndexes(), changeDependencyFor(), ObjectAddress::classId, elog, ereport, errcode(), errmsg(), ERROR, get_namespace_name(), get_relname_relid(), GETSTRUCT, heap_freetuple(), HeapTupleIsValid, InvalidOid, InvokeObjectPostAlterHook, NamespaceRelationId, NameStr, object_address_present(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RelationRelationId, RELOID, SearchSysCacheCopy1, simple_heap_update(), and HeapTupleData::t_self.

Referenced by AlterIndexNamespaces(), AlterSeqNamespaces(), AlterTableNamespaceInternal(), and AlterTypeNamespaceInternal().

11470 {
11471  HeapTuple classTup;
11472  Form_pg_class classForm;
11473  ObjectAddress thisobj;
11474  bool already_done = false;
11475 
11476  classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid));
11477  if (!HeapTupleIsValid(classTup))
11478  elog(ERROR, "cache lookup failed for relation %u", relOid);
11479  classForm = (Form_pg_class) GETSTRUCT(classTup);
11480 
11481  Assert(classForm->relnamespace == oldNspOid);
11482 
11483  thisobj.classId = RelationRelationId;
11484  thisobj.objectId = relOid;
11485  thisobj.objectSubId = 0;
11486 
11487  /*
11488  * If the object has already been moved, don't move it again. If it's
11489  * already in the right place, don't move it, but still fire the object
11490  * access hook.
11491  */
11492  already_done = object_address_present(&thisobj, objsMoved);
11493  if (!already_done && oldNspOid != newNspOid)
11494  {
11495  /* check for duplicate name (more friendly than unique-index failure) */
11496  if (get_relname_relid(NameStr(classForm->relname),
11497  newNspOid) != InvalidOid)
11498  ereport(ERROR,
11499  (errcode(ERRCODE_DUPLICATE_TABLE),
11500  errmsg("relation \"%s\" already exists in schema \"%s\"",
11501  NameStr(classForm->relname),
11502  get_namespace_name(newNspOid))));
11503 
11504  /* classTup is a copy, so OK to scribble on */
11505  classForm->relnamespace = newNspOid;
11506 
11507  simple_heap_update(classRel, &classTup->t_self, classTup);
11508  CatalogUpdateIndexes(classRel, classTup);
11509 
11510  /* Update dependency on schema if caller said so */
11511  if (hasDependEntry &&
11513  relOid,
11515  oldNspOid,
11516  newNspOid) != 1)
11517  elog(ERROR, "failed to change schema dependency for relation \"%s\"",
11518  NameStr(classForm->relname));
11519  }
11520  if (!already_done)
11521  {
11522  add_exact_object_address(&thisobj, objsMoved);
11523 
11525  }
11526 
11527  heap_freetuple(classTup);
11528 }
#define NamespaceRelationId
Definition: pg_namespace.h:34
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
#define RelationRelationId
Definition: pg_class.h:29
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2158
int errcode(int sqlerrcode)
Definition: elog.c:575
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2098
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1306
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1651
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:667
void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
Definition: indexing.c:157
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
Definition: heapam.c:4422
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:150
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:297
#define NameStr(name)
Definition: c.h:494
#define elog
Definition: elog.h:218
void AlterTable ( Oid  relid,
LOCKMODE  lockmode,
AlterTableStmt stmt 
)

Definition at line 2771 of file tablecmds.c.

References ATController(), CheckTableNotInUse(), AlterTableStmt::cmds, RangeVar::inhOpt, interpretInhOption(), NoLock, AlterTableStmt::relation, and relation_open().

Referenced by ProcessUtilitySlow().

2772 {
2773  Relation rel;
2774 
2775  /* Caller is required to provide an adequate lock. */
2776  rel = relation_open(relid, NoLock);
2777 
2778  CheckTableNotInUse(rel, "ALTER TABLE");
2779 
2780  ATController(stmt,
2781  rel, stmt->cmds, interpretInhOption(stmt->relation->inhOpt),
2782  lockmode);
2783 }
InhOption inhOpt
Definition: primnodes.h:75
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3083
bool interpretInhOption(InhOption inhOpt)
Definition: parse_clause.c:240
#define NoLock
Definition: lockdefs.h:34
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:2692
RangeVar * relation
Definition: parsenodes.h:1458
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
LOCKMODE AlterTableGetLockLevel ( List cmds)

Definition at line 2842 of file tablecmds.c.

References AccessExclusiveLock, AlterTableGetRelOptionsLockLevel(), AT_AddColumn, AT_AddColumnToView, AT_AddConstraint, AT_AddConstraintRecurse, AT_AddIndex, AT_AddIndexConstraint, AT_AddInherit, AT_AddOf, AT_AddOids, AT_AlterColumnGenericOptions, AT_AlterColumnType, AT_AlterConstraint, AT_ChangeOwner, AT_ClusterOn, AT_ColumnDefault, AT_DisableRowSecurity, AT_DisableRule, AT_DisableTrig, AT_DisableTrigAll, AT_DisableTrigUser, AT_DropCluster, AT_DropColumn, AT_DropConstraint, AT_DropInherit, AT_DropNotNull, AT_DropOf, AT_DropOids, AT_EnableAlwaysRule, AT_EnableAlwaysTrig, AT_EnableReplicaRule, AT_EnableReplicaTrig, AT_EnableRowSecurity, AT_EnableRule, AT_EnableTrig, AT_EnableTrigAll, AT_EnableTrigUser, AT_ForceRowSecurity, AT_GenericOptions, AT_NoForceRowSecurity, AT_ProcessedConstraint, AT_ReAddConstraint, AT_ReplaceRelOptions, AT_ReplicaIdentity, AT_ResetOptions, AT_ResetRelOptions, AT_SetLogged, AT_SetNotNull, AT_SetOptions, AT_SetRelOptions, AT_SetStatistics, AT_SetStorage, AT_SetTableSpace, AT_SetUnLogged, AT_ValidateConstraint, CONSTR_EXCLUSION, CONSTR_FOREIGN, CONSTR_PRIMARY, CONSTR_UNIQUE, Constraint::contype, AlterTableCmd::def, elog, ERROR, IsA, lfirst, ShareRowExclusiveLock, ShareUpdateExclusiveLock, and AlterTableCmd::subtype.

Referenced by AlterTableInternal(), and ProcessUtilitySlow().

2843 {
2844  /*
2845  * This only works if we read catalog tables using MVCC snapshots.
2846  */
2847  ListCell *lcmd;
2849 
2850  foreach(lcmd, cmds)
2851  {
2852  AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
2853  LOCKMODE cmd_lockmode = AccessExclusiveLock; /* default for compiler */
2854 
2855  switch (cmd->subtype)
2856  {
2857  /*
2858  * These subcommands rewrite the heap, so require full locks.
2859  */
2860  case AT_AddColumn: /* may rewrite heap, in some cases and visible
2861  * to SELECT */
2862  case AT_SetTableSpace: /* must rewrite heap */
2863  case AT_AlterColumnType: /* must rewrite heap */
2864  case AT_AddOids: /* must rewrite heap */
2865  cmd_lockmode = AccessExclusiveLock;
2866  break;
2867 
2868  /*
2869  * These subcommands may require addition of toast tables. If
2870  * we add a toast table to a table currently being scanned, we
2871  * might miss data added to the new toast table by concurrent
2872  * insert transactions.
2873  */
2874  case AT_SetStorage:/* may add toast tables, see
2875  * ATRewriteCatalogs() */
2876  cmd_lockmode = AccessExclusiveLock;
2877  break;
2878 
2879  /*
2880  * Removing constraints can affect SELECTs that have been
2881  * optimised assuming the constraint holds true.
2882  */
2883  case AT_DropConstraint: /* as DROP INDEX */
2884  case AT_DropNotNull: /* may change some SQL plans */
2885  cmd_lockmode = AccessExclusiveLock;
2886  break;
2887 
2888  /*
2889  * Subcommands that may be visible to concurrent SELECTs
2890  */
2891  case AT_DropColumn: /* change visible to SELECT */
2892  case AT_AddColumnToView: /* CREATE VIEW */
2893  case AT_DropOids: /* calls AT_DropColumn */
2894  case AT_EnableAlwaysRule: /* may change SELECT rules */
2895  case AT_EnableReplicaRule: /* may change SELECT rules */
2896  case AT_EnableRule: /* may change SELECT rules */
2897  case AT_DisableRule: /* may change SELECT rules */
2898  cmd_lockmode = AccessExclusiveLock;
2899  break;
2900 
2901  /*
2902  * Changing owner may remove implicit SELECT privileges
2903  */
2904  case AT_ChangeOwner: /* change visible to SELECT */
2905  cmd_lockmode = AccessExclusiveLock;
2906  break;
2907 
2908  /*
2909  * Changing foreign table options may affect optimisation.
2910  */
2911  case AT_GenericOptions:
2913  cmd_lockmode = AccessExclusiveLock;
2914  break;
2915 
2916  /*
2917  * These subcommands affect write operations only.
2918  */
2919  case AT_EnableTrig:
2920  case AT_EnableAlwaysTrig:
2921  case AT_EnableReplicaTrig:
2922  case AT_EnableTrigAll:
2923  case AT_EnableTrigUser:
2924  case AT_DisableTrig:
2925  case AT_DisableTrigAll:
2926  case AT_DisableTrigUser:
2927  cmd_lockmode = ShareRowExclusiveLock;
2928  break;
2929 
2930  /*
2931  * These subcommands affect write operations only. XXX
2932  * Theoretically, these could be ShareRowExclusiveLock.
2933  */
2934  case AT_ColumnDefault:
2935  case AT_AlterConstraint:
2936  case AT_AddIndex: /* from ADD CONSTRAINT */
2937  case AT_AddIndexConstraint:
2938  case AT_ReplicaIdentity:
2939  case AT_SetNotNull:
2940  case AT_EnableRowSecurity:
2941  case AT_DisableRowSecurity:
2942  case AT_ForceRowSecurity:
2943  case AT_NoForceRowSecurity:
2944  cmd_lockmode = AccessExclusiveLock;
2945  break;
2946 
2947  case AT_AddConstraint:
2948  case AT_ProcessedConstraint: /* becomes AT_AddConstraint */
2949  case AT_AddConstraintRecurse: /* becomes AT_AddConstraint */
2950  case AT_ReAddConstraint: /* becomes AT_AddConstraint */
2951  if (IsA(cmd->def, Constraint))
2952  {
2953  Constraint *con = (Constraint *) cmd->def;
2954 
2955  switch (con->contype)
2956  {
2957  case CONSTR_EXCLUSION:
2958  case CONSTR_PRIMARY:
2959  case CONSTR_UNIQUE:
2960 
2961  /*
2962  * Cases essentially the same as CREATE INDEX. We
2963  * could reduce the lock strength to ShareLock if
2964  * we can work out how to allow concurrent catalog
2965  * updates. XXX Might be set down to
2966  * ShareRowExclusiveLock but requires further
2967  * analysis.
2968  */
2969  cmd_lockmode = AccessExclusiveLock;
2970  break;
2971  case CONSTR_FOREIGN:
2972 
2973  /*
2974  * We add triggers to both tables when we add a
2975  * Foreign Key, so the lock level must be at least
2976  * as strong as CREATE TRIGGER.
2977  */
2978  cmd_lockmode = ShareRowExclusiveLock;
2979  break;
2980 
2981  default:
2982  cmd_lockmode = AccessExclusiveLock;
2983  }
2984  }
2985  break;
2986 
2987  /*
2988  * These subcommands affect inheritance behaviour. Queries
2989  * started before us will continue to see the old inheritance
2990  * behaviour, while queries started after we commit will see
2991  * new behaviour. No need to prevent reads or writes to the
2992  * subtable while we hook it up though. Changing the TupDesc
2993  * may be a problem, so keep highest lock.
2994  */
2995  case AT_AddInherit:
2996  case AT_DropInherit:
2997  cmd_lockmode = AccessExclusiveLock;
2998  break;
2999 
3000  /*
3001  * These subcommands affect implicit row type conversion. They
3002  * have affects similar to CREATE/DROP CAST on queries. don't
3003  * provide for invalidating parse trees as a result of such
3004  * changes, so we keep these at AccessExclusiveLock.
3005  */
3006  case AT_AddOf:
3007  case AT_DropOf:
3008  cmd_lockmode = AccessExclusiveLock;
3009  break;
3010 
3011  /*
3012  * Only used by CREATE OR REPLACE VIEW which must conflict
3013  * with an SELECTs currently using the view.
3014  */
3015  case AT_ReplaceRelOptions:
3016  cmd_lockmode = AccessExclusiveLock;
3017  break;
3018 
3019  /*
3020  * These subcommands affect general strategies for performance
3021  * and maintenance, though don't change the semantic results
3022  * from normal data reads and writes. Delaying an ALTER TABLE
3023  * behind currently active writes only delays the point where
3024  * the new strategy begins to take effect, so there is no
3025  * benefit in waiting. In this case the minimum restriction
3026  * applies: we don't currently allow concurrent catalog
3027  * updates.
3028  */
3029  case AT_SetStatistics: /* Uses MVCC in getTableAttrs() */
3030  case AT_ClusterOn: /* Uses MVCC in getIndexes() */
3031  case AT_DropCluster: /* Uses MVCC in getIndexes() */
3032  case AT_SetOptions: /* Uses MVCC in getTableAttrs() */
3033  case AT_ResetOptions: /* Uses MVCC in getTableAttrs() */
3034  cmd_lockmode = ShareUpdateExclusiveLock;
3035  break;
3036 
3037  case AT_SetLogged:
3038  case AT_SetUnLogged:
3039  cmd_lockmode = AccessExclusiveLock;
3040  break;
3041 
3042  case AT_ValidateConstraint: /* Uses MVCC in
3043  * getConstraints() */
3044  cmd_lockmode = ShareUpdateExclusiveLock;
3045  break;
3046 
3047  /*
3048  * Rel options are more complex than first appears. Options
3049  * are set here for tables, views and indexes; for historical
3050  * reasons these can all be used with ALTER TABLE, so we can't
3051  * decide between them using the basic grammar.
3052  */
3053  case AT_SetRelOptions: /* Uses MVCC in getIndexes() and
3054  * getTables() */
3055  case AT_ResetRelOptions: /* Uses MVCC in getIndexes() and
3056  * getTables() */
3057  cmd_lockmode = AlterTableGetRelOptionsLockLevel((List *) cmd->def);
3058  break;
3059 
3060  default: /* oops */
3061  elog(ERROR, "unrecognized alter table type: %d",
3062  (int) cmd->subtype);
3063  break;
3064  }
3065 
3066  /*
3067  * Take the greatest lockmode from any subcommand
3068  */
3069  if (cmd_lockmode > lockmode)
3070  lockmode = cmd_lockmode;
3071  }
3072 
3073  return lockmode;
3074 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:542
int LOCKMODE
Definition: lockdefs.h:26
AlterTableType subtype
Definition: parsenodes.h:1540
#define ERROR
Definition: elog.h:43
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define lfirst(lc)
Definition: pg_list.h:106
#define ShareRowExclusiveLock
Definition: lockdefs.h:42
LOCKMODE AlterTableGetRelOptionsLockLevel(List *defList)
Definition: reloptions.c:1476
#define AccessExclusiveLock
Definition: lockdefs.h:46
ConstrType contype
Definition: parsenodes.h:1824
#define elog
Definition: elog.h:218
Definition: pg_list.h:45
void AlterTableInternal ( Oid  relid,
List cmds,
bool  recurse 
)

Definition at line 2797 of file tablecmds.c.

References AlterTableGetLockLevel(), ATController(), EventTriggerAlterTableRelid(), NULL, and relation_open().

Referenced by AlterTableMoveAll(), DefineVirtualRelation(), and index_check_primary_key().

2798 {
2799  Relation rel;
2800  LOCKMODE lockmode = AlterTableGetLockLevel(cmds);
2801 
2802  rel = relation_open(relid, lockmode);
2803 
2805 
2806  ATController(NULL, rel, cmds, recurse, lockmode);
2807 }
int LOCKMODE
Definition: lockdefs.h:26
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3083
LOCKMODE AlterTableGetLockLevel(List *cmds)
Definition: tablecmds.c:2842
#define NULL
Definition: c.h:226
void EventTriggerAlterTableRelid(Oid objectId)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
Oid AlterTableLookupRelation ( AlterTableStmt stmt,
LOCKMODE  lockmode 
)

Definition at line 2721 of file tablecmds.c.

References AlterTableStmt::missing_ok, RangeVarCallbackForAlterRelation(), RangeVarGetRelidExtended(), and AlterTableStmt::relation.

Referenced by ProcessUtilitySlow().

2722 {
2723  return RangeVarGetRelidExtended(stmt->relation, lockmode, stmt->missing_ok, false,
2725  (void *) stmt);
2726 }
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:11944
RangeVar * relation
Definition: parsenodes.h:1458
Oid AlterTableMoveAll ( AlterTableMoveAllStmt stmt)

Definition at line 9726 of file tablecmds.c.

References AccessExclusiveLock, AccessShareLock, ACL_CREATE, ACL_KIND_CLASS, ACL_KIND_TABLESPACE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, AlterTableInternal(), Anum_pg_class_reltablespace, AT_SetTableSpace, BTEqualStrategyNumber, ConditionalLockRelationOid(), ereport, errcode(), errmsg(), ERROR, EventTriggerAlterTableEnd(), EventTriggerAlterTableStart(), ForwardScanDirection, get_namespace_name(), get_tablespace_name(), get_tablespace_oid(), GETSTRUCT, GetUserId(), GLOBALTABLESPACE_OID, heap_beginscan_catalog(), heap_close, heap_endscan(), heap_getnext(), heap_open(), HeapTupleGetOid, InvalidOid, isAnyTempNamespace(), IsSystemNamespace(), lappend(), lappend_oid(), lfirst_oid, list_member_oid(), LockRelationOid(), makeNode, MyDatabaseTableSpace, AlterTableCmd::name, NameStr, AlterTableMoveAllStmt::new_tablespacename, NIL, NOTICE, AlterTableMoveAllStmt::nowait, NULL, OBJECT_INDEX, OBJECT_MATVIEW, OBJECT_TABLE, ObjectIdGetDatum, AlterTableMoveAllStmt::objtype, OidIsValid, AlterTableMoveAllStmt::orig_tablespacename, pg_class_ownercheck(), pg_tablespace_aclcheck(), PG_TOAST_NAMESPACE, RelationRelationId, RELKIND_INDEX, RELKIND_MATVIEW, RELKIND_RELATION, AlterTableMoveAllStmt::roles, roleSpecsToIds(), ScanKeyInit(), and AlterTableCmd::subtype.

Referenced by ProcessUtilitySlow().

9727 {
9728  List *relations = NIL;
9729  ListCell *l;
9730  ScanKeyData key[1];
9731  Relation rel;
9732  HeapScanDesc scan;
9733  HeapTuple tuple;
9734  Oid orig_tablespaceoid;
9735  Oid new_tablespaceoid;
9736  List *role_oids = roleSpecsToIds(stmt->roles);
9737 
9738  /* Ensure we were not asked to move something we can't */
9739  if (stmt->objtype != OBJECT_TABLE && stmt->objtype != OBJECT_INDEX &&
9740  stmt->objtype != OBJECT_MATVIEW)
9741  ereport(ERROR,
9742  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
9743  errmsg("only tables, indexes, and materialized views exist in tablespaces")));
9744 
9745  /* Get the orig and new tablespace OIDs */
9746  orig_tablespaceoid = get_tablespace_oid(stmt->orig_tablespacename, false);
9747  new_tablespaceoid = get_tablespace_oid(stmt->new_tablespacename, false);
9748 
9749  /* Can't move shared relations in to or out of pg_global */
9750  /* This is also checked by ATExecSetTableSpace, but nice to stop earlier */
9751  if (orig_tablespaceoid == GLOBALTABLESPACE_OID ||
9752  new_tablespaceoid == GLOBALTABLESPACE_OID)
9753  ereport(ERROR,
9754  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
9755  errmsg("cannot move relations in to or out of pg_global tablespace")));
9756 
9757  /*
9758  * Must have CREATE rights on the new tablespace, unless it is the
9759  * database default tablespace (which all users implicitly have CREATE
9760  * rights on).
9761  */
9762  if (OidIsValid(new_tablespaceoid) && new_tablespaceoid != MyDatabaseTableSpace)
9763  {
9764  AclResult aclresult;
9765 
9766  aclresult = pg_tablespace_aclcheck(new_tablespaceoid, GetUserId(),
9767  ACL_CREATE);
9768  if (aclresult != ACLCHECK_OK)
9770  get_tablespace_name(new_tablespaceoid));
9771  }
9772 
9773  /*
9774  * Now that the checks are done, check if we should set either to
9775  * InvalidOid because it is our database's default tablespace.
9776  */
9777  if (orig_tablespaceoid == MyDatabaseTableSpace)
9778  orig_tablespaceoid = InvalidOid;
9779 
9780  if (new_tablespaceoid == MyDatabaseTableSpace)
9781  new_tablespaceoid = InvalidOid;
9782 
9783  /* no-op */
9784  if (orig_tablespaceoid == new_tablespaceoid)
9785  return new_tablespaceoid;
9786 
9787  /*
9788  * Walk the list of objects in the tablespace and move them. This will
9789  * only find objects in our database, of course.
9790  */
9791  ScanKeyInit(&key[0],
9793  BTEqualStrategyNumber, F_OIDEQ,
9794  ObjectIdGetDatum(orig_tablespaceoid));
9795 
9797  scan = heap_beginscan_catalog(rel, 1, key);
9798  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
9799  {
9800  Oid relOid = HeapTupleGetOid(tuple);
9801  Form_pg_class relForm;
9802 
9803  relForm = (Form_pg_class) GETSTRUCT(tuple);
9804 
9805  /*
9806  * Do not move objects in pg_catalog as part of this, if an admin
9807  * really wishes to do so, they can issue the individual ALTER
9808  * commands directly.
9809  *
9810  * Also, explicitly avoid any shared tables, temp tables, or TOAST
9811  * (TOAST will be moved with the main table).
9812  */
9813  if (IsSystemNamespace(relForm->relnamespace) || relForm->relisshared ||
9814  isAnyTempNamespace(relForm->relnamespace) ||
9815  relForm->relnamespace == PG_TOAST_NAMESPACE)
9816  continue;
9817 
9818  /* Only move the object type requested */
9819  if ((stmt->objtype == OBJECT_TABLE &&
9820  relForm->relkind != RELKIND_RELATION) ||
9821  (stmt->objtype == OBJECT_INDEX &&
9822  relForm->relkind != RELKIND_INDEX) ||
9823  (stmt->objtype == OBJECT_MATVIEW &&
9824  relForm->relkind != RELKIND_MATVIEW))
9825  continue;
9826 
9827  /* Check if we are only moving objects owned by certain roles */
9828  if (role_oids != NIL && !list_member_oid(role_oids, relForm->relowner))
9829  continue;
9830 
9831  /*
9832  * Handle permissions-checking here since we are locking the tables
9833  * and also to avoid doing a bunch of work only to fail part-way. Note
9834  * that permissions will also be checked by AlterTableInternal().
9835  *
9836  * Caller must be considered an owner on the table to move it.
9837  */
9838  if (!pg_class_ownercheck(relOid, GetUserId()))
9840  NameStr(relForm->relname));
9841 
9842  if (stmt->nowait &&
9844  ereport(ERROR,
9845  (errcode(ERRCODE_OBJECT_IN_USE),
9846  errmsg("aborting because lock on relation \"%s.%s\" is not available",
9847  get_namespace_name(relForm->relnamespace),
9848  NameStr(relForm->relname))));
9849  else
9851 
9852  /* Add to our list of objects to move */
9853  relations = lappend_oid(relations, relOid);
9854  }
9855 
9856  heap_endscan(scan);
9858 
9859  if (relations == NIL)
9860  ereport(NOTICE,
9861  (errcode(ERRCODE_NO_DATA_FOUND),
9862  errmsg("no matching relations in tablespace \"%s\" found",
9863  orig_tablespaceoid == InvalidOid ? "(database default)" :
9864  get_tablespace_name(orig_tablespaceoid))));
9865 
9866  /* Everything is locked, loop through and move all of the relations. */
9867  foreach(l, relations)
9868  {
9869  List *cmds = NIL;
9871 
9872  cmd->subtype = AT_SetTableSpace;
9873  cmd->name = stmt->new_tablespacename;
9874 
9875  cmds = lappend(cmds, cmd);
9876 
9878  /* OID is set by AlterTableInternal */
9879  AlterTableInternal(lfirst_oid(l), cmds, false);
9881  }
9882 
9883  return new_tablespaceoid;
9884 }
#define NIL
Definition: pg_list.h:69
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:138
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1384
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4479
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1592
Oid GetUserId(void)
Definition: miscinit.c:282
#define RelationRelationId
Definition: pg_class.h:29
#define Anum_pg_class_reltablespace
Definition: pg_class.h:107
#define RELKIND_MATVIEW
Definition: pg_class.h:162
#define AccessShareLock
Definition: lockdefs.h:36
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
Definition: nodes.h:491
int errcode(int sqlerrcode)
Definition: elog.c:575
AlterTableType subtype
Definition: parsenodes.h:1540
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_TOAST_NAMESPACE
Definition: pg_namespace.h:74
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:530
Oid MyDatabaseTableSpace
Definition: globals.c:76
void EventTriggerAlterTableStart(Node *parsetree)
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:73
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3391
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1413
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
AclResult
Definition: acl.h:169
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1792
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1298
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:161
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
#define makeNode(_type_)
Definition: nodes.h:539
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1379
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define NULL
Definition: c.h:226
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4529
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
void AlterTableInternal(Oid relid, List *cmds, bool recurse)
Definition: tablecmds.c:2797
#define AccessExclusiveLock
Definition: lockdefs.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1430
#define NameStr(name)
Definition: c.h:494
#define RELKIND_INDEX
Definition: pg_class.h:156
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
bool isAnyTempNamespace(Oid namespaceId)
Definition: namespace.c:3005
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:670
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
#define RELKIND_RELATION
Definition: pg_class.h:155
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:108
void EventTriggerAlterTableEnd(void)
ObjectAddress AlterTableNamespace ( AlterObjectSchemaStmt stmt,
Oid oldschema 
)

Definition at line 11359 of file tablecmds.c.

References AccessExclusiveLock, AlterTableNamespaceInternal(), CheckSetNamespace(), ereport, errcode(), errdetail(), errmsg(), ERROR, free_object_addresses(), get_rel_name(), InvalidObjectAddress, makeRangeVar(), AlterObjectSchemaStmt::missing_ok, new_object_addresses(), AlterObjectSchemaStmt::newschema, NoLock, NOTICE, NULL, ObjectAddressSet, OidIsValid, RangeVarCallbackForAlterRelation(), RangeVarGetAndCheckCreationNamespace(), RangeVarGetRelidExtended(), RelationData::rd_rel, AlterObjectSchemaStmt::relation, relation_close(), relation_open(), RelationGetNamespace, RelationGetRelationName, RelationRelationId, RELKIND_SEQUENCE, RangeVar::relname, and sequenceIsOwned().

Referenced by ExecAlterObjectSchemaStmt().

11360 {
11361  Relation rel;
11362  Oid relid;
11363  Oid oldNspOid;
11364  Oid nspOid;
11365  RangeVar *newrv;
11366  ObjectAddresses *objsMoved;
11367  ObjectAddress myself;
11368 
11370  stmt->missing_ok, false,
11372  (void *) stmt);
11373 
11374  if (!OidIsValid(relid))
11375  {
11376  ereport(NOTICE,
11377  (errmsg("relation \"%s\" does not exist, skipping",
11378  stmt->relation->relname)));
11379  return InvalidObjectAddress;
11380  }
11381 
11382  rel = relation_open(relid, NoLock);
11383 
11384  oldNspOid = RelationGetNamespace(rel);
11385 
11386  /* If it's an owned sequence, disallow moving it by itself. */
11387  if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
11388  {
11389  Oid tableId;
11390  int32 colId;
11391 
11392  if (sequenceIsOwned(relid, &tableId, &colId))
11393  ereport(ERROR,
11394  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11395  errmsg("cannot move an owned sequence into another schema"),
11396  errdetail("Sequence \"%s\" is linked to table \"%s\".",
11398  get_rel_name(tableId))));
11399  }
11400 
11401  /* Get and lock schema OID and check its permissions. */
11402  newrv = makeRangeVar(stmt->newschema, RelationGetRelationName(rel), -1);
11404 
11405  /* common checks on switching namespaces */
11406  CheckSetNamespace(oldNspOid, nspOid);
11407 
11408  objsMoved = new_object_addresses();
11409  AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
11410  free_object_addresses(objsMoved);
11411 
11412  ObjectAddressSet(myself, RelationRelationId, relid);
11413 
11414  if (oldschema)
11415  *oldschema = oldNspOid;
11416 
11417  /* close rel, but keep lock until commit */
11418  relation_close(rel, NoLock);
11419 
11420  return myself;
11421 }
bool sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
Definition: pg_depend.c:503
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
#define RelationRelationId
Definition: pg_class.h:29
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1274
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2043
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2314
Form_pg_class rd_rel
Definition: rel.h:83
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:530
signed int int32
Definition: c.h:253
char * relname
Definition: primnodes.h:74
#define ERROR
Definition: elog.h:43
void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid, ObjectAddresses *objsMoved)
Definition: tablecmds.c:11429
#define NoLock
Definition: lockdefs.h:34
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:11944
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:361
#define ereport(elevel, rest)
Definition: elog.h:122
void CheckSetNamespace(Oid oldNspOid, Oid nspOid)
Definition: namespace.c:2777
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:522
#define NOTICE
Definition: elog.h:37
#define NULL
Definition: c.h:226
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
#define RELKIND_SEQUENCE
Definition: pg_class.h:157
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1694
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:419
#define RelationGetNamespace(relation)
Definition: rel.h:368
void AlterTableNamespaceInternal ( Relation  rel,
Oid  oldNspOid,
Oid  nspOid,
ObjectAddresses objsMoved 
)

Definition at line 11429 of file tablecmds.c.

References AccessExclusiveLock, AlterConstraintNamespaces(), AlterIndexNamespaces(), AlterRelationNamespaceInternal(), AlterSeqNamespaces(), AlterTypeNamespaceInternal(), Assert, heap_close, heap_open(), NULL, RelationData::rd_rel, RelationGetRelid, RelationRelationId, RELKIND_MATVIEW, RELKIND_RELATION, and RowExclusiveLock.

Referenced by AlterObjectNamespace_oid(), and AlterTableNamespace().

11431 {
11432  Relation classRel;
11433 
11434  Assert(objsMoved != NULL);
11435 
11436  /* OK, modify the pg_class row and pg_depend entry */
11438 
11439  AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid,
11440  nspOid, true, objsMoved);
11441 
11442  /* Fix the table's row type too */
11443  AlterTypeNamespaceInternal(rel->rd_rel->reltype,
11444  nspOid, false, false, objsMoved);
11445 
11446  /* Fix other dependent stuff */
11447  if (rel->rd_rel->relkind == RELKIND_RELATION ||
11448  rel->rd_rel->relkind == RELKIND_MATVIEW)
11449  {
11450  AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
11451  AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
11452  objsMoved, AccessExclusiveLock);
11453  AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
11454  false, objsMoved);
11455  }
11456 
11457  heap_close(classRel, RowExclusiveLock);
11458 }
#define RelationRelationId
Definition: pg_class.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:162
Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses *objsMoved)
Definition: typecmds.c:3474
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:83
static void AlterIndexNamespaces(Relation classRel, Relation rel, Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved)
Definition: tablecmds.c:11537
void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId, Oid newNspId, bool isType, ObjectAddresses *objsMoved)
static void AlterSeqNamespaces(Relation classRel, Relation rel, Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved, LOCKMODE lockmode)
Definition: tablecmds.c:11582
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1298
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:667
void AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Oid oldNspOid, Oid newNspOid, bool hasDependEntry, ObjectAddresses *objsMoved)
Definition: tablecmds.c:11466
#define AccessExclusiveLock
Definition: lockdefs.h:46
#define RELKIND_RELATION
Definition: pg_class.h:155
#define RelationGetRelid(relation)
Definition: rel.h:341
void AtEOSubXact_on_commit_actions ( bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)

Definition at line 11834 of file tablecmds.c.

References OnCommitItem::creating_subid, OnCommitItem::deleting_subid, InvalidSubTransactionId, lfirst, list_delete_cell(), list_head(), lnext, NULL, and pfree().

Referenced by AbortSubTransaction(), and CommitSubTransaction().

11836 {
11837  ListCell *cur_item;
11838  ListCell *prev_item;
11839 
11840  prev_item = NULL;
11841  cur_item = list_head(on_commits);
11842 
11843  while (cur_item != NULL)
11844  {
11845  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
11846 
11847  if (!isCommit && oc->creating_subid == mySubid)
11848  {
11849  /* cur_item must be removed */
11850  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
11851  pfree(oc);
11852  if (prev_item)
11853  cur_item = lnext(prev_item);
11854  else
11855  cur_item = list_head(on_commits);
11856  }
11857  else
11858  {
11859  /* cur_item must be preserved */
11860  if (oc->creating_subid == mySubid)
11861  oc->creating_subid = parentSubid;
11862  if (oc->deleting_subid == mySubid)
11863  oc->deleting_subid = isCommit ? parentSubid : InvalidSubTransactionId;
11864  prev_item = cur_item;
11865  cur_item = lnext(prev_item);
11866  }
11867  }
11868 }
SubTransactionId creating_subid
Definition: tablecmds.c:115
void pfree(void *pointer)
Definition: mcxt.c:995
static List * on_commits
Definition: tablecmds.c:119
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
List * list_delete_cell(List *list, ListCell *cell, ListCell *prev)
Definition: list.c:528
SubTransactionId deleting_subid
Definition: tablecmds.c:116
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:399
void AtEOXact_on_commit_actions ( bool  isCommit)

Definition at line 11792 of file tablecmds.c.

References OnCommitItem::creating_subid, OnCommitItem::deleting_subid, InvalidSubTransactionId, lfirst, list_delete_cell(), list_head(), lnext, NULL, and pfree().

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

11793 {
11794  ListCell *cur_item;
11795  ListCell *prev_item;
11796 
11797  prev_item = NULL;
11798  cur_item = list_head(on_commits);
11799 
11800  while (cur_item != NULL)
11801  {
11802  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
11803 
11804  if (isCommit ? oc->deleting_subid != InvalidSubTransactionId :
11806  {
11807  /* cur_item must be removed */
11808  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
11809  pfree(oc);
11810  if (prev_item)
11811  cur_item = lnext(prev_item);
11812  else
11813  cur_item = list_head(on_commits);
11814  }
11815  else
11816  {
11817  /* cur_item must be preserved */
11820  prev_item = cur_item;
11821  cur_item = lnext(prev_item);
11822  }
11823  }
11824 }
SubTransactionId creating_subid
Definition: tablecmds.c:115
void pfree(void *pointer)
Definition: mcxt.c:995
static List * on_commits
Definition: tablecmds.c:119
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
List * list_delete_cell(List *list, ListCell *cell, ListCell *prev)
Definition: list.c:528
SubTransactionId deleting_subid
Definition: tablecmds.c:116
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:399
void ATExecChangeOwner ( Oid  relationOid,
Oid  newOwnerId,
bool  recursing,
LOCKMODE  lockmode 
)

Definition at line 8911 of file tablecmds.c.

References ACL_CREATE, ACL_KIND_CLASS, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, aclnewowner(), AlterTypeOwnerInternal(), Anum_pg_class_relacl, Anum_pg_class_relowner, ATExecChangeOwner(), CatalogUpdateIndexes(), change_owner_fix_column_acls(), change_owner_recurse_to_sequences(), changeDependencyOnOwner(), check_is_member_of_role(), DatumGetAclP, elog, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, get_namespace_name(), get_rel_name(), GETSTRUCT, GetUserId(), heap_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleIsValid, i, InvalidOid, InvokeObjectPostAlterHook, lfirst_oid, list_free(), NameStr, Natts_pg_class, NoLock, ObjectIdGetDatum, pg_class_ownercheck(), pg_namespace_aclcheck(), PointerGetDatum, relation_close(), relation_open(), RelationGetDescr, RelationGetIndexList(), RelationGetRelationName, RelationRelationId, ReleaseSysCache(), RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_INDEX, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RELKIND_VIEW, RELOID, RowExclusiveLock, SearchSysCache1, sequenceIsOwned(), simple_heap_update(), superuser(), SysCacheGetAttr(), HeapTupleData::t_self, and WARNING.

Referenced by AlterTypeOwner_oid(), ATExecChangeOwner(), ATExecCmd(), change_owner_recurse_to_sequences(), and shdepReassignOwned().

8912 {
8913  Relation target_rel;
8914  Relation class_rel;
8915  HeapTuple tuple;
8916  Form_pg_class tuple_class;
8917 
8918  /*
8919  * Get exclusive lock till end of transaction on the target table. Use
8920  * relation_open so that we can work on indexes and sequences.
8921  */
8922  target_rel = relation_open(relationOid, lockmode);
8923 
8924  /* Get its pg_class tuple, too */
8926 
8927  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationOid));
8928  if (!HeapTupleIsValid(tuple))
8929  elog(ERROR, "cache lookup failed for relation %u", relationOid);
8930  tuple_class = (Form_pg_class) GETSTRUCT(tuple);
8931 
8932  /* Can we change the ownership of this tuple? */
8933  switch (tuple_class->relkind)
8934  {
8935  case RELKIND_RELATION:
8936  case RELKIND_VIEW:
8937  case RELKIND_MATVIEW:
8938  case RELKIND_FOREIGN_TABLE:
8939  /* ok to change owner */
8940  break;
8941  case RELKIND_INDEX:
8942  if (!recursing)
8943  {
8944  /*
8945  * Because ALTER INDEX OWNER used to be allowed, and in fact
8946  * is generated by old versions of pg_dump, we give a warning
8947  * and do nothing rather than erroring out. Also, to avoid
8948  * unnecessary chatter while restoring those old dumps, say
8949  * nothing at all if the command would be a no-op anyway.
8950  */
8951  if (tuple_class->relowner != newOwnerId)
8952  ereport(WARNING,
8953  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8954  errmsg("cannot change owner of index \"%s\"",
8955  NameStr(tuple_class->relname)),
8956  errhint("Change the ownership of the index's table, instead.")));
8957  /* quick hack to exit via the no-op path */
8958  newOwnerId = tuple_class->relowner;
8959  }
8960  break;
8961  case RELKIND_SEQUENCE:
8962  if (!recursing &&
8963  tuple_class->relowner != newOwnerId)
8964  {
8965  /* if it's an owned sequence, disallow changing it by itself */
8966  Oid tableId;
8967  int32 colId;
8968 
8969  if (sequenceIsOwned(relationOid, &tableId, &colId))
8970  ereport(ERROR,
8971  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8972  errmsg("cannot change owner of sequence \"%s\"",
8973  NameStr(tuple_class->relname)),
8974  errdetail("Sequence \"%s\" is linked to table \"%s\".",
8975  NameStr(tuple_class->relname),
8976  get_rel_name(tableId))));
8977  }
8978  break;
8980  if (recursing)
8981  break;
8982  ereport(ERROR,
8983  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8984  errmsg("\"%s\" is a composite type",
8985  NameStr(tuple_class->relname)),
8986  errhint("Use ALTER TYPE instead.")));
8987  break;
8988  case RELKIND_TOASTVALUE:
8989  if (recursing)
8990  break;
8991  /* FALL THRU */
8992  default:
8993  ereport(ERROR,
8994  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8995  errmsg("\"%s\" is not a table, view, sequence, or foreign table",
8996  NameStr(tuple_class->relname))));
8997  }
8998 
8999  /*
9000  * If the new owner is the same as the existing owner, consider the
9001  * command to have succeeded. This is for dump restoration purposes.
9002  */
9003  if (tuple_class->relowner != newOwnerId)
9004  {
9005  Datum repl_val[Natts_pg_class];
9006  bool repl_null[Natts_pg_class];
9007  bool repl_repl[Natts_pg_class];
9008  Acl *newAcl;
9009  Datum aclDatum;
9010  bool isNull;
9011  HeapTuple newtuple;
9012 
9013  /* skip permission checks when recursing to index or toast table */
9014  if (!recursing)
9015  {
9016  /* Superusers can always do it */
9017  if (!superuser())
9018  {
9019  Oid namespaceOid = tuple_class->relnamespace;
9020  AclResult aclresult;
9021 
9022  /* Otherwise, must be owner of the existing object */
9023  if (!pg_class_ownercheck(relationOid, GetUserId()))
9025  RelationGetRelationName(target_rel));
9026 
9027  /* Must be able to become new owner */
9028  check_is_member_of_role(GetUserId(), newOwnerId);
9029 
9030  /* New owner must have CREATE privilege on namespace */
9031  aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
9032  ACL_CREATE);
9033  if (aclresult != ACLCHECK_OK)
9035  get_namespace_name(namespaceOid));
9036  }
9037  }
9038 
9039  memset(repl_null, false, sizeof(repl_null));
9040  memset(repl_repl, false, sizeof(repl_repl));
9041 
9042  repl_repl[Anum_pg_class_relowner - 1] = true;
9043  repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId);
9044 
9045  /*
9046  * Determine the modified ACL for the new owner. This is only
9047  * necessary when the ACL is non-null.
9048  */
9049  aclDatum = SysCacheGetAttr(RELOID, tuple,
9051  &isNull);
9052  if (!isNull)
9053  {
9054  newAcl = aclnewowner(DatumGetAclP(aclDatum),
9055  tuple_class->relowner, newOwnerId);
9056  repl_repl[Anum_pg_class_relacl - 1] = true;
9057  repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl);
9058  }
9059 
9060  newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl);
9061 
9062  simple_heap_update(class_rel, &newtuple->t_self, newtuple);
9063  CatalogUpdateIndexes(class_rel, newtuple);
9064 
9065  heap_freetuple(newtuple);
9066 
9067  /*
9068  * We must similarly update any per-column ACLs to reflect the new
9069  * owner; for neatness reasons that's split out as a subroutine.
9070  */
9071  change_owner_fix_column_acls(relationOid,
9072  tuple_class->relowner,
9073  newOwnerId);
9074 
9075  /*
9076  * Update owner dependency reference, if any. A composite type has
9077  * none, because it's tracked for the pg_type entry instead of here;
9078  * indexes and TOAST tables don't have their own entries either.
9079  */
9080  if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE &&
9081  tuple_class->relkind != RELKIND_INDEX &&
9082  tuple_class->relkind != RELKIND_TOASTVALUE)
9084  newOwnerId);
9085 
9086  /*
9087  * Also change the ownership of the table's row type, if it has one
9088  */
9089  if (tuple_class->relkind != RELKIND_INDEX)
9090  AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId);
9091 
9092  /*
9093  * If we are operating on a table or materialized view, also change
9094  * the ownership of any indexes and sequences that belong to the
9095  * relation, as well as its toast table (if it has one).
9096  */
9097  if (tuple_class->relkind == RELKIND_RELATION ||
9098  tuple_class->relkind == RELKIND_MATVIEW ||
9099  tuple_class->relkind == RELKIND_TOASTVALUE)
9100  {
9101  List *index_oid_list;
9102  ListCell *i;
9103 
9104  /* Find all the indexes belonging to this relation */
9105  index_oid_list = RelationGetIndexList(target_rel);
9106 
9107  /* For each index, recursively change its ownership */
9108  foreach(i, index_oid_list)
9109  ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
9110 
9111  list_free(index_oid_list);
9112  }
9113 
9114  if (tuple_class->relkind == RELKIND_RELATION ||
9115  tuple_class->relkind == RELKIND_MATVIEW)
9116  {
9117  /* If it has a toast table, recurse to change its ownership */
9118  if (tuple_class->reltoastrelid != InvalidOid)
9119  ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerId,
9120  true, lockmode);
9121 
9122  /* If it has dependent sequences, recurse to change them too */
9123  change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
9124  }
9125  }
9126 
9128 
9129  ReleaseSysCache(tuple);
9130  heap_close(class_rel, RowExclusiveLock);
9131  relation_close(target_rel, NoLock);
9132 }
#define Natts_pg_class
Definition: pg_class.h:99
bool sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
Definition: pg_depend.c:503
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
#define Anum_pg_class_relacl
Definition: pg_class.h:129
#define RelationGetDescr(relation)
Definition: rel.h:353
Oid GetUserId(void)
Definition: miscinit.c:282
#define DatumGetAclP(X)
Definition: acl.h:112
#define PointerGetDatum(X)
Definition: postgres.h:564
#define RelationRelationId
Definition: pg_class.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:162
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1274
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
Definition: typecmds.c:3342
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1306
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4467
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:160
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
signed int int32
Definition: c.h:253
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:306
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:73
ItemPointerData t_self
Definition: htup.h:65
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
#define NoLock
Definition: lockdefs.h:34
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3391
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:361
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:161
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4876
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
Definition: tablecmds.c:8911
#define WARNING
Definition: elog.h:40
#define RELKIND_TOASTVALUE
Definition: pg_class.h:158
AclResult
Definition: acl.h:169
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:990
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1152
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1298
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
Definition: indexing.c:157
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4529
static void change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lockmode)
Definition: tablecmds.c:9207
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
Definition: heapam.c:4422
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:3843
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
static void change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId)
Definition: tablecmds.c:9141
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_VIEW
Definition: pg_class.h:159
void list_free(List *list)
Definition: list.c:1133
int i
#define NameStr(name)
Definition: c.h:494
#define RELKIND_INDEX
Definition: pg_class.h:156
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
#define elog
Definition: elog.h:218
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:791
#define RELKIND_RELATION
Definition: pg_class.h:155
#define RELKIND_SEQUENCE
Definition: pg_class.h:157
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1694
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1035
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define Anum_pg_class_relowner
Definition: pg_class.h:104
void check_of_type ( HeapTuple  typetuple)

Definition at line 4641 of file tablecmds.c.

References AccessShareLock, Assert, ereport, errcode(), errmsg(), ERROR, format_type_be(), GETSTRUCT, HeapTupleGetOid, NoLock, OidIsValid, RelationData::rd_rel, relation_close(), relation_open(), RELKIND_COMPOSITE_TYPE, and TYPTYPE_COMPOSITE.

Referenced by ATExecAddOf(), and transformOfType().

4642 {
4643  Form_pg_type typ = (Form_pg_type) GETSTRUCT(typetuple);
4644  bool typeOk = false;
4645 
4646  if (typ->typtype == TYPTYPE_COMPOSITE)
4647  {
4648  Relation typeRelation;
4649 
4650  Assert(OidIsValid(typ->typrelid));
4651  typeRelation = relation_open(typ->typrelid, AccessShareLock);
4652  typeOk = (typeRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
4653 
4654  /*
4655  * Close the parent rel, but keep our AccessShareLock on it until xact
4656  * commit. That will prevent someone else from deleting or ALTERing
4657  * the type before the typed table creation/conversion commits.
4658  */
4659  relation_close(typeRelation, NoLock);
4660  }
4661  if (!typeOk)
4662  ereport(ERROR,
4663  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4664  errmsg("type %s is not a composite type",
4665  format_type_be(HeapTupleGetOid(typetuple)))));
4666 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:709
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1274
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
Form_pg_class rd_rel
Definition: rel.h:83
#define OidIsValid(objectId)
Definition: c.h:530
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:160
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define ereport(elevel, rest)
Definition: elog.h:122
#define Assert(condition)
Definition: c.h:667
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:670
void CheckTableNotInUse ( Relation  rel,
const char *  stmt 
)

Definition at line 2692 of file tablecmds.c.

References AfterTriggerPendingOnRel(), ereport, errcode(), errmsg(), ERROR, RelationData::rd_isnailed, RelationData::rd_refcnt, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, and RELKIND_INDEX.

Referenced by AlterTable(), ATAddCheckConstraint(), ATExecAddColumn(), ATExecDropColumn(), ATExecDropConstraint(), ATSimpleRecursion(), ATTypedTableRecursion(), cluster_rel(), DefineVirtualRelation(), ExecRefreshMatView(), heap_drop_with_catalog(), index_drop(), reindex_index(), and truncate_check_rel().

2693 {
2694  int expected_refcnt;
2695 
2696  expected_refcnt = rel->rd_isnailed ? 2 : 1;
2697  if (rel->rd_refcnt != expected_refcnt)
2698  ereport(ERROR,
2699  (errcode(ERRCODE_OBJECT_IN_USE),
2700  /* translator: first %s is a SQL command, eg ALTER TABLE */
2701  errmsg("cannot %s \"%s\" because "
2702  "it is being used by active queries in this session",
2703  stmt, RelationGetRelationName(rel))));
2704 
2705  if (rel->rd_rel->relkind != RELKIND_INDEX &&
2707  ereport(ERROR,
2708  (errcode(ERRCODE_OBJECT_IN_USE),
2709  /* translator: first %s is a SQL command, eg ALTER TABLE */
2710  errmsg("cannot %s \"%s\" because "
2711  "it has pending trigger events",
2712  stmt, RelationGetRelationName(rel))));
2713 }
bool rd_isnailed
Definition: rel.h:61
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:83
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:361
#define ereport(elevel, rest)
Definition: elog.h:122
bool AfterTriggerPendingOnRel(Oid relid)
Definition: trigger.c:4753
int errmsg(const char *fmt,...)
Definition: elog.c:797
int rd_refcnt
Definition: rel.h:58
#define RELKIND_INDEX
Definition: pg_class.h:156
#define RelationGetRelid(relation)
Definition: rel.h:341
ObjectAddress DefineRelation ( CreateStmt stmt,
char  relkind,
Oid  ownerId,
ObjectAddress typaddress 
)

Definition at line 457 of file tablecmds.c.

References AccessExclusiveLock, ACL_CREATE, ACL_KIND_TABLESPACE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_OK, AddRelationNewConstraints(), allowSystemTableMods, Assert, RawColumnDefault::attnum, CookedConstraint::attnum, tupleDesc::attrs, BuildDescForRelation(), CommandCounterIncrement(), CookedConstraint::conoid, CONSTR_DEFAULT, CreateStmt::constraints, CookedConstraint::contype, ColumnDef::cooked_default, ereport, errcode(), errmsg(), ERROR, CookedConstraint::expr, get_tablespace_name(), get_tablespace_oid(), GetDefaultTablespace(), GetUserId(), GLOBALTABLESPACE_OID, heap_create_with_catalog(), HEAP_RELOPT_NAMESPACES, heap_reloptions(), CookedConstraint::inhcount, CreateStmt::inhRelations, InSecurityRestrictedOperation(), interpretOidsOption(), InvalidOid, CookedConstraint::is_local, CookedConstraint::is_no_inherit, lappend(), lfirst, list_concat(), MergeAttributes(), MyDatabaseTableSpace, CookedConstraint::name, NAMEDATALEN, NIL, NoLock, NULL, ObjectAddressSet, CreateStmt::ofTypename, OidIsValid, CreateStmt::oncommit, ONCOMMIT_NOOP, CreateStmt::options, palloc(), pg_tablespace_aclcheck(), pg_type_aclcheck(), RangeVarGetAndCheckCreationNamespace(), RawColumnDefault::raw_default, ColumnDef::raw_default, CreateStmt::relation, relation_close(), relation_open(), RelationRelationId, RELKIND_RELATION, RELKIND_VIEW, RangeVar::relname, relname(), RangeVar::relpersistence, RELPERSISTENCE_TEMP, CookedConstraint::skip_validation, StoreCatalogInheritance(), StrNCpy, CreateStmt::tableElts, CreateStmt::tablespacename, tupleDesc::tdhasoid, transformRelOptions(), typenameTypeId(), and view_reloptions().

Referenced by DefineCompositeType(), DefineSequence(), DefineVirtualRelation(), intorel_startup(), and ProcessUtilitySlow().

459 {
460  char relname[NAMEDATALEN];
461  Oid namespaceId;
462  List *schema = stmt->tableElts;
463  Oid relationId;
464  Oid tablespaceId;
465  Relation rel;
467  List *inheritOids;
468  List *old_constraints;
469  bool localHasOids;
470  int parentOidCount;
471  List *rawDefaults;
472  List *cookedDefaults;
473  Datum reloptions;
474  ListCell *listptr;
475  AttrNumber attnum;
476  static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
477  Oid ofTypeId;
478  ObjectAddress address;
479 
480  /*
481  * Truncate relname to appropriate length (probably a waste of time, as
482  * parser should have done this already).
483  */
484  StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);
485 
486  /*
487  * Check consistency of arguments
488  */
489  if (stmt->oncommit != ONCOMMIT_NOOP
491  ereport(ERROR,
492  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
493  errmsg("ON COMMIT can only be used on temporary tables")));
494 
495  /*
496  * Look up the namespace in which we are supposed to create the relation,
497  * check we have permission to create there, lock it against concurrent
498  * drop, and mark stmt->relation as RELPERSISTENCE_TEMP if a temporary
499  * namespace is selected.
500  */
501  namespaceId =
503 
504  /*
505  * Security check: disallow creating temp tables from security-restricted
506  * code. This is needed because calling code might not expect untrusted
507  * tables to appear in pg_temp at the front of its search path.
508  */
511  ereport(ERROR,
512  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
513  errmsg("cannot create temporary table within security-restricted operation")));
514 
515  /*
516  * Select tablespace to use. If not specified, use default tablespace
517  * (which may in turn default to database's default).
518  */
519  if (stmt->tablespacename)
520  {
521  tablespaceId = get_tablespace_oid(stmt->tablespacename, false);
522  }
523  else
524  {
525  tablespaceId = GetDefaultTablespace(stmt->relation->relpersistence);
526  /* note InvalidOid is OK in this case */
527  }
528 
529  /* Check permissions except when using database's default */
530  if (OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
531  {
532  AclResult aclresult;
533 
534  aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),
535  ACL_CREATE);
536  if (aclresult != ACLCHECK_OK)
538  get_tablespace_name(tablespaceId));
539  }
540 
541  /* In all cases disallow placing user relations in pg_global */
542  if (tablespaceId == GLOBALTABLESPACE_OID)
543  ereport(ERROR,
544  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
545  errmsg("only shared relations can be placed in pg_global tablespace")));
546 
547  /* Identify user ID that will own the table */
548  if (!OidIsValid(ownerId))
549  ownerId = GetUserId();
550 
551  /*
552  * Parse and validate reloptions, if any.
553  */
554  reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
555  true, false);
556 
557  if (relkind == RELKIND_VIEW)
558  (void) view_reloptions(reloptions, true);
559  else
560  (void) heap_reloptions(relkind, reloptions, true);
561 
562  if (stmt->ofTypename)
563  {
564  AclResult aclresult;
565 
566  ofTypeId = typenameTypeId(NULL, stmt->ofTypename);
567 
568  aclresult = pg_type_aclcheck(ofTypeId, GetUserId(), ACL_USAGE);
569  if (aclresult != ACLCHECK_OK)
570  aclcheck_error_type(aclresult, ofTypeId);
571  }
572  else
573  ofTypeId = InvalidOid;
574 
575  /*
576  * Look up inheritance ancestors and generate relation schema, including
577  * inherited attributes.
578  */
579  schema = MergeAttributes(schema, stmt->inhRelations,
580  stmt->relation->relpersistence,
581  &inheritOids, &old_constraints, &parentOidCount);
582 
583  /*
584  * Create a tuple descriptor from the relation schema. Note that this
585  * deals with column names, types, and NOT NULL constraints, but not
586  * default values or CHECK constraints; we handle those below.
587  */
588  descriptor = BuildDescForRelation(schema);
589 
590  /*
591  * Notice that we allow OIDs here only for plain tables, even though some
592  * other relkinds can support them. This is necessary because the
593  * default_with_oids GUC must apply only to plain tables and not any other
594  * relkind; doing otherwise would break existing pg_dump files. We could
595  * allow explicit "WITH OIDS" while not allowing default_with_oids to
596  * affect other relkinds, but it would complicate interpretOidsOption().
597  */
598  localHasOids = interpretOidsOption(stmt->options,
599  (relkind == RELKIND_RELATION));
600  descriptor->tdhasoid = (localHasOids || parentOidCount > 0);
601 
602  /*
603  * Find columns with default values and prepare for insertion of the
604  * defaults. Pre-cooked (that is, inherited) defaults go into a list of
605  * CookedConstraint structs that we'll pass to heap_create_with_catalog,
606  * while raw defaults go into a list of RawColumnDefault structs that will
607  * be processed by AddRelationNewConstraints. (We can't deal with raw
608  * expressions until we can do transformExpr.)
609  *
610  * We can set the atthasdef flags now in the tuple descriptor; this just
611  * saves StoreAttrDefault from having to do an immediate update of the
612  * pg_attribute rows.
613  */
614  rawDefaults = NIL;
615  cookedDefaults = NIL;
616  attnum = 0;
617 
618  foreach(listptr, schema)
619  {
620  ColumnDef *colDef = lfirst(listptr);
621 
622  attnum++;
623 
624  if (colDef->raw_default != NULL)
625  {
626  RawColumnDefault *rawEnt;
627 
628  Assert(colDef->cooked_default == NULL);
629 
630  rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
631  rawEnt->attnum = attnum;
632  rawEnt->raw_default = colDef->raw_default;
633  rawDefaults = lappend(rawDefaults, rawEnt);
634  descriptor->attrs[attnum - 1]->atthasdef = true;
635  }
636  else if (colDef->cooked_default != NULL)
637  {
638  CookedConstraint *cooked;
639 
640  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
641  cooked->contype = CONSTR_DEFAULT;
642  cooked->conoid = InvalidOid; /* until created */
643  cooked->name = NULL;
644  cooked->attnum = attnum;
645  cooked->expr = colDef->cooked_default;
646  cooked->skip_validation = false;
647  cooked->is_local = true; /* not used for defaults */
648  cooked->inhcount = 0; /* ditto */
649  cooked->is_no_inherit = false;
650  cookedDefaults = lappend(cookedDefaults, cooked);
651  descriptor->attrs[attnum - 1]->atthasdef = true;
652  }
653  }
654 
655  /*
656  * Create the relation. Inherited defaults and constraints are passed in
657  * for immediate handling --- since they don't need parsing, they can be
658  * stored immediately.
659  */
660  relationId = heap_create_with_catalog(relname,
661  namespaceId,
662  tablespaceId,
663  InvalidOid,
664  InvalidOid,
665  ofTypeId,
666  ownerId,
667  descriptor,
668  list_concat(cookedDefaults,
669  old_constraints),
670  relkind,
671  stmt->relation->relpersistence,
672  false,
673  false,
674  localHasOids,
675  parentOidCount,
676  stmt->oncommit,
677  reloptions,
678  true,
680  false,
681  typaddress);
682 
683  /* Store inheritance information for new rel. */
684  StoreCatalogInheritance(relationId, inheritOids);
685 
686  /*
687  * We must bump the command counter to make the newly-created relation
688  * tuple visible for opening.
689  */
691 
692  /*
693  * Open the new relation and acquire exclusive lock on it. This isn't
694  * really necessary for locking out other backends (since they can't see
695  * the new rel anyway until we commit), but it keeps the lock manager from
696  * complaining about deadlock risks.
697  */
698  rel = relation_open(relationId, AccessExclusiveLock);
699 
700  /*
701  * Now add any newly specified column default values and CHECK constraints
702  * to the new relation. These are passed to us in the form of raw
703  * parsetrees; we need to transform them to executable expression trees
704  * before they can be added. The most convenient way to do that is to
705  * apply the parser's transformExpr routine, but transformExpr doesn't
706  * work unless we have a pre-existing relation. So, the transformation has
707  * to be postponed to this final step of CREATE TABLE.
708  */
709  if (rawDefaults || stmt->constraints)
710  AddRelationNewConstraints(rel, rawDefaults, stmt->constraints,
711  true, true, false);
712 
713  ObjectAddressSet(address, RelationRelationId, relationId);
714 
715  /*
716  * Clean up. We keep lock on new relation (although it shouldn't be
717  * visible to anyone else anyway, until commit).
718  */
719  relation_close(rel, NoLock);
720 
721  return address;
722 }
RangeVar * relation
Definition: parsenodes.h:1749
bytea * heap_reloptions(char relkind, Datum reloptions, bool validate)
Definition: reloptions.c:1360
#define NIL
Definition: pg_list.h:69
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1384
OnCommitAction oncommit
Definition: parsenodes.h:1756
List * inhRelations
Definition: parsenodes.h:1751
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4479
static void StoreCatalogInheritance(Oid relationId, List *supers)
Definition: tablecmds.c:1976
bool is_no_inherit
Definition: heap.h:38
bool tdhasoid
Definition: tupdesc.h:79
AttrNumber attnum
Definition: heap.h:24
Oid GetUserId(void)
Definition: miscinit.c:282
#define RelationRelationId
Definition: pg_class.h:29
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1274
List * list_concat(List *list1, List *list2)
Definition: list.c:321
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:530
Oid GetDefaultTablespace(char relpersistence)
Definition: tablespace.c:1115
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3449
Oid MyDatabaseTableSpace
Definition: globals.c:76
bytea * view_reloptions(Datum reloptions, bool validate)
Definition: reloptions.c:1328
static char * relname(char const *dir, char const *base)
Definition: zic.c:755
List * constraints
Definition: parsenodes.h:1754
#define NAMEDATALEN
Node * cooked_default
Definition: parsenodes.h:596
char * relname
Definition: primnodes.h:74
AttrNumber attnum
Definition: heap.h:33
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:73
int inhcount
Definition: heap.h:37
#define NoLock
Definition: lockdefs.h:34
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3391
List * options
Definition: parsenodes.h:1755
Node * raw_default
Definition: heap.h:25
#define ACL_USAGE
Definition: parsenodes.h:71
bool skip_validation
Definition: heap.h:35
#define HEAP_RELOPT_NAMESPACES
Definition: reloptions.h:58
ConstrType contype
Definition: heap.h:30
#define ereport(elevel, rest)
Definition: elog.h:122
Node * raw_default
Definition: parsenodes.h:595
List * lappend(List *list, void *datum)
Definition: list.c:128
char * tablespacename
Definition: parsenodes.h:1757
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:522
AclResult
Definition: acl.h:169
uintptr_t Datum
Definition: postgres.h:374
void CommandCounterIncrement(void)
Definition: xact.c:919
Datum transformRelOptions(Datum oldOptions, List *defList, char *namspace, char *validnsps[], bool ignoreOids, bool isReset)
Definition: reloptions.c:693
bool allowSystemTableMods
Definition: globals.c:109
#define InvalidOid
Definition: postgres_ext.h:36
List * tableElts
Definition: parsenodes.h:1750
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:667
#define lfirst(lc)
Definition: pg_list.h:106
#define StrNCpy(dst, src, len)
Definition: c.h:822
bool InSecurityRestrictedOperation(void)
Definition: miscinit.c:414
static List * MergeAttributes(List *schema, List *supers, char relpersistence, List **supOids, List **supconstr, int *supOidCount)
Definition: tablecmds.c:1412
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
char relpersistence
Definition: primnodes.h:77
bool interpretOidsOption(List *defList, bool allowOids)
Definition: parse_clause.c:266
#define AccessExclusiveLock
Definition: lockdefs.h:46
void * palloc(Size size)
Definition: mcxt.c:894
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1430
#define RELKIND_VIEW
Definition: pg_class.h:159
Oid heap_create_with_catalog(const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid reltypeid, Oid reloftypeid, Oid ownerid, TupleDesc tupdesc, List *cooked_constraints, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool oidislocal, int oidinhcount, OnCommitAction oncommit, Datum reloptions, bool use_user_acl, bool allow_system_table_mods, bool is_internal, ObjectAddress *typaddress)
Definition: heap.c:1018
Oid conoid
Definition: heap.h:31
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
Node * expr
Definition: heap.h:34
TupleDesc BuildDescForRelation(List *schema)
Definition: tupdesc.c:588
#define RELPERSISTENCE_TEMP
Definition: pg_class.h:166
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4517
#define RELKIND_RELATION
Definition: pg_class.h:155
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
char * name
Definition: heap.h:32
List * AddRelationNewConstraints(Relation rel, List *newColDefaults, List *newConstraints, bool allow_merge, bool is_local, bool is_internal)
Definition: heap.c:2154
TypeName * ofTypename
Definition: parsenodes.h:1753
bool is_local
Definition: heap.h:36
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
void ExecuteTruncate ( TruncateStmt stmt)

Definition at line 1003 of file tablecmds.c.

References AccessExclusiveLock, ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_NOT_OWNER, AfterTriggerBeginQuery(), AfterTriggerEndQuery(), TruncateStmt::behavior, CheckTableForSerializableConflictIn(), CreateExecutorState(), DROP_CASCADE, DROP_RESTRICT, ereport, errmsg(), EState::es_num_result_relations, EState::es_result_relation_info, EState::es_result_relations, ExecASTruncateTriggers(), ExecBSTruncateTriggers(), find_all_inheritors(), FreeExecutorState(), GetCurrentSubTransactionId(), GetOldestMultiXactId(), getOwnedSequences(), GetUserId(), heap_close, heap_create_init_fork(), heap_open(), heap_openrv(), heap_truncate_check_FKs(), heap_truncate_find_FKs(), heap_truncate_one_rel(), RangeVar::inhOpt, InitResultRelInfo(), interpretInhOption(), lappend(), lappend_oid(), lfirst, lfirst_oid, list_length(), list_member_oid(), NIL, NoLock, NOTICE, NULL, OidIsValid, palloc(), pg_class_ownercheck(), pgstat_count_truncate(), RelationData::rd_createSubid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_rel, RecentXmin, REINDEX_REL_PROCESS_TOAST, reindex_relation(), relation_close(), relation_open(), RelationGetRelationName, RelationGetRelid, TruncateStmt::relations, RelationSetNewRelfilenode(), RELPERSISTENCE_UNLOGGED, ResetSequence(), TruncateStmt::restart_seqs, and truncate_check_rel().

Referenced by standard_ProcessUtility().

1004 {
1005  List *rels = NIL;
1006  List *relids = NIL;
1007  List *seq_relids = NIL;
1008  EState *estate;
1009  ResultRelInfo *resultRelInfos;
1010  ResultRelInfo *resultRelInfo;
1011  SubTransactionId mySubid;
1012  ListCell *cell;
1013 
1014  /*
1015  * Open, exclusive-lock, and check all the explicitly-specified relations
1016  */
1017  foreach(cell, stmt->relations)
1018  {
1019  RangeVar *rv = lfirst(cell);
1020  Relation rel;
1021  bool recurse = interpretInhOption(rv->inhOpt);
1022  Oid myrelid;
1023 
1024  rel = heap_openrv(rv, AccessExclusiveLock);
1025  myrelid = RelationGetRelid(rel);
1026  /* don't throw error for "TRUNCATE foo, foo" */
1027  if (list_member_oid(relids, myrelid))
1028  {
1030  continue;
1031  }
1032  truncate_check_rel(rel);
1033  rels = lappend(rels, rel);
1034  relids = lappend_oid(relids, myrelid);
1035 
1036  if (recurse)
1037  {
1038  ListCell *child;
1039  List *children;
1040 
1041  children = find_all_inheritors(myrelid, AccessExclusiveLock, NULL);
1042 
1043  foreach(child, children)
1044  {
1045  Oid childrelid = lfirst_oid(child);
1046 
1047  if (list_member_oid(relids, childrelid))
1048  continue;
1049 
1050  /* find_all_inheritors already got lock */
1051  rel = heap_open(childrelid, NoLock);
1052  truncate_check_rel(rel);
1053  rels = lappend(rels, rel);
1054  relids = lappend_oid(relids, childrelid);
1055  }
1056  }
1057  }
1058 
1059  /*
1060  * In CASCADE mode, suck in all referencing relations as well. This
1061  * requires multiple iterations to find indirectly-dependent relations. At
1062  * each phase, we need to exclusive-lock new rels before looking for their
1063  * dependencies, else we might miss something. Also, we check each rel as
1064  * soon as we open it, to avoid a faux pas such as holding lock for a long
1065  * time on a rel we have no permissions for.
1066  */
1067  if (stmt->behavior == DROP_CASCADE)
1068  {
1069  for (;;)
1070  {
1071  List *newrelids;
1072 
1073  newrelids = heap_truncate_find_FKs(relids);
1074  if (newrelids == NIL)
1075  break; /* nothing else to add */
1076 
1077  foreach(cell, newrelids)
1078  {
1079  Oid relid = lfirst_oid(cell);
1080  Relation rel;
1081 
1082  rel = heap_open(relid, AccessExclusiveLock);
1083  ereport(NOTICE,
1084  (errmsg("truncate cascades to table \"%s\"",
1085  RelationGetRelationName(rel))));
1086  truncate_check_rel(rel);
1087  rels = lappend(rels, rel);
1088  relids = lappend_oid(relids, relid);
1089  }
1090  }
1091  }
1092 
1093  /*
1094  * Check foreign key references. In CASCADE mode, this should be
1095  * unnecessary since we just pulled in all the references; but as a
1096  * cross-check, do it anyway if in an Assert-enabled build.
1097  */
1098 #ifdef USE_ASSERT_CHECKING
1099  heap_truncate_check_FKs(rels, false);
1100 #else
1101  if (stmt->behavior == DROP_RESTRICT)
1102  heap_truncate_check_FKs(rels, false);
1103 #endif
1104 
1105  /*
1106  * If we are asked to restart sequences, find all the sequences, lock them
1107  * (we need AccessExclusiveLock for ResetSequence), and check permissions.
1108  * We want to do this early since it's pointless to do all the truncation
1109  * work only to fail on sequence permissions.
1110  */
1111  if (stmt->restart_seqs)
1112  {
1113  foreach(cell, rels)
1114  {
1115  Relation rel = (Relation) lfirst(cell);
1116  List *seqlist = getOwnedSequences(RelationGetRelid(rel));
1117  ListCell *seqcell;
1118 
1119  foreach(seqcell, seqlist)
1120  {
1121  Oid seq_relid = lfirst_oid(seqcell);
1122  Relation seq_rel;
1123 
1124  seq_rel = relation_open(seq_relid, AccessExclusiveLock);
1125 
1126  /* This check must match AlterSequence! */
1127  if (!pg_class_ownercheck(seq_relid, GetUserId()))
1129  RelationGetRelationName(seq_rel));
1130 
1131  seq_relids = lappend_oid(seq_relids, seq_relid);
1132 
1133  relation_close(seq_rel, NoLock);
1134  }
1135  }
1136  }
1137 
1138  /* Prepare to catch AFTER triggers. */
1140 
1141  /*
1142  * To fire triggers, we'll need an EState as well as a ResultRelInfo for
1143  * each relation. We don't need to call ExecOpenIndices, though.
1144  */
1145  estate = CreateExecutorState();
1146  resultRelInfos = (ResultRelInfo *)
1147  palloc(list_length(rels) * sizeof(ResultRelInfo));
1148  resultRelInfo = resultRelInfos;
1149  foreach(cell, rels)
1150  {
1151  Relation rel = (Relation) lfirst(cell);
1152 
1153  InitResultRelInfo(resultRelInfo,
1154  rel,
1155  0, /* dummy rangetable index */
1156  0);
1157  resultRelInfo++;
1158  }
1159  estate->es_result_relations = resultRelInfos;
1160  estate->es_num_result_relations = list_length(rels);
1161 
1162  /*
1163  * Process all BEFORE STATEMENT TRUNCATE triggers before we begin
1164  * truncating (this is because one of them might throw an error). Also, if
1165  * we were to allow them to prevent statement execution, that would need
1166  * to be handled here.
1167  */
1168  resultRelInfo = resultRelInfos;
1169  foreach(cell, rels)
1170  {
1171  estate->es_result_relation_info = resultRelInfo;
1172  ExecBSTruncateTriggers(estate, resultRelInfo);
1173  resultRelInfo++;
1174  }
1175 
1176  /*
1177  * OK, truncate each table.
1178  */
1179  mySubid = GetCurrentSubTransactionId();
1180 
1181  foreach(cell, rels)
1182  {
1183  Relation rel = (Relation) lfirst(cell);
1184 
1185  /*
1186  * Normally, we need a transaction-safe truncation here. However, if
1187  * the table was either created in the current (sub)transaction or has
1188  * a new relfilenode in the current (sub)transaction, then we can just
1189  * truncate it in-place, because a rollback would cause the whole
1190  * table or the current physical file to be thrown away anyway.
1191  */
1192  if (rel->rd_createSubid == mySubid ||
1193  rel->rd_newRelfilenodeSubid == mySubid)
1194  {
1195  /* Immediate, non-rollbackable truncation is OK */
1196  heap_truncate_one_rel(rel);
1197  }
1198  else
1199  {
1200  Oid heap_relid;
1201  Oid toast_relid;
1202  MultiXactId minmulti;
1203 
1204  /*
1205  * This effectively deletes all rows in the table, and may be done
1206  * in a serializable transaction. In that case we must record a
1207  * rw-conflict in to this transaction from each transaction
1208  * holding a predicate lock on the table.
1209  */
1211 
1212  minmulti = GetOldestMultiXactId();
1213 
1214  /*
1215  * Need the full transaction-safe pushups.
1216  *
1217  * Create a new empty storage file for the relation, and assign it
1218  * as the relfilenode value. The old storage file is scheduled for
1219  * deletion at commit.
1220  */
1221  RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
1222  RecentXmin, minmulti);
1223  if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
1224  heap_create_init_fork(rel);
1225 
1226  heap_relid = RelationGetRelid(rel);
1227  toast_relid = rel->rd_rel->reltoastrelid;
1228 
1229  /*
1230  * The same for the toast table, if any.
1231  */
1232  if (OidIsValid(toast_relid))
1233  {
1234  rel = relation_open(toast_relid, AccessExclusiveLock);
1235  RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
1236  RecentXmin, minmulti);
1237  if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
1238  heap_create_init_fork(rel);
1239  heap_close(rel, NoLock);
1240  }
1241 
1242  /*
1243  * Reconstruct the indexes to match, and we're done.
1244  */
1246  }
1247 
1248  pgstat_count_truncate(rel);
1249  }
1250 
1251  /*
1252  * Restart owned sequences if we were asked to.
1253  */
1254  foreach(cell, seq_relids)
1255  {
1256  Oid seq_relid = lfirst_oid(cell);
1257 
1258  ResetSequence(seq_relid);
1259  }
1260 
1261  /*
1262  * Process all AFTER STATEMENT TRUNCATE triggers.
1263  */
1264  resultRelInfo = resultRelInfos;
1265  foreach(cell, rels)
1266  {
1267  estate->es_result_relation_info = resultRelInfo;
1268  ExecASTruncateTriggers(estate, resultRelInfo);
1269  resultRelInfo++;
1270  }
1271 
1272  /* Handle queued AFTER triggers */
1273  AfterTriggerEndQuery(estate);
1274 
1275  /* We can clean up the EState now */
1276  FreeExecutorState(estate);
1277 
1278  /* And close the rels (can't do this while EState still holds refs) */
1279  foreach(cell, rels)
1280  {
1281  Relation rel = (Relation) lfirst(cell);
1282 
1283  heap_close(rel, NoLock);
1284  }
1285 }
#define NIL
Definition: pg_list.h:69
void RelationSetNewRelfilenode(Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
Definition: relcache.c:3078
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:165
Oid GetUserId(void)
Definition: miscinit.c:282
InhOption inhOpt
Definition: primnodes.h:75
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:2784
TransactionId RecentXmin
Definition: snapmgr.c:167
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:2821
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1274
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:80
uint32 SubTransactionId
Definition: c.h:397
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:83
unsigned int Oid
Definition: postgres_ext.h:31
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, int instrument_options)
Definition: execMain.c:1212
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:530
bool interpretInhOption(InhOption inhOpt)
Definition: parse_clause.c:240
void FreeExecutorState(EState *estate)
Definition: execUtils.c:169
DropBehavior behavior
Definition: parsenodes.h:2330
struct RelationData * Relation
Definition: relcache.h:21
void ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2619
struct ResultRelInfo ResultRelInfo
List * relations
Definition: parsenodes.h:2328
#define NoLock
Definition: lockdefs.h:34
void heap_create_init_fork(Relation rel)
Definition: heap.c:1378
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3391
ResultRelInfo * es_result_relations
Definition: execnodes.h:371
bool restart_seqs
Definition: parsenodes.h:2329
void ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2669
#define RelationGetRelationName(relation)
Definition: rel.h:361
void pgstat_count_truncate(Relation rel)
Definition: pgstat.c:1893
#define ereport(elevel, rest)
Definition: elog.h:122
EState * CreateExecutorState(void)
Definition: execUtils.c:72
List * lappend(List *list, void *datum)
Definition: list.c:128
SubTransactionId rd_createSubid
Definition: rel.h:79
List * getOwnedSequences(Oid relid)
Definition: pg_depend.c:563
MultiXactId GetOldestMultiXactId(void)
Definition: multixact.c:2490
static void truncate_check_rel(Relation rel)
Definition: tablecmds.c:1291
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1298
int es_num_result_relations
Definition: execnodes.h:372
Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1326
#define NOTICE
Definition: elog.h:37
void AfterTriggerBeginQuery(void)
Definition: trigger.c:3939
TransactionId MultiXactId
Definition: c.h:403
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:646
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4529
static int list_length(const List *l)
Definition: pg_list.h:89
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4338
#define AccessExclusiveLock
Definition: lockdefs.h:46
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:159
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:3959
void * palloc(Size size)
Definition: mcxt.c:894
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
#define REINDEX_REL_PROCESS_TOAST
Definition: index.h:122
void ResetSequence(Oid seq_relid)
Definition: sequence.c:270
bool reindex_relation(Oid relid, int flags, int options)
Definition: index.c:3486
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:341
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:2913
#define lfirst_oid(lc)
Definition: pg_list.h:108
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:373
void find_composite_type_dependencies ( Oid  typeOid,
Relation  origRelation,
const char *  origTypeName 
)

Definition at line 4487 of file tablecmds.c.

References AccessShareLock, Anum_pg_depend_refclassid, Anum_pg_depend_refobjid, tupleDesc::attrs, BTEqualStrategyNumber, DependReferenceIndexId, DependRelationId, ereport, errcode(), errmsg(), ERROR, find_composite_type_dependencies(), get_array_type(), GETSTRUCT, heap_open(), HeapTupleIsValid, NameStr, NULL, ObjectIdGetDatum, OidIsValid, RelationData::rd_att, RelationData::rd_rel, relation_close(), relation_open(), RelationGetRelationName, RelationRelationId, RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_RELATION, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and TypeRelationId.

Referenced by ATPrepAlterColumnType(), ATRewriteTables(), find_composite_type_dependencies(), and get_rels_with_domain().

4489 {
4490  Relation depRel;
4491  ScanKeyData key[2];
4492  SysScanDesc depScan;
4493  HeapTuple depTup;
4494  Oid arrayOid;
4495 
4496  /*
4497  * We scan pg_depend to find those things that depend on the rowtype. (We
4498  * assume we can ignore refobjsubid for a rowtype.)
4499  */
4501 
4502  ScanKeyInit(&key[0],
4504  BTEqualStrategyNumber, F_OIDEQ,
4506  ScanKeyInit(&key[1],
4508  BTEqualStrategyNumber, F_OIDEQ,
4509  ObjectIdGetDatum(typeOid));
4510 
4511  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
4512  NULL, 2, key);
4513 
4514  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
4515  {
4516  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
4517  Relation rel;
4518  Form_pg_attribute att;
4519 
4520  /* Ignore dependees that aren't user columns of relations */
4521  /* (we assume system columns are never of rowtypes) */
4522  if (pg_depend->classid != RelationRelationId ||
4523  pg_depend->objsubid <= 0)
4524  continue;
4525 
4526  rel = relation_open(pg_depend->objid, AccessShareLock);
4527  att = rel->rd_att->attrs[pg_depend->objsubid - 1];
4528 
4529  if (rel->rd_rel->relkind == RELKIND_RELATION ||
4530  rel->rd_rel->relkind == RELKIND_MATVIEW)
4531  {
4532  if (origTypeName)
4533  ereport(ERROR,
4534  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4535  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4536  origTypeName,
4538  NameStr(att->attname))));
4539  else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
4540  ereport(ERROR,
4541  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4542  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4543  RelationGetRelationName(origRelation),
4545  NameStr(att->attname))));
4546  else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4547  ereport(ERROR,
4548  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4549  errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
4550  RelationGetRelationName(origRelation),
4552  NameStr(att->attname))));
4553  else
4554  ereport(ERROR,
4555  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4556  errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
4557  RelationGetRelationName(origRelation),
4559  NameStr(att->attname))));
4560  }
4561  else if (OidIsValid(rel->rd_rel->reltype))
4562  {
4563  /*
4564  * A view or composite type itself isn't a problem, but we must
4565  * recursively check for indirect dependencies via its rowtype.
4566  */
4568  origRelation, origTypeName);
4569  }
4570 
4572  }
4573 
4574  systable_endscan(depScan);
4575 
4577 
4578  /*
4579  * If there's an array type for the rowtype, must check for uses of it,
4580  * too.
4581  */
4582  arrayOid = get_array_type(typeOid);
4583  if (OidIsValid(arrayOid))
4584  find_composite_type_dependencies(arrayOid, origRelation, origTypeName);
4585 }
#define Anum_pg_depend_refobjid
Definition: pg_depend.h:72
#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:631
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2480
#define RelationRelationId
Definition: pg_class.h:29
#define DependReferenceIndexId
Definition: indexing.h:141
void find_composite_type_dependencies(Oid typeOid, Relation origRelation, const char *origTypeName)
Definition: tablecmds.c:4487
#define DependRelationId
Definition: pg_depend.h:29
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define RELKIND_MATVIEW
Definition: pg_class.h:162
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1274
Form_pg_class rd_rel
Definition: rel.h:83
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:530
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:160
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:361
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:184
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:161
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:61
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1298
TupleDesc rd_att
Definition: rel.h:84
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:494
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
#define RELKIND_RELATION
Definition: pg_class.h:155
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void PreCommit_on_commit_actions ( void  )

Definition at line 11721 of file tablecmds.c.

References Assert, ObjectAddress::classId, CommandCounterIncrement(), OnCommitItem::deleting_subid, DROP_CASCADE, heap_truncate(), InvalidSubTransactionId, lappend_oid(), lfirst, MyXactAccessedTempRel, NIL, OnCommitItem::oncommit, ONCOMMIT_DELETE_ROWS, ONCOMMIT_DROP, ONCOMMIT_NOOP, ONCOMMIT_PRESERVE_ROWS, PERFORM_DELETION_INTERNAL, performDeletion(), RelationRelationId, and OnCommitItem::relid.

Referenced by CommitTransaction(), and PrepareTransaction().

11722 {
11723  ListCell *l;
11724  List *oids_to_truncate = NIL;
11725 
11726  foreach(l, on_commits)
11727  {
11728  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
11729 
11730  /* Ignore entry if already dropped in this xact */
11732  continue;
11733 
11734  switch (oc->oncommit)
11735  {
11736  case ONCOMMIT_NOOP:
11738  /* Do nothing (there shouldn't be such entries, actually) */
11739  break;
11740  case ONCOMMIT_DELETE_ROWS:
11741 
11742  /*
11743  * If this transaction hasn't accessed any temporary
11744  * relations, we can skip truncating ON COMMIT DELETE ROWS
11745  * tables, as they must still be empty.
11746  */
11748  oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
11749  break;
11750  case ONCOMMIT_DROP:
11751  {
11752  ObjectAddress object;
11753 
11754  object.classId = RelationRelationId;
11755  object.objectId = oc->relid;
11756  object.objectSubId = 0;
11757 
11758  /*
11759  * Since this is an automatic drop, rather than one
11760  * directly initiated by the user, we pass the
11761  * PERFORM_DELETION_INTERNAL flag.
11762  */
11763  performDeletion(&object,
11765 
11766  /*
11767  * Note that table deletion will call
11768  * remove_on_commit_action, so the entry should get marked
11769  * as deleted.
11770  */
11772  break;
11773  }
11774  }
11775  }
11776  if (oids_to_truncate != NIL)
11777  {
11778  heap_truncate(oids_to_truncate);
11779  CommandCounterIncrement(); /* XXX needed? */
11780  }
11781 }
#define NIL
Definition: pg_list.h:69
OnCommitAction oncommit
Definition: tablecmds.c:106
#define RelationRelationId
Definition: pg_class.h:29
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
static List * on_commits
Definition: tablecmds.c:119
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:270
bool MyXactAccessedTempRel
Definition: xact.c:114
SubTransactionId deleting_subid
Definition: tablecmds.c:116
void CommandCounterIncrement(void)
Definition: xact.c:919
#define Assert(condition)
Definition: c.h:667
#define lfirst(lc)
Definition: pg_list.h:106
void heap_truncate(List *relids)
Definition: heap.c:2743
#define InvalidSubTransactionId
Definition: c.h:399
Definition: pg_list.h:45
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:172
void RangeVarCallbackOwnsRelation ( const RangeVar relation,
Oid  relId,
Oid  oldRelId,
void *  noCatalogs 
)

Definition at line 11912 of file tablecmds.c.

References ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_NOT_OWNER, allowSystemTableMods, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, GetUserId(), HeapTupleIsValid, IsSystemClass(), ObjectIdGetDatum, OidIsValid, pg_class_ownercheck(), ReleaseSysCache(), RangeVar::relname, RELOID, and SearchSysCache1.

Referenced by ProcessUtilitySlow().

11914 {
11915  HeapTuple tuple;
11916 
11917  /* Nothing to do if the relation was not found. */
11918  if (!OidIsValid(relId))
11919  return;
11920 
11921  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relId));
11922  if (!HeapTupleIsValid(tuple)) /* should not happen */
11923  elog(ERROR, "cache lookup failed for relation %u", relId);
11924 
11925  if (!pg_class_ownercheck(relId, GetUserId()))
11927  relation->relname);
11928 
11929  if (!allowSystemTableMods &&
11930  IsSystemClass(relId, (Form_pg_class) GETSTRUCT(tuple)))
11931  ereport(ERROR,
11932  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
11933  errmsg("permission denied: \"%s\" is a system catalog",
11934  relation->relname)));
11935 
11936  ReleaseSysCache(tuple);
11937 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
Oid GetUserId(void)
Definition: miscinit.c:282
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:530
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:73
char * relname
Definition: primnodes.h:74
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3391
#define ereport(elevel, rest)
Definition: elog.h:122
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:990
bool allowSystemTableMods
Definition: globals.c:109
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4529
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:218
void RangeVarCallbackOwnsTable ( const RangeVar relation,
Oid  relId,
Oid  oldRelId,
void *  arg 
)

Definition at line 11879 of file tablecmds.c.

References ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_NOT_OWNER, ereport, errcode(), errmsg(), ERROR, get_rel_relkind(), GetUserId(), OidIsValid, pg_class_ownercheck(), DropRelationCallbackState::relkind, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_TOASTVALUE, and RangeVar::relname.

Referenced by cluster(), ExecRefreshMatView(), and ReindexTable().

11881 {
11882  char relkind;
11883 
11884  /* Nothing to do if the relation was not found. */
11885  if (!OidIsValid(relId))
11886  return;
11887 
11888  /*
11889  * If the relation does exist, check whether it's an index. But note that
11890  * the relation might have been dropped between the time we did the name
11891  * lookup and now. In that case, there's nothing to do.
11892  */
11893  relkind = get_rel_relkind(relId);
11894  if (!relkind)
11895  return;
11896  if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
11897  relkind != RELKIND_MATVIEW)
11898  ereport(ERROR,
11899  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11900  errmsg("\"%s\" is not a table or materialized view", relation->relname)));
11901 
11902  /* Check permissions */
11903  if (!pg_class_ownercheck(relId, GetUserId()))
11905 }
Oid GetUserId(void)
Definition: miscinit.c:282
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1769
#define RELKIND_MATVIEW
Definition: pg_class.h:162
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:530
char * relname
Definition: primnodes.h:74
#define ERROR
Definition: elog.h:43
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3391
#define ereport(elevel, rest)
Definition: elog.h:122
#define RELKIND_TOASTVALUE
Definition: pg_class.h:158
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4529
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_RELATION
Definition: pg_class.h:155
void register_on_commit_action ( Oid  relid,
OnCommitAction  action 
)

Definition at line 11667 of file tablecmds.c.

References CacheMemoryContext, OnCommitItem::creating_subid, OnCommitItem::deleting_subid, GetCurrentSubTransactionId(), InvalidSubTransactionId, lcons(), MemoryContextSwitchTo(), OnCommitItem::oncommit, ONCOMMIT_NOOP, ONCOMMIT_PRESERVE_ROWS, palloc(), and OnCommitItem::relid.

Referenced by heap_create_with_catalog().

11668 {
11669  OnCommitItem *oc;
11670  MemoryContext oldcxt;
11671 
11672  /*
11673  * We needn't bother registering the relation unless there is an ON COMMIT
11674  * action we need to take.
11675  */
11676  if (action == ONCOMMIT_NOOP || action == ONCOMMIT_PRESERVE_ROWS)
11677  return;
11678 
11680 
11681  oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
11682  oc->relid = relid;
11683  oc->oncommit = action;
11686 
11687  on_commits = lcons(oc, on_commits);
11688 
11689  MemoryContextSwitchTo(oldcxt);
11690 }
OnCommitAction oncommit
Definition: tablecmds.c:106
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SubTransactionId creating_subid
Definition: tablecmds.c:115
static List * on_commits
Definition: tablecmds.c:119
SubTransactionId deleting_subid
Definition: tablecmds.c:116
List * lcons(void *datum, List *list)
Definition: list.c:259
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:646
#define InvalidSubTransactionId
Definition: c.h:399
void * palloc(Size size)
Definition: mcxt.c:894
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void remove_on_commit_action ( Oid  relid)

Definition at line 11698 of file tablecmds.c.

References OnCommitItem::deleting_subid, GetCurrentSubTransactionId(), lfirst, and OnCommitItem::relid.

Referenced by heap_drop_with_catalog().

11699 {
11700  ListCell *l;
11701 
11702  foreach(l, on_commits)
11703  {
11704  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
11705 
11706  if (oc->relid == relid)
11707  {
11709  break;
11710  }
11711  }
11712 }
static List * on_commits
Definition: tablecmds.c:119
SubTransactionId deleting_subid
Definition: tablecmds.c:116
#define lfirst(lc)
Definition: pg_list.h:106
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:646
void RemoveRelations ( DropStmt drop)

Definition at line 804 of file tablecmds.c.

References AcceptInvalidationMessages(), AccessExclusiveLock, add_exact_object_address(), Assert, DropStmt::behavior, ObjectAddress::classId, DropRelationCallbackState::concurrent, DropStmt::concurrent, DROP_CASCADE, DropErrorMsgNonExistent(), elog, ereport, errcode(), errmsg(), ERROR, free_object_addresses(), DropRelationCallbackState::heapOid, InvalidOid, lfirst, list_length(), makeRangeVarFromNameList(), DropStmt::missing_ok, new_object_addresses(), OBJECT_FOREIGN_TABLE, OBJECT_INDEX, OBJECT_MATVIEW, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_VIEW, ObjectAddress::objectId, DropStmt::objects, ObjectAddress::objectSubId, OidIsValid, PERFORM_DELETION_CONCURRENTLY, performMultipleDeletions(), RangeVarCallbackForDropRelation(), RangeVarGetRelidExtended(), RelationRelationId, DropRelationCallbackState::relkind, RELKIND_FOREIGN_TABLE, RELKIND_INDEX, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, DropStmt::removeType, and ShareUpdateExclusiveLock.

Referenced by ExecDropStmt().

805 {
806  ObjectAddresses *objects;
807  char relkind;
808  ListCell *cell;
809  int flags = 0;
810  LOCKMODE lockmode = AccessExclusiveLock;
811 
812  /* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */
813  if (drop->concurrent)
814  {
816  lockmode = ShareUpdateExclusiveLock;
817  Assert(drop->removeType == OBJECT_INDEX);
818  if (list_length(drop->objects) != 1)
819  ereport(ERROR,
820  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
821  errmsg("DROP INDEX CONCURRENTLY does not support dropping multiple objects")));
822  if (drop->behavior == DROP_CASCADE)
823  ereport(ERROR,
824  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
825  errmsg("DROP INDEX CONCURRENTLY does not support CASCADE")));
826  }
827 
828  /*
829  * First we identify all the relations, then we delete them in a single
830  * performMultipleDeletions() call. This is to avoid unwanted DROP
831  * RESTRICT errors if one of the relations depends on another.
832  */
833 
834  /* Determine required relkind */
835  switch (drop->removeType)
836  {
837  case OBJECT_TABLE:
838  relkind = RELKIND_RELATION;
839  break;
840 
841  case OBJECT_INDEX:
842  relkind = RELKIND_INDEX;
843  break;
844 
845  case OBJECT_SEQUENCE:
846  relkind = RELKIND_SEQUENCE;
847  break;
848 
849  case OBJECT_VIEW:
850  relkind = RELKIND_VIEW;
851  break;
852 
853  case OBJECT_MATVIEW:
854  relkind = RELKIND_MATVIEW;
855  break;
856 
858  relkind = RELKIND_FOREIGN_TABLE;
859  break;
860 
861  default:
862  elog(ERROR, "unrecognized drop object type: %d",
863  (int) drop->removeType);
864  relkind = 0; /* keep compiler quiet */
865  break;
866  }
867 
868  /* Lock and validate each relation; build a list of object addresses */
869  objects = new_object_addresses();
870 
871  foreach(cell, drop->objects)
872  {
873  RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell));
874  Oid relOid;
875  ObjectAddress obj;
877 
878  /*
879  * These next few steps are a great deal like relation_openrv, but we
880  * don't bother building a relcache entry since we don't need it.
881  *
882  * Check for shared-cache-inval messages before trying to access the
883  * relation. This is needed to cover the case where the name
884  * identifies a rel that has been dropped and recreated since the
885  * start of our transaction: if we don't flush the old syscache entry,
886  * then we'll latch onto that entry and suffer an error later.
887  */
889 
890  /* Look up the appropriate relation using namespace search. */
891  state.relkind = relkind;
892  state.heapOid = InvalidOid;
893  state.concurrent = drop->concurrent;
894  relOid = RangeVarGetRelidExtended(rel, lockmode, true,
895  false,
897  (void *) &state);
898 
899  /* Not there? */
900  if (!OidIsValid(relOid))
901  {
902  DropErrorMsgNonExistent(rel, relkind, drop->missing_ok);
903  continue;
904  }
905 
906  /* OK, we're ready to delete this one */
908  obj.objectId = relOid;
909  obj.objectSubId = 0;
910 
911  add_exact_object_address(&obj, objects);
912  }
913 
914  performMultipleDeletions(objects, drop->behavior, flags);
915 
916  free_object_addresses(objects);
917 }
void AcceptInvalidationMessages(void)
Definition: inval.c:660
int LOCKMODE
Definition: lockdefs.h:26
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
#define RelationRelationId
Definition: pg_class.h:29
List * objects
Definition: parsenodes.h:2313
bool missing_ok
Definition: parsenodes.h:2317
#define RELKIND_MATVIEW
Definition: pg_class.h:162
int errcode(int sqlerrcode)
Definition: elog.c:575
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:2872
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2098
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2043
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2314
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:530
ObjectType removeType
Definition: parsenodes.h:2315
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:173
#define ERROR
Definition: elog.h:43
bool concurrent
Definition: parsenodes.h:2318
DropBehavior behavior
Definition: parsenodes.h:2316
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:161
#define ereport(elevel, rest)
Definition: elog.h:122
static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid, void *arg)
Definition: tablecmds.c:924
#define InvalidOid
Definition: postgres_ext.h:36
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define Assert(condition)
Definition: c.h:667
#define lfirst(lc)
Definition: pg_list.h:106
Definition: regguts.h:313
static int list_length(const List *l)
Definition: pg_list.h:89
#define AccessExclusiveLock
Definition: lockdefs.h:46
static void DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
Definition: tablecmds.c:729
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_VIEW
Definition: pg_class.h:159
#define RELKIND_INDEX
Definition: pg_class.h:156
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:328
#define elog
Definition: elog.h:218
#define RELKIND_RELATION
Definition: pg_class.h:155
#define RELKIND_SEQUENCE
Definition: pg_class.h:157
Definition: pg_list.h:45
ObjectAddress renameatt ( RenameStmt stmt)

Definition at line 2362 of file tablecmds.c.

References AccessExclusiveLock, RenameStmt::behavior, ereport, errmsg(), RangeVar::inhOpt, interpretInhOption(), InvalidObjectAddress, RenameStmt::missing_ok, RenameStmt::newname, NOTICE, NULL, ObjectAddressSubSet, OidIsValid, RangeVarCallbackForRenameAttribute(), RangeVarGetRelidExtended(), RenameStmt::relation, RelationRelationId, RangeVar::relname, renameatt_internal(), and RenameStmt::subname.

Referenced by ExecRenameStmt().

2363 {
2364  Oid relid;
2365  AttrNumber attnum;
2366  ObjectAddress address;
2367 
2368  /* lock level taken here should match renameatt_internal */
2370  stmt->missing_ok, false,
2372  NULL);
2373 
2374  if (!OidIsValid(relid))
2375  {
2376  ereport(NOTICE,
2377  (errmsg("relation \"%s\" does not exist, skipping",
2378  stmt->relation->relname)));
2379  return InvalidObjectAddress;
2380  }
2381 
2382  attnum =
2383  renameatt_internal(relid,
2384  stmt->subname, /* old att name */
2385  stmt->newname, /* new att name */
2386  interpretInhOption(stmt->relation->inhOpt), /* recursive? */
2387  false, /* recursing? */
2388  0, /* expected inhcount */
2389  stmt->behavior);
2390 
2391  ObjectAddressSubSet(address, RelationRelationId, relid, attnum);
2392 
2393  return address;
2394 }
char * subname
Definition: parsenodes.h:2531
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
InhOption inhOpt
Definition: primnodes.h:75
#define RelationRelationId
Definition: pg_class.h:29
char * newname
Definition: parsenodes.h:2533
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:530
bool interpretInhOption(InhOption inhOpt)
Definition: parse_clause.c:240
char * relname
Definition: primnodes.h:74
bool missing_ok
Definition: parsenodes.h:2535
#define ereport(elevel, rest)
Definition: elog.h:122
RangeVar * relation
Definition: parsenodes.h:2528
#define NOTICE
Definition: elog.h:37
static void RangeVarCallbackForRenameAttribute(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:2342
#define NULL
Definition: c.h:226
static AttrNumber renameatt_internal(Oid myrelid, const char *oldattname, const char *newattname, bool recurse, bool recursing, int expected_parents, DropBehavior behavior)
Definition: tablecmds.c:2194
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
Definition: objectaddress.h:33
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
DropBehavior behavior
Definition: parsenodes.h:2534
int16 AttrNumber
Definition: attnum.h:21
ObjectAddress renameatt_type ( RenameStmt stmt)
ObjectAddress RenameConstraint ( RenameStmt stmt)

Definition at line 2499 of file tablecmds.c.

References AccessExclusiveLock, checkDomainOwner(), elog, ereport, errmsg(), ERROR, heap_close, heap_open(), HeapTupleIsValid, RangeVar::inhOpt, interpretInhOption(), InvalidObjectAddress, InvalidOid, makeTypeNameFromNameList(), RenameStmt::missing_ok, RenameStmt::newname, NoLock, NOTICE, NULL, RenameStmt::object, OBJECT_DOMCONSTRAINT, ObjectIdGetDatum, OidIsValid, RangeVarCallbackForRenameAttribute(), RangeVarGetRelidExtended(), RenameStmt::relation, ReleaseSysCache(), RangeVar::relname, rename_constraint_internal(), RenameStmt::renameType, RowExclusiveLock, SearchSysCache1, RenameStmt::subname, typenameTypeId(), TYPEOID, and TypeRelationId.

Referenced by ExecRenameStmt().

2500 {
2501  Oid relid = InvalidOid;
2502  Oid typid = InvalidOid;
2503 
2504  if (stmt->renameType == OBJECT_DOMCONSTRAINT)
2505  {
2506  Relation rel;
2507  HeapTuple tup;
2508 
2511  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2512  if (!HeapTupleIsValid(tup))
2513  elog(ERROR, "cache lookup failed for type %u", typid);
2514  checkDomainOwner(tup);
2515  ReleaseSysCache(tup);
2516  heap_close(rel, NoLock);
2517  }
2518  else
2519  {
2520  /* lock level taken here should match rename_constraint_internal */
2522  stmt->missing_ok, false,
2524  NULL);
2525  if (!OidIsValid(relid))
2526  {
2527  ereport(NOTICE,
2528  (errmsg("relation \"%s\" does not exist, skipping",
2529  stmt->relation->relname)));
2530  return InvalidObjectAddress;
2531  }
2532  }
2533 
2534  return
2535  rename_constraint_internal(relid, typid,
2536  stmt->subname,
2537  stmt->newname,
2538  stmt->relation ? interpretInhOption(stmt->relation->inhOpt) : false, /* recursive? */
2539  false, /* recursing? */
2540  0 /* expected inhcount */ );
2541 
2542 }
char * subname
Definition: parsenodes.h:2531
ObjectType renameType
Definition: parsenodes.h:2526
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
InhOption inhOpt
Definition: primnodes.h:75
#define heap_close(r, l)
Definition: heapam.h:97
static ObjectAddress rename_constraint_internal(Oid myrelid, Oid mytypid, const char *oldconname, const char *newconname, bool recurse, bool recursing, int expected_parents)
Definition: tablecmds.c:2400
char * newname
Definition: parsenodes.h:2533
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:530
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
bool interpretInhOption(InhOption inhOpt)
Definition: parse_clause.c:240
char * relname
Definition: primnodes.h:74
bool missing_ok
Definition: parsenodes.h:2535
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:990
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1298
RangeVar * relation
Definition: parsenodes.h:2528
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static void RangeVarCallbackForRenameAttribute(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:2342
#define NULL
Definition: c.h:226
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:2963
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:453
#define elog
Definition: elog.h:218
List * object
Definition: parsenodes.h:2529
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
ObjectAddress RenameRelation ( RenameStmt stmt)

Definition at line 2549 of file tablecmds.c.

References AccessExclusiveLock, ereport, errmsg(), InvalidObjectAddress, RenameStmt::missing_ok, RenameStmt::newname, NOTICE, ObjectAddressSet, OidIsValid, RangeVarCallbackForAlterRelation(), RangeVarGetRelidExtended(), RenameStmt::relation, RelationRelationId, RangeVar::relname, and RenameRelationInternal().

Referenced by ExecRenameStmt().

2550 {
2551  Oid relid;
2552  ObjectAddress address;
2553 
2554  /*
2555  * Grab an exclusive lock on the target table, index, sequence, view,
2556  * materialized view, or foreign table, which we will NOT release until
2557  * end of transaction.
2558  *
2559  * Lock level used here should match RenameRelationInternal, to avoid lock
2560  * escalation.
2561  */
2563  stmt->missing_ok, false,
2565  (void *) stmt);
2566 
2567  if (!OidIsValid(relid))
2568  {
2569  ereport(NOTICE,
2570  (errmsg("relation \"%s\" does not exist, skipping",
2571  stmt->relation->relname)));
2572  return InvalidObjectAddress;
2573  }
2574 
2575  /* Do the work */
2576  RenameRelationInternal(relid, stmt->newname, false);
2577 
2578  ObjectAddressSet(address, RelationRelationId, relid);
2579 
2580  return address;
2581 }
void RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
Definition: tablecmds.c:2593
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
#define RelationRelationId
Definition: pg_class.h:29
char * newname
Definition: parsenodes.h:2533
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:530
char * relname
Definition: primnodes.h:74
bool missing_ok
Definition: parsenodes.h:2535
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:11944
#define ereport(elevel, rest)
Definition: elog.h:122
RangeVar * relation
Definition: parsenodes.h:2528
#define NOTICE
Definition: elog.h:37
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
void RenameRelationInternal ( Oid  myrelid,
const char *  newrelname,
bool  is_internal 
)

Definition at line 2593 of file tablecmds.c.

References AccessExclusiveLock, CatalogUpdateIndexes(), elog, ereport, errcode(), errmsg(), ERROR, get_index_constraint(), get_relname_relid(), GETSTRUCT, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, InvalidOid, InvokeObjectPostAlterHookArg, namestrcpy(), NoLock, ObjectIdGetDatum, OidIsValid, RelationData::rd_rel, relation_close(), relation_open(), RelationGetNamespace, RelationRelationId, RELKIND_INDEX, RELOID, RenameConstraintById(), RenameTypeInternal(), RowExclusiveLock, SearchSysCacheCopy1, simple_heap_update(), and HeapTupleData::t_self.

Referenced by ATExecAddIndexConstraint(), finish_heap_swap(), rename_constraint_internal(), RenameRelation(), and RenameType().

2594 {
2595  Relation targetrelation;
2596  Relation relrelation; /* for RELATION relation */
2597  HeapTuple reltup;
2598  Form_pg_class relform;
2599  Oid namespaceId;
2600 
2601  /*
2602  * Grab an exclusive lock on the target table, index, sequence, view,
2603  * materialized view, or foreign table, which we will NOT release until
2604  * end of transaction.
2605  */
2606  targetrelation = relation_open(myrelid, AccessExclusiveLock);
2607  namespaceId = RelationGetNamespace(targetrelation);
2608 
2609  /*
2610  * Find relation's pg_class tuple, and make sure newrelname isn't in use.
2611  */
2613 
2614  reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
2615  if (!HeapTupleIsValid(reltup)) /* shouldn't happen */
2616  elog(ERROR, "cache lookup failed for relation %u", myrelid);
2617  relform = (Form_pg_class) GETSTRUCT(reltup);
2618 
2619  if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
2620  ereport(ERROR,
2621  (errcode(ERRCODE_DUPLICATE_TABLE),
2622  errmsg("relation \"%s\" already exists",
2623  newrelname)));
2624 
2625  /*
2626  * Update pg_class tuple with new relname. (Scribbling on reltup is OK
2627  * because it's a copy...)
2628  */
2629  namestrcpy(&(relform->relname), newrelname);
2630 
2631  simple_heap_update(relrelation, &reltup->t_self, reltup);
2632 
2633  /* keep the system catalog indexes current */
2634  CatalogUpdateIndexes(relrelation, reltup);
2635 
2637  InvalidOid, is_internal);
2638 
2639  heap_freetuple(reltup);
2640  heap_close(relrelation, RowExclusiveLock);
2641 
2642  /*
2643  * Also rename the associated type, if any.
2644  */
2645  if (OidIsValid(targetrelation->rd_rel->reltype))
2646  RenameTypeInternal(targetrelation->rd_rel->reltype,
2647  newrelname, namespaceId);
2648 
2649  /*
2650  * Also rename the associated constraint, if any.
2651  */
2652  if (targetrelation->rd_rel->relkind == RELKIND_INDEX)
2653  {
2654  Oid constraintId = get_index_constraint(myrelid);
2655 
2656  if (OidIsValid(constraintId))
2657  RenameConstraintById(constraintId, newrelname);
2658  }
2659 
2660  /*
2661  * Close rel, but keep exclusive lock!
2662  */
2663  relation_close(targetrelation, NoLock);
2664 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
#define RelationRelationId
Definition: pg_class.h:29
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1274
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:83
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1306
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:217
#define OidIsValid(objectId)
Definition: c.h:530
void RenameConstraintById(Oid conId, const char *newname)
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1651
#define NoLock
Definition: lockdefs.h:34
#define InvokeObjectPostAlterHookArg(classId, objectId, subId,auxiliaryId, is_internal)
Definition: objectaccess.h:166
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid get_index_constraint(Oid indexId)
Definition: pg_depend.c:679
#define ereport(elevel, rest)
Definition: elog.h:122
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:697
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1298
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
Definition: indexing.c:157
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
Definition: heapam.c:4422
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:150
#define AccessExclusiveLock
Definition: lockdefs.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_INDEX
Definition: pg_class.h:156
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
#define elog
Definition: elog.h:218
#define RelationGetNamespace(relation)
Definition: rel.h:368
void SetRelationHasSubclass ( Oid  relationId,
bool  relhassubclass 
)

Definition at line 2111 of file tablecmds.c.

References CacheInvalidateRelcacheByTuple(), CatalogUpdateIndexes(), elog, ERROR, GETSTRUCT, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, ObjectIdGetDatum, RelationRelationId, RELOID, RowExclusiveLock, SearchSysCacheCopy1, simple_heap_update(), and HeapTupleData::t_self.

Referenced by acquire_inherited_sample_rows(), and StoreCatalogInheritance1().

2112 {
2113  Relation relationRelation;
2114  HeapTuple tuple;
2115  Form_pg_class classtuple;
2116 
2117  /*
2118  * Fetch a modifiable copy of the tuple, modify it, update pg_class.
2119  */
2120  relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
2121  tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
2122  if (!HeapTupleIsValid(tuple))
2123  elog(ERROR, "cache lookup failed for relation %u", relationId);
2124  classtuple = (Form_pg_class) GETSTRUCT(tuple);
2125 
2126  if (classtuple->relhassubclass != relhassubclass)
2127  {
2128  classtuple->relhassubclass = relhassubclass;
2129  simple_heap_update(relationRelation, &tuple->t_self, tuple);
2130 
2131  /* keep the catalog indexes up to date */
2132  CatalogUpdateIndexes(relationRelation, tuple);
2133  }
2134  else
2135  {
2136  /* no need to change tuple, but force relcache rebuild anyway */
2138  }
2139 
2140  heap_freetuple(tuple);
2141  heap_close(relationRelation, RowExclusiveLock);
2142 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
#define RelationRelationId
Definition: pg_class.h:29
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1306
#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
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1298
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
Definition: indexing.c:157
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
Definition: heapam.c:4422
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:150
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1234
#define elog
Definition: elog.h:218